net/i40e: fix Rx packet statistics
[dpdk.git] / drivers / net / softnic / parser.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2016 Intel Corporation.
3  * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
4  * All rights reserved.
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
25 static uint32_t
26 get_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
41 int
42 softnic_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
79 int
80 softnic_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
97 int
98 softnic_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                 /* 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
137 int
138 softnic_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
157 int
158 softnic_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
173 int
174 softnic_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
189 int
190 softnic_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
205 int
206 softnic_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
221 int
222 softnic_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
237 int
238 softnic_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
253 int
254 softnic_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
277 int
278 softnic_parse_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
313 int
314 softnic_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         /* 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 static struct rte_ether_addr *
352 my_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         /* Junk at the end of line */
369         if (end[0] != 0)
370                 return NULL;
371
372         /* Support the format XX:XX:XX:XX:XX:XX */
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         /* Support the format XXXX:XXXX:XXXX */
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         /* unknown format */
388         } else
389                 return NULL;
390
391         return (struct rte_ether_addr *)&ether_addr;
392 }
393
394 int
395 softnic_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
406 int
407 softnic_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
418 int
419 softnic_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
431 int
432 softnic_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         /* Expect <CORE> or [sX][cY][h]. At least one parameter is required. */
447         while (*next != '\0') {
448                 /* If everything parsed nothing should left */
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                         /* If it start from digit it must be only core id. */
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 }