aboutsummaryrefslogtreecommitdiffstats
path: root/examples/l4fwd/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'examples/l4fwd/parse.c')
-rw-r--r--examples/l4fwd/parse.c839
1 files changed, 839 insertions, 0 deletions
diff --git a/examples/l4fwd/parse.c b/examples/l4fwd/parse.c
new file mode 100644
index 0000000..6593221
--- /dev/null
+++ b/examples/l4fwd/parse.c
@@ -0,0 +1,839 @@
+/*
+ * Copyright (c) 2016 Intel Corporation.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "netbe.h"
+#include "parse.h"
+
+#define DEF_LINE_NUM 0x400
+
+static const struct {
+ const char *name;
+ uint16_t op;
+} name2feop[] = {
+ { .name = "rx", .op = RXONLY,},
+ { .name = "tx", .op = TXONLY,},
+ { .name = "echo", .op = RXTX,},
+ { .name = "fwd", .op = FWD,},
+};
+
+#define OPT_SHORT_ARP 'a'
+#define OPT_LONG_ARP "enable-arp"
+
+#define OPT_SHORT_SBULK 'B'
+#define OPT_LONG_SBULK "sburst"
+
+#define OPT_SHORT_PROMISC 'P'
+#define OPT_LONG_PROMISC "promisc"
+
+#define OPT_SHORT_RBUFS 'R'
+#define OPT_LONG_RBUFS "rbufs"
+
+#define OPT_SHORT_SBUFS 'S'
+#define OPT_LONG_SBUFS "sbufs"
+
+#define OPT_SHORT_BECFG 'b'
+#define OPT_LONG_BECFG "becfg"
+
+#define OPT_SHORT_FECFG 'f'
+#define OPT_LONG_FECFG "fecfg"
+
+#define OPT_SHORT_STREAMS 's'
+#define OPT_LONG_STREAMS "streams"
+
+#define OPT_SHORT_UDP 'U'
+#define OPT_LONG_UDP "udp"
+
+#define OPT_SHORT_TCP 'T'
+#define OPT_LONG_TCP "tcp"
+
+#define OPT_SHORT_LISTEN 'L'
+#define OPT_LONG_LISTEN "listen"
+
+#define OPT_SHORT_VERBOSE 'v'
+#define OPT_LONG_VERBOSE "verbose"
+
+static const struct option long_opt[] = {
+ {OPT_LONG_ARP, 1, 0, OPT_SHORT_ARP},
+ {OPT_LONG_SBULK, 1, 0, OPT_SHORT_SBULK},
+ {OPT_LONG_PROMISC, 0, 0, OPT_SHORT_PROMISC},
+ {OPT_LONG_RBUFS, 1, 0, OPT_SHORT_RBUFS},
+ {OPT_LONG_SBUFS, 1, 0, OPT_SHORT_SBUFS},
+ {OPT_LONG_BECFG, 1, 0, OPT_SHORT_BECFG},
+ {OPT_LONG_FECFG, 1, 0, OPT_SHORT_FECFG},
+ {OPT_LONG_STREAMS, 1, 0, OPT_SHORT_STREAMS},
+ {OPT_LONG_UDP, 0, 0, OPT_SHORT_UDP},
+ {OPT_LONG_TCP, 0, 0, OPT_SHORT_TCP},
+ {OPT_LONG_LISTEN, 0, 0, OPT_SHORT_LISTEN},
+ {OPT_LONG_VERBOSE, 1, 0, OPT_SHORT_VERBOSE},
+ {NULL, 0, 0, 0}
+};
+
+static int
+parse_uint_val(__rte_unused const char *key, const char *val, void *prm)
+{
+ union parse_val *rv;
+ unsigned long v;
+ char *end;
+
+ rv = prm;
+ errno = 0;
+ v = strtoul(val, &end, 0);
+ if (errno != 0 || end[0] != 0 || v > UINT32_MAX)
+ return -EINVAL;
+
+ rv->u64 = v;
+ return 0;
+}
+
+static int
+parse_ipv4_val(__rte_unused const char *key, const char *val, void *prm)
+{
+ union parse_val *rv;
+
+ rv = prm;
+ if (inet_pton(AF_INET, val, &rv->in.addr4) != 1)
+ return -EINVAL;
+ rv->in.family = AF_INET;
+ return 0;
+}
+
+static int
+parse_ipv6_val(__rte_unused const char *key, const char *val, void *prm)
+{
+ union parse_val *rv;
+
+ rv = prm;
+ if (inet_pton(AF_INET6, val, &rv->in.addr6) != 1)
+ return -EINVAL;
+ rv->in.family = AF_INET6;
+ return 0;
+}
+
+static int
+parse_ip_val(__rte_unused const char *key, const char *val, void *prm)
+{
+ if (parse_ipv6_val(key, val, prm) != 0 &&
+ parse_ipv4_val(key, val, prm) != 0)
+ return -EINVAL;
+ return 0;
+}
+
+#define PARSE_UINT8x16(s, v, l) \
+do { \
+ char *end; \
+ unsigned long t; \
+ errno = 0; \
+ t = strtoul((s), &end, 16); \
+ if (errno != 0 || end[0] != (l) || t > UINT8_MAX) \
+ return -EINVAL; \
+ (s) = end + 1; \
+ (v) = t; \
+} while (0)
+
+static int
+parse_mac_val(__rte_unused const char *key, const char *val, void *prm)
+{
+ union parse_val *rv;
+ const char *s;
+
+ rv = prm;
+ s = val;
+
+ PARSE_UINT8x16(s, rv->mac.addr_bytes[0], ':');
+ PARSE_UINT8x16(s, rv->mac.addr_bytes[1], ':');
+ PARSE_UINT8x16(s, rv->mac.addr_bytes[2], ':');
+ PARSE_UINT8x16(s, rv->mac.addr_bytes[3], ':');
+ PARSE_UINT8x16(s, rv->mac.addr_bytes[4], ':');
+ PARSE_UINT8x16(s, rv->mac.addr_bytes[5], 0);
+ return 0;
+}
+
+static int
+parse_feop_val(__rte_unused const char *key, const char *val, void *prm)
+{
+ uint32_t i;
+ union parse_val *rv;
+
+ rv = prm;
+ for (i = 0; i != RTE_DIM(name2feop); i++) {
+ if (strcmp(val, name2feop[i].name) == 0) {
+ rv->u64 = name2feop[i].op;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int
+parse_lcore_list_val(__rte_unused const char *key, const char *val, void *prm)
+{
+ union parse_val *rv;
+ unsigned long a, b;
+ uint32_t i;
+ char *end;
+
+ rv = prm;
+
+ errno = 0;
+ a = strtoul(val, &end, 0);
+ if (errno != 0 || (end[0] != 0 && end[0] != '-') || a > UINT32_MAX)
+ return -EINVAL;
+
+ if (end[0] == '-') {
+ val = end + 1;
+ errno = 0;
+ b = strtoul(val, &end, 0);
+ if (errno != 0 || end[0] != 0 || b > UINT32_MAX)
+ return -EINVAL;
+ } else
+ b = a;
+
+ if (a <= b) {
+ for (i = a; i <= b; i++)
+ CPU_SET(i, &rv->cpuset);
+ } else {
+ RTE_LOG(ERR, USER1,
+ "%s: lcores not in ascending order\n", __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
+parse_kvargs(const char *arg, const char *keys_man[], uint32_t nb_man,
+ const char *keys_opt[], uint32_t nb_opt,
+ const arg_handler_t hndl[], union parse_val val[])
+{
+ uint32_t j, k;
+ struct rte_kvargs *kvl;
+
+ kvl = rte_kvargs_parse(arg, NULL);
+ if (kvl == NULL) {
+ RTE_LOG(ERR, USER1,
+ "%s: invalid parameter: %s\n",
+ __func__, arg);
+ return -EINVAL;
+ }
+
+ for (j = 0; j != nb_man; j++) {
+ if (rte_kvargs_count(kvl, keys_man[j]) == 0) {
+ RTE_LOG(ERR, USER1,
+ "%s: %s missing mandatory key: %s\n",
+ __func__, arg, keys_man[j]);
+ rte_kvargs_free(kvl);
+ return -EINVAL;
+ }
+ }
+
+ for (j = 0; j != nb_man; j++) {
+ if (rte_kvargs_process(kvl, keys_man[j], hndl[j],
+ val + j) != 0) {
+ RTE_LOG(ERR, USER1,
+ "%s: %s invalid value for man key: %s\n",
+ __func__, arg, keys_man[j]);
+ rte_kvargs_free(kvl);
+ return -EINVAL;
+ }
+ }
+
+ for (j = 0; j != nb_opt; j++) {
+ k = j + nb_man;
+ if (rte_kvargs_process(kvl, keys_opt[j], hndl[k],
+ val + k) != 0) {
+ RTE_LOG(ERR, USER1,
+ "%s: %s invalid value for opt key: %s\n",
+ __func__, arg, keys_opt[j]);
+ rte_kvargs_free(kvl);
+ return -EINVAL;
+ }
+ }
+
+ rte_kvargs_free(kvl);
+ return 0;
+}
+
+int
+parse_netbe_arg(struct netbe_port *prt, const char *arg, rte_cpuset_t *pcpu)
+{
+ int32_t rc;
+ uint32_t i, j, nc;
+
+ static const char *keys_man[] = {
+ "port",
+ "lcore",
+ };
+
+ static const char *keys_opt[] = {
+ "mtu",
+ "rx_offload",
+ "tx_offload",
+ "ipv4",
+ "ipv6",
+ };
+
+ static const arg_handler_t hndl[] = {
+ parse_uint_val,
+ parse_lcore_list_val,
+ parse_uint_val,
+ parse_uint_val,
+ parse_uint_val,
+ parse_ipv4_val,
+ parse_ipv6_val,
+ };
+
+ union parse_val val[RTE_DIM(hndl)];
+
+ memset(val, 0, sizeof(val));
+ val[2].u64 = ETHER_MAX_VLAN_FRAME_LEN - ETHER_CRC_LEN;
+
+ rc = parse_kvargs(arg, keys_man, RTE_DIM(keys_man),
+ keys_opt, RTE_DIM(keys_opt), hndl, val);
+ if (rc != 0)
+ return rc;
+
+ prt->id = val[0].u64;
+
+ for (i = 0, nc = 0; i < RTE_MAX_LCORE; i++)
+ nc += CPU_ISSET(i, &val[1].cpuset);
+ prt->lcore_id = rte_zmalloc(NULL, nc * sizeof(prt->lcore_id[0]),
+ RTE_CACHE_LINE_SIZE);
+ prt->nb_lcore = nc;
+
+ for (i = 0, j = 0; i < RTE_MAX_LCORE; i++)
+ if (CPU_ISSET(i, &val[1].cpuset))
+ prt->lcore_id[j++] = i;
+ CPU_OR(pcpu, pcpu, &val[1].cpuset);
+
+ prt->mtu = val[2].u64;
+ prt->rx_offload = val[3].u64;
+ prt->tx_offload = val[4].u64;
+ prt->ipv4 = val[5].in.addr4.s_addr;
+ prt->ipv6 = val[6].in.addr6;
+
+ return 0;
+}
+
+static int
+check_netbe_dest(const struct netbe_dest *dst)
+{
+ if (dst->port >= RTE_MAX_ETHPORTS) {
+ RTE_LOG(ERR, USER1, "%s(line=%u) invalid port=%u",
+ __func__, dst->line, dst->port);
+ return -EINVAL;
+ } else if ((dst->family == AF_INET &&
+ dst->prfx > sizeof(struct in_addr) * CHAR_BIT) ||
+ (dst->family == AF_INET6 &&
+ dst->prfx > sizeof(struct in6_addr) * CHAR_BIT)) {
+ RTE_LOG(ERR, USER1, "%s(line=%u) invalid masklen=%u",
+ __func__, dst->line, dst->prfx);
+ return -EINVAL;
+ } else if (dst->mtu > ETHER_MAX_JUMBO_FRAME_LEN - ETHER_CRC_LEN) {
+ RTE_LOG(ERR, USER1, "%s(line=%u) invalid mtu=%u",
+ __func__, dst->line, dst->mtu);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int
+parse_netbe_dest(struct netbe_dest *dst, const char *arg)
+{
+ int32_t rc;
+
+ static const char *keys_man[] = {
+ "port",
+ "addr",
+ "masklen",
+ "mac",
+ };
+
+ static const char *keys_opt[] = {
+ "mtu",
+ };
+
+ static const arg_handler_t hndl[] = {
+ parse_uint_val,
+ parse_ip_val,
+ parse_uint_val,
+ parse_mac_val,
+ parse_uint_val,
+ };
+
+ union parse_val val[RTE_DIM(hndl)];
+
+ /* set default values. */
+ memset(val, 0, sizeof(val));
+ val[4].u64 = ETHER_MAX_JUMBO_FRAME_LEN - ETHER_CRC_LEN;
+
+ rc = parse_kvargs(arg, keys_man, RTE_DIM(keys_man),
+ keys_opt, RTE_DIM(keys_opt), hndl, val);
+ if (rc != 0)
+ return rc;
+
+ dst->port = val[0].u64;
+ dst->family = val[1].in.family;
+ if (val[1].in.family == AF_INET)
+ dst->ipv4 = val[1].in.addr4;
+ else
+ dst->ipv6 = val[1].in.addr6;
+ dst->prfx = val[2].u64;
+ memcpy(&dst->mac, &val[3].mac, sizeof(dst->mac));
+ dst->mtu = val[4].u64;
+
+ return 0;
+}
+
+int
+netbe_parse_dest(const char *fname, struct netbe_dest_prm *prm)
+{
+ uint32_t i, ln, n, num;
+ int32_t rc;
+ size_t sz;
+ char *s;
+ FILE *f;
+ struct netbe_dest *dp;
+ char line[LINE_MAX];
+
+ f = fopen(fname, "r");
+ if (f == NULL) {
+ RTE_LOG(ERR, USER1, "%s failed to open file \"%s\"\n",
+ __func__, fname);
+ return -EINVAL;
+ }
+
+ n = 0;
+ num = 0;
+ dp = NULL;
+ rc = 0;
+ for (ln = 0; fgets(line, sizeof(line), f) != NULL; ln++) {
+
+ /* skip spaces at the start. */
+ for (s = line; isspace(s[0]); s++)
+ ;
+
+ /* skip comment line. */
+ if (s[0] == '#' || s[0] == 0)
+ continue;
+
+ /* skip spaces at the end. */
+ for (i = strlen(s); i-- != 0 && isspace(s[i]); s[i] = 0)
+ ;
+
+ if (n == num) {
+ num += DEF_LINE_NUM;
+ sz = sizeof(dp[0]) * num;
+ dp = realloc(dp, sizeof(dp[0]) * num);
+ if (dp == NULL) {
+ RTE_LOG(ERR, USER1,
+ "%s(%s) allocation of %zu bytes "
+ "failed\n",
+ __func__, fname, sz);
+ rc = -ENOMEM;
+ break;
+ }
+ memset(&dp[n], 0, sizeof(dp[0]) * (num - n));
+ }
+
+ dp[n].line = ln + 1;
+ rc = parse_netbe_dest(dp + n, s);
+ rc = (rc != 0) ? rc : check_netbe_dest(dp + n);
+ if (rc != 0) {
+ RTE_LOG(ERR, USER1, "%s(%s) failed to parse line %u\n",
+ __func__, fname, dp[n].line);
+ break;
+ }
+ n++;
+ }
+
+ fclose(f);
+
+ if (rc != 0) {
+ free(dp);
+ dp = NULL;
+ n = 0;
+ }
+
+ prm->dest = dp;
+ prm->nb_dest = n;
+ return rc;
+}
+
+static void
+pv2saddr(struct sockaddr_storage *ss, const union parse_val *pva,
+ const union parse_val *pvp)
+{
+ ss->ss_family = pva->in.family;
+ if (pva->in.family == AF_INET) {
+ struct sockaddr_in *si = (struct sockaddr_in *)ss;
+ si->sin_addr = pva->in.addr4;
+ si->sin_port = rte_cpu_to_be_16((uint16_t)pvp->u64);
+ } else {
+ struct sockaddr_in6 *si = (struct sockaddr_in6 *)ss;
+ si->sin6_addr = pva->in.addr6;
+ si->sin6_port = rte_cpu_to_be_16((uint16_t)pvp->u64);
+ }
+}
+
+static int
+parse_netfe_arg(struct netfe_stream_prm *sp, const char *arg)
+{
+ int32_t rc;
+
+ static const char *keys_man[] = {
+ "lcore",
+ "op",
+ "laddr",
+ "lport",
+ "raddr",
+ "rport",
+ };
+
+ static const char *keys_opt[] = {
+ "txlen",
+ "fwladdr",
+ "fwlport",
+ "fwraddr",
+ "fwrport",
+ "belcore",
+ };
+
+ static const arg_handler_t hndl[] = {
+ parse_uint_val,
+ parse_feop_val,
+ parse_ip_val,
+ parse_uint_val,
+ parse_ip_val,
+ parse_uint_val,
+ parse_uint_val,
+ parse_ip_val,
+ parse_uint_val,
+ parse_ip_val,
+ parse_uint_val,
+ parse_uint_val,
+ };
+
+ union parse_val val[RTE_DIM(hndl)];
+
+ memset(val, 0, sizeof(val));
+ val[11].u64 = LCORE_ID_ANY;
+ rc = parse_kvargs(arg, keys_man, RTE_DIM(keys_man),
+ keys_opt, RTE_DIM(keys_opt), hndl, val);
+ if (rc != 0)
+ return rc;
+ sp->lcore = val[0].u64;
+ sp->op = val[1].u64;
+ pv2saddr(&sp->sprm.local_addr, val + 2, val + 3);
+ pv2saddr(&sp->sprm.remote_addr, val + 4, val + 5);
+ sp->txlen = val[6].u64;
+ pv2saddr(&sp->fprm.local_addr, val + 7, val + 8);
+ pv2saddr(&sp->fprm.remote_addr, val + 9, val + 10);
+ sp->belcore = val[11].u64;
+
+ return 0;
+}
+
+static const char *
+format_feop(uint16_t op)
+{
+ uint32_t i;
+
+ for (i = 0; i != RTE_DIM(name2feop); i++) {
+ if (name2feop[i].op == op)
+ return name2feop[i].name;
+ }
+
+ return NULL;
+}
+
+static int
+is_addr_wc(const struct sockaddr_storage *sp)
+{
+ const struct sockaddr_in *i4;
+ const struct sockaddr_in6 *i6;
+
+ if (sp->ss_family == AF_INET) {
+ i4 = (const struct sockaddr_in *)sp;
+ return (i4->sin_addr.s_addr == INADDR_ANY);
+ } else if (sp->ss_family == AF_INET6) {
+ i6 = (const struct sockaddr_in6 *)sp;
+ return (memcmp(&i6->sin6_addr, &in6addr_any,
+ sizeof(i6->sin6_addr)) == 0);
+ }
+ return 0;
+}
+
+static int
+check_netfe_arg(const struct netfe_stream_prm *sp)
+{
+ char buf[INET6_ADDRSTRLEN];
+
+ if (sp->sprm.local_addr.ss_family !=
+ sp->sprm.remote_addr.ss_family) {
+ RTE_LOG(ERR, USER1, "invalid arg at line %u: "
+ "laddr and raddr for different protocols\n",
+ sp->line);
+ return -EINVAL;
+ }
+
+ if (sp->op == TXONLY) {
+ if (sp->txlen > RTE_MBUF_DEFAULT_DATAROOM || sp->txlen == 0) {
+ RTE_LOG(ERR, USER1, "invalid arg at line %u: txlen=%u "
+ "exceeds allowed values: (0, %u]\n",
+ sp->line, sp->txlen, RTE_MBUF_DEFAULT_DATAROOM);
+ return -EINVAL;
+ } else if (is_addr_wc(&sp->sprm.remote_addr)) {
+ RTE_LOG(ERR, USER1, "invalid arg at line %u: "
+ "raddr=%s are not allowed for op=%s;\n",
+ sp->line,
+ format_addr(&sp->sprm.remote_addr,
+ buf, sizeof(buf)),
+ format_feop(sp->op));
+ return -EINVAL;
+ }
+ } else if (sp->op == FWD) {
+ if (sp->fprm.local_addr.ss_family !=
+ sp->fprm.remote_addr.ss_family) {
+ RTE_LOG(ERR, USER1, "invalid arg at line %u: "
+ "fwladdr and fwraddr for different protocols\n",
+ sp->line);
+ return -EINVAL;
+ } else if (is_addr_wc(&sp->fprm.remote_addr)) {
+ RTE_LOG(ERR, USER1, "invalid arg at line %u: "
+ "fwaddr=%s are not allowed for op=%s;\n",
+ sp->line,
+ format_addr(&sp->fprm.remote_addr,
+ buf, sizeof(buf)),
+ format_feop(sp->op));
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+int
+netfe_parse_cfg(const char *fname, struct netfe_lcore_prm *lp)
+{
+ uint32_t i, ln, n, num;
+ int32_t rc;
+ size_t sz;
+ char *s;
+ FILE *f;
+ struct netfe_stream_prm *sp;
+ char line[LINE_MAX];
+
+ f = fopen(fname, "r");
+ if (f == NULL) {
+ RTE_LOG(ERR, USER1, "%s failed to open file \"%s\"\n",
+ __func__, fname);
+ return -EINVAL;
+ }
+
+ n = 0;
+ num = 0;
+ sp = NULL;
+ rc = 0;
+ for (ln = 0; fgets(line, sizeof(line), f) != NULL; ln++) {
+
+ /* skip spaces at the start. */
+ for (s = line; isspace(s[0]); s++)
+ ;
+
+ /* skip comment line. */
+ if (s[0] == '#' || s[0] == 0)
+ continue;
+
+ /* skip spaces at the end. */
+ for (i = strlen(s); i-- != 0 && isspace(s[i]); s[i] = 0)
+ ;
+
+ if (n == lp->max_streams) {
+ RTE_LOG(ERR, USER1,
+ "%s(%s) number of entries exceed max streams "
+ "value: %u\n",
+ __func__, fname, n);
+ rc = -EINVAL;
+ break;
+ }
+
+ if (n == num) {
+ num += DEF_LINE_NUM;
+ sz = sizeof(sp[0]) * num;
+ sp = realloc(sp, sizeof(sp[0]) * num);
+ if (sp == NULL) {
+ RTE_LOG(ERR, USER1,
+ "%s(%s) allocation of %zu bytes "
+ "failed\n",
+ __func__, fname, sz);
+ rc = -ENOMEM;
+ break;
+ }
+ memset(&sp[n], 0, sizeof(sp[0]) * (num - n));
+ }
+
+ sp[n].line = ln + 1;
+ rc = parse_netfe_arg(sp + n, s);
+ rc = (rc != 0) ? rc : check_netfe_arg(sp + n);
+ if (rc != 0) {
+ RTE_LOG(ERR, USER1, "%s(%s) failed to parse line %u\n",
+ __func__, fname, sp[n].line);
+ break;
+ }
+ n++;
+ }
+
+ fclose(f);
+
+ if (rc != 0) {
+ free(sp);
+ sp = NULL;
+ n = 0;
+ }
+
+ lp->stream = sp;
+ lp->nb_streams = n;
+ return rc;
+}
+
+int
+parse_app_options(int argc, char **argv, struct netbe_cfg *cfg,
+ struct tle_ctx_param *ctx_prm,
+ char *fecfg_fname, char *becfg_fname)
+{
+ int32_t opt, opt_idx, rc;
+ uint64_t v;
+ uint32_t i, j, n, nc;
+ rte_cpuset_t cpuset;
+ uint32_t udp = 0, tcp = 0, listen = 0;
+
+ optind = 0;
+ optarg = NULL;
+ while ((opt = getopt_long(argc, argv, "aB:LPR:S:TUb:f:s:v:", long_opt,
+ &opt_idx)) != EOF) {
+ if (opt == OPT_SHORT_ARP) {
+ cfg->arp = 1;
+ } else if (opt == OPT_SHORT_SBULK) {
+ rc = parse_uint_val(NULL, optarg, &v);
+ if (rc < 0)
+ rte_exit(EXIT_FAILURE, "%s: invalid value: %s "
+ "for option: \'%c\'\n",
+ __func__, optarg, opt);
+ ctx_prm->send_bulk_size = v;
+ } else if (opt == OPT_SHORT_PROMISC) {
+ cfg->promisc = 1;
+ } else if (opt == OPT_SHORT_RBUFS) {
+ rc = parse_uint_val(NULL, optarg, &v);
+ if (rc < 0)
+ rte_exit(EXIT_FAILURE, "%s: invalid value: %s "
+ "for option: \'%c\'\n",
+ __func__, optarg, opt);
+ ctx_prm->max_stream_rbufs = v;
+ } else if (opt == OPT_SHORT_SBUFS) {
+ rc = parse_uint_val(NULL, optarg, &v);
+ if (rc < 0)
+ rte_exit(EXIT_FAILURE, "%s: invalid value: %s "
+ "for option: \'%c\'\n",
+ __func__, optarg, opt);
+ ctx_prm->max_stream_sbufs = v;
+ } else if (opt == OPT_SHORT_STREAMS) {
+ rc = parse_uint_val(NULL, optarg, &v);
+ if (rc < 0)
+ rte_exit(EXIT_FAILURE, "%s: invalid value: %s "
+ "for option: \'%c\'\n",
+ __func__, optarg, opt);
+ ctx_prm->max_streams = v;
+ } else if (opt == OPT_SHORT_VERBOSE) {
+ rc = parse_uint_val(NULL, optarg, &v);
+ if (rc < 0)
+ rte_exit(EXIT_FAILURE, "%s: invalid value: %s "
+ "for option: \'%c\'\n",
+ __func__, optarg, opt);
+ verbose = (v > VERBOSE_NUM) ? VERBOSE_NUM : v;
+ } else if (opt == OPT_SHORT_BECFG) {
+ snprintf(becfg_fname, PATH_MAX, "%s",
+ optarg);
+ } else if (opt == OPT_SHORT_FECFG) {
+ snprintf(fecfg_fname, PATH_MAX, "%s",
+ optarg);
+ } else if (opt == OPT_SHORT_UDP) {
+ udp = 1;
+ cfg->proto = TLE_PROTO_UDP;
+ } else if (opt == OPT_SHORT_TCP) {
+ tcp = 1;
+ cfg->proto = TLE_PROTO_TCP;
+ } else if (opt == OPT_SHORT_LISTEN) {
+ listen = 1;
+ cfg->server = 1;
+ } else {
+ rte_exit(EXIT_FAILURE,
+ "%s: unknown option: \'%c\'\n",
+ __func__, opt);
+ }
+ }
+
+ if (!udp && !tcp)
+ rte_exit(EXIT_FAILURE, "%s: either UDP or TCP option has to be "
+ "provided\n", __func__);
+
+ if (udp && tcp)
+ rte_exit(EXIT_FAILURE, "%s: both UDP and TCP options are not "
+ "allowed\n", __func__);
+
+ if (udp && listen)
+ rte_exit(EXIT_FAILURE,
+ "%s: listen mode cannot be opened with UDP\n",
+ __func__);
+
+ if (udp && cfg->arp)
+ rte_exit(EXIT_FAILURE,
+ "%s: arp cannot be enabled with UDP\n",
+ __func__);
+
+ /* parse port params */
+ argc -= optind;
+ argv += optind;
+
+ /* allocate memory for number of ports defined */
+ n = (uint32_t)argc;
+ cfg->prt = rte_zmalloc(NULL, sizeof(struct netbe_port) * n,
+ RTE_CACHE_LINE_SIZE);
+ cfg->prt_num = n;
+
+ rc = 0;
+ for (i = 0; i != n; i++) {
+ rc = parse_netbe_arg(cfg->prt + i, argv[i], &cpuset);
+ if (rc != 0) {
+ RTE_LOG(ERR, USER1,
+ "%s: processing of \"%s\" failed with error "
+ "code: %d\n", __func__, argv[i], rc);
+ for (j = 0; j != i; j++)
+ rte_free(cfg->prt[j].lcore_id);
+ rte_free(cfg->prt);
+ return rc;
+ }
+ }
+
+ /* count the number of CPU defined in ports */
+ for (i = 0, nc = 0; i < RTE_MAX_LCORE; i++)
+ nc += CPU_ISSET(i, &cpuset);
+
+ /* allocate memory for number of CPU defined */
+ cfg->cpu = rte_zmalloc(NULL, sizeof(struct netbe_lcore) * nc,
+ RTE_CACHE_LINE_SIZE);
+
+ return 0;
+}