]> git.proxmox.com Git - ceph.git/blame - ceph/src/spdk/dpdk/examples/ip_pipeline/parser.c
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / spdk / dpdk / examples / ip_pipeline / parser.c
CommitLineData
11fdf7f2
TL
1/* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2016 Intel Corporation.
7c673cae
FG
3 * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
4 * All rights reserved.
7c673cae
FG
5 */
6
7/*
8 * For inet_pton4() and inet_pton6() functions:
9 *
10 * Copyright (c) 1996 by Internet Software Consortium.
11 *
12 * Permission to use, copy, modify, and distribute this software for any
13 * purpose with or without fee is hereby granted, provided that the above
14 * copyright notice and this permission notice appear in all copies.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
17 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
19 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
20 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
21 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
22 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
23 * SOFTWARE.
24 */
25
26#include <stdint.h>
27#include <stdlib.h>
28#include <stdio.h>
29#include <ctype.h>
30#include <getopt.h>
31#include <errno.h>
32#include <stdarg.h>
33#include <string.h>
34#include <libgen.h>
35#include <unistd.h>
36#include <sys/wait.h>
37
38#include <rte_errno.h>
7c673cae
FG
39#include <rte_string_fns.h>
40
7c673cae
FG
41#include "parser.h"
42
43static uint32_t
44get_hex_val(char c)
45{
46 switch (c) {
47 case '0': case '1': case '2': case '3': case '4': case '5':
48 case '6': case '7': case '8': case '9':
49 return c - '0';
50 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
51 return c - 'A' + 10;
52 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
53 return c - 'a' + 10;
54 default:
55 return 0;
56 }
57}
58
59int
60parser_read_arg_bool(const char *p)
61{
62 p = skip_white_spaces(p);
63 int result = -EINVAL;
64
65 if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) ||
66 ((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) {
67 p += 3;
68 result = 1;
69 }
70
71 if (((p[0] == 'o') && (p[1] == 'n')) ||
72 ((p[0] == 'O') && (p[1] == 'N'))) {
73 p += 2;
74 result = 1;
75 }
76
77 if (((p[0] == 'n') && (p[1] == 'o')) ||
78 ((p[0] == 'N') && (p[1] == 'O'))) {
79 p += 2;
80 result = 0;
81 }
82
83 if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) ||
84 ((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) {
85 p += 3;
86 result = 0;
87 }
88
89 p = skip_white_spaces(p);
90
91 if (p[0] != '\0')
92 return -EINVAL;
93
94 return result;
95}
96
97int
98parser_read_uint64(uint64_t *value, const char *p)
99{
100 char *next;
101 uint64_t val;
102
103 p = skip_white_spaces(p);
104 if (!isdigit(*p))
105 return -EINVAL;
106
107 val = strtoul(p, &next, 10);
108 if (p == next)
109 return -EINVAL;
110
111 p = next;
112 switch (*p) {
113 case 'T':
114 val *= 1024ULL;
115 /* fall through */
116 case 'G':
117 val *= 1024ULL;
118 /* fall through */
119 case 'M':
120 val *= 1024ULL;
121 /* fall through */
122 case 'k':
123 case 'K':
124 val *= 1024ULL;
125 p++;
126 break;
127 }
128
129 p = skip_white_spaces(p);
130 if (*p != '\0')
131 return -EINVAL;
132
133 *value = val;
134 return 0;
135}
136
137int
138parser_read_uint64_hex(uint64_t *value, const char *p)
139{
140 char *next;
141 uint64_t val;
142
143 p = skip_white_spaces(p);
144
145 val = strtoul(p, &next, 16);
146 if (p == next)
147 return -EINVAL;
148
149 p = skip_white_spaces(next);
150 if (*p != '\0')
151 return -EINVAL;
152
153 *value = val;
154 return 0;
155}
156
157int
158parser_read_uint32(uint32_t *value, const char *p)
159{
160 uint64_t val = 0;
161 int ret = parser_read_uint64(&val, p);
162
163 if (ret < 0)
164 return ret;
165
166 if (val > UINT32_MAX)
167 return -ERANGE;
168
169 *value = val;
170 return 0;
171}
172
173int
174parser_read_uint32_hex(uint32_t *value, const char *p)
175{
176 uint64_t val = 0;
177 int ret = parser_read_uint64_hex(&val, p);
178
179 if (ret < 0)
180 return ret;
181
182 if (val > UINT32_MAX)
183 return -ERANGE;
184
185 *value = val;
186 return 0;
187}
188
189int
190parser_read_uint16(uint16_t *value, const char *p)
191{
192 uint64_t val = 0;
193 int ret = parser_read_uint64(&val, p);
194
195 if (ret < 0)
196 return ret;
197
198 if (val > UINT16_MAX)
199 return -ERANGE;
200
201 *value = val;
202 return 0;
203}
204
205int
206parser_read_uint16_hex(uint16_t *value, const char *p)
207{
208 uint64_t val = 0;
209 int ret = parser_read_uint64_hex(&val, p);
210
211 if (ret < 0)
212 return ret;
213
214 if (val > UINT16_MAX)
215 return -ERANGE;
216
217 *value = val;
218 return 0;
219}
220
221int
222parser_read_uint8(uint8_t *value, const char *p)
223{
224 uint64_t val = 0;
225 int ret = parser_read_uint64(&val, p);
226
227 if (ret < 0)
228 return ret;
229
230 if (val > UINT8_MAX)
231 return -ERANGE;
232
233 *value = val;
234 return 0;
235}
236
237int
238parser_read_uint8_hex(uint8_t *value, const char *p)
239{
240 uint64_t val = 0;
241 int ret = parser_read_uint64_hex(&val, p);
242
243 if (ret < 0)
244 return ret;
245
246 if (val > UINT8_MAX)
247 return -ERANGE;
248
249 *value = val;
250 return 0;
251}
252
253int
254parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
255{
256 uint32_t i;
257
258 if ((string == NULL) ||
259 (tokens == NULL) ||
260 (*n_tokens < 1))
261 return -EINVAL;
262
263 for (i = 0; i < *n_tokens; i++) {
264 tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
265 if (tokens[i] == NULL)
266 break;
267 }
268
269 if ((i == *n_tokens) &&
270 (NULL != strtok_r(string, PARSE_DELIMITER, &string)))
271 return -E2BIG;
272
273 *n_tokens = i;
274 return 0;
275}
276
277int
278parse_hex_string(char *src, uint8_t *dst, uint32_t *size)
279{
280 char *c;
281 uint32_t len, i;
282
283 /* Check input parameters */
284 if ((src == NULL) ||
285 (dst == NULL) ||
286 (size == NULL) ||
287 (*size == 0))
288 return -1;
289
290 len = strlen(src);
291 if (((len & 3) != 0) ||
292 (len > (*size) * 2))
293 return -1;
294 *size = len / 2;
295
296 for (c = src; *c != 0; c++) {
297 if ((((*c) >= '0') && ((*c) <= '9')) ||
298 (((*c) >= 'A') && ((*c) <= 'F')) ||
299 (((*c) >= 'a') && ((*c) <= 'f')))
300 continue;
301
302 return -1;
303 }
304
305 /* Convert chars to bytes */
306 for (i = 0; i < *size; i++)
307 dst[i] = get_hex_val(src[2 * i]) * 16 +
308 get_hex_val(src[2 * i + 1]);
309
310 return 0;
311}
312
313int
314parse_mpls_labels(char *string, uint32_t *labels, uint32_t *n_labels)
315{
316 uint32_t n_max_labels = *n_labels, count = 0;
317
318 /* Check for void list of labels */
319 if (strcmp(string, "<void>") == 0) {
320 *n_labels = 0;
321 return 0;
322 }
323
324 /* At least one label should be present */
325 for ( ; (*string != '\0'); ) {
326 char *next;
327 int value;
328
329 if (count >= n_max_labels)
330 return -1;
331
332 if (count > 0) {
333 if (string[0] != ':')
334 return -1;
335
336 string++;
337 }
338
339 value = strtol(string, &next, 10);
340 if (next == string)
341 return -1;
342 string = next;
343
344 labels[count++] = (uint32_t) value;
345 }
346
347 *n_labels = count;
348 return 0;
349}
350
351#define INADDRSZ 4
352#define IN6ADDRSZ 16
353
354/* int
355 * inet_pton4(src, dst)
356 * like inet_aton() but without all the hexadecimal and shorthand.
357 * return:
358 * 1 if `src' is a valid dotted quad, else 0.
359 * notice:
360 * does not touch `dst' unless it's returning 1.
361 * author:
362 * Paul Vixie, 1996.
363 */
364static int
365inet_pton4(const char *src, unsigned char *dst)
366{
367 static const char digits[] = "0123456789";
368 int saw_digit, octets, ch;
369 unsigned char tmp[INADDRSZ], *tp;
370
371 saw_digit = 0;
372 octets = 0;
373 *(tp = tmp) = 0;
374 while ((ch = *src++) != '\0') {
375 const char *pch;
376
377 pch = strchr(digits, ch);
378 if (pch != NULL) {
379 unsigned int new = *tp * 10 + (pch - digits);
380
381 if (new > 255)
382 return 0;
383 if (!saw_digit) {
384 if (++octets > 4)
385 return 0;
386 saw_digit = 1;
387 }
388 *tp = (unsigned char)new;
389 } else if (ch == '.' && saw_digit) {
390 if (octets == 4)
391 return 0;
392 *++tp = 0;
393 saw_digit = 0;
394 } else
395 return 0;
396 }
397 if (octets < 4)
398 return 0;
399
400 memcpy(dst, tmp, INADDRSZ);
401 return 1;
402}
403
404/* int
405 * inet_pton6(src, dst)
406 * convert presentation level address to network order binary form.
407 * return:
408 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
409 * notice:
410 * (1) does not touch `dst' unless it's returning 1.
411 * (2) :: in a full address is silently ignored.
412 * credit:
413 * inspired by Mark Andrews.
414 * author:
415 * Paul Vixie, 1996.
416 */
417static int
418inet_pton6(const char *src, unsigned char *dst)
419{
420 static const char xdigits_l[] = "0123456789abcdef",
421 xdigits_u[] = "0123456789ABCDEF";
422 unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0;
423 const char *xdigits = 0, *curtok = 0;
424 int ch = 0, saw_xdigit = 0, count_xdigit = 0;
425 unsigned int val = 0;
426 unsigned dbloct_count = 0;
427
428 memset((tp = tmp), '\0', IN6ADDRSZ);
429 endp = tp + IN6ADDRSZ;
430 colonp = NULL;
431 /* Leading :: requires some special handling. */
432 if (*src == ':')
433 if (*++src != ':')
434 return 0;
435 curtok = src;
436 saw_xdigit = count_xdigit = 0;
437 val = 0;
438
439 while ((ch = *src++) != '\0') {
440 const char *pch;
441
442 pch = strchr((xdigits = xdigits_l), ch);
443 if (pch == NULL)
444 pch = strchr((xdigits = xdigits_u), ch);
445 if (pch != NULL) {
446 if (count_xdigit >= 4)
447 return 0;
448 val <<= 4;
449 val |= (pch - xdigits);
450 if (val > 0xffff)
451 return 0;
452 saw_xdigit = 1;
453 count_xdigit++;
454 continue;
455 }
456 if (ch == ':') {
457 curtok = src;
458 if (!saw_xdigit) {
459 if (colonp)
460 return 0;
461 colonp = tp;
462 continue;
463 } else if (*src == '\0') {
464 return 0;
465 }
466 if (tp + sizeof(int16_t) > endp)
467 return 0;
468 *tp++ = (unsigned char) ((val >> 8) & 0xff);
469 *tp++ = (unsigned char) (val & 0xff);
470 saw_xdigit = 0;
471 count_xdigit = 0;
472 val = 0;
473 dbloct_count++;
474 continue;
475 }
476 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
477 inet_pton4(curtok, tp) > 0) {
478 tp += INADDRSZ;
479 saw_xdigit = 0;
480 dbloct_count += 2;
481 break; /* '\0' was seen by inet_pton4(). */
482 }
483 return 0;
484 }
485 if (saw_xdigit) {
486 if (tp + sizeof(int16_t) > endp)
487 return 0;
488 *tp++ = (unsigned char) ((val >> 8) & 0xff);
489 *tp++ = (unsigned char) (val & 0xff);
490 dbloct_count++;
491 }
492 if (colonp != NULL) {
493 /* if we already have 8 double octets, having a colon means error */
494 if (dbloct_count == 8)
495 return 0;
496
497 /*
498 * Since some memmove()'s erroneously fail to handle
499 * overlapping regions, we'll do the shift by hand.
500 */
501 const int n = tp - colonp;
502 int i;
503
504 for (i = 1; i <= n; i++) {
505 endp[-i] = colonp[n - i];
506 colonp[n - i] = 0;
507 }
508 tp = endp;
509 }
510 if (tp != endp)
511 return 0;
512 memcpy(dst, tmp, IN6ADDRSZ);
513 return 1;
514}
515
f67539c2 516static struct rte_ether_addr *
7c673cae
FG
517my_ether_aton(const char *a)
518{
519 int i;
520 char *end;
f67539c2
TL
521 unsigned long o[RTE_ETHER_ADDR_LEN];
522 static struct rte_ether_addr ether_addr;
7c673cae
FG
523
524 i = 0;
525 do {
526 errno = 0;
527 o[i] = strtoul(a, &end, 16);
528 if (errno != 0 || end == a || (end[0] != ':' && end[0] != 0))
529 return NULL;
530 a = end + 1;
f67539c2 531 } while (++i != RTE_DIM(o) && end[0] != 0);
7c673cae
FG
532
533 /* Junk at the end of line */
534 if (end[0] != 0)
535 return NULL;
536
537 /* Support the format XX:XX:XX:XX:XX:XX */
f67539c2 538 if (i == RTE_ETHER_ADDR_LEN) {
7c673cae
FG
539 while (i-- != 0) {
540 if (o[i] > UINT8_MAX)
541 return NULL;
542 ether_addr.addr_bytes[i] = (uint8_t)o[i];
543 }
544 /* Support the format XXXX:XXXX:XXXX */
f67539c2 545 } else if (i == RTE_ETHER_ADDR_LEN / 2) {
7c673cae
FG
546 while (i-- != 0) {
547 if (o[i] > UINT16_MAX)
548 return NULL;
549 ether_addr.addr_bytes[i * 2] = (uint8_t)(o[i] >> 8);
550 ether_addr.addr_bytes[i * 2 + 1] = (uint8_t)(o[i] & 0xff);
551 }
552 /* unknown format */
553 } else
554 return NULL;
555
f67539c2 556 return (struct rte_ether_addr *)&ether_addr;
7c673cae
FG
557}
558
559int
560parse_ipv4_addr(const char *token, struct in_addr *ipv4)
561{
562 if (strlen(token) >= INET_ADDRSTRLEN)
563 return -EINVAL;
564
565 if (inet_pton4(token, (unsigned char *)ipv4) != 1)
566 return -EINVAL;
567
568 return 0;
569}
570
571int
572parse_ipv6_addr(const char *token, struct in6_addr *ipv6)
573{
574 if (strlen(token) >= INET6_ADDRSTRLEN)
575 return -EINVAL;
576
577 if (inet_pton6(token, (unsigned char *)ipv6) != 1)
578 return -EINVAL;
579
580 return 0;
581}
582
583int
f67539c2 584parse_mac_addr(const char *token, struct rte_ether_addr *addr)
7c673cae 585{
f67539c2 586 struct rte_ether_addr *tmp;
7c673cae
FG
587
588 tmp = my_ether_aton(token);
589 if (tmp == NULL)
590 return -1;
591
f67539c2 592 memcpy(addr, tmp, sizeof(struct rte_ether_addr));
7c673cae
FG
593 return 0;
594}
595
596int
11fdf7f2
TL
597parse_cpu_core(const char *entry,
598 struct cpu_core_params *p)
7c673cae
FG
599{
600 size_t num_len;
601 char num[8];
602
603 uint32_t s = 0, c = 0, h = 0, val;
604 uint8_t s_parsed = 0, c_parsed = 0, h_parsed = 0;
605 const char *next = skip_white_spaces(entry);
606 char type;
607
11fdf7f2
TL
608 if (p == NULL)
609 return -EINVAL;
610
7c673cae
FG
611 /* Expect <CORE> or [sX][cY][h]. At least one parameter is required. */
612 while (*next != '\0') {
613 /* If everything parsed nothing should left */
614 if (s_parsed && c_parsed && h_parsed)
615 return -EINVAL;
616
617 type = *next;
618 switch (type) {
619 case 's':
620 case 'S':
621 if (s_parsed || c_parsed || h_parsed)
622 return -EINVAL;
623 s_parsed = 1;
624 next++;
625 break;
626 case 'c':
627 case 'C':
628 if (c_parsed || h_parsed)
629 return -EINVAL;
630 c_parsed = 1;
631 next++;
632 break;
633 case 'h':
634 case 'H':
635 if (h_parsed)
636 return -EINVAL;
637 h_parsed = 1;
638 next++;
639 break;
640 default:
641 /* If it start from digit it must be only core id. */
642 if (!isdigit(*next) || s_parsed || c_parsed || h_parsed)
643 return -EINVAL;
644
645 type = 'C';
646 }
647
648 for (num_len = 0; *next != '\0'; next++, num_len++) {
649 if (num_len == RTE_DIM(num))
650 return -EINVAL;
651
652 if (!isdigit(*next))
653 break;
654
655 num[num_len] = *next;
656 }
657
658 if (num_len == 0 && type != 'h' && type != 'H')
659 return -EINVAL;
660
661 if (num_len != 0 && (type == 'h' || type == 'H'))
662 return -EINVAL;
663
664 num[num_len] = '\0';
665 val = strtol(num, NULL, 10);
666
667 h = 0;
668 switch (type) {
669 case 's':
670 case 'S':
671 s = val;
672 break;
673 case 'c':
674 case 'C':
675 c = val;
676 break;
677 case 'h':
678 case 'H':
679 h = 1;
680 break;
681 }
682 }
683
11fdf7f2
TL
684 p->socket_id = s;
685 p->core_id = c;
686 p->thread_id = h;
7c673cae
FG
687 return 0;
688}