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