14418919fSjohnjiang /* SPDX-License-Identifier: BSD-3-Clause
24418919fSjohnjiang * Copyright(c) 2010-2014 Intel Corporation
34418919fSjohnjiang */
44418919fSjohnjiang
54418919fSjohnjiang #include <stdio.h>
64418919fSjohnjiang #include <string.h>
74418919fSjohnjiang #include <inttypes.h>
84418919fSjohnjiang
94418919fSjohnjiang #include <rte_ether.h>
104418919fSjohnjiang #include <rte_string_fns.h>
114418919fSjohnjiang
124418919fSjohnjiang #include <cmdline_parse.h>
134418919fSjohnjiang #include <cmdline_parse_etheraddr.h>
144418919fSjohnjiang
154418919fSjohnjiang #include "test_cmdline.h"
164418919fSjohnjiang
174418919fSjohnjiang struct ether_addr_str {
184418919fSjohnjiang const char * str;
194418919fSjohnjiang uint64_t address;
204418919fSjohnjiang };
214418919fSjohnjiang
224418919fSjohnjiang /* valid strings */
234418919fSjohnjiang const struct ether_addr_str ether_addr_valid_strs[] = {
244418919fSjohnjiang {"01:23:45:67:89:AB", 0xAB8967452301ULL},
254418919fSjohnjiang {"4567:89AB:CDEF", 0xEFCDAB896745ULL},
264418919fSjohnjiang };
274418919fSjohnjiang
284418919fSjohnjiang /* valid strings with various garbage at the end.
294418919fSjohnjiang * these strings are still valid because parser checks for
304418919fSjohnjiang * end of token, which is either space chars, null char or
314418919fSjohnjiang * a hash sign.
324418919fSjohnjiang */
334418919fSjohnjiang const char * ether_addr_garbage_strs[] = {
344418919fSjohnjiang "00:11:22:33:44:55\0garbage",
354418919fSjohnjiang "00:11:22:33:44:55#garbage",
364418919fSjohnjiang "00:11:22:33:44:55 garbage",
374418919fSjohnjiang "00:11:22:33:44:55\tgarbage",
384418919fSjohnjiang "00:11:22:33:44:55\ngarbage",
394418919fSjohnjiang "00:11:22:33:44:55\rgarbage",
404418919fSjohnjiang "00:11:22:33:44:55#",
414418919fSjohnjiang "00:11:22:33:44:55 ",
424418919fSjohnjiang "00:11:22:33:44:55\t",
434418919fSjohnjiang "00:11:22:33:44:55\n",
444418919fSjohnjiang "00:11:22:33:44:55\r",
454418919fSjohnjiang };
464418919fSjohnjiang #define GARBAGE_ETHERADDR 0x554433221100ULL /* corresponding address */
474418919fSjohnjiang
484418919fSjohnjiang
494418919fSjohnjiang const char * ether_addr_invalid_strs[] = {
504418919fSjohnjiang /* valid chars, invalid syntax */
514418919fSjohnjiang "0123:45:67:89:AB",
524418919fSjohnjiang "01:23:4567:89:AB",
534418919fSjohnjiang "01:23:45:67:89AB",
544418919fSjohnjiang "012:345:678:9AB",
554418919fSjohnjiang "01:23:45:67:89:ABC",
564418919fSjohnjiang "01:23:45:67:89:A",
574418919fSjohnjiang "01:23:45:67:89",
584418919fSjohnjiang "01:23:45:67:89:AB:CD",
594418919fSjohnjiang /* invalid chars, valid syntax */
604418919fSjohnjiang "IN:VA:LI:DC:HA:RS",
614418919fSjohnjiang "INVA:LIDC:HARS",
624418919fSjohnjiang /* misc */
634418919fSjohnjiang "01 23 45 67 89 AB",
644418919fSjohnjiang "01.23.45.67.89.AB",
654418919fSjohnjiang "01,23,45,67,89,AB",
664418919fSjohnjiang "01:23:45\0:67:89:AB",
674418919fSjohnjiang "01:23:45#:67:89:AB",
684418919fSjohnjiang "random invalid text",
694418919fSjohnjiang "random text",
704418919fSjohnjiang "",
714418919fSjohnjiang "\0",
724418919fSjohnjiang " ",
734418919fSjohnjiang };
744418919fSjohnjiang
754418919fSjohnjiang static int
is_addr_different(const struct rte_ether_addr addr,uint64_t num)764418919fSjohnjiang is_addr_different(const struct rte_ether_addr addr, uint64_t num)
774418919fSjohnjiang {
784418919fSjohnjiang int i;
794418919fSjohnjiang for (i = 0; i < RTE_ETHER_ADDR_LEN; i++, num >>= 8)
804418919fSjohnjiang if (addr.addr_bytes[i] != (num & 0xFF)) {
814418919fSjohnjiang return 1;
824418919fSjohnjiang }
834418919fSjohnjiang return 0;
844418919fSjohnjiang }
854418919fSjohnjiang
864418919fSjohnjiang /* test invalid parameters */
874418919fSjohnjiang int
test_parse_etheraddr_invalid_param(void)884418919fSjohnjiang test_parse_etheraddr_invalid_param(void)
894418919fSjohnjiang {
904418919fSjohnjiang char buf[CMDLINE_TEST_BUFSIZE];
914418919fSjohnjiang struct rte_ether_addr result;
924418919fSjohnjiang int ret = 0;
934418919fSjohnjiang
944418919fSjohnjiang /* try all null */
954418919fSjohnjiang ret = cmdline_parse_etheraddr(NULL, NULL, NULL, 0);
964418919fSjohnjiang if (ret != -1) {
974418919fSjohnjiang printf("Error: parser accepted null parameters!\n");
984418919fSjohnjiang return -1;
994418919fSjohnjiang }
1004418919fSjohnjiang
1014418919fSjohnjiang /* try null buf */
1024418919fSjohnjiang ret = cmdline_parse_etheraddr(NULL, NULL, (void*)&result,
1034418919fSjohnjiang sizeof(result));
1044418919fSjohnjiang if (ret != -1) {
1054418919fSjohnjiang printf("Error: parser accepted null string!\n");
1064418919fSjohnjiang return -1;
1074418919fSjohnjiang }
1084418919fSjohnjiang
1094418919fSjohnjiang /* try null result */
1104418919fSjohnjiang
1114418919fSjohnjiang /* copy string to buffer */
1124418919fSjohnjiang strlcpy(buf, ether_addr_valid_strs[0].str, sizeof(buf));
1134418919fSjohnjiang
1144418919fSjohnjiang ret = cmdline_parse_etheraddr(NULL, buf, NULL, 0);
1154418919fSjohnjiang if (ret == -1) {
1164418919fSjohnjiang printf("Error: parser rejected null result!\n");
1174418919fSjohnjiang return -1;
1184418919fSjohnjiang }
1194418919fSjohnjiang
1204418919fSjohnjiang /* token is not used in ether_parse anyway so there's no point in
1214418919fSjohnjiang * testing it */
1224418919fSjohnjiang
1234418919fSjohnjiang /* test help function */
1244418919fSjohnjiang memset(&buf, 0, sizeof(buf));
1254418919fSjohnjiang
1264418919fSjohnjiang /* coverage! */
1274418919fSjohnjiang ret = cmdline_get_help_etheraddr(NULL, buf, sizeof(buf));
1284418919fSjohnjiang if (ret < 0) {
1294418919fSjohnjiang printf("Error: help function failed with valid parameters!\n");
1304418919fSjohnjiang return -1;
1314418919fSjohnjiang }
1324418919fSjohnjiang
1334418919fSjohnjiang return 0;
1344418919fSjohnjiang }
1354418919fSjohnjiang
1364418919fSjohnjiang /* test valid parameters but invalid data */
1374418919fSjohnjiang int
test_parse_etheraddr_invalid_data(void)1384418919fSjohnjiang test_parse_etheraddr_invalid_data(void)
1394418919fSjohnjiang {
1404418919fSjohnjiang int ret = 0;
1414418919fSjohnjiang unsigned i;
1424418919fSjohnjiang struct rte_ether_addr result;
1434418919fSjohnjiang
1444418919fSjohnjiang /* test full strings */
145*2d9fd380Sjfb8856606 for (i = 0; i < RTE_DIM(ether_addr_invalid_strs); i++) {
1464418919fSjohnjiang
1474418919fSjohnjiang memset(&result, 0, sizeof(struct rte_ether_addr));
1484418919fSjohnjiang
1494418919fSjohnjiang ret = cmdline_parse_etheraddr(NULL, ether_addr_invalid_strs[i],
1504418919fSjohnjiang (void*)&result, sizeof(result));
1514418919fSjohnjiang if (ret != -1) {
1524418919fSjohnjiang printf("Error: parsing %s succeeded!\n",
1534418919fSjohnjiang ether_addr_invalid_strs[i]);
1544418919fSjohnjiang return -1;
1554418919fSjohnjiang }
1564418919fSjohnjiang }
1574418919fSjohnjiang
1584418919fSjohnjiang return 0;
1594418919fSjohnjiang }
1604418919fSjohnjiang
1614418919fSjohnjiang /* test valid parameters and data */
1624418919fSjohnjiang int
test_parse_etheraddr_valid(void)1634418919fSjohnjiang test_parse_etheraddr_valid(void)
1644418919fSjohnjiang {
1654418919fSjohnjiang int ret = 0;
1664418919fSjohnjiang unsigned i;
1674418919fSjohnjiang struct rte_ether_addr result;
1684418919fSjohnjiang
1694418919fSjohnjiang /* test full strings */
170*2d9fd380Sjfb8856606 for (i = 0; i < RTE_DIM(ether_addr_valid_strs); i++) {
1714418919fSjohnjiang
1724418919fSjohnjiang memset(&result, 0, sizeof(struct rte_ether_addr));
1734418919fSjohnjiang
1744418919fSjohnjiang ret = cmdline_parse_etheraddr(NULL, ether_addr_valid_strs[i].str,
1754418919fSjohnjiang (void*)&result, sizeof(result));
1764418919fSjohnjiang if (ret < 0) {
1774418919fSjohnjiang printf("Error: parsing %s failed!\n",
1784418919fSjohnjiang ether_addr_valid_strs[i].str);
1794418919fSjohnjiang return -1;
1804418919fSjohnjiang }
1814418919fSjohnjiang if (is_addr_different(result, ether_addr_valid_strs[i].address)) {
1824418919fSjohnjiang printf("Error: parsing %s failed: address mismatch!\n",
1834418919fSjohnjiang ether_addr_valid_strs[i].str);
1844418919fSjohnjiang return -1;
1854418919fSjohnjiang }
1864418919fSjohnjiang }
1874418919fSjohnjiang
1884418919fSjohnjiang /* test garbage strings */
189*2d9fd380Sjfb8856606 for (i = 0; i < RTE_DIM(ether_addr_garbage_strs); i++) {
1904418919fSjohnjiang
1914418919fSjohnjiang memset(&result, 0, sizeof(struct rte_ether_addr));
1924418919fSjohnjiang
1934418919fSjohnjiang ret = cmdline_parse_etheraddr(NULL, ether_addr_garbage_strs[i],
1944418919fSjohnjiang (void*)&result, sizeof(result));
1954418919fSjohnjiang if (ret < 0) {
1964418919fSjohnjiang printf("Error: parsing %s failed!\n",
1974418919fSjohnjiang ether_addr_garbage_strs[i]);
1984418919fSjohnjiang return -1;
1994418919fSjohnjiang }
2004418919fSjohnjiang if (is_addr_different(result, GARBAGE_ETHERADDR)) {
2014418919fSjohnjiang printf("Error: parsing %s failed: address mismatch!\n",
2024418919fSjohnjiang ether_addr_garbage_strs[i]);
2034418919fSjohnjiang return -1;
2044418919fSjohnjiang }
2054418919fSjohnjiang }
2064418919fSjohnjiang
2074418919fSjohnjiang return 0;
2084418919fSjohnjiang }
209