xref: /f-stack/dpdk/drivers/net/softnic/parser.c (revision 0c6bd470)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2016 Intel Corporation.
3  * Copyright (c) 2009, Olivier MATZ <[email protected]>
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
get_hex_val(char c)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
softnic_parser_read_arg_bool(const char * p)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
softnic_parser_read_int32(int32_t * value,const char * p)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
softnic_parser_read_uint64(uint64_t * value,const char * p)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
softnic_parser_read_uint64_hex(uint64_t * value,const char * p)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
softnic_parser_read_uint32(uint32_t * value,const char * p)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
softnic_parser_read_uint32_hex(uint32_t * value,const char * p)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
softnic_parser_read_uint16(uint16_t * value,const char * p)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
softnic_parser_read_uint16_hex(uint16_t * value,const char * p)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
softnic_parser_read_uint8(uint8_t * value,const char * p)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
softnic_parser_read_uint8_hex(uint8_t * value,const char * p)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
softnic_parse_tokenize_string(char * string,char * tokens[],uint32_t * n_tokens)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
softnic_parse_hex_string(char * src,uint8_t * dst,uint32_t * size)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
softnic_parse_mpls_labels(char * string,uint32_t * labels,uint32_t * n_labels)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 *
my_ether_aton(const char * a)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
softnic_parse_ipv4_addr(const char * token,struct in_addr * ipv4)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
softnic_parse_ipv6_addr(const char * token,struct in6_addr * ipv6)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
softnic_parse_mac_addr(const char * token,struct rte_ether_addr * addr)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
softnic_parse_cpu_core(const char * entry,struct softnic_cpu_core_params * p)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 }
524