1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2016 Intel Corporation.
3 * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
7 /* For inet_pton4() and inet_pton6() functions:
9 * Copyright (c) 1996 by Internet Software Consortium.
11 * Permission to use, copy, modify, and distribute this software for any
12 * purpose with or without fee is hereby granted, provided that the above
13 * copyright notice and this permission notice appear in all copies.
15 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
16 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
18 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
19 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
20 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
21 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
37 #include <rte_errno.h>
45 case '0': case '1': case '2': case '3': case '4': case '5':
46 case '6': case '7': case '8': case '9':
48 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
50 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
58 softnic_parser_read_arg_bool(const char *p)
60 p = skip_white_spaces(p);
63 if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) ||
64 ((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) {
69 if (((p[0] == 'o') && (p[1] == 'n')) ||
70 ((p[0] == 'O') && (p[1] == 'N'))) {
75 if (((p[0] == 'n') && (p[1] == 'o')) ||
76 ((p[0] == 'N') && (p[1] == 'O'))) {
81 if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) ||
82 ((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) {
87 p = skip_white_spaces(p);
96 softnic_parser_read_int32(int32_t *value, const char *p)
101 p = skip_white_spaces(p);
105 val = strtol(p, &next, 10);
114 softnic_parser_read_uint64(uint64_t *value, const char *p)
119 p = skip_white_spaces(p);
123 val = strtoul(p, &next, 10);
145 p = skip_white_spaces(p);
154 softnic_parser_read_uint64_hex(uint64_t *value, const char *p)
159 p = skip_white_spaces(p);
161 val = strtoul(p, &next, 16);
165 p = skip_white_spaces(next);
174 softnic_parser_read_uint32(uint32_t *value, const char *p)
177 int ret = softnic_parser_read_uint64(&val, p);
182 if (val > UINT32_MAX)
190 softnic_parser_read_uint32_hex(uint32_t *value, const char *p)
193 int ret = softnic_parser_read_uint64_hex(&val, p);
198 if (val > UINT32_MAX)
206 softnic_parser_read_uint16(uint16_t *value, const char *p)
209 int ret = softnic_parser_read_uint64(&val, p);
214 if (val > UINT16_MAX)
222 softnic_parser_read_uint16_hex(uint16_t *value, const char *p)
225 int ret = softnic_parser_read_uint64_hex(&val, p);
230 if (val > UINT16_MAX)
238 softnic_parser_read_uint8(uint8_t *value, const char *p)
241 int ret = softnic_parser_read_uint64(&val, p);
254 softnic_parser_read_uint8_hex(uint8_t *value, const char *p)
257 int ret = softnic_parser_read_uint64_hex(&val, p);
270 softnic_parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
274 if (string == NULL ||
279 for (i = 0; i < *n_tokens; i++) {
280 tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
281 if (tokens[i] == NULL)
285 if (i == *n_tokens &&
286 strtok_r(string, PARSE_DELIMITER, &string) != NULL)
294 softnic_parse_hex_string(char *src, uint8_t *dst, uint32_t *size)
299 /* Check input parameters */
307 if (((len & 3) != 0) ||
312 for (c = src; *c != 0; c++) {
313 if ((((*c) >= '0') && ((*c) <= '9')) ||
314 (((*c) >= 'A') && ((*c) <= 'F')) ||
315 (((*c) >= 'a') && ((*c) <= 'f')))
321 /* Convert chars to bytes */
322 for (i = 0; i < *size; i++)
323 dst[i] = get_hex_val(src[2 * i]) * 16 +
324 get_hex_val(src[2 * i + 1]);
330 softnic_parse_mpls_labels(char *string, uint32_t *labels, uint32_t *n_labels)
332 uint32_t n_max_labels = *n_labels, count = 0;
334 /* Check for void list of labels */
335 if (strcmp(string, "<void>") == 0) {
340 /* At least one label should be present */
341 for ( ; (*string != '\0'); ) {
345 if (count >= n_max_labels)
349 if (string[0] != ':')
355 value = strtol(string, &next, 10);
360 labels[count++] = (uint32_t)value;
371 * inet_pton4(src, dst)
372 * like inet_aton() but without all the hexadecimal and shorthand.
374 * 1 if `src' is a valid dotted quad, else 0.
376 * does not touch `dst' unless it's returning 1.
381 inet_pton4(const char *src, unsigned char *dst)
383 static const char digits[] = "0123456789";
384 int saw_digit, octets, ch;
385 unsigned char tmp[INADDRSZ], *tp;
390 while ((ch = *src++) != '\0') {
393 pch = strchr(digits, ch);
395 unsigned int new = *tp * 10 + (pch - digits);
404 *tp = (unsigned char)new;
405 } else if (ch == '.' && saw_digit) {
416 memcpy(dst, tmp, INADDRSZ);
421 * inet_pton6(src, dst)
422 * convert presentation level address to network order binary form.
424 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
426 * (1) does not touch `dst' unless it's returning 1.
427 * (2) :: in a full address is silently ignored.
429 * inspired by Mark Andrews.
434 inet_pton6(const char *src, unsigned char *dst)
436 static const char xdigits_l[] = "0123456789abcdef",
437 xdigits_u[] = "0123456789ABCDEF";
438 unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0;
439 const char *xdigits = 0, *curtok = 0;
440 int ch = 0, saw_xdigit = 0, count_xdigit = 0;
441 unsigned int val = 0;
442 unsigned int dbloct_count = 0;
444 memset((tp = tmp), '\0', IN6ADDRSZ);
445 endp = tp + IN6ADDRSZ;
447 /* Leading :: requires some special handling. */
452 saw_xdigit = count_xdigit = 0;
455 while ((ch = *src++) != '\0') {
458 pch = strchr((xdigits = xdigits_l), ch);
460 pch = strchr((xdigits = xdigits_u), ch);
462 if (count_xdigit >= 4)
465 val |= (pch - xdigits);
479 } else if (*src == '\0') {
482 if (tp + sizeof(int16_t) > endp)
484 *tp++ = (unsigned char)((val >> 8) & 0xff);
485 *tp++ = (unsigned char)(val & 0xff);
492 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
493 inet_pton4(curtok, tp) > 0) {
497 break; /* '\0' was seen by inet_pton4(). */
502 if (tp + sizeof(int16_t) > endp)
504 *tp++ = (unsigned char)((val >> 8) & 0xff);
505 *tp++ = (unsigned char)(val & 0xff);
508 if (colonp != NULL) {
509 /* if we already have 8 double octets, having a colon means error */
510 if (dbloct_count == 8)
513 /* Since some memmove()'s erroneously fail to handle
514 * overlapping regions, we'll do the shift by hand.
516 const int n = tp - colonp;
519 for (i = 1; i <= n; i++) {
520 endp[-i] = colonp[n - i];
527 memcpy(dst, tmp, IN6ADDRSZ);
531 static struct rte_ether_addr *
532 my_ether_aton(const char *a)
536 unsigned long o[RTE_ETHER_ADDR_LEN];
537 static struct rte_ether_addr ether_addr;
542 o[i] = strtoul(a, &end, 16);
543 if (errno != 0 || end == a || (end[0] != ':' && end[0] != 0))
546 } while (++i != sizeof(o) / sizeof(o[0]) && end[0] != 0);
548 /* Junk at the end of line */
552 /* Support the format XX:XX:XX:XX:XX:XX */
553 if (i == RTE_ETHER_ADDR_LEN) {
555 if (o[i] > UINT8_MAX)
557 ether_addr.addr_bytes[i] = (uint8_t)o[i];
559 /* Support the format XXXX:XXXX:XXXX */
560 } else if (i == RTE_ETHER_ADDR_LEN / 2) {
562 if (o[i] > UINT16_MAX)
564 ether_addr.addr_bytes[i * 2] = (uint8_t)(o[i] >> 8);
565 ether_addr.addr_bytes[i * 2 + 1] = (uint8_t)(o[i] & 0xff);
571 return (struct rte_ether_addr *)ðer_addr;
575 softnic_parse_ipv4_addr(const char *token, struct in_addr *ipv4)
577 if (strlen(token) >= INET_ADDRSTRLEN)
580 if (inet_pton4(token, (unsigned char *)ipv4) != 1)
587 softnic_parse_ipv6_addr(const char *token, struct in6_addr *ipv6)
589 if (strlen(token) >= INET6_ADDRSTRLEN)
592 if (inet_pton6(token, (unsigned char *)ipv6) != 1)
599 softnic_parse_mac_addr(const char *token, struct rte_ether_addr *addr)
601 struct rte_ether_addr *tmp;
603 tmp = my_ether_aton(token);
607 memcpy(addr, tmp, sizeof(struct rte_ether_addr));
612 softnic_parse_cpu_core(const char *entry,
613 struct softnic_cpu_core_params *p)
618 uint32_t s = 0, c = 0, h = 0, val;
619 uint8_t s_parsed = 0, c_parsed = 0, h_parsed = 0;
620 const char *next = skip_white_spaces(entry);
626 /* Expect <CORE> or [sX][cY][h]. At least one parameter is required. */
627 while (*next != '\0') {
628 /* If everything parsed nothing should left */
629 if (s_parsed && c_parsed && h_parsed)
636 if (s_parsed || c_parsed || h_parsed)
643 if (c_parsed || h_parsed)
656 /* If it start from digit it must be only core id. */
657 if (!isdigit(*next) || s_parsed || c_parsed || h_parsed)
663 for (num_len = 0; *next != '\0'; next++, num_len++) {
664 if (num_len == RTE_DIM(num))
670 num[num_len] = *next;
673 if (num_len == 0 && type != 'h' && type != 'H')
676 if (num_len != 0 && (type == 'h' || type == 'H'))
680 val = strtol(num, NULL, 10);