1
2
3
4
5
6
7#include <stdint.h>
8#include <stdlib.h>
9#include <stdio.h>
10#include <ctype.h>
11#include <getopt.h>
12#include <errno.h>
13#include <stdarg.h>
14#include <string.h>
15#include <libgen.h>
16#include <unistd.h>
17#include <sys/wait.h>
18#include <arpa/inet.h>
19#include <sys/socket.h>
20
21#include <rte_errno.h>
22
23#include "parser.h"
24
25static uint32_t
26get_hex_val(char c)
27{
28 switch (c) {
29 case '0': case '1': case '2': case '3': case '4': case '5':
30 case '6': case '7': case '8': case '9':
31 return c - '0';
32 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
33 return c - 'A' + 10;
34 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
35 return c - 'a' + 10;
36 default:
37 return 0;
38 }
39}
40
41int
42softnic_parser_read_arg_bool(const char *p)
43{
44 p = skip_white_spaces(p);
45 int result = -EINVAL;
46
47 if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) ||
48 ((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) {
49 p += 3;
50 result = 1;
51 }
52
53 if (((p[0] == 'o') && (p[1] == 'n')) ||
54 ((p[0] == 'O') && (p[1] == 'N'))) {
55 p += 2;
56 result = 1;
57 }
58
59 if (((p[0] == 'n') && (p[1] == 'o')) ||
60 ((p[0] == 'N') && (p[1] == 'O'))) {
61 p += 2;
62 result = 0;
63 }
64
65 if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) ||
66 ((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) {
67 p += 3;
68 result = 0;
69 }
70
71 p = skip_white_spaces(p);
72
73 if (p[0] != '\0')
74 return -EINVAL;
75
76 return result;
77}
78
79int
80softnic_parser_read_int32(int32_t *value, const char *p)
81{
82 char *next;
83 int32_t val;
84
85 p = skip_white_spaces(p);
86 if (!isdigit(*p))
87 return -EINVAL;
88
89 val = strtol(p, &next, 10);
90 if (p == next)
91 return -EINVAL;
92
93 *value = val;
94 return 0;
95}
96
97int
98softnic_parser_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
116 case 'G':
117 val *= 1024ULL;
118
119 case 'M':
120 val *= 1024ULL;
121
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
138softnic_parser_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
158softnic_parser_read_uint32(uint32_t *value, const char *p)
159{
160 uint64_t val = 0;
161 int ret = softnic_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
174softnic_parser_read_uint32_hex(uint32_t *value, const char *p)
175{
176 uint64_t val = 0;
177 int ret = softnic_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
190softnic_parser_read_uint16(uint16_t *value, const char *p)
191{
192 uint64_t val = 0;
193 int ret = softnic_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
206softnic_parser_read_uint16_hex(uint16_t *value, const char *p)
207{
208 uint64_t val = 0;
209 int ret = softnic_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
222softnic_parser_read_uint8(uint8_t *value, const char *p)
223{
224 uint64_t val = 0;
225 int ret = softnic_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
238softnic_parser_read_uint8_hex(uint8_t *value, const char *p)
239{
240 uint64_t val = 0;
241 int ret = softnic_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
254softnic_parse_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 strtok_r(string, PARSE_DELIMITER, &string) != NULL)
271 return -E2BIG;
272
273 *n_tokens = i;
274 return 0;
275}
276
277int
278softnic_parse_hex_string(char *src, uint8_t *dst, uint32_t *size)
279{
280 char *c;
281 uint32_t len, i;
282
283
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
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
314softnic_parse_mpls_labels(char *string, uint32_t *labels, uint32_t *n_labels)
315{
316 uint32_t n_max_labels = *n_labels, count = 0;
317
318
319 if (strcmp(string, "<void>") == 0) {
320 *n_labels = 0;
321 return 0;
322 }
323
324
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
351static struct rte_ether_addr *
352my_ether_aton(const char *a)
353{
354 int i;
355 char *end;
356 unsigned long o[RTE_ETHER_ADDR_LEN];
357 static struct rte_ether_addr ether_addr;
358
359 i = 0;
360 do {
361 errno = 0;
362 o[i] = strtoul(a, &end, 16);
363 if (errno != 0 || end == a || (end[0] != ':' && end[0] != 0))
364 return NULL;
365 a = end + 1;
366 } while (++i != sizeof(o) / sizeof(o[0]) && end[0] != 0);
367
368
369 if (end[0] != 0)
370 return NULL;
371
372
373 if (i == RTE_ETHER_ADDR_LEN) {
374 while (i-- != 0) {
375 if (o[i] > UINT8_MAX)
376 return NULL;
377 ether_addr.addr_bytes[i] = (uint8_t)o[i];
378 }
379
380 } else if (i == RTE_ETHER_ADDR_LEN / 2) {
381 while (i-- != 0) {
382 if (o[i] > UINT16_MAX)
383 return NULL;
384 ether_addr.addr_bytes[i * 2] = (uint8_t)(o[i] >> 8);
385 ether_addr.addr_bytes[i * 2 + 1] = (uint8_t)(o[i] & 0xff);
386 }
387
388 } else
389 return NULL;
390
391 return (struct rte_ether_addr *)ðer_addr;
392}
393
394int
395softnic_parse_ipv4_addr(const char *token, struct in_addr *ipv4)
396{
397 if (strlen(token) >= INET_ADDRSTRLEN)
398 return -EINVAL;
399
400 if (inet_pton(AF_INET, token, ipv4) != 1)
401 return -EINVAL;
402
403 return 0;
404}
405
406int
407softnic_parse_ipv6_addr(const char *token, struct in6_addr *ipv6)
408{
409 if (strlen(token) >= INET6_ADDRSTRLEN)
410 return -EINVAL;
411
412 if (inet_pton(AF_INET6, token, ipv6) != 1)
413 return -EINVAL;
414
415 return 0;
416}
417
418int
419softnic_parse_mac_addr(const char *token, struct rte_ether_addr *addr)
420{
421 struct rte_ether_addr *tmp;
422
423 tmp = my_ether_aton(token);
424 if (tmp == NULL)
425 return -1;
426
427 memcpy(addr, tmp, sizeof(struct rte_ether_addr));
428 return 0;
429}
430
431int
432softnic_parse_cpu_core(const char *entry,
433 struct softnic_cpu_core_params *p)
434{
435 size_t num_len;
436 char num[8];
437
438 uint32_t s = 0, c = 0, h = 0, val;
439 uint8_t s_parsed = 0, c_parsed = 0, h_parsed = 0;
440 const char *next = skip_white_spaces(entry);
441 char type;
442
443 if (p == NULL)
444 return -EINVAL;
445
446
447 while (*next != '\0') {
448
449 if (s_parsed && c_parsed && h_parsed)
450 return -EINVAL;
451
452 type = *next;
453 switch (type) {
454 case 's':
455 case 'S':
456 if (s_parsed || c_parsed || h_parsed)
457 return -EINVAL;
458 s_parsed = 1;
459 next++;
460 break;
461 case 'c':
462 case 'C':
463 if (c_parsed || h_parsed)
464 return -EINVAL;
465 c_parsed = 1;
466 next++;
467 break;
468 case 'h':
469 case 'H':
470 if (h_parsed)
471 return -EINVAL;
472 h_parsed = 1;
473 next++;
474 break;
475 default:
476
477 if (!isdigit(*next) || s_parsed || c_parsed || h_parsed)
478 return -EINVAL;
479
480 type = 'C';
481 }
482
483 for (num_len = 0; *next != '\0'; next++, num_len++) {
484 if (num_len == RTE_DIM(num))
485 return -EINVAL;
486
487 if (!isdigit(*next))
488 break;
489
490 num[num_len] = *next;
491 }
492
493 if (num_len == 0 && type != 'h' && type != 'H')
494 return -EINVAL;
495
496 if (num_len != 0 && (type == 'h' || type == 'H'))
497 return -EINVAL;
498
499 num[num_len] = '\0';
500 val = strtol(num, NULL, 10);
501
502 h = 0;
503 switch (type) {
504 case 's':
505 case 'S':
506 s = val;
507 break;
508 case 'c':
509 case 'C':
510 c = val;
511 break;
512 case 'h':
513 case 'H':
514 h = 1;
515 break;
516 }
517 }
518
519 p->socket_id = s;
520 p->core_id = c;
521 p->thread_id = h;
522 return 0;
523}
524