diff options
author | Petri Savolainen <petri.savolainen@nokia.com> | 2016-02-09 14:25:08 +0200 |
---|---|---|
committer | Maxim Uvarov <maxim.uvarov@linaro.org> | 2016-03-03 22:32:04 +0300 |
commit | 96cef77a0aad6940f5b210277ffb0bccb6e5b3c1 (patch) | |
tree | 55001f97f8d7d94200e8d27ab035a9b5cca3ab97 /helper | |
parent | cc03b63e667c3acf580f20765910dbb342d452b2 (diff) |
helper: ip: added ipv4 address parse
IPv4 address parse function is commonly needed by
test applications. A common parse function harmonizes the
definition IPv4 address as a command line parameter.
Signed-off-by: Petri Savolainen <petri.savolainen@nokia.com>
Reviewed-by: Juha-Matti Tilli <juha-matti.tilli@nokia.com>
Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
Diffstat (limited to 'helper')
-rw-r--r-- | helper/Makefile.am | 1 | ||||
-rw-r--r-- | helper/include/odp/helper/ip.h | 22 | ||||
-rw-r--r-- | helper/ip.c | 30 | ||||
-rw-r--r-- | helper/test/odp_parse.c | 153 |
4 files changed, 203 insertions, 3 deletions
diff --git a/helper/Makefile.am b/helper/Makefile.am index 6f6d6cd28..4753c48fe 100644 --- a/helper/Makefile.am +++ b/helper/Makefile.am @@ -29,6 +29,7 @@ noinst_HEADERS = \ __LIB__libodphelper_la_SOURCES = \ eth.c \ + ip.c \ linux.c \ hashtable.c \ lineartable.c diff --git a/helper/include/odp/helper/ip.h b/helper/include/odp/helper/ip.h index 2fa4aae47..769384f62 100644 --- a/helper/include/odp/helper/ip.h +++ b/helper/include/odp/helper/ip.h @@ -18,9 +18,7 @@ extern "C" { #endif -#include <odp/align.h> -#include <odp/debug.h> -#include <odp/byteorder.h> +#include <odp.h> #include <odp/helper/chksum.h> #include <string.h> @@ -32,6 +30,7 @@ extern "C" { #define ODPH_IPV4 4 /**< IP version 4 */ #define ODPH_IPV4HDR_LEN 20 /**< Min length of IP header (no options) */ #define ODPH_IPV4HDR_IHL_MIN 5 /**< Minimum IHL value*/ +#define ODPH_IPV4ADDR_LEN 4 /**< IPv4 address length in bytes */ /** @internal Returns IPv4 version */ #define ODPH_IPV4HDR_VER(ver_ihl) (((ver_ihl) & 0xf0) >> 4) @@ -176,6 +175,23 @@ typedef struct ODP_PACKED { /**@}*/ /** + * Parse IPv4 address from a string + * + * Parses IPv4 address from the string which must be passed in the format of + * four decimal digits delimited by dots (xxx.xxx.xxx.xxx). All four digits + * have to be present and may have leading zeros. String does not have to be + * NULL terminated. The address is written only when successful. The address + * byte order is CPU native. + * + * @param[out] ip_addr Pointer to IPv4 address for output (in native endian) + * @param str IPv4 address string to be parsed + * + * @retval 0 on success + * @retval <0 on failure + */ +int odph_ipv4_addr_parse(uint32_t *ip_addr, const char *str); + +/** * @} */ #ifdef __cplusplus diff --git a/helper/ip.c b/helper/ip.c new file mode 100644 index 000000000..eb73e5a08 --- /dev/null +++ b/helper/ip.c @@ -0,0 +1,30 @@ +/* Copyright (c) 2016, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <odp/helper/ip.h> + +#include <stdio.h> +#include <string.h> + +int odph_ipv4_addr_parse(uint32_t *ip_addr, const char *str) +{ + unsigned byte[ODPH_IPV4ADDR_LEN]; + int i; + + memset(byte, 0, sizeof(byte)); + + if (sscanf(str, "%u.%u.%u.%u", + &byte[0], &byte[1], &byte[2], &byte[3]) != ODPH_IPV4ADDR_LEN) + return -1; + + for (i = 0; i < ODPH_IPV4ADDR_LEN; i++) + if (byte[i] > 255) + return -1; + + *ip_addr = byte[0] << 24 | byte[1] << 16 | byte[2] << 8 | byte[3]; + + return 0; +} diff --git a/helper/test/odp_parse.c b/helper/test/odp_parse.c index f20b9096a..77c506b17 100644 --- a/helper/test/odp_parse.c +++ b/helper/test/odp_parse.c @@ -8,6 +8,7 @@ #include <odp.h> #include <odp/helper/eth.h> +#include <odp/helper/ip.h> #include <stdio.h> #include <string.h> @@ -22,6 +23,11 @@ static int different_mac(odph_ethaddr_t *mac1, odph_ethaddr_t *mac2) mac1->addr[5] != mac2->addr[5]; } +static int different_ipv4(uint32_t *ip_addr1, uint32_t *ip_addr2) +{ + return *ip_addr1 != *ip_addr2; +} + static int test_mac(void) { odph_ethaddr_t mac; @@ -195,11 +201,158 @@ static int test_mac(void) return 0; } +static int test_ipv4(void) +{ + uint32_t ip_addr; + uint32_t ref; + + ip_addr = 0; + ref = 0; + + /* + * Erroneous strings + */ + + /* String must not start with other chars */ + if (!odph_ipv4_addr_parse(&ip_addr, "foo 1.2.3.4")) { + LOG_ERR("Accepted bad string\n"); + return -1; + } + + /* Missing digit */ + if (!odph_ipv4_addr_parse(&ip_addr, "1.2.3.")) { + LOG_ERR("Accepted bad string\n"); + return -1; + } + + /* Missing dot */ + if (!odph_ipv4_addr_parse(&ip_addr, "1.2.3 4")) { + LOG_ERR("Accepted bad string\n"); + return -1; + } + + /* Too large value */ + if (!odph_ipv4_addr_parse(&ip_addr, "1.2.3.256")) { + LOG_ERR("Accepted bad string\n"); + return -1; + } + + /* Negative value */ + if (!odph_ipv4_addr_parse(&ip_addr, "-1.2.3.4")) { + LOG_ERR("Accepted bad string\n"); + return -1; + } + + /* Failed function call must not store address */ + if (different_ipv4(&ip_addr, &ref)) { + LOG_ERR("Modified address when failed\n"); + return -1; + } + + ref = 0x01020304; + + /* Zero pre-fixed */ + ip_addr = 0; + if (odph_ipv4_addr_parse(&ip_addr, "001.002.003.004")) { + LOG_ERR("Parse call failed\n"); + return -1; + } + + if (different_ipv4(&ip_addr, &ref)) { + LOG_ERR("Bad parse result\n"); + return -1; + } + + /* Not zero pre-fixed */ + ip_addr = 0; + if (odph_ipv4_addr_parse(&ip_addr, "1.2.3.4")) { + LOG_ERR("Parse call failed\n"); + return -1; + } + + if (different_ipv4(&ip_addr, &ref)) { + LOG_ERR("Bad parse result\n"); + return -1; + } + + /* String may continue with other chars */ + ip_addr = 0; + if (odph_ipv4_addr_parse(&ip_addr, "1.2.3.4 foobar")) { + LOG_ERR("Parse call failed\n"); + return -1; + } + + if (different_ipv4(&ip_addr, &ref)) { + LOG_ERR("Bad parse result\n"); + return -1; + } + + ref = 0x1a2b3c4d; + + /* Dual digits */ + ip_addr = 0; + if (odph_ipv4_addr_parse(&ip_addr, "26.43.60.77")) { + LOG_ERR("Parse call failed\n"); + return -1; + } + + if (different_ipv4(&ip_addr, &ref)) { + LOG_ERR("Bad parse result\n"); + return -1; + } + + ref = 0xa1b2c3d4; + + /* Triple digits */ + ip_addr = 0; + if (odph_ipv4_addr_parse(&ip_addr, "161.178.195.212")) { + LOG_ERR("Parse call failed\n"); + return -1; + } + + if (different_ipv4(&ip_addr, &ref)) { + LOG_ERR("Bad parse result\n"); + return -1; + } + + ref = 0; + + /* All zeros */ + ip_addr = 0; + if (odph_ipv4_addr_parse(&ip_addr, "0.0.0.0")) { + LOG_ERR("Parse call failed\n"); + return -1; + } + + if (different_ipv4(&ip_addr, &ref)) { + LOG_ERR("Bad parse result\n"); + return -1; + } + + ref = 0xffffffff; + + /* All ones */ + ip_addr = 0; + if (odph_ipv4_addr_parse(&ip_addr, "255.255.255.255")) { + LOG_ERR("Parse call failed\n"); + return -1; + } + + if (different_ipv4(&ip_addr, &ref)) { + LOG_ERR("Bad parse result\n"); + return -1; + } + + printf("IPv4 address parse test successful\n"); + return 0; +} + int main(void) { int ret = 0; ret += test_mac(); + ret += test_ipv4(); return ret; } |