xref: /f-stack/dpdk/examples/ip_pipeline/parser.c (revision 2d9fd380)
1d30ea906Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause
2d30ea906Sjfb8856606  * Copyright(c) 2016 Intel Corporation.
3a9643ea8Slogwang  * Copyright (c) 2009, Olivier MATZ <[email protected]>
4a9643ea8Slogwang  * All rights reserved.
5a9643ea8Slogwang  */
6a9643ea8Slogwang 
7a9643ea8Slogwang #include <stdint.h>
8a9643ea8Slogwang #include <stdlib.h>
9a9643ea8Slogwang #include <stdio.h>
10a9643ea8Slogwang #include <ctype.h>
11a9643ea8Slogwang #include <getopt.h>
12a9643ea8Slogwang #include <errno.h>
13a9643ea8Slogwang #include <stdarg.h>
14a9643ea8Slogwang #include <string.h>
15a9643ea8Slogwang #include <libgen.h>
16a9643ea8Slogwang #include <unistd.h>
17a9643ea8Slogwang #include <sys/wait.h>
180c6bd470Sfengbojiang #include <arpa/inet.h>
190c6bd470Sfengbojiang #include <sys/socket.h>
20a9643ea8Slogwang 
21a9643ea8Slogwang #include <rte_errno.h>
22a9643ea8Slogwang #include <rte_string_fns.h>
23a9643ea8Slogwang 
24a9643ea8Slogwang #include "parser.h"
25a9643ea8Slogwang 
26a9643ea8Slogwang static uint32_t
get_hex_val(char c)27a9643ea8Slogwang get_hex_val(char c)
28a9643ea8Slogwang {
29a9643ea8Slogwang 	switch (c) {
30a9643ea8Slogwang 	case '0': case '1': case '2': case '3': case '4': case '5':
31a9643ea8Slogwang 	case '6': case '7': case '8': case '9':
32a9643ea8Slogwang 		return c - '0';
33a9643ea8Slogwang 	case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
34a9643ea8Slogwang 		return c - 'A' + 10;
35a9643ea8Slogwang 	case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
36a9643ea8Slogwang 		return c - 'a' + 10;
37a9643ea8Slogwang 	default:
38a9643ea8Slogwang 		return 0;
39a9643ea8Slogwang 	}
40a9643ea8Slogwang }
41a9643ea8Slogwang 
42a9643ea8Slogwang int
parser_read_arg_bool(const char * p)43a9643ea8Slogwang parser_read_arg_bool(const char *p)
44a9643ea8Slogwang {
45a9643ea8Slogwang 	p = skip_white_spaces(p);
46a9643ea8Slogwang 	int result = -EINVAL;
47a9643ea8Slogwang 
48a9643ea8Slogwang 	if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) ||
49a9643ea8Slogwang 		((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) {
50a9643ea8Slogwang 		p += 3;
51a9643ea8Slogwang 		result = 1;
52a9643ea8Slogwang 	}
53a9643ea8Slogwang 
54a9643ea8Slogwang 	if (((p[0] == 'o') && (p[1] == 'n')) ||
55a9643ea8Slogwang 		((p[0] == 'O') && (p[1] == 'N'))) {
56a9643ea8Slogwang 		p += 2;
57a9643ea8Slogwang 		result = 1;
58a9643ea8Slogwang 	}
59a9643ea8Slogwang 
60a9643ea8Slogwang 	if (((p[0] == 'n') && (p[1] == 'o')) ||
61a9643ea8Slogwang 		((p[0] == 'N') && (p[1] == 'O'))) {
62a9643ea8Slogwang 		p += 2;
63a9643ea8Slogwang 		result = 0;
64a9643ea8Slogwang 	}
65a9643ea8Slogwang 
66a9643ea8Slogwang 	if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) ||
67a9643ea8Slogwang 		((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) {
68a9643ea8Slogwang 		p += 3;
69a9643ea8Slogwang 		result = 0;
70a9643ea8Slogwang 	}
71a9643ea8Slogwang 
72a9643ea8Slogwang 	p = skip_white_spaces(p);
73a9643ea8Slogwang 
74a9643ea8Slogwang 	if (p[0] != '\0')
75a9643ea8Slogwang 		return -EINVAL;
76a9643ea8Slogwang 
77a9643ea8Slogwang 	return result;
78a9643ea8Slogwang }
79a9643ea8Slogwang 
80a9643ea8Slogwang int
parser_read_uint64(uint64_t * value,const char * p)81a9643ea8Slogwang parser_read_uint64(uint64_t *value, const char *p)
82a9643ea8Slogwang {
83a9643ea8Slogwang 	char *next;
84a9643ea8Slogwang 	uint64_t val;
85a9643ea8Slogwang 
86a9643ea8Slogwang 	p = skip_white_spaces(p);
87a9643ea8Slogwang 	if (!isdigit(*p))
88a9643ea8Slogwang 		return -EINVAL;
89a9643ea8Slogwang 
90a9643ea8Slogwang 	val = strtoul(p, &next, 10);
91a9643ea8Slogwang 	if (p == next)
92a9643ea8Slogwang 		return -EINVAL;
93a9643ea8Slogwang 
94a9643ea8Slogwang 	p = next;
95a9643ea8Slogwang 	switch (*p) {
96a9643ea8Slogwang 	case 'T':
97a9643ea8Slogwang 		val *= 1024ULL;
98a9643ea8Slogwang 		/* fall through */
99a9643ea8Slogwang 	case 'G':
100a9643ea8Slogwang 		val *= 1024ULL;
101a9643ea8Slogwang 		/* fall through */
102a9643ea8Slogwang 	case 'M':
103a9643ea8Slogwang 		val *= 1024ULL;
104a9643ea8Slogwang 		/* fall through */
105a9643ea8Slogwang 	case 'k':
106a9643ea8Slogwang 	case 'K':
107a9643ea8Slogwang 		val *= 1024ULL;
108a9643ea8Slogwang 		p++;
109a9643ea8Slogwang 		break;
110a9643ea8Slogwang 	}
111a9643ea8Slogwang 
112a9643ea8Slogwang 	p = skip_white_spaces(p);
113a9643ea8Slogwang 	if (*p != '\0')
114a9643ea8Slogwang 		return -EINVAL;
115a9643ea8Slogwang 
116a9643ea8Slogwang 	*value = val;
117a9643ea8Slogwang 	return 0;
118a9643ea8Slogwang }
119a9643ea8Slogwang 
120a9643ea8Slogwang int
parser_read_uint64_hex(uint64_t * value,const char * p)121a9643ea8Slogwang parser_read_uint64_hex(uint64_t *value, const char *p)
122a9643ea8Slogwang {
123a9643ea8Slogwang 	char *next;
124a9643ea8Slogwang 	uint64_t val;
125a9643ea8Slogwang 
126a9643ea8Slogwang 	p = skip_white_spaces(p);
127a9643ea8Slogwang 
128a9643ea8Slogwang 	val = strtoul(p, &next, 16);
129a9643ea8Slogwang 	if (p == next)
130a9643ea8Slogwang 		return -EINVAL;
131a9643ea8Slogwang 
132a9643ea8Slogwang 	p = skip_white_spaces(next);
133a9643ea8Slogwang 	if (*p != '\0')
134a9643ea8Slogwang 		return -EINVAL;
135a9643ea8Slogwang 
136a9643ea8Slogwang 	*value = val;
137a9643ea8Slogwang 	return 0;
138a9643ea8Slogwang }
139a9643ea8Slogwang 
140a9643ea8Slogwang int
parser_read_uint32(uint32_t * value,const char * p)141a9643ea8Slogwang parser_read_uint32(uint32_t *value, const char *p)
142a9643ea8Slogwang {
143a9643ea8Slogwang 	uint64_t val = 0;
144a9643ea8Slogwang 	int ret = parser_read_uint64(&val, p);
145a9643ea8Slogwang 
146a9643ea8Slogwang 	if (ret < 0)
147a9643ea8Slogwang 		return ret;
148a9643ea8Slogwang 
149a9643ea8Slogwang 	if (val > UINT32_MAX)
150a9643ea8Slogwang 		return -ERANGE;
151a9643ea8Slogwang 
152a9643ea8Slogwang 	*value = val;
153a9643ea8Slogwang 	return 0;
154a9643ea8Slogwang }
155a9643ea8Slogwang 
156a9643ea8Slogwang int
parser_read_uint32_hex(uint32_t * value,const char * p)157a9643ea8Slogwang parser_read_uint32_hex(uint32_t *value, const char *p)
158a9643ea8Slogwang {
159a9643ea8Slogwang 	uint64_t val = 0;
160a9643ea8Slogwang 	int ret = parser_read_uint64_hex(&val, p);
161a9643ea8Slogwang 
162a9643ea8Slogwang 	if (ret < 0)
163a9643ea8Slogwang 		return ret;
164a9643ea8Slogwang 
165a9643ea8Slogwang 	if (val > UINT32_MAX)
166a9643ea8Slogwang 		return -ERANGE;
167a9643ea8Slogwang 
168a9643ea8Slogwang 	*value = val;
169a9643ea8Slogwang 	return 0;
170a9643ea8Slogwang }
171a9643ea8Slogwang 
172a9643ea8Slogwang int
parser_read_uint16(uint16_t * value,const char * p)173a9643ea8Slogwang parser_read_uint16(uint16_t *value, const char *p)
174a9643ea8Slogwang {
175a9643ea8Slogwang 	uint64_t val = 0;
176a9643ea8Slogwang 	int ret = parser_read_uint64(&val, p);
177a9643ea8Slogwang 
178a9643ea8Slogwang 	if (ret < 0)
179a9643ea8Slogwang 		return ret;
180a9643ea8Slogwang 
181a9643ea8Slogwang 	if (val > UINT16_MAX)
182a9643ea8Slogwang 		return -ERANGE;
183a9643ea8Slogwang 
184a9643ea8Slogwang 	*value = val;
185a9643ea8Slogwang 	return 0;
186a9643ea8Slogwang }
187a9643ea8Slogwang 
188a9643ea8Slogwang int
parser_read_uint16_hex(uint16_t * value,const char * p)189a9643ea8Slogwang parser_read_uint16_hex(uint16_t *value, const char *p)
190a9643ea8Slogwang {
191a9643ea8Slogwang 	uint64_t val = 0;
192a9643ea8Slogwang 	int ret = parser_read_uint64_hex(&val, p);
193a9643ea8Slogwang 
194a9643ea8Slogwang 	if (ret < 0)
195a9643ea8Slogwang 		return ret;
196a9643ea8Slogwang 
197a9643ea8Slogwang 	if (val > UINT16_MAX)
198a9643ea8Slogwang 		return -ERANGE;
199a9643ea8Slogwang 
200a9643ea8Slogwang 	*value = val;
201a9643ea8Slogwang 	return 0;
202a9643ea8Slogwang }
203a9643ea8Slogwang 
204a9643ea8Slogwang int
parser_read_uint8(uint8_t * value,const char * p)205a9643ea8Slogwang parser_read_uint8(uint8_t *value, const char *p)
206a9643ea8Slogwang {
207a9643ea8Slogwang 	uint64_t val = 0;
208a9643ea8Slogwang 	int ret = parser_read_uint64(&val, p);
209a9643ea8Slogwang 
210a9643ea8Slogwang 	if (ret < 0)
211a9643ea8Slogwang 		return ret;
212a9643ea8Slogwang 
213a9643ea8Slogwang 	if (val > UINT8_MAX)
214a9643ea8Slogwang 		return -ERANGE;
215a9643ea8Slogwang 
216a9643ea8Slogwang 	*value = val;
217a9643ea8Slogwang 	return 0;
218a9643ea8Slogwang }
219a9643ea8Slogwang 
220a9643ea8Slogwang int
parser_read_uint8_hex(uint8_t * value,const char * p)221a9643ea8Slogwang parser_read_uint8_hex(uint8_t *value, const char *p)
222a9643ea8Slogwang {
223a9643ea8Slogwang 	uint64_t val = 0;
224a9643ea8Slogwang 	int ret = parser_read_uint64_hex(&val, p);
225a9643ea8Slogwang 
226a9643ea8Slogwang 	if (ret < 0)
227a9643ea8Slogwang 		return ret;
228a9643ea8Slogwang 
229a9643ea8Slogwang 	if (val > UINT8_MAX)
230a9643ea8Slogwang 		return -ERANGE;
231a9643ea8Slogwang 
232a9643ea8Slogwang 	*value = val;
233a9643ea8Slogwang 	return 0;
234a9643ea8Slogwang }
235a9643ea8Slogwang 
236a9643ea8Slogwang int
parse_tokenize_string(char * string,char * tokens[],uint32_t * n_tokens)237a9643ea8Slogwang parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
238a9643ea8Slogwang {
239a9643ea8Slogwang 	uint32_t i;
240a9643ea8Slogwang 
241a9643ea8Slogwang 	if ((string == NULL) ||
242a9643ea8Slogwang 		(tokens == NULL) ||
243a9643ea8Slogwang 		(*n_tokens < 1))
244a9643ea8Slogwang 		return -EINVAL;
245a9643ea8Slogwang 
246a9643ea8Slogwang 	for (i = 0; i < *n_tokens; i++) {
247a9643ea8Slogwang 		tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
248a9643ea8Slogwang 		if (tokens[i] == NULL)
249a9643ea8Slogwang 			break;
250a9643ea8Slogwang 	}
251a9643ea8Slogwang 
252a9643ea8Slogwang 	if ((i == *n_tokens) &&
253a9643ea8Slogwang 		(NULL != strtok_r(string, PARSE_DELIMITER, &string)))
254a9643ea8Slogwang 		return -E2BIG;
255a9643ea8Slogwang 
256a9643ea8Slogwang 	*n_tokens = i;
257a9643ea8Slogwang 	return 0;
258a9643ea8Slogwang }
259a9643ea8Slogwang 
260a9643ea8Slogwang int
parse_hex_string(char * src,uint8_t * dst,uint32_t * size)261a9643ea8Slogwang parse_hex_string(char *src, uint8_t *dst, uint32_t *size)
262a9643ea8Slogwang {
263a9643ea8Slogwang 	char *c;
264a9643ea8Slogwang 	uint32_t len, i;
265a9643ea8Slogwang 
266a9643ea8Slogwang 	/* Check input parameters */
267a9643ea8Slogwang 	if ((src == NULL) ||
268a9643ea8Slogwang 		(dst == NULL) ||
269a9643ea8Slogwang 		(size == NULL) ||
270a9643ea8Slogwang 		(*size == 0))
271a9643ea8Slogwang 		return -1;
272a9643ea8Slogwang 
273a9643ea8Slogwang 	len = strlen(src);
274a9643ea8Slogwang 	if (((len & 3) != 0) ||
275a9643ea8Slogwang 		(len > (*size) * 2))
276a9643ea8Slogwang 		return -1;
277a9643ea8Slogwang 	*size = len / 2;
278a9643ea8Slogwang 
279a9643ea8Slogwang 	for (c = src; *c != 0; c++) {
280a9643ea8Slogwang 		if ((((*c) >= '0') && ((*c) <= '9')) ||
281a9643ea8Slogwang 			(((*c) >= 'A') && ((*c) <= 'F')) ||
282a9643ea8Slogwang 			(((*c) >= 'a') && ((*c) <= 'f')))
283a9643ea8Slogwang 			continue;
284a9643ea8Slogwang 
285a9643ea8Slogwang 		return -1;
286a9643ea8Slogwang 	}
287a9643ea8Slogwang 
288a9643ea8Slogwang 	/* Convert chars to bytes */
289a9643ea8Slogwang 	for (i = 0; i < *size; i++)
290a9643ea8Slogwang 		dst[i] = get_hex_val(src[2 * i]) * 16 +
291a9643ea8Slogwang 			get_hex_val(src[2 * i + 1]);
292a9643ea8Slogwang 
293a9643ea8Slogwang 	return 0;
294a9643ea8Slogwang }
295a9643ea8Slogwang 
296a9643ea8Slogwang int
parse_mpls_labels(char * string,uint32_t * labels,uint32_t * n_labels)297a9643ea8Slogwang parse_mpls_labels(char *string, uint32_t *labels, uint32_t *n_labels)
298a9643ea8Slogwang {
299a9643ea8Slogwang 	uint32_t n_max_labels = *n_labels, count = 0;
300a9643ea8Slogwang 
301a9643ea8Slogwang 	/* Check for void list of labels */
302a9643ea8Slogwang 	if (strcmp(string, "<void>") == 0) {
303a9643ea8Slogwang 		*n_labels = 0;
304a9643ea8Slogwang 		return 0;
305a9643ea8Slogwang 	}
306a9643ea8Slogwang 
307a9643ea8Slogwang 	/* At least one label should be present */
308a9643ea8Slogwang 	for ( ; (*string != '\0'); ) {
309a9643ea8Slogwang 		char *next;
310a9643ea8Slogwang 		int value;
311a9643ea8Slogwang 
312a9643ea8Slogwang 		if (count >= n_max_labels)
313a9643ea8Slogwang 			return -1;
314a9643ea8Slogwang 
315a9643ea8Slogwang 		if (count > 0) {
316a9643ea8Slogwang 			if (string[0] != ':')
317a9643ea8Slogwang 				return -1;
318a9643ea8Slogwang 
319a9643ea8Slogwang 			string++;
320a9643ea8Slogwang 		}
321a9643ea8Slogwang 
322a9643ea8Slogwang 		value = strtol(string, &next, 10);
323a9643ea8Slogwang 		if (next == string)
324a9643ea8Slogwang 			return -1;
325a9643ea8Slogwang 		string = next;
326a9643ea8Slogwang 
327a9643ea8Slogwang 		labels[count++] = (uint32_t) value;
328a9643ea8Slogwang 	}
329a9643ea8Slogwang 
330a9643ea8Slogwang 	*n_labels = count;
331a9643ea8Slogwang 	return 0;
332a9643ea8Slogwang }
333a9643ea8Slogwang 
3344418919fSjohnjiang static struct rte_ether_addr *
my_ether_aton(const char * a)335a9643ea8Slogwang my_ether_aton(const char *a)
336a9643ea8Slogwang {
337a9643ea8Slogwang 	int i;
338a9643ea8Slogwang 	char *end;
3394418919fSjohnjiang 	unsigned long o[RTE_ETHER_ADDR_LEN];
3404418919fSjohnjiang 	static struct rte_ether_addr ether_addr;
341a9643ea8Slogwang 
342a9643ea8Slogwang 	i = 0;
343a9643ea8Slogwang 	do {
344a9643ea8Slogwang 		errno = 0;
345a9643ea8Slogwang 		o[i] = strtoul(a, &end, 16);
346a9643ea8Slogwang 		if (errno != 0 || end == a || (end[0] != ':' && end[0] != 0))
347a9643ea8Slogwang 			return NULL;
348a9643ea8Slogwang 		a = end + 1;
349*2d9fd380Sjfb8856606 	} while (++i != RTE_DIM(o) && end[0] != 0);
350a9643ea8Slogwang 
351a9643ea8Slogwang 	/* Junk at the end of line */
352a9643ea8Slogwang 	if (end[0] != 0)
353a9643ea8Slogwang 		return NULL;
354a9643ea8Slogwang 
355a9643ea8Slogwang 	/* Support the format XX:XX:XX:XX:XX:XX */
3564418919fSjohnjiang 	if (i == RTE_ETHER_ADDR_LEN) {
357a9643ea8Slogwang 		while (i-- != 0) {
358a9643ea8Slogwang 			if (o[i] > UINT8_MAX)
359a9643ea8Slogwang 				return NULL;
360a9643ea8Slogwang 			ether_addr.addr_bytes[i] = (uint8_t)o[i];
361a9643ea8Slogwang 		}
362a9643ea8Slogwang 	/* Support the format XXXX:XXXX:XXXX */
3634418919fSjohnjiang 	} else if (i == RTE_ETHER_ADDR_LEN / 2) {
364a9643ea8Slogwang 		while (i-- != 0) {
365a9643ea8Slogwang 			if (o[i] > UINT16_MAX)
366a9643ea8Slogwang 				return NULL;
367a9643ea8Slogwang 			ether_addr.addr_bytes[i * 2] = (uint8_t)(o[i] >> 8);
368a9643ea8Slogwang 			ether_addr.addr_bytes[i * 2 + 1] = (uint8_t)(o[i] & 0xff);
369a9643ea8Slogwang 		}
370a9643ea8Slogwang 	/* unknown format */
371a9643ea8Slogwang 	} else
372a9643ea8Slogwang 		return NULL;
373a9643ea8Slogwang 
3744418919fSjohnjiang 	return (struct rte_ether_addr *)&ether_addr;
375a9643ea8Slogwang }
376a9643ea8Slogwang 
377a9643ea8Slogwang int
parse_ipv4_addr(const char * token,struct in_addr * ipv4)378a9643ea8Slogwang parse_ipv4_addr(const char *token, struct in_addr *ipv4)
379a9643ea8Slogwang {
380a9643ea8Slogwang 	if (strlen(token) >= INET_ADDRSTRLEN)
381a9643ea8Slogwang 		return -EINVAL;
382a9643ea8Slogwang 
3830c6bd470Sfengbojiang 	if (inet_pton(AF_INET, token, ipv4) != 1)
384a9643ea8Slogwang 		return -EINVAL;
385a9643ea8Slogwang 
386a9643ea8Slogwang 	return 0;
387a9643ea8Slogwang }
388a9643ea8Slogwang 
389a9643ea8Slogwang int
parse_ipv6_addr(const char * token,struct in6_addr * ipv6)390a9643ea8Slogwang parse_ipv6_addr(const char *token, struct in6_addr *ipv6)
391a9643ea8Slogwang {
392a9643ea8Slogwang 	if (strlen(token) >= INET6_ADDRSTRLEN)
393a9643ea8Slogwang 		return -EINVAL;
394a9643ea8Slogwang 
3950c6bd470Sfengbojiang 	if (inet_pton(AF_INET6, token, ipv6) != 1)
396a9643ea8Slogwang 		return -EINVAL;
397a9643ea8Slogwang 
398a9643ea8Slogwang 	return 0;
399a9643ea8Slogwang }
400a9643ea8Slogwang 
401a9643ea8Slogwang int
parse_mac_addr(const char * token,struct rte_ether_addr * addr)4024418919fSjohnjiang parse_mac_addr(const char *token, struct rte_ether_addr *addr)
403a9643ea8Slogwang {
4044418919fSjohnjiang 	struct rte_ether_addr *tmp;
405a9643ea8Slogwang 
406a9643ea8Slogwang 	tmp = my_ether_aton(token);
407a9643ea8Slogwang 	if (tmp == NULL)
408a9643ea8Slogwang 		return -1;
409a9643ea8Slogwang 
4104418919fSjohnjiang 	memcpy(addr, tmp, sizeof(struct rte_ether_addr));
411a9643ea8Slogwang 	return 0;
412a9643ea8Slogwang }
413a9643ea8Slogwang 
414a9643ea8Slogwang int
parse_cpu_core(const char * entry,struct cpu_core_params * p)415d30ea906Sjfb8856606 parse_cpu_core(const char *entry,
416d30ea906Sjfb8856606 	struct cpu_core_params *p)
417a9643ea8Slogwang {
418a9643ea8Slogwang 	size_t num_len;
419a9643ea8Slogwang 	char num[8];
420a9643ea8Slogwang 
421a9643ea8Slogwang 	uint32_t s = 0, c = 0, h = 0, val;
422a9643ea8Slogwang 	uint8_t s_parsed = 0, c_parsed = 0, h_parsed = 0;
423a9643ea8Slogwang 	const char *next = skip_white_spaces(entry);
424a9643ea8Slogwang 	char type;
425a9643ea8Slogwang 
426d30ea906Sjfb8856606 	if (p == NULL)
427d30ea906Sjfb8856606 		return -EINVAL;
428d30ea906Sjfb8856606 
429a9643ea8Slogwang 	/* Expect <CORE> or [sX][cY][h]. At least one parameter is required. */
430a9643ea8Slogwang 	while (*next != '\0') {
431a9643ea8Slogwang 		/* If everything parsed nothing should left */
432a9643ea8Slogwang 		if (s_parsed && c_parsed && h_parsed)
433a9643ea8Slogwang 			return -EINVAL;
434a9643ea8Slogwang 
435a9643ea8Slogwang 		type = *next;
436a9643ea8Slogwang 		switch (type) {
437a9643ea8Slogwang 		case 's':
438a9643ea8Slogwang 		case 'S':
439a9643ea8Slogwang 			if (s_parsed || c_parsed || h_parsed)
440a9643ea8Slogwang 				return -EINVAL;
441a9643ea8Slogwang 			s_parsed = 1;
442a9643ea8Slogwang 			next++;
443a9643ea8Slogwang 			break;
444a9643ea8Slogwang 		case 'c':
445a9643ea8Slogwang 		case 'C':
446a9643ea8Slogwang 			if (c_parsed || h_parsed)
447a9643ea8Slogwang 				return -EINVAL;
448a9643ea8Slogwang 			c_parsed = 1;
449a9643ea8Slogwang 			next++;
450a9643ea8Slogwang 			break;
451a9643ea8Slogwang 		case 'h':
452a9643ea8Slogwang 		case 'H':
453a9643ea8Slogwang 			if (h_parsed)
454a9643ea8Slogwang 				return -EINVAL;
455a9643ea8Slogwang 			h_parsed = 1;
456a9643ea8Slogwang 			next++;
457a9643ea8Slogwang 			break;
458a9643ea8Slogwang 		default:
459a9643ea8Slogwang 			/* If it start from digit it must be only core id. */
460a9643ea8Slogwang 			if (!isdigit(*next) || s_parsed || c_parsed || h_parsed)
461a9643ea8Slogwang 				return -EINVAL;
462a9643ea8Slogwang 
463a9643ea8Slogwang 			type = 'C';
464a9643ea8Slogwang 		}
465a9643ea8Slogwang 
466a9643ea8Slogwang 		for (num_len = 0; *next != '\0'; next++, num_len++) {
467a9643ea8Slogwang 			if (num_len == RTE_DIM(num))
468a9643ea8Slogwang 				return -EINVAL;
469a9643ea8Slogwang 
470a9643ea8Slogwang 			if (!isdigit(*next))
471a9643ea8Slogwang 				break;
472a9643ea8Slogwang 
473a9643ea8Slogwang 			num[num_len] = *next;
474a9643ea8Slogwang 		}
475a9643ea8Slogwang 
476a9643ea8Slogwang 		if (num_len == 0 && type != 'h' && type != 'H')
477a9643ea8Slogwang 			return -EINVAL;
478a9643ea8Slogwang 
479a9643ea8Slogwang 		if (num_len != 0 && (type == 'h' || type == 'H'))
480a9643ea8Slogwang 			return -EINVAL;
481a9643ea8Slogwang 
482a9643ea8Slogwang 		num[num_len] = '\0';
483a9643ea8Slogwang 		val = strtol(num, NULL, 10);
484a9643ea8Slogwang 
485a9643ea8Slogwang 		h = 0;
486a9643ea8Slogwang 		switch (type) {
487a9643ea8Slogwang 		case 's':
488a9643ea8Slogwang 		case 'S':
489a9643ea8Slogwang 			s = val;
490a9643ea8Slogwang 			break;
491a9643ea8Slogwang 		case 'c':
492a9643ea8Slogwang 		case 'C':
493a9643ea8Slogwang 			c = val;
494a9643ea8Slogwang 			break;
495a9643ea8Slogwang 		case 'h':
496a9643ea8Slogwang 		case 'H':
497a9643ea8Slogwang 			h = 1;
498a9643ea8Slogwang 			break;
499a9643ea8Slogwang 		}
500a9643ea8Slogwang 	}
501a9643ea8Slogwang 
502d30ea906Sjfb8856606 	p->socket_id = s;
503d30ea906Sjfb8856606 	p->core_id = c;
504d30ea906Sjfb8856606 	p->thread_id = h;
505a9643ea8Slogwang 	return 0;
506a9643ea8Slogwang }
507