13395610eSKonstantin Ananyev/*
27e18fa1bSKonstantin Ananyev * Copyright (c) 2016-2017  Intel Corporation.
33395610eSKonstantin Ananyev * Licensed under the Apache License, Version 2.0 (the "License");
43395610eSKonstantin Ananyev * you may not use this file except in compliance with the License.
53395610eSKonstantin Ananyev * You may obtain a copy of the License at:
63395610eSKonstantin Ananyev *
73395610eSKonstantin Ananyev *     http://www.apache.org/licenses/LICENSE-2.0
83395610eSKonstantin Ananyev *
93395610eSKonstantin Ananyev * Unless required by applicable law or agreed to in writing, software
103395610eSKonstantin Ananyev * distributed under the License is distributed on an "AS IS" BASIS,
113395610eSKonstantin Ananyev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123395610eSKonstantin Ananyev * See the License for the specific language governing permissions and
133395610eSKonstantin Ananyev * limitations under the License.
143395610eSKonstantin Ananyev */
153395610eSKonstantin Ananyev
169fa82a63SReshma Pattan#include <stdlib.h>
179fa82a63SReshma Pattan#include <stdio.h>
189fa82a63SReshma Pattan#include <string.h>
193726dc50SKonstantin Ananyev#include <sys/stat.h>
203726dc50SKonstantin Ananyev#include <unistd.h>
213726dc50SKonstantin Ananyev#include <fcntl.h>
223726dc50SKonstantin Ananyev
233395610eSKonstantin Ananyev#include "netbe.h"
243395610eSKonstantin Ananyev#include "parse.h"
253395610eSKonstantin Ananyev
263395610eSKonstantin Ananyev#define DEF_LINE_NUM	0x400
273395610eSKonstantin Ananyev
283395610eSKonstantin Ananyevstatic const struct {
293395610eSKonstantin Ananyev	const char *name;
303395610eSKonstantin Ananyev	uint16_t op;
313395610eSKonstantin Ananyev} name2feop[] = {
323395610eSKonstantin Ananyev	{ .name = "rx", .op = RXONLY,},
333395610eSKonstantin Ananyev	{ .name = "tx", .op = TXONLY,},
34e151ee29SRemy Horton	{ .name = "echo", .op = ECHO,},
35e151ee29SRemy Horton	{ .name = "rxtx", .op = RXTX,},
363395610eSKonstantin Ananyev	{ .name = "fwd", .op = FWD,},
373395610eSKonstantin Ananyev};
383395610eSKonstantin Ananyev
39aa97dd1cSKonstantin Ananyev#define	OPT_SHORT_SBULK		'B'
40aa97dd1cSKonstantin Ananyev#define	OPT_LONG_SBULK		"sburst"
41aa97dd1cSKonstantin Ananyev
427e18fa1bSKonstantin Ananyev#define	OPT_SHORT_CTXFLAGS	'C'
437e18fa1bSKonstantin Ananyev#define	OPT_LONG_CTXFLAGS	"ctxflags"
447e18fa1bSKonstantin Ananyev
45aa97dd1cSKonstantin Ananyev#define	OPT_SHORT_PROMISC	'P'
46aa97dd1cSKonstantin Ananyev#define	OPT_LONG_PROMISC	"promisc"
47aa97dd1cSKonstantin Ananyev
4874a56517SMariusz Drost#define	OPT_SHORT_MBUFNUM	'M'
4974a56517SMariusz Drost#define	OPT_LONG_MBUFNUM	"mbuf-num"
5074a56517SMariusz Drost
51aa97dd1cSKonstantin Ananyev#define	OPT_SHORT_RBUFS	'R'
52aa97dd1cSKonstantin Ananyev#define	OPT_LONG_RBUFS	"rbufs"
53aa97dd1cSKonstantin Ananyev
54aa97dd1cSKonstantin Ananyev#define	OPT_SHORT_SBUFS	'S'
55aa97dd1cSKonstantin Ananyev#define	OPT_LONG_SBUFS	"sbufs"
56aa97dd1cSKonstantin Ananyev
573726dc50SKonstantin Ananyev#define	OPT_SHORT_ARP		'a'
583726dc50SKonstantin Ananyev#define	OPT_LONG_ARP		"enable-arp"
593726dc50SKonstantin Ananyev
60aa97dd1cSKonstantin Ananyev#define	OPT_SHORT_BECFG	'b'
61aa97dd1cSKonstantin Ananyev#define	OPT_LONG_BECFG	"becfg"
62aa97dd1cSKonstantin Ananyev
633726dc50SKonstantin Ananyev#define	OPT_SHORT_TXCNT	'c'
643726dc50SKonstantin Ananyev#define	OPT_LONG_TXCNT	"txcnt"
653726dc50SKonstantin Ananyev
66aa97dd1cSKonstantin Ananyev#define	OPT_SHORT_FECFG	'f'
67aa97dd1cSKonstantin Ananyev#define	OPT_LONG_FECFG	"fecfg"
68aa97dd1cSKonstantin Ananyev
69aa97dd1cSKonstantin Ananyev#define	OPT_SHORT_STREAMS	's'
70aa97dd1cSKonstantin Ananyev#define	OPT_LONG_STREAMS	"streams"
71aa97dd1cSKonstantin Ananyev
72aa97dd1cSKonstantin Ananyev#define	OPT_SHORT_UDP	'U'
73aa97dd1cSKonstantin Ananyev#define	OPT_LONG_UDP	"udp"
74aa97dd1cSKonstantin Ananyev
75aa97dd1cSKonstantin Ananyev#define	OPT_SHORT_TCP	'T'
76aa97dd1cSKonstantin Ananyev#define	OPT_LONG_TCP	"tcp"
77aa97dd1cSKonstantin Ananyev
78aa97dd1cSKonstantin Ananyev#define	OPT_SHORT_LISTEN	'L'
79aa97dd1cSKonstantin Ananyev#define	OPT_LONG_LISTEN		"listen"
80aa97dd1cSKonstantin Ananyev
819fa82a63SReshma Pattan#define OPT_SHORT_HASH         'H'
829fa82a63SReshma Pattan#define OPT_LONG_HASH          "hash"
839fa82a63SReshma Pattan
849fa82a63SReshma Pattan#define OPT_SHORT_SEC_KEY         'K'
859fa82a63SReshma Pattan#define OPT_LONG_SEC_KEY          "seckey"
869fa82a63SReshma Pattan
87aa97dd1cSKonstantin Ananyev#define	OPT_SHORT_VERBOSE	'v'
88aa97dd1cSKonstantin Ananyev#define	OPT_LONG_VERBOSE	"verbose"
89aa97dd1cSKonstantin Ananyev
907e18fa1bSKonstantin Ananyev#define	OPT_SHORT_WINDOW	'w'
917e18fa1bSKonstantin Ananyev#define	OPT_LONG_WINDOW		"initial-window"
927e18fa1bSKonstantin Ananyev
937e18fa1bSKonstantin Ananyev#define	OPT_SHORT_TIMEWAIT	'W'
947e18fa1bSKonstantin Ananyev#define	OPT_LONG_TIMEWAIT	"timewait"
957e18fa1bSKonstantin Ananyev
96aa97dd1cSKonstantin Ananyevstatic const struct option long_opt[] = {
97aa97dd1cSKonstantin Ananyev	{OPT_LONG_ARP, 1, 0, OPT_SHORT_ARP},
98aa97dd1cSKonstantin Ananyev	{OPT_LONG_SBULK, 1, 0, OPT_SHORT_SBULK},
997e18fa1bSKonstantin Ananyev	{OPT_LONG_CTXFLAGS, 1, 0, OPT_SHORT_CTXFLAGS},
100aa97dd1cSKonstantin Ananyev	{OPT_LONG_PROMISC, 0, 0, OPT_SHORT_PROMISC},
10174a56517SMariusz Drost	{OPT_LONG_MBUFNUM, 1, 0, OPT_SHORT_MBUFNUM},
102aa97dd1cSKonstantin Ananyev	{OPT_LONG_RBUFS, 1, 0, OPT_SHORT_RBUFS},
103aa97dd1cSKonstantin Ananyev	{OPT_LONG_SBUFS, 1, 0, OPT_SHORT_SBUFS},
104aa97dd1cSKonstantin Ananyev	{OPT_LONG_BECFG, 1, 0, OPT_SHORT_BECFG},
105aa97dd1cSKonstantin Ananyev	{OPT_LONG_FECFG, 1, 0, OPT_SHORT_FECFG},
106aa97dd1cSKonstantin Ananyev	{OPT_LONG_STREAMS, 1, 0, OPT_SHORT_STREAMS},
107aa97dd1cSKonstantin Ananyev	{OPT_LONG_UDP, 0, 0, OPT_SHORT_UDP},
108aa97dd1cSKonstantin Ananyev	{OPT_LONG_TCP, 0, 0, OPT_SHORT_TCP},
1099fa82a63SReshma Pattan	{OPT_LONG_HASH, 1, 0, OPT_SHORT_HASH},
1109fa82a63SReshma Pattan	{OPT_LONG_SEC_KEY, 1, 0, OPT_SHORT_SEC_KEY},
111aa97dd1cSKonstantin Ananyev	{OPT_LONG_LISTEN, 0, 0, OPT_SHORT_LISTEN},
112aa97dd1cSKonstantin Ananyev	{OPT_LONG_VERBOSE, 1, 0, OPT_SHORT_VERBOSE},
1137e18fa1bSKonstantin Ananyev	{OPT_LONG_WINDOW, 1, 0, OPT_SHORT_WINDOW},
1147e18fa1bSKonstantin Ananyev	{OPT_LONG_TIMEWAIT, 1, 0, OPT_SHORT_TIMEWAIT},
1153726dc50SKonstantin Ananyev	{OPT_LONG_TXCNT, 1, 0, OPT_SHORT_TXCNT},
116aa97dd1cSKonstantin Ananyev	{NULL, 0, 0, 0}
117aa97dd1cSKonstantin Ananyev};
118aa97dd1cSKonstantin Ananyev
119aa97dd1cSKonstantin Ananyevstatic int
120aa97dd1cSKonstantin Ananyevparse_uint_val(__rte_unused const char *key, const char *val, void *prm)
121aa97dd1cSKonstantin Ananyev{
122aa97dd1cSKonstantin Ananyev	union parse_val *rv;
123aa97dd1cSKonstantin Ananyev	unsigned long v;
124aa97dd1cSKonstantin Ananyev	char *end;
125aa97dd1cSKonstantin Ananyev
126aa97dd1cSKonstantin Ananyev	rv = prm;
127aa97dd1cSKonstantin Ananyev	errno = 0;
128aa97dd1cSKonstantin Ananyev	v = strtoul(val, &end, 0);
129aa97dd1cSKonstantin Ananyev	if (errno != 0 || end[0] != 0 || v > UINT32_MAX)
130aa97dd1cSKonstantin Ananyev		return -EINVAL;
131aa97dd1cSKonstantin Ananyev
132aa97dd1cSKonstantin Ananyev	rv->u64 = v;
133aa97dd1cSKonstantin Ananyev	return 0;
134aa97dd1cSKonstantin Ananyev}
135aa97dd1cSKonstantin Ananyev
1363395610eSKonstantin Ananyevstatic int
1373395610eSKonstantin Ananyevparse_ipv4_val(__rte_unused const char *key, const char *val, void *prm)
1383395610eSKonstantin Ananyev{
1393395610eSKonstantin Ananyev	union parse_val *rv;
1403395610eSKonstantin Ananyev
1413395610eSKonstantin Ananyev	rv = prm;
1423395610eSKonstantin Ananyev	if (inet_pton(AF_INET, val, &rv->in.addr4) != 1)
1433395610eSKonstantin Ananyev		return -EINVAL;
1443395610eSKonstantin Ananyev	rv->in.family = AF_INET;
1453395610eSKonstantin Ananyev	return 0;
1463395610eSKonstantin Ananyev}
1473395610eSKonstantin Ananyev
1483395610eSKonstantin Ananyevstatic int
1493395610eSKonstantin Ananyevparse_ipv6_val(__rte_unused const char *key, const char *val, void *prm)
1503395610eSKonstantin Ananyev{
1513395610eSKonstantin Ananyev	union parse_val *rv;
1523395610eSKonstantin Ananyev
1533395610eSKonstantin Ananyev	rv = prm;
1543395610eSKonstantin Ananyev	if (inet_pton(AF_INET6, val, &rv->in.addr6) != 1)
1553395610eSKonstantin Ananyev		return -EINVAL;
1563395610eSKonstantin Ananyev	rv->in.family = AF_INET6;
1573395610eSKonstantin Ananyev	return 0;
1583395610eSKonstantin Ananyev}
1593395610eSKonstantin Ananyev
1603395610eSKonstantin Ananyevstatic int
1613395610eSKonstantin Ananyevparse_ip_val(__rte_unused const char *key, const char *val, void *prm)
1623395610eSKonstantin Ananyev{
1633395610eSKonstantin Ananyev	if (parse_ipv6_val(key, val, prm) != 0 &&
1643395610eSKonstantin Ananyev			parse_ipv4_val(key, val, prm) != 0)
1653395610eSKonstantin Ananyev		return -EINVAL;
1663395610eSKonstantin Ananyev	return 0;
1673395610eSKonstantin Ananyev}
1683395610eSKonstantin Ananyev
1693395610eSKonstantin Ananyev#define PARSE_UINT8x16(s, v, l)	                          \
1703395610eSKonstantin Ananyevdo {                                                      \
1713395610eSKonstantin Ananyev	char *end;                                        \
1723395610eSKonstantin Ananyev	unsigned long t;                                  \
1733395610eSKonstantin Ananyev	errno = 0;                                        \
1743395610eSKonstantin Ananyev	t = strtoul((s), &end, 16);                       \
1753395610eSKonstantin Ananyev	if (errno != 0 || end[0] != (l) || t > UINT8_MAX) \
1763395610eSKonstantin Ananyev		return -EINVAL;                           \
1773395610eSKonstantin Ananyev	(s) = end + 1;                                    \
1783395610eSKonstantin Ananyev	(v) = t;                                          \
1793395610eSKonstantin Ananyev} while (0)
1803395610eSKonstantin Ananyev
1813395610eSKonstantin Ananyevstatic int
1823395610eSKonstantin Ananyevparse_mac_val(__rte_unused const char *key, const char *val, void *prm)
1833395610eSKonstantin Ananyev{
1843395610eSKonstantin Ananyev	union parse_val *rv;
1853395610eSKonstantin Ananyev	const char *s;
1863395610eSKonstantin Ananyev
1873395610eSKonstantin Ananyev	rv = prm;
1883395610eSKonstantin Ananyev	s = val;
1893395610eSKonstantin Ananyev
1903395610eSKonstantin Ananyev	PARSE_UINT8x16(s, rv->mac.addr_bytes[0], ':');
1913395610eSKonstantin Ananyev	PARSE_UINT8x16(s, rv->mac.addr_bytes[1], ':');
1923395610eSKonstantin Ananyev	PARSE_UINT8x16(s, rv->mac.addr_bytes[2], ':');
1933395610eSKonstantin Ananyev	PARSE_UINT8x16(s, rv->mac.addr_bytes[3], ':');
1943395610eSKonstantin Ananyev	PARSE_UINT8x16(s, rv->mac.addr_bytes[4], ':');
1953395610eSKonstantin Ananyev	PARSE_UINT8x16(s, rv->mac.addr_bytes[5], 0);
1963395610eSKonstantin Ananyev	return 0;
1973395610eSKonstantin Ananyev}
1983395610eSKonstantin Ananyev
1993395610eSKonstantin Ananyevstatic int
2003395610eSKonstantin Ananyevparse_feop_val(__rte_unused const char *key, const char *val, void *prm)
2013395610eSKonstantin Ananyev{
2023395610eSKonstantin Ananyev	uint32_t i;
2033395610eSKonstantin Ananyev	union parse_val *rv;
2043395610eSKonstantin Ananyev
2053395610eSKonstantin Ananyev	rv = prm;
2063395610eSKonstantin Ananyev	for (i = 0; i != RTE_DIM(name2feop); i++) {
2073395610eSKonstantin Ananyev		if (strcmp(val, name2feop[i].name) == 0) {
2083395610eSKonstantin Ananyev			rv->u64 = name2feop[i].op;
2093395610eSKonstantin Ananyev			return 0;
2103395610eSKonstantin Ananyev		}
2113395610eSKonstantin Ananyev	}
2123395610eSKonstantin Ananyev
2133395610eSKonstantin Ananyev	return -EINVAL;
2143395610eSKonstantin Ananyev}
2153395610eSKonstantin Ananyev
2168ae38dfbSMohammad Abdul Awalstatic int
2178ae38dfbSMohammad Abdul Awalparse_lcore_list_val(__rte_unused const char *key, const char *val, void *prm)
2188ae38dfbSMohammad Abdul Awal{
2198ae38dfbSMohammad Abdul Awal	union parse_val *rv;
2208ae38dfbSMohammad Abdul Awal	unsigned long a, b;
2218ae38dfbSMohammad Abdul Awal	uint32_t i;
2228ae38dfbSMohammad Abdul Awal	char *end;
2238ae38dfbSMohammad Abdul Awal
2248ae38dfbSMohammad Abdul Awal	rv = prm;
225aa97dd1cSKonstantin Ananyev
2268ae38dfbSMohammad Abdul Awal	errno = 0;
2278ae38dfbSMohammad Abdul Awal	a = strtoul(val, &end, 0);
2288ae38dfbSMohammad Abdul Awal	if (errno != 0 || (end[0] != 0 && end[0] != '-') || a > UINT32_MAX)
2298ae38dfbSMohammad Abdul Awal		return -EINVAL;
2308ae38dfbSMohammad Abdul Awal
2318ae38dfbSMohammad Abdul Awal	if (end[0] == '-') {
2328ae38dfbSMohammad Abdul Awal		val = end + 1;
2338ae38dfbSMohammad Abdul Awal		errno = 0;
2348ae38dfbSMohammad Abdul Awal		b = strtoul(val, &end, 0);
2358ae38dfbSMohammad Abdul Awal		if (errno != 0 || end[0] != 0 || b > UINT32_MAX)
2368ae38dfbSMohammad Abdul Awal			return -EINVAL;
2378ae38dfbSMohammad Abdul Awal	} else
2388ae38dfbSMohammad Abdul Awal		b = a;
2398ae38dfbSMohammad Abdul Awal
2408ae38dfbSMohammad Abdul Awal	if (a <= b) {
2418ae38dfbSMohammad Abdul Awal		for (i = a; i <= b; i++)
2428ae38dfbSMohammad Abdul Awal			CPU_SET(i, &rv->cpuset);
2438ae38dfbSMohammad Abdul Awal	} else {
2448ae38dfbSMohammad Abdul Awal		RTE_LOG(ERR, USER1,
2458ae38dfbSMohammad Abdul Awal			"%s: lcores not in ascending order\n", __func__);
2468ae38dfbSMohammad Abdul Awal		return -EINVAL;
2478ae38dfbSMohammad Abdul Awal	}
2488ae38dfbSMohammad Abdul Awal
2498ae38dfbSMohammad Abdul Awal	return 0;
2508ae38dfbSMohammad Abdul Awal}
2518ae38dfbSMohammad Abdul Awal
2523395610eSKonstantin Ananyevstatic int
2533395610eSKonstantin Ananyevparse_kvargs(const char *arg, const char *keys_man[], uint32_t nb_man,
2543395610eSKonstantin Ananyev	const char *keys_opt[], uint32_t nb_opt,
2553395610eSKonstantin Ananyev	const arg_handler_t hndl[], union parse_val val[])
2563395610eSKonstantin Ananyev{
2573395610eSKonstantin Ananyev	uint32_t j, k;
2583395610eSKonstantin Ananyev	struct rte_kvargs *kvl;
2593395610eSKonstantin Ananyev
2603395610eSKonstantin Ananyev	kvl = rte_kvargs_parse(arg, NULL);
2613395610eSKonstantin Ananyev	if (kvl == NULL) {
2623395610eSKonstantin Ananyev		RTE_LOG(ERR, USER1,
2633395610eSKonstantin Ananyev			"%s: invalid parameter: %s\n",
2643395610eSKonstantin Ananyev			__func__, arg);
2653395610eSKonstantin Ananyev		return -EINVAL;
2663395610eSKonstantin Ananyev	}
2673395610eSKonstantin Ananyev
2683395610eSKonstantin Ananyev	for (j = 0; j != nb_man; j++) {
2693395610eSKonstantin Ananyev		if (rte_kvargs_count(kvl, keys_man[j]) == 0) {
2703395610eSKonstantin Ananyev			RTE_LOG(ERR, USER1,
2713395610eSKonstantin Ananyev				"%s: %s missing mandatory key: %s\n",
2723395610eSKonstantin Ananyev				__func__, arg, keys_man[j]);
2733395610eSKonstantin Ananyev			rte_kvargs_free(kvl);
2743395610eSKonstantin Ananyev			return -EINVAL;
2753395610eSKonstantin Ananyev		}
2763395610eSKonstantin Ananyev	}
2773395610eSKonstantin Ananyev
2783395610eSKonstantin Ananyev	for (j = 0; j != nb_man; j++) {
2793395610eSKonstantin Ananyev		if (rte_kvargs_process(kvl, keys_man[j], hndl[j],
2803395610eSKonstantin Ananyev				val + j) != 0) {
2813395610eSKonstantin Ananyev			RTE_LOG(ERR, USER1,
2828ae38dfbSMohammad Abdul Awal				"%s: %s invalid value for man key: %s\n",
2833395610eSKonstantin Ananyev				__func__, arg, keys_man[j]);
2843395610eSKonstantin Ananyev			rte_kvargs_free(kvl);
2853395610eSKonstantin Ananyev			return -EINVAL;
2863395610eSKonstantin Ananyev		}
2873395610eSKonstantin Ananyev	}
2883395610eSKonstantin Ananyev
2893395610eSKonstantin Ananyev	for (j = 0; j != nb_opt; j++) {
2903395610eSKonstantin Ananyev		k = j + nb_man;
2913395610eSKonstantin Ananyev		if (rte_kvargs_process(kvl, keys_opt[j], hndl[k],
2923395610eSKonstantin Ananyev				val + k) != 0) {
2933395610eSKonstantin Ananyev			RTE_LOG(ERR, USER1,
2948ae38dfbSMohammad Abdul Awal				"%s: %s invalid value for opt key: %s\n",
2953395610eSKonstantin Ananyev				__func__, arg, keys_opt[j]);
2963395610eSKonstantin Ananyev			rte_kvargs_free(kvl);
2973395610eSKonstantin Ananyev			return -EINVAL;
2983395610eSKonstantin Ananyev		}
2993395610eSKonstantin Ananyev	}
3003395610eSKonstantin Ananyev
3013395610eSKonstantin Ananyev	rte_kvargs_free(kvl);
3023395610eSKonstantin Ananyev	return 0;
3033395610eSKonstantin Ananyev}
3043395610eSKonstantin Ananyev
3053395610eSKonstantin Ananyevint
306aa97dd1cSKonstantin Ananyevparse_netbe_arg(struct netbe_port *prt, const char *arg, rte_cpuset_t *pcpu)
3073395610eSKonstantin Ananyev{
3083395610eSKonstantin Ananyev	int32_t rc;
309258f299aSMohammad Abdul Awal	uint32_t i, j, nc;
3103395610eSKonstantin Ananyev
3113395610eSKonstantin Ananyev	static const char *keys_man[] = {
3123395610eSKonstantin Ananyev		"port",
3133395610eSKonstantin Ananyev		"lcore",
3143395610eSKonstantin Ananyev	};
3153395610eSKonstantin Ananyev
3163395610eSKonstantin Ananyev	static const char *keys_opt[] = {
3173395610eSKonstantin Ananyev		"mtu",
3183395610eSKonstantin Ananyev		"rx_offload",
3193395610eSKonstantin Ananyev		"tx_offload",
3203395610eSKonstantin Ananyev		"ipv4",
3213395610eSKonstantin Ananyev		"ipv6",
3223395610eSKonstantin Ananyev	};
3233395610eSKonstantin Ananyev
3243395610eSKonstantin Ananyev	static const arg_handler_t hndl[] = {
3253395610eSKonstantin Ananyev		parse_uint_val,
3268ae38dfbSMohammad Abdul Awal		parse_lcore_list_val,
3273395610eSKonstantin Ananyev		parse_uint_val,
3283395610eSKonstantin Ananyev		parse_uint_val,
3293395610eSKonstantin Ananyev		parse_uint_val,
3303395610eSKonstantin Ananyev		parse_ipv4_val,
3313395610eSKonstantin Ananyev		parse_ipv6_val,
3323395610eSKonstantin Ananyev	};
3333395610eSKonstantin Ananyev
3343395610eSKonstantin Ananyev	union parse_val val[RTE_DIM(hndl)];
3353395610eSKonstantin Ananyev
3363395610eSKonstantin Ananyev	memset(val, 0, sizeof(val));
33736d90e3aSMohammad Abdul Awal	val[2].u64 = ETHER_MAX_LEN - ETHER_CRC_LEN;
3383395610eSKonstantin Ananyev
3393395610eSKonstantin Ananyev	rc = parse_kvargs(arg, keys_man, RTE_DIM(keys_man),
3403395610eSKonstantin Ananyev		keys_opt, RTE_DIM(keys_opt), hndl, val);
3413395610eSKonstantin Ananyev	if (rc != 0)
3423395610eSKonstantin Ananyev		return rc;
3433395610eSKonstantin Ananyev
3443395610eSKonstantin Ananyev	prt->id = val[0].u64;
345258f299aSMohammad Abdul Awal
346258f299aSMohammad Abdul Awal	for (i = 0, nc = 0; i < RTE_MAX_LCORE; i++)
347258f299aSMohammad Abdul Awal		nc += CPU_ISSET(i, &val[1].cpuset);
348aa97dd1cSKonstantin Ananyev	prt->lcore_id = rte_zmalloc(NULL, nc * sizeof(prt->lcore_id[0]),
349258f299aSMohammad Abdul Awal		RTE_CACHE_LINE_SIZE);
350258f299aSMohammad Abdul Awal	prt->nb_lcore = nc;
351258f299aSMohammad Abdul Awal
3528ae38dfbSMohammad Abdul Awal	for (i = 0, j = 0; i < RTE_MAX_LCORE; i++)
3538ae38dfbSMohammad Abdul Awal		if (CPU_ISSET(i, &val[1].cpuset))
354aa97dd1cSKonstantin Ananyev			prt->lcore_id[j++] = i;
355aa97dd1cSKonstantin Ananyev	CPU_OR(pcpu, pcpu, &val[1].cpuset);
356258f299aSMohammad Abdul Awal
3573395610eSKonstantin Ananyev	prt->mtu = val[2].u64;
3583395610eSKonstantin Ananyev	prt->rx_offload = val[3].u64;
3593395610eSKonstantin Ananyev	prt->tx_offload = val[4].u64;
3603395610eSKonstantin Ananyev	prt->ipv4 = val[5].in.addr4.s_addr;
3613395610eSKonstantin Ananyev	prt->ipv6 = val[6].in.addr6;
3623395610eSKonstantin Ananyev
3633395610eSKonstantin Ananyev	return 0;
3643395610eSKonstantin Ananyev}
3658ae38dfbSMohammad Abdul Awal
3663395610eSKonstantin Ananyevstatic int
3673395610eSKonstantin Ananyevcheck_netbe_dest(const struct netbe_dest *dst)
3683395610eSKonstantin Ananyev{
3693395610eSKonstantin Ananyev	if (dst->port >= RTE_MAX_ETHPORTS) {
3703395610eSKonstantin Ananyev		RTE_LOG(ERR, USER1, "%s(line=%u) invalid port=%u",
3713395610eSKonstantin Ananyev			__func__, dst->line, dst->port);
3723395610eSKonstantin Ananyev		return -EINVAL;
3733395610eSKonstantin Ananyev	} else if ((dst->family == AF_INET &&
3743395610eSKonstantin Ananyev			dst->prfx > sizeof(struct in_addr) * CHAR_BIT) ||
3753395610eSKonstantin Ananyev			(dst->family == AF_INET6 &&
3763395610eSKonstantin Ananyev			dst->prfx > sizeof(struct in6_addr) * CHAR_BIT)) {
3773395610eSKonstantin Ananyev		RTE_LOG(ERR, USER1, "%s(line=%u) invalid masklen=%u",
3783395610eSKonstantin Ananyev			__func__, dst->line, dst->prfx);
3793395610eSKonstantin Ananyev		return -EINVAL;
3803395610eSKonstantin Ananyev	} else if (dst->mtu > ETHER_MAX_JUMBO_FRAME_LEN - ETHER_CRC_LEN) {
3813395610eSKonstantin Ananyev		RTE_LOG(ERR, USER1, "%s(line=%u) invalid mtu=%u",
3823395610eSKonstantin Ananyev			__func__, dst->line, dst->mtu);
3833395610eSKonstantin Ananyev		return -EINVAL;
3843395610eSKonstantin Ananyev	}
3853395610eSKonstantin Ananyev	return 0;
3863395610eSKonstantin Ananyev}
3873395610eSKonstantin Ananyev
3883395610eSKonstantin Ananyevstatic int
3893395610eSKonstantin Ananyevparse_netbe_dest(struct netbe_dest *dst, const char *arg)
3903395610eSKonstantin Ananyev{
3913395610eSKonstantin Ananyev	int32_t rc;
3923395610eSKonstantin Ananyev
3933395610eSKonstantin Ananyev	static const char *keys_man[] = {
3943395610eSKonstantin Ananyev		"port",
3953395610eSKonstantin Ananyev		"addr",
3963395610eSKonstantin Ananyev		"masklen",
3973395610eSKonstantin Ananyev		"mac",
3983395610eSKonstantin Ananyev	};
3993395610eSKonstantin Ananyev
4003395610eSKonstantin Ananyev	static const char *keys_opt[] = {
4013395610eSKonstantin Ananyev		"mtu",
4023395610eSKonstantin Ananyev	};
4033395610eSKonstantin Ananyev
4043395610eSKonstantin Ananyev	static const arg_handler_t hndl[] = {
4053395610eSKonstantin Ananyev		parse_uint_val,
4063395610eSKonstantin Ananyev		parse_ip_val,
4073395610eSKonstantin Ananyev		parse_uint_val,
4083395610eSKonstantin Ananyev		parse_mac_val,
4093395610eSKonstantin Ananyev		parse_uint_val,
4103395610eSKonstantin Ananyev	};
4113395610eSKonstantin Ananyev
4123395610eSKonstantin Ananyev	union parse_val val[RTE_DIM(hndl)];
4133395610eSKonstantin Ananyev
4143395610eSKonstantin Ananyev	/* set default values. */
4153395610eSKonstantin Ananyev	memset(val, 0, sizeof(val));
4163395610eSKonstantin Ananyev	val[4].u64 = ETHER_MAX_JUMBO_FRAME_LEN - ETHER_CRC_LEN;
4173395610eSKonstantin Ananyev
4183395610eSKonstantin Ananyev	rc = parse_kvargs(arg, keys_man, RTE_DIM(keys_man),
4193395610eSKonstantin Ananyev		keys_opt, RTE_DIM(keys_opt), hndl, val);
4203395610eSKonstantin Ananyev	if (rc != 0)
4213395610eSKonstantin Ananyev		return rc;
4223395610eSKonstantin Ananyev
4233395610eSKonstantin Ananyev	dst->port = val[0].u64;
4243395610eSKonstantin Ananyev	dst->family = val[1].in.family;
4253395610eSKonstantin Ananyev	if (val[1].in.family == AF_INET)
4263395610eSKonstantin Ananyev		dst->ipv4 = val[1].in.addr4;
4273395610eSKonstantin Ananyev	else
4283395610eSKonstantin Ananyev		dst->ipv6 = val[1].in.addr6;
4293395610eSKonstantin Ananyev	dst->prfx = val[2].u64;
4303395610eSKonstantin Ananyev	memcpy(&dst->mac, &val[3].mac, sizeof(dst->mac));
4313395610eSKonstantin Ananyev	dst->mtu = val[4].u64;
4323395610eSKonstantin Ananyev
4333395610eSKonstantin Ananyev	return 0;
4343395610eSKonstantin Ananyev}
4353395610eSKonstantin Ananyev
4363395610eSKonstantin Ananyevint
4373395610eSKonstantin Ananyevnetbe_parse_dest(const char *fname, struct netbe_dest_prm *prm)
4383395610eSKonstantin Ananyev{
4393395610eSKonstantin Ananyev	uint32_t i, ln, n, num;
4403395610eSKonstantin Ananyev	int32_t rc;
4413395610eSKonstantin Ananyev	size_t sz;
4423395610eSKonstantin Ananyev	char *s;
4433395610eSKonstantin Ananyev	FILE *f;
4443395610eSKonstantin Ananyev	struct netbe_dest *dp;
4453395610eSKonstantin Ananyev	char line[LINE_MAX];
4463395610eSKonstantin Ananyev
4473395610eSKonstantin Ananyev	f = fopen(fname, "r");
4483395610eSKonstantin Ananyev	if (f == NULL) {
4493395610eSKonstantin Ananyev		RTE_LOG(ERR, USER1, "%s failed to open file \"%s\"\n",
4503395610eSKonstantin Ananyev			__func__, fname);
4513395610eSKonstantin Ananyev		return -EINVAL;
4523395610eSKonstantin Ananyev	}
4533395610eSKonstantin Ananyev
4543395610eSKonstantin Ananyev	n = 0;
4553395610eSKonstantin Ananyev	num = 0;
4563395610eSKonstantin Ananyev	dp = NULL;
457aa97dd1cSKonstantin Ananyev	rc = 0;
4583395610eSKonstantin Ananyev	for (ln = 0; fgets(line, sizeof(line), f) != NULL; ln++) {
4593395610eSKonstantin Ananyev
4603395610eSKonstantin Ananyev		/* skip spaces at the start. */
4613395610eSKonstantin Ananyev		for (s = line; isspace(s[0]); s++)
4623395610eSKonstantin Ananyev			;
4633395610eSKonstantin Ananyev
4643395610eSKonstantin Ananyev		/* skip comment line. */
4653395610eSKonstantin Ananyev		if (s[0] == '#' || s[0] == 0)
4663395610eSKonstantin Ananyev			continue;
4673395610eSKonstantin Ananyev
4683395610eSKonstantin Ananyev		/* skip spaces at the end. */
4693395610eSKonstantin Ananyev		for (i = strlen(s); i-- != 0 && isspace(s[i]); s[i] = 0)
4703395610eSKonstantin Ananyev			;
4713395610eSKonstantin Ananyev
4723395610eSKonstantin Ananyev		if (n == num) {
4733395610eSKonstantin Ananyev			num += DEF_LINE_NUM;
4743395610eSKonstantin Ananyev			sz = sizeof(dp[0]) * num;
4753395610eSKonstantin Ananyev			dp = realloc(dp, sizeof(dp[0]) * num);
4763395610eSKonstantin Ananyev			if (dp == NULL) {
4773395610eSKonstantin Ananyev				RTE_LOG(ERR, USER1,
4783395610eSKonstantin Ananyev					"%s(%s) allocation of %zu bytes "
4793395610eSKonstantin Ananyev					"failed\n",
4803395610eSKonstantin Ananyev					__func__, fname, sz);
4813395610eSKonstantin Ananyev				rc = -ENOMEM;
4823395610eSKonstantin Ananyev				break;
4833395610eSKonstantin Ananyev			}
484d09ce4f4SMohammad Abdul Awal			memset(&dp[n], 0, sizeof(dp[0]) * (num - n));
4853395610eSKonstantin Ananyev		}
4863395610eSKonstantin Ananyev
4873395610eSKonstantin Ananyev		dp[n].line = ln + 1;
488aa97dd1cSKonstantin Ananyev		rc = parse_netbe_dest(dp + n, s);
489aa97dd1cSKonstantin Ananyev		rc = (rc != 0) ? rc : check_netbe_dest(dp + n);
490aa97dd1cSKonstantin Ananyev		if (rc != 0) {
4913395610eSKonstantin Ananyev			RTE_LOG(ERR, USER1, "%s(%s) failed to parse line %u\n",
4923395610eSKonstantin Ananyev				__func__, fname, dp[n].line);
4933395610eSKonstantin Ananyev			break;
4943395610eSKonstantin Ananyev		}
4953395610eSKonstantin Ananyev		n++;
4963395610eSKonstantin Ananyev	}
4973395610eSKonstantin Ananyev
4983395610eSKonstantin Ananyev	fclose(f);
4993395610eSKonstantin Ananyev
5003395610eSKonstantin Ananyev	if (rc != 0) {
5013395610eSKonstantin Ananyev		free(dp);
5023395610eSKonstantin Ananyev		dp = NULL;
5033395610eSKonstantin Ananyev		n = 0;
5043395610eSKonstantin Ananyev	}
5053395610eSKonstantin Ananyev
5063395610eSKonstantin Ananyev	prm->dest = dp;
5073395610eSKonstantin Ananyev	prm->nb_dest = n;
5083395610eSKonstantin Ananyev	return rc;
5093395610eSKonstantin Ananyev}
5103395610eSKonstantin Ananyev
5113395610eSKonstantin Ananyevstatic void
5123395610eSKonstantin Ananyevpv2saddr(struct sockaddr_storage *ss, const union parse_val *pva,
5133395610eSKonstantin Ananyev	const union parse_val *pvp)
5143395610eSKonstantin Ananyev{
5153395610eSKonstantin Ananyev	ss->ss_family = pva->in.family;
5163395610eSKonstantin Ananyev	if (pva->in.family == AF_INET) {
5173395610eSKonstantin Ananyev		struct sockaddr_in *si = (struct sockaddr_in *)ss;
5183395610eSKonstantin Ananyev		si->sin_addr = pva->in.addr4;
5193395610eSKonstantin Ananyev		si->sin_port = rte_cpu_to_be_16((uint16_t)pvp->u64);
5203395610eSKonstantin Ananyev	} else {
5213395610eSKonstantin Ananyev		struct sockaddr_in6 *si = (struct sockaddr_in6 *)ss;
5223395610eSKonstantin Ananyev		si->sin6_addr = pva->in.addr6;
5233395610eSKonstantin Ananyev		si->sin6_port = rte_cpu_to_be_16((uint16_t)pvp->u64);
5243395610eSKonstantin Ananyev	}
5253395610eSKonstantin Ananyev}
5263395610eSKonstantin Ananyev
5273395610eSKonstantin Ananyevstatic int
5283395610eSKonstantin Ananyevparse_netfe_arg(struct netfe_stream_prm *sp, const char *arg)
5293395610eSKonstantin Ananyev{
5303395610eSKonstantin Ananyev	int32_t rc;
5313395610eSKonstantin Ananyev
5323395610eSKonstantin Ananyev	static const char *keys_man[] = {
5333395610eSKonstantin Ananyev		"lcore",
5343395610eSKonstantin Ananyev		"op",
5353395610eSKonstantin Ananyev		"laddr",
5363395610eSKonstantin Ananyev		"lport",
5373395610eSKonstantin Ananyev		"raddr",
5383395610eSKonstantin Ananyev		"rport",
5393395610eSKonstantin Ananyev	};
5403395610eSKonstantin Ananyev
5413395610eSKonstantin Ananyev	static const char *keys_opt[] = {
5423395610eSKonstantin Ananyev		"txlen",
5433395610eSKonstantin Ananyev		"fwladdr",
5443395610eSKonstantin Ananyev		"fwlport",
5453395610eSKonstantin Ananyev		"fwraddr",
5463395610eSKonstantin Ananyev		"fwrport",
5478ae38dfbSMohammad Abdul Awal		"belcore",
548e151ee29SRemy Horton		"rxlen",
5493395610eSKonstantin Ananyev	};
5503395610eSKonstantin Ananyev
5513395610eSKonstantin Ananyev	static const arg_handler_t hndl[] = {
5523395610eSKonstantin Ananyev		parse_uint_val,
5533395610eSKonstantin Ananyev		parse_feop_val,
5543395610eSKonstantin Ananyev		parse_ip_val,
5553395610eSKonstantin Ananyev		parse_uint_val,
5563395610eSKonstantin Ananyev		parse_ip_val,
5573395610eSKonstantin Ananyev		parse_uint_val,
5583395610eSKonstantin Ananyev		parse_uint_val,
5593395610eSKonstantin Ananyev		parse_ip_val,
5603395610eSKonstantin Ananyev		parse_uint_val,
5613395610eSKonstantin Ananyev		parse_ip_val,
5623395610eSKonstantin Ananyev		parse_uint_val,
5638ae38dfbSMohammad Abdul Awal		parse_uint_val,
564e151ee29SRemy Horton		parse_uint_val,
5653395610eSKonstantin Ananyev	};
5663395610eSKonstantin Ananyev
5673395610eSKonstantin Ananyev	union parse_val val[RTE_DIM(hndl)];
5683395610eSKonstantin Ananyev
5693395610eSKonstantin Ananyev	memset(val, 0, sizeof(val));
5708ae38dfbSMohammad Abdul Awal	val[11].u64 = LCORE_ID_ANY;
5713395610eSKonstantin Ananyev	rc = parse_kvargs(arg, keys_man, RTE_DIM(keys_man),
5723395610eSKonstantin Ananyev		keys_opt, RTE_DIM(keys_opt), hndl, val);
5733395610eSKonstantin Ananyev	if (rc != 0)
5743395610eSKonstantin Ananyev		return rc;
5753395610eSKonstantin Ananyev	sp->lcore = val[0].u64;
5763395610eSKonstantin Ananyev	sp->op = val[1].u64;
577aa97dd1cSKonstantin Ananyev	pv2saddr(&sp->sprm.local_addr, val + 2, val + 3);
578aa97dd1cSKonstantin Ananyev	pv2saddr(&sp->sprm.remote_addr, val + 4, val + 5);
5793395610eSKonstantin Ananyev	sp->txlen = val[6].u64;
580aa97dd1cSKonstantin Ananyev	pv2saddr(&sp->fprm.local_addr, val + 7, val + 8);
581aa97dd1cSKonstantin Ananyev	pv2saddr(&sp->fprm.remote_addr, val + 9, val + 10);
582aa97dd1cSKonstantin Ananyev	sp->belcore = val[11].u64;
583e151ee29SRemy Horton	sp->rxlen = val[12].u64;
5843395610eSKonstantin Ananyev
5853395610eSKonstantin Ananyev	return 0;
5863395610eSKonstantin Ananyev}
5873395610eSKonstantin Ananyev
5883395610eSKonstantin Ananyevstatic const char *
5893395610eSKonstantin Ananyevformat_feop(uint16_t op)
5903395610eSKonstantin Ananyev{
5913395610eSKonstantin Ananyev	uint32_t i;
5923395610eSKonstantin Ananyev
5933395610eSKonstantin Ananyev	for (i = 0; i != RTE_DIM(name2feop); i++) {
5943395610eSKonstantin Ananyev		if (name2feop[i].op == op)
5953395610eSKonstantin Ananyev			return name2feop[i].name;
5963395610eSKonstantin Ananyev	}
5973395610eSKonstantin Ananyev
5983395610eSKonstantin Ananyev	return NULL;
5993395610eSKonstantin Ananyev}
6003395610eSKonstantin Ananyev
6013395610eSKonstantin Ananyevstatic int
6023395610eSKonstantin Ananyevis_addr_wc(const struct sockaddr_storage *sp)
6033395610eSKonstantin Ananyev{
6043395610eSKonstantin Ananyev	const struct sockaddr_in *i4;
6053395610eSKonstantin Ananyev	const struct sockaddr_in6 *i6;
6063395610eSKonstantin Ananyev
6073395610eSKonstantin Ananyev	if (sp->ss_family == AF_INET) {
6083395610eSKonstantin Ananyev		i4 = (const struct sockaddr_in *)sp;
6093395610eSKonstantin Ananyev		return  (i4->sin_addr.s_addr == INADDR_ANY);
6103395610eSKonstantin Ananyev	} else if (sp->ss_family == AF_INET6) {
6113395610eSKonstantin Ananyev		i6 = (const struct sockaddr_in6 *)sp;
6123395610eSKonstantin Ananyev		return (memcmp(&i6->sin6_addr, &in6addr_any,
6133395610eSKonstantin Ananyev			sizeof(i6->sin6_addr)) == 0);
6143395610eSKonstantin Ananyev	}
6153395610eSKonstantin Ananyev	return 0;
6163395610eSKonstantin Ananyev}
6173395610eSKonstantin Ananyev
6183395610eSKonstantin Ananyevstatic int
6193395610eSKonstantin Ananyevcheck_netfe_arg(const struct netfe_stream_prm *sp)
6203395610eSKonstantin Ananyev{
6213395610eSKonstantin Ananyev	char buf[INET6_ADDRSTRLEN];
6223395610eSKonstantin Ananyev
623aa97dd1cSKonstantin Ananyev	if (sp->sprm.local_addr.ss_family !=
624aa97dd1cSKonstantin Ananyev			sp->sprm.remote_addr.ss_family) {
6253395610eSKonstantin Ananyev		RTE_LOG(ERR, USER1, "invalid arg at line %u: "
6263395610eSKonstantin Ananyev			"laddr and raddr for different protocols\n",
6273395610eSKonstantin Ananyev			sp->line);
6283395610eSKonstantin Ananyev		return -EINVAL;
6293395610eSKonstantin Ananyev	}
6303395610eSKonstantin Ananyev
6313395610eSKonstantin Ananyev	if (sp->op == TXONLY) {
6323395610eSKonstantin Ananyev		if (sp->txlen > RTE_MBUF_DEFAULT_DATAROOM || sp->txlen == 0) {
6333395610eSKonstantin Ananyev			RTE_LOG(ERR, USER1, "invalid arg at line %u: txlen=%u "
6343395610eSKonstantin Ananyev				"exceeds allowed values: (0, %u]\n",
6353395610eSKonstantin Ananyev				sp->line, sp->txlen, RTE_MBUF_DEFAULT_DATAROOM);
6363395610eSKonstantin Ananyev			return -EINVAL;
637aa97dd1cSKonstantin Ananyev		} else if (is_addr_wc(&sp->sprm.remote_addr)) {
6383395610eSKonstantin Ananyev			RTE_LOG(ERR, USER1, "invalid arg at line %u: "
6393395610eSKonstantin Ananyev				"raddr=%s are not allowed for op=%s;\n",
6403395610eSKonstantin Ananyev				sp->line,
641aa97dd1cSKonstantin Ananyev				format_addr(&sp->sprm.remote_addr,
6423395610eSKonstantin Ananyev				buf, sizeof(buf)),
6433395610eSKonstantin Ananyev				format_feop(sp->op));
6443395610eSKonstantin Ananyev			return -EINVAL;
6453395610eSKonstantin Ananyev		}
6463395610eSKonstantin Ananyev	} else if (sp->op == FWD) {
647aa97dd1cSKonstantin Ananyev		if (sp->fprm.local_addr.ss_family !=
648aa97dd1cSKonstantin Ananyev				sp->fprm.remote_addr.ss_family) {
6493395610eSKonstantin Ananyev			RTE_LOG(ERR, USER1, "invalid arg at line %u: "
6503395610eSKonstantin Ananyev				"fwladdr and fwraddr for different protocols\n",
6513395610eSKonstantin Ananyev				sp->line);
6523395610eSKonstantin Ananyev			return -EINVAL;
653aa97dd1cSKonstantin Ananyev		} else if (is_addr_wc(&sp->fprm.remote_addr)) {
6543395610eSKonstantin Ananyev			RTE_LOG(ERR, USER1, "invalid arg at line %u: "
6553395610eSKonstantin Ananyev				"fwaddr=%s are not allowed for op=%s;\n",
6563395610eSKonstantin Ananyev				sp->line,
657aa97dd1cSKonstantin Ananyev				format_addr(&sp->fprm.remote_addr,
6583395610eSKonstantin Ananyev				buf, sizeof(buf)),
6593395610eSKonstantin Ananyev				format_feop(sp->op));
6603395610eSKonstantin Ananyev			return -EINVAL;
6613395610eSKonstantin Ananyev		}
662e151ee29SRemy Horton	} else if (sp->op == RXTX) {
663e151ee29SRemy Horton		/* RXTX: Check tx pkt size */
664e151ee29SRemy Horton		if (sp->txlen == 0) {
665e151ee29SRemy Horton			RTE_LOG(ERR, USER1, "invalid arg at line %u: "
666e151ee29SRemy Horton				"txlen cannot be zero.\n", sp->line);
667e151ee29SRemy Horton			return -EINVAL;
668e151ee29SRemy Horton		}
669e151ee29SRemy Horton		if (sp->rxlen == 0) {
670e151ee29SRemy Horton			RTE_LOG(ERR, USER1, "invalid arg at line %u: "
671e151ee29SRemy Horton				"rxlen cannot be zero.\n", sp->line);
672e151ee29SRemy Horton			return -EINVAL;
673e151ee29SRemy Horton		}
6743395610eSKonstantin Ananyev	}
6753395610eSKonstantin Ananyev
6763395610eSKonstantin Ananyev	return 0;
6773395610eSKonstantin Ananyev}
6783395610eSKonstantin Ananyev
6793395610eSKonstantin Ananyevint
6803395610eSKonstantin Ananyevnetfe_parse_cfg(const char *fname, struct netfe_lcore_prm *lp)
6813395610eSKonstantin Ananyev{
6823395610eSKonstantin Ananyev	uint32_t i, ln, n, num;
6833395610eSKonstantin Ananyev	int32_t rc;
6843395610eSKonstantin Ananyev	size_t sz;
6853395610eSKonstantin Ananyev	char *s;
6863395610eSKonstantin Ananyev	FILE *f;
6873395610eSKonstantin Ananyev	struct netfe_stream_prm *sp;
6883395610eSKonstantin Ananyev	char line[LINE_MAX];
6893395610eSKonstantin Ananyev
6903395610eSKonstantin Ananyev	f = fopen(fname, "r");
6913395610eSKonstantin Ananyev	if (f == NULL) {
6923395610eSKonstantin Ananyev		RTE_LOG(ERR, USER1, "%s failed to open file \"%s\"\n",
6933395610eSKonstantin Ananyev			__func__, fname);
6943395610eSKonstantin Ananyev		return -EINVAL;
6953395610eSKonstantin Ananyev	}
6963395610eSKonstantin Ananyev
6973395610eSKonstantin Ananyev	n = 0;
6983395610eSKonstantin Ananyev	num = 0;
6993395610eSKonstantin Ananyev	sp = NULL;
700aa97dd1cSKonstantin Ananyev	rc = 0;
7013395610eSKonstantin Ananyev	for (ln = 0; fgets(line, sizeof(line), f) != NULL; ln++) {
7023395610eSKonstantin Ananyev
7033395610eSKonstantin Ananyev		/* skip spaces at the start. */
7043395610eSKonstantin Ananyev		for (s = line; isspace(s[0]); s++)
7053395610eSKonstantin Ananyev			;
7063395610eSKonstantin Ananyev
7073395610eSKonstantin Ananyev		/* skip comment line. */
7083395610eSKonstantin Ananyev		if (s[0] == '#' || s[0] == 0)
7093395610eSKonstantin Ananyev			continue;
7103395610eSKonstantin Ananyev
7113395610eSKonstantin Ananyev		/* skip spaces at the end. */
7123395610eSKonstantin Ananyev		for (i = strlen(s); i-- != 0 && isspace(s[i]); s[i] = 0)
7133395610eSKonstantin Ananyev			;
7143395610eSKonstantin Ananyev
7153395610eSKonstantin Ananyev		if (n == lp->max_streams) {
7163395610eSKonstantin Ananyev			RTE_LOG(ERR, USER1,
7173395610eSKonstantin Ananyev				"%s(%s) number of entries exceed max streams "
7183395610eSKonstantin Ananyev				"value: %u\n",
7193395610eSKonstantin Ananyev				__func__, fname, n);
7203395610eSKonstantin Ananyev				rc = -EINVAL;
7213395610eSKonstantin Ananyev				break;
7223395610eSKonstantin Ananyev		}
7233395610eSKonstantin Ananyev
7243395610eSKonstantin Ananyev		if (n == num) {
7253395610eSKonstantin Ananyev			num += DEF_LINE_NUM;
7263395610eSKonstantin Ananyev			sz = sizeof(sp[0]) * num;
7273395610eSKonstantin Ananyev			sp = realloc(sp, sizeof(sp[0]) * num);
7283395610eSKonstantin Ananyev			if (sp == NULL) {
7293395610eSKonstantin Ananyev				RTE_LOG(ERR, USER1,
7303395610eSKonstantin Ananyev					"%s(%s) allocation of %zu bytes "
7313395610eSKonstantin Ananyev					"failed\n",
7323395610eSKonstantin Ananyev					__func__, fname, sz);
7333395610eSKonstantin Ananyev				rc = -ENOMEM;
7343395610eSKonstantin Ananyev				break;
7353395610eSKonstantin Ananyev			}
736d09ce4f4SMohammad Abdul Awal			memset(&sp[n], 0, sizeof(sp[0]) * (num - n));
7373395610eSKonstantin Ananyev		}
7383395610eSKonstantin Ananyev
7393395610eSKonstantin Ananyev		sp[n].line = ln + 1;
740aa97dd1cSKonstantin Ananyev		rc = parse_netfe_arg(sp + n, s);
741aa97dd1cSKonstantin Ananyev		rc = (rc != 0) ? rc : check_netfe_arg(sp + n);
742aa97dd1cSKonstantin Ananyev		if (rc != 0) {
7433395610eSKonstantin Ananyev			RTE_LOG(ERR, USER1, "%s(%s) failed to parse line %u\n",
7443395610eSKonstantin Ananyev				__func__, fname, sp[n].line);
7453395610eSKonstantin Ananyev			break;
7463395610eSKonstantin Ananyev		}
7473395610eSKonstantin Ananyev		n++;
7483395610eSKonstantin Ananyev	}
7493395610eSKonstantin Ananyev
7503395610eSKonstantin Ananyev	fclose(f);
7513395610eSKonstantin Ananyev
7523395610eSKonstantin Ananyev	if (rc != 0) {
7533395610eSKonstantin Ananyev		free(sp);
7543395610eSKonstantin Ananyev		sp = NULL;
7553395610eSKonstantin Ananyev		n = 0;
7563395610eSKonstantin Ananyev	}
7573395610eSKonstantin Ananyev
7583395610eSKonstantin Ananyev	lp->stream = sp;
7593395610eSKonstantin Ananyev	lp->nb_streams = n;
7603395610eSKonstantin Ananyev	return rc;
7613395610eSKonstantin Ananyev}
762aa97dd1cSKonstantin Ananyev
7639fa82a63SReshma Pattanstatic uint32_t
7649fa82a63SReshma Pattanparse_hash_alg(const char *val)
7659fa82a63SReshma Pattan{
7669fa82a63SReshma Pattan	if (strcmp(val, "jhash") == 0)
7679fa82a63SReshma Pattan		return TLE_JHASH;
7689fa82a63SReshma Pattan	else if (strcmp(val, "siphash") == 0)
7699fa82a63SReshma Pattan		return TLE_SIPHASH;
7709fa82a63SReshma Pattan	else
7719fa82a63SReshma Pattan		return TLE_HASH_NUM;
7729fa82a63SReshma Pattan}
7739fa82a63SReshma Pattan
7743726dc50SKonstantin Ananyevstatic int
7753726dc50SKonstantin Ananyevread_tx_content(const char *fname, struct tx_content *tx)
7763726dc50SKonstantin Ananyev{
7773726dc50SKonstantin Ananyev	int32_t fd, rc;
7783726dc50SKonstantin Ananyev	ssize_t sz;
7793726dc50SKonstantin Ananyev	struct stat st;
7803726dc50SKonstantin Ananyev
7813726dc50SKonstantin Ananyev	rc = stat(fname, &st);
7823726dc50SKonstantin Ananyev	if (rc != 0)
7833726dc50SKonstantin Ananyev		return -errno;
7843726dc50SKonstantin Ananyev
7853726dc50SKonstantin Ananyev	tx->data = rte_malloc(NULL, st.st_size, RTE_CACHE_LINE_SIZE);
7863726dc50SKonstantin Ananyev	if (tx->data == NULL) {
7873726dc50SKonstantin Ananyev		RTE_LOG(ERR, USER1, "%s(%s): failed to alloc %zu bytes;\n",
7883726dc50SKonstantin Ananyev			__func__, fname, st.st_size);
7893726dc50SKonstantin Ananyev		return -ENOMEM;
7903726dc50SKonstantin Ananyev	}
7913726dc50SKonstantin Ananyev
7923726dc50SKonstantin Ananyev	fd = open(fname, O_RDONLY);
7933726dc50SKonstantin Ananyev	sz = read(fd, tx->data, st.st_size);
7943726dc50SKonstantin Ananyev
7953726dc50SKonstantin Ananyev	RTE_LOG(NOTICE, USER1, "%s(%s): read %zd bytes from fd=%d;\n",
7963726dc50SKonstantin Ananyev		__func__, fname, sz, fd);
7973726dc50SKonstantin Ananyev
7983726dc50SKonstantin Ananyev	close(fd);
7993726dc50SKonstantin Ananyev
8003726dc50SKonstantin Ananyev	if (sz != st.st_size) {
8013726dc50SKonstantin Ananyev		rc = -errno;
8023726dc50SKonstantin Ananyev		sz = 0;
8033726dc50SKonstantin Ananyev		rte_free(tx->data);
8043726dc50SKonstantin Ananyev	}
8053726dc50SKonstantin Ananyev
8063726dc50SKonstantin Ananyev	tx->sz = sz;
8073726dc50SKonstantin Ananyev	return rc;
8083726dc50SKonstantin Ananyev}
8093726dc50SKonstantin Ananyev
810aa97dd1cSKonstantin Ananyevint
811aa97dd1cSKonstantin Ananyevparse_app_options(int argc, char **argv, struct netbe_cfg *cfg,
812aa97dd1cSKonstantin Ananyev	struct tle_ctx_param *ctx_prm,
813aa97dd1cSKonstantin Ananyev	char *fecfg_fname, char *becfg_fname)
814aa97dd1cSKonstantin Ananyev{
815aa97dd1cSKonstantin Ananyev	int32_t opt, opt_idx, rc;
816aa97dd1cSKonstantin Ananyev	uint64_t v;
817aa97dd1cSKonstantin Ananyev	uint32_t i, j, n, nc;
818aa97dd1cSKonstantin Ananyev	rte_cpuset_t cpuset;
819aa97dd1cSKonstantin Ananyev	uint32_t udp = 0, tcp = 0, listen = 0;
820aa97dd1cSKonstantin Ananyev
821aa97dd1cSKonstantin Ananyev	optind = 0;
822aa97dd1cSKonstantin Ananyev	optarg = NULL;
82374a56517SMariusz Drost	while ((opt = getopt_long(argc, argv, "aB:C:c:LPR:S:M:TUb:f:s:v:H:K:W:w:",
8249fa82a63SReshma Pattan			long_opt, &opt_idx)) != EOF) {
825aa97dd1cSKonstantin Ananyev		if (opt == OPT_SHORT_ARP) {
826aa97dd1cSKonstantin Ananyev			cfg->arp = 1;
827aa97dd1cSKonstantin Ananyev		} else if (opt == OPT_SHORT_SBULK) {
828aa97dd1cSKonstantin Ananyev			rc = parse_uint_val(NULL, optarg, &v);
829aa97dd1cSKonstantin Ananyev			if (rc < 0)
830aa97dd1cSKonstantin Ananyev				rte_exit(EXIT_FAILURE, "%s: invalid value: %s "
831aa97dd1cSKonstantin Ananyev					"for option: \'%c\'\n",
832aa97dd1cSKonstantin Ananyev					__func__, optarg, opt);
833aa97dd1cSKonstantin Ananyev			ctx_prm->send_bulk_size = v;
8347e18fa1bSKonstantin Ananyev		} else if (opt == OPT_SHORT_CTXFLAGS) {
8357e18fa1bSKonstantin Ananyev			rc = parse_uint_val(NULL, optarg, &v);
8367e18fa1bSKonstantin Ananyev			if (rc < 0)
8377e18fa1bSKonstantin Ananyev				rte_exit(EXIT_FAILURE, "%s: invalid value: %s "
8387e18fa1bSKonstantin Ananyev					"for option: \'%c\'\n",
8397e18fa1bSKonstantin Ananyev					__func__, optarg, opt);
8407e18fa1bSKonstantin Ananyev			ctx_prm->flags = v;
84174a56517SMariusz Drost		} else if (opt == OPT_SHORT_MBUFNUM) {
84274a56517SMariusz Drost			rc = parse_uint_val(NULL, optarg, &v);
84374a56517SMariusz Drost			if (rc < 0)
84474a56517SMariusz Drost				rte_exit(EXIT_FAILURE, "%s: invalid value: %s "
84574a56517SMariusz Drost					"for option: \'%c\'\n",
84674a56517SMariusz Drost					__func__, optarg, opt);
84774a56517SMariusz Drost			cfg->mpool_buf_num = v;
848aa97dd1cSKonstantin Ananyev		} else if (opt == OPT_SHORT_PROMISC) {
849aa97dd1cSKonstantin Ananyev			cfg->promisc = 1;
850aa97dd1cSKonstantin Ananyev		} else if (opt == OPT_SHORT_RBUFS) {
851aa97dd1cSKonstantin Ananyev			rc = parse_uint_val(NULL, optarg, &v);
852aa97dd1cSKonstantin Ananyev			if (rc < 0)
853aa97dd1cSKonstantin Ananyev				rte_exit(EXIT_FAILURE, "%s: invalid value: %s "
854aa97dd1cSKonstantin Ananyev					"for option: \'%c\'\n",
855aa97dd1cSKonstantin Ananyev					__func__, optarg, opt);
856aa97dd1cSKonstantin Ananyev			ctx_prm->max_stream_rbufs = v;
857aa97dd1cSKonstantin Ananyev		} else if (opt == OPT_SHORT_SBUFS) {
858aa97dd1cSKonstantin Ananyev			rc = parse_uint_val(NULL, optarg, &v);
859aa97dd1cSKonstantin Ananyev			if (rc < 0)
860aa97dd1cSKonstantin Ananyev				rte_exit(EXIT_FAILURE, "%s: invalid value: %s "
861aa97dd1cSKonstantin Ananyev					"for option: \'%c\'\n",
862aa97dd1cSKonstantin Ananyev					__func__, optarg, opt);
863aa97dd1cSKonstantin Ananyev			ctx_prm->max_stream_sbufs = v;
864aa97dd1cSKonstantin Ananyev		} else if (opt == OPT_SHORT_STREAMS) {
865aa97dd1cSKonstantin Ananyev			rc = parse_uint_val(NULL, optarg, &v);
866aa97dd1cSKonstantin Ananyev			if (rc < 0)
867aa97dd1cSKonstantin Ananyev				rte_exit(EXIT_FAILURE, "%s: invalid value: %s "
868aa97dd1cSKonstantin Ananyev					"for option: \'%c\'\n",
869aa97dd1cSKonstantin Ananyev					__func__, optarg, opt);
870aa97dd1cSKonstantin Ananyev			ctx_prm->max_streams = v;
871aa97dd1cSKonstantin Ananyev		} else if (opt == OPT_SHORT_VERBOSE) {
872aa97dd1cSKonstantin Ananyev			rc = parse_uint_val(NULL, optarg, &v);
873aa97dd1cSKonstantin Ananyev			if (rc < 0)
874aa97dd1cSKonstantin Ananyev				rte_exit(EXIT_FAILURE, "%s: invalid value: %s "
875aa97dd1cSKonstantin Ananyev					"for option: \'%c\'\n",
876aa97dd1cSKonstantin Ananyev					__func__, optarg, opt);
877aa97dd1cSKonstantin Ananyev			verbose = (v > VERBOSE_NUM) ? VERBOSE_NUM : v;
878aa97dd1cSKonstantin Ananyev		} else if (opt == OPT_SHORT_BECFG) {
879aa97dd1cSKonstantin Ananyev			snprintf(becfg_fname, PATH_MAX, "%s",
880aa97dd1cSKonstantin Ananyev				optarg);
881aa97dd1cSKonstantin Ananyev		} else if (opt == OPT_SHORT_FECFG) {
882aa97dd1cSKonstantin Ananyev			snprintf(fecfg_fname, PATH_MAX, "%s",
883aa97dd1cSKonstantin Ananyev				optarg);
884aa97dd1cSKonstantin Ananyev		} else if (opt == OPT_SHORT_UDP) {
885aa97dd1cSKonstantin Ananyev			udp = 1;
886aa97dd1cSKonstantin Ananyev			cfg->proto = TLE_PROTO_UDP;
887aa97dd1cSKonstantin Ananyev		} else if (opt == OPT_SHORT_TCP) {
888aa97dd1cSKonstantin Ananyev			tcp = 1;
889aa97dd1cSKonstantin Ananyev			cfg->proto = TLE_PROTO_TCP;
890aa97dd1cSKonstantin Ananyev		} else if (opt == OPT_SHORT_LISTEN) {
891aa97dd1cSKonstantin Ananyev			listen = 1;
892aa97dd1cSKonstantin Ananyev			cfg->server = 1;
8939fa82a63SReshma Pattan		} else if (opt == OPT_SHORT_HASH) {
8949fa82a63SReshma Pattan			ctx_prm->hash_alg = parse_hash_alg(optarg);
8959fa82a63SReshma Pattan			if (ctx_prm->hash_alg >= TLE_HASH_NUM) {
8969fa82a63SReshma Pattan				rte_exit(EXIT_FAILURE,
8979fa82a63SReshma Pattan					"%s: invalid hash algorithm %s "
8989fa82a63SReshma Pattan					"for option: \'%c\'\n",
8999fa82a63SReshma Pattan					__func__, optarg, opt);
9009fa82a63SReshma Pattan			}
9019fa82a63SReshma Pattan		} else if (opt == OPT_SHORT_SEC_KEY) {
9029fa82a63SReshma Pattan			n = strlen(optarg);
9039fa82a63SReshma Pattan			if (n != sizeof(ctx_prm->secret_key)) {
9049fa82a63SReshma Pattan				rte_exit(EXIT_FAILURE,
9059fa82a63SReshma Pattan					"%s: invalid length %s "
9069fa82a63SReshma Pattan					"for option \'%c\' "
9079fa82a63SReshma Pattan					"must be 16 characters long\n",
9089fa82a63SReshma Pattan					__func__, optarg, opt);
9099fa82a63SReshma Pattan			}
9109fa82a63SReshma Pattan			memcpy(&ctx_prm->secret_key, optarg,
9119fa82a63SReshma Pattan				sizeof(ctx_prm->secret_key));
9127e18fa1bSKonstantin Ananyev		} else if (opt == OPT_SHORT_WINDOW) {
9137e18fa1bSKonstantin Ananyev			rc = parse_uint_val(NULL, optarg, &v);
9147e18fa1bSKonstantin Ananyev			if (rc < 0)
9157e18fa1bSKonstantin Ananyev				rte_exit(EXIT_FAILURE, "%s: invalid value: %s "
9167e18fa1bSKonstantin Ananyev					"for option: \'%c\'\n",
9177e18fa1bSKonstantin Ananyev					__func__, optarg, opt);
9187e18fa1bSKonstantin Ananyev			ctx_prm->icw = v;
9197e18fa1bSKonstantin Ananyev		} else if (opt == OPT_SHORT_TIMEWAIT) {
9207e18fa1bSKonstantin Ananyev			rc = parse_uint_val(NULL, optarg, &v);
9217e18fa1bSKonstantin Ananyev			if (rc < 0)
9227e18fa1bSKonstantin Ananyev				rte_exit(EXIT_FAILURE, "%s: invalid value: %s "
9237e18fa1bSKonstantin Ananyev					"for option: \'%c\'\n",
9247e18fa1bSKonstantin Ananyev					__func__, optarg, opt);
9257e18fa1bSKonstantin Ananyev			ctx_prm->timewait = v;
9263726dc50SKonstantin Ananyev		} else if (opt == OPT_SHORT_TXCNT) {
9273726dc50SKonstantin Ananyev			rc = read_tx_content(optarg, &tx_content);
9283726dc50SKonstantin Ananyev			if (rc < 0)
9293726dc50SKonstantin Ananyev				rte_exit(EXIT_FAILURE,
9303726dc50SKonstantin Ananyev					"%s: failed to read tx contents "
9313726dc50SKonstantin Ananyev					"from \'%s\', error code: %d(%s)\n",
9323726dc50SKonstantin Ananyev					__func__, optarg, rc, strerror(-rc));
9337e18fa1bSKonstantin Ananyev		} else {
934aa97dd1cSKonstantin Ananyev			rte_exit(EXIT_FAILURE,
935aa97dd1cSKonstantin Ananyev				"%s: unknown option: \'%c\'\n",
936aa97dd1cSKonstantin Ananyev				__func__, opt);
937aa97dd1cSKonstantin Ananyev		}
938aa97dd1cSKonstantin Ananyev	}
939aa97dd1cSKonstantin Ananyev
940aa97dd1cSKonstantin Ananyev	if (!udp && !tcp)