parse.c revision 36d90e3a
1/*
2 * Copyright (c) 2016  Intel Corporation.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <stdlib.h>
17#include <stdio.h>
18#include <string.h>
19#include "netbe.h"
20#include "parse.h"
21
22#define DEF_LINE_NUM	0x400
23
24static const struct {
25	const char *name;
26	uint16_t op;
27} name2feop[] = {
28	{ .name = "rx", .op = RXONLY,},
29	{ .name = "tx", .op = TXONLY,},
30	{ .name = "echo", .op = RXTX,},
31	{ .name = "fwd", .op = FWD,},
32};
33
34#define	OPT_SHORT_ARP		'a'
35#define	OPT_LONG_ARP		"enable-arp"
36
37#define	OPT_SHORT_SBULK		'B'
38#define	OPT_LONG_SBULK		"sburst"
39
40#define	OPT_SHORT_PROMISC	'P'
41#define	OPT_LONG_PROMISC	"promisc"
42
43#define	OPT_SHORT_RBUFS	'R'
44#define	OPT_LONG_RBUFS	"rbufs"
45
46#define	OPT_SHORT_SBUFS	'S'
47#define	OPT_LONG_SBUFS	"sbufs"
48
49#define	OPT_SHORT_BECFG	'b'
50#define	OPT_LONG_BECFG	"becfg"
51
52#define	OPT_SHORT_FECFG	'f'
53#define	OPT_LONG_FECFG	"fecfg"
54
55#define	OPT_SHORT_STREAMS	's'
56#define	OPT_LONG_STREAMS	"streams"
57
58#define	OPT_SHORT_UDP	'U'
59#define	OPT_LONG_UDP	"udp"
60
61#define	OPT_SHORT_TCP	'T'
62#define	OPT_LONG_TCP	"tcp"
63
64#define	OPT_SHORT_LISTEN	'L'
65#define	OPT_LONG_LISTEN		"listen"
66
67#define OPT_SHORT_HASH         'H'
68#define OPT_LONG_HASH          "hash"
69
70#define OPT_SHORT_SEC_KEY         'K'
71#define OPT_LONG_SEC_KEY          "seckey"
72
73#define	OPT_SHORT_VERBOSE	'v'
74#define	OPT_LONG_VERBOSE	"verbose"
75
76static const struct option long_opt[] = {
77	{OPT_LONG_ARP, 1, 0, OPT_SHORT_ARP},
78	{OPT_LONG_SBULK, 1, 0, OPT_SHORT_SBULK},
79	{OPT_LONG_PROMISC, 0, 0, OPT_SHORT_PROMISC},
80	{OPT_LONG_RBUFS, 1, 0, OPT_SHORT_RBUFS},
81	{OPT_LONG_SBUFS, 1, 0, OPT_SHORT_SBUFS},
82	{OPT_LONG_BECFG, 1, 0, OPT_SHORT_BECFG},
83	{OPT_LONG_FECFG, 1, 0, OPT_SHORT_FECFG},
84	{OPT_LONG_STREAMS, 1, 0, OPT_SHORT_STREAMS},
85	{OPT_LONG_UDP, 0, 0, OPT_SHORT_UDP},
86	{OPT_LONG_TCP, 0, 0, OPT_SHORT_TCP},
87	{OPT_LONG_HASH, 1, 0, OPT_SHORT_HASH},
88	{OPT_LONG_SEC_KEY, 1, 0, OPT_SHORT_SEC_KEY},
89	{OPT_LONG_LISTEN, 0, 0, OPT_SHORT_LISTEN},
90	{OPT_LONG_VERBOSE, 1, 0, OPT_SHORT_VERBOSE},
91	{NULL, 0, 0, 0}
92};
93
94static int
95parse_uint_val(__rte_unused const char *key, const char *val, void *prm)
96{
97	union parse_val *rv;
98	unsigned long v;
99	char *end;
100
101	rv = prm;
102	errno = 0;
103	v = strtoul(val, &end, 0);
104	if (errno != 0 || end[0] != 0 || v > UINT32_MAX)
105		return -EINVAL;
106
107	rv->u64 = v;
108	return 0;
109}
110
111static int
112parse_ipv4_val(__rte_unused const char *key, const char *val, void *prm)
113{
114	union parse_val *rv;
115
116	rv = prm;
117	if (inet_pton(AF_INET, val, &rv->in.addr4) != 1)
118		return -EINVAL;
119	rv->in.family = AF_INET;
120	return 0;
121}
122
123static int
124parse_ipv6_val(__rte_unused const char *key, const char *val, void *prm)
125{
126	union parse_val *rv;
127
128	rv = prm;
129	if (inet_pton(AF_INET6, val, &rv->in.addr6) != 1)
130		return -EINVAL;
131	rv->in.family = AF_INET6;
132	return 0;
133}
134
135static int
136parse_ip_val(__rte_unused const char *key, const char *val, void *prm)
137{
138	if (parse_ipv6_val(key, val, prm) != 0 &&
139			parse_ipv4_val(key, val, prm) != 0)
140		return -EINVAL;
141	return 0;
142}
143
144#define PARSE_UINT8x16(s, v, l)	                          \
145do {                                                      \
146	char *end;                                        \
147	unsigned long t;                                  \
148	errno = 0;                                        \
149	t = strtoul((s), &end, 16);                       \
150	if (errno != 0 || end[0] != (l) || t > UINT8_MAX) \
151		return -EINVAL;                           \
152	(s) = end + 1;                                    \
153	(v) = t;                                          \
154} while (0)
155
156static int
157parse_mac_val(__rte_unused const char *key, const char *val, void *prm)
158{
159	union parse_val *rv;
160	const char *s;
161
162	rv = prm;
163	s = val;
164
165	PARSE_UINT8x16(s, rv->mac.addr_bytes[0], ':');
166	PARSE_UINT8x16(s, rv->mac.addr_bytes[1], ':');
167	PARSE_UINT8x16(s, rv->mac.addr_bytes[2], ':');
168	PARSE_UINT8x16(s, rv->mac.addr_bytes[3], ':');
169	PARSE_UINT8x16(s, rv->mac.addr_bytes[4], ':');
170	PARSE_UINT8x16(s, rv->mac.addr_bytes[5], 0);
171	return 0;
172}
173
174static int
175parse_feop_val(__rte_unused const char *key, const char *val, void *prm)
176{
177	uint32_t i;
178	union parse_val *rv;
179
180	rv = prm;
181	for (i = 0; i != RTE_DIM(name2feop); i++) {
182		if (strcmp(val, name2feop[i].name) == 0) {
183			rv->u64 = name2feop[i].op;
184			return 0;
185		}
186	}
187
188	return -EINVAL;
189}
190
191static int
192parse_lcore_list_val(__rte_unused const char *key, const char *val, void *prm)
193{
194	union parse_val *rv;
195	unsigned long a, b;
196	uint32_t i;
197	char *end;
198
199	rv = prm;
200
201	errno = 0;
202	a = strtoul(val, &end, 0);
203	if (errno != 0 || (end[0] != 0 && end[0] != '-') || a > UINT32_MAX)
204		return -EINVAL;
205
206	if (end[0] == '-') {
207		val = end + 1;
208		errno = 0;
209		b = strtoul(val, &end, 0);
210		if (errno != 0 || end[0] != 0 || b > UINT32_MAX)
211			return -EINVAL;
212	} else
213		b = a;
214
215	if (a <= b) {
216		for (i = a; i <= b; i++)
217			CPU_SET(i, &rv->cpuset);
218	} else {
219		RTE_LOG(ERR, USER1,
220			"%s: lcores not in ascending order\n", __func__);
221		return -EINVAL;
222	}
223
224	return 0;
225}
226
227static int
228parse_kvargs(const char *arg, const char *keys_man[], uint32_t nb_man,
229	const char *keys_opt[], uint32_t nb_opt,
230	const arg_handler_t hndl[], union parse_val val[])
231{
232	uint32_t j, k;
233	struct rte_kvargs *kvl;
234
235	kvl = rte_kvargs_parse(arg, NULL);
236	if (kvl == NULL) {
237		RTE_LOG(ERR, USER1,
238			"%s: invalid parameter: %s\n",
239			__func__, arg);
240		return -EINVAL;
241	}
242
243	for (j = 0; j != nb_man; j++) {
244		if (rte_kvargs_count(kvl, keys_man[j]) == 0) {
245			RTE_LOG(ERR, USER1,
246				"%s: %s missing mandatory key: %s\n",
247				__func__, arg, keys_man[j]);
248			rte_kvargs_free(kvl);
249			return -EINVAL;
250		}
251	}
252
253	for (j = 0; j != nb_man; j++) {
254		if (rte_kvargs_process(kvl, keys_man[j], hndl[j],
255				val + j) != 0) {
256			RTE_LOG(ERR, USER1,
257				"%s: %s invalid value for man key: %s\n",
258				__func__, arg, keys_man[j]);
259			rte_kvargs_free(kvl);
260			return -EINVAL;
261		}
262	}
263
264	for (j = 0; j != nb_opt; j++) {
265		k = j + nb_man;
266		if (rte_kvargs_process(kvl, keys_opt[j], hndl[k],
267				val + k) != 0) {
268			RTE_LOG(ERR, USER1,
269				"%s: %s invalid value for opt key: %s\n",
270				__func__, arg, keys_opt[j]);
271			rte_kvargs_free(kvl);
272			return -EINVAL;
273		}
274	}
275
276	rte_kvargs_free(kvl);
277	return 0;
278}
279
280int
281parse_netbe_arg(struct netbe_port *prt, const char *arg, rte_cpuset_t *pcpu)
282{
283	int32_t rc;
284	uint32_t i, j, nc;
285
286	static const char *keys_man[] = {
287		"port",
288		"lcore",
289	};
290
291	static const char *keys_opt[] = {
292		"mtu",
293		"rx_offload",
294		"tx_offload",
295		"ipv4",
296		"ipv6",
297	};
298
299	static const arg_handler_t hndl[] = {
300		parse_uint_val,
301		parse_lcore_list_val,
302		parse_uint_val,
303		parse_uint_val,
304		parse_uint_val,
305		parse_ipv4_val,
306		parse_ipv6_val,
307	};
308
309	union parse_val val[RTE_DIM(hndl)];
310
311	memset(val, 0, sizeof(val));
312	val[2].u64 = ETHER_MAX_LEN - ETHER_CRC_LEN;
313
314	rc = parse_kvargs(arg, keys_man, RTE_DIM(keys_man),
315		keys_opt, RTE_DIM(keys_opt), hndl, val);
316	if (rc != 0)
317		return rc;
318
319	prt->id = val[0].u64;
320
321	for (i = 0, nc = 0; i < RTE_MAX_LCORE; i++)
322		nc += CPU_ISSET(i, &val[1].cpuset);
323	prt->lcore_id = rte_zmalloc(NULL, nc * sizeof(prt->lcore_id[0]),
324		RTE_CACHE_LINE_SIZE);
325	prt->nb_lcore = nc;
326
327	for (i = 0, j = 0; i < RTE_MAX_LCORE; i++)
328		if (CPU_ISSET(i, &val[1].cpuset))
329			prt->lcore_id[j++] = i;
330	CPU_OR(pcpu, pcpu, &val[1].cpuset);
331
332	prt->mtu = val[2].u64;
333	prt->rx_offload = val[3].u64;
334	prt->tx_offload = val[4].u64;
335	prt->ipv4 = val[5].in.addr4.s_addr;
336	prt->ipv6 = val[6].in.addr6;
337
338	return 0;
339}
340
341static int
342check_netbe_dest(const struct netbe_dest *dst)
343{
344	if (dst->port >= RTE_MAX_ETHPORTS) {
345		RTE_LOG(ERR, USER1, "%s(line=%u) invalid port=%u",
346			__func__, dst->line, dst->port);
347		return -EINVAL;
348	} else if ((dst->family == AF_INET &&
349			dst->prfx > sizeof(struct in_addr) * CHAR_BIT) ||
350			(dst->family == AF_INET6 &&
351			dst->prfx > sizeof(struct in6_addr) * CHAR_BIT)) {
352		RTE_LOG(ERR, USER1, "%s(line=%u) invalid masklen=%u",
353			__func__, dst->line, dst->prfx);
354		return -EINVAL;
355	} else if (dst->mtu > ETHER_MAX_JUMBO_FRAME_LEN - ETHER_CRC_LEN) {
356		RTE_LOG(ERR, USER1, "%s(line=%u) invalid mtu=%u",
357			__func__, dst->line, dst->mtu);
358		return -EINVAL;
359	}
360	return 0;
361}
362
363static int
364parse_netbe_dest(struct netbe_dest *dst, const char *arg)
365{
366	int32_t rc;
367
368	static const char *keys_man[] = {
369		"port",
370		"addr",
371		"masklen",
372		"mac",
373	};
374
375	static const char *keys_opt[] = {
376		"mtu",
377	};
378
379	static const arg_handler_t hndl[] = {
380		parse_uint_val,
381		parse_ip_val,
382		parse_uint_val,
383		parse_mac_val,
384		parse_uint_val,
385	};
386
387	union parse_val val[RTE_DIM(hndl)];
388
389	/* set default values. */
390	memset(val, 0, sizeof(val));
391	val[4].u64 = ETHER_MAX_JUMBO_FRAME_LEN - ETHER_CRC_LEN;
392
393	rc = parse_kvargs(arg, keys_man, RTE_DIM(keys_man),
394		keys_opt, RTE_DIM(keys_opt), hndl, val);
395	if (rc != 0)
396		return rc;
397
398	dst->port = val[0].u64;
399	dst->family = val[1].in.family;
400	if (val[1].in.family == AF_INET)
401		dst->ipv4 = val[1].in.addr4;
402	else
403		dst->ipv6 = val[1].in.addr6;
404	dst->prfx = val[2].u64;
405	memcpy(&dst->mac, &val[3].mac, sizeof(dst->mac));
406	dst->mtu = val[4].u64;
407
408	return 0;
409}
410
411int
412netbe_parse_dest(const char *fname, struct netbe_dest_prm *prm)
413{
414	uint32_t i, ln, n, num;
415	int32_t rc;
416	size_t sz;
417	char *s;
418	FILE *f;
419	struct netbe_dest *dp;
420	char line[LINE_MAX];
421
422	f = fopen(fname, "r");
423	if (f == NULL) {
424		RTE_LOG(ERR, USER1, "%s failed to open file \"%s\"\n",
425			__func__, fname);
426		return -EINVAL;
427	}
428
429	n = 0;
430	num = 0;
431	dp = NULL;
432	rc = 0;
433	for (ln = 0; fgets(line, sizeof(line), f) != NULL; ln++) {
434
435		/* skip spaces at the start. */
436		for (s = line; isspace(s[0]); s++)
437			;
438
439		/* skip comment line. */
440		if (s[0] == '#' || s[0] == 0)
441			continue;
442
443		/* skip spaces at the end. */
444		for (i = strlen(s); i-- != 0 && isspace(s[i]); s[i] = 0)
445			;
446
447		if (n == num) {
448			num += DEF_LINE_NUM;
449			sz = sizeof(dp[0]) * num;
450			dp = realloc(dp, sizeof(dp[0]) * num);
451			if (dp == NULL) {
452				RTE_LOG(ERR, USER1,
453					"%s(%s) allocation of %zu bytes "
454					"failed\n",
455					__func__, fname, sz);
456				rc = -ENOMEM;
457				break;
458			}
459			memset(&dp[n], 0, sizeof(dp[0]) * (num - n));
460		}
461
462		dp[n].line = ln + 1;
463		rc = parse_netbe_dest(dp + n, s);
464		rc = (rc != 0) ? rc : check_netbe_dest(dp + n);
465		if (rc != 0) {
466			RTE_LOG(ERR, USER1, "%s(%s) failed to parse line %u\n",
467				__func__, fname, dp[n].line);
468			break;
469		}
470		n++;
471	}
472
473	fclose(f);
474
475	if (rc != 0) {
476		free(dp);
477		dp = NULL;
478		n = 0;
479	}
480
481	prm->dest = dp;
482	prm->nb_dest = n;
483	return rc;
484}
485
486static void
487pv2saddr(struct sockaddr_storage *ss, const union parse_val *pva,
488	const union parse_val *pvp)
489{
490	ss->ss_family = pva->in.family;
491	if (pva->in.family == AF_INET) {
492		struct sockaddr_in *si = (struct sockaddr_in *)ss;
493		si->sin_addr = pva->in.addr4;
494		si->sin_port = rte_cpu_to_be_16((uint16_t)pvp->u64);
495	} else {
496		struct sockaddr_in6 *si = (struct sockaddr_in6 *)ss;
497		si->sin6_addr = pva->in.addr6;
498		si->sin6_port = rte_cpu_to_be_16((uint16_t)pvp->u64);
499	}
500}
501
502static int
503parse_netfe_arg(struct netfe_stream_prm *sp, const char *arg)
504{
505	int32_t rc;
506
507	static const char *keys_man[] = {
508		"lcore",
509		"op",
510		"laddr",
511		"lport",
512		"raddr",
513		"rport",
514	};
515
516	static const char *keys_opt[] = {
517		"txlen",
518		"fwladdr",
519		"fwlport",
520		"fwraddr",
521		"fwrport",
522		"belcore",
523	};
524
525	static const arg_handler_t hndl[] = {
526		parse_uint_val,
527		parse_feop_val,
528		parse_ip_val,
529		parse_uint_val,
530		parse_ip_val,
531		parse_uint_val,
532		parse_uint_val,
533		parse_ip_val,
534		parse_uint_val,
535		parse_ip_val,
536		parse_uint_val,
537		parse_uint_val,
538	};
539
540	union parse_val val[RTE_DIM(hndl)];
541
542	memset(val, 0, sizeof(val));
543	val[11].u64 = LCORE_ID_ANY;
544	rc = parse_kvargs(arg, keys_man, RTE_DIM(keys_man),
545		keys_opt, RTE_DIM(keys_opt), hndl, val);
546	if (rc != 0)
547		return rc;
548	sp->lcore = val[0].u64;
549	sp->op = val[1].u64;
550	pv2saddr(&sp->sprm.local_addr, val + 2, val + 3);
551	pv2saddr(&sp->sprm.remote_addr, val + 4, val + 5);
552	sp->txlen = val[6].u64;
553	pv2saddr(&sp->fprm.local_addr, val + 7, val + 8);
554	pv2saddr(&sp->fprm.remote_addr, val + 9, val + 10);
555	sp->belcore = val[11].u64;
556
557	return 0;
558}
559
560static const char *
561format_feop(uint16_t op)
562{
563	uint32_t i;
564
565	for (i = 0; i != RTE_DIM(name2feop); i++) {
566		if (name2feop[i].op == op)
567			return name2feop[i].name;
568	}
569
570	return NULL;
571}
572
573static int
574is_addr_wc(const struct sockaddr_storage *sp)
575{
576	const struct sockaddr_in *i4;
577	const struct sockaddr_in6 *i6;
578
579	if (sp->ss_family == AF_INET) {
580		i4 = (const struct sockaddr_in *)sp;
581		return  (i4->sin_addr.s_addr == INADDR_ANY);
582	} else if (sp->ss_family == AF_INET6) {
583		i6 = (const struct sockaddr_in6 *)sp;
584		return (memcmp(&i6->sin6_addr, &in6addr_any,
585			sizeof(i6->sin6_addr)) == 0);
586	}
587	return 0;
588}
589
590static int
591check_netfe_arg(const struct netfe_stream_prm *sp)
592{
593	char buf[INET6_ADDRSTRLEN];
594
595	if (sp->sprm.local_addr.ss_family !=
596			sp->sprm.remote_addr.ss_family) {
597		RTE_LOG(ERR, USER1, "invalid arg at line %u: "
598			"laddr and raddr for different protocols\n",
599			sp->line);
600		return -EINVAL;
601	}
602
603	if (sp->op == TXONLY) {
604		if (sp->txlen > RTE_MBUF_DEFAULT_DATAROOM || sp->txlen == 0) {
605			RTE_LOG(ERR, USER1, "invalid arg at line %u: txlen=%u "
606				"exceeds allowed values: (0, %u]\n",
607				sp->line, sp->txlen, RTE_MBUF_DEFAULT_DATAROOM);
608			return -EINVAL;
609		} else if (is_addr_wc(&sp->sprm.remote_addr)) {
610			RTE_LOG(ERR, USER1, "invalid arg at line %u: "
611				"raddr=%s are not allowed for op=%s;\n",
612				sp->line,
613				format_addr(&sp->sprm.remote_addr,
614				buf, sizeof(buf)),
615				format_feop(sp->op));
616			return -EINVAL;
617		}
618	} else if (sp->op == FWD) {
619		if (sp->fprm.local_addr.ss_family !=
620				sp->fprm.remote_addr.ss_family) {
621			RTE_LOG(ERR, USER1, "invalid arg at line %u: "
622				"fwladdr and fwraddr for different protocols\n",
623				sp->line);
624			return -EINVAL;
625		} else if (is_addr_wc(&sp->fprm.remote_addr)) {
626			RTE_LOG(ERR, USER1, "invalid arg at line %u: "
627				"fwaddr=%s are not allowed for op=%s;\n",
628				sp->line,
629				format_addr(&sp->fprm.remote_addr,
630				buf, sizeof(buf)),
631				format_feop(sp->op));
632			return -EINVAL;
633		}
634	}
635
636	return 0;
637}
638
639int
640netfe_parse_cfg(const char *fname, struct netfe_lcore_prm *lp)
641{
642	uint32_t i, ln, n, num;
643	int32_t rc;
644	size_t sz;
645	char *s;
646	FILE *f;
647	struct netfe_stream_prm *sp;
648	char line[LINE_MAX];
649
650	f = fopen(fname, "r");
651	if (f == NULL) {
652		RTE_LOG(ERR, USER1, "%s failed to open file \"%s\"\n",
653			__func__, fname);
654		return -EINVAL;
655	}
656
657	n = 0;
658	num = 0;
659	sp = NULL;
660	rc = 0;
661	for (ln = 0; fgets(line, sizeof(line), f) != NULL; ln++) {
662
663		/* skip spaces at the start. */
664		for (s = line; isspace(s[0]); s++)
665			;
666
667		/* skip comment line. */
668		if (s[0] == '#' || s[0] == 0)
669			continue;
670
671		/* skip spaces at the end. */
672		for (i = strlen(s); i-- != 0 && isspace(s[i]); s[i] = 0)
673			;
674
675		if (n == lp->max_streams) {
676			RTE_LOG(ERR, USER1,
677				"%s(%s) number of entries exceed max streams "
678				"value: %u\n",
679				__func__, fname, n);
680				rc = -EINVAL;
681				break;
682		}
683
684		if (n == num) {
685			num += DEF_LINE_NUM;
686			sz = sizeof(sp[0]) * num;
687			sp = realloc(sp, sizeof(sp[0]) * num);
688			if (sp == NULL) {
689				RTE_LOG(ERR, USER1,
690					"%s(%s) allocation of %zu bytes "
691					"failed\n",
692					__func__, fname, sz);
693				rc = -ENOMEM;
694				break;
695			}
696			memset(&sp[n], 0, sizeof(sp[0]) * (num - n));
697		}
698
699		sp[n].line = ln + 1;
700		rc = parse_netfe_arg(sp + n, s);
701		rc = (rc != 0) ? rc : check_netfe_arg(sp + n);
702		if (rc != 0) {
703			RTE_LOG(ERR, USER1, "%s(%s) failed to parse line %u\n",
704				__func__, fname, sp[n].line);
705			break;
706		}
707		n++;
708	}
709
710	fclose(f);
711
712	if (rc != 0) {
713		free(sp);
714		sp = NULL;
715		n = 0;
716	}
717
718	lp->stream = sp;
719	lp->nb_streams = n;
720	return rc;
721}
722
723static uint32_t
724parse_hash_alg(const char *val)
725{
726	if (strcmp(val, "jhash") == 0)
727		return TLE_JHASH;
728	else if (strcmp(val, "siphash") == 0)
729		return TLE_SIPHASH;
730	else
731		return TLE_HASH_NUM;
732}
733
734int
735parse_app_options(int argc, char **argv, struct netbe_cfg *cfg,
736	struct tle_ctx_param *ctx_prm,
737	char *fecfg_fname, char *becfg_fname)
738{
739	int32_t opt, opt_idx, rc;
740	uint64_t v;
741	uint32_t i, j, n, nc;
742	rte_cpuset_t cpuset;
743	uint32_t udp = 0, tcp = 0, listen = 0;
744
745	optind = 0;
746	optarg = NULL;
747	while ((opt = getopt_long(argc, argv, "aB:LPR:S:TUb:f:s:v:H:K:",
748			long_opt, &opt_idx)) != EOF) {
749		if (opt == OPT_SHORT_ARP) {
750			cfg->arp = 1;
751		} else if (opt == OPT_SHORT_SBULK) {
752			rc = parse_uint_val(NULL, optarg, &v);
753			if (rc < 0)
754				rte_exit(EXIT_FAILURE, "%s: invalid value: %s "
755					"for option: \'%c\'\n",
756					__func__, optarg, opt);
757			ctx_prm->send_bulk_size = v;
758		} else if (opt == OPT_SHORT_PROMISC) {
759			cfg->promisc = 1;
760		} else if (opt == OPT_SHORT_RBUFS) {
761			rc = parse_uint_val(NULL, optarg, &v);
762			if (rc < 0)
763				rte_exit(EXIT_FAILURE, "%s: invalid value: %s "
764					"for option: \'%c\'\n",
765					__func__, optarg, opt);
766			ctx_prm->max_stream_rbufs = v;
767		} else if (opt == OPT_SHORT_SBUFS) {
768			rc = parse_uint_val(NULL, optarg, &v);
769			if (rc < 0)
770				rte_exit(EXIT_FAILURE, "%s: invalid value: %s "
771					"for option: \'%c\'\n",
772					__func__, optarg, opt);
773			ctx_prm->max_stream_sbufs = v;
774		} else if (opt == OPT_SHORT_STREAMS) {
775			rc = parse_uint_val(NULL, optarg, &v);
776			if (rc < 0)
777				rte_exit(EXIT_FAILURE, "%s: invalid value: %s "
778					"for option: \'%c\'\n",
779					__func__, optarg, opt);
780			ctx_prm->max_streams = v;
781		} else if (opt == OPT_SHORT_VERBOSE) {
782			rc = parse_uint_val(NULL, optarg, &v);
783			if (rc < 0)
784				rte_exit(EXIT_FAILURE, "%s: invalid value: %s "
785					"for option: \'%c\'\n",
786					__func__, optarg, opt);
787			verbose = (v > VERBOSE_NUM) ? VERBOSE_NUM : v;
788		} else if (opt == OPT_SHORT_BECFG) {
789			snprintf(becfg_fname, PATH_MAX, "%s",
790				optarg);
791		} else if (opt == OPT_SHORT_FECFG) {
792			snprintf(fecfg_fname, PATH_MAX, "%s",
793				optarg);
794		} else if (opt == OPT_SHORT_UDP) {
795			udp = 1;
796			cfg->proto = TLE_PROTO_UDP;
797		} else if (opt == OPT_SHORT_TCP) {
798			tcp = 1;
799			cfg->proto = TLE_PROTO_TCP;
800		} else if (opt == OPT_SHORT_LISTEN) {
801			listen = 1;
802			cfg->server = 1;
803		} else if (opt == OPT_SHORT_HASH) {
804			ctx_prm->hash_alg = parse_hash_alg(optarg);
805			if (ctx_prm->hash_alg >= TLE_HASH_NUM) {
806				rte_exit(EXIT_FAILURE,
807					"%s: invalid hash algorithm %s "
808					"for option: \'%c\'\n",
809					__func__, optarg, opt);
810			}
811		} else if (opt == OPT_SHORT_SEC_KEY) {
812			n = strlen(optarg);
813			if (n != sizeof(ctx_prm->secret_key)) {
814				rte_exit(EXIT_FAILURE,
815					"%s: invalid length %s "
816					"for option \'%c\' "
817					"must be 16 characters long\n",
818					__func__, optarg, opt);
819			}
820			memcpy(&ctx_prm->secret_key, optarg,
821				sizeof(ctx_prm->secret_key));
822		}
823
824		else {
825			rte_exit(EXIT_FAILURE,
826				"%s: unknown option: \'%c\'\n",
827				__func__, opt);
828		}
829	}
830
831	if (!udp && !tcp)
832		rte_exit(EXIT_FAILURE, "%s: either UDP or TCP option has to be "
833			"provided\n", __func__);
834
835	if (udp && tcp)
836		rte_exit(EXIT_FAILURE, "%s: both UDP and TCP options are not "
837			"allowed\n", __func__);
838
839	if (udp && listen)
840		rte_exit(EXIT_FAILURE,
841			"%s: listen mode cannot be opened with UDP\n",
842			__func__);
843
844	if (udp && cfg->arp)
845		rte_exit(EXIT_FAILURE,
846			"%s: arp cannot be enabled with UDP\n",
847			__func__);
848
849	/* parse port params */
850	argc -= optind;
851	argv += optind;
852
853	/* allocate memory for number of ports defined */
854	n = (uint32_t)argc;
855	cfg->prt = rte_zmalloc(NULL, sizeof(struct netbe_port) * n,
856		RTE_CACHE_LINE_SIZE);
857	cfg->prt_num = n;
858
859	rc = 0;
860	for (i = 0; i != n; i++) {
861		rc = parse_netbe_arg(cfg->prt + i, argv[i], &cpuset);
862		if (rc != 0) {
863			RTE_LOG(ERR, USER1,
864				"%s: processing of \"%s\" failed with error "
865				"code: %d\n", __func__, argv[i], rc);
866			for (j = 0; j != i; j++)
867				rte_free(cfg->prt[j].lcore_id);
868			rte_free(cfg->prt);
869			return rc;
870		}
871	}
872
873	/* count the number of CPU defined in ports */
874	for (i = 0, nc = 0; i < RTE_MAX_LCORE; i++)
875		nc += CPU_ISSET(i, &cpuset);
876
877	/* allocate memory for number of CPU defined */
878	cfg->cpu = rte_zmalloc(NULL, sizeof(struct netbe_lcore) * nc,
879		RTE_CACHE_LINE_SIZE);
880
881	return 0;
882}
883