summaryrefslogtreecommitdiffstats
path: root/src/seastar/dpdk/app
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
commit483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch)
treee5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/seastar/dpdk/app
parentInitial commit. (diff)
downloadceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.tar.xz
ceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.zip
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--src/seastar/dpdk/app/Makefile42
-rw-r--r--src/seastar/dpdk/app/pdump/Makefile46
-rw-r--r--src/seastar/dpdk/app/pdump/main.c915
-rw-r--r--src/seastar/dpdk/app/proc_info/Makefile42
-rw-r--r--src/seastar/dpdk/app/proc_info/main.c692
-rw-r--r--src/seastar/dpdk/app/test-crypto-perf/Makefile48
-rw-r--r--src/seastar/dpdk/app/test-crypto-perf/cperf.h58
-rw-r--r--src/seastar/dpdk/app/test-crypto-perf/cperf_ops.c515
-rw-r--r--src/seastar/dpdk/app/test-crypto-perf/cperf_ops.h62
-rw-r--r--src/seastar/dpdk/app/test-crypto-perf/cperf_options.h115
-rw-r--r--src/seastar/dpdk/app/test-crypto-perf/cperf_options_parsing.c934
-rw-r--r--src/seastar/dpdk/app/test-crypto-perf/cperf_test_latency.c552
-rw-r--r--src/seastar/dpdk/app/test-crypto-perf/cperf_test_latency.h57
-rw-r--r--src/seastar/dpdk/app/test-crypto-perf/cperf_test_throughput.c518
-rw-r--r--src/seastar/dpdk/app/test-crypto-perf/cperf_test_throughput.h58
-rw-r--r--src/seastar/dpdk/app/test-crypto-perf/cperf_test_vector_parsing.c507
-rw-r--r--src/seastar/dpdk/app/test-crypto-perf/cperf_test_vector_parsing.h73
-rw-r--r--src/seastar/dpdk/app/test-crypto-perf/cperf_test_vectors.c500
-rw-r--r--src/seastar/dpdk/app/test-crypto-perf/cperf_test_vectors.h98
-rw-r--r--src/seastar/dpdk/app/test-crypto-perf/cperf_test_verify.c579
-rw-r--r--src/seastar/dpdk/app/test-crypto-perf/cperf_test_verify.h58
-rw-r--r--src/seastar/dpdk/app/test-crypto-perf/data/aes_cbc_128_sha.data502
-rw-r--r--src/seastar/dpdk/app/test-crypto-perf/data/aes_cbc_192_sha.data504
-rw-r--r--src/seastar/dpdk/app/test-crypto-perf/data/aes_cbc_256_sha.data504
-rw-r--r--src/seastar/dpdk/app/test-crypto-perf/main.c444
-rw-r--r--src/seastar/dpdk/app/test-pmd/Makefile86
-rw-r--r--src/seastar/dpdk/app/test-pmd/cmdline.c13825
-rw-r--r--src/seastar/dpdk/app/test-pmd/cmdline_flow.c2812
-rw-r--r--src/seastar/dpdk/app/test-pmd/config.c3321
-rw-r--r--src/seastar/dpdk/app/test-pmd/csumonly.c896
-rw-r--r--src/seastar/dpdk/app/test-pmd/flowgen.c248
-rw-r--r--src/seastar/dpdk/app/test-pmd/icmpecho.c560
-rw-r--r--src/seastar/dpdk/app/test-pmd/ieee1588fwd.c249
-rw-r--r--src/seastar/dpdk/app/test-pmd/iofwd.c142
-rw-r--r--src/seastar/dpdk/app/test-pmd/macfwd.c169
-rw-r--r--src/seastar/dpdk/app/test-pmd/macswap.c170
-rw-r--r--src/seastar/dpdk/app/test-pmd/parameters.c1107
-rw-r--r--src/seastar/dpdk/app/test-pmd/rxonly.c249
-rw-r--r--src/seastar/dpdk/app/test-pmd/testpmd.c2362
-rw-r--r--src/seastar/dpdk/app/test-pmd/testpmd.h663
-rw-r--r--src/seastar/dpdk/app/test-pmd/txonly.c339
41 files changed, 35621 insertions, 0 deletions
diff --git a/src/seastar/dpdk/app/Makefile b/src/seastar/dpdk/app/Makefile
new file mode 100644
index 00000000..c3aeebf6
--- /dev/null
+++ b/src/seastar/dpdk/app/Makefile
@@ -0,0 +1,42 @@
+# BSD LICENSE
+#
+# Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+DIRS-$(CONFIG_RTE_TEST_PMD) += test-pmd
+DIRS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += proc_info
+DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += pdump
+
+ifeq ($(CONFIG_RTE_LIBRTE_CRYPTODEV),y)
+DIRS-$(CONFIG_RTE_APP_CRYPTO_PERF) += test-crypto-perf
+endif
+
+include $(RTE_SDK)/mk/rte.subdir.mk
diff --git a/src/seastar/dpdk/app/pdump/Makefile b/src/seastar/dpdk/app/pdump/Makefile
new file mode 100644
index 00000000..38ac3e9a
--- /dev/null
+++ b/src/seastar/dpdk/app/pdump/Makefile
@@ -0,0 +1,46 @@
+# BSD LICENSE
+#
+# Copyright(c) 2016 Intel Corporation. All rights reserved.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+ifeq ($(CONFIG_RTE_LIBRTE_PDUMP),y)
+
+APP = dpdk-pdump
+
+CFLAGS += $(WERROR_FLAGS)
+
+# all source are stored in SRCS-y
+
+SRCS-y := main.c
+
+include $(RTE_SDK)/mk/rte.app.mk
+
+endif
diff --git a/src/seastar/dpdk/app/pdump/main.c b/src/seastar/dpdk/app/pdump/main.c
new file mode 100644
index 00000000..3b13753d
--- /dev/null
+++ b/src/seastar/dpdk/app/pdump/main.c
@@ -0,0 +1,915 @@
+/*
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <net/if.h>
+
+#include <rte_eal.h>
+#include <rte_common.h>
+#include <rte_debug.h>
+#include <rte_ethdev.h>
+#include <rte_memory.h>
+#include <rte_lcore.h>
+#include <rte_branch_prediction.h>
+#include <rte_errno.h>
+#include <rte_dev.h>
+#include <rte_kvargs.h>
+#include <rte_mempool.h>
+#include <rte_ring.h>
+#include <rte_pdump.h>
+
+#define CMD_LINE_OPT_PDUMP "pdump"
+#define PDUMP_PORT_ARG "port"
+#define PDUMP_PCI_ARG "device_id"
+#define PDUMP_QUEUE_ARG "queue"
+#define PDUMP_DIR_ARG "dir"
+#define PDUMP_RX_DEV_ARG "rx-dev"
+#define PDUMP_TX_DEV_ARG "tx-dev"
+#define PDUMP_RING_SIZE_ARG "ring-size"
+#define PDUMP_MSIZE_ARG "mbuf-size"
+#define PDUMP_NUM_MBUFS_ARG "total-num-mbufs"
+#define CMD_LINE_OPT_SER_SOCK_PATH "server-socket-path"
+#define CMD_LINE_OPT_CLI_SOCK_PATH "client-socket-path"
+
+#define VDEV_PCAP "net_pcap_%s_%d,tx_pcap=%s"
+#define VDEV_IFACE "net_pcap_%s_%d,tx_iface=%s"
+#define TX_STREAM_SIZE 64
+
+#define MP_NAME "pdump_pool_%d"
+
+#define RX_RING "rx_ring_%d"
+#define TX_RING "tx_ring_%d"
+
+#define RX_STR "rx"
+#define TX_STR "tx"
+
+/* Maximum long option length for option parsing. */
+#define APP_ARG_TCPDUMP_MAX_TUPLES 54
+#define MBUF_POOL_CACHE_SIZE 250
+#define TX_DESC_PER_QUEUE 512
+#define RX_DESC_PER_QUEUE 128
+#define MBUFS_PER_POOL 65535
+#define MAX_LONG_OPT_SZ 64
+#define RING_SIZE 16384
+#define SIZE 256
+#define BURST_SIZE 32
+#define NUM_VDEVS 2
+
+/* true if x is a power of 2 */
+#define POWEROF2(x) ((((x)-1) & (x)) == 0)
+
+enum pdump_en_dis {
+ DISABLE = 1,
+ ENABLE = 2
+};
+
+enum pcap_stream {
+ IFACE = 1,
+ PCAP = 2
+};
+
+enum pdump_by {
+ PORT_ID = 1,
+ DEVICE_ID = 2
+};
+
+const char *valid_pdump_arguments[] = {
+ PDUMP_PORT_ARG,
+ PDUMP_PCI_ARG,
+ PDUMP_QUEUE_ARG,
+ PDUMP_DIR_ARG,
+ PDUMP_RX_DEV_ARG,
+ PDUMP_TX_DEV_ARG,
+ PDUMP_RING_SIZE_ARG,
+ PDUMP_MSIZE_ARG,
+ PDUMP_NUM_MBUFS_ARG,
+ NULL
+};
+
+struct pdump_stats {
+ uint64_t dequeue_pkts;
+ uint64_t tx_pkts;
+ uint64_t freed_pkts;
+};
+
+struct pdump_tuples {
+ /* cli params */
+ uint8_t port;
+ char *device_id;
+ uint16_t queue;
+ char rx_dev[TX_STREAM_SIZE];
+ char tx_dev[TX_STREAM_SIZE];
+ uint32_t ring_size;
+ uint16_t mbuf_data_size;
+ uint32_t total_num_mbufs;
+
+ /* params for library API call */
+ uint32_t dir;
+ struct rte_mempool *mp;
+ struct rte_ring *rx_ring;
+ struct rte_ring *tx_ring;
+
+ /* params for packet dumping */
+ enum pdump_by dump_by_type;
+ int rx_vdev_id;
+ int tx_vdev_id;
+ enum pcap_stream rx_vdev_stream_type;
+ enum pcap_stream tx_vdev_stream_type;
+ bool single_pdump_dev;
+
+ /* stats */
+ struct pdump_stats stats;
+} __rte_cache_aligned;
+static struct pdump_tuples pdump_t[APP_ARG_TCPDUMP_MAX_TUPLES];
+
+struct parse_val {
+ uint64_t min;
+ uint64_t max;
+ uint64_t val;
+};
+
+int num_tuples;
+static struct rte_eth_conf port_conf_default;
+volatile uint8_t quit_signal;
+static char server_socket_path[PATH_MAX];
+static char client_socket_path[PATH_MAX];
+
+/**< display usage */
+static void
+pdump_usage(const char *prgname)
+{
+ printf("usage: %s [EAL options] -- --pdump "
+ "'(port=<port id> | device_id=<pci id or vdev name>),"
+ "(queue=<queue_id>),"
+ "(rx-dev=<iface or pcap file> |"
+ " tx-dev=<iface or pcap file>,"
+ "[ring-size=<ring size>default:16384],"
+ "[mbuf-size=<mbuf data size>default:2176],"
+ "[total-num-mbufs=<number of mbufs>default:65535]'\n"
+ "[--server-socket-path=<server socket dir>"
+ "default:/var/run/.dpdk/ (or) ~/.dpdk/]\n"
+ "[--client-socket-path=<client socket dir>"
+ "default:/var/run/.dpdk/ (or) ~/.dpdk/]\n",
+ prgname);
+}
+
+static int
+parse_device_id(const char *key __rte_unused, const char *value,
+ void *extra_args)
+{
+ struct pdump_tuples *pt = extra_args;
+
+ pt->device_id = strdup(value);
+ pt->dump_by_type = DEVICE_ID;
+
+ return 0;
+}
+
+static int
+parse_queue(const char *key __rte_unused, const char *value, void *extra_args)
+{
+ unsigned long n;
+ struct pdump_tuples *pt = extra_args;
+
+ if (!strcmp(value, "*"))
+ pt->queue = RTE_PDUMP_ALL_QUEUES;
+ else {
+ n = strtoul(value, NULL, 10);
+ pt->queue = (uint16_t) n;
+ }
+ return 0;
+}
+
+static int
+parse_rxtxdev(const char *key, const char *value, void *extra_args)
+{
+
+ struct pdump_tuples *pt = extra_args;
+
+ if (!strcmp(key, PDUMP_RX_DEV_ARG)) {
+ snprintf(pt->rx_dev, sizeof(pt->rx_dev), "%s", value);
+ /* identify the tx stream type for pcap vdev */
+ if (if_nametoindex(pt->rx_dev))
+ pt->rx_vdev_stream_type = IFACE;
+ } else if (!strcmp(key, PDUMP_TX_DEV_ARG)) {
+ snprintf(pt->tx_dev, sizeof(pt->tx_dev), "%s", value);
+ /* identify the tx stream type for pcap vdev */
+ if (if_nametoindex(pt->tx_dev))
+ pt->tx_vdev_stream_type = IFACE;
+ }
+
+ return 0;
+}
+
+static int
+parse_uint_value(const char *key, const char *value, void *extra_args)
+{
+ struct parse_val *v;
+ unsigned long t;
+ char *end;
+ int ret = 0;
+
+ errno = 0;
+ v = extra_args;
+ t = strtoul(value, &end, 10);
+
+ if (errno != 0 || end[0] != 0 || t < v->min || t > v->max) {
+ printf("invalid value:\"%s\" for key:\"%s\", "
+ "value must be >= %"PRIu64" and <= %"PRIu64"\n",
+ value, key, v->min, v->max);
+ ret = -EINVAL;
+ }
+ if (!strcmp(key, PDUMP_RING_SIZE_ARG) && !POWEROF2(t)) {
+ printf("invalid value:\"%s\" for key:\"%s\", "
+ "value must be power of 2\n", value, key);
+ ret = -EINVAL;
+ }
+
+ if (ret != 0)
+ return ret;
+
+ v->val = t;
+ return 0;
+}
+
+static int
+parse_pdump(const char *optarg)
+{
+ struct rte_kvargs *kvlist;
+ int ret = 0, cnt1, cnt2;
+ struct pdump_tuples *pt;
+ struct parse_val v = {0};
+
+ pt = &pdump_t[num_tuples];
+
+ /* initial check for invalid arguments */
+ kvlist = rte_kvargs_parse(optarg, valid_pdump_arguments);
+ if (kvlist == NULL) {
+ printf("--pdump=\"%s\": invalid argument passed\n", optarg);
+ return -1;
+ }
+
+ /* port/device_id parsing and validation */
+ cnt1 = rte_kvargs_count(kvlist, PDUMP_PORT_ARG);
+ cnt2 = rte_kvargs_count(kvlist, PDUMP_PCI_ARG);
+ if (!((cnt1 == 1 && cnt2 == 0) || (cnt1 == 0 && cnt2 == 1))) {
+ printf("--pdump=\"%s\": must have either port or "
+ "device_id argument\n", optarg);
+ ret = -1;
+ goto free_kvlist;
+ } else if (cnt1 == 1) {
+ v.min = 0;
+ v.max = RTE_MAX_ETHPORTS-1;
+ ret = rte_kvargs_process(kvlist, PDUMP_PORT_ARG,
+ &parse_uint_value, &v);
+ if (ret < 0)
+ goto free_kvlist;
+ pt->port = (uint8_t) v.val;
+ pt->dump_by_type = PORT_ID;
+ } else if (cnt2 == 1) {
+ ret = rte_kvargs_process(kvlist, PDUMP_PCI_ARG,
+ &parse_device_id, pt);
+ if (ret < 0)
+ goto free_kvlist;
+ }
+
+ /* queue parsing and validation */
+ cnt1 = rte_kvargs_count(kvlist, PDUMP_QUEUE_ARG);
+ if (cnt1 != 1) {
+ printf("--pdump=\"%s\": must have queue argument\n", optarg);
+ ret = -1;
+ goto free_kvlist;
+ }
+ ret = rte_kvargs_process(kvlist, PDUMP_QUEUE_ARG, &parse_queue, pt);
+ if (ret < 0)
+ goto free_kvlist;
+
+ /* rx-dev and tx-dev parsing and validation */
+ cnt1 = rte_kvargs_count(kvlist, PDUMP_RX_DEV_ARG);
+ cnt2 = rte_kvargs_count(kvlist, PDUMP_TX_DEV_ARG);
+ if (cnt1 == 0 && cnt2 == 0) {
+ printf("--pdump=\"%s\": must have either rx-dev or "
+ "tx-dev argument\n", optarg);
+ ret = -1;
+ goto free_kvlist;
+ } else if (cnt1 == 1 && cnt2 == 1) {
+ ret = rte_kvargs_process(kvlist, PDUMP_RX_DEV_ARG,
+ &parse_rxtxdev, pt);
+ if (ret < 0)
+ goto free_kvlist;
+ ret = rte_kvargs_process(kvlist, PDUMP_TX_DEV_ARG,
+ &parse_rxtxdev, pt);
+ if (ret < 0)
+ goto free_kvlist;
+ /* if captured packets has to send to the same vdev */
+ if (!strcmp(pt->rx_dev, pt->tx_dev))
+ pt->single_pdump_dev = true;
+ pt->dir = RTE_PDUMP_FLAG_RXTX;
+ } else if (cnt1 == 1) {
+ ret = rte_kvargs_process(kvlist, PDUMP_RX_DEV_ARG,
+ &parse_rxtxdev, pt);
+ if (ret < 0)
+ goto free_kvlist;
+ pt->dir = RTE_PDUMP_FLAG_RX;
+ } else if (cnt2 == 1) {
+ ret = rte_kvargs_process(kvlist, PDUMP_TX_DEV_ARG,
+ &parse_rxtxdev, pt);
+ if (ret < 0)
+ goto free_kvlist;
+ pt->dir = RTE_PDUMP_FLAG_TX;
+ }
+
+ /* optional */
+ /* ring_size parsing and validation */
+ cnt1 = rte_kvargs_count(kvlist, PDUMP_RING_SIZE_ARG);
+ if (cnt1 == 1) {
+ v.min = 2;
+ v.max = RTE_RING_SZ_MASK-1;
+ ret = rte_kvargs_process(kvlist, PDUMP_RING_SIZE_ARG,
+ &parse_uint_value, &v);
+ if (ret < 0)
+ goto free_kvlist;
+ pt->ring_size = (uint32_t) v.val;
+ } else
+ pt->ring_size = RING_SIZE;
+
+ /* mbuf_data_size parsing and validation */
+ cnt1 = rte_kvargs_count(kvlist, PDUMP_MSIZE_ARG);
+ if (cnt1 == 1) {
+ v.min = 1;
+ v.max = UINT16_MAX;
+ ret = rte_kvargs_process(kvlist, PDUMP_MSIZE_ARG,
+ &parse_uint_value, &v);
+ if (ret < 0)
+ goto free_kvlist;
+ pt->mbuf_data_size = (uint16_t) v.val;
+ } else
+ pt->mbuf_data_size = RTE_MBUF_DEFAULT_BUF_SIZE;
+
+ /* total_num_mbufs parsing and validation */
+ cnt1 = rte_kvargs_count(kvlist, PDUMP_NUM_MBUFS_ARG);
+ if (cnt1 == 1) {
+ v.min = 1025;
+ v.max = UINT16_MAX;
+ ret = rte_kvargs_process(kvlist, PDUMP_NUM_MBUFS_ARG,
+ &parse_uint_value, &v);
+ if (ret < 0)
+ goto free_kvlist;
+ pt->total_num_mbufs = (uint16_t) v.val;
+ } else
+ pt->total_num_mbufs = MBUFS_PER_POOL;
+
+ num_tuples++;
+
+free_kvlist:
+ rte_kvargs_free(kvlist);
+ return ret;
+}
+
+/* Parse the argument given in the command line of the application */
+static int
+launch_args_parse(int argc, char **argv, char *prgname)
+{
+ int opt, ret;
+ int option_index;
+ static struct option long_option[] = {
+ {"pdump", 1, 0, 0},
+ {"server-socket-path", 1, 0, 0},
+ {"client-socket-path", 1, 0, 0},
+ {NULL, 0, 0, 0}
+ };
+
+ if (argc == 1)
+ pdump_usage(prgname);
+
+ /* Parse command line */
+ while ((opt = getopt_long(argc, argv, " ",
+ long_option, &option_index)) != EOF) {
+ switch (opt) {
+ case 0:
+ if (!strncmp(long_option[option_index].name,
+ CMD_LINE_OPT_PDUMP,
+ sizeof(CMD_LINE_OPT_PDUMP))) {
+ ret = parse_pdump(optarg);
+ if (ret) {
+ pdump_usage(prgname);
+ return -1;
+ }
+ }
+
+ if (!strncmp(long_option[option_index].name,
+ CMD_LINE_OPT_SER_SOCK_PATH,
+ sizeof(CMD_LINE_OPT_SER_SOCK_PATH))) {
+ snprintf(server_socket_path,
+ sizeof(server_socket_path), "%s",
+ optarg);
+ }
+
+ if (!strncmp(long_option[option_index].name,
+ CMD_LINE_OPT_CLI_SOCK_PATH,
+ sizeof(CMD_LINE_OPT_CLI_SOCK_PATH))) {
+ snprintf(client_socket_path,
+ sizeof(client_socket_path), "%s",
+ optarg);
+ }
+
+ break;
+ default:
+ pdump_usage(prgname);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static void
+print_pdump_stats(void)
+{
+ int i;
+ struct pdump_tuples *pt;
+
+ for (i = 0; i < num_tuples; i++) {
+ printf("##### PDUMP DEBUG STATS #####\n");
+ pt = &pdump_t[i];
+ printf(" -packets dequeued: %"PRIu64"\n",
+ pt->stats.dequeue_pkts);
+ printf(" -packets transmitted to vdev: %"PRIu64"\n",
+ pt->stats.tx_pkts);
+ printf(" -packets freed: %"PRIu64"\n",
+ pt->stats.freed_pkts);
+ }
+}
+
+static inline void
+disable_pdump(struct pdump_tuples *pt)
+{
+ if (pt->dump_by_type == DEVICE_ID)
+ rte_pdump_disable_by_deviceid(pt->device_id, pt->queue,
+ pt->dir);
+ else if (pt->dump_by_type == PORT_ID)
+ rte_pdump_disable(pt->port, pt->queue, pt->dir);
+}
+
+static inline void
+pdump_rxtx(struct rte_ring *ring, uint8_t vdev_id, struct pdump_stats *stats)
+{
+ /* write input packets of port to vdev for pdump */
+ struct rte_mbuf *rxtx_bufs[BURST_SIZE];
+
+ /* first dequeue packets from ring of primary process */
+ const uint16_t nb_in_deq = rte_ring_dequeue_burst(ring,
+ (void *)rxtx_bufs, BURST_SIZE, NULL);
+ stats->dequeue_pkts += nb_in_deq;
+
+ if (nb_in_deq) {
+ /* then sent on vdev */
+ uint16_t nb_in_txd = rte_eth_tx_burst(
+ vdev_id,
+ 0, rxtx_bufs, nb_in_deq);
+ stats->tx_pkts += nb_in_txd;
+
+ if (unlikely(nb_in_txd < nb_in_deq)) {
+ do {
+ rte_pktmbuf_free(rxtx_bufs[nb_in_txd]);
+ stats->freed_pkts++;
+ } while (++nb_in_txd < nb_in_deq);
+ }
+ }
+}
+
+static void
+free_ring_data(struct rte_ring *ring, uint8_t vdev_id,
+ struct pdump_stats *stats)
+{
+ while (rte_ring_count(ring))
+ pdump_rxtx(ring, vdev_id, stats);
+}
+
+static void
+cleanup_rings(void)
+{
+ int i;
+ struct pdump_tuples *pt;
+
+ for (i = 0; i < num_tuples; i++) {
+ pt = &pdump_t[i];
+
+ if (pt->device_id)
+ free(pt->device_id);
+
+ /* free the rings */
+ if (pt->rx_ring)
+ rte_ring_free(pt->rx_ring);
+ if (pt->tx_ring)
+ rte_ring_free(pt->tx_ring);
+ }
+}
+
+static void
+cleanup_pdump_resources(void)
+{
+ int i;
+ struct pdump_tuples *pt;
+
+ /* disable pdump and free the pdump_tuple resources */
+ for (i = 0; i < num_tuples; i++) {
+ pt = &pdump_t[i];
+
+ /* remove callbacks */
+ disable_pdump(pt);
+
+ /*
+ * transmit rest of the enqueued packets of the rings on to
+ * the vdev, in order to release mbufs to the mepool.
+ **/
+ if (pt->dir & RTE_PDUMP_FLAG_RX)
+ free_ring_data(pt->rx_ring, pt->rx_vdev_id, &pt->stats);
+ if (pt->dir & RTE_PDUMP_FLAG_TX)
+ free_ring_data(pt->tx_ring, pt->tx_vdev_id, &pt->stats);
+ }
+ cleanup_rings();
+}
+
+static void
+signal_handler(int sig_num)
+{
+ if (sig_num == SIGINT) {
+ printf("\n\nSignal %d received, preparing to exit...\n",
+ sig_num);
+ quit_signal = 1;
+ }
+}
+
+static inline int
+configure_vdev(uint8_t port_id)
+{
+ struct ether_addr addr;
+ const uint16_t rxRings = 0, txRings = 1;
+ const uint8_t nb_ports = rte_eth_dev_count();
+ int ret;
+ uint16_t q;
+
+ if (port_id > nb_ports)
+ return -1;
+
+ ret = rte_eth_dev_configure(port_id, rxRings, txRings,
+ &port_conf_default);
+ if (ret != 0)
+ rte_exit(EXIT_FAILURE, "dev config failed\n");
+
+ for (q = 0; q < txRings; q++) {
+ ret = rte_eth_tx_queue_setup(port_id, q, TX_DESC_PER_QUEUE,
+ rte_eth_dev_socket_id(port_id), NULL);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "queue setup failed\n");
+ }
+
+ ret = rte_eth_dev_start(port_id);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "dev start failed\n");
+
+ rte_eth_macaddr_get(port_id, &addr);
+ printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8
+ " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n",
+ (unsigned)port_id,
+ addr.addr_bytes[0], addr.addr_bytes[1],
+ addr.addr_bytes[2], addr.addr_bytes[3],
+ addr.addr_bytes[4], addr.addr_bytes[5]);
+
+ rte_eth_promiscuous_enable(port_id);
+
+ return 0;
+}
+
+static void
+create_mp_ring_vdev(void)
+{
+ int i;
+ uint8_t portid;
+ struct pdump_tuples *pt = NULL;
+ struct rte_mempool *mbuf_pool = NULL;
+ char vdev_args[SIZE];
+ char ring_name[SIZE];
+ char mempool_name[SIZE];
+
+ for (i = 0; i < num_tuples; i++) {
+ pt = &pdump_t[i];
+ snprintf(mempool_name, SIZE, MP_NAME, i);
+ mbuf_pool = rte_mempool_lookup(mempool_name);
+ if (mbuf_pool == NULL) {
+ /* create mempool */
+ mbuf_pool = rte_pktmbuf_pool_create(mempool_name,
+ pt->total_num_mbufs,
+ MBUF_POOL_CACHE_SIZE, 0,
+ pt->mbuf_data_size,
+ rte_socket_id());
+ if (mbuf_pool == NULL) {
+ cleanup_rings();
+ rte_exit(EXIT_FAILURE,
+ "Mempool creation failed: %s\n",
+ rte_strerror(rte_errno));
+ }
+ }
+ pt->mp = mbuf_pool;
+
+ if (pt->dir == RTE_PDUMP_FLAG_RXTX) {
+ /* if captured packets has to send to the same vdev */
+ /* create rx_ring */
+ snprintf(ring_name, SIZE, RX_RING, i);
+ pt->rx_ring = rte_ring_create(ring_name, pt->ring_size,
+ rte_socket_id(), 0);
+ if (pt->rx_ring == NULL) {
+ cleanup_rings();
+ rte_exit(EXIT_FAILURE, "%s:%s:%d\n",
+ rte_strerror(rte_errno),
+ __func__, __LINE__);
+ }
+
+ /* create tx_ring */
+ snprintf(ring_name, SIZE, TX_RING, i);
+ pt->tx_ring = rte_ring_create(ring_name, pt->ring_size,
+ rte_socket_id(), 0);
+ if (pt->tx_ring == NULL) {
+ cleanup_rings();
+ rte_exit(EXIT_FAILURE, "%s:%s:%d\n",
+ rte_strerror(rte_errno),
+ __func__, __LINE__);
+ }
+
+ /* create vdevs */
+ (pt->rx_vdev_stream_type == IFACE) ?
+ snprintf(vdev_args, SIZE, VDEV_IFACE, RX_STR, i,
+ pt->rx_dev) :
+ snprintf(vdev_args, SIZE, VDEV_PCAP, RX_STR, i,
+ pt->rx_dev);
+ if (rte_eth_dev_attach(vdev_args, &portid) < 0) {
+ cleanup_rings();
+ rte_exit(EXIT_FAILURE,
+ "vdev creation failed:%s:%d\n",
+ __func__, __LINE__);
+ }
+ pt->rx_vdev_id = portid;
+
+ /* configure vdev */
+ configure_vdev(pt->rx_vdev_id);
+
+ if (pt->single_pdump_dev)
+ pt->tx_vdev_id = portid;
+ else {
+ (pt->tx_vdev_stream_type == IFACE) ?
+ snprintf(vdev_args, SIZE, VDEV_IFACE, TX_STR, i,
+ pt->tx_dev) :
+ snprintf(vdev_args, SIZE, VDEV_PCAP, TX_STR, i,
+ pt->tx_dev);
+ if (rte_eth_dev_attach(vdev_args,
+ &portid) < 0) {
+ cleanup_rings();
+ rte_exit(EXIT_FAILURE,
+ "vdev creation failed:"
+ "%s:%d\n", __func__, __LINE__);
+ }
+ pt->tx_vdev_id = portid;
+
+ /* configure vdev */
+ configure_vdev(pt->tx_vdev_id);
+ }
+ } else if (pt->dir == RTE_PDUMP_FLAG_RX) {
+
+ /* create rx_ring */
+ snprintf(ring_name, SIZE, RX_RING, i);
+ pt->rx_ring = rte_ring_create(ring_name, pt->ring_size,
+ rte_socket_id(), 0);
+ if (pt->rx_ring == NULL) {
+ cleanup_rings();
+ rte_exit(EXIT_FAILURE, "%s\n",
+ rte_strerror(rte_errno));
+ }
+
+ (pt->rx_vdev_stream_type == IFACE) ?
+ snprintf(vdev_args, SIZE, VDEV_IFACE, RX_STR, i,
+ pt->rx_dev) :
+ snprintf(vdev_args, SIZE, VDEV_PCAP, RX_STR, i,
+ pt->rx_dev);
+ if (rte_eth_dev_attach(vdev_args, &portid) < 0) {
+ cleanup_rings();
+ rte_exit(EXIT_FAILURE,
+ "vdev creation failed:%s:%d\n",
+ __func__, __LINE__);
+ }
+ pt->rx_vdev_id = portid;
+ /* configure vdev */
+ configure_vdev(pt->rx_vdev_id);
+ } else if (pt->dir == RTE_PDUMP_FLAG_TX) {
+
+ /* create tx_ring */
+ snprintf(ring_name, SIZE, TX_RING, i);
+ pt->tx_ring = rte_ring_create(ring_name, pt->ring_size,
+ rte_socket_id(), 0);
+ if (pt->tx_ring == NULL) {
+ cleanup_rings();
+ rte_exit(EXIT_FAILURE, "%s\n",
+ rte_strerror(rte_errno));
+ }
+
+ (pt->tx_vdev_stream_type == IFACE) ?
+ snprintf(vdev_args, SIZE, VDEV_IFACE, TX_STR, i,
+ pt->tx_dev) :
+ snprintf(vdev_args, SIZE, VDEV_PCAP, TX_STR, i,
+ pt->tx_dev);
+ if (rte_eth_dev_attach(vdev_args, &portid) < 0) {
+ cleanup_rings();
+ rte_exit(EXIT_FAILURE,
+ "vdev creation failed\n");
+ }
+ pt->tx_vdev_id = portid;
+
+ /* configure vdev */
+ configure_vdev(pt->tx_vdev_id);
+ }
+ }
+}
+
+static void
+enable_pdump(void)
+{
+ int i;
+ struct pdump_tuples *pt;
+ int ret = 0, ret1 = 0;
+
+ if (server_socket_path[0] != 0)
+ ret = rte_pdump_set_socket_dir(server_socket_path,
+ RTE_PDUMP_SOCKET_SERVER);
+ if (ret == 0 && client_socket_path[0] != 0) {
+ ret = rte_pdump_set_socket_dir(client_socket_path,
+ RTE_PDUMP_SOCKET_CLIENT);
+ }
+ if (ret < 0) {
+ cleanup_pdump_resources();
+ rte_exit(EXIT_FAILURE,
+ "failed to set socket paths of server:%s, "
+ "client:%s\n",
+ server_socket_path,
+ client_socket_path);
+ }
+
+ for (i = 0; i < num_tuples; i++) {
+ pt = &pdump_t[i];
+ if (pt->dir == RTE_PDUMP_FLAG_RXTX) {
+ if (pt->dump_by_type == DEVICE_ID) {
+ ret = rte_pdump_enable_by_deviceid(
+ pt->device_id,
+ pt->queue,
+ RTE_PDUMP_FLAG_RX,
+ pt->rx_ring,
+ pt->mp, NULL);
+ ret1 = rte_pdump_enable_by_deviceid(
+ pt->device_id,
+ pt->queue,
+ RTE_PDUMP_FLAG_TX,
+ pt->tx_ring,
+ pt->mp, NULL);
+ } else if (pt->dump_by_type == PORT_ID) {
+ ret = rte_pdump_enable(pt->port, pt->queue,
+ RTE_PDUMP_FLAG_RX,
+ pt->rx_ring, pt->mp, NULL);
+ ret1 = rte_pdump_enable(pt->port, pt->queue,
+ RTE_PDUMP_FLAG_TX,
+ pt->tx_ring, pt->mp, NULL);
+ }
+ } else if (pt->dir == RTE_PDUMP_FLAG_RX) {
+ if (pt->dump_by_type == DEVICE_ID)
+ ret = rte_pdump_enable_by_deviceid(
+ pt->device_id,
+ pt->queue,
+ pt->dir, pt->rx_ring,
+ pt->mp, NULL);
+ else if (pt->dump_by_type == PORT_ID)
+ ret = rte_pdump_enable(pt->port, pt->queue,
+ pt->dir,
+ pt->rx_ring, pt->mp, NULL);
+ } else if (pt->dir == RTE_PDUMP_FLAG_TX) {
+ if (pt->dump_by_type == DEVICE_ID)
+ ret = rte_pdump_enable_by_deviceid(
+ pt->device_id,
+ pt->queue,
+ pt->dir,
+ pt->tx_ring, pt->mp, NULL);
+ else if (pt->dump_by_type == PORT_ID)
+ ret = rte_pdump_enable(pt->port, pt->queue,
+ pt->dir,
+ pt->tx_ring, pt->mp, NULL);
+ }
+ if (ret < 0 || ret1 < 0) {
+ cleanup_pdump_resources();
+ rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno));
+ }
+ }
+}
+
+static inline void
+dump_packets(void)
+{
+ int i;
+ struct pdump_tuples *pt;
+
+ while (!quit_signal) {
+ for (i = 0; i < num_tuples; i++) {
+ pt = &pdump_t[i];
+ if (pt->dir & RTE_PDUMP_FLAG_RX)
+ pdump_rxtx(pt->rx_ring, pt->rx_vdev_id,
+ &pt->stats);
+ if (pt->dir & RTE_PDUMP_FLAG_TX)
+ pdump_rxtx(pt->tx_ring, pt->tx_vdev_id,
+ &pt->stats);
+ }
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ int diag;
+ int ret;
+ int i;
+
+ char c_flag[] = "-c1";
+ char n_flag[] = "-n4";
+ char mp_flag[] = "--proc-type=secondary";
+ char *argp[argc + 3];
+
+ /* catch ctrl-c so we can print on exit */
+ signal(SIGINT, signal_handler);
+
+ argp[0] = argv[0];
+ argp[1] = c_flag;
+ argp[2] = n_flag;
+ argp[3] = mp_flag;
+
+ for (i = 1; i < argc; i++)
+ argp[i + 3] = argv[i];
+
+ argc += 3;
+
+ diag = rte_eal_init(argc, argp);
+ if (diag < 0)
+ rte_panic("Cannot init EAL\n");
+
+ argc -= diag;
+ argv += (diag - 3);
+
+ /* parse app arguments */
+ if (argc > 1) {
+ ret = launch_args_parse(argc, argv, argp[0]);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "Invalid argument\n");
+ }
+
+ /* create mempool, ring and vdevs info */
+ create_mp_ring_vdev();
+ enable_pdump();
+ dump_packets();
+
+ cleanup_pdump_resources();
+ /* dump debug stats */
+ print_pdump_stats();
+
+ return 0;
+}
diff --git a/src/seastar/dpdk/app/proc_info/Makefile b/src/seastar/dpdk/app/proc_info/Makefile
new file mode 100644
index 00000000..9e90438e
--- /dev/null
+++ b/src/seastar/dpdk/app/proc_info/Makefile
@@ -0,0 +1,42 @@
+# BSD LICENSE
+#
+# Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+APP = dpdk-procinfo
+
+CFLAGS += $(WERROR_FLAGS)
+
+# all source are stored in SRCS-y
+
+SRCS-y := main.c
+
+include $(RTE_SDK)/mk/rte.app.mk
diff --git a/src/seastar/dpdk/app/proc_info/main.c b/src/seastar/dpdk/app/proc_info/main.c
new file mode 100644
index 00000000..d4f6a823
--- /dev/null
+++ b/src/seastar/dpdk/app/proc_info/main.c
@@ -0,0 +1,692 @@
+/*
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <inttypes.h>
+#include <sys/queue.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <unistd.h>
+
+#include <rte_eal.h>
+#include <rte_common.h>
+#include <rte_debug.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_memory.h>
+#include <rte_memzone.h>
+#include <rte_launch.h>
+#include <rte_tailq.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_debug.h>
+#include <rte_log.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_string_fns.h>
+#include <rte_metrics.h>
+
+/* Maximum long option length for option parsing. */
+#define MAX_LONG_OPT_SZ 64
+#define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1
+
+#define MAX_STRING_LEN 256
+
+/**< mask of enabled ports */
+static uint32_t enabled_port_mask;
+/**< Enable stats. */
+static uint32_t enable_stats;
+/**< Enable xstats. */
+static uint32_t enable_xstats;
+/**< Enable collectd format*/
+static uint32_t enable_collectd_format;
+/**< FD to send collectd format messages to STDOUT*/
+static int stdout_fd;
+/**< Host id process is running on */
+static char host_id[MAX_LONG_OPT_SZ];
+/**< Enable metrics. */
+static uint32_t enable_metrics;
+/**< Enable stats reset. */
+static uint32_t reset_stats;
+/**< Enable xstats reset. */
+static uint32_t reset_xstats;
+/**< Enable memory info. */
+static uint32_t mem_info;
+/**< Enable displaying xstat name. */
+static uint32_t enable_xstats_name;
+static char *xstats_name;
+
+/**< Enable xstats by ids. */
+#define MAX_NB_XSTATS_IDS 1024
+static uint32_t nb_xstats_ids;
+static uint64_t xstats_ids[MAX_NB_XSTATS_IDS];
+
+/**< display usage */
+static void
+proc_info_usage(const char *prgname)
+{
+ printf("%s [EAL options] -- -p PORTMASK\n"
+ " -m to display DPDK memory zones, segments and TAILQ information\n"
+ " -p PORTMASK: hexadecimal bitmask of ports to retrieve stats for\n"
+ " --stats: to display port statistics, enabled by default\n"
+ " --xstats: to display extended port statistics, disabled by "
+ "default\n"
+ " --metrics: to display derived metrics of the ports, disabled by "
+ "default\n"
+ " --xstats-name NAME: to display single xstat id by NAME\n"
+ " --xstats-ids IDLIST: to display xstat values by id. "
+ "The argument is comma-separated list of xstat ids to print out.\n"
+ " --stats-reset: to reset port statistics\n"
+ " --xstats-reset: to reset port extended statistics\n"
+ " --collectd-format: to print statistics to STDOUT in expected by collectd format\n"
+ " --host-id STRING: host id used to identify the system process is running on\n",
+ prgname);
+}
+
+/*
+ * Parse the portmask provided at run time.
+ */
+static int
+parse_portmask(const char *portmask)
+{
+ char *end = NULL;
+ unsigned long pm;
+
+ errno = 0;
+
+ /* parse hexadecimal string */
+ pm = strtoul(portmask, &end, 16);
+ if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0') ||
+ (errno != 0)) {
+ printf("%s ERROR parsing the port mask\n", __func__);
+ return -1;
+ }
+
+ if (pm == 0)
+ return -1;
+
+ return pm;
+
+}
+
+/*
+ * Parse ids value list into array
+ */
+static int
+parse_xstats_ids(char *list, uint64_t *ids, int limit) {
+ int length;
+ char *token;
+ char *ctx = NULL;
+ char *endptr;
+
+ length = 0;
+ token = strtok_r(list, ",", &ctx);
+ while (token != NULL) {
+ ids[length] = strtoull(token, &endptr, 10);
+ if (*endptr != '\0')
+ return -EINVAL;
+
+ length++;
+ if (length >= limit)
+ return -E2BIG;
+
+ token = strtok_r(NULL, ",", &ctx);
+ }
+
+ return length;
+}
+
+static int
+proc_info_preparse_args(int argc, char **argv)
+{
+ char *prgname = argv[0];
+ int i;
+
+ for (i = 0; i < argc; i++) {
+ /* Print stats or xstats to STDOUT in collectd format */
+ if (!strncmp(argv[i], "--collectd-format", MAX_LONG_OPT_SZ)) {
+ enable_collectd_format = 1;
+ stdout_fd = dup(STDOUT_FILENO);
+ close(STDOUT_FILENO);
+ }
+ if (!strncmp(argv[i], "--host-id", MAX_LONG_OPT_SZ)) {
+ if ((i + 1) == argc) {
+ printf("Invalid host id or not specified\n");
+ proc_info_usage(prgname);
+ return -1;
+ }
+ strncpy(host_id, argv[i+1], sizeof(host_id));
+ }
+ }
+
+ if (!strlen(host_id)) {
+ int err = gethostname(host_id, MAX_LONG_OPT_SZ-1);
+
+ if (err)
+ strcpy(host_id, "unknown");
+ }
+
+ return 0;
+}
+
+/* Parse the argument given in the command line of the application */
+static int
+proc_info_parse_args(int argc, char **argv)
+{
+ int opt;
+ int option_index;
+ char *prgname = argv[0];
+ static struct option long_option[] = {
+ {"stats", 0, NULL, 0},
+ {"stats-reset", 0, NULL, 0},
+ {"xstats", 0, NULL, 0},
+ {"metrics", 0, NULL, 0},
+ {"xstats-reset", 0, NULL, 0},
+ {"xstats-name", required_argument, NULL, 1},
+ {"collectd-format", 0, NULL, 0},
+ {"xstats-ids", 1, NULL, 1},
+ {"host-id", 0, NULL, 0},
+ {NULL, 0, 0, 0}
+ };
+
+ if (argc == 1)
+ proc_info_usage(prgname);
+
+ /* Parse command line */
+ while ((opt = getopt_long(argc, argv, "p:m",
+ long_option, &option_index)) != EOF) {
+ switch (opt) {
+ /* portmask */
+ case 'p':
+ enabled_port_mask = parse_portmask(optarg);
+ if (enabled_port_mask == 0) {
+ printf("invalid portmask\n");
+ proc_info_usage(prgname);
+ return -1;
+ }
+ break;
+ case 'm':
+ mem_info = 1;
+ break;
+ case 0:
+ /* Print stats */
+ if (!strncmp(long_option[option_index].name, "stats",
+ MAX_LONG_OPT_SZ))
+ enable_stats = 1;
+ /* Print xstats */
+ else if (!strncmp(long_option[option_index].name, "xstats",
+ MAX_LONG_OPT_SZ))
+ enable_xstats = 1;
+ else if (!strncmp(long_option[option_index].name,
+ "metrics",
+ MAX_LONG_OPT_SZ))
+ enable_metrics = 1;
+ /* Reset stats */
+ if (!strncmp(long_option[option_index].name, "stats-reset",
+ MAX_LONG_OPT_SZ))
+ reset_stats = 1;
+ /* Reset xstats */
+ else if (!strncmp(long_option[option_index].name, "xstats-reset",
+ MAX_LONG_OPT_SZ))
+ reset_xstats = 1;
+ break;
+ case 1:
+ /* Print xstat single value given by name*/
+ if (!strncmp(long_option[option_index].name,
+ "xstats-name", MAX_LONG_OPT_SZ)) {
+ enable_xstats_name = 1;
+ xstats_name = optarg;
+ printf("name:%s:%s\n",
+ long_option[option_index].name,
+ optarg);
+ } else if (!strncmp(long_option[option_index].name,
+ "xstats-ids",
+ MAX_LONG_OPT_SZ)) {
+ nb_xstats_ids = parse_xstats_ids(optarg,
+ xstats_ids, MAX_NB_XSTATS_IDS);
+
+ if (nb_xstats_ids <= 0) {
+ printf("xstats-id list parse error.\n");
+ return -1;
+ }
+
+ }
+ break;
+ default:
+ proc_info_usage(prgname);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static void
+meminfo_display(void)
+{
+ printf("----------- MEMORY_SEGMENTS -----------\n");
+ rte_dump_physmem_layout(stdout);
+ printf("--------- END_MEMORY_SEGMENTS ---------\n");
+
+ printf("------------ MEMORY_ZONES -------------\n");
+ rte_memzone_dump(stdout);
+ printf("---------- END_MEMORY_ZONES -----------\n");
+
+ printf("------------- TAIL_QUEUES -------------\n");
+ rte_dump_tailq(stdout);
+ printf("---------- END_TAIL_QUEUES ------------\n");
+}
+
+static void
+nic_stats_display(uint8_t port_id)
+{
+ struct rte_eth_stats stats;
+ uint8_t i;
+
+ static const char *nic_stats_border = "########################";
+
+ rte_eth_stats_get(port_id, &stats);
+ printf("\n %s NIC statistics for port %-2d %s\n",
+ nic_stats_border, port_id, nic_stats_border);
+
+ printf(" RX-packets: %-10"PRIu64" RX-errors: %-10"PRIu64
+ " RX-bytes: %-10"PRIu64"\n", stats.ipackets, stats.ierrors,
+ stats.ibytes);
+ printf(" RX-nombuf: %-10"PRIu64"\n", stats.rx_nombuf);
+ printf(" TX-packets: %-10"PRIu64" TX-errors: %-10"PRIu64
+ " TX-bytes: %-10"PRIu64"\n", stats.opackets, stats.oerrors,
+ stats.obytes);
+
+ printf("\n");
+ for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) {
+ printf(" Stats reg %2d RX-packets: %-10"PRIu64
+ " RX-errors: %-10"PRIu64
+ " RX-bytes: %-10"PRIu64"\n",
+ i, stats.q_ipackets[i], stats.q_errors[i], stats.q_ibytes[i]);
+ }
+
+ printf("\n");
+ for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) {
+ printf(" Stats reg %2d TX-packets: %-10"PRIu64
+ " TX-bytes: %-10"PRIu64"\n",
+ i, stats.q_opackets[i], stats.q_obytes[i]);
+ }
+
+ printf(" %s############################%s\n",
+ nic_stats_border, nic_stats_border);
+}
+
+static void
+nic_stats_clear(uint8_t port_id)
+{
+ printf("\n Clearing NIC stats for port %d\n", port_id);
+ rte_eth_stats_reset(port_id);
+ printf("\n NIC statistics for port %d cleared\n", port_id);
+}
+
+static void collectd_resolve_cnt_type(char *cnt_type, size_t cnt_type_len,
+ const char *cnt_name) {
+ char *type_end = strrchr(cnt_name, '_');
+
+ if ((type_end != NULL) &&
+ (strncmp(cnt_name, "rx_", strlen("rx_")) == 0)) {
+ if (strncmp(type_end, "_errors", strlen("_errors")) == 0)
+ strncpy(cnt_type, "if_rx_errors", cnt_type_len);
+ else if (strncmp(type_end, "_dropped", strlen("_dropped")) == 0)
+ strncpy(cnt_type, "if_rx_dropped", cnt_type_len);
+ else if (strncmp(type_end, "_bytes", strlen("_bytes")) == 0)
+ strncpy(cnt_type, "if_rx_octets", cnt_type_len);
+ else if (strncmp(type_end, "_packets", strlen("_packets")) == 0)
+ strncpy(cnt_type, "if_rx_packets", cnt_type_len);
+ else if (strncmp(type_end, "_placement",
+ strlen("_placement")) == 0)
+ strncpy(cnt_type, "if_rx_errors", cnt_type_len);
+ else if (strncmp(type_end, "_buff", strlen("_buff")) == 0)
+ strncpy(cnt_type, "if_rx_errors", cnt_type_len);
+ else
+ /* Does not fit obvious type: use a more generic one */
+ strncpy(cnt_type, "derive", cnt_type_len);
+ } else if ((type_end != NULL) &&
+ (strncmp(cnt_name, "tx_", strlen("tx_"))) == 0) {
+ if (strncmp(type_end, "_errors", strlen("_errors")) == 0)
+ strncpy(cnt_type, "if_tx_errors", cnt_type_len);
+ else if (strncmp(type_end, "_dropped", strlen("_dropped")) == 0)
+ strncpy(cnt_type, "if_tx_dropped", cnt_type_len);
+ else if (strncmp(type_end, "_bytes", strlen("_bytes")) == 0)
+ strncpy(cnt_type, "if_tx_octets", cnt_type_len);
+ else if (strncmp(type_end, "_packets", strlen("_packets")) == 0)
+ strncpy(cnt_type, "if_tx_packets", cnt_type_len);
+ else
+ /* Does not fit obvious type: use a more generic one */
+ strncpy(cnt_type, "derive", cnt_type_len);
+ } else if ((type_end != NULL) &&
+ (strncmp(cnt_name, "flow_", strlen("flow_"))) == 0) {
+ if (strncmp(type_end, "_filters", strlen("_filters")) == 0)
+ strncpy(cnt_type, "operations", cnt_type_len);
+ else if (strncmp(type_end, "_errors", strlen("_errors")) == 0)
+ strncpy(cnt_type, "errors", cnt_type_len);
+ else if (strncmp(type_end, "_filters", strlen("_filters")) == 0)
+ strncpy(cnt_type, "filter_result", cnt_type_len);
+ } else if ((type_end != NULL) &&
+ (strncmp(cnt_name, "mac_", strlen("mac_"))) == 0) {
+ if (strncmp(type_end, "_errors", strlen("_errors")) == 0)
+ strncpy(cnt_type, "errors", cnt_type_len);
+ } else {
+ /* Does not fit obvious type, or strrchr error: */
+ /* use a more generic type */
+ strncpy(cnt_type, "derive", cnt_type_len);
+ }
+}
+
+static void
+nic_xstats_by_name_display(uint8_t port_id, char *name)
+{
+ uint64_t id;
+
+ printf("###### NIC statistics for port %-2d, statistic name '%s':\n",
+ port_id, name);
+
+ if (rte_eth_xstats_get_id_by_name(port_id, name, &id) == 0)
+ printf("%s: %"PRIu64"\n", name, id);
+ else
+ printf("Statistic not found...\n");
+
+}
+
+static void
+nic_xstats_by_ids_display(uint8_t port_id, uint64_t *ids, int len)
+{
+ struct rte_eth_xstat_name *xstats_names;
+ uint64_t *values;
+ int ret, i;
+ static const char *nic_stats_border = "########################";
+
+ values = malloc(sizeof(*values) * len);
+ if (values == NULL) {
+ printf("Cannot allocate memory for xstats\n");
+ return;
+ }
+
+ xstats_names = malloc(sizeof(struct rte_eth_xstat_name) * len);
+ if (xstats_names == NULL) {
+ printf("Cannot allocate memory for xstat names\n");
+ free(values);
+ return;
+ }
+
+ if (len != rte_eth_xstats_get_names_by_id(
+ port_id, xstats_names, len, ids)) {
+ printf("Cannot get xstat names\n");
+ goto err;
+ }
+
+ printf("###### NIC extended statistics for port %-2d #########\n",
+ port_id);
+ printf("%s############################\n", nic_stats_border);
+ ret = rte_eth_xstats_get_by_id(port_id, ids, values, len);
+ if (ret < 0 || ret > len) {
+ printf("Cannot get xstats\n");
+ goto err;
+ }
+
+ for (i = 0; i < len; i++)
+ printf("%s: %"PRIu64"\n",
+ xstats_names[i].name,
+ values[i]);
+
+ printf("%s############################\n", nic_stats_border);
+err:
+ free(values);
+ free(xstats_names);
+}
+
+static void
+nic_xstats_display(uint8_t port_id)
+{
+ struct rte_eth_xstat_name *xstats_names;
+ uint64_t *values;
+ int len, ret, i;
+ static const char *nic_stats_border = "########################";
+
+ len = rte_eth_xstats_get_names_by_id(port_id, NULL, 0, NULL);
+ if (len < 0) {
+ printf("Cannot get xstats count\n");
+ return;
+ }
+ values = malloc(sizeof(*values) * len);
+ if (values == NULL) {
+ printf("Cannot allocate memory for xstats\n");
+ return;
+ }
+
+ xstats_names = malloc(sizeof(struct rte_eth_xstat_name) * len);
+ if (xstats_names == NULL) {
+ printf("Cannot allocate memory for xstat names\n");
+ free(values);
+ return;
+ }
+ if (len != rte_eth_xstats_get_names_by_id(
+ port_id, xstats_names, len, NULL)) {
+ printf("Cannot get xstat names\n");
+ goto err;
+ }
+
+ printf("###### NIC extended statistics for port %-2d #########\n",
+ port_id);
+ printf("%s############################\n",
+ nic_stats_border);
+ ret = rte_eth_xstats_get_by_id(port_id, NULL, values, len);
+ if (ret < 0 || ret > len) {
+ printf("Cannot get xstats\n");
+ goto err;
+ }
+
+ for (i = 0; i < len; i++) {
+ if (enable_collectd_format) {
+ char counter_type[MAX_STRING_LEN];
+ char buf[MAX_STRING_LEN];
+
+ collectd_resolve_cnt_type(counter_type,
+ sizeof(counter_type),
+ xstats_names[i].name);
+ sprintf(buf, "PUTVAL %s/dpdkstat-port.%u/%s-%s N:%"
+ PRIu64"\n", host_id, port_id, counter_type,
+ xstats_names[i].name, values[i]);
+ write(stdout_fd, buf, strlen(buf));
+ } else {
+ printf("%s: %"PRIu64"\n", xstats_names[i].name,
+ values[i]);
+ }
+ }
+
+ printf("%s############################\n",
+ nic_stats_border);
+err:
+ free(values);
+ free(xstats_names);
+}
+
+static void
+nic_xstats_clear(uint8_t port_id)
+{
+ printf("\n Clearing NIC xstats for port %d\n", port_id);
+ rte_eth_xstats_reset(port_id);
+ printf("\n NIC extended statistics for port %d cleared\n", port_id);
+}
+
+static void
+metrics_display(int port_id)
+{
+ struct rte_metric_value *metrics;
+ struct rte_metric_name *names;
+ int len, ret;
+ static const char *nic_stats_border = "########################";
+
+ len = rte_metrics_get_names(NULL, 0);
+ if (len < 0) {
+ printf("Cannot get metrics count\n");
+ return;
+ }
+ if (len == 0) {
+ printf("No metrics to display (none have been registered)\n");
+ return;
+ }
+
+ metrics = rte_malloc("proc_info_metrics",
+ sizeof(struct rte_metric_value) * len, 0);
+ if (metrics == NULL) {
+ printf("Cannot allocate memory for metrics\n");
+ return;
+ }
+
+ names = rte_malloc(NULL, sizeof(struct rte_metric_name) * len, 0);
+ if (names == NULL) {
+ printf("Cannot allocate memory for metrcis names\n");
+ rte_free(metrics);
+ return;
+ }
+
+ if (len != rte_metrics_get_names(names, len)) {
+ printf("Cannot get metrics names\n");
+ rte_free(metrics);
+ rte_free(names);
+ return;
+ }
+
+ if (port_id == RTE_METRICS_GLOBAL)
+ printf("###### Non port specific metrics #########\n");
+ else
+ printf("###### metrics for port %-2d #########\n", port_id);
+ printf("%s############################\n", nic_stats_border);
+ ret = rte_metrics_get_values(port_id, metrics, len);
+ if (ret < 0 || ret > len) {
+ printf("Cannot get metrics values\n");
+ rte_free(metrics);
+ rte_free(names);
+ return;
+ }
+
+ int i;
+ for (i = 0; i < len; i++)
+ printf("%s: %"PRIu64"\n", names[i].name, metrics[i].value);
+
+ printf("%s############################\n", nic_stats_border);
+ rte_free(metrics);
+ rte_free(names);
+}
+
+int
+main(int argc, char **argv)
+{
+ int ret;
+ int i;
+ char c_flag[] = "-c1";
+ char n_flag[] = "-n4";
+ char mp_flag[] = "--proc-type=secondary";
+ char *argp[argc + 3];
+ uint8_t nb_ports;
+
+ /* preparse app arguments */
+ ret = proc_info_preparse_args(argc, argv);
+ if (ret < 0) {
+ printf("Failed to parse arguments\n");
+ return -1;
+ }
+
+ argp[0] = argv[0];
+ argp[1] = c_flag;
+ argp[2] = n_flag;
+ argp[3] = mp_flag;
+
+ for (i = 1; i < argc; i++)
+ argp[i + 3] = argv[i];
+
+ argc += 3;
+
+ ret = rte_eal_init(argc, argp);
+ if (ret < 0)
+ rte_panic("Cannot init EAL\n");
+
+ argc -= ret;
+ argv += (ret - 3);
+
+ if (!rte_eal_primary_proc_alive(NULL))
+ rte_exit(EXIT_FAILURE, "No primary DPDK process is running.\n");
+
+ /* parse app arguments */
+ ret = proc_info_parse_args(argc, argv);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "Invalid argument\n");
+
+ if (mem_info) {
+ meminfo_display();
+ return 0;
+ }
+
+ nb_ports = rte_eth_dev_count();
+ if (nb_ports == 0)
+ rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
+
+ /* If no port mask was specified*/
+ if (enabled_port_mask == 0)
+ enabled_port_mask = 0xffff;
+
+ for (i = 0; i < nb_ports; i++) {
+ if (enabled_port_mask & (1 << i)) {
+ if (enable_stats)
+ nic_stats_display(i);
+ else if (enable_xstats)
+ nic_xstats_display(i);
+ else if (reset_stats)
+ nic_stats_clear(i);
+ else if (reset_xstats)
+ nic_xstats_clear(i);
+ else if (enable_xstats_name)
+ nic_xstats_by_name_display(i, xstats_name);
+ else if (nb_xstats_ids > 0)
+ nic_xstats_by_ids_display(i, xstats_ids,
+ nb_xstats_ids);
+ else if (enable_metrics)
+ metrics_display(i);
+ }
+ }
+
+ /* print port independent stats */
+ if (enable_metrics)
+ metrics_display(RTE_METRICS_GLOBAL);
+
+ return 0;
+}
diff --git a/src/seastar/dpdk/app/test-crypto-perf/Makefile b/src/seastar/dpdk/app/test-crypto-perf/Makefile
new file mode 100644
index 00000000..e4a989fe
--- /dev/null
+++ b/src/seastar/dpdk/app/test-crypto-perf/Makefile
@@ -0,0 +1,48 @@
+# BSD LICENSE
+#
+# Copyright(c) 2016-2017 Intel Corporation. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+
+APP = dpdk-test-crypto-perf
+
+CFLAGS += $(WERROR_FLAGS)
+
+# all source are stored in SRCS-y
+SRCS-y := main.c
+SRCS-y += cperf_ops.c
+SRCS-y += cperf_options_parsing.c
+SRCS-y += cperf_test_vectors.c
+SRCS-y += cperf_test_throughput.c
+SRCS-y += cperf_test_latency.c
+SRCS-y += cperf_test_verify.c
+SRCS-y += cperf_test_vector_parsing.c
+
+include $(RTE_SDK)/mk/rte.app.mk
diff --git a/src/seastar/dpdk/app/test-crypto-perf/cperf.h b/src/seastar/dpdk/app/test-crypto-perf/cperf.h
new file mode 100644
index 00000000..293ba940
--- /dev/null
+++ b/src/seastar/dpdk/app/test-crypto-perf/cperf.h
@@ -0,0 +1,58 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016-2017 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _CPERF_
+#define _CPERF_
+
+#include <rte_crypto.h>
+
+#include "cperf_ops.h"
+
+struct cperf_options;
+struct cperf_test_vector;
+struct cperf_op_fns;
+
+typedef void *(*cperf_constructor_t)(uint8_t dev_id, uint16_t qp_id,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *t_vec,
+ const struct cperf_op_fns *op_fns);
+
+typedef int (*cperf_runner_t)(void *test_ctx);
+typedef void (*cperf_destructor_t)(void *test_ctx);
+
+struct cperf_test {
+ cperf_constructor_t constructor;
+ cperf_runner_t runner;
+ cperf_destructor_t destructor;
+};
+
+#endif /* _CPERF_ */
diff --git a/src/seastar/dpdk/app/test-crypto-perf/cperf_ops.c b/src/seastar/dpdk/app/test-crypto-perf/cperf_ops.c
new file mode 100644
index 00000000..c2c3db57
--- /dev/null
+++ b/src/seastar/dpdk/app/test-crypto-perf/cperf_ops.c
@@ -0,0 +1,515 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016-2017 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rte_cryptodev.h>
+
+#include "cperf_ops.h"
+#include "cperf_test_vectors.h"
+
+static int
+cperf_set_ops_null_cipher(struct rte_crypto_op **ops,
+ struct rte_mbuf **bufs_in, struct rte_mbuf **bufs_out,
+ uint16_t nb_ops, struct rte_cryptodev_sym_session *sess,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector __rte_unused)
+{
+ uint16_t i;
+
+ for (i = 0; i < nb_ops; i++) {
+ struct rte_crypto_sym_op *sym_op = ops[i]->sym;
+
+ rte_crypto_op_attach_sym_session(ops[i], sess);
+
+ sym_op->m_src = bufs_in[i];
+ sym_op->m_dst = bufs_out[i];
+
+ /* cipher parameters */
+ sym_op->cipher.data.length = options->test_buffer_size;
+ sym_op->cipher.data.offset = 0;
+ }
+
+ return 0;
+}
+
+static int
+cperf_set_ops_null_auth(struct rte_crypto_op **ops,
+ struct rte_mbuf **bufs_in, struct rte_mbuf **bufs_out,
+ uint16_t nb_ops, struct rte_cryptodev_sym_session *sess,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector __rte_unused)
+{
+ uint16_t i;
+
+ for (i = 0; i < nb_ops; i++) {
+ struct rte_crypto_sym_op *sym_op = ops[i]->sym;
+
+ rte_crypto_op_attach_sym_session(ops[i], sess);
+
+ sym_op->m_src = bufs_in[i];
+ sym_op->m_dst = bufs_out[i];
+
+ /* auth parameters */
+ sym_op->auth.data.length = options->test_buffer_size;
+ sym_op->auth.data.offset = 0;
+ }
+
+ return 0;
+}
+
+static int
+cperf_set_ops_cipher(struct rte_crypto_op **ops,
+ struct rte_mbuf **bufs_in, struct rte_mbuf **bufs_out,
+ uint16_t nb_ops, struct rte_cryptodev_sym_session *sess,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector)
+{
+ uint16_t i;
+
+ for (i = 0; i < nb_ops; i++) {
+ struct rte_crypto_sym_op *sym_op = ops[i]->sym;
+
+ rte_crypto_op_attach_sym_session(ops[i], sess);
+
+ sym_op->m_src = bufs_in[i];
+ sym_op->m_dst = bufs_out[i];
+
+ /* cipher parameters */
+ sym_op->cipher.iv.data = test_vector->iv.data;
+ sym_op->cipher.iv.phys_addr = test_vector->iv.phys_addr;
+ sym_op->cipher.iv.length = test_vector->iv.length;
+
+ if (options->cipher_algo == RTE_CRYPTO_CIPHER_SNOW3G_UEA2 ||
+ options->cipher_algo == RTE_CRYPTO_CIPHER_KASUMI_F8 ||
+ options->cipher_algo == RTE_CRYPTO_CIPHER_ZUC_EEA3)
+ sym_op->cipher.data.length = options->test_buffer_size << 3;
+ else
+ sym_op->cipher.data.length = options->test_buffer_size;
+
+ sym_op->cipher.data.offset = 0;
+ }
+
+ return 0;
+}
+
+static int
+cperf_set_ops_auth(struct rte_crypto_op **ops,
+ struct rte_mbuf **bufs_in, struct rte_mbuf **bufs_out,
+ uint16_t nb_ops, struct rte_cryptodev_sym_session *sess,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector)
+{
+ uint16_t i;
+
+ for (i = 0; i < nb_ops; i++) {
+ struct rte_crypto_sym_op *sym_op = ops[i]->sym;
+
+ rte_crypto_op_attach_sym_session(ops[i], sess);
+
+ sym_op->m_src = bufs_in[i];
+ sym_op->m_dst = bufs_out[i];
+
+ /* authentication parameters */
+ if (options->auth_op == RTE_CRYPTO_AUTH_OP_VERIFY) {
+ sym_op->auth.digest.data = test_vector->digest.data;
+ sym_op->auth.digest.phys_addr =
+ test_vector->digest.phys_addr;
+ sym_op->auth.digest.length = options->auth_digest_sz;
+ } else {
+
+ uint32_t offset = options->test_buffer_size;
+ struct rte_mbuf *buf, *tbuf;
+
+ if (options->out_of_place) {
+ buf = bufs_out[i];
+ } else {
+ buf = bufs_in[i];
+
+ tbuf = buf;
+ while ((tbuf->next != NULL) &&
+ (offset >= tbuf->data_len)) {
+ offset -= tbuf->data_len;
+ tbuf = tbuf->next;
+ }
+ }
+
+ sym_op->auth.digest.data = rte_pktmbuf_mtod_offset(buf,
+ uint8_t *, offset);
+ sym_op->auth.digest.phys_addr =
+ rte_pktmbuf_mtophys_offset(buf, offset);
+ sym_op->auth.digest.length = options->auth_digest_sz;
+ sym_op->auth.aad.phys_addr = test_vector->aad.phys_addr;
+ sym_op->auth.aad.data = test_vector->aad.data;
+ sym_op->auth.aad.length = options->auth_aad_sz;
+
+ }
+
+ if (options->auth_algo == RTE_CRYPTO_AUTH_SNOW3G_UIA2 ||
+ options->auth_algo == RTE_CRYPTO_AUTH_KASUMI_F9 ||
+ options->auth_algo == RTE_CRYPTO_AUTH_ZUC_EIA3)
+ sym_op->auth.data.length = options->test_buffer_size << 3;
+ else
+ sym_op->auth.data.length = options->test_buffer_size;
+
+ sym_op->auth.data.offset = 0;
+ }
+
+ return 0;
+}
+
+static int
+cperf_set_ops_cipher_auth(struct rte_crypto_op **ops,
+ struct rte_mbuf **bufs_in, struct rte_mbuf **bufs_out,
+ uint16_t nb_ops, struct rte_cryptodev_sym_session *sess,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector)
+{
+ uint16_t i;
+
+ for (i = 0; i < nb_ops; i++) {
+ struct rte_crypto_sym_op *sym_op = ops[i]->sym;
+
+ rte_crypto_op_attach_sym_session(ops[i], sess);
+
+ sym_op->m_src = bufs_in[i];
+ sym_op->m_dst = bufs_out[i];
+
+ /* cipher parameters */
+ sym_op->cipher.iv.data = test_vector->iv.data;
+ sym_op->cipher.iv.phys_addr = test_vector->iv.phys_addr;
+ sym_op->cipher.iv.length = test_vector->iv.length;
+
+ if (options->cipher_algo == RTE_CRYPTO_CIPHER_SNOW3G_UEA2 ||
+ options->cipher_algo == RTE_CRYPTO_CIPHER_KASUMI_F8 ||
+ options->cipher_algo == RTE_CRYPTO_CIPHER_ZUC_EEA3)
+ sym_op->cipher.data.length = options->test_buffer_size << 3;
+ else
+ sym_op->cipher.data.length = options->test_buffer_size;
+
+ sym_op->cipher.data.offset = 0;
+
+ /* authentication parameters */
+ if (options->auth_op == RTE_CRYPTO_AUTH_OP_VERIFY) {
+ sym_op->auth.digest.data = test_vector->digest.data;
+ sym_op->auth.digest.phys_addr =
+ test_vector->digest.phys_addr;
+ sym_op->auth.digest.length = options->auth_digest_sz;
+ } else {
+
+ uint32_t offset = options->test_buffer_size;
+ struct rte_mbuf *buf, *tbuf;
+
+ if (options->out_of_place) {
+ buf = bufs_out[i];
+ } else {
+ buf = bufs_in[i];
+
+ tbuf = buf;
+ while ((tbuf->next != NULL) &&
+ (offset >= tbuf->data_len)) {
+ offset -= tbuf->data_len;
+ tbuf = tbuf->next;
+ }
+ }
+
+ sym_op->auth.digest.data = rte_pktmbuf_mtod_offset(buf,
+ uint8_t *, offset);
+ sym_op->auth.digest.phys_addr =
+ rte_pktmbuf_mtophys_offset(buf, offset);
+ sym_op->auth.digest.length = options->auth_digest_sz;
+ sym_op->auth.aad.phys_addr = test_vector->aad.phys_addr;
+ sym_op->auth.aad.data = test_vector->aad.data;
+ sym_op->auth.aad.length = options->auth_aad_sz;
+ }
+
+ if (options->auth_algo == RTE_CRYPTO_AUTH_SNOW3G_UIA2 ||
+ options->auth_algo == RTE_CRYPTO_AUTH_KASUMI_F9 ||
+ options->auth_algo == RTE_CRYPTO_AUTH_ZUC_EIA3)
+ sym_op->auth.data.length = options->test_buffer_size << 3;
+ else
+ sym_op->auth.data.length = options->test_buffer_size;
+
+ sym_op->auth.data.offset = 0;
+ }
+
+ return 0;
+}
+
+static int
+cperf_set_ops_aead(struct rte_crypto_op **ops,
+ struct rte_mbuf **bufs_in, struct rte_mbuf **bufs_out,
+ uint16_t nb_ops, struct rte_cryptodev_sym_session *sess,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector)
+{
+ uint16_t i;
+
+ for (i = 0; i < nb_ops; i++) {
+ struct rte_crypto_sym_op *sym_op = ops[i]->sym;
+
+ rte_crypto_op_attach_sym_session(ops[i], sess);
+
+ sym_op->m_src = bufs_in[i];
+ sym_op->m_dst = bufs_out[i];
+
+ /* cipher parameters */
+ sym_op->cipher.iv.data = test_vector->iv.data;
+ sym_op->cipher.iv.phys_addr = test_vector->iv.phys_addr;
+ sym_op->cipher.iv.length = test_vector->iv.length;
+
+ sym_op->cipher.data.length = options->test_buffer_size;
+ sym_op->cipher.data.offset =
+ RTE_ALIGN_CEIL(options->auth_aad_sz, 16);
+
+ sym_op->auth.aad.data = rte_pktmbuf_mtod(bufs_in[i], uint8_t *);
+ sym_op->auth.aad.phys_addr = rte_pktmbuf_mtophys(bufs_in[i]);
+ sym_op->auth.aad.length = options->auth_aad_sz;
+
+ /* authentication parameters */
+ if (options->auth_op == RTE_CRYPTO_AUTH_OP_VERIFY) {
+ sym_op->auth.digest.data = test_vector->digest.data;
+ sym_op->auth.digest.phys_addr =
+ test_vector->digest.phys_addr;
+ sym_op->auth.digest.length = options->auth_digest_sz;
+ } else {
+
+ uint32_t offset = sym_op->cipher.data.length +
+ sym_op->cipher.data.offset;
+ struct rte_mbuf *buf, *tbuf;
+
+ if (options->out_of_place) {
+ buf = bufs_out[i];
+ } else {
+ buf = bufs_in[i];
+
+ tbuf = buf;
+ while ((tbuf->next != NULL) &&
+ (offset >= tbuf->data_len)) {
+ offset -= tbuf->data_len;
+ tbuf = tbuf->next;
+ }
+ }
+
+ sym_op->auth.digest.data = rte_pktmbuf_mtod_offset(buf,
+ uint8_t *, offset);
+ sym_op->auth.digest.phys_addr =
+ rte_pktmbuf_mtophys_offset(buf, offset);
+
+ sym_op->auth.digest.length = options->auth_digest_sz;
+ }
+
+ sym_op->auth.data.length = options->test_buffer_size;
+ sym_op->auth.data.offset = options->auth_aad_sz;
+ }
+
+ return 0;
+}
+
+static struct rte_cryptodev_sym_session *
+cperf_create_session(uint8_t dev_id,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector)
+{
+ struct rte_crypto_sym_xform cipher_xform;
+ struct rte_crypto_sym_xform auth_xform;
+ struct rte_cryptodev_sym_session *sess = NULL;
+
+ /*
+ * cipher only
+ */
+ if (options->op_type == CPERF_CIPHER_ONLY) {
+ cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cipher_xform.next = NULL;
+ cipher_xform.cipher.algo = options->cipher_algo;
+ cipher_xform.cipher.op = options->cipher_op;
+
+ /* cipher different than null */
+ if (options->cipher_algo != RTE_CRYPTO_CIPHER_NULL) {
+ cipher_xform.cipher.key.data =
+ test_vector->cipher_key.data;
+ cipher_xform.cipher.key.length =
+ test_vector->cipher_key.length;
+ } else {
+ cipher_xform.cipher.key.data = NULL;
+ cipher_xform.cipher.key.length = 0;
+ }
+ /* create crypto session */
+ sess = rte_cryptodev_sym_session_create(dev_id, &cipher_xform);
+ /*
+ * auth only
+ */
+ } else if (options->op_type == CPERF_AUTH_ONLY) {
+ auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ auth_xform.next = NULL;
+ auth_xform.auth.algo = options->auth_algo;
+ auth_xform.auth.op = options->auth_op;
+
+ /* auth different than null */
+ if (options->auth_algo != RTE_CRYPTO_AUTH_NULL) {
+ auth_xform.auth.digest_length =
+ options->auth_digest_sz;
+ auth_xform.auth.add_auth_data_length =
+ options->auth_aad_sz;
+ auth_xform.auth.key.length =
+ test_vector->auth_key.length;
+ auth_xform.auth.key.data = test_vector->auth_key.data;
+ } else {
+ auth_xform.auth.digest_length = 0;
+ auth_xform.auth.add_auth_data_length = 0;
+ auth_xform.auth.key.length = 0;
+ auth_xform.auth.key.data = NULL;
+ }
+ /* create crypto session */
+ sess = rte_cryptodev_sym_session_create(dev_id, &auth_xform);
+ /*
+ * cipher and auth
+ */
+ } else if (options->op_type == CPERF_CIPHER_THEN_AUTH
+ || options->op_type == CPERF_AUTH_THEN_CIPHER
+ || options->op_type == CPERF_AEAD) {
+
+ /*
+ * cipher
+ */
+ cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cipher_xform.next = NULL;
+ cipher_xform.cipher.algo = options->cipher_algo;
+ cipher_xform.cipher.op = options->cipher_op;
+
+ /* cipher different than null */
+ if (options->cipher_algo != RTE_CRYPTO_CIPHER_NULL) {
+ cipher_xform.cipher.key.data =
+ test_vector->cipher_key.data;
+ cipher_xform.cipher.key.length =
+ test_vector->cipher_key.length;
+ } else {
+ cipher_xform.cipher.key.data = NULL;
+ cipher_xform.cipher.key.length = 0;
+ }
+
+ /*
+ * auth
+ */
+ auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ auth_xform.next = NULL;
+ auth_xform.auth.algo = options->auth_algo;
+ auth_xform.auth.op = options->auth_op;
+
+ /* auth different than null */
+ if (options->auth_algo != RTE_CRYPTO_AUTH_NULL) {
+ auth_xform.auth.digest_length = options->auth_digest_sz;
+ auth_xform.auth.add_auth_data_length =
+ options->auth_aad_sz;
+ /* auth options for aes gcm */
+ if (options->cipher_algo == RTE_CRYPTO_CIPHER_AES_GCM &&
+ options->auth_algo == RTE_CRYPTO_AUTH_AES_GCM) {
+ auth_xform.auth.key.length = 0;
+ auth_xform.auth.key.data = NULL;
+ } else { /* auth options for others */
+ auth_xform.auth.key.length =
+ test_vector->auth_key.length;
+ auth_xform.auth.key.data =
+ test_vector->auth_key.data;
+ }
+ } else {
+ auth_xform.auth.digest_length = 0;
+ auth_xform.auth.add_auth_data_length = 0;
+ auth_xform.auth.key.length = 0;
+ auth_xform.auth.key.data = NULL;
+ }
+
+ /* create crypto session for aes gcm */
+ if (options->cipher_algo == RTE_CRYPTO_CIPHER_AES_GCM) {
+ if (options->cipher_op ==
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT) {
+ cipher_xform.next = &auth_xform;
+ /* create crypto session */
+ sess = rte_cryptodev_sym_session_create(dev_id,
+ &cipher_xform);
+ } else { /* decrypt */
+ auth_xform.next = &cipher_xform;
+ /* create crypto session */
+ sess = rte_cryptodev_sym_session_create(dev_id,
+ &auth_xform);
+ }
+ } else { /* create crypto session for other */
+ /* cipher then auth */
+ if (options->op_type == CPERF_CIPHER_THEN_AUTH) {
+ cipher_xform.next = &auth_xform;
+ /* create crypto session */
+ sess = rte_cryptodev_sym_session_create(dev_id,
+ &cipher_xform);
+ } else { /* auth then cipher */
+ auth_xform.next = &cipher_xform;
+ /* create crypto session */
+ sess = rte_cryptodev_sym_session_create(dev_id,
+ &auth_xform);
+ }
+ }
+ }
+ return sess;
+}
+
+int
+cperf_get_op_functions(const struct cperf_options *options,
+ struct cperf_op_fns *op_fns)
+{
+ memset(op_fns, 0, sizeof(struct cperf_op_fns));
+
+ op_fns->sess_create = cperf_create_session;
+
+ if (options->op_type == CPERF_AEAD
+ || options->op_type == CPERF_AUTH_THEN_CIPHER
+ || options->op_type == CPERF_CIPHER_THEN_AUTH) {
+ if (options->cipher_algo == RTE_CRYPTO_CIPHER_AES_GCM &&
+ options->auth_algo == RTE_CRYPTO_AUTH_AES_GCM)
+ op_fns->populate_ops = cperf_set_ops_aead;
+ else
+ op_fns->populate_ops = cperf_set_ops_cipher_auth;
+ return 0;
+ }
+ if (options->op_type == CPERF_AUTH_ONLY) {
+ if (options->auth_algo == RTE_CRYPTO_AUTH_NULL)
+ op_fns->populate_ops = cperf_set_ops_null_auth;
+ else
+ op_fns->populate_ops = cperf_set_ops_auth;
+ return 0;
+ }
+ if (options->op_type == CPERF_CIPHER_ONLY) {
+ if (options->cipher_algo == RTE_CRYPTO_CIPHER_NULL)
+ op_fns->populate_ops = cperf_set_ops_null_cipher;
+ else
+ op_fns->populate_ops = cperf_set_ops_cipher;
+ return 0;
+ }
+
+ return -1;
+}
diff --git a/src/seastar/dpdk/app/test-crypto-perf/cperf_ops.h b/src/seastar/dpdk/app/test-crypto-perf/cperf_ops.h
new file mode 100644
index 00000000..1b748daf
--- /dev/null
+++ b/src/seastar/dpdk/app/test-crypto-perf/cperf_ops.h
@@ -0,0 +1,62 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016-2017 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _CPERF_OPS_
+#define _CPERF_OPS_
+
+#include <rte_crypto.h>
+
+#include "cperf.h"
+#include "cperf_options.h"
+#include "cperf_test_vectors.h"
+
+
+typedef struct rte_cryptodev_sym_session *(*cperf_sessions_create_t)(
+ uint8_t dev_id, const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector);
+
+typedef int (*cperf_populate_ops_t)(struct rte_crypto_op **ops,
+ struct rte_mbuf **bufs_in, struct rte_mbuf **bufs_out,
+ uint16_t nb_ops, struct rte_cryptodev_sym_session *sess,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector);
+
+struct cperf_op_fns {
+ cperf_sessions_create_t sess_create;
+ cperf_populate_ops_t populate_ops;
+};
+
+int
+cperf_get_op_functions(const struct cperf_options *options,
+ struct cperf_op_fns *op_fns);
+
+#endif /* _CPERF_OPS_ */
diff --git a/src/seastar/dpdk/app/test-crypto-perf/cperf_options.h b/src/seastar/dpdk/app/test-crypto-perf/cperf_options.h
new file mode 100644
index 00000000..b928c584
--- /dev/null
+++ b/src/seastar/dpdk/app/test-crypto-perf/cperf_options.h
@@ -0,0 +1,115 @@
+
+#ifndef _CPERF_OPTIONS_
+#define _CPERF_OPTIONS_
+
+#include <rte_crypto.h>
+
+#define CPERF_PTEST_TYPE ("ptest")
+#define CPERF_SILENT ("silent")
+
+#define CPERF_POOL_SIZE ("pool-sz")
+#define CPERF_TOTAL_OPS ("total-ops")
+#define CPERF_BURST_SIZE ("burst-sz")
+#define CPERF_BUFFER_SIZE ("buffer-sz")
+#define CPERF_SEGMENTS_NB ("segments-nb")
+
+#define CPERF_DEVTYPE ("devtype")
+#define CPERF_OPTYPE ("optype")
+#define CPERF_SESSIONLESS ("sessionless")
+#define CPERF_OUT_OF_PLACE ("out-of-place")
+#define CPERF_TEST_FILE ("test-file")
+#define CPERF_TEST_NAME ("test-name")
+
+#define CPERF_CIPHER_ALGO ("cipher-algo")
+#define CPERF_CIPHER_OP ("cipher-op")
+#define CPERF_CIPHER_KEY_SZ ("cipher-key-sz")
+#define CPERF_CIPHER_IV_SZ ("cipher-iv-sz")
+
+#define CPERF_AUTH_ALGO ("auth-algo")
+#define CPERF_AUTH_OP ("auth-op")
+#define CPERF_AUTH_KEY_SZ ("auth-key-sz")
+#define CPERF_AUTH_DIGEST_SZ ("auth-digest-sz")
+#define CPERF_AUTH_AAD_SZ ("auth-aad-sz")
+#define CPERF_CSV ("csv-friendly")
+
+#define MAX_LIST 32
+
+enum cperf_perf_test_type {
+ CPERF_TEST_TYPE_THROUGHPUT,
+ CPERF_TEST_TYPE_LATENCY,
+ CPERF_TEST_TYPE_VERIFY
+};
+
+
+extern const char *cperf_test_type_strs[];
+
+enum cperf_op_type {
+ CPERF_CIPHER_ONLY = 1,
+ CPERF_AUTH_ONLY,
+ CPERF_CIPHER_THEN_AUTH,
+ CPERF_AUTH_THEN_CIPHER,
+ CPERF_AEAD
+};
+
+extern const char *cperf_op_type_strs[];
+
+struct cperf_options {
+ enum cperf_perf_test_type test;
+
+ uint32_t pool_sz;
+ uint32_t total_ops;
+ uint32_t segments_nb;
+ uint32_t test_buffer_size;
+
+ uint32_t sessionless:1;
+ uint32_t out_of_place:1;
+ uint32_t silent:1;
+ uint32_t csv:1;
+
+ enum rte_crypto_cipher_algorithm cipher_algo;
+ enum rte_crypto_cipher_operation cipher_op;
+
+ uint16_t cipher_key_sz;
+ uint16_t cipher_iv_sz;
+
+ enum rte_crypto_auth_algorithm auth_algo;
+ enum rte_crypto_auth_operation auth_op;
+
+ uint16_t auth_key_sz;
+ uint16_t auth_digest_sz;
+ uint16_t auth_aad_sz;
+
+ char device_type[RTE_CRYPTODEV_NAME_LEN];
+ enum cperf_op_type op_type;
+
+ char *test_file;
+ char *test_name;
+
+ uint32_t buffer_size_list[MAX_LIST];
+ uint8_t buffer_size_count;
+ uint32_t max_buffer_size;
+ uint32_t min_buffer_size;
+ uint32_t inc_buffer_size;
+
+ uint32_t burst_size_list[MAX_LIST];
+ uint8_t burst_size_count;
+ uint32_t max_burst_size;
+ uint32_t min_burst_size;
+ uint32_t inc_burst_size;
+
+};
+
+void
+cperf_options_default(struct cperf_options *options);
+
+int
+cperf_options_parse(struct cperf_options *options,
+ int argc, char **argv);
+
+int
+cperf_options_check(struct cperf_options *options);
+
+void
+cperf_options_dump(struct cperf_options *options);
+
+#endif
diff --git a/src/seastar/dpdk/app/test-crypto-perf/cperf_options_parsing.c b/src/seastar/dpdk/app/test-crypto-perf/cperf_options_parsing.c
new file mode 100644
index 00000000..d172671f
--- /dev/null
+++ b/src/seastar/dpdk/app/test-crypto-perf/cperf_options_parsing.c
@@ -0,0 +1,934 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016-2017 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <getopt.h>
+#include <unistd.h>
+
+#include <rte_cryptodev.h>
+#include <rte_malloc.h>
+
+#include "cperf_options.h"
+
+#define AES_BLOCK_SIZE 16
+#define DES_BLOCK_SIZE 8
+
+struct name_id_map {
+ const char *name;
+ uint32_t id;
+};
+
+static int
+get_str_key_id_mapping(struct name_id_map *map, unsigned int map_len,
+ const char *str_key)
+{
+ unsigned int i;
+
+ for (i = 0; i < map_len; i++) {
+
+ if (strcmp(str_key, map[i].name) == 0)
+ return map[i].id;
+ }
+
+ return -1;
+}
+
+static int
+parse_cperf_test_type(struct cperf_options *opts, const char *arg)
+{
+ struct name_id_map cperftest_namemap[] = {
+ {
+ cperf_test_type_strs[CPERF_TEST_TYPE_THROUGHPUT],
+ CPERF_TEST_TYPE_THROUGHPUT
+ },
+ {
+ cperf_test_type_strs[CPERF_TEST_TYPE_VERIFY],
+ CPERF_TEST_TYPE_VERIFY
+ },
+ {
+ cperf_test_type_strs[CPERF_TEST_TYPE_LATENCY],
+ CPERF_TEST_TYPE_LATENCY
+ }
+ };
+
+ int id = get_str_key_id_mapping(
+ (struct name_id_map *)cperftest_namemap,
+ RTE_DIM(cperftest_namemap), arg);
+ if (id < 0) {
+ RTE_LOG(ERR, USER1, "failed to parse test type");
+ return -1;
+ }
+
+ opts->test = (enum cperf_perf_test_type)id;
+
+ return 0;
+}
+
+static int
+parse_uint32_t(uint32_t *value, const char *arg)
+{
+ char *end = NULL;
+ unsigned long n = strtoul(arg, &end, 10);
+
+ if ((optarg[0] == '\0') || (end == NULL) || (*end != '\0'))
+ return -1;
+
+ if (n > UINT32_MAX)
+ return -ERANGE;
+
+ *value = (uint32_t) n;
+
+ return 0;
+}
+
+static int
+parse_uint16_t(uint16_t *value, const char *arg)
+{
+ uint32_t val = 0;
+ int ret = parse_uint32_t(&val, arg);
+
+ if (ret < 0)
+ return ret;
+
+ if (val > UINT16_MAX)
+ return -ERANGE;
+
+ *value = (uint16_t) val;
+
+ return 0;
+}
+
+static int
+parse_range(const char *arg, uint32_t *min, uint32_t *max, uint32_t *inc)
+{
+ char *token;
+ uint32_t number;
+
+ char *copy_arg = strdup(arg);
+
+ if (copy_arg == NULL)
+ return -1;
+
+ token = strtok(copy_arg, ":");
+
+ /* Parse minimum value */
+ if (token != NULL) {
+ number = strtoul(token, NULL, 10);
+
+ if (errno == EINVAL || errno == ERANGE ||
+ number == 0)
+ goto err_range;
+
+ *min = number;
+ } else
+ goto err_range;
+
+ token = strtok(NULL, ":");
+
+ /* Parse increment value */
+ if (token != NULL) {
+ number = strtoul(token, NULL, 10);
+
+ if (errno == EINVAL || errno == ERANGE ||
+ number == 0)
+ goto err_range;
+
+ *inc = number;
+ } else
+ goto err_range;
+
+ token = strtok(NULL, ":");
+
+ /* Parse maximum value */
+ if (token != NULL) {
+ number = strtoul(token, NULL, 10);
+
+ if (errno == EINVAL || errno == ERANGE ||
+ number == 0 ||
+ number < *min)
+ goto err_range;
+
+ *max = number;
+ } else
+ goto err_range;
+
+ if (strtok(NULL, ":") != NULL)
+ goto err_range;
+
+ free(copy_arg);
+ return 0;
+
+err_range:
+ free(copy_arg);
+ return -1;
+}
+
+static int
+parse_list(const char *arg, uint32_t *list, uint32_t *min, uint32_t *max)
+{
+ char *token;
+ uint32_t number;
+ uint8_t count = 0;
+
+ char *copy_arg = strdup(arg);
+
+ if (copy_arg == NULL)
+ return -1;
+
+ token = strtok(copy_arg, ",");
+
+ /* Parse first value */
+ if (token != NULL) {
+ number = strtoul(token, NULL, 10);
+
+ if (errno == EINVAL || errno == ERANGE ||
+ number == 0)
+ goto err_list;
+
+ list[count++] = number;
+ *min = number;
+ *max = number;
+ } else
+ goto err_list;
+
+ token = strtok(NULL, ",");
+
+ while (token != NULL) {
+ if (count == MAX_LIST) {
+ RTE_LOG(WARNING, USER1, "Using only the first %u sizes\n",
+ MAX_LIST);
+ break;
+ }
+
+ number = strtoul(token, NULL, 10);
+
+ if (errno == EINVAL || errno == ERANGE ||
+ number == 0)
+ goto err_list;
+
+ list[count++] = number;
+
+ if (number < *min)
+ *min = number;
+ if (number > *max)
+ *max = number;
+
+ token = strtok(NULL, ",");
+ }
+
+ free(copy_arg);
+ return count;
+
+err_list:
+ free(copy_arg);
+ return -1;
+}
+
+static int
+parse_total_ops(struct cperf_options *opts, const char *arg)
+{
+ int ret = parse_uint32_t(&opts->total_ops, arg);
+
+ if (ret)
+ RTE_LOG(ERR, USER1, "failed to parse total operations count\n");
+
+ if (opts->total_ops == 0) {
+ RTE_LOG(ERR, USER1,
+ "invalid total operations count number specified\n");
+ return -1;
+ }
+
+ return ret;
+}
+
+static int
+parse_pool_sz(struct cperf_options *opts, const char *arg)
+{
+ int ret = parse_uint32_t(&opts->pool_sz, arg);
+
+ if (ret)
+ RTE_LOG(ERR, USER1, "failed to parse pool size");
+ return ret;
+}
+
+static int
+parse_burst_sz(struct cperf_options *opts, const char *arg)
+{
+ int ret;
+
+ /* Try parsing the argument as a range, if it fails, parse it as a list */
+ if (parse_range(arg, &opts->min_burst_size, &opts->max_burst_size,
+ &opts->inc_burst_size) < 0) {
+ ret = parse_list(arg, opts->burst_size_list,
+ &opts->min_burst_size,
+ &opts->max_burst_size);
+ if (ret < 0) {
+ RTE_LOG(ERR, USER1, "failed to parse burst size/s\n");
+ return -1;
+ }
+ opts->burst_size_count = ret;
+ }
+
+ return 0;
+}
+
+static int
+parse_buffer_sz(struct cperf_options *opts, const char *arg)
+{
+ int ret;
+
+ /* Try parsing the argument as a range, if it fails, parse it as a list */
+ if (parse_range(arg, &opts->min_buffer_size, &opts->max_buffer_size,
+ &opts->inc_buffer_size) < 0) {
+ ret = parse_list(arg, opts->buffer_size_list,
+ &opts->min_buffer_size,
+ &opts->max_buffer_size);
+ if (ret < 0) {
+ RTE_LOG(ERR, USER1, "failed to parse burst size/s\n");
+ return -1;
+ }
+ opts->buffer_size_count = ret;
+ }
+
+ return 0;
+}
+
+static int
+parse_segments_nb(struct cperf_options *opts, const char *arg)
+{
+ int ret = parse_uint32_t(&opts->segments_nb, arg);
+
+ if (ret) {
+ RTE_LOG(ERR, USER1, "failed to parse segments number\n");
+ return -1;
+ }
+
+ if ((opts->segments_nb == 0) || (opts->segments_nb > 255)) {
+ RTE_LOG(ERR, USER1, "invalid segments number specified\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+parse_device_type(struct cperf_options *opts, const char *arg)
+{
+ if (strlen(arg) > (sizeof(opts->device_type) - 1))
+ return -1;
+
+ strncpy(opts->device_type, arg, sizeof(opts->device_type) - 1);
+ *(opts->device_type + sizeof(opts->device_type) - 1) = '\0';
+
+ return 0;
+}
+
+static int
+parse_op_type(struct cperf_options *opts, const char *arg)
+{
+ struct name_id_map optype_namemap[] = {
+ {
+ cperf_op_type_strs[CPERF_CIPHER_ONLY],
+ CPERF_CIPHER_ONLY
+ },
+ {
+ cperf_op_type_strs[CPERF_AUTH_ONLY],
+ CPERF_AUTH_ONLY
+ },
+ {
+ cperf_op_type_strs[CPERF_CIPHER_THEN_AUTH],
+ CPERF_CIPHER_THEN_AUTH
+ },
+ {
+ cperf_op_type_strs[CPERF_AUTH_THEN_CIPHER],
+ CPERF_AUTH_THEN_CIPHER
+ },
+ {
+ cperf_op_type_strs[CPERF_AEAD],
+ CPERF_AEAD
+ }
+ };
+
+ int id = get_str_key_id_mapping(optype_namemap,
+ RTE_DIM(optype_namemap), arg);
+ if (id < 0) {
+ RTE_LOG(ERR, USER1, "invalid opt type specified\n");
+ return -1;
+ }
+
+ opts->op_type = (enum cperf_op_type)id;
+
+ return 0;
+}
+
+static int
+parse_sessionless(struct cperf_options *opts,
+ const char *arg __rte_unused)
+{
+ opts->sessionless = 1;
+ return 0;
+}
+
+static int
+parse_out_of_place(struct cperf_options *opts,
+ const char *arg __rte_unused)
+{
+ opts->out_of_place = 1;
+ return 0;
+}
+
+static int
+parse_test_file(struct cperf_options *opts,
+ const char *arg)
+{
+ opts->test_file = strdup(arg);
+ if (access(opts->test_file, F_OK) != -1)
+ return 0;
+ RTE_LOG(ERR, USER1, "Test vector file doesn't exist\n");
+
+ return -1;
+}
+
+static int
+parse_test_name(struct cperf_options *opts,
+ const char *arg)
+{
+ char *test_name = (char *) rte_zmalloc(NULL,
+ sizeof(char) * (strlen(arg) + 3), 0);
+ snprintf(test_name, strlen(arg) + 3, "[%s]", arg);
+ opts->test_name = test_name;
+
+ return 0;
+}
+
+static int
+parse_silent(struct cperf_options *opts,
+ const char *arg __rte_unused)
+{
+ opts->silent = 1;
+
+ return 0;
+}
+
+static int
+parse_cipher_algo(struct cperf_options *opts, const char *arg)
+{
+
+ enum rte_crypto_cipher_algorithm cipher_algo;
+
+ if (rte_cryptodev_get_cipher_algo_enum(&cipher_algo, arg) < 0) {
+ RTE_LOG(ERR, USER1, "Invalid cipher algorithm specified\n");
+ return -1;
+ }
+
+ opts->cipher_algo = cipher_algo;
+
+ return 0;
+}
+
+static int
+parse_cipher_op(struct cperf_options *opts, const char *arg)
+{
+ struct name_id_map cipher_op_namemap[] = {
+ {
+ rte_crypto_cipher_operation_strings
+ [RTE_CRYPTO_CIPHER_OP_ENCRYPT],
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT },
+ {
+ rte_crypto_cipher_operation_strings
+ [RTE_CRYPTO_CIPHER_OP_DECRYPT],
+ RTE_CRYPTO_CIPHER_OP_DECRYPT
+ }
+ };
+
+ int id = get_str_key_id_mapping(cipher_op_namemap,
+ RTE_DIM(cipher_op_namemap), arg);
+ if (id < 0) {
+ RTE_LOG(ERR, USER1, "Invalid cipher operation specified\n");
+ return -1;
+ }
+
+ opts->cipher_op = (enum rte_crypto_cipher_operation)id;
+
+ return 0;
+}
+
+static int
+parse_cipher_key_sz(struct cperf_options *opts, const char *arg)
+{
+ return parse_uint16_t(&opts->cipher_key_sz, arg);
+}
+
+static int
+parse_cipher_iv_sz(struct cperf_options *opts, const char *arg)
+{
+ return parse_uint16_t(&opts->cipher_iv_sz, arg);
+}
+
+static int
+parse_auth_algo(struct cperf_options *opts, const char *arg)
+{
+ enum rte_crypto_auth_algorithm auth_algo;
+
+ if (rte_cryptodev_get_auth_algo_enum(&auth_algo, arg) < 0) {
+ RTE_LOG(ERR, USER1, "Invalid authentication algorithm specified\n");
+ return -1;
+ }
+
+ opts->auth_algo = auth_algo;
+
+ return 0;
+}
+
+static int
+parse_auth_op(struct cperf_options *opts, const char *arg)
+{
+ struct name_id_map auth_op_namemap[] = {
+ {
+ rte_crypto_auth_operation_strings
+ [RTE_CRYPTO_AUTH_OP_GENERATE],
+ RTE_CRYPTO_AUTH_OP_GENERATE },
+ {
+ rte_crypto_auth_operation_strings
+ [RTE_CRYPTO_AUTH_OP_VERIFY],
+ RTE_CRYPTO_AUTH_OP_VERIFY
+ }
+ };
+
+ int id = get_str_key_id_mapping(auth_op_namemap,
+ RTE_DIM(auth_op_namemap), arg);
+ if (id < 0) {
+ RTE_LOG(ERR, USER1, "invalid authentication operation specified"
+ "\n");
+ return -1;
+ }
+
+ opts->auth_op = (enum rte_crypto_auth_operation)id;
+
+ return 0;
+}
+
+static int
+parse_auth_key_sz(struct cperf_options *opts, const char *arg)
+{
+ return parse_uint16_t(&opts->auth_key_sz, arg);
+}
+
+static int
+parse_auth_digest_sz(struct cperf_options *opts, const char *arg)
+{
+ return parse_uint16_t(&opts->auth_digest_sz, arg);
+}
+
+static int
+parse_auth_aad_sz(struct cperf_options *opts, const char *arg)
+{
+ return parse_uint16_t(&opts->auth_aad_sz, arg);
+}
+
+static int
+parse_csv_friendly(struct cperf_options *opts, const char *arg __rte_unused)
+{
+ opts->csv = 1;
+ opts->silent = 1;
+ return 0;
+}
+
+typedef int (*option_parser_t)(struct cperf_options *opts,
+ const char *arg);
+
+struct long_opt_parser {
+ const char *lgopt_name;
+ option_parser_t parser_fn;
+
+};
+
+static struct option lgopts[] = {
+
+ { CPERF_PTEST_TYPE, required_argument, 0, 0 },
+
+ { CPERF_POOL_SIZE, required_argument, 0, 0 },
+ { CPERF_TOTAL_OPS, required_argument, 0, 0 },
+ { CPERF_BURST_SIZE, required_argument, 0, 0 },
+ { CPERF_BUFFER_SIZE, required_argument, 0, 0 },
+ { CPERF_SEGMENTS_NB, required_argument, 0, 0 },
+
+ { CPERF_DEVTYPE, required_argument, 0, 0 },
+ { CPERF_OPTYPE, required_argument, 0, 0 },
+
+ { CPERF_SILENT, no_argument, 0, 0 },
+ { CPERF_SESSIONLESS, no_argument, 0, 0 },
+ { CPERF_OUT_OF_PLACE, no_argument, 0, 0 },
+ { CPERF_TEST_FILE, required_argument, 0, 0 },
+ { CPERF_TEST_NAME, required_argument, 0, 0 },
+
+ { CPERF_CIPHER_ALGO, required_argument, 0, 0 },
+ { CPERF_CIPHER_OP, required_argument, 0, 0 },
+
+ { CPERF_CIPHER_KEY_SZ, required_argument, 0, 0 },
+ { CPERF_CIPHER_IV_SZ, required_argument, 0, 0 },
+
+ { CPERF_AUTH_ALGO, required_argument, 0, 0 },
+ { CPERF_AUTH_OP, required_argument, 0, 0 },
+
+ { CPERF_AUTH_KEY_SZ, required_argument, 0, 0 },
+ { CPERF_AUTH_DIGEST_SZ, required_argument, 0, 0 },
+ { CPERF_AUTH_AAD_SZ, required_argument, 0, 0 },
+ { CPERF_CSV, no_argument, 0, 0},
+
+ { NULL, 0, 0, 0 }
+};
+
+void
+cperf_options_default(struct cperf_options *opts)
+{
+ opts->test = CPERF_TEST_TYPE_THROUGHPUT;
+
+ opts->pool_sz = 8192;
+ opts->total_ops = 10000000;
+
+ opts->buffer_size_list[0] = 64;
+ opts->buffer_size_count = 1;
+ opts->max_buffer_size = 64;
+ opts->min_buffer_size = 64;
+ opts->inc_buffer_size = 0;
+
+ opts->burst_size_list[0] = 32;
+ opts->burst_size_count = 1;
+ opts->max_burst_size = 32;
+ opts->min_burst_size = 32;
+ opts->inc_burst_size = 0;
+
+ opts->segments_nb = 1;
+
+ strncpy(opts->device_type, "crypto_aesni_mb",
+ sizeof(opts->device_type));
+
+ opts->op_type = CPERF_CIPHER_THEN_AUTH;
+
+ opts->silent = 0;
+ opts->test_file = NULL;
+ opts->test_name = NULL;
+ opts->sessionless = 0;
+ opts->out_of_place = 0;
+ opts->csv = 0;
+
+ opts->cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC;
+ opts->cipher_op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
+ opts->cipher_key_sz = 16;
+ opts->cipher_iv_sz = 16;
+
+ opts->auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC;
+ opts->auth_op = RTE_CRYPTO_AUTH_OP_GENERATE;
+
+ opts->auth_key_sz = 64;
+ opts->auth_digest_sz = 12;
+ opts->auth_aad_sz = 0;
+}
+
+static int
+cperf_opts_parse_long(int opt_idx, struct cperf_options *opts)
+{
+ struct long_opt_parser parsermap[] = {
+ { CPERF_PTEST_TYPE, parse_cperf_test_type },
+ { CPERF_SILENT, parse_silent },
+ { CPERF_POOL_SIZE, parse_pool_sz },
+ { CPERF_TOTAL_OPS, parse_total_ops },
+ { CPERF_BURST_SIZE, parse_burst_sz },
+ { CPERF_BUFFER_SIZE, parse_buffer_sz },
+ { CPERF_SEGMENTS_NB, parse_segments_nb },
+ { CPERF_DEVTYPE, parse_device_type },
+ { CPERF_OPTYPE, parse_op_type },
+ { CPERF_SESSIONLESS, parse_sessionless },
+ { CPERF_OUT_OF_PLACE, parse_out_of_place },
+ { CPERF_TEST_FILE, parse_test_file },
+ { CPERF_TEST_NAME, parse_test_name },
+ { CPERF_CIPHER_ALGO, parse_cipher_algo },
+ { CPERF_CIPHER_OP, parse_cipher_op },
+ { CPERF_CIPHER_KEY_SZ, parse_cipher_key_sz },
+ { CPERF_CIPHER_IV_SZ, parse_cipher_iv_sz },
+ { CPERF_AUTH_ALGO, parse_auth_algo },
+ { CPERF_AUTH_OP, parse_auth_op },
+ { CPERF_AUTH_KEY_SZ, parse_auth_key_sz },
+ { CPERF_AUTH_DIGEST_SZ, parse_auth_digest_sz },
+ { CPERF_AUTH_AAD_SZ, parse_auth_aad_sz },
+ { CPERF_CSV, parse_csv_friendly},
+ };
+ unsigned int i;
+
+ for (i = 0; i < RTE_DIM(parsermap); i++) {
+ if (strncmp(lgopts[opt_idx].name, parsermap[i].lgopt_name,
+ strlen(lgopts[opt_idx].name)) == 0)
+ return parsermap[i].parser_fn(opts, optarg);
+ }
+
+ return -EINVAL;
+}
+
+int
+cperf_options_parse(struct cperf_options *options, int argc, char **argv)
+{
+ int opt, retval, opt_idx;
+
+ while ((opt = getopt_long(argc, argv, "", lgopts, &opt_idx)) != EOF) {
+ switch (opt) {
+ /* long options */
+ case 0:
+
+ retval = cperf_opts_parse_long(opt_idx, options);
+ if (retval != 0)
+ return retval;
+
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+int
+cperf_options_check(struct cperf_options *options)
+{
+ uint32_t buffer_size, buffer_size_idx = 0;
+
+ if (options->segments_nb > options->min_buffer_size) {
+ RTE_LOG(ERR, USER1,
+ "Segments number greater than buffer size.\n");
+ return -EINVAL;
+ }
+
+ if (options->test == CPERF_TEST_TYPE_VERIFY &&
+ options->test_file == NULL) {
+ RTE_LOG(ERR, USER1, "Define path to the file with test"
+ " vectors.\n");
+ return -EINVAL;
+ }
+
+ if (options->test == CPERF_TEST_TYPE_VERIFY &&
+ options->op_type != CPERF_CIPHER_ONLY &&
+ options->test_name == NULL) {
+ RTE_LOG(ERR, USER1, "Define test name to get the correct digest"
+ " from the test vectors.\n");
+ return -EINVAL;
+ }
+
+ if (options->test_name != NULL && options->test_file == NULL) {
+ RTE_LOG(ERR, USER1, "Define path to the file with test"
+ " vectors.\n");
+ return -EINVAL;
+ }
+
+ if (options->auth_op == RTE_CRYPTO_AUTH_OP_VERIFY &&
+ options->test_file == NULL) {
+ RTE_LOG(ERR, USER1, "Define path to the file with test"
+ " vectors.\n");
+ return -EINVAL;
+ }
+
+ if (options->test == CPERF_TEST_TYPE_VERIFY &&
+ options->total_ops > options->pool_sz) {
+ RTE_LOG(ERR, USER1, "Total number of ops must be less than or"
+ " equal to the pool size.\n");
+ return -EINVAL;
+ }
+
+ if (options->test == CPERF_TEST_TYPE_VERIFY &&
+ (options->inc_buffer_size != 0 ||
+ options->buffer_size_count > 1)) {
+ RTE_LOG(ERR, USER1, "Only one buffer size is allowed when "
+ "using the verify test.\n");
+ return -EINVAL;
+ }
+
+ if (options->test == CPERF_TEST_TYPE_VERIFY &&
+ (options->inc_burst_size != 0 ||
+ options->burst_size_count > 1)) {
+ RTE_LOG(ERR, USER1, "Only one burst size is allowed when "
+ "using the verify test.\n");
+ return -EINVAL;
+ }
+
+ if (options->op_type == CPERF_CIPHER_THEN_AUTH) {
+ if (options->cipher_op != RTE_CRYPTO_CIPHER_OP_ENCRYPT &&
+ options->auth_op !=
+ RTE_CRYPTO_AUTH_OP_GENERATE) {
+ RTE_LOG(ERR, USER1, "Option cipher then auth must use"
+ " options: encrypt and generate.\n");
+ return -EINVAL;
+ }
+ } else if (options->op_type == CPERF_AUTH_THEN_CIPHER) {
+ if (options->cipher_op != RTE_CRYPTO_CIPHER_OP_DECRYPT &&
+ options->auth_op !=
+ RTE_CRYPTO_AUTH_OP_VERIFY) {
+ RTE_LOG(ERR, USER1, "Option auth then cipher must use"
+ " options: decrypt and verify.\n");
+ return -EINVAL;
+ }
+ } else if (options->op_type == CPERF_AEAD) {
+ if (!(options->cipher_op == RTE_CRYPTO_CIPHER_OP_ENCRYPT &&
+ options->auth_op ==
+ RTE_CRYPTO_AUTH_OP_GENERATE) &&
+ !(options->cipher_op ==
+ RTE_CRYPTO_CIPHER_OP_DECRYPT &&
+ options->auth_op ==
+ RTE_CRYPTO_AUTH_OP_VERIFY)) {
+ RTE_LOG(ERR, USER1, "Use together options: encrypt and"
+ " generate or decrypt and verify.\n");
+ return -EINVAL;
+ }
+ }
+
+ if (options->cipher_algo == RTE_CRYPTO_CIPHER_AES_GCM ||
+ options->cipher_algo == RTE_CRYPTO_CIPHER_AES_CCM ||
+ options->auth_algo == RTE_CRYPTO_AUTH_AES_GCM ||
+ options->auth_algo == RTE_CRYPTO_AUTH_AES_CCM ||
+ options->auth_algo == RTE_CRYPTO_AUTH_AES_GMAC) {
+ if (options->op_type != CPERF_AEAD) {
+ RTE_LOG(ERR, USER1, "Use --optype aead\n");
+ return -EINVAL;
+ }
+ }
+
+ if (options->cipher_algo == RTE_CRYPTO_CIPHER_AES_CBC ||
+ options->cipher_algo == RTE_CRYPTO_CIPHER_AES_ECB) {
+ if (options->inc_buffer_size != 0)
+ buffer_size = options->min_buffer_size;
+ else
+ buffer_size = options->buffer_size_list[0];
+
+ while (buffer_size <= options->max_buffer_size) {
+ if ((buffer_size % AES_BLOCK_SIZE) != 0) {
+ RTE_LOG(ERR, USER1, "Some of the buffer sizes are "
+ "not suitable for the algorithm selected\n");
+ return -EINVAL;
+ }
+
+ if (options->inc_buffer_size != 0)
+ buffer_size += options->inc_buffer_size;
+ else {
+ if (++buffer_size_idx == options->buffer_size_count)
+ break;
+ buffer_size = options->buffer_size_list[buffer_size_idx];
+ }
+
+ }
+ }
+
+ if (options->cipher_algo == RTE_CRYPTO_CIPHER_DES_CBC ||
+ options->cipher_algo == RTE_CRYPTO_CIPHER_3DES_CBC ||
+ options->cipher_algo == RTE_CRYPTO_CIPHER_3DES_ECB) {
+ for (buffer_size = options->min_buffer_size;
+ buffer_size < options->max_buffer_size;
+ buffer_size += options->inc_buffer_size) {
+ if ((buffer_size % DES_BLOCK_SIZE) != 0) {
+ RTE_LOG(ERR, USER1, "Some of the buffer sizes are "
+ "not suitable for the algorithm selected\n");
+ return -EINVAL;
+ }
+ }
+ }
+
+ return 0;
+}
+
+void
+cperf_options_dump(struct cperf_options *opts)
+{
+ uint8_t size_idx;
+
+ printf("# Crypto Performance Application Options:\n");
+ printf("#\n");
+ printf("# cperf test: %s\n", cperf_test_type_strs[opts->test]);
+ printf("#\n");
+ printf("# size of crypto op / mbuf pool: %u\n", opts->pool_sz);
+ printf("# total number of ops: %u\n", opts->total_ops);
+ if (opts->inc_buffer_size != 0) {
+ printf("# buffer size:\n");
+ printf("#\t min: %u\n", opts->min_buffer_size);
+ printf("#\t max: %u\n", opts->max_buffer_size);
+ printf("#\t inc: %u\n", opts->inc_buffer_size);
+ } else {
+ printf("# buffer sizes: ");
+ for (size_idx = 0; size_idx < opts->buffer_size_count; size_idx++)
+ printf("%u ", opts->buffer_size_list[size_idx]);
+ printf("\n");
+ }
+ if (opts->inc_burst_size != 0) {
+ printf("# burst size:\n");
+ printf("#\t min: %u\n", opts->min_burst_size);
+ printf("#\t max: %u\n", opts->max_burst_size);
+ printf("#\t inc: %u\n", opts->inc_burst_size);
+ } else {
+ printf("# burst sizes: ");
+ for (size_idx = 0; size_idx < opts->burst_size_count; size_idx++)
+ printf("%u ", opts->burst_size_list[size_idx]);
+ printf("\n");
+ }
+ printf("\n# segments per buffer: %u\n", opts->segments_nb);
+ printf("#\n");
+ printf("# cryptodev type: %s\n", opts->device_type);
+ printf("#\n");
+ printf("# crypto operation: %s\n", cperf_op_type_strs[opts->op_type]);
+ printf("# sessionless: %s\n", opts->sessionless ? "yes" : "no");
+ printf("# out of place: %s\n", opts->out_of_place ? "yes" : "no");
+
+ printf("#\n");
+
+ if (opts->op_type == CPERF_AUTH_ONLY ||
+ opts->op_type == CPERF_CIPHER_THEN_AUTH ||
+ opts->op_type == CPERF_AUTH_THEN_CIPHER ||
+ opts->op_type == CPERF_AEAD) {
+ printf("# auth algorithm: %s\n",
+ rte_crypto_auth_algorithm_strings[opts->auth_algo]);
+ printf("# auth operation: %s\n",
+ rte_crypto_auth_operation_strings[opts->auth_op]);
+ printf("# auth key size: %u\n", opts->auth_key_sz);
+ printf("# auth digest size: %u\n", opts->auth_digest_sz);
+ printf("# auth aad size: %u\n", opts->auth_aad_sz);
+ printf("#\n");
+ }
+
+ if (opts->op_type == CPERF_CIPHER_ONLY ||
+ opts->op_type == CPERF_CIPHER_THEN_AUTH ||
+ opts->op_type == CPERF_AUTH_THEN_CIPHER ||
+ opts->op_type == CPERF_AEAD) {
+ printf("# cipher algorithm: %s\n",
+ rte_crypto_cipher_algorithm_strings[opts->cipher_algo]);
+ printf("# cipher operation: %s\n",
+ rte_crypto_cipher_operation_strings[opts->cipher_op]);
+ printf("# cipher key size: %u\n", opts->cipher_key_sz);
+ printf("# cipher iv size: %u\n", opts->cipher_iv_sz);
+ printf("#\n");
+ }
+}
diff --git a/src/seastar/dpdk/app/test-crypto-perf/cperf_test_latency.c b/src/seastar/dpdk/app/test-crypto-perf/cperf_test_latency.c
new file mode 100644
index 00000000..e61ac972
--- /dev/null
+++ b/src/seastar/dpdk/app/test-crypto-perf/cperf_test_latency.c
@@ -0,0 +1,552 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016-2017 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rte_malloc.h>
+#include <rte_cycles.h>
+#include <rte_crypto.h>
+#include <rte_cryptodev.h>
+
+#include "cperf_test_latency.h"
+#include "cperf_ops.h"
+
+
+struct cperf_op_result {
+ uint64_t tsc_start;
+ uint64_t tsc_end;
+ enum rte_crypto_op_status status;
+};
+
+struct cperf_latency_ctx {
+ uint8_t dev_id;
+ uint16_t qp_id;
+ uint8_t lcore_id;
+
+ struct rte_mempool *pkt_mbuf_pool_in;
+ struct rte_mempool *pkt_mbuf_pool_out;
+ struct rte_mbuf **mbufs_in;
+ struct rte_mbuf **mbufs_out;
+
+ struct rte_mempool *crypto_op_pool;
+
+ struct rte_cryptodev_sym_session *sess;
+
+ cperf_populate_ops_t populate_ops;
+
+ const struct cperf_options *options;
+ const struct cperf_test_vector *test_vector;
+ struct cperf_op_result *res;
+};
+
+#define max(a, b) (a > b ? (uint64_t)a : (uint64_t)b)
+#define min(a, b) (a < b ? (uint64_t)a : (uint64_t)b)
+
+static void
+cperf_latency_test_free(struct cperf_latency_ctx *ctx, uint32_t mbuf_nb)
+{
+ uint32_t i;
+
+ if (ctx) {
+ if (ctx->sess)
+ rte_cryptodev_sym_session_free(ctx->dev_id, ctx->sess);
+
+ if (ctx->mbufs_in) {
+ for (i = 0; i < mbuf_nb; i++)
+ rte_pktmbuf_free(ctx->mbufs_in[i]);
+
+ rte_free(ctx->mbufs_in);
+ }
+
+ if (ctx->mbufs_out) {
+ for (i = 0; i < mbuf_nb; i++) {
+ if (ctx->mbufs_out[i] != NULL)
+ rte_pktmbuf_free(ctx->mbufs_out[i]);
+ }
+
+ rte_free(ctx->mbufs_out);
+ }
+
+ if (ctx->pkt_mbuf_pool_in)
+ rte_mempool_free(ctx->pkt_mbuf_pool_in);
+
+ if (ctx->pkt_mbuf_pool_out)
+ rte_mempool_free(ctx->pkt_mbuf_pool_out);
+
+ if (ctx->crypto_op_pool)
+ rte_mempool_free(ctx->crypto_op_pool);
+
+ rte_free(ctx->res);
+ rte_free(ctx);
+ }
+}
+
+static struct rte_mbuf *
+cperf_mbuf_create(struct rte_mempool *mempool,
+ uint32_t segments_nb,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector)
+{
+ struct rte_mbuf *mbuf;
+ uint32_t segment_sz = options->max_buffer_size / segments_nb;
+ uint32_t last_sz = options->max_buffer_size % segments_nb;
+ uint8_t *mbuf_data;
+ uint8_t *test_data =
+ (options->cipher_op == RTE_CRYPTO_CIPHER_OP_ENCRYPT) ?
+ test_vector->plaintext.data :
+ test_vector->ciphertext.data;
+
+ mbuf = rte_pktmbuf_alloc(mempool);
+ if (mbuf == NULL)
+ goto error;
+
+ mbuf_data = (uint8_t *)rte_pktmbuf_append(mbuf, segment_sz);
+ if (mbuf_data == NULL)
+ goto error;
+
+ memcpy(mbuf_data, test_data, segment_sz);
+ test_data += segment_sz;
+ segments_nb--;
+
+ while (segments_nb) {
+ struct rte_mbuf *m;
+
+ m = rte_pktmbuf_alloc(mempool);
+ if (m == NULL)
+ goto error;
+
+ rte_pktmbuf_chain(mbuf, m);
+
+ mbuf_data = (uint8_t *)rte_pktmbuf_append(mbuf, segment_sz);
+ if (mbuf_data == NULL)
+ goto error;
+
+ memcpy(mbuf_data, test_data, segment_sz);
+ test_data += segment_sz;
+ segments_nb--;
+ }
+
+ if (last_sz) {
+ mbuf_data = (uint8_t *)rte_pktmbuf_append(mbuf, last_sz);
+ if (mbuf_data == NULL)
+ goto error;
+
+ memcpy(mbuf_data, test_data, last_sz);
+ }
+
+ if (options->op_type != CPERF_CIPHER_ONLY) {
+ mbuf_data = (uint8_t *)rte_pktmbuf_append(mbuf,
+ options->auth_digest_sz);
+ if (mbuf_data == NULL)
+ goto error;
+ }
+
+ if (options->op_type == CPERF_AEAD) {
+ uint8_t *aead = (uint8_t *)rte_pktmbuf_prepend(mbuf,
+ RTE_ALIGN_CEIL(options->auth_aad_sz, 16));
+
+ if (aead == NULL)
+ goto error;
+
+ memcpy(aead, test_vector->aad.data, test_vector->aad.length);
+ }
+
+ return mbuf;
+error:
+ if (mbuf != NULL)
+ rte_pktmbuf_free(mbuf);
+
+ return NULL;
+}
+
+void *
+cperf_latency_test_constructor(uint8_t dev_id, uint16_t qp_id,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector,
+ const struct cperf_op_fns *op_fns)
+{
+ struct cperf_latency_ctx *ctx = NULL;
+ unsigned int mbuf_idx = 0;
+ char pool_name[32] = "";
+
+ ctx = rte_malloc(NULL, sizeof(struct cperf_latency_ctx), 0);
+ if (ctx == NULL)
+ goto err;
+
+ ctx->dev_id = dev_id;
+ ctx->qp_id = qp_id;
+
+ ctx->populate_ops = op_fns->populate_ops;
+ ctx->options = options;
+ ctx->test_vector = test_vector;
+
+ ctx->sess = op_fns->sess_create(dev_id, options, test_vector);
+ if (ctx->sess == NULL)
+ goto err;
+
+ snprintf(pool_name, sizeof(pool_name), "cperf_pool_in_cdev_%d",
+ dev_id);
+
+ ctx->pkt_mbuf_pool_in = rte_pktmbuf_pool_create(pool_name,
+ options->pool_sz * options->segments_nb, 0, 0,
+ RTE_PKTMBUF_HEADROOM +
+ RTE_CACHE_LINE_ROUNDUP(
+ (options->max_buffer_size / options->segments_nb) +
+ (options->max_buffer_size % options->segments_nb) +
+ options->auth_digest_sz),
+ rte_socket_id());
+
+ if (ctx->pkt_mbuf_pool_in == NULL)
+ goto err;
+
+ /* Generate mbufs_in with plaintext populated for test */
+ ctx->mbufs_in = rte_malloc(NULL,
+ (sizeof(struct rte_mbuf *) *
+ ctx->options->pool_sz), 0);
+
+ for (mbuf_idx = 0; mbuf_idx < options->pool_sz; mbuf_idx++) {
+ ctx->mbufs_in[mbuf_idx] = cperf_mbuf_create(
+ ctx->pkt_mbuf_pool_in, options->segments_nb,
+ options, test_vector);
+ if (ctx->mbufs_in[mbuf_idx] == NULL)
+ goto err;
+ }
+
+ if (options->out_of_place == 1) {
+
+ snprintf(pool_name, sizeof(pool_name),
+ "cperf_pool_out_cdev_%d",
+ dev_id);
+
+ ctx->pkt_mbuf_pool_out = rte_pktmbuf_pool_create(
+ pool_name, options->pool_sz, 0, 0,
+ RTE_PKTMBUF_HEADROOM +
+ RTE_CACHE_LINE_ROUNDUP(
+ options->max_buffer_size +
+ options->auth_digest_sz),
+ rte_socket_id());
+
+ if (ctx->pkt_mbuf_pool_out == NULL)
+ goto err;
+ }
+
+ ctx->mbufs_out = rte_malloc(NULL,
+ (sizeof(struct rte_mbuf *) *
+ ctx->options->pool_sz), 0);
+
+ for (mbuf_idx = 0; mbuf_idx < options->pool_sz; mbuf_idx++) {
+ if (options->out_of_place == 1) {
+ ctx->mbufs_out[mbuf_idx] = cperf_mbuf_create(
+ ctx->pkt_mbuf_pool_out, 1,
+ options, test_vector);
+ if (ctx->mbufs_out[mbuf_idx] == NULL)
+ goto err;
+ } else {
+ ctx->mbufs_out[mbuf_idx] = NULL;
+ }
+ }
+
+ snprintf(pool_name, sizeof(pool_name), "cperf_op_pool_cdev_%d",
+ dev_id);
+
+ ctx->crypto_op_pool = rte_crypto_op_pool_create(pool_name,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC, options->pool_sz, 0, 0,
+ rte_socket_id());
+ if (ctx->crypto_op_pool == NULL)
+ goto err;
+
+ ctx->res = rte_malloc(NULL, sizeof(struct cperf_op_result) *
+ ctx->options->total_ops, 0);
+
+ if (ctx->res == NULL)
+ goto err;
+
+ return ctx;
+err:
+ cperf_latency_test_free(ctx, mbuf_idx);
+
+ return NULL;
+}
+
+int
+cperf_latency_test_runner(void *arg)
+{
+ struct cperf_latency_ctx *ctx = arg;
+ struct cperf_op_result *pres;
+ uint16_t test_burst_size;
+ uint8_t burst_size_idx = 0;
+
+ static int only_once;
+
+ if (ctx == NULL)
+ return 0;
+
+ struct rte_crypto_op *ops[ctx->options->max_burst_size];
+ struct rte_crypto_op *ops_processed[ctx->options->max_burst_size];
+ uint64_t i;
+
+ uint32_t lcore = rte_lcore_id();
+
+#ifdef CPERF_LINEARIZATION_ENABLE
+ struct rte_cryptodev_info dev_info;
+ int linearize = 0;
+
+ /* Check if source mbufs require coalescing */
+ if (ctx->options->segments_nb > 1) {
+ rte_cryptodev_info_get(ctx->dev_id, &dev_info);
+ if ((dev_info.feature_flags &
+ RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER) == 0)
+ linearize = 1;
+ }
+#endif /* CPERF_LINEARIZATION_ENABLE */
+
+ ctx->lcore_id = lcore;
+
+ /* Warm up the host CPU before starting the test */
+ for (i = 0; i < ctx->options->total_ops; i++)
+ rte_cryptodev_enqueue_burst(ctx->dev_id, ctx->qp_id, NULL, 0);
+
+ /* Get first size from range or list */
+ if (ctx->options->inc_burst_size != 0)
+ test_burst_size = ctx->options->min_burst_size;
+ else
+ test_burst_size = ctx->options->burst_size_list[0];
+
+ while (test_burst_size <= ctx->options->max_burst_size) {
+ uint64_t ops_enqd = 0, ops_deqd = 0;
+ uint64_t m_idx = 0, b_idx = 0;
+
+ uint64_t tsc_val, tsc_end, tsc_start;
+ uint64_t tsc_max = 0, tsc_min = ~0UL, tsc_tot = 0, tsc_idx = 0;
+ uint64_t enqd_max = 0, enqd_min = ~0UL, enqd_tot = 0;
+ uint64_t deqd_max = 0, deqd_min = ~0UL, deqd_tot = 0;
+
+ while (enqd_tot < ctx->options->total_ops) {
+
+ uint16_t burst_size = ((enqd_tot + test_burst_size)
+ <= ctx->options->total_ops) ?
+ test_burst_size :
+ ctx->options->total_ops -
+ enqd_tot;
+
+ /* Allocate crypto ops from pool */
+ if (burst_size != rte_crypto_op_bulk_alloc(
+ ctx->crypto_op_pool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ ops, burst_size))
+ return -1;
+
+ /* Setup crypto op, attach mbuf etc */
+ (ctx->populate_ops)(ops, &ctx->mbufs_in[m_idx],
+ &ctx->mbufs_out[m_idx],
+ burst_size, ctx->sess, ctx->options,
+ ctx->test_vector);
+
+ tsc_start = rte_rdtsc_precise();
+
+#ifdef CPERF_LINEARIZATION_ENABLE
+ if (linearize) {
+ /* PMD doesn't support scatter-gather and source buffer
+ * is segmented.
+ * We need to linearize it before enqueuing.
+ */
+ for (i = 0; i < burst_size; i++)
+ rte_pktmbuf_linearize(ops[i]->sym->m_src);
+ }
+#endif /* CPERF_LINEARIZATION_ENABLE */
+
+ /* Enqueue burst of ops on crypto device */
+ ops_enqd = rte_cryptodev_enqueue_burst(ctx->dev_id, ctx->qp_id,
+ ops, burst_size);
+
+ /* Dequeue processed burst of ops from crypto device */
+ ops_deqd = rte_cryptodev_dequeue_burst(ctx->dev_id, ctx->qp_id,
+ ops_processed, test_burst_size);
+
+ tsc_end = rte_rdtsc_precise();
+
+ /* Free memory for not enqueued operations */
+ for (i = ops_enqd; i < burst_size; i++)
+ rte_crypto_op_free(ops[i]);
+
+ for (i = 0; i < ops_enqd; i++) {
+ ctx->res[tsc_idx].tsc_start = tsc_start;
+ ops[i]->opaque_data = (void *)&ctx->res[tsc_idx];
+ tsc_idx++;
+ }
+
+ if (likely(ops_deqd)) {
+ /*
+ * free crypto ops so they can be reused. We don't free
+ * the mbufs here as we don't want to reuse them as
+ * the crypto operation will change the data and cause
+ * failures.
+ */
+ for (i = 0; i < ops_deqd; i++) {
+ pres = (struct cperf_op_result *)
+ (ops_processed[i]->opaque_data);
+ pres->status = ops_processed[i]->status;
+ pres->tsc_end = tsc_end;
+
+ rte_crypto_op_free(ops_processed[i]);
+ }
+
+ deqd_tot += ops_deqd;
+ deqd_max = max(ops_deqd, deqd_max);
+ deqd_min = min(ops_deqd, deqd_min);
+ }
+
+ enqd_tot += ops_enqd;
+ enqd_max = max(ops_enqd, enqd_max);
+ enqd_min = min(ops_enqd, enqd_min);
+
+ m_idx += ops_enqd;
+ m_idx = m_idx + test_burst_size > ctx->options->pool_sz ?
+ 0 : m_idx;
+ b_idx++;
+ }
+
+ /* Dequeue any operations still in the crypto device */
+ while (deqd_tot < ctx->options->total_ops) {
+ /* Sending 0 length burst to flush sw crypto device */
+ rte_cryptodev_enqueue_burst(ctx->dev_id, ctx->qp_id, NULL, 0);
+
+ /* dequeue burst */
+ ops_deqd = rte_cryptodev_dequeue_burst(ctx->dev_id, ctx->qp_id,
+ ops_processed, test_burst_size);
+
+ tsc_end = rte_rdtsc_precise();
+
+ if (ops_deqd != 0) {
+ for (i = 0; i < ops_deqd; i++) {
+ pres = (struct cperf_op_result *)
+ (ops_processed[i]->opaque_data);
+ pres->status = ops_processed[i]->status;
+ pres->tsc_end = tsc_end;
+
+ rte_crypto_op_free(ops_processed[i]);
+ }
+
+ deqd_tot += ops_deqd;
+ deqd_max = max(ops_deqd, deqd_max);
+ deqd_min = min(ops_deqd, deqd_min);
+ }
+ }
+
+ for (i = 0; i < tsc_idx; i++) {
+ tsc_val = ctx->res[i].tsc_end - ctx->res[i].tsc_start;
+ tsc_max = max(tsc_val, tsc_max);
+ tsc_min = min(tsc_val, tsc_min);
+ tsc_tot += tsc_val;
+ }
+
+ double time_tot, time_avg, time_max, time_min;
+
+ const uint64_t tunit = 1000000; /* us */
+ const uint64_t tsc_hz = rte_get_tsc_hz();
+
+ uint64_t enqd_avg = enqd_tot / b_idx;
+ uint64_t deqd_avg = deqd_tot / b_idx;
+ uint64_t tsc_avg = tsc_tot / tsc_idx;
+
+ time_tot = tunit*(double)(tsc_tot) / tsc_hz;
+ time_avg = tunit*(double)(tsc_avg) / tsc_hz;
+ time_max = tunit*(double)(tsc_max) / tsc_hz;
+ time_min = tunit*(double)(tsc_min) / tsc_hz;
+
+ if (ctx->options->csv) {
+ if (!only_once)
+ printf("\n# lcore, Buffer Size, Burst Size, Pakt Seq #, "
+ "Packet Size, cycles, time (us)");
+
+ for (i = 0; i < ctx->options->total_ops; i++) {
+
+ printf("\n%u;%u;%u;%"PRIu64";%"PRIu64";%.3f",
+ ctx->lcore_id, ctx->options->test_buffer_size,
+ test_burst_size, i + 1,
+ ctx->res[i].tsc_end - ctx->res[i].tsc_start,
+ tunit * (double) (ctx->res[i].tsc_end
+ - ctx->res[i].tsc_start)
+ / tsc_hz);
+
+ }
+ only_once = 1;
+ } else {
+ printf("\n# Device %d on lcore %u\n", ctx->dev_id,
+ ctx->lcore_id);
+ printf("\n# total operations: %u", ctx->options->total_ops);
+ printf("\n# Buffer size: %u", ctx->options->test_buffer_size);
+ printf("\n# Burst size: %u", test_burst_size);
+ printf("\n# Number of bursts: %"PRIu64,
+ b_idx);
+
+ printf("\n#");
+ printf("\n# \t Total\t Average\t "
+ "Maximum\t Minimum");
+ printf("\n# enqueued\t%12"PRIu64"\t%10"PRIu64"\t"
+ "%10"PRIu64"\t%10"PRIu64, enqd_tot,
+ enqd_avg, enqd_max, enqd_min);
+ printf("\n# dequeued\t%12"PRIu64"\t%10"PRIu64"\t"
+ "%10"PRIu64"\t%10"PRIu64, deqd_tot,
+ deqd_avg, deqd_max, deqd_min);
+ printf("\n# cycles\t%12"PRIu64"\t%10"PRIu64"\t"
+ "%10"PRIu64"\t%10"PRIu64, tsc_tot,
+ tsc_avg, tsc_max, tsc_min);
+ printf("\n# time [us]\t%12.0f\t%10.3f\t%10.3f\t%10.3f",
+ time_tot, time_avg, time_max, time_min);
+ printf("\n\n");
+
+ }
+
+ /* Get next size from range or list */
+ if (ctx->options->inc_burst_size != 0)
+ test_burst_size += ctx->options->inc_burst_size;
+ else {
+ if (++burst_size_idx == ctx->options->burst_size_count)
+ break;
+ test_burst_size =
+ ctx->options->burst_size_list[burst_size_idx];
+ }
+ }
+
+ return 0;
+}
+
+void
+cperf_latency_test_destructor(void *arg)
+{
+ struct cperf_latency_ctx *ctx = arg;
+
+ if (ctx == NULL)
+ return;
+
+ cperf_latency_test_free(ctx, ctx->options->pool_sz);
+
+}
diff --git a/src/seastar/dpdk/app/test-crypto-perf/cperf_test_latency.h b/src/seastar/dpdk/app/test-crypto-perf/cperf_test_latency.h
new file mode 100644
index 00000000..6a2cf610
--- /dev/null
+++ b/src/seastar/dpdk/app/test-crypto-perf/cperf_test_latency.h
@@ -0,0 +1,57 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016-2017 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _CPERF_LATENCY_
+#define _CPERF_LATENCY_
+
+#include <stdint.h>
+
+#include <rte_mbuf.h>
+
+#include "cperf.h"
+#include "cperf_ops.h"
+#include "cperf_options.h"
+#include "cperf_test_vectors.h"
+
+void *
+cperf_latency_test_constructor(uint8_t dev_id, uint16_t qp_id,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector,
+ const struct cperf_op_fns *ops_fn);
+
+int
+cperf_latency_test_runner(void *test_ctx);
+
+void
+cperf_latency_test_destructor(void *test_ctx);
+
+#endif /* _CPERF_LATENCY_ */
diff --git a/src/seastar/dpdk/app/test-crypto-perf/cperf_test_throughput.c b/src/seastar/dpdk/app/test-crypto-perf/cperf_test_throughput.c
new file mode 100644
index 00000000..61b27ea5
--- /dev/null
+++ b/src/seastar/dpdk/app/test-crypto-perf/cperf_test_throughput.c
@@ -0,0 +1,518 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016-2017 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rte_malloc.h>
+#include <rte_cycles.h>
+#include <rte_crypto.h>
+#include <rte_cryptodev.h>
+
+#include "cperf_test_throughput.h"
+#include "cperf_ops.h"
+
+struct cperf_throughput_ctx {
+ uint8_t dev_id;
+ uint16_t qp_id;
+ uint8_t lcore_id;
+
+ struct rte_mempool *pkt_mbuf_pool_in;
+ struct rte_mempool *pkt_mbuf_pool_out;
+ struct rte_mbuf **mbufs_in;
+ struct rte_mbuf **mbufs_out;
+
+ struct rte_mempool *crypto_op_pool;
+
+ struct rte_cryptodev_sym_session *sess;
+
+ cperf_populate_ops_t populate_ops;
+
+ const struct cperf_options *options;
+ const struct cperf_test_vector *test_vector;
+};
+
+static void
+cperf_throughput_test_free(struct cperf_throughput_ctx *ctx, uint32_t mbuf_nb)
+{
+ uint32_t i;
+
+ if (ctx) {
+ if (ctx->sess)
+ rte_cryptodev_sym_session_free(ctx->dev_id, ctx->sess);
+
+ if (ctx->mbufs_in) {
+ for (i = 0; i < mbuf_nb; i++)
+ rte_pktmbuf_free(ctx->mbufs_in[i]);
+
+ rte_free(ctx->mbufs_in);
+ }
+
+ if (ctx->mbufs_out) {
+ for (i = 0; i < mbuf_nb; i++) {
+ if (ctx->mbufs_out[i] != NULL)
+ rte_pktmbuf_free(ctx->mbufs_out[i]);
+ }
+
+ rte_free(ctx->mbufs_out);
+ }
+
+ if (ctx->pkt_mbuf_pool_in)
+ rte_mempool_free(ctx->pkt_mbuf_pool_in);
+
+ if (ctx->pkt_mbuf_pool_out)
+ rte_mempool_free(ctx->pkt_mbuf_pool_out);
+
+ if (ctx->crypto_op_pool)
+ rte_mempool_free(ctx->crypto_op_pool);
+
+ rte_free(ctx);
+ }
+}
+
+static struct rte_mbuf *
+cperf_mbuf_create(struct rte_mempool *mempool,
+ uint32_t segments_nb,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector)
+{
+ struct rte_mbuf *mbuf;
+ uint32_t segment_sz = options->max_buffer_size / segments_nb;
+ uint32_t last_sz = options->max_buffer_size % segments_nb;
+ uint8_t *mbuf_data;
+ uint8_t *test_data =
+ (options->cipher_op == RTE_CRYPTO_CIPHER_OP_ENCRYPT) ?
+ test_vector->plaintext.data :
+ test_vector->ciphertext.data;
+
+ mbuf = rte_pktmbuf_alloc(mempool);
+ if (mbuf == NULL)
+ goto error;
+
+ mbuf_data = (uint8_t *)rte_pktmbuf_append(mbuf, segment_sz);
+ if (mbuf_data == NULL)
+ goto error;
+
+ memcpy(mbuf_data, test_data, segment_sz);
+ test_data += segment_sz;
+ segments_nb--;
+
+ while (segments_nb) {
+ struct rte_mbuf *m;
+
+ m = rte_pktmbuf_alloc(mempool);
+ if (m == NULL)
+ goto error;
+
+ rte_pktmbuf_chain(mbuf, m);
+
+ mbuf_data = (uint8_t *)rte_pktmbuf_append(mbuf, segment_sz);
+ if (mbuf_data == NULL)
+ goto error;
+
+ memcpy(mbuf_data, test_data, segment_sz);
+ test_data += segment_sz;
+ segments_nb--;
+ }
+
+ if (last_sz) {
+ mbuf_data = (uint8_t *)rte_pktmbuf_append(mbuf, last_sz);
+ if (mbuf_data == NULL)
+ goto error;
+
+ memcpy(mbuf_data, test_data, last_sz);
+ }
+
+ if (options->op_type != CPERF_CIPHER_ONLY) {
+ mbuf_data = (uint8_t *)rte_pktmbuf_append(mbuf,
+ options->auth_digest_sz);
+ if (mbuf_data == NULL)
+ goto error;
+ }
+
+ if (options->op_type == CPERF_AEAD) {
+ uint8_t *aead = (uint8_t *)rte_pktmbuf_prepend(mbuf,
+ RTE_ALIGN_CEIL(options->auth_aad_sz, 16));
+
+ if (aead == NULL)
+ goto error;
+
+ memcpy(aead, test_vector->aad.data, test_vector->aad.length);
+ }
+
+ return mbuf;
+error:
+ if (mbuf != NULL)
+ rte_pktmbuf_free(mbuf);
+
+ return NULL;
+}
+
+void *
+cperf_throughput_test_constructor(uint8_t dev_id, uint16_t qp_id,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector,
+ const struct cperf_op_fns *op_fns)
+{
+ struct cperf_throughput_ctx *ctx = NULL;
+ unsigned int mbuf_idx = 0;
+ char pool_name[32] = "";
+
+ ctx = rte_malloc(NULL, sizeof(struct cperf_throughput_ctx), 0);
+ if (ctx == NULL)
+ goto err;
+
+ ctx->dev_id = dev_id;
+ ctx->qp_id = qp_id;
+
+ ctx->populate_ops = op_fns->populate_ops;
+ ctx->options = options;
+ ctx->test_vector = test_vector;
+
+ ctx->sess = op_fns->sess_create(dev_id, options, test_vector);
+ if (ctx->sess == NULL)
+ goto err;
+
+ snprintf(pool_name, sizeof(pool_name), "cperf_pool_in_cdev_%d",
+ dev_id);
+
+ ctx->pkt_mbuf_pool_in = rte_pktmbuf_pool_create(pool_name,
+ options->pool_sz * options->segments_nb, 0, 0,
+ RTE_PKTMBUF_HEADROOM +
+ RTE_CACHE_LINE_ROUNDUP(
+ (options->max_buffer_size / options->segments_nb) +
+ (options->max_buffer_size % options->segments_nb) +
+ options->auth_digest_sz),
+ rte_socket_id());
+
+ if (ctx->pkt_mbuf_pool_in == NULL)
+ goto err;
+
+ /* Generate mbufs_in with plaintext populated for test */
+ ctx->mbufs_in = rte_malloc(NULL,
+ (sizeof(struct rte_mbuf *) * ctx->options->pool_sz), 0);
+
+ for (mbuf_idx = 0; mbuf_idx < options->pool_sz; mbuf_idx++) {
+ ctx->mbufs_in[mbuf_idx] = cperf_mbuf_create(
+ ctx->pkt_mbuf_pool_in, options->segments_nb,
+ options, test_vector);
+ if (ctx->mbufs_in[mbuf_idx] == NULL)
+ goto err;
+ }
+
+ if (options->out_of_place == 1) {
+
+ snprintf(pool_name, sizeof(pool_name), "cperf_pool_out_cdev_%d",
+ dev_id);
+
+ ctx->pkt_mbuf_pool_out = rte_pktmbuf_pool_create(
+ pool_name, options->pool_sz, 0, 0,
+ RTE_PKTMBUF_HEADROOM +
+ RTE_CACHE_LINE_ROUNDUP(
+ options->max_buffer_size +
+ options->auth_digest_sz),
+ rte_socket_id());
+
+ if (ctx->pkt_mbuf_pool_out == NULL)
+ goto err;
+ }
+
+ ctx->mbufs_out = rte_malloc(NULL,
+ (sizeof(struct rte_mbuf *) *
+ ctx->options->pool_sz), 0);
+
+ for (mbuf_idx = 0; mbuf_idx < options->pool_sz; mbuf_idx++) {
+ if (options->out_of_place == 1) {
+ ctx->mbufs_out[mbuf_idx] = cperf_mbuf_create(
+ ctx->pkt_mbuf_pool_out, 1,
+ options, test_vector);
+ if (ctx->mbufs_out[mbuf_idx] == NULL)
+ goto err;
+ } else {
+ ctx->mbufs_out[mbuf_idx] = NULL;
+ }
+ }
+
+ snprintf(pool_name, sizeof(pool_name), "cperf_op_pool_cdev_%d",
+ dev_id);
+
+ ctx->crypto_op_pool = rte_crypto_op_pool_create(pool_name,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC, options->pool_sz, 0, 0,
+ rte_socket_id());
+ if (ctx->crypto_op_pool == NULL)
+ goto err;
+
+ return ctx;
+err:
+ cperf_throughput_test_free(ctx, mbuf_idx);
+
+ return NULL;
+}
+
+int
+cperf_throughput_test_runner(void *test_ctx)
+{
+ struct cperf_throughput_ctx *ctx = test_ctx;
+ uint16_t test_burst_size;
+ uint8_t burst_size_idx = 0;
+
+ static int only_once;
+
+ struct rte_crypto_op *ops[ctx->options->max_burst_size];
+ struct rte_crypto_op *ops_processed[ctx->options->max_burst_size];
+ uint64_t i;
+
+ uint32_t lcore = rte_lcore_id();
+
+#ifdef CPERF_LINEARIZATION_ENABLE
+ struct rte_cryptodev_info dev_info;
+ int linearize = 0;
+
+ /* Check if source mbufs require coalescing */
+ if (ctx->options->segments_nb > 1) {
+ rte_cryptodev_info_get(ctx->dev_id, &dev_info);
+ if ((dev_info.feature_flags &
+ RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER) == 0)
+ linearize = 1;
+ }
+#endif /* CPERF_LINEARIZATION_ENABLE */
+
+ ctx->lcore_id = lcore;
+
+ /* Warm up the host CPU before starting the test */
+ for (i = 0; i < ctx->options->total_ops; i++)
+ rte_cryptodev_enqueue_burst(ctx->dev_id, ctx->qp_id, NULL, 0);
+
+ /* Get first size from range or list */
+ if (ctx->options->inc_burst_size != 0)
+ test_burst_size = ctx->options->min_burst_size;
+ else
+ test_burst_size = ctx->options->burst_size_list[0];
+
+ while (test_burst_size <= ctx->options->max_burst_size) {
+ uint64_t ops_enqd = 0, ops_enqd_total = 0, ops_enqd_failed = 0;
+ uint64_t ops_deqd = 0, ops_deqd_total = 0, ops_deqd_failed = 0;
+
+ uint64_t m_idx = 0, tsc_start, tsc_end, tsc_duration;
+
+ uint16_t ops_unused = 0;
+
+ tsc_start = rte_rdtsc_precise();
+
+ while (ops_enqd_total < ctx->options->total_ops) {
+
+ uint16_t burst_size = ((ops_enqd_total + test_burst_size)
+ <= ctx->options->total_ops) ?
+ test_burst_size :
+ ctx->options->total_ops -
+ ops_enqd_total;
+
+ uint16_t ops_needed = burst_size - ops_unused;
+
+ /* Allocate crypto ops from pool */
+ if (ops_needed != rte_crypto_op_bulk_alloc(
+ ctx->crypto_op_pool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ ops, ops_needed))
+ return -1;
+
+ /* Setup crypto op, attach mbuf etc */
+ (ctx->populate_ops)(ops, &ctx->mbufs_in[m_idx],
+ &ctx->mbufs_out[m_idx],
+ ops_needed, ctx->sess, ctx->options,
+ ctx->test_vector);
+
+ /**
+ * When ops_needed is smaller than ops_enqd, the
+ * unused ops need to be moved to the front for
+ * next round use.
+ */
+ if (unlikely(ops_enqd > ops_needed)) {
+ size_t nb_b_to_mov = ops_unused * sizeof(
+ struct rte_crypto_op *);
+
+ memmove(&ops[ops_needed], &ops[ops_enqd],
+ nb_b_to_mov);
+ }
+
+#ifdef CPERF_LINEARIZATION_ENABLE
+ if (linearize) {
+ /* PMD doesn't support scatter-gather and source buffer
+ * is segmented.
+ * We need to linearize it before enqueuing.
+ */
+ for (i = 0; i < burst_size; i++)
+ rte_pktmbuf_linearize(ops[i]->sym->m_src);
+ }
+#endif /* CPERF_LINEARIZATION_ENABLE */
+
+ /* Enqueue burst of ops on crypto device */
+ ops_enqd = rte_cryptodev_enqueue_burst(ctx->dev_id, ctx->qp_id,
+ ops, burst_size);
+ if (ops_enqd < burst_size)
+ ops_enqd_failed++;
+
+ /**
+ * Calculate number of ops not enqueued (mainly for hw
+ * accelerators whose ingress queue can fill up).
+ */
+ ops_unused = burst_size - ops_enqd;
+ ops_enqd_total += ops_enqd;
+
+
+ /* Dequeue processed burst of ops from crypto device */
+ ops_deqd = rte_cryptodev_dequeue_burst(ctx->dev_id, ctx->qp_id,
+ ops_processed, test_burst_size);
+
+ if (likely(ops_deqd)) {
+ /* free crypto ops so they can be reused. We don't free
+ * the mbufs here as we don't want to reuse them as
+ * the crypto operation will change the data and cause
+ * failures.
+ */
+ for (i = 0; i < ops_deqd; i++)
+ rte_crypto_op_free(ops_processed[i]);
+
+ ops_deqd_total += ops_deqd;
+ } else {
+ /**
+ * Count dequeue polls which didn't return any
+ * processed operations. This statistic is mainly
+ * relevant to hw accelerators.
+ */
+ ops_deqd_failed++;
+ }
+
+ m_idx += ops_needed;
+ m_idx = m_idx + test_burst_size > ctx->options->pool_sz ?
+ 0 : m_idx;
+ }
+
+ /* Dequeue any operations still in the crypto device */
+
+ while (ops_deqd_total < ctx->options->total_ops) {
+ /* Sending 0 length burst to flush sw crypto device */
+ rte_cryptodev_enqueue_burst(ctx->dev_id, ctx->qp_id, NULL, 0);
+
+ /* dequeue burst */
+ ops_deqd = rte_cryptodev_dequeue_burst(ctx->dev_id, ctx->qp_id,
+ ops_processed, test_burst_size);
+ if (ops_deqd == 0)
+ ops_deqd_failed++;
+ else {
+ for (i = 0; i < ops_deqd; i++)
+ rte_crypto_op_free(ops_processed[i]);
+
+ ops_deqd_total += ops_deqd;
+ }
+ }
+
+ tsc_end = rte_rdtsc_precise();
+ tsc_duration = (tsc_end - tsc_start);
+
+ /* Calculate average operations processed per second */
+ double ops_per_second = ((double)ctx->options->total_ops /
+ tsc_duration) * rte_get_tsc_hz();
+
+ /* Calculate average throughput (Gbps) in bits per second */
+ double throughput_gbps = ((ops_per_second *
+ ctx->options->test_buffer_size * 8) / 1000000000);
+
+ /* Calculate average cycles per packet */
+ double cycles_per_packet = ((double)tsc_duration /
+ ctx->options->total_ops);
+
+ if (!ctx->options->csv) {
+ if (!only_once)
+ printf("%12s%12s%12s%12s%12s%12s%12s%12s%12s%12s\n\n",
+ "lcore id", "Buf Size", "Burst Size",
+ "Enqueued", "Dequeued", "Failed Enq",
+ "Failed Deq", "MOps", "Gbps",
+ "Cycles/Buf");
+ only_once = 1;
+
+ printf("%12u%12u%12u%12"PRIu64"%12"PRIu64"%12"PRIu64
+ "%12"PRIu64"%12.4f%12.4f%12.2f\n",
+ ctx->lcore_id,
+ ctx->options->test_buffer_size,
+ test_burst_size,
+ ops_enqd_total,
+ ops_deqd_total,
+ ops_enqd_failed,
+ ops_deqd_failed,
+ ops_per_second/1000000,
+ throughput_gbps,
+ cycles_per_packet);
+ } else {
+ if (!only_once)
+ printf("# lcore id, Buffer Size(B),"
+ "Burst Size,Enqueued,Dequeued,Failed Enq,"
+ "Failed Deq,Ops(Millions),Throughput(Gbps),"
+ "Cycles/Buf\n\n");
+ only_once = 1;
+
+ printf("%10u;%10u;%u;%"PRIu64";%"PRIu64";%"PRIu64";%"PRIu64";"
+ "%.f3;%.f3;%.f3\n",
+ ctx->lcore_id,
+ ctx->options->test_buffer_size,
+ test_burst_size,
+ ops_enqd_total,
+ ops_deqd_total,
+ ops_enqd_failed,
+ ops_deqd_failed,
+ ops_per_second/1000000,
+ throughput_gbps,
+ cycles_per_packet);
+ }
+
+ /* Get next size from range or list */
+ if (ctx->options->inc_burst_size != 0)
+ test_burst_size += ctx->options->inc_burst_size;
+ else {
+ if (++burst_size_idx == ctx->options->burst_size_count)
+ break;
+ test_burst_size = ctx->options->burst_size_list[burst_size_idx];
+ }
+
+ }
+
+ return 0;
+}
+
+
+void
+cperf_throughput_test_destructor(void *arg)
+{
+ struct cperf_throughput_ctx *ctx = arg;
+
+ if (ctx == NULL)
+ return;
+
+ cperf_throughput_test_free(ctx, ctx->options->pool_sz);
+}
diff --git a/src/seastar/dpdk/app/test-crypto-perf/cperf_test_throughput.h b/src/seastar/dpdk/app/test-crypto-perf/cperf_test_throughput.h
new file mode 100644
index 00000000..f1b5766c
--- /dev/null
+++ b/src/seastar/dpdk/app/test-crypto-perf/cperf_test_throughput.h
@@ -0,0 +1,58 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016-2017 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _CPERF_THROUGHPUT_
+#define _CPERF_THROUGHPUT_
+
+#include <stdint.h>
+
+#include <rte_mbuf.h>
+
+#include "cperf.h"
+#include "cperf_ops.h"
+#include "cperf_options.h"
+#include "cperf_test_vectors.h"
+
+
+void *
+cperf_throughput_test_constructor(uint8_t dev_id, uint16_t qp_id,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector,
+ const struct cperf_op_fns *ops_fn);
+
+int
+cperf_throughput_test_runner(void *test_ctx);
+
+void
+cperf_throughput_test_destructor(void *test_ctx);
+
+#endif /* _CPERF_THROUGHPUT_ */
diff --git a/src/seastar/dpdk/app/test-crypto-perf/cperf_test_vector_parsing.c b/src/seastar/dpdk/app/test-crypto-perf/cperf_test_vector_parsing.c
new file mode 100644
index 00000000..f384e3d9
--- /dev/null
+++ b/src/seastar/dpdk/app/test-crypto-perf/cperf_test_vector_parsing.c
@@ -0,0 +1,507 @@
+#ifdef RTE_EXEC_ENV_BSDAPP
+ #define _WITH_GETLINE
+#endif
+#include <stdio.h>
+
+#include <rte_malloc.h>
+
+#include "cperf_options.h"
+#include "cperf_test_vectors.h"
+#include "cperf_test_vector_parsing.h"
+
+int
+free_test_vector(struct cperf_test_vector *vector, struct cperf_options *opts)
+{
+ if (vector == NULL || opts == NULL)
+ return -1;
+
+ rte_free(vector->iv.data);
+ rte_free(vector->aad.data);
+ rte_free(vector->digest.data);
+
+ if (opts->test_file != NULL) {
+ rte_free(vector->plaintext.data);
+ rte_free(vector->cipher_key.data);
+ rte_free(vector->auth_key.data);
+ rte_free(vector->ciphertext.data);
+ }
+
+ rte_free(vector);
+
+ return 0;
+}
+
+void
+show_test_vector(struct cperf_test_vector *test_vector)
+{
+ const uint8_t wrap = 32;
+ uint32_t i;
+
+ if (test_vector == NULL)
+ return;
+
+ if (test_vector->plaintext.data) {
+ printf("\nplaintext =\n");
+ for (i = 0; i < test_vector->plaintext.length; ++i) {
+ if ((i % wrap == 0) && (i != 0))
+ printf("\n");
+ if (i == test_vector->plaintext.length - 1)
+ printf("0x%02x",
+ test_vector->plaintext.data[i]);
+ else
+ printf("0x%02x, ",
+ test_vector->plaintext.data[i]);
+ }
+ printf("\n");
+ }
+
+ if (test_vector->cipher_key.data) {
+ printf("\ncipher_key =\n");
+ for (i = 0; i < test_vector->cipher_key.length; ++i) {
+ if ((i % wrap == 0) && (i != 0))
+ printf("\n");
+ if (i == (uint32_t)(test_vector->cipher_key.length - 1))
+ printf("0x%02x",
+ test_vector->cipher_key.data[i]);
+ else
+ printf("0x%02x, ",
+ test_vector->cipher_key.data[i]);
+ }
+ printf("\n");
+ }
+
+ if (test_vector->auth_key.data) {
+ printf("\nauth_key =\n");
+ for (i = 0; i < test_vector->auth_key.length; ++i) {
+ if ((i % wrap == 0) && (i != 0))
+ printf("\n");
+ if (i == (uint32_t)(test_vector->auth_key.length - 1))
+ printf("0x%02x", test_vector->auth_key.data[i]);
+ else
+ printf("0x%02x, ",
+ test_vector->auth_key.data[i]);
+ }
+ printf("\n");
+ }
+
+ if (test_vector->iv.data) {
+ printf("\niv =\n");
+ for (i = 0; i < test_vector->iv.length; ++i) {
+ if ((i % wrap == 0) && (i != 0))
+ printf("\n");
+ if (i == (uint32_t)(test_vector->iv.length - 1))
+ printf("0x%02x", test_vector->iv.data[i]);
+ else
+ printf("0x%02x, ", test_vector->iv.data[i]);
+ }
+ printf("\n");
+ }
+
+ if (test_vector->ciphertext.data) {
+ printf("\nciphertext =\n");
+ for (i = 0; i < test_vector->ciphertext.length; ++i) {
+ if ((i % wrap == 0) && (i != 0))
+ printf("\n");
+ if (i == test_vector->ciphertext.length - 1)
+ printf("0x%02x",
+ test_vector->ciphertext.data[i]);
+ else
+ printf("0x%02x, ",
+ test_vector->ciphertext.data[i]);
+ }
+ printf("\n");
+ }
+
+ if (test_vector->aad.data) {
+ printf("\naad =\n");
+ for (i = 0; i < test_vector->aad.length; ++i) {
+ if ((i % wrap == 0) && (i != 0))
+ printf("\n");
+ if (i == (uint32_t)(test_vector->aad.length - 1))
+ printf("0x%02x", test_vector->aad.data[i]);
+ else
+ printf("0x%02x, ", test_vector->aad.data[i]);
+ }
+ printf("\n");
+ }
+
+ if (test_vector->digest.data) {
+ printf("\ndigest =\n");
+ for (i = 0; i < test_vector->digest.length; ++i) {
+ if ((i % wrap == 0) && (i != 0))
+ printf("\n");
+ if (i == (uint32_t)(test_vector->digest.length - 1))
+ printf("0x%02x", test_vector->digest.data[i]);
+ else
+ printf("0x%02x, ", test_vector->digest.data[i]);
+ }
+ printf("\n");
+ }
+}
+
+/* trim leading and trailing spaces */
+static char *
+trim_space(char *str)
+{
+ char *start, *end;
+
+ for (start = str; *start; start++) {
+ if (!isspace((unsigned char) start[0]))
+ break;
+ }
+
+ for (end = start + strlen(start); end > start + 1; end--) {
+ if (!isspace((unsigned char) end[-1]))
+ break;
+ }
+
+ *end = 0;
+
+ /* Shift from "start" to the beginning of the string */
+ if (start > str)
+ memmove(str, start, (end - start) + 1);
+
+ return str;
+}
+
+/* tokenization test values separated by a comma */
+static int
+parse_values(char *tokens, uint8_t **data, uint32_t *data_length)
+{
+ uint32_t n_tokens;
+ uint32_t data_size = 32;
+
+ uint8_t *values, *values_resized;
+ char *tok, *error = NULL;
+
+ tok = strtok(tokens, CPERF_VALUE_DELIMITER);
+ if (tok == NULL)
+ return -1;
+
+ values = (uint8_t *) rte_zmalloc(NULL, sizeof(uint8_t) * data_size, 0);
+ if (values == NULL)
+ return -1;
+
+ n_tokens = 0;
+ while (tok != NULL) {
+ values_resized = NULL;
+
+ if (n_tokens >= data_size) {
+ data_size *= 2;
+
+ values_resized = (uint8_t *) rte_realloc(values,
+ sizeof(uint8_t) * data_size, 0);
+ if (values_resized == NULL) {
+ rte_free(values);
+ return -1;
+ }
+ values = values_resized;
+ }
+
+ values[n_tokens] = (uint8_t) strtoul(tok, &error, 0);
+ if ((error == NULL) || (*error != '\0')) {
+ printf("Failed with convert '%s'\n", tok);
+ rte_free(values);
+ return -1;
+ }
+
+ tok = strtok(NULL, CPERF_VALUE_DELIMITER);
+ if (tok == NULL)
+ break;
+
+ n_tokens++;
+ }
+
+ values_resized = (uint8_t *) rte_realloc(values,
+ sizeof(uint8_t) * (n_tokens + 1), 0);
+
+ if (values_resized == NULL) {
+ rte_free(values);
+ return -1;
+ }
+
+ *data = values_resized;
+ *data_length = n_tokens + 1;
+
+ return 0;
+}
+
+/* checks the type of key and assigns data */
+static int
+parse_entry(char *entry, struct cperf_test_vector *vector,
+ struct cperf_options *opts, uint8_t tc_found)
+{
+ int status;
+ uint32_t data_length;
+
+ uint8_t *data = NULL;
+ char *token, *key_token;
+
+ if (entry == NULL) {
+ printf("Expected entry value\n");
+ return -1;
+ }
+
+ /* get key */
+ token = strtok(entry, CPERF_ENTRY_DELIMITER);
+ key_token = token;
+ /* get values for key */
+ token = strtok(NULL, CPERF_ENTRY_DELIMITER);
+
+ if (key_token == NULL || token == NULL) {
+ printf("Expected 'key = values' but was '%.40s'..\n", entry);
+ return -1;
+ }
+
+ status = parse_values(token, &data, &data_length);
+ if (status)
+ return -1;
+
+ /* compare keys */
+ if (strstr(key_token, "plaintext")) {
+ rte_free(vector->plaintext.data);
+ vector->plaintext.data = data;
+ if (tc_found)
+ vector->plaintext.length = data_length;
+ else {
+ if (opts->max_buffer_size > data_length) {
+ printf("Global plaintext shorter than "
+ "buffer_sz\n");
+ return -1;
+ }
+ vector->plaintext.length = opts->max_buffer_size;
+ }
+
+ } else if (strstr(key_token, "cipher_key")) {
+ rte_free(vector->cipher_key.data);
+ vector->cipher_key.data = data;
+ if (tc_found)
+ vector->cipher_key.length = data_length;
+ else {
+ if (opts->cipher_key_sz > data_length) {
+ printf("Global cipher_key shorter than "
+ "cipher_key_sz\n");
+ return -1;
+ }
+ vector->cipher_key.length = opts->cipher_key_sz;
+ }
+
+ } else if (strstr(key_token, "auth_key")) {
+ rte_free(vector->auth_key.data);
+ vector->auth_key.data = data;
+ if (tc_found)
+ vector->auth_key.length = data_length;
+ else {
+ if (opts->auth_key_sz > data_length) {
+ printf("Global auth_key shorter than "
+ "auth_key_sz\n");
+ return -1;
+ }
+ vector->auth_key.length = opts->auth_key_sz;
+ }
+
+ } else if (strstr(key_token, "iv")) {
+ rte_free(vector->iv.data);
+ vector->iv.data = data;
+ vector->iv.phys_addr = rte_malloc_virt2phy(vector->iv.data);
+ if (tc_found)
+ vector->iv.length = data_length;
+ else {
+ if (opts->cipher_iv_sz > data_length) {
+ printf("Global iv shorter than "
+ "cipher_iv_sz\n");
+ return -1;
+ }
+ vector->iv.length = opts->cipher_iv_sz;
+ }
+
+ } else if (strstr(key_token, "ciphertext")) {
+ rte_free(vector->ciphertext.data);
+ vector->ciphertext.data = data;
+ if (tc_found)
+ vector->ciphertext.length = data_length;
+ else {
+ if (opts->max_buffer_size > data_length) {
+ printf("Global ciphertext shorter than "
+ "buffer_sz\n");
+ return -1;
+ }
+ vector->ciphertext.length = opts->max_buffer_size;
+ }
+
+ } else if (strstr(key_token, "aad")) {
+ rte_free(vector->aad.data);
+ vector->aad.data = data;
+ vector->aad.phys_addr = rte_malloc_virt2phy(vector->aad.data);
+ if (tc_found)
+ vector->aad.length = data_length;
+ else {
+ if (opts->auth_aad_sz > data_length) {
+ printf("Global aad shorter than "
+ "auth_aad_sz\n");
+ return -1;
+ }
+ vector->aad.length = opts->auth_aad_sz;
+ }
+
+ } else if (strstr(key_token, "digest")) {
+ rte_free(vector->digest.data);
+ vector->digest.data = data;
+ vector->digest.phys_addr = rte_malloc_virt2phy(
+ vector->digest.data);
+ if (tc_found)
+ vector->digest.length = data_length;
+ else {
+ if (opts->auth_digest_sz > data_length) {
+ printf("Global digest shorter than "
+ "auth_digest_sz\n");
+ return -1;
+ }
+ vector->digest.length = opts->auth_digest_sz;
+ }
+ } else {
+ printf("Not valid key: '%s'\n", trim_space(key_token));
+ return -1;
+ }
+
+ return 0;
+}
+
+/* searches in the file for test keys and values */
+static int
+parse_file(struct cperf_test_vector *vector, struct cperf_options *opts)
+{
+ uint8_t tc_found = 0;
+ uint8_t tc_data_start = 0;
+ ssize_t read;
+ size_t len = 0;
+ int status = 0;
+
+ FILE *fp;
+ char *line = NULL;
+ char *entry = NULL;
+
+ fp = fopen(opts->test_file, "r");
+ if (fp == NULL) {
+ printf("File %s does not exists\n", opts->test_file);
+ return -1;
+ }
+
+ while ((read = getline(&line, &len, fp)) != -1) {
+
+ /* ignore comments and new lines */
+ if (line[0] == '#' || line[0] == '/' || line[0] == '\n'
+ || line[0] == '\r' || line[0] == ' ')
+ continue;
+
+ trim_space(line);
+
+ /* next test case is started */
+ if (line[0] == '[' && line[strlen(line) - 1] == ']' && tc_found)
+ break;
+ /* test case section started, end of global data */
+ else if (line[0] == '[' && line[strlen(line) - 1] == ']')
+ tc_data_start = 1;
+
+ /* test name unspecified, end after global data */
+ if (tc_data_start && opts->test_name == NULL)
+ break;
+ /* searching for a suitable test */
+ else if (tc_data_start && tc_found == 0) {
+ if (!strcmp(line, opts->test_name)) {
+ tc_found = 1;
+ continue;
+ } else
+ continue;
+ }
+
+ /* buffer for multiline */
+ entry = (char *) rte_realloc(entry,
+ sizeof(char) * strlen(line) + 1, 0);
+ if (entry == NULL)
+ return -1;
+
+ memset(entry, 0, strlen(line) + 1);
+ strncpy(entry, line, strlen(line));
+
+ /* check if entry ends with , or = */
+ if (entry[strlen(entry) - 1] == ','
+ || entry[strlen(entry) - 1] == '=') {
+ while ((read = getline(&line, &len, fp)) != -1) {
+ trim_space(line);
+
+ /* extend entry about length of new line */
+ char *entry_extended = (char *) rte_realloc(
+ entry, sizeof(char)
+ * (strlen(line) + strlen(entry))
+ + 1, 0);
+
+ if (entry_extended == NULL)
+ goto err;
+ entry = entry_extended;
+
+ strncat(entry, line, strlen(line));
+
+ if (entry[strlen(entry) - 1] != ',')
+ break;
+ }
+ }
+ status = parse_entry(entry, vector, opts, tc_found);
+ if (status) {
+ printf("An error occurred while parsing!\n");
+ goto err;
+ }
+ }
+
+ if (tc_found == 0 && opts->test_name != NULL) {
+ printf("Not found '%s' case in test file\n", opts->test_name);
+ goto err;
+ }
+
+ fclose(fp);
+ free(line);
+ rte_free(entry);
+
+ return 0;
+
+err:
+ if (fp)
+ fclose(fp);
+ if (line)
+ free(line);
+ if (entry)
+ rte_free(entry);
+
+ return -1;
+}
+
+struct cperf_test_vector*
+cperf_test_vector_get_from_file(struct cperf_options *opts)
+{
+ int status;
+ struct cperf_test_vector *test_vector = NULL;
+
+ if (opts == NULL || opts->test_file == NULL)
+ return test_vector;
+
+ test_vector = (struct cperf_test_vector *) rte_zmalloc(NULL,
+ sizeof(struct cperf_test_vector), 0);
+ if (test_vector == NULL)
+ return test_vector;
+
+ /* filling the vector with data from a file */
+ status = parse_file(test_vector, opts);
+ if (status) {
+ free_test_vector(test_vector, opts);
+ return NULL;
+ }
+
+ /* other values not included in the file */
+ test_vector->data.cipher_offset = 0;
+ test_vector->data.cipher_length = opts->max_buffer_size;
+
+ test_vector->data.auth_offset = 0;
+ test_vector->data.auth_length = opts->max_buffer_size;
+
+ return test_vector;
+}
diff --git a/src/seastar/dpdk/app/test-crypto-perf/cperf_test_vector_parsing.h b/src/seastar/dpdk/app/test-crypto-perf/cperf_test_vector_parsing.h
new file mode 100644
index 00000000..e3df98bd
--- /dev/null
+++ b/src/seastar/dpdk/app/test-crypto-perf/cperf_test_vector_parsing.h
@@ -0,0 +1,73 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016-2017 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef APP_CRYPTO_PERF_CPERF_TEST_VECTOR_PARSING_H_
+#define APP_CRYPTO_PERF_CPERF_TEST_VECTOR_PARSING_H_
+
+#define CPERF_VALUE_DELIMITER ","
+#define CPERF_ENTRY_DELIMITER "="
+
+/**
+ * Frees the allocated memory for test vector
+ *
+ * @param vector
+ * Destination vector test to release
+ * @param opts
+ * Test options
+ * @return
+ * 0 on success, (-1) on error.
+ */
+int
+free_test_vector(struct cperf_test_vector *vector, struct cperf_options *opts);
+
+/**
+ * Displays data in test vector
+ *
+ * @param vector
+ * Vector to display
+ */
+void
+show_test_vector(struct cperf_test_vector *test_vector);
+
+/**
+ * Completes test vector with data from file
+ *
+ * @param opts
+ * Test options
+ * @return
+ * NULL on error.
+ * Test vector pointer on successful.
+ */
+struct cperf_test_vector*
+cperf_test_vector_get_from_file(struct cperf_options *opts);
+
+#endif /* APP_CRYPTO_PERF_CPERF_TEST_VECTOR_PARSING_H_ */
diff --git a/src/seastar/dpdk/app/test-crypto-perf/cperf_test_vectors.c b/src/seastar/dpdk/app/test-crypto-perf/cperf_test_vectors.c
new file mode 100644
index 00000000..757957f7
--- /dev/null
+++ b/src/seastar/dpdk/app/test-crypto-perf/cperf_test_vectors.c
@@ -0,0 +1,500 @@
+#include <rte_crypto.h>
+#include <rte_malloc.h>
+
+#include "cperf_test_vectors.h"
+
+uint8_t plaintext[2048] = {
+ 0x71, 0x75, 0x83, 0x98, 0x75, 0x42, 0x51, 0x09, 0x94, 0x02, 0x13, 0x20,
+ 0x15, 0x64, 0x46, 0x32, 0x08, 0x18, 0x91, 0x82, 0x86, 0x52, 0x23, 0x93,
+ 0x44, 0x54, 0x28, 0x68, 0x78, 0x78, 0x70, 0x06, 0x42, 0x74, 0x41, 0x27,
+ 0x73, 0x38, 0x53, 0x77, 0x51, 0x96, 0x53, 0x24, 0x03, 0x88, 0x74, 0x14,
+ 0x70, 0x23, 0x88, 0x30, 0x85, 0x18, 0x89, 0x27, 0x41, 0x71, 0x61, 0x23,
+ 0x04, 0x83, 0x30, 0x57, 0x26, 0x47, 0x23, 0x75, 0x25, 0x62, 0x53, 0x80,
+ 0x38, 0x34, 0x21, 0x33, 0x34, 0x51, 0x46, 0x29, 0x94, 0x64, 0x22, 0x67,
+ 0x25, 0x45, 0x70, 0x26, 0x74, 0x39, 0x46, 0x71, 0x08, 0x85, 0x27, 0x18,
+ 0x93, 0x39, 0x72, 0x11, 0x57, 0x26, 0x88, 0x46, 0x47, 0x49, 0x86, 0x92,
+ 0x03, 0x37, 0x96, 0x40, 0x84, 0x53, 0x67, 0x47, 0x60, 0x60, 0x37, 0x67,
+ 0x02, 0x68, 0x76, 0x62, 0x42, 0x01, 0x59, 0x11, 0x01, 0x89, 0x40, 0x87,
+ 0x58, 0x20, 0x51, 0x21, 0x66, 0x26, 0x26, 0x73, 0x03, 0x06, 0x14, 0x25,
+ 0x98, 0x42, 0x44, 0x67, 0x24, 0x78, 0x71, 0x45, 0x32, 0x61, 0x20, 0x26,
+ 0x08, 0x88, 0x44, 0x26, 0x40, 0x63, 0x76, 0x23, 0x78, 0x55, 0x81, 0x97,
+ 0x95, 0x89, 0x39, 0x07, 0x14, 0x50, 0x50, 0x73, 0x07, 0x20, 0x86, 0x83,
+ 0x74, 0x57, 0x72, 0x36, 0x68, 0x61, 0x14, 0x41, 0x56, 0x49, 0x64, 0x72,
+ 0x75, 0x81, 0x47, 0x91, 0x08, 0x76, 0x47, 0x06, 0x55, 0x77, 0x61, 0x45,
+ 0x50, 0x10, 0x07, 0x46, 0x46, 0x89, 0x80, 0x07, 0x24, 0x95, 0x39, 0x43,
+ 0x03, 0x75, 0x24, 0x35, 0x57, 0x82, 0x09, 0x64, 0x29, 0x24, 0x26, 0x66,
+ 0x67, 0x29, 0x05, 0x90, 0x82, 0x02, 0x45, 0x71, 0x21, 0x34, 0x25, 0x48,
+ 0x68, 0x26, 0x01, 0x18, 0x73, 0x18, 0x46, 0x15, 0x14, 0x33, 0x28, 0x44,
+ 0x24, 0x82, 0x20, 0x12, 0x99, 0x43, 0x68, 0x43, 0x25, 0x14, 0x34, 0x33,
+ 0x31, 0x13, 0x77, 0x44, 0x95, 0x22, 0x99, 0x02, 0x30, 0x50, 0x74, 0x43,
+ 0x81, 0x78, 0x32, 0x17, 0x09, 0x85, 0x04, 0x37, 0x31, 0x98, 0x76, 0x79,
+ 0x64, 0x10, 0x39, 0x89, 0x59, 0x90, 0x50, 0x15, 0x77, 0x39, 0x28, 0x14,
+ 0x30, 0x19, 0x68, 0x77, 0x89, 0x48, 0x86, 0x16, 0x11, 0x33, 0x84, 0x56,
+ 0x10, 0x20, 0x94, 0x72, 0x41, 0x69, 0x13, 0x00, 0x56, 0x27, 0x01, 0x57,
+ 0x46, 0x65, 0x65, 0x19, 0x33, 0x07, 0x62, 0x19, 0x91, 0x60, 0x29, 0x11,
+ 0x41, 0x25, 0x88, 0x21, 0x93, 0x85, 0x87, 0x40, 0x91, 0x25, 0x32, 0x86,
+ 0x76, 0x54, 0x92, 0x52, 0x72, 0x46, 0x61, 0x84, 0x20, 0x14, 0x65, 0x83,
+ 0x69, 0x90, 0x80, 0x11, 0x35, 0x70, 0x42, 0x64, 0x74, 0x85, 0x15, 0x23,
+ 0x06, 0x55, 0x67, 0x49, 0x76, 0x47, 0x11, 0x95, 0x00, 0x85, 0x05, 0x12,
+ 0x58, 0x53, 0x25, 0x73, 0x62, 0x81, 0x63, 0x82, 0x32, 0x75, 0x16, 0x48,
+ 0x04, 0x96, 0x75, 0x16, 0x43, 0x83, 0x41, 0x85, 0x95, 0x67, 0x27, 0x83,
+ 0x22, 0x43, 0x02, 0x27, 0x69, 0x62, 0x78, 0x50, 0x57, 0x66, 0x99, 0x89,
+ 0x05, 0x06, 0x35, 0x86, 0x37, 0x27, 0x48, 0x46, 0x50, 0x80, 0x96, 0x40,
+ 0x42, 0x36, 0x21, 0x54, 0x49, 0x18, 0x63, 0x38, 0x45, 0x76, 0x23, 0x20,
+ 0x28, 0x06, 0x17, 0x32, 0x58, 0x50, 0x49, 0x54, 0x29, 0x46, 0x18, 0x12,
+ 0x17, 0x50, 0x02, 0x80, 0x99, 0x53, 0x15, 0x02, 0x07, 0x14, 0x19, 0x60,
+ 0x56, 0x43, 0x76, 0x71, 0x49, 0x99, 0x54, 0x83, 0x28, 0x94, 0x30, 0x30,
+ 0x57, 0x05, 0x89, 0x80, 0x11, 0x03, 0x78, 0x35, 0x73, 0x52, 0x67, 0x39,
+ 0x67, 0x07, 0x04, 0x49, 0x23, 0x83, 0x86, 0x89, 0x57, 0x71, 0x08, 0x41,
+ 0x15, 0x97, 0x19, 0x72, 0x03, 0x27, 0x72, 0x52, 0x66, 0x67, 0x99, 0x15,
+ 0x33, 0x64, 0x69, 0x78, 0x07, 0x83, 0x53, 0x71, 0x21, 0x50, 0x05, 0x48,
+ 0x59, 0x85, 0x01, 0x36, 0x65, 0x02, 0x52, 0x01, 0x09, 0x49, 0x28, 0x77,
+ 0x25, 0x35, 0x67, 0x77, 0x81, 0x64, 0x24, 0x29, 0x42, 0x32, 0x59, 0x22,
+ 0x93, 0x48, 0x59, 0x03, 0x85, 0x87, 0x15, 0x55, 0x23, 0x42, 0x58, 0x17,
+ 0x18, 0x37, 0x70, 0x83, 0x80, 0x12, 0x44, 0x83, 0x45, 0x70, 0x55, 0x86,
+ 0x03, 0x23, 0x01, 0x56, 0x94, 0x12, 0x41, 0x34, 0x82, 0x90, 0x83, 0x46,
+ 0x17, 0x56, 0x66, 0x96, 0x75, 0x80, 0x59, 0x07, 0x15, 0x84, 0x19, 0x52,
+ 0x37, 0x44, 0x44, 0x83, 0x72, 0x43, 0x25, 0x42, 0x26, 0x86, 0x87, 0x86,
+ 0x91, 0x62, 0x14, 0x90, 0x34, 0x26, 0x14, 0x33, 0x59, 0x70, 0x73, 0x15,
+ 0x49, 0x40, 0x66, 0x88, 0x42, 0x66, 0x16, 0x42, 0x55, 0x92, 0x82, 0x06,
+ 0x20, 0x96, 0x36, 0x96, 0x13, 0x07, 0x84, 0x94, 0x37, 0x66, 0x62, 0x78,
+ 0x60, 0x58, 0x80, 0x50, 0x69, 0x03, 0x97, 0x16, 0x64, 0x45, 0x21, 0x39,
+ 0x79, 0x28, 0x52, 0x17, 0x14, 0x77, 0x31, 0x60, 0x86, 0x70, 0x09, 0x53,
+ 0x39, 0x32, 0x52, 0x31, 0x35, 0x79, 0x24, 0x70, 0x25, 0x48, 0x23, 0x49,
+ 0x10, 0x64, 0x54, 0x30, 0x82, 0x34, 0x51, 0x20, 0x46, 0x04, 0x29, 0x25,
+ 0x65, 0x09, 0x55, 0x30, 0x30, 0x52, 0x85, 0x32, 0x79, 0x19, 0x59, 0x07,
+ 0x05, 0x12, 0x11, 0x03, 0x21, 0x90, 0x36, 0x62, 0x23, 0x67, 0x36, 0x67,
+ 0x47, 0x39, 0x92, 0x88, 0x45, 0x43, 0x71, 0x16, 0x48, 0x27, 0x68, 0x39,
+ 0x98, 0x38, 0x03, 0x31, 0x85, 0x10, 0x06, 0x95, 0x54, 0x79, 0x28, 0x79,
+ 0x56, 0x16, 0x65, 0x69, 0x00, 0x54, 0x09, 0x91, 0x06, 0x10, 0x10, 0x86,
+ 0x75, 0x01, 0x02, 0x71, 0x01, 0x09, 0x32, 0x94, 0x66, 0x43, 0x68, 0x36,
+ 0x19, 0x52, 0x02, 0x04, 0x45, 0x49, 0x40, 0x94, 0x07, 0x87, 0x86, 0x79,
+ 0x84, 0x07, 0x75, 0x30, 0x73, 0x02, 0x57, 0x81, 0x65, 0x02, 0x28, 0x96,
+ 0x57, 0x07, 0x70, 0x34, 0x39, 0x35, 0x75, 0x19, 0x47, 0x57, 0x08, 0x75,
+ 0x86, 0x57, 0x11, 0x32, 0x09, 0x47, 0x83, 0x93, 0x20, 0x94, 0x90, 0x88,
+ 0x39, 0x63, 0x22, 0x88, 0x54, 0x54, 0x95, 0x75, 0x67, 0x26, 0x02, 0x49,
+ 0x26, 0x17, 0x35, 0x16, 0x27, 0x65, 0x64, 0x26, 0x93, 0x92, 0x77, 0x85,
+ 0x84, 0x40, 0x59, 0x29, 0x49, 0x69, 0x94, 0x71, 0x72, 0x21, 0x55, 0x03,
+ 0x19, 0x74, 0x09, 0x40, 0x57, 0x68, 0x41, 0x19, 0x11, 0x21, 0x63, 0x56,
+ 0x29, 0x77, 0x57, 0x81, 0x44, 0x40, 0x76, 0x77, 0x02, 0x71, 0x66, 0x35,
+ 0x89, 0x02, 0x64, 0x51, 0x61, 0x02, 0x46, 0x91, 0x38, 0x93, 0x62, 0x57,
+ 0x18, 0x98, 0x12, 0x87, 0x29, 0x48, 0x65, 0x39, 0x99, 0x45, 0x54, 0x69,
+ 0x51, 0x16, 0x25, 0x75, 0x60, 0x70, 0x33, 0x72, 0x01, 0x60, 0x26, 0x51,
+ 0x44, 0x14, 0x39, 0x12, 0x95, 0x48, 0x87, 0x33, 0x90, 0x16, 0x42, 0x78,
+ 0x48, 0x58, 0x96, 0x93, 0x75, 0x23, 0x07, 0x13, 0x86, 0x07, 0x96, 0x30,
+ 0x22, 0x82, 0x91, 0x36, 0x72, 0x16, 0x48, 0x77, 0x64, 0x99, 0x07, 0x34,
+ 0x78, 0x60, 0x61, 0x13, 0x48, 0x93, 0x46, 0x62, 0x48, 0x38, 0x37, 0x96,
+ 0x58, 0x64, 0x39, 0x90, 0x69, 0x46, 0x81, 0x98, 0x61, 0x89, 0x15, 0x59,
+ 0x78, 0x98, 0x21, 0x34, 0x00, 0x69, 0x97, 0x80, 0x28, 0x81, 0x53, 0x49,
+ 0x79, 0x53, 0x92, 0x20, 0x29, 0x40, 0x70, 0x06, 0x09, 0x55, 0x99, 0x41,
+ 0x51, 0x35, 0x55, 0x27, 0x39, 0x06, 0x29, 0x83, 0x66, 0x03, 0x68, 0x14,
+ 0x11, 0x69, 0x95, 0x51, 0x71, 0x55, 0x24, 0x60, 0x52, 0x58, 0x88, 0x11,
+ 0x88, 0x25, 0x37, 0x86, 0x01, 0x52, 0x93, 0x52, 0x02, 0x24, 0x91, 0x58,
+ 0x56, 0x37, 0x50, 0x88, 0x39, 0x09, 0x61, 0x19, 0x08, 0x86, 0x29, 0x51,
+ 0x63, 0x38, 0x81, 0x14, 0x75, 0x75, 0x39, 0x99, 0x22, 0x04, 0x32, 0x63,
+ 0x14, 0x68, 0x41, 0x79, 0x09, 0x57, 0x87, 0x29, 0x26, 0x94, 0x05, 0x71,
+ 0x82, 0x41, 0x26, 0x98, 0x68, 0x18, 0x55, 0x42, 0x78, 0x05, 0x74, 0x17,
+ 0x34, 0x34, 0x07, 0x62, 0x94, 0x72, 0x21, 0x08, 0x54, 0x72, 0x21, 0x08,
+ 0x31, 0x53, 0x82, 0x35, 0x27, 0x40, 0x85, 0x77, 0x08, 0x52, 0x58, 0x48,
+ 0x03, 0x86, 0x65, 0x51, 0x96, 0x43, 0x89, 0x19, 0x15, 0x08, 0x49, 0x62,
+ 0x57, 0x46, 0x17, 0x68, 0x56, 0x04, 0x70, 0x63, 0x75, 0x88, 0x13, 0x27,
+ 0x87, 0x44, 0x46, 0x27, 0x02, 0x97, 0x71, 0x07, 0x40, 0x17, 0x24, 0x61,
+ 0x16, 0x94, 0x86, 0x85, 0x67, 0x58, 0x87, 0x92, 0x02, 0x84, 0x75, 0x19,
+ 0x43, 0x60, 0x68, 0x03, 0x54, 0x75, 0x33, 0x17, 0x97, 0x75, 0x12, 0x62,
+ 0x43, 0x08, 0x35, 0x75, 0x32, 0x21, 0x08, 0x82, 0x78, 0x04, 0x74, 0x09,
+ 0x13, 0x48, 0x63, 0x68, 0x67, 0x09, 0x08, 0x50, 0x11, 0x71, 0x64, 0x72,
+ 0x63, 0x76, 0x21, 0x62, 0x80, 0x57, 0x19, 0x15, 0x26, 0x88, 0x02, 0x26,
+ 0x83, 0x17, 0x61, 0x76, 0x28, 0x10, 0x22, 0x37, 0x56, 0x71, 0x51, 0x60,
+ 0x12, 0x79, 0x24, 0x83, 0x78, 0x47, 0x78, 0x20, 0x52, 0x27, 0x19, 0x88,
+ 0x81, 0x04, 0x70, 0x20, 0x25, 0x10, 0x04, 0x01, 0x72, 0x57, 0x30, 0x93,
+ 0x96, 0x23, 0x02, 0x94, 0x61, 0x44, 0x17, 0x65, 0x77, 0x60, 0x27, 0x43,
+ 0x24, 0x59, 0x46, 0x76, 0x00, 0x11, 0x31, 0x99, 0x41, 0x48, 0x75, 0x32,
+ 0x05, 0x15, 0x45, 0x31, 0x57, 0x89, 0x10, 0x47, 0x53, 0x14, 0x66, 0x54,
+ 0x60, 0x55, 0x36, 0x93, 0x30, 0x03, 0x63, 0x80, 0x65, 0x43, 0x17, 0x36,
+ 0x18, 0x64, 0x21, 0x38, 0x16, 0x19, 0x19, 0x51, 0x73, 0x80, 0x38, 0x27,
+ 0x30, 0x89, 0x13, 0x43, 0x54, 0x11, 0x78, 0x05, 0x24, 0x38, 0x83, 0x56,
+ 0x50, 0x59, 0x12, 0x47, 0x69, 0x70, 0x70, 0x91, 0x28, 0x02, 0x08, 0x91,
+ 0x66, 0x09, 0x31, 0x65, 0x46, 0x20, 0x04, 0x85, 0x89, 0x53, 0x91, 0x42,
+ 0x34, 0x09, 0x36, 0x92, 0x42, 0x06, 0x87, 0x88, 0x23, 0x54, 0x87, 0x85,
+ 0x52, 0x98, 0x95, 0x76, 0x13, 0x50, 0x59, 0x89, 0x18, 0x14, 0x17, 0x47,
+ 0x10, 0x97, 0x39, 0x14, 0x33, 0x79, 0x83, 0x62, 0x55, 0x18, 0x30, 0x83,
+ 0x03, 0x45, 0x38, 0x37, 0x35, 0x20, 0x94, 0x84, 0x89, 0x80, 0x89, 0x10,
+ 0x48, 0x77, 0x33, 0x36, 0x50, 0x07, 0x93, 0x02, 0x45, 0x42, 0x91, 0x12,
+ 0x98, 0x09, 0x77, 0x20, 0x31, 0x95, 0x10, 0x29, 0x89, 0x02, 0x38, 0x92,
+ 0x90, 0x19, 0x51, 0x10, 0x19, 0x82, 0x23, 0x68, 0x06, 0x00, 0x67, 0x50,
+ 0x25, 0x03, 0x41, 0x69, 0x53, 0x42, 0x23, 0x99, 0x29, 0x21, 0x63, 0x22,
+ 0x72, 0x54, 0x72, 0x40, 0x23, 0x39, 0x74, 0x92, 0x53, 0x28, 0x67, 0x56,
+ 0x46, 0x84, 0x59, 0x85, 0x10, 0x92, 0x31, 0x20, 0x39, 0x95, 0x65, 0x15,
+ 0x76, 0x35, 0x37, 0x21, 0x98, 0x41, 0x68, 0x74, 0x94, 0x94, 0x86, 0x90,
+ 0x35, 0x07, 0x06, 0x38, 0x78, 0x32, 0x00, 0x60, 0x86, 0x12, 0x34, 0x65,
+ 0x67, 0x35, 0x76, 0x94, 0x78, 0x22, 0x99, 0x42, 0x82, 0x40, 0x05, 0x74,
+ 0x18, 0x59, 0x03, 0x83, 0x89, 0x05, 0x19, 0x28, 0x88, 0x35, 0x59, 0x10,
+ 0x12, 0x96, 0x48, 0x67, 0x59, 0x87, 0x26, 0x85, 0x74, 0x64, 0x78, 0x56,
+ 0x91, 0x81, 0x45, 0x90, 0x21, 0x80, 0x32, 0x19, 0x61, 0x38, 0x61, 0x70,
+ 0x35, 0x08, 0x93, 0x53, 0x21, 0x95, 0x08, 0x27, 0x90, 0x28, 0x94, 0x27,
+ 0x35, 0x78, 0x03, 0x57, 0x74, 0x84, 0x73, 0x63, 0x27, 0x98, 0x14, 0x21,
+ 0x22, 0x36, 0x75, 0x31, 0x81, 0x65, 0x85, 0x51, 0x02, 0x45, 0x18, 0x06,
+ 0x39, 0x13, 0x29, 0x29, 0x73, 0x26, 0x99, 0x51, 0x38, 0x43, 0x35, 0x58,
+ 0x70, 0x92, 0x32, 0x13, 0x80, 0x16, 0x26, 0x44, 0x22, 0x28, 0x05, 0x45,
+ 0x86, 0x90, 0x38, 0x19, 0x40, 0x06, 0x30, 0x56, 0x94, 0x09, 0x02, 0x02,
+ 0x96, 0x29, 0x22, 0x44, 0x87, 0x38, 0x09, 0x95, 0x58, 0x46, 0x42, 0x78,
+ 0x72, 0x77, 0x86, 0x31, 0x97, 0x19, 0x86, 0x51, 0x73, 0x76, 0x63, 0x98,
+ 0x39, 0x40, 0x20, 0x20, 0x67, 0x42, 0x55, 0x50, 0x63, 0x76, 0x81, 0x87,
+ 0x13, 0x81, 0x19, 0x54, 0x11, 0x77, 0x90, 0x26, 0x47, 0x25, 0x92, 0x88,
+ 0x18, 0x56, 0x23, 0x73, 0x91, 0x52, 0x39, 0x08, 0x59, 0x51, 0x81, 0x57,
+ 0x78, 0x17, 0x13, 0x90, 0x90, 0x50, 0x65, 0x59, 0x99, 0x77, 0x42, 0x28,
+ 0x21, 0x59, 0x97, 0x64, 0x25, 0x17, 0x92, 0x24, 0x50, 0x00, 0x28, 0x40,
+ 0x85, 0x33, 0x78, 0x86, 0x79, 0x40, 0x28, 0x30, 0x14, 0x12, 0x01, 0x72,
+ 0x41, 0x43, 0x06, 0x87, 0x67, 0x31, 0x66, 0x77, 0x07, 0x50, 0x55, 0x50,
+ 0x22, 0x80, 0x42, 0x06, 0x38, 0x01, 0x63, 0x66, 0x70, 0x12, 0x52, 0x91,
+ 0x90, 0x97, 0x21, 0x28, 0x22, 0x65, 0x02, 0x80, 0x72, 0x31, 0x17, 0x76,
+ 0x35, 0x16, 0x03, 0x56, 0x59, 0x93, 0x36, 0x37, 0x67, 0x54, 0x46, 0x87,
+ 0x29, 0x01, 0x30, 0x80, 0x47, 0x47, 0x31, 0x98, 0x34, 0x30, 0x23, 0x86,
+ 0x86, 0x14, 0x05, 0x75, 0x09, 0x88, 0x77, 0x92, 0x59, 0x43, 0x98, 0x72,
+ 0x55, 0x54, 0x25, 0x59, 0x22, 0x27, 0x21, 0x62, 0x97, 0x10, 0x61, 0x73,
+ 0x86, 0x95, 0x99, 0x10, 0x62, 0x35, 0x25, 0x16, 0x62, 0x60, 0x51, 0x48,
+ 0x69, 0x69, 0x92, 0x27, 0x19, 0x43, 0x40, 0x52, 0x70, 0x23, 0x37, 0x28,
+ 0x73, 0x10, 0x32, 0x55, 0x85, 0x46, 0x97, 0x59, 0x88, 0x48, 0x54, 0x06,
+ 0x58, 0x04, 0x82, 0x98, 0x88, 0x34, 0x05, 0x41, 0x94, 0x44, 0x35, 0x10,
+ 0x96, 0x48, 0x21, 0x17, 0x24, 0x40, 0x26, 0x15, 0x49, 0x28, 0x12, 0x17,
+ 0x10, 0x17, 0x91, 0x42, 0x84, 0x15, 0x83, 0x36, 0x29, 0x49, 0x92, 0x77,
+ 0x74, 0x11, 0x72, 0x97, 0x64, 0x53, 0x23, 0x29, 0x16, 0x35, 0x22, 0x10,
+ 0x87, 0x07, 0x44, 0x78, 0x18, 0x19, 0x79, 0x03, 0x58, 0x24, 0x15, 0x63,
+ 0x55, 0x75, 0x56, 0x14, 0x63, 0x65, 0x86, 0x61, 0x92, 0x94, 0x30, 0x92,
+ 0x69, 0x78, 0x40, 0x95, 0x19, 0x81, 0x41, 0x66, 0x97, 0x00, 0x17, 0x37,
+ 0x20, 0x82, 0x14, 0x26, 0x42, 0x63, 0x84, 0x20, 0x96, 0x11, 0x68, 0x37,
+ 0x60, 0x28, 0x69, 0x85, 0x45, 0x04, 0x62, 0x20, 0x49, 0x39, 0x74, 0x84,
+ 0x60, 0x23, 0x38, 0x33, 0x42, 0x49, 0x38, 0x82, 0x30, 0x63, 0x21, 0x51,
+ 0x69, 0x09, 0x05, 0x55, 0x78, 0x90, 0x68, 0x69, 0x22, 0x20, 0x17, 0x26,
+ 0x54, 0x01, 0x10, 0x04, 0x68, 0x19, 0x88, 0x40, 0x91, 0x74, 0x81, 0x29,
+ 0x07, 0x45, 0x33, 0x77, 0x12, 0x47, 0x08, 0x60, 0x09, 0x42, 0x84, 0x15,
+ 0x63, 0x92, 0x64, 0x77, 0x07, 0x44, 0x11, 0x07, 0x79, 0x81, 0x24, 0x05,
+ 0x21, 0x60, 0x81, 0x70, 0x66, 0x36, 0x69, 0x68, 0x45, 0x01, 0x11, 0x95,
+ 0x67, 0x95, 0x55, 0x07, 0x96, 0x63, 0x84, 0x04, 0x74, 0x72, 0x61, 0x91,
+ 0x60, 0x09, 0x90, 0x14, 0x34, 0x94, 0x06, 0x12, 0x01, 0x94, 0x40, 0x14,
+ 0x12, 0x53, 0x64, 0x81, 0x75, 0x99, 0x36, 0x99, 0x11, 0x69, 0x95, 0x51,
+ 0x71, 0x55, 0x24, 0x60, 0x52, 0x58, 0x88, 0x11, 0x88, 0x25, 0x37, 0x86,
+ 0x66, 0x36, 0x69, 0x68, 0x45, 0x01, 0x11, 0x95
+};
+
+/* cipher text */
+uint8_t ciphertext[2048] = {
+ 0xE2, 0x19, 0x24, 0x56, 0x13, 0x59, 0xA6, 0x5D, 0xDF, 0xD0, 0x72, 0xAA,
+ 0x23, 0xC7, 0x36, 0x3A, 0xBB, 0x3E, 0x8B, 0x64, 0xD5, 0xBF, 0xDE, 0x65,
+ 0xA2, 0x75, 0xD9, 0x45, 0x6C, 0x3C, 0xD2, 0x6A, 0xC7, 0xD0, 0x9A, 0xD0,
+ 0x87, 0xB8, 0xE4, 0x94, 0x11, 0x62, 0x5A, 0xC3, 0xC3, 0x01, 0xA3, 0x86,
+ 0xBC, 0xBC, 0x9C, 0xC0, 0x81, 0x9F, 0xBF, 0x5C, 0x6F, 0x3F, 0x13, 0xF1,
+ 0xAE, 0xCF, 0x26, 0xB3, 0xBC, 0x49, 0xD6, 0x3B, 0x7A, 0x2E, 0x99, 0x9E,
+ 0x1B, 0x04, 0x50, 0x6C, 0x48, 0x6B, 0x4E, 0x72, 0xFC, 0xC8, 0xA7, 0x0C,
+ 0x2C, 0xD9, 0xED, 0xE4, 0x82, 0xC4, 0x81, 0xA6, 0xB4, 0xCC, 0xAD, 0x10,
+ 0xF3, 0x1C, 0x39, 0x05, 0x41, 0x2D, 0x57, 0x32, 0xE7, 0x16, 0xF8, 0x4D,
+ 0xF0, 0xDE, 0x40, 0x5B, 0x5F, 0x80, 0xDC, 0xA7, 0xC3, 0x2D, 0x3D, 0x9E,
+ 0x27, 0xD4, 0xE8, 0x10, 0x8E, 0xEB, 0xA5, 0x68, 0x6F, 0x3D, 0xC0, 0x44,
+ 0xE7, 0x77, 0x73, 0xB9, 0x92, 0x8E, 0xA2, 0x26, 0x5C, 0x6F, 0x33, 0x4B,
+ 0x0B, 0xEF, 0x37, 0x55, 0xBE, 0xEC, 0x98, 0x83, 0x1E, 0xDF, 0xB2, 0x9E,
+ 0x5D, 0x1D, 0x78, 0x14, 0xD7, 0x85, 0x0E, 0xF8, 0x12, 0x30, 0x8E, 0x5D,
+ 0x08, 0x77, 0x0B, 0x2E, 0x9B, 0xF9, 0xA6, 0x72, 0xD2, 0x41, 0xC1, 0x8E,
+ 0x6B, 0x5E, 0x11, 0x85, 0x22, 0x6E, 0xE4, 0xA3, 0xEA, 0x4C, 0x91, 0xE1,
+ 0x7D, 0xD0, 0xEB, 0x9F, 0xD9, 0xD7, 0x05, 0x77, 0xD9, 0xA1, 0xC2, 0xFD,
+ 0x41, 0x63, 0x51, 0xB4, 0x7A, 0x1F, 0x21, 0xF0, 0xBF, 0x11, 0x4D, 0x9B,
+ 0x97, 0xAB, 0xB4, 0x94, 0x36, 0x34, 0xC9, 0x2D, 0x8B, 0xE2, 0x61, 0xCF,
+ 0xAF, 0x69, 0xD5, 0x5C, 0xE9, 0xED, 0xE3, 0xA0, 0x69, 0xD3, 0xE5, 0xAE,
+ 0x67, 0x6C, 0xC7, 0x11, 0xB1, 0x21, 0x96, 0xD6, 0xDB, 0xA8, 0x1D, 0xC9,
+ 0x83, 0x0B, 0xE2, 0xC6, 0x6E, 0x94, 0xE9, 0x50, 0x12, 0x9B, 0x01, 0x72,
+ 0xAA, 0xFD, 0x8B, 0x7C, 0xEC, 0x0D, 0x01, 0xA4, 0x5D, 0x00, 0xE9, 0x79,
+ 0x58, 0xF5, 0x67, 0xF9, 0x61, 0xC3, 0x11, 0xB4, 0x7E, 0x76, 0x0A, 0x4C,
+ 0x60, 0xD6, 0xBD, 0xC8, 0x31, 0xD3, 0x0C, 0xD0, 0x5B, 0xDF, 0x7B, 0x05,
+ 0x9A, 0xBB, 0xC6, 0x2E, 0x9F, 0xF8, 0x18, 0x80, 0x6D, 0x1B, 0x21, 0xE5,
+ 0xAC, 0x75, 0xBC, 0x0D, 0x72, 0x51, 0x61, 0xD7, 0xEA, 0xA2, 0xAC, 0x0E,
+ 0xC1, 0xE7, 0x49, 0x37, 0xE7, 0x7C, 0xDE, 0xBD, 0x56, 0x00, 0x44, 0x6D,
+ 0xAB, 0x81, 0x2B, 0x26, 0x4A, 0xAA, 0x60, 0xE6, 0x43, 0x8D, 0x88, 0x1C,
+ 0x48, 0x55, 0x53, 0x25, 0xE8, 0x3C, 0x46, 0xF0, 0xA6, 0x33, 0x2D, 0xA2,
+ 0xDC, 0x99, 0x57, 0x38, 0x59, 0xCF, 0x53, 0xFA, 0x3E, 0x78, 0x46, 0xA0,
+ 0xA9, 0x50, 0x12, 0x72, 0xAC, 0x15, 0xC6, 0xA7, 0x42, 0x0F, 0x59, 0x6E,
+ 0xEA, 0xB0, 0x3D, 0xB8, 0x94, 0x32, 0xD1, 0xB6, 0xE8, 0x90, 0x06, 0x66,
+ 0x0C, 0xDE, 0xA9, 0x35, 0xC7, 0xDD, 0x72, 0x42, 0x38, 0x33, 0x32, 0x2F,
+ 0x2C, 0x3F, 0xBD, 0x01, 0xD6, 0x47, 0xFC, 0x89, 0x31, 0x38, 0x2E, 0xB9,
+ 0x6B, 0xED, 0xDB, 0x85, 0x38, 0xB1, 0xA5, 0x50, 0xFA, 0xFB, 0xA7, 0x31,
+ 0xEC, 0xB6, 0xBB, 0x82, 0x50, 0xB4, 0x88, 0x5C, 0xED, 0xE5, 0x4B, 0x5B,
+ 0xBF, 0xB3, 0x18, 0xFB, 0xAD, 0x24, 0x41, 0x55, 0x80, 0xCD, 0xA3, 0xA1,
+ 0xD6, 0xD5, 0xB6, 0x06, 0xE9, 0x85, 0x12, 0x33, 0x52, 0x56, 0xF1, 0xB7,
+ 0xDC, 0x57, 0x9E, 0xB4, 0x00, 0x1E, 0xCB, 0x62, 0x13, 0x4C, 0x90, 0x9A,
+ 0x9D, 0x64, 0x80, 0xD1, 0x5E, 0xB3, 0xCB, 0x8A, 0x73, 0x4E, 0x7B, 0xBE,
+ 0x4D, 0xA7, 0xF7, 0xB7, 0x9C, 0x1C, 0x7F, 0x27, 0x1E, 0x7F, 0x58, 0xB2,
+ 0x74, 0xAF, 0x94, 0x0E, 0x19, 0x23, 0xE1, 0x6B, 0xD8, 0x20, 0x4F, 0x2C,
+ 0x13, 0xE8, 0x8C, 0x37, 0x46, 0x27, 0x55, 0x68, 0xDA, 0x3F, 0x7A, 0xC6,
+ 0xEF, 0x87, 0x1D, 0x3B, 0x95, 0x43, 0x5E, 0x75, 0xE0, 0x02, 0x22, 0x0E,
+ 0x11, 0x60, 0xAB, 0x1A, 0x91, 0x94, 0xC4, 0xFA, 0xD9, 0x92, 0x2B, 0xE5,
+ 0x03, 0xE0, 0x7A, 0x17, 0x5C, 0x67, 0x22, 0xB3, 0xCB, 0x77, 0x9E, 0x22,
+ 0x01, 0x5F, 0x5D, 0x64, 0xE4, 0x2F, 0xC4, 0x61, 0xCA, 0xC7, 0xFD, 0x20,
+ 0x24, 0x30, 0xAB, 0x3F, 0x1A, 0x08, 0x85, 0x08, 0x39, 0xDE, 0x19, 0x1C,
+ 0x1A, 0xEA, 0xB8, 0x7E, 0xE5, 0xBC, 0xD9, 0xB2, 0x59, 0xC8, 0x81, 0x02,
+ 0x1D, 0x5C, 0xC0, 0xDD, 0x8D, 0x56, 0xB6, 0x2E, 0x85, 0x26, 0xA8, 0x34,
+ 0x92, 0x36, 0x9A, 0x84, 0xBD, 0x27, 0xC1, 0x9D, 0x5E, 0x14, 0xC4, 0xB7,
+ 0x02, 0xA8, 0xC9, 0xC2, 0xAD, 0xDC, 0x98, 0x42, 0x51, 0xDE, 0x94, 0x28,
+ 0x39, 0xEF, 0xE9, 0x7F, 0x05, 0x3F, 0x1D, 0x67, 0x72, 0x04, 0xCF, 0x7D,
+ 0x38, 0x49, 0xC4, 0x59, 0xA5, 0xF6, 0xB6, 0x02, 0x31, 0xD0, 0x05, 0x74,
+ 0x4B, 0xD0, 0x89, 0xD1, 0x7F, 0xC6, 0xDB, 0x7E, 0x75, 0x62, 0xA3, 0xC2,
+ 0x2E, 0xB0, 0xCC, 0x9A, 0xD3, 0xA4, 0x14, 0xB6, 0xF2, 0x91, 0x44, 0x3F,
+ 0x84, 0xE0, 0x90, 0x4A, 0x6A, 0x34, 0x8C, 0x35, 0x3C, 0xB2, 0xA9, 0x35,
+ 0x88, 0xB0, 0x88, 0xF8, 0x7E, 0x5C, 0xD2, 0x08, 0x5E, 0x08, 0x15, 0x03,
+ 0xBC, 0xF5, 0x42, 0x6B, 0x28, 0xED, 0xDD, 0xAA, 0x4D, 0x78, 0x10, 0x31,
+ 0x32, 0xA2, 0xC5, 0xCA, 0xEE, 0x9A, 0x62, 0x52, 0x3E, 0x48, 0x83, 0xA4,
+ 0xCA, 0xD4, 0xC7, 0xA7, 0xA5, 0x3F, 0x44, 0x1C, 0x86, 0xAD, 0x52, 0x7D,
+ 0x80, 0x1D, 0x9E, 0x32, 0x3F, 0x2A, 0x2E, 0xD8, 0x89, 0xC1, 0xA4, 0xD6,
+ 0xC1, 0x90, 0x2E, 0x1A, 0x20, 0x4B, 0x87, 0x32, 0x35, 0x25, 0xD8, 0xB8,
+ 0x57, 0x15, 0x85, 0x1E, 0x3C, 0x8A, 0xDC, 0x1A, 0x49, 0x3D, 0x70, 0x35,
+ 0x99, 0xAA, 0xDE, 0x2C, 0xD4, 0xAF, 0x79, 0x72, 0xAB, 0x97, 0x84, 0x20,
+ 0xB6, 0x4F, 0x34, 0x3F, 0xEA, 0xAE, 0x5F, 0x8F, 0x3A, 0x42, 0xDB, 0x68,
+ 0xE5, 0x84, 0x63, 0x2E, 0x7A, 0x0E, 0xBD, 0x28, 0x6A, 0x24, 0xB6, 0xAB,
+ 0xE4, 0xAC, 0x20, 0x7C, 0x81, 0xD0, 0x69, 0x89, 0xF8, 0xDE, 0xA9, 0x02,
+ 0xFD, 0x1F, 0x08, 0xDA, 0x26, 0xC2, 0x24, 0xCA, 0xEB, 0x44, 0x16, 0x8D,
+ 0x55, 0x5F, 0xB9, 0xA9, 0x5A, 0x18, 0x50, 0xB1, 0x54, 0xF1, 0xBF, 0x06,
+ 0xC2, 0xB0, 0x95, 0xC2, 0xAE, 0xE5, 0xBF, 0xB3, 0xFD, 0xC9, 0xBF, 0x75,
+ 0x42, 0x7D, 0xA0, 0xA8, 0x95, 0xF9, 0x62, 0x3B, 0x9C, 0x0D, 0x81, 0xF3,
+ 0x9C, 0xFC, 0x19, 0x5B, 0xF7, 0xD1, 0x9C, 0xF0, 0xAA, 0xFE, 0xEF, 0x35,
+ 0x1E, 0x81, 0x9E, 0x02, 0x46, 0x52, 0x9B, 0x99, 0x0D, 0x12, 0x8B, 0x71,
+ 0x6C, 0x32, 0xB5, 0x23, 0x17, 0x03, 0xC5, 0xB0, 0xA1, 0xC3, 0x4B, 0x10,
+ 0x01, 0x4D, 0x4C, 0x4A, 0x46, 0x8F, 0xD9, 0x79, 0xBB, 0x10, 0x44, 0xB0,
+ 0x3C, 0x7D, 0x46, 0xFD, 0x38, 0xDF, 0xAF, 0x6E, 0x58, 0x7D, 0xE1, 0xEB,
+ 0xBB, 0x8C, 0xDC, 0x79, 0xDA, 0x41, 0xD1, 0x8B, 0x0B, 0x11, 0x4F, 0xE5,
+ 0x1C, 0xC1, 0x59, 0xA7, 0x1E, 0x5A, 0xC1, 0xEE, 0x27, 0x33, 0xC8, 0x55,
+ 0xA9, 0x32, 0xEA, 0xF7, 0x45, 0xB0, 0x08, 0xE9, 0x32, 0xDF, 0x70, 0x24,
+ 0x82, 0xD3, 0x2A, 0x3E, 0x4F, 0x42, 0xB9, 0x25, 0x10, 0xD1, 0x73, 0xFA,
+ 0xFD, 0xC1, 0x84, 0xF2, 0xF7, 0x0E, 0xBC, 0x9D, 0x90, 0x39, 0xD7, 0xFD,
+ 0x45, 0x77, 0xBA, 0x29, 0xF9, 0x87, 0x45, 0xC1, 0x32, 0x44, 0xB0, 0x27,
+ 0x6B, 0xFC, 0x8A, 0xFE, 0x00, 0x6F, 0x61, 0x98, 0xD0, 0x60, 0xC8, 0x10,
+ 0xE5, 0xBC, 0x88, 0x13, 0x45, 0x44, 0xA5, 0xEB, 0x6E, 0xCB, 0x11, 0xAF,
+ 0x30, 0xDC, 0x8B, 0xF8, 0x30, 0x46, 0xDA, 0x76, 0xF1, 0xE5, 0x14, 0x51,
+ 0x8A, 0x02, 0x5A, 0x5A, 0xAA, 0x7B, 0x2D, 0x57, 0x0A, 0x5C, 0x73, 0xD1,
+ 0x88, 0xCE, 0xBE, 0x3D, 0x06, 0x3F, 0x48, 0x1D, 0x44, 0x24, 0x6F, 0x4F,
+ 0x7F, 0x6A, 0xF2, 0x16, 0x34, 0x35, 0x38, 0x73, 0x8A, 0xE5, 0x25, 0xF4,
+ 0x34, 0x9E, 0x5B, 0x40, 0x90, 0x04, 0x57, 0x1B, 0x57, 0x75, 0x8F, 0xEA,
+ 0x1C, 0xF8, 0x7A, 0x68, 0x01, 0x1C, 0x8D, 0xBA, 0xF4, 0xE3, 0xD3, 0x8F,
+ 0x7F, 0xE4, 0x50, 0x35, 0x6B, 0x6B, 0xF6, 0xFC, 0x5F, 0x9B, 0x98, 0x78,
+ 0x16, 0x68, 0x72, 0x74, 0x71, 0x78, 0x25, 0x68, 0xE5, 0x1E, 0x66, 0xE2,
+ 0x4E, 0xC8, 0xDB, 0x92, 0x8E, 0x88, 0x64, 0x74, 0xDE, 0xDB, 0x85, 0x56,
+ 0x9F, 0xF9, 0xC4, 0x29, 0x54, 0xA8, 0xFB, 0xBA, 0xEA, 0xAB, 0xC7, 0x49,
+ 0x5C, 0x6C, 0xD7, 0x61, 0x8C, 0xE2, 0x2B, 0xF5, 0xA0, 0xA8, 0xD2, 0x41,
+ 0xC0, 0x54, 0xAB, 0xA7, 0x56, 0x5C, 0xE7, 0xA5, 0xEA, 0xBC, 0x47, 0xD1,
+ 0x0D, 0xD9, 0xC0, 0xA9, 0xC4, 0xA7, 0x3E, 0xD1, 0x2B, 0x1E, 0x34, 0x31,
+ 0x36, 0x9D, 0xB9, 0x51, 0xD3, 0xAD, 0x29, 0xE6, 0x9B, 0xD8, 0x4B, 0x93,
+ 0x33, 0x2F, 0x30, 0xEF, 0x18, 0x90, 0x69, 0x11, 0x09, 0xEA, 0xBA, 0xE0,
+ 0x10, 0x93, 0x63, 0x71, 0xA8, 0x83, 0x59, 0xDB, 0xFC, 0x12, 0x22, 0x84,
+ 0xC7, 0x01, 0x20, 0x99, 0xEC, 0x59, 0xA9, 0xE6, 0x9B, 0x5B, 0x8B, 0xB8,
+ 0x68, 0x52, 0x61, 0x8B, 0x4E, 0xF3, 0x50, 0x69, 0xF1, 0x49, 0x9B, 0xAF,
+ 0x53, 0xAD, 0xA0, 0x9D, 0x23, 0xE0, 0xE0, 0xC4, 0x31, 0xE4, 0x8E, 0x1C,
+ 0x51, 0x14, 0xFC, 0x95, 0x9C, 0xA6, 0x34, 0x85, 0xB0, 0x36, 0xFC, 0x7A,
+ 0x53, 0x03, 0x31, 0x0E, 0xCB, 0x34, 0x3E, 0xDF, 0xD1, 0x71, 0xBC, 0xDB,
+ 0xA1, 0xAF, 0x59, 0x4A, 0x03, 0x19, 0xA7, 0x8E, 0xB5, 0x82, 0x15, 0x24,
+ 0x69, 0x68, 0xBD, 0x9C, 0x2E, 0xFA, 0x06, 0xB5, 0x70, 0xC5, 0x70, 0xC4,
+ 0x14, 0x99, 0x01, 0x49, 0xBD, 0x6E, 0xAE, 0x10, 0xA1, 0xE4, 0xEF, 0xDD,
+ 0xE5, 0x51, 0x22, 0x9D, 0xF7, 0x93, 0xAB, 0x41, 0xBD, 0x86, 0x7A, 0xCC,
+ 0x51, 0x94, 0xEC, 0x22, 0xBE, 0x0D, 0x67, 0xFD, 0xA3, 0xFD, 0xCF, 0xF8,
+ 0x74, 0x0A, 0x5E, 0x1C, 0x71, 0xAD, 0xB6, 0xD0, 0xD7, 0xF8, 0x71, 0x34,
+ 0xAB, 0x62, 0xE7, 0xA8, 0x6B, 0x8F, 0x1E, 0x43, 0x46, 0xA5, 0xE4, 0xB4,
+ 0x52, 0x81, 0x66, 0xB3, 0xE5, 0x10, 0x23, 0x21, 0x2B, 0x31, 0x0F, 0xB8,
+ 0xB6, 0xC5, 0xA5, 0xC9, 0x90, 0x07, 0x83, 0xD0, 0xC3, 0x10, 0x7A, 0x04,
+ 0xBD, 0x8A, 0x3C, 0x7B, 0xF9, 0x0E, 0x51, 0x81, 0x96, 0xC8, 0xAE, 0xF9,
+ 0x27, 0xDE, 0x62, 0x7A, 0x41, 0x60, 0x35, 0x8F, 0x77, 0xBC, 0x95, 0x11,
+ 0x2C, 0xC4, 0x6C, 0x47, 0x7A, 0xEB, 0x29, 0xE5, 0x8E, 0xB5, 0xD6, 0xA5,
+ 0x54, 0x1B, 0xD0, 0xE0, 0x0F, 0x7D, 0x5C, 0x51, 0xD8, 0x6C, 0x92, 0x2F,
+ 0x13, 0x4E, 0x90, 0x77, 0xF8, 0x8D, 0x69, 0x78, 0x96, 0x96, 0x49, 0x9F,
+ 0x3C, 0x2E, 0x5C, 0xA6, 0x73, 0x27, 0x7D, 0xAD, 0x8D, 0xE3, 0x9B, 0x4A,
+ 0x2F, 0x50, 0x0A, 0x42, 0x7E, 0xF2, 0x3B, 0x50, 0x5C, 0x81, 0xC9, 0x49,
+ 0x01, 0x96, 0x83, 0x0A, 0xEC, 0x7F, 0xED, 0x1C, 0xA5, 0x7D, 0xF1, 0xE6,
+ 0xC4, 0xB3, 0x8F, 0xF9, 0x0F, 0xDB, 0x7B, 0xC1, 0x35, 0xF7, 0x63, 0x4A,
+ 0x39, 0xD4, 0x0E, 0x9E, 0x05, 0xD9, 0x42, 0xAA, 0xAB, 0x52, 0xCA, 0x4E,
+ 0x98, 0x3B, 0x43, 0x1A, 0x91, 0x25, 0xA9, 0x34, 0xD5, 0x66, 0xB2, 0xF4,
+ 0xFF, 0xDE, 0x64, 0x91, 0x90, 0xB9, 0x17, 0x70, 0xA0, 0xD6, 0xEA, 0xB6,
+ 0x36, 0xF4, 0x44, 0xCE, 0x86, 0x7B, 0x18, 0x74, 0x9C, 0x18, 0xAD, 0xB6,
+ 0xE0, 0x74, 0xC1, 0x0E, 0x29, 0x5D, 0x6A, 0x36, 0xD1, 0x3E, 0xB8, 0x2A,
+ 0xE4, 0x23, 0x1D, 0xB2, 0xAE, 0xF5, 0x5B, 0x8E, 0x2C, 0xD9, 0xD1, 0xE1,
+ 0x4F, 0x58, 0xA6, 0xE3, 0x88, 0x2E, 0xF9, 0xCF, 0x32, 0x3E, 0x8E, 0x37,
+ 0x95, 0xFF, 0xAD, 0x68, 0x11, 0x5E, 0x7F, 0x3D, 0x38, 0x06, 0x7C, 0x33,
+ 0x32, 0x78, 0x09, 0xEC, 0xCA, 0x3E, 0x08, 0xF1, 0xD0, 0x95, 0x19, 0xC9,
+ 0x7E, 0x62, 0xB2, 0x02, 0xA3, 0x5D, 0xF8, 0x3F, 0xA2, 0xB0, 0x8B, 0x38,
+ 0xB1, 0x8C, 0xEA, 0xB3, 0xE4, 0xBF, 0xD3, 0x6C, 0x6D, 0x3D, 0xD1, 0xC6,
+ 0xDA, 0x6B, 0x7A, 0xBA, 0x05, 0xEA, 0x9E, 0xA5, 0xE9, 0x00, 0xCC, 0x80,
+ 0x57, 0xAB, 0xD9, 0x0A, 0xD1, 0x00, 0x82, 0x2A, 0x51, 0x4B, 0xA2, 0x96,
+ 0xEB, 0x96, 0x14, 0xA8, 0x46, 0xDF, 0x1D, 0x48, 0xAE, 0xFA, 0x12, 0xA8,
+ 0x89, 0x8E, 0xEF, 0xBC, 0x3C, 0xA1, 0x6E, 0xDD, 0x90, 0x66, 0x2E, 0x56,
+ 0x6B, 0xF7, 0x1D, 0xF0, 0x46, 0x11, 0x4A, 0xA6, 0x07, 0x73, 0xC4, 0xE3,
+ 0x97, 0xFE, 0x7E, 0x22, 0x6F, 0x22, 0xB4, 0x6F, 0xB0, 0x32, 0x0A, 0x5E,
+ 0x85, 0x7E, 0x54, 0xB4, 0x24, 0xBD, 0x36, 0xA7, 0x94, 0xE7, 0x37, 0xFD,
+ 0x1A, 0xAF, 0xF4, 0x44, 0xB4, 0x35, 0x4F, 0xE0, 0x41, 0x0E, 0x7D, 0x73,
+ 0x29, 0x28, 0xDA, 0xAF, 0x69, 0xB2, 0xC5, 0xA7, 0x2A, 0x0A, 0xB5, 0x9C,
+ 0xC2, 0xAC, 0x5F, 0x59, 0x5C, 0xEE, 0x44, 0x49, 0x6F, 0x4F, 0x64, 0x43,
+ 0x6F, 0x43, 0x44, 0xAA, 0xA0, 0x4E, 0x94, 0x7C, 0x26, 0x5A, 0xF1, 0xD9,
+ 0xE6, 0x09, 0x80, 0x7A, 0x7D, 0x2E, 0xA2, 0xB9, 0x1A, 0x7A, 0x8F, 0x2A,
+ 0x97, 0x77, 0x23, 0xB4, 0x10, 0xAD, 0x20, 0x7B, 0xA3, 0x0F, 0xFD, 0x44,
+ 0x38, 0xAD, 0x94, 0x39, 0x88, 0x1C, 0xC4, 0xC8, 0xDF, 0xF1, 0x04, 0xA6,
+ 0x51, 0x5D, 0x54, 0x53, 0x60, 0xE4, 0x8A, 0x89, 0x4A, 0x9C, 0xE1, 0x68,
+ 0x4D, 0xFE, 0x69, 0x94, 0x0B, 0x8E, 0xED, 0x6C, 0xFE, 0x11, 0xA7, 0x77,
+ 0xBF, 0x08, 0x41, 0x67, 0x22, 0x59, 0x51, 0x48, 0xEE, 0x59, 0x02, 0x0E,
+ 0x60, 0x6D, 0xAE, 0x8C, 0xC6, 0x39, 0xB7, 0x55, 0xC5, 0x3B, 0x87, 0xA9,
+ 0xBD, 0xD8, 0xEA, 0x48, 0x21, 0xE4, 0x57, 0x51, 0x56, 0x03, 0xF4, 0xBE,
+ 0xBD, 0xBD, 0xC5, 0x26, 0x9B, 0x27, 0xE3, 0xAE, 0xD5, 0x1E, 0x30, 0xE9,
+ 0x7C, 0x9D, 0xDB, 0xE1, 0x09, 0x9D, 0x82, 0x49, 0x15, 0x38, 0x69, 0xFC,
+ 0x1D, 0x52, 0x1A, 0x75, 0xE6, 0xDD, 0x1D, 0xBE, 0x06, 0xC4, 0x9F, 0x14,
+ 0x4C, 0x12, 0xDE, 0xDF, 0x4A, 0xE1, 0x3B, 0xE7, 0xD1, 0xE3, 0x71, 0xD1,
+ 0xFA, 0xD8, 0x0E, 0x63, 0x27, 0xA9, 0xC7, 0x9D, 0xC0, 0x01, 0xC2, 0xDD,
+ 0xFC, 0xA6, 0x1F, 0x59, 0x87, 0xC5, 0x56, 0x99, 0x80, 0xEB, 0xF0, 0xB8,
+ 0xB3, 0x00, 0x9A, 0x61, 0xDB, 0x50, 0x79, 0x48, 0x37, 0x35, 0xDA, 0xD8,
+ 0xF2, 0x37, 0xA7, 0x43, 0xA7, 0xEB, 0x88, 0x2C, 0x68, 0xB4, 0xBB, 0x14,
+ 0x45, 0x31, 0x6B, 0x87, 0x65, 0xE7, 0x82, 0xB4, 0x74, 0xD2, 0xFF, 0x7F,
+ 0x60, 0x15, 0x94, 0x75, 0xEE, 0x30, 0x3C, 0x4E, 0xFC, 0x41, 0xD1, 0x5B,
+ 0xDD, 0x84, 0x6E, 0x13, 0x6C, 0xF8, 0x12, 0xE6, 0xB7, 0xA4, 0xB9, 0xC8,
+ 0x13, 0x89, 0x0C, 0x34, 0xA6, 0xAF, 0x09, 0xEB, 0xF2, 0xB3, 0x79, 0x77,
+ 0x80, 0xD8, 0x77, 0x64, 0xAD, 0x32, 0x3D, 0xD2, 0x06, 0xDF, 0x72, 0x11,
+ 0x4A, 0xA7, 0x70, 0xCE, 0xF9, 0xE6, 0x81, 0x35, 0xA4, 0xA7, 0x52, 0xB5,
+ 0x13, 0x68, 0x5C, 0x69, 0x45, 0xE2, 0x77, 0x2D, 0xBE, 0x2C, 0xE9, 0x38,
+ 0x25, 0x28, 0x7B, 0x63, 0x2C, 0x19, 0x8F, 0x59
+};
+
+/* aad */
+uint8_t aad[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B
+};
+
+/* iv */
+uint8_t iv[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F
+};
+
+/* cipher key */
+uint8_t cipher_key[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
+};
+
+/* auth key */
+uint8_t auth_key[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23,
+ 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
+ 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53,
+ 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B,
+ 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F
+};
+
+/* Digests */
+uint8_t digest[2048] = { 0x00 };
+
+struct cperf_test_vector*
+cperf_test_vector_get_dummy(struct cperf_options *options)
+{
+ struct cperf_test_vector *t_vec;
+
+ t_vec = (struct cperf_test_vector *)rte_malloc(NULL,
+ sizeof(struct cperf_test_vector), 0);
+ if (t_vec == NULL)
+ return t_vec;
+
+ t_vec->plaintext.data = plaintext;
+ t_vec->plaintext.length = options->max_buffer_size;
+
+ if (options->op_type == CPERF_CIPHER_ONLY ||
+ options->op_type == CPERF_CIPHER_THEN_AUTH ||
+ options->op_type == CPERF_AUTH_THEN_CIPHER ||
+ options->op_type == CPERF_AEAD) {
+ if (options->cipher_algo == RTE_CRYPTO_CIPHER_NULL) {
+ t_vec->cipher_key.length = 0;
+ t_vec->ciphertext.data = plaintext;
+ t_vec->cipher_key.data = NULL;
+ t_vec->iv.data = NULL;
+ } else {
+ t_vec->cipher_key.length = options->cipher_key_sz;
+ t_vec->ciphertext.data = ciphertext;
+ t_vec->cipher_key.data = cipher_key;
+ t_vec->iv.data = rte_malloc(NULL, options->cipher_iv_sz,
+ 16);
+ if (t_vec->iv.data == NULL) {
+ rte_free(t_vec);
+ return NULL;
+ }
+ memcpy(t_vec->iv.data, iv, options->cipher_iv_sz);
+ }
+ t_vec->ciphertext.length = options->max_buffer_size;
+ t_vec->iv.phys_addr = rte_malloc_virt2phy(t_vec->iv.data);
+ t_vec->iv.length = options->cipher_iv_sz;
+ t_vec->data.cipher_offset = 0;
+ t_vec->data.cipher_length = options->max_buffer_size;
+ }
+
+ if (options->op_type == CPERF_AUTH_ONLY ||
+ options->op_type == CPERF_CIPHER_THEN_AUTH ||
+ options->op_type == CPERF_AUTH_THEN_CIPHER ||
+ options->op_type == CPERF_AEAD) {
+ uint8_t aad_alloc = 0;
+
+ t_vec->auth_key.length = options->auth_key_sz;
+
+ switch (options->auth_algo) {
+ case RTE_CRYPTO_AUTH_NULL:
+ t_vec->auth_key.data = NULL;
+ aad_alloc = 0;
+ break;
+ case RTE_CRYPTO_AUTH_AES_GCM:
+ t_vec->auth_key.data = NULL;
+ aad_alloc = 1;
+ break;
+ case RTE_CRYPTO_AUTH_SNOW3G_UIA2:
+ case RTE_CRYPTO_AUTH_KASUMI_F9:
+ case RTE_CRYPTO_AUTH_ZUC_EIA3:
+ t_vec->auth_key.data = auth_key;
+ aad_alloc = 1;
+ break;
+ case RTE_CRYPTO_AUTH_AES_GMAC:
+ /* auth key should be the same as cipher key */
+ t_vec->auth_key.data = cipher_key;
+ aad_alloc = 1;
+ break;
+ default:
+ t_vec->auth_key.data = auth_key;
+ aad_alloc = 0;
+ break;
+ }
+
+ if (aad_alloc && options->auth_aad_sz) {
+ t_vec->aad.data = rte_malloc(NULL,
+ options->auth_aad_sz, 16);
+ if (t_vec->aad.data == NULL) {
+ if (options->op_type != CPERF_AUTH_ONLY)
+ rte_free(t_vec->iv.data);
+ rte_free(t_vec);
+ return NULL;
+ }
+ memcpy(t_vec->aad.data, aad, options->auth_aad_sz);
+ } else {
+ t_vec->aad.data = NULL;
+ }
+
+ t_vec->aad.phys_addr = rte_malloc_virt2phy(t_vec->aad.data);
+ t_vec->aad.length = options->auth_aad_sz;
+ t_vec->digest.data = rte_malloc(NULL, options->auth_digest_sz,
+ 16);
+ if (t_vec->digest.data == NULL) {
+ if (options->op_type != CPERF_AUTH_ONLY)
+ rte_free(t_vec->iv.data);
+ rte_free(t_vec->aad.data);
+ rte_free(t_vec);
+ return NULL;
+ }
+ t_vec->digest.phys_addr =
+ rte_malloc_virt2phy(t_vec->digest.data);
+ t_vec->digest.length = options->auth_digest_sz;
+ memcpy(t_vec->digest.data, digest, options->auth_digest_sz);
+ t_vec->data.auth_offset = 0;
+ t_vec->data.auth_length = options->max_buffer_size;
+ }
+
+ return t_vec;
+}
diff --git a/src/seastar/dpdk/app/test-crypto-perf/cperf_test_vectors.h b/src/seastar/dpdk/app/test-crypto-perf/cperf_test_vectors.h
new file mode 100644
index 00000000..e64f1168
--- /dev/null
+++ b/src/seastar/dpdk/app/test-crypto-perf/cperf_test_vectors.h
@@ -0,0 +1,98 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016-2017 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _CPERF_TEST_VECTRORS_
+#define _CPERF_TEST_VECTRORS_
+
+#include "cperf_options.h"
+
+struct cperf_test_vector {
+ struct {
+ uint8_t *data;
+ uint32_t length;
+ } plaintext;
+
+ struct {
+ uint8_t *data;
+ uint16_t length;
+ } cipher_key;
+
+ struct {
+ uint8_t *data;
+ uint16_t length;
+ } auth_key;
+
+ struct {
+ uint8_t *data;
+ phys_addr_t phys_addr;
+ uint16_t length;
+ } iv;
+
+ struct {
+ uint8_t *data;
+ uint32_t length;
+ } ciphertext;
+
+ struct {
+ uint8_t *data;
+ phys_addr_t phys_addr;
+ uint16_t length;
+ } aad;
+
+ struct {
+ uint8_t *data;
+ phys_addr_t phys_addr;
+ uint16_t length;
+ } digest;
+
+ struct {
+ uint32_t auth_offset;
+ uint32_t auth_length;
+ uint32_t cipher_offset;
+ uint32_t cipher_length;
+ } data;
+};
+
+struct cperf_test_vector*
+cperf_test_vector_get_dummy(struct cperf_options *options);
+
+extern uint8_t ciphertext[2048];
+
+extern uint8_t cipher_key[];
+extern uint8_t auth_key[];
+
+extern uint8_t iv[];
+extern uint8_t aad[];
+
+extern uint8_t digest[2048];
+
+#endif
diff --git a/src/seastar/dpdk/app/test-crypto-perf/cperf_test_verify.c b/src/seastar/dpdk/app/test-crypto-perf/cperf_test_verify.c
new file mode 100644
index 00000000..454221e6
--- /dev/null
+++ b/src/seastar/dpdk/app/test-crypto-perf/cperf_test_verify.c
@@ -0,0 +1,579 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016-2017 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rte_malloc.h>
+#include <rte_cycles.h>
+#include <rte_crypto.h>
+#include <rte_cryptodev.h>
+
+#include "cperf_test_verify.h"
+#include "cperf_ops.h"
+
+struct cperf_verify_ctx {
+ uint8_t dev_id;
+ uint16_t qp_id;
+ uint8_t lcore_id;
+
+ struct rte_mempool *pkt_mbuf_pool_in;
+ struct rte_mempool *pkt_mbuf_pool_out;
+ struct rte_mbuf **mbufs_in;
+ struct rte_mbuf **mbufs_out;
+
+ struct rte_mempool *crypto_op_pool;
+
+ struct rte_cryptodev_sym_session *sess;
+
+ cperf_populate_ops_t populate_ops;
+
+ const struct cperf_options *options;
+ const struct cperf_test_vector *test_vector;
+};
+
+struct cperf_op_result {
+ enum rte_crypto_op_status status;
+};
+
+static void
+cperf_verify_test_free(struct cperf_verify_ctx *ctx, uint32_t mbuf_nb)
+{
+ uint32_t i;
+
+ if (ctx) {
+ if (ctx->sess)
+ rte_cryptodev_sym_session_free(ctx->dev_id, ctx->sess);
+
+ if (ctx->mbufs_in) {
+ for (i = 0; i < mbuf_nb; i++)
+ rte_pktmbuf_free(ctx->mbufs_in[i]);
+
+ rte_free(ctx->mbufs_in);
+ }
+
+ if (ctx->mbufs_out) {
+ for (i = 0; i < mbuf_nb; i++) {
+ if (ctx->mbufs_out[i] != NULL)
+ rte_pktmbuf_free(ctx->mbufs_out[i]);
+ }
+
+ rte_free(ctx->mbufs_out);
+ }
+
+ if (ctx->pkt_mbuf_pool_in)
+ rte_mempool_free(ctx->pkt_mbuf_pool_in);
+
+ if (ctx->pkt_mbuf_pool_out)
+ rte_mempool_free(ctx->pkt_mbuf_pool_out);
+
+ if (ctx->crypto_op_pool)
+ rte_mempool_free(ctx->crypto_op_pool);
+
+ rte_free(ctx);
+ }
+}
+
+static struct rte_mbuf *
+cperf_mbuf_create(struct rte_mempool *mempool,
+ uint32_t segments_nb,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector)
+{
+ struct rte_mbuf *mbuf;
+ uint32_t segment_sz = options->max_buffer_size / segments_nb;
+ uint32_t last_sz = options->max_buffer_size % segments_nb;
+ uint8_t *mbuf_data;
+ uint8_t *test_data =
+ (options->cipher_op == RTE_CRYPTO_CIPHER_OP_ENCRYPT) ?
+ test_vector->plaintext.data :
+ test_vector->ciphertext.data;
+
+ mbuf = rte_pktmbuf_alloc(mempool);
+ if (mbuf == NULL)
+ goto error;
+
+ mbuf_data = (uint8_t *)rte_pktmbuf_append(mbuf, segment_sz);
+ if (mbuf_data == NULL)
+ goto error;
+
+ memcpy(mbuf_data, test_data, segment_sz);
+ test_data += segment_sz;
+ segments_nb--;
+
+ while (segments_nb) {
+ struct rte_mbuf *m;
+
+ m = rte_pktmbuf_alloc(mempool);
+ if (m == NULL)
+ goto error;
+
+ rte_pktmbuf_chain(mbuf, m);
+
+ mbuf_data = (uint8_t *)rte_pktmbuf_append(mbuf, segment_sz);
+ if (mbuf_data == NULL)
+ goto error;
+
+ memcpy(mbuf_data, test_data, segment_sz);
+ test_data += segment_sz;
+ segments_nb--;
+ }
+
+ if (last_sz) {
+ mbuf_data = (uint8_t *)rte_pktmbuf_append(mbuf, last_sz);
+ if (mbuf_data == NULL)
+ goto error;
+
+ memcpy(mbuf_data, test_data, last_sz);
+ }
+
+ if (options->op_type != CPERF_CIPHER_ONLY) {
+ mbuf_data = (uint8_t *)rte_pktmbuf_append(mbuf,
+ options->auth_digest_sz);
+ if (mbuf_data == NULL)
+ goto error;
+ }
+
+ if (options->op_type == CPERF_AEAD) {
+ uint8_t *aead = (uint8_t *)rte_pktmbuf_prepend(mbuf,
+ RTE_ALIGN_CEIL(options->auth_aad_sz, 16));
+
+ if (aead == NULL)
+ goto error;
+
+ memcpy(aead, test_vector->aad.data, test_vector->aad.length);
+ }
+
+ return mbuf;
+error:
+ if (mbuf != NULL)
+ rte_pktmbuf_free(mbuf);
+
+ return NULL;
+}
+
+void *
+cperf_verify_test_constructor(uint8_t dev_id, uint16_t qp_id,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector,
+ const struct cperf_op_fns *op_fns)
+{
+ struct cperf_verify_ctx *ctx = NULL;
+ unsigned int mbuf_idx = 0;
+ char pool_name[32] = "";
+
+ ctx = rte_malloc(NULL, sizeof(struct cperf_verify_ctx), 0);
+ if (ctx == NULL)
+ goto err;
+
+ ctx->dev_id = dev_id;
+ ctx->qp_id = qp_id;
+
+ ctx->populate_ops = op_fns->populate_ops;
+ ctx->options = options;
+ ctx->test_vector = test_vector;
+
+ ctx->sess = op_fns->sess_create(dev_id, options, test_vector);
+ if (ctx->sess == NULL)
+ goto err;
+
+ snprintf(pool_name, sizeof(pool_name), "cperf_pool_in_cdev_%d",
+ dev_id);
+
+ ctx->pkt_mbuf_pool_in = rte_pktmbuf_pool_create(pool_name,
+ options->pool_sz * options->segments_nb, 0, 0,
+ RTE_PKTMBUF_HEADROOM +
+ RTE_CACHE_LINE_ROUNDUP(
+ (options->max_buffer_size / options->segments_nb) +
+ (options->max_buffer_size % options->segments_nb) +
+ options->auth_digest_sz),
+ rte_socket_id());
+
+ if (ctx->pkt_mbuf_pool_in == NULL)
+ goto err;
+
+ /* Generate mbufs_in with plaintext populated for test */
+ ctx->mbufs_in = rte_malloc(NULL,
+ (sizeof(struct rte_mbuf *) * ctx->options->pool_sz), 0);
+
+ for (mbuf_idx = 0; mbuf_idx < options->pool_sz; mbuf_idx++) {
+ ctx->mbufs_in[mbuf_idx] = cperf_mbuf_create(
+ ctx->pkt_mbuf_pool_in, options->segments_nb,
+ options, test_vector);
+ if (ctx->mbufs_in[mbuf_idx] == NULL)
+ goto err;
+ }
+
+ if (options->out_of_place == 1) {
+
+ snprintf(pool_name, sizeof(pool_name), "cperf_pool_out_cdev_%d",
+ dev_id);
+
+ ctx->pkt_mbuf_pool_out = rte_pktmbuf_pool_create(
+ pool_name, options->pool_sz, 0, 0,
+ RTE_PKTMBUF_HEADROOM +
+ RTE_CACHE_LINE_ROUNDUP(
+ options->max_buffer_size +
+ options->auth_digest_sz),
+ rte_socket_id());
+
+ if (ctx->pkt_mbuf_pool_out == NULL)
+ goto err;
+ }
+
+ ctx->mbufs_out = rte_malloc(NULL,
+ (sizeof(struct rte_mbuf *) *
+ ctx->options->pool_sz), 0);
+
+ for (mbuf_idx = 0; mbuf_idx < options->pool_sz; mbuf_idx++) {
+ if (options->out_of_place == 1) {
+ ctx->mbufs_out[mbuf_idx] = cperf_mbuf_create(
+ ctx->pkt_mbuf_pool_out, 1,
+ options, test_vector);
+ if (ctx->mbufs_out[mbuf_idx] == NULL)
+ goto err;
+ } else {
+ ctx->mbufs_out[mbuf_idx] = NULL;
+ }
+ }
+
+ snprintf(pool_name, sizeof(pool_name), "cperf_op_pool_cdev_%d",
+ dev_id);
+
+ ctx->crypto_op_pool = rte_crypto_op_pool_create(pool_name,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC, options->pool_sz, 0, 0,
+ rte_socket_id());
+ if (ctx->crypto_op_pool == NULL)
+ goto err;
+
+ return ctx;
+err:
+ cperf_verify_test_free(ctx, mbuf_idx);
+
+ return NULL;
+}
+
+static int
+cperf_verify_op(struct rte_crypto_op *op,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *vector)
+{
+ const struct rte_mbuf *m;
+ uint32_t len;
+ uint16_t nb_segs;
+ uint8_t *data;
+ uint32_t cipher_offset, auth_offset;
+ uint8_t cipher, auth;
+ int res = 0;
+
+ if (op->status != RTE_CRYPTO_OP_STATUS_SUCCESS)
+ return 1;
+
+ if (op->sym->m_dst)
+ m = op->sym->m_dst;
+ else
+ m = op->sym->m_src;
+ nb_segs = m->nb_segs;
+ len = 0;
+ while (m && nb_segs != 0) {
+ len += m->data_len;
+ m = m->next;
+ nb_segs--;
+ }
+
+ data = rte_malloc(NULL, len, 0);
+ if (data == NULL)
+ return 1;
+
+ if (op->sym->m_dst)
+ m = op->sym->m_dst;
+ else
+ m = op->sym->m_src;
+ nb_segs = m->nb_segs;
+ len = 0;
+ while (m && nb_segs != 0) {
+ memcpy(data + len, rte_pktmbuf_mtod(m, uint8_t *),
+ m->data_len);
+ len += m->data_len;
+ m = m->next;
+ nb_segs--;
+ }
+
+ switch (options->op_type) {
+ case CPERF_CIPHER_ONLY:
+ cipher = 1;
+ cipher_offset = 0;
+ auth = 0;
+ auth_offset = 0;
+ break;
+ case CPERF_CIPHER_THEN_AUTH:
+ cipher = 1;
+ cipher_offset = 0;
+ auth = 1;
+ auth_offset = options->test_buffer_size;
+ break;
+ case CPERF_AUTH_ONLY:
+ cipher = 0;
+ cipher_offset = 0;
+ auth = 1;
+ auth_offset = options->test_buffer_size;
+ break;
+ case CPERF_AUTH_THEN_CIPHER:
+ cipher = 1;
+ cipher_offset = 0;
+ auth = 1;
+ auth_offset = options->test_buffer_size;
+ break;
+ case CPERF_AEAD:
+ cipher = 1;
+ cipher_offset = vector->aad.length;
+ auth = 1;
+ auth_offset = vector->aad.length + options->test_buffer_size;
+ break;
+ }
+
+ if (cipher == 1) {
+ if (options->cipher_op == RTE_CRYPTO_CIPHER_OP_ENCRYPT)
+ res += memcmp(data + cipher_offset,
+ vector->ciphertext.data,
+ options->test_buffer_size);
+ else
+ res += memcmp(data + cipher_offset,
+ vector->plaintext.data,
+ options->test_buffer_size);
+ }
+
+ if (auth == 1) {
+ if (options->auth_op == RTE_CRYPTO_AUTH_OP_GENERATE)
+ res += memcmp(data + auth_offset,
+ vector->digest.data,
+ options->auth_digest_sz);
+ }
+
+ return !!res;
+}
+
+int
+cperf_verify_test_runner(void *test_ctx)
+{
+ struct cperf_verify_ctx *ctx = test_ctx;
+
+ uint64_t ops_enqd = 0, ops_enqd_total = 0, ops_enqd_failed = 0;
+ uint64_t ops_deqd = 0, ops_deqd_total = 0, ops_deqd_failed = 0;
+ uint64_t ops_failed = 0;
+
+ static int only_once;
+
+ uint64_t i, m_idx = 0;
+ uint16_t ops_unused = 0;
+
+ struct rte_crypto_op *ops[ctx->options->max_burst_size];
+ struct rte_crypto_op *ops_processed[ctx->options->max_burst_size];
+
+ uint32_t lcore = rte_lcore_id();
+
+#ifdef CPERF_LINEARIZATION_ENABLE
+ struct rte_cryptodev_info dev_info;
+ int linearize = 0;
+
+ /* Check if source mbufs require coalescing */
+ if (ctx->options->segments_nb > 1) {
+ rte_cryptodev_info_get(ctx->dev_id, &dev_info);
+ if ((dev_info.feature_flags &
+ RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER) == 0)
+ linearize = 1;
+ }
+#endif /* CPERF_LINEARIZATION_ENABLE */
+
+ ctx->lcore_id = lcore;
+
+ if (!ctx->options->csv)
+ printf("\n# Running verify test on device: %u, lcore: %u\n",
+ ctx->dev_id, lcore);
+
+ while (ops_enqd_total < ctx->options->total_ops) {
+
+ uint16_t burst_size = ((ops_enqd_total + ctx->options->max_burst_size)
+ <= ctx->options->total_ops) ?
+ ctx->options->max_burst_size :
+ ctx->options->total_ops -
+ ops_enqd_total;
+
+ uint16_t ops_needed = burst_size - ops_unused;
+
+ /* Allocate crypto ops from pool */
+ if (ops_needed != rte_crypto_op_bulk_alloc(
+ ctx->crypto_op_pool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ ops, ops_needed))
+ return -1;
+
+ /* Setup crypto op, attach mbuf etc */
+ (ctx->populate_ops)(ops, &ctx->mbufs_in[m_idx],
+ &ctx->mbufs_out[m_idx],
+ ops_needed, ctx->sess, ctx->options,
+ ctx->test_vector);
+
+#ifdef CPERF_LINEARIZATION_ENABLE
+ if (linearize) {
+ /* PMD doesn't support scatter-gather and source buffer
+ * is segmented.
+ * We need to linearize it before enqueuing.
+ */
+ for (i = 0; i < burst_size; i++)
+ rte_pktmbuf_linearize(ops[i]->sym->m_src);
+ }
+#endif /* CPERF_LINEARIZATION_ENABLE */
+
+ /* Enqueue burst of ops on crypto device */
+ ops_enqd = rte_cryptodev_enqueue_burst(ctx->dev_id, ctx->qp_id,
+ ops, burst_size);
+ if (ops_enqd < burst_size)
+ ops_enqd_failed++;
+
+ /**
+ * Calculate number of ops not enqueued (mainly for hw
+ * accelerators whose ingress queue can fill up).
+ */
+ ops_unused = burst_size - ops_enqd;
+ ops_enqd_total += ops_enqd;
+
+
+ /* Dequeue processed burst of ops from crypto device */
+ ops_deqd = rte_cryptodev_dequeue_burst(ctx->dev_id, ctx->qp_id,
+ ops_processed, ctx->options->max_burst_size);
+
+ m_idx += ops_needed;
+ if (m_idx + ctx->options->max_burst_size > ctx->options->pool_sz)
+ m_idx = 0;
+
+ if (ops_deqd == 0) {
+ /**
+ * Count dequeue polls which didn't return any
+ * processed operations. This statistic is mainly
+ * relevant to hw accelerators.
+ */
+ ops_deqd_failed++;
+ continue;
+ }
+
+ for (i = 0; i < ops_deqd; i++) {
+ if (cperf_verify_op(ops_processed[i], ctx->options,
+ ctx->test_vector))
+ ops_failed++;
+ /* free crypto ops so they can be reused. We don't free
+ * the mbufs here as we don't want to reuse them as
+ * the crypto operation will change the data and cause
+ * failures.
+ */
+ rte_crypto_op_free(ops_processed[i]);
+ }
+ ops_deqd_total += ops_deqd;
+ }
+
+ /* Dequeue any operations still in the crypto device */
+
+ while (ops_deqd_total < ctx->options->total_ops) {
+ /* Sending 0 length burst to flush sw crypto device */
+ rte_cryptodev_enqueue_burst(ctx->dev_id, ctx->qp_id, NULL, 0);
+
+ /* dequeue burst */
+ ops_deqd = rte_cryptodev_dequeue_burst(ctx->dev_id, ctx->qp_id,
+ ops_processed, ctx->options->max_burst_size);
+ if (ops_deqd == 0) {
+ ops_deqd_failed++;
+ continue;
+ }
+
+ for (i = 0; i < ops_deqd; i++) {
+ if (cperf_verify_op(ops_processed[i], ctx->options,
+ ctx->test_vector))
+ ops_failed++;
+ /* free crypto ops so they can be reused. We don't free
+ * the mbufs here as we don't want to reuse them as
+ * the crypto operation will change the data and cause
+ * failures.
+ */
+ rte_crypto_op_free(ops_processed[i]);
+ }
+ ops_deqd_total += ops_deqd;
+ }
+
+ if (!ctx->options->csv) {
+ if (!only_once)
+ printf("%12s%12s%12s%12s%12s%12s%12s%12s\n\n",
+ "lcore id", "Buf Size", "Burst size",
+ "Enqueued", "Dequeued", "Failed Enq",
+ "Failed Deq", "Failed Ops");
+ only_once = 1;
+
+ printf("%12u%12u%12u%12"PRIu64"%12"PRIu64"%12"PRIu64
+ "%12"PRIu64"%12"PRIu64"\n",
+ ctx->lcore_id,
+ ctx->options->max_buffer_size,
+ ctx->options->max_burst_size,
+ ops_enqd_total,
+ ops_deqd_total,
+ ops_enqd_failed,
+ ops_deqd_failed,
+ ops_failed);
+ } else {
+ if (!only_once)
+ printf("\n# lcore id, Buffer Size(B), "
+ "Burst Size,Enqueued,Dequeued,Failed Enq,"
+ "Failed Deq,Failed Ops\n");
+ only_once = 1;
+
+ printf("%10u;%10u;%u;%"PRIu64";%"PRIu64";%"PRIu64";%"PRIu64";"
+ "%"PRIu64"\n",
+ ctx->lcore_id,
+ ctx->options->max_buffer_size,
+ ctx->options->max_burst_size,
+ ops_enqd_total,
+ ops_deqd_total,
+ ops_enqd_failed,
+ ops_deqd_failed,
+ ops_failed);
+ }
+
+ return 0;
+}
+
+
+
+void
+cperf_verify_test_destructor(void *arg)
+{
+ struct cperf_verify_ctx *ctx = arg;
+
+ if (ctx == NULL)
+ return;
+
+ cperf_verify_test_free(ctx, ctx->options->pool_sz);
+}
diff --git a/src/seastar/dpdk/app/test-crypto-perf/cperf_test_verify.h b/src/seastar/dpdk/app/test-crypto-perf/cperf_test_verify.h
new file mode 100644
index 00000000..3fa78ee6
--- /dev/null
+++ b/src/seastar/dpdk/app/test-crypto-perf/cperf_test_verify.h
@@ -0,0 +1,58 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2016-2017 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _CPERF_VERIFY_
+#define _CPERF_VERIFY_
+
+#include <stdint.h>
+
+#include <rte_mbuf.h>
+
+#include "cperf.h"
+#include "cperf_ops.h"
+#include "cperf_options.h"
+#include "cperf_test_vectors.h"
+
+
+void *
+cperf_verify_test_constructor(uint8_t dev_id, uint16_t qp_id,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector,
+ const struct cperf_op_fns *ops_fn);
+
+int
+cperf_verify_test_runner(void *test_ctx);
+
+void
+cperf_verify_test_destructor(void *test_ctx);
+
+#endif /* _CPERF_VERIFY_ */
diff --git a/src/seastar/dpdk/app/test-crypto-perf/data/aes_cbc_128_sha.data b/src/seastar/dpdk/app/test-crypto-perf/data/aes_cbc_128_sha.data
new file mode 100644
index 00000000..0b054f5a
--- /dev/null
+++ b/src/seastar/dpdk/app/test-crypto-perf/data/aes_cbc_128_sha.data
@@ -0,0 +1,502 @@
+# List of tests for AES-128 CBC:
+# 1) [sha1_hmac_buff_x]
+# 2) [sha224_hmac_buff_x]
+# 3) [sha256_hmac_buff_x]
+# 4) [sha384_hmac_buff_x]
+# 5) [sha512_hmac_buff_x]
+# where x is one of the values: 32, 64, 128, 256, 512, 1024, 2048
+
+##########
+# GLOBAL #
+##########
+plaintext =
+0xff, 0xca, 0xfb, 0xf1, 0x38, 0x20, 0x2f, 0x7b, 0x24, 0x98, 0x26, 0x7d, 0x1d, 0x9f, 0xb3, 0x93,
+0xd9, 0xef, 0xbd, 0xad, 0x4e, 0x40, 0xbd, 0x60, 0xe9, 0x48, 0x59, 0x90, 0x67, 0xd7, 0x2b, 0x7b,
+0x8a, 0xe0, 0x4d, 0xb0, 0x70, 0x38, 0xcc, 0x48, 0x61, 0x7d, 0xee, 0xd6, 0x35, 0x49, 0xae, 0xb4,
+0xaf, 0x6b, 0xdd, 0xe6, 0x21, 0xc0, 0x60, 0xce, 0x0a, 0xf4, 0x1c, 0x2e, 0x1c, 0x8d, 0xe8, 0x7b,
+0x59, 0xda, 0x19, 0x4f, 0xec, 0x07, 0x8e, 0xe2, 0xf0, 0x61, 0xf9, 0x27, 0x61, 0x6f, 0xf8, 0xdf,
+0x62, 0x4d, 0xaf, 0x06, 0xfe, 0x41, 0xa6, 0xa6, 0xf9, 0xa2, 0x06, 0x40, 0xb3, 0x04, 0xbd, 0xe6,
+0xc8, 0x17, 0xfb, 0x56, 0x6f, 0xa9, 0x3b, 0x8e, 0xa6, 0x58, 0xdc, 0x91, 0x17, 0x58, 0x42, 0x95,
+0xa3, 0x7c, 0x81, 0x78, 0xa6, 0x3d, 0x3f, 0x75, 0x74, 0x17, 0x1a, 0xd3, 0x6c, 0x2f, 0x48, 0x39,
+0x20, 0x20, 0xc1, 0x9a, 0x29, 0x84, 0x7d, 0x2d, 0x52, 0xa1, 0xf9, 0x5c, 0xf3, 0x4f, 0x91, 0xfc,
+0x75, 0xcf, 0xd6, 0x2d, 0xe7, 0x9a, 0x59, 0x6e, 0x00, 0x0e, 0x8d, 0x22, 0x17, 0xbd, 0xa0, 0xdd,
+0x79, 0x1f, 0x71, 0xe6, 0xcd, 0x2f, 0xb1, 0xb6, 0xbc, 0xc3, 0xdb, 0x02, 0x91, 0x41, 0x9b, 0x09,
+0xa9, 0xd2, 0x7e, 0xbd, 0x2c, 0x18, 0xae, 0xc0, 0x93, 0x0c, 0x02, 0x9a, 0xdb, 0x4e, 0xaa, 0xeb,
+0x84, 0x4b, 0x43, 0x5e, 0xf0, 0x98, 0xf2, 0x5f, 0x86, 0x70, 0x96, 0x90, 0x15, 0x30, 0xcf, 0x3a,
+0xc9, 0x33, 0x21, 0xec, 0x59, 0x86, 0xfc, 0x65, 0x7d, 0xbe, 0xb9, 0xf8, 0x97, 0xf9, 0x30, 0xa9,
+0x6d, 0xfc, 0x0c, 0x6e, 0x36, 0x67, 0xd5, 0xa6, 0x67, 0xd9, 0xbd, 0x9b, 0x34, 0x5d, 0xa7, 0xdd,
+0xda, 0x46, 0x33, 0x25, 0x60, 0x4a, 0x18, 0xf1, 0x55, 0x07, 0xb2, 0xb7, 0x26, 0x7b, 0xa6, 0x1e,
+0x77, 0xbe, 0x7f, 0x35, 0x46, 0xdf, 0x56, 0x9c, 0x22, 0x19, 0xc8, 0x85, 0xa2, 0x45, 0xb2, 0xad,
+0xf9, 0x26, 0x66, 0xab, 0xfc, 0x97, 0x4b, 0x51, 0x32, 0x36, 0xbc, 0xad, 0xcf, 0x54, 0x3a, 0x4f,
+0x94, 0xdb, 0xd2, 0xf9, 0x67, 0x1b, 0x3b, 0xe5, 0xb2, 0x1d, 0xc5, 0x52, 0x64, 0x2c, 0x06, 0x44,
+0xcf, 0x18, 0x83, 0xe0, 0xd8, 0x04, 0x92, 0xa9, 0xc4, 0x3c, 0x8b, 0xa3, 0x2b, 0xbc, 0x88, 0x7e,
+0xc0, 0x76, 0xa7, 0xe2, 0x7b, 0x47, 0x90, 0xf2, 0xaa, 0x0a, 0x34, 0x1b, 0x91, 0x12, 0xd2, 0xd0,
+0x82, 0x45, 0xf4, 0x57, 0xf1, 0xbd, 0x91, 0x5e, 0xab, 0x41, 0x4c, 0xdf, 0x91, 0x4c, 0xdd, 0x67,
+0x04, 0xa0, 0x98, 0x23, 0x8c, 0x24, 0xbe, 0xd6, 0x80, 0xb3, 0x6d, 0x04, 0xa1, 0x77, 0x43, 0xa5,
+0xee, 0xb7, 0xce, 0xb1, 0x48, 0x43, 0x94, 0x61, 0x15, 0x20, 0x9d, 0xce, 0xd0, 0x14, 0x95, 0x37,
+0xc8, 0x64, 0xa3, 0x2d, 0x3d, 0xe3, 0xff, 0xb4, 0x55, 0x83, 0x84, 0x41, 0x50, 0x57, 0xbd, 0x5a,
+0x0c, 0xe4, 0xda, 0x3b, 0x36, 0x4d, 0x21, 0xb5, 0x6f, 0x73, 0x2a, 0x8c, 0x78, 0x4f, 0x9b, 0x83,
+0xda, 0x11, 0x3c, 0xf0, 0xc9, 0x7e, 0xa6, 0x48, 0x34, 0x53, 0x62, 0xd3, 0x0c, 0xff, 0xb1, 0x74,
+0xd6, 0xea, 0xa5, 0xfc, 0x13, 0x1c, 0x05, 0xa8, 0xc0, 0xbc, 0x95, 0x9c, 0x8c, 0xf6, 0x8c, 0xc3,
+0xf3, 0x69, 0xab, 0x93, 0x65, 0xc0, 0xb7, 0x7e, 0xb0, 0x16, 0x7c, 0xb5, 0x5f, 0x05, 0x28, 0xc9,
+0x09, 0x4e, 0x2a, 0x32, 0x87, 0xb3, 0xab, 0xf8, 0x4c, 0xab, 0xeb, 0x3b, 0x6a, 0xa0, 0x1d, 0x7f,
+0xef, 0xe5, 0x9b, 0xa4, 0xb7, 0xd7, 0xc2, 0x5e, 0x03, 0x0f, 0x99, 0xeb, 0xb1, 0xb1, 0xa6, 0x9d,
+0x1c, 0x7c, 0x5c, 0x94, 0x8b, 0x6e, 0x11, 0x7a, 0xb3, 0x6d, 0x1e, 0x61, 0x64, 0xc3, 0x7d, 0x1c,
+0xb3, 0x54, 0x65, 0x08, 0x3b, 0xda, 0x97, 0xb9, 0x75, 0xc1, 0x2b, 0x3e, 0xa8, 0x5c, 0x3c, 0x2d,
+0x81, 0x5b, 0xbf, 0x5a, 0x13, 0x0e, 0xeb, 0x66, 0xc0, 0x0b, 0x8f, 0x04, 0x68, 0x68, 0x9b, 0xe3,
+0x0d, 0x84, 0xe0, 0xcf, 0x83, 0xd7, 0x62, 0x48, 0xc1, 0x31, 0xa5, 0xd5, 0xbc, 0xe3, 0xa3, 0xa5,
+0xb6, 0xd1, 0xfd, 0x81, 0x91, 0x4d, 0xbd, 0xc4, 0x62, 0x4f, 0xe3, 0xd5, 0x99, 0x14, 0xf1, 0xcd,
+0xf4, 0x7d, 0x13, 0xda, 0x68, 0x0a, 0xca, 0xd6, 0x82, 0x0b, 0xf6, 0xea, 0xad, 0x78, 0xa4, 0xc8,
+0x14, 0x7a, 0xec, 0x11, 0xd3, 0x16, 0x86, 0x9f, 0x17, 0x37, 0x6a, 0x06, 0x56, 0xaa, 0x1b, 0xd1,
+0xaf, 0x85, 0x95, 0x21, 0x36, 0x69, 0xec, 0x1b, 0x56, 0x84, 0x01, 0x3f, 0x4d, 0x34, 0x3d, 0x2d,
+0x38, 0x57, 0x2d, 0x7e, 0xd9, 0x7b, 0x2d, 0x81, 0x86, 0xd4, 0x7c, 0x83, 0x12, 0x1d, 0x9d, 0x27,
+0x72, 0x1b, 0x5e, 0xf4, 0x15, 0xa5, 0xcd, 0xb7, 0x5f, 0xbb, 0x49, 0xa1, 0xd9, 0xdd, 0x8d, 0xad,
+0xa9, 0x2c, 0x65, 0x18, 0x91, 0xfd, 0xd2, 0xd4, 0x09, 0x60, 0x0c, 0xfd, 0xa4, 0xe1, 0x25, 0x87,
+0x32, 0x64, 0x7b, 0x99, 0xd7, 0x61, 0x2f, 0xd4, 0x73, 0xdd, 0x85, 0x26, 0x08, 0x92, 0xc0, 0xe1,
+0x4f, 0x0c, 0x76, 0x5b, 0x26, 0x69, 0xdb, 0x78, 0x35, 0x65, 0xb9, 0x58, 0x1f, 0x9c, 0x0f, 0x18,
+0x95, 0xfe, 0x40, 0xfc, 0xf7, 0x93, 0x71, 0x70, 0x8b, 0x73, 0xdc, 0xb0, 0x88, 0x72, 0x19, 0x26,
+0x94, 0x26, 0xa7, 0xaa, 0x00, 0x72, 0x61, 0x53, 0xd2, 0x5d, 0x8f, 0x5e, 0x51, 0x88, 0x2d, 0xa4,
+0x28, 0xd5, 0xaf, 0x2d, 0xd2, 0x84, 0x39, 0x75, 0x1e, 0xe7, 0xf0, 0x23, 0xc0, 0x4f, 0x8d, 0xdd,
+0x5c, 0x90, 0xef, 0x6e, 0x53, 0xe0, 0x54, 0x67, 0xe1, 0x5b, 0x10, 0xf1, 0xf5, 0xf8, 0x64, 0x34,
+0x94, 0xeb, 0x37, 0xf7, 0xe9, 0xaa, 0x6c, 0xa4, 0xd8, 0x74, 0x6d, 0xca, 0x8d, 0x1a, 0x31, 0x73,
+0xca, 0xb4, 0xc7, 0x47, 0x34, 0x7f, 0xf8, 0x24, 0x9b, 0xfa, 0xc9, 0xcc, 0xa8, 0x61, 0xb4, 0x0e,
+0x4d, 0x68, 0xc7, 0xa0, 0xcb, 0xea, 0xf0, 0xcc, 0x0a, 0x6c, 0xf2, 0x33, 0x42, 0x99, 0x6c, 0xd8,
+0x74, 0x7f, 0x1e, 0x8a, 0xa3, 0x0a, 0x48, 0x4b, 0x7e, 0xbe, 0xdb, 0x7f, 0x56, 0x69, 0x43, 0xe8,
+0xbf, 0x12, 0xc4, 0x7b, 0xc2, 0xd9, 0xfa, 0x5c, 0xeb, 0x45, 0xca, 0x07, 0x3d, 0xc0, 0xcd, 0x68,
+0x8b, 0xd0, 0x79, 0xea, 0x0a, 0x78, 0x06, 0xdc, 0x81, 0xd7, 0x32, 0x18, 0xb3, 0x65, 0xbe, 0x47,
+0xbb, 0xfa, 0x17, 0x09, 0xe9, 0x31, 0x95, 0x30, 0xef, 0x07, 0x44, 0xec, 0xd0, 0x98, 0x98, 0xc0,
+0x6b, 0x71, 0x5b, 0x23, 0xb8, 0xb6, 0xd2, 0x21, 0xff, 0x51, 0xdd, 0xae, 0x48, 0x29, 0x75, 0x0c,
+0xc3, 0x3d, 0x91, 0xfe, 0x9d, 0xa8, 0x5e, 0xb2, 0x34, 0xb2, 0xd3, 0x81, 0xf6, 0x27, 0x9c, 0xac,
+0x6b, 0x20, 0x56, 0x86, 0xa5, 0x4f, 0x7a, 0xdb, 0xf9, 0xac, 0xa9, 0x8e, 0xe3, 0x73, 0x21, 0x99,
+0x71, 0x2d, 0xaf, 0x27, 0x92, 0x0c, 0xc7, 0xd3, 0x85, 0xb3, 0x40, 0xda, 0x13, 0x4a, 0x04, 0x41,
+0x54, 0xf8, 0xf2, 0x55, 0xb7, 0x80, 0xdd, 0x77, 0xba, 0x01, 0x7a, 0x31, 0xbd, 0x6b, 0xdc, 0x5c,
+0x59, 0xf4, 0x2b, 0xca, 0x25, 0xbb, 0x50, 0xba, 0xfa, 0x42, 0x38, 0xd2, 0x28, 0x10, 0x8b, 0x7b,
+0x96, 0x45, 0x30, 0xbb, 0x7f, 0xf4, 0x5a, 0xf7, 0x28, 0x6f, 0x47, 0xdc, 0xd2, 0x82, 0xf2, 0xf7,
+0xdd, 0x20, 0xb5, 0x0c, 0x7e, 0x53, 0x85, 0xa7, 0xfc, 0x3b, 0x1a, 0xc0, 0x07, 0x7b, 0xa1, 0x43,
+0x05, 0x18, 0x19, 0xd3, 0xfc, 0x41, 0xc2, 0xce, 0xd9, 0x5b, 0x4b, 0x63, 0xe2, 0x8f, 0x86, 0x3a,
+0xd1, 0xd0, 0x1d, 0x74, 0x2e, 0xbc, 0xd3, 0xce, 0x08, 0x0c, 0x10, 0x7a, 0x42, 0x60, 0xc5, 0x3a,
+0xa6, 0xd8, 0xb0, 0x52, 0xcf, 0x53, 0x28, 0x70, 0x45, 0xb7, 0x72, 0x7d, 0x77, 0x66, 0x54, 0x3d,
+0x38, 0x26, 0xcf, 0xd5, 0xbf, 0xe4, 0x80, 0x10, 0xba, 0x2b, 0xe8, 0xdc, 0xc3, 0xfe, 0x28, 0xa3,
+0x52, 0x58, 0x70, 0x4a, 0xde, 0x84, 0x33, 0x5e, 0x93, 0x04, 0xa4, 0x7c, 0xe7, 0xea, 0x8e, 0xba,
+0xeb, 0x8a, 0x19, 0x26, 0x6a, 0x7f, 0x7c, 0x4a, 0x5b, 0xb4, 0x0d, 0xfc, 0xc8, 0x11, 0x1b, 0x41,
+0x68, 0x5d, 0x2a, 0x25, 0x04, 0x4f, 0xc8, 0xf4, 0x65, 0xfc, 0xb9, 0x58, 0xeb, 0xb4, 0x67, 0x50,
+0x24, 0xf5, 0x43, 0xf6, 0x91, 0x4a, 0xb0, 0x0f, 0x32, 0xe0, 0x07, 0x75, 0x69, 0x1b, 0x3c, 0xeb,
+0xb2, 0x65, 0x26, 0x6f, 0xb8, 0x79, 0xe0, 0x78, 0x8c, 0xdc, 0x39, 0x24, 0x48, 0x76, 0x11, 0xd4,
+0x3a, 0xc5, 0xd2, 0x2b, 0xaa, 0x55, 0xfb, 0x92, 0x12, 0x2d, 0x88, 0x05, 0xd1, 0xb1, 0x31, 0x36,
+0x1f, 0xc2, 0x44, 0x1c, 0xab, 0x2e, 0xcd, 0x1c, 0x72, 0x86, 0xf6, 0x83, 0x87, 0x2e, 0x8b, 0xdb,
+0xaa, 0x16, 0x0e, 0x1b, 0xe6, 0x5c, 0x4d, 0x2f, 0x82, 0xbd, 0x49, 0x11, 0x60, 0x22, 0x0f, 0xde,
+0x3b, 0x2b, 0x20, 0x1d, 0x56, 0xb7, 0x21, 0xae, 0x0b, 0x26, 0x4f, 0xde, 0x3d, 0xa6, 0x3f, 0x61,
+0x81, 0xe2, 0x76, 0x60, 0x08, 0xc5, 0x4b, 0x18, 0x0b, 0xd1, 0xf5, 0xff, 0x8d, 0x1a, 0x96, 0x76,
+0x51, 0x15, 0x05, 0x4d, 0x8c, 0x6b, 0x12, 0x90, 0x47, 0xd4, 0xa4, 0x38, 0xb9, 0x48, 0xe4, 0x4c,
+0x05, 0x69, 0x6a, 0x8b, 0x9d, 0x7c, 0xa1, 0xbc, 0x77, 0xeb, 0x86, 0x93, 0x0a, 0x15, 0x84, 0xba,
+0x8f, 0xf5, 0x7c, 0x44, 0x75, 0x31, 0x79, 0x16, 0xc1, 0x81, 0x1a, 0xb6, 0xe6, 0x6c, 0x3d, 0xb8,
+0x15, 0x46, 0xf5, 0xbe, 0x46, 0x04, 0xa6, 0xec, 0xec, 0xd1, 0x74, 0x8b, 0x87, 0x2b, 0xdb, 0xd0,
+0x9f, 0xb3, 0x99, 0x9d, 0x87, 0x8c, 0xc6, 0xaa, 0xd4, 0x64, 0x45, 0xbd, 0xe8, 0xed, 0xa3, 0xc1,
+0x2a, 0x41, 0x1e, 0x26, 0xaf, 0x86, 0x16, 0xed, 0x80, 0x08, 0xca, 0x64, 0x21, 0x3a, 0xce, 0x21,
+0x4c, 0x41, 0xb9, 0x13, 0x2d, 0xf7, 0x1b, 0xdf, 0x2b, 0x33, 0x69, 0xe7, 0x5c, 0x8c, 0x7b, 0xfb,
+0xe3, 0x41, 0xe9, 0xce, 0xd7, 0xff, 0x0e, 0x54, 0xfe, 0xb0, 0x71, 0x78, 0xdc, 0xde, 0x7e, 0xdd,
+0x1f, 0x1c, 0x4a, 0x8f, 0x3e, 0x16, 0xfd, 0x91, 0x82, 0x94, 0xd4, 0xc2, 0xf7, 0xb2, 0x77, 0x89,
+0x16, 0x2c, 0xba, 0xb6, 0xbd, 0xed, 0x95, 0x43, 0x05, 0x9b, 0xf2, 0xc4, 0xbe, 0x46, 0x43, 0x90,
+0x1d, 0xd8, 0x24, 0x02, 0xd2, 0xea, 0xf4, 0x08, 0xd9, 0xf7, 0x84, 0x0e, 0xc6, 0xe7, 0x44, 0xdb,
+0xb8, 0xac, 0x0a, 0x53, 0x39, 0x61, 0x43, 0xdc, 0x22, 0x28, 0x8f, 0x22, 0x2f, 0x73, 0xbf, 0x59,
+0x2d, 0x3c, 0x8c, 0x0b, 0xcc, 0x2a, 0x67, 0xe0, 0x5b, 0x5c, 0x65, 0x5e, 0x6d, 0x98, 0x99, 0xaa,
+0x3b, 0x89, 0x12, 0xe2, 0x99, 0xf6, 0x15, 0xa7, 0xd2, 0x6a, 0x79, 0xb4, 0xf6, 0x0b, 0xf5, 0x0d,
+0x2d, 0x4c, 0xcb, 0x1b, 0x35, 0x93, 0x61, 0x32, 0xa1, 0x8a, 0xa8, 0x27, 0xe8, 0x95, 0x5a, 0x56,
+0x59, 0x04, 0xfe, 0xce, 0xc2, 0xd8, 0x92, 0x97, 0xb2, 0x54, 0x63, 0xd0, 0x3b, 0xde, 0x10, 0x34,
+0x32, 0x16, 0x05, 0x51, 0x1d, 0xfc, 0x96, 0x8e, 0xf1, 0xf6, 0x4b, 0xd7, 0x48, 0x22, 0xce, 0xca,
+0x1c, 0x6b, 0xab, 0x1f, 0x59, 0xa2, 0x74, 0xd6, 0xcd, 0x15, 0x07, 0xab, 0xa2, 0xd5, 0x22, 0x81,
+0xec, 0x20, 0x14, 0x36, 0xac, 0xe4, 0x25, 0x7d, 0xe6, 0x09, 0x00, 0x2c, 0x92, 0x4d, 0x4e, 0xbf,
+0xbf, 0xa1, 0xd4, 0xbe, 0x6b, 0xd4, 0x1f, 0x95, 0x9b, 0xf3, 0xda, 0x99, 0xad, 0xa4, 0x6c, 0x73,
+0x55, 0xd1, 0x9d, 0x4b, 0x16, 0xd4, 0x06, 0xec, 0x46, 0x3d, 0xb7, 0xe7, 0xce, 0xd0, 0x1d, 0x94,
+0x65, 0xde, 0x61, 0xb3, 0xc1, 0x10, 0x65, 0xe5, 0x68, 0x9b, 0xb0, 0xb4, 0x43, 0x0b, 0x92, 0xaf,
+0xb7, 0x40, 0xa2, 0xe5, 0x06, 0x3d, 0x72, 0x00, 0xc5, 0x39, 0xab, 0x35, 0x29, 0x22, 0x4c, 0xa5,
+0xa5, 0x3f, 0x22, 0x90, 0x53, 0xd2, 0x36, 0x63, 0x1e, 0xd3, 0x33, 0xa5, 0xbb, 0x3d, 0xa3, 0x0c,
+0x14, 0x9c, 0x2e, 0x6d, 0x9a, 0x7a, 0xf7, 0xf1, 0x56, 0x66, 0xe5, 0x8d, 0x53, 0x83, 0x34, 0x3f,
+0xa9, 0x83, 0x84, 0x68, 0x90, 0xc9, 0x51, 0xc2, 0xd4, 0x8e, 0x6c, 0xc7, 0x6d, 0xa7, 0x19, 0x61,
+0xa7, 0x2e, 0x36, 0xbc, 0xd2, 0x0f, 0x17, 0x49, 0xd4, 0x6b, 0x36, 0x63, 0xfb, 0x1d, 0xf4, 0xb0,
+0x6b, 0xcf, 0x34, 0x5f, 0xd2, 0x77, 0xae, 0x12, 0xaf, 0xb3, 0xdf, 0x52, 0xf7, 0xc2, 0xc8, 0xf2,
+0x63, 0x61, 0xb6, 0x3e, 0x39, 0xf2, 0xa7, 0x1a, 0x89, 0x9d, 0x0e, 0x8f, 0xaf, 0xe1, 0x01, 0x24,
+0xa6, 0x3a, 0xd5, 0x9a, 0x62, 0x67, 0xa3, 0x66, 0xee, 0xbc, 0xc5, 0x94, 0x4b, 0xc3, 0x15, 0xa1,
+0x7e, 0x07, 0x07, 0x2b, 0xb7, 0x43, 0x2a, 0xb4, 0xb8, 0x25, 0x88, 0x86, 0x23, 0xab, 0xdf, 0x05,
+0xbe, 0x46, 0x56, 0xd7, 0xda, 0xd6, 0x75, 0x53, 0xd9, 0xc8, 0x26, 0x8f, 0x39, 0x67, 0xed, 0x21,
+0x53, 0x1c, 0x9c, 0x89, 0x46, 0xd3, 0xfe, 0x54, 0xe6, 0x1d, 0x02, 0xb9, 0x25, 0x82, 0x66, 0xe6,
+0xf9, 0x45, 0xd9, 0x3f, 0xa5, 0x71, 0xc1, 0x46, 0x66, 0x7a, 0x27, 0x8a, 0x82, 0xc9, 0x21, 0xe9,
+0x17, 0xab, 0x6c, 0xef, 0x45, 0xe5, 0x88, 0x93, 0x87, 0x80, 0xb3, 0x85, 0x25, 0x96, 0x19, 0x41,
+0xab, 0xd6, 0xba, 0x92, 0x76, 0x21, 0x8a, 0x58, 0xbd, 0xe2, 0x4b, 0xec, 0x45, 0x59, 0x2c, 0x13,
+0x1a, 0xb5, 0x13, 0x25, 0x44, 0xe7, 0x71, 0x26, 0x0a, 0x34, 0x33, 0xb9, 0x57, 0x15, 0xa4, 0x90,
+0x60, 0x11, 0x05, 0x8e, 0xc8, 0x8e, 0x74, 0x52, 0x4b, 0x31, 0x71, 0xeb, 0x66, 0x7e, 0xee, 0xb1,
+0x0a, 0x21, 0x52, 0xc0, 0x1a, 0xe9, 0xa1, 0x5a, 0xe3, 0x3a, 0x24, 0xfb, 0xf3, 0x1e, 0xd6, 0x83,
+0x1d, 0xfb, 0x81, 0xa8, 0x91, 0x60, 0x9e, 0xbc, 0x59, 0x20, 0xc9, 0x9e, 0x71, 0x19, 0x83, 0x2b,
+0x6a, 0x48, 0x4e, 0x6b, 0x46, 0x82, 0x89, 0xda, 0x60, 0xff, 0x1a, 0x46, 0x94, 0x55, 0xda, 0xe5,
+0x99, 0xfa, 0x84, 0xd7, 0x3b, 0xb9, 0xa5, 0x34, 0x87, 0x86, 0x5e, 0x6d, 0x75, 0x9a, 0xe7, 0x09,
+0xb8, 0xe6, 0x71, 0x15, 0x10, 0x56, 0xd7, 0xc1, 0xc8, 0xb2, 0x62, 0xbc, 0xec, 0xe0, 0x94, 0xa0,
+0xcd, 0xb4, 0x04, 0xa9, 0xc3, 0x51, 0xee, 0xf8, 0x2e, 0x42, 0x9a, 0xaa, 0x34, 0xd3, 0xb9, 0xb0,
+0x36, 0xf9, 0x47, 0xc1, 0x07, 0x49, 0xde, 0xb8, 0x32, 0x8a, 0x87, 0x68, 0x56, 0x9a, 0x35, 0x79,
+0xd1, 0xac, 0x49, 0x38, 0xc6, 0xfe, 0xfd, 0xdf, 0x6f, 0x3c, 0xda, 0x48, 0xbd, 0x23, 0xfd, 0x85,
+0xf0, 0x96, 0xee, 0x1c, 0x27, 0x18, 0x86, 0xa6, 0xf0, 0x7b, 0xd8, 0x3c, 0xc7, 0x22, 0x3e, 0x2f,
+0xac, 0xb1, 0x37, 0xbd, 0x84, 0x4b, 0xe3, 0x92, 0x82, 0xd0, 0x25, 0x14, 0x22, 0x65, 0xed, 0xeb,
+0xef, 0xb9, 0xb6, 0xe4, 0x95, 0x18, 0x0d, 0x2b, 0x8d, 0x4f, 0xaf, 0xc0, 0xa0, 0x05, 0x8b, 0x35,
+0x5b, 0x94, 0xb2, 0x68, 0x26, 0x4f, 0x4a, 0x9e, 0x85, 0x0e, 0x46, 0xe0, 0x4f, 0x60, 0x66, 0x01,
+0xa4, 0x39, 0xe8, 0x8b, 0x2a, 0x50, 0xf5, 0x18, 0x70, 0xe2, 0xfc, 0xd6, 0xbe, 0xd3, 0x46, 0x4b
+
+ciphertext =
+0x75, 0x95, 0xb3, 0x48, 0x38, 0xf9, 0xe4, 0x88, 0xec, 0xf8, 0x3b, 0x09, 0x40, 0xd4, 0xd6, 0xea,
+0xf1, 0x80, 0x6d, 0xfb, 0xba, 0x9e, 0xee, 0xac, 0x6a, 0xf9, 0x8f, 0xb6, 0xe1, 0xff, 0xea, 0x19,
+0x17, 0xc2, 0x77, 0x8d, 0xc2, 0x8d, 0x6c, 0x89, 0xd1, 0x5f, 0xa6, 0xf3, 0x2c, 0xa7, 0x6a, 0x7f,
+0x50, 0x1b, 0xc9, 0x4d, 0xb4, 0x36, 0x64, 0x6e, 0xa6, 0xd9, 0x39, 0x8b, 0xcf, 0x8e, 0x0c, 0x55,
+0x4d, 0xb8, 0xe8, 0xf5, 0xb6, 0x5a, 0xd4, 0x49, 0x63, 0x24, 0xa2, 0xdf, 0xf0, 0x7a, 0x1c, 0x3b,
+0x74, 0x0c, 0x1d, 0x9b, 0xe2, 0x2b, 0x31, 0xb5, 0xe3, 0xca, 0x9f, 0xe4, 0x23, 0xe8, 0x64, 0x83,
+0x1a, 0xf1, 0xaa, 0xbf, 0xd0, 0x6a, 0xd6, 0x43, 0xd1, 0x2d, 0x2b, 0x7f, 0x38, 0x8d, 0x55, 0xd8,
+0xb2, 0xa9, 0x96, 0xec, 0xf5, 0xf9, 0x56, 0x50, 0x65, 0xc8, 0x63, 0x35, 0x22, 0xb0, 0xf4, 0x11,
+0xf3, 0x96, 0x16, 0xc3, 0x55, 0x90, 0xd0, 0x42, 0x3a, 0x5b, 0xc7, 0xfa, 0x67, 0x9b, 0x9f, 0xbd,
+0xca, 0xa5, 0x89, 0xd1, 0xe6, 0xfb, 0xbe, 0x3c, 0x7a, 0x29, 0xcb, 0xd7, 0xd2, 0xaf, 0xfc, 0x2d,
+0x1e, 0xb2, 0x6c, 0x4f, 0x5e, 0x31, 0x67, 0x6f, 0xa9, 0x8e, 0x54, 0x1f, 0xdb, 0x87, 0xd4, 0x11,
+0xa4, 0x99, 0x50, 0xcc, 0x52, 0xd0, 0xfa, 0x43, 0x70, 0x03, 0xa6, 0xff, 0xe0, 0xcb, 0x22, 0xbd,
+0xf3, 0x66, 0xf2, 0x4d, 0x82, 0x13, 0x94, 0x28, 0x89, 0xae, 0x82, 0xdc, 0xa5, 0x3e, 0xf2, 0xd2,
+0x01, 0xda, 0xef, 0xb4, 0x81, 0x77, 0x86, 0x29, 0x35, 0xad, 0xca, 0x14, 0x84, 0xdb, 0x86, 0xbd,
+0x8c, 0xf0, 0x8b, 0xc4, 0x2a, 0xb0, 0x87, 0xd8, 0x0b, 0xcd, 0x2c, 0x32, 0xe1, 0xce, 0xca, 0x15,
+0x82, 0x6e, 0xf5, 0xc8, 0x20, 0x38, 0xa2, 0x60, 0xaf, 0xe1, 0xdc, 0xe7, 0x7b, 0xa4, 0x75, 0x4b,
+0xf2, 0xd1, 0xfb, 0x25, 0x36, 0xbe, 0x84, 0x67, 0x94, 0x06, 0x20, 0xc0, 0x21, 0x30, 0x29, 0xdf,
+0x63, 0xf5, 0x56, 0x3a, 0x07, 0xef, 0x8d, 0xad, 0x62, 0x0f, 0x60, 0xbe, 0xb0, 0x8e, 0x10, 0x27,
+0xc6, 0x46, 0x90, 0xe5, 0x59, 0xaa, 0x16, 0x55, 0xca, 0x68, 0x6c, 0xbf, 0x19, 0x4e, 0xcd, 0xe8,
+0xb4, 0xf8, 0x94, 0xc4, 0x55, 0x9d, 0x7c, 0x3c, 0x06, 0x4e, 0x1a, 0x34, 0x1b, 0x16, 0x80, 0xe4,
+0x56, 0x98, 0xd4, 0xaa, 0xee, 0x66, 0xea, 0x91, 0x71, 0x44, 0xbd, 0xcb, 0xb1, 0xc5, 0x57, 0x49,
+0xa8, 0x4e, 0xe2, 0x03, 0xc6, 0xd5, 0x39, 0xd8, 0x69, 0xa8, 0xa0, 0xad, 0xad, 0x0d, 0x8d, 0xa7,
+0x80, 0xd3, 0xba, 0xc1, 0xae, 0xfe, 0xf5, 0xa2, 0x55, 0x8d, 0xa6, 0x2f, 0xb1, 0x4c, 0x67, 0x3e,
+0xb4, 0xaa, 0xed, 0xab, 0x89, 0xbc, 0xa5, 0x6c, 0x96, 0xe1, 0xc2, 0x27, 0x80, 0x55, 0xe3, 0x1b,
+0x5c, 0x20, 0xad, 0x02, 0x83, 0xa1, 0xc9, 0x51, 0xbd, 0x63, 0xf6, 0x08, 0x64, 0x38, 0x75, 0x7c,
+0x50, 0xd9, 0xae, 0xbb, 0x1b, 0xab, 0x33, 0xd5, 0x61, 0xf1, 0xda, 0xe4, 0x52, 0x6d, 0x97, 0x3c,
+0xdb, 0xec, 0x62, 0x37, 0x5b, 0xe9, 0x84, 0xda, 0x26, 0x26, 0xa2, 0xc2, 0x00, 0x67, 0x50, 0x82,
+0x0c, 0xa2, 0xd4, 0xb0, 0xc9, 0xe7, 0x6e, 0x2a, 0x2a, 0xaa, 0x5a, 0x8a, 0x3c, 0xfa, 0xb8, 0xd6,
+0x95, 0xdf, 0xb5, 0x20, 0x08, 0x65, 0xf4, 0x2f, 0x49, 0x2a, 0xeb, 0x06, 0xd4, 0x1a, 0x3a, 0x3d,
+0xc7, 0xfe, 0xd2, 0x5c, 0xb5, 0x00, 0x14, 0x67, 0x32, 0xb2, 0x17, 0xe2, 0x17, 0x50, 0x97, 0xf0,
+0x11, 0xb5, 0x1a, 0xe4, 0xa9, 0xe1, 0x40, 0x21, 0xbb, 0x75, 0x96, 0xb2, 0xc1, 0x90, 0x8a, 0x66,
+0xfd, 0x2c, 0x1a, 0xa6, 0xc0, 0x4a, 0x53, 0xcb, 0x3e, 0x10, 0x0f, 0x0a, 0x73, 0x3c, 0x6b, 0x4f,
+0xba, 0x14, 0x57, 0xce, 0xc8, 0xb7, 0xd8, 0x33, 0xf1, 0xc4, 0xba, 0x02, 0x13, 0xaa, 0xc6, 0x15,
+0x9e, 0xd6, 0xfd, 0x77, 0x05, 0x81, 0x92, 0x61, 0x3b, 0x35, 0x3f, 0xbd, 0x38, 0x22, 0x2a, 0x5f,
+0xc3, 0x09, 0xc5, 0x73, 0x22, 0x2d, 0x27, 0x8a, 0x42, 0xac, 0x06, 0xe2, 0x8b, 0x9e, 0x3d, 0x73,
+0xfb, 0xf2, 0x71, 0x06, 0x07, 0x26, 0xc7, 0x25, 0xdd, 0x19, 0x7a, 0x54, 0xd8, 0xb8, 0x66, 0x6b,
+0x73, 0xad, 0xc8, 0xa2, 0x24, 0x39, 0x4a, 0xab, 0xdc, 0x5a, 0x6e, 0x32, 0xd9, 0x4a, 0x12, 0xe4,
+0xbd, 0x39, 0xf8, 0x72, 0x6a, 0xdc, 0x46, 0xfb, 0x18, 0x08, 0x01, 0xc5, 0xd3, 0xe7, 0xa2, 0xe9,
+0xf4, 0xe4, 0xcc, 0xaf, 0x91, 0x1c, 0xc7, 0x57, 0xdc, 0x18, 0x53, 0x2a, 0x66, 0xeb, 0x29, 0xf9,
+0xc5, 0x0e, 0x5a, 0x1c, 0x0d, 0xcc, 0xca, 0xb1, 0x67, 0x75, 0xff, 0x91, 0x58, 0x71, 0xff, 0x01,
+0x56, 0xaa, 0x51, 0x75, 0xfc, 0x61, 0x8a, 0x2a, 0x1c, 0xb3, 0x0a, 0x4b, 0x9a, 0xea, 0xe3, 0xc4,
+0x2a, 0x07, 0xd2, 0xce, 0x6d, 0xfc, 0x34, 0xf8, 0xb0, 0xe9, 0xe3, 0x4b, 0x71, 0x1f, 0x5f, 0x0e,
+0xb9, 0x87, 0x25, 0x1c, 0xad, 0x7b, 0x52, 0xa0, 0x56, 0xcf, 0x90, 0xbe, 0x7d, 0xc0, 0x6c, 0x34,
+0x28, 0x49, 0x77, 0xd4, 0x66, 0x12, 0x40, 0xa9, 0xd4, 0x32, 0xbe, 0x10, 0xad, 0x11, 0x73, 0xed,
+0x10, 0x60, 0xc5, 0x76, 0x63, 0xe8, 0x1a, 0x12, 0x26, 0x94, 0xa4, 0xa7, 0xee, 0xc3, 0xd3, 0x47,
+0xb6, 0x2f, 0xa1, 0x18, 0xe5, 0x7a, 0xf4, 0x85, 0x97, 0x1e, 0x09, 0xdf, 0xd6, 0x92, 0xc5, 0x2e,
+0x3e, 0xe5, 0xa9, 0x70, 0x7b, 0x89, 0x91, 0x5b, 0x72, 0x9a, 0x53, 0x5c, 0xdd, 0xb9, 0xd5, 0xe0,
+0xab, 0xb3, 0xc5, 0x14, 0x74, 0xcb, 0x67, 0xdc, 0xbb, 0x7c, 0x98, 0x31, 0xde, 0x2a, 0x61, 0x79,
+0x48, 0xdf, 0xb5, 0x1f, 0xb6, 0x3f, 0xbd, 0x15, 0xc8, 0xdf, 0x69, 0xc1, 0x11, 0xfc, 0xd2, 0xcf,
+0x33, 0xac, 0xe3, 0xdf, 0xc9, 0x26, 0xc7, 0x3c, 0x3d, 0xa8, 0x2b, 0xf1, 0xb7, 0x34, 0x01, 0x9e,
+0x53, 0x5a, 0x98, 0xe7, 0x45, 0x3a, 0x46, 0x90, 0xe1, 0xa3, 0x5f, 0xd3, 0xc4, 0xbc, 0x64, 0xea,
+0x9d, 0x90, 0xcc, 0xfc, 0x35, 0xa3, 0xd1, 0x8b, 0xc1, 0x9b, 0x6f, 0xce, 0xdb, 0xe7, 0x43, 0x3b,
+0x3d, 0x2e, 0xff, 0xc5, 0x81, 0x27, 0x2f, 0xd2, 0x66, 0x85, 0x7c, 0x8c, 0x3d, 0x4f, 0x3d, 0xca,
+0xce, 0x3a, 0xdf, 0xbc, 0xa2, 0x76, 0x3b, 0xe9, 0xc0, 0xf0, 0x22, 0xd8, 0x3c, 0xb8, 0x67, 0x7b,
+0x9b, 0xf1, 0x8d, 0x30, 0x0c, 0x1a, 0xd9, 0xe1, 0xff, 0x85, 0x26, 0xf1, 0xe8, 0x99, 0x92, 0x24,
+0xec, 0xb0, 0x7a, 0x20, 0xe3, 0x36, 0xe0, 0xe7, 0xc6, 0x9d, 0xfe, 0x7e, 0x52, 0x08, 0x00, 0x8c,
+0xc3, 0x8b, 0x8d, 0x3b, 0xf8, 0x07, 0x8c, 0x1e, 0x26, 0xbd, 0x1b, 0x82, 0x80, 0xe4, 0xec, 0x7a,
+0xf5, 0x3b, 0xb6, 0x2a, 0x59, 0xf0, 0x0c, 0x3d, 0x36, 0xaf, 0x8a, 0x59, 0xc1, 0x57, 0xc1, 0x9c,
+0xf1, 0x6e, 0x81, 0x98, 0xc2, 0x18, 0x0a, 0xb8, 0xe3, 0xe8, 0xa6, 0xd6, 0x54, 0x3a, 0xfd, 0xb2,
+0x3e, 0x13, 0x3e, 0xfb, 0xf9, 0x34, 0xc4, 0x8c, 0x6f, 0xbe, 0x11, 0x5b, 0x2d, 0x81, 0x7b, 0x20,
+0xc9, 0xd3, 0xe6, 0x71, 0x3e, 0xae, 0xbf, 0x23, 0x09, 0xa0, 0x87, 0xe7, 0x49, 0x2d, 0xc9, 0x6a,
+0x8d, 0xa3, 0x5e, 0x8e, 0xeb, 0x18, 0x33, 0x3a, 0xf8, 0x00, 0x3d, 0x91, 0xf0, 0x6c, 0x80, 0x38,
+0x3b, 0x0c, 0xa1, 0xb1, 0x17, 0xb1, 0xe0, 0x6d, 0x63, 0x7c, 0xa4, 0xf5, 0x9a, 0x65, 0xc8, 0x3e,
+0x09, 0xc5, 0x57, 0x79, 0x7a, 0x2a, 0x17, 0x8b, 0xbb, 0xe2, 0x75, 0xb8, 0x87, 0x14, 0x7b, 0xc6,
+0x21, 0xa8, 0x9e, 0x31, 0xdc, 0x15, 0xee, 0x43, 0xf6, 0xc0, 0x11, 0x30, 0xa8, 0x45, 0xd3, 0x4b,
+0x61, 0xfe, 0x9a, 0x19, 0xae, 0x01, 0x40, 0xf7, 0x56, 0xcc, 0xc6, 0xa9, 0x35, 0x10, 0xe7, 0x58,
+0xbb, 0x13, 0x79, 0x19, 0x11, 0x47, 0x90, 0xf4, 0xa3, 0x40, 0xf2, 0xa1, 0xe0, 0xd0, 0xb0, 0xe4,
+0xca, 0xf3, 0x03, 0x3a, 0xd5, 0xd9, 0x67, 0xbc, 0x35, 0x6d, 0x74, 0xa0, 0xd2, 0x10, 0x9a, 0x5e,
+0x14, 0x7e, 0xb9, 0x10, 0x17, 0x1c, 0x1d, 0x44, 0x31, 0xe4, 0xcc, 0xa6, 0x95, 0xd2, 0x45, 0x1a,
+0xfc, 0x9a, 0x7c, 0x62, 0xf2, 0xd8, 0xc4, 0x4b, 0x4c, 0x87, 0x13, 0xb7, 0x61, 0xe5, 0x7e, 0xa7,
+0x47, 0xac, 0x97, 0xf0, 0x86, 0x2b, 0xe6, 0x1e, 0x8c, 0xd0, 0x66, 0x86, 0xfa, 0x18, 0x1f, 0x12,
+0xa7, 0x84, 0x6f, 0x0d, 0x66, 0x1e, 0xe5, 0xf3, 0xb8, 0x1b, 0x37, 0xe4, 0x9a, 0x12, 0x81, 0x10,
+0x18, 0xad, 0xdd, 0x9d, 0x5a, 0x4b, 0xce, 0xf5, 0xcb, 0x31, 0x6d, 0x2e, 0xa5, 0x82, 0x40, 0x87,
+0x5c, 0x08, 0x62, 0xc2, 0xc2, 0x5d, 0xea, 0x78, 0x0a, 0xc1, 0x96, 0x99, 0xe5, 0xf4, 0x12, 0x5c,
+0xf1, 0xee, 0x70, 0x59, 0xc6, 0x5e, 0xc5, 0xfa, 0xb3, 0xa3, 0x62, 0x71, 0xd8, 0x22, 0x6a, 0x99,
+0xf9, 0xb7, 0xbe, 0x58, 0x45, 0x9a, 0x5a, 0xc1, 0xa9, 0x3f, 0x99, 0x7a, 0x16, 0x46, 0x52, 0x21,
+0x4b, 0x0c, 0x52, 0xce, 0xa6, 0x6c, 0x44, 0xf7, 0x77, 0xc2, 0x10, 0x11, 0x13, 0xe2, 0x19, 0x2e,
+0x5e, 0xb5, 0x4a, 0x5b, 0xfc, 0x66, 0x9d, 0xe1, 0xd0, 0x9d, 0xde, 0x46, 0xf2, 0xad, 0x35, 0x97,
+0x64, 0xa9, 0x05, 0x0e, 0x3b, 0x0f, 0xf9, 0xc7, 0xe0, 0xcd, 0x3b, 0x8c, 0xff, 0x6b, 0xde, 0xb0,
+0x7f, 0x3e, 0x1f, 0x3f, 0x7b, 0x66, 0xbd, 0x52, 0x40, 0x18, 0xde, 0x91, 0x61, 0xca, 0xae, 0x40,
+0x56, 0x9b, 0x46, 0x5f, 0xd9, 0x2f, 0x13, 0x62, 0x7e, 0x22, 0xec, 0x4b, 0x64, 0x8d, 0x21, 0xa2,
+0xe9, 0x83, 0xbb, 0xec, 0x7f, 0xd9, 0xb4, 0xfb, 0x4f, 0x21, 0x9e, 0xb4, 0x66, 0x15, 0x13, 0x95,
+0x0f, 0x50, 0xb4, 0x9f, 0x77, 0xe8, 0xad, 0x24, 0x0e, 0x00, 0xb3, 0x73, 0x29, 0xd0, 0xc4, 0x25,
+0xf7, 0x91, 0xe6, 0xac, 0xf4, 0x5f, 0x7f, 0xac, 0xd7, 0x68, 0x6b, 0x94, 0xd8, 0x7a, 0xcb, 0xb8,
+0xd8, 0xcb, 0x24, 0x06, 0x88, 0x2e, 0x8e, 0x91, 0xaf, 0xce, 0x6f, 0x36, 0x2f, 0x2d, 0x1a, 0xac,
+0xcc, 0x06, 0xb4, 0x0e, 0x66, 0x6e, 0x79, 0x15, 0xe5, 0xaa, 0x33, 0xeb, 0xb1, 0xe5, 0xa3, 0x62,
+0x7a, 0x76, 0xfc, 0x4a, 0xbd, 0xa2, 0xbe, 0x85, 0x44, 0x6c, 0x31, 0xae, 0x5b, 0xd9, 0x85, 0x5e,
+0xb7, 0x88, 0xdb, 0x29, 0xa1, 0x1e, 0x78, 0x98, 0x56, 0xbf, 0xfb, 0x4c, 0x63, 0xac, 0x96, 0xfb,
+0xa1, 0x18, 0x91, 0xc2, 0x21, 0x90, 0x7c, 0xfa, 0x9d, 0x6d, 0x09, 0xb9, 0xae, 0x9e, 0x90, 0xf3,
+0x33, 0x31, 0x95, 0xa3, 0xf4, 0xc1, 0xfa, 0x89, 0xad, 0x6d, 0x30, 0x1c, 0x42, 0x5b, 0x56, 0x6f,
+0x85, 0x26, 0x6a, 0xf6, 0x95, 0xf6, 0x3c, 0xbc, 0x9b, 0xb1, 0x70, 0x50, 0xeb, 0x9e, 0x40, 0xa2,
+0x97, 0x50, 0x2b, 0x90, 0x7b, 0x38, 0x64, 0xf1, 0xae, 0xa1, 0x23, 0xeb, 0x34, 0x22, 0x1a, 0x97,
+0x9d, 0xdb, 0x48, 0x44, 0x7d, 0x1a, 0x56, 0xfa, 0xdd, 0x18, 0xc9, 0xac, 0xe9, 0x2a, 0x98, 0x97,
+0x48, 0xff, 0x79, 0x66, 0x44, 0xfd, 0x2e, 0xa6, 0x15, 0x0b, 0x51, 0x3e, 0x0a, 0xaf, 0x62, 0x16,
+0x1a, 0x37, 0xab, 0x72, 0xa5, 0xf1, 0x0b, 0xa7, 0x8c, 0x00, 0xf2, 0xaa, 0xd3, 0x34, 0x01, 0xb1,
+0xd0, 0x2c, 0x88, 0xb8, 0x25, 0xd6, 0x62, 0x02, 0x52, 0xa4, 0x4a, 0xa2, 0xb1, 0xe3, 0x07, 0x91,
+0x41, 0x30, 0x55, 0x2f, 0x14, 0x61, 0x29, 0xd0, 0x94, 0x1e, 0x4e, 0xe3, 0x02, 0x39, 0xc9, 0xb1,
+0xfc, 0x43, 0xec, 0x83, 0x28, 0xf1, 0x98, 0x0e, 0xe9, 0x26, 0x79, 0x1c, 0x48, 0xa9, 0x22, 0x21,
+0x4a, 0x82, 0xaf, 0x43, 0x35, 0xf4, 0x9c, 0x39, 0x08, 0x8b, 0x93, 0xb8, 0x42, 0x40, 0x7b, 0x99,
+0x4c, 0xfa, 0x63, 0x90, 0x4e, 0x31, 0x5f, 0x9f, 0x60, 0x60, 0xa7, 0x1b, 0xb8, 0x38, 0x83, 0x63,
+0xb3, 0xe7, 0x2e, 0xcc, 0x1a, 0x21, 0xdd, 0x4b, 0xfb, 0x62, 0x2c, 0x30, 0xae, 0x15, 0x6b, 0xe2,
+0x37, 0x63, 0xc8, 0xa1, 0x16, 0x57, 0x83, 0x14, 0xcc, 0xae, 0xe4, 0x31, 0x1b, 0x06, 0xf7, 0xbe,
+0xf8, 0x56, 0xef, 0xd4, 0x60, 0x9e, 0x68, 0x0c, 0xa0, 0x82, 0x7e, 0x71, 0x87, 0x9e, 0xd2, 0xa7,
+0x5d, 0x86, 0xc6, 0x3d, 0x88, 0x4a, 0xd9, 0x01, 0x1e, 0x44, 0xa1, 0xc0, 0x91, 0x42, 0xd2, 0xfc,
+0xab, 0xf2, 0x7a, 0x94, 0x16, 0xf1, 0x39, 0x50, 0x83, 0x1c, 0x65, 0x9d, 0xc3, 0x26, 0x93, 0xdf,
+0x65, 0x0c, 0xe3, 0x83, 0xb5, 0x7f, 0x72, 0x73, 0xef, 0xd7, 0x62, 0xe9, 0x7f, 0xe2, 0xd1, 0xcc,
+0x9e, 0x77, 0x9f, 0xab, 0x30, 0x26, 0x2a, 0x2c, 0x18, 0xb1, 0x3c, 0x64, 0xcf, 0x54, 0x49, 0x75,
+0xe1, 0xbe, 0x51, 0xdc, 0xaa, 0xdf, 0xeb, 0xc0, 0x41, 0xc7, 0x24, 0x4b, 0xe3, 0xe0, 0xe7, 0xbc,
+0xed, 0x32, 0x15, 0x9f, 0x4b, 0x2f, 0x17, 0xc1, 0xce, 0x39, 0x38, 0x83, 0xcb, 0x97, 0x30, 0x7b,
+0x82, 0x46, 0x65, 0x55, 0x2d, 0xd8, 0x16, 0xa7, 0xd3, 0x33, 0x73, 0x5a, 0xb2, 0xe0, 0xae, 0xfc,
+0x12, 0x8a, 0xf4, 0x56, 0xd9, 0x7b, 0xd2, 0x02, 0xcf, 0x99, 0x37, 0x04, 0x56, 0x90, 0xab, 0x10,
+0x82, 0x3e, 0xcc, 0x2c, 0x8d, 0x53, 0x67, 0x9b, 0x43, 0x59, 0xc0, 0x80, 0xec, 0x18, 0x5e, 0x03,
+0x04, 0x5d, 0x1d, 0x5f, 0xb4, 0x03, 0x8f, 0xc7, 0x38, 0x10, 0x6c, 0xd7, 0xfe, 0x8f, 0x2c, 0xd4,
+0x0a, 0x1e, 0x47, 0x5f, 0x2a, 0x26, 0xd3, 0x4b, 0x3e, 0x46, 0x87, 0xd4, 0x94, 0xba, 0xe8, 0x19,
+0x89, 0x90, 0x70, 0x90, 0xa0, 0xee, 0x8d, 0x74, 0x87, 0x1c, 0x35, 0x6b, 0x48, 0x94, 0x3d, 0x80,
+0x4c, 0x8c, 0x84, 0x35, 0x86, 0x97, 0xb4, 0xe2, 0xae, 0x4c, 0xae, 0x30, 0xcf, 0x6e, 0x34, 0xa5,
+0xbb, 0xa5, 0xf5, 0xdd, 0x7e, 0xe8, 0xea, 0x37, 0x54, 0xe2, 0xc3, 0x91, 0x03, 0xcb, 0x8c, 0x4b,
+0x23, 0x73, 0x63, 0x5b, 0x35, 0x63, 0x5b, 0x89, 0xbb, 0x01, 0xce, 0x8d, 0x73, 0xa3, 0x4f, 0x89,
+0x76, 0x15, 0x5d, 0x50, 0x26, 0x01, 0x8c, 0x7b, 0x23, 0x6b, 0x84, 0xa6, 0x60, 0x44, 0x2a, 0x0b,
+0x33, 0x8f, 0x00, 0xad, 0x0e, 0x05, 0x75, 0x41, 0xae, 0x96, 0x1b, 0x2d, 0x0b, 0xe9, 0xdb, 0xba,
+0xbe, 0xe0, 0xc5, 0x65, 0x35, 0x02, 0xf2, 0x04, 0x6c, 0x3f, 0x81, 0xe0, 0x0c, 0x2c, 0xd7, 0xde,
+0xc8, 0xb2, 0x6c, 0x5d, 0x1e, 0x9b, 0xe0, 0x65, 0x1e, 0x13, 0xd8, 0x6a, 0x92, 0xa7, 0x59, 0x14,
+0x78, 0x92, 0xb7, 0x11, 0x06, 0xea, 0xc2, 0x8d, 0x61, 0x82, 0x5d, 0xfe, 0x18, 0x66, 0x02, 0x8e,
+0x7a, 0x09, 0x7f, 0xdc, 0x7e, 0xca, 0xa7, 0x76, 0x99, 0x50, 0x25, 0xf6, 0x7e, 0x30, 0xaa, 0xf7,
+0x82, 0xae, 0xfa, 0xe3, 0xdf, 0x56, 0xa9, 0xab, 0xa4, 0xa3, 0x2c, 0x4d, 0x02, 0x4c, 0x38, 0x02,
+0x2d, 0x7f, 0x37, 0x54, 0xca, 0x3f, 0x6e, 0x7b, 0x0e, 0xb2, 0xa5, 0x68, 0x76, 0x98, 0x85, 0xd4,
+0x83, 0x5b, 0x26, 0xb3, 0xcd, 0xe9, 0x0c, 0xdf, 0xa5, 0x35, 0x4d, 0xd8, 0x5c, 0x59, 0x53, 0xe8,
+0x81, 0xf0, 0x33, 0xc9, 0xc9, 0xef, 0x84, 0xf6, 0x5c, 0xf8, 0x6e, 0x32, 0xe7, 0x20, 0x94, 0x79
+
+cipher_key =
+0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2, 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A
+
+auth_key =
+0xaf, 0x96, 0x42, 0xf1, 0x8c, 0x50, 0xdc, 0x67, 0x1a, 0x43, 0x47, 0x62, 0xc7, 0x04, 0xab, 0x05,
+0xf5, 0x0c, 0xe7, 0xa2, 0xa6, 0x23, 0xd5, 0x3d, 0x95, 0xd8, 0xcd, 0x86, 0x79, 0xf5, 0x01, 0x47,
+0x4f, 0xf9, 0x1d, 0x9d, 0x36, 0xf7, 0x68, 0x1a, 0x64, 0x44, 0x58, 0x5d, 0xe5, 0x81, 0x15, 0x2a,
+0x41, 0xe4, 0x0e, 0xaa, 0x1f, 0x04, 0x21, 0xff, 0x2c, 0xf3, 0x73, 0x2b, 0x48, 0x1e, 0xd2, 0xf7,
+0xf6, 0xd9, 0xaf, 0xbf, 0x08, 0x3b, 0xbb, 0x19, 0x5f, 0xf6, 0x7d, 0x25, 0x85, 0xdf, 0x6b, 0x54,
+0xd0, 0xe7, 0x4b, 0x9e, 0xc7, 0xef, 0xca, 0x48, 0x6f, 0x21, 0xd7, 0x51, 0xc8, 0x21, 0xc1, 0x15,
+0xe8, 0x38, 0x36, 0x58, 0x39, 0xd9, 0x9a, 0xc5, 0xe7, 0x3b, 0xc4, 0x47, 0xe2, 0xbd, 0x80, 0x73,
+0xf8, 0xd1, 0x9a, 0x5e, 0x4b, 0xfb, 0x52, 0x6b, 0x50, 0xaf, 0x8b, 0xb7, 0xb5, 0x2c, 0x52, 0x84
+
+iv =
+0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+
+####################
+# sha_hmac_buff_32 #
+####################
+[sha1_hmac_buff_32]
+digest =
+0xAD, 0x0F, 0xE8, 0xAD, 0x30, 0xD6, 0x0A, 0x2B, 0x6B, 0x3D, 0x24, 0x79, 0x6D, 0xB6, 0x80, 0x43,
+0x1D, 0xD1, 0x8A, 0xA8
+
+[sha224_hmac_buff_32]
+digest =
+0xB4, 0x1C, 0xF4, 0x73, 0x04, 0x62, 0x2D, 0xAF, 0x59, 0x05, 0xE8, 0x55, 0xE4, 0x8B, 0x24, 0xB4,
+0x0F, 0x4C, 0x3D, 0xBE, 0xFF, 0xFF, 0x8D, 0x19, 0x0D, 0x38, 0xA1, 0xFC
+
+[sha256_hmac_buff_32]
+digest =
+0x77, 0x54, 0x8D, 0x73, 0x7D, 0xB9, 0x78, 0x2F, 0x3D, 0xEE, 0xA2, 0xE7, 0xC9, 0x03, 0xF3, 0xB0,
+0x17, 0x8E, 0x71, 0x81, 0xB7, 0xA7, 0x5F, 0x9F, 0xF3, 0xED, 0x55, 0x1A, 0x69, 0x68, 0x52, 0xE5
+
+[sha384_hmac_buff_32]
+digest =
+0x1A, 0x3D, 0x1A, 0xD8, 0x0C, 0x04, 0x4B, 0x14, 0x9F, 0xF6, 0x9B, 0x80, 0x5C, 0xA2, 0x78, 0xFC,
+0xE6, 0xA3, 0xBA, 0x32, 0x09, 0x04, 0x52, 0x24, 0x76, 0xC9, 0xFC, 0x70, 0xA6, 0x00, 0xB4, 0x41,
+0xA1, 0x48, 0x1D, 0xCC, 0x54, 0x59, 0xE6, 0x94, 0x35, 0x36, 0xCC, 0xAB, 0x4B, 0xF5, 0xE4, 0xCA
+
+[sha512_hmac_buff_32]
+digest =
+0xED, 0xD7, 0x96, 0x0B, 0xC4, 0x8F, 0xBF, 0xF3, 0xEA, 0x7D, 0x5D, 0x57, 0x2A, 0x50, 0x50, 0xAC,
+0x33, 0xF2, 0xED, 0x56, 0x0A, 0xF7, 0x97, 0x4A, 0x36, 0x8D, 0x3B, 0xA5, 0x9F, 0x7A, 0x6D, 0x57,
+0xE0, 0x94, 0x10, 0xB9, 0x15, 0xC6, 0x1B, 0x7F, 0x17, 0xB3, 0x48, 0xB5, 0xF9, 0x93, 0xD8, 0xCA,
+0x74, 0x56, 0xED, 0xBD, 0x55, 0x14, 0xD2, 0xB6, 0x36, 0x07, 0x06, 0x73, 0x66, 0x41, 0x50, 0x84
+
+####################
+# sha_hmac_buff_64 #
+####################
+[sha1_hmac_buff_64]
+digest =
+0xC9, 0xC3, 0x65, 0x23, 0xCE, 0x9D, 0x6E, 0x35, 0xDC, 0x65, 0x3B, 0x21, 0x33, 0xFF, 0x1E, 0x74,
+0xAF, 0x48, 0x24, 0xD9
+
+[sha224_hmac_buff_64]
+digest =
+0x9F, 0xC3, 0x34, 0x0F, 0xB0, 0xA5, 0x4D, 0x89, 0xA4, 0x20, 0x01, 0xDF, 0x40, 0xAE, 0xA2, 0x41,
+0x4E, 0x97, 0x38, 0xBA, 0xA7, 0xF9, 0x94, 0x1F, 0x56, 0x4E, 0x00, 0x0A
+
+[sha256_hmac_buff_64]
+digest =
+0x66, 0x52, 0xF3, 0xEB, 0xC7, 0x06, 0xEF, 0x21, 0x82, 0x7C, 0xCF, 0x7F, 0x5B, 0x6B, 0x77, 0x2F,
+0x28, 0x61, 0x06, 0x2B, 0x67, 0x4B, 0x2D, 0x62, 0x71, 0x53, 0xBE, 0x12, 0xF9, 0x5B, 0xD8, 0x64
+
+[sha384_hmac_buff_64]
+digest =
+0x63, 0x50, 0x09, 0x45, 0x87, 0x02, 0x7F, 0x85, 0xD3, 0xC8, 0xF2, 0x26, 0x01, 0xE8, 0x2C, 0x28,
+0xB4, 0x86, 0x5A, 0x8E, 0x8E, 0x95, 0x27, 0x6A, 0x74, 0xF0, 0x29, 0xC2, 0x2D, 0x13, 0x91, 0xD5,
+0x38, 0xDB, 0x06, 0x7E, 0xB4, 0x8C, 0xD6, 0x30, 0x54, 0x86, 0xE7, 0xBB, 0x5C, 0xB6, 0xDD, 0x90
+
+[sha512_hmac_buff_64]
+digest =
+0xBE, 0x52, 0xBF, 0x69, 0x2B, 0x7F, 0xD5, 0x37, 0x48, 0x76, 0xCF, 0xBD, 0x23, 0x18, 0x45, 0x90,
+0x74, 0x25, 0x07, 0x91, 0x13, 0x37, 0xF3, 0x26, 0xEE, 0x68, 0xEC, 0xFC, 0xCB, 0x60, 0x53, 0x96,
+0x54, 0xF6, 0xE8, 0xAC, 0xF7, 0xB1, 0x52, 0x31, 0x7E, 0x5D, 0x99, 0xF3, 0x86, 0xF2, 0x98, 0x7D,
+0xD4, 0x38, 0xD9, 0xF1, 0x4C, 0x08, 0x87, 0x7F, 0xB9, 0x17, 0x97, 0x39, 0xDB, 0x68, 0x39, 0x19
+#####################
+# sha_hmac_buff_128 #
+#####################
+[sha1_hmac_buff_128]
+digest =
+0xB0, 0x6F, 0x7D, 0xB3, 0x29, 0xC3, 0x2B, 0x5D, 0xB7, 0xF1, 0x13, 0xFB, 0x9E, 0x90, 0x5D, 0xF1,
+0x48, 0xBC, 0x71, 0xA4
+
+[sha224_hmac_buff_128]
+digest =
+0xFC, 0x59, 0xAF, 0xF2, 0x83, 0x2E, 0x07, 0x08, 0xBF, 0xB4, 0x3C, 0x24, 0xA8, 0x52, 0x7B, 0x9E,
+0x92, 0x83, 0xCE, 0x96, 0xEE, 0x8B, 0x65, 0x72, 0x00, 0x12, 0xC6, 0x98
+
+[sha256_hmac_buff_128]
+digest =
+0x7E, 0xCA, 0x95, 0xD5, 0x63, 0xA8, 0xCA, 0xA6, 0xC5, 0x41, 0x75, 0x12, 0x60, 0xDF, 0xFE, 0x16,
+0x70, 0xEB, 0xCC, 0x4E, 0xEB, 0x00, 0x86, 0xF0, 0xEC, 0x45, 0x44, 0x76, 0x62, 0x55, 0x48, 0x56
+
+[sha384_hmac_buff_128]
+digest =
+0x1B, 0x2A, 0xAA, 0x7F, 0x2E, 0x58, 0x1F, 0x64, 0xB4, 0xE6, 0x29, 0xE4, 0x74, 0x78, 0x09, 0xD7,
+0xBA, 0xDD, 0x18, 0xB6, 0xE4, 0x21, 0xF5, 0x8F, 0x40, 0x45, 0x65, 0xD1, 0xBE, 0x4F, 0x7B, 0x27,
+0xF4, 0x64, 0x72, 0x55, 0x53, 0xAB, 0x39, 0x05, 0x7A, 0x6D, 0xAA, 0x12, 0x75, 0x03, 0x67, 0x4E
+
+[sha512_hmac_buff_128]
+digest =
+0x5F, 0x8F, 0xA8, 0xFA, 0xEA, 0x05, 0x29, 0xBD, 0x3B, 0xBA, 0xF6, 0xA7, 0x93, 0x9E, 0x16, 0xF1,
+0x8B, 0x10, 0x2F, 0x6D, 0x08, 0x18, 0x54, 0xD2, 0x39, 0xEB, 0xF9, 0x70, 0xCC, 0x55, 0xA0, 0xC3,
+0x08, 0x9B, 0x8E, 0x55, 0x81, 0x1A, 0xCE, 0x0D, 0x09, 0x97, 0x4E, 0x34, 0xD1, 0xE6, 0x25, 0x05,
+0x94, 0xC7, 0x05, 0x30, 0xAF, 0x2F, 0x7F, 0x54, 0xAA, 0xB8, 0xC5, 0x8E, 0x3D, 0xBB, 0xF2, 0x12
+
+#####################
+# sha_hmac_buff_256 #
+#####################
+[sha1_hmac_buff_256]
+digest =
+0xF9, 0xCA, 0x12, 0x7D, 0x60, 0x68, 0xB7, 0xAF, 0xDC, 0xAC, 0x41, 0x13, 0x1C, 0xA8, 0xC1, 0x85,
+0x65, 0x11, 0x31, 0x4C
+
+[sha224_hmac_buff_256]
+digest =
+0x49, 0xED, 0xA4, 0x27, 0x51, 0x6A, 0x46, 0xE4, 0x31, 0x12, 0x72, 0x92, 0xB8, 0x81, 0x16, 0x97,
+0x19, 0x4F, 0x3B, 0xAC, 0xD1, 0xCE, 0x06, 0x40, 0xD4, 0xEA, 0x8E, 0xC3
+
+[sha256_hmac_buff_256]
+digest =
+0xB9, 0xFB, 0x21, 0x16, 0x0C, 0x08, 0xD1, 0xE0, 0x49, 0xB8, 0xC8, 0x7E, 0xCC, 0xF0, 0xBA, 0x29,
+0x32, 0xCE, 0x53, 0x03, 0xE8, 0xFB, 0xD2, 0x44, 0xB7, 0xB9, 0xFE, 0xE8, 0x03, 0x86, 0xE2, 0x68
+
+[sha384_hmac_buff_256]
+digest =
+0x47, 0xEA, 0x51, 0xA7, 0xAD, 0xA2, 0x34, 0x3D, 0x4A, 0x3A, 0x86, 0x89, 0x78, 0x56, 0xCF, 0x21,
+0x94, 0xBF, 0x80, 0x33, 0x6B, 0x42, 0x73, 0x01, 0xAD, 0x6B, 0xE0, 0xEC, 0x10, 0xEE, 0x6E, 0xEC,
+0xED, 0x54, 0x50, 0x5E, 0x96, 0x3B, 0xE8, 0x2A, 0x8C, 0x33, 0x67, 0x9B, 0x17, 0x6C, 0xBB, 0xF8
+
+[sha512_hmac_buff_256]
+digest =
+0x01, 0xAE, 0xE7, 0x74, 0xCD, 0x86, 0x43, 0xBC, 0x8A, 0xF6, 0xAF, 0x6C, 0xDE, 0x9E, 0x9A, 0xB7,
+0x6B, 0xCF, 0x98, 0x95, 0x31, 0xE8, 0x37, 0x3B, 0x3F, 0xF3, 0xC1, 0x00, 0xA0, 0xA6, 0xE5, 0x15,
+0x60, 0x36, 0x7E, 0x7C, 0x96, 0xAB, 0x17, 0xB9, 0x79, 0x3D, 0x3E, 0x43, 0xBC, 0xA0, 0xA0, 0x8B,
+0x14, 0x14, 0x22, 0x86, 0xE9, 0xF6, 0x96, 0x38, 0x9F, 0x24, 0x45, 0x9C, 0xE8, 0x63, 0x2A, 0x22
+
+#####################
+# sha_hmac_buff_512 #
+#####################
+[sha1_hmac_buff_512]
+digest =
+0x45, 0x8D, 0x5B, 0x40, 0x0D, 0x34, 0x3A, 0x7B, 0xB2, 0xB1, 0xE7, 0x62, 0xDE, 0x2B, 0xD0, 0x46,
+0xCD, 0x4B, 0x55, 0x95
+
+[sha224_hmac_buff_512]
+digest =
+0xE1, 0x82, 0x07, 0x4F, 0x6B, 0x24, 0x4A, 0x57, 0xE9, 0x04, 0x14, 0xB1, 0x7F, 0xD2, 0x4C, 0xA0,
+0x89, 0x8B, 0xB2, 0xA2, 0x28, 0x9F, 0xFE, 0x7C, 0xD1, 0x7F, 0x35, 0x07
+
+[sha256_hmac_buff_512]
+digest =
+0xB9, 0x75, 0x4F, 0x70, 0xC7, 0x8C, 0xF2, 0x62, 0x89, 0x3C, 0x41, 0x4D, 0x1D, 0x15, 0x81, 0x2A,
+0x5A, 0xCB, 0x56, 0x62, 0xF8, 0xE9, 0x38, 0x13, 0xC9, 0x4D, 0xC3, 0x9D, 0xF0, 0x82, 0xAC, 0xD2
+
+[sha384_hmac_buff_512]
+digest =
+0x9C, 0xAE, 0x77, 0x8D, 0x7E, 0x26, 0x01, 0xA6, 0x46, 0x47, 0xDF, 0xB7, 0x23, 0x6F, 0x17, 0x6B,
+0x9F, 0x4D, 0x94, 0xBB, 0x78, 0xD8, 0x2D, 0x90, 0xB1, 0xC1, 0x65, 0x6D, 0x92, 0x4E, 0x54, 0x7A,
+0xA5, 0xF6, 0x80, 0x29, 0x82, 0x77, 0xAC, 0xC3, 0x58, 0xE5, 0x14, 0x75, 0x64, 0x9D, 0x02, 0x6E
+
+[sha512_hmac_buff_512]
+digest =
+0x33, 0xB6, 0xD1, 0xC4, 0x5F, 0xDB, 0xEF, 0xF4, 0x14, 0xE8, 0xDA, 0x07, 0x30, 0xB6, 0xC6, 0xC9,
+0x4F, 0xCF, 0x64, 0x48, 0x08, 0xA2, 0xC1, 0x9D, 0x03, 0xAD, 0x93, 0x62, 0x41, 0xB6, 0xB9, 0xEC,
+0x1B, 0xD1, 0xAC, 0xA1, 0xC5, 0x94, 0x67, 0x19, 0xA3, 0x4B, 0x53, 0xCE, 0x0C, 0x8A, 0x27, 0x07,
+0x37, 0x75, 0x93, 0xC3, 0xC6, 0x60, 0x19, 0x39, 0x9E, 0x02, 0x23, 0x9A, 0xE6, 0xA9, 0x34, 0x1A
+
+######################
+# sha_hmac_buff_1024 #
+######################
+[sha1_hmac_buff_1024]
+digest =
+0x0B, 0x26, 0x34, 0xAD, 0x56, 0x44, 0x39, 0x4A, 0x0D, 0x2F, 0x14, 0xFB, 0x60, 0x77, 0xDD, 0xFC,
+0x0B, 0x5F, 0x9F, 0x99
+
+[sha224_hmac_buff_1024]
+digest =
+0x56, 0x41, 0xC2, 0xF0, 0x73, 0x5C, 0x21, 0x13, 0x7E, 0x47, 0xCC, 0xAB, 0x21, 0x3D, 0x5E, 0xA7,
+0xC6, 0x1E, 0xFF, 0x26, 0x59, 0x0C, 0x71, 0x95, 0x72, 0x76, 0x0D, 0x00
+
+[sha256_hmac_buff_1024]
+digest =
+0x08, 0x91, 0x23, 0x89, 0x0F, 0xB0, 0xE4, 0x25, 0x9F, 0xC7, 0x46, 0x6B, 0xC3, 0x39, 0xE0, 0x9C,
+0xE2, 0xAE, 0xA3, 0xCF, 0xB8, 0xA0, 0x0A, 0xCF, 0x29, 0xEE, 0x0D, 0x83, 0x8A, 0xE5, 0xE4, 0x85
+
+[sha384_hmac_buff_1024]
+digest =
+0x38, 0xC7, 0x19, 0xA4, 0x46, 0x14, 0x79, 0xA4, 0xAB, 0x40, 0x61, 0xBC, 0xFB, 0x87, 0x16, 0xE2,
+0x08, 0x90, 0xAD, 0x33, 0x5D, 0x37, 0xB6, 0xCA, 0x80, 0xEE, 0x59, 0x9C, 0xBF, 0xA8, 0xEB, 0x78,
+0xC2, 0xE2, 0x2D, 0x6E, 0x2E, 0x98, 0x98, 0x6F, 0x07, 0x6A, 0x39, 0x57, 0x8F, 0xCE, 0xEE, 0x64
+
+[sha512_hmac_buff_1024]
+digest =
+0x17, 0x60, 0x08, 0x57, 0x43, 0x20, 0xF6, 0xB5, 0x6D, 0x0D, 0x7F, 0x7C, 0xB9, 0x09, 0x3F, 0x6D,
+0x3E, 0x75, 0x2F, 0x17, 0xDA, 0x19, 0x58, 0xF0, 0xEC, 0xED, 0x96, 0xA9, 0x57, 0x05, 0xCD, 0x23,
+0x0F, 0x1E, 0x38, 0x55, 0x2D, 0x8E, 0x36, 0x14, 0xF4, 0x99, 0x5E, 0x3C, 0x33, 0xBB, 0x99, 0xC9,
+0xCD, 0x7A, 0xF4, 0x87, 0x10, 0xB8, 0x6C, 0xB1, 0x14, 0x2D, 0xA8, 0xCE, 0xFE, 0xF8, 0x6F, 0xD9
+
+######################
+# sha_hmac_buff_2048 #
+######################
+[sha1_hmac_buff_2048]
+digest =
+0x58, 0xE4, 0xBB, 0x8D, 0x63, 0x5D, 0x23, 0xF1, 0xAB, 0xB5, 0xBD, 0xD8, 0x71, 0xC9, 0x05, 0x0A,
+0x65, 0x5D, 0x2D, 0x2D
+
+[sha224_hmac_buff_2048]
+digest =
+0xA3, 0x9A, 0x47, 0x68, 0x32, 0x3A, 0xA8, 0xE4, 0xBE, 0x23, 0xEA, 0xEE, 0x2D, 0x5E, 0x3C, 0x2E,
+0xD3, 0x99, 0xBE, 0x87, 0x19, 0x17, 0xC5, 0x13, 0x6D, 0xB7, 0x05, 0x97
+
+[sha256_hmac_buff_2048]
+digest =
+0x5B, 0x36, 0x1A, 0xF0, 0x55, 0xAC, 0xC3, 0xEA, 0x1B, 0x01, 0xCF, 0xCE, 0x89, 0x0D, 0x6A, 0xC3,
+0x5F, 0x9A, 0xD3, 0x49, 0xCC, 0xA4, 0xDF, 0xDD, 0x44, 0x1F, 0x9D, 0x6C, 0xB1, 0x92, 0xDF, 0xB9
+
+[sha384_hmac_buff_2048]
+digest =
+0x24, 0x17, 0xA2, 0x61, 0xFF, 0x46, 0xA2, 0x2E, 0xE5, 0xC3, 0xB4, 0x47, 0x10, 0x8C, 0x54, 0xD2,
+0xC2, 0x4D, 0x15, 0xA2, 0x8D, 0xEF, 0x98, 0x6E, 0xE0, 0xB1, 0x31, 0x3B, 0x7D, 0xDE, 0x41, 0x8E,
+0x98, 0xB9, 0xE9, 0xD2, 0xD8, 0xE5, 0x75, 0x6D, 0xC5, 0xF0, 0x1A, 0xC4, 0x1B, 0x8B, 0xC1, 0xA4
+
+[sha512_hmac_buff_2048]
+digest =
+0xD8, 0x77, 0x7A, 0x0F, 0x63, 0x1E, 0x92, 0x7B, 0x87, 0xCE, 0x07, 0x24, 0x7E, 0xE4, 0x36, 0x30,
+0x16, 0x76, 0x0D, 0xEC, 0xEF, 0x01, 0xF5, 0xD5, 0x44, 0xB7, 0xF3, 0x51, 0x31, 0x6A, 0xC2, 0x80,
+0xCD, 0x4C, 0x7F, 0xD4, 0xA6, 0x90, 0x85, 0xAE, 0x49, 0xB1, 0xF1, 0xB0, 0xC4, 0x16, 0x79, 0xC3,
+0xE3, 0x8B, 0x67, 0xC3, 0xAA, 0xC1, 0x9C, 0x8D, 0xE0, 0x22, 0xB3, 0xFD, 0x09, 0xD5, 0x40, 0xAC
diff --git a/src/seastar/dpdk/app/test-crypto-perf/data/aes_cbc_192_sha.data b/src/seastar/dpdk/app/test-crypto-perf/data/aes_cbc_192_sha.data
new file mode 100644
index 00000000..7bfe3da7
--- /dev/null
+++ b/src/seastar/dpdk/app/test-crypto-perf/data/aes_cbc_192_sha.data
@@ -0,0 +1,504 @@
+# List of tests for AES-192 CBC:
+# 1) [sha1_hmac_buff_x]
+# 2) [sha224_hmac_buff_x]
+# 3) [sha256_hmac_buff_x]
+# 4) [sha384_hmac_buff_x]
+# 5) [sha512_hmac_buff_x]
+# where x is one of the values: 32, 64, 128, 256, 512, 1024, 2048
+
+##########
+# GLOBAL #
+##########
+plaintext =
+0xff, 0xca, 0xfb, 0xf1, 0x38, 0x20, 0x2f, 0x7b, 0x24, 0x98, 0x26, 0x7d, 0x1d, 0x9f, 0xb3, 0x93,
+0xd9, 0xef, 0xbd, 0xad, 0x4e, 0x40, 0xbd, 0x60, 0xe9, 0x48, 0x59, 0x90, 0x67, 0xd7, 0x2b, 0x7b,
+0x8a, 0xe0, 0x4d, 0xb0, 0x70, 0x38, 0xcc, 0x48, 0x61, 0x7d, 0xee, 0xd6, 0x35, 0x49, 0xae, 0xb4,
+0xaf, 0x6b, 0xdd, 0xe6, 0x21, 0xc0, 0x60, 0xce, 0x0a, 0xf4, 0x1c, 0x2e, 0x1c, 0x8d, 0xe8, 0x7b,
+0x59, 0xda, 0x19, 0x4f, 0xec, 0x07, 0x8e, 0xe2, 0xf0, 0x61, 0xf9, 0x27, 0x61, 0x6f, 0xf8, 0xdf,
+0x62, 0x4d, 0xaf, 0x06, 0xfe, 0x41, 0xa6, 0xa6, 0xf9, 0xa2, 0x06, 0x40, 0xb3, 0x04, 0xbd, 0xe6,
+0xc8, 0x17, 0xfb, 0x56, 0x6f, 0xa9, 0x3b, 0x8e, 0xa6, 0x58, 0xdc, 0x91, 0x17, 0x58, 0x42, 0x95,
+0xa3, 0x7c, 0x81, 0x78, 0xa6, 0x3d, 0x3f, 0x75, 0x74, 0x17, 0x1a, 0xd3, 0x6c, 0x2f, 0x48, 0x39,
+0x20, 0x20, 0xc1, 0x9a, 0x29, 0x84, 0x7d, 0x2d, 0x52, 0xa1, 0xf9, 0x5c, 0xf3, 0x4f, 0x91, 0xfc,
+0x75, 0xcf, 0xd6, 0x2d, 0xe7, 0x9a, 0x59, 0x6e, 0x00, 0x0e, 0x8d, 0x22, 0x17, 0xbd, 0xa0, 0xdd,
+0x79, 0x1f, 0x71, 0xe6, 0xcd, 0x2f, 0xb1, 0xb6, 0xbc, 0xc3, 0xdb, 0x02, 0x91, 0x41, 0x9b, 0x09,
+0xa9, 0xd2, 0x7e, 0xbd, 0x2c, 0x18, 0xae, 0xc0, 0x93, 0x0c, 0x02, 0x9a, 0xdb, 0x4e, 0xaa, 0xeb,
+0x84, 0x4b, 0x43, 0x5e, 0xf0, 0x98, 0xf2, 0x5f, 0x86, 0x70, 0x96, 0x90, 0x15, 0x30, 0xcf, 0x3a,
+0xc9, 0x33, 0x21, 0xec, 0x59, 0x86, 0xfc, 0x65, 0x7d, 0xbe, 0xb9, 0xf8, 0x97, 0xf9, 0x30, 0xa9,
+0x6d, 0xfc, 0x0c, 0x6e, 0x36, 0x67, 0xd5, 0xa6, 0x67, 0xd9, 0xbd, 0x9b, 0x34, 0x5d, 0xa7, 0xdd,
+0xda, 0x46, 0x33, 0x25, 0x60, 0x4a, 0x18, 0xf1, 0x55, 0x07, 0xb2, 0xb7, 0x26, 0x7b, 0xa6, 0x1e,
+0x77, 0xbe, 0x7f, 0x35, 0x46, 0xdf, 0x56, 0x9c, 0x22, 0x19, 0xc8, 0x85, 0xa2, 0x45, 0xb2, 0xad,
+0xf9, 0x26, 0x66, 0xab, 0xfc, 0x97, 0x4b, 0x51, 0x32, 0x36, 0xbc, 0xad, 0xcf, 0x54, 0x3a, 0x4f,
+0x94, 0xdb, 0xd2, 0xf9, 0x67, 0x1b, 0x3b, 0xe5, 0xb2, 0x1d, 0xc5, 0x52, 0x64, 0x2c, 0x06, 0x44,
+0xcf, 0x18, 0x83, 0xe0, 0xd8, 0x04, 0x92, 0xa9, 0xc4, 0x3c, 0x8b, 0xa3, 0x2b, 0xbc, 0x88, 0x7e,
+0xc0, 0x76, 0xa7, 0xe2, 0x7b, 0x47, 0x90, 0xf2, 0xaa, 0x0a, 0x34, 0x1b, 0x91, 0x12, 0xd2, 0xd0,
+0x82, 0x45, 0xf4, 0x57, 0xf1, 0xbd, 0x91, 0x5e, 0xab, 0x41, 0x4c, 0xdf, 0x91, 0x4c, 0xdd, 0x67,
+0x04, 0xa0, 0x98, 0x23, 0x8c, 0x24, 0xbe, 0xd6, 0x80, 0xb3, 0x6d, 0x04, 0xa1, 0x77, 0x43, 0xa5,
+0xee, 0xb7, 0xce, 0xb1, 0x48, 0x43, 0x94, 0x61, 0x15, 0x20, 0x9d, 0xce, 0xd0, 0x14, 0x95, 0x37,
+0xc8, 0x64, 0xa3, 0x2d, 0x3d, 0xe3, 0xff, 0xb4, 0x55, 0x83, 0x84, 0x41, 0x50, 0x57, 0xbd, 0x5a,
+0x0c, 0xe4, 0xda, 0x3b, 0x36, 0x4d, 0x21, 0xb5, 0x6f, 0x73, 0x2a, 0x8c, 0x78, 0x4f, 0x9b, 0x83,
+0xda, 0x11, 0x3c, 0xf0, 0xc9, 0x7e, 0xa6, 0x48, 0x34, 0x53, 0x62, 0xd3, 0x0c, 0xff, 0xb1, 0x74,
+0xd6, 0xea, 0xa5, 0xfc, 0x13, 0x1c, 0x05, 0xa8, 0xc0, 0xbc, 0x95, 0x9c, 0x8c, 0xf6, 0x8c, 0xc3,
+0xf3, 0x69, 0xab, 0x93, 0x65, 0xc0, 0xb7, 0x7e, 0xb0, 0x16, 0x7c, 0xb5, 0x5f, 0x05, 0x28, 0xc9,
+0x09, 0x4e, 0x2a, 0x32, 0x87, 0xb3, 0xab, 0xf8, 0x4c, 0xab, 0xeb, 0x3b, 0x6a, 0xa0, 0x1d, 0x7f,
+0xef, 0xe5, 0x9b, 0xa4, 0xb7, 0xd7, 0xc2, 0x5e, 0x03, 0x0f, 0x99, 0xeb, 0xb1, 0xb1, 0xa6, 0x9d,
+0x1c, 0x7c, 0x5c, 0x94, 0x8b, 0x6e, 0x11, 0x7a, 0xb3, 0x6d, 0x1e, 0x61, 0x64, 0xc3, 0x7d, 0x1c,
+0xb3, 0x54, 0x65, 0x08, 0x3b, 0xda, 0x97, 0xb9, 0x75, 0xc1, 0x2b, 0x3e, 0xa8, 0x5c, 0x3c, 0x2d,
+0x81, 0x5b, 0xbf, 0x5a, 0x13, 0x0e, 0xeb, 0x66, 0xc0, 0x0b, 0x8f, 0x04, 0x68, 0x68, 0x9b, 0xe3,
+0x0d, 0x84, 0xe0, 0xcf, 0x83, 0xd7, 0x62, 0x48, 0xc1, 0x31, 0xa5, 0xd5, 0xbc, 0xe3, 0xa3, 0xa5,
+0xb6, 0xd1, 0xfd, 0x81, 0x91, 0x4d, 0xbd, 0xc4, 0x62, 0x4f, 0xe3, 0xd5, 0x99, 0x14, 0xf1, 0xcd,
+0xf4, 0x7d, 0x13, 0xda, 0x68, 0x0a, 0xca, 0xd6, 0x82, 0x0b, 0xf6, 0xea, 0xad, 0x78, 0xa4, 0xc8,
+0x14, 0x7a, 0xec, 0x11, 0xd3, 0x16, 0x86, 0x9f, 0x17, 0x37, 0x6a, 0x06, 0x56, 0xaa, 0x1b, 0xd1,
+0xaf, 0x85, 0x95, 0x21, 0x36, 0x69, 0xec, 0x1b, 0x56, 0x84, 0x01, 0x3f, 0x4d, 0x34, 0x3d, 0x2d,
+0x38, 0x57, 0x2d, 0x7e, 0xd9, 0x7b, 0x2d, 0x81, 0x86, 0xd4, 0x7c, 0x83, 0x12, 0x1d, 0x9d, 0x27,
+0x72, 0x1b, 0x5e, 0xf4, 0x15, 0xa5, 0xcd, 0xb7, 0x5f, 0xbb, 0x49, 0xa1, 0xd9, 0xdd, 0x8d, 0xad,
+0xa9, 0x2c, 0x65, 0x18, 0x91, 0xfd, 0xd2, 0xd4, 0x09, 0x60, 0x0c, 0xfd, 0xa4, 0xe1, 0x25, 0x87,
+0x32, 0x64, 0x7b, 0x99, 0xd7, 0x61, 0x2f, 0xd4, 0x73, 0xdd, 0x85, 0x26, 0x08, 0x92, 0xc0, 0xe1,
+0x4f, 0x0c, 0x76, 0x5b, 0x26, 0x69, 0xdb, 0x78, 0x35, 0x65, 0xb9, 0x58, 0x1f, 0x9c, 0x0f, 0x18,
+0x95, 0xfe, 0x40, 0xfc, 0xf7, 0x93, 0x71, 0x70, 0x8b, 0x73, 0xdc, 0xb0, 0x88, 0x72, 0x19, 0x26,
+0x94, 0x26, 0xa7, 0xaa, 0x00, 0x72, 0x61, 0x53, 0xd2, 0x5d, 0x8f, 0x5e, 0x51, 0x88, 0x2d, 0xa4,
+0x28, 0xd5, 0xaf, 0x2d, 0xd2, 0x84, 0x39, 0x75, 0x1e, 0xe7, 0xf0, 0x23, 0xc0, 0x4f, 0x8d, 0xdd,
+0x5c, 0x90, 0xef, 0x6e, 0x53, 0xe0, 0x54, 0x67, 0xe1, 0x5b, 0x10, 0xf1, 0xf5, 0xf8, 0x64, 0x34,
+0x94, 0xeb, 0x37, 0xf7, 0xe9, 0xaa, 0x6c, 0xa4, 0xd8, 0x74, 0x6d, 0xca, 0x8d, 0x1a, 0x31, 0x73,
+0xca, 0xb4, 0xc7, 0x47, 0x34, 0x7f, 0xf8, 0x24, 0x9b, 0xfa, 0xc9, 0xcc, 0xa8, 0x61, 0xb4, 0x0e,
+0x4d, 0x68, 0xc7, 0xa0, 0xcb, 0xea, 0xf0, 0xcc, 0x0a, 0x6c, 0xf2, 0x33, 0x42, 0x99, 0x6c, 0xd8,
+0x74, 0x7f, 0x1e, 0x8a, 0xa3, 0x0a, 0x48, 0x4b, 0x7e, 0xbe, 0xdb, 0x7f, 0x56, 0x69, 0x43, 0xe8,
+0xbf, 0x12, 0xc4, 0x7b, 0xc2, 0xd9, 0xfa, 0x5c, 0xeb, 0x45, 0xca, 0x07, 0x3d, 0xc0, 0xcd, 0x68,
+0x8b, 0xd0, 0x79, 0xea, 0x0a, 0x78, 0x06, 0xdc, 0x81, 0xd7, 0x32, 0x18, 0xb3, 0x65, 0xbe, 0x47,
+0xbb, 0xfa, 0x17, 0x09, 0xe9, 0x31, 0x95, 0x30, 0xef, 0x07, 0x44, 0xec, 0xd0, 0x98, 0x98, 0xc0,
+0x6b, 0x71, 0x5b, 0x23, 0xb8, 0xb6, 0xd2, 0x21, 0xff, 0x51, 0xdd, 0xae, 0x48, 0x29, 0x75, 0x0c,
+0xc3, 0x3d, 0x91, 0xfe, 0x9d, 0xa8, 0x5e, 0xb2, 0x34, 0xb2, 0xd3, 0x81, 0xf6, 0x27, 0x9c, 0xac,
+0x6b, 0x20, 0x56, 0x86, 0xa5, 0x4f, 0x7a, 0xdb, 0xf9, 0xac, 0xa9, 0x8e, 0xe3, 0x73, 0x21, 0x99,
+0x71, 0x2d, 0xaf, 0x27, 0x92, 0x0c, 0xc7, 0xd3, 0x85, 0xb3, 0x40, 0xda, 0x13, 0x4a, 0x04, 0x41,
+0x54, 0xf8, 0xf2, 0x55, 0xb7, 0x80, 0xdd, 0x77, 0xba, 0x01, 0x7a, 0x31, 0xbd, 0x6b, 0xdc, 0x5c,
+0x59, 0xf4, 0x2b, 0xca, 0x25, 0xbb, 0x50, 0xba, 0xfa, 0x42, 0x38, 0xd2, 0x28, 0x10, 0x8b, 0x7b,
+0x96, 0x45, 0x30, 0xbb, 0x7f, 0xf4, 0x5a, 0xf7, 0x28, 0x6f, 0x47, 0xdc, 0xd2, 0x82, 0xf2, 0xf7,
+0xdd, 0x20, 0xb5, 0x0c, 0x7e, 0x53, 0x85, 0xa7, 0xfc, 0x3b, 0x1a, 0xc0, 0x07, 0x7b, 0xa1, 0x43,
+0x05, 0x18, 0x19, 0xd3, 0xfc, 0x41, 0xc2, 0xce, 0xd9, 0x5b, 0x4b, 0x63, 0xe2, 0x8f, 0x86, 0x3a,
+0xd1, 0xd0, 0x1d, 0x74, 0x2e, 0xbc, 0xd3, 0xce, 0x08, 0x0c, 0x10, 0x7a, 0x42, 0x60, 0xc5, 0x3a,
+0xa6, 0xd8, 0xb0, 0x52, 0xcf, 0x53, 0x28, 0x70, 0x45, 0xb7, 0x72, 0x7d, 0x77, 0x66, 0x54, 0x3d,
+0x38, 0x26, 0xcf, 0xd5, 0xbf, 0xe4, 0x80, 0x10, 0xba, 0x2b, 0xe8, 0xdc, 0xc3, 0xfe, 0x28, 0xa3,
+0x52, 0x58, 0x70, 0x4a, 0xde, 0x84, 0x33, 0x5e, 0x93, 0x04, 0xa4, 0x7c, 0xe7, 0xea, 0x8e, 0xba,
+0xeb, 0x8a, 0x19, 0x26, 0x6a, 0x7f, 0x7c, 0x4a, 0x5b, 0xb4, 0x0d, 0xfc, 0xc8, 0x11, 0x1b, 0x41,
+0x68, 0x5d, 0x2a, 0x25, 0x04, 0x4f, 0xc8, 0xf4, 0x65, 0xfc, 0xb9, 0x58, 0xeb, 0xb4, 0x67, 0x50,
+0x24, 0xf5, 0x43, 0xf6, 0x91, 0x4a, 0xb0, 0x0f, 0x32, 0xe0, 0x07, 0x75, 0x69, 0x1b, 0x3c, 0xeb,
+0xb2, 0x65, 0x26, 0x6f, 0xb8, 0x79, 0xe0, 0x78, 0x8c, 0xdc, 0x39, 0x24, 0x48, 0x76, 0x11, 0xd4,
+0x3a, 0xc5, 0xd2, 0x2b, 0xaa, 0x55, 0xfb, 0x92, 0x12, 0x2d, 0x88, 0x05, 0xd1, 0xb1, 0x31, 0x36,
+0x1f, 0xc2, 0x44, 0x1c, 0xab, 0x2e, 0xcd, 0x1c, 0x72, 0x86, 0xf6, 0x83, 0x87, 0x2e, 0x8b, 0xdb,
+0xaa, 0x16, 0x0e, 0x1b, 0xe6, 0x5c, 0x4d, 0x2f, 0x82, 0xbd, 0x49, 0x11, 0x60, 0x22, 0x0f, 0xde,
+0x3b, 0x2b, 0x20, 0x1d, 0x56, 0xb7, 0x21, 0xae, 0x0b, 0x26, 0x4f, 0xde, 0x3d, 0xa6, 0x3f, 0x61,
+0x81, 0xe2, 0x76, 0x60, 0x08, 0xc5, 0x4b, 0x18, 0x0b, 0xd1, 0xf5, 0xff, 0x8d, 0x1a, 0x96, 0x76,
+0x51, 0x15, 0x05, 0x4d, 0x8c, 0x6b, 0x12, 0x90, 0x47, 0xd4, 0xa4, 0x38, 0xb9, 0x48, 0xe4, 0x4c,
+0x05, 0x69, 0x6a, 0x8b, 0x9d, 0x7c, 0xa1, 0xbc, 0x77, 0xeb, 0x86, 0x93, 0x0a, 0x15, 0x84, 0xba,
+0x8f, 0xf5, 0x7c, 0x44, 0x75, 0x31, 0x79, 0x16, 0xc1, 0x81, 0x1a, 0xb6, 0xe6, 0x6c, 0x3d, 0xb8,
+0x15, 0x46, 0xf5, 0xbe, 0x46, 0x04, 0xa6, 0xec, 0xec, 0xd1, 0x74, 0x8b, 0x87, 0x2b, 0xdb, 0xd0,
+0x9f, 0xb3, 0x99, 0x9d, 0x87, 0x8c, 0xc6, 0xaa, 0xd4, 0x64, 0x45, 0xbd, 0xe8, 0xed, 0xa3, 0xc1,
+0x2a, 0x41, 0x1e, 0x26, 0xaf, 0x86, 0x16, 0xed, 0x80, 0x08, 0xca, 0x64, 0x21, 0x3a, 0xce, 0x21,
+0x4c, 0x41, 0xb9, 0x13, 0x2d, 0xf7, 0x1b, 0xdf, 0x2b, 0x33, 0x69, 0xe7, 0x5c, 0x8c, 0x7b, 0xfb,
+0xe3, 0x41, 0xe9, 0xce, 0xd7, 0xff, 0x0e, 0x54, 0xfe, 0xb0, 0x71, 0x78, 0xdc, 0xde, 0x7e, 0xdd,
+0x1f, 0x1c, 0x4a, 0x8f, 0x3e, 0x16, 0xfd, 0x91, 0x82, 0x94, 0xd4, 0xc2, 0xf7, 0xb2, 0x77, 0x89,
+0x16, 0x2c, 0xba, 0xb6, 0xbd, 0xed, 0x95, 0x43, 0x05, 0x9b, 0xf2, 0xc4, 0xbe, 0x46, 0x43, 0x90,
+0x1d, 0xd8, 0x24, 0x02, 0xd2, 0xea, 0xf4, 0x08, 0xd9, 0xf7, 0x84, 0x0e, 0xc6, 0xe7, 0x44, 0xdb,
+0xb8, 0xac, 0x0a, 0x53, 0x39, 0x61, 0x43, 0xdc, 0x22, 0x28, 0x8f, 0x22, 0x2f, 0x73, 0xbf, 0x59,
+0x2d, 0x3c, 0x8c, 0x0b, 0xcc, 0x2a, 0x67, 0xe0, 0x5b, 0x5c, 0x65, 0x5e, 0x6d, 0x98, 0x99, 0xaa,
+0x3b, 0x89, 0x12, 0xe2, 0x99, 0xf6, 0x15, 0xa7, 0xd2, 0x6a, 0x79, 0xb4, 0xf6, 0x0b, 0xf5, 0x0d,
+0x2d, 0x4c, 0xcb, 0x1b, 0x35, 0x93, 0x61, 0x32, 0xa1, 0x8a, 0xa8, 0x27, 0xe8, 0x95, 0x5a, 0x56,
+0x59, 0x04, 0xfe, 0xce, 0xc2, 0xd8, 0x92, 0x97, 0xb2, 0x54, 0x63, 0xd0, 0x3b, 0xde, 0x10, 0x34,
+0x32, 0x16, 0x05, 0x51, 0x1d, 0xfc, 0x96, 0x8e, 0xf1, 0xf6, 0x4b, 0xd7, 0x48, 0x22, 0xce, 0xca,
+0x1c, 0x6b, 0xab, 0x1f, 0x59, 0xa2, 0x74, 0xd6, 0xcd, 0x15, 0x07, 0xab, 0xa2, 0xd5, 0x22, 0x81,
+0xec, 0x20, 0x14, 0x36, 0xac, 0xe4, 0x25, 0x7d, 0xe6, 0x09, 0x00, 0x2c, 0x92, 0x4d, 0x4e, 0xbf,
+0xbf, 0xa1, 0xd4, 0xbe, 0x6b, 0xd4, 0x1f, 0x95, 0x9b, 0xf3, 0xda, 0x99, 0xad, 0xa4, 0x6c, 0x73,
+0x55, 0xd1, 0x9d, 0x4b, 0x16, 0xd4, 0x06, 0xec, 0x46, 0x3d, 0xb7, 0xe7, 0xce, 0xd0, 0x1d, 0x94,
+0x65, 0xde, 0x61, 0xb3, 0xc1, 0x10, 0x65, 0xe5, 0x68, 0x9b, 0xb0, 0xb4, 0x43, 0x0b, 0x92, 0xaf,
+0xb7, 0x40, 0xa2, 0xe5, 0x06, 0x3d, 0x72, 0x00, 0xc5, 0x39, 0xab, 0x35, 0x29, 0x22, 0x4c, 0xa5,
+0xa5, 0x3f, 0x22, 0x90, 0x53, 0xd2, 0x36, 0x63, 0x1e, 0xd3, 0x33, 0xa5, 0xbb, 0x3d, 0xa3, 0x0c,
+0x14, 0x9c, 0x2e, 0x6d, 0x9a, 0x7a, 0xf7, 0xf1, 0x56, 0x66, 0xe5, 0x8d, 0x53, 0x83, 0x34, 0x3f,
+0xa9, 0x83, 0x84, 0x68, 0x90, 0xc9, 0x51, 0xc2, 0xd4, 0x8e, 0x6c, 0xc7, 0x6d, 0xa7, 0x19, 0x61,
+0xa7, 0x2e, 0x36, 0xbc, 0xd2, 0x0f, 0x17, 0x49, 0xd4, 0x6b, 0x36, 0x63, 0xfb, 0x1d, 0xf4, 0xb0,
+0x6b, 0xcf, 0x34, 0x5f, 0xd2, 0x77, 0xae, 0x12, 0xaf, 0xb3, 0xdf, 0x52, 0xf7, 0xc2, 0xc8, 0xf2,
+0x63, 0x61, 0xb6, 0x3e, 0x39, 0xf2, 0xa7, 0x1a, 0x89, 0x9d, 0x0e, 0x8f, 0xaf, 0xe1, 0x01, 0x24,
+0xa6, 0x3a, 0xd5, 0x9a, 0x62, 0x67, 0xa3, 0x66, 0xee, 0xbc, 0xc5, 0x94, 0x4b, 0xc3, 0x15, 0xa1,
+0x7e, 0x07, 0x07, 0x2b, 0xb7, 0x43, 0x2a, 0xb4, 0xb8, 0x25, 0x88, 0x86, 0x23, 0xab, 0xdf, 0x05,
+0xbe, 0x46, 0x56, 0xd7, 0xda, 0xd6, 0x75, 0x53, 0xd9, 0xc8, 0x26, 0x8f, 0x39, 0x67, 0xed, 0x21,
+0x53, 0x1c, 0x9c, 0x89, 0x46, 0xd3, 0xfe, 0x54, 0xe6, 0x1d, 0x02, 0xb9, 0x25, 0x82, 0x66, 0xe6,
+0xf9, 0x45, 0xd9, 0x3f, 0xa5, 0x71, 0xc1, 0x46, 0x66, 0x7a, 0x27, 0x8a, 0x82, 0xc9, 0x21, 0xe9,
+0x17, 0xab, 0x6c, 0xef, 0x45, 0xe5, 0x88, 0x93, 0x87, 0x80, 0xb3, 0x85, 0x25, 0x96, 0x19, 0x41,
+0xab, 0xd6, 0xba, 0x92, 0x76, 0x21, 0x8a, 0x58, 0xbd, 0xe2, 0x4b, 0xec, 0x45, 0x59, 0x2c, 0x13,
+0x1a, 0xb5, 0x13, 0x25, 0x44, 0xe7, 0x71, 0x26, 0x0a, 0x34, 0x33, 0xb9, 0x57, 0x15, 0xa4, 0x90,
+0x60, 0x11, 0x05, 0x8e, 0xc8, 0x8e, 0x74, 0x52, 0x4b, 0x31, 0x71, 0xeb, 0x66, 0x7e, 0xee, 0xb1,
+0x0a, 0x21, 0x52, 0xc0, 0x1a, 0xe9, 0xa1, 0x5a, 0xe3, 0x3a, 0x24, 0xfb, 0xf3, 0x1e, 0xd6, 0x83,
+0x1d, 0xfb, 0x81, 0xa8, 0x91, 0x60, 0x9e, 0xbc, 0x59, 0x20, 0xc9, 0x9e, 0x71, 0x19, 0x83, 0x2b,
+0x6a, 0x48, 0x4e, 0x6b, 0x46, 0x82, 0x89, 0xda, 0x60, 0xff, 0x1a, 0x46, 0x94, 0x55, 0xda, 0xe5,
+0x99, 0xfa, 0x84, 0xd7, 0x3b, 0xb9, 0xa5, 0x34, 0x87, 0x86, 0x5e, 0x6d, 0x75, 0x9a, 0xe7, 0x09,
+0xb8, 0xe6, 0x71, 0x15, 0x10, 0x56, 0xd7, 0xc1, 0xc8, 0xb2, 0x62, 0xbc, 0xec, 0xe0, 0x94, 0xa0,
+0xcd, 0xb4, 0x04, 0xa9, 0xc3, 0x51, 0xee, 0xf8, 0x2e, 0x42, 0x9a, 0xaa, 0x34, 0xd3, 0xb9, 0xb0,
+0x36, 0xf9, 0x47, 0xc1, 0x07, 0x49, 0xde, 0xb8, 0x32, 0x8a, 0x87, 0x68, 0x56, 0x9a, 0x35, 0x79,
+0xd1, 0xac, 0x49, 0x38, 0xc6, 0xfe, 0xfd, 0xdf, 0x6f, 0x3c, 0xda, 0x48, 0xbd, 0x23, 0xfd, 0x85,
+0xf0, 0x96, 0xee, 0x1c, 0x27, 0x18, 0x86, 0xa6, 0xf0, 0x7b, 0xd8, 0x3c, 0xc7, 0x22, 0x3e, 0x2f,
+0xac, 0xb1, 0x37, 0xbd, 0x84, 0x4b, 0xe3, 0x92, 0x82, 0xd0, 0x25, 0x14, 0x22, 0x65, 0xed, 0xeb,
+0xef, 0xb9, 0xb6, 0xe4, 0x95, 0x18, 0x0d, 0x2b, 0x8d, 0x4f, 0xaf, 0xc0, 0xa0, 0x05, 0x8b, 0x35,
+0x5b, 0x94, 0xb2, 0x68, 0x26, 0x4f, 0x4a, 0x9e, 0x85, 0x0e, 0x46, 0xe0, 0x4f, 0x60, 0x66, 0x01,
+0xa4, 0x39, 0xe8, 0x8b, 0x2a, 0x50, 0xf5, 0x18, 0x70, 0xe2, 0xfc, 0xd6, 0xbe, 0xd3, 0x46, 0x4b
+
+ciphertext =
+0x0F, 0x9B, 0xF5, 0x9F, 0xE2, 0xB3, 0xD9, 0x12, 0x27, 0x51, 0x18, 0xD7, 0x4E, 0x1F, 0x40, 0x4C,
+0xC1, 0xDF, 0x66, 0xAB, 0x1A, 0xFA, 0xF8, 0xEE, 0xA4, 0x40, 0x63, 0x72, 0x58, 0xAE, 0x7E, 0x98,
+0x76, 0x63, 0x56, 0x1F, 0x71, 0xDB, 0x80, 0x07, 0xFE, 0x34, 0x23, 0x43, 0x1E, 0x3D, 0xDE, 0x7E,
+0xC0, 0x72, 0xEF, 0xAD, 0xF4, 0x30, 0xDF, 0x4E, 0x3B, 0x9F, 0xCA, 0x90, 0xC3, 0x95, 0x8A, 0x66,
+0x5C, 0xD6, 0xCA, 0xBD, 0x3C, 0xC9, 0xD2, 0xFE, 0x30, 0x02, 0xA9, 0x8E, 0xAA, 0x80, 0xF6, 0xFF,
+0xCD, 0x40, 0xBC, 0x99, 0xD2, 0x25, 0x7F, 0xBF, 0xC5, 0xF3, 0x50, 0x31, 0x69, 0xE1, 0xC8, 0x64,
+0xC5, 0x5F, 0x30, 0x30, 0xD9, 0xD7, 0xF9, 0xF0, 0xD3, 0x77, 0xE0, 0xD0, 0x11, 0xB8, 0xC9, 0x54,
+0xD9, 0x9C, 0x10, 0x74, 0xCA, 0x4A, 0xFE, 0xD2, 0x16, 0xA5, 0xD8, 0x2D, 0xC0, 0xDA, 0x39, 0x24,
+0xAF, 0x5E, 0xF2, 0xEB, 0xC7, 0x9D, 0xBC, 0xEF, 0x94, 0xA0, 0x49, 0x56, 0x39, 0xCE, 0x8A, 0x38,
+0x3B, 0x70, 0xC7, 0xB2, 0xE0, 0xD4, 0x43, 0xD7, 0xAC, 0xB4, 0xB3, 0xDB, 0xA2, 0x2B, 0x75, 0xE2,
+0x0E, 0x38, 0x2B, 0xE6, 0x42, 0x1A, 0x11, 0x08, 0x79, 0x9A, 0x32, 0xD2, 0x41, 0xCC, 0x28, 0xC3,
+0x4B, 0x3E, 0xD4, 0xB0, 0x10, 0x89, 0x7B, 0x0D, 0xB7, 0x95, 0xBE, 0x22, 0x01, 0xD0, 0x86, 0xA8,
+0xC6, 0xD0, 0xDD, 0xDF, 0x18, 0x2C, 0x1B, 0x49, 0xE3, 0x2B, 0x84, 0x53, 0x54, 0x14, 0xE6, 0x04,
+0xE1, 0xD6, 0x98, 0x91, 0x17, 0xE0, 0xD9, 0x39, 0xAF, 0xF9, 0x71, 0x35, 0x90, 0xCE, 0x4B, 0xD2,
+0x45, 0xB2, 0x4B, 0x68, 0x26, 0xBB, 0x8C, 0xBD, 0xA3, 0xF7, 0x60, 0xD4, 0x38, 0xAA, 0xDF, 0x5B,
+0x3B, 0x53, 0xF6, 0xA4, 0x45, 0x49, 0x4A, 0xEF, 0x6F, 0x04, 0x00, 0xFF, 0xE3, 0x3F, 0x7C, 0x7D,
+0xDC, 0xB0, 0x62, 0x9C, 0x6A, 0x99, 0x07, 0x85, 0xB3, 0x13, 0x2B, 0x40, 0x06, 0xAF, 0xE3, 0xA0,
+0x17, 0x97, 0x0D, 0x4E, 0xD7, 0xB0, 0x6B, 0xF8, 0x3C, 0x91, 0x0A, 0xF3, 0x17, 0x51, 0x30, 0xC8,
+0x58, 0x20, 0x20, 0xE2, 0xA3, 0xE6, 0x3B, 0x2F, 0x77, 0x7C, 0x52, 0x31, 0x4F, 0x4C, 0xA8, 0xD8,
+0x84, 0xB1, 0xE9, 0xB4, 0x86, 0xD8, 0x93, 0xBF, 0x2D, 0x6A, 0xDA, 0x5D, 0x39, 0x62, 0x5B, 0x52,
+0xFB, 0xBA, 0x9F, 0x83, 0x82, 0x3C, 0x40, 0x57, 0x02, 0x92, 0x6A, 0x97, 0x06, 0x39, 0x17, 0x0B,
+0xA7, 0xF5, 0x6A, 0x1A, 0x8E, 0x64, 0x74, 0x90, 0x33, 0xA6, 0xA3, 0x1E, 0x30, 0x1E, 0x67, 0x49,
+0x5A, 0x76, 0x43, 0x97, 0x71, 0xE0, 0x4E, 0xCC, 0x5A, 0xFD, 0x44, 0xFD, 0x5C, 0x41, 0x3A, 0x09,
+0x8E, 0x4E, 0xD2, 0xF0, 0x9A, 0x52, 0x39, 0x5B, 0x0E, 0xC4, 0xF2, 0xFE, 0xB4, 0x66, 0x6C, 0x60,
+0x47, 0x96, 0x80, 0x91, 0xBE, 0x6C, 0xA8, 0x33, 0x66, 0x4D, 0x08, 0x70, 0x27, 0x0C, 0x33, 0x50,
+0x8F, 0xEF, 0x05, 0xC9, 0x93, 0x21, 0x8D, 0xA4, 0x94, 0xF3, 0xBC, 0x4D, 0x96, 0x9A, 0x51, 0x29,
+0xDA, 0x8E, 0x32, 0xB4, 0xB3, 0xD8, 0x75, 0x20, 0x37, 0x9F, 0x33, 0xE2, 0xF9, 0xEB, 0xFA, 0xF2,
+0x6E, 0x3F, 0x71, 0x0C, 0x29, 0x8D, 0xFE, 0xE1, 0xF9, 0xC6, 0x49, 0xB6, 0x6E, 0x53, 0xBC, 0x24,
+0x1D, 0x0B, 0x24, 0x75, 0x54, 0x51, 0x0B, 0xEB, 0xDD, 0x67, 0x40, 0x61, 0xCA, 0x3F, 0xD2, 0x85,
+0x71, 0x16, 0xFC, 0x77, 0x9C, 0x56, 0xE5, 0xCA, 0x43, 0xC6, 0xC3, 0x2A, 0x47, 0xA8, 0x98, 0x40,
+0x02, 0x1D, 0x64, 0x47, 0x85, 0x99, 0x2F, 0x8F, 0x2D, 0xC2, 0x29, 0x7B, 0x8D, 0x64, 0xD9, 0x8F,
+0xF4, 0x91, 0x6F, 0x2A, 0xB0, 0x5C, 0xDC, 0xB0, 0xBE, 0xDE, 0x34, 0xA8, 0x99, 0x40, 0x23, 0x9F,
+0x8A, 0xF5, 0x0C, 0x32, 0xDE, 0x53, 0xA5, 0x55, 0xFE, 0x4C, 0xF8, 0x87, 0x83, 0xB6, 0xA1, 0x31,
+0x2C, 0xB4, 0xE9, 0x78, 0xB8, 0x45, 0xAA, 0x33, 0x6E, 0x8A, 0xBE, 0xDB, 0x76, 0x35, 0xDD, 0xDF,
+0xA1, 0x98, 0x21, 0x2B, 0x42, 0xF3, 0xA4, 0x3E, 0x2C, 0x38, 0xA9, 0xB1, 0x07, 0x38, 0xA1, 0x1D,
+0xA5, 0x85, 0x61, 0x87, 0xF1, 0xA1, 0x9D, 0x3D, 0x2C, 0xA6, 0x2F, 0x26, 0xFD, 0xE8, 0x46, 0x0D,
+0xBD, 0xDA, 0x44, 0xC4, 0xB5, 0xFF, 0x6F, 0xDB, 0xF7, 0xF4, 0xDB, 0x0A, 0x80, 0x7C, 0x81, 0x27,
+0xF4, 0x27, 0x41, 0x15, 0x9F, 0xEC, 0xA5, 0xAA, 0x79, 0x30, 0x9B, 0x0D, 0x84, 0xAC, 0x4D, 0x50,
+0x68, 0x56, 0x55, 0x32, 0xF9, 0x28, 0x06, 0xC3, 0x96, 0xD6, 0x57, 0x61, 0x04, 0xCF, 0xD8, 0xB9,
+0x36, 0x0D, 0x33, 0x11, 0xEE, 0x8A, 0x88, 0x5A, 0x11, 0x6C, 0x11, 0x71, 0x41, 0xFC, 0xD5, 0xF1,
+0xB7, 0xC2, 0x94, 0x98, 0x6F, 0xAB, 0x12, 0x5F, 0x34, 0x46, 0xDD, 0xBC, 0x65, 0x5C, 0x76, 0x3A,
+0x81, 0x42, 0xF8, 0x6D, 0xC2, 0x08, 0x93, 0x58, 0x30, 0x1B, 0x82, 0x28, 0xD7, 0xFB, 0x90, 0x61,
+0x24, 0x38, 0x12, 0xDC, 0xFB, 0x88, 0xFB, 0xC8, 0xB9, 0xB8, 0x23, 0xA5, 0xEB, 0x85, 0xB1, 0x92,
+0x55, 0x34, 0xA7, 0x8E, 0x2C, 0x3D, 0xD7, 0x07, 0xF6, 0x2C, 0xF5, 0x5A, 0x72, 0x38, 0x25, 0x5A,
+0x3F, 0x1F, 0xF5, 0x7B, 0x02, 0xFC, 0x70, 0xB1, 0x31, 0x01, 0xCA, 0xD6, 0x18, 0x7C, 0xF4, 0x0A,
+0x3A, 0xAE, 0x7B, 0x89, 0x0B, 0xE8, 0x5E, 0x7D, 0x64, 0x7A, 0x10, 0xE0, 0x8C, 0x8C, 0x02, 0xF7,
+0x2F, 0x52, 0x06, 0xE7, 0xD7, 0xFA, 0x56, 0xBB, 0xC4, 0x5A, 0x82, 0x14, 0x13, 0x7D, 0x41, 0xD0,
+0xCE, 0x57, 0xE6, 0x41, 0x3A, 0x08, 0xAD, 0x7C, 0x20, 0xDC, 0x15, 0xA8, 0xBA, 0xE6, 0xB8, 0x58,
+0xA6, 0xF4, 0x82, 0x70, 0xDE, 0x09, 0xE2, 0x8B, 0xFC, 0xAA, 0x7D, 0xD9, 0xFD, 0xCE, 0xBC, 0xAC,
+0xB8, 0xE8, 0xB2, 0x46, 0xC5, 0xC4, 0xF9, 0xFC, 0xE5, 0xFF, 0xF5, 0xCA, 0xB3, 0x51, 0x3C, 0xB8,
+0x25, 0xD7, 0x83, 0x3C, 0x91, 0xCD, 0xFB, 0x86, 0x94, 0x5E, 0x36, 0xCF, 0xDE, 0x8E, 0x37, 0x4F,
+0x9D, 0x54, 0xBB, 0x8D, 0x52, 0xE6, 0x86, 0x5C, 0x8B, 0x72, 0x23, 0xAF, 0x93, 0xF5, 0xFF, 0xB5,
+0xC5, 0xFE, 0xC1, 0x31, 0xCE, 0x72, 0xD7, 0x3A, 0x2E, 0x25, 0xBF, 0xC1, 0xEE, 0xD5, 0x28, 0xDB,
+0xB7, 0xD2, 0x4E, 0xC6, 0x2B, 0xE3, 0x6F, 0x87, 0x2D, 0xA5, 0xFB, 0xDB, 0x03, 0xB0, 0x13, 0x58,
+0x3F, 0x3B, 0xBD, 0x2E, 0x0B, 0x78, 0xC2, 0xDC, 0xF8, 0x30, 0x2F, 0x08, 0xA6, 0x6A, 0x00, 0x57,
+0x82, 0x79, 0x06, 0x11, 0xC2, 0x20, 0x49, 0xD1, 0xDD, 0x53, 0xF6, 0xA8, 0xB1, 0x0A, 0x1C, 0x97,
+0x11, 0x5C, 0xA4, 0x98, 0xBC, 0xE7, 0x10, 0x27, 0x73, 0x54, 0x3C, 0x91, 0x98, 0x58, 0x2F, 0xA8,
+0x96, 0xB2, 0xE8, 0x54, 0xC0, 0x6B, 0x4B, 0x69, 0x0E, 0x92, 0xFB, 0xF0, 0x5E, 0xDC, 0x45, 0xAE,
+0x6B, 0x12, 0x29, 0xBE, 0x59, 0xA2, 0x0B, 0xD6, 0xD2, 0x09, 0xE0, 0xBA, 0xE2, 0x1D, 0xD9, 0x8A,
+0x6D, 0x70, 0xD0, 0x62, 0x0C, 0x9D, 0xC4, 0x38, 0x3A, 0x11, 0xBA, 0xF8, 0x8B, 0x0A, 0xDF, 0xDF,
+0xD1, 0xBF, 0x87, 0x98, 0xC8, 0xFF, 0x42, 0x85, 0x13, 0xE7, 0x6C, 0xDE, 0xFE, 0x45, 0xFE, 0xF8,
+0x67, 0x28, 0x56, 0xF7, 0x3C, 0x12, 0x4E, 0x88, 0x05, 0x8B, 0x56, 0x53, 0x2E, 0xE8, 0x6F, 0x3B,
+0xEE, 0x40, 0x4D, 0x3C, 0x1B, 0x0C, 0xE7, 0xCA, 0xD1, 0x3A, 0xA3, 0x2A, 0xDB, 0xC0, 0xDB, 0x9D,
+0xA4, 0xC1, 0xDA, 0x50, 0x81, 0x59, 0x52, 0x87, 0x33, 0x10, 0xE6, 0x58, 0xC3, 0x3E, 0x08, 0x69,
+0xFF, 0x3B, 0x4C, 0x82, 0xBA, 0xC3, 0x81, 0x82, 0xB5, 0xF2, 0x9F, 0x0A, 0x20, 0xCF, 0x70, 0xFB,
+0x81, 0x63, 0xB7, 0x04, 0x95, 0xFE, 0x08, 0x33, 0x1A, 0xED, 0xB0, 0x0A, 0x86, 0xA6, 0x42, 0x8F,
+0xEB, 0x48, 0xD8, 0xF4, 0xFE, 0x50, 0xA2, 0xC6, 0x5E, 0xD8, 0x33, 0xAE, 0x44, 0x83, 0xE6, 0x7C,
+0x88, 0xA3, 0xEC, 0x74, 0xA4, 0x26, 0x58, 0xE6, 0x3C, 0xD4, 0x04, 0xAC, 0x71, 0xBD, 0xBE, 0xCC,
+0xC6, 0xE8, 0x55, 0xDE, 0x98, 0x7F, 0x6B, 0x4F, 0x62, 0xF6, 0x4E, 0x1C, 0x95, 0x44, 0xBE, 0xD7,
+0x77, 0x9C, 0xD2, 0x13, 0xD7, 0xF5, 0x2C, 0x8D, 0xC1, 0xC7, 0xCA, 0xF8, 0x68, 0x91, 0x06, 0x24,
+0x01, 0x5D, 0xD0, 0x9E, 0xC9, 0x24, 0x12, 0x83, 0xA1, 0xF4, 0x05, 0xE0, 0xB2, 0xA9, 0xAD, 0xFC,
+0xC3, 0x64, 0x08, 0x17, 0x58, 0xAB, 0xB7, 0x39, 0xA4, 0xB6, 0x77, 0x26, 0x37, 0x13, 0x24, 0x20,
+0xEB, 0xEE, 0x61, 0x28, 0x0E, 0x33, 0x7C, 0x4D, 0xD5, 0xEA, 0x42, 0x39, 0xB7, 0x20, 0xCB, 0x97,
+0x44, 0xBE, 0x6D, 0x67, 0x28, 0xF9, 0x99, 0xE1, 0xE7, 0x3A, 0x5D, 0x7D, 0xAA, 0xBB, 0x1D, 0xEC,
+0xA4, 0xF6, 0xAA, 0xED, 0xC5, 0x1F, 0xAD, 0xDF, 0x0E, 0xD3, 0x94, 0xA9, 0xD9, 0xFF, 0x29, 0x56,
+0x3C, 0x43, 0x5E, 0xC2, 0x3B, 0xB3, 0x2E, 0x4A, 0xB7, 0x9F, 0xF4, 0xA0, 0xF1, 0xD6, 0x93, 0xFF,
+0x4A, 0xC8, 0xF2, 0xDE, 0x1A, 0x96, 0xB1, 0x83, 0x37, 0x45, 0x0C, 0x79, 0x40, 0x51, 0xD1, 0x08,
+0xF2, 0xDC, 0xFA, 0xBF, 0xB4, 0x15, 0x9A, 0x60, 0x37, 0x81, 0x5F, 0x76, 0xB2, 0x87, 0x82, 0x2D,
+0xA8, 0x0A, 0x70, 0x1B, 0xA2, 0xD6, 0x7E, 0x65, 0xAC, 0x02, 0x36, 0xDA, 0x0F, 0xB4, 0xD5, 0x6E,
+0xEE, 0x60, 0x0B, 0xC8, 0xD6, 0x1B, 0x9C, 0xF1, 0xCF, 0x66, 0xCA, 0x1D, 0x9D, 0xE5, 0xC7, 0x0B,
+0x1A, 0xE1, 0x9E, 0x68, 0xFF, 0xCE, 0xCE, 0x1B, 0x0A, 0x1E, 0x8D, 0x25, 0x37, 0x40, 0x05, 0x20,
+0xE4, 0xA1, 0x4F, 0x4C, 0x33, 0x29, 0xB3, 0x7B, 0x47, 0xFA, 0x7E, 0xEF, 0x87, 0x89, 0x13, 0x10,
+0x1C, 0x0F, 0x15, 0x03, 0xFD, 0xD8, 0x81, 0xD7, 0xB9, 0xA7, 0xBA, 0xD0, 0x6F, 0x6F, 0x76, 0xF6,
+0xD1, 0xF3, 0xCE, 0x57, 0x21, 0x02, 0x12, 0xAA, 0x5E, 0x61, 0xD4, 0xCA, 0xF2, 0x84, 0x80, 0xF0,
+0x90, 0x37, 0x0B, 0xE5, 0xC9, 0xE4, 0xAD, 0xD5, 0x8C, 0x47, 0x6D, 0xFA, 0xE1, 0xE5, 0xC6, 0x3A,
+0xE4, 0x0A, 0x82, 0xCE, 0x05, 0xD6, 0x46, 0x39, 0xAE, 0xE9, 0xE4, 0x6A, 0xD7, 0xE5, 0x9E, 0x85,
+0x4A, 0x31, 0xFA, 0xA0, 0x86, 0x01, 0x4B, 0xC8, 0x77, 0xC2, 0x10, 0xED, 0x70, 0xD5, 0x7D, 0x0F,
+0xF4, 0xDC, 0x97, 0x93, 0xB2, 0x7D, 0x45, 0x7A, 0x24, 0x37, 0x2D, 0x39, 0xAC, 0xB6, 0x53, 0x6B,
+0xA5, 0x9B, 0xDC, 0xC1, 0xAC, 0x95, 0x01, 0x3E, 0x52, 0x53, 0x11, 0x0A, 0xB7, 0x1E, 0x1F, 0xCD,
+0x29, 0xC0, 0xE9, 0x0A, 0xDF, 0xE5, 0xF5, 0x54, 0xF7, 0xF7, 0x23, 0x7C, 0xC6, 0xB3, 0x18, 0xEA,
+0x0E, 0x08, 0xE3, 0x76, 0x8D, 0xDC, 0x01, 0x45, 0xB7, 0x45, 0xAF, 0x5C, 0x88, 0xEA, 0x74, 0xFE,
+0xE0, 0xC5, 0xA3, 0x73, 0x2D, 0x2E, 0x47, 0xF1, 0x2E, 0xC0, 0x01, 0x97, 0xE5, 0x64, 0x84, 0x59,
+0xC6, 0x83, 0xF5, 0xFC, 0x0D, 0x2D, 0x70, 0x46, 0x0E, 0x17, 0xE1, 0xC9, 0xE2, 0xBF, 0xF2, 0xF4,
+0x7B, 0x5C, 0xF1, 0xBE, 0xC3, 0xA7, 0x81, 0x96, 0xA1, 0x24, 0x67, 0x85, 0xF5, 0x6C, 0xD4, 0xA3,
+0x2A, 0xBE, 0xF5, 0x05, 0x2A, 0xBB, 0xF2, 0x18, 0xAF, 0xDC, 0x21, 0x8A, 0x76, 0x2E, 0xAC, 0x31,
+0xB7, 0x56, 0x55, 0xFD, 0x09, 0x48, 0x3A, 0xA6, 0x66, 0x1C, 0x2F, 0x92, 0x2C, 0x07, 0xDF, 0x09,
+0x3A, 0xD1, 0xEA, 0x7A, 0xFA, 0x87, 0xE3, 0xF6, 0x5D, 0x03, 0x45, 0xC9, 0x3F, 0x97, 0x60, 0x4F,
+0x9C, 0x6C, 0xCC, 0x55, 0x1F, 0xE1, 0xBD, 0x5E, 0xE5, 0x5D, 0x76, 0x0C, 0x00, 0xE0, 0xDA, 0xB9,
+0x60, 0xFC, 0xF4, 0xC5, 0xFC, 0x14, 0x3E, 0x2C, 0xF2, 0x18, 0xEC, 0x7D, 0x2B, 0x56, 0xFC, 0x6D,
+0xCE, 0x3D, 0x94, 0x5E, 0xA1, 0x00, 0xDC, 0x00, 0xA6, 0x73, 0xCE, 0xDE, 0x57, 0x87, 0xB3, 0x90,
+0xE5, 0x16, 0x82, 0x24, 0x62, 0xAD, 0x27, 0x8B, 0xFF, 0xDD, 0xD6, 0x7C, 0xFB, 0x45, 0x8A, 0x09,
+0xB0, 0x80, 0x15, 0x86, 0x90, 0xB9, 0xE9, 0x0F, 0x59, 0x86, 0x9E, 0xBA, 0xA2, 0x6A, 0xBA, 0x33,
+0xDD, 0xE5, 0xE8, 0x08, 0x6F, 0x3F, 0xF4, 0x2E, 0xF7, 0x25, 0x28, 0x23, 0x60, 0x51, 0x88, 0x50,
+0x66, 0x31, 0xEA, 0xEE, 0x83, 0x98, 0x62, 0x04, 0xBD, 0x48, 0x17, 0x34, 0x15, 0x2E, 0x9F, 0x33,
+0x8C, 0x96, 0x83, 0x71, 0x1C, 0x0F, 0x72, 0xEB, 0x5F, 0x1C, 0x1A, 0x79, 0x7C, 0x22, 0x4C, 0x84,
+0xC6, 0xA6, 0xD6, 0xDD, 0x29, 0x67, 0x78, 0xC5, 0xEC, 0x37, 0x3E, 0x00, 0xCF, 0xEF, 0x7E, 0x4B,
+0x6D, 0xB2, 0xBD, 0xD3, 0x70, 0x41, 0x2A, 0x89, 0x00, 0x0E, 0xCA, 0x89, 0xC6, 0x31, 0x9F, 0xCB,
+0x59, 0x0C, 0x9B, 0x47, 0x6A, 0x0C, 0x56, 0x6D, 0x03, 0xF7, 0xD4, 0x81, 0x15, 0x3E, 0x9F, 0x6F,
+0x15, 0x22, 0x10, 0x52, 0xCC, 0xD9, 0x2C, 0xA3, 0x85, 0xA5, 0x42, 0x04, 0x7E, 0xD2, 0xE2, 0x16,
+0x98, 0xB1, 0x40, 0x57, 0x8A, 0x5A, 0x54, 0xA1, 0xF8, 0x9B, 0x8C, 0x77, 0x7A, 0x5F, 0x26, 0x4B,
+0x85, 0xE0, 0x3C, 0xB2, 0xC2, 0xC2, 0x90, 0xDD, 0x8E, 0xD9, 0xF5, 0x94, 0xAC, 0x3E, 0x56, 0x20,
+0x63, 0x13, 0x08, 0x48, 0x69, 0x9C, 0xD7, 0xD7, 0x05, 0x1B, 0xB0, 0xF3, 0x8A, 0x81, 0x78, 0x43,
+0x62, 0x04, 0xAB, 0x8D, 0xA8, 0xD7, 0x51, 0x2C, 0xFE, 0x66, 0x80, 0x06, 0xC0, 0x10, 0x92, 0xF3,
+0xBA, 0xBF, 0x42, 0x95, 0x96, 0xB7, 0xDB, 0xA5, 0x73, 0x06, 0xB8, 0x0D, 0xAE, 0xDA, 0x00, 0xA7,
+0xD2, 0xF8, 0x63, 0xF0, 0x35, 0x15, 0x7D, 0x9B, 0x1C, 0x3D, 0x3F, 0x83, 0x9C, 0xAE, 0xC1, 0xFA,
+0xE3, 0x62, 0x9A, 0x8A, 0xF3, 0x86, 0x2F, 0xE4, 0xDB, 0x49, 0xDF, 0x2C, 0x17, 0xFE, 0x2C, 0x30,
+0xD1, 0x76, 0x88, 0x92, 0x60, 0x60, 0xB9, 0xF9, 0x35, 0x0F, 0xE2, 0xE8, 0x8E, 0x73, 0x9E, 0x7C,
+0xF6, 0xD0, 0x5F, 0x81, 0x22, 0x2A, 0x5D, 0x5F, 0x10, 0xFE, 0x7B, 0x06, 0xB5, 0x5F, 0xF3, 0x42,
+0x94, 0xC4, 0x3E, 0xE0, 0x0E, 0x11, 0xCC, 0x3B, 0x4F, 0xBD, 0x06, 0xD1, 0x15, 0xF5, 0x32, 0x76,
+0xE4, 0x97, 0xBF, 0xA7, 0xC5, 0xD0, 0x5E, 0x5A, 0x1C, 0x35, 0x18, 0x43, 0x6B, 0x10, 0xD2, 0xAB,
+0x8B, 0xF6, 0xE1, 0xBB, 0x8C, 0xE9, 0x9C, 0x6C, 0x27, 0x96, 0xF8, 0x19, 0x6F, 0x6E, 0x73, 0x28,
+0x8F, 0x51, 0x61, 0x0B, 0x4D, 0x4F, 0x22, 0x15, 0x1A, 0xCD, 0x88, 0x2C, 0x6F, 0x9C, 0xEC, 0x79,
+0x51, 0x70, 0x27, 0x8E, 0x58, 0xEF, 0xDE, 0x0B, 0xAA, 0x4D, 0xD2, 0x8F, 0x96, 0xE0, 0x71, 0x6A,
+0x8C, 0x41, 0xDB, 0x98, 0xF7, 0x2A, 0x09, 0x59, 0xD9, 0x48, 0x7B, 0x14, 0x87, 0x9B, 0x4A, 0xBB,
+0x88, 0xF2, 0x9D, 0x9D, 0x47, 0xF2, 0x80, 0x4B, 0xD9, 0x0E, 0xF3, 0xA9, 0x7E, 0xEF, 0xA1, 0x80,
+0x9D, 0x6F, 0x67, 0x6C, 0x14, 0x09, 0x2C, 0xB9, 0x03, 0xF3, 0x58, 0x37, 0xAE, 0x6B, 0xF7, 0x01,
+0x86, 0xDF, 0x43, 0xD5, 0xE4, 0xE2, 0x28, 0x8E, 0x8D, 0xA4, 0xF2, 0xC5, 0x7A, 0xA7, 0x89, 0x3A,
+0xE2, 0x7E, 0x77, 0xFD, 0x3A, 0x9A, 0x65, 0x5D, 0x87, 0xDC, 0x85, 0x70, 0xAB, 0xF3, 0x18, 0x0A
+
+cipher_key =
+0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2, 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A,
+0xd0, 0xe7, 0x4b, 0xfb, 0x5d, 0xe5, 0x0c, 0xe7
+
+auth_key =
+0xaf, 0x96, 0x42, 0xf1, 0x8c, 0x50, 0xdc, 0x67, 0x1a, 0x43, 0x47, 0x62, 0xc7, 0x04, 0xab, 0x05,
+0xf5, 0x0c, 0xe7, 0xa2, 0xa6, 0x23, 0xd5, 0x3d, 0x95, 0xd8, 0xcd, 0x86, 0x79, 0xf5, 0x01, 0x47,
+0x4f, 0xf9, 0x1d, 0x9d, 0x36, 0xf7, 0x68, 0x1a, 0x64, 0x44, 0x58, 0x5d, 0xe5, 0x81, 0x15, 0x2a,
+0x41, 0xe4, 0x0e, 0xaa, 0x1f, 0x04, 0x21, 0xff, 0x2c, 0xf3, 0x73, 0x2b, 0x48, 0x1e, 0xd2, 0xf7,
+0xf6, 0xd9, 0xaf, 0xbf, 0x08, 0x3b, 0xbb, 0x19, 0x5f, 0xf6, 0x7d, 0x25, 0x85, 0xdf, 0x6b, 0x54,
+0xd0, 0xe7, 0x4b, 0x9e, 0xc7, 0xef, 0xca, 0x48, 0x6f, 0x21, 0xd7, 0x51, 0xc8, 0x21, 0xc1, 0x15,
+0xe8, 0x38, 0x36, 0x58, 0x39, 0xd9, 0x9a, 0xc5, 0xe7, 0x3b, 0xc4, 0x47, 0xe2, 0xbd, 0x80, 0x73,
+0xf8, 0xd1, 0x9a, 0x5e, 0x4b, 0xfb, 0x52, 0x6b, 0x50, 0xaf, 0x8b, 0xb7, 0xb5, 0x2c, 0x52, 0x84
+
+iv =
+0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+
+####################
+# sha_hmac_buff_32 #
+####################
+[sha1_hmac_buff_32]
+digest =
+0x34, 0xCB, 0xFA, 0xE6, 0xBF, 0x60, 0x88, 0x82, 0x2C, 0x9F, 0x96, 0x4A, 0x5A, 0xD8, 0xAE, 0x48,
+0x1D, 0x2B, 0x0A, 0x22
+
+[sha224_hmac_buff_32]
+digest =
+0x17, 0xDD, 0xF3, 0xC0, 0xFC, 0xBC, 0x89, 0xE1, 0x02, 0x94, 0x51, 0x2B, 0xA0, 0x63, 0x4D, 0x1B,
+0x78, 0xCA, 0x0D, 0xD5, 0x99, 0xC0, 0xB8, 0x8E, 0x7F, 0x8A, 0xCB, 0x92
+
+[sha256_hmac_buff_32]
+digest =
+0xF7, 0xC0, 0xFD, 0x09, 0x94, 0x8F, 0x88, 0xF3, 0x26, 0xE1, 0xB1, 0xA6, 0x70, 0xFD, 0x57, 0xA2,
+0xB7, 0x63, 0x9C, 0x35, 0x97, 0x60, 0x27, 0x6A, 0xCC, 0xD8, 0x4A, 0xAE, 0xFD, 0xEC, 0x14, 0x56
+
+[sha384_hmac_buff_32]
+digest =
+0x01, 0x90, 0x96, 0x95, 0x8B, 0xE8, 0xF8, 0x30, 0xE0, 0xFE, 0xD4, 0x83, 0xE4, 0xE1, 0x48, 0xEB,
+0xEB, 0x3E, 0x6D, 0xBC, 0x72, 0xD8, 0xBF, 0x00, 0x86, 0x0B, 0x80, 0xCB, 0xCF, 0x0E, 0x83, 0x7E,
+0x77, 0x29, 0xA0, 0x71, 0xA9, 0x15, 0x8F, 0xE5, 0xC4, 0x32, 0xC8, 0xDB, 0x0A, 0xD1, 0xE3, 0x79
+
+[sha512_hmac_buff_32]
+digest =
+0x45, 0x72, 0x2B, 0xF4, 0x10, 0x82, 0xB6, 0xBC, 0xDB, 0x44, 0x34, 0x47, 0x55, 0xA7, 0x34, 0x4C,
+0x1C, 0x5D, 0x4D, 0x88, 0x58, 0x0B, 0xC2, 0x3E, 0xE7, 0x49, 0xF4, 0x6A, 0x99, 0x35, 0xE5, 0x2B,
+0xF4, 0x18, 0xD7, 0xD1, 0xAF, 0xC9, 0x81, 0xC5, 0x97, 0xE7, 0x94, 0xC4, 0xFD, 0x95, 0x7E, 0x1D,
+0x4E, 0xF4, 0x88, 0xC0, 0x10, 0x31, 0xB5, 0x1E, 0x39, 0x91, 0x1A, 0x48, 0xC2, 0x2F, 0xFE, 0xF6
+
+####################
+# sha_hmac_buff_64 #
+####################
+[sha1_hmac_buff_64]
+digest =
+0xD5, 0x0D, 0x9A, 0x30, 0xED, 0x71, 0x88, 0xF3, 0x72, 0x5D, 0x1C, 0xEF, 0x44, 0x36, 0xC1, 0x0C,
+0x66, 0x32, 0x15, 0xB5
+
+[sha224_hmac_buff_64]
+digest =
+0x59, 0xF0, 0x38, 0xA5, 0x7F, 0xDC, 0x55, 0xAF, 0x0A, 0x18, 0x0B, 0x34, 0xC1, 0x48, 0xFC, 0xB2,
+0xF8, 0x3B, 0xC2, 0x4A, 0x36, 0x0F, 0xEA, 0x4F, 0xD9, 0x46, 0x25, 0x1F
+
+[sha256_hmac_buff_64]
+digest =
+0x00, 0xD2, 0x5F, 0xAC, 0x89, 0x4B, 0x16, 0x08, 0x89, 0x8D, 0x4F, 0x8F, 0x56, 0xF5, 0xA2, 0x9B,
+0xDB, 0x91, 0x2F, 0xCE, 0x90, 0x0E, 0x4B, 0x17, 0x74, 0x8B, 0xC4, 0x8A, 0x47, 0xF0, 0x7C, 0x7A
+
+[sha384_hmac_buff_64]
+digest =
+0xFE, 0x79, 0x5C, 0x3D, 0xEA, 0x2C, 0x04, 0xB9, 0xE9, 0x37, 0x4E, 0x02, 0xE8, 0x56, 0xE8, 0x7E,
+0xB4, 0xA7, 0x3D, 0x37, 0xDD, 0x05, 0x58, 0x6A, 0x3D, 0x44, 0x0E, 0x84, 0xA9, 0xB4, 0x1F, 0x26,
+0xED, 0xAF, 0xA3, 0x4D, 0xA3, 0x6E, 0x30, 0x8F, 0xE3, 0x79, 0xB9, 0x58, 0x4E, 0xB3, 0x36, 0x1D
+
+[sha512_hmac_buff_64]
+digest =
+0x3A, 0xFE, 0x1E, 0xC8, 0x75, 0x0D, 0xF3, 0x15, 0x03, 0xCC, 0x7B, 0x50, 0xD1, 0x3E, 0x35, 0x97,
+0x4D, 0x80, 0xB8, 0x0B, 0x5E, 0x22, 0x4D, 0xB9, 0xD2, 0xC9, 0x0E, 0x24, 0xC4, 0xD9, 0xDD, 0x95,
+0xA1, 0x7D, 0xED, 0xE4, 0x28, 0x17, 0x7C, 0x50, 0x0B, 0x40, 0x81, 0x18, 0xEA, 0xFF, 0xBA, 0x1C,
+0x8C, 0x5D, 0x17, 0xB3, 0x5B, 0x39, 0x70, 0x93, 0x9A, 0xA0, 0x47, 0x59, 0x06, 0x01, 0xE5, 0xD0
+
+#####################
+# sha_hmac_buff_128 #
+#####################
+[sha1_hmac_buff_128]
+digest =
+0xF6, 0x21, 0x56, 0x15, 0xEC, 0xB6, 0xDE, 0x2B, 0x68, 0x79, 0x30, 0x69, 0x69, 0x82, 0x4B, 0x97,
+0x57, 0x61, 0xED, 0x01
+
+[sha224_hmac_buff_128]
+digest =
+0xC4, 0x5A, 0x48, 0x07, 0xCC, 0xFD, 0x68, 0x28, 0xCC, 0xDA, 0x13, 0x9C, 0xFE, 0x02, 0x22, 0x1C,
+0xD5, 0x2E, 0x9F, 0x0D, 0xED, 0x0B, 0x9B, 0x6D, 0xF3, 0x81, 0xD6, 0xDF
+
+[sha256_hmac_buff_128]
+digest =
+0x44, 0xA6, 0x70, 0x6C, 0xD2, 0xA6, 0x3F, 0xFB, 0x98, 0xB9, 0x6A, 0x71, 0x40, 0xCF, 0xD2, 0x40,
+0xA3, 0xC0, 0xC6, 0x4E, 0xF6, 0xD8, 0x4D, 0x87, 0xF5, 0x9B, 0xAC, 0xB0, 0x7B, 0xB7, 0x35, 0x5B
+
+[sha384_hmac_buff_128]
+digest =
+0xD7, 0xFA, 0xF1, 0xC5, 0xD6, 0xCE, 0xB9, 0x77, 0xD5, 0x6B, 0x4D, 0x7F, 0xFE, 0xAF, 0xDF, 0xCE,
+0x68, 0x1A, 0xB7, 0x3E, 0xA5, 0x9A, 0xF5, 0x79, 0x91, 0x96, 0x7C, 0xED, 0xC9, 0x02, 0x31, 0x67,
+0xC4, 0xD9, 0xD7, 0x5A, 0xD7, 0xF0, 0x82, 0x2C, 0xBD, 0x4A, 0xFF, 0x03, 0x25, 0xB6, 0x50, 0x17
+
+[sha512_hmac_buff_128]
+digest =
+0x78, 0xE1, 0x86, 0x74, 0xC1, 0x83, 0xDB, 0x3C, 0xAC, 0x2B, 0x17, 0xAC, 0x12, 0xAA, 0x30, 0xDE,
+0x2C, 0x86, 0xC4, 0x53, 0x4A, 0xC2, 0x78, 0x86, 0x3A, 0x8A, 0x96, 0x36, 0x2B, 0x09, 0xB1, 0x62,
+0xCA, 0xD0, 0x25, 0xB2, 0x5B, 0x3A, 0x76, 0xFA, 0xED, 0x5B, 0xFB, 0xF0, 0x8F, 0xF2, 0x06, 0x76,
+0x9B, 0xE0, 0x82, 0x25, 0x10, 0x5E, 0x8A, 0x13, 0xA1, 0x25, 0x3B, 0xB7, 0xFC, 0xC3, 0x15, 0xED
+
+#####################
+# sha_hmac_buff_256 #
+#####################
+[sha1_hmac_buff_256]
+digest =
+0x31, 0x36, 0xC8, 0xC7, 0x95, 0xDB, 0xF7, 0xF3, 0xA0, 0xFF, 0x89, 0x94, 0x8D, 0xB2, 0x3D, 0x5F,
+0x7A, 0xC1, 0x38, 0x97
+
+[sha224_hmac_buff_256]
+digest =
+0xAE, 0x1B, 0xA4, 0x42, 0xE6, 0x3C, 0x3D, 0xEE, 0xEE, 0xD1, 0x24, 0xD2, 0xFF, 0xD2, 0x1A, 0xF3,
+0x28, 0x87, 0x8F, 0x00, 0xE3, 0x74, 0xA1, 0xA2, 0xED, 0x70, 0x2D, 0x9D
+
+[sha256_hmac_buff_256]
+digest =
+0x73, 0x89, 0x54, 0x06, 0x65, 0x71, 0x1D, 0xA1, 0xAB, 0x4A, 0x0A, 0x36, 0x63, 0x92, 0xB8, 0x94,
+0x98, 0x98, 0xB5, 0x27, 0x9D, 0x9C, 0xF2, 0x91, 0x0C, 0x56, 0xC4, 0xEE, 0x99, 0xC6, 0xDE, 0xC7
+
+[sha384_hmac_buff_256]
+digest =
+0xFE, 0x6E, 0xA5, 0xDC, 0x82, 0x57, 0xBB, 0x4D, 0xA8, 0xF1, 0x2F, 0xD1, 0xA2, 0x05, 0x0A, 0xFE,
+0xF2, 0x64, 0x8A, 0xB3, 0x96, 0xBA, 0x06, 0x47, 0xA4, 0x40, 0x76, 0x8E, 0xB8, 0xE3, 0xAD, 0xD1,
+0xB2, 0x90, 0x9A, 0x02, 0xD1, 0x13, 0x4F, 0x74, 0x9B, 0xEB, 0x09, 0xFC, 0x7F, 0x99, 0xAC, 0xCD
+
+[sha512_hmac_buff_256]
+digest =
+0x9F, 0x71, 0xE0, 0x86, 0xF9, 0x76, 0x3F, 0xAB, 0x16, 0x4D, 0x9C, 0x28, 0x72, 0x3A, 0x17, 0x8F,
+0x35, 0xD1, 0x44, 0x18, 0xE0, 0x4A, 0xBD, 0x8B, 0x25, 0x9F, 0x6E, 0x5B, 0xE3, 0xF4, 0x1C, 0x40,
+0x2B, 0xF4, 0x61, 0x59, 0x60, 0x8D, 0x55, 0xD8, 0x18, 0x9B, 0x65, 0x8D, 0x9F, 0xAA, 0xB3, 0x71,
+0x3D, 0xB5, 0x70, 0xD2, 0x26, 0xF1, 0x55, 0xDC, 0xCE, 0x49, 0x40, 0xD7, 0x23, 0x6B, 0x20, 0x4A
+
+#####################
+# sha_hmac_buff_512 #
+#####################
+[sha1_hmac_buff_512]
+digest =
+0x0F, 0xF6, 0x33, 0x61, 0x16, 0x5C, 0xD1, 0x9E, 0xE0, 0x3D, 0x95, 0x93, 0xD2, 0x82, 0xDE, 0x2E,
+0xFA, 0x25, 0x56, 0xE4
+
+[sha224_hmac_buff_512]
+digest =
+0x85, 0x61, 0x57, 0x9F, 0x3E, 0x6A, 0xE1, 0x5C, 0x1D, 0xA3, 0x98, 0x9C, 0x28, 0x2C, 0x96, 0x8E,
+0xD0, 0x7D, 0x70, 0x7D, 0xF5, 0x98, 0xA4, 0x7C, 0x88, 0x1C, 0xA4, 0x5C
+
+[sha256_hmac_buff_512]
+digest =
+0xF4, 0x77, 0xB2, 0x2E, 0xAD, 0xBC, 0xA2, 0xCD, 0x49, 0xE0, 0xD2, 0xB0, 0xB3, 0xDE, 0x51, 0xD0,
+0xBC, 0xEF, 0x33, 0x50, 0x4F, 0x39, 0xBC, 0x94, 0x18, 0xF3, 0xDD, 0xFC, 0xB5, 0x8E, 0x44, 0x18
+
+[sha384_hmac_buff_512]
+digest =
+0x03, 0x4F, 0x86, 0xA0, 0xBC, 0x00, 0x44, 0xEB, 0x06, 0x75, 0x61, 0x13, 0x92, 0x60, 0x74, 0x44,
+0x1D, 0xCB, 0x2C, 0x8D, 0xEC, 0xE5, 0x5C, 0xBE, 0xA3, 0xAE, 0x5F, 0xE2, 0x71, 0xED, 0xAC, 0x69,
+0x9C, 0x6C, 0xE3, 0x20, 0x5C, 0x90, 0xC3, 0xF4, 0x36, 0x76, 0x70, 0xAE, 0x2A, 0x9C, 0xF5, 0x0B
+
+[sha512_hmac_buff_512]
+digest =
+0x3B, 0x83, 0x4B, 0x7F, 0x2A, 0x62, 0x9A, 0xF6, 0x42, 0x29, 0x7A, 0xF0, 0xCA, 0xE7, 0xBE, 0x1F,
+0x92, 0x5C, 0x66, 0x88, 0x58, 0xFA, 0xA4, 0xC7, 0xE7, 0xF0, 0xEA, 0x83, 0xB2, 0x0A, 0x2C, 0x3B,
+0xA7, 0xD4, 0xA4, 0x3E, 0x87, 0x00, 0x44, 0x2B, 0x3F, 0xB2, 0x4B, 0xFF, 0xAD, 0x9B, 0x07, 0x7D,
+0xA1, 0x09, 0x09, 0x60, 0x68, 0x2F, 0x7B, 0x16, 0x43, 0x0E, 0x22, 0xAF, 0x78, 0x8D, 0xC7, 0x16
+
+######################
+# sha_hmac_buff_1024 #
+######################
+[sha1_hmac_buff_1024]
+digest =
+0xCD, 0x04, 0x78, 0x4A, 0xD5, 0xFE, 0x95, 0xFB, 0x04, 0x85, 0xD5, 0x25, 0x58, 0xE6, 0x6C, 0x81,
+0xFA, 0x4B, 0xE7, 0x75
+
+[sha224_hmac_buff_1024]
+digest =
+0x10, 0xA5, 0x18, 0x56, 0x66, 0xDE, 0xE6, 0xF6, 0x71, 0xAF, 0x65, 0xEC, 0xE3, 0x77, 0x08, 0x58,
+0xD5, 0x45, 0xE6, 0x21, 0xF5, 0xCC, 0x2B, 0xE2, 0x76, 0x91, 0x51, 0xD9
+
+[sha256_hmac_buff_1024]
+digest =
+0xB4, 0x09, 0xF9, 0xA0, 0x5B, 0x80, 0xFF, 0xBA, 0x21, 0x5F, 0x57, 0xAB, 0x8B, 0x67, 0x89, 0x6D,
+0xB4, 0xE9, 0xEA, 0x5D, 0x77, 0x57, 0xBD, 0x0A, 0x60, 0xA4, 0x6B, 0xE8, 0xAA, 0x8A, 0x9B, 0xC7
+
+[sha384_hmac_buff_1024]
+digest =
+0x9D, 0xAE, 0x37, 0x87, 0x2C, 0x36, 0xFD, 0x51, 0xF1, 0xF2, 0x4C, 0x82, 0x27, 0xB5, 0x99, 0x63,
+0xAB, 0xD7, 0x62, 0x4A, 0x4E, 0xF1, 0xBF, 0xFB, 0xCA, 0x30, 0x55, 0x3F, 0x43, 0x85, 0xDE, 0x6B,
+0xA2, 0xB2, 0x8B, 0x45, 0x2A, 0x9D, 0x39, 0x29, 0x63, 0x1C, 0x04, 0x47, 0x58, 0x94, 0x5C, 0x91
+
+[sha512_hmac_buff_1024]
+digest =
+0xBF, 0x06, 0x94, 0xBB, 0x2E, 0x9C, 0x0A, 0xA4, 0xF3, 0x5F, 0x52, 0x4B, 0x42, 0x6E, 0xE1, 0x6C,
+0xA8, 0xAB, 0xB7, 0xE9, 0x6F, 0xAB, 0x77, 0xF8, 0x94, 0xD0, 0xA1, 0x81, 0xB8, 0x17, 0x21, 0xAC,
+0xB2, 0x3C, 0x73, 0x71, 0xDD, 0x76, 0xF8, 0x58, 0x84, 0xE7, 0xBB, 0xD4, 0x4A, 0x4F, 0x51, 0xF5,
+0x8C, 0x87, 0xAA, 0xAC, 0xCE, 0x5E, 0xFB, 0xD3, 0x1F, 0xA2, 0x49, 0xF2, 0x40, 0xAB, 0xB8, 0x76
+
+######################
+# sha_hmac_buff_2048 #
+######################
+[sha1_hmac_buff_2048]
+digest =
+0x56, 0xE7, 0x86, 0x23, 0x2C, 0x77, 0xBE, 0x2B, 0xE6, 0x76, 0xA1, 0xE9, 0xB1, 0x0F, 0x25, 0x15,
+0x1D, 0x59, 0x7F, 0x4A
+
+[sha224_hmac_buff_2048]
+digest =
+0xFD, 0xEB, 0x9E, 0x04, 0x53, 0xC7, 0xEA, 0x56, 0x21, 0x91, 0x6D, 0x8B, 0xDC, 0xA1, 0x0A, 0x2F,
+0x73, 0x4D, 0x05, 0x36, 0x43, 0x58, 0x71, 0xB2, 0x74, 0x6E, 0x7B, 0xAF
+
+[sha256_hmac_buff_2048]
+digest =
+0x25, 0x76, 0xA5, 0x64, 0x00, 0x13, 0xF7, 0xE7, 0x2D, 0x6D, 0x17, 0x36, 0x13, 0xF3, 0xC7, 0x57,
+0x70, 0x30, 0xB2, 0x76, 0x7A, 0xF4, 0x8F, 0xAF, 0x6B, 0x8C, 0x26, 0x88, 0x73, 0x2E, 0x49, 0xC0
+
+[sha384_hmac_buff_2048]
+digest =
+0xF0, 0x69, 0x78, 0x9A, 0x34, 0x88, 0x25, 0x3C, 0x3D, 0xF5, 0x42, 0x65, 0x25, 0x79, 0xB2, 0xFC,
+0x3B, 0x92, 0x46, 0xF9, 0x0D, 0x6D, 0xC1, 0x8E, 0x45, 0xBE, 0x8B, 0x70, 0x7D, 0x1B, 0x7E, 0xDE,
+0x93, 0x04, 0xC8, 0x59, 0x4B, 0x37, 0x2C, 0x20, 0x51, 0xB1, 0x91, 0x4F, 0xA4, 0x30, 0x09, 0xED
+
+[sha512_hmac_buff_2048]
+digest =
+0xAE, 0x8A, 0x42, 0x03, 0x11, 0x25, 0xE8, 0xC3, 0x4B, 0x4B, 0xC0, 0x29, 0x27, 0xE0, 0x0D, 0x27,
+0x13, 0x8F, 0x7D, 0x82, 0x72, 0x94, 0x4B, 0xF8, 0xC3, 0x1A, 0xE1, 0x5A, 0xF3, 0x8E, 0x23, 0x27,
+0x76, 0xE4, 0xF5, 0x3E, 0x24, 0x5B, 0xA3, 0xFA, 0x49, 0x8E, 0x57, 0xE3, 0x88, 0x15, 0x1D, 0xF6,
+0x27, 0xA5, 0xC8, 0xFB, 0x34, 0x44, 0x18, 0x6A, 0x64, 0xBE, 0xFB, 0x1E, 0x87, 0xA8, 0x36, 0x1E
diff --git a/src/seastar/dpdk/app/test-crypto-perf/data/aes_cbc_256_sha.data b/src/seastar/dpdk/app/test-crypto-perf/data/aes_cbc_256_sha.data
new file mode 100644
index 00000000..52dafb93
--- /dev/null
+++ b/src/seastar/dpdk/app/test-crypto-perf/data/aes_cbc_256_sha.data
@@ -0,0 +1,504 @@
+# List of tests for AES-256 CBC:
+# 1) [sha1_hmac_buff_x]
+# 2) [sha224_hmac_buff_x]
+# 3) [sha256_hmac_buff_x]
+# 4) [sha384_hmac_buff_x]
+# 5) [sha512_hmac_buff_x]
+# where x is one of the values: 32, 64, 128, 256, 512, 1024, 2048
+
+##########
+# GLOBAL #
+##########
+plaintext =
+0xff, 0xca, 0xfb, 0xf1, 0x38, 0x20, 0x2f, 0x7b, 0x24, 0x98, 0x26, 0x7d, 0x1d, 0x9f, 0xb3, 0x93,
+0xd9, 0xef, 0xbd, 0xad, 0x4e, 0x40, 0xbd, 0x60, 0xe9, 0x48, 0x59, 0x90, 0x67, 0xd7, 0x2b, 0x7b,
+0x8a, 0xe0, 0x4d, 0xb0, 0x70, 0x38, 0xcc, 0x48, 0x61, 0x7d, 0xee, 0xd6, 0x35, 0x49, 0xae, 0xb4,
+0xaf, 0x6b, 0xdd, 0xe6, 0x21, 0xc0, 0x60, 0xce, 0x0a, 0xf4, 0x1c, 0x2e, 0x1c, 0x8d, 0xe8, 0x7b,
+0x59, 0xda, 0x19, 0x4f, 0xec, 0x07, 0x8e, 0xe2, 0xf0, 0x61, 0xf9, 0x27, 0x61, 0x6f, 0xf8, 0xdf,
+0x62, 0x4d, 0xaf, 0x06, 0xfe, 0x41, 0xa6, 0xa6, 0xf9, 0xa2, 0x06, 0x40, 0xb3, 0x04, 0xbd, 0xe6,
+0xc8, 0x17, 0xfb, 0x56, 0x6f, 0xa9, 0x3b, 0x8e, 0xa6, 0x58, 0xdc, 0x91, 0x17, 0x58, 0x42, 0x95,
+0xa3, 0x7c, 0x81, 0x78, 0xa6, 0x3d, 0x3f, 0x75, 0x74, 0x17, 0x1a, 0xd3, 0x6c, 0x2f, 0x48, 0x39,
+0x20, 0x20, 0xc1, 0x9a, 0x29, 0x84, 0x7d, 0x2d, 0x52, 0xa1, 0xf9, 0x5c, 0xf3, 0x4f, 0x91, 0xfc,
+0x75, 0xcf, 0xd6, 0x2d, 0xe7, 0x9a, 0x59, 0x6e, 0x00, 0x0e, 0x8d, 0x22, 0x17, 0xbd, 0xa0, 0xdd,
+0x79, 0x1f, 0x71, 0xe6, 0xcd, 0x2f, 0xb1, 0xb6, 0xbc, 0xc3, 0xdb, 0x02, 0x91, 0x41, 0x9b, 0x09,
+0xa9, 0xd2, 0x7e, 0xbd, 0x2c, 0x18, 0xae, 0xc0, 0x93, 0x0c, 0x02, 0x9a, 0xdb, 0x4e, 0xaa, 0xeb,
+0x84, 0x4b, 0x43, 0x5e, 0xf0, 0x98, 0xf2, 0x5f, 0x86, 0x70, 0x96, 0x90, 0x15, 0x30, 0xcf, 0x3a,
+0xc9, 0x33, 0x21, 0xec, 0x59, 0x86, 0xfc, 0x65, 0x7d, 0xbe, 0xb9, 0xf8, 0x97, 0xf9, 0x30, 0xa9,
+0x6d, 0xfc, 0x0c, 0x6e, 0x36, 0x67, 0xd5, 0xa6, 0x67, 0xd9, 0xbd, 0x9b, 0x34, 0x5d, 0xa7, 0xdd,
+0xda, 0x46, 0x33, 0x25, 0x60, 0x4a, 0x18, 0xf1, 0x55, 0x07, 0xb2, 0xb7, 0x26, 0x7b, 0xa6, 0x1e,
+0x77, 0xbe, 0x7f, 0x35, 0x46, 0xdf, 0x56, 0x9c, 0x22, 0x19, 0xc8, 0x85, 0xa2, 0x45, 0xb2, 0xad,
+0xf9, 0x26, 0x66, 0xab, 0xfc, 0x97, 0x4b, 0x51, 0x32, 0x36, 0xbc, 0xad, 0xcf, 0x54, 0x3a, 0x4f,
+0x94, 0xdb, 0xd2, 0xf9, 0x67, 0x1b, 0x3b, 0xe5, 0xb2, 0x1d, 0xc5, 0x52, 0x64, 0x2c, 0x06, 0x44,
+0xcf, 0x18, 0x83, 0xe0, 0xd8, 0x04, 0x92, 0xa9, 0xc4, 0x3c, 0x8b, 0xa3, 0x2b, 0xbc, 0x88, 0x7e,
+0xc0, 0x76, 0xa7, 0xe2, 0x7b, 0x47, 0x90, 0xf2, 0xaa, 0x0a, 0x34, 0x1b, 0x91, 0x12, 0xd2, 0xd0,
+0x82, 0x45, 0xf4, 0x57, 0xf1, 0xbd, 0x91, 0x5e, 0xab, 0x41, 0x4c, 0xdf, 0x91, 0x4c, 0xdd, 0x67,
+0x04, 0xa0, 0x98, 0x23, 0x8c, 0x24, 0xbe, 0xd6, 0x80, 0xb3, 0x6d, 0x04, 0xa1, 0x77, 0x43, 0xa5,
+0xee, 0xb7, 0xce, 0xb1, 0x48, 0x43, 0x94, 0x61, 0x15, 0x20, 0x9d, 0xce, 0xd0, 0x14, 0x95, 0x37,
+0xc8, 0x64, 0xa3, 0x2d, 0x3d, 0xe3, 0xff, 0xb4, 0x55, 0x83, 0x84, 0x41, 0x50, 0x57, 0xbd, 0x5a,
+0x0c, 0xe4, 0xda, 0x3b, 0x36, 0x4d, 0x21, 0xb5, 0x6f, 0x73, 0x2a, 0x8c, 0x78, 0x4f, 0x9b, 0x83,
+0xda, 0x11, 0x3c, 0xf0, 0xc9, 0x7e, 0xa6, 0x48, 0x34, 0x53, 0x62, 0xd3, 0x0c, 0xff, 0xb1, 0x74,
+0xd6, 0xea, 0xa5, 0xfc, 0x13, 0x1c, 0x05, 0xa8, 0xc0, 0xbc, 0x95, 0x9c, 0x8c, 0xf6, 0x8c, 0xc3,
+0xf3, 0x69, 0xab, 0x93, 0x65, 0xc0, 0xb7, 0x7e, 0xb0, 0x16, 0x7c, 0xb5, 0x5f, 0x05, 0x28, 0xc9,
+0x09, 0x4e, 0x2a, 0x32, 0x87, 0xb3, 0xab, 0xf8, 0x4c, 0xab, 0xeb, 0x3b, 0x6a, 0xa0, 0x1d, 0x7f,
+0xef, 0xe5, 0x9b, 0xa4, 0xb7, 0xd7, 0xc2, 0x5e, 0x03, 0x0f, 0x99, 0xeb, 0xb1, 0xb1, 0xa6, 0x9d,
+0x1c, 0x7c, 0x5c, 0x94, 0x8b, 0x6e, 0x11, 0x7a, 0xb3, 0x6d, 0x1e, 0x61, 0x64, 0xc3, 0x7d, 0x1c,
+0xb3, 0x54, 0x65, 0x08, 0x3b, 0xda, 0x97, 0xb9, 0x75, 0xc1, 0x2b, 0x3e, 0xa8, 0x5c, 0x3c, 0x2d,
+0x81, 0x5b, 0xbf, 0x5a, 0x13, 0x0e, 0xeb, 0x66, 0xc0, 0x0b, 0x8f, 0x04, 0x68, 0x68, 0x9b, 0xe3,
+0x0d, 0x84, 0xe0, 0xcf, 0x83, 0xd7, 0x62, 0x48, 0xc1, 0x31, 0xa5, 0xd5, 0xbc, 0xe3, 0xa3, 0xa5,
+0xb6, 0xd1, 0xfd, 0x81, 0x91, 0x4d, 0xbd, 0xc4, 0x62, 0x4f, 0xe3, 0xd5, 0x99, 0x14, 0xf1, 0xcd,
+0xf4, 0x7d, 0x13, 0xda, 0x68, 0x0a, 0xca, 0xd6, 0x82, 0x0b, 0xf6, 0xea, 0xad, 0x78, 0xa4, 0xc8,
+0x14, 0x7a, 0xec, 0x11, 0xd3, 0x16, 0x86, 0x9f, 0x17, 0x37, 0x6a, 0x06, 0x56, 0xaa, 0x1b, 0xd1,
+0xaf, 0x85, 0x95, 0x21, 0x36, 0x69, 0xec, 0x1b, 0x56, 0x84, 0x01, 0x3f, 0x4d, 0x34, 0x3d, 0x2d,
+0x38, 0x57, 0x2d, 0x7e, 0xd9, 0x7b, 0x2d, 0x81, 0x86, 0xd4, 0x7c, 0x83, 0x12, 0x1d, 0x9d, 0x27,
+0x72, 0x1b, 0x5e, 0xf4, 0x15, 0xa5, 0xcd, 0xb7, 0x5f, 0xbb, 0x49, 0xa1, 0xd9, 0xdd, 0x8d, 0xad,
+0xa9, 0x2c, 0x65, 0x18, 0x91, 0xfd, 0xd2, 0xd4, 0x09, 0x60, 0x0c, 0xfd, 0xa4, 0xe1, 0x25, 0x87,
+0x32, 0x64, 0x7b, 0x99, 0xd7, 0x61, 0x2f, 0xd4, 0x73, 0xdd, 0x85, 0x26, 0x08, 0x92, 0xc0, 0xe1,
+0x4f, 0x0c, 0x76, 0x5b, 0x26, 0x69, 0xdb, 0x78, 0x35, 0x65, 0xb9, 0x58, 0x1f, 0x9c, 0x0f, 0x18,
+0x95, 0xfe, 0x40, 0xfc, 0xf7, 0x93, 0x71, 0x70, 0x8b, 0x73, 0xdc, 0xb0, 0x88, 0x72, 0x19, 0x26,
+0x94, 0x26, 0xa7, 0xaa, 0x00, 0x72, 0x61, 0x53, 0xd2, 0x5d, 0x8f, 0x5e, 0x51, 0x88, 0x2d, 0xa4,
+0x28, 0xd5, 0xaf, 0x2d, 0xd2, 0x84, 0x39, 0x75, 0x1e, 0xe7, 0xf0, 0x23, 0xc0, 0x4f, 0x8d, 0xdd,
+0x5c, 0x90, 0xef, 0x6e, 0x53, 0xe0, 0x54, 0x67, 0xe1, 0x5b, 0x10, 0xf1, 0xf5, 0xf8, 0x64, 0x34,
+0x94, 0xeb, 0x37, 0xf7, 0xe9, 0xaa, 0x6c, 0xa4, 0xd8, 0x74, 0x6d, 0xca, 0x8d, 0x1a, 0x31, 0x73,
+0xca, 0xb4, 0xc7, 0x47, 0x34, 0x7f, 0xf8, 0x24, 0x9b, 0xfa, 0xc9, 0xcc, 0xa8, 0x61, 0xb4, 0x0e,
+0x4d, 0x68, 0xc7, 0xa0, 0xcb, 0xea, 0xf0, 0xcc, 0x0a, 0x6c, 0xf2, 0x33, 0x42, 0x99, 0x6c, 0xd8,
+0x74, 0x7f, 0x1e, 0x8a, 0xa3, 0x0a, 0x48, 0x4b, 0x7e, 0xbe, 0xdb, 0x7f, 0x56, 0x69, 0x43, 0xe8,
+0xbf, 0x12, 0xc4, 0x7b, 0xc2, 0xd9, 0xfa, 0x5c, 0xeb, 0x45, 0xca, 0x07, 0x3d, 0xc0, 0xcd, 0x68,
+0x8b, 0xd0, 0x79, 0xea, 0x0a, 0x78, 0x06, 0xdc, 0x81, 0xd7, 0x32, 0x18, 0xb3, 0x65, 0xbe, 0x47,
+0xbb, 0xfa, 0x17, 0x09, 0xe9, 0x31, 0x95, 0x30, 0xef, 0x07, 0x44, 0xec, 0xd0, 0x98, 0x98, 0xc0,
+0x6b, 0x71, 0x5b, 0x23, 0xb8, 0xb6, 0xd2, 0x21, 0xff, 0x51, 0xdd, 0xae, 0x48, 0x29, 0x75, 0x0c,
+0xc3, 0x3d, 0x91, 0xfe, 0x9d, 0xa8, 0x5e, 0xb2, 0x34, 0xb2, 0xd3, 0x81, 0xf6, 0x27, 0x9c, 0xac,
+0x6b, 0x20, 0x56, 0x86, 0xa5, 0x4f, 0x7a, 0xdb, 0xf9, 0xac, 0xa9, 0x8e, 0xe3, 0x73, 0x21, 0x99,
+0x71, 0x2d, 0xaf, 0x27, 0x92, 0x0c, 0xc7, 0xd3, 0x85, 0xb3, 0x40, 0xda, 0x13, 0x4a, 0x04, 0x41,
+0x54, 0xf8, 0xf2, 0x55, 0xb7, 0x80, 0xdd, 0x77, 0xba, 0x01, 0x7a, 0x31, 0xbd, 0x6b, 0xdc, 0x5c,
+0x59, 0xf4, 0x2b, 0xca, 0x25, 0xbb, 0x50, 0xba, 0xfa, 0x42, 0x38, 0xd2, 0x28, 0x10, 0x8b, 0x7b,
+0x96, 0x45, 0x30, 0xbb, 0x7f, 0xf4, 0x5a, 0xf7, 0x28, 0x6f, 0x47, 0xdc, 0xd2, 0x82, 0xf2, 0xf7,
+0xdd, 0x20, 0xb5, 0x0c, 0x7e, 0x53, 0x85, 0xa7, 0xfc, 0x3b, 0x1a, 0xc0, 0x07, 0x7b, 0xa1, 0x43,
+0x05, 0x18, 0x19, 0xd3, 0xfc, 0x41, 0xc2, 0xce, 0xd9, 0x5b, 0x4b, 0x63, 0xe2, 0x8f, 0x86, 0x3a,
+0xd1, 0xd0, 0x1d, 0x74, 0x2e, 0xbc, 0xd3, 0xce, 0x08, 0x0c, 0x10, 0x7a, 0x42, 0x60, 0xc5, 0x3a,
+0xa6, 0xd8, 0xb0, 0x52, 0xcf, 0x53, 0x28, 0x70, 0x45, 0xb7, 0x72, 0x7d, 0x77, 0x66, 0x54, 0x3d,
+0x38, 0x26, 0xcf, 0xd5, 0xbf, 0xe4, 0x80, 0x10, 0xba, 0x2b, 0xe8, 0xdc, 0xc3, 0xfe, 0x28, 0xa3,
+0x52, 0x58, 0x70, 0x4a, 0xde, 0x84, 0x33, 0x5e, 0x93, 0x04, 0xa4, 0x7c, 0xe7, 0xea, 0x8e, 0xba,
+0xeb, 0x8a, 0x19, 0x26, 0x6a, 0x7f, 0x7c, 0x4a, 0x5b, 0xb4, 0x0d, 0xfc, 0xc8, 0x11, 0x1b, 0x41,
+0x68, 0x5d, 0x2a, 0x25, 0x04, 0x4f, 0xc8, 0xf4, 0x65, 0xfc, 0xb9, 0x58, 0xeb, 0xb4, 0x67, 0x50,
+0x24, 0xf5, 0x43, 0xf6, 0x91, 0x4a, 0xb0, 0x0f, 0x32, 0xe0, 0x07, 0x75, 0x69, 0x1b, 0x3c, 0xeb,
+0xb2, 0x65, 0x26, 0x6f, 0xb8, 0x79, 0xe0, 0x78, 0x8c, 0xdc, 0x39, 0x24, 0x48, 0x76, 0x11, 0xd4,
+0x3a, 0xc5, 0xd2, 0x2b, 0xaa, 0x55, 0xfb, 0x92, 0x12, 0x2d, 0x88, 0x05, 0xd1, 0xb1, 0x31, 0x36,
+0x1f, 0xc2, 0x44, 0x1c, 0xab, 0x2e, 0xcd, 0x1c, 0x72, 0x86, 0xf6, 0x83, 0x87, 0x2e, 0x8b, 0xdb,
+0xaa, 0x16, 0x0e, 0x1b, 0xe6, 0x5c, 0x4d, 0x2f, 0x82, 0xbd, 0x49, 0x11, 0x60, 0x22, 0x0f, 0xde,
+0x3b, 0x2b, 0x20, 0x1d, 0x56, 0xb7, 0x21, 0xae, 0x0b, 0x26, 0x4f, 0xde, 0x3d, 0xa6, 0x3f, 0x61,
+0x81, 0xe2, 0x76, 0x60, 0x08, 0xc5, 0x4b, 0x18, 0x0b, 0xd1, 0xf5, 0xff, 0x8d, 0x1a, 0x96, 0x76,
+0x51, 0x15, 0x05, 0x4d, 0x8c, 0x6b, 0x12, 0x90, 0x47, 0xd4, 0xa4, 0x38, 0xb9, 0x48, 0xe4, 0x4c,
+0x05, 0x69, 0x6a, 0x8b, 0x9d, 0x7c, 0xa1, 0xbc, 0x77, 0xeb, 0x86, 0x93, 0x0a, 0x15, 0x84, 0xba,
+0x8f, 0xf5, 0x7c, 0x44, 0x75, 0x31, 0x79, 0x16, 0xc1, 0x81, 0x1a, 0xb6, 0xe6, 0x6c, 0x3d, 0xb8,
+0x15, 0x46, 0xf5, 0xbe, 0x46, 0x04, 0xa6, 0xec, 0xec, 0xd1, 0x74, 0x8b, 0x87, 0x2b, 0xdb, 0xd0,
+0x9f, 0xb3, 0x99, 0x9d, 0x87, 0x8c, 0xc6, 0xaa, 0xd4, 0x64, 0x45, 0xbd, 0xe8, 0xed, 0xa3, 0xc1,
+0x2a, 0x41, 0x1e, 0x26, 0xaf, 0x86, 0x16, 0xed, 0x80, 0x08, 0xca, 0x64, 0x21, 0x3a, 0xce, 0x21,
+0x4c, 0x41, 0xb9, 0x13, 0x2d, 0xf7, 0x1b, 0xdf, 0x2b, 0x33, 0x69, 0xe7, 0x5c, 0x8c, 0x7b, 0xfb,
+0xe3, 0x41, 0xe9, 0xce, 0xd7, 0xff, 0x0e, 0x54, 0xfe, 0xb0, 0x71, 0x78, 0xdc, 0xde, 0x7e, 0xdd,
+0x1f, 0x1c, 0x4a, 0x8f, 0x3e, 0x16, 0xfd, 0x91, 0x82, 0x94, 0xd4, 0xc2, 0xf7, 0xb2, 0x77, 0x89,
+0x16, 0x2c, 0xba, 0xb6, 0xbd, 0xed, 0x95, 0x43, 0x05, 0x9b, 0xf2, 0xc4, 0xbe, 0x46, 0x43, 0x90,
+0x1d, 0xd8, 0x24, 0x02, 0xd2, 0xea, 0xf4, 0x08, 0xd9, 0xf7, 0x84, 0x0e, 0xc6, 0xe7, 0x44, 0xdb,
+0xb8, 0xac, 0x0a, 0x53, 0x39, 0x61, 0x43, 0xdc, 0x22, 0x28, 0x8f, 0x22, 0x2f, 0x73, 0xbf, 0x59,
+0x2d, 0x3c, 0x8c, 0x0b, 0xcc, 0x2a, 0x67, 0xe0, 0x5b, 0x5c, 0x65, 0x5e, 0x6d, 0x98, 0x99, 0xaa,
+0x3b, 0x89, 0x12, 0xe2, 0x99, 0xf6, 0x15, 0xa7, 0xd2, 0x6a, 0x79, 0xb4, 0xf6, 0x0b, 0xf5, 0x0d,
+0x2d, 0x4c, 0xcb, 0x1b, 0x35, 0x93, 0x61, 0x32, 0xa1, 0x8a, 0xa8, 0x27, 0xe8, 0x95, 0x5a, 0x56,
+0x59, 0x04, 0xfe, 0xce, 0xc2, 0xd8, 0x92, 0x97, 0xb2, 0x54, 0x63, 0xd0, 0x3b, 0xde, 0x10, 0x34,
+0x32, 0x16, 0x05, 0x51, 0x1d, 0xfc, 0x96, 0x8e, 0xf1, 0xf6, 0x4b, 0xd7, 0x48, 0x22, 0xce, 0xca,
+0x1c, 0x6b, 0xab, 0x1f, 0x59, 0xa2, 0x74, 0xd6, 0xcd, 0x15, 0x07, 0xab, 0xa2, 0xd5, 0x22, 0x81,
+0xec, 0x20, 0x14, 0x36, 0xac, 0xe4, 0x25, 0x7d, 0xe6, 0x09, 0x00, 0x2c, 0x92, 0x4d, 0x4e, 0xbf,
+0xbf, 0xa1, 0xd4, 0xbe, 0x6b, 0xd4, 0x1f, 0x95, 0x9b, 0xf3, 0xda, 0x99, 0xad, 0xa4, 0x6c, 0x73,
+0x55, 0xd1, 0x9d, 0x4b, 0x16, 0xd4, 0x06, 0xec, 0x46, 0x3d, 0xb7, 0xe7, 0xce, 0xd0, 0x1d, 0x94,
+0x65, 0xde, 0x61, 0xb3, 0xc1, 0x10, 0x65, 0xe5, 0x68, 0x9b, 0xb0, 0xb4, 0x43, 0x0b, 0x92, 0xaf,
+0xb7, 0x40, 0xa2, 0xe5, 0x06, 0x3d, 0x72, 0x00, 0xc5, 0x39, 0xab, 0x35, 0x29, 0x22, 0x4c, 0xa5,
+0xa5, 0x3f, 0x22, 0x90, 0x53, 0xd2, 0x36, 0x63, 0x1e, 0xd3, 0x33, 0xa5, 0xbb, 0x3d, 0xa3, 0x0c,
+0x14, 0x9c, 0x2e, 0x6d, 0x9a, 0x7a, 0xf7, 0xf1, 0x56, 0x66, 0xe5, 0x8d, 0x53, 0x83, 0x34, 0x3f,
+0xa9, 0x83, 0x84, 0x68, 0x90, 0xc9, 0x51, 0xc2, 0xd4, 0x8e, 0x6c, 0xc7, 0x6d, 0xa7, 0x19, 0x61,
+0xa7, 0x2e, 0x36, 0xbc, 0xd2, 0x0f, 0x17, 0x49, 0xd4, 0x6b, 0x36, 0x63, 0xfb, 0x1d, 0xf4, 0xb0,
+0x6b, 0xcf, 0x34, 0x5f, 0xd2, 0x77, 0xae, 0x12, 0xaf, 0xb3, 0xdf, 0x52, 0xf7, 0xc2, 0xc8, 0xf2,
+0x63, 0x61, 0xb6, 0x3e, 0x39, 0xf2, 0xa7, 0x1a, 0x89, 0x9d, 0x0e, 0x8f, 0xaf, 0xe1, 0x01, 0x24,
+0xa6, 0x3a, 0xd5, 0x9a, 0x62, 0x67, 0xa3, 0x66, 0xee, 0xbc, 0xc5, 0x94, 0x4b, 0xc3, 0x15, 0xa1,
+0x7e, 0x07, 0x07, 0x2b, 0xb7, 0x43, 0x2a, 0xb4, 0xb8, 0x25, 0x88, 0x86, 0x23, 0xab, 0xdf, 0x05,
+0xbe, 0x46, 0x56, 0xd7, 0xda, 0xd6, 0x75, 0x53, 0xd9, 0xc8, 0x26, 0x8f, 0x39, 0x67, 0xed, 0x21,
+0x53, 0x1c, 0x9c, 0x89, 0x46, 0xd3, 0xfe, 0x54, 0xe6, 0x1d, 0x02, 0xb9, 0x25, 0x82, 0x66, 0xe6,
+0xf9, 0x45, 0xd9, 0x3f, 0xa5, 0x71, 0xc1, 0x46, 0x66, 0x7a, 0x27, 0x8a, 0x82, 0xc9, 0x21, 0xe9,
+0x17, 0xab, 0x6c, 0xef, 0x45, 0xe5, 0x88, 0x93, 0x87, 0x80, 0xb3, 0x85, 0x25, 0x96, 0x19, 0x41,
+0xab, 0xd6, 0xba, 0x92, 0x76, 0x21, 0x8a, 0x58, 0xbd, 0xe2, 0x4b, 0xec, 0x45, 0x59, 0x2c, 0x13,
+0x1a, 0xb5, 0x13, 0x25, 0x44, 0xe7, 0x71, 0x26, 0x0a, 0x34, 0x33, 0xb9, 0x57, 0x15, 0xa4, 0x90,
+0x60, 0x11, 0x05, 0x8e, 0xc8, 0x8e, 0x74, 0x52, 0x4b, 0x31, 0x71, 0xeb, 0x66, 0x7e, 0xee, 0xb1,
+0x0a, 0x21, 0x52, 0xc0, 0x1a, 0xe9, 0xa1, 0x5a, 0xe3, 0x3a, 0x24, 0xfb, 0xf3, 0x1e, 0xd6, 0x83,
+0x1d, 0xfb, 0x81, 0xa8, 0x91, 0x60, 0x9e, 0xbc, 0x59, 0x20, 0xc9, 0x9e, 0x71, 0x19, 0x83, 0x2b,
+0x6a, 0x48, 0x4e, 0x6b, 0x46, 0x82, 0x89, 0xda, 0x60, 0xff, 0x1a, 0x46, 0x94, 0x55, 0xda, 0xe5,
+0x99, 0xfa, 0x84, 0xd7, 0x3b, 0xb9, 0xa5, 0x34, 0x87, 0x86, 0x5e, 0x6d, 0x75, 0x9a, 0xe7, 0x09,
+0xb8, 0xe6, 0x71, 0x15, 0x10, 0x56, 0xd7, 0xc1, 0xc8, 0xb2, 0x62, 0xbc, 0xec, 0xe0, 0x94, 0xa0,
+0xcd, 0xb4, 0x04, 0xa9, 0xc3, 0x51, 0xee, 0xf8, 0x2e, 0x42, 0x9a, 0xaa, 0x34, 0xd3, 0xb9, 0xb0,
+0x36, 0xf9, 0x47, 0xc1, 0x07, 0x49, 0xde, 0xb8, 0x32, 0x8a, 0x87, 0x68, 0x56, 0x9a, 0x35, 0x79,
+0xd1, 0xac, 0x49, 0x38, 0xc6, 0xfe, 0xfd, 0xdf, 0x6f, 0x3c, 0xda, 0x48, 0xbd, 0x23, 0xfd, 0x85,
+0xf0, 0x96, 0xee, 0x1c, 0x27, 0x18, 0x86, 0xa6, 0xf0, 0x7b, 0xd8, 0x3c, 0xc7, 0x22, 0x3e, 0x2f,
+0xac, 0xb1, 0x37, 0xbd, 0x84, 0x4b, 0xe3, 0x92, 0x82, 0xd0, 0x25, 0x14, 0x22, 0x65, 0xed, 0xeb,
+0xef, 0xb9, 0xb6, 0xe4, 0x95, 0x18, 0x0d, 0x2b, 0x8d, 0x4f, 0xaf, 0xc0, 0xa0, 0x05, 0x8b, 0x35,
+0x5b, 0x94, 0xb2, 0x68, 0x26, 0x4f, 0x4a, 0x9e, 0x85, 0x0e, 0x46, 0xe0, 0x4f, 0x60, 0x66, 0x01,
+0xa4, 0x39, 0xe8, 0x8b, 0x2a, 0x50, 0xf5, 0x18, 0x70, 0xe2, 0xfc, 0xd6, 0xbe, 0xd3, 0x46, 0x4b
+
+ciphertext =
+0x77, 0xF9, 0xF7, 0x7A, 0xA3, 0xCB, 0x68, 0x1A, 0x11, 0x70, 0xD8, 0x7A, 0xB6, 0xE2, 0x37, 0x7E,
+0xD1, 0x57, 0x1C, 0x8E, 0x85, 0xD8, 0x08, 0xBF, 0x57, 0x1F, 0x21, 0x6C, 0xAD, 0xAD, 0x47, 0x1E,
+0x0D, 0x6B, 0x79, 0x39, 0x15, 0x4E, 0x5B, 0x59, 0x2D, 0x76, 0x87, 0xA6, 0xD6, 0x47, 0x8F, 0x82,
+0xB8, 0x51, 0x91, 0x32, 0x60, 0xCB, 0x97, 0xDE, 0xBE, 0xF0, 0xAD, 0xFC, 0x23, 0x2E, 0x22, 0x02,
+0x46, 0x17, 0x3F, 0x8F, 0x24, 0x0E, 0x31, 0x80, 0xEA, 0xD6, 0x85, 0x50, 0xA5, 0xEE, 0xB7, 0x15,
+0xD0, 0x2F, 0xA6, 0x92, 0xEF, 0xCD, 0x8B, 0x91, 0x4A, 0xEA, 0x03, 0x92, 0xB4, 0x65, 0x19, 0x66,
+0x9E, 0x73, 0x79, 0xCE, 0xA7, 0x4D, 0x8B, 0x77, 0x74, 0x44, 0x1C, 0x9F, 0xEE, 0x15, 0x91, 0xF2,
+0xF9, 0x50, 0x7D, 0x2A, 0xC2, 0x6B, 0x58, 0x36, 0xF7, 0x62, 0x25, 0x9C, 0x71, 0x34, 0x43, 0x14,
+0x9E, 0x17, 0xF7, 0xB7, 0x56, 0x1D, 0x91, 0x4C, 0xF6, 0x6C, 0xF2, 0x19, 0x39, 0xA2, 0x29, 0xA3,
+0x22, 0x4F, 0x14, 0x18, 0x76, 0x8A, 0x59, 0xAD, 0x3E, 0x5F, 0xDC, 0xC9, 0x80, 0x07, 0x51, 0xB2,
+0x90, 0x6A, 0xB9, 0x0C, 0xA4, 0x3F, 0x42, 0xBD, 0x40, 0xB7, 0xA7, 0xF5, 0x85, 0xBF, 0xEA, 0xD8,
+0x89, 0xA9, 0xE9, 0xC7, 0x25, 0xEC, 0xFF, 0x80, 0xE8, 0x94, 0x3B, 0xE7, 0xD1, 0x68, 0xDA, 0x1C,
+0xFA, 0x5D, 0xCD, 0x68, 0x09, 0x72, 0x63, 0xBA, 0x34, 0x56, 0xD4, 0x5F, 0xB0, 0xA7, 0xAE, 0xCF,
+0xFB, 0xA8, 0xBD, 0x52, 0x79, 0x98, 0xF6, 0x39, 0x52, 0xD3, 0xA7, 0xE1, 0xFB, 0x75, 0x76, 0x87,
+0xBC, 0x11, 0x18, 0x17, 0x47, 0x65, 0xDA, 0xE3, 0x25, 0x3E, 0x17, 0x43, 0x7B, 0x0D, 0x8B, 0x7F,
+0x20, 0xFF, 0x03, 0xFA, 0x28, 0xC7, 0xD3, 0xF8, 0xC2, 0xA8, 0xC1, 0xE5, 0xDA, 0x77, 0x41, 0x28,
+0x06, 0xC4, 0x20, 0xFC, 0x1B, 0xAA, 0x99, 0x78, 0x5C, 0x28, 0xDA, 0x9A, 0x2B, 0x6C, 0x56, 0x7E,
+0x63, 0x34, 0xCF, 0xCD, 0x5D, 0xB6, 0x13, 0xF5, 0x98, 0x08, 0x2E, 0x02, 0x2C, 0x63, 0xEC, 0xE3,
+0x43, 0xE8, 0x3B, 0xE6, 0x59, 0x8C, 0x61, 0x60, 0xDD, 0x33, 0x3F, 0x29, 0xA4, 0xA5, 0xD5, 0x33,
+0xEF, 0xAA, 0x7E, 0x8C, 0xAE, 0x9C, 0x1B, 0x0D, 0x74, 0xF6, 0x01, 0x8C, 0xF1, 0x04, 0xEB, 0x62,
+0x75, 0xC0, 0x98, 0x24, 0xB2, 0xDF, 0xB1, 0xBA, 0x50, 0xC3, 0x01, 0x5B, 0x13, 0x3A, 0xF9, 0x7A,
+0xF6, 0xF4, 0x75, 0xAF, 0x55, 0x54, 0x10, 0xBE, 0x11, 0x91, 0x7D, 0xF6, 0x66, 0x79, 0xE6, 0x4D,
+0x0E, 0x0B, 0x70, 0x3C, 0x00, 0x68, 0x2E, 0xA3, 0x84, 0xCE, 0xE1, 0x0A, 0xDC, 0xFE, 0xF9, 0xD2,
+0x59, 0x23, 0x05, 0xCA, 0x79, 0xF0, 0x89, 0xB9, 0x76, 0xD9, 0xAA, 0x04, 0x43, 0x30, 0x97, 0x15,
+0x59, 0x0B, 0x7C, 0x22, 0x0E, 0x72, 0xC6, 0x61, 0x19, 0x35, 0xC3, 0x6A, 0xF2, 0x6B, 0x39, 0xB6,
+0x1B, 0xD3, 0xE3, 0xF7, 0xCB, 0x46, 0x26, 0x97, 0x39, 0xBA, 0x41, 0xD8, 0xA4, 0x48, 0x96, 0xBC,
+0x22, 0x38, 0xCF, 0xE2, 0xCF, 0xD6, 0x36, 0x30, 0xD9, 0x96, 0x73, 0xAF, 0xA4, 0x0F, 0x52, 0x9D,
+0x64, 0x28, 0xAB, 0x3D, 0xF7, 0x1B, 0xA6, 0xDB, 0x47, 0x09, 0x45, 0x48, 0x30, 0x27, 0x4B, 0x37,
+0x38, 0x5B, 0xC5, 0x90, 0x8C, 0xCC, 0x82, 0x48, 0x7A, 0x98, 0x1C, 0x46, 0x24, 0xB1, 0xDA, 0xB9,
+0x6C, 0x30, 0x48, 0xF3, 0x6C, 0x84, 0xBD, 0x3F, 0x95, 0x3E, 0xC1, 0x27, 0x8B, 0x3C, 0x2F, 0xDA,
+0xD9, 0xF6, 0x54, 0x73, 0x04, 0x38, 0xD6, 0x45, 0xC5, 0x5C, 0x92, 0xDE, 0xB2, 0xE3, 0x62, 0x31,
+0xCE, 0x70, 0xD7, 0x11, 0x5E, 0x7A, 0x63, 0x0F, 0xA1, 0xD4, 0x8A, 0x2B, 0xDE, 0x38, 0xAA, 0x9F,
+0x33, 0x71, 0x67, 0x05, 0xDB, 0x48, 0xE4, 0x09, 0x73, 0x3A, 0x35, 0x1F, 0xC2, 0x0F, 0x44, 0x99,
+0x35, 0xBD, 0xBD, 0x7E, 0x85, 0x77, 0x46, 0x3A, 0x41, 0x79, 0xAB, 0x67, 0xA5, 0x87, 0xBD, 0x96,
+0xAE, 0xC2, 0x99, 0x35, 0xC3, 0xCA, 0x90, 0x36, 0xB1, 0x15, 0x9C, 0x37, 0x62, 0x54, 0xCA, 0x72,
+0x10, 0x07, 0x07, 0x6E, 0x1D, 0xD0, 0xFE, 0x4C, 0xE8, 0x48, 0x92, 0x7A, 0xA1, 0x7B, 0xA5, 0xAC,
+0xF7, 0xE1, 0x99, 0xC0, 0x99, 0x20, 0xD5, 0x07, 0x77, 0x1D, 0xE5, 0x14, 0x36, 0xA6, 0xF3, 0x77,
+0x9B, 0x61, 0x87, 0x98, 0xD6, 0xD6, 0xF8, 0xE6, 0x34, 0x37, 0x6F, 0x58, 0x29, 0x97, 0x2D, 0xE6,
+0xD1, 0x56, 0xB1, 0xBB, 0x35, 0xBD, 0x2B, 0x44, 0xAD, 0x30, 0x0F, 0x1D, 0x48, 0x5F, 0xDD, 0x58,
+0x7C, 0xB8, 0x2C, 0x2E, 0x26, 0x9B, 0xDA, 0x55, 0x01, 0x06, 0x66, 0xB0, 0x3C, 0xAB, 0xA0, 0x60,
+0x98, 0xF4, 0x72, 0xAF, 0xBC, 0x00, 0xAA, 0x57, 0x6A, 0xD8, 0x47, 0xC7, 0xC1, 0xCE, 0xB1, 0x05,
+0x45, 0x84, 0x63, 0x1E, 0x9C, 0x47, 0x11, 0xB4, 0xE6, 0x80, 0x8D, 0x3E, 0xFF, 0xE9, 0xD9, 0x3A,
+0x56, 0x3D, 0x41, 0x68, 0x2C, 0x6C, 0xA2, 0x23, 0x4C, 0xD6, 0x08, 0x91, 0x93, 0xCD, 0xAA, 0xF7,
+0xAA, 0x2B, 0x55, 0xEC, 0x53, 0xE8, 0xD9, 0x2E, 0xCB, 0xE0, 0x67, 0x1D, 0x9F, 0xFF, 0x94, 0xB8,
+0xBA, 0x82, 0xA7, 0x6A, 0x8C, 0x61, 0x7C, 0x58, 0x90, 0xA5, 0x11, 0x57, 0x21, 0xCF, 0x30, 0xB0,
+0x97, 0x44, 0x7D, 0x1D, 0xD3, 0x91, 0x3F, 0xC2, 0x4F, 0x0E, 0x3B, 0x57, 0x3A, 0x1F, 0x85, 0x82,
+0x79, 0x91, 0x03, 0xB4, 0x9B, 0x70, 0x2A, 0x5F, 0x8B, 0x20, 0x66, 0x6F, 0xF4, 0x10, 0x96, 0x52,
+0x4C, 0x77, 0xA2, 0x45, 0x28, 0xF8, 0xAD, 0xA3, 0x8C, 0x99, 0x3F, 0xD2, 0x39, 0x4A, 0x1A, 0x3A,
+0x72, 0x7E, 0x47, 0x49, 0x25, 0x63, 0x87, 0xCB, 0xEA, 0x89, 0x1D, 0x7F, 0x0C, 0x86, 0x9A, 0x8E,
+0xB1, 0x0C, 0xFF, 0xC6, 0xF2, 0xB1, 0x01, 0x99, 0xEA, 0xF1, 0x4A, 0xF1, 0xF3, 0x71, 0x4B, 0x92,
+0xC6, 0xD6, 0xD8, 0x26, 0xE8, 0x28, 0xF2, 0xF5, 0x5B, 0xE8, 0xF1, 0xE4, 0x4B, 0x36, 0x46, 0xD3,
+0x12, 0x2F, 0x98, 0x61, 0x12, 0xD9, 0x26, 0x58, 0x5C, 0x80, 0x7C, 0x71, 0x4E, 0x57, 0x9A, 0xAC,
+0x59, 0xE0, 0xC3, 0x70, 0x55, 0x57, 0xAE, 0x55, 0xF6, 0xCF, 0x6A, 0xF0, 0x10, 0xDC, 0xF4, 0xED,
+0xCC, 0x32, 0x4B, 0xAC, 0xC1, 0x4B, 0x2F, 0x62, 0x69, 0xD2, 0x15, 0x63, 0x39, 0xD5, 0x29, 0x09,
+0xA2, 0xB5, 0xC7, 0xBC, 0xFA, 0xC7, 0xC7, 0x8C, 0x64, 0xCF, 0x43, 0x9B, 0x4C, 0x60, 0x97, 0x33,
+0xA2, 0xB9, 0x0F, 0x70, 0x05, 0x89, 0x56, 0x62, 0xB1, 0x48, 0x08, 0xB5, 0x77, 0x4C, 0x60, 0x24,
+0x1D, 0x35, 0xEF, 0xD6, 0x53, 0xB0, 0x2E, 0x7F, 0xA6, 0x4B, 0x94, 0xE7, 0xCD, 0xC4, 0xFE, 0xC4,
+0x12, 0x7A, 0xAB, 0xD4, 0x05, 0xA5, 0x32, 0xD4, 0xA1, 0x8D, 0x9C, 0x22, 0x10, 0xDD, 0x39, 0x66,
+0x96, 0x79, 0x49, 0x19, 0x80, 0x1C, 0xE1, 0x1F, 0x01, 0x69, 0x37, 0x03, 0xB5, 0x22, 0x8F, 0x95,
+0xF7, 0xBD, 0x36, 0x89, 0x38, 0x37, 0x29, 0x6C, 0x0E, 0x89, 0x55, 0x4D, 0xC9, 0x64, 0xD3, 0xD5,
+0x9B, 0xB0, 0x51, 0x43, 0xBB, 0xA6, 0x6B, 0xFF, 0x13, 0xB6, 0x1A, 0x06, 0xF3, 0x86, 0x51, 0xFD,
+0xB9, 0xC8, 0x26, 0xA9, 0x8A, 0x4A, 0xC1, 0xE0, 0xD9, 0x3D, 0x31, 0x48, 0x39, 0xC8, 0x48, 0xC7,
+0xDE, 0xB1, 0x58, 0x0F, 0x4D, 0xEC, 0x5B, 0x32, 0x9C, 0x8B, 0xF4, 0x3A, 0x02, 0xE2, 0x92, 0x4A,
+0x7D, 0xCD, 0x38, 0x07, 0x4F, 0xBA, 0xD1, 0xD4, 0xE4, 0x3C, 0xB0, 0x4D, 0xB7, 0xEF, 0xFB, 0x06,
+0xA9, 0x83, 0x20, 0x0D, 0x7A, 0x1F, 0x15, 0x02, 0x70, 0x08, 0x8B, 0x91, 0xE6, 0xFD, 0x8C, 0x0B,
+0x3C, 0xEA, 0x1F, 0x94, 0xB6, 0x17, 0xC6, 0xB2, 0x07, 0x2C, 0x73, 0x7A, 0x4A, 0x76, 0x5F, 0x30,
+0x38, 0xE5, 0x22, 0xC6, 0xA3, 0xA7, 0x4D, 0x6A, 0x3A, 0xA7, 0x82, 0x90, 0xBE, 0xD1, 0xE9, 0x89,
+0x2F, 0xF0, 0xC9, 0x0A, 0xB6, 0xDA, 0x0D, 0x3E, 0x25, 0x8E, 0x99, 0xB2, 0x06, 0xE3, 0x65, 0x53,
+0x3F, 0x1A, 0xD9, 0x45, 0xCE, 0x10, 0xBE, 0x2E, 0xF4, 0x4F, 0x60, 0x25, 0xA7, 0x0A, 0xAE, 0x82,
+0x92, 0xAE, 0xC0, 0xFF, 0xAB, 0x49, 0x97, 0x5C, 0x53, 0x73, 0x4E, 0x78, 0x1A, 0x65, 0x42, 0xD5,
+0x6F, 0x1E, 0xE2, 0x25, 0x76, 0x3B, 0x6D, 0xF8, 0xBC, 0xBD, 0x3A, 0xDE, 0xB5, 0xFB, 0xBD, 0x90,
+0xDC, 0xC2, 0xB8, 0x90, 0xD4, 0x03, 0xD2, 0xDD, 0x35, 0x86, 0x48, 0x58, 0xB4, 0xCB, 0x10, 0xB2,
+0x31, 0xBD, 0x6C, 0x16, 0x92, 0x7A, 0x3D, 0x67, 0x45, 0x6B, 0x57, 0x26, 0xD2, 0xC2, 0xAF, 0xB1,
+0xAB, 0x82, 0x4B, 0x95, 0x08, 0x7D, 0x48, 0x1D, 0x17, 0x9D, 0x8B, 0x16, 0xCF, 0xE0, 0x16, 0x94,
+0xE1, 0xA6, 0xFC, 0x6C, 0xE1, 0x71, 0x3C, 0x57, 0x7F, 0x17, 0xC8, 0x4E, 0xFF, 0x16, 0x46, 0x1E,
+0x21, 0x27, 0x05, 0x41, 0xD3, 0x19, 0x28, 0x58, 0x86, 0xFB, 0x5A, 0xEF, 0xC3, 0x00, 0xE7, 0xA3,
+0x25, 0x1A, 0x94, 0x41, 0xE3, 0x50, 0x98, 0x94, 0x29, 0x42, 0x1F, 0x1C, 0x69, 0x46, 0xF4, 0x89,
+0x30, 0x4E, 0x5C, 0xCE, 0x2F, 0x65, 0xC5, 0x34, 0x71, 0xB7, 0xD9, 0x54, 0xB2, 0xC1, 0xCC, 0xED,
+0x14, 0x3E, 0xF1, 0x7B, 0x5F, 0xAE, 0xD3, 0x8F, 0xA2, 0x18, 0x12, 0x15, 0x23, 0x92, 0x75, 0x61,
+0xFF, 0xFA, 0x8F, 0xD1, 0x77, 0xC8, 0xC7, 0xA3, 0x44, 0x9F, 0x06, 0x2B, 0x1E, 0xA4, 0x4D, 0x4F,
+0x8E, 0x9A, 0x02, 0xA8, 0x4A, 0x67, 0x5D, 0x2D, 0x59, 0xFD, 0x1A, 0x8F, 0xE6, 0x52, 0x0C, 0xC7,
+0x4A, 0x95, 0xAF, 0xDD, 0x04, 0x76, 0x26, 0xCE, 0x4C, 0x97, 0x4E, 0x55, 0x9C, 0x28, 0xA4, 0x1D,
+0x92, 0xD6, 0x84, 0x87, 0x29, 0x28, 0x16, 0x1B, 0x34, 0xE3, 0xBD, 0x2F, 0x9B, 0xF8, 0x6F, 0xDC,
+0x9B, 0x6C, 0xF5, 0xEB, 0x26, 0x51, 0x47, 0x78, 0xA2, 0xB5, 0x4C, 0x24, 0x1E, 0x3D, 0xE5, 0x33,
+0xA3, 0xD9, 0x04, 0x20, 0x8E, 0xA7, 0x32, 0x88, 0xC6, 0x52, 0x0B, 0x71, 0x0D, 0x26, 0xC3, 0x3F,
+0xC4, 0xC8, 0x7F, 0x6F, 0x3A, 0xAD, 0xC7, 0x27, 0x3D, 0xB3, 0xE6, 0x6B, 0x68, 0x66, 0xB3, 0xEE,
+0x6D, 0xC7, 0xAB, 0xD4, 0xA2, 0x88, 0xAF, 0xEB, 0x1A, 0x51, 0x76, 0x19, 0xFC, 0xF7, 0x29, 0xF0,
+0x4D, 0xC5, 0xAB, 0x42, 0x81, 0x9F, 0x10, 0xD9, 0xB0, 0x5C, 0x9D, 0x1A, 0x5A, 0xFE, 0xB3, 0x71,
+0xBC, 0x13, 0x69, 0xDA, 0xCE, 0x15, 0x7C, 0x18, 0x2C, 0x81, 0xFC, 0xA9, 0x1E, 0x0B, 0x33, 0xBF,
+0x82, 0x0D, 0xD5, 0x58, 0xD0, 0xB6, 0x17, 0x34, 0xFE, 0x53, 0x45, 0xE7, 0x57, 0x9B, 0xFA, 0x3C,
+0x04, 0xCF, 0x89, 0x38, 0x73, 0xE9, 0x60, 0xEA, 0xF4, 0x0F, 0xB2, 0x2E, 0x90, 0x60, 0xAE, 0xFB,
+0x57, 0xCB, 0xA5, 0x9D, 0x60, 0x44, 0x46, 0x13, 0x3C, 0xB3, 0xB6, 0x0A, 0x09, 0x12, 0x2B, 0x27,
+0x95, 0x45, 0x29, 0x92, 0x86, 0x00, 0x2A, 0x93, 0x77, 0x8D, 0xAA, 0xC3, 0xF8, 0x46, 0xBE, 0x3A,
+0x6A, 0x0E, 0x51, 0x9D, 0x94, 0x60, 0x9A, 0x76, 0x93, 0xF4, 0x01, 0x19, 0xC3, 0xB1, 0x86, 0xA9,
+0x7E, 0xD1, 0xF6, 0xF1, 0x88, 0x59, 0x4E, 0x9F, 0xCC, 0xF2, 0xF7, 0xDD, 0x1B, 0x91, 0x98, 0xAC,
+0xCC, 0xC6, 0x81, 0x57, 0x3F, 0x07, 0xF2, 0x52, 0x5B, 0x79, 0x5D, 0xFB, 0x07, 0xF7, 0x6A, 0x62,
+0x30, 0xE5, 0x77, 0x81, 0x00, 0x6C, 0xB1, 0x11, 0x8A, 0x1D, 0x0C, 0x9C, 0x94, 0x1A, 0xAD, 0xB6,
+0x85, 0x29, 0x70, 0x19, 0xFB, 0xE1, 0xF5, 0x89, 0x6D, 0xB3, 0x84, 0xC5, 0x56, 0x14, 0x1E, 0x67,
+0x46, 0x57, 0xFE, 0x30, 0xD0, 0x81, 0x2B, 0x27, 0xD6, 0x4B, 0x41, 0x74, 0xF3, 0x51, 0xD0, 0x78,
+0xCE, 0x3A, 0x5C, 0x46, 0xCC, 0xCE, 0x19, 0xC9, 0xC3, 0x1A, 0x81, 0xF4, 0x62, 0x9A, 0x8B, 0xAD,
+0x71, 0x9C, 0x3E, 0x5B, 0x23, 0xA7, 0x9F, 0x7E, 0x26, 0xDD, 0x21, 0xCC, 0x36, 0x75, 0x90, 0x09,
+0x61, 0x0B, 0x85, 0xC1, 0x0A, 0xF4, 0x9D, 0x93, 0x9F, 0x5F, 0x73, 0x71, 0xAB, 0x2B, 0xFA, 0x5E,
+0xD9, 0xA1, 0xF8, 0x7F, 0x0F, 0xD5, 0x07, 0x59, 0xB2, 0x4F, 0xF9, 0x71, 0xD4, 0x35, 0x3E, 0x5D,
+0x85, 0x6A, 0x32, 0x76, 0xDB, 0xBE, 0xC5, 0xD4, 0x2B, 0xC5, 0x70, 0x95, 0x7C, 0x64, 0x04, 0x0E,
+0xC0, 0x4E, 0x59, 0x76, 0x10, 0xBF, 0x93, 0xBE, 0xEC, 0x40, 0x2C, 0xDE, 0x2D, 0xE6, 0xD1, 0x77,
+0xC7, 0x84, 0x4B, 0xD6, 0x1C, 0x9A, 0xA1, 0x93, 0xE4, 0x50, 0xA8, 0x1B, 0x73, 0x29, 0x92, 0xB0,
+0x37, 0x83, 0x15, 0xE3, 0xB5, 0xCD, 0xD1, 0x47, 0x38, 0xD1, 0xB6, 0xB6, 0x04, 0x3D, 0x58, 0x28,
+0xB1, 0xB5, 0x9E, 0xF3, 0x95, 0x12, 0x1A, 0xC2, 0xA1, 0x71, 0x72, 0x45, 0x35, 0x0F, 0xB8, 0xC4,
+0xEF, 0xF7, 0xAD, 0xD6, 0x82, 0x6A, 0x6A, 0x9E, 0x0E, 0xEF, 0xAB, 0xAD, 0x9D, 0x8D, 0xE4, 0x77,
+0xA1, 0x93, 0xAE, 0xE1, 0xBA, 0x0E, 0xAF, 0x83, 0xC4, 0x84, 0x19, 0x6E, 0x5B, 0x15, 0xD7, 0xAE,
+0x33, 0xA4, 0x37, 0xE2, 0xA1, 0x18, 0x2A, 0x4A, 0x9C, 0x5E, 0x7C, 0x61, 0x70, 0x76, 0xE9, 0xE6,
+0x0E, 0x11, 0xEE, 0x71, 0x45, 0xE0, 0x5E, 0x72, 0x3C, 0x88, 0x0C, 0x34, 0x34, 0x78, 0x39, 0xD7,
+0xFB, 0x26, 0x14, 0x1B, 0xCE, 0xEE, 0x15, 0x3C, 0xA4, 0x3F, 0xD3, 0x2A, 0x7C, 0x66, 0x58, 0xDD,
+0x56, 0x46, 0xAF, 0x14, 0x04, 0x35, 0x33, 0xD5, 0x83, 0xA0, 0x07, 0xE0, 0xC0, 0x4B, 0x9D, 0x36,
+0xF0, 0x72, 0x90, 0x7D, 0xFC, 0x4B, 0x3B, 0xDD, 0x07, 0x5E, 0xCD, 0xBE, 0x0B, 0x30, 0x78, 0x8C,
+0x9B, 0x4D, 0xFB, 0xB4, 0x95, 0xC4, 0xDE, 0x57, 0xB3, 0x07, 0xE6, 0x8F, 0x20, 0xE7, 0x54, 0x84,
+0xC8, 0x35, 0x3B, 0x68, 0x15, 0x74, 0x0F, 0x6A, 0xAB, 0xCC, 0x3E, 0x90, 0x6B, 0x38, 0x0A, 0xA8,
+0x5A, 0x3F, 0xF3, 0xAC, 0x27, 0x12, 0xFC, 0x04, 0xF6, 0x93, 0xB4, 0x84, 0xF2, 0x82, 0xED, 0xAE,
+0xF9, 0x64, 0x53, 0x1F, 0x9A, 0x2F, 0xAD, 0xB7, 0x2A, 0x17, 0x60, 0xFC, 0xDB, 0x07, 0xB1, 0x01,
+0xC9, 0xF8, 0x02, 0x5F, 0xF3, 0x5B, 0x5B, 0x90, 0xD4, 0x96, 0x92, 0x99, 0x36, 0x22, 0x53, 0xEA,
+0x62, 0xAE, 0xB0, 0x22, 0x6A, 0xAB, 0x24, 0xCD, 0x19, 0xBB, 0x86, 0x54, 0x17, 0x0F, 0x9D, 0x1A,
+0x4A, 0x3D, 0xE4, 0xF0, 0x0D, 0x03, 0xF2, 0x9A, 0x6D, 0x70, 0xEE, 0xA5, 0x51, 0x5F, 0xE8, 0x74,
+0xC1, 0xAC, 0x4B, 0xC6, 0x1C, 0x58, 0x26, 0x8F, 0xBF, 0xE1, 0x1D, 0xDB, 0x2D, 0xCA, 0x7E, 0x56,
+0xB9, 0x5E, 0x28, 0x4D, 0x63, 0x21, 0xDA, 0x20, 0xC5, 0xBB, 0xE3, 0x23, 0x92, 0x90, 0xB3, 0x2D,
+0xCE, 0x5B, 0x97, 0xF1, 0x66, 0x4A, 0x1D, 0xD0, 0xA4, 0x9E, 0x72, 0xD5, 0x3C, 0xC8, 0x7C, 0xCF,
+0x78, 0x1F, 0x5B, 0x34, 0x9B, 0xFF, 0x92, 0x71, 0xF5, 0x02, 0x0E, 0x01, 0xAC, 0x6A, 0x1E, 0xE0,
+0x2D, 0x15, 0x05, 0x40, 0x37, 0xF1, 0x7B, 0x24, 0xD8, 0x92, 0x5B, 0xE9, 0xEB, 0xD1, 0x7F, 0xC1,
+0xCE, 0x9C, 0xAA, 0x6A, 0x48, 0x38, 0x3A, 0xF5, 0x5A, 0x3F, 0x17, 0xFF, 0x45, 0x09, 0x1B, 0x40
+
+cipher_key =
+0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2, 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A,
+0xd0, 0xe7, 0x4b, 0xfb, 0x5d, 0xe5, 0x0c, 0xe7, 0x6f, 0x21, 0xb5, 0x52, 0x2a, 0xbb, 0xc7, 0xf7
+
+auth_key =
+0xaf, 0x96, 0x42, 0xf1, 0x8c, 0x50, 0xdc, 0x67, 0x1a, 0x43, 0x47, 0x62, 0xc7, 0x04, 0xab, 0x05,
+0xf5, 0x0c, 0xe7, 0xa2, 0xa6, 0x23, 0xd5, 0x3d, 0x95, 0xd8, 0xcd, 0x86, 0x79, 0xf5, 0x01, 0x47,
+0x4f, 0xf9, 0x1d, 0x9d, 0x36, 0xf7, 0x68, 0x1a, 0x64, 0x44, 0x58, 0x5d, 0xe5, 0x81, 0x15, 0x2a,
+0x41, 0xe4, 0x0e, 0xaa, 0x1f, 0x04, 0x21, 0xff, 0x2c, 0xf3, 0x73, 0x2b, 0x48, 0x1e, 0xd2, 0xf7,
+0xf6, 0xd9, 0xaf, 0xbf, 0x08, 0x3b, 0xbb, 0x19, 0x5f, 0xf6, 0x7d, 0x25, 0x85, 0xdf, 0x6b, 0x54,
+0xd0, 0xe7, 0x4b, 0x9e, 0xc7, 0xef, 0xca, 0x48, 0x6f, 0x21, 0xd7, 0x51, 0xc8, 0x21, 0xc1, 0x15,
+0xe8, 0x38, 0x36, 0x58, 0x39, 0xd9, 0x9a, 0xc5, 0xe7, 0x3b, 0xc4, 0x47, 0xe2, 0xbd, 0x80, 0x73,
+0xf8, 0xd1, 0x9a, 0x5e, 0x4b, 0xfb, 0x52, 0x6b, 0x50, 0xaf, 0x8b, 0xb7, 0xb5, 0x2c, 0x52, 0x84
+
+iv =
+0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+
+####################
+# sha_hmac_buff_32 #
+####################
+[sha1_hmac_buff_32]
+digest =
+0x36, 0xCA, 0x49, 0x6A, 0xE3, 0x54, 0xD8, 0x4F, 0x0B, 0x76, 0xD8, 0xAA, 0x78, 0xEB, 0x9D, 0x65,
+0x2C, 0xCA, 0x1F, 0x97
+
+[sha224_hmac_buff_32]
+digest =
+0x48, 0xC1, 0x45, 0x25, 0x29, 0xA0, 0x8B, 0x88, 0x72, 0x7A, 0xBC, 0x00, 0x94, 0x37, 0xE1, 0x22,
+0xEB, 0xFA, 0x1B, 0x7D, 0x89, 0x81, 0x31, 0xC8, 0x64, 0x76, 0x55, 0xA4
+
+[sha256_hmac_buff_32]
+digest =
+0x1C, 0xB2, 0x3D, 0xD1, 0xF9, 0xC7, 0x6C, 0x49, 0x2E, 0xDA, 0x94, 0x8B, 0xF1, 0xCF, 0x96, 0x43,
+0x67, 0x50, 0x39, 0x76, 0xB5, 0xA1, 0xCE, 0xA1, 0xD7, 0x77, 0x10, 0x07, 0x43, 0x37, 0x05, 0xB4
+
+[sha384_hmac_buff_32]
+digest =
+0x6C, 0xBD, 0x1E, 0x2E, 0x75, 0xA7, 0x2C, 0x98, 0xC4, 0x1E, 0x03, 0x4E, 0x39, 0x4B, 0x27, 0x41,
+0xFB, 0xC6, 0x56, 0x87, 0x84, 0xEB, 0xFA, 0xB1, 0x20, 0x1F, 0x11, 0x81, 0x8D, 0xDC, 0xB6, 0xA7,
+0xAD, 0x1F, 0xAC, 0xA9, 0x43, 0x1D, 0x2B, 0xEB, 0x5F, 0x27, 0xC6, 0x0F, 0x9E, 0xFB, 0x1E, 0xB1
+
+[sha512_hmac_buff_32]
+digest =
+0xA4, 0x60, 0x7E, 0xBE, 0x5F, 0x47, 0x58, 0x3B, 0x41, 0x5F, 0x29, 0xDF, 0xE4, 0xD2, 0xFB, 0x30,
+0xF0, 0x2B, 0x09, 0x4E, 0x09, 0x50, 0xEC, 0x1C, 0x0E, 0x34, 0x79, 0xAE, 0xD8, 0x6D, 0xAC, 0xB6,
+0x9B, 0x7C, 0xB9, 0x06, 0xC2, 0x4A, 0x4E, 0x22, 0x14, 0x4D, 0x42, 0x46, 0x20, 0xE0, 0x6C, 0xEE,
+0x2F, 0xE1, 0x23, 0xA2, 0x7A, 0x2F, 0xDB, 0xAF, 0x78, 0x75, 0x56, 0xF7, 0x3A, 0x5E, 0x74, 0xEF
+
+####################
+# sha_hmac_buff_64 #
+####################
+[sha1_hmac_buff_64]
+digest =
+0xFC, 0x17, 0x7E, 0x0E, 0x52, 0x94, 0xE3, 0x27, 0xC0, 0x9B, 0x72, 0xAD, 0xC0, 0x5B, 0xCF, 0xFF,
+0x65, 0x88, 0x43, 0xE7
+
+[sha224_hmac_buff_64]
+digest =
+0xD7, 0x55, 0x25, 0xC0, 0x26, 0xDD, 0x8E, 0x14, 0x17, 0x8B, 0x89, 0x59, 0x8A, 0xBB, 0xEA, 0xD6,
+0x7D, 0x85, 0x00, 0x9F, 0xC2, 0x8A, 0xCB, 0x01, 0x7F, 0x8C, 0x6E, 0x24
+
+[sha256_hmac_buff_64]
+digest =
+0x8F, 0x4B, 0x3B, 0x4C, 0x58, 0x25, 0x3B, 0x07, 0xEB, 0xF8, 0x20, 0x81, 0xD9, 0xD9, 0x92, 0x8F,
+0xF4, 0x32, 0x7C, 0x2A, 0xD9, 0xEC, 0x92, 0x60, 0x8F, 0xE3, 0x90, 0x7F, 0xC5, 0x75, 0x05, 0xB6
+
+[sha384_hmac_buff_64]
+digest =
+0xD1, 0xC7, 0x64, 0x27, 0xF0, 0x30, 0x43, 0x8E, 0xD6, 0xA6, 0x78, 0xF7, 0xE9, 0xCC, 0x8E, 0x69,
+0x6D, 0xB8, 0x3E, 0xFA, 0xA0, 0x81, 0x9C, 0x61, 0x78, 0x72, 0xF0, 0x1C, 0x29, 0x35, 0x51, 0x3E,
+0x4A, 0x95, 0xDE, 0x2C, 0x6A, 0x3F, 0x56, 0xA8, 0x12, 0xBA, 0x44, 0x39, 0x1E, 0xDB, 0xF7, 0xF5
+
+[sha512_hmac_buff_64]
+digest =
+0xE6, 0xE9, 0xD8, 0x1D, 0x90, 0xAE, 0x32, 0x0E, 0xBA, 0x55, 0x58, 0xD5, 0x55, 0x97, 0x40, 0xB3,
+0xE9, 0x12, 0xD3, 0x08, 0xEF, 0x21, 0xED, 0xA5, 0x94, 0x8D, 0xF2, 0x4C, 0x52, 0x2C, 0x50, 0xB2,
+0xD2, 0xEC, 0xB7, 0xE1, 0x95, 0x2D, 0x68, 0xDB, 0xAD, 0xB5, 0x94, 0x50, 0x67, 0xF3, 0x0A, 0x83,
+0x54, 0x03, 0x33, 0x1C, 0xD5, 0x42, 0x7D, 0xB4, 0x3E, 0x69, 0x7C, 0x36, 0x7E, 0x96, 0x0D, 0x3E
+
+#####################
+# sha_hmac_buff_128 #
+#####################
+[sha1_hmac_buff_128]
+digest =
+0xAA, 0x90, 0x55, 0xA5, 0x71, 0xC4, 0x2B, 0xA3, 0x02, 0xAA, 0xB1, 0x1C, 0xB3, 0x88, 0x38, 0x6E,
+0xAD, 0x26, 0x98, 0xA7
+
+[sha224_hmac_buff_128]
+digest =
+0xBE, 0xCC, 0x83, 0x48, 0x4C, 0x58, 0xF9, 0x86, 0xFA, 0x93, 0x5F, 0xD1, 0x3C, 0x11, 0x8A, 0x37,
+0xA6, 0xEE, 0x52, 0x4D, 0xA3, 0x98, 0x3E, 0x35, 0xF1, 0x4F, 0xD9, 0xDB
+
+[sha256_hmac_buff_128]
+digest =
+0xE2, 0x9C, 0xE1, 0xDF, 0xCD, 0xAE, 0x50, 0x4B, 0x9A, 0xA6, 0x41, 0xAC, 0x0C, 0xF1, 0x66, 0xED,
+0xA1, 0x22, 0x05, 0x72, 0x49, 0x97, 0xA1, 0x30, 0xB8, 0xF9, 0xED, 0x36, 0x0A, 0x19, 0xE4, 0x2A
+
+[sha384_hmac_buff_128]
+digest =
+0xD9, 0x3C, 0xEB, 0xF4, 0x20, 0xC6, 0x4F, 0xC7, 0xBD, 0x34, 0xBA, 0xFD, 0x7C, 0xA9, 0xCE, 0xFF,
+0x26, 0x2E, 0xB4, 0x4A, 0xB7, 0x47, 0x71, 0x2C, 0x9E, 0xCF, 0x44, 0x0B, 0xD9, 0xAF, 0x8D, 0x17,
+0x0A, 0x3A, 0x02, 0xD0, 0xE9, 0xDF, 0xCF, 0x52, 0x5F, 0xDA, 0xA7, 0xB6, 0x51, 0x7C, 0x59, 0x09
+
+[sha512_hmac_buff_128]
+digest =
+0xAD, 0x7E, 0xB7, 0x33, 0xFB, 0x8A, 0x17, 0xD0, 0x3C, 0xB0, 0x80, 0x19, 0xF3, 0x9A, 0x6F, 0x90,
+0xDE, 0xF3, 0x53, 0xEA, 0x48, 0x75, 0x0A, 0x1E, 0x49, 0x02, 0xA0, 0x94, 0xC4, 0xE8, 0xFB, 0x87,
+0x83, 0x80, 0xD3, 0xFF, 0x6B, 0x79, 0x73, 0x54, 0xF9, 0x2F, 0x2D, 0x59, 0x69, 0x0E, 0x50, 0x29,
+0x2A, 0xDA, 0x59, 0x38, 0xDD, 0x62, 0xF9, 0x1A, 0x18, 0xA9, 0x51, 0x5A, 0xFE, 0x8E, 0xFD, 0xBF
+
+#####################
+# sha_hmac_buff_256 #
+#####################
+[sha1_hmac_buff_256]
+digest =
+0xB1, 0x18, 0x31, 0xBF, 0xEE, 0x81, 0x7E, 0xFC, 0x68, 0xDA, 0xB6, 0x8A, 0x5D, 0xDE, 0x39, 0x65,
+0xC8, 0xF8, 0xC3, 0xE5
+
+[sha224_hmac_buff_256]
+digest =
+0xCD, 0xF6, 0xC2, 0x6D, 0xFD, 0x33, 0x1A, 0xD8, 0x2F, 0x07, 0x4F, 0x1A, 0xE8, 0x18, 0xBD, 0x04,
+0xB1, 0xE5, 0x8D, 0xC1, 0x21, 0x95, 0x87, 0x75, 0xC2, 0x27, 0x4B, 0xF2
+
+[sha256_hmac_buff_256]
+digest =
+0xC0, 0xFA, 0x8F, 0x6F, 0x55, 0xFC, 0xF3, 0xDF, 0x8E, 0x5D, 0x93, 0x5E, 0x6B, 0x20, 0x0A, 0x9A,
+0x84, 0x3D, 0xCD, 0x4B, 0x57, 0x63, 0x2D, 0x93, 0x51, 0x45, 0xF2, 0x1E, 0xC7, 0xA4, 0xD4, 0x69
+
+[sha384_hmac_buff_256]
+digest =
+0x2B, 0x92, 0x9E, 0x85, 0x5A, 0x89, 0xB5, 0x12, 0x4A, 0x9B, 0x2D, 0xD2, 0xB2, 0x3E, 0xAB, 0xC1,
+0x1E, 0x7F, 0x53, 0xD9, 0x88, 0xEB, 0xEE, 0xA2, 0x49, 0x14, 0xDE, 0x1A, 0x9E, 0x20, 0xCE, 0xEC,
+0x7A, 0x5D, 0x25, 0xD8, 0x8F, 0xFE, 0x8B, 0xB1, 0xB1, 0x04, 0x5F, 0x46, 0x2D, 0x34, 0x2D, 0x72
+
+[sha512_hmac_buff_256]
+digest =
+0x4F, 0x96, 0x89, 0x9E, 0x9D, 0x53, 0xAC, 0x05, 0xC7, 0xA0, 0x0F, 0x4D, 0xB6, 0x3E, 0x06, 0x03,
+0x19, 0x68, 0x41, 0x4F, 0x11, 0x57, 0x77, 0x21, 0xBD, 0x60, 0x3E, 0xB4, 0xFE, 0x6A, 0x0D, 0xBF,
+0xE0, 0x4F, 0x32, 0x5B, 0xF9, 0xDF, 0x13, 0xBD, 0x02, 0x73, 0xD4, 0x0C, 0xE9, 0x9D, 0xB7, 0xD5,
+0x38, 0xA0, 0x20, 0xD9, 0xD1, 0x66, 0x17, 0x19, 0x54, 0x36, 0x18, 0xE1, 0xF5, 0x34, 0x12, 0x9E
+
+#####################
+# sha_hmac_buff_512 #
+#####################
+[sha1_hmac_buff_512]
+digest =
+0x78, 0x14, 0x01, 0xED, 0x93, 0x6F, 0x22, 0xB6, 0x96, 0x5A, 0x32, 0x05, 0xA9, 0xD3, 0x49, 0x04,
+0x55, 0xB0, 0x00, 0x06
+
+[sha224_hmac_buff_512]
+digest =
+0x25, 0xD4, 0x8F, 0x92, 0xE1, 0xD0, 0x4E, 0x3F, 0x34, 0x38, 0x01, 0xB8, 0xFE, 0x57, 0x3D, 0x34,
+0x39, 0x98, 0x82, 0x8D, 0x68, 0x04, 0x5A, 0x74, 0x28, 0x4F, 0x18, 0xCE
+
+[sha256_hmac_buff_512]
+digest =
+0x90, 0x06, 0x97, 0x8A, 0x7A, 0xEF, 0x62, 0x14, 0x4C, 0x14, 0xAA, 0x25, 0x4C, 0xE3, 0x5D, 0xE4,
+0xAD, 0x6C, 0xD6, 0x82, 0x2B, 0x87, 0x53, 0x3E, 0xE9, 0xE4, 0x97, 0x82, 0x82, 0x76, 0xE7, 0xF1
+
+[sha384_hmac_buff_512]
+digest =
+0xD5, 0xDA, 0x7C, 0x8A, 0x0D, 0x1B, 0xBE, 0x3E, 0x25, 0x1E, 0x6C, 0xA4, 0x50, 0x32, 0x92, 0x13,
+0x91, 0x4F, 0xA2, 0x29, 0x2A, 0x0A, 0x57, 0x62, 0x3D, 0x93, 0xF2, 0x45, 0x96, 0x22, 0xF8, 0x0D,
+0xA9, 0xE9, 0xAB, 0xAC, 0x7B, 0x2E, 0x42, 0xC2, 0x3E, 0x75, 0x23, 0xD0, 0xD2, 0xAA, 0x1E, 0xEE
+
+[sha512_hmac_buff_512]
+digest =
+0x57, 0x34, 0x65, 0x3D, 0xDE, 0x8B, 0x7B, 0x99, 0x62, 0x24, 0xF3, 0xAF, 0xA6, 0xB1, 0xF0, 0x01,
+0x23, 0xD4, 0x94, 0xC2, 0x06, 0x70, 0xA5, 0x8C, 0x80, 0x93, 0x49, 0x88, 0xB4, 0xB6, 0x45, 0xE5,
+0x37, 0xC9, 0xE4, 0xA1, 0xAB, 0x6C, 0xA5, 0x23, 0xD2, 0x07, 0x9B, 0x10, 0x4D, 0xFD, 0x75, 0xC0,
+0x28, 0xA1, 0x8A, 0x84, 0x03, 0x35, 0x22, 0xCC, 0xAC, 0x6C, 0x97, 0x93, 0x57, 0x08, 0x48, 0x51
+
+######################
+# sha_hmac_buff_1024 #
+######################
+[sha1_hmac_buff_1024]
+digest =
+0x74, 0xF7, 0x91, 0x04, 0x06, 0xDB, 0xA9, 0xF0, 0x08, 0x0E, 0x93, 0xCE, 0x55, 0xA8, 0x54, 0xF0,
+0x4B, 0x5E, 0x3F, 0xC7
+
+[sha224_hmac_buff_1024]
+digest =
+0x45, 0xDA, 0x2E, 0x83, 0xBD, 0x35, 0xA4, 0x58, 0x14, 0x74, 0xCB, 0xA4, 0x48, 0xA6, 0xBA, 0xDC,
+0x7D, 0x56, 0x6A, 0x44, 0xA7, 0xE9, 0x2F, 0x75, 0x20, 0x47, 0x2A, 0x5A
+
+[sha256_hmac_buff_1024]
+digest =
+0xA2, 0x81, 0xFE, 0x1A, 0x5C, 0x4F, 0x02, 0x72, 0xEF, 0x4F, 0xC6, 0xEE, 0x54, 0x71, 0x69, 0xAF,
+0x5C, 0x71, 0x9F, 0xB0, 0xAC, 0x5B, 0x7F, 0x51, 0xD6, 0x0D, 0x64, 0xD2, 0x2E, 0x0E, 0x30, 0x55
+
+[sha384_hmac_buff_1024]
+digest =
+0x26, 0x44, 0x13, 0x01, 0x25, 0x6E, 0xC7, 0xC3, 0x88, 0x25, 0xD5, 0xDD, 0x1D, 0xCA, 0x0C, 0xB1,
+0xB8, 0x82, 0xB2, 0xB8, 0x15, 0x3F, 0xE5, 0x54, 0x43, 0x47, 0x32, 0x3B, 0xB2, 0xE0, 0xC8, 0x58,
+0x64, 0xE7, 0x78, 0xC9, 0x1F, 0x81, 0x7B, 0xBD, 0x0D, 0x6D, 0x37, 0x9C, 0x01, 0x20, 0x6A, 0x8E
+
+[sha512_hmac_buff_1024]
+digest =
+0xBE, 0xDA, 0x0D, 0x3B, 0x47, 0x24, 0xBA, 0x45, 0xBA, 0xCA, 0x84, 0x5F, 0xEA, 0xAC, 0x33, 0x84,
+0x00, 0x62, 0xA5, 0x29, 0xB6, 0x2F, 0xB7, 0x86, 0xD0, 0x94, 0xFF, 0xFF, 0xE4, 0x1E, 0x5C, 0xFD,
+0xC8, 0xD5, 0x3A, 0xD4, 0xFC, 0xA6, 0x1C, 0x66, 0x4A, 0x6D, 0xF9, 0x2B, 0x1D, 0x7F, 0xA0, 0xCF,
+0x3D, 0x0F, 0x1F, 0x5B, 0xDD, 0x21, 0x12, 0xA8, 0x76, 0xB0, 0xD7, 0x30, 0x66, 0xA6, 0xA0, 0x6C
+
+######################
+# sha_hmac_buff_2048 #
+######################
+[sha1_hmac_buff_2048]
+digest =
+0x99, 0x32, 0xCD, 0xC3, 0xC9, 0x7F, 0x98, 0x1A, 0x96, 0xF6, 0x52, 0xC8, 0xA2, 0x16, 0x9C, 0x29,
+0x9D, 0x6E, 0x96, 0xF5
+
+[sha224_hmac_buff_2048]
+digest =
+0x1A, 0xC4, 0xDC, 0x46, 0xE5, 0x87, 0xFE, 0xE0, 0x47, 0x64, 0x53, 0xA3, 0x6A, 0x1F, 0x78, 0xC0,
+0xC0, 0x02, 0x03, 0x64, 0xB1, 0x55, 0x50, 0x66, 0xDA, 0xD6, 0x9E, 0xBC
+
+[sha256_hmac_buff_2048]
+digest =
+0xA6, 0xC6, 0x4B, 0x0C, 0x95, 0xDE, 0xD5, 0xE2, 0x40, 0x7D, 0x44, 0xC5, 0xBF, 0x00, 0x5A, 0xFB,
+0x6F, 0x3F, 0x5E, 0x69, 0xB1, 0x32, 0x91, 0xAB, 0x6C, 0x90, 0x25, 0xAB, 0xD9, 0x1B, 0x8F, 0x80
+
+[sha384_hmac_buff_2048]
+digest =
+0x16, 0xF1, 0x1B, 0xC1, 0x22, 0xDB, 0x21, 0x90, 0x08, 0xE3, 0x42, 0x0C, 0x9A, 0xF1, 0x0F, 0xF8,
+0x7A, 0xE9, 0x50, 0x09, 0xC6, 0x0C, 0x71, 0x65, 0x3A, 0x40, 0xB3, 0x78, 0x11, 0xE8, 0xD2, 0xD4,
+0xB0, 0x6C, 0xA9, 0x6A, 0x0C, 0xCD, 0xE1, 0x70, 0x7E, 0x90, 0x86, 0x34, 0xC1, 0x08, 0x9E, 0xFC
+
+[sha512_hmac_buff_2048]
+digest =
+0xDF, 0x7F, 0xC3, 0x26, 0x3E, 0x55, 0x80, 0x7D, 0x02, 0x06, 0x5A, 0x4B, 0x8C, 0xFD, 0x2F, 0x33,
+0xF8, 0x0E, 0x9C, 0x59, 0xAE, 0x56, 0xAE, 0x86, 0xA9, 0x25, 0x3F, 0xB7, 0xF7, 0x4C, 0x7A, 0xB4,
+0xD8, 0x0E, 0x43, 0xC0, 0x86, 0xDF, 0xDB, 0xBA, 0xA8, 0xCB, 0x46, 0x2A, 0x92, 0x34, 0xF5, 0x3B,
+0xBD, 0x59, 0x64, 0xDF, 0x30, 0x20, 0xF5, 0x13, 0xD7, 0x78, 0xB9, 0x27, 0xE6, 0xB6, 0x56, 0x19
diff --git a/src/seastar/dpdk/app/test-crypto-perf/main.c b/src/seastar/dpdk/app/test-crypto-perf/main.c
new file mode 100644
index 00000000..9ec2a4b4
--- /dev/null
+++ b/src/seastar/dpdk/app/test-crypto-perf/main.c
@@ -0,0 +1,444 @@
+#include <stdio.h>
+#include <unistd.h>
+
+#include <rte_eal.h>
+#include <rte_cryptodev.h>
+
+#include "cperf.h"
+#include "cperf_options.h"
+#include "cperf_test_vector_parsing.h"
+#include "cperf_test_throughput.h"
+#include "cperf_test_latency.h"
+#include "cperf_test_verify.h"
+
+const char *cperf_test_type_strs[] = {
+ [CPERF_TEST_TYPE_THROUGHPUT] = "throughput",
+ [CPERF_TEST_TYPE_LATENCY] = "latency",
+ [CPERF_TEST_TYPE_VERIFY] = "verify"
+};
+
+const char *cperf_op_type_strs[] = {
+ [CPERF_CIPHER_ONLY] = "cipher-only",
+ [CPERF_AUTH_ONLY] = "auth-only",
+ [CPERF_CIPHER_THEN_AUTH] = "cipher-then-auth",
+ [CPERF_AUTH_THEN_CIPHER] = "auth-then-cipher",
+ [CPERF_AEAD] = "aead"
+};
+
+const struct cperf_test cperf_testmap[] = {
+ [CPERF_TEST_TYPE_THROUGHPUT] = {
+ cperf_throughput_test_constructor,
+ cperf_throughput_test_runner,
+ cperf_throughput_test_destructor
+ },
+ [CPERF_TEST_TYPE_LATENCY] = {
+ cperf_latency_test_constructor,
+ cperf_latency_test_runner,
+ cperf_latency_test_destructor
+ },
+ [CPERF_TEST_TYPE_VERIFY] = {
+ cperf_verify_test_constructor,
+ cperf_verify_test_runner,
+ cperf_verify_test_destructor
+ }
+};
+
+static int
+cperf_initialize_cryptodev(struct cperf_options *opts, uint8_t *enabled_cdevs)
+{
+ uint8_t cdev_id, enabled_cdev_count = 0, nb_lcores;
+ int ret;
+
+ enabled_cdev_count = rte_cryptodev_devices_get(opts->device_type,
+ enabled_cdevs, RTE_CRYPTO_MAX_DEVS);
+ if (enabled_cdev_count == 0) {
+ printf("No crypto devices type %s available\n",
+ opts->device_type);
+ return -EINVAL;
+ }
+
+ nb_lcores = rte_lcore_count() - 1;
+
+ if (enabled_cdev_count > nb_lcores) {
+ printf("Number of capable crypto devices (%d) "
+ "has to be less or equal to number of slave "
+ "cores (%d)\n", enabled_cdev_count, nb_lcores);
+ return -EINVAL;
+ }
+
+ for (cdev_id = 0; cdev_id < enabled_cdev_count &&
+ cdev_id < RTE_CRYPTO_MAX_DEVS; cdev_id++) {
+
+ struct rte_cryptodev_config conf = {
+ .nb_queue_pairs = 1,
+ .socket_id = SOCKET_ID_ANY,
+ .session_mp = {
+ .nb_objs = 2048,
+ .cache_size = 64
+ }
+ };
+ struct rte_cryptodev_qp_conf qp_conf = {
+ .nb_descriptors = 2048
+ };
+
+ ret = rte_cryptodev_configure(enabled_cdevs[cdev_id], &conf);
+ if (ret < 0) {
+ printf("Failed to configure cryptodev %u",
+ enabled_cdevs[cdev_id]);
+ return -EINVAL;
+ }
+
+ ret = rte_cryptodev_queue_pair_setup(enabled_cdevs[cdev_id], 0,
+ &qp_conf, SOCKET_ID_ANY);
+ if (ret < 0) {
+ printf("Failed to setup queue pair %u on "
+ "cryptodev %u", 0, cdev_id);
+ return -EINVAL;
+ }
+
+ ret = rte_cryptodev_start(enabled_cdevs[cdev_id]);
+ if (ret < 0) {
+ printf("Failed to start device %u: error %d\n",
+ enabled_cdevs[cdev_id], ret);
+ return -EPERM;
+ }
+ }
+
+ return enabled_cdev_count;
+}
+
+static int
+cperf_verify_devices_capabilities(struct cperf_options *opts,
+ uint8_t *enabled_cdevs, uint8_t nb_cryptodevs)
+{
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ const struct rte_cryptodev_symmetric_capability *capability;
+
+ uint8_t i, cdev_id;
+ int ret;
+
+ for (i = 0; i < nb_cryptodevs; i++) {
+
+ cdev_id = enabled_cdevs[i];
+
+ if (opts->op_type == CPERF_AUTH_ONLY ||
+ opts->op_type == CPERF_CIPHER_THEN_AUTH ||
+ opts->op_type == CPERF_AUTH_THEN_CIPHER ||
+ opts->op_type == CPERF_AEAD) {
+
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = opts->auth_algo;
+
+ capability = rte_cryptodev_sym_capability_get(cdev_id,
+ &cap_idx);
+ if (capability == NULL)
+ return -1;
+
+ ret = rte_cryptodev_sym_capability_check_auth(
+ capability,
+ opts->auth_key_sz,
+ opts->auth_digest_sz,
+ opts->auth_aad_sz);
+ if (ret != 0)
+ return ret;
+ }
+
+ if (opts->op_type == CPERF_CIPHER_ONLY ||
+ opts->op_type == CPERF_CIPHER_THEN_AUTH ||
+ opts->op_type == CPERF_AUTH_THEN_CIPHER ||
+ opts->op_type == CPERF_AEAD) {
+
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = opts->cipher_algo;
+
+ capability = rte_cryptodev_sym_capability_get(cdev_id,
+ &cap_idx);
+ if (capability == NULL)
+ return -1;
+
+ ret = rte_cryptodev_sym_capability_check_cipher(
+ capability,
+ opts->cipher_key_sz,
+ opts->cipher_iv_sz);
+ if (ret != 0)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int
+cperf_check_test_vector(struct cperf_options *opts,
+ struct cperf_test_vector *test_vec)
+{
+ if (opts->op_type == CPERF_CIPHER_ONLY) {
+ if (opts->cipher_algo == RTE_CRYPTO_CIPHER_NULL) {
+ if (test_vec->plaintext.data == NULL)
+ return -1;
+ } else if (opts->cipher_algo != RTE_CRYPTO_CIPHER_NULL) {
+ if (test_vec->plaintext.data == NULL)
+ return -1;
+ if (test_vec->plaintext.length < opts->max_buffer_size)
+ return -1;
+ if (test_vec->ciphertext.data == NULL)
+ return -1;
+ if (test_vec->ciphertext.length < opts->max_buffer_size)
+ return -1;
+ if (test_vec->iv.data == NULL)
+ return -1;
+ if (test_vec->iv.length != opts->cipher_iv_sz)
+ return -1;
+ if (test_vec->cipher_key.data == NULL)
+ return -1;
+ if (test_vec->cipher_key.length != opts->cipher_key_sz)
+ return -1;
+ }
+ } else if (opts->op_type == CPERF_AUTH_ONLY) {
+ if (opts->auth_algo != RTE_CRYPTO_AUTH_NULL) {
+ if (test_vec->plaintext.data == NULL)
+ return -1;
+ if (test_vec->plaintext.length < opts->max_buffer_size)
+ return -1;
+ if (test_vec->auth_key.data == NULL)
+ return -1;
+ if (test_vec->auth_key.length != opts->auth_key_sz)
+ return -1;
+ if (test_vec->digest.data == NULL)
+ return -1;
+ if (test_vec->digest.length < opts->auth_digest_sz)
+ return -1;
+ }
+
+ } else if (opts->op_type == CPERF_CIPHER_THEN_AUTH ||
+ opts->op_type == CPERF_AUTH_THEN_CIPHER) {
+ if (opts->cipher_algo == RTE_CRYPTO_CIPHER_NULL) {
+ if (test_vec->plaintext.data == NULL)
+ return -1;
+ if (test_vec->plaintext.length < opts->max_buffer_size)
+ return -1;
+ } else if (opts->cipher_algo != RTE_CRYPTO_CIPHER_NULL) {
+ if (test_vec->plaintext.data == NULL)
+ return -1;
+ if (test_vec->plaintext.length < opts->max_buffer_size)
+ return -1;
+ if (test_vec->ciphertext.data == NULL)
+ return -1;
+ if (test_vec->ciphertext.length < opts->max_buffer_size)
+ return -1;
+ if (test_vec->iv.data == NULL)
+ return -1;
+ if (test_vec->iv.length != opts->cipher_iv_sz)
+ return -1;
+ if (test_vec->cipher_key.data == NULL)
+ return -1;
+ if (test_vec->cipher_key.length != opts->cipher_key_sz)
+ return -1;
+ }
+ if (opts->auth_algo != RTE_CRYPTO_AUTH_NULL) {
+ if (test_vec->auth_key.data == NULL)
+ return -1;
+ if (test_vec->auth_key.length != opts->auth_key_sz)
+ return -1;
+ if (test_vec->digest.data == NULL)
+ return -1;
+ if (test_vec->digest.length < opts->auth_digest_sz)
+ return -1;
+ }
+ } else if (opts->op_type == CPERF_AEAD) {
+ if (test_vec->plaintext.data == NULL)
+ return -1;
+ if (test_vec->plaintext.length < opts->max_buffer_size)
+ return -1;
+ if (test_vec->ciphertext.data == NULL)
+ return -1;
+ if (test_vec->ciphertext.length < opts->max_buffer_size)
+ return -1;
+ if (test_vec->aad.data == NULL)
+ return -1;
+ if (test_vec->aad.length != opts->auth_aad_sz)
+ return -1;
+ if (test_vec->digest.data == NULL)
+ return -1;
+ if (test_vec->digest.length < opts->auth_digest_sz)
+ return -1;
+ }
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ struct cperf_options opts = {0};
+ struct cperf_test_vector *t_vec = NULL;
+ struct cperf_op_fns op_fns;
+
+ void *ctx[RTE_MAX_LCORE] = { };
+
+ int nb_cryptodevs = 0;
+ uint8_t cdev_id, i;
+ uint8_t enabled_cdevs[RTE_CRYPTO_MAX_DEVS] = { 0 };
+
+ uint8_t buffer_size_idx = 0;
+
+ int ret;
+ uint32_t lcore_id;
+
+ /* Initialise DPDK EAL */
+ ret = rte_eal_init(argc, argv);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "Invalid EAL arguments!\n");
+ argc -= ret;
+ argv += ret;
+
+ cperf_options_default(&opts);
+
+ ret = cperf_options_parse(&opts, argc, argv);
+ if (ret) {
+ RTE_LOG(ERR, USER1, "Parsing on or more user options failed\n");
+ goto err;
+ }
+
+ ret = cperf_options_check(&opts);
+ if (ret) {
+ RTE_LOG(ERR, USER1,
+ "Checking on or more user options failed\n");
+ goto err;
+ }
+
+ if (!opts.silent)
+ cperf_options_dump(&opts);
+
+ nb_cryptodevs = cperf_initialize_cryptodev(&opts, enabled_cdevs);
+ if (nb_cryptodevs < 1) {
+ RTE_LOG(ERR, USER1, "Failed to initialise requested crypto "
+ "device type\n");
+ nb_cryptodevs = 0;
+ goto err;
+ }
+
+ ret = cperf_verify_devices_capabilities(&opts, enabled_cdevs,
+ nb_cryptodevs);
+ if (ret) {
+ RTE_LOG(ERR, USER1, "Crypto device type does not support "
+ "capabilities requested\n");
+ goto err;
+ }
+
+ if (opts.test_file != NULL) {
+ t_vec = cperf_test_vector_get_from_file(&opts);
+ if (t_vec == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Failed to create test vector for"
+ " specified file\n");
+ goto err;
+ }
+
+ if (cperf_check_test_vector(&opts, t_vec)) {
+ RTE_LOG(ERR, USER1, "Incomplete necessary test vectors"
+ "\n");
+ goto err;
+ }
+ } else {
+ t_vec = cperf_test_vector_get_dummy(&opts);
+ if (t_vec == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Failed to create test vector for"
+ " specified algorithms\n");
+ goto err;
+ }
+ }
+
+ ret = cperf_get_op_functions(&opts, &op_fns);
+ if (ret) {
+ RTE_LOG(ERR, USER1, "Failed to find function ops set for "
+ "specified algorithms combination\n");
+ goto err;
+ }
+
+ if (!opts.silent)
+ show_test_vector(t_vec);
+
+ i = 0;
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+
+ if (i == nb_cryptodevs)
+ break;
+
+ cdev_id = enabled_cdevs[i];
+
+ ctx[cdev_id] = cperf_testmap[opts.test].constructor(cdev_id, 0,
+ &opts, t_vec, &op_fns);
+ if (ctx[cdev_id] == NULL) {
+ RTE_LOG(ERR, USER1, "Test run constructor failed\n");
+ goto err;
+ }
+ i++;
+ }
+
+ /* Get first size from range or list */
+ if (opts.inc_buffer_size != 0)
+ opts.test_buffer_size = opts.min_buffer_size;
+ else
+ opts.test_buffer_size = opts.buffer_size_list[0];
+
+ while (opts.test_buffer_size <= opts.max_buffer_size) {
+ i = 0;
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+
+ if (i == nb_cryptodevs)
+ break;
+
+ cdev_id = enabled_cdevs[i];
+
+ rte_eal_remote_launch(cperf_testmap[opts.test].runner,
+ ctx[cdev_id], lcore_id);
+ i++;
+ }
+ rte_eal_mp_wait_lcore();
+
+ /* Get next size from range or list */
+ if (opts.inc_buffer_size != 0)
+ opts.test_buffer_size += opts.inc_buffer_size;
+ else {
+ if (++buffer_size_idx == opts.buffer_size_count)
+ break;
+ opts.test_buffer_size = opts.buffer_size_list[buffer_size_idx];
+ }
+ }
+
+ i = 0;
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+
+ if (i == nb_cryptodevs)
+ break;
+
+ cdev_id = enabled_cdevs[i];
+
+ cperf_testmap[opts.test].destructor(ctx[cdev_id]);
+ i++;
+ }
+
+ free_test_vector(t_vec, &opts);
+
+ printf("\n");
+ return EXIT_SUCCESS;
+
+err:
+ i = 0;
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ if (i == nb_cryptodevs)
+ break;
+
+ cdev_id = enabled_cdevs[i];
+
+ if (ctx[cdev_id] && cperf_testmap[opts.test].destructor)
+ cperf_testmap[opts.test].destructor(ctx[cdev_id]);
+ i++;
+ }
+
+ free_test_vector(t_vec, &opts);
+
+ printf("\n");
+ return EXIT_FAILURE;
+}
diff --git a/src/seastar/dpdk/app/test-pmd/Makefile b/src/seastar/dpdk/app/test-pmd/Makefile
new file mode 100644
index 00000000..35ecee9f
--- /dev/null
+++ b/src/seastar/dpdk/app/test-pmd/Makefile
@@ -0,0 +1,86 @@
+# BSD LICENSE
+#
+# Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+ifeq ($(CONFIG_RTE_TEST_PMD),y)
+
+#
+# library name
+#
+APP = testpmd
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-y := testpmd.c
+SRCS-y += parameters.c
+SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline.c
+SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_flow.c
+SRCS-y += config.c
+SRCS-y += iofwd.c
+SRCS-y += macfwd.c
+SRCS-y += macswap.c
+SRCS-y += flowgen.c
+SRCS-y += rxonly.c
+SRCS-y += txonly.c
+SRCS-y += csumonly.c
+SRCS-y += icmpecho.c
+SRCS-$(CONFIG_RTE_LIBRTE_IEEE1588) += ieee1588fwd.c
+
+ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y)
+
+ifeq ($(CONFIG_RTE_LIBRTE_PMD_BOND),y)
+LDLIBS += -lrte_pmd_bond
+endif
+
+ifeq ($(CONFIG_RTE_LIBRTE_IXGBE_PMD),y)
+LDLIBS += -lrte_pmd_ixgbe
+endif
+
+ifeq ($(CONFIG_RTE_LIBRTE_I40E_PMD),y)
+LDLIBS += -lrte_pmd_i40e
+endif
+
+ifeq ($(CONFIG_RTE_LIBRTE_PMD_XENVIRT),y)
+LDLIBS += -lrte_pmd_xenvirt
+endif
+
+endif
+
+CFLAGS_cmdline.o := -D_GNU_SOURCE
+
+include $(RTE_SDK)/mk/rte.app.mk
+
+endif
diff --git a/src/seastar/dpdk/app/test-pmd/cmdline.c b/src/seastar/dpdk/app/test-pmd/cmdline.c
new file mode 100644
index 00000000..0afac68c
--- /dev/null
+++ b/src/seastar/dpdk/app/test-pmd/cmdline.c
@@ -0,0 +1,13825 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
+ * Copyright(c) 2014 6WIND S.A.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdarg.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+#include <inttypes.h>
+#ifndef __linux__
+#ifndef __FreeBSD__
+#include <net/socket.h>
+#else
+#include <sys/socket.h>
+#endif
+#endif
+#include <netinet/in.h>
+
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_cycles.h>
+#include <rte_memory.h>
+#include <rte_memzone.h>
+#include <rte_malloc.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_ring.h>
+#include <rte_mempool.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_string_fns.h>
+#include <rte_devargs.h>
+#include <rte_eth_ctrl.h>
+#include <rte_flow.h>
+
+#include <cmdline_rdline.h>
+#include <cmdline_parse.h>
+#include <cmdline_parse_num.h>
+#include <cmdline_parse_string.h>
+#include <cmdline_parse_ipaddr.h>
+#include <cmdline_parse_etheraddr.h>
+#include <cmdline_socket.h>
+#include <cmdline.h>
+#ifdef RTE_LIBRTE_PMD_BOND
+#include <rte_eth_bond.h>
+#endif
+#ifdef RTE_LIBRTE_IXGBE_PMD
+#include <rte_pmd_ixgbe.h>
+#endif
+#ifdef RTE_LIBRTE_I40E_PMD
+#include <rte_pmd_i40e.h>
+#endif
+#include "testpmd.h"
+
+static struct cmdline *testpmd_cl;
+
+static void cmd_reconfig_device_queue(portid_t id, uint8_t dev, uint8_t queue);
+
+/* *** Help command with introduction. *** */
+struct cmd_help_brief_result {
+ cmdline_fixed_string_t help;
+};
+
+static void cmd_help_brief_parsed(__attribute__((unused)) void *parsed_result,
+ struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ cmdline_printf(
+ cl,
+ "\n"
+ "Help is available for the following sections:\n\n"
+ " help control : Start and stop forwarding.\n"
+ " help display : Displaying port, stats and config "
+ "information.\n"
+ " help config : Configuration information.\n"
+ " help ports : Configuring ports.\n"
+ " help registers : Reading and setting port registers.\n"
+ " help filters : Filters configuration help.\n"
+ " help all : All of the above sections.\n\n"
+ );
+
+}
+
+cmdline_parse_token_string_t cmd_help_brief_help =
+ TOKEN_STRING_INITIALIZER(struct cmd_help_brief_result, help, "help");
+
+cmdline_parse_inst_t cmd_help_brief = {
+ .f = cmd_help_brief_parsed,
+ .data = NULL,
+ .help_str = "help: Show help",
+ .tokens = {
+ (void *)&cmd_help_brief_help,
+ NULL,
+ },
+};
+
+/* *** Help command with help sections. *** */
+struct cmd_help_long_result {
+ cmdline_fixed_string_t help;
+ cmdline_fixed_string_t section;
+};
+
+static void cmd_help_long_parsed(void *parsed_result,
+ struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ int show_all = 0;
+ struct cmd_help_long_result *res = parsed_result;
+
+ if (!strcmp(res->section, "all"))
+ show_all = 1;
+
+ if (show_all || !strcmp(res->section, "control")) {
+
+ cmdline_printf(
+ cl,
+ "\n"
+ "Control forwarding:\n"
+ "-------------------\n\n"
+
+ "start\n"
+ " Start packet forwarding with current configuration.\n\n"
+
+ "start tx_first\n"
+ " Start packet forwarding with current config"
+ " after sending one burst of packets.\n\n"
+
+ "stop\n"
+ " Stop packet forwarding, and display accumulated"
+ " statistics.\n\n"
+
+ "quit\n"
+ " Quit to prompt.\n\n"
+ );
+ }
+
+ if (show_all || !strcmp(res->section, "display")) {
+
+ cmdline_printf(
+ cl,
+ "\n"
+ "Display:\n"
+ "--------\n\n"
+
+ "show port (info|stats|xstats|fdir|stat_qmap|dcb_tc|cap) (port_id|all)\n"
+ " Display information for port_id, or all.\n\n"
+
+ "show port X rss reta (size) (mask0,mask1,...)\n"
+ " Display the rss redirection table entry indicated"
+ " by masks on port X. size is used to indicate the"
+ " hardware supported reta size\n\n"
+
+ "show port rss-hash ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|"
+ "ipv4-sctp|ipv4-other|ipv6|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|"
+ "ipv6-other|l2-payload|ipv6-ex|ipv6-tcp-ex|ipv6-udp-ex [key]\n"
+ " Display the RSS hash functions and RSS hash key"
+ " of port X\n\n"
+
+ "clear port (info|stats|xstats|fdir|stat_qmap) (port_id|all)\n"
+ " Clear information for port_id, or all.\n\n"
+
+ "show (rxq|txq) info (port_id) (queue_id)\n"
+ " Display information for configured RX/TX queue.\n\n"
+
+ "show config (rxtx|cores|fwd|txpkts)\n"
+ " Display the given configuration.\n\n"
+
+ "read rxd (port_id) (queue_id) (rxd_id)\n"
+ " Display an RX descriptor of a port RX queue.\n\n"
+
+ "read txd (port_id) (queue_id) (txd_id)\n"
+ " Display a TX descriptor of a port TX queue.\n\n"
+
+ "ddp get list (port_id)\n"
+ " Get ddp profile info list\n\n"
+
+ "show vf stats (port_id) (vf_id)\n"
+ " Display a VF's statistics.\n\n"
+
+ "clear vf stats (port_id) (vf_id)\n"
+ " Reset a VF's statistics.\n\n"
+ );
+ }
+
+ if (show_all || !strcmp(res->section, "config")) {
+ cmdline_printf(
+ cl,
+ "\n"
+ "Configuration:\n"
+ "--------------\n"
+ "Configuration changes only become active when"
+ " forwarding is started/restarted.\n\n"
+
+ "set default\n"
+ " Reset forwarding to the default configuration.\n\n"
+
+ "set verbose (level)\n"
+ " Set the debug verbosity level X.\n\n"
+
+ "set nbport (num)\n"
+ " Set number of ports.\n\n"
+
+ "set nbcore (num)\n"
+ " Set number of cores.\n\n"
+
+ "set coremask (mask)\n"
+ " Set the forwarding cores hexadecimal mask.\n\n"
+
+ "set portmask (mask)\n"
+ " Set the forwarding ports hexadecimal mask.\n\n"
+
+ "set burst (num)\n"
+ " Set number of packets per burst.\n\n"
+
+ "set burst tx delay (microseconds) retry (num)\n"
+ " Set the transmit delay time and number of retries,"
+ " effective when retry is enabled.\n\n"
+
+ "set txpkts (x[,y]*)\n"
+ " Set the length of each segment of TXONLY"
+ " and optionally CSUM packets.\n\n"
+
+ "set txsplit (off|on|rand)\n"
+ " Set the split policy for the TX packets."
+ " Right now only applicable for CSUM and TXONLY"
+ " modes\n\n"
+
+ "set corelist (x[,y]*)\n"
+ " Set the list of forwarding cores.\n\n"
+
+ "set portlist (x[,y]*)\n"
+ " Set the list of forwarding ports.\n\n"
+
+ "set tx loopback (port_id) (on|off)\n"
+ " Enable or disable tx loopback.\n\n"
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ "set all queues drop (port_id) (on|off)\n"
+ " Set drop enable bit for all queues.\n\n"
+
+ "set vf split drop (port_id) (vf_id) (on|off)\n"
+ " Set split drop enable bit for a VF from the PF.\n\n"
+#endif
+
+ "set vf mac antispoof (port_id) (vf_id) (on|off).\n"
+ " Set MAC antispoof for a VF from the PF.\n\n"
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ "set macsec offload (port_id) on encrypt (on|off) replay-protect (on|off)\n"
+ " Enable MACsec offload.\n\n"
+
+ "set macsec offload (port_id) off\n"
+ " Disable MACsec offload.\n\n"
+
+ "set macsec sc (tx|rx) (port_id) (mac) (pi)\n"
+ " Configure MACsec secure connection (SC).\n\n"
+
+ "set macsec sa (tx|rx) (port_id) (idx) (an) (pn) (key)\n"
+ " Configure MACsec secure association (SA).\n\n"
+#endif
+
+ "set vf broadcast (port_id) (vf_id) (on|off)\n"
+ " Set VF broadcast for a VF from the PF.\n\n"
+
+ "vlan set strip (on|off) (port_id)\n"
+ " Set the VLAN strip on a port.\n\n"
+
+ "vlan set stripq (on|off) (port_id,queue_id)\n"
+ " Set the VLAN strip for a queue on a port.\n\n"
+
+ "set vf vlan stripq (port_id) (vf_id) (on|off)\n"
+ " Set the VLAN strip for all queues in a pool for a VF from the PF.\n\n"
+
+ "set vf vlan insert (port_id) (vf_id) (vlan_id)\n"
+ " Set VLAN insert for a VF from the PF.\n\n"
+
+ "set vf vlan antispoof (port_id) (vf_id) (on|off)\n"
+ " Set VLAN antispoof for a VF from the PF.\n\n"
+
+ "set vf vlan tag (port_id) (vf_id) (on|off)\n"
+ " Set VLAN tag for a VF from the PF.\n\n"
+
+ "set vf tx max-bandwidth (port_id) (vf_id) (bandwidth)\n"
+ " Set a VF's max bandwidth(Mbps).\n\n"
+
+ "set vf tc tx min-bandwidth (port_id) (vf_id) (bw1, bw2, ...)\n"
+ " Set all TCs' min bandwidth(%%) on a VF.\n\n"
+
+ "set vf tc tx max-bandwidth (port_id) (vf_id) (tc_no) (bandwidth)\n"
+ " Set a TC's max bandwidth(Mbps) on a VF.\n\n"
+
+ "set tx strict-link-priority (port_id) (tc_bitmap)\n"
+ " Set some TCs' strict link priority mode on a physical port.\n\n"
+
+ "set tc tx min-bandwidth (port_id) (bw1, bw2, ...)\n"
+ " Set all TCs' min bandwidth(%%) for all PF and VFs.\n\n"
+
+ "vlan set filter (on|off) (port_id)\n"
+ " Set the VLAN filter on a port.\n\n"
+
+ "vlan set qinq (on|off) (port_id)\n"
+ " Set the VLAN QinQ (extended queue in queue)"
+ " on a port.\n\n"
+
+ "vlan set (inner|outer) tpid (value) (port_id)\n"
+ " Set the VLAN TPID for Packet Filtering on"
+ " a port\n\n"
+
+ "rx_vlan add (vlan_id|all) (port_id)\n"
+ " Add a vlan_id, or all identifiers, to the set"
+ " of VLAN identifiers filtered by port_id.\n\n"
+
+ "rx_vlan rm (vlan_id|all) (port_id)\n"
+ " Remove a vlan_id, or all identifiers, from the set"
+ " of VLAN identifiers filtered by port_id.\n\n"
+
+ "rx_vlan add (vlan_id) port (port_id) vf (vf_mask)\n"
+ " Add a vlan_id, to the set of VLAN identifiers"
+ "filtered for VF(s) from port_id.\n\n"
+
+ "rx_vlan rm (vlan_id) port (port_id) vf (vf_mask)\n"
+ " Remove a vlan_id, to the set of VLAN identifiers"
+ "filtered for VF(s) from port_id.\n\n"
+
+ "tunnel_filter add (port_id) (outer_mac) (inner_mac) (ip_addr) "
+ "(inner_vlan) (vxlan|nvgre|ipingre) (imac-ivlan|imac-ivlan-tenid|"
+ "imac-tenid|imac|omac-imac-tenid|oip|iip) (tenant_id) (queue_id)\n"
+ " add a tunnel filter of a port.\n\n"
+
+ "tunnel_filter rm (port_id) (outer_mac) (inner_mac) (ip_addr) "
+ "(inner_vlan) (vxlan|nvgre|ipingre) (imac-ivlan|imac-ivlan-tenid|"
+ "imac-tenid|imac|omac-imac-tenid|oip|iip) (tenant_id) (queue_id)\n"
+ " remove a tunnel filter of a port.\n\n"
+
+ "rx_vxlan_port add (udp_port) (port_id)\n"
+ " Add an UDP port for VXLAN packet filter on a port\n\n"
+
+ "rx_vxlan_port rm (udp_port) (port_id)\n"
+ " Remove an UDP port for VXLAN packet filter on a port\n\n"
+
+ "tx_vlan set (port_id) vlan_id[, vlan_id_outer]\n"
+ " Set hardware insertion of VLAN IDs (single or double VLAN "
+ "depends on the number of VLAN IDs) in packets sent on a port.\n\n"
+
+ "tx_vlan set pvid port_id vlan_id (on|off)\n"
+ " Set port based TX VLAN insertion.\n\n"
+
+ "tx_vlan reset (port_id)\n"
+ " Disable hardware insertion of a VLAN header in"
+ " packets sent on a port.\n\n"
+
+ "csum set (ip|udp|tcp|sctp|outer-ip) (hw|sw) (port_id)\n"
+ " Select hardware or software calculation of the"
+ " checksum when transmitting a packet using the"
+ " csum forward engine.\n"
+ " ip|udp|tcp|sctp always concern the inner layer.\n"
+ " outer-ip concerns the outer IP layer in"
+ " case the packet is recognized as a tunnel packet by"
+ " the forward engine (vxlan, gre and ipip are supported)\n"
+ " Please check the NIC datasheet for HW limits.\n\n"
+
+ "csum parse-tunnel (on|off) (tx_port_id)\n"
+ " If disabled, treat tunnel packets as non-tunneled"
+ " packets (treat inner headers as payload). The port\n"
+ " argument is the port used for TX in csum forward"
+ " engine.\n\n"
+
+ "csum show (port_id)\n"
+ " Display tx checksum offload configuration\n\n"
+
+ "tso set (segsize) (portid)\n"
+ " Enable TCP Segmentation Offload in csum forward"
+ " engine.\n"
+ " Please check the NIC datasheet for HW limits.\n\n"
+
+ "tso show (portid)"
+ " Display the status of TCP Segmentation Offload.\n\n"
+
+ "set fwd (%s)\n"
+ " Set packet forwarding mode.\n\n"
+
+ "mac_addr add (port_id) (XX:XX:XX:XX:XX:XX)\n"
+ " Add a MAC address on port_id.\n\n"
+
+ "mac_addr remove (port_id) (XX:XX:XX:XX:XX:XX)\n"
+ " Remove a MAC address from port_id.\n\n"
+
+ "mac_addr set (port_id) (XX:XX:XX:XX:XX:XX)\n"
+ " Set the default MAC address for port_id.\n\n"
+
+ "mac_addr add port (port_id) vf (vf_id) (mac_address)\n"
+ " Add a MAC address for a VF on the port.\n\n"
+
+ "set vf mac addr (port_id) (vf_id) (XX:XX:XX:XX:XX:XX)\n"
+ " Set the MAC address for a VF from the PF.\n\n"
+
+ "set port (port_id) uta (mac_address|all) (on|off)\n"
+ " Add/Remove a or all unicast hash filter(s)"
+ "from port X.\n\n"
+
+ "set promisc (port_id|all) (on|off)\n"
+ " Set the promiscuous mode on port_id, or all.\n\n"
+
+ "set allmulti (port_id|all) (on|off)\n"
+ " Set the allmulti mode on port_id, or all.\n\n"
+
+ "set vf promisc (port_id) (vf_id) (on|off)\n"
+ " Set unicast promiscuous mode for a VF from the PF.\n\n"
+
+ "set vf allmulti (port_id) (vf_id) (on|off)\n"
+ " Set multicast promiscuous mode for a VF from the PF.\n\n"
+
+ "set flow_ctrl rx (on|off) tx (on|off) (high_water)"
+ " (low_water) (pause_time) (send_xon) mac_ctrl_frame_fwd"
+ " (on|off) autoneg (on|off) (port_id)\n"
+ "set flow_ctrl rx (on|off) (portid)\n"
+ "set flow_ctrl tx (on|off) (portid)\n"
+ "set flow_ctrl high_water (high_water) (portid)\n"
+ "set flow_ctrl low_water (low_water) (portid)\n"
+ "set flow_ctrl pause_time (pause_time) (portid)\n"
+ "set flow_ctrl send_xon (send_xon) (portid)\n"
+ "set flow_ctrl mac_ctrl_frame_fwd (on|off) (portid)\n"
+ "set flow_ctrl autoneg (on|off) (port_id)\n"
+ " Set the link flow control parameter on a port.\n\n"
+
+ "set pfc_ctrl rx (on|off) tx (on|off) (high_water)"
+ " (low_water) (pause_time) (priority) (port_id)\n"
+ " Set the priority flow control parameter on a"
+ " port.\n\n"
+
+ "set stat_qmap (tx|rx) (port_id) (queue_id) (qmapping)\n"
+ " Set statistics mapping (qmapping 0..15) for RX/TX"
+ " queue on port.\n"
+ " e.g., 'set stat_qmap rx 0 2 5' sets rx queue 2"
+ " on port 0 to mapping 5.\n\n"
+
+ "set port (port_id) vf (vf_id) rx|tx on|off\n"
+ " Enable/Disable a VF receive/tranmit from a port\n\n"
+
+ "set port (port_id) vf (vf_id) (mac_addr)"
+ " (exact-mac#exact-mac-vlan#hashmac|hashmac-vlan) on|off\n"
+ " Add/Remove unicast or multicast MAC addr filter"
+ " for a VF.\n\n"
+
+ "set port (port_id) vf (vf_id) rxmode (AUPE|ROPE|BAM"
+ "|MPE) (on|off)\n"
+ " AUPE:accepts untagged VLAN;"
+ "ROPE:accept unicast hash\n\n"
+ " BAM:accepts broadcast packets;"
+ "MPE:accepts all multicast packets\n\n"
+ " Enable/Disable a VF receive mode of a port\n\n"
+
+ "set port (port_id) queue (queue_id) rate (rate_num)\n"
+ " Set rate limit for a queue of a port\n\n"
+
+ "set port (port_id) vf (vf_id) rate (rate_num) "
+ "queue_mask (queue_mask_value)\n"
+ " Set rate limit for queues in VF of a port\n\n"
+
+ "set port (port_id) mirror-rule (rule_id)"
+ " (pool-mirror-up|pool-mirror-down|vlan-mirror)"
+ " (poolmask|vlanid[,vlanid]*) dst-pool (pool_id) (on|off)\n"
+ " Set pool or vlan type mirror rule on a port.\n"
+ " e.g., 'set port 0 mirror-rule 0 vlan-mirror 0,1"
+ " dst-pool 0 on' enable mirror traffic with vlan 0,1"
+ " to pool 0.\n\n"
+
+ "set port (port_id) mirror-rule (rule_id)"
+ " (uplink-mirror|downlink-mirror) dst-pool"
+ " (pool_id) (on|off)\n"
+ " Set uplink or downlink type mirror rule on a port.\n"
+ " e.g., 'set port 0 mirror-rule 0 uplink-mirror dst-pool"
+ " 0 on' enable mirror income traffic to pool 0.\n\n"
+
+ "reset port (port_id) mirror-rule (rule_id)\n"
+ " Reset a mirror rule.\n\n"
+
+ "set flush_rx (on|off)\n"
+ " Flush (default) or don't flush RX streams before"
+ " forwarding. Mainly used with PCAP drivers.\n\n"
+
+ #ifdef RTE_NIC_BYPASS
+ "set bypass mode (normal|bypass|isolate) (port_id)\n"
+ " Set the bypass mode for the lowest port on bypass enabled"
+ " NIC.\n\n"
+
+ "set bypass event (timeout|os_on|os_off|power_on|power_off) "
+ "mode (normal|bypass|isolate) (port_id)\n"
+ " Set the event required to initiate specified bypass mode for"
+ " the lowest port on a bypass enabled NIC where:\n"
+ " timeout = enable bypass after watchdog timeout.\n"
+ " os_on = enable bypass when OS/board is powered on.\n"
+ " os_off = enable bypass when OS/board is powered off.\n"
+ " power_on = enable bypass when power supply is turned on.\n"
+ " power_off = enable bypass when power supply is turned off."
+ "\n\n"
+
+ "set bypass timeout (0|1.5|2|3|4|8|16|32)\n"
+ " Set the bypass watchdog timeout to 'n' seconds"
+ " where 0 = instant.\n\n"
+
+ "show bypass config (port_id)\n"
+ " Show the bypass configuration for a bypass enabled NIC"
+ " using the lowest port on the NIC.\n\n"
+#endif
+#ifdef RTE_LIBRTE_PMD_BOND
+ "create bonded device (mode) (socket)\n"
+ " Create a new bonded device with specific bonding mode and socket.\n\n"
+
+ "add bonding slave (slave_id) (port_id)\n"
+ " Add a slave device to a bonded device.\n\n"
+
+ "remove bonding slave (slave_id) (port_id)\n"
+ " Remove a slave device from a bonded device.\n\n"
+
+ "set bonding mode (value) (port_id)\n"
+ " Set the bonding mode on a bonded device.\n\n"
+
+ "set bonding primary (slave_id) (port_id)\n"
+ " Set the primary slave for a bonded device.\n\n"
+
+ "show bonding config (port_id)\n"
+ " Show the bonding config for port_id.\n\n"
+
+ "set bonding mac_addr (port_id) (address)\n"
+ " Set the MAC address of a bonded device.\n\n"
+
+ "set bonding xmit_balance_policy (port_id) (l2|l23|l34)\n"
+ " Set the transmit balance policy for bonded device running in balance mode.\n\n"
+
+ "set bonding mon_period (port_id) (value)\n"
+ " Set the bonding link status monitoring polling period in ms.\n\n"
+#endif
+ "set link-up port (port_id)\n"
+ " Set link up for a port.\n\n"
+
+ "set link-down port (port_id)\n"
+ " Set link down for a port.\n\n"
+
+ "E-tag set insertion on port-tag-id (value)"
+ " port (port_id) vf (vf_id)\n"
+ " Enable E-tag insertion for a VF on a port\n\n"
+
+ "E-tag set insertion off port (port_id) vf (vf_id)\n"
+ " Disable E-tag insertion for a VF on a port\n\n"
+
+ "E-tag set stripping (on|off) port (port_id)\n"
+ " Enable/disable E-tag stripping on a port\n\n"
+
+ "E-tag set forwarding (on|off) port (port_id)\n"
+ " Enable/disable E-tag based forwarding"
+ " on a port\n\n"
+
+ "E-tag set filter add e-tag-id (value) dst-pool"
+ " (pool_id) port (port_id)\n"
+ " Add an E-tag forwarding filter on a port\n\n"
+
+ "E-tag set filter del e-tag-id (value) port (port_id)\n"
+ " Delete an E-tag forwarding filter on a port\n\n"
+
+ "ddp add (port_id) (profile_path)\n"
+ " Load a profile package on a port\n\n"
+
+ "ptype mapping get (port_id) (valid_only)\n"
+ " Get ptype mapping on a port\n\n"
+
+ "ptype mapping replace (port_id) (target) (mask) (pky_type)\n"
+ " Replace target with the pkt_type in ptype mapping\n\n"
+
+ "ptype mapping reset (port_id)\n"
+ " Reset ptype mapping on a port\n\n"
+
+ "ptype mapping update (port_id) (hw_ptype) (sw_ptype)\n"
+ " Update a ptype mapping item on a port\n\n"
+
+ , list_pkt_forwarding_modes()
+ );
+ }
+
+ if (show_all || !strcmp(res->section, "ports")) {
+
+ cmdline_printf(
+ cl,
+ "\n"
+ "Port Operations:\n"
+ "----------------\n\n"
+
+ "port start (port_id|all)\n"
+ " Start all ports or port_id.\n\n"
+
+ "port stop (port_id|all)\n"
+ " Stop all ports or port_id.\n\n"
+
+ "port close (port_id|all)\n"
+ " Close all ports or port_id.\n\n"
+
+ "port attach (ident)\n"
+ " Attach physical or virtual dev by pci address or virtual device name\n\n"
+
+ "port detach (port_id)\n"
+ " Detach physical or virtual dev by port_id\n\n"
+
+ "port config (port_id|all)"
+ " speed (10|100|1000|10000|25000|40000|50000|100000|auto)"
+ " duplex (half|full|auto)\n"
+ " Set speed and duplex for all ports or port_id\n\n"
+
+ "port config all (rxq|txq|rxd|txd) (value)\n"
+ " Set number for rxq/txq/rxd/txd.\n\n"
+
+ "port config all max-pkt-len (value)\n"
+ " Set the max packet length.\n\n"
+
+ "port config all (crc-strip|scatter|rx-cksum|hw-vlan|hw-vlan-filter|"
+ "hw-vlan-strip|hw-vlan-extend|drop-en)"
+ " (on|off)\n"
+ " Set crc-strip/scatter/rx-checksum/hardware-vlan/drop_en"
+ " for ports.\n\n"
+
+ "port config all rss (all|ip|tcp|udp|sctp|ether|port|vxlan|geneve|nvgre|none)\n"
+ " Set the RSS mode.\n\n"
+
+ "port config port-id rss reta (hash,queue)[,(hash,queue)]\n"
+ " Set the RSS redirection table.\n\n"
+
+ "port config (port_id) dcb vt (on|off) (traffic_class)"
+ " pfc (on|off)\n"
+ " Set the DCB mode.\n\n"
+
+ "port config all burst (value)\n"
+ " Set the number of packets per burst.\n\n"
+
+ "port config all (txpt|txht|txwt|rxpt|rxht|rxwt)"
+ " (value)\n"
+ " Set the ring prefetch/host/writeback threshold"
+ " for tx/rx queue.\n\n"
+
+ "port config all (txfreet|txrst|rxfreet) (value)\n"
+ " Set free threshold for rx/tx, or set"
+ " tx rs bit threshold.\n\n"
+ "port config mtu X value\n"
+ " Set the MTU of port X to a given value\n\n"
+
+ "port (port_id) (rxq|txq) (queue_id) (start|stop)\n"
+ " Start/stop a rx/tx queue of port X. Only take effect"
+ " when port X is started\n\n"
+
+ "port config (port_id|all) l2-tunnel E-tag ether-type"
+ " (value)\n"
+ " Set the value of E-tag ether-type.\n\n"
+
+ "port config (port_id|all) l2-tunnel E-tag"
+ " (enable|disable)\n"
+ " Enable/disable the E-tag support.\n\n"
+ );
+ }
+
+ if (show_all || !strcmp(res->section, "registers")) {
+
+ cmdline_printf(
+ cl,
+ "\n"
+ "Registers:\n"
+ "----------\n\n"
+
+ "read reg (port_id) (address)\n"
+ " Display value of a port register.\n\n"
+
+ "read regfield (port_id) (address) (bit_x) (bit_y)\n"
+ " Display a port register bit field.\n\n"
+
+ "read regbit (port_id) (address) (bit_x)\n"
+ " Display a single port register bit.\n\n"
+
+ "write reg (port_id) (address) (value)\n"
+ " Set value of a port register.\n\n"
+
+ "write regfield (port_id) (address) (bit_x) (bit_y)"
+ " (value)\n"
+ " Set bit field of a port register.\n\n"
+
+ "write regbit (port_id) (address) (bit_x) (value)\n"
+ " Set single bit value of a port register.\n\n"
+ );
+ }
+ if (show_all || !strcmp(res->section, "filters")) {
+
+ cmdline_printf(
+ cl,
+ "\n"
+ "filters:\n"
+ "--------\n\n"
+
+ "ethertype_filter (port_id) (add|del)"
+ " (mac_addr|mac_ignr) (mac_address) ethertype"
+ " (ether_type) (drop|fwd) queue (queue_id)\n"
+ " Add/Del an ethertype filter.\n\n"
+
+ "2tuple_filter (port_id) (add|del)"
+ " dst_port (dst_port_value) protocol (protocol_value)"
+ " mask (mask_value) tcp_flags (tcp_flags_value)"
+ " priority (prio_value) queue (queue_id)\n"
+ " Add/Del a 2tuple filter.\n\n"
+
+ "5tuple_filter (port_id) (add|del)"
+ " dst_ip (dst_address) src_ip (src_address)"
+ " dst_port (dst_port_value) src_port (src_port_value)"
+ " protocol (protocol_value)"
+ " mask (mask_value) tcp_flags (tcp_flags_value)"
+ " priority (prio_value) queue (queue_id)\n"
+ " Add/Del a 5tuple filter.\n\n"
+
+ "syn_filter (port_id) (add|del) priority (high|low) queue (queue_id)"
+ " Add/Del syn filter.\n\n"
+
+ "flex_filter (port_id) (add|del) len (len_value)"
+ " bytes (bytes_value) mask (mask_value)"
+ " priority (prio_value) queue (queue_id)\n"
+ " Add/Del a flex filter.\n\n"
+
+ "flow_director_filter (port_id) mode IP (add|del|update)"
+ " flow (ipv4-other|ipv4-frag|ipv6-other|ipv6-frag)"
+ " src (src_ip_address) dst (dst_ip_address)"
+ " tos (tos_value) proto (proto_value) ttl (ttl_value)"
+ " vlan (vlan_value) flexbytes (flexbytes_value)"
+ " (drop|fwd) pf|vf(vf_id) queue (queue_id)"
+ " fd_id (fd_id_value)\n"
+ " Add/Del an IP type flow director filter.\n\n"
+
+ "flow_director_filter (port_id) mode IP (add|del|update)"
+ " flow (ipv4-tcp|ipv4-udp|ipv6-tcp|ipv6-udp)"
+ " src (src_ip_address) (src_port)"
+ " dst (dst_ip_address) (dst_port)"
+ " tos (tos_value) ttl (ttl_value)"
+ " vlan (vlan_value) flexbytes (flexbytes_value)"
+ " (drop|fwd) pf|vf(vf_id) queue (queue_id)"
+ " fd_id (fd_id_value)\n"
+ " Add/Del an UDP/TCP type flow director filter.\n\n"
+
+ "flow_director_filter (port_id) mode IP (add|del|update)"
+ " flow (ipv4-sctp|ipv6-sctp)"
+ " src (src_ip_address) (src_port)"
+ " dst (dst_ip_address) (dst_port)"
+ " tag (verification_tag) "
+ " tos (tos_value) ttl (ttl_value)"
+ " vlan (vlan_value)"
+ " flexbytes (flexbytes_value) (drop|fwd)"
+ " pf|vf(vf_id) queue (queue_id) fd_id (fd_id_value)\n"
+ " Add/Del a SCTP type flow director filter.\n\n"
+
+ "flow_director_filter (port_id) mode IP (add|del|update)"
+ " flow l2_payload ether (ethertype)"
+ " flexbytes (flexbytes_value) (drop|fwd)"
+ " pf|vf(vf_id) queue (queue_id) fd_id (fd_id_value)\n"
+ " Add/Del a l2 payload type flow director filter.\n\n"
+
+ "flow_director_filter (port_id) mode MAC-VLAN (add|del|update)"
+ " mac (mac_address) vlan (vlan_value)"
+ " flexbytes (flexbytes_value) (drop|fwd)"
+ " queue (queue_id) fd_id (fd_id_value)\n"
+ " Add/Del a MAC-VLAN flow director filter.\n\n"
+
+ "flow_director_filter (port_id) mode Tunnel (add|del|update)"
+ " mac (mac_address) vlan (vlan_value)"
+ " tunnel (NVGRE|VxLAN) tunnel-id (tunnel_id_value)"
+ " flexbytes (flexbytes_value) (drop|fwd)"
+ " queue (queue_id) fd_id (fd_id_value)\n"
+ " Add/Del a Tunnel flow director filter.\n\n"
+
+ "flush_flow_director (port_id)\n"
+ " Flush all flow director entries of a device.\n\n"
+
+ "flow_director_mask (port_id) mode IP vlan (vlan_value)"
+ " src_mask (ipv4_src) (ipv6_src) (src_port)"
+ " dst_mask (ipv4_dst) (ipv6_dst) (dst_port)\n"
+ " Set flow director IP mask.\n\n"
+
+ "flow_director_mask (port_id) mode MAC-VLAN"
+ " vlan (vlan_value)\n"
+ " Set flow director MAC-VLAN mask.\n\n"
+
+ "flow_director_mask (port_id) mode Tunnel"
+ " vlan (vlan_value) mac (mac_value)"
+ " tunnel-type (tunnel_type_value)"
+ " tunnel-id (tunnel_id_value)\n"
+ " Set flow director Tunnel mask.\n\n"
+
+ "flow_director_flex_mask (port_id)"
+ " flow (none|ipv4-other|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|"
+ "ipv6-other|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|l2_payload|all)"
+ " (mask)\n"
+ " Configure mask of flex payload.\n\n"
+
+ "flow_director_flex_payload (port_id)"
+ " (raw|l2|l3|l4) (config)\n"
+ " Configure flex payload selection.\n\n"
+
+ "get_sym_hash_ena_per_port (port_id)\n"
+ " get symmetric hash enable configuration per port.\n\n"
+
+ "set_sym_hash_ena_per_port (port_id) (enable|disable)\n"
+ " set symmetric hash enable configuration per port"
+ " to enable or disable.\n\n"
+
+ "get_hash_global_config (port_id)\n"
+ " Get the global configurations of hash filters.\n\n"
+
+ "set_hash_global_config (port_id) (toeplitz|simple_xor|default)"
+ " (ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|"
+ "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload)"
+ " (enable|disable)\n"
+ " Set the global configurations of hash filters.\n\n"
+
+ "set_hash_input_set (port_id) (ipv4|ipv4-frag|"
+ "ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|"
+ "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|"
+ "l2_payload) (ovlan|ivlan|src-ipv4|dst-ipv4|src-ipv6|"
+ "dst-ipv6|ipv4-tos|ipv4-proto|ipv6-tc|"
+ "ipv6-next-header|udp-src-port|udp-dst-port|"
+ "tcp-src-port|tcp-dst-port|sctp-src-port|"
+ "sctp-dst-port|sctp-veri-tag|udp-key|gre-key|fld-1st|"
+ "fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|fld-7th|"
+ "fld-8th|none) (select|add)\n"
+ " Set the input set for hash.\n\n"
+
+ "set_fdir_input_set (port_id) "
+ "(ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|"
+ "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|"
+ "l2_payload) (ivlan|ethertype|src-ipv4|dst-ipv4|src-ipv6|"
+ "dst-ipv6|ipv4-tos|ipv4-proto|ipv4-ttl|ipv6-tc|"
+ "ipv6-next-header|ipv6-hop-limits|udp-src-port|"
+ "udp-dst-port|tcp-src-port|tcp-dst-port|"
+ "sctp-src-port|sctp-dst-port|sctp-veri-tag|none)"
+ " (select|add)\n"
+ " Set the input set for FDir.\n\n"
+
+ "flow validate {port_id}"
+ " [group {group_id}] [priority {level}]"
+ " [ingress] [egress]"
+ " pattern {item} [/ {item} [...]] / end"
+ " actions {action} [/ {action} [...]] / end\n"
+ " Check whether a flow rule can be created.\n\n"
+
+ "flow create {port_id}"
+ " [group {group_id}] [priority {level}]"
+ " [ingress] [egress]"
+ " pattern {item} [/ {item} [...]] / end"
+ " actions {action} [/ {action} [...]] / end\n"
+ " Create a flow rule.\n\n"
+
+ "flow destroy {port_id} rule {rule_id} [...]\n"
+ " Destroy specific flow rules.\n\n"
+
+ "flow flush {port_id}\n"
+ " Destroy all flow rules.\n\n"
+
+ "flow query {port_id} {rule_id} {action}\n"
+ " Query an existing flow rule.\n\n"
+
+ "flow list {port_id} [group {group_id}] [...]\n"
+ " List existing flow rules sorted by priority,"
+ " filtered by group identifiers.\n\n"
+ );
+ }
+}
+
+cmdline_parse_token_string_t cmd_help_long_help =
+ TOKEN_STRING_INITIALIZER(struct cmd_help_long_result, help, "help");
+
+cmdline_parse_token_string_t cmd_help_long_section =
+ TOKEN_STRING_INITIALIZER(struct cmd_help_long_result, section,
+ "all#control#display#config#"
+ "ports#registers#filters");
+
+cmdline_parse_inst_t cmd_help_long = {
+ .f = cmd_help_long_parsed,
+ .data = NULL,
+ .help_str = "help all|control|display|config|ports|register|filters: "
+ "Show help",
+ .tokens = {
+ (void *)&cmd_help_long_help,
+ (void *)&cmd_help_long_section,
+ NULL,
+ },
+};
+
+
+/* *** start/stop/close all ports *** */
+struct cmd_operate_port_result {
+ cmdline_fixed_string_t keyword;
+ cmdline_fixed_string_t name;
+ cmdline_fixed_string_t value;
+};
+
+static void cmd_operate_port_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_operate_port_result *res = parsed_result;
+
+ if (!strcmp(res->name, "start"))
+ start_port(RTE_PORT_ALL);
+ else if (!strcmp(res->name, "stop"))
+ stop_port(RTE_PORT_ALL);
+ else if (!strcmp(res->name, "close"))
+ close_port(RTE_PORT_ALL);
+ else
+ printf("Unknown parameter\n");
+}
+
+cmdline_parse_token_string_t cmd_operate_port_all_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_operate_port_result, keyword,
+ "port");
+cmdline_parse_token_string_t cmd_operate_port_all_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_operate_port_result, name,
+ "start#stop#close");
+cmdline_parse_token_string_t cmd_operate_port_all_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_operate_port_result, value, "all");
+
+cmdline_parse_inst_t cmd_operate_port = {
+ .f = cmd_operate_port_parsed,
+ .data = NULL,
+ .help_str = "port start|stop|close all: Start/Stop/Close all ports",
+ .tokens = {
+ (void *)&cmd_operate_port_all_cmd,
+ (void *)&cmd_operate_port_all_port,
+ (void *)&cmd_operate_port_all_all,
+ NULL,
+ },
+};
+
+/* *** start/stop/close specific port *** */
+struct cmd_operate_specific_port_result {
+ cmdline_fixed_string_t keyword;
+ cmdline_fixed_string_t name;
+ uint8_t value;
+};
+
+static void cmd_operate_specific_port_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_operate_specific_port_result *res = parsed_result;
+
+ if (!strcmp(res->name, "start"))
+ start_port(res->value);
+ else if (!strcmp(res->name, "stop"))
+ stop_port(res->value);
+ else if (!strcmp(res->name, "close"))
+ close_port(res->value);
+ else
+ printf("Unknown parameter\n");
+}
+
+cmdline_parse_token_string_t cmd_operate_specific_port_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_operate_specific_port_result,
+ keyword, "port");
+cmdline_parse_token_string_t cmd_operate_specific_port_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_operate_specific_port_result,
+ name, "start#stop#close");
+cmdline_parse_token_num_t cmd_operate_specific_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_operate_specific_port_result,
+ value, UINT8);
+
+cmdline_parse_inst_t cmd_operate_specific_port = {
+ .f = cmd_operate_specific_port_parsed,
+ .data = NULL,
+ .help_str = "port start|stop|close <port_id>: Start/Stop/Close port_id",
+ .tokens = {
+ (void *)&cmd_operate_specific_port_cmd,
+ (void *)&cmd_operate_specific_port_port,
+ (void *)&cmd_operate_specific_port_id,
+ NULL,
+ },
+};
+
+/* *** attach a specified port *** */
+struct cmd_operate_attach_port_result {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ cmdline_fixed_string_t identifier;
+};
+
+static void cmd_operate_attach_port_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_operate_attach_port_result *res = parsed_result;
+
+ if (!strcmp(res->keyword, "attach"))
+ attach_port(res->identifier);
+ else
+ printf("Unknown parameter\n");
+}
+
+cmdline_parse_token_string_t cmd_operate_attach_port_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result,
+ port, "port");
+cmdline_parse_token_string_t cmd_operate_attach_port_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result,
+ keyword, "attach");
+cmdline_parse_token_string_t cmd_operate_attach_port_identifier =
+ TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result,
+ identifier, NULL);
+
+cmdline_parse_inst_t cmd_operate_attach_port = {
+ .f = cmd_operate_attach_port_parsed,
+ .data = NULL,
+ .help_str = "port attach <identifier>: "
+ "(identifier: pci address or virtual dev name)",
+ .tokens = {
+ (void *)&cmd_operate_attach_port_port,
+ (void *)&cmd_operate_attach_port_keyword,
+ (void *)&cmd_operate_attach_port_identifier,
+ NULL,
+ },
+};
+
+/* *** detach a specified port *** */
+struct cmd_operate_detach_port_result {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ uint8_t port_id;
+};
+
+static void cmd_operate_detach_port_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_operate_detach_port_result *res = parsed_result;
+
+ if (!strcmp(res->keyword, "detach"))
+ detach_port(res->port_id);
+ else
+ printf("Unknown parameter\n");
+}
+
+cmdline_parse_token_string_t cmd_operate_detach_port_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_operate_detach_port_result,
+ port, "port");
+cmdline_parse_token_string_t cmd_operate_detach_port_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_operate_detach_port_result,
+ keyword, "detach");
+cmdline_parse_token_num_t cmd_operate_detach_port_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_operate_detach_port_result,
+ port_id, UINT8);
+
+cmdline_parse_inst_t cmd_operate_detach_port = {
+ .f = cmd_operate_detach_port_parsed,
+ .data = NULL,
+ .help_str = "port detach <port_id>",
+ .tokens = {
+ (void *)&cmd_operate_detach_port_port,
+ (void *)&cmd_operate_detach_port_keyword,
+ (void *)&cmd_operate_detach_port_port_id,
+ NULL,
+ },
+};
+
+/* *** configure speed for all ports *** */
+struct cmd_config_speed_all {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ cmdline_fixed_string_t all;
+ cmdline_fixed_string_t item1;
+ cmdline_fixed_string_t item2;
+ cmdline_fixed_string_t value1;
+ cmdline_fixed_string_t value2;
+};
+
+static int
+parse_and_check_speed_duplex(char *speedstr, char *duplexstr, uint32_t *speed)
+{
+
+ int duplex;
+
+ if (!strcmp(duplexstr, "half")) {
+ duplex = ETH_LINK_HALF_DUPLEX;
+ } else if (!strcmp(duplexstr, "full")) {
+ duplex = ETH_LINK_FULL_DUPLEX;
+ } else if (!strcmp(duplexstr, "auto")) {
+ duplex = ETH_LINK_FULL_DUPLEX;
+ } else {
+ printf("Unknown duplex parameter\n");
+ return -1;
+ }
+
+ if (!strcmp(speedstr, "10")) {
+ *speed = (duplex == ETH_LINK_HALF_DUPLEX) ?
+ ETH_LINK_SPEED_10M_HD : ETH_LINK_SPEED_10M;
+ } else if (!strcmp(speedstr, "100")) {
+ *speed = (duplex == ETH_LINK_HALF_DUPLEX) ?
+ ETH_LINK_SPEED_100M_HD : ETH_LINK_SPEED_100M;
+ } else {
+ if (duplex != ETH_LINK_FULL_DUPLEX) {
+ printf("Invalid speed/duplex parameters\n");
+ return -1;
+ }
+ if (!strcmp(speedstr, "1000")) {
+ *speed = ETH_LINK_SPEED_1G;
+ } else if (!strcmp(speedstr, "10000")) {
+ *speed = ETH_LINK_SPEED_10G;
+ } else if (!strcmp(speedstr, "25000")) {
+ *speed = ETH_LINK_SPEED_25G;
+ } else if (!strcmp(speedstr, "40000")) {
+ *speed = ETH_LINK_SPEED_40G;
+ } else if (!strcmp(speedstr, "50000")) {
+ *speed = ETH_LINK_SPEED_50G;
+ } else if (!strcmp(speedstr, "100000")) {
+ *speed = ETH_LINK_SPEED_100G;
+ } else if (!strcmp(speedstr, "auto")) {
+ *speed = ETH_LINK_SPEED_AUTONEG;
+ } else {
+ printf("Unknown speed parameter\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static void
+cmd_config_speed_all_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_config_speed_all *res = parsed_result;
+ uint32_t link_speed;
+ portid_t pid;
+
+ if (!all_ports_stopped()) {
+ printf("Please stop all ports first\n");
+ return;
+ }
+
+ if (parse_and_check_speed_duplex(res->value1, res->value2,
+ &link_speed) < 0)
+ return;
+
+ RTE_ETH_FOREACH_DEV(pid) {
+ ports[pid].dev_conf.link_speeds = link_speed;
+ }
+
+ cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_config_speed_all_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, port, "port");
+cmdline_parse_token_string_t cmd_config_speed_all_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, keyword,
+ "config");
+cmdline_parse_token_string_t cmd_config_speed_all_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, all, "all");
+cmdline_parse_token_string_t cmd_config_speed_all_item1 =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, item1, "speed");
+cmdline_parse_token_string_t cmd_config_speed_all_value1 =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, value1,
+ "10#100#1000#10000#25000#40000#50000#100000#auto");
+cmdline_parse_token_string_t cmd_config_speed_all_item2 =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, item2, "duplex");
+cmdline_parse_token_string_t cmd_config_speed_all_value2 =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, value2,
+ "half#full#auto");
+
+cmdline_parse_inst_t cmd_config_speed_all = {
+ .f = cmd_config_speed_all_parsed,
+ .data = NULL,
+ .help_str = "port config all speed "
+ "10|100|1000|10000|25000|40000|50000|100000|auto duplex "
+ "half|full|auto",
+ .tokens = {
+ (void *)&cmd_config_speed_all_port,
+ (void *)&cmd_config_speed_all_keyword,
+ (void *)&cmd_config_speed_all_all,
+ (void *)&cmd_config_speed_all_item1,
+ (void *)&cmd_config_speed_all_value1,
+ (void *)&cmd_config_speed_all_item2,
+ (void *)&cmd_config_speed_all_value2,
+ NULL,
+ },
+};
+
+/* *** configure speed for specific port *** */
+struct cmd_config_speed_specific {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ uint8_t id;
+ cmdline_fixed_string_t item1;
+ cmdline_fixed_string_t item2;
+ cmdline_fixed_string_t value1;
+ cmdline_fixed_string_t value2;
+};
+
+static void
+cmd_config_speed_specific_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_config_speed_specific *res = parsed_result;
+ uint32_t link_speed;
+
+ if (!all_ports_stopped()) {
+ printf("Please stop all ports first\n");
+ return;
+ }
+
+ if (port_id_is_invalid(res->id, ENABLED_WARN))
+ return;
+
+ if (parse_and_check_speed_duplex(res->value1, res->value2,
+ &link_speed) < 0)
+ return;
+
+ ports[res->id].dev_conf.link_speeds = link_speed;
+
+ cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+}
+
+
+cmdline_parse_token_string_t cmd_config_speed_specific_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, port,
+ "port");
+cmdline_parse_token_string_t cmd_config_speed_specific_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, keyword,
+ "config");
+cmdline_parse_token_num_t cmd_config_speed_specific_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_speed_specific, id, UINT8);
+cmdline_parse_token_string_t cmd_config_speed_specific_item1 =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, item1,
+ "speed");
+cmdline_parse_token_string_t cmd_config_speed_specific_value1 =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, value1,
+ "10#100#1000#10000#25000#40000#50000#100000#auto");
+cmdline_parse_token_string_t cmd_config_speed_specific_item2 =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, item2,
+ "duplex");
+cmdline_parse_token_string_t cmd_config_speed_specific_value2 =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, value2,
+ "half#full#auto");
+
+cmdline_parse_inst_t cmd_config_speed_specific = {
+ .f = cmd_config_speed_specific_parsed,
+ .data = NULL,
+ .help_str = "port config <port_id> speed "
+ "10|100|1000|10000|25000|40000|50000|100000|auto duplex "
+ "half|full|auto",
+ .tokens = {
+ (void *)&cmd_config_speed_specific_port,
+ (void *)&cmd_config_speed_specific_keyword,
+ (void *)&cmd_config_speed_specific_id,
+ (void *)&cmd_config_speed_specific_item1,
+ (void *)&cmd_config_speed_specific_value1,
+ (void *)&cmd_config_speed_specific_item2,
+ (void *)&cmd_config_speed_specific_value2,
+ NULL,
+ },
+};
+
+/* *** configure txq/rxq, txd/rxd *** */
+struct cmd_config_rx_tx {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ cmdline_fixed_string_t all;
+ cmdline_fixed_string_t name;
+ uint16_t value;
+};
+
+static void
+cmd_config_rx_tx_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_config_rx_tx *res = parsed_result;
+
+ if (!all_ports_stopped()) {
+ printf("Please stop all ports first\n");
+ return;
+ }
+ if (!strcmp(res->name, "rxq")) {
+ if (!res->value && !nb_txq) {
+ printf("Warning: Either rx or tx queues should be non zero\n");
+ return;
+ }
+ nb_rxq = res->value;
+ }
+ else if (!strcmp(res->name, "txq")) {
+ if (!res->value && !nb_rxq) {
+ printf("Warning: Either rx or tx queues should be non zero\n");
+ return;
+ }
+ nb_txq = res->value;
+ }
+ else if (!strcmp(res->name, "rxd")) {
+ if (res->value <= 0 || res->value > RTE_TEST_RX_DESC_MAX) {
+ printf("rxd %d invalid - must be > 0 && <= %d\n",
+ res->value, RTE_TEST_RX_DESC_MAX);
+ return;
+ }
+ nb_rxd = res->value;
+ } else if (!strcmp(res->name, "txd")) {
+ if (res->value <= 0 || res->value > RTE_TEST_TX_DESC_MAX) {
+ printf("txd %d invalid - must be > 0 && <= %d\n",
+ res->value, RTE_TEST_TX_DESC_MAX);
+ return;
+ }
+ nb_txd = res->value;
+ } else {
+ printf("Unknown parameter\n");
+ return;
+ }
+
+ fwd_config_setup();
+
+ init_port_config();
+
+ cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_config_rx_tx_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rx_tx, port, "port");
+cmdline_parse_token_string_t cmd_config_rx_tx_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rx_tx, keyword, "config");
+cmdline_parse_token_string_t cmd_config_rx_tx_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rx_tx, all, "all");
+cmdline_parse_token_string_t cmd_config_rx_tx_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rx_tx, name,
+ "rxq#txq#rxd#txd");
+cmdline_parse_token_num_t cmd_config_rx_tx_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_rx_tx, value, UINT16);
+
+cmdline_parse_inst_t cmd_config_rx_tx = {
+ .f = cmd_config_rx_tx_parsed,
+ .data = NULL,
+ .help_str = "port config all rxq|txq|rxd|txd <value>",
+ .tokens = {
+ (void *)&cmd_config_rx_tx_port,
+ (void *)&cmd_config_rx_tx_keyword,
+ (void *)&cmd_config_rx_tx_all,
+ (void *)&cmd_config_rx_tx_name,
+ (void *)&cmd_config_rx_tx_value,
+ NULL,
+ },
+};
+
+/* *** config max packet length *** */
+struct cmd_config_max_pkt_len_result {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ cmdline_fixed_string_t all;
+ cmdline_fixed_string_t name;
+ uint32_t value;
+};
+
+static void
+cmd_config_max_pkt_len_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_config_max_pkt_len_result *res = parsed_result;
+
+ if (!all_ports_stopped()) {
+ printf("Please stop all ports first\n");
+ return;
+ }
+
+ if (!strcmp(res->name, "max-pkt-len")) {
+ if (res->value < ETHER_MIN_LEN) {
+ printf("max-pkt-len can not be less than %d\n",
+ ETHER_MIN_LEN);
+ return;
+ }
+ if (res->value == rx_mode.max_rx_pkt_len)
+ return;
+
+ rx_mode.max_rx_pkt_len = res->value;
+ if (res->value > ETHER_MAX_LEN)
+ rx_mode.jumbo_frame = 1;
+ else
+ rx_mode.jumbo_frame = 0;
+ } else {
+ printf("Unknown parameter\n");
+ return;
+ }
+
+ init_port_config();
+
+ cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_config_max_pkt_len_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_max_pkt_len_result, port,
+ "port");
+cmdline_parse_token_string_t cmd_config_max_pkt_len_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_max_pkt_len_result, keyword,
+ "config");
+cmdline_parse_token_string_t cmd_config_max_pkt_len_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_max_pkt_len_result, all,
+ "all");
+cmdline_parse_token_string_t cmd_config_max_pkt_len_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_max_pkt_len_result, name,
+ "max-pkt-len");
+cmdline_parse_token_num_t cmd_config_max_pkt_len_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_max_pkt_len_result, value,
+ UINT32);
+
+cmdline_parse_inst_t cmd_config_max_pkt_len = {
+ .f = cmd_config_max_pkt_len_parsed,
+ .data = NULL,
+ .help_str = "port config all max-pkt-len <value>",
+ .tokens = {
+ (void *)&cmd_config_max_pkt_len_port,
+ (void *)&cmd_config_max_pkt_len_keyword,
+ (void *)&cmd_config_max_pkt_len_all,
+ (void *)&cmd_config_max_pkt_len_name,
+ (void *)&cmd_config_max_pkt_len_value,
+ NULL,
+ },
+};
+
+/* *** configure port MTU *** */
+struct cmd_config_mtu_result {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ cmdline_fixed_string_t mtu;
+ uint8_t port_id;
+ uint16_t value;
+};
+
+static void
+cmd_config_mtu_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_config_mtu_result *res = parsed_result;
+
+ if (res->value < ETHER_MIN_LEN) {
+ printf("mtu cannot be less than %d\n", ETHER_MIN_LEN);
+ return;
+ }
+ port_mtu_set(res->port_id, res->value);
+}
+
+cmdline_parse_token_string_t cmd_config_mtu_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_mtu_result, port,
+ "port");
+cmdline_parse_token_string_t cmd_config_mtu_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_mtu_result, keyword,
+ "config");
+cmdline_parse_token_string_t cmd_config_mtu_mtu =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_mtu_result, keyword,
+ "mtu");
+cmdline_parse_token_num_t cmd_config_mtu_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_mtu_result, port_id, UINT8);
+cmdline_parse_token_num_t cmd_config_mtu_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_mtu_result, value, UINT16);
+
+cmdline_parse_inst_t cmd_config_mtu = {
+ .f = cmd_config_mtu_parsed,
+ .data = NULL,
+ .help_str = "port config mtu <port_id> <value>",
+ .tokens = {
+ (void *)&cmd_config_mtu_port,
+ (void *)&cmd_config_mtu_keyword,
+ (void *)&cmd_config_mtu_mtu,
+ (void *)&cmd_config_mtu_port_id,
+ (void *)&cmd_config_mtu_value,
+ NULL,
+ },
+};
+
+/* *** configure rx mode *** */
+struct cmd_config_rx_mode_flag {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ cmdline_fixed_string_t all;
+ cmdline_fixed_string_t name;
+ cmdline_fixed_string_t value;
+};
+
+static void
+cmd_config_rx_mode_flag_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_config_rx_mode_flag *res = parsed_result;
+
+ if (!all_ports_stopped()) {
+ printf("Please stop all ports first\n");
+ return;
+ }
+
+ if (!strcmp(res->name, "crc-strip")) {
+ if (!strcmp(res->value, "on"))
+ rx_mode.hw_strip_crc = 1;
+ else if (!strcmp(res->value, "off"))
+ rx_mode.hw_strip_crc = 0;
+ else {
+ printf("Unknown parameter\n");
+ return;
+ }
+ } else if (!strcmp(res->name, "scatter")) {
+ if (!strcmp(res->value, "on"))
+ rx_mode.enable_scatter = 1;
+ else if (!strcmp(res->value, "off"))
+ rx_mode.enable_scatter = 0;
+ else {
+ printf("Unknown parameter\n");
+ return;
+ }
+ } else if (!strcmp(res->name, "rx-cksum")) {
+ if (!strcmp(res->value, "on"))
+ rx_mode.hw_ip_checksum = 1;
+ else if (!strcmp(res->value, "off"))
+ rx_mode.hw_ip_checksum = 0;
+ else {
+ printf("Unknown parameter\n");
+ return;
+ }
+ } else if (!strcmp(res->name, "hw-vlan")) {
+ if (!strcmp(res->value, "on")) {
+ rx_mode.hw_vlan_filter = 1;
+ rx_mode.hw_vlan_strip = 1;
+ }
+ else if (!strcmp(res->value, "off")) {
+ rx_mode.hw_vlan_filter = 0;
+ rx_mode.hw_vlan_strip = 0;
+ }
+ else {
+ printf("Unknown parameter\n");
+ return;
+ }
+ } else if (!strcmp(res->name, "hw-vlan-filter")) {
+ if (!strcmp(res->value, "on"))
+ rx_mode.hw_vlan_filter = 1;
+ else if (!strcmp(res->value, "off"))
+ rx_mode.hw_vlan_filter = 0;
+ else {
+ printf("Unknown parameter\n");
+ return;
+ }
+ } else if (!strcmp(res->name, "hw-vlan-strip")) {
+ if (!strcmp(res->value, "on"))
+ rx_mode.hw_vlan_strip = 1;
+ else if (!strcmp(res->value, "off"))
+ rx_mode.hw_vlan_strip = 0;
+ else {
+ printf("Unknown parameter\n");
+ return;
+ }
+ } else if (!strcmp(res->name, "hw-vlan-extend")) {
+ if (!strcmp(res->value, "on"))
+ rx_mode.hw_vlan_extend = 1;
+ else if (!strcmp(res->value, "off"))
+ rx_mode.hw_vlan_extend = 0;
+ else {
+ printf("Unknown parameter\n");
+ return;
+ }
+ } else if (!strcmp(res->name, "drop-en")) {
+ if (!strcmp(res->value, "on"))
+ rx_drop_en = 1;
+ else if (!strcmp(res->value, "off"))
+ rx_drop_en = 0;
+ else {
+ printf("Unknown parameter\n");
+ return;
+ }
+ } else {
+ printf("Unknown parameter\n");
+ return;
+ }
+
+ init_port_config();
+
+ cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_config_rx_mode_flag_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rx_mode_flag, port, "port");
+cmdline_parse_token_string_t cmd_config_rx_mode_flag_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rx_mode_flag, keyword,
+ "config");
+cmdline_parse_token_string_t cmd_config_rx_mode_flag_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rx_mode_flag, all, "all");
+cmdline_parse_token_string_t cmd_config_rx_mode_flag_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rx_mode_flag, name,
+ "crc-strip#scatter#rx-cksum#hw-vlan#"
+ "hw-vlan-filter#hw-vlan-strip#hw-vlan-extend");
+cmdline_parse_token_string_t cmd_config_rx_mode_flag_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rx_mode_flag, value,
+ "on#off");
+
+cmdline_parse_inst_t cmd_config_rx_mode_flag = {
+ .f = cmd_config_rx_mode_flag_parsed,
+ .data = NULL,
+ .help_str = "port config all crc-strip|scatter|rx-cksum|hw-vlan|"
+ "hw-vlan-filter|hw-vlan-strip|hw-vlan-extend on|off",
+ .tokens = {
+ (void *)&cmd_config_rx_mode_flag_port,
+ (void *)&cmd_config_rx_mode_flag_keyword,
+ (void *)&cmd_config_rx_mode_flag_all,
+ (void *)&cmd_config_rx_mode_flag_name,
+ (void *)&cmd_config_rx_mode_flag_value,
+ NULL,
+ },
+};
+
+/* *** configure rss *** */
+struct cmd_config_rss {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ cmdline_fixed_string_t all;
+ cmdline_fixed_string_t name;
+ cmdline_fixed_string_t value;
+};
+
+static void
+cmd_config_rss_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_config_rss *res = parsed_result;
+ struct rte_eth_rss_conf rss_conf;
+ int diag;
+ uint8_t i;
+
+ if (!strcmp(res->value, "all"))
+ rss_conf.rss_hf = ETH_RSS_IP | ETH_RSS_TCP |
+ ETH_RSS_UDP | ETH_RSS_SCTP |
+ ETH_RSS_L2_PAYLOAD;
+ else if (!strcmp(res->value, "ip"))
+ rss_conf.rss_hf = ETH_RSS_IP;
+ else if (!strcmp(res->value, "udp"))
+ rss_conf.rss_hf = ETH_RSS_UDP;
+ else if (!strcmp(res->value, "tcp"))
+ rss_conf.rss_hf = ETH_RSS_TCP;
+ else if (!strcmp(res->value, "sctp"))
+ rss_conf.rss_hf = ETH_RSS_SCTP;
+ else if (!strcmp(res->value, "ether"))
+ rss_conf.rss_hf = ETH_RSS_L2_PAYLOAD;
+ else if (!strcmp(res->value, "port"))
+ rss_conf.rss_hf = ETH_RSS_PORT;
+ else if (!strcmp(res->value, "vxlan"))
+ rss_conf.rss_hf = ETH_RSS_VXLAN;
+ else if (!strcmp(res->value, "geneve"))
+ rss_conf.rss_hf = ETH_RSS_GENEVE;
+ else if (!strcmp(res->value, "nvgre"))
+ rss_conf.rss_hf = ETH_RSS_NVGRE;
+ else if (!strcmp(res->value, "none"))
+ rss_conf.rss_hf = 0;
+ else {
+ printf("Unknown parameter\n");
+ return;
+ }
+ rss_conf.rss_key = NULL;
+ for (i = 0; i < rte_eth_dev_count(); i++) {
+ diag = rte_eth_dev_rss_hash_update(i, &rss_conf);
+ if (diag < 0)
+ printf("Configuration of RSS hash at ethernet port %d "
+ "failed with error (%d): %s.\n",
+ i, -diag, strerror(-diag));
+ }
+}
+
+cmdline_parse_token_string_t cmd_config_rss_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss, port, "port");
+cmdline_parse_token_string_t cmd_config_rss_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss, keyword, "config");
+cmdline_parse_token_string_t cmd_config_rss_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss, all, "all");
+cmdline_parse_token_string_t cmd_config_rss_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss, name, "rss");
+cmdline_parse_token_string_t cmd_config_rss_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss, value,
+ "all#ip#tcp#udp#sctp#ether#port#vxlan#geneve#nvgre#none");
+
+cmdline_parse_inst_t cmd_config_rss = {
+ .f = cmd_config_rss_parsed,
+ .data = NULL,
+ .help_str = "port config all rss "
+ "all|ip|tcp|udp|sctp|ether|port|vxlan|geneve|nvgre|none",
+ .tokens = {
+ (void *)&cmd_config_rss_port,
+ (void *)&cmd_config_rss_keyword,
+ (void *)&cmd_config_rss_all,
+ (void *)&cmd_config_rss_name,
+ (void *)&cmd_config_rss_value,
+ NULL,
+ },
+};
+
+/* *** configure rss hash key *** */
+struct cmd_config_rss_hash_key {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t config;
+ uint8_t port_id;
+ cmdline_fixed_string_t rss_hash_key;
+ cmdline_fixed_string_t rss_type;
+ cmdline_fixed_string_t key;
+};
+
+static uint8_t
+hexa_digit_to_value(char hexa_digit)
+{
+ if ((hexa_digit >= '0') && (hexa_digit <= '9'))
+ return (uint8_t) (hexa_digit - '0');
+ if ((hexa_digit >= 'a') && (hexa_digit <= 'f'))
+ return (uint8_t) ((hexa_digit - 'a') + 10);
+ if ((hexa_digit >= 'A') && (hexa_digit <= 'F'))
+ return (uint8_t) ((hexa_digit - 'A') + 10);
+ /* Invalid hexa digit */
+ return 0xFF;
+}
+
+static uint8_t
+parse_and_check_key_hexa_digit(char *key, int idx)
+{
+ uint8_t hexa_v;
+
+ hexa_v = hexa_digit_to_value(key[idx]);
+ if (hexa_v == 0xFF)
+ printf("invalid key: character %c at position %d is not a "
+ "valid hexa digit\n", key[idx], idx);
+ return hexa_v;
+}
+
+static void
+cmd_config_rss_hash_key_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_config_rss_hash_key *res = parsed_result;
+ uint8_t hash_key[RSS_HASH_KEY_LENGTH];
+ uint8_t xdgt0;
+ uint8_t xdgt1;
+ int i;
+ struct rte_eth_dev_info dev_info;
+ uint8_t hash_key_size;
+ uint32_t key_len;
+
+ memset(&dev_info, 0, sizeof(dev_info));
+ rte_eth_dev_info_get(res->port_id, &dev_info);
+ if (dev_info.hash_key_size > 0 &&
+ dev_info.hash_key_size <= sizeof(hash_key))
+ hash_key_size = dev_info.hash_key_size;
+ else {
+ printf("dev_info did not provide a valid hash key size\n");
+ return;
+ }
+ /* Check the length of the RSS hash key */
+ key_len = strlen(res->key);
+ if (key_len != (hash_key_size * 2)) {
+ printf("key length: %d invalid - key must be a string of %d"
+ " hexa-decimal numbers\n",
+ (int) key_len, hash_key_size * 2);
+ return;
+ }
+ /* Translate RSS hash key into binary representation */
+ for (i = 0; i < hash_key_size; i++) {
+ xdgt0 = parse_and_check_key_hexa_digit(res->key, (i * 2));
+ if (xdgt0 == 0xFF)
+ return;
+ xdgt1 = parse_and_check_key_hexa_digit(res->key, (i * 2) + 1);
+ if (xdgt1 == 0xFF)
+ return;
+ hash_key[i] = (uint8_t) ((xdgt0 * 16) + xdgt1);
+ }
+ port_rss_hash_key_update(res->port_id, res->rss_type, hash_key,
+ hash_key_size);
+}
+
+cmdline_parse_token_string_t cmd_config_rss_hash_key_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss_hash_key, port, "port");
+cmdline_parse_token_string_t cmd_config_rss_hash_key_config =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss_hash_key, config,
+ "config");
+cmdline_parse_token_num_t cmd_config_rss_hash_key_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_rss_hash_key, port_id, UINT8);
+cmdline_parse_token_string_t cmd_config_rss_hash_key_rss_hash_key =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss_hash_key,
+ rss_hash_key, "rss-hash-key");
+cmdline_parse_token_string_t cmd_config_rss_hash_key_rss_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss_hash_key, rss_type,
+ "ipv4#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#"
+ "ipv4-other#ipv6#ipv6-frag#ipv6-tcp#ipv6-udp#"
+ "ipv6-sctp#ipv6-other#l2-payload#ipv6-ex#"
+ "ipv6-tcp-ex#ipv6-udp-ex");
+cmdline_parse_token_string_t cmd_config_rss_hash_key_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss_hash_key, key, NULL);
+
+cmdline_parse_inst_t cmd_config_rss_hash_key = {
+ .f = cmd_config_rss_hash_key_parsed,
+ .data = NULL,
+ .help_str = "port config <port_id> rss-hash-key "
+ "ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|"
+ "ipv6|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|"
+ "l2-payload|ipv6-ex|ipv6-tcp-ex|ipv6-udp-ex "
+ "<string of hex digits (variable length, NIC dependent)>",
+ .tokens = {
+ (void *)&cmd_config_rss_hash_key_port,
+ (void *)&cmd_config_rss_hash_key_config,
+ (void *)&cmd_config_rss_hash_key_port_id,
+ (void *)&cmd_config_rss_hash_key_rss_hash_key,
+ (void *)&cmd_config_rss_hash_key_rss_type,
+ (void *)&cmd_config_rss_hash_key_value,
+ NULL,
+ },
+};
+
+/* *** configure port rxq/txq start/stop *** */
+struct cmd_config_rxtx_queue {
+ cmdline_fixed_string_t port;
+ uint8_t portid;
+ cmdline_fixed_string_t rxtxq;
+ uint16_t qid;
+ cmdline_fixed_string_t opname;
+};
+
+static void
+cmd_config_rxtx_queue_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_config_rxtx_queue *res = parsed_result;
+ uint8_t isrx;
+ uint8_t isstart;
+ int ret = 0;
+
+ if (test_done == 0) {
+ printf("Please stop forwarding first\n");
+ return;
+ }
+
+ if (port_id_is_invalid(res->portid, ENABLED_WARN))
+ return;
+
+ if (port_is_started(res->portid) != 1) {
+ printf("Please start port %u first\n", res->portid);
+ return;
+ }
+
+ if (!strcmp(res->rxtxq, "rxq"))
+ isrx = 1;
+ else if (!strcmp(res->rxtxq, "txq"))
+ isrx = 0;
+ else {
+ printf("Unknown parameter\n");
+ return;
+ }
+
+ if (isrx && rx_queue_id_is_invalid(res->qid))
+ return;
+ else if (!isrx && tx_queue_id_is_invalid(res->qid))
+ return;
+
+ if (!strcmp(res->opname, "start"))
+ isstart = 1;
+ else if (!strcmp(res->opname, "stop"))
+ isstart = 0;
+ else {
+ printf("Unknown parameter\n");
+ return;
+ }
+
+ if (isstart && isrx)
+ ret = rte_eth_dev_rx_queue_start(res->portid, res->qid);
+ else if (!isstart && isrx)
+ ret = rte_eth_dev_rx_queue_stop(res->portid, res->qid);
+ else if (isstart && !isrx)
+ ret = rte_eth_dev_tx_queue_start(res->portid, res->qid);
+ else
+ ret = rte_eth_dev_tx_queue_stop(res->portid, res->qid);
+
+ if (ret == -ENOTSUP)
+ printf("Function not supported in PMD driver\n");
+}
+
+cmdline_parse_token_string_t cmd_config_rxtx_queue_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rxtx_queue, port, "port");
+cmdline_parse_token_num_t cmd_config_rxtx_queue_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_rxtx_queue, portid, UINT8);
+cmdline_parse_token_string_t cmd_config_rxtx_queue_rxtxq =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rxtx_queue, rxtxq, "rxq#txq");
+cmdline_parse_token_num_t cmd_config_rxtx_queue_qid =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_rxtx_queue, qid, UINT16);
+cmdline_parse_token_string_t cmd_config_rxtx_queue_opname =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rxtx_queue, opname,
+ "start#stop");
+
+cmdline_parse_inst_t cmd_config_rxtx_queue = {
+ .f = cmd_config_rxtx_queue_parsed,
+ .data = NULL,
+ .help_str = "port <port_id> rxq|txq <queue_id> start|stop",
+ .tokens = {
+ (void *)&cmd_config_speed_all_port,
+ (void *)&cmd_config_rxtx_queue_portid,
+ (void *)&cmd_config_rxtx_queue_rxtxq,
+ (void *)&cmd_config_rxtx_queue_qid,
+ (void *)&cmd_config_rxtx_queue_opname,
+ NULL,
+ },
+};
+
+/* *** Configure RSS RETA *** */
+struct cmd_config_rss_reta {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ uint8_t port_id;
+ cmdline_fixed_string_t name;
+ cmdline_fixed_string_t list_name;
+ cmdline_fixed_string_t list_of_items;
+};
+
+static int
+parse_reta_config(const char *str,
+ struct rte_eth_rss_reta_entry64 *reta_conf,
+ uint16_t nb_entries)
+{
+ int i;
+ unsigned size;
+ uint16_t hash_index, idx, shift;
+ uint16_t nb_queue;
+ char s[256];
+ const char *p, *p0 = str;
+ char *end;
+ enum fieldnames {
+ FLD_HASH_INDEX = 0,
+ FLD_QUEUE,
+ _NUM_FLD
+ };
+ unsigned long int_fld[_NUM_FLD];
+ char *str_fld[_NUM_FLD];
+
+ while ((p = strchr(p0,'(')) != NULL) {
+ ++p;
+ if((p0 = strchr(p,')')) == NULL)
+ return -1;
+
+ size = p0 - p;
+ if(size >= sizeof(s))
+ return -1;
+
+ snprintf(s, sizeof(s), "%.*s", size, p);
+ if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != _NUM_FLD)
+ return -1;
+ for (i = 0; i < _NUM_FLD; i++) {
+ errno = 0;
+ int_fld[i] = strtoul(str_fld[i], &end, 0);
+ if (errno != 0 || end == str_fld[i] ||
+ int_fld[i] > 65535)
+ return -1;
+ }
+
+ hash_index = (uint16_t)int_fld[FLD_HASH_INDEX];
+ nb_queue = (uint16_t)int_fld[FLD_QUEUE];
+
+ if (hash_index >= nb_entries) {
+ printf("Invalid RETA hash index=%d\n", hash_index);
+ return -1;
+ }
+
+ idx = hash_index / RTE_RETA_GROUP_SIZE;
+ shift = hash_index % RTE_RETA_GROUP_SIZE;
+ reta_conf[idx].mask |= (1ULL << shift);
+ reta_conf[idx].reta[shift] = nb_queue;
+ }
+
+ return 0;
+}
+
+static void
+cmd_set_rss_reta_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ int ret;
+ struct rte_eth_dev_info dev_info;
+ struct rte_eth_rss_reta_entry64 reta_conf[8];
+ struct cmd_config_rss_reta *res = parsed_result;
+
+ memset(&dev_info, 0, sizeof(dev_info));
+ rte_eth_dev_info_get(res->port_id, &dev_info);
+ if (dev_info.reta_size == 0) {
+ printf("Redirection table size is 0 which is "
+ "invalid for RSS\n");
+ return;
+ } else
+ printf("The reta size of port %d is %u\n",
+ res->port_id, dev_info.reta_size);
+ if (dev_info.reta_size > ETH_RSS_RETA_SIZE_512) {
+ printf("Currently do not support more than %u entries of "
+ "redirection table\n", ETH_RSS_RETA_SIZE_512);
+ return;
+ }
+
+ memset(reta_conf, 0, sizeof(reta_conf));
+ if (!strcmp(res->list_name, "reta")) {
+ if (parse_reta_config(res->list_of_items, reta_conf,
+ dev_info.reta_size)) {
+ printf("Invalid RSS Redirection Table "
+ "config entered\n");
+ return;
+ }
+ ret = rte_eth_dev_rss_reta_update(res->port_id,
+ reta_conf, dev_info.reta_size);
+ if (ret != 0)
+ printf("Bad redirection table parameter, "
+ "return code = %d \n", ret);
+ }
+}
+
+cmdline_parse_token_string_t cmd_config_rss_reta_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss_reta, port, "port");
+cmdline_parse_token_string_t cmd_config_rss_reta_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss_reta, keyword, "config");
+cmdline_parse_token_num_t cmd_config_rss_reta_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_rss_reta, port_id, UINT8);
+cmdline_parse_token_string_t cmd_config_rss_reta_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss_reta, name, "rss");
+cmdline_parse_token_string_t cmd_config_rss_reta_list_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss_reta, list_name, "reta");
+cmdline_parse_token_string_t cmd_config_rss_reta_list_of_items =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss_reta, list_of_items,
+ NULL);
+cmdline_parse_inst_t cmd_config_rss_reta = {
+ .f = cmd_set_rss_reta_parsed,
+ .data = NULL,
+ .help_str = "port config <port_id> rss reta <hash,queue[,hash,queue]*>",
+ .tokens = {
+ (void *)&cmd_config_rss_reta_port,
+ (void *)&cmd_config_rss_reta_keyword,
+ (void *)&cmd_config_rss_reta_port_id,
+ (void *)&cmd_config_rss_reta_name,
+ (void *)&cmd_config_rss_reta_list_name,
+ (void *)&cmd_config_rss_reta_list_of_items,
+ NULL,
+ },
+};
+
+/* *** SHOW PORT RETA INFO *** */
+struct cmd_showport_reta {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t port;
+ uint8_t port_id;
+ cmdline_fixed_string_t rss;
+ cmdline_fixed_string_t reta;
+ uint16_t size;
+ cmdline_fixed_string_t list_of_items;
+};
+
+static int
+showport_parse_reta_config(struct rte_eth_rss_reta_entry64 *conf,
+ uint16_t nb_entries,
+ char *str)
+{
+ uint32_t size;
+ const char *p, *p0 = str;
+ char s[256];
+ char *end;
+ char *str_fld[8];
+ uint16_t i;
+ uint16_t num = (nb_entries + RTE_RETA_GROUP_SIZE - 1) /
+ RTE_RETA_GROUP_SIZE;
+ int ret;
+
+ p = strchr(p0, '(');
+ if (p == NULL)
+ return -1;
+ p++;
+ p0 = strchr(p, ')');
+ if (p0 == NULL)
+ return -1;
+ size = p0 - p;
+ if (size >= sizeof(s)) {
+ printf("The string size exceeds the internal buffer size\n");
+ return -1;
+ }
+ snprintf(s, sizeof(s), "%.*s", size, p);
+ ret = rte_strsplit(s, sizeof(s), str_fld, num, ',');
+ if (ret <= 0 || ret != num) {
+ printf("The bits of masks do not match the number of "
+ "reta entries: %u\n", num);
+ return -1;
+ }
+ for (i = 0; i < ret; i++)
+ conf[i].mask = (uint64_t)strtoul(str_fld[i], &end, 0);
+
+ return 0;
+}
+
+static void
+cmd_showport_reta_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_showport_reta *res = parsed_result;
+ struct rte_eth_rss_reta_entry64 reta_conf[8];
+ struct rte_eth_dev_info dev_info;
+
+ memset(&dev_info, 0, sizeof(dev_info));
+ rte_eth_dev_info_get(res->port_id, &dev_info);
+ if (dev_info.reta_size == 0 || res->size != dev_info.reta_size ||
+ res->size > ETH_RSS_RETA_SIZE_512) {
+ printf("Invalid redirection table size: %u\n", res->size);
+ return;
+ }
+
+ memset(reta_conf, 0, sizeof(reta_conf));
+ if (showport_parse_reta_config(reta_conf, res->size,
+ res->list_of_items) < 0) {
+ printf("Invalid string: %s for reta masks\n",
+ res->list_of_items);
+ return;
+ }
+ port_rss_reta_info(res->port_id, reta_conf, res->size);
+}
+
+cmdline_parse_token_string_t cmd_showport_reta_show =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_reta, show, "show");
+cmdline_parse_token_string_t cmd_showport_reta_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_reta, port, "port");
+cmdline_parse_token_num_t cmd_showport_reta_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_showport_reta, port_id, UINT8);
+cmdline_parse_token_string_t cmd_showport_reta_rss =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_reta, rss, "rss");
+cmdline_parse_token_string_t cmd_showport_reta_reta =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_reta, reta, "reta");
+cmdline_parse_token_num_t cmd_showport_reta_size =
+ TOKEN_NUM_INITIALIZER(struct cmd_showport_reta, size, UINT16);
+cmdline_parse_token_string_t cmd_showport_reta_list_of_items =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_reta,
+ list_of_items, NULL);
+
+cmdline_parse_inst_t cmd_showport_reta = {
+ .f = cmd_showport_reta_parsed,
+ .data = NULL,
+ .help_str = "show port <port_id> rss reta <size> <mask0[,mask1]*>",
+ .tokens = {
+ (void *)&cmd_showport_reta_show,
+ (void *)&cmd_showport_reta_port,
+ (void *)&cmd_showport_reta_port_id,
+ (void *)&cmd_showport_reta_rss,
+ (void *)&cmd_showport_reta_reta,
+ (void *)&cmd_showport_reta_size,
+ (void *)&cmd_showport_reta_list_of_items,
+ NULL,
+ },
+};
+
+/* *** Show RSS hash configuration *** */
+struct cmd_showport_rss_hash {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t port;
+ uint8_t port_id;
+ cmdline_fixed_string_t rss_hash;
+ cmdline_fixed_string_t rss_type;
+ cmdline_fixed_string_t key; /* optional argument */
+};
+
+static void cmd_showport_rss_hash_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ void *show_rss_key)
+{
+ struct cmd_showport_rss_hash *res = parsed_result;
+
+ port_rss_hash_conf_show(res->port_id, res->rss_type,
+ show_rss_key != NULL);
+}
+
+cmdline_parse_token_string_t cmd_showport_rss_hash_show =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_rss_hash, show, "show");
+cmdline_parse_token_string_t cmd_showport_rss_hash_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_rss_hash, port, "port");
+cmdline_parse_token_num_t cmd_showport_rss_hash_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_showport_rss_hash, port_id, UINT8);
+cmdline_parse_token_string_t cmd_showport_rss_hash_rss_hash =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_rss_hash, rss_hash,
+ "rss-hash");
+cmdline_parse_token_string_t cmd_showport_rss_hash_rss_hash_info =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_rss_hash, rss_type,
+ "ipv4#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#"
+ "ipv4-other#ipv6#ipv6-frag#ipv6-tcp#ipv6-udp#"
+ "ipv6-sctp#ipv6-other#l2-payload#ipv6-ex#"
+ "ipv6-tcp-ex#ipv6-udp-ex");
+cmdline_parse_token_string_t cmd_showport_rss_hash_rss_key =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_rss_hash, key, "key");
+
+cmdline_parse_inst_t cmd_showport_rss_hash = {
+ .f = cmd_showport_rss_hash_parsed,
+ .data = NULL,
+ .help_str = "show port <port_id> rss-hash "
+ "ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|"
+ "ipv6|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|"
+ "l2-payload|ipv6-ex|ipv6-tcp-ex|ipv6-udp-ex",
+ .tokens = {
+ (void *)&cmd_showport_rss_hash_show,
+ (void *)&cmd_showport_rss_hash_port,
+ (void *)&cmd_showport_rss_hash_port_id,
+ (void *)&cmd_showport_rss_hash_rss_hash,
+ (void *)&cmd_showport_rss_hash_rss_hash_info,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_showport_rss_hash_key = {
+ .f = cmd_showport_rss_hash_parsed,
+ .data = (void *)1,
+ .help_str = "show port <port_id> rss-hash "
+ "ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|"
+ "ipv6|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|"
+ "l2-payload|ipv6-ex|ipv6-tcp-ex|ipv6-udp-ex key",
+ .tokens = {
+ (void *)&cmd_showport_rss_hash_show,
+ (void *)&cmd_showport_rss_hash_port,
+ (void *)&cmd_showport_rss_hash_port_id,
+ (void *)&cmd_showport_rss_hash_rss_hash,
+ (void *)&cmd_showport_rss_hash_rss_hash_info,
+ (void *)&cmd_showport_rss_hash_rss_key,
+ NULL,
+ },
+};
+
+/* *** Configure DCB *** */
+struct cmd_config_dcb {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t config;
+ uint8_t port_id;
+ cmdline_fixed_string_t dcb;
+ cmdline_fixed_string_t vt;
+ cmdline_fixed_string_t vt_en;
+ uint8_t num_tcs;
+ cmdline_fixed_string_t pfc;
+ cmdline_fixed_string_t pfc_en;
+};
+
+static void
+cmd_config_dcb_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_config_dcb *res = parsed_result;
+ portid_t port_id = res->port_id;
+ struct rte_port *port;
+ uint8_t pfc_en;
+ int ret;
+
+ port = &ports[port_id];
+ /** Check if the port is not started **/
+ if (port->port_status != RTE_PORT_STOPPED) {
+ printf("Please stop port %d first\n", port_id);
+ return;
+ }
+
+ if ((res->num_tcs != ETH_4_TCS) && (res->num_tcs != ETH_8_TCS)) {
+ printf("The invalid number of traffic class,"
+ " only 4 or 8 allowed.\n");
+ return;
+ }
+
+ if (nb_fwd_lcores < res->num_tcs) {
+ printf("nb_cores shouldn't be less than number of TCs.\n");
+ return;
+ }
+ if (!strncmp(res->pfc_en, "on", 2))
+ pfc_en = 1;
+ else
+ pfc_en = 0;
+
+ /* DCB in VT mode */
+ if (!strncmp(res->vt_en, "on", 2))
+ ret = init_port_dcb_config(port_id, DCB_VT_ENABLED,
+ (enum rte_eth_nb_tcs)res->num_tcs,
+ pfc_en);
+ else
+ ret = init_port_dcb_config(port_id, DCB_ENABLED,
+ (enum rte_eth_nb_tcs)res->num_tcs,
+ pfc_en);
+
+
+ if (ret != 0) {
+ printf("Cannot initialize network ports.\n");
+ return;
+ }
+
+ cmd_reconfig_device_queue(port_id, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_config_dcb_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_dcb, port, "port");
+cmdline_parse_token_string_t cmd_config_dcb_config =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_dcb, config, "config");
+cmdline_parse_token_num_t cmd_config_dcb_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_dcb, port_id, UINT8);
+cmdline_parse_token_string_t cmd_config_dcb_dcb =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_dcb, dcb, "dcb");
+cmdline_parse_token_string_t cmd_config_dcb_vt =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_dcb, vt, "vt");
+cmdline_parse_token_string_t cmd_config_dcb_vt_en =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_dcb, vt_en, "on#off");
+cmdline_parse_token_num_t cmd_config_dcb_num_tcs =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_dcb, num_tcs, UINT8);
+cmdline_parse_token_string_t cmd_config_dcb_pfc=
+ TOKEN_STRING_INITIALIZER(struct cmd_config_dcb, pfc, "pfc");
+cmdline_parse_token_string_t cmd_config_dcb_pfc_en =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_dcb, pfc_en, "on#off");
+
+cmdline_parse_inst_t cmd_config_dcb = {
+ .f = cmd_config_dcb_parsed,
+ .data = NULL,
+ .help_str = "port config <port-id> dcb vt on|off <num_tcs> pfc on|off",
+ .tokens = {
+ (void *)&cmd_config_dcb_port,
+ (void *)&cmd_config_dcb_config,
+ (void *)&cmd_config_dcb_port_id,
+ (void *)&cmd_config_dcb_dcb,
+ (void *)&cmd_config_dcb_vt,
+ (void *)&cmd_config_dcb_vt_en,
+ (void *)&cmd_config_dcb_num_tcs,
+ (void *)&cmd_config_dcb_pfc,
+ (void *)&cmd_config_dcb_pfc_en,
+ NULL,
+ },
+};
+
+/* *** configure number of packets per burst *** */
+struct cmd_config_burst {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ cmdline_fixed_string_t all;
+ cmdline_fixed_string_t name;
+ uint16_t value;
+};
+
+static void
+cmd_config_burst_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_config_burst *res = parsed_result;
+
+ if (!all_ports_stopped()) {
+ printf("Please stop all ports first\n");
+ return;
+ }
+
+ if (!strcmp(res->name, "burst")) {
+ if (res->value < 1 || res->value > MAX_PKT_BURST) {
+ printf("burst must be >= 1 && <= %d\n", MAX_PKT_BURST);
+ return;
+ }
+ nb_pkt_per_burst = res->value;
+ } else {
+ printf("Unknown parameter\n");
+ return;
+ }
+
+ init_port_config();
+
+ cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_config_burst_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_burst, port, "port");
+cmdline_parse_token_string_t cmd_config_burst_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_burst, keyword, "config");
+cmdline_parse_token_string_t cmd_config_burst_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_burst, all, "all");
+cmdline_parse_token_string_t cmd_config_burst_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_burst, name, "burst");
+cmdline_parse_token_num_t cmd_config_burst_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_burst, value, UINT16);
+
+cmdline_parse_inst_t cmd_config_burst = {
+ .f = cmd_config_burst_parsed,
+ .data = NULL,
+ .help_str = "port config all burst <value>",
+ .tokens = {
+ (void *)&cmd_config_burst_port,
+ (void *)&cmd_config_burst_keyword,
+ (void *)&cmd_config_burst_all,
+ (void *)&cmd_config_burst_name,
+ (void *)&cmd_config_burst_value,
+ NULL,
+ },
+};
+
+/* *** configure rx/tx queues *** */
+struct cmd_config_thresh {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ cmdline_fixed_string_t all;
+ cmdline_fixed_string_t name;
+ uint8_t value;
+};
+
+static void
+cmd_config_thresh_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_config_thresh *res = parsed_result;
+
+ if (!all_ports_stopped()) {
+ printf("Please stop all ports first\n");
+ return;
+ }
+
+ if (!strcmp(res->name, "txpt"))
+ tx_pthresh = res->value;
+ else if(!strcmp(res->name, "txht"))
+ tx_hthresh = res->value;
+ else if(!strcmp(res->name, "txwt"))
+ tx_wthresh = res->value;
+ else if(!strcmp(res->name, "rxpt"))
+ rx_pthresh = res->value;
+ else if(!strcmp(res->name, "rxht"))
+ rx_hthresh = res->value;
+ else if(!strcmp(res->name, "rxwt"))
+ rx_wthresh = res->value;
+ else {
+ printf("Unknown parameter\n");
+ return;
+ }
+
+ init_port_config();
+
+ cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_config_thresh_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_thresh, port, "port");
+cmdline_parse_token_string_t cmd_config_thresh_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_thresh, keyword, "config");
+cmdline_parse_token_string_t cmd_config_thresh_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_thresh, all, "all");
+cmdline_parse_token_string_t cmd_config_thresh_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_thresh, name,
+ "txpt#txht#txwt#rxpt#rxht#rxwt");
+cmdline_parse_token_num_t cmd_config_thresh_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_thresh, value, UINT8);
+
+cmdline_parse_inst_t cmd_config_thresh = {
+ .f = cmd_config_thresh_parsed,
+ .data = NULL,
+ .help_str = "port config all txpt|txht|txwt|rxpt|rxht|rxwt <value>",
+ .tokens = {
+ (void *)&cmd_config_thresh_port,
+ (void *)&cmd_config_thresh_keyword,
+ (void *)&cmd_config_thresh_all,
+ (void *)&cmd_config_thresh_name,
+ (void *)&cmd_config_thresh_value,
+ NULL,
+ },
+};
+
+/* *** configure free/rs threshold *** */
+struct cmd_config_threshold {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ cmdline_fixed_string_t all;
+ cmdline_fixed_string_t name;
+ uint16_t value;
+};
+
+static void
+cmd_config_threshold_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_config_threshold *res = parsed_result;
+
+ if (!all_ports_stopped()) {
+ printf("Please stop all ports first\n");
+ return;
+ }
+
+ if (!strcmp(res->name, "txfreet"))
+ tx_free_thresh = res->value;
+ else if (!strcmp(res->name, "txrst"))
+ tx_rs_thresh = res->value;
+ else if (!strcmp(res->name, "rxfreet"))
+ rx_free_thresh = res->value;
+ else {
+ printf("Unknown parameter\n");
+ return;
+ }
+
+ init_port_config();
+
+ cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_config_threshold_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_threshold, port, "port");
+cmdline_parse_token_string_t cmd_config_threshold_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_threshold, keyword,
+ "config");
+cmdline_parse_token_string_t cmd_config_threshold_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_threshold, all, "all");
+cmdline_parse_token_string_t cmd_config_threshold_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_threshold, name,
+ "txfreet#txrst#rxfreet");
+cmdline_parse_token_num_t cmd_config_threshold_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_threshold, value, UINT16);
+
+cmdline_parse_inst_t cmd_config_threshold = {
+ .f = cmd_config_threshold_parsed,
+ .data = NULL,
+ .help_str = "port config all txfreet|txrst|rxfreet <value>",
+ .tokens = {
+ (void *)&cmd_config_threshold_port,
+ (void *)&cmd_config_threshold_keyword,
+ (void *)&cmd_config_threshold_all,
+ (void *)&cmd_config_threshold_name,
+ (void *)&cmd_config_threshold_value,
+ NULL,
+ },
+};
+
+/* *** stop *** */
+struct cmd_stop_result {
+ cmdline_fixed_string_t stop;
+};
+
+static void cmd_stop_parsed(__attribute__((unused)) void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ stop_packet_forwarding();
+}
+
+cmdline_parse_token_string_t cmd_stop_stop =
+ TOKEN_STRING_INITIALIZER(struct cmd_stop_result, stop, "stop");
+
+cmdline_parse_inst_t cmd_stop = {
+ .f = cmd_stop_parsed,
+ .data = NULL,
+ .help_str = "stop: Stop packet forwarding",
+ .tokens = {
+ (void *)&cmd_stop_stop,
+ NULL,
+ },
+};
+
+/* *** SET CORELIST and PORTLIST CONFIGURATION *** */
+
+unsigned int
+parse_item_list(char* str, const char* item_name, unsigned int max_items,
+ unsigned int *parsed_items, int check_unique_values)
+{
+ unsigned int nb_item;
+ unsigned int value;
+ unsigned int i;
+ unsigned int j;
+ int value_ok;
+ char c;
+
+ /*
+ * First parse all items in the list and store their value.
+ */
+ value = 0;
+ nb_item = 0;
+ value_ok = 0;
+ for (i = 0; i < strnlen(str, STR_TOKEN_SIZE); i++) {
+ c = str[i];
+ if ((c >= '0') && (c <= '9')) {
+ value = (unsigned int) (value * 10 + (c - '0'));
+ value_ok = 1;
+ continue;
+ }
+ if (c != ',') {
+ printf("character %c is not a decimal digit\n", c);
+ return 0;
+ }
+ if (! value_ok) {
+ printf("No valid value before comma\n");
+ return 0;
+ }
+ if (nb_item < max_items) {
+ parsed_items[nb_item] = value;
+ value_ok = 0;
+ value = 0;
+ }
+ nb_item++;
+ }
+ if (nb_item >= max_items) {
+ printf("Number of %s = %u > %u (maximum items)\n",
+ item_name, nb_item + 1, max_items);
+ return 0;
+ }
+ parsed_items[nb_item++] = value;
+ if (! check_unique_values)
+ return nb_item;
+
+ /*
+ * Then, check that all values in the list are differents.
+ * No optimization here...
+ */
+ for (i = 0; i < nb_item; i++) {
+ for (j = i + 1; j < nb_item; j++) {
+ if (parsed_items[j] == parsed_items[i]) {
+ printf("duplicated %s %u at index %u and %u\n",
+ item_name, parsed_items[i], i, j);
+ return 0;
+ }
+ }
+ }
+ return nb_item;
+}
+
+struct cmd_set_list_result {
+ cmdline_fixed_string_t cmd_keyword;
+ cmdline_fixed_string_t list_name;
+ cmdline_fixed_string_t list_of_items;
+};
+
+static void cmd_set_list_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_list_result *res;
+ union {
+ unsigned int lcorelist[RTE_MAX_LCORE];
+ unsigned int portlist[RTE_MAX_ETHPORTS];
+ } parsed_items;
+ unsigned int nb_item;
+
+ if (test_done == 0) {
+ printf("Please stop forwarding first\n");
+ return;
+ }
+
+ res = parsed_result;
+ if (!strcmp(res->list_name, "corelist")) {
+ nb_item = parse_item_list(res->list_of_items, "core",
+ RTE_MAX_LCORE,
+ parsed_items.lcorelist, 1);
+ if (nb_item > 0) {
+ set_fwd_lcores_list(parsed_items.lcorelist, nb_item);
+ fwd_config_setup();
+ }
+ return;
+ }
+ if (!strcmp(res->list_name, "portlist")) {
+ nb_item = parse_item_list(res->list_of_items, "port",
+ RTE_MAX_ETHPORTS,
+ parsed_items.portlist, 1);
+ if (nb_item > 0) {
+ set_fwd_ports_list(parsed_items.portlist, nb_item);
+ fwd_config_setup();
+ }
+ }
+}
+
+cmdline_parse_token_string_t cmd_set_list_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_list_result, cmd_keyword,
+ "set");
+cmdline_parse_token_string_t cmd_set_list_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_list_result, list_name,
+ "corelist#portlist");
+cmdline_parse_token_string_t cmd_set_list_of_items =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_list_result, list_of_items,
+ NULL);
+
+cmdline_parse_inst_t cmd_set_fwd_list = {
+ .f = cmd_set_list_parsed,
+ .data = NULL,
+ .help_str = "set corelist|portlist <list0[,list1]*>",
+ .tokens = {
+ (void *)&cmd_set_list_keyword,
+ (void *)&cmd_set_list_name,
+ (void *)&cmd_set_list_of_items,
+ NULL,
+ },
+};
+
+/* *** SET COREMASK and PORTMASK CONFIGURATION *** */
+
+struct cmd_setmask_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t mask;
+ uint64_t hexavalue;
+};
+
+static void cmd_set_mask_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_setmask_result *res = parsed_result;
+
+ if (test_done == 0) {
+ printf("Please stop forwarding first\n");
+ return;
+ }
+ if (!strcmp(res->mask, "coremask")) {
+ set_fwd_lcores_mask(res->hexavalue);
+ fwd_config_setup();
+ } else if (!strcmp(res->mask, "portmask")) {
+ set_fwd_ports_mask(res->hexavalue);
+ fwd_config_setup();
+ }
+}
+
+cmdline_parse_token_string_t cmd_setmask_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_setmask_result, set, "set");
+cmdline_parse_token_string_t cmd_setmask_mask =
+ TOKEN_STRING_INITIALIZER(struct cmd_setmask_result, mask,
+ "coremask#portmask");
+cmdline_parse_token_num_t cmd_setmask_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_setmask_result, hexavalue, UINT64);
+
+cmdline_parse_inst_t cmd_set_fwd_mask = {
+ .f = cmd_set_mask_parsed,
+ .data = NULL,
+ .help_str = "set coremask|portmask <hexadecimal value>",
+ .tokens = {
+ (void *)&cmd_setmask_set,
+ (void *)&cmd_setmask_mask,
+ (void *)&cmd_setmask_value,
+ NULL,
+ },
+};
+
+/*
+ * SET NBPORT, NBCORE, PACKET BURST, and VERBOSE LEVEL CONFIGURATION
+ */
+struct cmd_set_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t what;
+ uint16_t value;
+};
+
+static void cmd_set_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_result *res = parsed_result;
+ if (!strcmp(res->what, "nbport")) {
+ set_fwd_ports_number(res->value);
+ fwd_config_setup();
+ } else if (!strcmp(res->what, "nbcore")) {
+ set_fwd_lcores_number(res->value);
+ fwd_config_setup();
+ } else if (!strcmp(res->what, "burst"))
+ set_nb_pkt_per_burst(res->value);
+ else if (!strcmp(res->what, "verbose"))
+ set_verbose_level(res->value);
+}
+
+cmdline_parse_token_string_t cmd_set_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_result, set, "set");
+cmdline_parse_token_string_t cmd_set_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_result, what,
+ "nbport#nbcore#burst#verbose");
+cmdline_parse_token_num_t cmd_set_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_result, value, UINT16);
+
+cmdline_parse_inst_t cmd_set_numbers = {
+ .f = cmd_set_parsed,
+ .data = NULL,
+ .help_str = "set nbport|nbcore|burst|verbose <value>",
+ .tokens = {
+ (void *)&cmd_set_set,
+ (void *)&cmd_set_what,
+ (void *)&cmd_set_value,
+ NULL,
+ },
+};
+
+/* *** SET SEGMENT LENGTHS OF TXONLY PACKETS *** */
+
+struct cmd_set_txpkts_result {
+ cmdline_fixed_string_t cmd_keyword;
+ cmdline_fixed_string_t txpkts;
+ cmdline_fixed_string_t seg_lengths;
+};
+
+static void
+cmd_set_txpkts_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_txpkts_result *res;
+ unsigned seg_lengths[RTE_MAX_SEGS_PER_PKT];
+ unsigned int nb_segs;
+
+ res = parsed_result;
+ nb_segs = parse_item_list(res->seg_lengths, "segment lengths",
+ RTE_MAX_SEGS_PER_PKT, seg_lengths, 0);
+ if (nb_segs > 0)
+ set_tx_pkt_segments(seg_lengths, nb_segs);
+}
+
+cmdline_parse_token_string_t cmd_set_txpkts_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_txpkts_result,
+ cmd_keyword, "set");
+cmdline_parse_token_string_t cmd_set_txpkts_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_txpkts_result,
+ txpkts, "txpkts");
+cmdline_parse_token_string_t cmd_set_txpkts_lengths =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_txpkts_result,
+ seg_lengths, NULL);
+
+cmdline_parse_inst_t cmd_set_txpkts = {
+ .f = cmd_set_txpkts_parsed,
+ .data = NULL,
+ .help_str = "set txpkts <len0[,len1]*>",
+ .tokens = {
+ (void *)&cmd_set_txpkts_keyword,
+ (void *)&cmd_set_txpkts_name,
+ (void *)&cmd_set_txpkts_lengths,
+ NULL,
+ },
+};
+
+/* *** SET COPY AND SPLIT POLICY ON TX PACKETS *** */
+
+struct cmd_set_txsplit_result {
+ cmdline_fixed_string_t cmd_keyword;
+ cmdline_fixed_string_t txsplit;
+ cmdline_fixed_string_t mode;
+};
+
+static void
+cmd_set_txsplit_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_txsplit_result *res;
+
+ res = parsed_result;
+ set_tx_pkt_split(res->mode);
+}
+
+cmdline_parse_token_string_t cmd_set_txsplit_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_txsplit_result,
+ cmd_keyword, "set");
+cmdline_parse_token_string_t cmd_set_txsplit_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_txsplit_result,
+ txsplit, "txsplit");
+cmdline_parse_token_string_t cmd_set_txsplit_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_txsplit_result,
+ mode, NULL);
+
+cmdline_parse_inst_t cmd_set_txsplit = {
+ .f = cmd_set_txsplit_parsed,
+ .data = NULL,
+ .help_str = "set txsplit on|off|rand",
+ .tokens = {
+ (void *)&cmd_set_txsplit_keyword,
+ (void *)&cmd_set_txsplit_name,
+ (void *)&cmd_set_txsplit_mode,
+ NULL,
+ },
+};
+
+/* *** CONFIG TX QUEUE FLAGS *** */
+
+struct cmd_config_txqflags_result {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t config;
+ cmdline_fixed_string_t all;
+ cmdline_fixed_string_t what;
+ int32_t hexvalue;
+};
+
+static void cmd_config_txqflags_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_config_txqflags_result *res = parsed_result;
+
+ if (!all_ports_stopped()) {
+ printf("Please stop all ports first\n");
+ return;
+ }
+
+ if (strcmp(res->what, "txqflags")) {
+ printf("Unknown parameter\n");
+ return;
+ }
+
+ if (res->hexvalue >= 0) {
+ txq_flags = res->hexvalue;
+ } else {
+ printf("txqflags must be >= 0\n");
+ return;
+ }
+
+ init_port_config();
+
+ cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_config_txqflags_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_txqflags_result, port,
+ "port");
+cmdline_parse_token_string_t cmd_config_txqflags_config =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_txqflags_result, config,
+ "config");
+cmdline_parse_token_string_t cmd_config_txqflags_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_txqflags_result, all,
+ "all");
+cmdline_parse_token_string_t cmd_config_txqflags_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_txqflags_result, what,
+ "txqflags");
+cmdline_parse_token_num_t cmd_config_txqflags_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_txqflags_result,
+ hexvalue, INT32);
+
+cmdline_parse_inst_t cmd_config_txqflags = {
+ .f = cmd_config_txqflags_parsed,
+ .data = NULL,
+ .help_str = "port config all txqflags <value>",
+ .tokens = {
+ (void *)&cmd_config_txqflags_port,
+ (void *)&cmd_config_txqflags_config,
+ (void *)&cmd_config_txqflags_all,
+ (void *)&cmd_config_txqflags_what,
+ (void *)&cmd_config_txqflags_value,
+ NULL,
+ },
+};
+
+/* *** ADD/REMOVE ALL VLAN IDENTIFIERS TO/FROM A PORT VLAN RX FILTER *** */
+struct cmd_rx_vlan_filter_all_result {
+ cmdline_fixed_string_t rx_vlan;
+ cmdline_fixed_string_t what;
+ cmdline_fixed_string_t all;
+ uint8_t port_id;
+};
+
+static void
+cmd_rx_vlan_filter_all_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_rx_vlan_filter_all_result *res = parsed_result;
+
+ if (!strcmp(res->what, "add"))
+ rx_vlan_all_filter_set(res->port_id, 1);
+ else
+ rx_vlan_all_filter_set(res->port_id, 0);
+}
+
+cmdline_parse_token_string_t cmd_rx_vlan_filter_all_rx_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_rx_vlan_filter_all_result,
+ rx_vlan, "rx_vlan");
+cmdline_parse_token_string_t cmd_rx_vlan_filter_all_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_rx_vlan_filter_all_result,
+ what, "add#rm");
+cmdline_parse_token_string_t cmd_rx_vlan_filter_all_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_rx_vlan_filter_all_result,
+ all, "all");
+cmdline_parse_token_num_t cmd_rx_vlan_filter_all_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_rx_vlan_filter_all_result,
+ port_id, UINT8);
+
+cmdline_parse_inst_t cmd_rx_vlan_filter_all = {
+ .f = cmd_rx_vlan_filter_all_parsed,
+ .data = NULL,
+ .help_str = "rx_vlan add|rm all <port_id>: "
+ "Add/Remove all identifiers to/from the set of VLAN "
+ "identifiers filtered by a port",
+ .tokens = {
+ (void *)&cmd_rx_vlan_filter_all_rx_vlan,
+ (void *)&cmd_rx_vlan_filter_all_what,
+ (void *)&cmd_rx_vlan_filter_all_all,
+ (void *)&cmd_rx_vlan_filter_all_portid,
+ NULL,
+ },
+};
+
+/* *** VLAN OFFLOAD SET ON A PORT *** */
+struct cmd_vlan_offload_result {
+ cmdline_fixed_string_t vlan;
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vlan_type;
+ cmdline_fixed_string_t what;
+ cmdline_fixed_string_t on;
+ cmdline_fixed_string_t port_id;
+};
+
+static void
+cmd_vlan_offload_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ int on;
+ struct cmd_vlan_offload_result *res = parsed_result;
+ char *str;
+ int i, len = 0;
+ portid_t port_id = 0;
+ unsigned int tmp;
+
+ str = res->port_id;
+ len = strnlen(str, STR_TOKEN_SIZE);
+ i = 0;
+ /* Get port_id first */
+ while(i < len){
+ if(str[i] == ',')
+ break;
+
+ i++;
+ }
+ str[i]='\0';
+ tmp = strtoul(str, NULL, 0);
+ /* If port_id greater that what portid_t can represent, return */
+ if(tmp >= RTE_MAX_ETHPORTS)
+ return;
+ port_id = (portid_t)tmp;
+
+ if (!strcmp(res->on, "on"))
+ on = 1;
+ else
+ on = 0;
+
+ if (!strcmp(res->what, "strip"))
+ rx_vlan_strip_set(port_id, on);
+ else if(!strcmp(res->what, "stripq")){
+ uint16_t queue_id = 0;
+
+ /* No queue_id, return */
+ if(i + 1 >= len) {
+ printf("must specify (port,queue_id)\n");
+ return;
+ }
+ tmp = strtoul(str + i + 1, NULL, 0);
+ /* If queue_id greater that what 16-bits can represent, return */
+ if(tmp > 0xffff)
+ return;
+
+ queue_id = (uint16_t)tmp;
+ rx_vlan_strip_set_on_queue(port_id, queue_id, on);
+ }
+ else if (!strcmp(res->what, "filter"))
+ rx_vlan_filter_set(port_id, on);
+ else
+ vlan_extend_set(port_id, on);
+
+ return;
+}
+
+cmdline_parse_token_string_t cmd_vlan_offload_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_vlan_offload_result,
+ vlan, "vlan");
+cmdline_parse_token_string_t cmd_vlan_offload_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_vlan_offload_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_vlan_offload_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_vlan_offload_result,
+ what, "strip#filter#qinq#stripq");
+cmdline_parse_token_string_t cmd_vlan_offload_on =
+ TOKEN_STRING_INITIALIZER(struct cmd_vlan_offload_result,
+ on, "on#off");
+cmdline_parse_token_string_t cmd_vlan_offload_portid =
+ TOKEN_STRING_INITIALIZER(struct cmd_vlan_offload_result,
+ port_id, NULL);
+
+cmdline_parse_inst_t cmd_vlan_offload = {
+ .f = cmd_vlan_offload_parsed,
+ .data = NULL,
+ .help_str = "vlan set strip|filter|qinq|stripq on|off "
+ "<port_id[,queue_id]>: "
+ "Filter/Strip for rx side qinq(extended) for both rx/tx sides",
+ .tokens = {
+ (void *)&cmd_vlan_offload_vlan,
+ (void *)&cmd_vlan_offload_set,
+ (void *)&cmd_vlan_offload_what,
+ (void *)&cmd_vlan_offload_on,
+ (void *)&cmd_vlan_offload_portid,
+ NULL,
+ },
+};
+
+/* *** VLAN TPID SET ON A PORT *** */
+struct cmd_vlan_tpid_result {
+ cmdline_fixed_string_t vlan;
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vlan_type;
+ cmdline_fixed_string_t what;
+ uint16_t tp_id;
+ uint8_t port_id;
+};
+
+static void
+cmd_vlan_tpid_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_vlan_tpid_result *res = parsed_result;
+ enum rte_vlan_type vlan_type;
+
+ if (!strcmp(res->vlan_type, "inner"))
+ vlan_type = ETH_VLAN_TYPE_INNER;
+ else if (!strcmp(res->vlan_type, "outer"))
+ vlan_type = ETH_VLAN_TYPE_OUTER;
+ else {
+ printf("Unknown vlan type\n");
+ return;
+ }
+ vlan_tpid_set(res->port_id, vlan_type, res->tp_id);
+}
+
+cmdline_parse_token_string_t cmd_vlan_tpid_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_vlan_tpid_result,
+ vlan, "vlan");
+cmdline_parse_token_string_t cmd_vlan_tpid_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_vlan_tpid_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_vlan_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_vlan_tpid_result,
+ vlan_type, "inner#outer");
+cmdline_parse_token_string_t cmd_vlan_tpid_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_vlan_tpid_result,
+ what, "tpid");
+cmdline_parse_token_num_t cmd_vlan_tpid_tpid =
+ TOKEN_NUM_INITIALIZER(struct cmd_vlan_tpid_result,
+ tp_id, UINT16);
+cmdline_parse_token_num_t cmd_vlan_tpid_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_vlan_tpid_result,
+ port_id, UINT8);
+
+cmdline_parse_inst_t cmd_vlan_tpid = {
+ .f = cmd_vlan_tpid_parsed,
+ .data = NULL,
+ .help_str = "vlan set inner|outer tpid <tp_id> <port_id>: "
+ "Set the VLAN Ether type",
+ .tokens = {
+ (void *)&cmd_vlan_tpid_vlan,
+ (void *)&cmd_vlan_tpid_set,
+ (void *)&cmd_vlan_type,
+ (void *)&cmd_vlan_tpid_what,
+ (void *)&cmd_vlan_tpid_tpid,
+ (void *)&cmd_vlan_tpid_portid,
+ NULL,
+ },
+};
+
+/* *** ADD/REMOVE A VLAN IDENTIFIER TO/FROM A PORT VLAN RX FILTER *** */
+struct cmd_rx_vlan_filter_result {
+ cmdline_fixed_string_t rx_vlan;
+ cmdline_fixed_string_t what;
+ uint16_t vlan_id;
+ uint8_t port_id;
+};
+
+static void
+cmd_rx_vlan_filter_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_rx_vlan_filter_result *res = parsed_result;
+
+ if (!strcmp(res->what, "add"))
+ rx_vft_set(res->port_id, res->vlan_id, 1);
+ else
+ rx_vft_set(res->port_id, res->vlan_id, 0);
+}
+
+cmdline_parse_token_string_t cmd_rx_vlan_filter_rx_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_rx_vlan_filter_result,
+ rx_vlan, "rx_vlan");
+cmdline_parse_token_string_t cmd_rx_vlan_filter_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_rx_vlan_filter_result,
+ what, "add#rm");
+cmdline_parse_token_num_t cmd_rx_vlan_filter_vlanid =
+ TOKEN_NUM_INITIALIZER(struct cmd_rx_vlan_filter_result,
+ vlan_id, UINT16);
+cmdline_parse_token_num_t cmd_rx_vlan_filter_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_rx_vlan_filter_result,
+ port_id, UINT8);
+
+cmdline_parse_inst_t cmd_rx_vlan_filter = {
+ .f = cmd_rx_vlan_filter_parsed,
+ .data = NULL,
+ .help_str = "rx_vlan add|rm <vlan_id> <port_id>: "
+ "Add/Remove a VLAN identifier to/from the set of VLAN "
+ "identifiers filtered by a port",
+ .tokens = {
+ (void *)&cmd_rx_vlan_filter_rx_vlan,
+ (void *)&cmd_rx_vlan_filter_what,
+ (void *)&cmd_rx_vlan_filter_vlanid,
+ (void *)&cmd_rx_vlan_filter_portid,
+ NULL,
+ },
+};
+
+/* *** ENABLE HARDWARE INSERTION OF VLAN HEADER IN TX PACKETS *** */
+struct cmd_tx_vlan_set_result {
+ cmdline_fixed_string_t tx_vlan;
+ cmdline_fixed_string_t set;
+ uint8_t port_id;
+ uint16_t vlan_id;
+};
+
+static void
+cmd_tx_vlan_set_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_tx_vlan_set_result *res = parsed_result;
+
+ tx_vlan_set(res->port_id, res->vlan_id);
+}
+
+cmdline_parse_token_string_t cmd_tx_vlan_set_tx_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_set_result,
+ tx_vlan, "tx_vlan");
+cmdline_parse_token_string_t cmd_tx_vlan_set_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_set_result,
+ set, "set");
+cmdline_parse_token_num_t cmd_tx_vlan_set_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_tx_vlan_set_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_tx_vlan_set_vlanid =
+ TOKEN_NUM_INITIALIZER(struct cmd_tx_vlan_set_result,
+ vlan_id, UINT16);
+
+cmdline_parse_inst_t cmd_tx_vlan_set = {
+ .f = cmd_tx_vlan_set_parsed,
+ .data = NULL,
+ .help_str = "tx_vlan set <port_id> <vlan_id>: "
+ "Enable hardware insertion of a single VLAN header "
+ "with a given TAG Identifier in packets sent on a port",
+ .tokens = {
+ (void *)&cmd_tx_vlan_set_tx_vlan,
+ (void *)&cmd_tx_vlan_set_set,
+ (void *)&cmd_tx_vlan_set_portid,
+ (void *)&cmd_tx_vlan_set_vlanid,
+ NULL,
+ },
+};
+
+/* *** ENABLE HARDWARE INSERTION OF Double VLAN HEADER IN TX PACKETS *** */
+struct cmd_tx_vlan_set_qinq_result {
+ cmdline_fixed_string_t tx_vlan;
+ cmdline_fixed_string_t set;
+ uint8_t port_id;
+ uint16_t vlan_id;
+ uint16_t vlan_id_outer;
+};
+
+static void
+cmd_tx_vlan_set_qinq_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_tx_vlan_set_qinq_result *res = parsed_result;
+
+ tx_qinq_set(res->port_id, res->vlan_id, res->vlan_id_outer);
+}
+
+cmdline_parse_token_string_t cmd_tx_vlan_set_qinq_tx_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_set_qinq_result,
+ tx_vlan, "tx_vlan");
+cmdline_parse_token_string_t cmd_tx_vlan_set_qinq_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_set_qinq_result,
+ set, "set");
+cmdline_parse_token_num_t cmd_tx_vlan_set_qinq_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_tx_vlan_set_qinq_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_tx_vlan_set_qinq_vlanid =
+ TOKEN_NUM_INITIALIZER(struct cmd_tx_vlan_set_qinq_result,
+ vlan_id, UINT16);
+cmdline_parse_token_num_t cmd_tx_vlan_set_qinq_vlanid_outer =
+ TOKEN_NUM_INITIALIZER(struct cmd_tx_vlan_set_qinq_result,
+ vlan_id_outer, UINT16);
+
+cmdline_parse_inst_t cmd_tx_vlan_set_qinq = {
+ .f = cmd_tx_vlan_set_qinq_parsed,
+ .data = NULL,
+ .help_str = "tx_vlan set <port_id> <vlan_id> <outer_vlan_id>: "
+ "Enable hardware insertion of double VLAN header "
+ "with given TAG Identifiers in packets sent on a port",
+ .tokens = {
+ (void *)&cmd_tx_vlan_set_qinq_tx_vlan,
+ (void *)&cmd_tx_vlan_set_qinq_set,
+ (void *)&cmd_tx_vlan_set_qinq_portid,
+ (void *)&cmd_tx_vlan_set_qinq_vlanid,
+ (void *)&cmd_tx_vlan_set_qinq_vlanid_outer,
+ NULL,
+ },
+};
+
+/* *** ENABLE/DISABLE PORT BASED TX VLAN INSERTION *** */
+struct cmd_tx_vlan_set_pvid_result {
+ cmdline_fixed_string_t tx_vlan;
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t pvid;
+ uint8_t port_id;
+ uint16_t vlan_id;
+ cmdline_fixed_string_t mode;
+};
+
+static void
+cmd_tx_vlan_set_pvid_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_tx_vlan_set_pvid_result *res = parsed_result;
+
+ if (strcmp(res->mode, "on") == 0)
+ tx_vlan_pvid_set(res->port_id, res->vlan_id, 1);
+ else
+ tx_vlan_pvid_set(res->port_id, res->vlan_id, 0);
+}
+
+cmdline_parse_token_string_t cmd_tx_vlan_set_pvid_tx_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_set_pvid_result,
+ tx_vlan, "tx_vlan");
+cmdline_parse_token_string_t cmd_tx_vlan_set_pvid_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_set_pvid_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_tx_vlan_set_pvid_pvid =
+ TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_set_pvid_result,
+ pvid, "pvid");
+cmdline_parse_token_num_t cmd_tx_vlan_set_pvid_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_tx_vlan_set_pvid_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_tx_vlan_set_pvid_vlan_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_tx_vlan_set_pvid_result,
+ vlan_id, UINT16);
+cmdline_parse_token_string_t cmd_tx_vlan_set_pvid_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_set_pvid_result,
+ mode, "on#off");
+
+cmdline_parse_inst_t cmd_tx_vlan_set_pvid = {
+ .f = cmd_tx_vlan_set_pvid_parsed,
+ .data = NULL,
+ .help_str = "tx_vlan set pvid <port_id> <vlan_id> on|off",
+ .tokens = {
+ (void *)&cmd_tx_vlan_set_pvid_tx_vlan,
+ (void *)&cmd_tx_vlan_set_pvid_set,
+ (void *)&cmd_tx_vlan_set_pvid_pvid,
+ (void *)&cmd_tx_vlan_set_pvid_port_id,
+ (void *)&cmd_tx_vlan_set_pvid_vlan_id,
+ (void *)&cmd_tx_vlan_set_pvid_mode,
+ NULL,
+ },
+};
+
+/* *** DISABLE HARDWARE INSERTION OF VLAN HEADER IN TX PACKETS *** */
+struct cmd_tx_vlan_reset_result {
+ cmdline_fixed_string_t tx_vlan;
+ cmdline_fixed_string_t reset;
+ uint8_t port_id;
+};
+
+static void
+cmd_tx_vlan_reset_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_tx_vlan_reset_result *res = parsed_result;
+
+ tx_vlan_reset(res->port_id);
+}
+
+cmdline_parse_token_string_t cmd_tx_vlan_reset_tx_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_reset_result,
+ tx_vlan, "tx_vlan");
+cmdline_parse_token_string_t cmd_tx_vlan_reset_reset =
+ TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_reset_result,
+ reset, "reset");
+cmdline_parse_token_num_t cmd_tx_vlan_reset_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_tx_vlan_reset_result,
+ port_id, UINT8);
+
+cmdline_parse_inst_t cmd_tx_vlan_reset = {
+ .f = cmd_tx_vlan_reset_parsed,
+ .data = NULL,
+ .help_str = "tx_vlan reset <port_id>: Disable hardware insertion of a "
+ "VLAN header in packets sent on a port",
+ .tokens = {
+ (void *)&cmd_tx_vlan_reset_tx_vlan,
+ (void *)&cmd_tx_vlan_reset_reset,
+ (void *)&cmd_tx_vlan_reset_portid,
+ NULL,
+ },
+};
+
+
+/* *** ENABLE HARDWARE INSERTION OF CHECKSUM IN TX PACKETS *** */
+struct cmd_csum_result {
+ cmdline_fixed_string_t csum;
+ cmdline_fixed_string_t mode;
+ cmdline_fixed_string_t proto;
+ cmdline_fixed_string_t hwsw;
+ uint8_t port_id;
+};
+
+static void
+csum_show(int port_id)
+{
+ struct rte_eth_dev_info dev_info;
+ uint16_t ol_flags;
+
+ ol_flags = ports[port_id].tx_ol_flags;
+ printf("Parse tunnel is %s\n",
+ (ol_flags & TESTPMD_TX_OFFLOAD_PARSE_TUNNEL) ? "on" : "off");
+ printf("IP checksum offload is %s\n",
+ (ol_flags & TESTPMD_TX_OFFLOAD_IP_CKSUM) ? "hw" : "sw");
+ printf("UDP checksum offload is %s\n",
+ (ol_flags & TESTPMD_TX_OFFLOAD_UDP_CKSUM) ? "hw" : "sw");
+ printf("TCP checksum offload is %s\n",
+ (ol_flags & TESTPMD_TX_OFFLOAD_TCP_CKSUM) ? "hw" : "sw");
+ printf("SCTP checksum offload is %s\n",
+ (ol_flags & TESTPMD_TX_OFFLOAD_SCTP_CKSUM) ? "hw" : "sw");
+ printf("Outer-Ip checksum offload is %s\n",
+ (ol_flags & TESTPMD_TX_OFFLOAD_OUTER_IP_CKSUM) ? "hw" : "sw");
+
+ /* display warnings if configuration is not supported by the NIC */
+ rte_eth_dev_info_get(port_id, &dev_info);
+ if ((ol_flags & TESTPMD_TX_OFFLOAD_IP_CKSUM) &&
+ (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM) == 0) {
+ printf("Warning: hardware IP checksum enabled but not "
+ "supported by port %d\n", port_id);
+ }
+ if ((ol_flags & TESTPMD_TX_OFFLOAD_UDP_CKSUM) &&
+ (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM) == 0) {
+ printf("Warning: hardware UDP checksum enabled but not "
+ "supported by port %d\n", port_id);
+ }
+ if ((ol_flags & TESTPMD_TX_OFFLOAD_TCP_CKSUM) &&
+ (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM) == 0) {
+ printf("Warning: hardware TCP checksum enabled but not "
+ "supported by port %d\n", port_id);
+ }
+ if ((ol_flags & TESTPMD_TX_OFFLOAD_SCTP_CKSUM) &&
+ (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_SCTP_CKSUM) == 0) {
+ printf("Warning: hardware SCTP checksum enabled but not "
+ "supported by port %d\n", port_id);
+ }
+ if ((ol_flags & TESTPMD_TX_OFFLOAD_OUTER_IP_CKSUM) &&
+ (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM) == 0) {
+ printf("Warning: hardware outer IP checksum enabled but not "
+ "supported by port %d\n", port_id);
+ }
+}
+
+static void
+cmd_csum_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_csum_result *res = parsed_result;
+ int hw = 0;
+ uint16_t mask = 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN)) {
+ printf("invalid port %d\n", res->port_id);
+ return;
+ }
+
+ if (!strcmp(res->mode, "set")) {
+
+ if (!strcmp(res->hwsw, "hw"))
+ hw = 1;
+
+ if (!strcmp(res->proto, "ip")) {
+ mask = TESTPMD_TX_OFFLOAD_IP_CKSUM;
+ } else if (!strcmp(res->proto, "udp")) {
+ mask = TESTPMD_TX_OFFLOAD_UDP_CKSUM;
+ } else if (!strcmp(res->proto, "tcp")) {
+ mask = TESTPMD_TX_OFFLOAD_TCP_CKSUM;
+ } else if (!strcmp(res->proto, "sctp")) {
+ mask = TESTPMD_TX_OFFLOAD_SCTP_CKSUM;
+ } else if (!strcmp(res->proto, "outer-ip")) {
+ mask = TESTPMD_TX_OFFLOAD_OUTER_IP_CKSUM;
+ }
+
+ if (hw)
+ ports[res->port_id].tx_ol_flags |= mask;
+ else
+ ports[res->port_id].tx_ol_flags &= (~mask);
+ }
+ csum_show(res->port_id);
+}
+
+cmdline_parse_token_string_t cmd_csum_csum =
+ TOKEN_STRING_INITIALIZER(struct cmd_csum_result,
+ csum, "csum");
+cmdline_parse_token_string_t cmd_csum_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_csum_result,
+ mode, "set");
+cmdline_parse_token_string_t cmd_csum_proto =
+ TOKEN_STRING_INITIALIZER(struct cmd_csum_result,
+ proto, "ip#tcp#udp#sctp#outer-ip");
+cmdline_parse_token_string_t cmd_csum_hwsw =
+ TOKEN_STRING_INITIALIZER(struct cmd_csum_result,
+ hwsw, "hw#sw");
+cmdline_parse_token_num_t cmd_csum_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_csum_result,
+ port_id, UINT8);
+
+cmdline_parse_inst_t cmd_csum_set = {
+ .f = cmd_csum_parsed,
+ .data = NULL,
+ .help_str = "csum set ip|tcp|udp|sctp|outer-ip hw|sw <port_id>: "
+ "Enable/Disable hardware calculation of L3/L4 checksum when "
+ "using csum forward engine",
+ .tokens = {
+ (void *)&cmd_csum_csum,
+ (void *)&cmd_csum_mode,
+ (void *)&cmd_csum_proto,
+ (void *)&cmd_csum_hwsw,
+ (void *)&cmd_csum_portid,
+ NULL,
+ },
+};
+
+cmdline_parse_token_string_t cmd_csum_mode_show =
+ TOKEN_STRING_INITIALIZER(struct cmd_csum_result,
+ mode, "show");
+
+cmdline_parse_inst_t cmd_csum_show = {
+ .f = cmd_csum_parsed,
+ .data = NULL,
+ .help_str = "csum show <port_id>: Show checksum offload configuration",
+ .tokens = {
+ (void *)&cmd_csum_csum,
+ (void *)&cmd_csum_mode_show,
+ (void *)&cmd_csum_portid,
+ NULL,
+ },
+};
+
+/* Enable/disable tunnel parsing */
+struct cmd_csum_tunnel_result {
+ cmdline_fixed_string_t csum;
+ cmdline_fixed_string_t parse;
+ cmdline_fixed_string_t onoff;
+ uint8_t port_id;
+};
+
+static void
+cmd_csum_tunnel_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_csum_tunnel_result *res = parsed_result;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ if (!strcmp(res->onoff, "on"))
+ ports[res->port_id].tx_ol_flags |=
+ TESTPMD_TX_OFFLOAD_PARSE_TUNNEL;
+ else
+ ports[res->port_id].tx_ol_flags &=
+ (~TESTPMD_TX_OFFLOAD_PARSE_TUNNEL);
+
+ csum_show(res->port_id);
+}
+
+cmdline_parse_token_string_t cmd_csum_tunnel_csum =
+ TOKEN_STRING_INITIALIZER(struct cmd_csum_tunnel_result,
+ csum, "csum");
+cmdline_parse_token_string_t cmd_csum_tunnel_parse =
+ TOKEN_STRING_INITIALIZER(struct cmd_csum_tunnel_result,
+ parse, "parse_tunnel");
+cmdline_parse_token_string_t cmd_csum_tunnel_onoff =
+ TOKEN_STRING_INITIALIZER(struct cmd_csum_tunnel_result,
+ onoff, "on#off");
+cmdline_parse_token_num_t cmd_csum_tunnel_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_csum_tunnel_result,
+ port_id, UINT8);
+
+cmdline_parse_inst_t cmd_csum_tunnel = {
+ .f = cmd_csum_tunnel_parsed,
+ .data = NULL,
+ .help_str = "csum parse_tunnel on|off <port_id>: "
+ "Enable/Disable parsing of tunnels for csum engine",
+ .tokens = {
+ (void *)&cmd_csum_tunnel_csum,
+ (void *)&cmd_csum_tunnel_parse,
+ (void *)&cmd_csum_tunnel_onoff,
+ (void *)&cmd_csum_tunnel_portid,
+ NULL,
+ },
+};
+
+/* *** ENABLE HARDWARE SEGMENTATION IN TX NON-TUNNELED PACKETS *** */
+struct cmd_tso_set_result {
+ cmdline_fixed_string_t tso;
+ cmdline_fixed_string_t mode;
+ uint16_t tso_segsz;
+ uint8_t port_id;
+};
+
+static void
+cmd_tso_set_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_tso_set_result *res = parsed_result;
+ struct rte_eth_dev_info dev_info;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ if (!strcmp(res->mode, "set"))
+ ports[res->port_id].tso_segsz = res->tso_segsz;
+
+ if (ports[res->port_id].tso_segsz == 0)
+ printf("TSO for non-tunneled packets is disabled\n");
+ else
+ printf("TSO segment size for non-tunneled packets is %d\n",
+ ports[res->port_id].tso_segsz);
+
+ /* display warnings if configuration is not supported by the NIC */
+ rte_eth_dev_info_get(res->port_id, &dev_info);
+ if ((ports[res->port_id].tso_segsz != 0) &&
+ (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_TSO) == 0) {
+ printf("Warning: TSO enabled but not "
+ "supported by port %d\n", res->port_id);
+ }
+}
+
+cmdline_parse_token_string_t cmd_tso_set_tso =
+ TOKEN_STRING_INITIALIZER(struct cmd_tso_set_result,
+ tso, "tso");
+cmdline_parse_token_string_t cmd_tso_set_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_tso_set_result,
+ mode, "set");
+cmdline_parse_token_num_t cmd_tso_set_tso_segsz =
+ TOKEN_NUM_INITIALIZER(struct cmd_tso_set_result,
+ tso_segsz, UINT16);
+cmdline_parse_token_num_t cmd_tso_set_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_tso_set_result,
+ port_id, UINT8);
+
+cmdline_parse_inst_t cmd_tso_set = {
+ .f = cmd_tso_set_parsed,
+ .data = NULL,
+ .help_str = "tso set <tso_segsz> <port_id>: "
+ "Set TSO segment size of non-tunneled packets for csum engine "
+ "(0 to disable)",
+ .tokens = {
+ (void *)&cmd_tso_set_tso,
+ (void *)&cmd_tso_set_mode,
+ (void *)&cmd_tso_set_tso_segsz,
+ (void *)&cmd_tso_set_portid,
+ NULL,
+ },
+};
+
+cmdline_parse_token_string_t cmd_tso_show_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_tso_set_result,
+ mode, "show");
+
+
+cmdline_parse_inst_t cmd_tso_show = {
+ .f = cmd_tso_set_parsed,
+ .data = NULL,
+ .help_str = "tso show <port_id>: "
+ "Show TSO segment size of non-tunneled packets for csum engine",
+ .tokens = {
+ (void *)&cmd_tso_set_tso,
+ (void *)&cmd_tso_show_mode,
+ (void *)&cmd_tso_set_portid,
+ NULL,
+ },
+};
+
+/* *** ENABLE HARDWARE SEGMENTATION IN TX TUNNELED PACKETS *** */
+struct cmd_tunnel_tso_set_result {
+ cmdline_fixed_string_t tso;
+ cmdline_fixed_string_t mode;
+ uint16_t tso_segsz;
+ uint8_t port_id;
+};
+
+static void
+check_tunnel_tso_nic_support(uint8_t port_id)
+{
+ struct rte_eth_dev_info dev_info;
+
+ rte_eth_dev_info_get(port_id, &dev_info);
+ if (!(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_VXLAN_TNL_TSO))
+ printf("Warning: TSO enabled but VXLAN TUNNEL TSO not "
+ "supported by port %d\n", port_id);
+ if (!(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_GRE_TNL_TSO))
+ printf("Warning: TSO enabled but GRE TUNNEL TSO not "
+ "supported by port %d\n", port_id);
+ if (!(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPIP_TNL_TSO))
+ printf("Warning: TSO enabled but IPIP TUNNEL TSO not "
+ "supported by port %d\n", port_id);
+ if (!(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_GENEVE_TNL_TSO))
+ printf("Warning: TSO enabled but GENEVE TUNNEL TSO not "
+ "supported by port %d\n", port_id);
+}
+
+static void
+cmd_tunnel_tso_set_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_tunnel_tso_set_result *res = parsed_result;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ if (!strcmp(res->mode, "set"))
+ ports[res->port_id].tunnel_tso_segsz = res->tso_segsz;
+
+ if (ports[res->port_id].tunnel_tso_segsz == 0)
+ printf("TSO for tunneled packets is disabled\n");
+ else {
+ printf("TSO segment size for tunneled packets is %d\n",
+ ports[res->port_id].tunnel_tso_segsz);
+
+ /* Below conditions are needed to make it work:
+ * (1) tunnel TSO is supported by the NIC;
+ * (2) "csum parse_tunnel" must be set so that tunneled pkts
+ * are recognized;
+ * (3) for tunneled pkts with outer L3 of IPv4,
+ * "csum set outer-ip" must be set to hw, because after tso,
+ * total_len of outer IP header is changed, and the checksum
+ * of outer IP header calculated by sw should be wrong; that
+ * is not necessary for IPv6 tunneled pkts because there's no
+ * checksum in IP header anymore.
+ */
+ check_tunnel_tso_nic_support(res->port_id);
+
+ if (!(ports[res->port_id].tx_ol_flags &
+ TESTPMD_TX_OFFLOAD_PARSE_TUNNEL))
+ printf("Warning: csum parse_tunnel must be set "
+ "so that tunneled packets are recognized\n");
+ if (!(ports[res->port_id].tx_ol_flags &
+ TESTPMD_TX_OFFLOAD_OUTER_IP_CKSUM))
+ printf("Warning: csum set outer-ip must be set to hw "
+ "if outer L3 is IPv4; not necessary for IPv6\n");
+ }
+}
+
+cmdline_parse_token_string_t cmd_tunnel_tso_set_tso =
+ TOKEN_STRING_INITIALIZER(struct cmd_tunnel_tso_set_result,
+ tso, "tunnel_tso");
+cmdline_parse_token_string_t cmd_tunnel_tso_set_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_tunnel_tso_set_result,
+ mode, "set");
+cmdline_parse_token_num_t cmd_tunnel_tso_set_tso_segsz =
+ TOKEN_NUM_INITIALIZER(struct cmd_tunnel_tso_set_result,
+ tso_segsz, UINT16);
+cmdline_parse_token_num_t cmd_tunnel_tso_set_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_tunnel_tso_set_result,
+ port_id, UINT8);
+
+cmdline_parse_inst_t cmd_tunnel_tso_set = {
+ .f = cmd_tunnel_tso_set_parsed,
+ .data = NULL,
+ .help_str = "tunnel_tso set <tso_segsz> <port_id>: "
+ "Set TSO segment size of tunneled packets for csum engine "
+ "(0 to disable)",
+ .tokens = {
+ (void *)&cmd_tunnel_tso_set_tso,
+ (void *)&cmd_tunnel_tso_set_mode,
+ (void *)&cmd_tunnel_tso_set_tso_segsz,
+ (void *)&cmd_tunnel_tso_set_portid,
+ NULL,
+ },
+};
+
+cmdline_parse_token_string_t cmd_tunnel_tso_show_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_tunnel_tso_set_result,
+ mode, "show");
+
+
+cmdline_parse_inst_t cmd_tunnel_tso_show = {
+ .f = cmd_tunnel_tso_set_parsed,
+ .data = NULL,
+ .help_str = "tunnel_tso show <port_id> "
+ "Show TSO segment size of tunneled packets for csum engine",
+ .tokens = {
+ (void *)&cmd_tunnel_tso_set_tso,
+ (void *)&cmd_tunnel_tso_show_mode,
+ (void *)&cmd_tunnel_tso_set_portid,
+ NULL,
+ },
+};
+
+/* *** ENABLE/DISABLE FLUSH ON RX STREAMS *** */
+struct cmd_set_flush_rx {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t flush_rx;
+ cmdline_fixed_string_t mode;
+};
+
+static void
+cmd_set_flush_rx_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_flush_rx *res = parsed_result;
+ no_flush_rx = (uint8_t)((strcmp(res->mode, "on") == 0) ? 0 : 1);
+}
+
+cmdline_parse_token_string_t cmd_setflushrx_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_flush_rx,
+ set, "set");
+cmdline_parse_token_string_t cmd_setflushrx_flush_rx =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_flush_rx,
+ flush_rx, "flush_rx");
+cmdline_parse_token_string_t cmd_setflushrx_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_flush_rx,
+ mode, "on#off");
+
+
+cmdline_parse_inst_t cmd_set_flush_rx = {
+ .f = cmd_set_flush_rx_parsed,
+ .help_str = "set flush_rx on|off: Enable/Disable flush on rx streams",
+ .data = NULL,
+ .tokens = {
+ (void *)&cmd_setflushrx_set,
+ (void *)&cmd_setflushrx_flush_rx,
+ (void *)&cmd_setflushrx_mode,
+ NULL,
+ },
+};
+
+/* *** ENABLE/DISABLE LINK STATUS CHECK *** */
+struct cmd_set_link_check {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t link_check;
+ cmdline_fixed_string_t mode;
+};
+
+static void
+cmd_set_link_check_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_link_check *res = parsed_result;
+ no_link_check = (uint8_t)((strcmp(res->mode, "on") == 0) ? 0 : 1);
+}
+
+cmdline_parse_token_string_t cmd_setlinkcheck_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_link_check,
+ set, "set");
+cmdline_parse_token_string_t cmd_setlinkcheck_link_check =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_link_check,
+ link_check, "link_check");
+cmdline_parse_token_string_t cmd_setlinkcheck_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_link_check,
+ mode, "on#off");
+
+
+cmdline_parse_inst_t cmd_set_link_check = {
+ .f = cmd_set_link_check_parsed,
+ .help_str = "set link_check on|off: Enable/Disable link status check "
+ "when starting/stopping a port",
+ .data = NULL,
+ .tokens = {
+ (void *)&cmd_setlinkcheck_set,
+ (void *)&cmd_setlinkcheck_link_check,
+ (void *)&cmd_setlinkcheck_mode,
+ NULL,
+ },
+};
+
+#ifdef RTE_NIC_BYPASS
+/* *** SET NIC BYPASS MODE *** */
+struct cmd_set_bypass_mode_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t bypass;
+ cmdline_fixed_string_t mode;
+ cmdline_fixed_string_t value;
+ uint8_t port_id;
+};
+
+static void
+cmd_set_bypass_mode_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_bypass_mode_result *res = parsed_result;
+ portid_t port_id = res->port_id;
+ uint32_t bypass_mode = RTE_BYPASS_MODE_NORMAL;
+
+ if (!strcmp(res->value, "bypass"))
+ bypass_mode = RTE_BYPASS_MODE_BYPASS;
+ else if (!strcmp(res->value, "isolate"))
+ bypass_mode = RTE_BYPASS_MODE_ISOLATE;
+ else
+ bypass_mode = RTE_BYPASS_MODE_NORMAL;
+
+ /* Set the bypass mode for the relevant port. */
+ if (0 != rte_eth_dev_bypass_state_set(port_id, &bypass_mode)) {
+ printf("\t Failed to set bypass mode for port = %d.\n", port_id);
+ }
+}
+
+cmdline_parse_token_string_t cmd_setbypass_mode_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_mode_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_setbypass_mode_bypass =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_mode_result,
+ bypass, "bypass");
+cmdline_parse_token_string_t cmd_setbypass_mode_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_mode_result,
+ mode, "mode");
+cmdline_parse_token_string_t cmd_setbypass_mode_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_mode_result,
+ value, "normal#bypass#isolate");
+cmdline_parse_token_num_t cmd_setbypass_mode_port =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_bypass_mode_result,
+ port_id, UINT8);
+
+cmdline_parse_inst_t cmd_set_bypass_mode = {
+ .f = cmd_set_bypass_mode_parsed,
+ .help_str = "set bypass mode normal|bypass|isolate <port_id>: "
+ "Set the NIC bypass mode for port_id",
+ .data = NULL,
+ .tokens = {
+ (void *)&cmd_setbypass_mode_set,
+ (void *)&cmd_setbypass_mode_bypass,
+ (void *)&cmd_setbypass_mode_mode,
+ (void *)&cmd_setbypass_mode_value,
+ (void *)&cmd_setbypass_mode_port,
+ NULL,
+ },
+};
+
+/* *** SET NIC BYPASS EVENT *** */
+struct cmd_set_bypass_event_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t bypass;
+ cmdline_fixed_string_t event;
+ cmdline_fixed_string_t event_value;
+ cmdline_fixed_string_t mode;
+ cmdline_fixed_string_t mode_value;
+ uint8_t port_id;
+};
+
+static void
+cmd_set_bypass_event_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ int32_t rc;
+ struct cmd_set_bypass_event_result *res = parsed_result;
+ portid_t port_id = res->port_id;
+ uint32_t bypass_event = RTE_BYPASS_EVENT_NONE;
+ uint32_t bypass_mode = RTE_BYPASS_MODE_NORMAL;
+
+ if (!strcmp(res->event_value, "timeout"))
+ bypass_event = RTE_BYPASS_EVENT_TIMEOUT;
+ else if (!strcmp(res->event_value, "os_on"))
+ bypass_event = RTE_BYPASS_EVENT_OS_ON;
+ else if (!strcmp(res->event_value, "os_off"))
+ bypass_event = RTE_BYPASS_EVENT_OS_OFF;
+ else if (!strcmp(res->event_value, "power_on"))
+ bypass_event = RTE_BYPASS_EVENT_POWER_ON;
+ else if (!strcmp(res->event_value, "power_off"))
+ bypass_event = RTE_BYPASS_EVENT_POWER_OFF;
+ else
+ bypass_event = RTE_BYPASS_EVENT_NONE;
+
+ if (!strcmp(res->mode_value, "bypass"))
+ bypass_mode = RTE_BYPASS_MODE_BYPASS;
+ else if (!strcmp(res->mode_value, "isolate"))
+ bypass_mode = RTE_BYPASS_MODE_ISOLATE;
+ else
+ bypass_mode = RTE_BYPASS_MODE_NORMAL;
+
+ /* Set the watchdog timeout. */
+ if (bypass_event == RTE_BYPASS_EVENT_TIMEOUT) {
+
+ rc = -EINVAL;
+ if (!RTE_BYPASS_TMT_VALID(bypass_timeout) ||
+ (rc = rte_eth_dev_wd_timeout_store(port_id,
+ bypass_timeout)) != 0) {
+ printf("Failed to set timeout value %u "
+ "for port %d, errto code: %d.\n",
+ bypass_timeout, port_id, rc);
+ }
+ }
+
+ /* Set the bypass event to transition to bypass mode. */
+ if (0 != rte_eth_dev_bypass_event_store(port_id,
+ bypass_event, bypass_mode)) {
+ printf("\t Failed to set bypass event for port = %d.\n", port_id);
+ }
+
+}
+
+cmdline_parse_token_string_t cmd_setbypass_event_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_event_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_setbypass_event_bypass =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_event_result,
+ bypass, "bypass");
+cmdline_parse_token_string_t cmd_setbypass_event_event =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_event_result,
+ event, "event");
+cmdline_parse_token_string_t cmd_setbypass_event_event_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_event_result,
+ event_value, "none#timeout#os_off#os_on#power_on#power_off");
+cmdline_parse_token_string_t cmd_setbypass_event_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_event_result,
+ mode, "mode");
+cmdline_parse_token_string_t cmd_setbypass_event_mode_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_event_result,
+ mode_value, "normal#bypass#isolate");
+cmdline_parse_token_num_t cmd_setbypass_event_port =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_bypass_event_result,
+ port_id, UINT8);
+
+cmdline_parse_inst_t cmd_set_bypass_event = {
+ .f = cmd_set_bypass_event_parsed,
+ .help_str = "set bypass event none|timeout|os_on|os_off|power_on|"
+ "power_off mode normal|bypass|isolate <port_id>: "
+ "Set the NIC bypass event mode for port_id",
+ .data = NULL,
+ .tokens = {
+ (void *)&cmd_setbypass_event_set,
+ (void *)&cmd_setbypass_event_bypass,
+ (void *)&cmd_setbypass_event_event,
+ (void *)&cmd_setbypass_event_event_value,
+ (void *)&cmd_setbypass_event_mode,
+ (void *)&cmd_setbypass_event_mode_value,
+ (void *)&cmd_setbypass_event_port,
+ NULL,
+ },
+};
+
+
+/* *** SET NIC BYPASS TIMEOUT *** */
+struct cmd_set_bypass_timeout_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t bypass;
+ cmdline_fixed_string_t timeout;
+ cmdline_fixed_string_t value;
+};
+
+static void
+cmd_set_bypass_timeout_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_bypass_timeout_result *res = parsed_result;
+
+ if (!strcmp(res->value, "1.5"))
+ bypass_timeout = RTE_BYPASS_TMT_1_5_SEC;
+ else if (!strcmp(res->value, "2"))
+ bypass_timeout = RTE_BYPASS_TMT_2_SEC;
+ else if (!strcmp(res->value, "3"))
+ bypass_timeout = RTE_BYPASS_TMT_3_SEC;
+ else if (!strcmp(res->value, "4"))
+ bypass_timeout = RTE_BYPASS_TMT_4_SEC;
+ else if (!strcmp(res->value, "8"))
+ bypass_timeout = RTE_BYPASS_TMT_8_SEC;
+ else if (!strcmp(res->value, "16"))
+ bypass_timeout = RTE_BYPASS_TMT_16_SEC;
+ else if (!strcmp(res->value, "32"))
+ bypass_timeout = RTE_BYPASS_TMT_32_SEC;
+ else
+ bypass_timeout = RTE_BYPASS_TMT_OFF;
+}
+
+cmdline_parse_token_string_t cmd_setbypass_timeout_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_timeout_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_setbypass_timeout_bypass =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_timeout_result,
+ bypass, "bypass");
+cmdline_parse_token_string_t cmd_setbypass_timeout_timeout =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_timeout_result,
+ timeout, "timeout");
+cmdline_parse_token_string_t cmd_setbypass_timeout_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_timeout_result,
+ value, "0#1.5#2#3#4#8#16#32");
+
+cmdline_parse_inst_t cmd_set_bypass_timeout = {
+ .f = cmd_set_bypass_timeout_parsed,
+ .help_str = "set bypass timeout 0|1.5|2|3|4|8|16|32: "
+ "Set the NIC bypass watchdog timeout in seconds",
+ .data = NULL,
+ .tokens = {
+ (void *)&cmd_setbypass_timeout_set,
+ (void *)&cmd_setbypass_timeout_bypass,
+ (void *)&cmd_setbypass_timeout_timeout,
+ (void *)&cmd_setbypass_timeout_value,
+ NULL,
+ },
+};
+
+/* *** SHOW NIC BYPASS MODE *** */
+struct cmd_show_bypass_config_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t bypass;
+ cmdline_fixed_string_t config;
+ uint8_t port_id;
+};
+
+static void
+cmd_show_bypass_config_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_show_bypass_config_result *res = parsed_result;
+ uint32_t event_mode;
+ uint32_t bypass_mode;
+ portid_t port_id = res->port_id;
+ uint32_t timeout = bypass_timeout;
+ int i;
+
+ static const char * const timeouts[RTE_BYPASS_TMT_NUM] =
+ {"off", "1.5", "2", "3", "4", "8", "16", "32"};
+ static const char * const modes[RTE_BYPASS_MODE_NUM] =
+ {"UNKNOWN", "normal", "bypass", "isolate"};
+ static const char * const events[RTE_BYPASS_EVENT_NUM] = {
+ "NONE",
+ "OS/board on",
+ "power supply on",
+ "OS/board off",
+ "power supply off",
+ "timeout"};
+ int num_events = (sizeof events) / (sizeof events[0]);
+
+ /* Display the bypass mode.*/
+ if (0 != rte_eth_dev_bypass_state_show(port_id, &bypass_mode)) {
+ printf("\tFailed to get bypass mode for port = %d\n", port_id);
+ return;
+ }
+ else {
+ if (!RTE_BYPASS_MODE_VALID(bypass_mode))
+ bypass_mode = RTE_BYPASS_MODE_NONE;
+
+ printf("\tbypass mode = %s\n", modes[bypass_mode]);
+ }
+
+ /* Display the bypass timeout.*/
+ if (!RTE_BYPASS_TMT_VALID(timeout))
+ timeout = RTE_BYPASS_TMT_OFF;
+
+ printf("\tbypass timeout = %s\n", timeouts[timeout]);
+
+ /* Display the bypass events and associated modes. */
+ for (i = RTE_BYPASS_EVENT_START; i < num_events; i++) {
+
+ if (0 != rte_eth_dev_bypass_event_show(port_id, i, &event_mode)) {
+ printf("\tFailed to get bypass mode for event = %s\n",
+ events[i]);
+ } else {
+ if (!RTE_BYPASS_MODE_VALID(event_mode))
+ event_mode = RTE_BYPASS_MODE_NONE;
+
+ printf("\tbypass event: %-16s = %s\n", events[i],
+ modes[event_mode]);
+ }
+ }
+}
+
+cmdline_parse_token_string_t cmd_showbypass_config_show =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_bypass_config_result,
+ show, "show");
+cmdline_parse_token_string_t cmd_showbypass_config_bypass =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_bypass_config_result,
+ bypass, "bypass");
+cmdline_parse_token_string_t cmd_showbypass_config_config =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_bypass_config_result,
+ config, "config");
+cmdline_parse_token_num_t cmd_showbypass_config_port =
+ TOKEN_NUM_INITIALIZER(struct cmd_show_bypass_config_result,
+ port_id, UINT8);
+
+cmdline_parse_inst_t cmd_show_bypass_config = {
+ .f = cmd_show_bypass_config_parsed,
+ .help_str = "show bypass config <port_id>: "
+ "Show the NIC bypass config for port_id",
+ .data = NULL,
+ .tokens = {
+ (void *)&cmd_showbypass_config_show,
+ (void *)&cmd_showbypass_config_bypass,
+ (void *)&cmd_showbypass_config_config,
+ (void *)&cmd_showbypass_config_port,
+ NULL,
+ },
+};
+#endif
+
+#ifdef RTE_LIBRTE_PMD_BOND
+/* *** SET BONDING MODE *** */
+struct cmd_set_bonding_mode_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t bonding;
+ cmdline_fixed_string_t mode;
+ uint8_t value;
+ uint8_t port_id;
+};
+
+static void cmd_set_bonding_mode_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_bonding_mode_result *res = parsed_result;
+ portid_t port_id = res->port_id;
+
+ /* Set the bonding mode for the relevant port. */
+ if (0 != rte_eth_bond_mode_set(port_id, res->value))
+ printf("\t Failed to set bonding mode for port = %d.\n", port_id);
+}
+
+cmdline_parse_token_string_t cmd_setbonding_mode_set =
+TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_mode_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_setbonding_mode_bonding =
+TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_mode_result,
+ bonding, "bonding");
+cmdline_parse_token_string_t cmd_setbonding_mode_mode =
+TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_mode_result,
+ mode, "mode");
+cmdline_parse_token_num_t cmd_setbonding_mode_value =
+TOKEN_NUM_INITIALIZER(struct cmd_set_bonding_mode_result,
+ value, UINT8);
+cmdline_parse_token_num_t cmd_setbonding_mode_port =
+TOKEN_NUM_INITIALIZER(struct cmd_set_bonding_mode_result,
+ port_id, UINT8);
+
+cmdline_parse_inst_t cmd_set_bonding_mode = {
+ .f = cmd_set_bonding_mode_parsed,
+ .help_str = "set bonding mode <mode_value> <port_id>: "
+ "Set the bonding mode for port_id",
+ .data = NULL,
+ .tokens = {
+ (void *) &cmd_setbonding_mode_set,
+ (void *) &cmd_setbonding_mode_bonding,
+ (void *) &cmd_setbonding_mode_mode,
+ (void *) &cmd_setbonding_mode_value,
+ (void *) &cmd_setbonding_mode_port,
+ NULL
+ }
+};
+
+/* *** SET BALANCE XMIT POLICY *** */
+struct cmd_set_bonding_balance_xmit_policy_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t bonding;
+ cmdline_fixed_string_t balance_xmit_policy;
+ uint8_t port_id;
+ cmdline_fixed_string_t policy;
+};
+
+static void cmd_set_bonding_balance_xmit_policy_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_bonding_balance_xmit_policy_result *res = parsed_result;
+ portid_t port_id = res->port_id;
+ uint8_t policy;
+
+ if (!strcmp(res->policy, "l2")) {
+ policy = BALANCE_XMIT_POLICY_LAYER2;
+ } else if (!strcmp(res->policy, "l23")) {
+ policy = BALANCE_XMIT_POLICY_LAYER23;
+ } else if (!strcmp(res->policy, "l34")) {
+ policy = BALANCE_XMIT_POLICY_LAYER34;
+ } else {
+ printf("\t Invalid xmit policy selection");
+ return;
+ }
+
+ /* Set the bonding mode for the relevant port. */
+ if (0 != rte_eth_bond_xmit_policy_set(port_id, policy)) {
+ printf("\t Failed to set bonding balance xmit policy for port = %d.\n",
+ port_id);
+ }
+}
+
+cmdline_parse_token_string_t cmd_setbonding_balance_xmit_policy_set =
+TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_balance_xmit_policy_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_setbonding_balance_xmit_policy_bonding =
+TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_balance_xmit_policy_result,
+ bonding, "bonding");
+cmdline_parse_token_string_t cmd_setbonding_balance_xmit_policy_balance_xmit_policy =
+TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_balance_xmit_policy_result,
+ balance_xmit_policy, "balance_xmit_policy");
+cmdline_parse_token_num_t cmd_setbonding_balance_xmit_policy_port =
+TOKEN_NUM_INITIALIZER(struct cmd_set_bonding_balance_xmit_policy_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_setbonding_balance_xmit_policy_policy =
+TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_balance_xmit_policy_result,
+ policy, "l2#l23#l34");
+
+cmdline_parse_inst_t cmd_set_balance_xmit_policy = {
+ .f = cmd_set_bonding_balance_xmit_policy_parsed,
+ .help_str = "set bonding balance_xmit_policy <port_id> "
+ "l2|l23|l34: "
+ "Set the bonding balance_xmit_policy for port_id",
+ .data = NULL,
+ .tokens = {
+ (void *)&cmd_setbonding_balance_xmit_policy_set,
+ (void *)&cmd_setbonding_balance_xmit_policy_bonding,
+ (void *)&cmd_setbonding_balance_xmit_policy_balance_xmit_policy,
+ (void *)&cmd_setbonding_balance_xmit_policy_port,
+ (void *)&cmd_setbonding_balance_xmit_policy_policy,
+ NULL
+ }
+};
+
+/* *** SHOW NIC BONDING CONFIGURATION *** */
+struct cmd_show_bonding_config_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t bonding;
+ cmdline_fixed_string_t config;
+ uint8_t port_id;
+};
+
+static void cmd_show_bonding_config_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_show_bonding_config_result *res = parsed_result;
+ int bonding_mode;
+ uint8_t slaves[RTE_MAX_ETHPORTS];
+ int num_slaves, num_active_slaves;
+ int primary_id;
+ int i;
+ portid_t port_id = res->port_id;
+
+ /* Display the bonding mode.*/
+ bonding_mode = rte_eth_bond_mode_get(port_id);
+ if (bonding_mode < 0) {
+ printf("\tFailed to get bonding mode for port = %d\n", port_id);
+ return;
+ } else
+ printf("\tBonding mode: %d\n", bonding_mode);
+
+ if (bonding_mode == BONDING_MODE_BALANCE) {
+ int balance_xmit_policy;
+
+ balance_xmit_policy = rte_eth_bond_xmit_policy_get(port_id);
+ if (balance_xmit_policy < 0) {
+ printf("\tFailed to get balance xmit policy for port = %d\n",
+ port_id);
+ return;
+ } else {
+ printf("\tBalance Xmit Policy: ");
+
+ switch (balance_xmit_policy) {
+ case BALANCE_XMIT_POLICY_LAYER2:
+ printf("BALANCE_XMIT_POLICY_LAYER2");
+ break;
+ case BALANCE_XMIT_POLICY_LAYER23:
+ printf("BALANCE_XMIT_POLICY_LAYER23");
+ break;
+ case BALANCE_XMIT_POLICY_LAYER34:
+ printf("BALANCE_XMIT_POLICY_LAYER34");
+ break;
+ }
+ printf("\n");
+ }
+ }
+
+ num_slaves = rte_eth_bond_slaves_get(port_id, slaves, RTE_MAX_ETHPORTS);
+
+ if (num_slaves < 0) {
+ printf("\tFailed to get slave list for port = %d\n", port_id);
+ return;
+ }
+ if (num_slaves > 0) {
+ printf("\tSlaves (%d): [", num_slaves);
+ for (i = 0; i < num_slaves - 1; i++)
+ printf("%d ", slaves[i]);
+
+ printf("%d]\n", slaves[num_slaves - 1]);
+ } else {
+ printf("\tSlaves: []\n");
+
+ }
+
+ num_active_slaves = rte_eth_bond_active_slaves_get(port_id, slaves,
+ RTE_MAX_ETHPORTS);
+
+ if (num_active_slaves < 0) {
+ printf("\tFailed to get active slave list for port = %d\n", port_id);
+ return;
+ }
+ if (num_active_slaves > 0) {
+ printf("\tActive Slaves (%d): [", num_active_slaves);
+ for (i = 0; i < num_active_slaves - 1; i++)
+ printf("%d ", slaves[i]);
+
+ printf("%d]\n", slaves[num_active_slaves - 1]);
+
+ } else {
+ printf("\tActive Slaves: []\n");
+
+ }
+
+ primary_id = rte_eth_bond_primary_get(port_id);
+ if (primary_id < 0) {
+ printf("\tFailed to get primary slave for port = %d\n", port_id);
+ return;
+ } else
+ printf("\tPrimary: [%d]\n", primary_id);
+
+}
+
+cmdline_parse_token_string_t cmd_showbonding_config_show =
+TOKEN_STRING_INITIALIZER(struct cmd_show_bonding_config_result,
+ show, "show");
+cmdline_parse_token_string_t cmd_showbonding_config_bonding =
+TOKEN_STRING_INITIALIZER(struct cmd_show_bonding_config_result,
+ bonding, "bonding");
+cmdline_parse_token_string_t cmd_showbonding_config_config =
+TOKEN_STRING_INITIALIZER(struct cmd_show_bonding_config_result,
+ config, "config");
+cmdline_parse_token_num_t cmd_showbonding_config_port =
+TOKEN_NUM_INITIALIZER(struct cmd_show_bonding_config_result,
+ port_id, UINT8);
+
+cmdline_parse_inst_t cmd_show_bonding_config = {
+ .f = cmd_show_bonding_config_parsed,
+ .help_str = "show bonding config <port_id>: "
+ "Show the bonding config for port_id",
+ .data = NULL,
+ .tokens = {
+ (void *)&cmd_showbonding_config_show,
+ (void *)&cmd_showbonding_config_bonding,
+ (void *)&cmd_showbonding_config_config,
+ (void *)&cmd_showbonding_config_port,
+ NULL
+ }
+};
+
+/* *** SET BONDING PRIMARY *** */
+struct cmd_set_bonding_primary_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t bonding;
+ cmdline_fixed_string_t primary;
+ uint8_t slave_id;
+ uint8_t port_id;
+};
+
+static void cmd_set_bonding_primary_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_bonding_primary_result *res = parsed_result;
+ portid_t master_port_id = res->port_id;
+ portid_t slave_port_id = res->slave_id;
+
+ /* Set the primary slave for a bonded device. */
+ if (0 != rte_eth_bond_primary_set(master_port_id, slave_port_id)) {
+ printf("\t Failed to set primary slave for port = %d.\n",
+ master_port_id);
+ return;
+ }
+ init_port_config();
+}
+
+cmdline_parse_token_string_t cmd_setbonding_primary_set =
+TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_primary_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_setbonding_primary_bonding =
+TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_primary_result,
+ bonding, "bonding");
+cmdline_parse_token_string_t cmd_setbonding_primary_primary =
+TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_primary_result,
+ primary, "primary");
+cmdline_parse_token_num_t cmd_setbonding_primary_slave =
+TOKEN_NUM_INITIALIZER(struct cmd_set_bonding_primary_result,
+ slave_id, UINT8);
+cmdline_parse_token_num_t cmd_setbonding_primary_port =
+TOKEN_NUM_INITIALIZER(struct cmd_set_bonding_primary_result,
+ port_id, UINT8);
+
+cmdline_parse_inst_t cmd_set_bonding_primary = {
+ .f = cmd_set_bonding_primary_parsed,
+ .help_str = "set bonding primary <slave_id> <port_id>: "
+ "Set the primary slave for port_id",
+ .data = NULL,
+ .tokens = {
+ (void *)&cmd_setbonding_primary_set,
+ (void *)&cmd_setbonding_primary_bonding,
+ (void *)&cmd_setbonding_primary_primary,
+ (void *)&cmd_setbonding_primary_slave,
+ (void *)&cmd_setbonding_primary_port,
+ NULL
+ }
+};
+
+/* *** ADD SLAVE *** */
+struct cmd_add_bonding_slave_result {
+ cmdline_fixed_string_t add;
+ cmdline_fixed_string_t bonding;
+ cmdline_fixed_string_t slave;
+ uint8_t slave_id;
+ uint8_t port_id;
+};
+
+static void cmd_add_bonding_slave_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_add_bonding_slave_result *res = parsed_result;
+ portid_t master_port_id = res->port_id;
+ portid_t slave_port_id = res->slave_id;
+
+ /* Set the primary slave for a bonded device. */
+ if (0 != rte_eth_bond_slave_add(master_port_id, slave_port_id)) {
+ printf("\t Failed to add slave %d to master port = %d.\n",
+ slave_port_id, master_port_id);
+ return;
+ }
+ init_port_config();
+ set_port_slave_flag(slave_port_id);
+}
+
+cmdline_parse_token_string_t cmd_addbonding_slave_add =
+TOKEN_STRING_INITIALIZER(struct cmd_add_bonding_slave_result,
+ add, "add");
+cmdline_parse_token_string_t cmd_addbonding_slave_bonding =
+TOKEN_STRING_INITIALIZER(struct cmd_add_bonding_slave_result,
+ bonding, "bonding");
+cmdline_parse_token_string_t cmd_addbonding_slave_slave =
+TOKEN_STRING_INITIALIZER(struct cmd_add_bonding_slave_result,
+ slave, "slave");
+cmdline_parse_token_num_t cmd_addbonding_slave_slaveid =
+TOKEN_NUM_INITIALIZER(struct cmd_add_bonding_slave_result,
+ slave_id, UINT8);
+cmdline_parse_token_num_t cmd_addbonding_slave_port =
+TOKEN_NUM_INITIALIZER(struct cmd_add_bonding_slave_result,
+ port_id, UINT8);
+
+cmdline_parse_inst_t cmd_add_bonding_slave = {
+ .f = cmd_add_bonding_slave_parsed,
+ .help_str = "add bonding slave <slave_id> <port_id>: "
+ "Add a slave device to a bonded device",
+ .data = NULL,
+ .tokens = {
+ (void *)&cmd_addbonding_slave_add,
+ (void *)&cmd_addbonding_slave_bonding,
+ (void *)&cmd_addbonding_slave_slave,
+ (void *)&cmd_addbonding_slave_slaveid,
+ (void *)&cmd_addbonding_slave_port,
+ NULL
+ }
+};
+
+/* *** REMOVE SLAVE *** */
+struct cmd_remove_bonding_slave_result {
+ cmdline_fixed_string_t remove;
+ cmdline_fixed_string_t bonding;
+ cmdline_fixed_string_t slave;
+ uint8_t slave_id;
+ uint8_t port_id;
+};
+
+static void cmd_remove_bonding_slave_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_remove_bonding_slave_result *res = parsed_result;
+ portid_t master_port_id = res->port_id;
+ portid_t slave_port_id = res->slave_id;
+
+ /* Set the primary slave for a bonded device. */
+ if (0 != rte_eth_bond_slave_remove(master_port_id, slave_port_id)) {
+ printf("\t Failed to remove slave %d from master port = %d.\n",
+ slave_port_id, master_port_id);
+ return;
+ }
+ init_port_config();
+ clear_port_slave_flag(slave_port_id);
+}
+
+cmdline_parse_token_string_t cmd_removebonding_slave_remove =
+ TOKEN_STRING_INITIALIZER(struct cmd_remove_bonding_slave_result,
+ remove, "remove");
+cmdline_parse_token_string_t cmd_removebonding_slave_bonding =
+ TOKEN_STRING_INITIALIZER(struct cmd_remove_bonding_slave_result,
+ bonding, "bonding");
+cmdline_parse_token_string_t cmd_removebonding_slave_slave =
+ TOKEN_STRING_INITIALIZER(struct cmd_remove_bonding_slave_result,
+ slave, "slave");
+cmdline_parse_token_num_t cmd_removebonding_slave_slaveid =
+ TOKEN_NUM_INITIALIZER(struct cmd_remove_bonding_slave_result,
+ slave_id, UINT8);
+cmdline_parse_token_num_t cmd_removebonding_slave_port =
+ TOKEN_NUM_INITIALIZER(struct cmd_remove_bonding_slave_result,
+ port_id, UINT8);
+
+cmdline_parse_inst_t cmd_remove_bonding_slave = {
+ .f = cmd_remove_bonding_slave_parsed,
+ .help_str = "remove bonding slave <slave_id> <port_id>: "
+ "Remove a slave device from a bonded device",
+ .data = NULL,
+ .tokens = {
+ (void *)&cmd_removebonding_slave_remove,
+ (void *)&cmd_removebonding_slave_bonding,
+ (void *)&cmd_removebonding_slave_slave,
+ (void *)&cmd_removebonding_slave_slaveid,
+ (void *)&cmd_removebonding_slave_port,
+ NULL
+ }
+};
+
+/* *** CREATE BONDED DEVICE *** */
+struct cmd_create_bonded_device_result {
+ cmdline_fixed_string_t create;
+ cmdline_fixed_string_t bonded;
+ cmdline_fixed_string_t device;
+ uint8_t mode;
+ uint8_t socket;
+};
+
+static int bond_dev_num = 0;
+
+static void cmd_create_bonded_device_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_create_bonded_device_result *res = parsed_result;
+ char ethdev_name[RTE_ETH_NAME_MAX_LEN];
+ int port_id;
+
+ if (test_done == 0) {
+ printf("Please stop forwarding first\n");
+ return;
+ }
+
+ snprintf(ethdev_name, RTE_ETH_NAME_MAX_LEN, "net_bond_testpmd_%d",
+ bond_dev_num++);
+
+ /* Create a new bonded device. */
+ port_id = rte_eth_bond_create(ethdev_name, res->mode, res->socket);
+ if (port_id < 0) {
+ printf("\t Failed to create bonded device.\n");
+ return;
+ } else {
+ printf("Created new bonded device %s on (port %d).\n", ethdev_name,
+ port_id);
+
+ /* Update number of ports */
+ nb_ports = rte_eth_dev_count();
+ reconfig(port_id, res->socket);
+ rte_eth_promiscuous_enable(port_id);
+ }
+
+}
+
+cmdline_parse_token_string_t cmd_createbonded_device_create =
+ TOKEN_STRING_INITIALIZER(struct cmd_create_bonded_device_result,
+ create, "create");
+cmdline_parse_token_string_t cmd_createbonded_device_bonded =
+ TOKEN_STRING_INITIALIZER(struct cmd_create_bonded_device_result,
+ bonded, "bonded");
+cmdline_parse_token_string_t cmd_createbonded_device_device =
+ TOKEN_STRING_INITIALIZER(struct cmd_create_bonded_device_result,
+ device, "device");
+cmdline_parse_token_num_t cmd_createbonded_device_mode =
+ TOKEN_NUM_INITIALIZER(struct cmd_create_bonded_device_result,
+ mode, UINT8);
+cmdline_parse_token_num_t cmd_createbonded_device_socket =
+ TOKEN_NUM_INITIALIZER(struct cmd_create_bonded_device_result,
+ socket, UINT8);
+
+cmdline_parse_inst_t cmd_create_bonded_device = {
+ .f = cmd_create_bonded_device_parsed,
+ .help_str = "create bonded device <mode> <socket>: "
+ "Create a new bonded device with specific bonding mode and socket",
+ .data = NULL,
+ .tokens = {
+ (void *)&cmd_createbonded_device_create,
+ (void *)&cmd_createbonded_device_bonded,
+ (void *)&cmd_createbonded_device_device,
+ (void *)&cmd_createbonded_device_mode,
+ (void *)&cmd_createbonded_device_socket,
+ NULL
+ }
+};
+
+/* *** SET MAC ADDRESS IN BONDED DEVICE *** */
+struct cmd_set_bond_mac_addr_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t bonding;
+ cmdline_fixed_string_t mac_addr;
+ uint8_t port_num;
+ struct ether_addr address;
+};
+
+static void cmd_set_bond_mac_addr_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_bond_mac_addr_result *res = parsed_result;
+ int ret;
+
+ if (port_id_is_invalid(res->port_num, ENABLED_WARN))
+ return;
+
+ ret = rte_eth_bond_mac_address_set(res->port_num, &res->address);
+
+ /* check the return value and print it if is < 0 */
+ if (ret < 0)
+ printf("set_bond_mac_addr error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_set_bond_mac_addr_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bond_mac_addr_result, set, "set");
+cmdline_parse_token_string_t cmd_set_bond_mac_addr_bonding =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bond_mac_addr_result, bonding,
+ "bonding");
+cmdline_parse_token_string_t cmd_set_bond_mac_addr_mac =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bond_mac_addr_result, mac_addr,
+ "mac_addr");
+cmdline_parse_token_num_t cmd_set_bond_mac_addr_portnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_bond_mac_addr_result, port_num, UINT8);
+cmdline_parse_token_etheraddr_t cmd_set_bond_mac_addr_addr =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_bond_mac_addr_result, address);
+
+cmdline_parse_inst_t cmd_set_bond_mac_addr = {
+ .f = cmd_set_bond_mac_addr_parsed,
+ .data = (void *) 0,
+ .help_str = "set bonding mac_addr <port_id> <mac_addr>",
+ .tokens = {
+ (void *)&cmd_set_bond_mac_addr_set,
+ (void *)&cmd_set_bond_mac_addr_bonding,
+ (void *)&cmd_set_bond_mac_addr_mac,
+ (void *)&cmd_set_bond_mac_addr_portnum,
+ (void *)&cmd_set_bond_mac_addr_addr,
+ NULL
+ }
+};
+
+
+/* *** SET LINK STATUS MONITORING POLLING PERIOD ON BONDED DEVICE *** */
+struct cmd_set_bond_mon_period_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t bonding;
+ cmdline_fixed_string_t mon_period;
+ uint8_t port_num;
+ uint32_t period_ms;
+};
+
+static void cmd_set_bond_mon_period_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_bond_mon_period_result *res = parsed_result;
+ int ret;
+
+ if (res->port_num >= nb_ports) {
+ printf("Port id %d must be less than %d\n", res->port_num, nb_ports);
+ return;
+ }
+
+ ret = rte_eth_bond_link_monitoring_set(res->port_num, res->period_ms);
+
+ /* check the return value and print it if is < 0 */
+ if (ret < 0)
+ printf("set_bond_mac_addr error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_set_bond_mon_period_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bond_mon_period_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_set_bond_mon_period_bonding =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bond_mon_period_result,
+ bonding, "bonding");
+cmdline_parse_token_string_t cmd_set_bond_mon_period_mon_period =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bond_mon_period_result,
+ mon_period, "mon_period");
+cmdline_parse_token_num_t cmd_set_bond_mon_period_portnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_bond_mon_period_result,
+ port_num, UINT8);
+cmdline_parse_token_num_t cmd_set_bond_mon_period_period_ms =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_bond_mon_period_result,
+ period_ms, UINT32);
+
+cmdline_parse_inst_t cmd_set_bond_mon_period = {
+ .f = cmd_set_bond_mon_period_parsed,
+ .data = (void *) 0,
+ .help_str = "set bonding mon_period <port_id> <period_ms>",
+ .tokens = {
+ (void *)&cmd_set_bond_mon_period_set,
+ (void *)&cmd_set_bond_mon_period_bonding,
+ (void *)&cmd_set_bond_mon_period_mon_period,
+ (void *)&cmd_set_bond_mon_period_portnum,
+ (void *)&cmd_set_bond_mon_period_period_ms,
+ NULL
+ }
+};
+
+#endif /* RTE_LIBRTE_PMD_BOND */
+
+/* *** SET FORWARDING MODE *** */
+struct cmd_set_fwd_mode_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t fwd;
+ cmdline_fixed_string_t mode;
+};
+
+static void cmd_set_fwd_mode_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_fwd_mode_result *res = parsed_result;
+
+ retry_enabled = 0;
+ set_pkt_forwarding_mode(res->mode);
+}
+
+cmdline_parse_token_string_t cmd_setfwd_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_fwd_mode_result, set, "set");
+cmdline_parse_token_string_t cmd_setfwd_fwd =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_fwd_mode_result, fwd, "fwd");
+cmdline_parse_token_string_t cmd_setfwd_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_fwd_mode_result, mode,
+ "" /* defined at init */);
+
+cmdline_parse_inst_t cmd_set_fwd_mode = {
+ .f = cmd_set_fwd_mode_parsed,
+ .data = NULL,
+ .help_str = NULL, /* defined at init */
+ .tokens = {
+ (void *)&cmd_setfwd_set,
+ (void *)&cmd_setfwd_fwd,
+ (void *)&cmd_setfwd_mode,
+ NULL,
+ },
+};
+
+static void cmd_set_fwd_mode_init(void)
+{
+ char *modes, *c;
+ static char token[128];
+ static char help[256];
+ cmdline_parse_token_string_t *token_struct;
+
+ modes = list_pkt_forwarding_modes();
+ snprintf(help, sizeof(help), "set fwd %s: "
+ "Set packet forwarding mode", modes);
+ cmd_set_fwd_mode.help_str = help;
+
+ /* string token separator is # */
+ for (c = token; *modes != '\0'; modes++)
+ if (*modes == '|')
+ *c++ = '#';
+ else
+ *c++ = *modes;
+ token_struct = (cmdline_parse_token_string_t*)cmd_set_fwd_mode.tokens[2];
+ token_struct->string_data.str = token;
+}
+
+/* *** SET RETRY FORWARDING MODE *** */
+struct cmd_set_fwd_retry_mode_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t fwd;
+ cmdline_fixed_string_t mode;
+ cmdline_fixed_string_t retry;
+};
+
+static void cmd_set_fwd_retry_mode_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_fwd_retry_mode_result *res = parsed_result;
+
+ retry_enabled = 1;
+ set_pkt_forwarding_mode(res->mode);
+}
+
+cmdline_parse_token_string_t cmd_setfwd_retry_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_fwd_retry_mode_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_setfwd_retry_fwd =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_fwd_retry_mode_result,
+ fwd, "fwd");
+cmdline_parse_token_string_t cmd_setfwd_retry_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_fwd_retry_mode_result,
+ mode,
+ "" /* defined at init */);
+cmdline_parse_token_string_t cmd_setfwd_retry_retry =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_fwd_retry_mode_result,
+ retry, "retry");
+
+cmdline_parse_inst_t cmd_set_fwd_retry_mode = {
+ .f = cmd_set_fwd_retry_mode_parsed,
+ .data = NULL,
+ .help_str = NULL, /* defined at init */
+ .tokens = {
+ (void *)&cmd_setfwd_retry_set,
+ (void *)&cmd_setfwd_retry_fwd,
+ (void *)&cmd_setfwd_retry_mode,
+ (void *)&cmd_setfwd_retry_retry,
+ NULL,
+ },
+};
+
+static void cmd_set_fwd_retry_mode_init(void)
+{
+ char *modes, *c;
+ static char token[128];
+ static char help[256];
+ cmdline_parse_token_string_t *token_struct;
+
+ modes = list_pkt_forwarding_retry_modes();
+ snprintf(help, sizeof(help), "set fwd %s retry: "
+ "Set packet forwarding mode with retry", modes);
+ cmd_set_fwd_retry_mode.help_str = help;
+
+ /* string token separator is # */
+ for (c = token; *modes != '\0'; modes++)
+ if (*modes == '|')
+ *c++ = '#';
+ else
+ *c++ = *modes;
+ token_struct = (cmdline_parse_token_string_t *)
+ cmd_set_fwd_retry_mode.tokens[2];
+ token_struct->string_data.str = token;
+}
+
+/* *** SET BURST TX DELAY TIME RETRY NUMBER *** */
+struct cmd_set_burst_tx_retry_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t burst;
+ cmdline_fixed_string_t tx;
+ cmdline_fixed_string_t delay;
+ uint32_t time;
+ cmdline_fixed_string_t retry;
+ uint32_t retry_num;
+};
+
+static void cmd_set_burst_tx_retry_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_burst_tx_retry_result *res = parsed_result;
+
+ if (!strcmp(res->set, "set") && !strcmp(res->burst, "burst")
+ && !strcmp(res->tx, "tx")) {
+ if (!strcmp(res->delay, "delay"))
+ burst_tx_delay_time = res->time;
+ if (!strcmp(res->retry, "retry"))
+ burst_tx_retry_num = res->retry_num;
+ }
+
+}
+
+cmdline_parse_token_string_t cmd_set_burst_tx_retry_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_burst_tx_retry_result, set, "set");
+cmdline_parse_token_string_t cmd_set_burst_tx_retry_burst =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_burst_tx_retry_result, burst,
+ "burst");
+cmdline_parse_token_string_t cmd_set_burst_tx_retry_tx =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_burst_tx_retry_result, tx, "tx");
+cmdline_parse_token_string_t cmd_set_burst_tx_retry_delay =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_burst_tx_retry_result, delay, "delay");
+cmdline_parse_token_num_t cmd_set_burst_tx_retry_time =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_burst_tx_retry_result, time, UINT32);
+cmdline_parse_token_string_t cmd_set_burst_tx_retry_retry =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_burst_tx_retry_result, retry, "retry");
+cmdline_parse_token_num_t cmd_set_burst_tx_retry_retry_num =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_burst_tx_retry_result, retry_num, UINT32);
+
+cmdline_parse_inst_t cmd_set_burst_tx_retry = {
+ .f = cmd_set_burst_tx_retry_parsed,
+ .help_str = "set burst tx delay <delay_usec> retry <num_retry>",
+ .tokens = {
+ (void *)&cmd_set_burst_tx_retry_set,
+ (void *)&cmd_set_burst_tx_retry_burst,
+ (void *)&cmd_set_burst_tx_retry_tx,
+ (void *)&cmd_set_burst_tx_retry_delay,
+ (void *)&cmd_set_burst_tx_retry_time,
+ (void *)&cmd_set_burst_tx_retry_retry,
+ (void *)&cmd_set_burst_tx_retry_retry_num,
+ NULL,
+ },
+};
+
+/* *** SET PROMISC MODE *** */
+struct cmd_set_promisc_mode_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t promisc;
+ cmdline_fixed_string_t port_all; /* valid if "allports" argument == 1 */
+ uint8_t port_num; /* valid if "allports" argument == 0 */
+ cmdline_fixed_string_t mode;
+};
+
+static void cmd_set_promisc_mode_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ void *allports)
+{
+ struct cmd_set_promisc_mode_result *res = parsed_result;
+ int enable;
+ portid_t i;
+
+ if (!strcmp(res->mode, "on"))
+ enable = 1;
+ else
+ enable = 0;
+
+ /* all ports */
+ if (allports) {
+ RTE_ETH_FOREACH_DEV(i) {
+ if (enable)
+ rte_eth_promiscuous_enable(i);
+ else
+ rte_eth_promiscuous_disable(i);
+ }
+ }
+ else {
+ if (enable)
+ rte_eth_promiscuous_enable(res->port_num);
+ else
+ rte_eth_promiscuous_disable(res->port_num);
+ }
+}
+
+cmdline_parse_token_string_t cmd_setpromisc_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_promisc_mode_result, set, "set");
+cmdline_parse_token_string_t cmd_setpromisc_promisc =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_promisc_mode_result, promisc,
+ "promisc");
+cmdline_parse_token_string_t cmd_setpromisc_portall =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_promisc_mode_result, port_all,
+ "all");
+cmdline_parse_token_num_t cmd_setpromisc_portnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_promisc_mode_result, port_num,
+ UINT8);
+cmdline_parse_token_string_t cmd_setpromisc_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_promisc_mode_result, mode,
+ "on#off");
+
+cmdline_parse_inst_t cmd_set_promisc_mode_all = {
+ .f = cmd_set_promisc_mode_parsed,
+ .data = (void *)1,
+ .help_str = "set promisc all on|off: Set promisc mode for all ports",
+ .tokens = {
+ (void *)&cmd_setpromisc_set,
+ (void *)&cmd_setpromisc_promisc,
+ (void *)&cmd_setpromisc_portall,
+ (void *)&cmd_setpromisc_mode,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_set_promisc_mode_one = {
+ .f = cmd_set_promisc_mode_parsed,
+ .data = (void *)0,
+ .help_str = "set promisc <port_id> on|off: Set promisc mode on port_id",
+ .tokens = {
+ (void *)&cmd_setpromisc_set,
+ (void *)&cmd_setpromisc_promisc,
+ (void *)&cmd_setpromisc_portnum,
+ (void *)&cmd_setpromisc_mode,
+ NULL,
+ },
+};
+
+/* *** SET ALLMULTI MODE *** */
+struct cmd_set_allmulti_mode_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t allmulti;
+ cmdline_fixed_string_t port_all; /* valid if "allports" argument == 1 */
+ uint8_t port_num; /* valid if "allports" argument == 0 */
+ cmdline_fixed_string_t mode;
+};
+
+static void cmd_set_allmulti_mode_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ void *allports)
+{
+ struct cmd_set_allmulti_mode_result *res = parsed_result;
+ int enable;
+ portid_t i;
+
+ if (!strcmp(res->mode, "on"))
+ enable = 1;
+ else
+ enable = 0;
+
+ /* all ports */
+ if (allports) {
+ RTE_ETH_FOREACH_DEV(i) {
+ if (enable)
+ rte_eth_allmulticast_enable(i);
+ else
+ rte_eth_allmulticast_disable(i);
+ }
+ }
+ else {
+ if (enable)
+ rte_eth_allmulticast_enable(res->port_num);
+ else
+ rte_eth_allmulticast_disable(res->port_num);
+ }
+}
+
+cmdline_parse_token_string_t cmd_setallmulti_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_allmulti_mode_result, set, "set");
+cmdline_parse_token_string_t cmd_setallmulti_allmulti =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_allmulti_mode_result, allmulti,
+ "allmulti");
+cmdline_parse_token_string_t cmd_setallmulti_portall =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_allmulti_mode_result, port_all,
+ "all");
+cmdline_parse_token_num_t cmd_setallmulti_portnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_allmulti_mode_result, port_num,
+ UINT8);
+cmdline_parse_token_string_t cmd_setallmulti_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_allmulti_mode_result, mode,
+ "on#off");
+
+cmdline_parse_inst_t cmd_set_allmulti_mode_all = {
+ .f = cmd_set_allmulti_mode_parsed,
+ .data = (void *)1,
+ .help_str = "set allmulti all on|off: Set allmulti mode for all ports",
+ .tokens = {
+ (void *)&cmd_setallmulti_set,
+ (void *)&cmd_setallmulti_allmulti,
+ (void *)&cmd_setallmulti_portall,
+ (void *)&cmd_setallmulti_mode,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_set_allmulti_mode_one = {
+ .f = cmd_set_allmulti_mode_parsed,
+ .data = (void *)0,
+ .help_str = "set allmulti <port_id> on|off: "
+ "Set allmulti mode on port_id",
+ .tokens = {
+ (void *)&cmd_setallmulti_set,
+ (void *)&cmd_setallmulti_allmulti,
+ (void *)&cmd_setallmulti_portnum,
+ (void *)&cmd_setallmulti_mode,
+ NULL,
+ },
+};
+
+/* *** SETUP ETHERNET LINK FLOW CONTROL *** */
+struct cmd_link_flow_ctrl_set_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t flow_ctrl;
+ cmdline_fixed_string_t rx;
+ cmdline_fixed_string_t rx_lfc_mode;
+ cmdline_fixed_string_t tx;
+ cmdline_fixed_string_t tx_lfc_mode;
+ cmdline_fixed_string_t mac_ctrl_frame_fwd;
+ cmdline_fixed_string_t mac_ctrl_frame_fwd_mode;
+ cmdline_fixed_string_t autoneg_str;
+ cmdline_fixed_string_t autoneg;
+ cmdline_fixed_string_t hw_str;
+ uint32_t high_water;
+ cmdline_fixed_string_t lw_str;
+ uint32_t low_water;
+ cmdline_fixed_string_t pt_str;
+ uint16_t pause_time;
+ cmdline_fixed_string_t xon_str;
+ uint16_t send_xon;
+ uint8_t port_id;
+};
+
+cmdline_parse_token_string_t cmd_lfc_set_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_lfc_set_flow_ctrl =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ flow_ctrl, "flow_ctrl");
+cmdline_parse_token_string_t cmd_lfc_set_rx =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ rx, "rx");
+cmdline_parse_token_string_t cmd_lfc_set_rx_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ rx_lfc_mode, "on#off");
+cmdline_parse_token_string_t cmd_lfc_set_tx =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ tx, "tx");
+cmdline_parse_token_string_t cmd_lfc_set_tx_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ tx_lfc_mode, "on#off");
+cmdline_parse_token_string_t cmd_lfc_set_high_water_str =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ hw_str, "high_water");
+cmdline_parse_token_num_t cmd_lfc_set_high_water =
+ TOKEN_NUM_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ high_water, UINT32);
+cmdline_parse_token_string_t cmd_lfc_set_low_water_str =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ lw_str, "low_water");
+cmdline_parse_token_num_t cmd_lfc_set_low_water =
+ TOKEN_NUM_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ low_water, UINT32);
+cmdline_parse_token_string_t cmd_lfc_set_pause_time_str =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ pt_str, "pause_time");
+cmdline_parse_token_num_t cmd_lfc_set_pause_time =
+ TOKEN_NUM_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ pause_time, UINT16);
+cmdline_parse_token_string_t cmd_lfc_set_send_xon_str =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ xon_str, "send_xon");
+cmdline_parse_token_num_t cmd_lfc_set_send_xon =
+ TOKEN_NUM_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ send_xon, UINT16);
+cmdline_parse_token_string_t cmd_lfc_set_mac_ctrl_frame_fwd_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ mac_ctrl_frame_fwd, "mac_ctrl_frame_fwd");
+cmdline_parse_token_string_t cmd_lfc_set_mac_ctrl_frame_fwd =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ mac_ctrl_frame_fwd_mode, "on#off");
+cmdline_parse_token_string_t cmd_lfc_set_autoneg_str =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ autoneg_str, "autoneg");
+cmdline_parse_token_string_t cmd_lfc_set_autoneg =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ autoneg, "on#off");
+cmdline_parse_token_num_t cmd_lfc_set_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ port_id, UINT8);
+
+/* forward declaration */
+static void
+cmd_link_flow_ctrl_set_parsed(void *parsed_result, struct cmdline *cl,
+ void *data);
+
+cmdline_parse_inst_t cmd_link_flow_control_set = {
+ .f = cmd_link_flow_ctrl_set_parsed,
+ .data = NULL,
+ .help_str = "set flow_ctrl rx on|off tx on|off <high_water> "
+ "<low_water> <pause_time> <send_xon> mac_ctrl_frame_fwd on|off "
+ "autoneg on|off <port_id>: Configure the Ethernet flow control",
+ .tokens = {
+ (void *)&cmd_lfc_set_set,
+ (void *)&cmd_lfc_set_flow_ctrl,
+ (void *)&cmd_lfc_set_rx,
+ (void *)&cmd_lfc_set_rx_mode,
+ (void *)&cmd_lfc_set_tx,
+ (void *)&cmd_lfc_set_tx_mode,
+ (void *)&cmd_lfc_set_high_water,
+ (void *)&cmd_lfc_set_low_water,
+ (void *)&cmd_lfc_set_pause_time,
+ (void *)&cmd_lfc_set_send_xon,
+ (void *)&cmd_lfc_set_mac_ctrl_frame_fwd_mode,
+ (void *)&cmd_lfc_set_mac_ctrl_frame_fwd,
+ (void *)&cmd_lfc_set_autoneg_str,
+ (void *)&cmd_lfc_set_autoneg,
+ (void *)&cmd_lfc_set_portid,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_link_flow_control_set_rx = {
+ .f = cmd_link_flow_ctrl_set_parsed,
+ .data = (void *)&cmd_link_flow_control_set_rx,
+ .help_str = "set flow_ctrl rx on|off <port_id>: "
+ "Change rx flow control parameter",
+ .tokens = {
+ (void *)&cmd_lfc_set_set,
+ (void *)&cmd_lfc_set_flow_ctrl,
+ (void *)&cmd_lfc_set_rx,
+ (void *)&cmd_lfc_set_rx_mode,
+ (void *)&cmd_lfc_set_portid,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_link_flow_control_set_tx = {
+ .f = cmd_link_flow_ctrl_set_parsed,
+ .data = (void *)&cmd_link_flow_control_set_tx,
+ .help_str = "set flow_ctrl tx on|off <port_id>: "
+ "Change tx flow control parameter",
+ .tokens = {
+ (void *)&cmd_lfc_set_set,
+ (void *)&cmd_lfc_set_flow_ctrl,
+ (void *)&cmd_lfc_set_tx,
+ (void *)&cmd_lfc_set_tx_mode,
+ (void *)&cmd_lfc_set_portid,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_link_flow_control_set_hw = {
+ .f = cmd_link_flow_ctrl_set_parsed,
+ .data = (void *)&cmd_link_flow_control_set_hw,
+ .help_str = "set flow_ctrl high_water <value> <port_id>: "
+ "Change high water flow control parameter",
+ .tokens = {
+ (void *)&cmd_lfc_set_set,
+ (void *)&cmd_lfc_set_flow_ctrl,
+ (void *)&cmd_lfc_set_high_water_str,
+ (void *)&cmd_lfc_set_high_water,
+ (void *)&cmd_lfc_set_portid,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_link_flow_control_set_lw = {
+ .f = cmd_link_flow_ctrl_set_parsed,
+ .data = (void *)&cmd_link_flow_control_set_lw,
+ .help_str = "set flow_ctrl low_water <value> <port_id>: "
+ "Change low water flow control parameter",
+ .tokens = {
+ (void *)&cmd_lfc_set_set,
+ (void *)&cmd_lfc_set_flow_ctrl,
+ (void *)&cmd_lfc_set_low_water_str,
+ (void *)&cmd_lfc_set_low_water,
+ (void *)&cmd_lfc_set_portid,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_link_flow_control_set_pt = {
+ .f = cmd_link_flow_ctrl_set_parsed,
+ .data = (void *)&cmd_link_flow_control_set_pt,
+ .help_str = "set flow_ctrl pause_time <value> <port_id>: "
+ "Change pause time flow control parameter",
+ .tokens = {
+ (void *)&cmd_lfc_set_set,
+ (void *)&cmd_lfc_set_flow_ctrl,
+ (void *)&cmd_lfc_set_pause_time_str,
+ (void *)&cmd_lfc_set_pause_time,
+ (void *)&cmd_lfc_set_portid,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_link_flow_control_set_xon = {
+ .f = cmd_link_flow_ctrl_set_parsed,
+ .data = (void *)&cmd_link_flow_control_set_xon,
+ .help_str = "set flow_ctrl send_xon <value> <port_id>: "
+ "Change send_xon flow control parameter",
+ .tokens = {
+ (void *)&cmd_lfc_set_set,
+ (void *)&cmd_lfc_set_flow_ctrl,
+ (void *)&cmd_lfc_set_send_xon_str,
+ (void *)&cmd_lfc_set_send_xon,
+ (void *)&cmd_lfc_set_portid,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_link_flow_control_set_macfwd = {
+ .f = cmd_link_flow_ctrl_set_parsed,
+ .data = (void *)&cmd_link_flow_control_set_macfwd,
+ .help_str = "set flow_ctrl mac_ctrl_frame_fwd on|off <port_id>: "
+ "Change mac ctrl fwd flow control parameter",
+ .tokens = {
+ (void *)&cmd_lfc_set_set,
+ (void *)&cmd_lfc_set_flow_ctrl,
+ (void *)&cmd_lfc_set_mac_ctrl_frame_fwd_mode,
+ (void *)&cmd_lfc_set_mac_ctrl_frame_fwd,
+ (void *)&cmd_lfc_set_portid,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_link_flow_control_set_autoneg = {
+ .f = cmd_link_flow_ctrl_set_parsed,
+ .data = (void *)&cmd_link_flow_control_set_autoneg,
+ .help_str = "set flow_ctrl autoneg on|off <port_id>: "
+ "Change autoneg flow control parameter",
+ .tokens = {
+ (void *)&cmd_lfc_set_set,
+ (void *)&cmd_lfc_set_flow_ctrl,
+ (void *)&cmd_lfc_set_autoneg_str,
+ (void *)&cmd_lfc_set_autoneg,
+ (void *)&cmd_lfc_set_portid,
+ NULL,
+ },
+};
+
+static void
+cmd_link_flow_ctrl_set_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ void *data)
+{
+ struct cmd_link_flow_ctrl_set_result *res = parsed_result;
+ cmdline_parse_inst_t *cmd = data;
+ struct rte_eth_fc_conf fc_conf;
+ int rx_fc_en = 0;
+ int tx_fc_en = 0;
+ int ret;
+
+ /*
+ * Rx on/off, flow control is enabled/disabled on RX side. This can indicate
+ * the RTE_FC_TX_PAUSE, Transmit pause frame at the Rx side.
+ * Tx on/off, flow control is enabled/disabled on TX side. This can indicate
+ * the RTE_FC_RX_PAUSE, Respond to the pause frame at the Tx side.
+ */
+ static enum rte_eth_fc_mode rx_tx_onoff_2_lfc_mode[2][2] = {
+ {RTE_FC_NONE, RTE_FC_TX_PAUSE}, {RTE_FC_RX_PAUSE, RTE_FC_FULL}
+ };
+
+ /* Partial command line, retrieve current configuration */
+ if (cmd) {
+ ret = rte_eth_dev_flow_ctrl_get(res->port_id, &fc_conf);
+ if (ret != 0) {
+ printf("cannot get current flow ctrl parameters, return"
+ "code = %d\n", ret);
+ return;
+ }
+
+ if ((fc_conf.mode == RTE_FC_RX_PAUSE) ||
+ (fc_conf.mode == RTE_FC_FULL))
+ rx_fc_en = 1;
+ if ((fc_conf.mode == RTE_FC_TX_PAUSE) ||
+ (fc_conf.mode == RTE_FC_FULL))
+ tx_fc_en = 1;
+ }
+
+ if (!cmd || cmd == &cmd_link_flow_control_set_rx)
+ rx_fc_en = (!strcmp(res->rx_lfc_mode, "on")) ? 1 : 0;
+
+ if (!cmd || cmd == &cmd_link_flow_control_set_tx)
+ tx_fc_en = (!strcmp(res->tx_lfc_mode, "on")) ? 1 : 0;
+
+ fc_conf.mode = rx_tx_onoff_2_lfc_mode[rx_fc_en][tx_fc_en];
+
+ if (!cmd || cmd == &cmd_link_flow_control_set_hw)
+ fc_conf.high_water = res->high_water;
+
+ if (!cmd || cmd == &cmd_link_flow_control_set_lw)
+ fc_conf.low_water = res->low_water;
+
+ if (!cmd || cmd == &cmd_link_flow_control_set_pt)
+ fc_conf.pause_time = res->pause_time;
+
+ if (!cmd || cmd == &cmd_link_flow_control_set_xon)
+ fc_conf.send_xon = res->send_xon;
+
+ if (!cmd || cmd == &cmd_link_flow_control_set_macfwd) {
+ if (!strcmp(res->mac_ctrl_frame_fwd_mode, "on"))
+ fc_conf.mac_ctrl_frame_fwd = 1;
+ else
+ fc_conf.mac_ctrl_frame_fwd = 0;
+ }
+
+ if (!cmd || cmd == &cmd_link_flow_control_set_autoneg)
+ fc_conf.autoneg = (!strcmp(res->autoneg, "on")) ? 1 : 0;
+
+ ret = rte_eth_dev_flow_ctrl_set(res->port_id, &fc_conf);
+ if (ret != 0)
+ printf("bad flow contrl parameter, return code = %d \n", ret);
+}
+
+/* *** SETUP ETHERNET PRIORITY FLOW CONTROL *** */
+struct cmd_priority_flow_ctrl_set_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t pfc_ctrl;
+ cmdline_fixed_string_t rx;
+ cmdline_fixed_string_t rx_pfc_mode;
+ cmdline_fixed_string_t tx;
+ cmdline_fixed_string_t tx_pfc_mode;
+ uint32_t high_water;
+ uint32_t low_water;
+ uint16_t pause_time;
+ uint8_t priority;
+ uint8_t port_id;
+};
+
+static void
+cmd_priority_flow_ctrl_set_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_priority_flow_ctrl_set_result *res = parsed_result;
+ struct rte_eth_pfc_conf pfc_conf;
+ int rx_fc_enable, tx_fc_enable;
+ int ret;
+
+ /*
+ * Rx on/off, flow control is enabled/disabled on RX side. This can indicate
+ * the RTE_FC_TX_PAUSE, Transmit pause frame at the Rx side.
+ * Tx on/off, flow control is enabled/disabled on TX side. This can indicate
+ * the RTE_FC_RX_PAUSE, Respond to the pause frame at the Tx side.
+ */
+ static enum rte_eth_fc_mode rx_tx_onoff_2_pfc_mode[2][2] = {
+ {RTE_FC_NONE, RTE_FC_RX_PAUSE}, {RTE_FC_TX_PAUSE, RTE_FC_FULL}
+ };
+
+ rx_fc_enable = (!strncmp(res->rx_pfc_mode, "on",2)) ? 1 : 0;
+ tx_fc_enable = (!strncmp(res->tx_pfc_mode, "on",2)) ? 1 : 0;
+ pfc_conf.fc.mode = rx_tx_onoff_2_pfc_mode[rx_fc_enable][tx_fc_enable];
+ pfc_conf.fc.high_water = res->high_water;
+ pfc_conf.fc.low_water = res->low_water;
+ pfc_conf.fc.pause_time = res->pause_time;
+ pfc_conf.priority = res->priority;
+
+ ret = rte_eth_dev_priority_flow_ctrl_set(res->port_id, &pfc_conf);
+ if (ret != 0)
+ printf("bad priority flow contrl parameter, return code = %d \n", ret);
+}
+
+cmdline_parse_token_string_t cmd_pfc_set_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_priority_flow_ctrl_set_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_pfc_set_flow_ctrl =
+ TOKEN_STRING_INITIALIZER(struct cmd_priority_flow_ctrl_set_result,
+ pfc_ctrl, "pfc_ctrl");
+cmdline_parse_token_string_t cmd_pfc_set_rx =
+ TOKEN_STRING_INITIALIZER(struct cmd_priority_flow_ctrl_set_result,
+ rx, "rx");
+cmdline_parse_token_string_t cmd_pfc_set_rx_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_priority_flow_ctrl_set_result,
+ rx_pfc_mode, "on#off");
+cmdline_parse_token_string_t cmd_pfc_set_tx =
+ TOKEN_STRING_INITIALIZER(struct cmd_priority_flow_ctrl_set_result,
+ tx, "tx");
+cmdline_parse_token_string_t cmd_pfc_set_tx_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_priority_flow_ctrl_set_result,
+ tx_pfc_mode, "on#off");
+cmdline_parse_token_num_t cmd_pfc_set_high_water =
+ TOKEN_NUM_INITIALIZER(struct cmd_priority_flow_ctrl_set_result,
+ high_water, UINT32);
+cmdline_parse_token_num_t cmd_pfc_set_low_water =
+ TOKEN_NUM_INITIALIZER(struct cmd_priority_flow_ctrl_set_result,
+ low_water, UINT32);
+cmdline_parse_token_num_t cmd_pfc_set_pause_time =
+ TOKEN_NUM_INITIALIZER(struct cmd_priority_flow_ctrl_set_result,
+ pause_time, UINT16);
+cmdline_parse_token_num_t cmd_pfc_set_priority =
+ TOKEN_NUM_INITIALIZER(struct cmd_priority_flow_ctrl_set_result,
+ priority, UINT8);
+cmdline_parse_token_num_t cmd_pfc_set_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_priority_flow_ctrl_set_result,
+ port_id, UINT8);
+
+cmdline_parse_inst_t cmd_priority_flow_control_set = {
+ .f = cmd_priority_flow_ctrl_set_parsed,
+ .data = NULL,
+ .help_str = "set pfc_ctrl rx on|off tx on|off <high_water> <low_water> "
+ "<pause_time> <priority> <port_id>: "
+ "Configure the Ethernet priority flow control",
+ .tokens = {
+ (void *)&cmd_pfc_set_set,
+ (void *)&cmd_pfc_set_flow_ctrl,
+ (void *)&cmd_pfc_set_rx,
+ (void *)&cmd_pfc_set_rx_mode,
+ (void *)&cmd_pfc_set_tx,
+ (void *)&cmd_pfc_set_tx_mode,
+ (void *)&cmd_pfc_set_high_water,
+ (void *)&cmd_pfc_set_low_water,
+ (void *)&cmd_pfc_set_pause_time,
+ (void *)&cmd_pfc_set_priority,
+ (void *)&cmd_pfc_set_portid,
+ NULL,
+ },
+};
+
+/* *** RESET CONFIGURATION *** */
+struct cmd_reset_result {
+ cmdline_fixed_string_t reset;
+ cmdline_fixed_string_t def;
+};
+
+static void cmd_reset_parsed(__attribute__((unused)) void *parsed_result,
+ struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ cmdline_printf(cl, "Reset to default forwarding configuration...\n");
+ set_def_fwd_config();
+}
+
+cmdline_parse_token_string_t cmd_reset_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_reset_result, reset, "set");
+cmdline_parse_token_string_t cmd_reset_def =
+ TOKEN_STRING_INITIALIZER(struct cmd_reset_result, def,
+ "default");
+
+cmdline_parse_inst_t cmd_reset = {
+ .f = cmd_reset_parsed,
+ .data = NULL,
+ .help_str = "set default: Reset default forwarding configuration",
+ .tokens = {
+ (void *)&cmd_reset_set,
+ (void *)&cmd_reset_def,
+ NULL,
+ },
+};
+
+/* *** START FORWARDING *** */
+struct cmd_start_result {
+ cmdline_fixed_string_t start;
+};
+
+cmdline_parse_token_string_t cmd_start_start =
+ TOKEN_STRING_INITIALIZER(struct cmd_start_result, start, "start");
+
+static void cmd_start_parsed(__attribute__((unused)) void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ start_packet_forwarding(0);
+}
+
+cmdline_parse_inst_t cmd_start = {
+ .f = cmd_start_parsed,
+ .data = NULL,
+ .help_str = "start: Start packet forwarding",
+ .tokens = {
+ (void *)&cmd_start_start,
+ NULL,
+ },
+};
+
+/* *** START FORWARDING WITH ONE TX BURST FIRST *** */
+struct cmd_start_tx_first_result {
+ cmdline_fixed_string_t start;
+ cmdline_fixed_string_t tx_first;
+};
+
+static void
+cmd_start_tx_first_parsed(__attribute__((unused)) void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ start_packet_forwarding(1);
+}
+
+cmdline_parse_token_string_t cmd_start_tx_first_start =
+ TOKEN_STRING_INITIALIZER(struct cmd_start_tx_first_result, start,
+ "start");
+cmdline_parse_token_string_t cmd_start_tx_first_tx_first =
+ TOKEN_STRING_INITIALIZER(struct cmd_start_tx_first_result,
+ tx_first, "tx_first");
+
+cmdline_parse_inst_t cmd_start_tx_first = {
+ .f = cmd_start_tx_first_parsed,
+ .data = NULL,
+ .help_str = "start tx_first: Start packet forwarding, "
+ "after sending 1 burst of packets",
+ .tokens = {
+ (void *)&cmd_start_tx_first_start,
+ (void *)&cmd_start_tx_first_tx_first,
+ NULL,
+ },
+};
+
+/* *** START FORWARDING WITH N TX BURST FIRST *** */
+struct cmd_start_tx_first_n_result {
+ cmdline_fixed_string_t start;
+ cmdline_fixed_string_t tx_first;
+ uint32_t tx_num;
+};
+
+static void
+cmd_start_tx_first_n_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_start_tx_first_n_result *res = parsed_result;
+
+ start_packet_forwarding(res->tx_num);
+}
+
+cmdline_parse_token_string_t cmd_start_tx_first_n_start =
+ TOKEN_STRING_INITIALIZER(struct cmd_start_tx_first_n_result,
+ start, "start");
+cmdline_parse_token_string_t cmd_start_tx_first_n_tx_first =
+ TOKEN_STRING_INITIALIZER(struct cmd_start_tx_first_n_result,
+ tx_first, "tx_first");
+cmdline_parse_token_num_t cmd_start_tx_first_n_tx_num =
+ TOKEN_NUM_INITIALIZER(struct cmd_start_tx_first_n_result,
+ tx_num, UINT32);
+
+cmdline_parse_inst_t cmd_start_tx_first_n = {
+ .f = cmd_start_tx_first_n_parsed,
+ .data = NULL,
+ .help_str = "start tx_first <num>: "
+ "packet forwarding, after sending <num> bursts of packets",
+ .tokens = {
+ (void *)&cmd_start_tx_first_n_start,
+ (void *)&cmd_start_tx_first_n_tx_first,
+ (void *)&cmd_start_tx_first_n_tx_num,
+ NULL,
+ },
+};
+
+/* *** SET LINK UP *** */
+struct cmd_set_link_up_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t link_up;
+ cmdline_fixed_string_t port;
+ uint8_t port_id;
+};
+
+cmdline_parse_token_string_t cmd_set_link_up_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_link_up_result, set, "set");
+cmdline_parse_token_string_t cmd_set_link_up_link_up =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_link_up_result, link_up,
+ "link-up");
+cmdline_parse_token_string_t cmd_set_link_up_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_link_up_result, port, "port");
+cmdline_parse_token_num_t cmd_set_link_up_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_link_up_result, port_id, UINT8);
+
+static void cmd_set_link_up_parsed(__attribute__((unused)) void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_link_up_result *res = parsed_result;
+ dev_set_link_up(res->port_id);
+}
+
+cmdline_parse_inst_t cmd_set_link_up = {
+ .f = cmd_set_link_up_parsed,
+ .data = NULL,
+ .help_str = "set link-up port <port id>",
+ .tokens = {
+ (void *)&cmd_set_link_up_set,
+ (void *)&cmd_set_link_up_link_up,
+ (void *)&cmd_set_link_up_port,
+ (void *)&cmd_set_link_up_port_id,
+ NULL,
+ },
+};
+
+/* *** SET LINK DOWN *** */
+struct cmd_set_link_down_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t link_down;
+ cmdline_fixed_string_t port;
+ uint8_t port_id;
+};
+
+cmdline_parse_token_string_t cmd_set_link_down_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_link_down_result, set, "set");
+cmdline_parse_token_string_t cmd_set_link_down_link_down =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_link_down_result, link_down,
+ "link-down");
+cmdline_parse_token_string_t cmd_set_link_down_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_link_down_result, port, "port");
+cmdline_parse_token_num_t cmd_set_link_down_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_link_down_result, port_id, UINT8);
+
+static void cmd_set_link_down_parsed(
+ __attribute__((unused)) void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_link_down_result *res = parsed_result;
+ dev_set_link_down(res->port_id);
+}
+
+cmdline_parse_inst_t cmd_set_link_down = {
+ .f = cmd_set_link_down_parsed,
+ .data = NULL,
+ .help_str = "set link-down port <port id>",
+ .tokens = {
+ (void *)&cmd_set_link_down_set,
+ (void *)&cmd_set_link_down_link_down,
+ (void *)&cmd_set_link_down_port,
+ (void *)&cmd_set_link_down_port_id,
+ NULL,
+ },
+};
+
+/* *** SHOW CFG *** */
+struct cmd_showcfg_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t cfg;
+ cmdline_fixed_string_t what;
+};
+
+static void cmd_showcfg_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_showcfg_result *res = parsed_result;
+ if (!strcmp(res->what, "rxtx"))
+ rxtx_config_display();
+ else if (!strcmp(res->what, "cores"))
+ fwd_lcores_config_display();
+ else if (!strcmp(res->what, "fwd"))
+ pkt_fwd_config_display(&cur_fwd_config);
+ else if (!strcmp(res->what, "txpkts"))
+ show_tx_pkt_segments();
+}
+
+cmdline_parse_token_string_t cmd_showcfg_show =
+ TOKEN_STRING_INITIALIZER(struct cmd_showcfg_result, show, "show");
+cmdline_parse_token_string_t cmd_showcfg_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_showcfg_result, cfg, "config");
+cmdline_parse_token_string_t cmd_showcfg_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_showcfg_result, what,
+ "rxtx#cores#fwd#txpkts");
+
+cmdline_parse_inst_t cmd_showcfg = {
+ .f = cmd_showcfg_parsed,
+ .data = NULL,
+ .help_str = "show config rxtx|cores|fwd|txpkts",
+ .tokens = {
+ (void *)&cmd_showcfg_show,
+ (void *)&cmd_showcfg_port,
+ (void *)&cmd_showcfg_what,
+ NULL,
+ },
+};
+
+/* *** SHOW ALL PORT INFO *** */
+struct cmd_showportall_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t what;
+ cmdline_fixed_string_t all;
+};
+
+static void cmd_showportall_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ portid_t i;
+
+ struct cmd_showportall_result *res = parsed_result;
+ if (!strcmp(res->show, "clear")) {
+ if (!strcmp(res->what, "stats"))
+ RTE_ETH_FOREACH_DEV(i)
+ nic_stats_clear(i);
+ else if (!strcmp(res->what, "xstats"))
+ RTE_ETH_FOREACH_DEV(i)
+ nic_xstats_clear(i);
+ } else if (!strcmp(res->what, "info"))
+ RTE_ETH_FOREACH_DEV(i)
+ port_infos_display(i);
+ else if (!strcmp(res->what, "stats"))
+ RTE_ETH_FOREACH_DEV(i)
+ nic_stats_display(i);
+ else if (!strcmp(res->what, "xstats"))
+ RTE_ETH_FOREACH_DEV(i)
+ nic_xstats_display(i);
+ else if (!strcmp(res->what, "fdir"))
+ RTE_ETH_FOREACH_DEV(i)
+ fdir_get_infos(i);
+ else if (!strcmp(res->what, "stat_qmap"))
+ RTE_ETH_FOREACH_DEV(i)
+ nic_stats_mapping_display(i);
+ else if (!strcmp(res->what, "dcb_tc"))
+ RTE_ETH_FOREACH_DEV(i)
+ port_dcb_info_display(i);
+ else if (!strcmp(res->what, "cap"))
+ RTE_ETH_FOREACH_DEV(i)
+ port_offload_cap_display(i);
+}
+
+cmdline_parse_token_string_t cmd_showportall_show =
+ TOKEN_STRING_INITIALIZER(struct cmd_showportall_result, show,
+ "show#clear");
+cmdline_parse_token_string_t cmd_showportall_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_showportall_result, port, "port");
+cmdline_parse_token_string_t cmd_showportall_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_showportall_result, what,
+ "info#stats#xstats#fdir#stat_qmap#dcb_tc#cap");
+cmdline_parse_token_string_t cmd_showportall_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_showportall_result, all, "all");
+cmdline_parse_inst_t cmd_showportall = {
+ .f = cmd_showportall_parsed,
+ .data = NULL,
+ .help_str = "show|clear port "
+ "info|stats|xstats|fdir|stat_qmap|dcb_tc|cap all",
+ .tokens = {
+ (void *)&cmd_showportall_show,
+ (void *)&cmd_showportall_port,
+ (void *)&cmd_showportall_what,
+ (void *)&cmd_showportall_all,
+ NULL,
+ },
+};
+
+/* *** SHOW PORT INFO *** */
+struct cmd_showport_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t what;
+ uint8_t portnum;
+};
+
+static void cmd_showport_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_showport_result *res = parsed_result;
+ if (!strcmp(res->show, "clear")) {
+ if (!strcmp(res->what, "stats"))
+ nic_stats_clear(res->portnum);
+ else if (!strcmp(res->what, "xstats"))
+ nic_xstats_clear(res->portnum);
+ } else if (!strcmp(res->what, "info"))
+ port_infos_display(res->portnum);
+ else if (!strcmp(res->what, "stats"))
+ nic_stats_display(res->portnum);
+ else if (!strcmp(res->what, "xstats"))
+ nic_xstats_display(res->portnum);
+ else if (!strcmp(res->what, "fdir"))
+ fdir_get_infos(res->portnum);
+ else if (!strcmp(res->what, "stat_qmap"))
+ nic_stats_mapping_display(res->portnum);
+ else if (!strcmp(res->what, "dcb_tc"))
+ port_dcb_info_display(res->portnum);
+ else if (!strcmp(res->what, "cap"))
+ port_offload_cap_display(res->portnum);
+}
+
+cmdline_parse_token_string_t cmd_showport_show =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_result, show,
+ "show#clear");
+cmdline_parse_token_string_t cmd_showport_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_result, port, "port");
+cmdline_parse_token_string_t cmd_showport_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_result, what,
+ "info#stats#xstats#fdir#stat_qmap#dcb_tc#cap");
+cmdline_parse_token_num_t cmd_showport_portnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_showport_result, portnum, UINT8);
+
+cmdline_parse_inst_t cmd_showport = {
+ .f = cmd_showport_parsed,
+ .data = NULL,
+ .help_str = "show|clear port "
+ "info|stats|xstats|fdir|stat_qmap|dcb_tc|cap "
+ "<port_id>",
+ .tokens = {
+ (void *)&cmd_showport_show,
+ (void *)&cmd_showport_port,
+ (void *)&cmd_showport_what,
+ (void *)&cmd_showport_portnum,
+ NULL,
+ },
+};
+
+/* *** SHOW QUEUE INFO *** */
+struct cmd_showqueue_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t type;
+ cmdline_fixed_string_t what;
+ uint8_t portnum;
+ uint16_t queuenum;
+};
+
+static void
+cmd_showqueue_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_showqueue_result *res = parsed_result;
+
+ if (!strcmp(res->type, "rxq"))
+ rx_queue_infos_display(res->portnum, res->queuenum);
+ else if (!strcmp(res->type, "txq"))
+ tx_queue_infos_display(res->portnum, res->queuenum);
+}
+
+cmdline_parse_token_string_t cmd_showqueue_show =
+ TOKEN_STRING_INITIALIZER(struct cmd_showqueue_result, show, "show");
+cmdline_parse_token_string_t cmd_showqueue_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_showqueue_result, type, "rxq#txq");
+cmdline_parse_token_string_t cmd_showqueue_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_showqueue_result, what, "info");
+cmdline_parse_token_num_t cmd_showqueue_portnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_showqueue_result, portnum, UINT8);
+cmdline_parse_token_num_t cmd_showqueue_queuenum =
+ TOKEN_NUM_INITIALIZER(struct cmd_showqueue_result, queuenum, UINT16);
+
+cmdline_parse_inst_t cmd_showqueue = {
+ .f = cmd_showqueue_parsed,
+ .data = NULL,
+ .help_str = "show rxq|txq info <port_id> <queue_id>",
+ .tokens = {
+ (void *)&cmd_showqueue_show,
+ (void *)&cmd_showqueue_type,
+ (void *)&cmd_showqueue_what,
+ (void *)&cmd_showqueue_portnum,
+ (void *)&cmd_showqueue_queuenum,
+ NULL,
+ },
+};
+
+/* *** READ PORT REGISTER *** */
+struct cmd_read_reg_result {
+ cmdline_fixed_string_t read;
+ cmdline_fixed_string_t reg;
+ uint8_t port_id;
+ uint32_t reg_off;
+};
+
+static void
+cmd_read_reg_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_read_reg_result *res = parsed_result;
+ port_reg_display(res->port_id, res->reg_off);
+}
+
+cmdline_parse_token_string_t cmd_read_reg_read =
+ TOKEN_STRING_INITIALIZER(struct cmd_read_reg_result, read, "read");
+cmdline_parse_token_string_t cmd_read_reg_reg =
+ TOKEN_STRING_INITIALIZER(struct cmd_read_reg_result, reg, "reg");
+cmdline_parse_token_num_t cmd_read_reg_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_read_reg_result, port_id, UINT8);
+cmdline_parse_token_num_t cmd_read_reg_reg_off =
+ TOKEN_NUM_INITIALIZER(struct cmd_read_reg_result, reg_off, UINT32);
+
+cmdline_parse_inst_t cmd_read_reg = {
+ .f = cmd_read_reg_parsed,
+ .data = NULL,
+ .help_str = "read reg <port_id> <reg_off>",
+ .tokens = {
+ (void *)&cmd_read_reg_read,
+ (void *)&cmd_read_reg_reg,
+ (void *)&cmd_read_reg_port_id,
+ (void *)&cmd_read_reg_reg_off,
+ NULL,
+ },
+};
+
+/* *** READ PORT REGISTER BIT FIELD *** */
+struct cmd_read_reg_bit_field_result {
+ cmdline_fixed_string_t read;
+ cmdline_fixed_string_t regfield;
+ uint8_t port_id;
+ uint32_t reg_off;
+ uint8_t bit1_pos;
+ uint8_t bit2_pos;
+};
+
+static void
+cmd_read_reg_bit_field_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_read_reg_bit_field_result *res = parsed_result;
+ port_reg_bit_field_display(res->port_id, res->reg_off,
+ res->bit1_pos, res->bit2_pos);
+}
+
+cmdline_parse_token_string_t cmd_read_reg_bit_field_read =
+ TOKEN_STRING_INITIALIZER(struct cmd_read_reg_bit_field_result, read,
+ "read");
+cmdline_parse_token_string_t cmd_read_reg_bit_field_regfield =
+ TOKEN_STRING_INITIALIZER(struct cmd_read_reg_bit_field_result,
+ regfield, "regfield");
+cmdline_parse_token_num_t cmd_read_reg_bit_field_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_read_reg_bit_field_result, port_id,
+ UINT8);
+cmdline_parse_token_num_t cmd_read_reg_bit_field_reg_off =
+ TOKEN_NUM_INITIALIZER(struct cmd_read_reg_bit_field_result, reg_off,
+ UINT32);
+cmdline_parse_token_num_t cmd_read_reg_bit_field_bit1_pos =
+ TOKEN_NUM_INITIALIZER(struct cmd_read_reg_bit_field_result, bit1_pos,
+ UINT8);
+cmdline_parse_token_num_t cmd_read_reg_bit_field_bit2_pos =
+ TOKEN_NUM_INITIALIZER(struct cmd_read_reg_bit_field_result, bit2_pos,
+ UINT8);
+
+cmdline_parse_inst_t cmd_read_reg_bit_field = {
+ .f = cmd_read_reg_bit_field_parsed,
+ .data = NULL,
+ .help_str = "read regfield <port_id> <reg_off> <bit_x> <bit_y>: "
+ "Read register bit field between bit_x and bit_y included",
+ .tokens = {
+ (void *)&cmd_read_reg_bit_field_read,
+ (void *)&cmd_read_reg_bit_field_regfield,
+ (void *)&cmd_read_reg_bit_field_port_id,
+ (void *)&cmd_read_reg_bit_field_reg_off,
+ (void *)&cmd_read_reg_bit_field_bit1_pos,
+ (void *)&cmd_read_reg_bit_field_bit2_pos,
+ NULL,
+ },
+};
+
+/* *** READ PORT REGISTER BIT *** */
+struct cmd_read_reg_bit_result {
+ cmdline_fixed_string_t read;
+ cmdline_fixed_string_t regbit;
+ uint8_t port_id;
+ uint32_t reg_off;
+ uint8_t bit_pos;
+};
+
+static void
+cmd_read_reg_bit_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_read_reg_bit_result *res = parsed_result;
+ port_reg_bit_display(res->port_id, res->reg_off, res->bit_pos);
+}
+
+cmdline_parse_token_string_t cmd_read_reg_bit_read =
+ TOKEN_STRING_INITIALIZER(struct cmd_read_reg_bit_result, read, "read");
+cmdline_parse_token_string_t cmd_read_reg_bit_regbit =
+ TOKEN_STRING_INITIALIZER(struct cmd_read_reg_bit_result,
+ regbit, "regbit");
+cmdline_parse_token_num_t cmd_read_reg_bit_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_read_reg_bit_result, port_id, UINT8);
+cmdline_parse_token_num_t cmd_read_reg_bit_reg_off =
+ TOKEN_NUM_INITIALIZER(struct cmd_read_reg_bit_result, reg_off, UINT32);
+cmdline_parse_token_num_t cmd_read_reg_bit_bit_pos =
+ TOKEN_NUM_INITIALIZER(struct cmd_read_reg_bit_result, bit_pos, UINT8);
+
+cmdline_parse_inst_t cmd_read_reg_bit = {
+ .f = cmd_read_reg_bit_parsed,
+ .data = NULL,
+ .help_str = "read regbit <port_id> <reg_off> <bit_x>: 0 <= bit_x <= 31",
+ .tokens = {
+ (void *)&cmd_read_reg_bit_read,
+ (void *)&cmd_read_reg_bit_regbit,
+ (void *)&cmd_read_reg_bit_port_id,
+ (void *)&cmd_read_reg_bit_reg_off,
+ (void *)&cmd_read_reg_bit_bit_pos,
+ NULL,
+ },
+};
+
+/* *** WRITE PORT REGISTER *** */
+struct cmd_write_reg_result {
+ cmdline_fixed_string_t write;
+ cmdline_fixed_string_t reg;
+ uint8_t port_id;
+ uint32_t reg_off;
+ uint32_t value;
+};
+
+static void
+cmd_write_reg_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_write_reg_result *res = parsed_result;
+ port_reg_set(res->port_id, res->reg_off, res->value);
+}
+
+cmdline_parse_token_string_t cmd_write_reg_write =
+ TOKEN_STRING_INITIALIZER(struct cmd_write_reg_result, write, "write");
+cmdline_parse_token_string_t cmd_write_reg_reg =
+ TOKEN_STRING_INITIALIZER(struct cmd_write_reg_result, reg, "reg");
+cmdline_parse_token_num_t cmd_write_reg_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_write_reg_result, port_id, UINT8);
+cmdline_parse_token_num_t cmd_write_reg_reg_off =
+ TOKEN_NUM_INITIALIZER(struct cmd_write_reg_result, reg_off, UINT32);
+cmdline_parse_token_num_t cmd_write_reg_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_write_reg_result, value, UINT32);
+
+cmdline_parse_inst_t cmd_write_reg = {
+ .f = cmd_write_reg_parsed,
+ .data = NULL,
+ .help_str = "write reg <port_id> <reg_off> <reg_value>",
+ .tokens = {
+ (void *)&cmd_write_reg_write,
+ (void *)&cmd_write_reg_reg,
+ (void *)&cmd_write_reg_port_id,
+ (void *)&cmd_write_reg_reg_off,
+ (void *)&cmd_write_reg_value,
+ NULL,
+ },
+};
+
+/* *** WRITE PORT REGISTER BIT FIELD *** */
+struct cmd_write_reg_bit_field_result {
+ cmdline_fixed_string_t write;
+ cmdline_fixed_string_t regfield;
+ uint8_t port_id;
+ uint32_t reg_off;
+ uint8_t bit1_pos;
+ uint8_t bit2_pos;
+ uint32_t value;
+};
+
+static void
+cmd_write_reg_bit_field_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_write_reg_bit_field_result *res = parsed_result;
+ port_reg_bit_field_set(res->port_id, res->reg_off,
+ res->bit1_pos, res->bit2_pos, res->value);
+}
+
+cmdline_parse_token_string_t cmd_write_reg_bit_field_write =
+ TOKEN_STRING_INITIALIZER(struct cmd_write_reg_bit_field_result, write,
+ "write");
+cmdline_parse_token_string_t cmd_write_reg_bit_field_regfield =
+ TOKEN_STRING_INITIALIZER(struct cmd_write_reg_bit_field_result,
+ regfield, "regfield");
+cmdline_parse_token_num_t cmd_write_reg_bit_field_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_write_reg_bit_field_result, port_id,
+ UINT8);
+cmdline_parse_token_num_t cmd_write_reg_bit_field_reg_off =
+ TOKEN_NUM_INITIALIZER(struct cmd_write_reg_bit_field_result, reg_off,
+ UINT32);
+cmdline_parse_token_num_t cmd_write_reg_bit_field_bit1_pos =
+ TOKEN_NUM_INITIALIZER(struct cmd_write_reg_bit_field_result, bit1_pos,
+ UINT8);
+cmdline_parse_token_num_t cmd_write_reg_bit_field_bit2_pos =
+ TOKEN_NUM_INITIALIZER(struct cmd_write_reg_bit_field_result, bit2_pos,
+ UINT8);
+cmdline_parse_token_num_t cmd_write_reg_bit_field_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_write_reg_bit_field_result, value,
+ UINT32);
+
+cmdline_parse_inst_t cmd_write_reg_bit_field = {
+ .f = cmd_write_reg_bit_field_parsed,
+ .data = NULL,
+ .help_str = "write regfield <port_id> <reg_off> <bit_x> <bit_y> "
+ "<reg_value>: "
+ "Set register bit field between bit_x and bit_y included",
+ .tokens = {
+ (void *)&cmd_write_reg_bit_field_write,
+ (void *)&cmd_write_reg_bit_field_regfield,
+ (void *)&cmd_write_reg_bit_field_port_id,
+ (void *)&cmd_write_reg_bit_field_reg_off,
+ (void *)&cmd_write_reg_bit_field_bit1_pos,
+ (void *)&cmd_write_reg_bit_field_bit2_pos,
+ (void *)&cmd_write_reg_bit_field_value,
+ NULL,
+ },
+};
+
+/* *** WRITE PORT REGISTER BIT *** */
+struct cmd_write_reg_bit_result {
+ cmdline_fixed_string_t write;
+ cmdline_fixed_string_t regbit;
+ uint8_t port_id;
+ uint32_t reg_off;
+ uint8_t bit_pos;
+ uint8_t value;
+};
+
+static void
+cmd_write_reg_bit_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_write_reg_bit_result *res = parsed_result;
+ port_reg_bit_set(res->port_id, res->reg_off, res->bit_pos, res->value);
+}
+
+cmdline_parse_token_string_t cmd_write_reg_bit_write =
+ TOKEN_STRING_INITIALIZER(struct cmd_write_reg_bit_result, write,
+ "write");
+cmdline_parse_token_string_t cmd_write_reg_bit_regbit =
+ TOKEN_STRING_INITIALIZER(struct cmd_write_reg_bit_result,
+ regbit, "regbit");
+cmdline_parse_token_num_t cmd_write_reg_bit_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_write_reg_bit_result, port_id, UINT8);
+cmdline_parse_token_num_t cmd_write_reg_bit_reg_off =
+ TOKEN_NUM_INITIALIZER(struct cmd_write_reg_bit_result, reg_off, UINT32);
+cmdline_parse_token_num_t cmd_write_reg_bit_bit_pos =
+ TOKEN_NUM_INITIALIZER(struct cmd_write_reg_bit_result, bit_pos, UINT8);
+cmdline_parse_token_num_t cmd_write_reg_bit_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_write_reg_bit_result, value, UINT8);
+
+cmdline_parse_inst_t cmd_write_reg_bit = {
+ .f = cmd_write_reg_bit_parsed,
+ .data = NULL,
+ .help_str = "write regbit <port_id> <reg_off> <bit_x> 0|1: "
+ "0 <= bit_x <= 31",
+ .tokens = {
+ (void *)&cmd_write_reg_bit_write,
+ (void *)&cmd_write_reg_bit_regbit,
+ (void *)&cmd_write_reg_bit_port_id,
+ (void *)&cmd_write_reg_bit_reg_off,
+ (void *)&cmd_write_reg_bit_bit_pos,
+ (void *)&cmd_write_reg_bit_value,
+ NULL,
+ },
+};
+
+/* *** READ A RING DESCRIPTOR OF A PORT RX/TX QUEUE *** */
+struct cmd_read_rxd_txd_result {
+ cmdline_fixed_string_t read;
+ cmdline_fixed_string_t rxd_txd;
+ uint8_t port_id;
+ uint16_t queue_id;
+ uint16_t desc_id;
+};
+
+static void
+cmd_read_rxd_txd_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_read_rxd_txd_result *res = parsed_result;
+
+ if (!strcmp(res->rxd_txd, "rxd"))
+ rx_ring_desc_display(res->port_id, res->queue_id, res->desc_id);
+ else if (!strcmp(res->rxd_txd, "txd"))
+ tx_ring_desc_display(res->port_id, res->queue_id, res->desc_id);
+}
+
+cmdline_parse_token_string_t cmd_read_rxd_txd_read =
+ TOKEN_STRING_INITIALIZER(struct cmd_read_rxd_txd_result, read, "read");
+cmdline_parse_token_string_t cmd_read_rxd_txd_rxd_txd =
+ TOKEN_STRING_INITIALIZER(struct cmd_read_rxd_txd_result, rxd_txd,
+ "rxd#txd");
+cmdline_parse_token_num_t cmd_read_rxd_txd_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_read_rxd_txd_result, port_id, UINT8);
+cmdline_parse_token_num_t cmd_read_rxd_txd_queue_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_read_rxd_txd_result, queue_id, UINT16);
+cmdline_parse_token_num_t cmd_read_rxd_txd_desc_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_read_rxd_txd_result, desc_id, UINT16);
+
+cmdline_parse_inst_t cmd_read_rxd_txd = {
+ .f = cmd_read_rxd_txd_parsed,
+ .data = NULL,
+ .help_str = "read rxd|txd <port_id> <queue_id> <desc_id>",
+ .tokens = {
+ (void *)&cmd_read_rxd_txd_read,
+ (void *)&cmd_read_rxd_txd_rxd_txd,
+ (void *)&cmd_read_rxd_txd_port_id,
+ (void *)&cmd_read_rxd_txd_queue_id,
+ (void *)&cmd_read_rxd_txd_desc_id,
+ NULL,
+ },
+};
+
+/* *** QUIT *** */
+struct cmd_quit_result {
+ cmdline_fixed_string_t quit;
+};
+
+static void cmd_quit_parsed(__attribute__((unused)) void *parsed_result,
+ struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ pmd_test_exit();
+ cmdline_quit(cl);
+}
+
+cmdline_parse_token_string_t cmd_quit_quit =
+ TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit");
+
+cmdline_parse_inst_t cmd_quit = {
+ .f = cmd_quit_parsed,
+ .data = NULL,
+ .help_str = "quit: Exit application",
+ .tokens = {
+ (void *)&cmd_quit_quit,
+ NULL,
+ },
+};
+
+/* *** ADD/REMOVE MAC ADDRESS FROM A PORT *** */
+struct cmd_mac_addr_result {
+ cmdline_fixed_string_t mac_addr_cmd;
+ cmdline_fixed_string_t what;
+ uint8_t port_num;
+ struct ether_addr address;
+};
+
+static void cmd_mac_addr_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_mac_addr_result *res = parsed_result;
+ int ret;
+
+ if (strcmp(res->what, "add") == 0)
+ ret = rte_eth_dev_mac_addr_add(res->port_num, &res->address, 0);
+ else if (strcmp(res->what, "set") == 0)
+ ret = rte_eth_dev_default_mac_addr_set(res->port_num,
+ &res->address);
+ else
+ ret = rte_eth_dev_mac_addr_remove(res->port_num, &res->address);
+
+ /* check the return value and print it if is < 0 */
+ if(ret < 0)
+ printf("mac_addr_cmd error: (%s)\n", strerror(-ret));
+
+}
+
+cmdline_parse_token_string_t cmd_mac_addr_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_mac_addr_result, mac_addr_cmd,
+ "mac_addr");
+cmdline_parse_token_string_t cmd_mac_addr_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_mac_addr_result, what,
+ "add#remove#set");
+cmdline_parse_token_num_t cmd_mac_addr_portnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_mac_addr_result, port_num, UINT8);
+cmdline_parse_token_etheraddr_t cmd_mac_addr_addr =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_mac_addr_result, address);
+
+cmdline_parse_inst_t cmd_mac_addr = {
+ .f = cmd_mac_addr_parsed,
+ .data = (void *)0,
+ .help_str = "mac_addr add|remove|set <port_id> <mac_addr>: "
+ "Add/Remove/Set MAC address on port_id",
+ .tokens = {
+ (void *)&cmd_mac_addr_cmd,
+ (void *)&cmd_mac_addr_what,
+ (void *)&cmd_mac_addr_portnum,
+ (void *)&cmd_mac_addr_addr,
+ NULL,
+ },
+};
+
+
+/* *** CONFIGURE QUEUE STATS COUNTER MAPPINGS *** */
+struct cmd_set_qmap_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t qmap;
+ cmdline_fixed_string_t what;
+ uint8_t port_id;
+ uint16_t queue_id;
+ uint8_t map_value;
+};
+
+static void
+cmd_set_qmap_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_qmap_result *res = parsed_result;
+ int is_rx = (strcmp(res->what, "tx") == 0) ? 0 : 1;
+
+ set_qmap(res->port_id, (uint8_t)is_rx, res->queue_id, res->map_value);
+}
+
+cmdline_parse_token_string_t cmd_setqmap_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_qmap_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_setqmap_qmap =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_qmap_result,
+ qmap, "stat_qmap");
+cmdline_parse_token_string_t cmd_setqmap_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_qmap_result,
+ what, "tx#rx");
+cmdline_parse_token_num_t cmd_setqmap_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_qmap_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_setqmap_queueid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_qmap_result,
+ queue_id, UINT16);
+cmdline_parse_token_num_t cmd_setqmap_mapvalue =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_qmap_result,
+ map_value, UINT8);
+
+cmdline_parse_inst_t cmd_set_qmap = {
+ .f = cmd_set_qmap_parsed,
+ .data = NULL,
+ .help_str = "set stat_qmap rx|tx <port_id> <queue_id> <map_value>: "
+ "Set statistics mapping value on tx|rx queue_id of port_id",
+ .tokens = {
+ (void *)&cmd_setqmap_set,
+ (void *)&cmd_setqmap_qmap,
+ (void *)&cmd_setqmap_what,
+ (void *)&cmd_setqmap_portid,
+ (void *)&cmd_setqmap_queueid,
+ (void *)&cmd_setqmap_mapvalue,
+ NULL,
+ },
+};
+
+/* *** CONFIGURE UNICAST HASH TABLE *** */
+struct cmd_set_uc_hash_table {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ uint8_t port_id;
+ cmdline_fixed_string_t what;
+ struct ether_addr address;
+ cmdline_fixed_string_t mode;
+};
+
+static void
+cmd_set_uc_hash_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ int ret=0;
+ struct cmd_set_uc_hash_table *res = parsed_result;
+
+ int is_on = (strcmp(res->mode, "on") == 0) ? 1 : 0;
+
+ if (strcmp(res->what, "uta") == 0)
+ ret = rte_eth_dev_uc_hash_table_set(res->port_id,
+ &res->address,(uint8_t)is_on);
+ if (ret < 0)
+ printf("bad unicast hash table parameter, return code = %d \n", ret);
+
+}
+
+cmdline_parse_token_string_t cmd_set_uc_hash_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_uc_hash_table,
+ set, "set");
+cmdline_parse_token_string_t cmd_set_uc_hash_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_uc_hash_table,
+ port, "port");
+cmdline_parse_token_num_t cmd_set_uc_hash_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_uc_hash_table,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_set_uc_hash_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_uc_hash_table,
+ what, "uta");
+cmdline_parse_token_etheraddr_t cmd_set_uc_hash_mac =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_uc_hash_table,
+ address);
+cmdline_parse_token_string_t cmd_set_uc_hash_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_uc_hash_table,
+ mode, "on#off");
+
+cmdline_parse_inst_t cmd_set_uc_hash_filter = {
+ .f = cmd_set_uc_hash_parsed,
+ .data = NULL,
+ .help_str = "set port <port_id> uta <mac_addr> on|off)",
+ .tokens = {
+ (void *)&cmd_set_uc_hash_set,
+ (void *)&cmd_set_uc_hash_port,
+ (void *)&cmd_set_uc_hash_portid,
+ (void *)&cmd_set_uc_hash_what,
+ (void *)&cmd_set_uc_hash_mac,
+ (void *)&cmd_set_uc_hash_mode,
+ NULL,
+ },
+};
+
+struct cmd_set_uc_all_hash_table {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ uint8_t port_id;
+ cmdline_fixed_string_t what;
+ cmdline_fixed_string_t value;
+ cmdline_fixed_string_t mode;
+};
+
+static void
+cmd_set_uc_all_hash_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ int ret=0;
+ struct cmd_set_uc_all_hash_table *res = parsed_result;
+
+ int is_on = (strcmp(res->mode, "on") == 0) ? 1 : 0;
+
+ if ((strcmp(res->what, "uta") == 0) &&
+ (strcmp(res->value, "all") == 0))
+ ret = rte_eth_dev_uc_all_hash_table_set(res->port_id,(uint8_t) is_on);
+ if (ret < 0)
+ printf("bad unicast hash table parameter,"
+ "return code = %d \n", ret);
+}
+
+cmdline_parse_token_string_t cmd_set_uc_all_hash_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_uc_all_hash_table,
+ set, "set");
+cmdline_parse_token_string_t cmd_set_uc_all_hash_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_uc_all_hash_table,
+ port, "port");
+cmdline_parse_token_num_t cmd_set_uc_all_hash_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_uc_all_hash_table,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_set_uc_all_hash_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_uc_all_hash_table,
+ what, "uta");
+cmdline_parse_token_string_t cmd_set_uc_all_hash_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_uc_all_hash_table,
+ value,"all");
+cmdline_parse_token_string_t cmd_set_uc_all_hash_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_uc_all_hash_table,
+ mode, "on#off");
+
+cmdline_parse_inst_t cmd_set_uc_all_hash_filter = {
+ .f = cmd_set_uc_all_hash_parsed,
+ .data = NULL,
+ .help_str = "set port <port_id> uta all on|off",
+ .tokens = {
+ (void *)&cmd_set_uc_all_hash_set,
+ (void *)&cmd_set_uc_all_hash_port,
+ (void *)&cmd_set_uc_all_hash_portid,
+ (void *)&cmd_set_uc_all_hash_what,
+ (void *)&cmd_set_uc_all_hash_value,
+ (void *)&cmd_set_uc_all_hash_mode,
+ NULL,
+ },
+};
+
+/* *** CONFIGURE MACVLAN FILTER FOR VF(s) *** */
+struct cmd_set_vf_macvlan_filter {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ uint8_t port_id;
+ cmdline_fixed_string_t vf;
+ uint8_t vf_id;
+ struct ether_addr address;
+ cmdline_fixed_string_t filter_type;
+ cmdline_fixed_string_t mode;
+};
+
+static void
+cmd_set_vf_macvlan_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ int is_on, ret = 0;
+ struct cmd_set_vf_macvlan_filter *res = parsed_result;
+ struct rte_eth_mac_filter filter;
+
+ memset(&filter, 0, sizeof(struct rte_eth_mac_filter));
+
+ (void)rte_memcpy(&filter.mac_addr, &res->address, ETHER_ADDR_LEN);
+
+ /* set VF MAC filter */
+ filter.is_vf = 1;
+
+ /* set VF ID */
+ filter.dst_id = res->vf_id;
+
+ if (!strcmp(res->filter_type, "exact-mac"))
+ filter.filter_type = RTE_MAC_PERFECT_MATCH;
+ else if (!strcmp(res->filter_type, "exact-mac-vlan"))
+ filter.filter_type = RTE_MACVLAN_PERFECT_MATCH;
+ else if (!strcmp(res->filter_type, "hashmac"))
+ filter.filter_type = RTE_MAC_HASH_MATCH;
+ else if (!strcmp(res->filter_type, "hashmac-vlan"))
+ filter.filter_type = RTE_MACVLAN_HASH_MATCH;
+
+ is_on = (strcmp(res->mode, "on") == 0) ? 1 : 0;
+
+ if (is_on)
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_MACVLAN,
+ RTE_ETH_FILTER_ADD,
+ &filter);
+ else
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_MACVLAN,
+ RTE_ETH_FILTER_DELETE,
+ &filter);
+
+ if (ret < 0)
+ printf("bad set MAC hash parameter, return code = %d\n", ret);
+
+}
+
+cmdline_parse_token_string_t cmd_set_vf_macvlan_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_macvlan_filter,
+ set, "set");
+cmdline_parse_token_string_t cmd_set_vf_macvlan_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_macvlan_filter,
+ port, "port");
+cmdline_parse_token_num_t cmd_set_vf_macvlan_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_vf_macvlan_filter,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_set_vf_macvlan_vf =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_macvlan_filter,
+ vf, "vf");
+cmdline_parse_token_num_t cmd_set_vf_macvlan_vf_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_vf_macvlan_filter,
+ vf_id, UINT8);
+cmdline_parse_token_etheraddr_t cmd_set_vf_macvlan_mac =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_vf_macvlan_filter,
+ address);
+cmdline_parse_token_string_t cmd_set_vf_macvlan_filter_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_macvlan_filter,
+ filter_type, "exact-mac#exact-mac-vlan"
+ "#hashmac#hashmac-vlan");
+cmdline_parse_token_string_t cmd_set_vf_macvlan_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_macvlan_filter,
+ mode, "on#off");
+
+cmdline_parse_inst_t cmd_set_vf_macvlan_filter = {
+ .f = cmd_set_vf_macvlan_parsed,
+ .data = NULL,
+ .help_str = "set port <port_id> vf <vf_id> <mac_addr> "
+ "exact-mac|exact-mac-vlan|hashmac|hashmac-vlan on|off: "
+ "Exact match rule: exact match of MAC or MAC and VLAN; "
+ "hash match rule: hash match of MAC and exact match of VLAN",
+ .tokens = {
+ (void *)&cmd_set_vf_macvlan_set,
+ (void *)&cmd_set_vf_macvlan_port,
+ (void *)&cmd_set_vf_macvlan_portid,
+ (void *)&cmd_set_vf_macvlan_vf,
+ (void *)&cmd_set_vf_macvlan_vf_id,
+ (void *)&cmd_set_vf_macvlan_mac,
+ (void *)&cmd_set_vf_macvlan_filter_type,
+ (void *)&cmd_set_vf_macvlan_mode,
+ NULL,
+ },
+};
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+/* *** CONFIGURE VF TRAFFIC CONTROL *** */
+struct cmd_set_vf_traffic {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ uint8_t port_id;
+ cmdline_fixed_string_t vf;
+ uint8_t vf_id;
+ cmdline_fixed_string_t what;
+ cmdline_fixed_string_t mode;
+};
+
+static void
+cmd_set_vf_traffic_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_vf_traffic *res = parsed_result;
+ int is_rx = (strcmp(res->what, "rx") == 0) ? 1 : 0;
+ int is_on = (strcmp(res->mode, "on") == 0) ? 1 : 0;
+
+ set_vf_traffic(res->port_id, (uint8_t)is_rx, res->vf_id,(uint8_t) is_on);
+}
+
+cmdline_parse_token_string_t cmd_setvf_traffic_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_traffic,
+ set, "set");
+cmdline_parse_token_string_t cmd_setvf_traffic_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_traffic,
+ port, "port");
+cmdline_parse_token_num_t cmd_setvf_traffic_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_vf_traffic,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_setvf_traffic_vf =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_traffic,
+ vf, "vf");
+cmdline_parse_token_num_t cmd_setvf_traffic_vfid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_vf_traffic,
+ vf_id, UINT8);
+cmdline_parse_token_string_t cmd_setvf_traffic_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_traffic,
+ what, "tx#rx");
+cmdline_parse_token_string_t cmd_setvf_traffic_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_traffic,
+ mode, "on#off");
+
+cmdline_parse_inst_t cmd_set_vf_traffic = {
+ .f = cmd_set_vf_traffic_parsed,
+ .data = NULL,
+ .help_str = "set port <port_id> vf <vf_id> rx|tx on|off",
+ .tokens = {
+ (void *)&cmd_setvf_traffic_set,
+ (void *)&cmd_setvf_traffic_port,
+ (void *)&cmd_setvf_traffic_portid,
+ (void *)&cmd_setvf_traffic_vf,
+ (void *)&cmd_setvf_traffic_vfid,
+ (void *)&cmd_setvf_traffic_what,
+ (void *)&cmd_setvf_traffic_mode,
+ NULL,
+ },
+};
+
+/* *** CONFIGURE VF RECEIVE MODE *** */
+struct cmd_set_vf_rxmode {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ uint8_t port_id;
+ cmdline_fixed_string_t vf;
+ uint8_t vf_id;
+ cmdline_fixed_string_t what;
+ cmdline_fixed_string_t mode;
+ cmdline_fixed_string_t on;
+};
+
+static void
+cmd_set_vf_rxmode_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ int ret;
+ uint16_t rx_mode = 0;
+ struct cmd_set_vf_rxmode *res = parsed_result;
+
+ int is_on = (strcmp(res->on, "on") == 0) ? 1 : 0;
+ if (!strcmp(res->what,"rxmode")) {
+ if (!strcmp(res->mode, "AUPE"))
+ rx_mode |= ETH_VMDQ_ACCEPT_UNTAG;
+ else if (!strcmp(res->mode, "ROPE"))
+ rx_mode |= ETH_VMDQ_ACCEPT_HASH_UC;
+ else if (!strcmp(res->mode, "BAM"))
+ rx_mode |= ETH_VMDQ_ACCEPT_BROADCAST;
+ else if (!strncmp(res->mode, "MPE",3))
+ rx_mode |= ETH_VMDQ_ACCEPT_MULTICAST;
+ }
+
+ ret = rte_pmd_ixgbe_set_vf_rxmode(res->port_id, res->vf_id, rx_mode, (uint8_t)is_on);
+ if (ret < 0)
+ printf("bad VF receive mode parameter, return code = %d \n",
+ ret);
+}
+
+cmdline_parse_token_string_t cmd_set_vf_rxmode_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_rxmode,
+ set, "set");
+cmdline_parse_token_string_t cmd_set_vf_rxmode_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_rxmode,
+ port, "port");
+cmdline_parse_token_num_t cmd_set_vf_rxmode_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_vf_rxmode,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_set_vf_rxmode_vf =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_rxmode,
+ vf, "vf");
+cmdline_parse_token_num_t cmd_set_vf_rxmode_vfid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_vf_rxmode,
+ vf_id, UINT8);
+cmdline_parse_token_string_t cmd_set_vf_rxmode_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_rxmode,
+ what, "rxmode");
+cmdline_parse_token_string_t cmd_set_vf_rxmode_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_rxmode,
+ mode, "AUPE#ROPE#BAM#MPE");
+cmdline_parse_token_string_t cmd_set_vf_rxmode_on =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_rxmode,
+ on, "on#off");
+
+cmdline_parse_inst_t cmd_set_vf_rxmode = {
+ .f = cmd_set_vf_rxmode_parsed,
+ .data = NULL,
+ .help_str = "set port <port_id> vf <vf_id> rxmode "
+ "AUPE|ROPE|BAM|MPE on|off",
+ .tokens = {
+ (void *)&cmd_set_vf_rxmode_set,
+ (void *)&cmd_set_vf_rxmode_port,
+ (void *)&cmd_set_vf_rxmode_portid,
+ (void *)&cmd_set_vf_rxmode_vf,
+ (void *)&cmd_set_vf_rxmode_vfid,
+ (void *)&cmd_set_vf_rxmode_what,
+ (void *)&cmd_set_vf_rxmode_mode,
+ (void *)&cmd_set_vf_rxmode_on,
+ NULL,
+ },
+};
+#endif
+
+/* *** ADD MAC ADDRESS FILTER FOR A VF OF A PORT *** */
+struct cmd_vf_mac_addr_result {
+ cmdline_fixed_string_t mac_addr_cmd;
+ cmdline_fixed_string_t what;
+ cmdline_fixed_string_t port;
+ uint8_t port_num;
+ cmdline_fixed_string_t vf;
+ uint8_t vf_num;
+ struct ether_addr address;
+};
+
+static void cmd_vf_mac_addr_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_vf_mac_addr_result *res = parsed_result;
+ int ret = 0;
+
+ if (strcmp(res->what, "add") == 0)
+ ret = rte_eth_dev_mac_addr_add(res->port_num,
+ &res->address, res->vf_num);
+ if(ret < 0)
+ printf("vf_mac_addr_cmd error: (%s)\n", strerror(-ret));
+
+}
+
+cmdline_parse_token_string_t cmd_vf_mac_addr_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_mac_addr_result,
+ mac_addr_cmd,"mac_addr");
+cmdline_parse_token_string_t cmd_vf_mac_addr_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_mac_addr_result,
+ what,"add");
+cmdline_parse_token_string_t cmd_vf_mac_addr_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_mac_addr_result,
+ port,"port");
+cmdline_parse_token_num_t cmd_vf_mac_addr_portnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_vf_mac_addr_result,
+ port_num, UINT8);
+cmdline_parse_token_string_t cmd_vf_mac_addr_vf =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_mac_addr_result,
+ vf,"vf");
+cmdline_parse_token_num_t cmd_vf_mac_addr_vfnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_vf_mac_addr_result,
+ vf_num, UINT8);
+cmdline_parse_token_etheraddr_t cmd_vf_mac_addr_addr =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_vf_mac_addr_result,
+ address);
+
+cmdline_parse_inst_t cmd_vf_mac_addr_filter = {
+ .f = cmd_vf_mac_addr_parsed,
+ .data = (void *)0,
+ .help_str = "mac_addr add port <port_id> vf <vf_id> <mac_addr>: "
+ "Add MAC address filtering for a VF on port_id",
+ .tokens = {
+ (void *)&cmd_vf_mac_addr_cmd,
+ (void *)&cmd_vf_mac_addr_what,
+ (void *)&cmd_vf_mac_addr_port,
+ (void *)&cmd_vf_mac_addr_portnum,
+ (void *)&cmd_vf_mac_addr_vf,
+ (void *)&cmd_vf_mac_addr_vfnum,
+ (void *)&cmd_vf_mac_addr_addr,
+ NULL,
+ },
+};
+
+/* *** ADD/REMOVE A VLAN IDENTIFIER TO/FROM A PORT VLAN RX FILTER *** */
+struct cmd_vf_rx_vlan_filter {
+ cmdline_fixed_string_t rx_vlan;
+ cmdline_fixed_string_t what;
+ uint16_t vlan_id;
+ cmdline_fixed_string_t port;
+ uint8_t port_id;
+ cmdline_fixed_string_t vf;
+ uint64_t vf_mask;
+};
+
+static void
+cmd_vf_rx_vlan_filter_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_vf_rx_vlan_filter *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ __rte_unused int is_add = (strcmp(res->what, "add") == 0) ? 1 : 0;
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_ixgbe_set_vf_vlan_filter(res->port_id,
+ res->vlan_id, res->vf_mask, is_add);
+#endif
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_i40e_set_vf_vlan_filter(res->port_id,
+ res->vlan_id, res->vf_mask, is_add);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vlan_id %d or vf_mask %"PRIu64"\n",
+ res->vlan_id, res->vf_mask);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented or supported\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_token_string_t cmd_vf_rx_vlan_filter_rx_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_rx_vlan_filter,
+ rx_vlan, "rx_vlan");
+cmdline_parse_token_string_t cmd_vf_rx_vlan_filter_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_rx_vlan_filter,
+ what, "add#rm");
+cmdline_parse_token_num_t cmd_vf_rx_vlan_filter_vlanid =
+ TOKEN_NUM_INITIALIZER(struct cmd_vf_rx_vlan_filter,
+ vlan_id, UINT16);
+cmdline_parse_token_string_t cmd_vf_rx_vlan_filter_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_rx_vlan_filter,
+ port, "port");
+cmdline_parse_token_num_t cmd_vf_rx_vlan_filter_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_vf_rx_vlan_filter,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_vf_rx_vlan_filter_vf =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_rx_vlan_filter,
+ vf, "vf");
+cmdline_parse_token_num_t cmd_vf_rx_vlan_filter_vf_mask =
+ TOKEN_NUM_INITIALIZER(struct cmd_vf_rx_vlan_filter,
+ vf_mask, UINT64);
+
+cmdline_parse_inst_t cmd_vf_rxvlan_filter = {
+ .f = cmd_vf_rx_vlan_filter_parsed,
+ .data = NULL,
+ .help_str = "rx_vlan add|rm <vlan_id> port <port_id> vf <vf_mask>: "
+ "(vf_mask = hexadecimal VF mask)",
+ .tokens = {
+ (void *)&cmd_vf_rx_vlan_filter_rx_vlan,
+ (void *)&cmd_vf_rx_vlan_filter_what,
+ (void *)&cmd_vf_rx_vlan_filter_vlanid,
+ (void *)&cmd_vf_rx_vlan_filter_port,
+ (void *)&cmd_vf_rx_vlan_filter_portid,
+ (void *)&cmd_vf_rx_vlan_filter_vf,
+ (void *)&cmd_vf_rx_vlan_filter_vf_mask,
+ NULL,
+ },
+};
+
+/* *** SET RATE LIMIT FOR A QUEUE OF A PORT *** */
+struct cmd_queue_rate_limit_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ uint8_t port_num;
+ cmdline_fixed_string_t queue;
+ uint8_t queue_num;
+ cmdline_fixed_string_t rate;
+ uint16_t rate_num;
+};
+
+static void cmd_queue_rate_limit_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_queue_rate_limit_result *res = parsed_result;
+ int ret = 0;
+
+ if ((strcmp(res->set, "set") == 0) && (strcmp(res->port, "port") == 0)
+ && (strcmp(res->queue, "queue") == 0)
+ && (strcmp(res->rate, "rate") == 0))
+ ret = set_queue_rate_limit(res->port_num, res->queue_num,
+ res->rate_num);
+ if (ret < 0)
+ printf("queue_rate_limit_cmd error: (%s)\n", strerror(-ret));
+
+}
+
+cmdline_parse_token_string_t cmd_queue_rate_limit_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_queue_rate_limit_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_queue_rate_limit_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_queue_rate_limit_result,
+ port, "port");
+cmdline_parse_token_num_t cmd_queue_rate_limit_portnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_queue_rate_limit_result,
+ port_num, UINT8);
+cmdline_parse_token_string_t cmd_queue_rate_limit_queue =
+ TOKEN_STRING_INITIALIZER(struct cmd_queue_rate_limit_result,
+ queue, "queue");
+cmdline_parse_token_num_t cmd_queue_rate_limit_queuenum =
+ TOKEN_NUM_INITIALIZER(struct cmd_queue_rate_limit_result,
+ queue_num, UINT8);
+cmdline_parse_token_string_t cmd_queue_rate_limit_rate =
+ TOKEN_STRING_INITIALIZER(struct cmd_queue_rate_limit_result,
+ rate, "rate");
+cmdline_parse_token_num_t cmd_queue_rate_limit_ratenum =
+ TOKEN_NUM_INITIALIZER(struct cmd_queue_rate_limit_result,
+ rate_num, UINT16);
+
+cmdline_parse_inst_t cmd_queue_rate_limit = {
+ .f = cmd_queue_rate_limit_parsed,
+ .data = (void *)0,
+ .help_str = "set port <port_id> queue <queue_id> rate <rate_value>: "
+ "Set rate limit for a queue on port_id",
+ .tokens = {
+ (void *)&cmd_queue_rate_limit_set,
+ (void *)&cmd_queue_rate_limit_port,
+ (void *)&cmd_queue_rate_limit_portnum,
+ (void *)&cmd_queue_rate_limit_queue,
+ (void *)&cmd_queue_rate_limit_queuenum,
+ (void *)&cmd_queue_rate_limit_rate,
+ (void *)&cmd_queue_rate_limit_ratenum,
+ NULL,
+ },
+};
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+/* *** SET RATE LIMIT FOR A VF OF A PORT *** */
+struct cmd_vf_rate_limit_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ uint8_t port_num;
+ cmdline_fixed_string_t vf;
+ uint8_t vf_num;
+ cmdline_fixed_string_t rate;
+ uint16_t rate_num;
+ cmdline_fixed_string_t q_msk;
+ uint64_t q_msk_val;
+};
+
+static void cmd_vf_rate_limit_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_vf_rate_limit_result *res = parsed_result;
+ int ret = 0;
+
+ if ((strcmp(res->set, "set") == 0) && (strcmp(res->port, "port") == 0)
+ && (strcmp(res->vf, "vf") == 0)
+ && (strcmp(res->rate, "rate") == 0)
+ && (strcmp(res->q_msk, "queue_mask") == 0))
+ ret = set_vf_rate_limit(res->port_num, res->vf_num,
+ res->rate_num, res->q_msk_val);
+ if (ret < 0)
+ printf("vf_rate_limit_cmd error: (%s)\n", strerror(-ret));
+
+}
+
+cmdline_parse_token_string_t cmd_vf_rate_limit_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_rate_limit_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_vf_rate_limit_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_rate_limit_result,
+ port, "port");
+cmdline_parse_token_num_t cmd_vf_rate_limit_portnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_vf_rate_limit_result,
+ port_num, UINT8);
+cmdline_parse_token_string_t cmd_vf_rate_limit_vf =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_rate_limit_result,
+ vf, "vf");
+cmdline_parse_token_num_t cmd_vf_rate_limit_vfnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_vf_rate_limit_result,
+ vf_num, UINT8);
+cmdline_parse_token_string_t cmd_vf_rate_limit_rate =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_rate_limit_result,
+ rate, "rate");
+cmdline_parse_token_num_t cmd_vf_rate_limit_ratenum =
+ TOKEN_NUM_INITIALIZER(struct cmd_vf_rate_limit_result,
+ rate_num, UINT16);
+cmdline_parse_token_string_t cmd_vf_rate_limit_q_msk =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_rate_limit_result,
+ q_msk, "queue_mask");
+cmdline_parse_token_num_t cmd_vf_rate_limit_q_msk_val =
+ TOKEN_NUM_INITIALIZER(struct cmd_vf_rate_limit_result,
+ q_msk_val, UINT64);
+
+cmdline_parse_inst_t cmd_vf_rate_limit = {
+ .f = cmd_vf_rate_limit_parsed,
+ .data = (void *)0,
+ .help_str = "set port <port_id> vf <vf_id> rate <rate_value> "
+ "queue_mask <queue_mask_value>: "
+ "Set rate limit for queues of VF on port_id",
+ .tokens = {
+ (void *)&cmd_vf_rate_limit_set,
+ (void *)&cmd_vf_rate_limit_port,
+ (void *)&cmd_vf_rate_limit_portnum,
+ (void *)&cmd_vf_rate_limit_vf,
+ (void *)&cmd_vf_rate_limit_vfnum,
+ (void *)&cmd_vf_rate_limit_rate,
+ (void *)&cmd_vf_rate_limit_ratenum,
+ (void *)&cmd_vf_rate_limit_q_msk,
+ (void *)&cmd_vf_rate_limit_q_msk_val,
+ NULL,
+ },
+};
+#endif
+
+/* *** ADD TUNNEL FILTER OF A PORT *** */
+struct cmd_tunnel_filter_result {
+ cmdline_fixed_string_t cmd;
+ cmdline_fixed_string_t what;
+ uint8_t port_id;
+ struct ether_addr outer_mac;
+ struct ether_addr inner_mac;
+ cmdline_ipaddr_t ip_value;
+ uint16_t inner_vlan;
+ cmdline_fixed_string_t tunnel_type;
+ cmdline_fixed_string_t filter_type;
+ uint32_t tenant_id;
+ uint16_t queue_num;
+};
+
+static void
+cmd_tunnel_filter_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_tunnel_filter_result *res = parsed_result;
+ struct rte_eth_tunnel_filter_conf tunnel_filter_conf;
+ int ret = 0;
+
+ memset(&tunnel_filter_conf, 0, sizeof(tunnel_filter_conf));
+
+ ether_addr_copy(&res->outer_mac, &tunnel_filter_conf.outer_mac);
+ ether_addr_copy(&res->inner_mac, &tunnel_filter_conf.inner_mac);
+ tunnel_filter_conf.inner_vlan = res->inner_vlan;
+
+ if (res->ip_value.family == AF_INET) {
+ tunnel_filter_conf.ip_addr.ipv4_addr =
+ res->ip_value.addr.ipv4.s_addr;
+ tunnel_filter_conf.ip_type = RTE_TUNNEL_IPTYPE_IPV4;
+ } else {
+ memcpy(&(tunnel_filter_conf.ip_addr.ipv6_addr),
+ &(res->ip_value.addr.ipv6),
+ sizeof(struct in6_addr));
+ tunnel_filter_conf.ip_type = RTE_TUNNEL_IPTYPE_IPV6;
+ }
+
+ if (!strcmp(res->filter_type, "imac-ivlan"))
+ tunnel_filter_conf.filter_type = RTE_TUNNEL_FILTER_IMAC_IVLAN;
+ else if (!strcmp(res->filter_type, "imac-ivlan-tenid"))
+ tunnel_filter_conf.filter_type =
+ RTE_TUNNEL_FILTER_IMAC_IVLAN_TENID;
+ else if (!strcmp(res->filter_type, "imac-tenid"))
+ tunnel_filter_conf.filter_type = RTE_TUNNEL_FILTER_IMAC_TENID;
+ else if (!strcmp(res->filter_type, "imac"))
+ tunnel_filter_conf.filter_type = ETH_TUNNEL_FILTER_IMAC;
+ else if (!strcmp(res->filter_type, "omac-imac-tenid"))
+ tunnel_filter_conf.filter_type =
+ RTE_TUNNEL_FILTER_OMAC_TENID_IMAC;
+ else if (!strcmp(res->filter_type, "oip"))
+ tunnel_filter_conf.filter_type = ETH_TUNNEL_FILTER_OIP;
+ else if (!strcmp(res->filter_type, "iip"))
+ tunnel_filter_conf.filter_type = ETH_TUNNEL_FILTER_IIP;
+ else {
+ printf("The filter type is not supported");
+ return;
+ }
+
+ if (!strcmp(res->tunnel_type, "vxlan"))
+ tunnel_filter_conf.tunnel_type = RTE_TUNNEL_TYPE_VXLAN;
+ else if (!strcmp(res->tunnel_type, "nvgre"))
+ tunnel_filter_conf.tunnel_type = RTE_TUNNEL_TYPE_NVGRE;
+ else if (!strcmp(res->tunnel_type, "ipingre"))
+ tunnel_filter_conf.tunnel_type = RTE_TUNNEL_TYPE_IP_IN_GRE;
+ else {
+ printf("The tunnel type %s not supported.\n", res->tunnel_type);
+ return;
+ }
+
+ tunnel_filter_conf.tenant_id = res->tenant_id;
+ tunnel_filter_conf.queue_id = res->queue_num;
+ if (!strcmp(res->what, "add"))
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_TUNNEL,
+ RTE_ETH_FILTER_ADD,
+ &tunnel_filter_conf);
+ else
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_TUNNEL,
+ RTE_ETH_FILTER_DELETE,
+ &tunnel_filter_conf);
+ if (ret < 0)
+ printf("cmd_tunnel_filter_parsed error: (%s)\n",
+ strerror(-ret));
+
+}
+cmdline_parse_token_string_t cmd_tunnel_filter_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_tunnel_filter_result,
+ cmd, "tunnel_filter");
+cmdline_parse_token_string_t cmd_tunnel_filter_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_tunnel_filter_result,
+ what, "add#rm");
+cmdline_parse_token_num_t cmd_tunnel_filter_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_tunnel_filter_result,
+ port_id, UINT8);
+cmdline_parse_token_etheraddr_t cmd_tunnel_filter_outer_mac =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_tunnel_filter_result,
+ outer_mac);
+cmdline_parse_token_etheraddr_t cmd_tunnel_filter_inner_mac =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_tunnel_filter_result,
+ inner_mac);
+cmdline_parse_token_num_t cmd_tunnel_filter_innner_vlan =
+ TOKEN_NUM_INITIALIZER(struct cmd_tunnel_filter_result,
+ inner_vlan, UINT16);
+cmdline_parse_token_ipaddr_t cmd_tunnel_filter_ip_value =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_tunnel_filter_result,
+ ip_value);
+cmdline_parse_token_string_t cmd_tunnel_filter_tunnel_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_tunnel_filter_result,
+ tunnel_type, "vxlan#nvgre#ipingre");
+
+cmdline_parse_token_string_t cmd_tunnel_filter_filter_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_tunnel_filter_result,
+ filter_type, "oip#iip#imac-ivlan#imac-ivlan-tenid#imac-tenid#"
+ "imac#omac-imac-tenid");
+cmdline_parse_token_num_t cmd_tunnel_filter_tenant_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_tunnel_filter_result,
+ tenant_id, UINT32);
+cmdline_parse_token_num_t cmd_tunnel_filter_queue_num =
+ TOKEN_NUM_INITIALIZER(struct cmd_tunnel_filter_result,
+ queue_num, UINT16);
+
+cmdline_parse_inst_t cmd_tunnel_filter = {
+ .f = cmd_tunnel_filter_parsed,
+ .data = (void *)0,
+ .help_str = "tunnel_filter add|rm <port_id> <outer_mac> <inner_mac> "
+ "<ip> <inner_vlan> vxlan|nvgre|ipingre oip|iip|imac-ivlan|"
+ "imac-ivlan-tenid|imac-tenid|imac|omac-imac-tenid <tenant_id> "
+ "<queue_id>: Add/Rm tunnel filter of a port",
+ .tokens = {
+ (void *)&cmd_tunnel_filter_cmd,
+ (void *)&cmd_tunnel_filter_what,
+ (void *)&cmd_tunnel_filter_port_id,
+ (void *)&cmd_tunnel_filter_outer_mac,
+ (void *)&cmd_tunnel_filter_inner_mac,
+ (void *)&cmd_tunnel_filter_ip_value,
+ (void *)&cmd_tunnel_filter_innner_vlan,
+ (void *)&cmd_tunnel_filter_tunnel_type,
+ (void *)&cmd_tunnel_filter_filter_type,
+ (void *)&cmd_tunnel_filter_tenant_id,
+ (void *)&cmd_tunnel_filter_queue_num,
+ NULL,
+ },
+};
+
+/* *** CONFIGURE TUNNEL UDP PORT *** */
+struct cmd_tunnel_udp_config {
+ cmdline_fixed_string_t cmd;
+ cmdline_fixed_string_t what;
+ uint16_t udp_port;
+ uint8_t port_id;
+};
+
+static void
+cmd_tunnel_udp_config_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_tunnel_udp_config *res = parsed_result;
+ struct rte_eth_udp_tunnel tunnel_udp;
+ int ret;
+
+ tunnel_udp.udp_port = res->udp_port;
+
+ if (!strcmp(res->cmd, "rx_vxlan_port"))
+ tunnel_udp.prot_type = RTE_TUNNEL_TYPE_VXLAN;
+
+ if (!strcmp(res->what, "add"))
+ ret = rte_eth_dev_udp_tunnel_port_add(res->port_id,
+ &tunnel_udp);
+ else
+ ret = rte_eth_dev_udp_tunnel_port_delete(res->port_id,
+ &tunnel_udp);
+
+ if (ret < 0)
+ printf("udp tunneling add error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_tunnel_udp_config_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_tunnel_udp_config,
+ cmd, "rx_vxlan_port");
+cmdline_parse_token_string_t cmd_tunnel_udp_config_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_tunnel_udp_config,
+ what, "add#rm");
+cmdline_parse_token_num_t cmd_tunnel_udp_config_udp_port =
+ TOKEN_NUM_INITIALIZER(struct cmd_tunnel_udp_config,
+ udp_port, UINT16);
+cmdline_parse_token_num_t cmd_tunnel_udp_config_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_tunnel_udp_config,
+ port_id, UINT8);
+
+cmdline_parse_inst_t cmd_tunnel_udp_config = {
+ .f = cmd_tunnel_udp_config_parsed,
+ .data = (void *)0,
+ .help_str = "rx_vxlan_port add|rm <udp_port> <port_id>: "
+ "Add/Remove a tunneling UDP port filter",
+ .tokens = {
+ (void *)&cmd_tunnel_udp_config_cmd,
+ (void *)&cmd_tunnel_udp_config_what,
+ (void *)&cmd_tunnel_udp_config_udp_port,
+ (void *)&cmd_tunnel_udp_config_port_id,
+ NULL,
+ },
+};
+
+/* *** GLOBAL CONFIG *** */
+struct cmd_global_config_result {
+ cmdline_fixed_string_t cmd;
+ uint8_t port_id;
+ cmdline_fixed_string_t cfg_type;
+ uint8_t len;
+};
+
+static void
+cmd_global_config_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_global_config_result *res = parsed_result;
+ struct rte_eth_global_cfg conf;
+ int ret;
+
+ memset(&conf, 0, sizeof(conf));
+ conf.cfg_type = RTE_ETH_GLOBAL_CFG_TYPE_GRE_KEY_LEN;
+ conf.cfg.gre_key_len = res->len;
+ ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_NONE,
+ RTE_ETH_FILTER_SET, &conf);
+ if (ret != 0)
+ printf("Global config error\n");
+}
+
+cmdline_parse_token_string_t cmd_global_config_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_global_config_result, cmd,
+ "global_config");
+cmdline_parse_token_num_t cmd_global_config_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_global_config_result, port_id, UINT8);
+cmdline_parse_token_string_t cmd_global_config_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_global_config_result,
+ cfg_type, "gre-key-len");
+cmdline_parse_token_num_t cmd_global_config_gre_key_len =
+ TOKEN_NUM_INITIALIZER(struct cmd_global_config_result,
+ len, UINT8);
+
+cmdline_parse_inst_t cmd_global_config = {
+ .f = cmd_global_config_parsed,
+ .data = (void *)NULL,
+ .help_str = "global_config <port_id> gre-key-len <key_len>",
+ .tokens = {
+ (void *)&cmd_global_config_cmd,
+ (void *)&cmd_global_config_port_id,
+ (void *)&cmd_global_config_type,
+ (void *)&cmd_global_config_gre_key_len,
+ NULL,
+ },
+};
+
+/* *** CONFIGURE VM MIRROR VLAN/POOL RULE *** */
+struct cmd_set_mirror_mask_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ uint8_t port_id;
+ cmdline_fixed_string_t mirror;
+ uint8_t rule_id;
+ cmdline_fixed_string_t what;
+ cmdline_fixed_string_t value;
+ cmdline_fixed_string_t dstpool;
+ uint8_t dstpool_id;
+ cmdline_fixed_string_t on;
+};
+
+cmdline_parse_token_string_t cmd_mirror_mask_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_mask_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_mirror_mask_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_mask_result,
+ port, "port");
+cmdline_parse_token_num_t cmd_mirror_mask_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_mirror_mask_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_mirror_mask_mirror =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_mask_result,
+ mirror, "mirror-rule");
+cmdline_parse_token_num_t cmd_mirror_mask_ruleid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_mirror_mask_result,
+ rule_id, UINT8);
+cmdline_parse_token_string_t cmd_mirror_mask_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_mask_result,
+ what, "pool-mirror-up#pool-mirror-down"
+ "#vlan-mirror");
+cmdline_parse_token_string_t cmd_mirror_mask_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_mask_result,
+ value, NULL);
+cmdline_parse_token_string_t cmd_mirror_mask_dstpool =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_mask_result,
+ dstpool, "dst-pool");
+cmdline_parse_token_num_t cmd_mirror_mask_poolid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_mirror_mask_result,
+ dstpool_id, UINT8);
+cmdline_parse_token_string_t cmd_mirror_mask_on =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_mask_result,
+ on, "on#off");
+
+static void
+cmd_set_mirror_mask_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ int ret,nb_item,i;
+ struct cmd_set_mirror_mask_result *res = parsed_result;
+ struct rte_eth_mirror_conf mr_conf;
+
+ memset(&mr_conf, 0, sizeof(struct rte_eth_mirror_conf));
+
+ unsigned int vlan_list[ETH_MIRROR_MAX_VLANS];
+
+ mr_conf.dst_pool = res->dstpool_id;
+
+ if (!strcmp(res->what, "pool-mirror-up")) {
+ mr_conf.pool_mask = strtoull(res->value, NULL, 16);
+ mr_conf.rule_type = ETH_MIRROR_VIRTUAL_POOL_UP;
+ } else if (!strcmp(res->what, "pool-mirror-down")) {
+ mr_conf.pool_mask = strtoull(res->value, NULL, 16);
+ mr_conf.rule_type = ETH_MIRROR_VIRTUAL_POOL_DOWN;
+ } else if (!strcmp(res->what, "vlan-mirror")) {
+ mr_conf.rule_type = ETH_MIRROR_VLAN;
+ nb_item = parse_item_list(res->value, "vlan",
+ ETH_MIRROR_MAX_VLANS, vlan_list, 1);
+ if (nb_item <= 0)
+ return;
+
+ for (i = 0; i < nb_item; i++) {
+ if (vlan_list[i] > ETHER_MAX_VLAN_ID) {
+ printf("Invalid vlan_id: must be < 4096\n");
+ return;
+ }
+
+ mr_conf.vlan.vlan_id[i] = (uint16_t)vlan_list[i];
+ mr_conf.vlan.vlan_mask |= 1ULL << i;
+ }
+ }
+
+ if (!strcmp(res->on, "on"))
+ ret = rte_eth_mirror_rule_set(res->port_id, &mr_conf,
+ res->rule_id, 1);
+ else
+ ret = rte_eth_mirror_rule_set(res->port_id, &mr_conf,
+ res->rule_id, 0);
+ if (ret < 0)
+ printf("mirror rule add error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_mirror_mask = {
+ .f = cmd_set_mirror_mask_parsed,
+ .data = NULL,
+ .help_str = "set port <port_id> mirror-rule <rule_id> "
+ "pool-mirror-up|pool-mirror-down|vlan-mirror "
+ "<pool_mask|vlan_id[,vlan_id]*> dst-pool <pool_id> on|off",
+ .tokens = {
+ (void *)&cmd_mirror_mask_set,
+ (void *)&cmd_mirror_mask_port,
+ (void *)&cmd_mirror_mask_portid,
+ (void *)&cmd_mirror_mask_mirror,
+ (void *)&cmd_mirror_mask_ruleid,
+ (void *)&cmd_mirror_mask_what,
+ (void *)&cmd_mirror_mask_value,
+ (void *)&cmd_mirror_mask_dstpool,
+ (void *)&cmd_mirror_mask_poolid,
+ (void *)&cmd_mirror_mask_on,
+ NULL,
+ },
+};
+
+/* *** CONFIGURE VM MIRROR UPLINK/DOWNLINK RULE *** */
+struct cmd_set_mirror_link_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ uint8_t port_id;
+ cmdline_fixed_string_t mirror;
+ uint8_t rule_id;
+ cmdline_fixed_string_t what;
+ cmdline_fixed_string_t dstpool;
+ uint8_t dstpool_id;
+ cmdline_fixed_string_t on;
+};
+
+cmdline_parse_token_string_t cmd_mirror_link_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_link_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_mirror_link_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_link_result,
+ port, "port");
+cmdline_parse_token_num_t cmd_mirror_link_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_mirror_link_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_mirror_link_mirror =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_link_result,
+ mirror, "mirror-rule");
+cmdline_parse_token_num_t cmd_mirror_link_ruleid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_mirror_link_result,
+ rule_id, UINT8);
+cmdline_parse_token_string_t cmd_mirror_link_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_link_result,
+ what, "uplink-mirror#downlink-mirror");
+cmdline_parse_token_string_t cmd_mirror_link_dstpool =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_link_result,
+ dstpool, "dst-pool");
+cmdline_parse_token_num_t cmd_mirror_link_poolid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_mirror_link_result,
+ dstpool_id, UINT8);
+cmdline_parse_token_string_t cmd_mirror_link_on =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_link_result,
+ on, "on#off");
+
+static void
+cmd_set_mirror_link_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ int ret;
+ struct cmd_set_mirror_link_result *res = parsed_result;
+ struct rte_eth_mirror_conf mr_conf;
+
+ memset(&mr_conf, 0, sizeof(struct rte_eth_mirror_conf));
+ if (!strcmp(res->what, "uplink-mirror"))
+ mr_conf.rule_type = ETH_MIRROR_UPLINK_PORT;
+ else
+ mr_conf.rule_type = ETH_MIRROR_DOWNLINK_PORT;
+
+ mr_conf.dst_pool = res->dstpool_id;
+
+ if (!strcmp(res->on, "on"))
+ ret = rte_eth_mirror_rule_set(res->port_id, &mr_conf,
+ res->rule_id, 1);
+ else
+ ret = rte_eth_mirror_rule_set(res->port_id, &mr_conf,
+ res->rule_id, 0);
+
+ /* check the return value and print it if is < 0 */
+ if (ret < 0)
+ printf("mirror rule add error: (%s)\n", strerror(-ret));
+
+}
+
+cmdline_parse_inst_t cmd_set_mirror_link = {
+ .f = cmd_set_mirror_link_parsed,
+ .data = NULL,
+ .help_str = "set port <port_id> mirror-rule <rule_id> "
+ "uplink-mirror|downlink-mirror dst-pool <pool_id> on|off",
+ .tokens = {
+ (void *)&cmd_mirror_link_set,
+ (void *)&cmd_mirror_link_port,
+ (void *)&cmd_mirror_link_portid,
+ (void *)&cmd_mirror_link_mirror,
+ (void *)&cmd_mirror_link_ruleid,
+ (void *)&cmd_mirror_link_what,
+ (void *)&cmd_mirror_link_dstpool,
+ (void *)&cmd_mirror_link_poolid,
+ (void *)&cmd_mirror_link_on,
+ NULL,
+ },
+};
+
+/* *** RESET VM MIRROR RULE *** */
+struct cmd_rm_mirror_rule_result {
+ cmdline_fixed_string_t reset;
+ cmdline_fixed_string_t port;
+ uint8_t port_id;
+ cmdline_fixed_string_t mirror;
+ uint8_t rule_id;
+};
+
+cmdline_parse_token_string_t cmd_rm_mirror_rule_reset =
+ TOKEN_STRING_INITIALIZER(struct cmd_rm_mirror_rule_result,
+ reset, "reset");
+cmdline_parse_token_string_t cmd_rm_mirror_rule_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_rm_mirror_rule_result,
+ port, "port");
+cmdline_parse_token_num_t cmd_rm_mirror_rule_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_rm_mirror_rule_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_rm_mirror_rule_mirror =
+ TOKEN_STRING_INITIALIZER(struct cmd_rm_mirror_rule_result,
+ mirror, "mirror-rule");
+cmdline_parse_token_num_t cmd_rm_mirror_rule_ruleid =
+ TOKEN_NUM_INITIALIZER(struct cmd_rm_mirror_rule_result,
+ rule_id, UINT8);
+
+static void
+cmd_reset_mirror_rule_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ int ret;
+ struct cmd_set_mirror_link_result *res = parsed_result;
+ /* check rule_id */
+ ret = rte_eth_mirror_rule_reset(res->port_id,res->rule_id);
+ if(ret < 0)
+ printf("mirror rule remove error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_reset_mirror_rule = {
+ .f = cmd_reset_mirror_rule_parsed,
+ .data = NULL,
+ .help_str = "reset port <port_id> mirror-rule <rule_id>",
+ .tokens = {
+ (void *)&cmd_rm_mirror_rule_reset,
+ (void *)&cmd_rm_mirror_rule_port,
+ (void *)&cmd_rm_mirror_rule_portid,
+ (void *)&cmd_rm_mirror_rule_mirror,
+ (void *)&cmd_rm_mirror_rule_ruleid,
+ NULL,
+ },
+};
+
+/* ******************************************************************************** */
+
+struct cmd_dump_result {
+ cmdline_fixed_string_t dump;
+};
+
+static void
+dump_struct_sizes(void)
+{
+#define DUMP_SIZE(t) printf("sizeof(" #t ") = %u\n", (unsigned)sizeof(t));
+ DUMP_SIZE(struct rte_mbuf);
+ DUMP_SIZE(struct rte_mempool);
+ DUMP_SIZE(struct rte_ring);
+#undef DUMP_SIZE
+}
+
+static void cmd_dump_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_dump_result *res = parsed_result;
+
+ if (!strcmp(res->dump, "dump_physmem"))
+ rte_dump_physmem_layout(stdout);
+ else if (!strcmp(res->dump, "dump_memzone"))
+ rte_memzone_dump(stdout);
+ else if (!strcmp(res->dump, "dump_struct_sizes"))
+ dump_struct_sizes();
+ else if (!strcmp(res->dump, "dump_ring"))
+ rte_ring_list_dump(stdout);
+ else if (!strcmp(res->dump, "dump_mempool"))
+ rte_mempool_list_dump(stdout);
+ else if (!strcmp(res->dump, "dump_devargs"))
+ rte_eal_devargs_dump(stdout);
+ else if (!strcmp(res->dump, "dump_log_types"))
+ rte_log_dump(stdout);
+}
+
+cmdline_parse_token_string_t cmd_dump_dump =
+ TOKEN_STRING_INITIALIZER(struct cmd_dump_result, dump,
+ "dump_physmem#"
+ "dump_memzone#"
+ "dump_struct_sizes#"
+ "dump_ring#"
+ "dump_mempool#"
+ "dump_devargs#"
+ "dump_log_types");
+
+cmdline_parse_inst_t cmd_dump = {
+ .f = cmd_dump_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "Dump status",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_dump_dump,
+ NULL,
+ },
+};
+
+/* ******************************************************************************** */
+
+struct cmd_dump_one_result {
+ cmdline_fixed_string_t dump;
+ cmdline_fixed_string_t name;
+};
+
+static void cmd_dump_one_parsed(void *parsed_result, struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_dump_one_result *res = parsed_result;
+
+ if (!strcmp(res->dump, "dump_ring")) {
+ struct rte_ring *r;
+ r = rte_ring_lookup(res->name);
+ if (r == NULL) {
+ cmdline_printf(cl, "Cannot find ring\n");
+ return;
+ }
+ rte_ring_dump(stdout, r);
+ } else if (!strcmp(res->dump, "dump_mempool")) {
+ struct rte_mempool *mp;
+ mp = rte_mempool_lookup(res->name);
+ if (mp == NULL) {
+ cmdline_printf(cl, "Cannot find mempool\n");
+ return;
+ }
+ rte_mempool_dump(stdout, mp);
+ }
+}
+
+cmdline_parse_token_string_t cmd_dump_one_dump =
+ TOKEN_STRING_INITIALIZER(struct cmd_dump_one_result, dump,
+ "dump_ring#dump_mempool");
+
+cmdline_parse_token_string_t cmd_dump_one_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_dump_one_result, name, NULL);
+
+cmdline_parse_inst_t cmd_dump_one = {
+ .f = cmd_dump_one_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "dump_ring|dump_mempool <name>: Dump one ring/mempool",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_dump_one_dump,
+ (void *)&cmd_dump_one_name,
+ NULL,
+ },
+};
+
+/* *** Add/Del syn filter *** */
+struct cmd_syn_filter_result {
+ cmdline_fixed_string_t filter;
+ uint8_t port_id;
+ cmdline_fixed_string_t ops;
+ cmdline_fixed_string_t priority;
+ cmdline_fixed_string_t high;
+ cmdline_fixed_string_t queue;
+ uint16_t queue_id;
+};
+
+static void
+cmd_syn_filter_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_syn_filter_result *res = parsed_result;
+ struct rte_eth_syn_filter syn_filter;
+ int ret = 0;
+
+ ret = rte_eth_dev_filter_supported(res->port_id,
+ RTE_ETH_FILTER_SYN);
+ if (ret < 0) {
+ printf("syn filter is not supported on port %u.\n",
+ res->port_id);
+ return;
+ }
+
+ memset(&syn_filter, 0, sizeof(syn_filter));
+
+ if (!strcmp(res->ops, "add")) {
+ if (!strcmp(res->high, "high"))
+ syn_filter.hig_pri = 1;
+ else
+ syn_filter.hig_pri = 0;
+
+ syn_filter.queue = res->queue_id;
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_SYN,
+ RTE_ETH_FILTER_ADD,
+ &syn_filter);
+ } else
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_SYN,
+ RTE_ETH_FILTER_DELETE,
+ &syn_filter);
+
+ if (ret < 0)
+ printf("syn filter programming error: (%s)\n",
+ strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_syn_filter_filter =
+ TOKEN_STRING_INITIALIZER(struct cmd_syn_filter_result,
+ filter, "syn_filter");
+cmdline_parse_token_num_t cmd_syn_filter_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_syn_filter_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_syn_filter_ops =
+ TOKEN_STRING_INITIALIZER(struct cmd_syn_filter_result,
+ ops, "add#del");
+cmdline_parse_token_string_t cmd_syn_filter_priority =
+ TOKEN_STRING_INITIALIZER(struct cmd_syn_filter_result,
+ priority, "priority");
+cmdline_parse_token_string_t cmd_syn_filter_high =
+ TOKEN_STRING_INITIALIZER(struct cmd_syn_filter_result,
+ high, "high#low");
+cmdline_parse_token_string_t cmd_syn_filter_queue =
+ TOKEN_STRING_INITIALIZER(struct cmd_syn_filter_result,
+ queue, "queue");
+cmdline_parse_token_num_t cmd_syn_filter_queue_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_syn_filter_result,
+ queue_id, UINT16);
+
+cmdline_parse_inst_t cmd_syn_filter = {
+ .f = cmd_syn_filter_parsed,
+ .data = NULL,
+ .help_str = "syn_filter <port_id> add|del priority high|low queue "
+ "<queue_id>: Add/Delete syn filter",
+ .tokens = {
+ (void *)&cmd_syn_filter_filter,
+ (void *)&cmd_syn_filter_port_id,
+ (void *)&cmd_syn_filter_ops,
+ (void *)&cmd_syn_filter_priority,
+ (void *)&cmd_syn_filter_high,
+ (void *)&cmd_syn_filter_queue,
+ (void *)&cmd_syn_filter_queue_id,
+ NULL,
+ },
+};
+
+/* *** ADD/REMOVE A 2tuple FILTER *** */
+struct cmd_2tuple_filter_result {
+ cmdline_fixed_string_t filter;
+ uint8_t port_id;
+ cmdline_fixed_string_t ops;
+ cmdline_fixed_string_t dst_port;
+ uint16_t dst_port_value;
+ cmdline_fixed_string_t protocol;
+ uint8_t protocol_value;
+ cmdline_fixed_string_t mask;
+ uint8_t mask_value;
+ cmdline_fixed_string_t tcp_flags;
+ uint8_t tcp_flags_value;
+ cmdline_fixed_string_t priority;
+ uint8_t priority_value;
+ cmdline_fixed_string_t queue;
+ uint16_t queue_id;
+};
+
+static void
+cmd_2tuple_filter_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct rte_eth_ntuple_filter filter;
+ struct cmd_2tuple_filter_result *res = parsed_result;
+ int ret = 0;
+
+ ret = rte_eth_dev_filter_supported(res->port_id, RTE_ETH_FILTER_NTUPLE);
+ if (ret < 0) {
+ printf("ntuple filter is not supported on port %u.\n",
+ res->port_id);
+ return;
+ }
+
+ memset(&filter, 0, sizeof(struct rte_eth_ntuple_filter));
+
+ filter.flags = RTE_2TUPLE_FLAGS;
+ filter.dst_port_mask = (res->mask_value & 0x02) ? UINT16_MAX : 0;
+ filter.proto_mask = (res->mask_value & 0x01) ? UINT8_MAX : 0;
+ filter.proto = res->protocol_value;
+ filter.priority = res->priority_value;
+ if (res->tcp_flags_value != 0 && filter.proto != IPPROTO_TCP) {
+ printf("nonzero tcp_flags is only meaningful"
+ " when protocol is TCP.\n");
+ return;
+ }
+ if (res->tcp_flags_value > TCP_FLAG_ALL) {
+ printf("invalid TCP flags.\n");
+ return;
+ }
+
+ if (res->tcp_flags_value != 0) {
+ filter.flags |= RTE_NTUPLE_FLAGS_TCP_FLAG;
+ filter.tcp_flags = res->tcp_flags_value;
+ }
+
+ /* need convert to big endian. */
+ filter.dst_port = rte_cpu_to_be_16(res->dst_port_value);
+ filter.queue = res->queue_id;
+
+ if (!strcmp(res->ops, "add"))
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_NTUPLE,
+ RTE_ETH_FILTER_ADD,
+ &filter);
+ else
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_NTUPLE,
+ RTE_ETH_FILTER_DELETE,
+ &filter);
+ if (ret < 0)
+ printf("2tuple filter programming error: (%s)\n",
+ strerror(-ret));
+
+}
+
+cmdline_parse_token_string_t cmd_2tuple_filter_filter =
+ TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+ filter, "2tuple_filter");
+cmdline_parse_token_num_t cmd_2tuple_filter_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_ops =
+ TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+ ops, "add#del");
+cmdline_parse_token_string_t cmd_2tuple_filter_dst_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+ dst_port, "dst_port");
+cmdline_parse_token_num_t cmd_2tuple_filter_dst_port_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+ dst_port_value, UINT16);
+cmdline_parse_token_string_t cmd_2tuple_filter_protocol =
+ TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+ protocol, "protocol");
+cmdline_parse_token_num_t cmd_2tuple_filter_protocol_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+ protocol_value, UINT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_mask =
+ TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+ mask, "mask");
+cmdline_parse_token_num_t cmd_2tuple_filter_mask_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+ mask_value, INT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_tcp_flags =
+ TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+ tcp_flags, "tcp_flags");
+cmdline_parse_token_num_t cmd_2tuple_filter_tcp_flags_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+ tcp_flags_value, UINT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_priority =
+ TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+ priority, "priority");
+cmdline_parse_token_num_t cmd_2tuple_filter_priority_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+ priority_value, UINT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_queue =
+ TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+ queue, "queue");
+cmdline_parse_token_num_t cmd_2tuple_filter_queue_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+ queue_id, UINT16);
+
+cmdline_parse_inst_t cmd_2tuple_filter = {
+ .f = cmd_2tuple_filter_parsed,
+ .data = NULL,
+ .help_str = "2tuple_filter <port_id> add|del dst_port <value> protocol "
+ "<value> mask <value> tcp_flags <value> priority <value> queue "
+ "<queue_id>: Add a 2tuple filter",
+ .tokens = {
+ (void *)&cmd_2tuple_filter_filter,
+ (void *)&cmd_2tuple_filter_port_id,
+ (void *)&cmd_2tuple_filter_ops,
+ (void *)&cmd_2tuple_filter_dst_port,
+ (void *)&cmd_2tuple_filter_dst_port_value,
+ (void *)&cmd_2tuple_filter_protocol,
+ (void *)&cmd_2tuple_filter_protocol_value,
+ (void *)&cmd_2tuple_filter_mask,
+ (void *)&cmd_2tuple_filter_mask_value,
+ (void *)&cmd_2tuple_filter_tcp_flags,
+ (void *)&cmd_2tuple_filter_tcp_flags_value,
+ (void *)&cmd_2tuple_filter_priority,
+ (void *)&cmd_2tuple_filter_priority_value,
+ (void *)&cmd_2tuple_filter_queue,
+ (void *)&cmd_2tuple_filter_queue_id,
+ NULL,
+ },
+};
+
+/* *** ADD/REMOVE A 5tuple FILTER *** */
+struct cmd_5tuple_filter_result {
+ cmdline_fixed_string_t filter;
+ uint8_t port_id;
+ cmdline_fixed_string_t ops;
+ cmdline_fixed_string_t dst_ip;
+ cmdline_ipaddr_t dst_ip_value;
+ cmdline_fixed_string_t src_ip;
+ cmdline_ipaddr_t src_ip_value;
+ cmdline_fixed_string_t dst_port;
+ uint16_t dst_port_value;
+ cmdline_fixed_string_t src_port;
+ uint16_t src_port_value;
+ cmdline_fixed_string_t protocol;
+ uint8_t protocol_value;
+ cmdline_fixed_string_t mask;
+ uint8_t mask_value;
+ cmdline_fixed_string_t tcp_flags;
+ uint8_t tcp_flags_value;
+ cmdline_fixed_string_t priority;
+ uint8_t priority_value;
+ cmdline_fixed_string_t queue;
+ uint16_t queue_id;
+};
+
+static void
+cmd_5tuple_filter_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct rte_eth_ntuple_filter filter;
+ struct cmd_5tuple_filter_result *res = parsed_result;
+ int ret = 0;
+
+ ret = rte_eth_dev_filter_supported(res->port_id, RTE_ETH_FILTER_NTUPLE);
+ if (ret < 0) {
+ printf("ntuple filter is not supported on port %u.\n",
+ res->port_id);
+ return;
+ }
+
+ memset(&filter, 0, sizeof(struct rte_eth_ntuple_filter));
+
+ filter.flags = RTE_5TUPLE_FLAGS;
+ filter.dst_ip_mask = (res->mask_value & 0x10) ? UINT32_MAX : 0;
+ filter.src_ip_mask = (res->mask_value & 0x08) ? UINT32_MAX : 0;
+ filter.dst_port_mask = (res->mask_value & 0x04) ? UINT16_MAX : 0;
+ filter.src_port_mask = (res->mask_value & 0x02) ? UINT16_MAX : 0;
+ filter.proto_mask = (res->mask_value & 0x01) ? UINT8_MAX : 0;
+ filter.proto = res->protocol_value;
+ filter.priority = res->priority_value;
+ if (res->tcp_flags_value != 0 && filter.proto != IPPROTO_TCP) {
+ printf("nonzero tcp_flags is only meaningful"
+ " when protocol is TCP.\n");
+ return;
+ }
+ if (res->tcp_flags_value > TCP_FLAG_ALL) {
+ printf("invalid TCP flags.\n");
+ return;
+ }
+
+ if (res->tcp_flags_value != 0) {
+ filter.flags |= RTE_NTUPLE_FLAGS_TCP_FLAG;
+ filter.tcp_flags = res->tcp_flags_value;
+ }
+
+ if (res->dst_ip_value.family == AF_INET)
+ /* no need to convert, already big endian. */
+ filter.dst_ip = res->dst_ip_value.addr.ipv4.s_addr;
+ else {
+ if (filter.dst_ip_mask == 0) {
+ printf("can not support ipv6 involved compare.\n");
+ return;
+ }
+ filter.dst_ip = 0;
+ }
+
+ if (res->src_ip_value.family == AF_INET)
+ /* no need to convert, already big endian. */
+ filter.src_ip = res->src_ip_value.addr.ipv4.s_addr;
+ else {
+ if (filter.src_ip_mask == 0) {
+ printf("can not support ipv6 involved compare.\n");
+ return;
+ }
+ filter.src_ip = 0;
+ }
+ /* need convert to big endian. */
+ filter.dst_port = rte_cpu_to_be_16(res->dst_port_value);
+ filter.src_port = rte_cpu_to_be_16(res->src_port_value);
+ filter.queue = res->queue_id;
+
+ if (!strcmp(res->ops, "add"))
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_NTUPLE,
+ RTE_ETH_FILTER_ADD,
+ &filter);
+ else
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_NTUPLE,
+ RTE_ETH_FILTER_DELETE,
+ &filter);
+ if (ret < 0)
+ printf("5tuple filter programming error: (%s)\n",
+ strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_5tuple_filter_filter =
+ TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+ filter, "5tuple_filter");
+cmdline_parse_token_num_t cmd_5tuple_filter_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_5tuple_filter_ops =
+ TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+ ops, "add#del");
+cmdline_parse_token_string_t cmd_5tuple_filter_dst_ip =
+ TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+ dst_ip, "dst_ip");
+cmdline_parse_token_ipaddr_t cmd_5tuple_filter_dst_ip_value =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_5tuple_filter_result,
+ dst_ip_value);
+cmdline_parse_token_string_t cmd_5tuple_filter_src_ip =
+ TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+ src_ip, "src_ip");
+cmdline_parse_token_ipaddr_t cmd_5tuple_filter_src_ip_value =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_5tuple_filter_result,
+ src_ip_value);
+cmdline_parse_token_string_t cmd_5tuple_filter_dst_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+ dst_port, "dst_port");
+cmdline_parse_token_num_t cmd_5tuple_filter_dst_port_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+ dst_port_value, UINT16);
+cmdline_parse_token_string_t cmd_5tuple_filter_src_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+ src_port, "src_port");
+cmdline_parse_token_num_t cmd_5tuple_filter_src_port_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+ src_port_value, UINT16);
+cmdline_parse_token_string_t cmd_5tuple_filter_protocol =
+ TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+ protocol, "protocol");
+cmdline_parse_token_num_t cmd_5tuple_filter_protocol_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+ protocol_value, UINT8);
+cmdline_parse_token_string_t cmd_5tuple_filter_mask =
+ TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+ mask, "mask");
+cmdline_parse_token_num_t cmd_5tuple_filter_mask_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+ mask_value, INT8);
+cmdline_parse_token_string_t cmd_5tuple_filter_tcp_flags =
+ TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+ tcp_flags, "tcp_flags");
+cmdline_parse_token_num_t cmd_5tuple_filter_tcp_flags_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+ tcp_flags_value, UINT8);
+cmdline_parse_token_string_t cmd_5tuple_filter_priority =
+ TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+ priority, "priority");
+cmdline_parse_token_num_t cmd_5tuple_filter_priority_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+ priority_value, UINT8);
+cmdline_parse_token_string_t cmd_5tuple_filter_queue =
+ TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+ queue, "queue");
+cmdline_parse_token_num_t cmd_5tuple_filter_queue_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+ queue_id, UINT16);
+
+cmdline_parse_inst_t cmd_5tuple_filter = {
+ .f = cmd_5tuple_filter_parsed,
+ .data = NULL,
+ .help_str = "5tuple_filter <port_id> add|del dst_ip <value> "
+ "src_ip <value> dst_port <value> src_port <value> "
+ "protocol <value> mask <value> tcp_flags <value> "
+ "priority <value> queue <queue_id>: Add/Del a 5tuple filter",
+ .tokens = {
+ (void *)&cmd_5tuple_filter_filter,
+ (void *)&cmd_5tuple_filter_port_id,
+ (void *)&cmd_5tuple_filter_ops,
+ (void *)&cmd_5tuple_filter_dst_ip,
+ (void *)&cmd_5tuple_filter_dst_ip_value,
+ (void *)&cmd_5tuple_filter_src_ip,
+ (void *)&cmd_5tuple_filter_src_ip_value,
+ (void *)&cmd_5tuple_filter_dst_port,
+ (void *)&cmd_5tuple_filter_dst_port_value,
+ (void *)&cmd_5tuple_filter_src_port,
+ (void *)&cmd_5tuple_filter_src_port_value,
+ (void *)&cmd_5tuple_filter_protocol,
+ (void *)&cmd_5tuple_filter_protocol_value,
+ (void *)&cmd_5tuple_filter_mask,
+ (void *)&cmd_5tuple_filter_mask_value,
+ (void *)&cmd_5tuple_filter_tcp_flags,
+ (void *)&cmd_5tuple_filter_tcp_flags_value,
+ (void *)&cmd_5tuple_filter_priority,
+ (void *)&cmd_5tuple_filter_priority_value,
+ (void *)&cmd_5tuple_filter_queue,
+ (void *)&cmd_5tuple_filter_queue_id,
+ NULL,
+ },
+};
+
+/* *** ADD/REMOVE A flex FILTER *** */
+struct cmd_flex_filter_result {
+ cmdline_fixed_string_t filter;
+ cmdline_fixed_string_t ops;
+ uint8_t port_id;
+ cmdline_fixed_string_t len;
+ uint8_t len_value;
+ cmdline_fixed_string_t bytes;
+ cmdline_fixed_string_t bytes_value;
+ cmdline_fixed_string_t mask;
+ cmdline_fixed_string_t mask_value;
+ cmdline_fixed_string_t priority;
+ uint8_t priority_value;
+ cmdline_fixed_string_t queue;
+ uint16_t queue_id;
+};
+
+static int xdigit2val(unsigned char c)
+{
+ int val;
+ if (isdigit(c))
+ val = c - '0';
+ else if (isupper(c))
+ val = c - 'A' + 10;
+ else
+ val = c - 'a' + 10;
+ return val;
+}
+
+static void
+cmd_flex_filter_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ int ret = 0;
+ struct rte_eth_flex_filter filter;
+ struct cmd_flex_filter_result *res = parsed_result;
+ char *bytes_ptr, *mask_ptr;
+ uint16_t len, i, j = 0;
+ char c;
+ int val;
+ uint8_t byte = 0;
+
+ if (res->len_value > RTE_FLEX_FILTER_MAXLEN) {
+ printf("the len exceed the max length 128\n");
+ return;
+ }
+ memset(&filter, 0, sizeof(struct rte_eth_flex_filter));
+ filter.len = res->len_value;
+ filter.priority = res->priority_value;
+ filter.queue = res->queue_id;
+ bytes_ptr = res->bytes_value;
+ mask_ptr = res->mask_value;
+
+ /* translate bytes string to array. */
+ if (bytes_ptr[0] == '0' && ((bytes_ptr[1] == 'x') ||
+ (bytes_ptr[1] == 'X')))
+ bytes_ptr += 2;
+ len = strnlen(bytes_ptr, res->len_value * 2);
+ if (len == 0 || (len % 8 != 0)) {
+ printf("please check len and bytes input\n");
+ return;
+ }
+ for (i = 0; i < len; i++) {
+ c = bytes_ptr[i];
+ if (isxdigit(c) == 0) {
+ /* invalid characters. */
+ printf("invalid input\n");
+ return;
+ }
+ val = xdigit2val(c);
+ if (i % 2) {
+ byte |= val;
+ filter.bytes[j] = byte;
+ printf("bytes[%d]:%02x ", j, filter.bytes[j]);
+ j++;
+ byte = 0;
+ } else
+ byte |= val << 4;
+ }
+ printf("\n");
+ /* translate mask string to uint8_t array. */
+ if (mask_ptr[0] == '0' && ((mask_ptr[1] == 'x') ||
+ (mask_ptr[1] == 'X')))
+ mask_ptr += 2;
+ len = strnlen(mask_ptr, (res->len_value + 3) / 4);
+ if (len == 0) {
+ printf("invalid input\n");
+ return;
+ }
+ j = 0;
+ byte = 0;
+ for (i = 0; i < len; i++) {
+ c = mask_ptr[i];
+ if (isxdigit(c) == 0) {
+ /* invalid characters. */
+ printf("invalid input\n");
+ return;
+ }
+ val = xdigit2val(c);
+ if (i % 2) {
+ byte |= val;
+ filter.mask[j] = byte;
+ printf("mask[%d]:%02x ", j, filter.mask[j]);
+ j++;
+ byte = 0;
+ } else
+ byte |= val << 4;
+ }
+ printf("\n");
+
+ if (!strcmp(res->ops, "add"))
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_FLEXIBLE,
+ RTE_ETH_FILTER_ADD,
+ &filter);
+ else
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_FLEXIBLE,
+ RTE_ETH_FILTER_DELETE,
+ &filter);
+
+ if (ret < 0)
+ printf("flex filter setting error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_flex_filter_filter =
+ TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+ filter, "flex_filter");
+cmdline_parse_token_num_t cmd_flex_filter_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_flex_filter_ops =
+ TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+ ops, "add#del");
+cmdline_parse_token_string_t cmd_flex_filter_len =
+ TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+ len, "len");
+cmdline_parse_token_num_t cmd_flex_filter_len_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+ len_value, UINT8);
+cmdline_parse_token_string_t cmd_flex_filter_bytes =
+ TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+ bytes, "bytes");
+cmdline_parse_token_string_t cmd_flex_filter_bytes_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+ bytes_value, NULL);
+cmdline_parse_token_string_t cmd_flex_filter_mask =
+ TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+ mask, "mask");
+cmdline_parse_token_string_t cmd_flex_filter_mask_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+ mask_value, NULL);
+cmdline_parse_token_string_t cmd_flex_filter_priority =
+ TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+ priority, "priority");
+cmdline_parse_token_num_t cmd_flex_filter_priority_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+ priority_value, UINT8);
+cmdline_parse_token_string_t cmd_flex_filter_queue =
+ TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+ queue, "queue");
+cmdline_parse_token_num_t cmd_flex_filter_queue_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+ queue_id, UINT16);
+cmdline_parse_inst_t cmd_flex_filter = {
+ .f = cmd_flex_filter_parsed,
+ .data = NULL,
+ .help_str = "flex_filter <port_id> add|del len <value> bytes "
+ "<value> mask <value> priority <value> queue <queue_id>: "
+ "Add/Del a flex filter",
+ .tokens = {
+ (void *)&cmd_flex_filter_filter,
+ (void *)&cmd_flex_filter_port_id,
+ (void *)&cmd_flex_filter_ops,
+ (void *)&cmd_flex_filter_len,
+ (void *)&cmd_flex_filter_len_value,
+ (void *)&cmd_flex_filter_bytes,
+ (void *)&cmd_flex_filter_bytes_value,
+ (void *)&cmd_flex_filter_mask,
+ (void *)&cmd_flex_filter_mask_value,
+ (void *)&cmd_flex_filter_priority,
+ (void *)&cmd_flex_filter_priority_value,
+ (void *)&cmd_flex_filter_queue,
+ (void *)&cmd_flex_filter_queue_id,
+ NULL,
+ },
+};
+
+/* *** Filters Control *** */
+
+/* *** deal with ethertype filter *** */
+struct cmd_ethertype_filter_result {
+ cmdline_fixed_string_t filter;
+ uint8_t port_id;
+ cmdline_fixed_string_t ops;
+ cmdline_fixed_string_t mac;
+ struct ether_addr mac_addr;
+ cmdline_fixed_string_t ethertype;
+ uint16_t ethertype_value;
+ cmdline_fixed_string_t drop;
+ cmdline_fixed_string_t queue;
+ uint16_t queue_id;
+};
+
+cmdline_parse_token_string_t cmd_ethertype_filter_filter =
+ TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+ filter, "ethertype_filter");
+cmdline_parse_token_num_t cmd_ethertype_filter_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_ethertype_filter_ops =
+ TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+ ops, "add#del");
+cmdline_parse_token_string_t cmd_ethertype_filter_mac =
+ TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+ mac, "mac_addr#mac_ignr");
+cmdline_parse_token_etheraddr_t cmd_ethertype_filter_mac_addr =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_ethertype_filter_result,
+ mac_addr);
+cmdline_parse_token_string_t cmd_ethertype_filter_ethertype =
+ TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+ ethertype, "ethertype");
+cmdline_parse_token_num_t cmd_ethertype_filter_ethertype_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result,
+ ethertype_value, UINT16);
+cmdline_parse_token_string_t cmd_ethertype_filter_drop =
+ TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+ drop, "drop#fwd");
+cmdline_parse_token_string_t cmd_ethertype_filter_queue =
+ TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+ queue, "queue");
+cmdline_parse_token_num_t cmd_ethertype_filter_queue_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result,
+ queue_id, UINT16);
+
+static void
+cmd_ethertype_filter_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_ethertype_filter_result *res = parsed_result;
+ struct rte_eth_ethertype_filter filter;
+ int ret = 0;
+
+ ret = rte_eth_dev_filter_supported(res->port_id,
+ RTE_ETH_FILTER_ETHERTYPE);
+ if (ret < 0) {
+ printf("ethertype filter is not supported on port %u.\n",
+ res->port_id);
+ return;
+ }
+
+ memset(&filter, 0, sizeof(filter));
+ if (!strcmp(res->mac, "mac_addr")) {
+ filter.flags |= RTE_ETHTYPE_FLAGS_MAC;
+ (void)rte_memcpy(&filter.mac_addr, &res->mac_addr,
+ sizeof(struct ether_addr));
+ }
+ if (!strcmp(res->drop, "drop"))
+ filter.flags |= RTE_ETHTYPE_FLAGS_DROP;
+ filter.ether_type = res->ethertype_value;
+ filter.queue = res->queue_id;
+
+ if (!strcmp(res->ops, "add"))
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_ETHERTYPE,
+ RTE_ETH_FILTER_ADD,
+ &filter);
+ else
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_ETHERTYPE,
+ RTE_ETH_FILTER_DELETE,
+ &filter);
+ if (ret < 0)
+ printf("ethertype filter programming error: (%s)\n",
+ strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_ethertype_filter = {
+ .f = cmd_ethertype_filter_parsed,
+ .data = NULL,
+ .help_str = "ethertype_filter <port_id> add|del mac_addr|mac_ignr "
+ "<mac_addr> ethertype <value> drop|fw queue <queue_id>: "
+ "Add or delete an ethertype filter entry",
+ .tokens = {
+ (void *)&cmd_ethertype_filter_filter,
+ (void *)&cmd_ethertype_filter_port_id,
+ (void *)&cmd_ethertype_filter_ops,
+ (void *)&cmd_ethertype_filter_mac,
+ (void *)&cmd_ethertype_filter_mac_addr,
+ (void *)&cmd_ethertype_filter_ethertype,
+ (void *)&cmd_ethertype_filter_ethertype_value,
+ (void *)&cmd_ethertype_filter_drop,
+ (void *)&cmd_ethertype_filter_queue,
+ (void *)&cmd_ethertype_filter_queue_id,
+ NULL,
+ },
+};
+
+/* *** deal with flow director filter *** */
+struct cmd_flow_director_result {
+ cmdline_fixed_string_t flow_director_filter;
+ uint8_t port_id;
+ cmdline_fixed_string_t mode;
+ cmdline_fixed_string_t mode_value;
+ cmdline_fixed_string_t ops;
+ cmdline_fixed_string_t flow;
+ cmdline_fixed_string_t flow_type;
+ cmdline_fixed_string_t ether;
+ uint16_t ether_type;
+ cmdline_fixed_string_t src;
+ cmdline_ipaddr_t ip_src;
+ uint16_t port_src;
+ cmdline_fixed_string_t dst;
+ cmdline_ipaddr_t ip_dst;
+ uint16_t port_dst;
+ cmdline_fixed_string_t verify_tag;
+ uint32_t verify_tag_value;
+ cmdline_ipaddr_t tos;
+ uint8_t tos_value;
+ cmdline_ipaddr_t proto;
+ uint8_t proto_value;
+ cmdline_ipaddr_t ttl;
+ uint8_t ttl_value;
+ cmdline_fixed_string_t vlan;
+ uint16_t vlan_value;
+ cmdline_fixed_string_t flexbytes;
+ cmdline_fixed_string_t flexbytes_value;
+ cmdline_fixed_string_t pf_vf;
+ cmdline_fixed_string_t drop;
+ cmdline_fixed_string_t queue;
+ uint16_t queue_id;
+ cmdline_fixed_string_t fd_id;
+ uint32_t fd_id_value;
+ cmdline_fixed_string_t mac;
+ struct ether_addr mac_addr;
+ cmdline_fixed_string_t tunnel;
+ cmdline_fixed_string_t tunnel_type;
+ cmdline_fixed_string_t tunnel_id;
+ uint32_t tunnel_id_value;
+};
+
+static inline int
+parse_flexbytes(const char *q_arg, uint8_t *flexbytes, uint16_t max_num)
+{
+ char s[256];
+ const char *p, *p0 = q_arg;
+ char *end;
+ unsigned long int_fld;
+ char *str_fld[max_num];
+ int i;
+ unsigned size;
+ int ret = -1;
+
+ p = strchr(p0, '(');
+ if (p == NULL)
+ return -1;
+ ++p;
+ p0 = strchr(p, ')');
+ if (p0 == NULL)
+ return -1;
+
+ size = p0 - p;
+ if (size >= sizeof(s))
+ return -1;
+
+ snprintf(s, sizeof(s), "%.*s", size, p);
+ ret = rte_strsplit(s, sizeof(s), str_fld, max_num, ',');
+ if (ret < 0 || ret > max_num)
+ return -1;
+ for (i = 0; i < ret; i++) {
+ errno = 0;
+ int_fld = strtoul(str_fld[i], &end, 0);
+ if (errno != 0 || *end != '\0' || int_fld > UINT8_MAX)
+ return -1;
+ flexbytes[i] = (uint8_t)int_fld;
+ }
+ return ret;
+}
+
+static uint16_t
+str2flowtype(char *string)
+{
+ uint8_t i = 0;
+ static const struct {
+ char str[32];
+ uint16_t type;
+ } flowtype_str[] = {
+ {"raw", RTE_ETH_FLOW_RAW},
+ {"ipv4", RTE_ETH_FLOW_IPV4},
+ {"ipv4-frag", RTE_ETH_FLOW_FRAG_IPV4},
+ {"ipv4-tcp", RTE_ETH_FLOW_NONFRAG_IPV4_TCP},
+ {"ipv4-udp", RTE_ETH_FLOW_NONFRAG_IPV4_UDP},
+ {"ipv4-sctp", RTE_ETH_FLOW_NONFRAG_IPV4_SCTP},
+ {"ipv4-other", RTE_ETH_FLOW_NONFRAG_IPV4_OTHER},
+ {"ipv6", RTE_ETH_FLOW_IPV6},
+ {"ipv6-frag", RTE_ETH_FLOW_FRAG_IPV6},
+ {"ipv6-tcp", RTE_ETH_FLOW_NONFRAG_IPV6_TCP},
+ {"ipv6-udp", RTE_ETH_FLOW_NONFRAG_IPV6_UDP},
+ {"ipv6-sctp", RTE_ETH_FLOW_NONFRAG_IPV6_SCTP},
+ {"ipv6-other", RTE_ETH_FLOW_NONFRAG_IPV6_OTHER},
+ {"l2_payload", RTE_ETH_FLOW_L2_PAYLOAD},
+ };
+
+ for (i = 0; i < RTE_DIM(flowtype_str); i++) {
+ if (!strcmp(flowtype_str[i].str, string))
+ return flowtype_str[i].type;
+ }
+ return RTE_ETH_FLOW_UNKNOWN;
+}
+
+static enum rte_eth_fdir_tunnel_type
+str2fdir_tunneltype(char *string)
+{
+ uint8_t i = 0;
+
+ static const struct {
+ char str[32];
+ enum rte_eth_fdir_tunnel_type type;
+ } tunneltype_str[] = {
+ {"NVGRE", RTE_FDIR_TUNNEL_TYPE_NVGRE},
+ {"VxLAN", RTE_FDIR_TUNNEL_TYPE_VXLAN},
+ };
+
+ for (i = 0; i < RTE_DIM(tunneltype_str); i++) {
+ if (!strcmp(tunneltype_str[i].str, string))
+ return tunneltype_str[i].type;
+ }
+ return RTE_FDIR_TUNNEL_TYPE_UNKNOWN;
+}
+
+#define IPV4_ADDR_TO_UINT(ip_addr, ip) \
+do { \
+ if ((ip_addr).family == AF_INET) \
+ (ip) = (ip_addr).addr.ipv4.s_addr; \
+ else { \
+ printf("invalid parameter.\n"); \
+ return; \
+ } \
+} while (0)
+
+#define IPV6_ADDR_TO_ARRAY(ip_addr, ip) \
+do { \
+ if ((ip_addr).family == AF_INET6) \
+ (void)rte_memcpy(&(ip), \
+ &((ip_addr).addr.ipv6), \
+ sizeof(struct in6_addr)); \
+ else { \
+ printf("invalid parameter.\n"); \
+ return; \
+ } \
+} while (0)
+
+static void
+cmd_flow_director_filter_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_flow_director_result *res = parsed_result;
+ struct rte_eth_fdir_filter entry;
+ uint8_t flexbytes[RTE_ETH_FDIR_MAX_FLEXLEN];
+ char *end;
+ unsigned long vf_id;
+ int ret = 0;
+
+ ret = rte_eth_dev_filter_supported(res->port_id, RTE_ETH_FILTER_FDIR);
+ if (ret < 0) {
+ printf("flow director is not supported on port %u.\n",
+ res->port_id);
+ return;
+ }
+ memset(flexbytes, 0, sizeof(flexbytes));
+ memset(&entry, 0, sizeof(struct rte_eth_fdir_filter));
+
+ if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) {
+ if (strcmp(res->mode_value, "MAC-VLAN")) {
+ printf("Please set mode to MAC-VLAN.\n");
+ return;
+ }
+ } else if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_TUNNEL) {
+ if (strcmp(res->mode_value, "Tunnel")) {
+ printf("Please set mode to Tunnel.\n");
+ return;
+ }
+ } else {
+ if (strcmp(res->mode_value, "IP")) {
+ printf("Please set mode to IP.\n");
+ return;
+ }
+ entry.input.flow_type = str2flowtype(res->flow_type);
+ }
+
+ ret = parse_flexbytes(res->flexbytes_value,
+ flexbytes,
+ RTE_ETH_FDIR_MAX_FLEXLEN);
+ if (ret < 0) {
+ printf("error: Cannot parse flexbytes input.\n");
+ return;
+ }
+
+ switch (entry.input.flow_type) {
+ case RTE_ETH_FLOW_FRAG_IPV4:
+ case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER:
+ entry.input.flow.ip4_flow.proto = res->proto_value;
+ /* fall-through */
+ case RTE_ETH_FLOW_NONFRAG_IPV4_UDP:
+ case RTE_ETH_FLOW_NONFRAG_IPV4_TCP:
+ IPV4_ADDR_TO_UINT(res->ip_dst,
+ entry.input.flow.ip4_flow.dst_ip);
+ IPV4_ADDR_TO_UINT(res->ip_src,
+ entry.input.flow.ip4_flow.src_ip);
+ entry.input.flow.ip4_flow.tos = res->tos_value;
+ entry.input.flow.ip4_flow.ttl = res->ttl_value;
+ /* need convert to big endian. */
+ entry.input.flow.udp4_flow.dst_port =
+ rte_cpu_to_be_16(res->port_dst);
+ entry.input.flow.udp4_flow.src_port =
+ rte_cpu_to_be_16(res->port_src);
+ break;
+ case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP:
+ IPV4_ADDR_TO_UINT(res->ip_dst,
+ entry.input.flow.sctp4_flow.ip.dst_ip);
+ IPV4_ADDR_TO_UINT(res->ip_src,
+ entry.input.flow.sctp4_flow.ip.src_ip);
+ entry.input.flow.ip4_flow.tos = res->tos_value;
+ entry.input.flow.ip4_flow.ttl = res->ttl_value;
+ /* need convert to big endian. */
+ entry.input.flow.sctp4_flow.dst_port =
+ rte_cpu_to_be_16(res->port_dst);
+ entry.input.flow.sctp4_flow.src_port =
+ rte_cpu_to_be_16(res->port_src);
+ entry.input.flow.sctp4_flow.verify_tag =
+ rte_cpu_to_be_32(res->verify_tag_value);
+ break;
+ case RTE_ETH_FLOW_FRAG_IPV6:
+ case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER:
+ entry.input.flow.ipv6_flow.proto = res->proto_value;
+ /* fall-through */
+ case RTE_ETH_FLOW_NONFRAG_IPV6_UDP:
+ case RTE_ETH_FLOW_NONFRAG_IPV6_TCP:
+ IPV6_ADDR_TO_ARRAY(res->ip_dst,
+ entry.input.flow.ipv6_flow.dst_ip);
+ IPV6_ADDR_TO_ARRAY(res->ip_src,
+ entry.input.flow.ipv6_flow.src_ip);
+ entry.input.flow.ipv6_flow.tc = res->tos_value;
+ entry.input.flow.ipv6_flow.hop_limits = res->ttl_value;
+ /* need convert to big endian. */
+ entry.input.flow.udp6_flow.dst_port =
+ rte_cpu_to_be_16(res->port_dst);
+ entry.input.flow.udp6_flow.src_port =
+ rte_cpu_to_be_16(res->port_src);
+ break;
+ case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP:
+ IPV6_ADDR_TO_ARRAY(res->ip_dst,
+ entry.input.flow.sctp6_flow.ip.dst_ip);
+ IPV6_ADDR_TO_ARRAY(res->ip_src,
+ entry.input.flow.sctp6_flow.ip.src_ip);
+ entry.input.flow.ipv6_flow.tc = res->tos_value;
+ entry.input.flow.ipv6_flow.hop_limits = res->ttl_value;
+ /* need convert to big endian. */
+ entry.input.flow.sctp6_flow.dst_port =
+ rte_cpu_to_be_16(res->port_dst);
+ entry.input.flow.sctp6_flow.src_port =
+ rte_cpu_to_be_16(res->port_src);
+ entry.input.flow.sctp6_flow.verify_tag =
+ rte_cpu_to_be_32(res->verify_tag_value);
+ break;
+ case RTE_ETH_FLOW_L2_PAYLOAD:
+ entry.input.flow.l2_flow.ether_type =
+ rte_cpu_to_be_16(res->ether_type);
+ break;
+ default:
+ break;
+ }
+
+ if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN)
+ (void)rte_memcpy(&entry.input.flow.mac_vlan_flow.mac_addr,
+ &res->mac_addr,
+ sizeof(struct ether_addr));
+
+ if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_TUNNEL) {
+ (void)rte_memcpy(&entry.input.flow.tunnel_flow.mac_addr,
+ &res->mac_addr,
+ sizeof(struct ether_addr));
+ entry.input.flow.tunnel_flow.tunnel_type =
+ str2fdir_tunneltype(res->tunnel_type);
+ entry.input.flow.tunnel_flow.tunnel_id =
+ rte_cpu_to_be_32(res->tunnel_id_value);
+ }
+
+ (void)rte_memcpy(entry.input.flow_ext.flexbytes,
+ flexbytes,
+ RTE_ETH_FDIR_MAX_FLEXLEN);
+
+ entry.input.flow_ext.vlan_tci = rte_cpu_to_be_16(res->vlan_value);
+
+ entry.action.flex_off = 0; /*use 0 by default */
+ if (!strcmp(res->drop, "drop"))
+ entry.action.behavior = RTE_ETH_FDIR_REJECT;
+ else
+ entry.action.behavior = RTE_ETH_FDIR_ACCEPT;
+
+ if (fdir_conf.mode != RTE_FDIR_MODE_PERFECT_MAC_VLAN &&
+ fdir_conf.mode != RTE_FDIR_MODE_PERFECT_TUNNEL) {
+ if (!strcmp(res->pf_vf, "pf"))
+ entry.input.flow_ext.is_vf = 0;
+ else if (!strncmp(res->pf_vf, "vf", 2)) {
+ struct rte_eth_dev_info dev_info;
+
+ memset(&dev_info, 0, sizeof(dev_info));
+ rte_eth_dev_info_get(res->port_id, &dev_info);
+ errno = 0;
+ vf_id = strtoul(res->pf_vf + 2, &end, 10);
+ if (errno != 0 || *end != '\0' ||
+ vf_id >= dev_info.max_vfs) {
+ printf("invalid parameter %s.\n", res->pf_vf);
+ return;
+ }
+ entry.input.flow_ext.is_vf = 1;
+ entry.input.flow_ext.dst_id = (uint16_t)vf_id;
+ } else {
+ printf("invalid parameter %s.\n", res->pf_vf);
+ return;
+ }
+ }
+
+ /* set to report FD ID by default */
+ entry.action.report_status = RTE_ETH_FDIR_REPORT_ID;
+ entry.action.rx_queue = res->queue_id;
+ entry.soft_id = res->fd_id_value;
+ if (!strcmp(res->ops, "add"))
+ ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_ADD, &entry);
+ else if (!strcmp(res->ops, "del"))
+ ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_DELETE, &entry);
+ else
+ ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_UPDATE, &entry);
+ if (ret < 0)
+ printf("flow director programming error: (%s)\n",
+ strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_flow_director_filter =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ flow_director_filter, "flow_director_filter");
+cmdline_parse_token_num_t cmd_flow_director_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_flow_director_ops =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ ops, "add#del#update");
+cmdline_parse_token_string_t cmd_flow_director_flow =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ flow, "flow");
+cmdline_parse_token_string_t cmd_flow_director_flow_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ flow_type, "ipv4-other#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#"
+ "ipv6-other#ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#l2_payload");
+cmdline_parse_token_string_t cmd_flow_director_ether =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ ether, "ether");
+cmdline_parse_token_num_t cmd_flow_director_ether_type =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ ether_type, UINT16);
+cmdline_parse_token_string_t cmd_flow_director_src =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ src, "src");
+cmdline_parse_token_ipaddr_t cmd_flow_director_ip_src =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_flow_director_result,
+ ip_src);
+cmdline_parse_token_num_t cmd_flow_director_port_src =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ port_src, UINT16);
+cmdline_parse_token_string_t cmd_flow_director_dst =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ dst, "dst");
+cmdline_parse_token_ipaddr_t cmd_flow_director_ip_dst =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_flow_director_result,
+ ip_dst);
+cmdline_parse_token_num_t cmd_flow_director_port_dst =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ port_dst, UINT16);
+cmdline_parse_token_string_t cmd_flow_director_verify_tag =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ verify_tag, "verify_tag");
+cmdline_parse_token_num_t cmd_flow_director_verify_tag_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ verify_tag_value, UINT32);
+cmdline_parse_token_string_t cmd_flow_director_tos =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ tos, "tos");
+cmdline_parse_token_num_t cmd_flow_director_tos_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ tos_value, UINT8);
+cmdline_parse_token_string_t cmd_flow_director_proto =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ proto, "proto");
+cmdline_parse_token_num_t cmd_flow_director_proto_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ proto_value, UINT8);
+cmdline_parse_token_string_t cmd_flow_director_ttl =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ ttl, "ttl");
+cmdline_parse_token_num_t cmd_flow_director_ttl_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ ttl_value, UINT8);
+cmdline_parse_token_string_t cmd_flow_director_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ vlan, "vlan");
+cmdline_parse_token_num_t cmd_flow_director_vlan_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ vlan_value, UINT16);
+cmdline_parse_token_string_t cmd_flow_director_flexbytes =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ flexbytes, "flexbytes");
+cmdline_parse_token_string_t cmd_flow_director_flexbytes_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ flexbytes_value, NULL);
+cmdline_parse_token_string_t cmd_flow_director_drop =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ drop, "drop#fwd");
+cmdline_parse_token_string_t cmd_flow_director_pf_vf =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ pf_vf, NULL);
+cmdline_parse_token_string_t cmd_flow_director_queue =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ queue, "queue");
+cmdline_parse_token_num_t cmd_flow_director_queue_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ queue_id, UINT16);
+cmdline_parse_token_string_t cmd_flow_director_fd_id =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ fd_id, "fd_id");
+cmdline_parse_token_num_t cmd_flow_director_fd_id_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ fd_id_value, UINT32);
+
+cmdline_parse_token_string_t cmd_flow_director_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ mode, "mode");
+cmdline_parse_token_string_t cmd_flow_director_mode_ip =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ mode_value, "IP");
+cmdline_parse_token_string_t cmd_flow_director_mode_mac_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ mode_value, "MAC-VLAN");
+cmdline_parse_token_string_t cmd_flow_director_mode_tunnel =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ mode_value, "Tunnel");
+cmdline_parse_token_string_t cmd_flow_director_mac =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ mac, "mac");
+cmdline_parse_token_etheraddr_t cmd_flow_director_mac_addr =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_flow_director_result,
+ mac_addr);
+cmdline_parse_token_string_t cmd_flow_director_tunnel =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ tunnel, "tunnel");
+cmdline_parse_token_string_t cmd_flow_director_tunnel_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ tunnel_type, "NVGRE#VxLAN");
+cmdline_parse_token_string_t cmd_flow_director_tunnel_id =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ tunnel_id, "tunnel-id");
+cmdline_parse_token_num_t cmd_flow_director_tunnel_id_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ tunnel_id_value, UINT32);
+
+cmdline_parse_inst_t cmd_add_del_ip_flow_director = {
+ .f = cmd_flow_director_filter_parsed,
+ .data = NULL,
+ .help_str = "flow_director_filter <port_id> mode IP add|del|update flow"
+ " ipv4-other|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|"
+ "ipv6-other|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|"
+ "l2_payload src <src_ip> dst <dst_ip> tos <tos_value> "
+ "proto <proto_value> ttl <ttl_value> vlan <vlan_value> "
+ "flexbytes <flexbyte_vaues> drop|fw <pf_vf> queue <queue_id> "
+ "fd_id <fd_id_value>: "
+ "Add or delete an ip flow director entry on NIC",
+ .tokens = {
+ (void *)&cmd_flow_director_filter,
+ (void *)&cmd_flow_director_port_id,
+ (void *)&cmd_flow_director_mode,
+ (void *)&cmd_flow_director_mode_ip,
+ (void *)&cmd_flow_director_ops,
+ (void *)&cmd_flow_director_flow,
+ (void *)&cmd_flow_director_flow_type,
+ (void *)&cmd_flow_director_src,
+ (void *)&cmd_flow_director_ip_src,
+ (void *)&cmd_flow_director_dst,
+ (void *)&cmd_flow_director_ip_dst,
+ (void *)&cmd_flow_director_tos,
+ (void *)&cmd_flow_director_tos_value,
+ (void *)&cmd_flow_director_proto,
+ (void *)&cmd_flow_director_proto_value,
+ (void *)&cmd_flow_director_ttl,
+ (void *)&cmd_flow_director_ttl_value,
+ (void *)&cmd_flow_director_vlan,
+ (void *)&cmd_flow_director_vlan_value,
+ (void *)&cmd_flow_director_flexbytes,
+ (void *)&cmd_flow_director_flexbytes_value,
+ (void *)&cmd_flow_director_drop,
+ (void *)&cmd_flow_director_pf_vf,
+ (void *)&cmd_flow_director_queue,
+ (void *)&cmd_flow_director_queue_id,
+ (void *)&cmd_flow_director_fd_id,
+ (void *)&cmd_flow_director_fd_id_value,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_add_del_udp_flow_director = {
+ .f = cmd_flow_director_filter_parsed,
+ .data = NULL,
+ .help_str = "flow_director_filter ... : Add or delete an udp/tcp flow "
+ "director entry on NIC",
+ .tokens = {
+ (void *)&cmd_flow_director_filter,
+ (void *)&cmd_flow_director_port_id,
+ (void *)&cmd_flow_director_mode,
+ (void *)&cmd_flow_director_mode_ip,
+ (void *)&cmd_flow_director_ops,
+ (void *)&cmd_flow_director_flow,
+ (void *)&cmd_flow_director_flow_type,
+ (void *)&cmd_flow_director_src,
+ (void *)&cmd_flow_director_ip_src,
+ (void *)&cmd_flow_director_port_src,
+ (void *)&cmd_flow_director_dst,
+ (void *)&cmd_flow_director_ip_dst,
+ (void *)&cmd_flow_director_port_dst,
+ (void *)&cmd_flow_director_tos,
+ (void *)&cmd_flow_director_tos_value,
+ (void *)&cmd_flow_director_ttl,
+ (void *)&cmd_flow_director_ttl_value,
+ (void *)&cmd_flow_director_vlan,
+ (void *)&cmd_flow_director_vlan_value,
+ (void *)&cmd_flow_director_flexbytes,
+ (void *)&cmd_flow_director_flexbytes_value,
+ (void *)&cmd_flow_director_drop,
+ (void *)&cmd_flow_director_pf_vf,
+ (void *)&cmd_flow_director_queue,
+ (void *)&cmd_flow_director_queue_id,
+ (void *)&cmd_flow_director_fd_id,
+ (void *)&cmd_flow_director_fd_id_value,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_add_del_sctp_flow_director = {
+ .f = cmd_flow_director_filter_parsed,
+ .data = NULL,
+ .help_str = "flow_director_filter ... : Add or delete a sctp flow "
+ "director entry on NIC",
+ .tokens = {
+ (void *)&cmd_flow_director_filter,
+ (void *)&cmd_flow_director_port_id,
+ (void *)&cmd_flow_director_mode,
+ (void *)&cmd_flow_director_mode_ip,
+ (void *)&cmd_flow_director_ops,
+ (void *)&cmd_flow_director_flow,
+ (void *)&cmd_flow_director_flow_type,
+ (void *)&cmd_flow_director_src,
+ (void *)&cmd_flow_director_ip_src,
+ (void *)&cmd_flow_director_port_dst,
+ (void *)&cmd_flow_director_dst,
+ (void *)&cmd_flow_director_ip_dst,
+ (void *)&cmd_flow_director_port_dst,
+ (void *)&cmd_flow_director_verify_tag,
+ (void *)&cmd_flow_director_verify_tag_value,
+ (void *)&cmd_flow_director_tos,
+ (void *)&cmd_flow_director_tos_value,
+ (void *)&cmd_flow_director_ttl,
+ (void *)&cmd_flow_director_ttl_value,
+ (void *)&cmd_flow_director_vlan,
+ (void *)&cmd_flow_director_vlan_value,
+ (void *)&cmd_flow_director_flexbytes,
+ (void *)&cmd_flow_director_flexbytes_value,
+ (void *)&cmd_flow_director_drop,
+ (void *)&cmd_flow_director_pf_vf,
+ (void *)&cmd_flow_director_queue,
+ (void *)&cmd_flow_director_queue_id,
+ (void *)&cmd_flow_director_fd_id,
+ (void *)&cmd_flow_director_fd_id_value,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_add_del_l2_flow_director = {
+ .f = cmd_flow_director_filter_parsed,
+ .data = NULL,
+ .help_str = "flow_director_filter ... : Add or delete a L2 flow "
+ "director entry on NIC",
+ .tokens = {
+ (void *)&cmd_flow_director_filter,
+ (void *)&cmd_flow_director_port_id,
+ (void *)&cmd_flow_director_mode,
+ (void *)&cmd_flow_director_mode_ip,
+ (void *)&cmd_flow_director_ops,
+ (void *)&cmd_flow_director_flow,
+ (void *)&cmd_flow_director_flow_type,
+ (void *)&cmd_flow_director_ether,
+ (void *)&cmd_flow_director_ether_type,
+ (void *)&cmd_flow_director_flexbytes,
+ (void *)&cmd_flow_director_flexbytes_value,
+ (void *)&cmd_flow_director_drop,
+ (void *)&cmd_flow_director_pf_vf,
+ (void *)&cmd_flow_director_queue,
+ (void *)&cmd_flow_director_queue_id,
+ (void *)&cmd_flow_director_fd_id,
+ (void *)&cmd_flow_director_fd_id_value,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_add_del_mac_vlan_flow_director = {
+ .f = cmd_flow_director_filter_parsed,
+ .data = NULL,
+ .help_str = "flow_director_filter ... : Add or delete a MAC VLAN flow "
+ "director entry on NIC",
+ .tokens = {
+ (void *)&cmd_flow_director_filter,
+ (void *)&cmd_flow_director_port_id,
+ (void *)&cmd_flow_director_mode,
+ (void *)&cmd_flow_director_mode_mac_vlan,
+ (void *)&cmd_flow_director_ops,
+ (void *)&cmd_flow_director_mac,
+ (void *)&cmd_flow_director_mac_addr,
+ (void *)&cmd_flow_director_vlan,
+ (void *)&cmd_flow_director_vlan_value,
+ (void *)&cmd_flow_director_flexbytes,
+ (void *)&cmd_flow_director_flexbytes_value,
+ (void *)&cmd_flow_director_drop,
+ (void *)&cmd_flow_director_queue,
+ (void *)&cmd_flow_director_queue_id,
+ (void *)&cmd_flow_director_fd_id,
+ (void *)&cmd_flow_director_fd_id_value,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_add_del_tunnel_flow_director = {
+ .f = cmd_flow_director_filter_parsed,
+ .data = NULL,
+ .help_str = "flow_director_filter ... : Add or delete a tunnel flow "
+ "director entry on NIC",
+ .tokens = {
+ (void *)&cmd_flow_director_filter,
+ (void *)&cmd_flow_director_port_id,
+ (void *)&cmd_flow_director_mode,
+ (void *)&cmd_flow_director_mode_tunnel,
+ (void *)&cmd_flow_director_ops,
+ (void *)&cmd_flow_director_mac,
+ (void *)&cmd_flow_director_mac_addr,
+ (void *)&cmd_flow_director_vlan,
+ (void *)&cmd_flow_director_vlan_value,
+ (void *)&cmd_flow_director_tunnel,
+ (void *)&cmd_flow_director_tunnel_type,
+ (void *)&cmd_flow_director_tunnel_id,
+ (void *)&cmd_flow_director_tunnel_id_value,
+ (void *)&cmd_flow_director_flexbytes,
+ (void *)&cmd_flow_director_flexbytes_value,
+ (void *)&cmd_flow_director_drop,
+ (void *)&cmd_flow_director_queue,
+ (void *)&cmd_flow_director_queue_id,
+ (void *)&cmd_flow_director_fd_id,
+ (void *)&cmd_flow_director_fd_id_value,
+ NULL,
+ },
+};
+
+struct cmd_flush_flow_director_result {
+ cmdline_fixed_string_t flush_flow_director;
+ uint8_t port_id;
+};
+
+cmdline_parse_token_string_t cmd_flush_flow_director_flush =
+ TOKEN_STRING_INITIALIZER(struct cmd_flush_flow_director_result,
+ flush_flow_director, "flush_flow_director");
+cmdline_parse_token_num_t cmd_flush_flow_director_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_flush_flow_director_result,
+ port_id, UINT8);
+
+static void
+cmd_flush_flow_director_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_flow_director_result *res = parsed_result;
+ int ret = 0;
+
+ ret = rte_eth_dev_filter_supported(res->port_id, RTE_ETH_FILTER_FDIR);
+ if (ret < 0) {
+ printf("flow director is not supported on port %u.\n",
+ res->port_id);
+ return;
+ }
+
+ ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_FLUSH, NULL);
+ if (ret < 0)
+ printf("flow director table flushing error: (%s)\n",
+ strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_flush_flow_director = {
+ .f = cmd_flush_flow_director_parsed,
+ .data = NULL,
+ .help_str = "flush_flow_director <port_id>: "
+ "Flush all flow director entries of a device on NIC",
+ .tokens = {
+ (void *)&cmd_flush_flow_director_flush,
+ (void *)&cmd_flush_flow_director_port_id,
+ NULL,
+ },
+};
+
+/* *** deal with flow director mask *** */
+struct cmd_flow_director_mask_result {
+ cmdline_fixed_string_t flow_director_mask;
+ uint8_t port_id;
+ cmdline_fixed_string_t mode;
+ cmdline_fixed_string_t mode_value;
+ cmdline_fixed_string_t vlan;
+ uint16_t vlan_mask;
+ cmdline_fixed_string_t src_mask;
+ cmdline_ipaddr_t ipv4_src;
+ cmdline_ipaddr_t ipv6_src;
+ uint16_t port_src;
+ cmdline_fixed_string_t dst_mask;
+ cmdline_ipaddr_t ipv4_dst;
+ cmdline_ipaddr_t ipv6_dst;
+ uint16_t port_dst;
+ cmdline_fixed_string_t mac;
+ uint8_t mac_addr_byte_mask;
+ cmdline_fixed_string_t tunnel_id;
+ uint32_t tunnel_id_mask;
+ cmdline_fixed_string_t tunnel_type;
+ uint8_t tunnel_type_mask;
+};
+
+static void
+cmd_flow_director_mask_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_flow_director_mask_result *res = parsed_result;
+ struct rte_eth_fdir_masks *mask;
+ struct rte_port *port;
+
+ if (res->port_id > nb_ports) {
+ printf("Invalid port, range is [0, %d]\n", nb_ports - 1);
+ return;
+ }
+
+ port = &ports[res->port_id];
+ /** Check if the port is not started **/
+ if (port->port_status != RTE_PORT_STOPPED) {
+ printf("Please stop port %d first\n", res->port_id);
+ return;
+ }
+
+ mask = &port->dev_conf.fdir_conf.mask;
+
+ if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) {
+ if (strcmp(res->mode_value, "MAC-VLAN")) {
+ printf("Please set mode to MAC-VLAN.\n");
+ return;
+ }
+
+ mask->vlan_tci_mask = rte_cpu_to_be_16(res->vlan_mask);
+ } else if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_TUNNEL) {
+ if (strcmp(res->mode_value, "Tunnel")) {
+ printf("Please set mode to Tunnel.\n");
+ return;
+ }
+
+ mask->vlan_tci_mask = rte_cpu_to_be_16(res->vlan_mask);
+ mask->mac_addr_byte_mask = res->mac_addr_byte_mask;
+ mask->tunnel_id_mask = rte_cpu_to_be_32(res->tunnel_id_mask);
+ mask->tunnel_type_mask = res->tunnel_type_mask;
+ } else {
+ if (strcmp(res->mode_value, "IP")) {
+ printf("Please set mode to IP.\n");
+ return;
+ }
+
+ mask->vlan_tci_mask = rte_cpu_to_be_16(res->vlan_mask);
+ IPV4_ADDR_TO_UINT(res->ipv4_src, mask->ipv4_mask.src_ip);
+ IPV4_ADDR_TO_UINT(res->ipv4_dst, mask->ipv4_mask.dst_ip);
+ IPV6_ADDR_TO_ARRAY(res->ipv6_src, mask->ipv6_mask.src_ip);
+ IPV6_ADDR_TO_ARRAY(res->ipv6_dst, mask->ipv6_mask.dst_ip);
+ mask->src_port_mask = rte_cpu_to_be_16(res->port_src);
+ mask->dst_port_mask = rte_cpu_to_be_16(res->port_dst);
+ }
+
+ cmd_reconfig_device_queue(res->port_id, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_flow_director_mask =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_mask_result,
+ flow_director_mask, "flow_director_mask");
+cmdline_parse_token_num_t cmd_flow_director_mask_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_mask_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_flow_director_mask_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_mask_result,
+ vlan, "vlan");
+cmdline_parse_token_num_t cmd_flow_director_mask_vlan_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_mask_result,
+ vlan_mask, UINT16);
+cmdline_parse_token_string_t cmd_flow_director_mask_src =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_mask_result,
+ src_mask, "src_mask");
+cmdline_parse_token_ipaddr_t cmd_flow_director_mask_ipv4_src =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_flow_director_mask_result,
+ ipv4_src);
+cmdline_parse_token_ipaddr_t cmd_flow_director_mask_ipv6_src =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_flow_director_mask_result,
+ ipv6_src);
+cmdline_parse_token_num_t cmd_flow_director_mask_port_src =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_mask_result,
+ port_src, UINT16);
+cmdline_parse_token_string_t cmd_flow_director_mask_dst =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_mask_result,
+ dst_mask, "dst_mask");
+cmdline_parse_token_ipaddr_t cmd_flow_director_mask_ipv4_dst =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_flow_director_mask_result,
+ ipv4_dst);
+cmdline_parse_token_ipaddr_t cmd_flow_director_mask_ipv6_dst =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_flow_director_mask_result,
+ ipv6_dst);
+cmdline_parse_token_num_t cmd_flow_director_mask_port_dst =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_mask_result,
+ port_dst, UINT16);
+
+cmdline_parse_token_string_t cmd_flow_director_mask_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_mask_result,
+ mode, "mode");
+cmdline_parse_token_string_t cmd_flow_director_mask_mode_ip =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_mask_result,
+ mode_value, "IP");
+cmdline_parse_token_string_t cmd_flow_director_mask_mode_mac_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_mask_result,
+ mode_value, "MAC-VLAN");
+cmdline_parse_token_string_t cmd_flow_director_mask_mode_tunnel =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_mask_result,
+ mode_value, "Tunnel");
+cmdline_parse_token_string_t cmd_flow_director_mask_mac =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_mask_result,
+ mac, "mac");
+cmdline_parse_token_num_t cmd_flow_director_mask_mac_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_mask_result,
+ mac_addr_byte_mask, UINT8);
+cmdline_parse_token_string_t cmd_flow_director_mask_tunnel_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_mask_result,
+ tunnel_type, "tunnel-type");
+cmdline_parse_token_num_t cmd_flow_director_mask_tunnel_type_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_mask_result,
+ tunnel_type_mask, UINT8);
+cmdline_parse_token_string_t cmd_flow_director_mask_tunnel_id =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_mask_result,
+ tunnel_id, "tunnel-id");
+cmdline_parse_token_num_t cmd_flow_director_mask_tunnel_id_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_mask_result,
+ tunnel_id_mask, UINT32);
+
+cmdline_parse_inst_t cmd_set_flow_director_ip_mask = {
+ .f = cmd_flow_director_mask_parsed,
+ .data = NULL,
+ .help_str = "flow_director_mask ... : "
+ "Set IP mode flow director's mask on NIC",
+ .tokens = {
+ (void *)&cmd_flow_director_mask,
+ (void *)&cmd_flow_director_mask_port_id,
+ (void *)&cmd_flow_director_mask_mode,
+ (void *)&cmd_flow_director_mask_mode_ip,
+ (void *)&cmd_flow_director_mask_vlan,
+ (void *)&cmd_flow_director_mask_vlan_value,
+ (void *)&cmd_flow_director_mask_src,
+ (void *)&cmd_flow_director_mask_ipv4_src,
+ (void *)&cmd_flow_director_mask_ipv6_src,
+ (void *)&cmd_flow_director_mask_port_src,
+ (void *)&cmd_flow_director_mask_dst,
+ (void *)&cmd_flow_director_mask_ipv4_dst,
+ (void *)&cmd_flow_director_mask_ipv6_dst,
+ (void *)&cmd_flow_director_mask_port_dst,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_set_flow_director_mac_vlan_mask = {
+ .f = cmd_flow_director_mask_parsed,
+ .data = NULL,
+ .help_str = "flow_director_mask ... : Set MAC VLAN mode "
+ "flow director's mask on NIC",
+ .tokens = {
+ (void *)&cmd_flow_director_mask,
+ (void *)&cmd_flow_director_mask_port_id,
+ (void *)&cmd_flow_director_mask_mode,
+ (void *)&cmd_flow_director_mask_mode_mac_vlan,
+ (void *)&cmd_flow_director_mask_vlan,
+ (void *)&cmd_flow_director_mask_vlan_value,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_set_flow_director_tunnel_mask = {
+ .f = cmd_flow_director_mask_parsed,
+ .data = NULL,
+ .help_str = "flow_director_mask ... : Set tunnel mode "
+ "flow director's mask on NIC",
+ .tokens = {
+ (void *)&cmd_flow_director_mask,
+ (void *)&cmd_flow_director_mask_port_id,
+ (void *)&cmd_flow_director_mask_mode,
+ (void *)&cmd_flow_director_mask_mode_tunnel,
+ (void *)&cmd_flow_director_mask_vlan,
+ (void *)&cmd_flow_director_mask_vlan_value,
+ (void *)&cmd_flow_director_mask_mac,
+ (void *)&cmd_flow_director_mask_mac_value,
+ (void *)&cmd_flow_director_mask_tunnel_type,
+ (void *)&cmd_flow_director_mask_tunnel_type_value,
+ (void *)&cmd_flow_director_mask_tunnel_id,
+ (void *)&cmd_flow_director_mask_tunnel_id_value,
+ NULL,
+ },
+};
+
+/* *** deal with flow director mask on flexible payload *** */
+struct cmd_flow_director_flex_mask_result {
+ cmdline_fixed_string_t flow_director_flexmask;
+ uint8_t port_id;
+ cmdline_fixed_string_t flow;
+ cmdline_fixed_string_t flow_type;
+ cmdline_fixed_string_t mask;
+};
+
+static void
+cmd_flow_director_flex_mask_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_flow_director_flex_mask_result *res = parsed_result;
+ struct rte_eth_fdir_info fdir_info;
+ struct rte_eth_fdir_flex_mask flex_mask;
+ struct rte_port *port;
+ uint32_t flow_type_mask;
+ uint16_t i;
+ int ret;
+
+ if (res->port_id > nb_ports) {
+ printf("Invalid port, range is [0, %d]\n", nb_ports - 1);
+ return;
+ }
+
+ port = &ports[res->port_id];
+ /** Check if the port is not started **/
+ if (port->port_status != RTE_PORT_STOPPED) {
+ printf("Please stop port %d first\n", res->port_id);
+ return;
+ }
+
+ memset(&flex_mask, 0, sizeof(struct rte_eth_fdir_flex_mask));
+ ret = parse_flexbytes(res->mask,
+ flex_mask.mask,
+ RTE_ETH_FDIR_MAX_FLEXLEN);
+ if (ret < 0) {
+ printf("error: Cannot parse mask input.\n");
+ return;
+ }
+
+ memset(&fdir_info, 0, sizeof(fdir_info));
+ ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_INFO, &fdir_info);
+ if (ret < 0) {
+ printf("Cannot get FDir filter info\n");
+ return;
+ }
+
+ if (!strcmp(res->flow_type, "none")) {
+ /* means don't specify the flow type */
+ flex_mask.flow_type = RTE_ETH_FLOW_UNKNOWN;
+ for (i = 0; i < RTE_ETH_FLOW_MAX; i++)
+ memset(&port->dev_conf.fdir_conf.flex_conf.flex_mask[i],
+ 0, sizeof(struct rte_eth_fdir_flex_mask));
+ port->dev_conf.fdir_conf.flex_conf.nb_flexmasks = 1;
+ (void)rte_memcpy(&port->dev_conf.fdir_conf.flex_conf.flex_mask[0],
+ &flex_mask,
+ sizeof(struct rte_eth_fdir_flex_mask));
+ cmd_reconfig_device_queue(res->port_id, 1, 1);
+ return;
+ }
+ flow_type_mask = fdir_info.flow_types_mask[0];
+ if (!strcmp(res->flow_type, "all")) {
+ if (!flow_type_mask) {
+ printf("No flow type supported\n");
+ return;
+ }
+ for (i = RTE_ETH_FLOW_UNKNOWN; i < RTE_ETH_FLOW_MAX; i++) {
+ if (flow_type_mask & (1 << i)) {
+ flex_mask.flow_type = i;
+ fdir_set_flex_mask(res->port_id, &flex_mask);
+ }
+ }
+ cmd_reconfig_device_queue(res->port_id, 1, 1);
+ return;
+ }
+ flex_mask.flow_type = str2flowtype(res->flow_type);
+ if (!(flow_type_mask & (1 << flex_mask.flow_type))) {
+ printf("Flow type %s not supported on port %d\n",
+ res->flow_type, res->port_id);
+ return;
+ }
+ fdir_set_flex_mask(res->port_id, &flex_mask);
+ cmd_reconfig_device_queue(res->port_id, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_flow_director_flexmask =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flex_mask_result,
+ flow_director_flexmask,
+ "flow_director_flex_mask");
+cmdline_parse_token_num_t cmd_flow_director_flexmask_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_flex_mask_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_flow_director_flexmask_flow =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flex_mask_result,
+ flow, "flow");
+cmdline_parse_token_string_t cmd_flow_director_flexmask_flow_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flex_mask_result,
+ flow_type, "none#ipv4-other#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#"
+ "ipv6-other#ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#l2_payload#all");
+cmdline_parse_token_string_t cmd_flow_director_flexmask_mask =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flex_mask_result,
+ mask, NULL);
+
+cmdline_parse_inst_t cmd_set_flow_director_flex_mask = {
+ .f = cmd_flow_director_flex_mask_parsed,
+ .data = NULL,
+ .help_str = "flow_director_flex_mask ... : "
+ "Set flow director's flex mask on NIC",
+ .tokens = {
+ (void *)&cmd_flow_director_flexmask,
+ (void *)&cmd_flow_director_flexmask_port_id,
+ (void *)&cmd_flow_director_flexmask_flow,
+ (void *)&cmd_flow_director_flexmask_flow_type,
+ (void *)&cmd_flow_director_flexmask_mask,
+ NULL,
+ },
+};
+
+/* *** deal with flow director flexible payload configuration *** */
+struct cmd_flow_director_flexpayload_result {
+ cmdline_fixed_string_t flow_director_flexpayload;
+ uint8_t port_id;
+ cmdline_fixed_string_t payload_layer;
+ cmdline_fixed_string_t payload_cfg;
+};
+
+static inline int
+parse_offsets(const char *q_arg, uint16_t *offsets, uint16_t max_num)
+{
+ char s[256];
+ const char *p, *p0 = q_arg;
+ char *end;
+ unsigned long int_fld;
+ char *str_fld[max_num];
+ int i;
+ unsigned size;
+ int ret = -1;
+
+ p = strchr(p0, '(');
+ if (p == NULL)
+ return -1;
+ ++p;
+ p0 = strchr(p, ')');
+ if (p0 == NULL)
+ return -1;
+
+ size = p0 - p;
+ if (size >= sizeof(s))
+ return -1;
+
+ snprintf(s, sizeof(s), "%.*s", size, p);
+ ret = rte_strsplit(s, sizeof(s), str_fld, max_num, ',');
+ if (ret < 0 || ret > max_num)
+ return -1;
+ for (i = 0; i < ret; i++) {
+ errno = 0;
+ int_fld = strtoul(str_fld[i], &end, 0);
+ if (errno != 0 || *end != '\0' || int_fld > UINT16_MAX)
+ return -1;
+ offsets[i] = (uint16_t)int_fld;
+ }
+ return ret;
+}
+
+static void
+cmd_flow_director_flxpld_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_flow_director_flexpayload_result *res = parsed_result;
+ struct rte_eth_flex_payload_cfg flex_cfg;
+ struct rte_port *port;
+ int ret = 0;
+
+ if (res->port_id > nb_ports) {
+ printf("Invalid port, range is [0, %d]\n", nb_ports - 1);
+ return;
+ }
+
+ port = &ports[res->port_id];
+ /** Check if the port is not started **/
+ if (port->port_status != RTE_PORT_STOPPED) {
+ printf("Please stop port %d first\n", res->port_id);
+ return;
+ }
+
+ memset(&flex_cfg, 0, sizeof(struct rte_eth_flex_payload_cfg));
+
+ if (!strcmp(res->payload_layer, "raw"))
+ flex_cfg.type = RTE_ETH_RAW_PAYLOAD;
+ else if (!strcmp(res->payload_layer, "l2"))
+ flex_cfg.type = RTE_ETH_L2_PAYLOAD;
+ else if (!strcmp(res->payload_layer, "l3"))
+ flex_cfg.type = RTE_ETH_L3_PAYLOAD;
+ else if (!strcmp(res->payload_layer, "l4"))
+ flex_cfg.type = RTE_ETH_L4_PAYLOAD;
+
+ ret = parse_offsets(res->payload_cfg, flex_cfg.src_offset,
+ RTE_ETH_FDIR_MAX_FLEXLEN);
+ if (ret < 0) {
+ printf("error: Cannot parse flex payload input.\n");
+ return;
+ }
+
+ fdir_set_flex_payload(res->port_id, &flex_cfg);
+ cmd_reconfig_device_queue(res->port_id, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_flow_director_flexpayload =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flexpayload_result,
+ flow_director_flexpayload,
+ "flow_director_flex_payload");
+cmdline_parse_token_num_t cmd_flow_director_flexpayload_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_flexpayload_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_flow_director_flexpayload_payload_layer =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flexpayload_result,
+ payload_layer, "raw#l2#l3#l4");
+cmdline_parse_token_string_t cmd_flow_director_flexpayload_payload_cfg =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flexpayload_result,
+ payload_cfg, NULL);
+
+cmdline_parse_inst_t cmd_set_flow_director_flex_payload = {
+ .f = cmd_flow_director_flxpld_parsed,
+ .data = NULL,
+ .help_str = "flow_director_flexpayload ... : "
+ "Set flow director's flex payload on NIC",
+ .tokens = {
+ (void *)&cmd_flow_director_flexpayload,
+ (void *)&cmd_flow_director_flexpayload_port_id,
+ (void *)&cmd_flow_director_flexpayload_payload_layer,
+ (void *)&cmd_flow_director_flexpayload_payload_cfg,
+ NULL,
+ },
+};
+
+/* Generic flow interface command. */
+extern cmdline_parse_inst_t cmd_flow;
+
+/* *** Classification Filters Control *** */
+/* *** Get symmetric hash enable per port *** */
+struct cmd_get_sym_hash_ena_per_port_result {
+ cmdline_fixed_string_t get_sym_hash_ena_per_port;
+ uint8_t port_id;
+};
+
+static void
+cmd_get_sym_hash_per_port_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_get_sym_hash_ena_per_port_result *res = parsed_result;
+ struct rte_eth_hash_filter_info info;
+ int ret;
+
+ if (rte_eth_dev_filter_supported(res->port_id,
+ RTE_ETH_FILTER_HASH) < 0) {
+ printf("RTE_ETH_FILTER_HASH not supported on port: %d\n",
+ res->port_id);
+ return;
+ }
+
+ memset(&info, 0, sizeof(info));
+ info.info_type = RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT;
+ ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH,
+ RTE_ETH_FILTER_GET, &info);
+
+ if (ret < 0) {
+ printf("Cannot get symmetric hash enable per port "
+ "on port %u\n", res->port_id);
+ return;
+ }
+
+ printf("Symmetric hash is %s on port %u\n", info.info.enable ?
+ "enabled" : "disabled", res->port_id);
+}
+
+cmdline_parse_token_string_t cmd_get_sym_hash_ena_per_port_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_get_sym_hash_ena_per_port_result,
+ get_sym_hash_ena_per_port, "get_sym_hash_ena_per_port");
+cmdline_parse_token_num_t cmd_get_sym_hash_ena_per_port_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_get_sym_hash_ena_per_port_result,
+ port_id, UINT8);
+
+cmdline_parse_inst_t cmd_get_sym_hash_ena_per_port = {
+ .f = cmd_get_sym_hash_per_port_parsed,
+ .data = NULL,
+ .help_str = "get_sym_hash_ena_per_port <port_id>",
+ .tokens = {
+ (void *)&cmd_get_sym_hash_ena_per_port_all,
+ (void *)&cmd_get_sym_hash_ena_per_port_port_id,
+ NULL,
+ },
+};
+
+/* *** Set symmetric hash enable per port *** */
+struct cmd_set_sym_hash_ena_per_port_result {
+ cmdline_fixed_string_t set_sym_hash_ena_per_port;
+ cmdline_fixed_string_t enable;
+ uint8_t port_id;
+};
+
+static void
+cmd_set_sym_hash_per_port_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_sym_hash_ena_per_port_result *res = parsed_result;
+ struct rte_eth_hash_filter_info info;
+ int ret;
+
+ if (rte_eth_dev_filter_supported(res->port_id,
+ RTE_ETH_FILTER_HASH) < 0) {
+ printf("RTE_ETH_FILTER_HASH not supported on port: %d\n",
+ res->port_id);
+ return;
+ }
+
+ memset(&info, 0, sizeof(info));
+ info.info_type = RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT;
+ if (!strcmp(res->enable, "enable"))
+ info.info.enable = 1;
+ ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH,
+ RTE_ETH_FILTER_SET, &info);
+ if (ret < 0) {
+ printf("Cannot set symmetric hash enable per port on "
+ "port %u\n", res->port_id);
+ return;
+ }
+ printf("Symmetric hash has been set to %s on port %u\n",
+ res->enable, res->port_id);
+}
+
+cmdline_parse_token_string_t cmd_set_sym_hash_ena_per_port_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_sym_hash_ena_per_port_result,
+ set_sym_hash_ena_per_port, "set_sym_hash_ena_per_port");
+cmdline_parse_token_num_t cmd_set_sym_hash_ena_per_port_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_sym_hash_ena_per_port_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_set_sym_hash_ena_per_port_enable =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_sym_hash_ena_per_port_result,
+ enable, "enable#disable");
+
+cmdline_parse_inst_t cmd_set_sym_hash_ena_per_port = {
+ .f = cmd_set_sym_hash_per_port_parsed,
+ .data = NULL,
+ .help_str = "set_sym_hash_ena_per_port <port_id> enable|disable",
+ .tokens = {
+ (void *)&cmd_set_sym_hash_ena_per_port_all,
+ (void *)&cmd_set_sym_hash_ena_per_port_port_id,
+ (void *)&cmd_set_sym_hash_ena_per_port_enable,
+ NULL,
+ },
+};
+
+/* Get global config of hash function */
+struct cmd_get_hash_global_config_result {
+ cmdline_fixed_string_t get_hash_global_config;
+ uint8_t port_id;
+};
+
+static char *
+flowtype_to_str(uint16_t ftype)
+{
+ uint16_t i;
+ static struct {
+ char str[16];
+ uint16_t ftype;
+ } ftype_table[] = {
+ {"ipv4", RTE_ETH_FLOW_IPV4},
+ {"ipv4-frag", RTE_ETH_FLOW_FRAG_IPV4},
+ {"ipv4-tcp", RTE_ETH_FLOW_NONFRAG_IPV4_TCP},
+ {"ipv4-udp", RTE_ETH_FLOW_NONFRAG_IPV4_UDP},
+ {"ipv4-sctp", RTE_ETH_FLOW_NONFRAG_IPV4_SCTP},
+ {"ipv4-other", RTE_ETH_FLOW_NONFRAG_IPV4_OTHER},
+ {"ipv6", RTE_ETH_FLOW_IPV6},
+ {"ipv6-frag", RTE_ETH_FLOW_FRAG_IPV6},
+ {"ipv6-tcp", RTE_ETH_FLOW_NONFRAG_IPV6_TCP},
+ {"ipv6-udp", RTE_ETH_FLOW_NONFRAG_IPV6_UDP},
+ {"ipv6-sctp", RTE_ETH_FLOW_NONFRAG_IPV6_SCTP},
+ {"ipv6-other", RTE_ETH_FLOW_NONFRAG_IPV6_OTHER},
+ {"l2_payload", RTE_ETH_FLOW_L2_PAYLOAD},
+ {"port", RTE_ETH_FLOW_PORT},
+ {"vxlan", RTE_ETH_FLOW_VXLAN},
+ {"geneve", RTE_ETH_FLOW_GENEVE},
+ {"nvgre", RTE_ETH_FLOW_NVGRE},
+ };
+
+ for (i = 0; i < RTE_DIM(ftype_table); i++) {
+ if (ftype_table[i].ftype == ftype)
+ return ftype_table[i].str;
+ }
+
+ return NULL;
+}
+
+static void
+cmd_get_hash_global_config_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_get_hash_global_config_result *res = parsed_result;
+ struct rte_eth_hash_filter_info info;
+ uint32_t idx, offset;
+ uint16_t i;
+ char *str;
+ int ret;
+
+ if (rte_eth_dev_filter_supported(res->port_id,
+ RTE_ETH_FILTER_HASH) < 0) {
+ printf("RTE_ETH_FILTER_HASH not supported on port %d\n",
+ res->port_id);
+ return;
+ }
+
+ memset(&info, 0, sizeof(info));
+ info.info_type = RTE_ETH_HASH_FILTER_GLOBAL_CONFIG;
+ ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH,
+ RTE_ETH_FILTER_GET, &info);
+ if (ret < 0) {
+ printf("Cannot get hash global configurations by port %d\n",
+ res->port_id);
+ return;
+ }
+
+ switch (info.info.global_conf.hash_func) {
+ case RTE_ETH_HASH_FUNCTION_TOEPLITZ:
+ printf("Hash function is Toeplitz\n");
+ break;
+ case RTE_ETH_HASH_FUNCTION_SIMPLE_XOR:
+ printf("Hash function is Simple XOR\n");
+ break;
+ default:
+ printf("Unknown hash function\n");
+ break;
+ }
+
+ for (i = 0; i < RTE_ETH_FLOW_MAX; i++) {
+ idx = i / UINT32_BIT;
+ offset = i % UINT32_BIT;
+ if (!(info.info.global_conf.valid_bit_mask[idx] &
+ (1UL << offset)))
+ continue;
+ str = flowtype_to_str(i);
+ if (!str)
+ continue;
+ printf("Symmetric hash is %s globally for flow type %s "
+ "by port %d\n",
+ ((info.info.global_conf.sym_hash_enable_mask[idx] &
+ (1UL << offset)) ? "enabled" : "disabled"), str,
+ res->port_id);
+ }
+}
+
+cmdline_parse_token_string_t cmd_get_hash_global_config_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_get_hash_global_config_result,
+ get_hash_global_config, "get_hash_global_config");
+cmdline_parse_token_num_t cmd_get_hash_global_config_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_get_hash_global_config_result,
+ port_id, UINT8);
+
+cmdline_parse_inst_t cmd_get_hash_global_config = {
+ .f = cmd_get_hash_global_config_parsed,
+ .data = NULL,
+ .help_str = "get_hash_global_config <port_id>",
+ .tokens = {
+ (void *)&cmd_get_hash_global_config_all,
+ (void *)&cmd_get_hash_global_config_port_id,
+ NULL,
+ },
+};
+
+/* Set global config of hash function */
+struct cmd_set_hash_global_config_result {
+ cmdline_fixed_string_t set_hash_global_config;
+ uint8_t port_id;
+ cmdline_fixed_string_t hash_func;
+ cmdline_fixed_string_t flow_type;
+ cmdline_fixed_string_t enable;
+};
+
+static void
+cmd_set_hash_global_config_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_hash_global_config_result *res = parsed_result;
+ struct rte_eth_hash_filter_info info;
+ uint32_t ftype, idx, offset;
+ int ret;
+
+ if (rte_eth_dev_filter_supported(res->port_id,
+ RTE_ETH_FILTER_HASH) < 0) {
+ printf("RTE_ETH_FILTER_HASH not supported on port %d\n",
+ res->port_id);
+ return;
+ }
+ memset(&info, 0, sizeof(info));
+ info.info_type = RTE_ETH_HASH_FILTER_GLOBAL_CONFIG;
+ if (!strcmp(res->hash_func, "toeplitz"))
+ info.info.global_conf.hash_func =
+ RTE_ETH_HASH_FUNCTION_TOEPLITZ;
+ else if (!strcmp(res->hash_func, "simple_xor"))
+ info.info.global_conf.hash_func =
+ RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
+ else if (!strcmp(res->hash_func, "default"))
+ info.info.global_conf.hash_func =
+ RTE_ETH_HASH_FUNCTION_DEFAULT;
+
+ ftype = str2flowtype(res->flow_type);
+ idx = ftype / (CHAR_BIT * sizeof(uint32_t));
+ offset = ftype % (CHAR_BIT * sizeof(uint32_t));
+ info.info.global_conf.valid_bit_mask[idx] |= (1UL << offset);
+ if (!strcmp(res->enable, "enable"))
+ info.info.global_conf.sym_hash_enable_mask[idx] |=
+ (1UL << offset);
+ ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH,
+ RTE_ETH_FILTER_SET, &info);
+ if (ret < 0)
+ printf("Cannot set global hash configurations by port %d\n",
+ res->port_id);
+ else
+ printf("Global hash configurations have been set "
+ "succcessfully by port %d\n", res->port_id);
+}
+
+cmdline_parse_token_string_t cmd_set_hash_global_config_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_hash_global_config_result,
+ set_hash_global_config, "set_hash_global_config");
+cmdline_parse_token_num_t cmd_set_hash_global_config_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_hash_global_config_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_set_hash_global_config_hash_func =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_hash_global_config_result,
+ hash_func, "toeplitz#simple_xor#default");
+cmdline_parse_token_string_t cmd_set_hash_global_config_flow_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_hash_global_config_result,
+ flow_type,
+ "ipv4#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#ipv4-other#ipv6#"
+ "ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#ipv6-other#l2_payload");
+cmdline_parse_token_string_t cmd_set_hash_global_config_enable =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_hash_global_config_result,
+ enable, "enable#disable");
+
+cmdline_parse_inst_t cmd_set_hash_global_config = {
+ .f = cmd_set_hash_global_config_parsed,
+ .data = NULL,
+ .help_str = "set_hash_global_config <port_id> "
+ "toeplitz|simple_xor|default "
+ "ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|"
+ "ipv6|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|"
+ "l2_payload enable|disable",
+ .tokens = {
+ (void *)&cmd_set_hash_global_config_all,
+ (void *)&cmd_set_hash_global_config_port_id,
+ (void *)&cmd_set_hash_global_config_hash_func,
+ (void *)&cmd_set_hash_global_config_flow_type,
+ (void *)&cmd_set_hash_global_config_enable,
+ NULL,
+ },
+};
+
+/* Set hash input set */
+struct cmd_set_hash_input_set_result {
+ cmdline_fixed_string_t set_hash_input_set;
+ uint8_t port_id;
+ cmdline_fixed_string_t flow_type;
+ cmdline_fixed_string_t inset_field;
+ cmdline_fixed_string_t select;
+};
+
+static enum rte_eth_input_set_field
+str2inset(char *string)
+{
+ uint16_t i;
+
+ static const struct {
+ char str[32];
+ enum rte_eth_input_set_field inset;
+ } inset_table[] = {
+ {"ethertype", RTE_ETH_INPUT_SET_L2_ETHERTYPE},
+ {"ovlan", RTE_ETH_INPUT_SET_L2_OUTER_VLAN},
+ {"ivlan", RTE_ETH_INPUT_SET_L2_INNER_VLAN},
+ {"src-ipv4", RTE_ETH_INPUT_SET_L3_SRC_IP4},
+ {"dst-ipv4", RTE_ETH_INPUT_SET_L3_DST_IP4},
+ {"ipv4-tos", RTE_ETH_INPUT_SET_L3_IP4_TOS},
+ {"ipv4-proto", RTE_ETH_INPUT_SET_L3_IP4_PROTO},
+ {"ipv4-ttl", RTE_ETH_INPUT_SET_L3_IP4_TTL},
+ {"src-ipv6", RTE_ETH_INPUT_SET_L3_SRC_IP6},
+ {"dst-ipv6", RTE_ETH_INPUT_SET_L3_DST_IP6},
+ {"ipv6-tc", RTE_ETH_INPUT_SET_L3_IP6_TC},
+ {"ipv6-next-header", RTE_ETH_INPUT_SET_L3_IP6_NEXT_HEADER},
+ {"ipv6-hop-limits", RTE_ETH_INPUT_SET_L3_IP6_HOP_LIMITS},
+ {"udp-src-port", RTE_ETH_INPUT_SET_L4_UDP_SRC_PORT},
+ {"udp-dst-port", RTE_ETH_INPUT_SET_L4_UDP_DST_PORT},
+ {"tcp-src-port", RTE_ETH_INPUT_SET_L4_TCP_SRC_PORT},
+ {"tcp-dst-port", RTE_ETH_INPUT_SET_L4_TCP_DST_PORT},
+ {"sctp-src-port", RTE_ETH_INPUT_SET_L4_SCTP_SRC_PORT},
+ {"sctp-dst-port", RTE_ETH_INPUT_SET_L4_SCTP_DST_PORT},
+ {"sctp-veri-tag", RTE_ETH_INPUT_SET_L4_SCTP_VERIFICATION_TAG},
+ {"udp-key", RTE_ETH_INPUT_SET_TUNNEL_L4_UDP_KEY},
+ {"gre-key", RTE_ETH_INPUT_SET_TUNNEL_GRE_KEY},
+ {"fld-1st", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_1ST_WORD},
+ {"fld-2nd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_2ND_WORD},
+ {"fld-3rd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_3RD_WORD},
+ {"fld-4th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_4TH_WORD},
+ {"fld-5th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_5TH_WORD},
+ {"fld-6th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_6TH_WORD},
+ {"fld-7th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_7TH_WORD},
+ {"fld-8th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_8TH_WORD},
+ {"none", RTE_ETH_INPUT_SET_NONE},
+ };
+
+ for (i = 0; i < RTE_DIM(inset_table); i++) {
+ if (!strcmp(string, inset_table[i].str))
+ return inset_table[i].inset;
+ }
+
+ return RTE_ETH_INPUT_SET_UNKNOWN;
+}
+
+static void
+cmd_set_hash_input_set_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_hash_input_set_result *res = parsed_result;
+ struct rte_eth_hash_filter_info info;
+
+ memset(&info, 0, sizeof(info));
+ info.info_type = RTE_ETH_HASH_FILTER_INPUT_SET_SELECT;
+ info.info.input_set_conf.flow_type = str2flowtype(res->flow_type);
+ info.info.input_set_conf.field[0] = str2inset(res->inset_field);
+ info.info.input_set_conf.inset_size = 1;
+ if (!strcmp(res->select, "select"))
+ info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT;
+ else if (!strcmp(res->select, "add"))
+ info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD;
+ rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH,
+ RTE_ETH_FILTER_SET, &info);
+}
+
+cmdline_parse_token_string_t cmd_set_hash_input_set_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result,
+ set_hash_input_set, "set_hash_input_set");
+cmdline_parse_token_num_t cmd_set_hash_input_set_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_hash_input_set_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_set_hash_input_set_flow_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result,
+ flow_type,
+ "ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#ipv4-other#"
+ "ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#ipv6-other#l2_payload");
+cmdline_parse_token_string_t cmd_set_hash_input_set_field =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result,
+ inset_field,
+ "ovlan#ivlan#src-ipv4#dst-ipv4#src-ipv6#dst-ipv6#"
+ "ipv4-tos#ipv4-proto#ipv6-tc#ipv6-next-header#udp-src-port#"
+ "udp-dst-port#tcp-src-port#tcp-dst-port#sctp-src-port#"
+ "sctp-dst-port#sctp-veri-tag#udp-key#gre-key#fld-1st#"
+ "fld-2nd#fld-3rd#fld-4th#fld-5th#fld-6th#fld-7th#"
+ "fld-8th#none");
+cmdline_parse_token_string_t cmd_set_hash_input_set_select =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result,
+ select, "select#add");
+
+cmdline_parse_inst_t cmd_set_hash_input_set = {
+ .f = cmd_set_hash_input_set_parsed,
+ .data = NULL,
+ .help_str = "set_hash_input_set <port_id> "
+ "ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|"
+ "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload "
+ "ovlan|ivlan|src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|ipv4-tos|ipv4-proto|"
+ "ipv6-tc|ipv6-next-header|udp-src-port|udp-dst-port|tcp-src-port|"
+ "tcp-dst-port|sctp-src-port|sctp-dst-port|sctp-veri-tag|udp-key|"
+ "gre-key|fld-1st|fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|"
+ "fld-7th|fld-8th|none select|add",
+ .tokens = {
+ (void *)&cmd_set_hash_input_set_cmd,
+ (void *)&cmd_set_hash_input_set_port_id,
+ (void *)&cmd_set_hash_input_set_flow_type,
+ (void *)&cmd_set_hash_input_set_field,
+ (void *)&cmd_set_hash_input_set_select,
+ NULL,
+ },
+};
+
+/* Set flow director input set */
+struct cmd_set_fdir_input_set_result {
+ cmdline_fixed_string_t set_fdir_input_set;
+ uint8_t port_id;
+ cmdline_fixed_string_t flow_type;
+ cmdline_fixed_string_t inset_field;
+ cmdline_fixed_string_t select;
+};
+
+static void
+cmd_set_fdir_input_set_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_fdir_input_set_result *res = parsed_result;
+ struct rte_eth_fdir_filter_info info;
+
+ memset(&info, 0, sizeof(info));
+ info.info_type = RTE_ETH_FDIR_FILTER_INPUT_SET_SELECT;
+ info.info.input_set_conf.flow_type = str2flowtype(res->flow_type);
+ info.info.input_set_conf.field[0] = str2inset(res->inset_field);
+ info.info.input_set_conf.inset_size = 1;
+ if (!strcmp(res->select, "select"))
+ info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT;
+ else if (!strcmp(res->select, "add"))
+ info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD;
+ rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_SET, &info);
+}
+
+cmdline_parse_token_string_t cmd_set_fdir_input_set_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result,
+ set_fdir_input_set, "set_fdir_input_set");
+cmdline_parse_token_num_t cmd_set_fdir_input_set_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_fdir_input_set_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_set_fdir_input_set_flow_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result,
+ flow_type,
+ "ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#ipv4-other#"
+ "ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#ipv6-other#l2_payload");
+cmdline_parse_token_string_t cmd_set_fdir_input_set_field =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result,
+ inset_field,
+ "ivlan#ethertype#src-ipv4#dst-ipv4#src-ipv6#dst-ipv6#"
+ "ipv4-tos#ipv4-proto#ipv4-ttl#ipv6-tc#ipv6-next-header#"
+ "ipv6-hop-limits#udp-src-port#udp-dst-port#"
+ "tcp-src-port#tcp-dst-port#sctp-src-port#sctp-dst-port#"
+ "sctp-veri-tag#none");
+cmdline_parse_token_string_t cmd_set_fdir_input_set_select =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result,
+ select, "select#add");
+
+cmdline_parse_inst_t cmd_set_fdir_input_set = {
+ .f = cmd_set_fdir_input_set_parsed,
+ .data = NULL,
+ .help_str = "set_fdir_input_set <port_id> "
+ "ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|"
+ "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload "
+ "ivlan|ethertype|src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|"
+ "ipv4-tos|ipv4-proto|ipv4-ttl|ipv6-tc|ipv6-next-header|"
+ "ipv6-hop-limits|udp-src-port|udp-dst-port|"
+ "tcp-src-port|tcp-dst-port|sctp-src-port|sctp-dst-port|"
+ "sctp-veri-tag|none select|add",
+ .tokens = {
+ (void *)&cmd_set_fdir_input_set_cmd,
+ (void *)&cmd_set_fdir_input_set_port_id,
+ (void *)&cmd_set_fdir_input_set_flow_type,
+ (void *)&cmd_set_fdir_input_set_field,
+ (void *)&cmd_set_fdir_input_set_select,
+ NULL,
+ },
+};
+
+/* *** ADD/REMOVE A MULTICAST MAC ADDRESS TO/FROM A PORT *** */
+struct cmd_mcast_addr_result {
+ cmdline_fixed_string_t mcast_addr_cmd;
+ cmdline_fixed_string_t what;
+ uint8_t port_num;
+ struct ether_addr mc_addr;
+};
+
+static void cmd_mcast_addr_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_mcast_addr_result *res = parsed_result;
+
+ if (!is_multicast_ether_addr(&res->mc_addr)) {
+ printf("Invalid multicast addr %02X:%02X:%02X:%02X:%02X:%02X\n",
+ res->mc_addr.addr_bytes[0], res->mc_addr.addr_bytes[1],
+ res->mc_addr.addr_bytes[2], res->mc_addr.addr_bytes[3],
+ res->mc_addr.addr_bytes[4], res->mc_addr.addr_bytes[5]);
+ return;
+ }
+ if (strcmp(res->what, "add") == 0)
+ mcast_addr_add(res->port_num, &res->mc_addr);
+ else
+ mcast_addr_remove(res->port_num, &res->mc_addr);
+}
+
+cmdline_parse_token_string_t cmd_mcast_addr_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_mcast_addr_result,
+ mcast_addr_cmd, "mcast_addr");
+cmdline_parse_token_string_t cmd_mcast_addr_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_mcast_addr_result, what,
+ "add#remove");
+cmdline_parse_token_num_t cmd_mcast_addr_portnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_mcast_addr_result, port_num, UINT8);
+cmdline_parse_token_etheraddr_t cmd_mcast_addr_addr =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_mac_addr_result, address);
+
+cmdline_parse_inst_t cmd_mcast_addr = {
+ .f = cmd_mcast_addr_parsed,
+ .data = (void *)0,
+ .help_str = "mcast_addr add|remove <port_id> <mcast_addr>: "
+ "Add/Remove multicast MAC address on port_id",
+ .tokens = {
+ (void *)&cmd_mcast_addr_cmd,
+ (void *)&cmd_mcast_addr_what,
+ (void *)&cmd_mcast_addr_portnum,
+ (void *)&cmd_mcast_addr_addr,
+ NULL,
+ },
+};
+
+/* l2 tunnel config
+ * only support E-tag now.
+ */
+
+/* Ether type config */
+struct cmd_config_l2_tunnel_eth_type_result {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t config;
+ cmdline_fixed_string_t all;
+ uint8_t id;
+ cmdline_fixed_string_t l2_tunnel;
+ cmdline_fixed_string_t l2_tunnel_type;
+ cmdline_fixed_string_t eth_type;
+ uint16_t eth_type_val;
+};
+
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_port =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_l2_tunnel_eth_type_result,
+ port, "port");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_config =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_l2_tunnel_eth_type_result,
+ config, "config");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_all_str =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_l2_tunnel_eth_type_result,
+ all, "all");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_eth_type_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_config_l2_tunnel_eth_type_result,
+ id, UINT8);
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_l2_tunnel =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_l2_tunnel_eth_type_result,
+ l2_tunnel, "l2-tunnel");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_l2_tunnel_type =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_l2_tunnel_eth_type_result,
+ l2_tunnel_type, "E-tag");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_eth_type =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_l2_tunnel_eth_type_result,
+ eth_type, "ether-type");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_eth_type_eth_type_val =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_config_l2_tunnel_eth_type_result,
+ eth_type_val, UINT16);
+
+static enum rte_eth_tunnel_type
+str2fdir_l2_tunnel_type(char *string)
+{
+ uint32_t i = 0;
+
+ static const struct {
+ char str[32];
+ enum rte_eth_tunnel_type type;
+ } l2_tunnel_type_str[] = {
+ {"E-tag", RTE_L2_TUNNEL_TYPE_E_TAG},
+ };
+
+ for (i = 0; i < RTE_DIM(l2_tunnel_type_str); i++) {
+ if (!strcmp(l2_tunnel_type_str[i].str, string))
+ return l2_tunnel_type_str[i].type;
+ }
+ return RTE_TUNNEL_TYPE_NONE;
+}
+
+/* ether type config for all ports */
+static void
+cmd_config_l2_tunnel_eth_type_all_parsed
+ (void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_config_l2_tunnel_eth_type_result *res = parsed_result;
+ struct rte_eth_l2_tunnel_conf entry;
+ portid_t pid;
+
+ entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+ entry.ether_type = res->eth_type_val;
+
+ RTE_ETH_FOREACH_DEV(pid) {
+ rte_eth_dev_l2_tunnel_eth_type_conf(pid, &entry);
+ }
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_eth_type_all = {
+ .f = cmd_config_l2_tunnel_eth_type_all_parsed,
+ .data = NULL,
+ .help_str = "port config all l2-tunnel E-tag ether-type <value>",
+ .tokens = {
+ (void *)&cmd_config_l2_tunnel_eth_type_port,
+ (void *)&cmd_config_l2_tunnel_eth_type_config,
+ (void *)&cmd_config_l2_tunnel_eth_type_all_str,
+ (void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel,
+ (void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel_type,
+ (void *)&cmd_config_l2_tunnel_eth_type_eth_type,
+ (void *)&cmd_config_l2_tunnel_eth_type_eth_type_val,
+ NULL,
+ },
+};
+
+/* ether type config for a specific port */
+static void
+cmd_config_l2_tunnel_eth_type_specific_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_config_l2_tunnel_eth_type_result *res =
+ parsed_result;
+ struct rte_eth_l2_tunnel_conf entry;
+
+ if (port_id_is_invalid(res->id, ENABLED_WARN))
+ return;
+
+ entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+ entry.ether_type = res->eth_type_val;
+
+ rte_eth_dev_l2_tunnel_eth_type_conf(res->id, &entry);
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_eth_type_specific = {
+ .f = cmd_config_l2_tunnel_eth_type_specific_parsed,
+ .data = NULL,
+ .help_str = "port config <port_id> l2-tunnel E-tag ether-type <value>",
+ .tokens = {
+ (void *)&cmd_config_l2_tunnel_eth_type_port,
+ (void *)&cmd_config_l2_tunnel_eth_type_config,
+ (void *)&cmd_config_l2_tunnel_eth_type_id,
+ (void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel,
+ (void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel_type,
+ (void *)&cmd_config_l2_tunnel_eth_type_eth_type,
+ (void *)&cmd_config_l2_tunnel_eth_type_eth_type_val,
+ NULL,
+ },
+};
+
+/* Enable/disable l2 tunnel */
+struct cmd_config_l2_tunnel_en_dis_result {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t config;
+ cmdline_fixed_string_t all;
+ uint8_t id;
+ cmdline_fixed_string_t l2_tunnel;
+ cmdline_fixed_string_t l2_tunnel_type;
+ cmdline_fixed_string_t en_dis;
+};
+
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_port =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_l2_tunnel_en_dis_result,
+ port, "port");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_config =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_l2_tunnel_en_dis_result,
+ config, "config");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_all_str =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_l2_tunnel_en_dis_result,
+ all, "all");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_en_dis_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_config_l2_tunnel_en_dis_result,
+ id, UINT8);
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_l2_tunnel =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_l2_tunnel_en_dis_result,
+ l2_tunnel, "l2-tunnel");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_l2_tunnel_type =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_l2_tunnel_en_dis_result,
+ l2_tunnel_type, "E-tag");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_en_dis =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_l2_tunnel_en_dis_result,
+ en_dis, "enable#disable");
+
+/* enable/disable l2 tunnel for all ports */
+static void
+cmd_config_l2_tunnel_en_dis_all_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_config_l2_tunnel_en_dis_result *res = parsed_result;
+ struct rte_eth_l2_tunnel_conf entry;
+ portid_t pid;
+ uint8_t en;
+
+ entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+
+ if (!strcmp("enable", res->en_dis))
+ en = 1;
+ else
+ en = 0;
+
+ RTE_ETH_FOREACH_DEV(pid) {
+ rte_eth_dev_l2_tunnel_offload_set(pid,
+ &entry,
+ ETH_L2_TUNNEL_ENABLE_MASK,
+ en);
+ }
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_all = {
+ .f = cmd_config_l2_tunnel_en_dis_all_parsed,
+ .data = NULL,
+ .help_str = "port config all l2-tunnel E-tag enable|disable",
+ .tokens = {
+ (void *)&cmd_config_l2_tunnel_en_dis_port,
+ (void *)&cmd_config_l2_tunnel_en_dis_config,
+ (void *)&cmd_config_l2_tunnel_en_dis_all_str,
+ (void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel,
+ (void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel_type,
+ (void *)&cmd_config_l2_tunnel_en_dis_en_dis,
+ NULL,
+ },
+};
+
+/* enable/disable l2 tunnel for a port */
+static void
+cmd_config_l2_tunnel_en_dis_specific_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_config_l2_tunnel_en_dis_result *res =
+ parsed_result;
+ struct rte_eth_l2_tunnel_conf entry;
+
+ if (port_id_is_invalid(res->id, ENABLED_WARN))
+ return;
+
+ entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+
+ if (!strcmp("enable", res->en_dis))
+ rte_eth_dev_l2_tunnel_offload_set(res->id,
+ &entry,
+ ETH_L2_TUNNEL_ENABLE_MASK,
+ 1);
+ else
+ rte_eth_dev_l2_tunnel_offload_set(res->id,
+ &entry,
+ ETH_L2_TUNNEL_ENABLE_MASK,
+ 0);
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_specific = {
+ .f = cmd_config_l2_tunnel_en_dis_specific_parsed,
+ .data = NULL,
+ .help_str = "port config <port_id> l2-tunnel E-tag enable|disable",
+ .tokens = {
+ (void *)&cmd_config_l2_tunnel_en_dis_port,
+ (void *)&cmd_config_l2_tunnel_en_dis_config,
+ (void *)&cmd_config_l2_tunnel_en_dis_id,
+ (void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel,
+ (void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel_type,
+ (void *)&cmd_config_l2_tunnel_en_dis_en_dis,
+ NULL,
+ },
+};
+
+/* E-tag configuration */
+
+/* Common result structure for all E-tag configuration */
+struct cmd_config_e_tag_result {
+ cmdline_fixed_string_t e_tag;
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t insertion;
+ cmdline_fixed_string_t stripping;
+ cmdline_fixed_string_t forwarding;
+ cmdline_fixed_string_t filter;
+ cmdline_fixed_string_t add;
+ cmdline_fixed_string_t del;
+ cmdline_fixed_string_t on;
+ cmdline_fixed_string_t off;
+ cmdline_fixed_string_t on_off;
+ cmdline_fixed_string_t port_tag_id;
+ uint32_t port_tag_id_val;
+ cmdline_fixed_string_t e_tag_id;
+ uint16_t e_tag_id_val;
+ cmdline_fixed_string_t dst_pool;
+ uint8_t dst_pool_val;
+ cmdline_fixed_string_t port;
+ uint8_t port_id;
+ cmdline_fixed_string_t vf;
+ uint8_t vf_id;
+};
+
+/* Common CLI fields for all E-tag configuration */
+cmdline_parse_token_string_t cmd_config_e_tag_e_tag =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ e_tag, "E-tag");
+cmdline_parse_token_string_t cmd_config_e_tag_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_config_e_tag_insertion =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ insertion, "insertion");
+cmdline_parse_token_string_t cmd_config_e_tag_stripping =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ stripping, "stripping");
+cmdline_parse_token_string_t cmd_config_e_tag_forwarding =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ forwarding, "forwarding");
+cmdline_parse_token_string_t cmd_config_e_tag_filter =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ filter, "filter");
+cmdline_parse_token_string_t cmd_config_e_tag_add =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ add, "add");
+cmdline_parse_token_string_t cmd_config_e_tag_del =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ del, "del");
+cmdline_parse_token_string_t cmd_config_e_tag_on =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ on, "on");
+cmdline_parse_token_string_t cmd_config_e_tag_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ off, "off");
+cmdline_parse_token_string_t cmd_config_e_tag_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ on_off, "on#off");
+cmdline_parse_token_string_t cmd_config_e_tag_port_tag_id =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ port_tag_id, "port-tag-id");
+cmdline_parse_token_num_t cmd_config_e_tag_port_tag_id_val =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ port_tag_id_val, UINT32);
+cmdline_parse_token_string_t cmd_config_e_tag_e_tag_id =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ e_tag_id, "e-tag-id");
+cmdline_parse_token_num_t cmd_config_e_tag_e_tag_id_val =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ e_tag_id_val, UINT16);
+cmdline_parse_token_string_t cmd_config_e_tag_dst_pool =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ dst_pool, "dst-pool");
+cmdline_parse_token_num_t cmd_config_e_tag_dst_pool_val =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ dst_pool_val, UINT8);
+cmdline_parse_token_string_t cmd_config_e_tag_port =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ port, "port");
+cmdline_parse_token_num_t cmd_config_e_tag_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_config_e_tag_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ vf, "vf");
+cmdline_parse_token_num_t cmd_config_e_tag_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ vf_id, UINT8);
+
+/* E-tag insertion configuration */
+static void
+cmd_config_e_tag_insertion_en_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_config_e_tag_result *res =
+ parsed_result;
+ struct rte_eth_l2_tunnel_conf entry;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+ entry.tunnel_id = res->port_tag_id_val;
+ entry.vf_id = res->vf_id;
+ rte_eth_dev_l2_tunnel_offload_set(res->port_id,
+ &entry,
+ ETH_L2_TUNNEL_INSERTION_MASK,
+ 1);
+}
+
+static void
+cmd_config_e_tag_insertion_dis_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_config_e_tag_result *res =
+ parsed_result;
+ struct rte_eth_l2_tunnel_conf entry;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+ entry.vf_id = res->vf_id;
+
+ rte_eth_dev_l2_tunnel_offload_set(res->port_id,
+ &entry,
+ ETH_L2_TUNNEL_INSERTION_MASK,
+ 0);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_insertion_en = {
+ .f = cmd_config_e_tag_insertion_en_parsed,
+ .data = NULL,
+ .help_str = "E-tag ... : E-tag insertion enable",
+ .tokens = {
+ (void *)&cmd_config_e_tag_e_tag,
+ (void *)&cmd_config_e_tag_set,
+ (void *)&cmd_config_e_tag_insertion,
+ (void *)&cmd_config_e_tag_on,
+ (void *)&cmd_config_e_tag_port_tag_id,
+ (void *)&cmd_config_e_tag_port_tag_id_val,
+ (void *)&cmd_config_e_tag_port,
+ (void *)&cmd_config_e_tag_port_id,
+ (void *)&cmd_config_e_tag_vf,
+ (void *)&cmd_config_e_tag_vf_id,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_config_e_tag_insertion_dis = {
+ .f = cmd_config_e_tag_insertion_dis_parsed,
+ .data = NULL,
+ .help_str = "E-tag ... : E-tag insertion disable",
+ .tokens = {
+ (void *)&cmd_config_e_tag_e_tag,
+ (void *)&cmd_config_e_tag_set,
+ (void *)&cmd_config_e_tag_insertion,
+ (void *)&cmd_config_e_tag_off,
+ (void *)&cmd_config_e_tag_port,
+ (void *)&cmd_config_e_tag_port_id,
+ (void *)&cmd_config_e_tag_vf,
+ (void *)&cmd_config_e_tag_vf_id,
+ NULL,
+ },
+};
+
+/* E-tag stripping configuration */
+static void
+cmd_config_e_tag_stripping_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_config_e_tag_result *res =
+ parsed_result;
+ struct rte_eth_l2_tunnel_conf entry;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+
+ if (!strcmp(res->on_off, "on"))
+ rte_eth_dev_l2_tunnel_offload_set
+ (res->port_id,
+ &entry,
+ ETH_L2_TUNNEL_STRIPPING_MASK,
+ 1);
+ else
+ rte_eth_dev_l2_tunnel_offload_set
+ (res->port_id,
+ &entry,
+ ETH_L2_TUNNEL_STRIPPING_MASK,
+ 0);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_stripping_en_dis = {
+ .f = cmd_config_e_tag_stripping_parsed,
+ .data = NULL,
+ .help_str = "E-tag ... : E-tag stripping enable/disable",
+ .tokens = {
+ (void *)&cmd_config_e_tag_e_tag,
+ (void *)&cmd_config_e_tag_set,
+ (void *)&cmd_config_e_tag_stripping,
+ (void *)&cmd_config_e_tag_on_off,
+ (void *)&cmd_config_e_tag_port,
+ (void *)&cmd_config_e_tag_port_id,
+ NULL,
+ },
+};
+
+/* E-tag forwarding configuration */
+static void
+cmd_config_e_tag_forwarding_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_config_e_tag_result *res = parsed_result;
+ struct rte_eth_l2_tunnel_conf entry;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+
+ if (!strcmp(res->on_off, "on"))
+ rte_eth_dev_l2_tunnel_offload_set
+ (res->port_id,
+ &entry,
+ ETH_L2_TUNNEL_FORWARDING_MASK,
+ 1);
+ else
+ rte_eth_dev_l2_tunnel_offload_set
+ (res->port_id,
+ &entry,
+ ETH_L2_TUNNEL_FORWARDING_MASK,
+ 0);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_forwarding_en_dis = {
+ .f = cmd_config_e_tag_forwarding_parsed,
+ .data = NULL,
+ .help_str = "E-tag ... : E-tag forwarding enable/disable",
+ .tokens = {
+ (void *)&cmd_config_e_tag_e_tag,
+ (void *)&cmd_config_e_tag_set,
+ (void *)&cmd_config_e_tag_forwarding,
+ (void *)&cmd_config_e_tag_on_off,
+ (void *)&cmd_config_e_tag_port,
+ (void *)&cmd_config_e_tag_port_id,
+ NULL,
+ },
+};
+
+/* E-tag filter configuration */
+static void
+cmd_config_e_tag_filter_add_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_config_e_tag_result *res = parsed_result;
+ struct rte_eth_l2_tunnel_conf entry;
+ int ret = 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ if (res->e_tag_id_val > 0x3fff) {
+ printf("e-tag-id must be equal or less than 0x3fff.\n");
+ return;
+ }
+
+ ret = rte_eth_dev_filter_supported(res->port_id,
+ RTE_ETH_FILTER_L2_TUNNEL);
+ if (ret < 0) {
+ printf("E-tag filter is not supported on port %u.\n",
+ res->port_id);
+ return;
+ }
+
+ entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+ entry.tunnel_id = res->e_tag_id_val;
+ entry.pool = res->dst_pool_val;
+
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_L2_TUNNEL,
+ RTE_ETH_FILTER_ADD,
+ &entry);
+ if (ret < 0)
+ printf("E-tag filter programming error: (%s)\n",
+ strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_filter_add = {
+ .f = cmd_config_e_tag_filter_add_parsed,
+ .data = NULL,
+ .help_str = "E-tag ... : E-tag filter add",
+ .tokens = {
+ (void *)&cmd_config_e_tag_e_tag,
+ (void *)&cmd_config_e_tag_set,
+ (void *)&cmd_config_e_tag_filter,
+ (void *)&cmd_config_e_tag_add,
+ (void *)&cmd_config_e_tag_e_tag_id,
+ (void *)&cmd_config_e_tag_e_tag_id_val,
+ (void *)&cmd_config_e_tag_dst_pool,
+ (void *)&cmd_config_e_tag_dst_pool_val,
+ (void *)&cmd_config_e_tag_port,
+ (void *)&cmd_config_e_tag_port_id,
+ NULL,
+ },
+};
+
+static void
+cmd_config_e_tag_filter_del_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_config_e_tag_result *res = parsed_result;
+ struct rte_eth_l2_tunnel_conf entry;
+ int ret = 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ if (res->e_tag_id_val > 0x3fff) {
+ printf("e-tag-id must be less than 0x3fff.\n");
+ return;
+ }
+
+ ret = rte_eth_dev_filter_supported(res->port_id,
+ RTE_ETH_FILTER_L2_TUNNEL);
+ if (ret < 0) {
+ printf("E-tag filter is not supported on port %u.\n",
+ res->port_id);
+ return;
+ }
+
+ entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+ entry.tunnel_id = res->e_tag_id_val;
+
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_L2_TUNNEL,
+ RTE_ETH_FILTER_DELETE,
+ &entry);
+ if (ret < 0)
+ printf("E-tag filter programming error: (%s)\n",
+ strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_filter_del = {
+ .f = cmd_config_e_tag_filter_del_parsed,
+ .data = NULL,
+ .help_str = "E-tag ... : E-tag filter delete",
+ .tokens = {
+ (void *)&cmd_config_e_tag_e_tag,
+ (void *)&cmd_config_e_tag_set,
+ (void *)&cmd_config_e_tag_filter,
+ (void *)&cmd_config_e_tag_del,
+ (void *)&cmd_config_e_tag_e_tag_id,
+ (void *)&cmd_config_e_tag_e_tag_id_val,
+ (void *)&cmd_config_e_tag_port,
+ (void *)&cmd_config_e_tag_port_id,
+ NULL,
+ },
+};
+
+/* vf vlan anti spoof configuration */
+
+/* Common result structure for vf vlan anti spoof */
+struct cmd_vf_vlan_anti_spoof_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t vlan;
+ cmdline_fixed_string_t antispoof;
+ uint8_t port_id;
+ uint32_t vf_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf vlan anti spoof enable disable */
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_anti_spoof_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_anti_spoof_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_vlan =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_anti_spoof_result,
+ vlan, "vlan");
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_antispoof =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_anti_spoof_result,
+ antispoof, "antispoof");
+cmdline_parse_token_num_t cmd_vf_vlan_anti_spoof_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_vlan_anti_spoof_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_vlan_anti_spoof_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_vlan_anti_spoof_result,
+ vf_id, UINT32);
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_anti_spoof_result,
+ on_off, "on#off");
+
+static void
+cmd_set_vf_vlan_anti_spoof_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_vf_vlan_anti_spoof_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ __rte_unused int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_ixgbe_set_vf_vlan_anti_spoof(res->port_id,
+ res->vf_id, is_on);
+#endif
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_i40e_set_vf_vlan_anti_spoof(res->port_id,
+ res->vf_id, is_on);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d\n", res->vf_id);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_vf_vlan_anti_spoof = {
+ .f = cmd_set_vf_vlan_anti_spoof_parsed,
+ .data = NULL,
+ .help_str = "set vf vlan antispoof <port_id> <vf_id> on|off",
+ .tokens = {
+ (void *)&cmd_vf_vlan_anti_spoof_set,
+ (void *)&cmd_vf_vlan_anti_spoof_vf,
+ (void *)&cmd_vf_vlan_anti_spoof_vlan,
+ (void *)&cmd_vf_vlan_anti_spoof_antispoof,
+ (void *)&cmd_vf_vlan_anti_spoof_port_id,
+ (void *)&cmd_vf_vlan_anti_spoof_vf_id,
+ (void *)&cmd_vf_vlan_anti_spoof_on_off,
+ NULL,
+ },
+};
+
+/* vf mac anti spoof configuration */
+
+/* Common result structure for vf mac anti spoof */
+struct cmd_vf_mac_anti_spoof_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t mac;
+ cmdline_fixed_string_t antispoof;
+ uint8_t port_id;
+ uint32_t vf_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf mac anti spoof enable disable */
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_mac_anti_spoof_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_mac_anti_spoof_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_mac =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_mac_anti_spoof_result,
+ mac, "mac");
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_antispoof =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_mac_anti_spoof_result,
+ antispoof, "antispoof");
+cmdline_parse_token_num_t cmd_vf_mac_anti_spoof_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_mac_anti_spoof_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_mac_anti_spoof_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_mac_anti_spoof_result,
+ vf_id, UINT32);
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_mac_anti_spoof_result,
+ on_off, "on#off");
+
+static void
+cmd_set_vf_mac_anti_spoof_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_vf_mac_anti_spoof_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ __rte_unused int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_ixgbe_set_vf_mac_anti_spoof(res->port_id,
+ res->vf_id, is_on);
+#endif
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_i40e_set_vf_mac_anti_spoof(res->port_id,
+ res->vf_id, is_on);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d or is_on %d\n", res->vf_id, is_on);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_vf_mac_anti_spoof = {
+ .f = cmd_set_vf_mac_anti_spoof_parsed,
+ .data = NULL,
+ .help_str = "set vf mac antispoof <port_id> <vf_id> on|off",
+ .tokens = {
+ (void *)&cmd_vf_mac_anti_spoof_set,
+ (void *)&cmd_vf_mac_anti_spoof_vf,
+ (void *)&cmd_vf_mac_anti_spoof_mac,
+ (void *)&cmd_vf_mac_anti_spoof_antispoof,
+ (void *)&cmd_vf_mac_anti_spoof_port_id,
+ (void *)&cmd_vf_mac_anti_spoof_vf_id,
+ (void *)&cmd_vf_mac_anti_spoof_on_off,
+ NULL,
+ },
+};
+
+/* vf vlan strip queue configuration */
+
+/* Common result structure for vf mac anti spoof */
+struct cmd_vf_vlan_stripq_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t vlan;
+ cmdline_fixed_string_t stripq;
+ uint8_t port_id;
+ uint16_t vf_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf vlan strip enable disable */
+cmdline_parse_token_string_t cmd_vf_vlan_stripq_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_stripq_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_vf_vlan_stripq_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_stripq_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_vf_vlan_stripq_vlan =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_stripq_result,
+ vlan, "vlan");
+cmdline_parse_token_string_t cmd_vf_vlan_stripq_stripq =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_stripq_result,
+ stripq, "stripq");
+cmdline_parse_token_num_t cmd_vf_vlan_stripq_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_vlan_stripq_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_vlan_stripq_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_vlan_stripq_result,
+ vf_id, UINT16);
+cmdline_parse_token_string_t cmd_vf_vlan_stripq_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_stripq_result,
+ on_off, "on#off");
+
+static void
+cmd_set_vf_vlan_stripq_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_vf_vlan_stripq_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ __rte_unused int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_ixgbe_set_vf_vlan_stripq(res->port_id,
+ res->vf_id, is_on);
+#endif
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_i40e_set_vf_vlan_stripq(res->port_id,
+ res->vf_id, is_on);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d or is_on %d\n", res->vf_id, is_on);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_vf_vlan_stripq = {
+ .f = cmd_set_vf_vlan_stripq_parsed,
+ .data = NULL,
+ .help_str = "set vf vlan stripq <port_id> <vf_id> on|off",
+ .tokens = {
+ (void *)&cmd_vf_vlan_stripq_set,
+ (void *)&cmd_vf_vlan_stripq_vf,
+ (void *)&cmd_vf_vlan_stripq_vlan,
+ (void *)&cmd_vf_vlan_stripq_stripq,
+ (void *)&cmd_vf_vlan_stripq_port_id,
+ (void *)&cmd_vf_vlan_stripq_vf_id,
+ (void *)&cmd_vf_vlan_stripq_on_off,
+ NULL,
+ },
+};
+
+/* vf vlan insert configuration */
+
+/* Common result structure for vf vlan insert */
+struct cmd_vf_vlan_insert_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t vlan;
+ cmdline_fixed_string_t insert;
+ uint8_t port_id;
+ uint16_t vf_id;
+ uint16_t vlan_id;
+};
+
+/* Common CLI fields for vf vlan insert enable disable */
+cmdline_parse_token_string_t cmd_vf_vlan_insert_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_insert_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_vf_vlan_insert_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_insert_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_vf_vlan_insert_vlan =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_insert_result,
+ vlan, "vlan");
+cmdline_parse_token_string_t cmd_vf_vlan_insert_insert =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_insert_result,
+ insert, "insert");
+cmdline_parse_token_num_t cmd_vf_vlan_insert_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_vlan_insert_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_vlan_insert_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_vlan_insert_result,
+ vf_id, UINT16);
+cmdline_parse_token_num_t cmd_vf_vlan_insert_vlan_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_vlan_insert_result,
+ vlan_id, UINT16);
+
+static void
+cmd_set_vf_vlan_insert_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_vf_vlan_insert_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_ixgbe_set_vf_vlan_insert(res->port_id, res->vf_id,
+ res->vlan_id);
+#endif
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_i40e_set_vf_vlan_insert(res->port_id, res->vf_id,
+ res->vlan_id);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d or vlan_id %d\n", res->vf_id, res->vlan_id);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_vf_vlan_insert = {
+ .f = cmd_set_vf_vlan_insert_parsed,
+ .data = NULL,
+ .help_str = "set vf vlan insert <port_id> <vf_id> <vlan_id>",
+ .tokens = {
+ (void *)&cmd_vf_vlan_insert_set,
+ (void *)&cmd_vf_vlan_insert_vf,
+ (void *)&cmd_vf_vlan_insert_vlan,
+ (void *)&cmd_vf_vlan_insert_insert,
+ (void *)&cmd_vf_vlan_insert_port_id,
+ (void *)&cmd_vf_vlan_insert_vf_id,
+ (void *)&cmd_vf_vlan_insert_vlan_id,
+ NULL,
+ },
+};
+
+/* tx loopback configuration */
+
+/* Common result structure for tx loopback */
+struct cmd_tx_loopback_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t tx;
+ cmdline_fixed_string_t loopback;
+ uint8_t port_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for tx loopback enable disable */
+cmdline_parse_token_string_t cmd_tx_loopback_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_tx_loopback_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_tx_loopback_tx =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_tx_loopback_result,
+ tx, "tx");
+cmdline_parse_token_string_t cmd_tx_loopback_loopback =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_tx_loopback_result,
+ loopback, "loopback");
+cmdline_parse_token_num_t cmd_tx_loopback_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_tx_loopback_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_tx_loopback_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_tx_loopback_result,
+ on_off, "on#off");
+
+static void
+cmd_set_tx_loopback_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_tx_loopback_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ __rte_unused int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_ixgbe_set_tx_loopback(res->port_id, is_on);
+#endif
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_i40e_set_tx_loopback(res->port_id, is_on);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid is_on %d\n", is_on);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_tx_loopback = {
+ .f = cmd_set_tx_loopback_parsed,
+ .data = NULL,
+ .help_str = "set tx loopback <port_id> on|off",
+ .tokens = {
+ (void *)&cmd_tx_loopback_set,
+ (void *)&cmd_tx_loopback_tx,
+ (void *)&cmd_tx_loopback_loopback,
+ (void *)&cmd_tx_loopback_port_id,
+ (void *)&cmd_tx_loopback_on_off,
+ NULL,
+ },
+};
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+/* all queues drop enable configuration */
+
+/* Common result structure for all queues drop enable */
+struct cmd_all_queues_drop_en_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t all;
+ cmdline_fixed_string_t queues;
+ cmdline_fixed_string_t drop;
+ uint8_t port_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for tx loopback enable disable */
+cmdline_parse_token_string_t cmd_all_queues_drop_en_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_all_queues_drop_en_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_all_queues_drop_en_all =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_all_queues_drop_en_result,
+ all, "all");
+cmdline_parse_token_string_t cmd_all_queues_drop_en_queues =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_all_queues_drop_en_result,
+ queues, "queues");
+cmdline_parse_token_string_t cmd_all_queues_drop_en_drop =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_all_queues_drop_en_result,
+ drop, "drop");
+cmdline_parse_token_num_t cmd_all_queues_drop_en_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_all_queues_drop_en_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_all_queues_drop_en_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_all_queues_drop_en_result,
+ on_off, "on#off");
+
+static void
+cmd_set_all_queues_drop_en_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_all_queues_drop_en_result *res = parsed_result;
+ int ret = 0;
+ int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ ret = rte_pmd_ixgbe_set_all_queues_drop_en(res->port_id, is_on);
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid is_on %d\n", is_on);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_all_queues_drop_en = {
+ .f = cmd_set_all_queues_drop_en_parsed,
+ .data = NULL,
+ .help_str = "set all queues drop <port_id> on|off",
+ .tokens = {
+ (void *)&cmd_all_queues_drop_en_set,
+ (void *)&cmd_all_queues_drop_en_all,
+ (void *)&cmd_all_queues_drop_en_queues,
+ (void *)&cmd_all_queues_drop_en_drop,
+ (void *)&cmd_all_queues_drop_en_port_id,
+ (void *)&cmd_all_queues_drop_en_on_off,
+ NULL,
+ },
+};
+
+/* vf split drop enable configuration */
+
+/* Common result structure for vf split drop enable */
+struct cmd_vf_split_drop_en_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t split;
+ cmdline_fixed_string_t drop;
+ uint8_t port_id;
+ uint16_t vf_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf split drop enable disable */
+cmdline_parse_token_string_t cmd_vf_split_drop_en_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_split_drop_en_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_vf_split_drop_en_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_split_drop_en_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_vf_split_drop_en_split =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_split_drop_en_result,
+ split, "split");
+cmdline_parse_token_string_t cmd_vf_split_drop_en_drop =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_split_drop_en_result,
+ drop, "drop");
+cmdline_parse_token_num_t cmd_vf_split_drop_en_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_split_drop_en_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_split_drop_en_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_split_drop_en_result,
+ vf_id, UINT16);
+cmdline_parse_token_string_t cmd_vf_split_drop_en_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_split_drop_en_result,
+ on_off, "on#off");
+
+static void
+cmd_set_vf_split_drop_en_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_vf_split_drop_en_result *res = parsed_result;
+ int ret;
+ int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ ret = rte_pmd_ixgbe_set_vf_split_drop_en(res->port_id, res->vf_id,
+ is_on);
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d or is_on %d\n", res->vf_id, is_on);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_vf_split_drop_en = {
+ .f = cmd_set_vf_split_drop_en_parsed,
+ .data = NULL,
+ .help_str = "set vf split drop <port_id> <vf_id> on|off",
+ .tokens = {
+ (void *)&cmd_vf_split_drop_en_set,
+ (void *)&cmd_vf_split_drop_en_vf,
+ (void *)&cmd_vf_split_drop_en_split,
+ (void *)&cmd_vf_split_drop_en_drop,
+ (void *)&cmd_vf_split_drop_en_port_id,
+ (void *)&cmd_vf_split_drop_en_vf_id,
+ (void *)&cmd_vf_split_drop_en_on_off,
+ NULL,
+ },
+};
+#endif
+
+/* vf mac address configuration */
+
+/* Common result structure for vf mac address */
+struct cmd_set_vf_mac_addr_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t mac;
+ cmdline_fixed_string_t addr;
+ uint8_t port_id;
+ uint16_t vf_id;
+ struct ether_addr mac_addr;
+
+};
+
+/* Common CLI fields for vf split drop enable disable */
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_mac_addr_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_mac_addr_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_mac =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_mac_addr_result,
+ mac, "mac");
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_addr =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_mac_addr_result,
+ addr, "addr");
+cmdline_parse_token_num_t cmd_set_vf_mac_addr_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_set_vf_mac_addr_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_set_vf_mac_addr_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_set_vf_mac_addr_result,
+ vf_id, UINT16);
+cmdline_parse_token_etheraddr_t cmd_set_vf_mac_addr_mac_addr =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_vf_mac_addr_result,
+ mac_addr);
+
+static void
+cmd_set_vf_mac_addr_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_vf_mac_addr_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_ixgbe_set_vf_mac_addr(res->port_id, res->vf_id,
+ &res->mac_addr);
+#endif
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_i40e_set_vf_mac_addr(res->port_id, res->vf_id,
+ &res->mac_addr);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d or mac_addr\n", res->vf_id);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_vf_mac_addr = {
+ .f = cmd_set_vf_mac_addr_parsed,
+ .data = NULL,
+ .help_str = "set vf mac addr <port_id> <vf_id> <mac_addr>",
+ .tokens = {
+ (void *)&cmd_set_vf_mac_addr_set,
+ (void *)&cmd_set_vf_mac_addr_vf,
+ (void *)&cmd_set_vf_mac_addr_mac,
+ (void *)&cmd_set_vf_mac_addr_addr,
+ (void *)&cmd_set_vf_mac_addr_port_id,
+ (void *)&cmd_set_vf_mac_addr_vf_id,
+ (void *)&cmd_set_vf_mac_addr_mac_addr,
+ NULL,
+ },
+};
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+/* MACsec configuration */
+
+/* Common result structure for MACsec offload enable */
+struct cmd_macsec_offload_on_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t macsec;
+ cmdline_fixed_string_t offload;
+ uint8_t port_id;
+ cmdline_fixed_string_t on;
+ cmdline_fixed_string_t encrypt;
+ cmdline_fixed_string_t en_on_off;
+ cmdline_fixed_string_t replay_protect;
+ cmdline_fixed_string_t rp_on_off;
+};
+
+/* Common CLI fields for MACsec offload disable */
+cmdline_parse_token_string_t cmd_macsec_offload_on_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_offload_on_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_macsec_offload_on_macsec =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_offload_on_result,
+ macsec, "macsec");
+cmdline_parse_token_string_t cmd_macsec_offload_on_offload =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_offload_on_result,
+ offload, "offload");
+cmdline_parse_token_num_t cmd_macsec_offload_on_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_macsec_offload_on_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_macsec_offload_on_on =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_offload_on_result,
+ on, "on");
+cmdline_parse_token_string_t cmd_macsec_offload_on_encrypt =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_offload_on_result,
+ encrypt, "encrypt");
+cmdline_parse_token_string_t cmd_macsec_offload_on_en_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_offload_on_result,
+ en_on_off, "on#off");
+cmdline_parse_token_string_t cmd_macsec_offload_on_replay_protect =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_offload_on_result,
+ replay_protect, "replay-protect");
+cmdline_parse_token_string_t cmd_macsec_offload_on_rp_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_offload_on_result,
+ rp_on_off, "on#off");
+
+static void
+cmd_set_macsec_offload_on_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_macsec_offload_on_result *res = parsed_result;
+ int ret;
+ portid_t port_id = res->port_id;
+ int en = (strcmp(res->en_on_off, "on") == 0) ? 1 : 0;
+ int rp = (strcmp(res->rp_on_off, "on") == 0) ? 1 : 0;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ ports[port_id].tx_ol_flags |= TESTPMD_TX_OFFLOAD_MACSEC;
+ ret = rte_pmd_ixgbe_macsec_enable(port_id, en, rp);
+
+ switch (ret) {
+ case 0:
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", port_id);
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_macsec_offload_on = {
+ .f = cmd_set_macsec_offload_on_parsed,
+ .data = NULL,
+ .help_str = "set macsec offload <port_id> on "
+ "encrypt on|off replay-protect on|off",
+ .tokens = {
+ (void *)&cmd_macsec_offload_on_set,
+ (void *)&cmd_macsec_offload_on_macsec,
+ (void *)&cmd_macsec_offload_on_offload,
+ (void *)&cmd_macsec_offload_on_port_id,
+ (void *)&cmd_macsec_offload_on_on,
+ (void *)&cmd_macsec_offload_on_encrypt,
+ (void *)&cmd_macsec_offload_on_en_on_off,
+ (void *)&cmd_macsec_offload_on_replay_protect,
+ (void *)&cmd_macsec_offload_on_rp_on_off,
+ NULL,
+ },
+};
+
+/* Common result structure for MACsec offload disable */
+struct cmd_macsec_offload_off_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t macsec;
+ cmdline_fixed_string_t offload;
+ uint8_t port_id;
+ cmdline_fixed_string_t off;
+};
+
+/* Common CLI fields for MACsec offload disable */
+cmdline_parse_token_string_t cmd_macsec_offload_off_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_offload_off_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_macsec_offload_off_macsec =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_offload_off_result,
+ macsec, "macsec");
+cmdline_parse_token_string_t cmd_macsec_offload_off_offload =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_offload_off_result,
+ offload, "offload");
+cmdline_parse_token_num_t cmd_macsec_offload_off_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_macsec_offload_off_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_macsec_offload_off_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_offload_off_result,
+ off, "off");
+
+static void
+cmd_set_macsec_offload_off_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_macsec_offload_off_result *res = parsed_result;
+ int ret;
+ portid_t port_id = res->port_id;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ ports[port_id].tx_ol_flags &= ~TESTPMD_TX_OFFLOAD_MACSEC;
+ ret = rte_pmd_ixgbe_macsec_disable(port_id);
+
+ switch (ret) {
+ case 0:
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", port_id);
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_macsec_offload_off = {
+ .f = cmd_set_macsec_offload_off_parsed,
+ .data = NULL,
+ .help_str = "set macsec offload <port_id> off",
+ .tokens = {
+ (void *)&cmd_macsec_offload_off_set,
+ (void *)&cmd_macsec_offload_off_macsec,
+ (void *)&cmd_macsec_offload_off_offload,
+ (void *)&cmd_macsec_offload_off_port_id,
+ (void *)&cmd_macsec_offload_off_off,
+ NULL,
+ },
+};
+
+/* Common result structure for MACsec secure connection configure */
+struct cmd_macsec_sc_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t macsec;
+ cmdline_fixed_string_t sc;
+ cmdline_fixed_string_t tx_rx;
+ uint8_t port_id;
+ struct ether_addr mac;
+ uint16_t pi;
+};
+
+/* Common CLI fields for MACsec secure connection configure */
+cmdline_parse_token_string_t cmd_macsec_sc_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_sc_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_macsec_sc_macsec =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_sc_result,
+ macsec, "macsec");
+cmdline_parse_token_string_t cmd_macsec_sc_sc =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_sc_result,
+ sc, "sc");
+cmdline_parse_token_string_t cmd_macsec_sc_tx_rx =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_sc_result,
+ tx_rx, "tx#rx");
+cmdline_parse_token_num_t cmd_macsec_sc_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_macsec_sc_result,
+ port_id, UINT8);
+cmdline_parse_token_etheraddr_t cmd_macsec_sc_mac =
+ TOKEN_ETHERADDR_INITIALIZER
+ (struct cmd_macsec_sc_result,
+ mac);
+cmdline_parse_token_num_t cmd_macsec_sc_pi =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_macsec_sc_result,
+ pi, UINT16);
+
+static void
+cmd_set_macsec_sc_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_macsec_sc_result *res = parsed_result;
+ int ret;
+ int is_tx = (strcmp(res->tx_rx, "tx") == 0) ? 1 : 0;
+
+ ret = is_tx ?
+ rte_pmd_ixgbe_macsec_config_txsc(res->port_id,
+ res->mac.addr_bytes) :
+ rte_pmd_ixgbe_macsec_config_rxsc(res->port_id,
+ res->mac.addr_bytes, res->pi);
+ switch (ret) {
+ case 0:
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_macsec_sc = {
+ .f = cmd_set_macsec_sc_parsed,
+ .data = NULL,
+ .help_str = "set macsec sc tx|rx <port_id> <mac> <pi>",
+ .tokens = {
+ (void *)&cmd_macsec_sc_set,
+ (void *)&cmd_macsec_sc_macsec,
+ (void *)&cmd_macsec_sc_sc,
+ (void *)&cmd_macsec_sc_tx_rx,
+ (void *)&cmd_macsec_sc_port_id,
+ (void *)&cmd_macsec_sc_mac,
+ (void *)&cmd_macsec_sc_pi,
+ NULL,
+ },
+};
+
+/* Common result structure for MACsec secure connection configure */
+struct cmd_macsec_sa_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t macsec;
+ cmdline_fixed_string_t sa;
+ cmdline_fixed_string_t tx_rx;
+ uint8_t port_id;
+ uint8_t idx;
+ uint8_t an;
+ uint32_t pn;
+ cmdline_fixed_string_t key;
+};
+
+/* Common CLI fields for MACsec secure connection configure */
+cmdline_parse_token_string_t cmd_macsec_sa_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_sa_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_macsec_sa_macsec =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_sa_result,
+ macsec, "macsec");
+cmdline_parse_token_string_t cmd_macsec_sa_sa =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_sa_result,
+ sa, "sa");
+cmdline_parse_token_string_t cmd_macsec_sa_tx_rx =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_sa_result,
+ tx_rx, "tx#rx");
+cmdline_parse_token_num_t cmd_macsec_sa_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_macsec_sa_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_macsec_sa_idx =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_macsec_sa_result,
+ idx, UINT8);
+cmdline_parse_token_num_t cmd_macsec_sa_an =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_macsec_sa_result,
+ an, UINT8);
+cmdline_parse_token_num_t cmd_macsec_sa_pn =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_macsec_sa_result,
+ pn, UINT32);
+cmdline_parse_token_string_t cmd_macsec_sa_key =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_sa_result,
+ key, NULL);
+
+static void
+cmd_set_macsec_sa_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_macsec_sa_result *res = parsed_result;
+ int ret;
+ int is_tx = (strcmp(res->tx_rx, "tx") == 0) ? 1 : 0;
+ uint8_t key[16] = { 0 };
+ uint8_t xdgt0;
+ uint8_t xdgt1;
+ int key_len;
+ int i;
+
+ key_len = strlen(res->key) / 2;
+ if (key_len > 16)
+ key_len = 16;
+
+ for (i = 0; i < key_len; i++) {
+ xdgt0 = parse_and_check_key_hexa_digit(res->key, (i * 2));
+ if (xdgt0 == 0xFF)
+ return;
+ xdgt1 = parse_and_check_key_hexa_digit(res->key, (i * 2) + 1);
+ if (xdgt1 == 0xFF)
+ return;
+ key[i] = (uint8_t) ((xdgt0 * 16) + xdgt1);
+ }
+
+ ret = is_tx ?
+ rte_pmd_ixgbe_macsec_select_txsa(res->port_id,
+ res->idx, res->an, res->pn, key) :
+ rte_pmd_ixgbe_macsec_select_rxsa(res->port_id,
+ res->idx, res->an, res->pn, key);
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid idx %d or an %d\n", res->idx, res->an);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_macsec_sa = {
+ .f = cmd_set_macsec_sa_parsed,
+ .data = NULL,
+ .help_str = "set macsec sa tx|rx <port_id> <idx> <an> <pn> <key>",
+ .tokens = {
+ (void *)&cmd_macsec_sa_set,
+ (void *)&cmd_macsec_sa_macsec,
+ (void *)&cmd_macsec_sa_sa,
+ (void *)&cmd_macsec_sa_tx_rx,
+ (void *)&cmd_macsec_sa_port_id,
+ (void *)&cmd_macsec_sa_idx,
+ (void *)&cmd_macsec_sa_an,
+ (void *)&cmd_macsec_sa_pn,
+ (void *)&cmd_macsec_sa_key,
+ NULL,
+ },
+};
+#endif
+
+/* VF unicast promiscuous mode configuration */
+
+/* Common result structure for VF unicast promiscuous mode */
+struct cmd_vf_promisc_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t promisc;
+ uint8_t port_id;
+ uint32_t vf_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for VF unicast promiscuous mode enable disable */
+cmdline_parse_token_string_t cmd_vf_promisc_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_promisc_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_vf_promisc_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_promisc_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_vf_promisc_promisc =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_promisc_result,
+ promisc, "promisc");
+cmdline_parse_token_num_t cmd_vf_promisc_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_promisc_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_promisc_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_promisc_result,
+ vf_id, UINT32);
+cmdline_parse_token_string_t cmd_vf_promisc_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_promisc_result,
+ on_off, "on#off");
+
+static void
+cmd_set_vf_promisc_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_vf_promisc_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ __rte_unused int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ ret = rte_pmd_i40e_set_vf_unicast_promisc(res->port_id,
+ res->vf_id, is_on);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d\n", res->vf_id);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_vf_promisc = {
+ .f = cmd_set_vf_promisc_parsed,
+ .data = NULL,
+ .help_str = "set vf promisc <port_id> <vf_id> on|off: "
+ "Set unicast promiscuous mode for a VF from the PF",
+ .tokens = {
+ (void *)&cmd_vf_promisc_set,
+ (void *)&cmd_vf_promisc_vf,
+ (void *)&cmd_vf_promisc_promisc,
+ (void *)&cmd_vf_promisc_port_id,
+ (void *)&cmd_vf_promisc_vf_id,
+ (void *)&cmd_vf_promisc_on_off,
+ NULL,
+ },
+};
+
+/* VF multicast promiscuous mode configuration */
+
+/* Common result structure for VF multicast promiscuous mode */
+struct cmd_vf_allmulti_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t allmulti;
+ uint8_t port_id;
+ uint32_t vf_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for VF multicast promiscuous mode enable disable */
+cmdline_parse_token_string_t cmd_vf_allmulti_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_allmulti_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_vf_allmulti_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_allmulti_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_vf_allmulti_allmulti =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_allmulti_result,
+ allmulti, "allmulti");
+cmdline_parse_token_num_t cmd_vf_allmulti_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_allmulti_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_allmulti_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_allmulti_result,
+ vf_id, UINT32);
+cmdline_parse_token_string_t cmd_vf_allmulti_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_allmulti_result,
+ on_off, "on#off");
+
+static void
+cmd_set_vf_allmulti_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_vf_allmulti_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ __rte_unused int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ ret = rte_pmd_i40e_set_vf_multicast_promisc(res->port_id,
+ res->vf_id, is_on);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d\n", res->vf_id);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_vf_allmulti = {
+ .f = cmd_set_vf_allmulti_parsed,
+ .data = NULL,
+ .help_str = "set vf allmulti <port_id> <vf_id> on|off: "
+ "Set multicast promiscuous mode for a VF from the PF",
+ .tokens = {
+ (void *)&cmd_vf_allmulti_set,
+ (void *)&cmd_vf_allmulti_vf,
+ (void *)&cmd_vf_allmulti_allmulti,
+ (void *)&cmd_vf_allmulti_port_id,
+ (void *)&cmd_vf_allmulti_vf_id,
+ (void *)&cmd_vf_allmulti_on_off,
+ NULL,
+ },
+};
+
+/* vf broadcast mode configuration */
+
+/* Common result structure for vf broadcast */
+struct cmd_set_vf_broadcast_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t broadcast;
+ uint8_t port_id;
+ uint16_t vf_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf broadcast enable disable */
+cmdline_parse_token_string_t cmd_set_vf_broadcast_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_broadcast_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_set_vf_broadcast_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_broadcast_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_set_vf_broadcast_broadcast =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_broadcast_result,
+ broadcast, "broadcast");
+cmdline_parse_token_num_t cmd_set_vf_broadcast_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_set_vf_broadcast_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_set_vf_broadcast_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_set_vf_broadcast_result,
+ vf_id, UINT16);
+cmdline_parse_token_string_t cmd_set_vf_broadcast_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_broadcast_result,
+ on_off, "on#off");
+
+static void
+cmd_set_vf_broadcast_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_vf_broadcast_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ __rte_unused int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ ret = rte_pmd_i40e_set_vf_broadcast(res->port_id,
+ res->vf_id, is_on);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d or is_on %d\n", res->vf_id, is_on);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_vf_broadcast = {
+ .f = cmd_set_vf_broadcast_parsed,
+ .data = NULL,
+ .help_str = "set vf broadcast <port_id> <vf_id> on|off",
+ .tokens = {
+ (void *)&cmd_set_vf_broadcast_set,
+ (void *)&cmd_set_vf_broadcast_vf,
+ (void *)&cmd_set_vf_broadcast_broadcast,
+ (void *)&cmd_set_vf_broadcast_port_id,
+ (void *)&cmd_set_vf_broadcast_vf_id,
+ (void *)&cmd_set_vf_broadcast_on_off,
+ NULL,
+ },
+};
+
+/* vf vlan tag configuration */
+
+/* Common result structure for vf vlan tag */
+struct cmd_set_vf_vlan_tag_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t vlan;
+ cmdline_fixed_string_t tag;
+ uint8_t port_id;
+ uint16_t vf_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf vlan tag enable disable */
+cmdline_parse_token_string_t cmd_set_vf_vlan_tag_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_set_vf_vlan_tag_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_set_vf_vlan_tag_vlan =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ vlan, "vlan");
+cmdline_parse_token_string_t cmd_set_vf_vlan_tag_tag =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ tag, "tag");
+cmdline_parse_token_num_t cmd_set_vf_vlan_tag_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_set_vf_vlan_tag_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ vf_id, UINT16);
+cmdline_parse_token_string_t cmd_set_vf_vlan_tag_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ on_off, "on#off");
+
+static void
+cmd_set_vf_vlan_tag_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_set_vf_vlan_tag_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ __rte_unused int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ ret = rte_pmd_i40e_set_vf_vlan_tag(res->port_id,
+ res->vf_id, is_on);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d or is_on %d\n", res->vf_id, is_on);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_vf_vlan_tag = {
+ .f = cmd_set_vf_vlan_tag_parsed,
+ .data = NULL,
+ .help_str = "set vf vlan tag <port_id> <vf_id> on|off",
+ .tokens = {
+ (void *)&cmd_set_vf_vlan_tag_set,
+ (void *)&cmd_set_vf_vlan_tag_vf,
+ (void *)&cmd_set_vf_vlan_tag_vlan,
+ (void *)&cmd_set_vf_vlan_tag_tag,
+ (void *)&cmd_set_vf_vlan_tag_port_id,
+ (void *)&cmd_set_vf_vlan_tag_vf_id,
+ (void *)&cmd_set_vf_vlan_tag_on_off,
+ NULL,
+ },
+};
+
+/* Common definition of VF and TC TX bandwidth configuration */
+struct cmd_vf_tc_bw_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t tc;
+ cmdline_fixed_string_t tx;
+ cmdline_fixed_string_t min_bw;
+ cmdline_fixed_string_t max_bw;
+ cmdline_fixed_string_t strict_link_prio;
+ uint8_t port_id;
+ uint16_t vf_id;
+ uint8_t tc_no;
+ uint32_t bw;
+ cmdline_fixed_string_t bw_list;
+ uint8_t tc_map;
+};
+
+cmdline_parse_token_string_t cmd_vf_tc_bw_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_tc_bw_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_vf_tc_bw_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_tc_bw_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_vf_tc_bw_tc =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_tc_bw_result,
+ tc, "tc");
+cmdline_parse_token_string_t cmd_vf_tc_bw_tx =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_tc_bw_result,
+ tx, "tx");
+cmdline_parse_token_string_t cmd_vf_tc_bw_strict_link_prio =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_tc_bw_result,
+ strict_link_prio, "strict-link-priority");
+cmdline_parse_token_string_t cmd_vf_tc_bw_min_bw =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_tc_bw_result,
+ min_bw, "min-bandwidth");
+cmdline_parse_token_string_t cmd_vf_tc_bw_max_bw =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_tc_bw_result,
+ max_bw, "max-bandwidth");
+cmdline_parse_token_num_t cmd_vf_tc_bw_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_tc_bw_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_vf_tc_bw_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_tc_bw_result,
+ vf_id, UINT16);
+cmdline_parse_token_num_t cmd_vf_tc_bw_tc_no =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_tc_bw_result,
+ tc_no, UINT8);
+cmdline_parse_token_num_t cmd_vf_tc_bw_bw =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_tc_bw_result,
+ bw, UINT32);
+cmdline_parse_token_string_t cmd_vf_tc_bw_bw_list =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_tc_bw_result,
+ bw_list, NULL);
+cmdline_parse_token_num_t cmd_vf_tc_bw_tc_map =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_tc_bw_result,
+ tc_map, UINT8);
+
+/* VF max bandwidth setting */
+static void
+cmd_vf_max_bw_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_vf_tc_bw_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ ret = rte_pmd_i40e_set_vf_max_bw(res->port_id,
+ res->vf_id, res->bw);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d or bandwidth %d\n",
+ res->vf_id, res->bw);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_vf_max_bw = {
+ .f = cmd_vf_max_bw_parsed,
+ .data = NULL,
+ .help_str = "set vf tx max-bandwidth <port_id> <vf_id> <bandwidth>",
+ .tokens = {
+ (void *)&cmd_vf_tc_bw_set,
+ (void *)&cmd_vf_tc_bw_vf,
+ (void *)&cmd_vf_tc_bw_tx,
+ (void *)&cmd_vf_tc_bw_max_bw,
+ (void *)&cmd_vf_tc_bw_port_id,
+ (void *)&cmd_vf_tc_bw_vf_id,
+ (void *)&cmd_vf_tc_bw_bw,
+ NULL,
+ },
+};
+
+static int
+vf_tc_min_bw_parse_bw_list(uint8_t *bw_list,
+ uint8_t *tc_num,
+ char *str)
+{
+ uint32_t size;
+ const char *p, *p0 = str;
+ char s[256];
+ char *end;
+ char *str_fld[16];
+ uint16_t i;
+ int ret;
+
+ p = strchr(p0, '(');
+ if (p == NULL) {
+ printf("The bandwidth-list should be '(bw1, bw2, ...)'\n");
+ return -1;
+ }
+ p++;
+ p0 = strchr(p, ')');
+ if (p0 == NULL) {
+ printf("The bandwidth-list should be '(bw1, bw2, ...)'\n");
+ return -1;
+ }
+ size = p0 - p;
+ if (size >= sizeof(s)) {
+ printf("The string size exceeds the internal buffer size\n");
+ return -1;
+ }
+ snprintf(s, sizeof(s), "%.*s", size, p);
+ ret = rte_strsplit(s, sizeof(s), str_fld, 16, ',');
+ if (ret <= 0) {
+ printf("Failed to get the bandwidth list. ");
+ return -1;
+ }
+ *tc_num = ret;
+ for (i = 0; i < ret; i++)
+ bw_list[i] = (uint8_t)strtoul(str_fld[i], &end, 0);
+
+ return 0;
+}
+
+/* TC min bandwidth setting */
+static void
+cmd_vf_tc_min_bw_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_vf_tc_bw_result *res = parsed_result;
+ uint8_t tc_num;
+ uint8_t bw[16];
+ int ret = -ENOTSUP;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ ret = vf_tc_min_bw_parse_bw_list(bw, &tc_num, res->bw_list);
+ if (ret)
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ ret = rte_pmd_i40e_set_vf_tc_bw_alloc(res->port_id, res->vf_id,
+ tc_num, bw);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d or bandwidth\n", res->vf_id);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_vf_tc_min_bw = {
+ .f = cmd_vf_tc_min_bw_parsed,
+ .data = NULL,
+ .help_str = "set vf tc tx min-bandwidth <port_id> <vf_id>"
+ " <bw1, bw2, ...>",
+ .tokens = {
+ (void *)&cmd_vf_tc_bw_set,
+ (void *)&cmd_vf_tc_bw_vf,
+ (void *)&cmd_vf_tc_bw_tc,
+ (void *)&cmd_vf_tc_bw_tx,
+ (void *)&cmd_vf_tc_bw_min_bw,
+ (void *)&cmd_vf_tc_bw_port_id,
+ (void *)&cmd_vf_tc_bw_vf_id,
+ (void *)&cmd_vf_tc_bw_bw_list,
+ NULL,
+ },
+};
+
+static void
+cmd_tc_min_bw_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_vf_tc_bw_result *res = parsed_result;
+ struct rte_port *port;
+ uint8_t tc_num;
+ uint8_t bw[16];
+ int ret = -ENOTSUP;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ port = &ports[res->port_id];
+ /** Check if the port is not started **/
+ if (port->port_status != RTE_PORT_STOPPED) {
+ printf("Please stop port %d first\n", res->port_id);
+ return;
+ }
+
+ ret = vf_tc_min_bw_parse_bw_list(bw, &tc_num, res->bw_list);
+ if (ret)
+ return;
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ ret = rte_pmd_ixgbe_set_tc_bw_alloc(res->port_id, tc_num, bw);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid bandwidth\n");
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_tc_min_bw = {
+ .f = cmd_tc_min_bw_parsed,
+ .data = NULL,
+ .help_str = "set tc tx min-bandwidth <port_id> <bw1, bw2, ...>",
+ .tokens = {
+ (void *)&cmd_vf_tc_bw_set,
+ (void *)&cmd_vf_tc_bw_tc,
+ (void *)&cmd_vf_tc_bw_tx,
+ (void *)&cmd_vf_tc_bw_min_bw,
+ (void *)&cmd_vf_tc_bw_port_id,
+ (void *)&cmd_vf_tc_bw_bw_list,
+ NULL,
+ },
+};
+
+/* TC max bandwidth setting */
+static void
+cmd_vf_tc_max_bw_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_vf_tc_bw_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ ret = rte_pmd_i40e_set_vf_tc_max_bw(res->port_id, res->vf_id,
+ res->tc_no, res->bw);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d, tc_no %d or bandwidth %d\n",
+ res->vf_id, res->tc_no, res->bw);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_vf_tc_max_bw = {
+ .f = cmd_vf_tc_max_bw_parsed,
+ .data = NULL,
+ .help_str = "set vf tc tx max-bandwidth <port_id> <vf_id> <tc_no>"
+ " <bandwidth>",
+ .tokens = {
+ (void *)&cmd_vf_tc_bw_set,
+ (void *)&cmd_vf_tc_bw_vf,
+ (void *)&cmd_vf_tc_bw_tc,
+ (void *)&cmd_vf_tc_bw_tx,
+ (void *)&cmd_vf_tc_bw_max_bw,
+ (void *)&cmd_vf_tc_bw_port_id,
+ (void *)&cmd_vf_tc_bw_vf_id,
+ (void *)&cmd_vf_tc_bw_tc_no,
+ (void *)&cmd_vf_tc_bw_bw,
+ NULL,
+ },
+};
+
+/* Strict link priority scheduling mode setting */
+static void
+cmd_strict_link_prio_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_vf_tc_bw_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ ret = rte_pmd_i40e_set_tc_strict_prio(res->port_id, res->tc_map);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid tc_bitmap 0x%x\n", res->tc_map);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_strict_link_prio = {
+ .f = cmd_strict_link_prio_parsed,
+ .data = NULL,
+ .help_str = "set tx strict-link-priority <port_id> <tc_bitmap>",
+ .tokens = {
+ (void *)&cmd_vf_tc_bw_set,
+ (void *)&cmd_vf_tc_bw_tx,
+ (void *)&cmd_vf_tc_bw_strict_link_prio,
+ (void *)&cmd_vf_tc_bw_port_id,
+ (void *)&cmd_vf_tc_bw_tc_map,
+ NULL,
+ },
+};
+
+/* Load dynamic device personalization*/
+struct cmd_ddp_add_result {
+ cmdline_fixed_string_t ddp;
+ cmdline_fixed_string_t add;
+ uint8_t port_id;
+ char filepath[];
+};
+
+cmdline_parse_token_string_t cmd_ddp_add_ddp =
+ TOKEN_STRING_INITIALIZER(struct cmd_ddp_add_result, ddp, "ddp");
+cmdline_parse_token_string_t cmd_ddp_add_add =
+ TOKEN_STRING_INITIALIZER(struct cmd_ddp_add_result, add, "add");
+cmdline_parse_token_num_t cmd_ddp_add_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_ddp_add_result, port_id, UINT8);
+cmdline_parse_token_string_t cmd_ddp_add_filepath =
+ TOKEN_STRING_INITIALIZER(struct cmd_ddp_add_result, filepath, NULL);
+
+static void
+cmd_ddp_add_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_ddp_add_result *res = parsed_result;
+ uint8_t *buff;
+ uint32_t size;
+ int ret = -ENOTSUP;
+
+ if (res->port_id > nb_ports) {
+ printf("Invalid port, range is [0, %d]\n", nb_ports - 1);
+ return;
+ }
+
+ if (!all_ports_stopped()) {
+ printf("Please stop all ports first\n");
+ return;
+ }
+
+ buff = open_ddp_package_file(res->filepath, &size);
+ if (!buff)
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_i40e_process_ddp_package(res->port_id,
+ buff, size,
+ RTE_PMD_I40E_PKG_OP_WR_ADD);
+#endif
+
+ if (ret < 0)
+ printf("Failed to load profile.\n");
+ else if (ret > 0)
+ printf("Profile has already existed.\n");
+
+ close_ddp_package_file(buff);
+}
+
+cmdline_parse_inst_t cmd_ddp_add = {
+ .f = cmd_ddp_add_parsed,
+ .data = NULL,
+ .help_str = "ddp add <port_id> <profile_path>",
+ .tokens = {
+ (void *)&cmd_ddp_add_ddp,
+ (void *)&cmd_ddp_add_add,
+ (void *)&cmd_ddp_add_port_id,
+ (void *)&cmd_ddp_add_filepath,
+ NULL,
+ },
+};
+
+/* Get dynamic device personalization profile info list*/
+#define PROFILE_INFO_SIZE 48
+#define MAX_PROFILE_NUM 16
+
+struct cmd_ddp_get_list_result {
+ cmdline_fixed_string_t ddp;
+ cmdline_fixed_string_t get;
+ cmdline_fixed_string_t list;
+ uint8_t port_id;
+};
+
+cmdline_parse_token_string_t cmd_ddp_get_list_ddp =
+ TOKEN_STRING_INITIALIZER(struct cmd_ddp_get_list_result, ddp, "ddp");
+cmdline_parse_token_string_t cmd_ddp_get_list_get =
+ TOKEN_STRING_INITIALIZER(struct cmd_ddp_get_list_result, get, "get");
+cmdline_parse_token_string_t cmd_ddp_get_list_list =
+ TOKEN_STRING_INITIALIZER(struct cmd_ddp_get_list_result, list, "list");
+cmdline_parse_token_num_t cmd_ddp_get_list_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_ddp_get_list_result, port_id, UINT8);
+
+static void
+cmd_ddp_get_list_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_ddp_get_list_result *res = parsed_result;
+#ifdef RTE_LIBRTE_I40E_PMD
+ struct rte_pmd_i40e_profile_list *p_list;
+ struct rte_pmd_i40e_profile_info *p_info;
+ uint32_t p_num;
+ uint32_t size;
+ uint32_t i;
+#endif
+ int ret = -ENOTSUP;
+
+ if (res->port_id > nb_ports) {
+ printf("Invalid port, range is [0, %d]\n", nb_ports - 1);
+ return;
+ }
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ size = PROFILE_INFO_SIZE * MAX_PROFILE_NUM + 4;
+ p_list = (struct rte_pmd_i40e_profile_list *)malloc(size);
+ if (!p_list)
+ printf("%s: Failed to malloc buffer\n", __func__);
+
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_i40e_get_ddp_list(res->port_id,
+ (uint8_t *)p_list, size);
+
+ if (!ret) {
+ p_num = p_list->p_count;
+ printf("Profile number is: %d\n\n", p_num);
+
+ for (i = 0; i < p_num; i++) {
+ p_info = &p_list->p_info[i];
+ printf("Profile %d:\n", i);
+ printf("Track id: 0x%x\n", p_info->track_id);
+ printf("Version: %d.%d.%d.%d\n",
+ p_info->version.major,
+ p_info->version.minor,
+ p_info->version.update,
+ p_info->version.draft);
+ printf("Profile name: %s\n\n", p_info->name);
+ }
+ }
+
+ free(p_list);
+#endif
+
+ if (ret < 0)
+ printf("Failed to get ddp list\n");
+}
+
+cmdline_parse_inst_t cmd_ddp_get_list = {
+ .f = cmd_ddp_get_list_parsed,
+ .data = NULL,
+ .help_str = "ddp get list <port_id>",
+ .tokens = {
+ (void *)&cmd_ddp_get_list_ddp,
+ (void *)&cmd_ddp_get_list_get,
+ (void *)&cmd_ddp_get_list_list,
+ (void *)&cmd_ddp_get_list_port_id,
+ NULL,
+ },
+};
+
+/* show vf stats */
+
+/* Common result structure for show vf stats */
+struct cmd_show_vf_stats_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t stats;
+ uint8_t port_id;
+ uint16_t vf_id;
+};
+
+/* Common CLI fields show vf stats*/
+cmdline_parse_token_string_t cmd_show_vf_stats_show =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_show_vf_stats_result,
+ show, "show");
+cmdline_parse_token_string_t cmd_show_vf_stats_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_show_vf_stats_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_show_vf_stats_stats =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_show_vf_stats_result,
+ stats, "stats");
+cmdline_parse_token_num_t cmd_show_vf_stats_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_show_vf_stats_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_show_vf_stats_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_show_vf_stats_result,
+ vf_id, UINT16);
+
+static void
+cmd_show_vf_stats_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_show_vf_stats_result *res = parsed_result;
+ struct rte_eth_stats stats;
+ int ret = -ENOTSUP;
+ static const char *nic_stats_border = "########################";
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ memset(&stats, 0, sizeof(stats));
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ ret = rte_pmd_i40e_get_vf_stats(res->port_id,
+ res->vf_id,
+ &stats);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d\n", res->vf_id);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+
+ printf("\n %s NIC statistics for port %-2d vf %-2d %s\n",
+ nic_stats_border, res->port_id, res->vf_id, nic_stats_border);
+
+ printf(" RX-packets: %-10"PRIu64" RX-missed: %-10"PRIu64" RX-bytes: "
+ "%-"PRIu64"\n",
+ stats.ipackets, stats.imissed, stats.ibytes);
+ printf(" RX-errors: %-"PRIu64"\n", stats.ierrors);
+ printf(" RX-nombuf: %-10"PRIu64"\n",
+ stats.rx_nombuf);
+ printf(" TX-packets: %-10"PRIu64" TX-errors: %-10"PRIu64" TX-bytes: "
+ "%-"PRIu64"\n",
+ stats.opackets, stats.oerrors, stats.obytes);
+
+ printf(" %s############################%s\n",
+ nic_stats_border, nic_stats_border);
+}
+
+cmdline_parse_inst_t cmd_show_vf_stats = {
+ .f = cmd_show_vf_stats_parsed,
+ .data = NULL,
+ .help_str = "show vf stats <port_id> <vf_id>",
+ .tokens = {
+ (void *)&cmd_show_vf_stats_show,
+ (void *)&cmd_show_vf_stats_vf,
+ (void *)&cmd_show_vf_stats_stats,
+ (void *)&cmd_show_vf_stats_port_id,
+ (void *)&cmd_show_vf_stats_vf_id,
+ NULL,
+ },
+};
+
+/* clear vf stats */
+
+/* Common result structure for clear vf stats */
+struct cmd_clear_vf_stats_result {
+ cmdline_fixed_string_t clear;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t stats;
+ uint8_t port_id;
+ uint16_t vf_id;
+};
+
+/* Common CLI fields clear vf stats*/
+cmdline_parse_token_string_t cmd_clear_vf_stats_clear =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_clear_vf_stats_result,
+ clear, "clear");
+cmdline_parse_token_string_t cmd_clear_vf_stats_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_clear_vf_stats_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_clear_vf_stats_stats =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_clear_vf_stats_result,
+ stats, "stats");
+cmdline_parse_token_num_t cmd_clear_vf_stats_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_clear_vf_stats_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_clear_vf_stats_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_clear_vf_stats_result,
+ vf_id, UINT16);
+
+static void
+cmd_clear_vf_stats_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_clear_vf_stats_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ ret = rte_pmd_i40e_reset_vf_stats(res->port_id,
+ res->vf_id);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d\n", res->vf_id);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_clear_vf_stats = {
+ .f = cmd_clear_vf_stats_parsed,
+ .data = NULL,
+ .help_str = "clear vf stats <port_id> <vf_id>",
+ .tokens = {
+ (void *)&cmd_clear_vf_stats_clear,
+ (void *)&cmd_clear_vf_stats_vf,
+ (void *)&cmd_clear_vf_stats_stats,
+ (void *)&cmd_clear_vf_stats_port_id,
+ (void *)&cmd_clear_vf_stats_vf_id,
+ NULL,
+ },
+};
+
+/* ptype mapping get */
+
+/* Common result structure for ptype mapping get */
+struct cmd_ptype_mapping_get_result {
+ cmdline_fixed_string_t ptype;
+ cmdline_fixed_string_t mapping;
+ cmdline_fixed_string_t get;
+ uint8_t port_id;
+ uint8_t valid_only;
+};
+
+/* Common CLI fields for ptype mapping get */
+cmdline_parse_token_string_t cmd_ptype_mapping_get_ptype =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_ptype_mapping_get_result,
+ ptype, "ptype");
+cmdline_parse_token_string_t cmd_ptype_mapping_get_mapping =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_ptype_mapping_get_result,
+ mapping, "mapping");
+cmdline_parse_token_string_t cmd_ptype_mapping_get_get =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_ptype_mapping_get_result,
+ get, "get");
+cmdline_parse_token_num_t cmd_ptype_mapping_get_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_ptype_mapping_get_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_ptype_mapping_get_valid_only =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_ptype_mapping_get_result,
+ valid_only, UINT8);
+
+static void
+cmd_ptype_mapping_get_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_ptype_mapping_get_result *res = parsed_result;
+ int ret = -ENOTSUP;
+#ifdef RTE_LIBRTE_I40E_PMD
+ int max_ptype_num = 256;
+ struct rte_pmd_i40e_ptype_mapping mapping[max_ptype_num];
+ uint16_t count;
+ int i;
+#endif
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ ret = rte_pmd_i40e_ptype_mapping_get(res->port_id,
+ mapping,
+ max_ptype_num,
+ &count,
+ res->valid_only);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (!ret) {
+ for (i = 0; i < count; i++)
+ printf("%3d\t0x%08x\n",
+ mapping[i].hw_ptype, mapping[i].sw_ptype);
+ }
+#endif
+}
+
+cmdline_parse_inst_t cmd_ptype_mapping_get = {
+ .f = cmd_ptype_mapping_get_parsed,
+ .data = NULL,
+ .help_str = "ptype mapping get <port_id> <valid_only>",
+ .tokens = {
+ (void *)&cmd_ptype_mapping_get_ptype,
+ (void *)&cmd_ptype_mapping_get_mapping,
+ (void *)&cmd_ptype_mapping_get_get,
+ (void *)&cmd_ptype_mapping_get_port_id,
+ (void *)&cmd_ptype_mapping_get_valid_only,
+ NULL,
+ },
+};
+
+/* ptype mapping replace */
+
+/* Common result structure for ptype mapping replace */
+struct cmd_ptype_mapping_replace_result {
+ cmdline_fixed_string_t ptype;
+ cmdline_fixed_string_t mapping;
+ cmdline_fixed_string_t replace;
+ uint8_t port_id;
+ uint32_t target;
+ uint8_t mask;
+ uint32_t pkt_type;
+};
+
+/* Common CLI fields for ptype mapping replace */
+cmdline_parse_token_string_t cmd_ptype_mapping_replace_ptype =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_ptype_mapping_replace_result,
+ ptype, "ptype");
+cmdline_parse_token_string_t cmd_ptype_mapping_replace_mapping =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_ptype_mapping_replace_result,
+ mapping, "mapping");
+cmdline_parse_token_string_t cmd_ptype_mapping_replace_replace =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_ptype_mapping_replace_result,
+ replace, "replace");
+cmdline_parse_token_num_t cmd_ptype_mapping_replace_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_ptype_mapping_replace_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_ptype_mapping_replace_target =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_ptype_mapping_replace_result,
+ target, UINT32);
+cmdline_parse_token_num_t cmd_ptype_mapping_replace_mask =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_ptype_mapping_replace_result,
+ mask, UINT8);
+cmdline_parse_token_num_t cmd_ptype_mapping_replace_pkt_type =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_ptype_mapping_replace_result,
+ pkt_type, UINT32);
+
+static void
+cmd_ptype_mapping_replace_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_ptype_mapping_replace_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ ret = rte_pmd_i40e_ptype_mapping_replace(res->port_id,
+ res->target,
+ res->mask,
+ res->pkt_type);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid ptype 0x%8x or 0x%8x\n",
+ res->target, res->pkt_type);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_ptype_mapping_replace = {
+ .f = cmd_ptype_mapping_replace_parsed,
+ .data = NULL,
+ .help_str =
+ "ptype mapping replace <port_id> <target> <mask> <pkt_type>",
+ .tokens = {
+ (void *)&cmd_ptype_mapping_replace_ptype,
+ (void *)&cmd_ptype_mapping_replace_mapping,
+ (void *)&cmd_ptype_mapping_replace_replace,
+ (void *)&cmd_ptype_mapping_replace_port_id,
+ (void *)&cmd_ptype_mapping_replace_target,
+ (void *)&cmd_ptype_mapping_replace_mask,
+ (void *)&cmd_ptype_mapping_replace_pkt_type,
+ NULL,
+ },
+};
+
+/* ptype mapping reset */
+
+/* Common result structure for ptype mapping reset */
+struct cmd_ptype_mapping_reset_result {
+ cmdline_fixed_string_t ptype;
+ cmdline_fixed_string_t mapping;
+ cmdline_fixed_string_t reset;
+ uint8_t port_id;
+};
+
+/* Common CLI fields for ptype mapping reset*/
+cmdline_parse_token_string_t cmd_ptype_mapping_reset_ptype =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_ptype_mapping_reset_result,
+ ptype, "ptype");
+cmdline_parse_token_string_t cmd_ptype_mapping_reset_mapping =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_ptype_mapping_reset_result,
+ mapping, "mapping");
+cmdline_parse_token_string_t cmd_ptype_mapping_reset_reset =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_ptype_mapping_reset_result,
+ reset, "reset");
+cmdline_parse_token_num_t cmd_ptype_mapping_reset_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_ptype_mapping_reset_result,
+ port_id, UINT8);
+
+static void
+cmd_ptype_mapping_reset_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_ptype_mapping_reset_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ ret = rte_pmd_i40e_ptype_mapping_reset(res->port_id);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_ptype_mapping_reset = {
+ .f = cmd_ptype_mapping_reset_parsed,
+ .data = NULL,
+ .help_str = "ptype mapping reset <port_id>",
+ .tokens = {
+ (void *)&cmd_ptype_mapping_reset_ptype,
+ (void *)&cmd_ptype_mapping_reset_mapping,
+ (void *)&cmd_ptype_mapping_reset_reset,
+ (void *)&cmd_ptype_mapping_reset_port_id,
+ NULL,
+ },
+};
+
+/* ptype mapping update */
+
+/* Common result structure for ptype mapping update */
+struct cmd_ptype_mapping_update_result {
+ cmdline_fixed_string_t ptype;
+ cmdline_fixed_string_t mapping;
+ cmdline_fixed_string_t reset;
+ uint8_t port_id;
+ uint8_t hw_ptype;
+ uint32_t sw_ptype;
+};
+
+/* Common CLI fields for ptype mapping update*/
+cmdline_parse_token_string_t cmd_ptype_mapping_update_ptype =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_ptype_mapping_update_result,
+ ptype, "ptype");
+cmdline_parse_token_string_t cmd_ptype_mapping_update_mapping =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_ptype_mapping_update_result,
+ mapping, "mapping");
+cmdline_parse_token_string_t cmd_ptype_mapping_update_update =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_ptype_mapping_update_result,
+ reset, "update");
+cmdline_parse_token_num_t cmd_ptype_mapping_update_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_ptype_mapping_update_result,
+ port_id, UINT8);
+cmdline_parse_token_num_t cmd_ptype_mapping_update_hw_ptype =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_ptype_mapping_update_result,
+ hw_ptype, UINT8);
+cmdline_parse_token_num_t cmd_ptype_mapping_update_sw_ptype =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_ptype_mapping_update_result,
+ sw_ptype, UINT32);
+
+static void
+cmd_ptype_mapping_update_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_ptype_mapping_update_result *res = parsed_result;
+ int ret = -ENOTSUP;
+#ifdef RTE_LIBRTE_I40E_PMD
+ struct rte_pmd_i40e_ptype_mapping mapping;
+#endif
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ mapping.hw_ptype = res->hw_ptype;
+ mapping.sw_ptype = res->sw_ptype;
+ ret = rte_pmd_i40e_ptype_mapping_update(res->port_id,
+ &mapping,
+ 1,
+ 0);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid ptype 0x%8x\n", res->sw_ptype);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_ptype_mapping_update = {
+ .f = cmd_ptype_mapping_update_parsed,
+ .data = NULL,
+ .help_str = "ptype mapping update <port_id> <hw_ptype> <sw_ptype>",
+ .tokens = {
+ (void *)&cmd_ptype_mapping_update_ptype,
+ (void *)&cmd_ptype_mapping_update_mapping,
+ (void *)&cmd_ptype_mapping_update_update,
+ (void *)&cmd_ptype_mapping_update_port_id,
+ (void *)&cmd_ptype_mapping_update_hw_ptype,
+ (void *)&cmd_ptype_mapping_update_sw_ptype,
+ NULL,
+ },
+};
+
+/* Common result structure for file commands */
+struct cmd_cmdfile_result {
+ cmdline_fixed_string_t load;
+ cmdline_fixed_string_t filename;
+};
+
+/* Common CLI fields for file commands */
+cmdline_parse_token_string_t cmd_load_cmdfile =
+ TOKEN_STRING_INITIALIZER(struct cmd_cmdfile_result, load, "load");
+cmdline_parse_token_string_t cmd_load_cmdfile_filename =
+ TOKEN_STRING_INITIALIZER(struct cmd_cmdfile_result, filename, NULL);
+
+static void
+cmd_load_from_file_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_cmdfile_result *res = parsed_result;
+
+ cmdline_read_from_file(res->filename);
+}
+
+cmdline_parse_inst_t cmd_load_from_file = {
+ .f = cmd_load_from_file_parsed,
+ .data = NULL,
+ .help_str = "load <filename>",
+ .tokens = {
+ (void *)&cmd_load_cmdfile,
+ (void *)&cmd_load_cmdfile_filename,
+ NULL,
+ },
+};
+
+/* ******************************************************************************** */
+
+/* list of instructions */
+cmdline_parse_ctx_t main_ctx[] = {
+ (cmdline_parse_inst_t *)&cmd_help_brief,
+ (cmdline_parse_inst_t *)&cmd_help_long,
+ (cmdline_parse_inst_t *)&cmd_quit,
+ (cmdline_parse_inst_t *)&cmd_load_from_file,
+ (cmdline_parse_inst_t *)&cmd_showport,
+ (cmdline_parse_inst_t *)&cmd_showqueue,
+ (cmdline_parse_inst_t *)&cmd_showportall,
+ (cmdline_parse_inst_t *)&cmd_showcfg,
+ (cmdline_parse_inst_t *)&cmd_start,
+ (cmdline_parse_inst_t *)&cmd_start_tx_first,
+ (cmdline_parse_inst_t *)&cmd_start_tx_first_n,
+ (cmdline_parse_inst_t *)&cmd_set_link_up,
+ (cmdline_parse_inst_t *)&cmd_set_link_down,
+ (cmdline_parse_inst_t *)&cmd_reset,
+ (cmdline_parse_inst_t *)&cmd_set_numbers,
+ (cmdline_parse_inst_t *)&cmd_set_txpkts,
+ (cmdline_parse_inst_t *)&cmd_set_txsplit,
+ (cmdline_parse_inst_t *)&cmd_set_fwd_list,
+ (cmdline_parse_inst_t *)&cmd_set_fwd_mask,
+ (cmdline_parse_inst_t *)&cmd_set_fwd_mode,
+ (cmdline_parse_inst_t *)&cmd_set_fwd_retry_mode,
+ (cmdline_parse_inst_t *)&cmd_set_burst_tx_retry,
+ (cmdline_parse_inst_t *)&cmd_set_promisc_mode_one,
+ (cmdline_parse_inst_t *)&cmd_set_promisc_mode_all,
+ (cmdline_parse_inst_t *)&cmd_set_allmulti_mode_one,
+ (cmdline_parse_inst_t *)&cmd_set_allmulti_mode_all,
+ (cmdline_parse_inst_t *)&cmd_set_flush_rx,
+ (cmdline_parse_inst_t *)&cmd_set_link_check,
+#ifdef RTE_NIC_BYPASS
+ (cmdline_parse_inst_t *)&cmd_set_bypass_mode,
+ (cmdline_parse_inst_t *)&cmd_set_bypass_event,
+ (cmdline_parse_inst_t *)&cmd_set_bypass_timeout,
+ (cmdline_parse_inst_t *)&cmd_show_bypass_config,
+#endif
+#ifdef RTE_LIBRTE_PMD_BOND
+ (cmdline_parse_inst_t *) &cmd_set_bonding_mode,
+ (cmdline_parse_inst_t *) &cmd_show_bonding_config,
+ (cmdline_parse_inst_t *) &cmd_set_bonding_primary,
+ (cmdline_parse_inst_t *) &cmd_add_bonding_slave,
+ (cmdline_parse_inst_t *) &cmd_remove_bonding_slave,
+ (cmdline_parse_inst_t *) &cmd_create_bonded_device,
+ (cmdline_parse_inst_t *) &cmd_set_bond_mac_addr,
+ (cmdline_parse_inst_t *) &cmd_set_balance_xmit_policy,
+ (cmdline_parse_inst_t *) &cmd_set_bond_mon_period,
+#endif
+ (cmdline_parse_inst_t *)&cmd_vlan_offload,
+ (cmdline_parse_inst_t *)&cmd_vlan_tpid,
+ (cmdline_parse_inst_t *)&cmd_rx_vlan_filter_all,
+ (cmdline_parse_inst_t *)&cmd_rx_vlan_filter,
+ (cmdline_parse_inst_t *)&cmd_tx_vlan_set,
+ (cmdline_parse_inst_t *)&cmd_tx_vlan_set_qinq,
+ (cmdline_parse_inst_t *)&cmd_tx_vlan_reset,
+ (cmdline_parse_inst_t *)&cmd_tx_vlan_set_pvid,
+ (cmdline_parse_inst_t *)&cmd_csum_set,
+ (cmdline_parse_inst_t *)&cmd_csum_show,
+ (cmdline_parse_inst_t *)&cmd_csum_tunnel,
+ (cmdline_parse_inst_t *)&cmd_tso_set,
+ (cmdline_parse_inst_t *)&cmd_tso_show,
+ (cmdline_parse_inst_t *)&cmd_tunnel_tso_set,
+ (cmdline_parse_inst_t *)&cmd_tunnel_tso_show,
+ (cmdline_parse_inst_t *)&cmd_link_flow_control_set,
+ (cmdline_parse_inst_t *)&cmd_link_flow_control_set_rx,
+ (cmdline_parse_inst_t *)&cmd_link_flow_control_set_tx,
+ (cmdline_parse_inst_t *)&cmd_link_flow_control_set_hw,
+ (cmdline_parse_inst_t *)&cmd_link_flow_control_set_lw,
+ (cmdline_parse_inst_t *)&cmd_link_flow_control_set_pt,
+ (cmdline_parse_inst_t *)&cmd_link_flow_control_set_xon,
+ (cmdline_parse_inst_t *)&cmd_link_flow_control_set_macfwd,
+ (cmdline_parse_inst_t *)&cmd_link_flow_control_set_autoneg,
+ (cmdline_parse_inst_t *)&cmd_priority_flow_control_set,
+ (cmdline_parse_inst_t *)&cmd_config_dcb,
+ (cmdline_parse_inst_t *)&cmd_read_reg,
+ (cmdline_parse_inst_t *)&cmd_read_reg_bit_field,
+ (cmdline_parse_inst_t *)&cmd_read_reg_bit,
+ (cmdline_parse_inst_t *)&cmd_write_reg,
+ (cmdline_parse_inst_t *)&cmd_write_reg_bit_field,
+ (cmdline_parse_inst_t *)&cmd_write_reg_bit,
+ (cmdline_parse_inst_t *)&cmd_read_rxd_txd,
+ (cmdline_parse_inst_t *)&cmd_stop,
+ (cmdline_parse_inst_t *)&cmd_mac_addr,
+ (cmdline_parse_inst_t *)&cmd_set_qmap,
+ (cmdline_parse_inst_t *)&cmd_operate_port,
+ (cmdline_parse_inst_t *)&cmd_operate_specific_port,
+ (cmdline_parse_inst_t *)&cmd_operate_attach_port,
+ (cmdline_parse_inst_t *)&cmd_operate_detach_port,
+ (cmdline_parse_inst_t *)&cmd_config_speed_all,
+ (cmdline_parse_inst_t *)&cmd_config_speed_specific,
+ (cmdline_parse_inst_t *)&cmd_config_rx_tx,
+ (cmdline_parse_inst_t *)&cmd_config_mtu,
+ (cmdline_parse_inst_t *)&cmd_config_max_pkt_len,
+ (cmdline_parse_inst_t *)&cmd_config_rx_mode_flag,
+ (cmdline_parse_inst_t *)&cmd_config_rss,
+ (cmdline_parse_inst_t *)&cmd_config_rxtx_queue,
+ (cmdline_parse_inst_t *)&cmd_config_txqflags,
+ (cmdline_parse_inst_t *)&cmd_config_rss_reta,
+ (cmdline_parse_inst_t *)&cmd_showport_reta,
+ (cmdline_parse_inst_t *)&cmd_config_burst,
+ (cmdline_parse_inst_t *)&cmd_config_thresh,
+ (cmdline_parse_inst_t *)&cmd_config_threshold,
+ (cmdline_parse_inst_t *)&cmd_set_uc_hash_filter,
+ (cmdline_parse_inst_t *)&cmd_set_uc_all_hash_filter,
+ (cmdline_parse_inst_t *)&cmd_vf_mac_addr_filter,
+ (cmdline_parse_inst_t *)&cmd_set_vf_macvlan_filter,
+ (cmdline_parse_inst_t *)&cmd_queue_rate_limit,
+ (cmdline_parse_inst_t *)&cmd_tunnel_filter,
+ (cmdline_parse_inst_t *)&cmd_tunnel_udp_config,
+ (cmdline_parse_inst_t *)&cmd_global_config,
+ (cmdline_parse_inst_t *)&cmd_set_mirror_mask,
+ (cmdline_parse_inst_t *)&cmd_set_mirror_link,
+ (cmdline_parse_inst_t *)&cmd_reset_mirror_rule,
+ (cmdline_parse_inst_t *)&cmd_showport_rss_hash,
+ (cmdline_parse_inst_t *)&cmd_showport_rss_hash_key,
+ (cmdline_parse_inst_t *)&cmd_config_rss_hash_key,
+ (cmdline_parse_inst_t *)&cmd_dump,
+ (cmdline_parse_inst_t *)&cmd_dump_one,
+ (cmdline_parse_inst_t *)&cmd_ethertype_filter,
+ (cmdline_parse_inst_t *)&cmd_syn_filter,
+ (cmdline_parse_inst_t *)&cmd_2tuple_filter,
+ (cmdline_parse_inst_t *)&cmd_5tuple_filter,
+ (cmdline_parse_inst_t *)&cmd_flex_filter,
+ (cmdline_parse_inst_t *)&cmd_add_del_ip_flow_director,
+ (cmdline_parse_inst_t *)&cmd_add_del_udp_flow_director,
+ (cmdline_parse_inst_t *)&cmd_add_del_sctp_flow_director,
+ (cmdline_parse_inst_t *)&cmd_add_del_l2_flow_director,
+ (cmdline_parse_inst_t *)&cmd_add_del_mac_vlan_flow_director,
+ (cmdline_parse_inst_t *)&cmd_add_del_tunnel_flow_director,
+ (cmdline_parse_inst_t *)&cmd_flush_flow_director,
+ (cmdline_parse_inst_t *)&cmd_set_flow_director_ip_mask,
+ (cmdline_parse_inst_t *)&cmd_set_flow_director_mac_vlan_mask,
+ (cmdline_parse_inst_t *)&cmd_set_flow_director_tunnel_mask,
+ (cmdline_parse_inst_t *)&cmd_set_flow_director_flex_mask,
+ (cmdline_parse_inst_t *)&cmd_set_flow_director_flex_payload,
+ (cmdline_parse_inst_t *)&cmd_get_sym_hash_ena_per_port,
+ (cmdline_parse_inst_t *)&cmd_set_sym_hash_ena_per_port,
+ (cmdline_parse_inst_t *)&cmd_get_hash_global_config,
+ (cmdline_parse_inst_t *)&cmd_set_hash_global_config,
+ (cmdline_parse_inst_t *)&cmd_set_hash_input_set,
+ (cmdline_parse_inst_t *)&cmd_set_fdir_input_set,
+ (cmdline_parse_inst_t *)&cmd_flow,
+ (cmdline_parse_inst_t *)&cmd_mcast_addr,
+ (cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_all,
+ (cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_specific,
+ (cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_all,
+ (cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_specific,
+ (cmdline_parse_inst_t *)&cmd_config_e_tag_insertion_en,
+ (cmdline_parse_inst_t *)&cmd_config_e_tag_insertion_dis,
+ (cmdline_parse_inst_t *)&cmd_config_e_tag_stripping_en_dis,
+ (cmdline_parse_inst_t *)&cmd_config_e_tag_forwarding_en_dis,
+ (cmdline_parse_inst_t *)&cmd_config_e_tag_filter_add,
+ (cmdline_parse_inst_t *)&cmd_config_e_tag_filter_del,
+ (cmdline_parse_inst_t *)&cmd_set_vf_vlan_anti_spoof,
+ (cmdline_parse_inst_t *)&cmd_set_vf_mac_anti_spoof,
+ (cmdline_parse_inst_t *)&cmd_set_vf_vlan_stripq,
+ (cmdline_parse_inst_t *)&cmd_set_vf_vlan_insert,
+ (cmdline_parse_inst_t *)&cmd_set_tx_loopback,
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ (cmdline_parse_inst_t *)&cmd_set_all_queues_drop_en,
+ (cmdline_parse_inst_t *)&cmd_set_vf_split_drop_en,
+ (cmdline_parse_inst_t *)&cmd_set_macsec_offload_on,
+ (cmdline_parse_inst_t *)&cmd_set_macsec_offload_off,
+ (cmdline_parse_inst_t *)&cmd_set_macsec_sc,
+ (cmdline_parse_inst_t *)&cmd_set_macsec_sa,
+ (cmdline_parse_inst_t *)&cmd_set_vf_rxmode,
+ (cmdline_parse_inst_t *)&cmd_set_vf_traffic,
+ (cmdline_parse_inst_t *)&cmd_vf_rate_limit,
+#endif
+ (cmdline_parse_inst_t *)&cmd_vf_rxvlan_filter,
+ (cmdline_parse_inst_t *)&cmd_set_vf_mac_addr,
+ (cmdline_parse_inst_t *)&cmd_set_vf_promisc,
+ (cmdline_parse_inst_t *)&cmd_set_vf_allmulti,
+ (cmdline_parse_inst_t *)&cmd_set_vf_broadcast,
+ (cmdline_parse_inst_t *)&cmd_set_vf_vlan_tag,
+ (cmdline_parse_inst_t *)&cmd_vf_max_bw,
+ (cmdline_parse_inst_t *)&cmd_vf_tc_min_bw,
+ (cmdline_parse_inst_t *)&cmd_vf_tc_max_bw,
+ (cmdline_parse_inst_t *)&cmd_strict_link_prio,
+ (cmdline_parse_inst_t *)&cmd_tc_min_bw,
+ (cmdline_parse_inst_t *)&cmd_ddp_add,
+ (cmdline_parse_inst_t *)&cmd_ddp_get_list,
+ (cmdline_parse_inst_t *)&cmd_show_vf_stats,
+ (cmdline_parse_inst_t *)&cmd_clear_vf_stats,
+ (cmdline_parse_inst_t *)&cmd_ptype_mapping_get,
+ (cmdline_parse_inst_t *)&cmd_ptype_mapping_replace,
+ (cmdline_parse_inst_t *)&cmd_ptype_mapping_reset,
+ (cmdline_parse_inst_t *)&cmd_ptype_mapping_update,
+ NULL,
+};
+
+/* read cmdline commands from file */
+void
+cmdline_read_from_file(const char *filename)
+{
+ struct cmdline *cl;
+
+ cl = cmdline_file_new(main_ctx, "testpmd> ", filename);
+ if (cl == NULL) {
+ printf("Failed to create file based cmdline context: %s\n",
+ filename);
+ return;
+ }
+
+ cmdline_interact(cl);
+ cmdline_quit(cl);
+
+ cmdline_free(cl);
+
+ printf("Read CLI commands from %s\n", filename);
+}
+
+/* prompt function, called from main on MASTER lcore */
+void
+prompt(void)
+{
+ /* initialize non-constant commands */
+ cmd_set_fwd_mode_init();
+ cmd_set_fwd_retry_mode_init();
+
+ testpmd_cl = cmdline_stdin_new(main_ctx, "testpmd> ");
+ if (testpmd_cl == NULL)
+ return;
+ cmdline_interact(testpmd_cl);
+ cmdline_stdin_exit(testpmd_cl);
+}
+
+void
+prompt_exit(void)
+{
+ if (testpmd_cl != NULL)
+ cmdline_quit(testpmd_cl);
+}
+
+static void
+cmd_reconfig_device_queue(portid_t id, uint8_t dev, uint8_t queue)
+{
+ if (id == (portid_t)RTE_PORT_ALL) {
+ portid_t pid;
+
+ RTE_ETH_FOREACH_DEV(pid) {
+ /* check if need_reconfig has been set to 1 */
+ if (ports[pid].need_reconfig == 0)
+ ports[pid].need_reconfig = dev;
+ /* check if need_reconfig_queues has been set to 1 */
+ if (ports[pid].need_reconfig_queues == 0)
+ ports[pid].need_reconfig_queues = queue;
+ }
+ } else if (!port_id_is_invalid(id, DISABLED_WARN)) {
+ /* check if need_reconfig has been set to 1 */
+ if (ports[id].need_reconfig == 0)
+ ports[id].need_reconfig = dev;
+ /* check if need_reconfig_queues has been set to 1 */
+ if (ports[id].need_reconfig_queues == 0)
+ ports[id].need_reconfig_queues = queue;
+ }
+}
diff --git a/src/seastar/dpdk/app/test-pmd/cmdline_flow.c b/src/seastar/dpdk/app/test-pmd/cmdline_flow.c
new file mode 100644
index 00000000..0fd69f90
--- /dev/null
+++ b/src/seastar/dpdk/app/test-pmd/cmdline_flow.c
@@ -0,0 +1,2812 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright 2016 6WIND S.A.
+ * Copyright 2016 Mellanox.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of 6WIND S.A. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <ctype.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+
+#include <rte_common.h>
+#include <rte_ethdev.h>
+#include <rte_byteorder.h>
+#include <cmdline_parse.h>
+#include <cmdline_parse_etheraddr.h>
+#include <rte_flow.h>
+
+#include "testpmd.h"
+
+/** Parser token indices. */
+enum index {
+ /* Special tokens. */
+ ZERO = 0,
+ END,
+
+ /* Common tokens. */
+ INTEGER,
+ UNSIGNED,
+ PREFIX,
+ BOOLEAN,
+ STRING,
+ MAC_ADDR,
+ IPV4_ADDR,
+ IPV6_ADDR,
+ RULE_ID,
+ PORT_ID,
+ GROUP_ID,
+ PRIORITY_LEVEL,
+
+ /* Top-level command. */
+ FLOW,
+
+ /* Sub-level commands. */
+ VALIDATE,
+ CREATE,
+ DESTROY,
+ FLUSH,
+ QUERY,
+ LIST,
+
+ /* Destroy arguments. */
+ DESTROY_RULE,
+
+ /* Query arguments. */
+ QUERY_ACTION,
+
+ /* List arguments. */
+ LIST_GROUP,
+
+ /* Validate/create arguments. */
+ GROUP,
+ PRIORITY,
+ INGRESS,
+ EGRESS,
+
+ /* Validate/create pattern. */
+ PATTERN,
+ ITEM_PARAM_IS,
+ ITEM_PARAM_SPEC,
+ ITEM_PARAM_LAST,
+ ITEM_PARAM_MASK,
+ ITEM_PARAM_PREFIX,
+ ITEM_NEXT,
+ ITEM_END,
+ ITEM_VOID,
+ ITEM_INVERT,
+ ITEM_ANY,
+ ITEM_ANY_NUM,
+ ITEM_PF,
+ ITEM_VF,
+ ITEM_VF_ID,
+ ITEM_PORT,
+ ITEM_PORT_INDEX,
+ ITEM_RAW,
+ ITEM_RAW_RELATIVE,
+ ITEM_RAW_SEARCH,
+ ITEM_RAW_OFFSET,
+ ITEM_RAW_LIMIT,
+ ITEM_RAW_PATTERN,
+ ITEM_ETH,
+ ITEM_ETH_DST,
+ ITEM_ETH_SRC,
+ ITEM_ETH_TYPE,
+ ITEM_VLAN,
+ ITEM_VLAN_TPID,
+ ITEM_VLAN_TCI,
+ ITEM_VLAN_PCP,
+ ITEM_VLAN_DEI,
+ ITEM_VLAN_VID,
+ ITEM_IPV4,
+ ITEM_IPV4_TOS,
+ ITEM_IPV4_TTL,
+ ITEM_IPV4_PROTO,
+ ITEM_IPV4_SRC,
+ ITEM_IPV4_DST,
+ ITEM_IPV6,
+ ITEM_IPV6_TC,
+ ITEM_IPV6_FLOW,
+ ITEM_IPV6_PROTO,
+ ITEM_IPV6_HOP,
+ ITEM_IPV6_SRC,
+ ITEM_IPV6_DST,
+ ITEM_ICMP,
+ ITEM_ICMP_TYPE,
+ ITEM_ICMP_CODE,
+ ITEM_UDP,
+ ITEM_UDP_SRC,
+ ITEM_UDP_DST,
+ ITEM_TCP,
+ ITEM_TCP_SRC,
+ ITEM_TCP_DST,
+ ITEM_SCTP,
+ ITEM_SCTP_SRC,
+ ITEM_SCTP_DST,
+ ITEM_SCTP_TAG,
+ ITEM_SCTP_CKSUM,
+ ITEM_VXLAN,
+ ITEM_VXLAN_VNI,
+ ITEM_E_TAG,
+ ITEM_E_TAG_GRP_ECID_B,
+ ITEM_NVGRE,
+ ITEM_NVGRE_TNI,
+ ITEM_MPLS,
+ ITEM_MPLS_LABEL,
+ ITEM_GRE,
+ ITEM_GRE_PROTO,
+
+ /* Validate/create actions. */
+ ACTIONS,
+ ACTION_NEXT,
+ ACTION_END,
+ ACTION_VOID,
+ ACTION_PASSTHRU,
+ ACTION_MARK,
+ ACTION_MARK_ID,
+ ACTION_FLAG,
+ ACTION_QUEUE,
+ ACTION_QUEUE_INDEX,
+ ACTION_DROP,
+ ACTION_COUNT,
+ ACTION_DUP,
+ ACTION_DUP_INDEX,
+ ACTION_RSS,
+ ACTION_RSS_QUEUES,
+ ACTION_RSS_QUEUE,
+ ACTION_PF,
+ ACTION_VF,
+ ACTION_VF_ORIGINAL,
+ ACTION_VF_ID,
+};
+
+/** Size of pattern[] field in struct rte_flow_item_raw. */
+#define ITEM_RAW_PATTERN_SIZE 36
+
+/** Storage size for struct rte_flow_item_raw including pattern. */
+#define ITEM_RAW_SIZE \
+ (offsetof(struct rte_flow_item_raw, pattern) + ITEM_RAW_PATTERN_SIZE)
+
+/** Number of queue[] entries in struct rte_flow_action_rss. */
+#define ACTION_RSS_NUM 32
+
+/** Storage size for struct rte_flow_action_rss including queues. */
+#define ACTION_RSS_SIZE \
+ (offsetof(struct rte_flow_action_rss, queue) + \
+ sizeof(*((struct rte_flow_action_rss *)0)->queue) * ACTION_RSS_NUM)
+
+/** Maximum number of subsequent tokens and arguments on the stack. */
+#define CTX_STACK_SIZE 16
+
+/** Parser context. */
+struct context {
+ /** Stack of subsequent token lists to process. */
+ const enum index *next[CTX_STACK_SIZE];
+ /** Arguments for stacked tokens. */
+ const void *args[CTX_STACK_SIZE];
+ enum index curr; /**< Current token index. */
+ enum index prev; /**< Index of the last token seen. */
+ int next_num; /**< Number of entries in next[]. */
+ int args_num; /**< Number of entries in args[]. */
+ uint32_t reparse:1; /**< Start over from the beginning. */
+ uint32_t eol:1; /**< EOL has been detected. */
+ uint32_t last:1; /**< No more arguments. */
+ uint16_t port; /**< Current port ID (for completions). */
+ uint32_t objdata; /**< Object-specific data. */
+ void *object; /**< Address of current object for relative offsets. */
+ void *objmask; /**< Object a full mask must be written to. */
+};
+
+/** Token argument. */
+struct arg {
+ uint32_t hton:1; /**< Use network byte ordering. */
+ uint32_t sign:1; /**< Value is signed. */
+ uint32_t offset; /**< Relative offset from ctx->object. */
+ uint32_t size; /**< Field size. */
+ const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
+};
+
+/** Parser token definition. */
+struct token {
+ /** Type displayed during completion (defaults to "TOKEN"). */
+ const char *type;
+ /** Help displayed during completion (defaults to token name). */
+ const char *help;
+ /** Private data used by parser functions. */
+ const void *priv;
+ /**
+ * Lists of subsequent tokens to push on the stack. Each call to the
+ * parser consumes the last entry of that stack.
+ */
+ const enum index *const *next;
+ /** Arguments stack for subsequent tokens that need them. */
+ const struct arg *const *args;
+ /**
+ * Token-processing callback, returns -1 in case of error, the
+ * length of the matched string otherwise. If NULL, attempts to
+ * match the token name.
+ *
+ * If buf is not NULL, the result should be stored in it according
+ * to context. An error is returned if not large enough.
+ */
+ int (*call)(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size);
+ /**
+ * Callback that provides possible values for this token, used for
+ * completion. Returns -1 in case of error, the number of possible
+ * values otherwise. If NULL, the token name is used.
+ *
+ * If buf is not NULL, entry index ent is written to buf and the
+ * full length of the entry is returned (same behavior as
+ * snprintf()).
+ */
+ int (*comp)(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size);
+ /** Mandatory token name, no default value. */
+ const char *name;
+};
+
+/** Static initializer for the next field. */
+#define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
+
+/** Static initializer for a NEXT() entry. */
+#define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
+
+/** Static initializer for the args field. */
+#define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
+
+/** Static initializer for ARGS() to target a field. */
+#define ARGS_ENTRY(s, f) \
+ (&(const struct arg){ \
+ .offset = offsetof(s, f), \
+ .size = sizeof(((s *)0)->f), \
+ })
+
+/** Static initializer for ARGS() to target a bit-field. */
+#define ARGS_ENTRY_BF(s, f, b) \
+ (&(const struct arg){ \
+ .size = sizeof(s), \
+ .mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
+ })
+
+/** Static initializer for ARGS() to target an arbitrary bit-mask. */
+#define ARGS_ENTRY_MASK(s, f, m) \
+ (&(const struct arg){ \
+ .offset = offsetof(s, f), \
+ .size = sizeof(((s *)0)->f), \
+ .mask = (const void *)(m), \
+ })
+
+/** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
+#define ARGS_ENTRY_MASK_HTON(s, f, m) \
+ (&(const struct arg){ \
+ .hton = 1, \
+ .offset = offsetof(s, f), \
+ .size = sizeof(((s *)0)->f), \
+ .mask = (const void *)(m), \
+ })
+
+/** Static initializer for ARGS() to target a pointer. */
+#define ARGS_ENTRY_PTR(s, f) \
+ (&(const struct arg){ \
+ .size = sizeof(*((s *)0)->f), \
+ })
+
+/** Static initializer for ARGS() with arbitrary size. */
+#define ARGS_ENTRY_USZ(s, f, sz) \
+ (&(const struct arg){ \
+ .offset = offsetof(s, f), \
+ .size = (sz), \
+ })
+
+/** Same as ARGS_ENTRY() using network byte ordering. */
+#define ARGS_ENTRY_HTON(s, f) \
+ (&(const struct arg){ \
+ .hton = 1, \
+ .offset = offsetof(s, f), \
+ .size = sizeof(((s *)0)->f), \
+ })
+
+/** Parser output buffer layout expected by cmd_flow_parsed(). */
+struct buffer {
+ enum index command; /**< Flow command. */
+ uint16_t port; /**< Affected port ID. */
+ union {
+ struct {
+ struct rte_flow_attr attr;
+ struct rte_flow_item *pattern;
+ struct rte_flow_action *actions;
+ uint32_t pattern_n;
+ uint32_t actions_n;
+ uint8_t *data;
+ } vc; /**< Validate/create arguments. */
+ struct {
+ uint32_t *rule;
+ uint32_t rule_n;
+ } destroy; /**< Destroy arguments. */
+ struct {
+ uint32_t rule;
+ enum rte_flow_action_type action;
+ } query; /**< Query arguments. */
+ struct {
+ uint32_t *group;
+ uint32_t group_n;
+ } list; /**< List arguments. */
+ } args; /**< Command arguments. */
+};
+
+/** Private data for pattern items. */
+struct parse_item_priv {
+ enum rte_flow_item_type type; /**< Item type. */
+ uint32_t size; /**< Size of item specification structure. */
+};
+
+#define PRIV_ITEM(t, s) \
+ (&(const struct parse_item_priv){ \
+ .type = RTE_FLOW_ITEM_TYPE_ ## t, \
+ .size = s, \
+ })
+
+/** Private data for actions. */
+struct parse_action_priv {
+ enum rte_flow_action_type type; /**< Action type. */
+ uint32_t size; /**< Size of action configuration structure. */
+};
+
+#define PRIV_ACTION(t, s) \
+ (&(const struct parse_action_priv){ \
+ .type = RTE_FLOW_ACTION_TYPE_ ## t, \
+ .size = s, \
+ })
+
+static const enum index next_vc_attr[] = {
+ GROUP,
+ PRIORITY,
+ INGRESS,
+ EGRESS,
+ PATTERN,
+ ZERO,
+};
+
+static const enum index next_destroy_attr[] = {
+ DESTROY_RULE,
+ END,
+ ZERO,
+};
+
+static const enum index next_list_attr[] = {
+ LIST_GROUP,
+ END,
+ ZERO,
+};
+
+static const enum index item_param[] = {
+ ITEM_PARAM_IS,
+ ITEM_PARAM_SPEC,
+ ITEM_PARAM_LAST,
+ ITEM_PARAM_MASK,
+ ITEM_PARAM_PREFIX,
+ ZERO,
+};
+
+static const enum index next_item[] = {
+ ITEM_END,
+ ITEM_VOID,
+ ITEM_INVERT,
+ ITEM_ANY,
+ ITEM_PF,
+ ITEM_VF,
+ ITEM_PORT,
+ ITEM_RAW,
+ ITEM_ETH,
+ ITEM_VLAN,
+ ITEM_IPV4,
+ ITEM_IPV6,
+ ITEM_ICMP,
+ ITEM_UDP,
+ ITEM_TCP,
+ ITEM_SCTP,
+ ITEM_VXLAN,
+ ITEM_E_TAG,
+ ITEM_NVGRE,
+ ITEM_MPLS,
+ ITEM_GRE,
+ ZERO,
+};
+
+static const enum index item_any[] = {
+ ITEM_ANY_NUM,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_vf[] = {
+ ITEM_VF_ID,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_port[] = {
+ ITEM_PORT_INDEX,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_raw[] = {
+ ITEM_RAW_RELATIVE,
+ ITEM_RAW_SEARCH,
+ ITEM_RAW_OFFSET,
+ ITEM_RAW_LIMIT,
+ ITEM_RAW_PATTERN,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_eth[] = {
+ ITEM_ETH_DST,
+ ITEM_ETH_SRC,
+ ITEM_ETH_TYPE,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_vlan[] = {
+ ITEM_VLAN_TPID,
+ ITEM_VLAN_TCI,
+ ITEM_VLAN_PCP,
+ ITEM_VLAN_DEI,
+ ITEM_VLAN_VID,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_ipv4[] = {
+ ITEM_IPV4_TOS,
+ ITEM_IPV4_TTL,
+ ITEM_IPV4_PROTO,
+ ITEM_IPV4_SRC,
+ ITEM_IPV4_DST,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_ipv6[] = {
+ ITEM_IPV6_TC,
+ ITEM_IPV6_FLOW,
+ ITEM_IPV6_PROTO,
+ ITEM_IPV6_HOP,
+ ITEM_IPV6_SRC,
+ ITEM_IPV6_DST,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_icmp[] = {
+ ITEM_ICMP_TYPE,
+ ITEM_ICMP_CODE,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_udp[] = {
+ ITEM_UDP_SRC,
+ ITEM_UDP_DST,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_tcp[] = {
+ ITEM_TCP_SRC,
+ ITEM_TCP_DST,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_sctp[] = {
+ ITEM_SCTP_SRC,
+ ITEM_SCTP_DST,
+ ITEM_SCTP_TAG,
+ ITEM_SCTP_CKSUM,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_vxlan[] = {
+ ITEM_VXLAN_VNI,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_e_tag[] = {
+ ITEM_E_TAG_GRP_ECID_B,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_nvgre[] = {
+ ITEM_NVGRE_TNI,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_mpls[] = {
+ ITEM_MPLS_LABEL,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_gre[] = {
+ ITEM_GRE_PROTO,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index next_action[] = {
+ ACTION_END,
+ ACTION_VOID,
+ ACTION_PASSTHRU,
+ ACTION_MARK,
+ ACTION_FLAG,
+ ACTION_QUEUE,
+ ACTION_DROP,
+ ACTION_COUNT,
+ ACTION_DUP,
+ ACTION_RSS,
+ ACTION_PF,
+ ACTION_VF,
+ ZERO,
+};
+
+static const enum index action_mark[] = {
+ ACTION_MARK_ID,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_queue[] = {
+ ACTION_QUEUE_INDEX,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_dup[] = {
+ ACTION_DUP_INDEX,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_rss[] = {
+ ACTION_RSS_QUEUES,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_vf[] = {
+ ACTION_VF_ORIGINAL,
+ ACTION_VF_ID,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static int parse_init(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_vc(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_vc_spec(struct context *, const struct token *,
+ const char *, unsigned int, void *, unsigned int);
+static int parse_vc_conf(struct context *, const struct token *,
+ const char *, unsigned int, void *, unsigned int);
+static int parse_vc_action_rss_queue(struct context *, const struct token *,
+ const char *, unsigned int, void *,
+ unsigned int);
+static int parse_destroy(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_flush(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_query(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_action(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_list(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_int(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_prefix(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_boolean(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_string(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_mac_addr(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_ipv4_addr(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_ipv6_addr(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_port(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int comp_none(struct context *, const struct token *,
+ unsigned int, char *, unsigned int);
+static int comp_boolean(struct context *, const struct token *,
+ unsigned int, char *, unsigned int);
+static int comp_action(struct context *, const struct token *,
+ unsigned int, char *, unsigned int);
+static int comp_port(struct context *, const struct token *,
+ unsigned int, char *, unsigned int);
+static int comp_rule_id(struct context *, const struct token *,
+ unsigned int, char *, unsigned int);
+static int comp_vc_action_rss_queue(struct context *, const struct token *,
+ unsigned int, char *, unsigned int);
+
+/** Token definitions. */
+static const struct token token_list[] = {
+ /* Special tokens. */
+ [ZERO] = {
+ .name = "ZERO",
+ .help = "null entry, abused as the entry point",
+ .next = NEXT(NEXT_ENTRY(FLOW)),
+ },
+ [END] = {
+ .name = "",
+ .type = "RETURN",
+ .help = "command may end here",
+ },
+ /* Common tokens. */
+ [INTEGER] = {
+ .name = "{int}",
+ .type = "INTEGER",
+ .help = "integer value",
+ .call = parse_int,
+ .comp = comp_none,
+ },
+ [UNSIGNED] = {
+ .name = "{unsigned}",
+ .type = "UNSIGNED",
+ .help = "unsigned integer value",
+ .call = parse_int,
+ .comp = comp_none,
+ },
+ [PREFIX] = {
+ .name = "{prefix}",
+ .type = "PREFIX",
+ .help = "prefix length for bit-mask",
+ .call = parse_prefix,
+ .comp = comp_none,
+ },
+ [BOOLEAN] = {
+ .name = "{boolean}",
+ .type = "BOOLEAN",
+ .help = "any boolean value",
+ .call = parse_boolean,
+ .comp = comp_boolean,
+ },
+ [STRING] = {
+ .name = "{string}",
+ .type = "STRING",
+ .help = "fixed string",
+ .call = parse_string,
+ .comp = comp_none,
+ },
+ [MAC_ADDR] = {
+ .name = "{MAC address}",
+ .type = "MAC-48",
+ .help = "standard MAC address notation",
+ .call = parse_mac_addr,
+ .comp = comp_none,
+ },
+ [IPV4_ADDR] = {
+ .name = "{IPv4 address}",
+ .type = "IPV4 ADDRESS",
+ .help = "standard IPv4 address notation",
+ .call = parse_ipv4_addr,
+ .comp = comp_none,
+ },
+ [IPV6_ADDR] = {
+ .name = "{IPv6 address}",
+ .type = "IPV6 ADDRESS",
+ .help = "standard IPv6 address notation",
+ .call = parse_ipv6_addr,
+ .comp = comp_none,
+ },
+ [RULE_ID] = {
+ .name = "{rule id}",
+ .type = "RULE ID",
+ .help = "rule identifier",
+ .call = parse_int,
+ .comp = comp_rule_id,
+ },
+ [PORT_ID] = {
+ .name = "{port_id}",
+ .type = "PORT ID",
+ .help = "port identifier",
+ .call = parse_port,
+ .comp = comp_port,
+ },
+ [GROUP_ID] = {
+ .name = "{group_id}",
+ .type = "GROUP ID",
+ .help = "group identifier",
+ .call = parse_int,
+ .comp = comp_none,
+ },
+ [PRIORITY_LEVEL] = {
+ .name = "{level}",
+ .type = "PRIORITY",
+ .help = "priority level",
+ .call = parse_int,
+ .comp = comp_none,
+ },
+ /* Top-level command. */
+ [FLOW] = {
+ .name = "flow",
+ .type = "{command} {port_id} [{arg} [...]]",
+ .help = "manage ingress/egress flow rules",
+ .next = NEXT(NEXT_ENTRY
+ (VALIDATE,
+ CREATE,
+ DESTROY,
+ FLUSH,
+ LIST,
+ QUERY)),
+ .call = parse_init,
+ },
+ /* Sub-level commands. */
+ [VALIDATE] = {
+ .name = "validate",
+ .help = "check whether a flow rule can be created",
+ .next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+ .call = parse_vc,
+ },
+ [CREATE] = {
+ .name = "create",
+ .help = "create a flow rule",
+ .next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+ .call = parse_vc,
+ },
+ [DESTROY] = {
+ .name = "destroy",
+ .help = "destroy specific flow rules",
+ .next = NEXT(NEXT_ENTRY(DESTROY_RULE), NEXT_ENTRY(PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+ .call = parse_destroy,
+ },
+ [FLUSH] = {
+ .name = "flush",
+ .help = "destroy all flow rules",
+ .next = NEXT(NEXT_ENTRY(PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+ .call = parse_flush,
+ },
+ [QUERY] = {
+ .name = "query",
+ .help = "query an existing flow rule",
+ .next = NEXT(NEXT_ENTRY(QUERY_ACTION),
+ NEXT_ENTRY(RULE_ID),
+ NEXT_ENTRY(PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action),
+ ARGS_ENTRY(struct buffer, args.query.rule),
+ ARGS_ENTRY(struct buffer, port)),
+ .call = parse_query,
+ },
+ [LIST] = {
+ .name = "list",
+ .help = "list existing flow rules",
+ .next = NEXT(next_list_attr, NEXT_ENTRY(PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+ .call = parse_list,
+ },
+ /* Destroy arguments. */
+ [DESTROY_RULE] = {
+ .name = "rule",
+ .help = "specify a rule identifier",
+ .next = NEXT(next_destroy_attr, NEXT_ENTRY(RULE_ID)),
+ .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
+ .call = parse_destroy,
+ },
+ /* Query arguments. */
+ [QUERY_ACTION] = {
+ .name = "{action}",
+ .type = "ACTION",
+ .help = "action to query, must be part of the rule",
+ .call = parse_action,
+ .comp = comp_action,
+ },
+ /* List arguments. */
+ [LIST_GROUP] = {
+ .name = "group",
+ .help = "specify a group",
+ .next = NEXT(next_list_attr, NEXT_ENTRY(GROUP_ID)),
+ .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
+ .call = parse_list,
+ },
+ /* Validate/create attributes. */
+ [GROUP] = {
+ .name = "group",
+ .help = "specify a group",
+ .next = NEXT(next_vc_attr, NEXT_ENTRY(GROUP_ID)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
+ .call = parse_vc,
+ },
+ [PRIORITY] = {
+ .name = "priority",
+ .help = "specify a priority level",
+ .next = NEXT(next_vc_attr, NEXT_ENTRY(PRIORITY_LEVEL)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
+ .call = parse_vc,
+ },
+ [INGRESS] = {
+ .name = "ingress",
+ .help = "affect rule to ingress",
+ .next = NEXT(next_vc_attr),
+ .call = parse_vc,
+ },
+ [EGRESS] = {
+ .name = "egress",
+ .help = "affect rule to egress",
+ .next = NEXT(next_vc_attr),
+ .call = parse_vc,
+ },
+ /* Validate/create pattern. */
+ [PATTERN] = {
+ .name = "pattern",
+ .help = "submit a list of pattern items",
+ .next = NEXT(next_item),
+ .call = parse_vc,
+ },
+ [ITEM_PARAM_IS] = {
+ .name = "is",
+ .help = "match value perfectly (with full bit-mask)",
+ .call = parse_vc_spec,
+ },
+ [ITEM_PARAM_SPEC] = {
+ .name = "spec",
+ .help = "match value according to configured bit-mask",
+ .call = parse_vc_spec,
+ },
+ [ITEM_PARAM_LAST] = {
+ .name = "last",
+ .help = "specify upper bound to establish a range",
+ .call = parse_vc_spec,
+ },
+ [ITEM_PARAM_MASK] = {
+ .name = "mask",
+ .help = "specify bit-mask with relevant bits set to one",
+ .call = parse_vc_spec,
+ },
+ [ITEM_PARAM_PREFIX] = {
+ .name = "prefix",
+ .help = "generate bit-mask from a prefix length",
+ .call = parse_vc_spec,
+ },
+ [ITEM_NEXT] = {
+ .name = "/",
+ .help = "specify next pattern item",
+ .next = NEXT(next_item),
+ },
+ [ITEM_END] = {
+ .name = "end",
+ .help = "end list of pattern items",
+ .priv = PRIV_ITEM(END, 0),
+ .next = NEXT(NEXT_ENTRY(ACTIONS)),
+ .call = parse_vc,
+ },
+ [ITEM_VOID] = {
+ .name = "void",
+ .help = "no-op pattern item",
+ .priv = PRIV_ITEM(VOID, 0),
+ .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
+ .call = parse_vc,
+ },
+ [ITEM_INVERT] = {
+ .name = "invert",
+ .help = "perform actions when pattern does not match",
+ .priv = PRIV_ITEM(INVERT, 0),
+ .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
+ .call = parse_vc,
+ },
+ [ITEM_ANY] = {
+ .name = "any",
+ .help = "match any protocol for the current layer",
+ .priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
+ .next = NEXT(item_any),
+ .call = parse_vc,
+ },
+ [ITEM_ANY_NUM] = {
+ .name = "num",
+ .help = "number of layers covered",
+ .next = NEXT(item_any, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
+ },
+ [ITEM_PF] = {
+ .name = "pf",
+ .help = "match packets addressed to the physical function",
+ .priv = PRIV_ITEM(PF, 0),
+ .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
+ .call = parse_vc,
+ },
+ [ITEM_VF] = {
+ .name = "vf",
+ .help = "match packets addressed to a virtual function ID",
+ .priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)),
+ .next = NEXT(item_vf),
+ .call = parse_vc,
+ },
+ [ITEM_VF_ID] = {
+ .name = "id",
+ .help = "destination VF ID",
+ .next = NEXT(item_vf, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)),
+ },
+ [ITEM_PORT] = {
+ .name = "port",
+ .help = "device-specific physical port index to use",
+ .priv = PRIV_ITEM(PORT, sizeof(struct rte_flow_item_port)),
+ .next = NEXT(item_port),
+ .call = parse_vc,
+ },
+ [ITEM_PORT_INDEX] = {
+ .name = "index",
+ .help = "physical port index",
+ .next = NEXT(item_port, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_item_port, index)),
+ },
+ [ITEM_RAW] = {
+ .name = "raw",
+ .help = "match an arbitrary byte string",
+ .priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
+ .next = NEXT(item_raw),
+ .call = parse_vc,
+ },
+ [ITEM_RAW_RELATIVE] = {
+ .name = "relative",
+ .help = "look for pattern after the previous item",
+ .next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param),
+ .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
+ relative, 1)),
+ },
+ [ITEM_RAW_SEARCH] = {
+ .name = "search",
+ .help = "search pattern from offset (see also limit)",
+ .next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param),
+ .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
+ search, 1)),
+ },
+ [ITEM_RAW_OFFSET] = {
+ .name = "offset",
+ .help = "absolute or relative offset for pattern",
+ .next = NEXT(item_raw, NEXT_ENTRY(INTEGER), item_param),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
+ },
+ [ITEM_RAW_LIMIT] = {
+ .name = "limit",
+ .help = "search area limit for start of pattern",
+ .next = NEXT(item_raw, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
+ },
+ [ITEM_RAW_PATTERN] = {
+ .name = "pattern",
+ .help = "byte string to look for",
+ .next = NEXT(item_raw,
+ NEXT_ENTRY(STRING),
+ NEXT_ENTRY(ITEM_PARAM_IS,
+ ITEM_PARAM_SPEC,
+ ITEM_PARAM_MASK)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, length),
+ ARGS_ENTRY_USZ(struct rte_flow_item_raw,
+ pattern,
+ ITEM_RAW_PATTERN_SIZE)),
+ },
+ [ITEM_ETH] = {
+ .name = "eth",
+ .help = "match Ethernet header",
+ .priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
+ .next = NEXT(item_eth),
+ .call = parse_vc,
+ },
+ [ITEM_ETH_DST] = {
+ .name = "dst",
+ .help = "destination MAC",
+ .next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, dst)),
+ },
+ [ITEM_ETH_SRC] = {
+ .name = "src",
+ .help = "source MAC",
+ .next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, src)),
+ },
+ [ITEM_ETH_TYPE] = {
+ .name = "type",
+ .help = "EtherType",
+ .next = NEXT(item_eth, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)),
+ },
+ [ITEM_VLAN] = {
+ .name = "vlan",
+ .help = "match 802.1Q/ad VLAN tag",
+ .priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
+ .next = NEXT(item_vlan),
+ .call = parse_vc,
+ },
+ [ITEM_VLAN_TPID] = {
+ .name = "tpid",
+ .help = "tag protocol identifier",
+ .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tpid)),
+ },
+ [ITEM_VLAN_TCI] = {
+ .name = "tci",
+ .help = "tag control information",
+ .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)),
+ },
+ [ITEM_VLAN_PCP] = {
+ .name = "pcp",
+ .help = "priority code point",
+ .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
+ tci, "\xe0\x00")),
+ },
+ [ITEM_VLAN_DEI] = {
+ .name = "dei",
+ .help = "drop eligible indicator",
+ .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
+ tci, "\x10\x00")),
+ },
+ [ITEM_VLAN_VID] = {
+ .name = "vid",
+ .help = "VLAN identifier",
+ .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
+ tci, "\x0f\xff")),
+ },
+ [ITEM_IPV4] = {
+ .name = "ipv4",
+ .help = "match IPv4 header",
+ .priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
+ .next = NEXT(item_ipv4),
+ .call = parse_vc,
+ },
+ [ITEM_IPV4_TOS] = {
+ .name = "tos",
+ .help = "type of service",
+ .next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
+ hdr.type_of_service)),
+ },
+ [ITEM_IPV4_TTL] = {
+ .name = "ttl",
+ .help = "time to live",
+ .next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
+ hdr.time_to_live)),
+ },
+ [ITEM_IPV4_PROTO] = {
+ .name = "proto",
+ .help = "next protocol ID",
+ .next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
+ hdr.next_proto_id)),
+ },
+ [ITEM_IPV4_SRC] = {
+ .name = "src",
+ .help = "source address",
+ .next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
+ hdr.src_addr)),
+ },
+ [ITEM_IPV4_DST] = {
+ .name = "dst",
+ .help = "destination address",
+ .next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
+ hdr.dst_addr)),
+ },
+ [ITEM_IPV6] = {
+ .name = "ipv6",
+ .help = "match IPv6 header",
+ .priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
+ .next = NEXT(item_ipv6),
+ .call = parse_vc,
+ },
+ [ITEM_IPV6_TC] = {
+ .name = "tc",
+ .help = "traffic class",
+ .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
+ hdr.vtc_flow,
+ "\x0f\xf0\x00\x00")),
+ },
+ [ITEM_IPV6_FLOW] = {
+ .name = "flow",
+ .help = "flow label",
+ .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
+ hdr.vtc_flow,
+ "\x00\x0f\xff\xff")),
+ },
+ [ITEM_IPV6_PROTO] = {
+ .name = "proto",
+ .help = "protocol (next header)",
+ .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
+ hdr.proto)),
+ },
+ [ITEM_IPV6_HOP] = {
+ .name = "hop",
+ .help = "hop limit",
+ .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
+ hdr.hop_limits)),
+ },
+ [ITEM_IPV6_SRC] = {
+ .name = "src",
+ .help = "source address",
+ .next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
+ hdr.src_addr)),
+ },
+ [ITEM_IPV6_DST] = {
+ .name = "dst",
+ .help = "destination address",
+ .next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
+ hdr.dst_addr)),
+ },
+ [ITEM_ICMP] = {
+ .name = "icmp",
+ .help = "match ICMP header",
+ .priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
+ .next = NEXT(item_icmp),
+ .call = parse_vc,
+ },
+ [ITEM_ICMP_TYPE] = {
+ .name = "type",
+ .help = "ICMP packet type",
+ .next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
+ hdr.icmp_type)),
+ },
+ [ITEM_ICMP_CODE] = {
+ .name = "code",
+ .help = "ICMP packet code",
+ .next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
+ hdr.icmp_code)),
+ },
+ [ITEM_UDP] = {
+ .name = "udp",
+ .help = "match UDP header",
+ .priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
+ .next = NEXT(item_udp),
+ .call = parse_vc,
+ },
+ [ITEM_UDP_SRC] = {
+ .name = "src",
+ .help = "UDP source port",
+ .next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
+ hdr.src_port)),
+ },
+ [ITEM_UDP_DST] = {
+ .name = "dst",
+ .help = "UDP destination port",
+ .next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
+ hdr.dst_port)),
+ },
+ [ITEM_TCP] = {
+ .name = "tcp",
+ .help = "match TCP header",
+ .priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
+ .next = NEXT(item_tcp),
+ .call = parse_vc,
+ },
+ [ITEM_TCP_SRC] = {
+ .name = "src",
+ .help = "TCP source port",
+ .next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
+ hdr.src_port)),
+ },
+ [ITEM_TCP_DST] = {
+ .name = "dst",
+ .help = "TCP destination port",
+ .next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
+ hdr.dst_port)),
+ },
+ [ITEM_SCTP] = {
+ .name = "sctp",
+ .help = "match SCTP header",
+ .priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
+ .next = NEXT(item_sctp),
+ .call = parse_vc,
+ },
+ [ITEM_SCTP_SRC] = {
+ .name = "src",
+ .help = "SCTP source port",
+ .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
+ hdr.src_port)),
+ },
+ [ITEM_SCTP_DST] = {
+ .name = "dst",
+ .help = "SCTP destination port",
+ .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
+ hdr.dst_port)),
+ },
+ [ITEM_SCTP_TAG] = {
+ .name = "tag",
+ .help = "validation tag",
+ .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
+ hdr.tag)),
+ },
+ [ITEM_SCTP_CKSUM] = {
+ .name = "cksum",
+ .help = "checksum",
+ .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
+ hdr.cksum)),
+ },
+ [ITEM_VXLAN] = {
+ .name = "vxlan",
+ .help = "match VXLAN header",
+ .priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
+ .next = NEXT(item_vxlan),
+ .call = parse_vc,
+ },
+ [ITEM_VXLAN_VNI] = {
+ .name = "vni",
+ .help = "VXLAN identifier",
+ .next = NEXT(item_vxlan, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
+ },
+ [ITEM_E_TAG] = {
+ .name = "e_tag",
+ .help = "match E-Tag header",
+ .priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
+ .next = NEXT(item_e_tag),
+ .call = parse_vc,
+ },
+ [ITEM_E_TAG_GRP_ECID_B] = {
+ .name = "grp_ecid_b",
+ .help = "GRP and E-CID base",
+ .next = NEXT(item_e_tag, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
+ rsvd_grp_ecid_b,
+ "\x3f\xff")),
+ },
+ [ITEM_NVGRE] = {
+ .name = "nvgre",
+ .help = "match NVGRE header",
+ .priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
+ .next = NEXT(item_nvgre),
+ .call = parse_vc,
+ },
+ [ITEM_NVGRE_TNI] = {
+ .name = "tni",
+ .help = "virtual subnet ID",
+ .next = NEXT(item_nvgre, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
+ },
+ [ITEM_MPLS] = {
+ .name = "mpls",
+ .help = "match MPLS header",
+ .priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
+ .next = NEXT(item_mpls),
+ .call = parse_vc,
+ },
+ [ITEM_MPLS_LABEL] = {
+ .name = "label",
+ .help = "MPLS label",
+ .next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
+ label_tc_s,
+ "\xff\xff\xf0")),
+ },
+ [ITEM_GRE] = {
+ .name = "gre",
+ .help = "match GRE header",
+ .priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
+ .next = NEXT(item_gre),
+ .call = parse_vc,
+ },
+ [ITEM_GRE_PROTO] = {
+ .name = "protocol",
+ .help = "GRE protocol type",
+ .next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
+ protocol)),
+ },
+ /* Validate/create actions. */
+ [ACTIONS] = {
+ .name = "actions",
+ .help = "submit a list of associated actions",
+ .next = NEXT(next_action),
+ .call = parse_vc,
+ },
+ [ACTION_NEXT] = {
+ .name = "/",
+ .help = "specify next action",
+ .next = NEXT(next_action),
+ },
+ [ACTION_END] = {
+ .name = "end",
+ .help = "end list of actions",
+ .priv = PRIV_ACTION(END, 0),
+ .call = parse_vc,
+ },
+ [ACTION_VOID] = {
+ .name = "void",
+ .help = "no-op action",
+ .priv = PRIV_ACTION(VOID, 0),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc,
+ },
+ [ACTION_PASSTHRU] = {
+ .name = "passthru",
+ .help = "let subsequent rule process matched packets",
+ .priv = PRIV_ACTION(PASSTHRU, 0),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc,
+ },
+ [ACTION_MARK] = {
+ .name = "mark",
+ .help = "attach 32 bit value to packets",
+ .priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
+ .next = NEXT(action_mark),
+ .call = parse_vc,
+ },
+ [ACTION_MARK_ID] = {
+ .name = "id",
+ .help = "32 bit value to return with packets",
+ .next = NEXT(action_mark, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_FLAG] = {
+ .name = "flag",
+ .help = "flag packets",
+ .priv = PRIV_ACTION(FLAG, 0),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc,
+ },
+ [ACTION_QUEUE] = {
+ .name = "queue",
+ .help = "assign packets to a given queue index",
+ .priv = PRIV_ACTION(QUEUE,
+ sizeof(struct rte_flow_action_queue)),
+ .next = NEXT(action_queue),
+ .call = parse_vc,
+ },
+ [ACTION_QUEUE_INDEX] = {
+ .name = "index",
+ .help = "queue index to use",
+ .next = NEXT(action_queue, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_DROP] = {
+ .name = "drop",
+ .help = "drop packets (note: passthru has priority)",
+ .priv = PRIV_ACTION(DROP, 0),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc,
+ },
+ [ACTION_COUNT] = {
+ .name = "count",
+ .help = "enable counters for this rule",
+ .priv = PRIV_ACTION(COUNT, 0),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc,
+ },
+ [ACTION_DUP] = {
+ .name = "dup",
+ .help = "duplicate packets to a given queue index",
+ .priv = PRIV_ACTION(DUP, sizeof(struct rte_flow_action_dup)),
+ .next = NEXT(action_dup),
+ .call = parse_vc,
+ },
+ [ACTION_DUP_INDEX] = {
+ .name = "index",
+ .help = "queue index to duplicate packets to",
+ .next = NEXT(action_dup, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_action_dup, index)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_RSS] = {
+ .name = "rss",
+ .help = "spread packets among several queues",
+ .priv = PRIV_ACTION(RSS, ACTION_RSS_SIZE),
+ .next = NEXT(action_rss),
+ .call = parse_vc,
+ },
+ [ACTION_RSS_QUEUES] = {
+ .name = "queues",
+ .help = "queue indices to use",
+ .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_RSS_QUEUE] = {
+ .name = "{queue}",
+ .help = "queue index",
+ .call = parse_vc_action_rss_queue,
+ .comp = comp_vc_action_rss_queue,
+ },
+ [ACTION_PF] = {
+ .name = "pf",
+ .help = "redirect packets to physical device function",
+ .priv = PRIV_ACTION(PF, 0),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc,
+ },
+ [ACTION_VF] = {
+ .name = "vf",
+ .help = "redirect packets to virtual device function",
+ .priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
+ .next = NEXT(action_vf),
+ .call = parse_vc,
+ },
+ [ACTION_VF_ORIGINAL] = {
+ .name = "original",
+ .help = "use original VF ID if possible",
+ .next = NEXT(action_vf, NEXT_ENTRY(BOOLEAN)),
+ .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
+ original, 1)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_VF_ID] = {
+ .name = "id",
+ .help = "VF ID to redirect packets to",
+ .next = NEXT(action_vf, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
+ .call = parse_vc_conf,
+ },
+};
+
+/** Remove and return last entry from argument stack. */
+static const struct arg *
+pop_args(struct context *ctx)
+{
+ return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
+}
+
+/** Add entry on top of the argument stack. */
+static int
+push_args(struct context *ctx, const struct arg *arg)
+{
+ if (ctx->args_num == CTX_STACK_SIZE)
+ return -1;
+ ctx->args[ctx->args_num++] = arg;
+ return 0;
+}
+
+/** Spread value into buffer according to bit-mask. */
+static size_t
+arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
+{
+ uint32_t i = arg->size;
+ uint32_t end = 0;
+ int sub = 1;
+ int add = 0;
+ size_t len = 0;
+
+ if (!arg->mask)
+ return 0;
+#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
+ if (!arg->hton) {
+ i = 0;
+ end = arg->size;
+ sub = 0;
+ add = 1;
+ }
+#endif
+ while (i != end) {
+ unsigned int shift = 0;
+ uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
+
+ for (shift = 0; arg->mask[i] >> shift; ++shift) {
+ if (!(arg->mask[i] & (1 << shift)))
+ continue;
+ ++len;
+ if (!dst)
+ continue;
+ *buf &= ~(1 << shift);
+ *buf |= (val & 1) << shift;
+ val >>= 1;
+ }
+ i += add;
+ }
+ return len;
+}
+
+/**
+ * Parse a prefix length and generate a bit-mask.
+ *
+ * Last argument (ctx->args) is retrieved to determine mask size, storage
+ * location and whether the result must use network byte ordering.
+ */
+static int
+parse_prefix(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ const struct arg *arg = pop_args(ctx);
+ static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
+ char *end;
+ uintmax_t u;
+ unsigned int bytes;
+ unsigned int extra;
+
+ (void)token;
+ /* Argument is expected. */
+ if (!arg)
+ return -1;
+ errno = 0;
+ u = strtoumax(str, &end, 0);
+ if (errno || (size_t)(end - str) != len)
+ goto error;
+ if (arg->mask) {
+ uintmax_t v = 0;
+
+ extra = arg_entry_bf_fill(NULL, 0, arg);
+ if (u > extra)
+ goto error;
+ if (!ctx->object)
+ return len;
+ extra -= u;
+ while (u--)
+ (v <<= 1, v |= 1);
+ v <<= extra;
+ if (!arg_entry_bf_fill(ctx->object, v, arg) ||
+ !arg_entry_bf_fill(ctx->objmask, -1, arg))
+ goto error;
+ return len;
+ }
+ bytes = u / 8;
+ extra = u % 8;
+ size = arg->size;
+ if (bytes > size || bytes + !!extra > size)
+ goto error;
+ if (!ctx->object)
+ return len;
+ buf = (uint8_t *)ctx->object + arg->offset;
+#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
+ if (!arg->hton) {
+ memset((uint8_t *)buf + size - bytes, 0xff, bytes);
+ memset(buf, 0x00, size - bytes);
+ if (extra)
+ ((uint8_t *)buf)[size - bytes - 1] = conv[extra];
+ } else
+#endif
+ {
+ memset(buf, 0xff, bytes);
+ memset((uint8_t *)buf + bytes, 0x00, size - bytes);
+ if (extra)
+ ((uint8_t *)buf)[bytes] = conv[extra];
+ }
+ if (ctx->objmask)
+ memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
+ return len;
+error:
+ push_args(ctx, arg);
+ return -1;
+}
+
+/** Default parsing function for token name matching. */
+static int
+parse_default(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ (void)ctx;
+ (void)buf;
+ (void)size;
+ if (strncmp(str, token->name, len))
+ return -1;
+ return len;
+}
+
+/** Parse flow command, initialize output buffer for subsequent tokens. */
+static int
+parse_init(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ /* Make sure buffer is large enough. */
+ if (size < sizeof(*out))
+ return -1;
+ /* Initialize buffer. */
+ memset(out, 0x00, sizeof(*out));
+ memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ return len;
+}
+
+/** Parse tokens for validate/create commands. */
+static int
+parse_vc(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+ uint8_t *data;
+ uint32_t data_size;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command) {
+ if (ctx->curr != VALIDATE && ctx->curr != CREATE)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ out->args.vc.data = (uint8_t *)out + size;
+ return len;
+ }
+ ctx->objdata = 0;
+ ctx->object = &out->args.vc.attr;
+ ctx->objmask = NULL;
+ switch (ctx->curr) {
+ case GROUP:
+ case PRIORITY:
+ return len;
+ case INGRESS:
+ out->args.vc.attr.ingress = 1;
+ return len;
+ case EGRESS:
+ out->args.vc.attr.egress = 1;
+ return len;
+ case PATTERN:
+ out->args.vc.pattern =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
+ ctx->object = out->args.vc.pattern;
+ ctx->objmask = NULL;
+ return len;
+ case ACTIONS:
+ out->args.vc.actions =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)
+ (out->args.vc.pattern +
+ out->args.vc.pattern_n),
+ sizeof(double));
+ ctx->object = out->args.vc.actions;
+ ctx->objmask = NULL;
+ return len;
+ default:
+ if (!token->priv)
+ return -1;
+ break;
+ }
+ if (!out->args.vc.actions) {
+ const struct parse_item_priv *priv = token->priv;
+ struct rte_flow_item *item =
+ out->args.vc.pattern + out->args.vc.pattern_n;
+
+ data_size = priv->size * 3; /* spec, last, mask */
+ data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
+ (out->args.vc.data - data_size),
+ sizeof(double));
+ if ((uint8_t *)item + sizeof(*item) > data)
+ return -1;
+ *item = (struct rte_flow_item){
+ .type = priv->type,
+ };
+ ++out->args.vc.pattern_n;
+ ctx->object = item;
+ ctx->objmask = NULL;
+ } else {
+ const struct parse_action_priv *priv = token->priv;
+ struct rte_flow_action *action =
+ out->args.vc.actions + out->args.vc.actions_n;
+
+ data_size = priv->size; /* configuration */
+ data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
+ (out->args.vc.data - data_size),
+ sizeof(double));
+ if ((uint8_t *)action + sizeof(*action) > data)
+ return -1;
+ *action = (struct rte_flow_action){
+ .type = priv->type,
+ };
+ ++out->args.vc.actions_n;
+ ctx->object = action;
+ ctx->objmask = NULL;
+ }
+ memset(data, 0, data_size);
+ out->args.vc.data = data;
+ ctx->objdata = data_size;
+ return len;
+}
+
+/** Parse pattern item parameter type. */
+static int
+parse_vc_spec(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+ struct rte_flow_item *item;
+ uint32_t data_size;
+ int index;
+ int objmask = 0;
+
+ (void)size;
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Parse parameter types. */
+ switch (ctx->curr) {
+ static const enum index prefix[] = NEXT_ENTRY(PREFIX);
+
+ case ITEM_PARAM_IS:
+ index = 0;
+ objmask = 1;
+ break;
+ case ITEM_PARAM_SPEC:
+ index = 0;
+ break;
+ case ITEM_PARAM_LAST:
+ index = 1;
+ break;
+ case ITEM_PARAM_PREFIX:
+ /* Modify next token to expect a prefix. */
+ if (ctx->next_num < 2)
+ return -1;
+ ctx->next[ctx->next_num - 2] = prefix;
+ /* Fall through. */
+ case ITEM_PARAM_MASK:
+ index = 2;
+ break;
+ default:
+ return -1;
+ }
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->args.vc.pattern_n)
+ return -1;
+ item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
+ data_size = ctx->objdata / 3; /* spec, last, mask */
+ /* Point to selected object. */
+ ctx->object = out->args.vc.data + (data_size * index);
+ if (objmask) {
+ ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
+ item->mask = ctx->objmask;
+ } else
+ ctx->objmask = NULL;
+ /* Update relevant item pointer. */
+ *((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
+ ctx->object;
+ return len;
+}
+
+/** Parse action configuration field. */
+static int
+parse_vc_conf(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+ struct rte_flow_action *action;
+
+ (void)size;
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->args.vc.actions_n)
+ return -1;
+ action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+ /* Point to selected object. */
+ ctx->object = out->args.vc.data;
+ ctx->objmask = NULL;
+ /* Update configuration pointer. */
+ action->conf = ctx->object;
+ return len;
+}
+
+/**
+ * Parse queue field for RSS action.
+ *
+ * Valid tokens are queue indices and the "end" token.
+ */
+static int
+parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
+ int ret;
+ int i;
+
+ (void)token;
+ (void)buf;
+ (void)size;
+ if (ctx->curr != ACTION_RSS_QUEUE)
+ return -1;
+ i = ctx->objdata >> 16;
+ if (!strncmp(str, "end", len)) {
+ ctx->objdata &= 0xffff;
+ return len;
+ }
+ if (i >= ACTION_RSS_NUM)
+ return -1;
+ if (push_args(ctx, ARGS_ENTRY(struct rte_flow_action_rss, queue[i])))
+ return -1;
+ ret = parse_int(ctx, token, str, len, NULL, 0);
+ if (ret < 0) {
+ pop_args(ctx);
+ return -1;
+ }
+ ++i;
+ ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
+ /* Repeat token. */
+ if (ctx->next_num == RTE_DIM(ctx->next))
+ return -1;
+ ctx->next[ctx->next_num++] = next;
+ if (!ctx->object)
+ return len;
+ ((struct rte_flow_action_rss *)ctx->object)->num = i;
+ return len;
+}
+
+/** Parse tokens for destroy command. */
+static int
+parse_destroy(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command) {
+ if (ctx->curr != DESTROY)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ out->args.destroy.rule =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
+ return len;
+ }
+ if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
+ sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
+ return -1;
+ ctx->objdata = 0;
+ ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
+ ctx->objmask = NULL;
+ return len;
+}
+
+/** Parse tokens for flush command. */
+static int
+parse_flush(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command) {
+ if (ctx->curr != FLUSH)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ }
+ return len;
+}
+
+/** Parse tokens for query command. */
+static int
+parse_query(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command) {
+ if (ctx->curr != QUERY)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ }
+ return len;
+}
+
+/** Parse action names. */
+static int
+parse_action(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+ const struct arg *arg = pop_args(ctx);
+ unsigned int i;
+
+ (void)size;
+ /* Argument is expected. */
+ if (!arg)
+ return -1;
+ /* Parse action name. */
+ for (i = 0; next_action[i]; ++i) {
+ const struct parse_action_priv *priv;
+
+ token = &token_list[next_action[i]];
+ if (strncmp(token->name, str, len))
+ continue;
+ priv = token->priv;
+ if (!priv)
+ goto error;
+ if (out)
+ memcpy((uint8_t *)ctx->object + arg->offset,
+ &priv->type,
+ arg->size);
+ return len;
+ }
+error:
+ push_args(ctx, arg);
+ return -1;
+}
+
+/** Parse tokens for list command. */
+static int
+parse_list(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command) {
+ if (ctx->curr != LIST)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ out->args.list.group =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
+ return len;
+ }
+ if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
+ sizeof(*out->args.list.group)) > (uint8_t *)out + size)
+ return -1;
+ ctx->objdata = 0;
+ ctx->object = out->args.list.group + out->args.list.group_n++;
+ ctx->objmask = NULL;
+ return len;
+}
+
+/**
+ * Parse signed/unsigned integers 8 to 64-bit long.
+ *
+ * Last argument (ctx->args) is retrieved to determine integer type and
+ * storage location.
+ */
+static int
+parse_int(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ const struct arg *arg = pop_args(ctx);
+ uintmax_t u;
+ char *end;
+
+ (void)token;
+ /* Argument is expected. */
+ if (!arg)
+ return -1;
+ errno = 0;
+ u = arg->sign ?
+ (uintmax_t)strtoimax(str, &end, 0) :
+ strtoumax(str, &end, 0);
+ if (errno || (size_t)(end - str) != len)
+ goto error;
+ if (!ctx->object)
+ return len;
+ if (arg->mask) {
+ if (!arg_entry_bf_fill(ctx->object, u, arg) ||
+ !arg_entry_bf_fill(ctx->objmask, -1, arg))
+ goto error;
+ return len;
+ }
+ buf = (uint8_t *)ctx->object + arg->offset;
+ size = arg->size;
+objmask:
+ switch (size) {
+ case sizeof(uint8_t):
+ *(uint8_t *)buf = u;
+ break;
+ case sizeof(uint16_t):
+ *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
+ break;
+ case sizeof(uint8_t [3]):
+#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
+ if (!arg->hton) {
+ ((uint8_t *)buf)[0] = u;
+ ((uint8_t *)buf)[1] = u >> 8;
+ ((uint8_t *)buf)[2] = u >> 16;
+ break;
+ }
+#endif
+ ((uint8_t *)buf)[0] = u >> 16;
+ ((uint8_t *)buf)[1] = u >> 8;
+ ((uint8_t *)buf)[2] = u;
+ break;
+ case sizeof(uint32_t):
+ *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
+ break;
+ case sizeof(uint64_t):
+ *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
+ break;
+ default:
+ goto error;
+ }
+ if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
+ u = -1;
+ buf = (uint8_t *)ctx->objmask + arg->offset;
+ goto objmask;
+ }
+ return len;
+error:
+ push_args(ctx, arg);
+ return -1;
+}
+
+/**
+ * Parse a string.
+ *
+ * Two arguments (ctx->args) are retrieved from the stack to store data and
+ * its length (in that order).
+ */
+static int
+parse_string(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ const struct arg *arg_data = pop_args(ctx);
+ const struct arg *arg_len = pop_args(ctx);
+ char tmp[16]; /* Ought to be enough. */
+ int ret;
+
+ /* Arguments are expected. */
+ if (!arg_data)
+ return -1;
+ if (!arg_len) {
+ push_args(ctx, arg_data);
+ return -1;
+ }
+ size = arg_data->size;
+ /* Bit-mask fill is not supported. */
+ if (arg_data->mask || size < len)
+ goto error;
+ if (!ctx->object)
+ return len;
+ /* Let parse_int() fill length information first. */
+ ret = snprintf(tmp, sizeof(tmp), "%u", len);
+ if (ret < 0)
+ goto error;
+ push_args(ctx, arg_len);
+ ret = parse_int(ctx, token, tmp, ret, NULL, 0);
+ if (ret < 0) {
+ pop_args(ctx);
+ goto error;
+ }
+ buf = (uint8_t *)ctx->object + arg_data->offset;
+ /* Output buffer is not necessarily NUL-terminated. */
+ memcpy(buf, str, len);
+ memset((uint8_t *)buf + len, 0x55, size - len);
+ if (ctx->objmask)
+ memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
+ return len;
+error:
+ push_args(ctx, arg_len);
+ push_args(ctx, arg_data);
+ return -1;
+}
+
+/**
+ * Parse a MAC address.
+ *
+ * Last argument (ctx->args) is retrieved to determine storage size and
+ * location.
+ */
+static int
+parse_mac_addr(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ const struct arg *arg = pop_args(ctx);
+ struct ether_addr tmp;
+ int ret;
+
+ (void)token;
+ /* Argument is expected. */
+ if (!arg)
+ return -1;
+ size = arg->size;
+ /* Bit-mask fill is not supported. */
+ if (arg->mask || size != sizeof(tmp))
+ goto error;
+ /* Only network endian is supported. */
+ if (!arg->hton)
+ goto error;
+ ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
+ if (ret < 0 || (unsigned int)ret != len)
+ goto error;
+ if (!ctx->object)
+ return len;
+ buf = (uint8_t *)ctx->object + arg->offset;
+ memcpy(buf, &tmp, size);
+ if (ctx->objmask)
+ memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
+ return len;
+error:
+ push_args(ctx, arg);
+ return -1;
+}
+
+/**
+ * Parse an IPv4 address.
+ *
+ * Last argument (ctx->args) is retrieved to determine storage size and
+ * location.
+ */
+static int
+parse_ipv4_addr(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ const struct arg *arg = pop_args(ctx);
+ char str2[len + 1];
+ struct in_addr tmp;
+ int ret;
+
+ /* Argument is expected. */
+ if (!arg)
+ return -1;
+ size = arg->size;
+ /* Bit-mask fill is not supported. */
+ if (arg->mask || size != sizeof(tmp))
+ goto error;
+ /* Only network endian is supported. */
+ if (!arg->hton)
+ goto error;
+ memcpy(str2, str, len);
+ str2[len] = '\0';
+ ret = inet_pton(AF_INET, str2, &tmp);
+ if (ret != 1) {
+ /* Attempt integer parsing. */
+ push_args(ctx, arg);
+ return parse_int(ctx, token, str, len, buf, size);
+ }
+ if (!ctx->object)
+ return len;
+ buf = (uint8_t *)ctx->object + arg->offset;
+ memcpy(buf, &tmp, size);
+ if (ctx->objmask)
+ memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
+ return len;
+error:
+ push_args(ctx, arg);
+ return -1;
+}
+
+/**
+ * Parse an IPv6 address.
+ *
+ * Last argument (ctx->args) is retrieved to determine storage size and
+ * location.
+ */
+static int
+parse_ipv6_addr(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ const struct arg *arg = pop_args(ctx);
+ char str2[len + 1];
+ struct in6_addr tmp;
+ int ret;
+
+ (void)token;
+ /* Argument is expected. */
+ if (!arg)
+ return -1;
+ size = arg->size;
+ /* Bit-mask fill is not supported. */
+ if (arg->mask || size != sizeof(tmp))
+ goto error;
+ /* Only network endian is supported. */
+ if (!arg->hton)
+ goto error;
+ memcpy(str2, str, len);
+ str2[len] = '\0';
+ ret = inet_pton(AF_INET6, str2, &tmp);
+ if (ret != 1)
+ goto error;
+ if (!ctx->object)
+ return len;
+ buf = (uint8_t *)ctx->object + arg->offset;
+ memcpy(buf, &tmp, size);
+ if (ctx->objmask)
+ memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
+ return len;
+error:
+ push_args(ctx, arg);
+ return -1;
+}
+
+/** Boolean values (even indices stand for false). */
+static const char *const boolean_name[] = {
+ "0", "1",
+ "false", "true",
+ "no", "yes",
+ "N", "Y",
+ NULL,
+};
+
+/**
+ * Parse a boolean value.
+ *
+ * Last argument (ctx->args) is retrieved to determine storage size and
+ * location.
+ */
+static int
+parse_boolean(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ const struct arg *arg = pop_args(ctx);
+ unsigned int i;
+ int ret;
+
+ /* Argument is expected. */
+ if (!arg)
+ return -1;
+ for (i = 0; boolean_name[i]; ++i)
+ if (!strncmp(str, boolean_name[i], len))
+ break;
+ /* Process token as integer. */
+ if (boolean_name[i])
+ str = i & 1 ? "1" : "0";
+ push_args(ctx, arg);
+ ret = parse_int(ctx, token, str, strlen(str), buf, size);
+ return ret > 0 ? (int)len : ret;
+}
+
+/** Parse port and update context. */
+static int
+parse_port(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = &(struct buffer){ .port = 0 };
+ int ret;
+
+ if (buf)
+ out = buf;
+ else {
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ size = sizeof(*out);
+ }
+ ret = parse_int(ctx, token, str, len, out, size);
+ if (ret >= 0)
+ ctx->port = out->port;
+ if (!buf)
+ ctx->object = NULL;
+ return ret;
+}
+
+/** No completion. */
+static int
+comp_none(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size)
+{
+ (void)ctx;
+ (void)token;
+ (void)ent;
+ (void)buf;
+ (void)size;
+ return 0;
+}
+
+/** Complete boolean values. */
+static int
+comp_boolean(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size)
+{
+ unsigned int i;
+
+ (void)ctx;
+ (void)token;
+ for (i = 0; boolean_name[i]; ++i)
+ if (buf && i == ent)
+ return snprintf(buf, size, "%s", boolean_name[i]);
+ if (buf)
+ return -1;
+ return i;
+}
+
+/** Complete action names. */
+static int
+comp_action(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size)
+{
+ unsigned int i;
+
+ (void)ctx;
+ (void)token;
+ for (i = 0; next_action[i]; ++i)
+ if (buf && i == ent)
+ return snprintf(buf, size, "%s",
+ token_list[next_action[i]].name);
+ if (buf)
+ return -1;
+ return i;
+}
+
+/** Complete available ports. */
+static int
+comp_port(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size)
+{
+ unsigned int i = 0;
+ portid_t p;
+
+ (void)ctx;
+ (void)token;
+ RTE_ETH_FOREACH_DEV(p) {
+ if (buf && i == ent)
+ return snprintf(buf, size, "%u", p);
+ ++i;
+ }
+ if (buf)
+ return -1;
+ return i;
+}
+
+/** Complete available rule IDs. */
+static int
+comp_rule_id(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size)
+{
+ unsigned int i = 0;
+ struct rte_port *port;
+ struct port_flow *pf;
+
+ (void)token;
+ if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
+ ctx->port == (uint16_t)RTE_PORT_ALL)
+ return -1;
+ port = &ports[ctx->port];
+ for (pf = port->flow_list; pf != NULL; pf = pf->next) {
+ if (buf && i == ent)
+ return snprintf(buf, size, "%u", pf->id);
+ ++i;
+ }
+ if (buf)
+ return -1;
+ return i;
+}
+
+/** Complete queue field for RSS action. */
+static int
+comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size)
+{
+ static const char *const str[] = { "", "end", NULL };
+ unsigned int i;
+
+ (void)ctx;
+ (void)token;
+ for (i = 0; str[i] != NULL; ++i)
+ if (buf && i == ent)
+ return snprintf(buf, size, "%s", str[i]);
+ if (buf)
+ return -1;
+ return i;
+}
+
+/** Internal context. */
+static struct context cmd_flow_context;
+
+/** Global parser instance (cmdline API). */
+cmdline_parse_inst_t cmd_flow;
+
+/** Initialize context. */
+static void
+cmd_flow_context_init(struct context *ctx)
+{
+ /* A full memset() is not necessary. */
+ ctx->curr = ZERO;
+ ctx->prev = ZERO;
+ ctx->next_num = 0;
+ ctx->args_num = 0;
+ ctx->reparse = 0;
+ ctx->eol = 0;
+ ctx->last = 0;
+ ctx->port = 0;
+ ctx->objdata = 0;
+ ctx->object = NULL;
+ ctx->objmask = NULL;
+}
+
+/** Parse a token (cmdline API). */
+static int
+cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
+ unsigned int size)
+{
+ struct context *ctx = &cmd_flow_context;
+ const struct token *token;
+ const enum index *list;
+ int len;
+ int i;
+
+ (void)hdr;
+ /* Restart as requested. */
+ if (ctx->reparse)
+ cmd_flow_context_init(ctx);
+ token = &token_list[ctx->curr];
+ /* Check argument length. */
+ ctx->eol = 0;
+ ctx->last = 1;
+ for (len = 0; src[len]; ++len)
+ if (src[len] == '#' || isspace(src[len]))
+ break;
+ if (!len)
+ return -1;
+ /* Last argument and EOL detection. */
+ for (i = len; src[i]; ++i)
+ if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
+ break;
+ else if (!isspace(src[i])) {
+ ctx->last = 0;
+ break;
+ }
+ for (; src[i]; ++i)
+ if (src[i] == '\r' || src[i] == '\n') {
+ ctx->eol = 1;
+ break;
+ }
+ /* Initialize context if necessary. */
+ if (!ctx->next_num) {
+ if (!token->next)
+ return 0;
+ ctx->next[ctx->next_num++] = token->next[0];
+ }
+ /* Process argument through candidates. */
+ ctx->prev = ctx->curr;
+ list = ctx->next[ctx->next_num - 1];
+ for (i = 0; list[i]; ++i) {
+ const struct token *next = &token_list[list[i]];
+ int tmp;
+
+ ctx->curr = list[i];
+ if (next->call)
+ tmp = next->call(ctx, next, src, len, result, size);
+ else
+ tmp = parse_default(ctx, next, src, len, result, size);
+ if (tmp == -1 || tmp != len)
+ continue;
+ token = next;
+ break;
+ }
+ if (!list[i])
+ return -1;
+ --ctx->next_num;
+ /* Push subsequent tokens if any. */
+ if (token->next)
+ for (i = 0; token->next[i]; ++i) {
+ if (ctx->next_num == RTE_DIM(ctx->next))
+ return -1;
+ ctx->next[ctx->next_num++] = token->next[i];
+ }
+ /* Push arguments if any. */
+ if (token->args)
+ for (i = 0; token->args[i]; ++i) {
+ if (ctx->args_num == RTE_DIM(ctx->args))
+ return -1;
+ ctx->args[ctx->args_num++] = token->args[i];
+ }
+ return len;
+}
+
+/** Return number of completion entries (cmdline API). */
+static int
+cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
+{
+ struct context *ctx = &cmd_flow_context;
+ const struct token *token = &token_list[ctx->curr];
+ const enum index *list;
+ int i;
+
+ (void)hdr;
+ /* Tell cmd_flow_parse() that context must be reinitialized. */
+ ctx->reparse = 1;
+ /* Count number of tokens in current list. */
+ if (ctx->next_num)
+ list = ctx->next[ctx->next_num - 1];
+ else
+ list = token->next[0];
+ for (i = 0; list[i]; ++i)
+ ;
+ if (!i)
+ return 0;
+ /*
+ * If there is a single token, use its completion callback, otherwise
+ * return the number of entries.
+ */
+ token = &token_list[list[0]];
+ if (i == 1 && token->comp) {
+ /* Save index for cmd_flow_get_help(). */
+ ctx->prev = list[0];
+ return token->comp(ctx, token, 0, NULL, 0);
+ }
+ return i;
+}
+
+/** Return a completion entry (cmdline API). */
+static int
+cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
+ char *dst, unsigned int size)
+{
+ struct context *ctx = &cmd_flow_context;
+ const struct token *token = &token_list[ctx->curr];
+ const enum index *list;
+ int i;
+
+ (void)hdr;
+ /* Tell cmd_flow_parse() that context must be reinitialized. */
+ ctx->reparse = 1;
+ /* Count number of tokens in current list. */
+ if (ctx->next_num)
+ list = ctx->next[ctx->next_num - 1];
+ else
+ list = token->next[0];
+ for (i = 0; list[i]; ++i)
+ ;
+ if (!i)
+ return -1;
+ /* If there is a single token, use its completion callback. */
+ token = &token_list[list[0]];
+ if (i == 1 && token->comp) {
+ /* Save index for cmd_flow_get_help(). */
+ ctx->prev = list[0];
+ return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
+ }
+ /* Otherwise make sure the index is valid and use defaults. */
+ if (index >= i)
+ return -1;
+ token = &token_list[list[index]];
+ snprintf(dst, size, "%s", token->name);
+ /* Save index for cmd_flow_get_help(). */
+ ctx->prev = list[index];
+ return 0;
+}
+
+/** Populate help strings for current token (cmdline API). */
+static int
+cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
+{
+ struct context *ctx = &cmd_flow_context;
+ const struct token *token = &token_list[ctx->prev];
+
+ (void)hdr;
+ /* Tell cmd_flow_parse() that context must be reinitialized. */
+ ctx->reparse = 1;
+ if (!size)
+ return -1;
+ /* Set token type and update global help with details. */
+ snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
+ if (token->help)
+ cmd_flow.help_str = token->help;
+ else
+ cmd_flow.help_str = token->name;
+ return 0;
+}
+
+/** Token definition template (cmdline API). */
+static struct cmdline_token_hdr cmd_flow_token_hdr = {
+ .ops = &(struct cmdline_token_ops){
+ .parse = cmd_flow_parse,
+ .complete_get_nb = cmd_flow_complete_get_nb,
+ .complete_get_elt = cmd_flow_complete_get_elt,
+ .get_help = cmd_flow_get_help,
+ },
+ .offset = 0,
+};
+
+/** Populate the next dynamic token. */
+static void
+cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
+ cmdline_parse_token_hdr_t *(*hdrs)[])
+{
+ struct context *ctx = &cmd_flow_context;
+
+ /* Always reinitialize context before requesting the first token. */
+ if (!(hdr - *hdrs))
+ cmd_flow_context_init(ctx);
+ /* Return NULL when no more tokens are expected. */
+ if (!ctx->next_num && ctx->curr) {
+ *hdr = NULL;
+ return;
+ }
+ /* Determine if command should end here. */
+ if (ctx->eol && ctx->last && ctx->next_num) {
+ const enum index *list = ctx->next[ctx->next_num - 1];
+ int i;
+
+ for (i = 0; list[i]; ++i) {
+ if (list[i] != END)
+ continue;
+ *hdr = NULL;
+ return;
+ }
+ }
+ *hdr = &cmd_flow_token_hdr;
+}
+
+/** Dispatch parsed buffer to function calls. */
+static void
+cmd_flow_parsed(const struct buffer *in)
+{
+ switch (in->command) {
+ case VALIDATE:
+ port_flow_validate(in->port, &in->args.vc.attr,
+ in->args.vc.pattern, in->args.vc.actions);
+ break;
+ case CREATE:
+ port_flow_create(in->port, &in->args.vc.attr,
+ in->args.vc.pattern, in->args.vc.actions);
+ break;
+ case DESTROY:
+ port_flow_destroy(in->port, in->args.destroy.rule_n,
+ in->args.destroy.rule);
+ break;
+ case FLUSH:
+ port_flow_flush(in->port);
+ break;
+ case QUERY:
+ port_flow_query(in->port, in->args.query.rule,
+ in->args.query.action);
+ break;
+ case LIST:
+ port_flow_list(in->port, in->args.list.group_n,
+ in->args.list.group);
+ break;
+ default:
+ break;
+ }
+}
+
+/** Token generator and output processing callback (cmdline API). */
+static void
+cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
+{
+ if (cl == NULL)
+ cmd_flow_tok(arg0, arg2);
+ else
+ cmd_flow_parsed(arg0);
+}
+
+/** Global parser instance (cmdline API). */
+cmdline_parse_inst_t cmd_flow = {
+ .f = cmd_flow_cb,
+ .data = NULL, /**< Unused. */
+ .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
+ .tokens = {
+ NULL,
+ }, /**< Tokens are returned by cmd_flow_tok(). */
+};
diff --git a/src/seastar/dpdk/app/test-pmd/config.c b/src/seastar/dpdk/app/test-pmd/config.c
new file mode 100644
index 00000000..4d873cdd
--- /dev/null
+++ b/src/seastar/dpdk/app/test-pmd/config.c
@@ -0,0 +1,3321 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/* BSD LICENSE
+ *
+ * Copyright 2013-2014 6WIND S.A.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of 6WIND S.A. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdarg.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_debug.h>
+#include <rte_log.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_memzone.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_string_fns.h>
+#include <rte_cycles.h>
+#include <rte_flow.h>
+#include <rte_errno.h>
+#ifdef RTE_LIBRTE_IXGBE_PMD
+#include <rte_pmd_ixgbe.h>
+#endif
+
+#include "testpmd.h"
+
+static char *flowtype_to_str(uint16_t flow_type);
+
+static const struct {
+ enum tx_pkt_split split;
+ const char *name;
+} tx_split_name[] = {
+ {
+ .split = TX_PKT_SPLIT_OFF,
+ .name = "off",
+ },
+ {
+ .split = TX_PKT_SPLIT_ON,
+ .name = "on",
+ },
+ {
+ .split = TX_PKT_SPLIT_RND,
+ .name = "rand",
+ },
+};
+
+struct rss_type_info {
+ char str[32];
+ uint64_t rss_type;
+};
+
+static const struct rss_type_info rss_type_table[] = {
+ { "ipv4", ETH_RSS_IPV4 },
+ { "ipv4-frag", ETH_RSS_FRAG_IPV4 },
+ { "ipv4-tcp", ETH_RSS_NONFRAG_IPV4_TCP },
+ { "ipv4-udp", ETH_RSS_NONFRAG_IPV4_UDP },
+ { "ipv4-sctp", ETH_RSS_NONFRAG_IPV4_SCTP },
+ { "ipv4-other", ETH_RSS_NONFRAG_IPV4_OTHER },
+ { "ipv6", ETH_RSS_IPV6 },
+ { "ipv6-frag", ETH_RSS_FRAG_IPV6 },
+ { "ipv6-tcp", ETH_RSS_NONFRAG_IPV6_TCP },
+ { "ipv6-udp", ETH_RSS_NONFRAG_IPV6_UDP },
+ { "ipv6-sctp", ETH_RSS_NONFRAG_IPV6_SCTP },
+ { "ipv6-other", ETH_RSS_NONFRAG_IPV6_OTHER },
+ { "l2-payload", ETH_RSS_L2_PAYLOAD },
+ { "ipv6-ex", ETH_RSS_IPV6_EX },
+ { "ipv6-tcp-ex", ETH_RSS_IPV6_TCP_EX },
+ { "ipv6-udp-ex", ETH_RSS_IPV6_UDP_EX },
+ { "port", ETH_RSS_PORT },
+ { "vxlan", ETH_RSS_VXLAN },
+ { "geneve", ETH_RSS_GENEVE },
+ { "nvgre", ETH_RSS_NVGRE },
+
+};
+
+static void
+print_ethaddr(const char *name, struct ether_addr *eth_addr)
+{
+ char buf[ETHER_ADDR_FMT_SIZE];
+ ether_format_addr(buf, ETHER_ADDR_FMT_SIZE, eth_addr);
+ printf("%s%s", name, buf);
+}
+
+void
+nic_stats_display(portid_t port_id)
+{
+ static uint64_t prev_pkts_rx[RTE_MAX_ETHPORTS];
+ static uint64_t prev_pkts_tx[RTE_MAX_ETHPORTS];
+ static uint64_t prev_cycles[RTE_MAX_ETHPORTS];
+ uint64_t diff_pkts_rx, diff_pkts_tx, diff_cycles;
+ uint64_t mpps_rx, mpps_tx;
+ struct rte_eth_stats stats;
+ struct rte_port *port = &ports[port_id];
+ uint8_t i;
+ portid_t pid;
+
+ static const char *nic_stats_border = "########################";
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN)) {
+ printf("Valid port range is [0");
+ RTE_ETH_FOREACH_DEV(pid)
+ printf(", %d", pid);
+ printf("]\n");
+ return;
+ }
+ rte_eth_stats_get(port_id, &stats);
+ printf("\n %s NIC statistics for port %-2d %s\n",
+ nic_stats_border, port_id, nic_stats_border);
+
+ if ((!port->rx_queue_stats_mapping_enabled) && (!port->tx_queue_stats_mapping_enabled)) {
+ printf(" RX-packets: %-10"PRIu64" RX-missed: %-10"PRIu64" RX-bytes: "
+ "%-"PRIu64"\n",
+ stats.ipackets, stats.imissed, stats.ibytes);
+ printf(" RX-errors: %-"PRIu64"\n", stats.ierrors);
+ printf(" RX-nombuf: %-10"PRIu64"\n",
+ stats.rx_nombuf);
+ printf(" TX-packets: %-10"PRIu64" TX-errors: %-10"PRIu64" TX-bytes: "
+ "%-"PRIu64"\n",
+ stats.opackets, stats.oerrors, stats.obytes);
+ }
+ else {
+ printf(" RX-packets: %10"PRIu64" RX-errors: %10"PRIu64
+ " RX-bytes: %10"PRIu64"\n",
+ stats.ipackets, stats.ierrors, stats.ibytes);
+ printf(" RX-errors: %10"PRIu64"\n", stats.ierrors);
+ printf(" RX-nombuf: %10"PRIu64"\n",
+ stats.rx_nombuf);
+ printf(" TX-packets: %10"PRIu64" TX-errors: %10"PRIu64
+ " TX-bytes: %10"PRIu64"\n",
+ stats.opackets, stats.oerrors, stats.obytes);
+ }
+
+ if (port->rx_queue_stats_mapping_enabled) {
+ printf("\n");
+ for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) {
+ printf(" Stats reg %2d RX-packets: %10"PRIu64
+ " RX-errors: %10"PRIu64
+ " RX-bytes: %10"PRIu64"\n",
+ i, stats.q_ipackets[i], stats.q_errors[i], stats.q_ibytes[i]);
+ }
+ }
+ if (port->tx_queue_stats_mapping_enabled) {
+ printf("\n");
+ for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) {
+ printf(" Stats reg %2d TX-packets: %10"PRIu64
+ " TX-bytes: %10"PRIu64"\n",
+ i, stats.q_opackets[i], stats.q_obytes[i]);
+ }
+ }
+
+ diff_cycles = prev_cycles[port_id];
+ prev_cycles[port_id] = rte_rdtsc();
+ if (diff_cycles > 0)
+ diff_cycles = prev_cycles[port_id] - diff_cycles;
+
+ diff_pkts_rx = stats.ipackets - prev_pkts_rx[port_id];
+ diff_pkts_tx = stats.opackets - prev_pkts_tx[port_id];
+ prev_pkts_rx[port_id] = stats.ipackets;
+ prev_pkts_tx[port_id] = stats.opackets;
+ mpps_rx = diff_cycles > 0 ?
+ diff_pkts_rx * rte_get_tsc_hz() / diff_cycles : 0;
+ mpps_tx = diff_cycles > 0 ?
+ diff_pkts_tx * rte_get_tsc_hz() / diff_cycles : 0;
+ printf("\n Throughput (since last show)\n");
+ printf(" Rx-pps: %12"PRIu64"\n Tx-pps: %12"PRIu64"\n",
+ mpps_rx, mpps_tx);
+
+ printf(" %s############################%s\n",
+ nic_stats_border, nic_stats_border);
+}
+
+void
+nic_stats_clear(portid_t port_id)
+{
+ portid_t pid;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN)) {
+ printf("Valid port range is [0");
+ RTE_ETH_FOREACH_DEV(pid)
+ printf(", %d", pid);
+ printf("]\n");
+ return;
+ }
+ rte_eth_stats_reset(port_id);
+ printf("\n NIC statistics for port %d cleared\n", port_id);
+}
+
+void
+nic_xstats_display(portid_t port_id)
+{
+ struct rte_eth_xstat *xstats;
+ int cnt_xstats, idx_xstat;
+ struct rte_eth_xstat_name *xstats_names;
+
+ printf("###### NIC extended statistics for port %-2d\n", port_id);
+ if (!rte_eth_dev_is_valid_port(port_id)) {
+ printf("Error: Invalid port number %i\n", port_id);
+ return;
+ }
+
+ /* Get count */
+ cnt_xstats = rte_eth_xstats_get_names(port_id, NULL, 0);
+ if (cnt_xstats < 0) {
+ printf("Error: Cannot get count of xstats\n");
+ return;
+ }
+
+ /* Get id-name lookup table */
+ xstats_names = malloc(sizeof(struct rte_eth_xstat_name) * cnt_xstats);
+ if (xstats_names == NULL) {
+ printf("Cannot allocate memory for xstats lookup\n");
+ return;
+ }
+ if (cnt_xstats != rte_eth_xstats_get_names(
+ port_id, xstats_names, cnt_xstats)) {
+ printf("Error: Cannot get xstats lookup\n");
+ free(xstats_names);
+ return;
+ }
+
+ /* Get stats themselves */
+ xstats = malloc(sizeof(struct rte_eth_xstat) * cnt_xstats);
+ if (xstats == NULL) {
+ printf("Cannot allocate memory for xstats\n");
+ free(xstats_names);
+ return;
+ }
+ if (cnt_xstats != rte_eth_xstats_get(port_id, xstats, cnt_xstats)) {
+ printf("Error: Unable to get xstats\n");
+ free(xstats_names);
+ free(xstats);
+ return;
+ }
+
+ /* Display xstats */
+ for (idx_xstat = 0; idx_xstat < cnt_xstats; idx_xstat++)
+ printf("%s: %"PRIu64"\n",
+ xstats_names[idx_xstat].name,
+ xstats[idx_xstat].value);
+ free(xstats_names);
+ free(xstats);
+}
+
+void
+nic_xstats_clear(portid_t port_id)
+{
+ rte_eth_xstats_reset(port_id);
+}
+
+void
+nic_stats_mapping_display(portid_t port_id)
+{
+ struct rte_port *port = &ports[port_id];
+ uint16_t i;
+ portid_t pid;
+
+ static const char *nic_stats_mapping_border = "########################";
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN)) {
+ printf("Valid port range is [0");
+ RTE_ETH_FOREACH_DEV(pid)
+ printf(", %d", pid);
+ printf("]\n");
+ return;
+ }
+
+ if ((!port->rx_queue_stats_mapping_enabled) && (!port->tx_queue_stats_mapping_enabled)) {
+ printf("Port id %d - either does not support queue statistic mapping or"
+ " no queue statistic mapping set\n", port_id);
+ return;
+ }
+
+ printf("\n %s NIC statistics mapping for port %-2d %s\n",
+ nic_stats_mapping_border, port_id, nic_stats_mapping_border);
+
+ if (port->rx_queue_stats_mapping_enabled) {
+ for (i = 0; i < nb_rx_queue_stats_mappings; i++) {
+ if (rx_queue_stats_mappings[i].port_id == port_id) {
+ printf(" RX-queue %2d mapped to Stats Reg %2d\n",
+ rx_queue_stats_mappings[i].queue_id,
+ rx_queue_stats_mappings[i].stats_counter_id);
+ }
+ }
+ printf("\n");
+ }
+
+
+ if (port->tx_queue_stats_mapping_enabled) {
+ for (i = 0; i < nb_tx_queue_stats_mappings; i++) {
+ if (tx_queue_stats_mappings[i].port_id == port_id) {
+ printf(" TX-queue %2d mapped to Stats Reg %2d\n",
+ tx_queue_stats_mappings[i].queue_id,
+ tx_queue_stats_mappings[i].stats_counter_id);
+ }
+ }
+ }
+
+ printf(" %s####################################%s\n",
+ nic_stats_mapping_border, nic_stats_mapping_border);
+}
+
+void
+rx_queue_infos_display(portid_t port_id, uint16_t queue_id)
+{
+ struct rte_eth_rxq_info qinfo;
+ int32_t rc;
+ static const char *info_border = "*********************";
+
+ rc = rte_eth_rx_queue_info_get(port_id, queue_id, &qinfo);
+ if (rc != 0) {
+ printf("Failed to retrieve information for port: %hhu, "
+ "RX queue: %hu\nerror desc: %s(%d)\n",
+ port_id, queue_id, strerror(-rc), rc);
+ return;
+ }
+
+ printf("\n%s Infos for port %-2u, RX queue %-2u %s",
+ info_border, port_id, queue_id, info_border);
+
+ printf("\nMempool: %s", (qinfo.mp == NULL) ? "NULL" : qinfo.mp->name);
+ printf("\nRX prefetch threshold: %hhu", qinfo.conf.rx_thresh.pthresh);
+ printf("\nRX host threshold: %hhu", qinfo.conf.rx_thresh.hthresh);
+ printf("\nRX writeback threshold: %hhu", qinfo.conf.rx_thresh.wthresh);
+ printf("\nRX free threshold: %hu", qinfo.conf.rx_free_thresh);
+ printf("\nRX drop packets: %s",
+ (qinfo.conf.rx_drop_en != 0) ? "on" : "off");
+ printf("\nRX deferred start: %s",
+ (qinfo.conf.rx_deferred_start != 0) ? "on" : "off");
+ printf("\nRX scattered packets: %s",
+ (qinfo.scattered_rx != 0) ? "on" : "off");
+ printf("\nNumber of RXDs: %hu", qinfo.nb_desc);
+ printf("\n");
+}
+
+void
+tx_queue_infos_display(portid_t port_id, uint16_t queue_id)
+{
+ struct rte_eth_txq_info qinfo;
+ int32_t rc;
+ static const char *info_border = "*********************";
+
+ rc = rte_eth_tx_queue_info_get(port_id, queue_id, &qinfo);
+ if (rc != 0) {
+ printf("Failed to retrieve information for port: %hhu, "
+ "TX queue: %hu\nerror desc: %s(%d)\n",
+ port_id, queue_id, strerror(-rc), rc);
+ return;
+ }
+
+ printf("\n%s Infos for port %-2u, TX queue %-2u %s",
+ info_border, port_id, queue_id, info_border);
+
+ printf("\nTX prefetch threshold: %hhu", qinfo.conf.tx_thresh.pthresh);
+ printf("\nTX host threshold: %hhu", qinfo.conf.tx_thresh.hthresh);
+ printf("\nTX writeback threshold: %hhu", qinfo.conf.tx_thresh.wthresh);
+ printf("\nTX RS threshold: %hu", qinfo.conf.tx_rs_thresh);
+ printf("\nTX free threshold: %hu", qinfo.conf.tx_free_thresh);
+ printf("\nTX flags: %#x", qinfo.conf.txq_flags);
+ printf("\nTX deferred start: %s",
+ (qinfo.conf.tx_deferred_start != 0) ? "on" : "off");
+ printf("\nNumber of TXDs: %hu", qinfo.nb_desc);
+ printf("\n");
+}
+
+void
+port_infos_display(portid_t port_id)
+{
+ struct rte_port *port;
+ struct ether_addr mac_addr;
+ struct rte_eth_link link;
+ struct rte_eth_dev_info dev_info;
+ int vlan_offload;
+ struct rte_mempool * mp;
+ static const char *info_border = "*********************";
+ portid_t pid;
+ uint16_t mtu;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN)) {
+ printf("Valid port range is [0");
+ RTE_ETH_FOREACH_DEV(pid)
+ printf(", %d", pid);
+ printf("]\n");
+ return;
+ }
+ port = &ports[port_id];
+ rte_eth_link_get_nowait(port_id, &link);
+ memset(&dev_info, 0, sizeof(dev_info));
+ rte_eth_dev_info_get(port_id, &dev_info);
+ printf("\n%s Infos for port %-2d %s\n",
+ info_border, port_id, info_border);
+ rte_eth_macaddr_get(port_id, &mac_addr);
+ print_ethaddr("MAC address: ", &mac_addr);
+ printf("\nDriver name: %s", dev_info.driver_name);
+ printf("\nConnect to socket: %u", port->socket_id);
+
+ if (port_numa[port_id] != NUMA_NO_CONFIG) {
+ mp = mbuf_pool_find(port_numa[port_id]);
+ if (mp)
+ printf("\nmemory allocation on the socket: %d",
+ port_numa[port_id]);
+ } else
+ printf("\nmemory allocation on the socket: %u",port->socket_id);
+
+ printf("\nLink status: %s\n", (link.link_status) ? ("up") : ("down"));
+ printf("Link speed: %u Mbps\n", (unsigned) link.link_speed);
+ printf("Link duplex: %s\n", (link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
+ ("full-duplex") : ("half-duplex"));
+
+ if (!rte_eth_dev_get_mtu(port_id, &mtu))
+ printf("MTU: %u\n", mtu);
+
+ printf("Promiscuous mode: %s\n",
+ rte_eth_promiscuous_get(port_id) ? "enabled" : "disabled");
+ printf("Allmulticast mode: %s\n",
+ rte_eth_allmulticast_get(port_id) ? "enabled" : "disabled");
+ printf("Maximum number of MAC addresses: %u\n",
+ (unsigned int)(port->dev_info.max_mac_addrs));
+ printf("Maximum number of MAC addresses of hash filtering: %u\n",
+ (unsigned int)(port->dev_info.max_hash_mac_addrs));
+
+ vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
+ if (vlan_offload >= 0){
+ printf("VLAN offload: \n");
+ if (vlan_offload & ETH_VLAN_STRIP_OFFLOAD)
+ printf(" strip on \n");
+ else
+ printf(" strip off \n");
+
+ if (vlan_offload & ETH_VLAN_FILTER_OFFLOAD)
+ printf(" filter on \n");
+ else
+ printf(" filter off \n");
+
+ if (vlan_offload & ETH_VLAN_EXTEND_OFFLOAD)
+ printf(" qinq(extend) on \n");
+ else
+ printf(" qinq(extend) off \n");
+ }
+
+ if (dev_info.hash_key_size > 0)
+ printf("Hash key size in bytes: %u\n", dev_info.hash_key_size);
+ if (dev_info.reta_size > 0)
+ printf("Redirection table size: %u\n", dev_info.reta_size);
+ if (!dev_info.flow_type_rss_offloads)
+ printf("No flow type is supported.\n");
+ else {
+ uint16_t i;
+ char *p;
+
+ printf("Supported flow types:\n");
+ for (i = RTE_ETH_FLOW_UNKNOWN + 1; i < RTE_ETH_FLOW_MAX;
+ i++) {
+ if (!(dev_info.flow_type_rss_offloads & (1ULL << i)))
+ continue;
+ p = flowtype_to_str(i);
+ printf(" %s\n", (p ? p : "unknown"));
+ }
+ }
+
+ printf("Max possible RX queues: %u\n", dev_info.max_rx_queues);
+ printf("Max possible number of RXDs per queue: %hu\n",
+ dev_info.rx_desc_lim.nb_max);
+ printf("Min possible number of RXDs per queue: %hu\n",
+ dev_info.rx_desc_lim.nb_min);
+ printf("RXDs number alignment: %hu\n", dev_info.rx_desc_lim.nb_align);
+
+ printf("Max possible TX queues: %u\n", dev_info.max_tx_queues);
+ printf("Max possible number of TXDs per queue: %hu\n",
+ dev_info.tx_desc_lim.nb_max);
+ printf("Min possible number of TXDs per queue: %hu\n",
+ dev_info.tx_desc_lim.nb_min);
+ printf("TXDs number alignment: %hu\n", dev_info.tx_desc_lim.nb_align);
+}
+
+void
+port_offload_cap_display(portid_t port_id)
+{
+ struct rte_eth_dev *dev;
+ struct rte_eth_dev_info dev_info;
+ static const char *info_border = "************";
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ dev = &rte_eth_devices[port_id];
+ rte_eth_dev_info_get(port_id, &dev_info);
+
+ printf("\n%s Port %d supported offload features: %s\n",
+ info_border, port_id, info_border);
+
+ if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_VLAN_STRIP) {
+ printf("VLAN stripped: ");
+ if (dev->data->dev_conf.rxmode.hw_vlan_strip)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_QINQ_STRIP) {
+ printf("Double VLANs stripped: ");
+ if (dev->data->dev_conf.rxmode.hw_vlan_extend)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_IPV4_CKSUM) {
+ printf("RX IPv4 checksum: ");
+ if (dev->data->dev_conf.rxmode.hw_ip_checksum)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_UDP_CKSUM) {
+ printf("RX UDP checksum: ");
+ if (dev->data->dev_conf.rxmode.hw_ip_checksum)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_CKSUM) {
+ printf("RX TCP checksum: ");
+ if (dev->data->dev_conf.rxmode.hw_ip_checksum)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM)
+ printf("RX Outer IPv4 checksum: on");
+
+ if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_LRO) {
+ printf("Large receive offload: ");
+ if (dev->data->dev_conf.rxmode.enable_lro)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_VLAN_INSERT) {
+ printf("VLAN insert: ");
+ if (ports[port_id].tx_ol_flags &
+ TESTPMD_TX_OFFLOAD_INSERT_VLAN)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_QINQ_INSERT) {
+ printf("Double VLANs insert: ");
+ if (ports[port_id].tx_ol_flags &
+ TESTPMD_TX_OFFLOAD_INSERT_QINQ)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM) {
+ printf("TX IPv4 checksum: ");
+ if (ports[port_id].tx_ol_flags & TESTPMD_TX_OFFLOAD_IP_CKSUM)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM) {
+ printf("TX UDP checksum: ");
+ if (ports[port_id].tx_ol_flags & TESTPMD_TX_OFFLOAD_UDP_CKSUM)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM) {
+ printf("TX TCP checksum: ");
+ if (ports[port_id].tx_ol_flags & TESTPMD_TX_OFFLOAD_TCP_CKSUM)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_SCTP_CKSUM) {
+ printf("TX SCTP checksum: ");
+ if (ports[port_id].tx_ol_flags & TESTPMD_TX_OFFLOAD_SCTP_CKSUM)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM) {
+ printf("TX Outer IPv4 checksum: ");
+ if (ports[port_id].tx_ol_flags &
+ TESTPMD_TX_OFFLOAD_OUTER_IP_CKSUM)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_TSO) {
+ printf("TX TCP segmentation: ");
+ if (ports[port_id].tso_segsz != 0)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_TSO) {
+ printf("TX UDP segmentation: ");
+ if (ports[port_id].tso_segsz != 0)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_VXLAN_TNL_TSO) {
+ printf("TSO for VXLAN tunnel packet: ");
+ if (ports[port_id].tunnel_tso_segsz)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_GRE_TNL_TSO) {
+ printf("TSO for GRE tunnel packet: ");
+ if (ports[port_id].tunnel_tso_segsz)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPIP_TNL_TSO) {
+ printf("TSO for IPIP tunnel packet: ");
+ if (ports[port_id].tunnel_tso_segsz)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_GENEVE_TNL_TSO) {
+ printf("TSO for GENEVE tunnel packet: ");
+ if (ports[port_id].tunnel_tso_segsz)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+}
+
+int
+port_id_is_invalid(portid_t port_id, enum print_warning warning)
+{
+ if (port_id == (portid_t)RTE_PORT_ALL)
+ return 0;
+
+ if (rte_eth_dev_is_valid_port(port_id))
+ return 0;
+
+ if (warning == ENABLED_WARN)
+ printf("Invalid port %d\n", port_id);
+
+ return 1;
+}
+
+static int
+vlan_id_is_invalid(uint16_t vlan_id)
+{
+ if (vlan_id < 4096)
+ return 0;
+ printf("Invalid vlan_id %d (must be < 4096)\n", vlan_id);
+ return 1;
+}
+
+static int
+port_reg_off_is_invalid(portid_t port_id, uint32_t reg_off)
+{
+ uint64_t pci_len;
+
+ if (reg_off & 0x3) {
+ printf("Port register offset 0x%X not aligned on a 4-byte "
+ "boundary\n",
+ (unsigned)reg_off);
+ return 1;
+ }
+ pci_len = ports[port_id].dev_info.pci_dev->mem_resource[0].len;
+ if (reg_off >= pci_len) {
+ printf("Port %d: register offset %u (0x%X) out of port PCI "
+ "resource (length=%"PRIu64")\n",
+ port_id, (unsigned)reg_off, (unsigned)reg_off, pci_len);
+ return 1;
+ }
+ return 0;
+}
+
+static int
+reg_bit_pos_is_invalid(uint8_t bit_pos)
+{
+ if (bit_pos <= 31)
+ return 0;
+ printf("Invalid bit position %d (must be <= 31)\n", bit_pos);
+ return 1;
+}
+
+#define display_port_and_reg_off(port_id, reg_off) \
+ printf("port %d PCI register at offset 0x%X: ", (port_id), (reg_off))
+
+static inline void
+display_port_reg_value(portid_t port_id, uint32_t reg_off, uint32_t reg_v)
+{
+ display_port_and_reg_off(port_id, (unsigned)reg_off);
+ printf("0x%08X (%u)\n", (unsigned)reg_v, (unsigned)reg_v);
+}
+
+void
+port_reg_bit_display(portid_t port_id, uint32_t reg_off, uint8_t bit_x)
+{
+ uint32_t reg_v;
+
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ if (port_reg_off_is_invalid(port_id, reg_off))
+ return;
+ if (reg_bit_pos_is_invalid(bit_x))
+ return;
+ reg_v = port_id_pci_reg_read(port_id, reg_off);
+ display_port_and_reg_off(port_id, (unsigned)reg_off);
+ printf("bit %d=%d\n", bit_x, (int) ((reg_v & (1 << bit_x)) >> bit_x));
+}
+
+void
+port_reg_bit_field_display(portid_t port_id, uint32_t reg_off,
+ uint8_t bit1_pos, uint8_t bit2_pos)
+{
+ uint32_t reg_v;
+ uint8_t l_bit;
+ uint8_t h_bit;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ if (port_reg_off_is_invalid(port_id, reg_off))
+ return;
+ if (reg_bit_pos_is_invalid(bit1_pos))
+ return;
+ if (reg_bit_pos_is_invalid(bit2_pos))
+ return;
+ if (bit1_pos > bit2_pos)
+ l_bit = bit2_pos, h_bit = bit1_pos;
+ else
+ l_bit = bit1_pos, h_bit = bit2_pos;
+
+ reg_v = port_id_pci_reg_read(port_id, reg_off);
+ reg_v >>= l_bit;
+ if (h_bit < 31)
+ reg_v &= ((1 << (h_bit - l_bit + 1)) - 1);
+ display_port_and_reg_off(port_id, (unsigned)reg_off);
+ printf("bits[%d, %d]=0x%0*X (%u)\n", l_bit, h_bit,
+ ((h_bit - l_bit) / 4) + 1, (unsigned)reg_v, (unsigned)reg_v);
+}
+
+void
+port_reg_display(portid_t port_id, uint32_t reg_off)
+{
+ uint32_t reg_v;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ if (port_reg_off_is_invalid(port_id, reg_off))
+ return;
+ reg_v = port_id_pci_reg_read(port_id, reg_off);
+ display_port_reg_value(port_id, reg_off, reg_v);
+}
+
+void
+port_reg_bit_set(portid_t port_id, uint32_t reg_off, uint8_t bit_pos,
+ uint8_t bit_v)
+{
+ uint32_t reg_v;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ if (port_reg_off_is_invalid(port_id, reg_off))
+ return;
+ if (reg_bit_pos_is_invalid(bit_pos))
+ return;
+ if (bit_v > 1) {
+ printf("Invalid bit value %d (must be 0 or 1)\n", (int) bit_v);
+ return;
+ }
+ reg_v = port_id_pci_reg_read(port_id, reg_off);
+ if (bit_v == 0)
+ reg_v &= ~(1 << bit_pos);
+ else
+ reg_v |= (1 << bit_pos);
+ port_id_pci_reg_write(port_id, reg_off, reg_v);
+ display_port_reg_value(port_id, reg_off, reg_v);
+}
+
+void
+port_reg_bit_field_set(portid_t port_id, uint32_t reg_off,
+ uint8_t bit1_pos, uint8_t bit2_pos, uint32_t value)
+{
+ uint32_t max_v;
+ uint32_t reg_v;
+ uint8_t l_bit;
+ uint8_t h_bit;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ if (port_reg_off_is_invalid(port_id, reg_off))
+ return;
+ if (reg_bit_pos_is_invalid(bit1_pos))
+ return;
+ if (reg_bit_pos_is_invalid(bit2_pos))
+ return;
+ if (bit1_pos > bit2_pos)
+ l_bit = bit2_pos, h_bit = bit1_pos;
+ else
+ l_bit = bit1_pos, h_bit = bit2_pos;
+
+ if ((h_bit - l_bit) < 31)
+ max_v = (1 << (h_bit - l_bit + 1)) - 1;
+ else
+ max_v = 0xFFFFFFFF;
+
+ if (value > max_v) {
+ printf("Invalid value %u (0x%x) must be < %u (0x%x)\n",
+ (unsigned)value, (unsigned)value,
+ (unsigned)max_v, (unsigned)max_v);
+ return;
+ }
+ reg_v = port_id_pci_reg_read(port_id, reg_off);
+ reg_v &= ~(max_v << l_bit); /* Keep unchanged bits */
+ reg_v |= (value << l_bit); /* Set changed bits */
+ port_id_pci_reg_write(port_id, reg_off, reg_v);
+ display_port_reg_value(port_id, reg_off, reg_v);
+}
+
+void
+port_reg_set(portid_t port_id, uint32_t reg_off, uint32_t reg_v)
+{
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ if (port_reg_off_is_invalid(port_id, reg_off))
+ return;
+ port_id_pci_reg_write(port_id, reg_off, reg_v);
+ display_port_reg_value(port_id, reg_off, reg_v);
+}
+
+void
+port_mtu_set(portid_t port_id, uint16_t mtu)
+{
+ int diag;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ diag = rte_eth_dev_set_mtu(port_id, mtu);
+ if (diag == 0)
+ return;
+ printf("Set MTU failed. diag=%d\n", diag);
+}
+
+/* Generic flow management functions. */
+
+/** Generate flow_item[] entry. */
+#define MK_FLOW_ITEM(t, s) \
+ [RTE_FLOW_ITEM_TYPE_ ## t] = { \
+ .name = # t, \
+ .size = s, \
+ }
+
+/** Information about known flow pattern items. */
+static const struct {
+ const char *name;
+ size_t size;
+} flow_item[] = {
+ MK_FLOW_ITEM(END, 0),
+ MK_FLOW_ITEM(VOID, 0),
+ MK_FLOW_ITEM(INVERT, 0),
+ MK_FLOW_ITEM(ANY, sizeof(struct rte_flow_item_any)),
+ MK_FLOW_ITEM(PF, 0),
+ MK_FLOW_ITEM(VF, sizeof(struct rte_flow_item_vf)),
+ MK_FLOW_ITEM(PORT, sizeof(struct rte_flow_item_port)),
+ MK_FLOW_ITEM(RAW, sizeof(struct rte_flow_item_raw)), /* +pattern[] */
+ MK_FLOW_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
+ MK_FLOW_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
+ MK_FLOW_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
+ MK_FLOW_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
+ MK_FLOW_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
+ MK_FLOW_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
+ MK_FLOW_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
+ MK_FLOW_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
+ MK_FLOW_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
+ MK_FLOW_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
+ MK_FLOW_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
+};
+
+/** Compute storage space needed by item specification. */
+static void
+flow_item_spec_size(const struct rte_flow_item *item,
+ size_t *size, size_t *pad)
+{
+ if (!item->spec)
+ goto empty;
+ switch (item->type) {
+ union {
+ const struct rte_flow_item_raw *raw;
+ } spec;
+
+ case RTE_FLOW_ITEM_TYPE_RAW:
+ spec.raw = item->spec;
+ *size = offsetof(struct rte_flow_item_raw, pattern) +
+ spec.raw->length * sizeof(*spec.raw->pattern);
+ break;
+ default:
+empty:
+ *size = 0;
+ break;
+ }
+ *pad = RTE_ALIGN_CEIL(*size, sizeof(double)) - *size;
+}
+
+/** Generate flow_action[] entry. */
+#define MK_FLOW_ACTION(t, s) \
+ [RTE_FLOW_ACTION_TYPE_ ## t] = { \
+ .name = # t, \
+ .size = s, \
+ }
+
+/** Information about known flow actions. */
+static const struct {
+ const char *name;
+ size_t size;
+} flow_action[] = {
+ MK_FLOW_ACTION(END, 0),
+ MK_FLOW_ACTION(VOID, 0),
+ MK_FLOW_ACTION(PASSTHRU, 0),
+ MK_FLOW_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
+ MK_FLOW_ACTION(FLAG, 0),
+ MK_FLOW_ACTION(QUEUE, sizeof(struct rte_flow_action_queue)),
+ MK_FLOW_ACTION(DROP, 0),
+ MK_FLOW_ACTION(COUNT, 0),
+ MK_FLOW_ACTION(DUP, sizeof(struct rte_flow_action_dup)),
+ MK_FLOW_ACTION(RSS, sizeof(struct rte_flow_action_rss)), /* +queue[] */
+ MK_FLOW_ACTION(PF, 0),
+ MK_FLOW_ACTION(VF, sizeof(struct rte_flow_action_vf)),
+};
+
+/** Compute storage space needed by action configuration. */
+static void
+flow_action_conf_size(const struct rte_flow_action *action,
+ size_t *size, size_t *pad)
+{
+ if (!action->conf)
+ goto empty;
+ switch (action->type) {
+ union {
+ const struct rte_flow_action_rss *rss;
+ } conf;
+
+ case RTE_FLOW_ACTION_TYPE_RSS:
+ conf.rss = action->conf;
+ *size = offsetof(struct rte_flow_action_rss, queue) +
+ conf.rss->num * sizeof(*conf.rss->queue);
+ break;
+ default:
+empty:
+ *size = 0;
+ break;
+ }
+ *pad = RTE_ALIGN_CEIL(*size, sizeof(double)) - *size;
+}
+
+/** Generate a port_flow entry from attributes/pattern/actions. */
+static struct port_flow *
+port_flow_new(const struct rte_flow_attr *attr,
+ const struct rte_flow_item *pattern,
+ const struct rte_flow_action *actions)
+{
+ const struct rte_flow_item *item;
+ const struct rte_flow_action *action;
+ struct port_flow *pf = NULL;
+ size_t tmp;
+ size_t pad;
+ size_t off1 = 0;
+ size_t off2 = 0;
+ int err = ENOTSUP;
+
+store:
+ item = pattern;
+ if (pf)
+ pf->pattern = (void *)&pf->data[off1];
+ do {
+ struct rte_flow_item *dst = NULL;
+
+ if ((unsigned int)item->type >= RTE_DIM(flow_item) ||
+ !flow_item[item->type].name)
+ goto notsup;
+ if (pf)
+ dst = memcpy(pf->data + off1, item, sizeof(*item));
+ off1 += sizeof(*item);
+ flow_item_spec_size(item, &tmp, &pad);
+ if (item->spec) {
+ if (pf)
+ dst->spec = memcpy(pf->data + off2,
+ item->spec, tmp);
+ off2 += tmp + pad;
+ }
+ if (item->last) {
+ if (pf)
+ dst->last = memcpy(pf->data + off2,
+ item->last, tmp);
+ off2 += tmp + pad;
+ }
+ if (item->mask) {
+ if (pf)
+ dst->mask = memcpy(pf->data + off2,
+ item->mask, tmp);
+ off2 += tmp + pad;
+ }
+ off2 = RTE_ALIGN_CEIL(off2, sizeof(double));
+ } while ((item++)->type != RTE_FLOW_ITEM_TYPE_END);
+ off1 = RTE_ALIGN_CEIL(off1, sizeof(double));
+ action = actions;
+ if (pf)
+ pf->actions = (void *)&pf->data[off1];
+ do {
+ struct rte_flow_action *dst = NULL;
+
+ if ((unsigned int)action->type >= RTE_DIM(flow_action) ||
+ !flow_action[action->type].name)
+ goto notsup;
+ if (pf)
+ dst = memcpy(pf->data + off1, action, sizeof(*action));
+ off1 += sizeof(*action);
+ flow_action_conf_size(action, &tmp, &pad);
+ if (action->conf) {
+ if (pf)
+ dst->conf = memcpy(pf->data + off2,
+ action->conf, tmp);
+ off2 += tmp + pad;
+ }
+ off2 = RTE_ALIGN_CEIL(off2, sizeof(double));
+ } while ((action++)->type != RTE_FLOW_ACTION_TYPE_END);
+ if (pf != NULL)
+ return pf;
+ off1 = RTE_ALIGN_CEIL(off1, sizeof(double));
+ tmp = RTE_ALIGN_CEIL(offsetof(struct port_flow, data), sizeof(double));
+ pf = calloc(1, tmp + off1 + off2);
+ if (pf == NULL)
+ err = errno;
+ else {
+ *pf = (const struct port_flow){
+ .size = tmp + off1 + off2,
+ .attr = *attr,
+ };
+ tmp -= offsetof(struct port_flow, data);
+ off2 = tmp + off1;
+ off1 = tmp;
+ goto store;
+ }
+notsup:
+ rte_errno = err;
+ return NULL;
+}
+
+/** Print a message out of a flow error. */
+static int
+port_flow_complain(struct rte_flow_error *error)
+{
+ static const char *const errstrlist[] = {
+ [RTE_FLOW_ERROR_TYPE_NONE] = "no error",
+ [RTE_FLOW_ERROR_TYPE_UNSPECIFIED] = "cause unspecified",
+ [RTE_FLOW_ERROR_TYPE_HANDLE] = "flow rule (handle)",
+ [RTE_FLOW_ERROR_TYPE_ATTR_GROUP] = "group field",
+ [RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY] = "priority field",
+ [RTE_FLOW_ERROR_TYPE_ATTR_INGRESS] = "ingress field",
+ [RTE_FLOW_ERROR_TYPE_ATTR_EGRESS] = "egress field",
+ [RTE_FLOW_ERROR_TYPE_ATTR] = "attributes structure",
+ [RTE_FLOW_ERROR_TYPE_ITEM_NUM] = "pattern length",
+ [RTE_FLOW_ERROR_TYPE_ITEM] = "specific pattern item",
+ [RTE_FLOW_ERROR_TYPE_ACTION_NUM] = "number of actions",
+ [RTE_FLOW_ERROR_TYPE_ACTION] = "specific action",
+ };
+ const char *errstr;
+ char buf[32];
+ int err = rte_errno;
+
+ if ((unsigned int)error->type >= RTE_DIM(errstrlist) ||
+ !errstrlist[error->type])
+ errstr = "unknown type";
+ else
+ errstr = errstrlist[error->type];
+ printf("Caught error type %d (%s): %s%s\n",
+ error->type, errstr,
+ error->cause ? (snprintf(buf, sizeof(buf), "cause: %p, ",
+ error->cause), buf) : "",
+ error->message ? error->message : "(no stated reason)");
+ return -err;
+}
+
+/** Validate flow rule. */
+int
+port_flow_validate(portid_t port_id,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item *pattern,
+ const struct rte_flow_action *actions)
+{
+ struct rte_flow_error error;
+
+ /* Poisoning to make sure PMDs update it in case of error. */
+ memset(&error, 0x11, sizeof(error));
+ if (rte_flow_validate(port_id, attr, pattern, actions, &error))
+ return port_flow_complain(&error);
+ printf("Flow rule validated\n");
+ return 0;
+}
+
+/** Create flow rule. */
+int
+port_flow_create(portid_t port_id,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item *pattern,
+ const struct rte_flow_action *actions)
+{
+ struct rte_flow *flow;
+ struct rte_port *port;
+ struct port_flow *pf;
+ uint32_t id;
+ struct rte_flow_error error;
+
+ /* Poisoning to make sure PMDs update it in case of error. */
+ memset(&error, 0x22, sizeof(error));
+ flow = rte_flow_create(port_id, attr, pattern, actions, &error);
+ if (!flow)
+ return port_flow_complain(&error);
+ port = &ports[port_id];
+ if (port->flow_list) {
+ if (port->flow_list->id == UINT32_MAX) {
+ printf("Highest rule ID is already assigned, delete"
+ " it first");
+ rte_flow_destroy(port_id, flow, NULL);
+ return -ENOMEM;
+ }
+ id = port->flow_list->id + 1;
+ } else
+ id = 0;
+ pf = port_flow_new(attr, pattern, actions);
+ if (!pf) {
+ int err = rte_errno;
+
+ printf("Cannot allocate flow: %s\n", rte_strerror(err));
+ rte_flow_destroy(port_id, flow, NULL);
+ return -err;
+ }
+ pf->next = port->flow_list;
+ pf->id = id;
+ pf->flow = flow;
+ port->flow_list = pf;
+ printf("Flow rule #%u created\n", pf->id);
+ return 0;
+}
+
+/** Destroy a number of flow rules. */
+int
+port_flow_destroy(portid_t port_id, uint32_t n, const uint32_t *rule)
+{
+ struct rte_port *port;
+ struct port_flow **tmp;
+ uint32_t c = 0;
+ int ret = 0;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN) ||
+ port_id == (portid_t)RTE_PORT_ALL)
+ return -EINVAL;
+ port = &ports[port_id];
+ tmp = &port->flow_list;
+ while (*tmp) {
+ uint32_t i;
+
+ for (i = 0; i != n; ++i) {
+ struct rte_flow_error error;
+ struct port_flow *pf = *tmp;
+
+ if (rule[i] != pf->id)
+ continue;
+ /*
+ * Poisoning to make sure PMDs update it in case
+ * of error.
+ */
+ memset(&error, 0x33, sizeof(error));
+ if (rte_flow_destroy(port_id, pf->flow, &error)) {
+ ret = port_flow_complain(&error);
+ continue;
+ }
+ printf("Flow rule #%u destroyed\n", pf->id);
+ *tmp = pf->next;
+ free(pf);
+ break;
+ }
+ if (i == n)
+ tmp = &(*tmp)->next;
+ ++c;
+ }
+ return ret;
+}
+
+/** Remove all flow rules. */
+int
+port_flow_flush(portid_t port_id)
+{
+ struct rte_flow_error error;
+ struct rte_port *port;
+ int ret = 0;
+
+ /* Poisoning to make sure PMDs update it in case of error. */
+ memset(&error, 0x44, sizeof(error));
+ if (rte_flow_flush(port_id, &error)) {
+ ret = port_flow_complain(&error);
+ if (port_id_is_invalid(port_id, DISABLED_WARN) ||
+ port_id == (portid_t)RTE_PORT_ALL)
+ return ret;
+ }
+ port = &ports[port_id];
+ while (port->flow_list) {
+ struct port_flow *pf = port->flow_list->next;
+
+ free(port->flow_list);
+ port->flow_list = pf;
+ }
+ return ret;
+}
+
+/** Query a flow rule. */
+int
+port_flow_query(portid_t port_id, uint32_t rule,
+ enum rte_flow_action_type action)
+{
+ struct rte_flow_error error;
+ struct rte_port *port;
+ struct port_flow *pf;
+ const char *name;
+ union {
+ struct rte_flow_query_count count;
+ } query;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN) ||
+ port_id == (portid_t)RTE_PORT_ALL)
+ return -EINVAL;
+ port = &ports[port_id];
+ for (pf = port->flow_list; pf; pf = pf->next)
+ if (pf->id == rule)
+ break;
+ if (!pf) {
+ printf("Flow rule #%u not found\n", rule);
+ return -ENOENT;
+ }
+ if ((unsigned int)action >= RTE_DIM(flow_action) ||
+ !flow_action[action].name)
+ name = "unknown";
+ else
+ name = flow_action[action].name;
+ switch (action) {
+ case RTE_FLOW_ACTION_TYPE_COUNT:
+ break;
+ default:
+ printf("Cannot query action type %d (%s)\n", action, name);
+ return -ENOTSUP;
+ }
+ /* Poisoning to make sure PMDs update it in case of error. */
+ memset(&error, 0x55, sizeof(error));
+ memset(&query, 0, sizeof(query));
+ if (rte_flow_query(port_id, pf->flow, action, &query, &error))
+ return port_flow_complain(&error);
+ switch (action) {
+ case RTE_FLOW_ACTION_TYPE_COUNT:
+ printf("%s:\n"
+ " hits_set: %u\n"
+ " bytes_set: %u\n"
+ " hits: %" PRIu64 "\n"
+ " bytes: %" PRIu64 "\n",
+ name,
+ query.count.hits_set,
+ query.count.bytes_set,
+ query.count.hits,
+ query.count.bytes);
+ break;
+ default:
+ printf("Cannot display result for action type %d (%s)\n",
+ action, name);
+ break;
+ }
+ return 0;
+}
+
+/** List flow rules. */
+void
+port_flow_list(portid_t port_id, uint32_t n, const uint32_t group[n])
+{
+ struct rte_port *port;
+ struct port_flow *pf;
+ struct port_flow *list = NULL;
+ uint32_t i;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN) ||
+ port_id == (portid_t)RTE_PORT_ALL)
+ return;
+ port = &ports[port_id];
+ if (!port->flow_list)
+ return;
+ /* Sort flows by group, priority and ID. */
+ for (pf = port->flow_list; pf != NULL; pf = pf->next) {
+ struct port_flow **tmp;
+
+ if (n) {
+ /* Filter out unwanted groups. */
+ for (i = 0; i != n; ++i)
+ if (pf->attr.group == group[i])
+ break;
+ if (i == n)
+ continue;
+ }
+ tmp = &list;
+ while (*tmp &&
+ (pf->attr.group > (*tmp)->attr.group ||
+ (pf->attr.group == (*tmp)->attr.group &&
+ pf->attr.priority > (*tmp)->attr.priority) ||
+ (pf->attr.group == (*tmp)->attr.group &&
+ pf->attr.priority == (*tmp)->attr.priority &&
+ pf->id > (*tmp)->id)))
+ tmp = &(*tmp)->tmp;
+ pf->tmp = *tmp;
+ *tmp = pf;
+ }
+ printf("ID\tGroup\tPrio\tAttr\tRule\n");
+ for (pf = list; pf != NULL; pf = pf->tmp) {
+ const struct rte_flow_item *item = pf->pattern;
+ const struct rte_flow_action *action = pf->actions;
+
+ printf("%" PRIu32 "\t%" PRIu32 "\t%" PRIu32 "\t%c%c\t",
+ pf->id,
+ pf->attr.group,
+ pf->attr.priority,
+ pf->attr.ingress ? 'i' : '-',
+ pf->attr.egress ? 'e' : '-');
+ while (item->type != RTE_FLOW_ITEM_TYPE_END) {
+ if (item->type != RTE_FLOW_ITEM_TYPE_VOID)
+ printf("%s ", flow_item[item->type].name);
+ ++item;
+ }
+ printf("=>");
+ while (action->type != RTE_FLOW_ACTION_TYPE_END) {
+ if (action->type != RTE_FLOW_ACTION_TYPE_VOID)
+ printf(" %s", flow_action[action->type].name);
+ ++action;
+ }
+ printf("\n");
+ }
+}
+
+/*
+ * RX/TX ring descriptors display functions.
+ */
+int
+rx_queue_id_is_invalid(queueid_t rxq_id)
+{
+ if (rxq_id < nb_rxq)
+ return 0;
+ printf("Invalid RX queue %d (must be < nb_rxq=%d)\n", rxq_id, nb_rxq);
+ return 1;
+}
+
+int
+tx_queue_id_is_invalid(queueid_t txq_id)
+{
+ if (txq_id < nb_txq)
+ return 0;
+ printf("Invalid TX queue %d (must be < nb_rxq=%d)\n", txq_id, nb_txq);
+ return 1;
+}
+
+static int
+rx_desc_id_is_invalid(uint16_t rxdesc_id)
+{
+ if (rxdesc_id < nb_rxd)
+ return 0;
+ printf("Invalid RX descriptor %d (must be < nb_rxd=%d)\n",
+ rxdesc_id, nb_rxd);
+ return 1;
+}
+
+static int
+tx_desc_id_is_invalid(uint16_t txdesc_id)
+{
+ if (txdesc_id < nb_txd)
+ return 0;
+ printf("Invalid TX descriptor %d (must be < nb_txd=%d)\n",
+ txdesc_id, nb_txd);
+ return 1;
+}
+
+static const struct rte_memzone *
+ring_dma_zone_lookup(const char *ring_name, uint8_t port_id, uint16_t q_id)
+{
+ char mz_name[RTE_MEMZONE_NAMESIZE];
+ const struct rte_memzone *mz;
+
+ snprintf(mz_name, sizeof(mz_name), "%s_%s_%d_%d",
+ ports[port_id].dev_info.driver_name, ring_name, port_id, q_id);
+ mz = rte_memzone_lookup(mz_name);
+ if (mz == NULL)
+ printf("%s ring memory zoneof (port %d, queue %d) not"
+ "found (zone name = %s\n",
+ ring_name, port_id, q_id, mz_name);
+ return mz;
+}
+
+union igb_ring_dword {
+ uint64_t dword;
+ struct {
+#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+ uint32_t lo;
+ uint32_t hi;
+#else
+ uint32_t hi;
+ uint32_t lo;
+#endif
+ } words;
+};
+
+struct igb_ring_desc_32_bytes {
+ union igb_ring_dword lo_dword;
+ union igb_ring_dword hi_dword;
+ union igb_ring_dword resv1;
+ union igb_ring_dword resv2;
+};
+
+struct igb_ring_desc_16_bytes {
+ union igb_ring_dword lo_dword;
+ union igb_ring_dword hi_dword;
+};
+
+static void
+ring_rxd_display_dword(union igb_ring_dword dword)
+{
+ printf(" 0x%08X - 0x%08X\n", (unsigned)dword.words.lo,
+ (unsigned)dword.words.hi);
+}
+
+static void
+ring_rx_descriptor_display(const struct rte_memzone *ring_mz,
+#ifndef RTE_LIBRTE_I40E_16BYTE_RX_DESC
+ uint8_t port_id,
+#else
+ __rte_unused uint8_t port_id,
+#endif
+ uint16_t desc_id)
+{
+ struct igb_ring_desc_16_bytes *ring =
+ (struct igb_ring_desc_16_bytes *)ring_mz->addr;
+#ifndef RTE_LIBRTE_I40E_16BYTE_RX_DESC
+ struct rte_eth_dev_info dev_info;
+
+ memset(&dev_info, 0, sizeof(dev_info));
+ rte_eth_dev_info_get(port_id, &dev_info);
+ if (strstr(dev_info.driver_name, "i40e") != NULL) {
+ /* 32 bytes RX descriptor, i40e only */
+ struct igb_ring_desc_32_bytes *ring =
+ (struct igb_ring_desc_32_bytes *)ring_mz->addr;
+ ring[desc_id].lo_dword.dword =
+ rte_le_to_cpu_64(ring[desc_id].lo_dword.dword);
+ ring_rxd_display_dword(ring[desc_id].lo_dword);
+ ring[desc_id].hi_dword.dword =
+ rte_le_to_cpu_64(ring[desc_id].hi_dword.dword);
+ ring_rxd_display_dword(ring[desc_id].hi_dword);
+ ring[desc_id].resv1.dword =
+ rte_le_to_cpu_64(ring[desc_id].resv1.dword);
+ ring_rxd_display_dword(ring[desc_id].resv1);
+ ring[desc_id].resv2.dword =
+ rte_le_to_cpu_64(ring[desc_id].resv2.dword);
+ ring_rxd_display_dword(ring[desc_id].resv2);
+
+ return;
+ }
+#endif
+ /* 16 bytes RX descriptor */
+ ring[desc_id].lo_dword.dword =
+ rte_le_to_cpu_64(ring[desc_id].lo_dword.dword);
+ ring_rxd_display_dword(ring[desc_id].lo_dword);
+ ring[desc_id].hi_dword.dword =
+ rte_le_to_cpu_64(ring[desc_id].hi_dword.dword);
+ ring_rxd_display_dword(ring[desc_id].hi_dword);
+}
+
+static void
+ring_tx_descriptor_display(const struct rte_memzone *ring_mz, uint16_t desc_id)
+{
+ struct igb_ring_desc_16_bytes *ring;
+ struct igb_ring_desc_16_bytes txd;
+
+ ring = (struct igb_ring_desc_16_bytes *)ring_mz->addr;
+ txd.lo_dword.dword = rte_le_to_cpu_64(ring[desc_id].lo_dword.dword);
+ txd.hi_dword.dword = rte_le_to_cpu_64(ring[desc_id].hi_dword.dword);
+ printf(" 0x%08X - 0x%08X / 0x%08X - 0x%08X\n",
+ (unsigned)txd.lo_dword.words.lo,
+ (unsigned)txd.lo_dword.words.hi,
+ (unsigned)txd.hi_dword.words.lo,
+ (unsigned)txd.hi_dword.words.hi);
+}
+
+void
+rx_ring_desc_display(portid_t port_id, queueid_t rxq_id, uint16_t rxd_id)
+{
+ const struct rte_memzone *rx_mz;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ if (rx_queue_id_is_invalid(rxq_id))
+ return;
+ if (rx_desc_id_is_invalid(rxd_id))
+ return;
+ rx_mz = ring_dma_zone_lookup("rx_ring", port_id, rxq_id);
+ if (rx_mz == NULL)
+ return;
+ ring_rx_descriptor_display(rx_mz, port_id, rxd_id);
+}
+
+void
+tx_ring_desc_display(portid_t port_id, queueid_t txq_id, uint16_t txd_id)
+{
+ const struct rte_memzone *tx_mz;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ if (tx_queue_id_is_invalid(txq_id))
+ return;
+ if (tx_desc_id_is_invalid(txd_id))
+ return;
+ tx_mz = ring_dma_zone_lookup("tx_ring", port_id, txq_id);
+ if (tx_mz == NULL)
+ return;
+ ring_tx_descriptor_display(tx_mz, txd_id);
+}
+
+void
+fwd_lcores_config_display(void)
+{
+ lcoreid_t lc_id;
+
+ printf("List of forwarding lcores:");
+ for (lc_id = 0; lc_id < nb_cfg_lcores; lc_id++)
+ printf(" %2u", fwd_lcores_cpuids[lc_id]);
+ printf("\n");
+}
+void
+rxtx_config_display(void)
+{
+ printf(" %s packet forwarding%s - CRC stripping %s - "
+ "packets/burst=%d\n", cur_fwd_eng->fwd_mode_name,
+ retry_enabled == 0 ? "" : " with retry",
+ rx_mode.hw_strip_crc ? "enabled" : "disabled",
+ nb_pkt_per_burst);
+
+ if (cur_fwd_eng == &tx_only_engine || cur_fwd_eng == &flow_gen_engine)
+ printf(" packet len=%u - nb packet segments=%d\n",
+ (unsigned)tx_pkt_length, (int) tx_pkt_nb_segs);
+
+ struct rte_eth_rxconf *rx_conf = &ports[0].rx_conf;
+ struct rte_eth_txconf *tx_conf = &ports[0].tx_conf;
+
+ printf(" nb forwarding cores=%d - nb forwarding ports=%d\n",
+ nb_fwd_lcores, nb_fwd_ports);
+ printf(" RX queues=%d - RX desc=%d - RX free threshold=%d\n",
+ nb_rxq, nb_rxd, rx_conf->rx_free_thresh);
+ printf(" RX threshold registers: pthresh=%d hthresh=%d wthresh=%d\n",
+ rx_conf->rx_thresh.pthresh, rx_conf->rx_thresh.hthresh,
+ rx_conf->rx_thresh.wthresh);
+ printf(" TX queues=%d - TX desc=%d - TX free threshold=%d\n",
+ nb_txq, nb_txd, tx_conf->tx_free_thresh);
+ printf(" TX threshold registers: pthresh=%d hthresh=%d wthresh=%d\n",
+ tx_conf->tx_thresh.pthresh, tx_conf->tx_thresh.hthresh,
+ tx_conf->tx_thresh.wthresh);
+ printf(" TX RS bit threshold=%d - TXQ flags=0x%"PRIx32"\n",
+ tx_conf->tx_rs_thresh, tx_conf->txq_flags);
+}
+
+void
+port_rss_reta_info(portid_t port_id,
+ struct rte_eth_rss_reta_entry64 *reta_conf,
+ uint16_t nb_entries)
+{
+ uint16_t i, idx, shift;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ ret = rte_eth_dev_rss_reta_query(port_id, reta_conf, nb_entries);
+ if (ret != 0) {
+ printf("Failed to get RSS RETA info, return code = %d\n", ret);
+ return;
+ }
+
+ for (i = 0; i < nb_entries; i++) {
+ idx = i / RTE_RETA_GROUP_SIZE;
+ shift = i % RTE_RETA_GROUP_SIZE;
+ if (!(reta_conf[idx].mask & (1ULL << shift)))
+ continue;
+ printf("RSS RETA configuration: hash index=%u, queue=%u\n",
+ i, reta_conf[idx].reta[shift]);
+ }
+}
+
+/*
+ * Displays the RSS hash functions of a port, and, optionaly, the RSS hash
+ * key of the port.
+ */
+void
+port_rss_hash_conf_show(portid_t port_id, char rss_info[], int show_rss_key)
+{
+ struct rte_eth_rss_conf rss_conf;
+ uint8_t rss_key[RSS_HASH_KEY_LENGTH];
+ uint64_t rss_hf;
+ uint8_t i;
+ int diag;
+ struct rte_eth_dev_info dev_info;
+ uint8_t hash_key_size;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ memset(&dev_info, 0, sizeof(dev_info));
+ rte_eth_dev_info_get(port_id, &dev_info);
+ if (dev_info.hash_key_size > 0 &&
+ dev_info.hash_key_size <= sizeof(rss_key))
+ hash_key_size = dev_info.hash_key_size;
+ else {
+ printf("dev_info did not provide a valid hash key size\n");
+ return;
+ }
+
+ rss_conf.rss_hf = 0;
+ for (i = 0; i < RTE_DIM(rss_type_table); i++) {
+ if (!strcmp(rss_info, rss_type_table[i].str))
+ rss_conf.rss_hf = rss_type_table[i].rss_type;
+ }
+
+ /* Get RSS hash key if asked to display it */
+ rss_conf.rss_key = (show_rss_key) ? rss_key : NULL;
+ rss_conf.rss_key_len = hash_key_size;
+ diag = rte_eth_dev_rss_hash_conf_get(port_id, &rss_conf);
+ if (diag != 0) {
+ switch (diag) {
+ case -ENODEV:
+ printf("port index %d invalid\n", port_id);
+ break;
+ case -ENOTSUP:
+ printf("operation not supported by device\n");
+ break;
+ default:
+ printf("operation failed - diag=%d\n", diag);
+ break;
+ }
+ return;
+ }
+ rss_hf = rss_conf.rss_hf;
+ if (rss_hf == 0) {
+ printf("RSS disabled\n");
+ return;
+ }
+ printf("RSS functions:\n ");
+ for (i = 0; i < RTE_DIM(rss_type_table); i++) {
+ if (rss_hf & rss_type_table[i].rss_type)
+ printf("%s ", rss_type_table[i].str);
+ }
+ printf("\n");
+ if (!show_rss_key)
+ return;
+ printf("RSS key:\n");
+ for (i = 0; i < hash_key_size; i++)
+ printf("%02X", rss_key[i]);
+ printf("\n");
+}
+
+void
+port_rss_hash_key_update(portid_t port_id, char rss_type[], uint8_t *hash_key,
+ uint hash_key_len)
+{
+ struct rte_eth_rss_conf rss_conf;
+ int diag;
+ unsigned int i;
+
+ rss_conf.rss_key = NULL;
+ rss_conf.rss_key_len = hash_key_len;
+ rss_conf.rss_hf = 0;
+ for (i = 0; i < RTE_DIM(rss_type_table); i++) {
+ if (!strcmp(rss_type_table[i].str, rss_type))
+ rss_conf.rss_hf = rss_type_table[i].rss_type;
+ }
+ diag = rte_eth_dev_rss_hash_conf_get(port_id, &rss_conf);
+ if (diag == 0) {
+ rss_conf.rss_key = hash_key;
+ diag = rte_eth_dev_rss_hash_update(port_id, &rss_conf);
+ }
+ if (diag == 0)
+ return;
+
+ switch (diag) {
+ case -ENODEV:
+ printf("port index %d invalid\n", port_id);
+ break;
+ case -ENOTSUP:
+ printf("operation not supported by device\n");
+ break;
+ default:
+ printf("operation failed - diag=%d\n", diag);
+ break;
+ }
+}
+
+/*
+ * Setup forwarding configuration for each logical core.
+ */
+static void
+setup_fwd_config_of_each_lcore(struct fwd_config *cfg)
+{
+ streamid_t nb_fs_per_lcore;
+ streamid_t nb_fs;
+ streamid_t sm_id;
+ lcoreid_t nb_extra;
+ lcoreid_t nb_fc;
+ lcoreid_t nb_lc;
+ lcoreid_t lc_id;
+
+ nb_fs = cfg->nb_fwd_streams;
+ nb_fc = cfg->nb_fwd_lcores;
+ if (nb_fs <= nb_fc) {
+ nb_fs_per_lcore = 1;
+ nb_extra = 0;
+ } else {
+ nb_fs_per_lcore = (streamid_t) (nb_fs / nb_fc);
+ nb_extra = (lcoreid_t) (nb_fs % nb_fc);
+ }
+
+ nb_lc = (lcoreid_t) (nb_fc - nb_extra);
+ sm_id = 0;
+ for (lc_id = 0; lc_id < nb_lc; lc_id++) {
+ fwd_lcores[lc_id]->stream_idx = sm_id;
+ fwd_lcores[lc_id]->stream_nb = nb_fs_per_lcore;
+ sm_id = (streamid_t) (sm_id + nb_fs_per_lcore);
+ }
+
+ /*
+ * Assign extra remaining streams, if any.
+ */
+ nb_fs_per_lcore = (streamid_t) (nb_fs_per_lcore + 1);
+ for (lc_id = 0; lc_id < nb_extra; lc_id++) {
+ fwd_lcores[nb_lc + lc_id]->stream_idx = sm_id;
+ fwd_lcores[nb_lc + lc_id]->stream_nb = nb_fs_per_lcore;
+ sm_id = (streamid_t) (sm_id + nb_fs_per_lcore);
+ }
+}
+
+static void
+simple_fwd_config_setup(void)
+{
+ portid_t i;
+ portid_t j;
+ portid_t inc = 2;
+
+ if (port_topology == PORT_TOPOLOGY_CHAINED ||
+ port_topology == PORT_TOPOLOGY_LOOP) {
+ inc = 1;
+ } else if (nb_fwd_ports % 2) {
+ printf("\nWarning! Cannot handle an odd number of ports "
+ "with the current port topology. Configuration "
+ "must be changed to have an even number of ports, "
+ "or relaunch application with "
+ "--port-topology=chained\n\n");
+ }
+
+ cur_fwd_config.nb_fwd_ports = (portid_t) nb_fwd_ports;
+ cur_fwd_config.nb_fwd_streams =
+ (streamid_t) cur_fwd_config.nb_fwd_ports;
+
+ /* reinitialize forwarding streams */
+ init_fwd_streams();
+
+ /*
+ * In the simple forwarding test, the number of forwarding cores
+ * must be lower or equal to the number of forwarding ports.
+ */
+ cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores;
+ if (cur_fwd_config.nb_fwd_lcores > cur_fwd_config.nb_fwd_ports)
+ cur_fwd_config.nb_fwd_lcores =
+ (lcoreid_t) cur_fwd_config.nb_fwd_ports;
+ setup_fwd_config_of_each_lcore(&cur_fwd_config);
+
+ for (i = 0; i < cur_fwd_config.nb_fwd_ports; i = (portid_t) (i + inc)) {
+ if (port_topology != PORT_TOPOLOGY_LOOP)
+ j = (portid_t) ((i + 1) % cur_fwd_config.nb_fwd_ports);
+ else
+ j = i;
+ fwd_streams[i]->rx_port = fwd_ports_ids[i];
+ fwd_streams[i]->rx_queue = 0;
+ fwd_streams[i]->tx_port = fwd_ports_ids[j];
+ fwd_streams[i]->tx_queue = 0;
+ fwd_streams[i]->peer_addr = j;
+ fwd_streams[i]->retry_enabled = retry_enabled;
+
+ if (port_topology == PORT_TOPOLOGY_PAIRED) {
+ fwd_streams[j]->rx_port = fwd_ports_ids[j];
+ fwd_streams[j]->rx_queue = 0;
+ fwd_streams[j]->tx_port = fwd_ports_ids[i];
+ fwd_streams[j]->tx_queue = 0;
+ fwd_streams[j]->peer_addr = i;
+ fwd_streams[j]->retry_enabled = retry_enabled;
+ }
+ }
+}
+
+/**
+ * For the RSS forwarding test all streams distributed over lcores. Each stream
+ * being composed of a RX queue to poll on a RX port for input messages,
+ * associated with a TX queue of a TX port where to send forwarded packets.
+ * All packets received on the RX queue of index "RxQj" of the RX port "RxPi"
+ * are sent on the TX queue "TxQl" of the TX port "TxPk" according to the two
+ * following rules:
+ * - TxPk = (RxPi + 1) if RxPi is even, (RxPi - 1) if RxPi is odd
+ * - TxQl = RxQj
+ */
+static void
+rss_fwd_config_setup(void)
+{
+ portid_t rxp;
+ portid_t txp;
+ queueid_t rxq;
+ queueid_t nb_q;
+ streamid_t sm_id;
+
+ nb_q = nb_rxq;
+ if (nb_q > nb_txq)
+ nb_q = nb_txq;
+ cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores;
+ cur_fwd_config.nb_fwd_ports = nb_fwd_ports;
+ cur_fwd_config.nb_fwd_streams =
+ (streamid_t) (nb_q * cur_fwd_config.nb_fwd_ports);
+
+ if (cur_fwd_config.nb_fwd_streams < cur_fwd_config.nb_fwd_lcores)
+ cur_fwd_config.nb_fwd_lcores =
+ (lcoreid_t)cur_fwd_config.nb_fwd_streams;
+
+ /* reinitialize forwarding streams */
+ init_fwd_streams();
+
+ setup_fwd_config_of_each_lcore(&cur_fwd_config);
+ rxp = 0; rxq = 0;
+ for (sm_id = 0; sm_id < cur_fwd_config.nb_fwd_streams; sm_id++) {
+ struct fwd_stream *fs;
+
+ fs = fwd_streams[sm_id];
+
+ if ((rxp & 0x1) == 0)
+ txp = (portid_t) (rxp + 1);
+ else
+ txp = (portid_t) (rxp - 1);
+ /*
+ * if we are in loopback, simply send stuff out through the
+ * ingress port
+ */
+ if (port_topology == PORT_TOPOLOGY_LOOP)
+ txp = rxp;
+
+ fs->rx_port = fwd_ports_ids[rxp];
+ fs->rx_queue = rxq;
+ fs->tx_port = fwd_ports_ids[txp];
+ fs->tx_queue = rxq;
+ fs->peer_addr = fs->tx_port;
+ fs->retry_enabled = retry_enabled;
+ rxq = (queueid_t) (rxq + 1);
+ if (rxq < nb_q)
+ continue;
+ /*
+ * rxq == nb_q
+ * Restart from RX queue 0 on next RX port
+ */
+ rxq = 0;
+ if (numa_support && (nb_fwd_ports <= (nb_ports >> 1)))
+ rxp = (portid_t)
+ (rxp + ((nb_ports >> 1) / nb_fwd_ports));
+ else
+ rxp = (portid_t) (rxp + 1);
+ }
+}
+
+/**
+ * For the DCB forwarding test, each core is assigned on each traffic class.
+ *
+ * Each core is assigned a multi-stream, each stream being composed of
+ * a RX queue to poll on a RX port for input messages, associated with
+ * a TX queue of a TX port where to send forwarded packets. All RX and
+ * TX queues are mapping to the same traffic class.
+ * If VMDQ and DCB co-exist, each traffic class on different POOLs share
+ * the same core
+ */
+static void
+dcb_fwd_config_setup(void)
+{
+ struct rte_eth_dcb_info rxp_dcb_info, txp_dcb_info;
+ portid_t txp, rxp = 0;
+ queueid_t txq, rxq = 0;
+ lcoreid_t lc_id;
+ uint16_t nb_rx_queue, nb_tx_queue;
+ uint16_t i, j, k, sm_id = 0;
+ uint8_t tc = 0;
+
+ cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores;
+ cur_fwd_config.nb_fwd_ports = nb_fwd_ports;
+ cur_fwd_config.nb_fwd_streams =
+ (streamid_t) (nb_rxq * cur_fwd_config.nb_fwd_ports);
+
+ /* reinitialize forwarding streams */
+ init_fwd_streams();
+ sm_id = 0;
+ txp = 1;
+ /* get the dcb info on the first RX and TX ports */
+ (void)rte_eth_dev_get_dcb_info(fwd_ports_ids[rxp], &rxp_dcb_info);
+ (void)rte_eth_dev_get_dcb_info(fwd_ports_ids[txp], &txp_dcb_info);
+
+ for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++) {
+ fwd_lcores[lc_id]->stream_nb = 0;
+ fwd_lcores[lc_id]->stream_idx = sm_id;
+ for (i = 0; i < ETH_MAX_VMDQ_POOL; i++) {
+ /* if the nb_queue is zero, means this tc is
+ * not enabled on the POOL
+ */
+ if (rxp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue == 0)
+ break;
+ k = fwd_lcores[lc_id]->stream_nb +
+ fwd_lcores[lc_id]->stream_idx;
+ rxq = rxp_dcb_info.tc_queue.tc_rxq[i][tc].base;
+ txq = txp_dcb_info.tc_queue.tc_txq[i][tc].base;
+ nb_rx_queue = txp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue;
+ nb_tx_queue = txp_dcb_info.tc_queue.tc_txq[i][tc].nb_queue;
+ for (j = 0; j < nb_rx_queue; j++) {
+ struct fwd_stream *fs;
+
+ fs = fwd_streams[k + j];
+ fs->rx_port = fwd_ports_ids[rxp];
+ fs->rx_queue = rxq + j;
+ fs->tx_port = fwd_ports_ids[txp];
+ fs->tx_queue = txq + j % nb_tx_queue;
+ fs->peer_addr = fs->tx_port;
+ fs->retry_enabled = retry_enabled;
+ }
+ fwd_lcores[lc_id]->stream_nb +=
+ rxp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue;
+ }
+ sm_id = (streamid_t) (sm_id + fwd_lcores[lc_id]->stream_nb);
+
+ tc++;
+ if (tc < rxp_dcb_info.nb_tcs)
+ continue;
+ /* Restart from TC 0 on next RX port */
+ tc = 0;
+ if (numa_support && (nb_fwd_ports <= (nb_ports >> 1)))
+ rxp = (portid_t)
+ (rxp + ((nb_ports >> 1) / nb_fwd_ports));
+ else
+ rxp++;
+ if (rxp >= nb_fwd_ports)
+ return;
+ /* get the dcb information on next RX and TX ports */
+ if ((rxp & 0x1) == 0)
+ txp = (portid_t) (rxp + 1);
+ else
+ txp = (portid_t) (rxp - 1);
+ rte_eth_dev_get_dcb_info(fwd_ports_ids[rxp], &rxp_dcb_info);
+ rte_eth_dev_get_dcb_info(fwd_ports_ids[txp], &txp_dcb_info);
+ }
+}
+
+static void
+icmp_echo_config_setup(void)
+{
+ portid_t rxp;
+ queueid_t rxq;
+ lcoreid_t lc_id;
+ uint16_t sm_id;
+
+ if ((nb_txq * nb_fwd_ports) < nb_fwd_lcores)
+ cur_fwd_config.nb_fwd_lcores = (lcoreid_t)
+ (nb_txq * nb_fwd_ports);
+ else
+ cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores;
+ cur_fwd_config.nb_fwd_ports = nb_fwd_ports;
+ cur_fwd_config.nb_fwd_streams =
+ (streamid_t) (nb_rxq * cur_fwd_config.nb_fwd_ports);
+ if (cur_fwd_config.nb_fwd_streams < cur_fwd_config.nb_fwd_lcores)
+ cur_fwd_config.nb_fwd_lcores =
+ (lcoreid_t)cur_fwd_config.nb_fwd_streams;
+ if (verbose_level > 0) {
+ printf("%s fwd_cores=%d fwd_ports=%d fwd_streams=%d\n",
+ __FUNCTION__,
+ cur_fwd_config.nb_fwd_lcores,
+ cur_fwd_config.nb_fwd_ports,
+ cur_fwd_config.nb_fwd_streams);
+ }
+
+ /* reinitialize forwarding streams */
+ init_fwd_streams();
+ setup_fwd_config_of_each_lcore(&cur_fwd_config);
+ rxp = 0; rxq = 0;
+ for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++) {
+ if (verbose_level > 0)
+ printf(" core=%d: \n", lc_id);
+ for (sm_id = 0; sm_id < fwd_lcores[lc_id]->stream_nb; sm_id++) {
+ struct fwd_stream *fs;
+ fs = fwd_streams[fwd_lcores[lc_id]->stream_idx + sm_id];
+ fs->rx_port = fwd_ports_ids[rxp];
+ fs->rx_queue = rxq;
+ fs->tx_port = fs->rx_port;
+ fs->tx_queue = rxq;
+ fs->peer_addr = fs->tx_port;
+ fs->retry_enabled = retry_enabled;
+ if (verbose_level > 0)
+ printf(" stream=%d port=%d rxq=%d txq=%d\n",
+ sm_id, fs->rx_port, fs->rx_queue,
+ fs->tx_queue);
+ rxq = (queueid_t) (rxq + 1);
+ if (rxq == nb_rxq) {
+ rxq = 0;
+ rxp = (portid_t) (rxp + 1);
+ }
+ }
+ }
+}
+
+void
+fwd_config_setup(void)
+{
+ cur_fwd_config.fwd_eng = cur_fwd_eng;
+ if (strcmp(cur_fwd_eng->fwd_mode_name, "icmpecho") == 0) {
+ icmp_echo_config_setup();
+ return;
+ }
+ if ((nb_rxq > 1) && (nb_txq > 1)){
+ if (dcb_config)
+ dcb_fwd_config_setup();
+ else
+ rss_fwd_config_setup();
+ }
+ else
+ simple_fwd_config_setup();
+}
+
+void
+pkt_fwd_config_display(struct fwd_config *cfg)
+{
+ struct fwd_stream *fs;
+ lcoreid_t lc_id;
+ streamid_t sm_id;
+
+ printf("%s packet forwarding%s - ports=%d - cores=%d - streams=%d - "
+ "NUMA support %s, MP over anonymous pages %s\n",
+ cfg->fwd_eng->fwd_mode_name,
+ retry_enabled == 0 ? "" : " with retry",
+ cfg->nb_fwd_ports, cfg->nb_fwd_lcores, cfg->nb_fwd_streams,
+ numa_support == 1 ? "enabled" : "disabled",
+ mp_anon != 0 ? "enabled" : "disabled");
+
+ if (retry_enabled)
+ printf("TX retry num: %u, delay between TX retries: %uus\n",
+ burst_tx_retry_num, burst_tx_delay_time);
+ for (lc_id = 0; lc_id < cfg->nb_fwd_lcores; lc_id++) {
+ printf("Logical Core %u (socket %u) forwards packets on "
+ "%d streams:",
+ fwd_lcores_cpuids[lc_id],
+ rte_lcore_to_socket_id(fwd_lcores_cpuids[lc_id]),
+ fwd_lcores[lc_id]->stream_nb);
+ for (sm_id = 0; sm_id < fwd_lcores[lc_id]->stream_nb; sm_id++) {
+ fs = fwd_streams[fwd_lcores[lc_id]->stream_idx + sm_id];
+ printf("\n RX P=%d/Q=%d (socket %u) -> TX "
+ "P=%d/Q=%d (socket %u) ",
+ fs->rx_port, fs->rx_queue,
+ ports[fs->rx_port].socket_id,
+ fs->tx_port, fs->tx_queue,
+ ports[fs->tx_port].socket_id);
+ print_ethaddr("peer=",
+ &peer_eth_addrs[fs->peer_addr]);
+ }
+ printf("\n");
+ }
+ printf("\n");
+}
+
+int
+set_fwd_lcores_list(unsigned int *lcorelist, unsigned int nb_lc)
+{
+ unsigned int i;
+ unsigned int lcore_cpuid;
+ int record_now;
+
+ record_now = 0;
+ again:
+ for (i = 0; i < nb_lc; i++) {
+ lcore_cpuid = lcorelist[i];
+ if (! rte_lcore_is_enabled(lcore_cpuid)) {
+ printf("lcore %u not enabled\n", lcore_cpuid);
+ return -1;
+ }
+ if (lcore_cpuid == rte_get_master_lcore()) {
+ printf("lcore %u cannot be masked on for running "
+ "packet forwarding, which is the master lcore "
+ "and reserved for command line parsing only\n",
+ lcore_cpuid);
+ return -1;
+ }
+ if (record_now)
+ fwd_lcores_cpuids[i] = lcore_cpuid;
+ }
+ if (record_now == 0) {
+ record_now = 1;
+ goto again;
+ }
+ nb_cfg_lcores = (lcoreid_t) nb_lc;
+ if (nb_fwd_lcores != (lcoreid_t) nb_lc) {
+ printf("previous number of forwarding cores %u - changed to "
+ "number of configured cores %u\n",
+ (unsigned int) nb_fwd_lcores, nb_lc);
+ nb_fwd_lcores = (lcoreid_t) nb_lc;
+ }
+
+ return 0;
+}
+
+int
+set_fwd_lcores_mask(uint64_t lcoremask)
+{
+ unsigned int lcorelist[64];
+ unsigned int nb_lc;
+ unsigned int i;
+
+ if (lcoremask == 0) {
+ printf("Invalid NULL mask of cores\n");
+ return -1;
+ }
+ nb_lc = 0;
+ for (i = 0; i < 64; i++) {
+ if (! ((uint64_t)(1ULL << i) & lcoremask))
+ continue;
+ lcorelist[nb_lc++] = i;
+ }
+ return set_fwd_lcores_list(lcorelist, nb_lc);
+}
+
+void
+set_fwd_lcores_number(uint16_t nb_lc)
+{
+ if (nb_lc > nb_cfg_lcores) {
+ printf("nb fwd cores %u > %u (max. number of configured "
+ "lcores) - ignored\n",
+ (unsigned int) nb_lc, (unsigned int) nb_cfg_lcores);
+ return;
+ }
+ nb_fwd_lcores = (lcoreid_t) nb_lc;
+ printf("Number of forwarding cores set to %u\n",
+ (unsigned int) nb_fwd_lcores);
+}
+
+void
+set_fwd_ports_list(unsigned int *portlist, unsigned int nb_pt)
+{
+ unsigned int i;
+ portid_t port_id;
+ int record_now;
+
+ record_now = 0;
+ again:
+ for (i = 0; i < nb_pt; i++) {
+ port_id = (portid_t) portlist[i];
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ if (record_now)
+ fwd_ports_ids[i] = port_id;
+ }
+ if (record_now == 0) {
+ record_now = 1;
+ goto again;
+ }
+ nb_cfg_ports = (portid_t) nb_pt;
+ if (nb_fwd_ports != (portid_t) nb_pt) {
+ printf("previous number of forwarding ports %u - changed to "
+ "number of configured ports %u\n",
+ (unsigned int) nb_fwd_ports, nb_pt);
+ nb_fwd_ports = (portid_t) nb_pt;
+ }
+}
+
+void
+set_fwd_ports_mask(uint64_t portmask)
+{
+ unsigned int portlist[64];
+ unsigned int nb_pt;
+ unsigned int i;
+
+ if (portmask == 0) {
+ printf("Invalid NULL mask of ports\n");
+ return;
+ }
+ nb_pt = 0;
+ RTE_ETH_FOREACH_DEV(i) {
+ if (! ((uint64_t)(1ULL << i) & portmask))
+ continue;
+ portlist[nb_pt++] = i;
+ }
+ set_fwd_ports_list(portlist, nb_pt);
+}
+
+void
+set_fwd_ports_number(uint16_t nb_pt)
+{
+ if (nb_pt > nb_cfg_ports) {
+ printf("nb fwd ports %u > %u (number of configured "
+ "ports) - ignored\n",
+ (unsigned int) nb_pt, (unsigned int) nb_cfg_ports);
+ return;
+ }
+ nb_fwd_ports = (portid_t) nb_pt;
+ printf("Number of forwarding ports set to %u\n",
+ (unsigned int) nb_fwd_ports);
+}
+
+int
+port_is_forwarding(portid_t port_id)
+{
+ unsigned int i;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return -1;
+
+ for (i = 0; i < nb_fwd_ports; i++) {
+ if (fwd_ports_ids[i] == port_id)
+ return 1;
+ }
+
+ return 0;
+}
+
+void
+set_nb_pkt_per_burst(uint16_t nb)
+{
+ if (nb > MAX_PKT_BURST) {
+ printf("nb pkt per burst: %u > %u (maximum packet per burst) "
+ " ignored\n",
+ (unsigned int) nb, (unsigned int) MAX_PKT_BURST);
+ return;
+ }
+ nb_pkt_per_burst = nb;
+ printf("Number of packets per burst set to %u\n",
+ (unsigned int) nb_pkt_per_burst);
+}
+
+static const char *
+tx_split_get_name(enum tx_pkt_split split)
+{
+ uint32_t i;
+
+ for (i = 0; i != RTE_DIM(tx_split_name); i++) {
+ if (tx_split_name[i].split == split)
+ return tx_split_name[i].name;
+ }
+ return NULL;
+}
+
+void
+set_tx_pkt_split(const char *name)
+{
+ uint32_t i;
+
+ for (i = 0; i != RTE_DIM(tx_split_name); i++) {
+ if (strcmp(tx_split_name[i].name, name) == 0) {
+ tx_pkt_split = tx_split_name[i].split;
+ return;
+ }
+ }
+ printf("unknown value: \"%s\"\n", name);
+}
+
+void
+show_tx_pkt_segments(void)
+{
+ uint32_t i, n;
+ const char *split;
+
+ n = tx_pkt_nb_segs;
+ split = tx_split_get_name(tx_pkt_split);
+
+ printf("Number of segments: %u\n", n);
+ printf("Segment sizes: ");
+ for (i = 0; i != n - 1; i++)
+ printf("%hu,", tx_pkt_seg_lengths[i]);
+ printf("%hu\n", tx_pkt_seg_lengths[i]);
+ printf("Split packet: %s\n", split);
+}
+
+void
+set_tx_pkt_segments(unsigned *seg_lengths, unsigned nb_segs)
+{
+ uint16_t tx_pkt_len;
+ unsigned i;
+
+ if (nb_segs >= (unsigned) nb_txd) {
+ printf("nb segments per TX packets=%u >= nb_txd=%u - ignored\n",
+ nb_segs, (unsigned int) nb_txd);
+ return;
+ }
+
+ /*
+ * Check that each segment length is greater or equal than
+ * the mbuf data sise.
+ * Check also that the total packet length is greater or equal than the
+ * size of an empty UDP/IP packet (sizeof(struct ether_hdr) + 20 + 8).
+ */
+ tx_pkt_len = 0;
+ for (i = 0; i < nb_segs; i++) {
+ if (seg_lengths[i] > (unsigned) mbuf_data_size) {
+ printf("length[%u]=%u > mbuf_data_size=%u - give up\n",
+ i, seg_lengths[i], (unsigned) mbuf_data_size);
+ return;
+ }
+ tx_pkt_len = (uint16_t)(tx_pkt_len + seg_lengths[i]);
+ }
+ if (tx_pkt_len < (sizeof(struct ether_hdr) + 20 + 8)) {
+ printf("total packet length=%u < %d - give up\n",
+ (unsigned) tx_pkt_len,
+ (int)(sizeof(struct ether_hdr) + 20 + 8));
+ return;
+ }
+
+ for (i = 0; i < nb_segs; i++)
+ tx_pkt_seg_lengths[i] = (uint16_t) seg_lengths[i];
+
+ tx_pkt_length = tx_pkt_len;
+ tx_pkt_nb_segs = (uint8_t) nb_segs;
+}
+
+char*
+list_pkt_forwarding_modes(void)
+{
+ static char fwd_modes[128] = "";
+ const char *separator = "|";
+ struct fwd_engine *fwd_eng;
+ unsigned i = 0;
+
+ if (strlen (fwd_modes) == 0) {
+ while ((fwd_eng = fwd_engines[i++]) != NULL) {
+ strncat(fwd_modes, fwd_eng->fwd_mode_name,
+ sizeof(fwd_modes) - strlen(fwd_modes) - 1);
+ strncat(fwd_modes, separator,
+ sizeof(fwd_modes) - strlen(fwd_modes) - 1);
+ }
+ fwd_modes[strlen(fwd_modes) - strlen(separator)] = '\0';
+ }
+
+ return fwd_modes;
+}
+
+char*
+list_pkt_forwarding_retry_modes(void)
+{
+ static char fwd_modes[128] = "";
+ const char *separator = "|";
+ struct fwd_engine *fwd_eng;
+ unsigned i = 0;
+
+ if (strlen(fwd_modes) == 0) {
+ while ((fwd_eng = fwd_engines[i++]) != NULL) {
+ if (fwd_eng == &rx_only_engine)
+ continue;
+ strncat(fwd_modes, fwd_eng->fwd_mode_name,
+ sizeof(fwd_modes) -
+ strlen(fwd_modes) - 1);
+ strncat(fwd_modes, separator,
+ sizeof(fwd_modes) -
+ strlen(fwd_modes) - 1);
+ }
+ fwd_modes[strlen(fwd_modes) - strlen(separator)] = '\0';
+ }
+
+ return fwd_modes;
+}
+
+void
+set_pkt_forwarding_mode(const char *fwd_mode_name)
+{
+ struct fwd_engine *fwd_eng;
+ unsigned i;
+
+ i = 0;
+ while ((fwd_eng = fwd_engines[i]) != NULL) {
+ if (! strcmp(fwd_eng->fwd_mode_name, fwd_mode_name)) {
+ printf("Set %s packet forwarding mode%s\n",
+ fwd_mode_name,
+ retry_enabled == 0 ? "" : " with retry");
+ cur_fwd_eng = fwd_eng;
+ return;
+ }
+ i++;
+ }
+ printf("Invalid %s packet forwarding mode\n", fwd_mode_name);
+}
+
+void
+set_verbose_level(uint16_t vb_level)
+{
+ printf("Change verbose level from %u to %u\n",
+ (unsigned int) verbose_level, (unsigned int) vb_level);
+ verbose_level = vb_level;
+}
+
+void
+vlan_extend_set(portid_t port_id, int on)
+{
+ int diag;
+ int vlan_offload;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
+
+ if (on)
+ vlan_offload |= ETH_VLAN_EXTEND_OFFLOAD;
+ else
+ vlan_offload &= ~ETH_VLAN_EXTEND_OFFLOAD;
+
+ diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload);
+ if (diag < 0)
+ printf("rx_vlan_extend_set(port_pi=%d, on=%d) failed "
+ "diag=%d\n", port_id, on, diag);
+}
+
+void
+rx_vlan_strip_set(portid_t port_id, int on)
+{
+ int diag;
+ int vlan_offload;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
+
+ if (on)
+ vlan_offload |= ETH_VLAN_STRIP_OFFLOAD;
+ else
+ vlan_offload &= ~ETH_VLAN_STRIP_OFFLOAD;
+
+ diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload);
+ if (diag < 0)
+ printf("rx_vlan_strip_set(port_pi=%d, on=%d) failed "
+ "diag=%d\n", port_id, on, diag);
+}
+
+void
+rx_vlan_strip_set_on_queue(portid_t port_id, uint16_t queue_id, int on)
+{
+ int diag;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ diag = rte_eth_dev_set_vlan_strip_on_queue(port_id, queue_id, on);
+ if (diag < 0)
+ printf("rx_vlan_strip_set_on_queue(port_pi=%d, queue_id=%d, on=%d) failed "
+ "diag=%d\n", port_id, queue_id, on, diag);
+}
+
+void
+rx_vlan_filter_set(portid_t port_id, int on)
+{
+ int diag;
+ int vlan_offload;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
+
+ if (on)
+ vlan_offload |= ETH_VLAN_FILTER_OFFLOAD;
+ else
+ vlan_offload &= ~ETH_VLAN_FILTER_OFFLOAD;
+
+ diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload);
+ if (diag < 0)
+ printf("rx_vlan_filter_set(port_pi=%d, on=%d) failed "
+ "diag=%d\n", port_id, on, diag);
+}
+
+int
+rx_vft_set(portid_t port_id, uint16_t vlan_id, int on)
+{
+ int diag;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return 1;
+ if (vlan_id_is_invalid(vlan_id))
+ return 1;
+ diag = rte_eth_dev_vlan_filter(port_id, vlan_id, on);
+ if (diag == 0)
+ return 0;
+ printf("rte_eth_dev_vlan_filter(port_pi=%d, vlan_id=%d, on=%d) failed "
+ "diag=%d\n",
+ port_id, vlan_id, on, diag);
+ return -1;
+}
+
+void
+rx_vlan_all_filter_set(portid_t port_id, int on)
+{
+ uint16_t vlan_id;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ for (vlan_id = 0; vlan_id < 4096; vlan_id++) {
+ if (rx_vft_set(port_id, vlan_id, on))
+ break;
+ }
+}
+
+void
+vlan_tpid_set(portid_t port_id, enum rte_vlan_type vlan_type, uint16_t tp_id)
+{
+ int diag;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ diag = rte_eth_dev_set_vlan_ether_type(port_id, vlan_type, tp_id);
+ if (diag == 0)
+ return;
+
+ printf("tx_vlan_tpid_set(port_pi=%d, vlan_type=%d, tpid=%d) failed "
+ "diag=%d\n",
+ port_id, vlan_type, tp_id, diag);
+}
+
+void
+tx_vlan_set(portid_t port_id, uint16_t vlan_id)
+{
+ int vlan_offload;
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ if (vlan_id_is_invalid(vlan_id))
+ return;
+
+ vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
+ if (vlan_offload & ETH_VLAN_EXTEND_OFFLOAD) {
+ printf("Error, as QinQ has been enabled.\n");
+ return;
+ }
+
+ tx_vlan_reset(port_id);
+ ports[port_id].tx_ol_flags |= TESTPMD_TX_OFFLOAD_INSERT_VLAN;
+ ports[port_id].tx_vlan_id = vlan_id;
+}
+
+void
+tx_qinq_set(portid_t port_id, uint16_t vlan_id, uint16_t vlan_id_outer)
+{
+ int vlan_offload;
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ if (vlan_id_is_invalid(vlan_id))
+ return;
+ if (vlan_id_is_invalid(vlan_id_outer))
+ return;
+
+ vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
+ if (!(vlan_offload & ETH_VLAN_EXTEND_OFFLOAD)) {
+ printf("Error, as QinQ hasn't been enabled.\n");
+ return;
+ }
+
+ tx_vlan_reset(port_id);
+ ports[port_id].tx_ol_flags |= TESTPMD_TX_OFFLOAD_INSERT_QINQ;
+ ports[port_id].tx_vlan_id = vlan_id;
+ ports[port_id].tx_vlan_id_outer = vlan_id_outer;
+}
+
+void
+tx_vlan_reset(portid_t port_id)
+{
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ ports[port_id].tx_ol_flags &= ~(TESTPMD_TX_OFFLOAD_INSERT_VLAN |
+ TESTPMD_TX_OFFLOAD_INSERT_QINQ);
+ ports[port_id].tx_vlan_id = 0;
+ ports[port_id].tx_vlan_id_outer = 0;
+}
+
+void
+tx_vlan_pvid_set(portid_t port_id, uint16_t vlan_id, int on)
+{
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ rte_eth_dev_set_vlan_pvid(port_id, vlan_id, on);
+}
+
+void
+set_qmap(portid_t port_id, uint8_t is_rx, uint16_t queue_id, uint8_t map_value)
+{
+ uint16_t i;
+ uint8_t existing_mapping_found = 0;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ if (is_rx ? (rx_queue_id_is_invalid(queue_id)) : (tx_queue_id_is_invalid(queue_id)))
+ return;
+
+ if (map_value >= RTE_ETHDEV_QUEUE_STAT_CNTRS) {
+ printf("map_value not in required range 0..%d\n",
+ RTE_ETHDEV_QUEUE_STAT_CNTRS - 1);
+ return;
+ }
+
+ if (!is_rx) { /*then tx*/
+ for (i = 0; i < nb_tx_queue_stats_mappings; i++) {
+ if ((tx_queue_stats_mappings[i].port_id == port_id) &&
+ (tx_queue_stats_mappings[i].queue_id == queue_id)) {
+ tx_queue_stats_mappings[i].stats_counter_id = map_value;
+ existing_mapping_found = 1;
+ break;
+ }
+ }
+ if (!existing_mapping_found) { /* A new additional mapping... */
+ tx_queue_stats_mappings[nb_tx_queue_stats_mappings].port_id = port_id;
+ tx_queue_stats_mappings[nb_tx_queue_stats_mappings].queue_id = queue_id;
+ tx_queue_stats_mappings[nb_tx_queue_stats_mappings].stats_counter_id = map_value;
+ nb_tx_queue_stats_mappings++;
+ }
+ }
+ else { /*rx*/
+ for (i = 0; i < nb_rx_queue_stats_mappings; i++) {
+ if ((rx_queue_stats_mappings[i].port_id == port_id) &&
+ (rx_queue_stats_mappings[i].queue_id == queue_id)) {
+ rx_queue_stats_mappings[i].stats_counter_id = map_value;
+ existing_mapping_found = 1;
+ break;
+ }
+ }
+ if (!existing_mapping_found) { /* A new additional mapping... */
+ rx_queue_stats_mappings[nb_rx_queue_stats_mappings].port_id = port_id;
+ rx_queue_stats_mappings[nb_rx_queue_stats_mappings].queue_id = queue_id;
+ rx_queue_stats_mappings[nb_rx_queue_stats_mappings].stats_counter_id = map_value;
+ nb_rx_queue_stats_mappings++;
+ }
+ }
+}
+
+static inline void
+print_fdir_mask(struct rte_eth_fdir_masks *mask)
+{
+ printf("\n vlan_tci: 0x%04x", rte_be_to_cpu_16(mask->vlan_tci_mask));
+
+ if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_TUNNEL)
+ printf(", mac_addr: 0x%02x, tunnel_type: 0x%01x,"
+ " tunnel_id: 0x%08x",
+ mask->mac_addr_byte_mask, mask->tunnel_type_mask,
+ rte_be_to_cpu_32(mask->tunnel_id_mask));
+ else if (fdir_conf.mode != RTE_FDIR_MODE_PERFECT_MAC_VLAN) {
+ printf(", src_ipv4: 0x%08x, dst_ipv4: 0x%08x",
+ rte_be_to_cpu_32(mask->ipv4_mask.src_ip),
+ rte_be_to_cpu_32(mask->ipv4_mask.dst_ip));
+
+ printf("\n src_port: 0x%04x, dst_port: 0x%04x",
+ rte_be_to_cpu_16(mask->src_port_mask),
+ rte_be_to_cpu_16(mask->dst_port_mask));
+
+ printf("\n src_ipv6: 0x%08x,0x%08x,0x%08x,0x%08x",
+ rte_be_to_cpu_32(mask->ipv6_mask.src_ip[0]),
+ rte_be_to_cpu_32(mask->ipv6_mask.src_ip[1]),
+ rte_be_to_cpu_32(mask->ipv6_mask.src_ip[2]),
+ rte_be_to_cpu_32(mask->ipv6_mask.src_ip[3]));
+
+ printf("\n dst_ipv6: 0x%08x,0x%08x,0x%08x,0x%08x",
+ rte_be_to_cpu_32(mask->ipv6_mask.dst_ip[0]),
+ rte_be_to_cpu_32(mask->ipv6_mask.dst_ip[1]),
+ rte_be_to_cpu_32(mask->ipv6_mask.dst_ip[2]),
+ rte_be_to_cpu_32(mask->ipv6_mask.dst_ip[3]));
+ }
+
+ printf("\n");
+}
+
+static inline void
+print_fdir_flex_payload(struct rte_eth_fdir_flex_conf *flex_conf, uint32_t num)
+{
+ struct rte_eth_flex_payload_cfg *cfg;
+ uint32_t i, j;
+
+ for (i = 0; i < flex_conf->nb_payloads; i++) {
+ cfg = &flex_conf->flex_set[i];
+ if (cfg->type == RTE_ETH_RAW_PAYLOAD)
+ printf("\n RAW: ");
+ else if (cfg->type == RTE_ETH_L2_PAYLOAD)
+ printf("\n L2_PAYLOAD: ");
+ else if (cfg->type == RTE_ETH_L3_PAYLOAD)
+ printf("\n L3_PAYLOAD: ");
+ else if (cfg->type == RTE_ETH_L4_PAYLOAD)
+ printf("\n L4_PAYLOAD: ");
+ else
+ printf("\n UNKNOWN PAYLOAD(%u): ", cfg->type);
+ for (j = 0; j < num; j++)
+ printf(" %-5u", cfg->src_offset[j]);
+ }
+ printf("\n");
+}
+
+static char *
+flowtype_to_str(uint16_t flow_type)
+{
+ struct flow_type_info {
+ char str[32];
+ uint16_t ftype;
+ };
+
+ uint8_t i;
+ static struct flow_type_info flowtype_str_table[] = {
+ {"raw", RTE_ETH_FLOW_RAW},
+ {"ipv4", RTE_ETH_FLOW_IPV4},
+ {"ipv4-frag", RTE_ETH_FLOW_FRAG_IPV4},
+ {"ipv4-tcp", RTE_ETH_FLOW_NONFRAG_IPV4_TCP},
+ {"ipv4-udp", RTE_ETH_FLOW_NONFRAG_IPV4_UDP},
+ {"ipv4-sctp", RTE_ETH_FLOW_NONFRAG_IPV4_SCTP},
+ {"ipv4-other", RTE_ETH_FLOW_NONFRAG_IPV4_OTHER},
+ {"ipv6", RTE_ETH_FLOW_IPV6},
+ {"ipv6-frag", RTE_ETH_FLOW_FRAG_IPV6},
+ {"ipv6-tcp", RTE_ETH_FLOW_NONFRAG_IPV6_TCP},
+ {"ipv6-udp", RTE_ETH_FLOW_NONFRAG_IPV6_UDP},
+ {"ipv6-sctp", RTE_ETH_FLOW_NONFRAG_IPV6_SCTP},
+ {"ipv6-other", RTE_ETH_FLOW_NONFRAG_IPV6_OTHER},
+ {"l2_payload", RTE_ETH_FLOW_L2_PAYLOAD},
+ {"port", RTE_ETH_FLOW_PORT},
+ {"vxlan", RTE_ETH_FLOW_VXLAN},
+ {"geneve", RTE_ETH_FLOW_GENEVE},
+ {"nvgre", RTE_ETH_FLOW_NVGRE},
+ };
+
+ for (i = 0; i < RTE_DIM(flowtype_str_table); i++) {
+ if (flowtype_str_table[i].ftype == flow_type)
+ return flowtype_str_table[i].str;
+ }
+
+ return NULL;
+}
+
+static inline void
+print_fdir_flex_mask(struct rte_eth_fdir_flex_conf *flex_conf, uint32_t num)
+{
+ struct rte_eth_fdir_flex_mask *mask;
+ uint32_t i, j;
+ char *p;
+
+ for (i = 0; i < flex_conf->nb_flexmasks; i++) {
+ mask = &flex_conf->flex_mask[i];
+ p = flowtype_to_str(mask->flow_type);
+ printf("\n %s:\t", p ? p : "unknown");
+ for (j = 0; j < num; j++)
+ printf(" %02x", mask->mask[j]);
+ }
+ printf("\n");
+}
+
+static inline void
+print_fdir_flow_type(uint32_t flow_types_mask)
+{
+ int i;
+ char *p;
+
+ for (i = RTE_ETH_FLOW_UNKNOWN; i < RTE_ETH_FLOW_MAX; i++) {
+ if (!(flow_types_mask & (1 << i)))
+ continue;
+ p = flowtype_to_str(i);
+ if (p)
+ printf(" %s", p);
+ else
+ printf(" unknown");
+ }
+ printf("\n");
+}
+
+void
+fdir_get_infos(portid_t port_id)
+{
+ struct rte_eth_fdir_stats fdir_stat;
+ struct rte_eth_fdir_info fdir_info;
+ int ret;
+
+ static const char *fdir_stats_border = "########################";
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ ret = rte_eth_dev_filter_supported(port_id, RTE_ETH_FILTER_FDIR);
+ if (ret < 0) {
+ printf("\n FDIR is not supported on port %-2d\n",
+ port_id);
+ return;
+ }
+
+ memset(&fdir_info, 0, sizeof(fdir_info));
+ rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_INFO, &fdir_info);
+ memset(&fdir_stat, 0, sizeof(fdir_stat));
+ rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_STATS, &fdir_stat);
+ printf("\n %s FDIR infos for port %-2d %s\n",
+ fdir_stats_border, port_id, fdir_stats_border);
+ printf(" MODE: ");
+ if (fdir_info.mode == RTE_FDIR_MODE_PERFECT)
+ printf(" PERFECT\n");
+ else if (fdir_info.mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN)
+ printf(" PERFECT-MAC-VLAN\n");
+ else if (fdir_info.mode == RTE_FDIR_MODE_PERFECT_TUNNEL)
+ printf(" PERFECT-TUNNEL\n");
+ else if (fdir_info.mode == RTE_FDIR_MODE_SIGNATURE)
+ printf(" SIGNATURE\n");
+ else
+ printf(" DISABLE\n");
+ if (fdir_info.mode != RTE_FDIR_MODE_PERFECT_MAC_VLAN
+ && fdir_info.mode != RTE_FDIR_MODE_PERFECT_TUNNEL) {
+ printf(" SUPPORTED FLOW TYPE: ");
+ print_fdir_flow_type(fdir_info.flow_types_mask[0]);
+ }
+ printf(" FLEX PAYLOAD INFO:\n");
+ printf(" max_len: %-10"PRIu32" payload_limit: %-10"PRIu32"\n"
+ " payload_unit: %-10"PRIu32" payload_seg: %-10"PRIu32"\n"
+ " bitmask_unit: %-10"PRIu32" bitmask_num: %-10"PRIu32"\n",
+ fdir_info.max_flexpayload, fdir_info.flex_payload_limit,
+ fdir_info.flex_payload_unit,
+ fdir_info.max_flex_payload_segment_num,
+ fdir_info.flex_bitmask_unit, fdir_info.max_flex_bitmask_num);
+ printf(" MASK: ");
+ print_fdir_mask(&fdir_info.mask);
+ if (fdir_info.flex_conf.nb_payloads > 0) {
+ printf(" FLEX PAYLOAD SRC OFFSET:");
+ print_fdir_flex_payload(&fdir_info.flex_conf, fdir_info.max_flexpayload);
+ }
+ if (fdir_info.flex_conf.nb_flexmasks > 0) {
+ printf(" FLEX MASK CFG:");
+ print_fdir_flex_mask(&fdir_info.flex_conf, fdir_info.max_flexpayload);
+ }
+ printf(" guarant_count: %-10"PRIu32" best_count: %"PRIu32"\n",
+ fdir_stat.guarant_cnt, fdir_stat.best_cnt);
+ printf(" guarant_space: %-10"PRIu32" best_space: %"PRIu32"\n",
+ fdir_info.guarant_spc, fdir_info.best_spc);
+ printf(" collision: %-10"PRIu32" free: %"PRIu32"\n"
+ " maxhash: %-10"PRIu32" maxlen: %"PRIu32"\n"
+ " add: %-10"PRIu64" remove: %"PRIu64"\n"
+ " f_add: %-10"PRIu64" f_remove: %"PRIu64"\n",
+ fdir_stat.collision, fdir_stat.free,
+ fdir_stat.maxhash, fdir_stat.maxlen,
+ fdir_stat.add, fdir_stat.remove,
+ fdir_stat.f_add, fdir_stat.f_remove);
+ printf(" %s############################%s\n",
+ fdir_stats_border, fdir_stats_border);
+}
+
+void
+fdir_set_flex_mask(portid_t port_id, struct rte_eth_fdir_flex_mask *cfg)
+{
+ struct rte_port *port;
+ struct rte_eth_fdir_flex_conf *flex_conf;
+ int i, idx = 0;
+
+ port = &ports[port_id];
+ flex_conf = &port->dev_conf.fdir_conf.flex_conf;
+ for (i = 0; i < RTE_ETH_FLOW_MAX; i++) {
+ if (cfg->flow_type == flex_conf->flex_mask[i].flow_type) {
+ idx = i;
+ break;
+ }
+ }
+ if (i >= RTE_ETH_FLOW_MAX) {
+ if (flex_conf->nb_flexmasks < RTE_DIM(flex_conf->flex_mask)) {
+ idx = flex_conf->nb_flexmasks;
+ flex_conf->nb_flexmasks++;
+ } else {
+ printf("The flex mask table is full. Can not set flex"
+ " mask for flow_type(%u).", cfg->flow_type);
+ return;
+ }
+ }
+ (void)rte_memcpy(&flex_conf->flex_mask[idx],
+ cfg,
+ sizeof(struct rte_eth_fdir_flex_mask));
+}
+
+void
+fdir_set_flex_payload(portid_t port_id, struct rte_eth_flex_payload_cfg *cfg)
+{
+ struct rte_port *port;
+ struct rte_eth_fdir_flex_conf *flex_conf;
+ int i, idx = 0;
+
+ port = &ports[port_id];
+ flex_conf = &port->dev_conf.fdir_conf.flex_conf;
+ for (i = 0; i < RTE_ETH_PAYLOAD_MAX; i++) {
+ if (cfg->type == flex_conf->flex_set[i].type) {
+ idx = i;
+ break;
+ }
+ }
+ if (i >= RTE_ETH_PAYLOAD_MAX) {
+ if (flex_conf->nb_payloads < RTE_DIM(flex_conf->flex_set)) {
+ idx = flex_conf->nb_payloads;
+ flex_conf->nb_payloads++;
+ } else {
+ printf("The flex payload table is full. Can not set"
+ " flex payload for type(%u).", cfg->type);
+ return;
+ }
+ }
+ (void)rte_memcpy(&flex_conf->flex_set[idx],
+ cfg,
+ sizeof(struct rte_eth_flex_payload_cfg));
+
+}
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+void
+set_vf_traffic(portid_t port_id, uint8_t is_rx, uint16_t vf, uint8_t on)
+{
+ int diag;
+
+ if (is_rx)
+ diag = rte_pmd_ixgbe_set_vf_rx(port_id, vf, on);
+ else
+ diag = rte_pmd_ixgbe_set_vf_tx(port_id, vf, on);
+
+ if (diag == 0)
+ return;
+ if(is_rx)
+ printf("rte_pmd_ixgbe_set_vf_rx for port_id=%d failed "
+ "diag=%d\n", port_id, diag);
+ else
+ printf("rte_pmd_ixgbe_set_vf_tx for port_id=%d failed "
+ "diag=%d\n", port_id, diag);
+
+}
+#endif
+
+int
+set_queue_rate_limit(portid_t port_id, uint16_t queue_idx, uint16_t rate)
+{
+ int diag;
+ struct rte_eth_link link;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return 1;
+ rte_eth_link_get_nowait(port_id, &link);
+ if (rate > link.link_speed) {
+ printf("Invalid rate value:%u bigger than link speed: %u\n",
+ rate, link.link_speed);
+ return 1;
+ }
+ diag = rte_eth_set_queue_rate_limit(port_id, queue_idx, rate);
+ if (diag == 0)
+ return diag;
+ printf("rte_eth_set_queue_rate_limit for port_id=%d failed diag=%d\n",
+ port_id, diag);
+ return diag;
+}
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+int
+set_vf_rate_limit(portid_t port_id, uint16_t vf, uint16_t rate, uint64_t q_msk)
+{
+ int diag;
+
+ diag = rte_pmd_ixgbe_set_vf_rate_limit(port_id, vf, rate, q_msk);
+ if (diag == 0)
+ return diag;
+ printf("rte_pmd_ixgbe_set_vf_rate_limit for port_id=%d failed diag=%d\n",
+ port_id, diag);
+ return diag;
+}
+#endif
+
+/*
+ * Functions to manage the set of filtered Multicast MAC addresses.
+ *
+ * A pool of filtered multicast MAC addresses is associated with each port.
+ * The pool is allocated in chunks of MCAST_POOL_INC multicast addresses.
+ * The address of the pool and the number of valid multicast MAC addresses
+ * recorded in the pool are stored in the fields "mc_addr_pool" and
+ * "mc_addr_nb" of the "rte_port" data structure.
+ *
+ * The function "rte_eth_dev_set_mc_addr_list" of the PMDs API imposes
+ * to be supplied a contiguous array of multicast MAC addresses.
+ * To comply with this constraint, the set of multicast addresses recorded
+ * into the pool are systematically compacted at the beginning of the pool.
+ * Hence, when a multicast address is removed from the pool, all following
+ * addresses, if any, are copied back to keep the set contiguous.
+ */
+#define MCAST_POOL_INC 32
+
+static int
+mcast_addr_pool_extend(struct rte_port *port)
+{
+ struct ether_addr *mc_pool;
+ size_t mc_pool_size;
+
+ /*
+ * If a free entry is available at the end of the pool, just
+ * increment the number of recorded multicast addresses.
+ */
+ if ((port->mc_addr_nb % MCAST_POOL_INC) != 0) {
+ port->mc_addr_nb++;
+ return 0;
+ }
+
+ /*
+ * [re]allocate a pool with MCAST_POOL_INC more entries.
+ * The previous test guarantees that port->mc_addr_nb is a multiple
+ * of MCAST_POOL_INC.
+ */
+ mc_pool_size = sizeof(struct ether_addr) * (port->mc_addr_nb +
+ MCAST_POOL_INC);
+ mc_pool = (struct ether_addr *) realloc(port->mc_addr_pool,
+ mc_pool_size);
+ if (mc_pool == NULL) {
+ printf("allocation of pool of %u multicast addresses failed\n",
+ port->mc_addr_nb + MCAST_POOL_INC);
+ return -ENOMEM;
+ }
+
+ port->mc_addr_pool = mc_pool;
+ port->mc_addr_nb++;
+ return 0;
+
+}
+
+static void
+mcast_addr_pool_remove(struct rte_port *port, uint32_t addr_idx)
+{
+ port->mc_addr_nb--;
+ if (addr_idx == port->mc_addr_nb) {
+ /* No need to recompact the set of multicast addressses. */
+ if (port->mc_addr_nb == 0) {
+ /* free the pool of multicast addresses. */
+ free(port->mc_addr_pool);
+ port->mc_addr_pool = NULL;
+ }
+ return;
+ }
+ memmove(&port->mc_addr_pool[addr_idx],
+ &port->mc_addr_pool[addr_idx + 1],
+ sizeof(struct ether_addr) * (port->mc_addr_nb - addr_idx));
+}
+
+static void
+eth_port_multicast_addr_list_set(uint8_t port_id)
+{
+ struct rte_port *port;
+ int diag;
+
+ port = &ports[port_id];
+ diag = rte_eth_dev_set_mc_addr_list(port_id, port->mc_addr_pool,
+ port->mc_addr_nb);
+ if (diag == 0)
+ return;
+ printf("rte_eth_dev_set_mc_addr_list(port=%d, nb=%u) failed. diag=%d\n",
+ port->mc_addr_nb, port_id, -diag);
+}
+
+void
+mcast_addr_add(uint8_t port_id, struct ether_addr *mc_addr)
+{
+ struct rte_port *port;
+ uint32_t i;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ port = &ports[port_id];
+
+ /*
+ * Check that the added multicast MAC address is not already recorded
+ * in the pool of multicast addresses.
+ */
+ for (i = 0; i < port->mc_addr_nb; i++) {
+ if (is_same_ether_addr(mc_addr, &port->mc_addr_pool[i])) {
+ printf("multicast address already filtered by port\n");
+ return;
+ }
+ }
+
+ if (mcast_addr_pool_extend(port) != 0)
+ return;
+ ether_addr_copy(mc_addr, &port->mc_addr_pool[i]);
+ eth_port_multicast_addr_list_set(port_id);
+}
+
+void
+mcast_addr_remove(uint8_t port_id, struct ether_addr *mc_addr)
+{
+ struct rte_port *port;
+ uint32_t i;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ port = &ports[port_id];
+
+ /*
+ * Search the pool of multicast MAC addresses for the removed address.
+ */
+ for (i = 0; i < port->mc_addr_nb; i++) {
+ if (is_same_ether_addr(mc_addr, &port->mc_addr_pool[i]))
+ break;
+ }
+ if (i == port->mc_addr_nb) {
+ printf("multicast address not filtered by port %d\n", port_id);
+ return;
+ }
+
+ mcast_addr_pool_remove(port, i);
+ eth_port_multicast_addr_list_set(port_id);
+}
+
+void
+port_dcb_info_display(uint8_t port_id)
+{
+ struct rte_eth_dcb_info dcb_info;
+ uint16_t i;
+ int ret;
+ static const char *border = "================";
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ ret = rte_eth_dev_get_dcb_info(port_id, &dcb_info);
+ if (ret) {
+ printf("\n Failed to get dcb infos on port %-2d\n",
+ port_id);
+ return;
+ }
+ printf("\n %s DCB infos for port %-2d %s\n", border, port_id, border);
+ printf(" TC NUMBER: %d\n", dcb_info.nb_tcs);
+ printf("\n TC : ");
+ for (i = 0; i < dcb_info.nb_tcs; i++)
+ printf("\t%4d", i);
+ printf("\n Priority : ");
+ for (i = 0; i < dcb_info.nb_tcs; i++)
+ printf("\t%4d", dcb_info.prio_tc[i]);
+ printf("\n BW percent :");
+ for (i = 0; i < dcb_info.nb_tcs; i++)
+ printf("\t%4d%%", dcb_info.tc_bws[i]);
+ printf("\n RXQ base : ");
+ for (i = 0; i < dcb_info.nb_tcs; i++)
+ printf("\t%4d", dcb_info.tc_queue.tc_rxq[0][i].base);
+ printf("\n RXQ number :");
+ for (i = 0; i < dcb_info.nb_tcs; i++)
+ printf("\t%4d", dcb_info.tc_queue.tc_rxq[0][i].nb_queue);
+ printf("\n TXQ base : ");
+ for (i = 0; i < dcb_info.nb_tcs; i++)
+ printf("\t%4d", dcb_info.tc_queue.tc_txq[0][i].base);
+ printf("\n TXQ number :");
+ for (i = 0; i < dcb_info.nb_tcs; i++)
+ printf("\t%4d", dcb_info.tc_queue.tc_txq[0][i].nb_queue);
+ printf("\n");
+}
+
+uint8_t *
+open_ddp_package_file(const char *file_path, uint32_t *size)
+{
+ FILE *fh = fopen(file_path, "rb");
+ uint32_t pkg_size;
+ uint8_t *buf = NULL;
+ int ret = 0;
+
+ if (size)
+ *size = 0;
+
+ if (fh == NULL) {
+ printf("%s: Failed to open %s\n", __func__, file_path);
+ return buf;
+ }
+
+ ret = fseek(fh, 0, SEEK_END);
+ if (ret < 0) {
+ fclose(fh);
+ printf("%s: File operations failed\n", __func__);
+ return buf;
+ }
+
+ pkg_size = ftell(fh);
+
+ buf = (uint8_t *)malloc(pkg_size);
+ if (!buf) {
+ fclose(fh);
+ printf("%s: Failed to malloc memory\n", __func__);
+ return buf;
+ }
+
+ ret = fseek(fh, 0, SEEK_SET);
+ if (ret < 0) {
+ fclose(fh);
+ printf("%s: File seek operation failed\n", __func__);
+ close_ddp_package_file(buf);
+ return NULL;
+ }
+
+ ret = fread(buf, 1, pkg_size, fh);
+ if (ret < 0) {
+ fclose(fh);
+ printf("%s: File read operation failed\n", __func__);
+ close_ddp_package_file(buf);
+ return NULL;
+ }
+
+ if (size)
+ *size = pkg_size;
+
+ fclose(fh);
+
+ return buf;
+}
+
+int
+close_ddp_package_file(uint8_t *buf)
+{
+ if (buf) {
+ free((void *)buf);
+ return 0;
+ }
+
+ return -1;
+}
diff --git a/src/seastar/dpdk/app/test-pmd/csumonly.c b/src/seastar/dpdk/app/test-pmd/csumonly.c
new file mode 100644
index 00000000..66fc9a00
--- /dev/null
+++ b/src/seastar/dpdk/app/test-pmd/csumonly.c
@@ -0,0 +1,896 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ * Copyright 2014 6WIND S.A.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_cycles.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_memzone.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_memory.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_memcpy.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_udp.h>
+#include <rte_sctp.h>
+#include <rte_prefetch.h>
+#include <rte_string_fns.h>
+#include <rte_flow.h>
+#include "testpmd.h"
+
+#define IP_DEFTTL 64 /* from RFC 1340. */
+#define IP_VERSION 0x40
+#define IP_HDRLEN 0x05 /* default IP header length == five 32-bits words. */
+#define IP_VHL_DEF (IP_VERSION | IP_HDRLEN)
+
+#define GRE_KEY_PRESENT 0x2000
+#define GRE_KEY_LEN 4
+#define GRE_SUPPORTED_FIELDS GRE_KEY_PRESENT
+
+/* We cannot use rte_cpu_to_be_16() on a constant in a switch/case */
+#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
+#define _htons(x) ((uint16_t)((((x) & 0x00ffU) << 8) | (((x) & 0xff00U) >> 8)))
+#else
+#define _htons(x) (x)
+#endif
+
+/* structure that caches offload info for the current packet */
+struct testpmd_offload_info {
+ uint16_t ethertype;
+ uint16_t l2_len;
+ uint16_t l3_len;
+ uint16_t l4_len;
+ uint8_t l4_proto;
+ uint8_t is_tunnel;
+ uint16_t outer_ethertype;
+ uint16_t outer_l2_len;
+ uint16_t outer_l3_len;
+ uint8_t outer_l4_proto;
+ uint16_t tso_segsz;
+ uint16_t tunnel_tso_segsz;
+ uint32_t pkt_len;
+};
+
+/* simplified GRE header */
+struct simple_gre_hdr {
+ uint16_t flags;
+ uint16_t proto;
+} __attribute__((__packed__));
+
+static uint16_t
+get_udptcp_checksum(void *l3_hdr, void *l4_hdr, uint16_t ethertype)
+{
+ if (ethertype == _htons(ETHER_TYPE_IPv4))
+ return rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr);
+ else /* assume ethertype == ETHER_TYPE_IPv6 */
+ return rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr);
+}
+
+/* Parse an IPv4 header to fill l3_len, l4_len, and l4_proto */
+static void
+parse_ipv4(struct ipv4_hdr *ipv4_hdr, struct testpmd_offload_info *info)
+{
+ struct tcp_hdr *tcp_hdr;
+
+ info->l3_len = (ipv4_hdr->version_ihl & 0x0f) * 4;
+ info->l4_proto = ipv4_hdr->next_proto_id;
+
+ /* only fill l4_len for TCP, it's useful for TSO */
+ if (info->l4_proto == IPPROTO_TCP) {
+ tcp_hdr = (struct tcp_hdr *)((char *)ipv4_hdr + info->l3_len);
+ info->l4_len = (tcp_hdr->data_off & 0xf0) >> 2;
+ } else
+ info->l4_len = 0;
+}
+
+/* Parse an IPv6 header to fill l3_len, l4_len, and l4_proto */
+static void
+parse_ipv6(struct ipv6_hdr *ipv6_hdr, struct testpmd_offload_info *info)
+{
+ struct tcp_hdr *tcp_hdr;
+
+ info->l3_len = sizeof(struct ipv6_hdr);
+ info->l4_proto = ipv6_hdr->proto;
+
+ /* only fill l4_len for TCP, it's useful for TSO */
+ if (info->l4_proto == IPPROTO_TCP) {
+ tcp_hdr = (struct tcp_hdr *)((char *)ipv6_hdr + info->l3_len);
+ info->l4_len = (tcp_hdr->data_off & 0xf0) >> 2;
+ } else
+ info->l4_len = 0;
+}
+
+/*
+ * Parse an ethernet header to fill the ethertype, l2_len, l3_len and
+ * ipproto. This function is able to recognize IPv4/IPv6 with one optional vlan
+ * header. The l4_len argument is only set in case of TCP (useful for TSO).
+ */
+static void
+parse_ethernet(struct ether_hdr *eth_hdr, struct testpmd_offload_info *info)
+{
+ struct ipv4_hdr *ipv4_hdr;
+ struct ipv6_hdr *ipv6_hdr;
+
+ info->l2_len = sizeof(struct ether_hdr);
+ info->ethertype = eth_hdr->ether_type;
+
+ if (info->ethertype == _htons(ETHER_TYPE_VLAN)) {
+ struct vlan_hdr *vlan_hdr = (struct vlan_hdr *)(eth_hdr + 1);
+
+ info->l2_len += sizeof(struct vlan_hdr);
+ info->ethertype = vlan_hdr->eth_proto;
+ }
+
+ switch (info->ethertype) {
+ case _htons(ETHER_TYPE_IPv4):
+ ipv4_hdr = (struct ipv4_hdr *) ((char *)eth_hdr + info->l2_len);
+ parse_ipv4(ipv4_hdr, info);
+ break;
+ case _htons(ETHER_TYPE_IPv6):
+ ipv6_hdr = (struct ipv6_hdr *) ((char *)eth_hdr + info->l2_len);
+ parse_ipv6(ipv6_hdr, info);
+ break;
+ default:
+ info->l4_len = 0;
+ info->l3_len = 0;
+ info->l4_proto = 0;
+ break;
+ }
+}
+
+/* Parse a vxlan header */
+static void
+parse_vxlan(struct udp_hdr *udp_hdr,
+ struct testpmd_offload_info *info,
+ uint32_t pkt_type)
+{
+ struct ether_hdr *eth_hdr;
+
+ /* check udp destination port, 4789 is the default vxlan port
+ * (rfc7348) or that the rx offload flag is set (i40e only
+ * currently) */
+ if (udp_hdr->dst_port != _htons(4789) &&
+ RTE_ETH_IS_TUNNEL_PKT(pkt_type) == 0)
+ return;
+
+ info->is_tunnel = 1;
+ info->outer_ethertype = info->ethertype;
+ info->outer_l2_len = info->l2_len;
+ info->outer_l3_len = info->l3_len;
+ info->outer_l4_proto = info->l4_proto;
+
+ eth_hdr = (struct ether_hdr *)((char *)udp_hdr +
+ sizeof(struct udp_hdr) +
+ sizeof(struct vxlan_hdr));
+
+ parse_ethernet(eth_hdr, info);
+ info->l2_len += ETHER_VXLAN_HLEN; /* add udp + vxlan */
+}
+
+/* Parse a gre header */
+static void
+parse_gre(struct simple_gre_hdr *gre_hdr, struct testpmd_offload_info *info)
+{
+ struct ether_hdr *eth_hdr;
+ struct ipv4_hdr *ipv4_hdr;
+ struct ipv6_hdr *ipv6_hdr;
+ uint8_t gre_len = 0;
+
+ /* check which fields are supported */
+ if ((gre_hdr->flags & _htons(~GRE_SUPPORTED_FIELDS)) != 0)
+ return;
+
+ gre_len += sizeof(struct simple_gre_hdr);
+
+ if (gre_hdr->flags & _htons(GRE_KEY_PRESENT))
+ gre_len += GRE_KEY_LEN;
+
+ if (gre_hdr->proto == _htons(ETHER_TYPE_IPv4)) {
+ info->is_tunnel = 1;
+ info->outer_ethertype = info->ethertype;
+ info->outer_l2_len = info->l2_len;
+ info->outer_l3_len = info->l3_len;
+ info->outer_l4_proto = info->l4_proto;
+
+ ipv4_hdr = (struct ipv4_hdr *)((char *)gre_hdr + gre_len);
+
+ parse_ipv4(ipv4_hdr, info);
+ info->ethertype = _htons(ETHER_TYPE_IPv4);
+ info->l2_len = 0;
+
+ } else if (gre_hdr->proto == _htons(ETHER_TYPE_IPv6)) {
+ info->is_tunnel = 1;
+ info->outer_ethertype = info->ethertype;
+ info->outer_l2_len = info->l2_len;
+ info->outer_l3_len = info->l3_len;
+ info->outer_l4_proto = info->l4_proto;
+
+ ipv6_hdr = (struct ipv6_hdr *)((char *)gre_hdr + gre_len);
+
+ info->ethertype = _htons(ETHER_TYPE_IPv6);
+ parse_ipv6(ipv6_hdr, info);
+ info->l2_len = 0;
+
+ } else if (gre_hdr->proto == _htons(ETHER_TYPE_TEB)) {
+ info->is_tunnel = 1;
+ info->outer_ethertype = info->ethertype;
+ info->outer_l2_len = info->l2_len;
+ info->outer_l3_len = info->l3_len;
+ info->outer_l4_proto = info->l4_proto;
+
+ eth_hdr = (struct ether_hdr *)((char *)gre_hdr + gre_len);
+
+ parse_ethernet(eth_hdr, info);
+ } else
+ return;
+
+ info->l2_len += gre_len;
+}
+
+
+/* Parse an encapsulated ip or ipv6 header */
+static void
+parse_encap_ip(void *encap_ip, struct testpmd_offload_info *info)
+{
+ struct ipv4_hdr *ipv4_hdr = encap_ip;
+ struct ipv6_hdr *ipv6_hdr = encap_ip;
+ uint8_t ip_version;
+
+ ip_version = (ipv4_hdr->version_ihl & 0xf0) >> 4;
+
+ if (ip_version != 4 && ip_version != 6)
+ return;
+
+ info->is_tunnel = 1;
+ info->outer_ethertype = info->ethertype;
+ info->outer_l2_len = info->l2_len;
+ info->outer_l3_len = info->l3_len;
+
+ if (ip_version == 4) {
+ parse_ipv4(ipv4_hdr, info);
+ info->ethertype = _htons(ETHER_TYPE_IPv4);
+ } else {
+ parse_ipv6(ipv6_hdr, info);
+ info->ethertype = _htons(ETHER_TYPE_IPv6);
+ }
+ info->l2_len = 0;
+}
+
+/* if possible, calculate the checksum of a packet in hw or sw,
+ * depending on the testpmd command line configuration */
+static uint64_t
+process_inner_cksums(void *l3_hdr, const struct testpmd_offload_info *info,
+ uint16_t testpmd_ol_flags)
+{
+ struct ipv4_hdr *ipv4_hdr = l3_hdr;
+ struct udp_hdr *udp_hdr;
+ struct tcp_hdr *tcp_hdr;
+ struct sctp_hdr *sctp_hdr;
+ uint64_t ol_flags = 0;
+ uint32_t max_pkt_len, tso_segsz = 0;
+
+ /* ensure packet is large enough to require tso */
+ if (!info->is_tunnel) {
+ max_pkt_len = info->l2_len + info->l3_len + info->l4_len +
+ info->tso_segsz;
+ if (info->tso_segsz != 0 && info->pkt_len > max_pkt_len)
+ tso_segsz = info->tso_segsz;
+ } else {
+ max_pkt_len = info->outer_l2_len + info->outer_l3_len +
+ info->l2_len + info->l3_len + info->l4_len +
+ info->tunnel_tso_segsz;
+ if (info->tunnel_tso_segsz != 0 && info->pkt_len > max_pkt_len)
+ tso_segsz = info->tunnel_tso_segsz;
+ }
+
+ if (info->ethertype == _htons(ETHER_TYPE_IPv4)) {
+ ipv4_hdr = l3_hdr;
+ ipv4_hdr->hdr_checksum = 0;
+
+ ol_flags |= PKT_TX_IPV4;
+ if (info->l4_proto == IPPROTO_TCP && tso_segsz) {
+ ol_flags |= PKT_TX_IP_CKSUM;
+ } else {
+ if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_IP_CKSUM)
+ ol_flags |= PKT_TX_IP_CKSUM;
+ else
+ ipv4_hdr->hdr_checksum =
+ rte_ipv4_cksum(ipv4_hdr);
+ }
+ } else if (info->ethertype == _htons(ETHER_TYPE_IPv6))
+ ol_flags |= PKT_TX_IPV6;
+ else
+ return 0; /* packet type not supported, nothing to do */
+
+ if (info->l4_proto == IPPROTO_UDP) {
+ udp_hdr = (struct udp_hdr *)((char *)l3_hdr + info->l3_len);
+ /* do not recalculate udp cksum if it was 0 */
+ if (udp_hdr->dgram_cksum != 0) {
+ udp_hdr->dgram_cksum = 0;
+ if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_UDP_CKSUM)
+ ol_flags |= PKT_TX_UDP_CKSUM;
+ else {
+ udp_hdr->dgram_cksum =
+ get_udptcp_checksum(l3_hdr, udp_hdr,
+ info->ethertype);
+ }
+ }
+ } else if (info->l4_proto == IPPROTO_TCP) {
+ tcp_hdr = (struct tcp_hdr *)((char *)l3_hdr + info->l3_len);
+ tcp_hdr->cksum = 0;
+ if (tso_segsz)
+ ol_flags |= PKT_TX_TCP_SEG;
+ else if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_TCP_CKSUM)
+ ol_flags |= PKT_TX_TCP_CKSUM;
+ else {
+ tcp_hdr->cksum =
+ get_udptcp_checksum(l3_hdr, tcp_hdr,
+ info->ethertype);
+ }
+ } else if (info->l4_proto == IPPROTO_SCTP) {
+ sctp_hdr = (struct sctp_hdr *)((char *)l3_hdr + info->l3_len);
+ sctp_hdr->cksum = 0;
+ /* sctp payload must be a multiple of 4 to be
+ * offloaded */
+ if ((testpmd_ol_flags & TESTPMD_TX_OFFLOAD_SCTP_CKSUM) &&
+ ((ipv4_hdr->total_length & 0x3) == 0)) {
+ ol_flags |= PKT_TX_SCTP_CKSUM;
+ } else {
+ /* XXX implement CRC32c, example available in
+ * RFC3309 */
+ }
+ }
+
+ return ol_flags;
+}
+
+/* Calculate the checksum of outer header */
+static uint64_t
+process_outer_cksums(void *outer_l3_hdr, struct testpmd_offload_info *info,
+ uint16_t testpmd_ol_flags, int tso_enabled)
+{
+ struct ipv4_hdr *ipv4_hdr = outer_l3_hdr;
+ struct ipv6_hdr *ipv6_hdr = outer_l3_hdr;
+ struct udp_hdr *udp_hdr;
+ uint64_t ol_flags = 0;
+
+ if (info->outer_ethertype == _htons(ETHER_TYPE_IPv4)) {
+ ipv4_hdr->hdr_checksum = 0;
+ ol_flags |= PKT_TX_OUTER_IPV4;
+
+ if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_OUTER_IP_CKSUM)
+ ol_flags |= PKT_TX_OUTER_IP_CKSUM;
+ else
+ ipv4_hdr->hdr_checksum = rte_ipv4_cksum(ipv4_hdr);
+ } else
+ ol_flags |= PKT_TX_OUTER_IPV6;
+
+ if (info->outer_l4_proto != IPPROTO_UDP)
+ return ol_flags;
+
+ udp_hdr = (struct udp_hdr *)((char *)outer_l3_hdr + info->outer_l3_len);
+
+ /* outer UDP checksum is done in software as we have no hardware
+ * supporting it today, and no API for it. In the other side, for
+ * UDP tunneling, like VXLAN or Geneve, outer UDP checksum can be
+ * set to zero.
+ *
+ * If a packet will be TSOed into small packets by NIC, we cannot
+ * set/calculate a non-zero checksum, because it will be a wrong
+ * value after the packet be split into several small packets.
+ */
+ if (tso_enabled)
+ udp_hdr->dgram_cksum = 0;
+
+ /* do not recalculate udp cksum if it was 0 */
+ if (udp_hdr->dgram_cksum != 0) {
+ udp_hdr->dgram_cksum = 0;
+ if (info->outer_ethertype == _htons(ETHER_TYPE_IPv4))
+ udp_hdr->dgram_cksum =
+ rte_ipv4_udptcp_cksum(ipv4_hdr, udp_hdr);
+ else
+ udp_hdr->dgram_cksum =
+ rte_ipv6_udptcp_cksum(ipv6_hdr, udp_hdr);
+ }
+
+ return ol_flags;
+}
+
+/*
+ * Helper function.
+ * Performs actual copying.
+ * Returns number of segments in the destination mbuf on success,
+ * or negative error code on failure.
+ */
+static int
+mbuf_copy_split(const struct rte_mbuf *ms, struct rte_mbuf *md[],
+ uint16_t seglen[], uint8_t nb_seg)
+{
+ uint32_t dlen, slen, tlen;
+ uint32_t i, len;
+ const struct rte_mbuf *m;
+ const uint8_t *src;
+ uint8_t *dst;
+
+ dlen = 0;
+ slen = 0;
+ tlen = 0;
+
+ dst = NULL;
+ src = NULL;
+
+ m = ms;
+ i = 0;
+ while (ms != NULL && i != nb_seg) {
+
+ if (slen == 0) {
+ slen = rte_pktmbuf_data_len(ms);
+ src = rte_pktmbuf_mtod(ms, const uint8_t *);
+ }
+
+ if (dlen == 0) {
+ dlen = RTE_MIN(seglen[i], slen);
+ md[i]->data_len = dlen;
+ md[i]->next = (i + 1 == nb_seg) ? NULL : md[i + 1];
+ dst = rte_pktmbuf_mtod(md[i], uint8_t *);
+ }
+
+ len = RTE_MIN(slen, dlen);
+ memcpy(dst, src, len);
+ tlen += len;
+ slen -= len;
+ dlen -= len;
+ src += len;
+ dst += len;
+
+ if (slen == 0)
+ ms = ms->next;
+ if (dlen == 0)
+ i++;
+ }
+
+ if (ms != NULL)
+ return -ENOBUFS;
+ else if (tlen != m->pkt_len)
+ return -EINVAL;
+
+ md[0]->nb_segs = nb_seg;
+ md[0]->pkt_len = tlen;
+ md[0]->vlan_tci = m->vlan_tci;
+ md[0]->vlan_tci_outer = m->vlan_tci_outer;
+ md[0]->ol_flags = m->ol_flags;
+ md[0]->tx_offload = m->tx_offload;
+
+ return nb_seg;
+}
+
+/*
+ * Allocate a new mbuf with up to tx_pkt_nb_segs segments.
+ * Copy packet contents and offload information into then new segmented mbuf.
+ */
+static struct rte_mbuf *
+pkt_copy_split(const struct rte_mbuf *pkt)
+{
+ int32_t n, rc;
+ uint32_t i, len, nb_seg;
+ struct rte_mempool *mp;
+ uint16_t seglen[RTE_MAX_SEGS_PER_PKT];
+ struct rte_mbuf *p, *md[RTE_MAX_SEGS_PER_PKT];
+
+ mp = current_fwd_lcore()->mbp;
+
+ if (tx_pkt_split == TX_PKT_SPLIT_RND)
+ nb_seg = random() % tx_pkt_nb_segs + 1;
+ else
+ nb_seg = tx_pkt_nb_segs;
+
+ memcpy(seglen, tx_pkt_seg_lengths, nb_seg * sizeof(seglen[0]));
+
+ /* calculate number of segments to use and their length. */
+ len = 0;
+ for (i = 0; i != nb_seg && len < pkt->pkt_len; i++) {
+ len += seglen[i];
+ md[i] = NULL;
+ }
+
+ n = pkt->pkt_len - len;
+
+ /* update size of the last segment to fit rest of the packet */
+ if (n >= 0) {
+ seglen[i - 1] += n;
+ len += n;
+ }
+
+ nb_seg = i;
+ while (i != 0) {
+ p = rte_pktmbuf_alloc(mp);
+ if (p == NULL) {
+ RTE_LOG(ERR, USER1,
+ "failed to allocate %u-th of %u mbuf "
+ "from mempool: %s\n",
+ nb_seg - i, nb_seg, mp->name);
+ break;
+ }
+
+ md[--i] = p;
+ if (rte_pktmbuf_tailroom(md[i]) < seglen[i]) {
+ RTE_LOG(ERR, USER1, "mempool %s, %u-th segment: "
+ "expected seglen: %u, "
+ "actual mbuf tailroom: %u\n",
+ mp->name, i, seglen[i],
+ rte_pktmbuf_tailroom(md[i]));
+ break;
+ }
+ }
+
+ /* all mbufs successfully allocated, do copy */
+ if (i == 0) {
+ rc = mbuf_copy_split(pkt, md, seglen, nb_seg);
+ if (rc < 0)
+ RTE_LOG(ERR, USER1,
+ "mbuf_copy_split for %p(len=%u, nb_seg=%u) "
+ "into %u segments failed with error code: %d\n",
+ pkt, pkt->pkt_len, pkt->nb_segs, nb_seg, rc);
+
+ /* figure out how many mbufs to free. */
+ i = RTE_MAX(rc, 0);
+ }
+
+ /* free unused mbufs */
+ for (; i != nb_seg; i++) {
+ rte_pktmbuf_free_seg(md[i]);
+ md[i] = NULL;
+ }
+
+ return md[0];
+}
+
+/*
+ * Receive a burst of packets, and for each packet:
+ * - parse packet, and try to recognize a supported packet type (1)
+ * - if it's not a supported packet type, don't touch the packet, else:
+ * - reprocess the checksum of all supported layers. This is done in SW
+ * or HW, depending on testpmd command line configuration
+ * - if TSO is enabled in testpmd command line, also flag the mbuf for TCP
+ * segmentation offload (this implies HW TCP checksum)
+ * Then transmit packets on the output port.
+ *
+ * (1) Supported packets are:
+ * Ether / (vlan) / IP|IP6 / UDP|TCP|SCTP .
+ * Ether / (vlan) / outer IP|IP6 / outer UDP / VxLAN / Ether / IP|IP6 /
+ * UDP|TCP|SCTP
+ * Ether / (vlan) / outer IP|IP6 / GRE / Ether / IP|IP6 / UDP|TCP|SCTP
+ * Ether / (vlan) / outer IP|IP6 / GRE / IP|IP6 / UDP|TCP|SCTP
+ * Ether / (vlan) / outer IP|IP6 / IP|IP6 / UDP|TCP|SCTP
+ *
+ * The testpmd command line for this forward engine sets the flags
+ * TESTPMD_TX_OFFLOAD_* in ports[tx_port].tx_ol_flags. They control
+ * wether a checksum must be calculated in software or in hardware. The
+ * IP, UDP, TCP and SCTP flags always concern the inner layer. The
+ * OUTER_IP is only useful for tunnel packets.
+ */
+static void
+pkt_burst_checksum_forward(struct fwd_stream *fs)
+{
+ struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+ struct rte_port *txp;
+ struct rte_mbuf *m, *p;
+ struct ether_hdr *eth_hdr;
+ void *l3_hdr = NULL, *outer_l3_hdr = NULL; /* can be IPv4 or IPv6 */
+ uint16_t nb_rx;
+ uint16_t nb_tx;
+ uint16_t nb_prep;
+ uint16_t i;
+ uint64_t rx_ol_flags, tx_ol_flags;
+ uint16_t testpmd_ol_flags;
+ uint32_t retry;
+ uint32_t rx_bad_ip_csum;
+ uint32_t rx_bad_l4_csum;
+ struct testpmd_offload_info info;
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ uint64_t start_tsc;
+ uint64_t end_tsc;
+ uint64_t core_cycles;
+#endif
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ start_tsc = rte_rdtsc();
+#endif
+
+ /* receive a burst of packet */
+ nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst,
+ nb_pkt_per_burst);
+ if (unlikely(nb_rx == 0))
+ return;
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->rx_burst_stats.pkt_burst_spread[nb_rx]++;
+#endif
+ fs->rx_packets += nb_rx;
+ rx_bad_ip_csum = 0;
+ rx_bad_l4_csum = 0;
+
+ txp = &ports[fs->tx_port];
+ testpmd_ol_flags = txp->tx_ol_flags;
+ memset(&info, 0, sizeof(info));
+ info.tso_segsz = txp->tso_segsz;
+ info.tunnel_tso_segsz = txp->tunnel_tso_segsz;
+
+ for (i = 0; i < nb_rx; i++) {
+ if (likely(i < nb_rx - 1))
+ rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
+ void *));
+
+ m = pkts_burst[i];
+ info.is_tunnel = 0;
+ info.pkt_len = rte_pktmbuf_pkt_len(m);
+ tx_ol_flags = 0;
+ rx_ol_flags = m->ol_flags;
+
+ /* Update the L3/L4 checksum error packet statistics */
+ if ((rx_ol_flags & PKT_RX_IP_CKSUM_MASK) == PKT_RX_IP_CKSUM_BAD)
+ rx_bad_ip_csum += 1;
+ if ((rx_ol_flags & PKT_RX_L4_CKSUM_MASK) == PKT_RX_L4_CKSUM_BAD)
+ rx_bad_l4_csum += 1;
+
+ /* step 1: dissect packet, parsing optional vlan, ip4/ip6, vxlan
+ * and inner headers */
+
+ eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);
+ ether_addr_copy(&peer_eth_addrs[fs->peer_addr],
+ &eth_hdr->d_addr);
+ ether_addr_copy(&ports[fs->tx_port].eth_addr,
+ &eth_hdr->s_addr);
+ parse_ethernet(eth_hdr, &info);
+ l3_hdr = (char *)eth_hdr + info.l2_len;
+
+ /* check if it's a supported tunnel */
+ if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_PARSE_TUNNEL) {
+ if (info.l4_proto == IPPROTO_UDP) {
+ struct udp_hdr *udp_hdr;
+
+ udp_hdr = (struct udp_hdr *)((char *)l3_hdr +
+ info.l3_len);
+ parse_vxlan(udp_hdr, &info, m->packet_type);
+ if (info.is_tunnel)
+ tx_ol_flags |= PKT_TX_TUNNEL_VXLAN;
+ } else if (info.l4_proto == IPPROTO_GRE) {
+ struct simple_gre_hdr *gre_hdr;
+
+ gre_hdr = (struct simple_gre_hdr *)
+ ((char *)l3_hdr + info.l3_len);
+ parse_gre(gre_hdr, &info);
+ if (info.is_tunnel)
+ tx_ol_flags |= PKT_TX_TUNNEL_GRE;
+ } else if (info.l4_proto == IPPROTO_IPIP) {
+ void *encap_ip_hdr;
+
+ encap_ip_hdr = (char *)l3_hdr + info.l3_len;
+ parse_encap_ip(encap_ip_hdr, &info);
+ if (info.is_tunnel)
+ tx_ol_flags |= PKT_TX_TUNNEL_IPIP;
+ }
+ }
+
+ /* update l3_hdr and outer_l3_hdr if a tunnel was parsed */
+ if (info.is_tunnel) {
+ outer_l3_hdr = l3_hdr;
+ l3_hdr = (char *)l3_hdr + info.outer_l3_len + info.l2_len;
+ }
+
+ /* step 2: depending on user command line configuration,
+ * recompute checksum either in software or flag the
+ * mbuf to offload the calculation to the NIC. If TSO
+ * is configured, prepare the mbuf for TCP segmentation. */
+
+ /* process checksums of inner headers first */
+ tx_ol_flags |= process_inner_cksums(l3_hdr, &info,
+ testpmd_ol_flags);
+
+ /* Then process outer headers if any. Note that the software
+ * checksum will be wrong if one of the inner checksums is
+ * processed in hardware. */
+ if (info.is_tunnel == 1) {
+ tx_ol_flags |= process_outer_cksums(outer_l3_hdr, &info,
+ testpmd_ol_flags,
+ !!(tx_ol_flags & PKT_TX_TCP_SEG));
+ }
+
+ /* step 3: fill the mbuf meta data (flags and header lengths) */
+
+ if (info.is_tunnel == 1) {
+ if (info.tunnel_tso_segsz ||
+ (testpmd_ol_flags &
+ TESTPMD_TX_OFFLOAD_OUTER_IP_CKSUM) ||
+ (tx_ol_flags & PKT_TX_OUTER_IPV6)) {
+ m->outer_l2_len = info.outer_l2_len;
+ m->outer_l3_len = info.outer_l3_len;
+ m->l2_len = info.l2_len;
+ m->l3_len = info.l3_len;
+ m->l4_len = info.l4_len;
+ m->tso_segsz = info.tunnel_tso_segsz;
+ }
+ else {
+ /* if there is a outer UDP cksum
+ processed in sw and the inner in hw,
+ the outer checksum will be wrong as
+ the payload will be modified by the
+ hardware */
+ m->l2_len = info.outer_l2_len +
+ info.outer_l3_len + info.l2_len;
+ m->l3_len = info.l3_len;
+ m->l4_len = info.l4_len;
+ }
+ } else {
+ /* this is only useful if an offload flag is
+ * set, but it does not hurt to fill it in any
+ * case */
+ m->l2_len = info.l2_len;
+ m->l3_len = info.l3_len;
+ m->l4_len = info.l4_len;
+ m->tso_segsz = info.tso_segsz;
+ }
+ m->ol_flags = tx_ol_flags;
+
+ /* Do split & copy for the packet. */
+ if (tx_pkt_split != TX_PKT_SPLIT_OFF) {
+ p = pkt_copy_split(m);
+ if (p != NULL) {
+ rte_pktmbuf_free(m);
+ m = p;
+ pkts_burst[i] = m;
+ }
+ }
+
+ /* if verbose mode is enabled, dump debug info */
+ if (verbose_level > 0) {
+ char buf[256];
+
+ printf("-----------------\n");
+ printf("port=%u, mbuf=%p, pkt_len=%u, nb_segs=%u:\n",
+ fs->rx_port, m, m->pkt_len, m->nb_segs);
+ /* dump rx parsed packet info */
+ rte_get_rx_ol_flag_list(rx_ol_flags, buf, sizeof(buf));
+ printf("rx: l2_len=%d ethertype=%x l3_len=%d "
+ "l4_proto=%d l4_len=%d flags=%s\n",
+ info.l2_len, rte_be_to_cpu_16(info.ethertype),
+ info.l3_len, info.l4_proto, info.l4_len, buf);
+ if (rx_ol_flags & PKT_RX_LRO)
+ printf("rx: m->lro_segsz=%u\n", m->tso_segsz);
+ if (info.is_tunnel == 1)
+ printf("rx: outer_l2_len=%d outer_ethertype=%x "
+ "outer_l3_len=%d\n", info.outer_l2_len,
+ rte_be_to_cpu_16(info.outer_ethertype),
+ info.outer_l3_len);
+ /* dump tx packet info */
+ if ((testpmd_ol_flags & (TESTPMD_TX_OFFLOAD_IP_CKSUM |
+ TESTPMD_TX_OFFLOAD_UDP_CKSUM |
+ TESTPMD_TX_OFFLOAD_TCP_CKSUM |
+ TESTPMD_TX_OFFLOAD_SCTP_CKSUM)) ||
+ info.tso_segsz != 0)
+ printf("tx: m->l2_len=%d m->l3_len=%d "
+ "m->l4_len=%d\n",
+ m->l2_len, m->l3_len, m->l4_len);
+ if (info.is_tunnel == 1) {
+ if ((testpmd_ol_flags &
+ TESTPMD_TX_OFFLOAD_OUTER_IP_CKSUM) ||
+ (tx_ol_flags & PKT_TX_OUTER_IPV6))
+ printf("tx: m->outer_l2_len=%d "
+ "m->outer_l3_len=%d\n",
+ m->outer_l2_len,
+ m->outer_l3_len);
+ if (info.tunnel_tso_segsz != 0 &&
+ (m->ol_flags & PKT_TX_TCP_SEG))
+ printf("tx: m->tso_segsz=%d\n",
+ m->tso_segsz);
+ } else if (info.tso_segsz != 0 &&
+ (m->ol_flags & PKT_TX_TCP_SEG))
+ printf("tx: m->tso_segsz=%d\n", m->tso_segsz);
+ rte_get_tx_ol_flag_list(m->ol_flags, buf, sizeof(buf));
+ printf("tx: flags=%s", buf);
+ printf("\n");
+ }
+ }
+
+ nb_prep = rte_eth_tx_prepare(fs->tx_port, fs->tx_queue,
+ pkts_burst, nb_rx);
+ if (nb_prep != nb_rx)
+ printf("Preparing packet burst to transmit failed: %s\n",
+ rte_strerror(rte_errno));
+
+ nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst,
+ nb_prep);
+
+ /*
+ * Retry if necessary
+ */
+ if (unlikely(nb_tx < nb_rx) && fs->retry_enabled) {
+ retry = 0;
+ while (nb_tx < nb_rx && retry++ < burst_tx_retry_num) {
+ rte_delay_us(burst_tx_delay_time);
+ nb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue,
+ &pkts_burst[nb_tx], nb_rx - nb_tx);
+ }
+ }
+ fs->tx_packets += nb_tx;
+ fs->rx_bad_ip_csum += rx_bad_ip_csum;
+ fs->rx_bad_l4_csum += rx_bad_l4_csum;
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->tx_burst_stats.pkt_burst_spread[nb_tx]++;
+#endif
+ if (unlikely(nb_tx < nb_rx)) {
+ fs->fwd_dropped += (nb_rx - nb_tx);
+ do {
+ rte_pktmbuf_free(pkts_burst[nb_tx]);
+ } while (++nb_tx < nb_rx);
+ }
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ end_tsc = rte_rdtsc();
+ core_cycles = (end_tsc - start_tsc);
+ fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles);
+#endif
+}
+
+struct fwd_engine csum_fwd_engine = {
+ .fwd_mode_name = "csum",
+ .port_fwd_begin = NULL,
+ .port_fwd_end = NULL,
+ .packet_fwd = pkt_burst_checksum_forward,
+};
diff --git a/src/seastar/dpdk/app/test-pmd/flowgen.c b/src/seastar/dpdk/app/test-pmd/flowgen.c
new file mode 100644
index 00000000..13b4f900
--- /dev/null
+++ b/src/seastar/dpdk/app/test-pmd/flowgen.c
@@ -0,0 +1,248 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2013 Tilera Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Tilera Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_cycles.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_memzone.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_memory.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_udp.h>
+#include <rte_string_fns.h>
+#include <rte_flow.h>
+
+#include "testpmd.h"
+
+/* hardcoded configuration (for now) */
+static unsigned cfg_n_flows = 1024;
+static uint32_t cfg_ip_src = IPv4(10, 254, 0, 0);
+static uint32_t cfg_ip_dst = IPv4(10, 253, 0, 0);
+static uint16_t cfg_udp_src = 1000;
+static uint16_t cfg_udp_dst = 1001;
+static struct ether_addr cfg_ether_src =
+ {{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x00 }};
+static struct ether_addr cfg_ether_dst =
+ {{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x01 }};
+
+#define IP_DEFTTL 64 /* from RFC 1340. */
+#define IP_VERSION 0x40
+#define IP_HDRLEN 0x05 /* default IP header length == five 32-bits words. */
+#define IP_VHL_DEF (IP_VERSION | IP_HDRLEN)
+
+static inline uint16_t
+ip_sum(const unaligned_uint16_t *hdr, int hdr_len)
+{
+ uint32_t sum = 0;
+
+ while (hdr_len > 1)
+ {
+ sum += *hdr++;
+ if (sum & 0x80000000)
+ sum = (sum & 0xFFFF) + (sum >> 16);
+ hdr_len -= 2;
+ }
+
+ while (sum >> 16)
+ sum = (sum & 0xFFFF) + (sum >> 16);
+
+ return ~sum;
+}
+
+/*
+ * Multi-flow generation mode.
+ *
+ * We originate a bunch of flows (varying destination IP addresses), and
+ * terminate receive traffic. Received traffic is simply discarded, but we
+ * still do so in order to maintain traffic statistics.
+ */
+static void
+pkt_burst_flow_gen(struct fwd_stream *fs)
+{
+ unsigned pkt_size = tx_pkt_length - 4; /* Adjust FCS */
+ struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+ struct rte_mempool *mbp;
+ struct rte_mbuf *pkt;
+ struct ether_hdr *eth_hdr;
+ struct ipv4_hdr *ip_hdr;
+ struct udp_hdr *udp_hdr;
+ uint16_t vlan_tci, vlan_tci_outer;
+ uint16_t ol_flags;
+ uint16_t nb_rx;
+ uint16_t nb_tx;
+ uint16_t nb_pkt;
+ uint16_t i;
+ uint32_t retry;
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ uint64_t start_tsc;
+ uint64_t end_tsc;
+ uint64_t core_cycles;
+#endif
+ static int next_flow = 0;
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ start_tsc = rte_rdtsc();
+#endif
+
+ /* Receive a burst of packets and discard them. */
+ nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst,
+ nb_pkt_per_burst);
+ fs->rx_packets += nb_rx;
+
+ for (i = 0; i < nb_rx; i++)
+ rte_pktmbuf_free(pkts_burst[i]);
+
+ mbp = current_fwd_lcore()->mbp;
+ vlan_tci = ports[fs->tx_port].tx_vlan_id;
+ vlan_tci_outer = ports[fs->tx_port].tx_vlan_id_outer;
+ ol_flags = ports[fs->tx_port].tx_ol_flags;
+
+ for (nb_pkt = 0; nb_pkt < nb_pkt_per_burst; nb_pkt++) {
+ pkt = rte_mbuf_raw_alloc(mbp);
+ if (!pkt)
+ break;
+
+ pkt->data_len = pkt_size;
+ pkt->next = NULL;
+
+ /* Initialize Ethernet header. */
+ eth_hdr = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
+ ether_addr_copy(&cfg_ether_dst, &eth_hdr->d_addr);
+ ether_addr_copy(&cfg_ether_src, &eth_hdr->s_addr);
+ eth_hdr->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
+
+ /* Initialize IP header. */
+ ip_hdr = (struct ipv4_hdr *)(eth_hdr + 1);
+ memset(ip_hdr, 0, sizeof(*ip_hdr));
+ ip_hdr->version_ihl = IP_VHL_DEF;
+ ip_hdr->type_of_service = 0;
+ ip_hdr->fragment_offset = 0;
+ ip_hdr->time_to_live = IP_DEFTTL;
+ ip_hdr->next_proto_id = IPPROTO_UDP;
+ ip_hdr->packet_id = 0;
+ ip_hdr->src_addr = rte_cpu_to_be_32(cfg_ip_src);
+ ip_hdr->dst_addr = rte_cpu_to_be_32(cfg_ip_dst +
+ next_flow);
+ ip_hdr->total_length = RTE_CPU_TO_BE_16(pkt_size -
+ sizeof(*eth_hdr));
+ ip_hdr->hdr_checksum = ip_sum((unaligned_uint16_t *)ip_hdr,
+ sizeof(*ip_hdr));
+
+ /* Initialize UDP header. */
+ udp_hdr = (struct udp_hdr *)(ip_hdr + 1);
+ udp_hdr->src_port = rte_cpu_to_be_16(cfg_udp_src);
+ udp_hdr->dst_port = rte_cpu_to_be_16(cfg_udp_dst);
+ udp_hdr->dgram_cksum = 0; /* No UDP checksum. */
+ udp_hdr->dgram_len = RTE_CPU_TO_BE_16(pkt_size -
+ sizeof(*eth_hdr) -
+ sizeof(*ip_hdr));
+ pkt->nb_segs = 1;
+ pkt->pkt_len = pkt_size;
+ pkt->ol_flags = ol_flags;
+ pkt->vlan_tci = vlan_tci;
+ pkt->vlan_tci_outer = vlan_tci_outer;
+ pkt->l2_len = sizeof(struct ether_hdr);
+ pkt->l3_len = sizeof(struct ipv4_hdr);
+ pkts_burst[nb_pkt] = pkt;
+
+ next_flow = (next_flow + 1) % cfg_n_flows;
+ }
+
+ nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_pkt);
+ /*
+ * Retry if necessary
+ */
+ if (unlikely(nb_tx < nb_rx) && fs->retry_enabled) {
+ retry = 0;
+ while (nb_tx < nb_rx && retry++ < burst_tx_retry_num) {
+ rte_delay_us(burst_tx_delay_time);
+ nb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue,
+ &pkts_burst[nb_tx], nb_rx - nb_tx);
+ }
+ }
+ fs->tx_packets += nb_tx;
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->tx_burst_stats.pkt_burst_spread[nb_tx]++;
+#endif
+ if (unlikely(nb_tx < nb_pkt)) {
+ /* Back out the flow counter. */
+ next_flow -= (nb_pkt - nb_tx);
+ while (next_flow < 0)
+ next_flow += cfg_n_flows;
+
+ do {
+ rte_pktmbuf_free(pkts_burst[nb_tx]);
+ } while (++nb_tx < nb_pkt);
+ }
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ end_tsc = rte_rdtsc();
+ core_cycles = (end_tsc - start_tsc);
+ fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles);
+#endif
+}
+
+struct fwd_engine flow_gen_engine = {
+ .fwd_mode_name = "flowgen",
+ .port_fwd_begin = NULL,
+ .port_fwd_end = NULL,
+ .packet_fwd = pkt_burst_flow_gen,
+};
diff --git a/src/seastar/dpdk/app/test-pmd/icmpecho.c b/src/seastar/dpdk/app/test-pmd/icmpecho.c
new file mode 100644
index 00000000..d4b4c9eb
--- /dev/null
+++ b/src/seastar/dpdk/app/test-pmd/icmpecho.c
@@ -0,0 +1,560 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2013 6WIND
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of 6WIND S.A. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_cycles.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_memory.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_arp.h>
+#include <rte_ip.h>
+#include <rte_icmp.h>
+#include <rte_string_fns.h>
+#include <rte_flow.h>
+
+#include "testpmd.h"
+
+static const char *
+arp_op_name(uint16_t arp_op)
+{
+ switch (arp_op ) {
+ case ARP_OP_REQUEST:
+ return "ARP Request";
+ case ARP_OP_REPLY:
+ return "ARP Reply";
+ case ARP_OP_REVREQUEST:
+ return "Reverse ARP Request";
+ case ARP_OP_REVREPLY:
+ return "Reverse ARP Reply";
+ case ARP_OP_INVREQUEST:
+ return "Peer Identify Request";
+ case ARP_OP_INVREPLY:
+ return "Peer Identify Reply";
+ default:
+ break;
+ }
+ return "Unkwown ARP op";
+}
+
+static const char *
+ip_proto_name(uint16_t ip_proto)
+{
+ static const char * ip_proto_names[] = {
+ "IP6HOPOPTS", /**< IP6 hop-by-hop options */
+ "ICMP", /**< control message protocol */
+ "IGMP", /**< group mgmt protocol */
+ "GGP", /**< gateway^2 (deprecated) */
+ "IPv4", /**< IPv4 encapsulation */
+
+ "UNASSIGNED",
+ "TCP", /**< transport control protocol */
+ "ST", /**< Stream protocol II */
+ "EGP", /**< exterior gateway protocol */
+ "PIGP", /**< private interior gateway */
+
+ "RCC_MON", /**< BBN RCC Monitoring */
+ "NVPII", /**< network voice protocol*/
+ "PUP", /**< pup */
+ "ARGUS", /**< Argus */
+ "EMCON", /**< EMCON */
+
+ "XNET", /**< Cross Net Debugger */
+ "CHAOS", /**< Chaos*/
+ "UDP", /**< user datagram protocol */
+ "MUX", /**< Multiplexing */
+ "DCN_MEAS", /**< DCN Measurement Subsystems */
+
+ "HMP", /**< Host Monitoring */
+ "PRM", /**< Packet Radio Measurement */
+ "XNS_IDP", /**< xns idp */
+ "TRUNK1", /**< Trunk-1 */
+ "TRUNK2", /**< Trunk-2 */
+
+ "LEAF1", /**< Leaf-1 */
+ "LEAF2", /**< Leaf-2 */
+ "RDP", /**< Reliable Data */
+ "IRTP", /**< Reliable Transaction */
+ "TP4", /**< tp-4 w/ class negotiation */
+
+ "BLT", /**< Bulk Data Transfer */
+ "NSP", /**< Network Services */
+ "INP", /**< Merit Internodal */
+ "SEP", /**< Sequential Exchange */
+ "3PC", /**< Third Party Connect */
+
+ "IDPR", /**< InterDomain Policy Routing */
+ "XTP", /**< XTP */
+ "DDP", /**< Datagram Delivery */
+ "CMTP", /**< Control Message Transport */
+ "TPXX", /**< TP++ Transport */
+
+ "ILTP", /**< IL transport protocol */
+ "IPv6_HDR", /**< IP6 header */
+ "SDRP", /**< Source Demand Routing */
+ "IPv6_RTG", /**< IP6 routing header */
+ "IPv6_FRAG", /**< IP6 fragmentation header */
+
+ "IDRP", /**< InterDomain Routing*/
+ "RSVP", /**< resource reservation */
+ "GRE", /**< General Routing Encap. */
+ "MHRP", /**< Mobile Host Routing */
+ "BHA", /**< BHA */
+
+ "ESP", /**< IP6 Encap Sec. Payload */
+ "AH", /**< IP6 Auth Header */
+ "INLSP", /**< Integ. Net Layer Security */
+ "SWIPE", /**< IP with encryption */
+ "NHRP", /**< Next Hop Resolution */
+
+ "UNASSIGNED",
+ "UNASSIGNED",
+ "UNASSIGNED",
+ "ICMPv6", /**< ICMP6 */
+ "IPv6NONEXT", /**< IP6 no next header */
+
+ "Ipv6DSTOPTS",/**< IP6 destination option */
+ "AHIP", /**< any host internal protocol */
+ "CFTP", /**< CFTP */
+ "HELLO", /**< "hello" routing protocol */
+ "SATEXPAK", /**< SATNET/Backroom EXPAK */
+
+ "KRYPTOLAN", /**< Kryptolan */
+ "RVD", /**< Remote Virtual Disk */
+ "IPPC", /**< Pluribus Packet Core */
+ "ADFS", /**< Any distributed FS */
+ "SATMON", /**< Satnet Monitoring */
+
+ "VISA", /**< VISA Protocol */
+ "IPCV", /**< Packet Core Utility */
+ "CPNX", /**< Comp. Prot. Net. Executive */
+ "CPHB", /**< Comp. Prot. HeartBeat */
+ "WSN", /**< Wang Span Network */
+
+ "PVP", /**< Packet Video Protocol */
+ "BRSATMON", /**< BackRoom SATNET Monitoring */
+ "ND", /**< Sun net disk proto (temp.) */
+ "WBMON", /**< WIDEBAND Monitoring */
+ "WBEXPAK", /**< WIDEBAND EXPAK */
+
+ "EON", /**< ISO cnlp */
+ "VMTP", /**< VMTP */
+ "SVMTP", /**< Secure VMTP */
+ "VINES", /**< Banyon VINES */
+ "TTP", /**< TTP */
+
+ "IGP", /**< NSFNET-IGP */
+ "DGP", /**< dissimilar gateway prot. */
+ "TCF", /**< TCF */
+ "IGRP", /**< Cisco/GXS IGRP */
+ "OSPFIGP", /**< OSPFIGP */
+
+ "SRPC", /**< Strite RPC protocol */
+ "LARP", /**< Locus Address Resolution */
+ "MTP", /**< Multicast Transport */
+ "AX25", /**< AX.25 Frames */
+ "4IN4", /**< IP encapsulated in IP */
+
+ "MICP", /**< Mobile Int.ing control */
+ "SCCSP", /**< Semaphore Comm. security */
+ "ETHERIP", /**< Ethernet IP encapsulation */
+ "ENCAP", /**< encapsulation header */
+ "AES", /**< any private encr. scheme */
+
+ "GMTP", /**< GMTP */
+ "IPCOMP", /**< payload compression (IPComp) */
+ "UNASSIGNED",
+ "UNASSIGNED",
+ "PIM", /**< Protocol Independent Mcast */
+ };
+
+ if (ip_proto < sizeof(ip_proto_names) / sizeof(ip_proto_names[0]))
+ return ip_proto_names[ip_proto];
+ switch (ip_proto) {
+#ifdef IPPROTO_PGM
+ case IPPROTO_PGM: /**< PGM */
+ return "PGM";
+#endif
+ case IPPROTO_SCTP: /**< Stream Control Transport Protocol */
+ return "SCTP";
+#ifdef IPPROTO_DIVERT
+ case IPPROTO_DIVERT: /**< divert pseudo-protocol */
+ return "DIVERT";
+#endif
+ case IPPROTO_RAW: /**< raw IP packet */
+ return "RAW";
+ default:
+ break;
+ }
+ return "UNASSIGNED";
+}
+
+static void
+ipv4_addr_to_dot(uint32_t be_ipv4_addr, char *buf)
+{
+ uint32_t ipv4_addr;
+
+ ipv4_addr = rte_be_to_cpu_32(be_ipv4_addr);
+ sprintf(buf, "%d.%d.%d.%d", (ipv4_addr >> 24) & 0xFF,
+ (ipv4_addr >> 16) & 0xFF, (ipv4_addr >> 8) & 0xFF,
+ ipv4_addr & 0xFF);
+}
+
+static void
+ether_addr_dump(const char *what, const struct ether_addr *ea)
+{
+ char buf[ETHER_ADDR_FMT_SIZE];
+
+ ether_format_addr(buf, ETHER_ADDR_FMT_SIZE, ea);
+ if (what)
+ printf("%s", what);
+ printf("%s", buf);
+}
+
+static void
+ipv4_addr_dump(const char *what, uint32_t be_ipv4_addr)
+{
+ char buf[16];
+
+ ipv4_addr_to_dot(be_ipv4_addr, buf);
+ if (what)
+ printf("%s", what);
+ printf("%s", buf);
+}
+
+static uint16_t
+ipv4_hdr_cksum(struct ipv4_hdr *ip_h)
+{
+ uint16_t *v16_h;
+ uint32_t ip_cksum;
+
+ /*
+ * Compute the sum of successive 16-bit words of the IPv4 header,
+ * skipping the checksum field of the header.
+ */
+ v16_h = (unaligned_uint16_t *) ip_h;
+ ip_cksum = v16_h[0] + v16_h[1] + v16_h[2] + v16_h[3] +
+ v16_h[4] + v16_h[6] + v16_h[7] + v16_h[8] + v16_h[9];
+
+ /* reduce 32 bit checksum to 16 bits and complement it */
+ ip_cksum = (ip_cksum & 0xffff) + (ip_cksum >> 16);
+ ip_cksum = (ip_cksum & 0xffff) + (ip_cksum >> 16);
+ ip_cksum = (~ip_cksum) & 0x0000FFFF;
+ return (ip_cksum == 0) ? 0xFFFF : (uint16_t) ip_cksum;
+}
+
+#define is_multicast_ipv4_addr(ipv4_addr) \
+ (((rte_be_to_cpu_32((ipv4_addr)) >> 24) & 0x000000FF) == 0xE0)
+
+/*
+ * Receive a burst of packets, lookup for ICMP echo requests, and, if any,
+ * send back ICMP echo replies.
+ */
+static void
+reply_to_icmp_echo_rqsts(struct fwd_stream *fs)
+{
+ struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+ struct rte_mbuf *pkt;
+ struct ether_hdr *eth_h;
+ struct vlan_hdr *vlan_h;
+ struct arp_hdr *arp_h;
+ struct ipv4_hdr *ip_h;
+ struct icmp_hdr *icmp_h;
+ struct ether_addr eth_addr;
+ uint32_t retry;
+ uint32_t ip_addr;
+ uint16_t nb_rx;
+ uint16_t nb_tx;
+ uint16_t nb_replies;
+ uint16_t eth_type;
+ uint16_t vlan_id;
+ uint16_t arp_op;
+ uint16_t arp_pro;
+ uint32_t cksum;
+ uint8_t i;
+ int l2_len;
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ uint64_t start_tsc;
+ uint64_t end_tsc;
+ uint64_t core_cycles;
+#endif
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ start_tsc = rte_rdtsc();
+#endif
+
+ /*
+ * First, receive a burst of packets.
+ */
+ nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst,
+ nb_pkt_per_burst);
+ if (unlikely(nb_rx == 0))
+ return;
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->rx_burst_stats.pkt_burst_spread[nb_rx]++;
+#endif
+ fs->rx_packets += nb_rx;
+ nb_replies = 0;
+ for (i = 0; i < nb_rx; i++) {
+ if (likely(i < nb_rx - 1))
+ rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
+ void *));
+ pkt = pkts_burst[i];
+ eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
+ eth_type = RTE_BE_TO_CPU_16(eth_h->ether_type);
+ l2_len = sizeof(struct ether_hdr);
+ if (verbose_level > 0) {
+ printf("\nPort %d pkt-len=%u nb-segs=%u\n",
+ fs->rx_port, pkt->pkt_len, pkt->nb_segs);
+ ether_addr_dump(" ETH: src=", &eth_h->s_addr);
+ ether_addr_dump(" dst=", &eth_h->d_addr);
+ }
+ if (eth_type == ETHER_TYPE_VLAN) {
+ vlan_h = (struct vlan_hdr *)
+ ((char *)eth_h + sizeof(struct ether_hdr));
+ l2_len += sizeof(struct vlan_hdr);
+ eth_type = rte_be_to_cpu_16(vlan_h->eth_proto);
+ if (verbose_level > 0) {
+ vlan_id = rte_be_to_cpu_16(vlan_h->vlan_tci)
+ & 0xFFF;
+ printf(" [vlan id=%u]", vlan_id);
+ }
+ }
+ if (verbose_level > 0) {
+ printf(" type=0x%04x\n", eth_type);
+ }
+
+ /* Reply to ARP requests */
+ if (eth_type == ETHER_TYPE_ARP) {
+ arp_h = (struct arp_hdr *) ((char *)eth_h + l2_len);
+ arp_op = RTE_BE_TO_CPU_16(arp_h->arp_op);
+ arp_pro = RTE_BE_TO_CPU_16(arp_h->arp_pro);
+ if (verbose_level > 0) {
+ printf(" ARP: hrd=%d proto=0x%04x hln=%d "
+ "pln=%d op=%u (%s)\n",
+ RTE_BE_TO_CPU_16(arp_h->arp_hrd),
+ arp_pro, arp_h->arp_hln,
+ arp_h->arp_pln, arp_op,
+ arp_op_name(arp_op));
+ }
+ if ((RTE_BE_TO_CPU_16(arp_h->arp_hrd) !=
+ ARP_HRD_ETHER) ||
+ (arp_pro != ETHER_TYPE_IPv4) ||
+ (arp_h->arp_hln != 6) ||
+ (arp_h->arp_pln != 4)
+ ) {
+ rte_pktmbuf_free(pkt);
+ if (verbose_level > 0)
+ printf("\n");
+ continue;
+ }
+ if (verbose_level > 0) {
+ ether_addr_copy(&arp_h->arp_data.arp_sha, &eth_addr);
+ ether_addr_dump(" sha=", &eth_addr);
+ ip_addr = arp_h->arp_data.arp_sip;
+ ipv4_addr_dump(" sip=", ip_addr);
+ printf("\n");
+ ether_addr_copy(&arp_h->arp_data.arp_tha, &eth_addr);
+ ether_addr_dump(" tha=", &eth_addr);
+ ip_addr = arp_h->arp_data.arp_tip;
+ ipv4_addr_dump(" tip=", ip_addr);
+ printf("\n");
+ }
+ if (arp_op != ARP_OP_REQUEST) {
+ rte_pktmbuf_free(pkt);
+ continue;
+ }
+
+ /*
+ * Build ARP reply.
+ */
+
+ /* Use source MAC address as destination MAC address. */
+ ether_addr_copy(&eth_h->s_addr, &eth_h->d_addr);
+ /* Set source MAC address with MAC address of TX port */
+ ether_addr_copy(&ports[fs->tx_port].eth_addr,
+ &eth_h->s_addr);
+
+ arp_h->arp_op = rte_cpu_to_be_16(ARP_OP_REPLY);
+ ether_addr_copy(&arp_h->arp_data.arp_tha, &eth_addr);
+ ether_addr_copy(&arp_h->arp_data.arp_sha, &arp_h->arp_data.arp_tha);
+ ether_addr_copy(&eth_h->s_addr, &arp_h->arp_data.arp_sha);
+
+ /* Swap IP addresses in ARP payload */
+ ip_addr = arp_h->arp_data.arp_sip;
+ arp_h->arp_data.arp_sip = arp_h->arp_data.arp_tip;
+ arp_h->arp_data.arp_tip = ip_addr;
+ pkts_burst[nb_replies++] = pkt;
+ continue;
+ }
+
+ if (eth_type != ETHER_TYPE_IPv4) {
+ rte_pktmbuf_free(pkt);
+ continue;
+ }
+ ip_h = (struct ipv4_hdr *) ((char *)eth_h + l2_len);
+ if (verbose_level > 0) {
+ ipv4_addr_dump(" IPV4: src=", ip_h->src_addr);
+ ipv4_addr_dump(" dst=", ip_h->dst_addr);
+ printf(" proto=%d (%s)\n",
+ ip_h->next_proto_id,
+ ip_proto_name(ip_h->next_proto_id));
+ }
+
+ /*
+ * Check if packet is a ICMP echo request.
+ */
+ icmp_h = (struct icmp_hdr *) ((char *)ip_h +
+ sizeof(struct ipv4_hdr));
+ if (! ((ip_h->next_proto_id == IPPROTO_ICMP) &&
+ (icmp_h->icmp_type == IP_ICMP_ECHO_REQUEST) &&
+ (icmp_h->icmp_code == 0))) {
+ rte_pktmbuf_free(pkt);
+ continue;
+ }
+
+ if (verbose_level > 0)
+ printf(" ICMP: echo request seq id=%d\n",
+ rte_be_to_cpu_16(icmp_h->icmp_seq_nb));
+
+ /*
+ * Prepare ICMP echo reply to be sent back.
+ * - switch ethernet source and destinations addresses,
+ * - use the request IP source address as the reply IP
+ * destination address,
+ * - if the request IP destination address is a multicast
+ * address:
+ * - choose a reply IP source address different from the
+ * request IP source address,
+ * - re-compute the IP header checksum.
+ * Otherwise:
+ * - switch the request IP source and destination
+ * addresses in the reply IP header,
+ * - keep the IP header checksum unchanged.
+ * - set IP_ICMP_ECHO_REPLY in ICMP header.
+ * ICMP checksum is computed by assuming it is valid in the
+ * echo request and not verified.
+ */
+ ether_addr_copy(&eth_h->s_addr, &eth_addr);
+ ether_addr_copy(&eth_h->d_addr, &eth_h->s_addr);
+ ether_addr_copy(&eth_addr, &eth_h->d_addr);
+ ip_addr = ip_h->src_addr;
+ if (is_multicast_ipv4_addr(ip_h->dst_addr)) {
+ uint32_t ip_src;
+
+ ip_src = rte_be_to_cpu_32(ip_addr);
+ if ((ip_src & 0x00000003) == 1)
+ ip_src = (ip_src & 0xFFFFFFFC) | 0x00000002;
+ else
+ ip_src = (ip_src & 0xFFFFFFFC) | 0x00000001;
+ ip_h->src_addr = rte_cpu_to_be_32(ip_src);
+ ip_h->dst_addr = ip_addr;
+ ip_h->hdr_checksum = ipv4_hdr_cksum(ip_h);
+ } else {
+ ip_h->src_addr = ip_h->dst_addr;
+ ip_h->dst_addr = ip_addr;
+ }
+ icmp_h->icmp_type = IP_ICMP_ECHO_REPLY;
+ cksum = ~icmp_h->icmp_cksum & 0xffff;
+ cksum += ~htons(IP_ICMP_ECHO_REQUEST << 8) & 0xffff;
+ cksum += htons(IP_ICMP_ECHO_REPLY << 8);
+ cksum = (cksum & 0xffff) + (cksum >> 16);
+ cksum = (cksum & 0xffff) + (cksum >> 16);
+ icmp_h->icmp_cksum = ~cksum;
+ pkts_burst[nb_replies++] = pkt;
+ }
+
+ /* Send back ICMP echo replies, if any. */
+ if (nb_replies > 0) {
+ nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst,
+ nb_replies);
+ /*
+ * Retry if necessary
+ */
+ if (unlikely(nb_tx < nb_replies) && fs->retry_enabled) {
+ retry = 0;
+ while (nb_tx < nb_replies &&
+ retry++ < burst_tx_retry_num) {
+ rte_delay_us(burst_tx_delay_time);
+ nb_tx += rte_eth_tx_burst(fs->tx_port,
+ fs->tx_queue,
+ &pkts_burst[nb_tx],
+ nb_replies - nb_tx);
+ }
+ }
+ fs->tx_packets += nb_tx;
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->tx_burst_stats.pkt_burst_spread[nb_tx]++;
+#endif
+ if (unlikely(nb_tx < nb_replies)) {
+ fs->fwd_dropped += (nb_replies - nb_tx);
+ do {
+ rte_pktmbuf_free(pkts_burst[nb_tx]);
+ } while (++nb_tx < nb_replies);
+ }
+ }
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ end_tsc = rte_rdtsc();
+ core_cycles = (end_tsc - start_tsc);
+ fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles);
+#endif
+}
+
+struct fwd_engine icmp_echo_engine = {
+ .fwd_mode_name = "icmpecho",
+ .port_fwd_begin = NULL,
+ .port_fwd_end = NULL,
+ .packet_fwd = reply_to_icmp_echo_rqsts,
+};
diff --git a/src/seastar/dpdk/app/test-pmd/ieee1588fwd.c b/src/seastar/dpdk/app/test-pmd/ieee1588fwd.c
new file mode 100644
index 00000000..51170ee3
--- /dev/null
+++ b/src/seastar/dpdk/app/test-pmd/ieee1588fwd.c
@@ -0,0 +1,249 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <rte_cycles.h>
+#include <rte_ethdev.h>
+#include <rte_flow.h>
+
+#include "testpmd.h"
+
+/**
+ * The structure of a PTP V2 packet.
+ *
+ * Only the minimum fields used by the ieee1588 test are represented.
+ */
+struct ptpv2_msg {
+ uint8_t msg_id;
+ uint8_t version; /**< must be 0x02 */
+ uint8_t unused[34];
+};
+
+#define PTP_SYNC_MESSAGE 0x0
+#define PTP_DELAY_REQ_MESSAGE 0x1
+#define PTP_PATH_DELAY_REQ_MESSAGE 0x2
+#define PTP_PATH_DELAY_RESP_MESSAGE 0x3
+#define PTP_FOLLOWUP_MESSAGE 0x8
+#define PTP_DELAY_RESP_MESSAGE 0x9
+#define PTP_PATH_DELAY_FOLLOWUP_MESSAGE 0xA
+#define PTP_ANNOUNCE_MESSAGE 0xB
+#define PTP_SIGNALLING_MESSAGE 0xC
+#define PTP_MANAGEMENT_MESSAGE 0xD
+
+/*
+ * Forwarding of IEEE1588 Precise Time Protocol (PTP) packets.
+ *
+ * In this mode, packets are received one by one and are expected to be
+ * PTP V2 L2 Ethernet frames (with the specific Ethernet type "0x88F7")
+ * containing PTP "sync" messages (version 2 at offset 1, and message ID
+ * 0 at offset 0).
+ *
+ * Check that each received packet is a IEEE1588 PTP V2 packet of type
+ * PTP_SYNC_MESSAGE, and that it has been identified and timestamped
+ * by the hardware.
+ * Check that the value of the last RX timestamp recorded by the controller
+ * is greater than the previous one.
+ *
+ * If everything is OK, send the received packet back on the same port,
+ * requesting for it to be timestamped by the hardware.
+ * Check that the value of the last TX timestamp recorded by the controller
+ * is greater than the previous one.
+ */
+
+static void
+port_ieee1588_rx_timestamp_check(portid_t pi, uint32_t index)
+{
+ struct timespec timestamp = {0, 0};
+
+ if (rte_eth_timesync_read_rx_timestamp(pi, &timestamp, index) < 0) {
+ printf("Port %u RX timestamp registers not valid\n",
+ (unsigned) pi);
+ return;
+ }
+ printf("Port %u RX timestamp value %lu s %lu ns\n",
+ (unsigned) pi, timestamp.tv_sec, timestamp.tv_nsec);
+}
+
+#define MAX_TX_TMST_WAIT_MICROSECS 1000 /**< 1 milli-second */
+
+static void
+port_ieee1588_tx_timestamp_check(portid_t pi)
+{
+ struct timespec timestamp = {0, 0};
+ unsigned wait_us = 0;
+
+ while ((rte_eth_timesync_read_tx_timestamp(pi, &timestamp) < 0) &&
+ (wait_us < MAX_TX_TMST_WAIT_MICROSECS)) {
+ rte_delay_us(1);
+ wait_us++;
+ }
+ if (wait_us >= MAX_TX_TMST_WAIT_MICROSECS) {
+ printf("Port %u TX timestamp registers not valid after "
+ "%u micro-seconds\n",
+ (unsigned) pi, (unsigned) MAX_TX_TMST_WAIT_MICROSECS);
+ return;
+ }
+ printf("Port %u TX timestamp value %lu s %lu ns validated after "
+ "%u micro-second%s\n",
+ (unsigned) pi, timestamp.tv_sec, timestamp.tv_nsec, wait_us,
+ (wait_us == 1) ? "" : "s");
+}
+
+static void
+ieee1588_packet_fwd(struct fwd_stream *fs)
+{
+ struct rte_mbuf *mb;
+ struct ether_hdr *eth_hdr;
+ struct ether_addr addr;
+ struct ptpv2_msg *ptp_hdr;
+ uint16_t eth_type;
+ uint32_t timesync_index;
+
+ /*
+ * Receive 1 packet at a time.
+ */
+ if (rte_eth_rx_burst(fs->rx_port, fs->rx_queue, &mb, 1) == 0)
+ return;
+
+ fs->rx_packets += 1;
+
+ /*
+ * Check that the received packet is a PTP packet that was detected
+ * by the hardware.
+ */
+ eth_hdr = rte_pktmbuf_mtod(mb, struct ether_hdr *);
+ eth_type = rte_be_to_cpu_16(eth_hdr->ether_type);
+
+ if (! (mb->ol_flags & PKT_RX_IEEE1588_PTP)) {
+ if (eth_type == ETHER_TYPE_1588) {
+ printf("Port %u Received PTP packet not filtered"
+ " by hardware\n",
+ (unsigned) fs->rx_port);
+ } else {
+ printf("Port %u Received non PTP packet type=0x%4x "
+ "len=%u\n",
+ (unsigned) fs->rx_port, eth_type,
+ (unsigned) mb->pkt_len);
+ }
+ rte_pktmbuf_free(mb);
+ return;
+ }
+ if (eth_type != ETHER_TYPE_1588) {
+ printf("Port %u Received NON PTP packet incorrectly"
+ " detected by hardware\n",
+ (unsigned) fs->rx_port);
+ rte_pktmbuf_free(mb);
+ return;
+ }
+
+ /*
+ * Check that the received PTP packet is a PTP V2 packet of type
+ * PTP_SYNC_MESSAGE.
+ */
+ ptp_hdr = (struct ptpv2_msg *) (rte_pktmbuf_mtod(mb, char *) +
+ sizeof(struct ether_hdr));
+ if (ptp_hdr->version != 0x02) {
+ printf("Port %u Received PTP V2 Ethernet frame with wrong PTP"
+ " protocol version 0x%x (should be 0x02)\n",
+ (unsigned) fs->rx_port, ptp_hdr->version);
+ rte_pktmbuf_free(mb);
+ return;
+ }
+ if (ptp_hdr->msg_id != PTP_SYNC_MESSAGE) {
+ printf("Port %u Received PTP V2 Ethernet frame with unexpected"
+ " message ID 0x%x (expected 0x0 - PTP_SYNC_MESSAGE)\n",
+ (unsigned) fs->rx_port, ptp_hdr->msg_id);
+ rte_pktmbuf_free(mb);
+ return;
+ }
+ printf("Port %u IEEE1588 PTP V2 SYNC Message filtered by hardware\n",
+ (unsigned) fs->rx_port);
+
+ /*
+ * Check that the received PTP packet has been timestamped by the
+ * hardware.
+ */
+ if (! (mb->ol_flags & PKT_RX_IEEE1588_TMST)) {
+ printf("Port %u Received PTP packet not timestamped"
+ " by hardware\n",
+ (unsigned) fs->rx_port);
+ rte_pktmbuf_free(mb);
+ return;
+ }
+
+ /* For i40e we need the timesync register index. It is ignored for the
+ * other PMDs. */
+ timesync_index = mb->timesync & 0x3;
+ /* Read and check the RX timestamp. */
+ port_ieee1588_rx_timestamp_check(fs->rx_port, timesync_index);
+
+ /* Swap dest and src mac addresses. */
+ ether_addr_copy(&eth_hdr->d_addr, &addr);
+ ether_addr_copy(&eth_hdr->s_addr, &eth_hdr->d_addr);
+ ether_addr_copy(&addr, &eth_hdr->s_addr);
+
+ /* Forward PTP packet with hardware TX timestamp */
+ mb->ol_flags |= PKT_TX_IEEE1588_TMST;
+ fs->tx_packets += 1;
+ if (rte_eth_tx_burst(fs->rx_port, fs->tx_queue, &mb, 1) == 0) {
+ printf("Port %u sent PTP packet dropped\n",
+ (unsigned) fs->rx_port);
+ fs->fwd_dropped += 1;
+ rte_pktmbuf_free(mb);
+ return;
+ }
+
+ /*
+ * Check the TX timestamp.
+ */
+ port_ieee1588_tx_timestamp_check(fs->rx_port);
+}
+
+static void
+port_ieee1588_fwd_begin(portid_t pi)
+{
+ rte_eth_timesync_enable(pi);
+}
+
+static void
+port_ieee1588_fwd_end(portid_t pi)
+{
+ rte_eth_timesync_disable(pi);
+}
+
+struct fwd_engine ieee1588_fwd_engine = {
+ .fwd_mode_name = "ieee1588",
+ .port_fwd_begin = port_ieee1588_fwd_begin,
+ .port_fwd_end = port_ieee1588_fwd_end,
+ .packet_fwd = ieee1588_packet_fwd,
+};
diff --git a/src/seastar/dpdk/app/test-pmd/iofwd.c b/src/seastar/dpdk/app/test-pmd/iofwd.c
new file mode 100644
index 00000000..15cb4a20
--- /dev/null
+++ b/src/seastar/dpdk/app/test-pmd/iofwd.c
@@ -0,0 +1,142 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_cycles.h>
+#include <rte_memory.h>
+#include <rte_memzone.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_string_fns.h>
+#include <rte_flow.h>
+
+#include "testpmd.h"
+
+/*
+ * Forwarding of packets in I/O mode.
+ * Forward packets "as-is".
+ * This is the fastest possible forwarding operation, as it does not access
+ * to packets data.
+ */
+static void
+pkt_burst_io_forward(struct fwd_stream *fs)
+{
+ struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+ uint16_t nb_rx;
+ uint16_t nb_tx;
+ uint32_t retry;
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ uint64_t start_tsc;
+ uint64_t end_tsc;
+ uint64_t core_cycles;
+#endif
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ start_tsc = rte_rdtsc();
+#endif
+
+ /*
+ * Receive a burst of packets and forward them.
+ */
+ nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue,
+ pkts_burst, nb_pkt_per_burst);
+ if (unlikely(nb_rx == 0))
+ return;
+ fs->rx_packets += nb_rx;
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->rx_burst_stats.pkt_burst_spread[nb_rx]++;
+#endif
+ nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue,
+ pkts_burst, nb_rx);
+ /*
+ * Retry if necessary
+ */
+ if (unlikely(nb_tx < nb_rx) && fs->retry_enabled) {
+ retry = 0;
+ while (nb_tx < nb_rx && retry++ < burst_tx_retry_num) {
+ rte_delay_us(burst_tx_delay_time);
+ nb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue,
+ &pkts_burst[nb_tx], nb_rx - nb_tx);
+ }
+ }
+ fs->tx_packets += nb_tx;
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->tx_burst_stats.pkt_burst_spread[nb_tx]++;
+#endif
+ if (unlikely(nb_tx < nb_rx)) {
+ fs->fwd_dropped += (nb_rx - nb_tx);
+ do {
+ rte_pktmbuf_free(pkts_burst[nb_tx]);
+ } while (++nb_tx < nb_rx);
+ }
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ end_tsc = rte_rdtsc();
+ core_cycles = (end_tsc - start_tsc);
+ fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles);
+#endif
+}
+
+struct fwd_engine io_fwd_engine = {
+ .fwd_mode_name = "io",
+ .port_fwd_begin = NULL,
+ .port_fwd_end = NULL,
+ .packet_fwd = pkt_burst_io_forward,
+};
diff --git a/src/seastar/dpdk/app/test-pmd/macfwd.c b/src/seastar/dpdk/app/test-pmd/macfwd.c
new file mode 100644
index 00000000..cf7eab12
--- /dev/null
+++ b/src/seastar/dpdk/app/test-pmd/macfwd.c
@@ -0,0 +1,169 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_cycles.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_memzone.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_memory.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_ip.h>
+#include <rte_string_fns.h>
+#include <rte_flow.h>
+
+#include "testpmd.h"
+
+/*
+ * Forwarding of packets in MAC mode.
+ * Change the source and the destination Ethernet addressed of packets
+ * before forwarding them.
+ */
+static void
+pkt_burst_mac_forward(struct fwd_stream *fs)
+{
+ struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+ struct rte_port *txp;
+ struct rte_mbuf *mb;
+ struct ether_hdr *eth_hdr;
+ uint32_t retry;
+ uint16_t nb_rx;
+ uint16_t nb_tx;
+ uint16_t i;
+ uint64_t ol_flags = 0;
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ uint64_t start_tsc;
+ uint64_t end_tsc;
+ uint64_t core_cycles;
+#endif
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ start_tsc = rte_rdtsc();
+#endif
+
+ /*
+ * Receive a burst of packets and forward them.
+ */
+ nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst,
+ nb_pkt_per_burst);
+ if (unlikely(nb_rx == 0))
+ return;
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->rx_burst_stats.pkt_burst_spread[nb_rx]++;
+#endif
+ fs->rx_packets += nb_rx;
+ txp = &ports[fs->tx_port];
+ if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_INSERT_VLAN)
+ ol_flags = PKT_TX_VLAN_PKT;
+ if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_INSERT_QINQ)
+ ol_flags |= PKT_TX_QINQ_PKT;
+ if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_MACSEC)
+ ol_flags |= PKT_TX_MACSEC;
+ for (i = 0; i < nb_rx; i++) {
+ if (likely(i < nb_rx - 1))
+ rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
+ void *));
+ mb = pkts_burst[i];
+ eth_hdr = rte_pktmbuf_mtod(mb, struct ether_hdr *);
+ ether_addr_copy(&peer_eth_addrs[fs->peer_addr],
+ &eth_hdr->d_addr);
+ ether_addr_copy(&ports[fs->tx_port].eth_addr,
+ &eth_hdr->s_addr);
+ mb->ol_flags = ol_flags;
+ mb->l2_len = sizeof(struct ether_hdr);
+ mb->l3_len = sizeof(struct ipv4_hdr);
+ mb->vlan_tci = txp->tx_vlan_id;
+ mb->vlan_tci_outer = txp->tx_vlan_id_outer;
+ }
+ nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_rx);
+ /*
+ * Retry if necessary
+ */
+ if (unlikely(nb_tx < nb_rx) && fs->retry_enabled) {
+ retry = 0;
+ while (nb_tx < nb_rx && retry++ < burst_tx_retry_num) {
+ rte_delay_us(burst_tx_delay_time);
+ nb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue,
+ &pkts_burst[nb_tx], nb_rx - nb_tx);
+ }
+ }
+
+ fs->tx_packets += nb_tx;
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->tx_burst_stats.pkt_burst_spread[nb_tx]++;
+#endif
+ if (unlikely(nb_tx < nb_rx)) {
+ fs->fwd_dropped += (nb_rx - nb_tx);
+ do {
+ rte_pktmbuf_free(pkts_burst[nb_tx]);
+ } while (++nb_tx < nb_rx);
+ }
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ end_tsc = rte_rdtsc();
+ core_cycles = (end_tsc - start_tsc);
+ fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles);
+#endif
+}
+
+struct fwd_engine mac_fwd_engine = {
+ .fwd_mode_name = "mac",
+ .port_fwd_begin = NULL,
+ .port_fwd_end = NULL,
+ .packet_fwd = pkt_burst_mac_forward,
+};
diff --git a/src/seastar/dpdk/app/test-pmd/macswap.c b/src/seastar/dpdk/app/test-pmd/macswap.c
new file mode 100644
index 00000000..3a093512
--- /dev/null
+++ b/src/seastar/dpdk/app/test-pmd/macswap.c
@@ -0,0 +1,170 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2014 Tilera Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Tilera Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_cycles.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_memzone.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_memory.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_ip.h>
+#include <rte_string_fns.h>
+#include <rte_flow.h>
+
+#include "testpmd.h"
+
+/*
+ * MAC swap forwarding mode: Swap the source and the destination Ethernet
+ * addresses of packets before forwarding them.
+ */
+static void
+pkt_burst_mac_swap(struct fwd_stream *fs)
+{
+ struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+ struct rte_port *txp;
+ struct rte_mbuf *mb;
+ struct ether_hdr *eth_hdr;
+ struct ether_addr addr;
+ uint16_t nb_rx;
+ uint16_t nb_tx;
+ uint16_t i;
+ uint32_t retry;
+ uint64_t ol_flags = 0;
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ uint64_t start_tsc;
+ uint64_t end_tsc;
+ uint64_t core_cycles;
+#endif
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ start_tsc = rte_rdtsc();
+#endif
+
+ /*
+ * Receive a burst of packets and forward them.
+ */
+ nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst,
+ nb_pkt_per_burst);
+ if (unlikely(nb_rx == 0))
+ return;
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->rx_burst_stats.pkt_burst_spread[nb_rx]++;
+#endif
+ fs->rx_packets += nb_rx;
+ txp = &ports[fs->tx_port];
+ if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_INSERT_VLAN)
+ ol_flags = PKT_TX_VLAN_PKT;
+ if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_INSERT_QINQ)
+ ol_flags |= PKT_TX_QINQ_PKT;
+ if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_MACSEC)
+ ol_flags |= PKT_TX_MACSEC;
+ for (i = 0; i < nb_rx; i++) {
+ if (likely(i < nb_rx - 1))
+ rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
+ void *));
+ mb = pkts_burst[i];
+ eth_hdr = rte_pktmbuf_mtod(mb, struct ether_hdr *);
+
+ /* Swap dest and src mac addresses. */
+ ether_addr_copy(&eth_hdr->d_addr, &addr);
+ ether_addr_copy(&eth_hdr->s_addr, &eth_hdr->d_addr);
+ ether_addr_copy(&addr, &eth_hdr->s_addr);
+
+ mb->ol_flags = ol_flags;
+ mb->l2_len = sizeof(struct ether_hdr);
+ mb->l3_len = sizeof(struct ipv4_hdr);
+ mb->vlan_tci = txp->tx_vlan_id;
+ mb->vlan_tci_outer = txp->tx_vlan_id_outer;
+ }
+ nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_rx);
+ /*
+ * Retry if necessary
+ */
+ if (unlikely(nb_tx < nb_rx) && fs->retry_enabled) {
+ retry = 0;
+ while (nb_tx < nb_rx && retry++ < burst_tx_retry_num) {
+ rte_delay_us(burst_tx_delay_time);
+ nb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue,
+ &pkts_burst[nb_tx], nb_rx - nb_tx);
+ }
+ }
+ fs->tx_packets += nb_tx;
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->tx_burst_stats.pkt_burst_spread[nb_tx]++;
+#endif
+ if (unlikely(nb_tx < nb_rx)) {
+ fs->fwd_dropped += (nb_rx - nb_tx);
+ do {
+ rte_pktmbuf_free(pkts_burst[nb_tx]);
+ } while (++nb_tx < nb_rx);
+ }
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ end_tsc = rte_rdtsc();
+ core_cycles = (end_tsc - start_tsc);
+ fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles);
+#endif
+}
+
+struct fwd_engine mac_swap_engine = {
+ .fwd_mode_name = "macswap",
+ .port_fwd_begin = NULL,
+ .port_fwd_end = NULL,
+ .packet_fwd = pkt_burst_mac_swap,
+};
diff --git a/src/seastar/dpdk/app/test-pmd/parameters.c b/src/seastar/dpdk/app/test-pmd/parameters.c
new file mode 100644
index 00000000..fbe6284c
--- /dev/null
+++ b/src/seastar/dpdk/app/test-pmd/parameters.c
@@ -0,0 +1,1107 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <getopt.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <errno.h>
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_cycles.h>
+#include <rte_memory.h>
+#include <rte_memzone.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_mempool.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_string_fns.h>
+#ifdef RTE_LIBRTE_CMDLINE
+#include <cmdline_parse.h>
+#include <cmdline_parse_etheraddr.h>
+#endif
+#ifdef RTE_LIBRTE_PMD_BOND
+#include <rte_eth_bond.h>
+#endif
+#include <rte_flow.h>
+
+#include "testpmd.h"
+
+static void
+usage(char* progname)
+{
+ printf("usage: %s "
+#ifdef RTE_LIBRTE_CMDLINE
+ "[--interactive|-i] "
+ "[--cmdline-file=FILENAME] "
+#endif
+ "[--help|-h] | [--auto-start|-a] | ["
+ "--coremask=COREMASK --portmask=PORTMASK --numa "
+ "--mbuf-size= | --total-num-mbufs= | "
+ "--nb-cores= | --nb-ports= | "
+#ifdef RTE_LIBRTE_CMDLINE
+ "--eth-peers-configfile= | "
+ "--eth-peer=X,M:M:M:M:M:M | "
+#endif
+ "--pkt-filter-mode= |"
+ "--rss-ip | --rss-udp | "
+ "--rxpt= | --rxht= | --rxwt= | --rxfreet= | "
+ "--txpt= | --txht= | --txwt= | --txfreet= | "
+ "--txrst= | --txqflags= ]\n",
+ progname);
+#ifdef RTE_LIBRTE_CMDLINE
+ printf(" --interactive: run in interactive mode.\n");
+ printf(" --cmdline-file: execute cli commands before startup.\n");
+#endif
+ printf(" --auto-start: start forwarding on init "
+ "[always when non-interactive].\n");
+ printf(" --help: display this message and quit.\n");
+ printf(" --nb-cores=N: set the number of forwarding cores "
+ "(1 <= N <= %d).\n", nb_lcores);
+ printf(" --nb-ports=N: set the number of forwarding ports "
+ "(1 <= N <= %d).\n", nb_ports);
+ printf(" --coremask=COREMASK: hexadecimal bitmask of cores running "
+ "the packet forwarding test. The master lcore is reserved for "
+ "command line parsing only, and cannot be masked on for "
+ "packet forwarding.\n");
+ printf(" --portmask=PORTMASK: hexadecimal bitmask of ports used "
+ "by the packet forwarding test.\n");
+ printf(" --numa: enable NUMA-aware allocation of RX/TX rings and of "
+ "RX memory buffers (mbufs).\n");
+ printf(" --port-numa-config=(port,socket)[,(port,socket)]: "
+ "specify the socket on which the memory pool "
+ "used by the port will be allocated.\n");
+ printf(" --ring-numa-config=(port,flag,socket)[,(port,flag,socket)]: "
+ "specify the socket on which the TX/RX rings for "
+ "the port will be allocated "
+ "(flag: 1 for RX; 2 for TX; 3 for RX and TX).\n");
+ printf(" --socket-num=N: set socket from which all memory is allocated "
+ "in NUMA mode.\n");
+ printf(" --mbuf-size=N: set the data size of mbuf to N bytes.\n");
+ printf(" --total-num-mbufs=N: set the number of mbufs to be allocated "
+ "in mbuf pools.\n");
+ printf(" --max-pkt-len=N: set the maximum size of packet to N bytes.\n");
+#ifdef RTE_LIBRTE_CMDLINE
+ printf(" --eth-peers-configfile=name: config file with ethernet addresses "
+ "of peer ports.\n");
+ printf(" --eth-peer=X,M:M:M:M:M:M: set the MAC address of the X peer "
+ "port (0 <= X < %d).\n", RTE_MAX_ETHPORTS);
+#endif
+ printf(" --pkt-filter-mode=N: set Flow Director mode "
+ "(N: none (default mode) or signature or perfect).\n");
+ printf(" --pkt-filter-report-hash=N: set Flow Director report mode "
+ "(N: none or match (default) or always).\n");
+ printf(" --pkt-filter-size=N: set Flow Director mode "
+ "(N: 64K (default mode) or 128K or 256K).\n");
+ printf(" --pkt-filter-drop-queue=N: set drop-queue. "
+ "In perfect mode, when you add a rule with queue = -1 "
+ "the packet will be enqueued into the rx drop-queue. "
+ "If the drop-queue doesn't exist, the packet is dropped. "
+ "By default drop-queue=127.\n");
+#ifdef RTE_LIBRTE_LATENCY_STATS
+ printf(" --latencystats=N: enable latency and jitter statistcs "
+ "monitoring on forwarding lcore id N.\n");
+#endif
+ printf(" --disable-crc-strip: disable CRC stripping by hardware.\n");
+ printf(" --enable-lro: enable large receive offload.\n");
+ printf(" --enable-rx-cksum: enable rx hardware checksum offload.\n");
+ printf(" --disable-hw-vlan: disable hardware vlan.\n");
+ printf(" --disable-hw-vlan-filter: disable hardware vlan filter.\n");
+ printf(" --disable-hw-vlan-strip: disable hardware vlan strip.\n");
+ printf(" --disable-hw-vlan-extend: disable hardware vlan extend.\n");
+ printf(" --enable-drop-en: enable per queue packet drop.\n");
+ printf(" --disable-rss: disable rss.\n");
+ printf(" --port-topology=N: set port topology (N: paired (default) or "
+ "chained).\n");
+ printf(" --forward-mode=N: set forwarding mode (N: %s).\n",
+ list_pkt_forwarding_modes());
+ printf(" --rss-ip: set RSS functions to IPv4/IPv6 only .\n");
+ printf(" --rss-udp: set RSS functions to IPv4/IPv6 + UDP.\n");
+ printf(" --rxq=N: set the number of RX queues per port to N.\n");
+ printf(" --rxd=N: set the number of descriptors in RX rings to N.\n");
+ printf(" --txq=N: set the number of TX queues per port to N.\n");
+ printf(" --txd=N: set the number of descriptors in TX rings to N.\n");
+ printf(" --burst=N: set the number of packets per burst to N.\n");
+ printf(" --mbcache=N: set the cache of mbuf memory pool to N.\n");
+ printf(" --rxpt=N: set prefetch threshold register of RX rings to N.\n");
+ printf(" --rxht=N: set the host threshold register of RX rings to N.\n");
+ printf(" --rxfreet=N: set the free threshold of RX descriptors to N "
+ "(0 <= N < value of rxd).\n");
+ printf(" --rxwt=N: set the write-back threshold register of RX rings to N.\n");
+ printf(" --txpt=N: set the prefetch threshold register of TX rings to N.\n");
+ printf(" --txht=N: set the nhost threshold register of TX rings to N.\n");
+ printf(" --txwt=N: set the write-back threshold register of TX rings to N.\n");
+ printf(" --txfreet=N: set the transmit free threshold of TX rings to N "
+ "(0 <= N <= value of txd).\n");
+ printf(" --txrst=N: set the transmit RS bit threshold of TX rings to N "
+ "(0 <= N <= value of txd).\n");
+ printf(" --txqflags=0xXXXXXXXX: hexadecimal bitmask of TX queue flags "
+ "(0 <= N <= 0x7FFFFFFF).\n");
+ printf(" --tx-queue-stats-mapping=(port,queue,mapping)[,(port,queue,mapping]: "
+ "tx queues statistics counters mapping "
+ "(0 <= mapping <= %d).\n", RTE_ETHDEV_QUEUE_STAT_CNTRS - 1);
+ printf(" --rx-queue-stats-mapping=(port,queue,mapping)[,(port,queue,mapping]: "
+ "rx queues statistics counters mapping "
+ "(0 <= mapping <= %d).\n", RTE_ETHDEV_QUEUE_STAT_CNTRS - 1);
+ printf(" --no-flush-rx: Don't flush RX streams before forwarding."
+ " Used mainly with PCAP drivers.\n");
+ printf(" --txpkts=X[,Y]*: set TX segment sizes"
+ " or total packet length.\n");
+ printf(" --disable-link-check: disable check on link status when "
+ "starting/stopping ports.\n");
+ printf(" --no-lsc-interrupt: disable link status change interrupt.\n");
+ printf(" --no-rmv-interrupt: disable device removal interrupt.\n");
+ printf(" --bitrate-stats=N: set the logical core N to perform "
+ "bit-rate calculation.\n");
+ printf(" --print-event <unknown|intr_lsc|queue_state|intr_reset|vf_mbox|macsec|intr_rmv|all>: "
+ "enable print of designated event or all of them.");
+ printf(" --mask-event <unknown|intr_lsc|queue_state|intr_reset|vf_mbox|macsec|intr_rmv|all>: "
+ "disable print of designated event or all of them.");
+}
+
+#ifdef RTE_LIBRTE_CMDLINE
+static int
+init_peer_eth_addrs(char *config_filename)
+{
+ FILE *config_file;
+ portid_t i;
+ char buf[50];
+
+ config_file = fopen(config_filename, "r");
+ if (config_file == NULL) {
+ perror("Failed to open eth config file\n");
+ return -1;
+ }
+
+ for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
+
+ if (fgets(buf, sizeof(buf), config_file) == NULL)
+ break;
+
+ if (cmdline_parse_etheraddr(NULL, buf, &peer_eth_addrs[i],
+ sizeof(peer_eth_addrs[i])) < 0) {
+ printf("Bad MAC address format on line %d\n", i+1);
+ fclose(config_file);
+ return -1;
+ }
+ }
+ fclose(config_file);
+ nb_peer_eth_addrs = (portid_t) i;
+ return 0;
+}
+#endif
+
+/*
+ * Parse the coremask given as argument (hexadecimal string) and set
+ * the global configuration of forwarding cores.
+ */
+static void
+parse_fwd_coremask(const char *coremask)
+{
+ char *end;
+ unsigned long long int cm;
+
+ /* parse hexadecimal string */
+ end = NULL;
+ cm = strtoull(coremask, &end, 16);
+ if ((coremask[0] == '\0') || (end == NULL) || (*end != '\0'))
+ rte_exit(EXIT_FAILURE, "Invalid fwd core mask\n");
+ else if (set_fwd_lcores_mask((uint64_t) cm) < 0)
+ rte_exit(EXIT_FAILURE, "coremask is not valid\n");
+}
+
+/*
+ * Parse the coremask given as argument (hexadecimal string) and set
+ * the global configuration of forwarding cores.
+ */
+static void
+parse_fwd_portmask(const char *portmask)
+{
+ char *end;
+ unsigned long long int pm;
+
+ /* parse hexadecimal string */
+ end = NULL;
+ pm = strtoull(portmask, &end, 16);
+ if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0'))
+ rte_exit(EXIT_FAILURE, "Invalid fwd port mask\n");
+ else
+ set_fwd_ports_mask((uint64_t) pm);
+}
+
+
+static int
+parse_queue_stats_mapping_config(const char *q_arg, int is_rx)
+{
+ char s[256];
+ const char *p, *p0 = q_arg;
+ char *end;
+ enum fieldnames {
+ FLD_PORT = 0,
+ FLD_QUEUE,
+ FLD_STATS_COUNTER,
+ _NUM_FLD
+ };
+ unsigned long int_fld[_NUM_FLD];
+ char *str_fld[_NUM_FLD];
+ int i;
+ unsigned size;
+
+ /* reset from value set at definition */
+ is_rx ? (nb_rx_queue_stats_mappings = 0) : (nb_tx_queue_stats_mappings = 0);
+
+ while ((p = strchr(p0,'(')) != NULL) {
+ ++p;
+ if((p0 = strchr(p,')')) == NULL)
+ return -1;
+
+ size = p0 - p;
+ if(size >= sizeof(s))
+ return -1;
+
+ snprintf(s, sizeof(s), "%.*s", size, p);
+ if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != _NUM_FLD)
+ return -1;
+ for (i = 0; i < _NUM_FLD; i++){
+ errno = 0;
+ int_fld[i] = strtoul(str_fld[i], &end, 0);
+ if (errno != 0 || end == str_fld[i] || int_fld[i] > 255)
+ return -1;
+ }
+ /* Check mapping field is in correct range (0..RTE_ETHDEV_QUEUE_STAT_CNTRS-1) */
+ if (int_fld[FLD_STATS_COUNTER] >= RTE_ETHDEV_QUEUE_STAT_CNTRS) {
+ printf("Stats counter not in the correct range 0..%d\n",
+ RTE_ETHDEV_QUEUE_STAT_CNTRS - 1);
+ return -1;
+ }
+
+ if (!is_rx) {
+ if ((nb_tx_queue_stats_mappings >=
+ MAX_TX_QUEUE_STATS_MAPPINGS)) {
+ printf("exceeded max number of TX queue "
+ "statistics mappings: %hu\n",
+ nb_tx_queue_stats_mappings);
+ return -1;
+ }
+ tx_queue_stats_mappings_array[nb_tx_queue_stats_mappings].port_id =
+ (uint8_t)int_fld[FLD_PORT];
+ tx_queue_stats_mappings_array[nb_tx_queue_stats_mappings].queue_id =
+ (uint8_t)int_fld[FLD_QUEUE];
+ tx_queue_stats_mappings_array[nb_tx_queue_stats_mappings].stats_counter_id =
+ (uint8_t)int_fld[FLD_STATS_COUNTER];
+ ++nb_tx_queue_stats_mappings;
+ }
+ else {
+ if ((nb_rx_queue_stats_mappings >=
+ MAX_RX_QUEUE_STATS_MAPPINGS)) {
+ printf("exceeded max number of RX queue "
+ "statistics mappings: %hu\n",
+ nb_rx_queue_stats_mappings);
+ return -1;
+ }
+ rx_queue_stats_mappings_array[nb_rx_queue_stats_mappings].port_id =
+ (uint8_t)int_fld[FLD_PORT];
+ rx_queue_stats_mappings_array[nb_rx_queue_stats_mappings].queue_id =
+ (uint8_t)int_fld[FLD_QUEUE];
+ rx_queue_stats_mappings_array[nb_rx_queue_stats_mappings].stats_counter_id =
+ (uint8_t)int_fld[FLD_STATS_COUNTER];
+ ++nb_rx_queue_stats_mappings;
+ }
+
+ }
+/* Reassign the rx/tx_queue_stats_mappings pointer to point to this newly populated array rather */
+/* than to the default array (that was set at its definition) */
+ is_rx ? (rx_queue_stats_mappings = rx_queue_stats_mappings_array) :
+ (tx_queue_stats_mappings = tx_queue_stats_mappings_array);
+ return 0;
+}
+
+static void
+print_invalid_socket_id_error(void)
+{
+ unsigned int i = 0;
+
+ printf("Invalid socket id, options are: ");
+ for (i = 0; i < num_sockets; i++) {
+ printf("%u%s", socket_ids[i],
+ (i == num_sockets - 1) ? "\n" : ",");
+ }
+}
+
+static int
+parse_portnuma_config(const char *q_arg)
+{
+ char s[256];
+ const char *p, *p0 = q_arg;
+ char *end;
+ uint8_t i,port_id,socket_id;
+ unsigned size;
+ enum fieldnames {
+ FLD_PORT = 0,
+ FLD_SOCKET,
+ _NUM_FLD
+ };
+ unsigned long int_fld[_NUM_FLD];
+ char *str_fld[_NUM_FLD];
+ portid_t pid;
+
+ /* reset from value set at definition */
+ while ((p = strchr(p0,'(')) != NULL) {
+ ++p;
+ if((p0 = strchr(p,')')) == NULL)
+ return -1;
+
+ size = p0 - p;
+ if(size >= sizeof(s))
+ return -1;
+
+ snprintf(s, sizeof(s), "%.*s", size, p);
+ if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != _NUM_FLD)
+ return -1;
+ for (i = 0; i < _NUM_FLD; i++) {
+ errno = 0;
+ int_fld[i] = strtoul(str_fld[i], &end, 0);
+ if (errno != 0 || end == str_fld[i] || int_fld[i] > 255)
+ return -1;
+ }
+ port_id = (uint8_t)int_fld[FLD_PORT];
+ if (port_id_is_invalid(port_id, ENABLED_WARN)) {
+ printf("Valid port range is [0");
+ RTE_ETH_FOREACH_DEV(pid)
+ printf(", %d", pid);
+ printf("]\n");
+ return -1;
+ }
+ socket_id = (uint8_t)int_fld[FLD_SOCKET];
+ if (new_socket_id(socket_id)) {
+ print_invalid_socket_id_error();
+ return -1;
+ }
+ port_numa[port_id] = socket_id;
+ }
+
+ return 0;
+}
+
+static int
+parse_ringnuma_config(const char *q_arg)
+{
+ char s[256];
+ const char *p, *p0 = q_arg;
+ char *end;
+ uint8_t i,port_id,ring_flag,socket_id;
+ unsigned size;
+ enum fieldnames {
+ FLD_PORT = 0,
+ FLD_FLAG,
+ FLD_SOCKET,
+ _NUM_FLD
+ };
+ unsigned long int_fld[_NUM_FLD];
+ char *str_fld[_NUM_FLD];
+ portid_t pid;
+ #define RX_RING_ONLY 0x1
+ #define TX_RING_ONLY 0x2
+ #define RXTX_RING 0x3
+
+ /* reset from value set at definition */
+ while ((p = strchr(p0,'(')) != NULL) {
+ ++p;
+ if((p0 = strchr(p,')')) == NULL)
+ return -1;
+
+ size = p0 - p;
+ if(size >= sizeof(s))
+ return -1;
+
+ snprintf(s, sizeof(s), "%.*s", size, p);
+ if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != _NUM_FLD)
+ return -1;
+ for (i = 0; i < _NUM_FLD; i++) {
+ errno = 0;
+ int_fld[i] = strtoul(str_fld[i], &end, 0);
+ if (errno != 0 || end == str_fld[i] || int_fld[i] > 255)
+ return -1;
+ }
+ port_id = (uint8_t)int_fld[FLD_PORT];
+ if (port_id_is_invalid(port_id, ENABLED_WARN)) {
+ printf("Valid port range is [0");
+ RTE_ETH_FOREACH_DEV(pid)
+ printf(", %d", pid);
+ printf("]\n");
+ return -1;
+ }
+ socket_id = (uint8_t)int_fld[FLD_SOCKET];
+ if (new_socket_id(socket_id)) {
+ print_invalid_socket_id_error();
+ return -1;
+ }
+ ring_flag = (uint8_t)int_fld[FLD_FLAG];
+ if ((ring_flag < RX_RING_ONLY) || (ring_flag > RXTX_RING)) {
+ printf("Invalid ring-flag=%d config for port =%d\n",
+ ring_flag,port_id);
+ return -1;
+ }
+
+ switch (ring_flag & RXTX_RING) {
+ case RX_RING_ONLY:
+ rxring_numa[port_id] = socket_id;
+ break;
+ case TX_RING_ONLY:
+ txring_numa[port_id] = socket_id;
+ break;
+ case RXTX_RING:
+ rxring_numa[port_id] = socket_id;
+ txring_numa[port_id] = socket_id;
+ break;
+ default:
+ printf("Invalid ring-flag=%d config for port=%d\n",
+ ring_flag,port_id);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int
+parse_event_printing_config(const char *optarg, int enable)
+{
+ uint32_t mask = 0;
+
+ if (!strcmp(optarg, "unknown"))
+ mask = UINT32_C(1) << RTE_ETH_EVENT_UNKNOWN;
+ else if (!strcmp(optarg, "intr_lsc"))
+ mask = UINT32_C(1) << RTE_ETH_EVENT_INTR_LSC;
+ else if (!strcmp(optarg, "queue_state"))
+ mask = UINT32_C(1) << RTE_ETH_EVENT_QUEUE_STATE;
+ else if (!strcmp(optarg, "intr_reset"))
+ mask = UINT32_C(1) << RTE_ETH_EVENT_INTR_RESET;
+ else if (!strcmp(optarg, "vf_mbox"))
+ mask = UINT32_C(1) << RTE_ETH_EVENT_VF_MBOX;
+ else if (!strcmp(optarg, "macsec"))
+ mask = UINT32_C(1) << RTE_ETH_EVENT_MACSEC;
+ else if (!strcmp(optarg, "intr_rmv"))
+ mask = UINT32_C(1) << RTE_ETH_EVENT_INTR_RMV;
+ else if (!strcmp(optarg, "all"))
+ mask = ~UINT32_C(0);
+ else {
+ fprintf(stderr, "Invalid event: %s\n", optarg);
+ return -1;
+ }
+ if (enable)
+ event_print_mask |= mask;
+ else
+ event_print_mask &= ~mask;
+ return 0;
+}
+
+void
+launch_args_parse(int argc, char** argv)
+{
+ int n, opt;
+ char **argvopt;
+ int opt_idx;
+ enum { TX, RX };
+
+ static struct option lgopts[] = {
+ { "help", 0, 0, 0 },
+#ifdef RTE_LIBRTE_CMDLINE
+ { "interactive", 0, 0, 0 },
+ { "cmdline-file", 1, 0, 0 },
+ { "auto-start", 0, 0, 0 },
+ { "eth-peers-configfile", 1, 0, 0 },
+ { "eth-peer", 1, 0, 0 },
+#endif
+ { "ports", 1, 0, 0 },
+ { "nb-cores", 1, 0, 0 },
+ { "nb-ports", 1, 0, 0 },
+ { "coremask", 1, 0, 0 },
+ { "portmask", 1, 0, 0 },
+ { "numa", 0, 0, 0 },
+ { "no-numa", 0, 0, 0 },
+ { "mp-anon", 0, 0, 0 },
+ { "port-numa-config", 1, 0, 0 },
+ { "ring-numa-config", 1, 0, 0 },
+ { "socket-num", 1, 0, 0 },
+ { "mbuf-size", 1, 0, 0 },
+ { "total-num-mbufs", 1, 0, 0 },
+ { "max-pkt-len", 1, 0, 0 },
+ { "pkt-filter-mode", 1, 0, 0 },
+ { "pkt-filter-report-hash", 1, 0, 0 },
+ { "pkt-filter-size", 1, 0, 0 },
+ { "pkt-filter-drop-queue", 1, 0, 0 },
+#ifdef RTE_LIBRTE_LATENCY_STATS
+ { "latencystats", 1, 0, 0 },
+#endif
+#ifdef RTE_LIBRTE_BITRATE
+ { "bitrate-stats", 1, 0, 0 },
+#endif
+ { "disable-crc-strip", 0, 0, 0 },
+ { "enable-lro", 0, 0, 0 },
+ { "enable-rx-cksum", 0, 0, 0 },
+ { "enable-scatter", 0, 0, 0 },
+ { "disable-hw-vlan", 0, 0, 0 },
+ { "disable-hw-vlan-filter", 0, 0, 0 },
+ { "disable-hw-vlan-strip", 0, 0, 0 },
+ { "disable-hw-vlan-extend", 0, 0, 0 },
+ { "enable-drop-en", 0, 0, 0 },
+ { "disable-rss", 0, 0, 0 },
+ { "port-topology", 1, 0, 0 },
+ { "forward-mode", 1, 0, 0 },
+ { "rss-ip", 0, 0, 0 },
+ { "rss-udp", 0, 0, 0 },
+ { "rxq", 1, 0, 0 },
+ { "txq", 1, 0, 0 },
+ { "rxd", 1, 0, 0 },
+ { "txd", 1, 0, 0 },
+ { "burst", 1, 0, 0 },
+ { "mbcache", 1, 0, 0 },
+ { "txpt", 1, 0, 0 },
+ { "txht", 1, 0, 0 },
+ { "txwt", 1, 0, 0 },
+ { "txfreet", 1, 0, 0 },
+ { "txrst", 1, 0, 0 },
+ { "txqflags", 1, 0, 0 },
+ { "rxpt", 1, 0, 0 },
+ { "rxht", 1, 0, 0 },
+ { "rxwt", 1, 0, 0 },
+ { "rxfreet", 1, 0, 0 },
+ { "tx-queue-stats-mapping", 1, 0, 0 },
+ { "rx-queue-stats-mapping", 1, 0, 0 },
+ { "no-flush-rx", 0, 0, 0 },
+ { "txpkts", 1, 0, 0 },
+ { "disable-link-check", 0, 0, 0 },
+ { "no-lsc-interrupt", 0, 0, 0 },
+ { "no-rmv-interrupt", 0, 0, 0 },
+ { "print-event", 1, 0, 0 },
+ { "mask-event", 1, 0, 0 },
+ { 0, 0, 0, 0 },
+ };
+
+ argvopt = argv;
+
+#ifdef RTE_LIBRTE_CMDLINE
+#define SHORTOPTS "i"
+#else
+#define SHORTOPTS ""
+#endif
+ while ((opt = getopt_long(argc, argvopt, SHORTOPTS "ah",
+ lgopts, &opt_idx)) != EOF) {
+ switch (opt) {
+#ifdef RTE_LIBRTE_CMDLINE
+ case 'i':
+ printf("Interactive-mode selected\n");
+ interactive = 1;
+ break;
+#endif
+ case 'a':
+ printf("Auto-start selected\n");
+ auto_start = 1;
+ break;
+
+ case 0: /*long options */
+ if (!strcmp(lgopts[opt_idx].name, "help")) {
+ usage(argv[0]);
+ rte_exit(EXIT_SUCCESS, "Displayed help\n");
+ }
+#ifdef RTE_LIBRTE_CMDLINE
+ if (!strcmp(lgopts[opt_idx].name, "interactive")) {
+ printf("Interactive-mode selected\n");
+ interactive = 1;
+ }
+ if (!strcmp(lgopts[opt_idx].name, "cmdline-file")) {
+ printf("CLI commands to be read from %s\n",
+ optarg);
+ snprintf(cmdline_filename,
+ sizeof(cmdline_filename), "%s",
+ optarg);
+ }
+ if (!strcmp(lgopts[opt_idx].name, "auto-start")) {
+ printf("Auto-start selected\n");
+ auto_start = 1;
+ }
+ if (!strcmp(lgopts[opt_idx].name,
+ "eth-peers-configfile")) {
+ if (init_peer_eth_addrs(optarg) != 0)
+ rte_exit(EXIT_FAILURE,
+ "Cannot open logfile\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "eth-peer")) {
+ char *port_end;
+ uint8_t c, peer_addr[6];
+
+ errno = 0;
+ n = strtoul(optarg, &port_end, 10);
+ if (errno != 0 || port_end == optarg || *port_end++ != ',')
+ rte_exit(EXIT_FAILURE,
+ "Invalid eth-peer: %s", optarg);
+ if (n >= RTE_MAX_ETHPORTS)
+ rte_exit(EXIT_FAILURE,
+ "eth-peer: port %d >= RTE_MAX_ETHPORTS(%d)\n",
+ n, RTE_MAX_ETHPORTS);
+
+ if (cmdline_parse_etheraddr(NULL, port_end,
+ &peer_addr, sizeof(peer_addr)) < 0)
+ rte_exit(EXIT_FAILURE,
+ "Invalid ethernet address: %s\n",
+ port_end);
+ for (c = 0; c < 6; c++)
+ peer_eth_addrs[n].addr_bytes[c] =
+ peer_addr[c];
+ nb_peer_eth_addrs++;
+ }
+#endif
+ if (!strcmp(lgopts[opt_idx].name, "nb-ports")) {
+ n = atoi(optarg);
+ if (n > 0 && n <= nb_ports)
+ nb_fwd_ports = (uint8_t) n;
+ else
+ rte_exit(EXIT_FAILURE,
+ "Invalid port %d\n", n);
+ }
+ if (!strcmp(lgopts[opt_idx].name, "nb-cores")) {
+ n = atoi(optarg);
+ if (n > 0 && n <= nb_lcores)
+ nb_fwd_lcores = (uint8_t) n;
+ else
+ rte_exit(EXIT_FAILURE,
+ "nb-cores should be > 0 and <= %d\n",
+ nb_lcores);
+ }
+ if (!strcmp(lgopts[opt_idx].name, "coremask"))
+ parse_fwd_coremask(optarg);
+ if (!strcmp(lgopts[opt_idx].name, "portmask"))
+ parse_fwd_portmask(optarg);
+ if (!strcmp(lgopts[opt_idx].name, "no-numa"))
+ numa_support = 0;
+ if (!strcmp(lgopts[opt_idx].name, "numa"))
+ numa_support = 1;
+ if (!strcmp(lgopts[opt_idx].name, "mp-anon")) {
+ mp_anon = 1;
+ }
+ if (!strcmp(lgopts[opt_idx].name, "port-numa-config")) {
+ if (parse_portnuma_config(optarg))
+ rte_exit(EXIT_FAILURE,
+ "invalid port-numa configuration\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "ring-numa-config"))
+ if (parse_ringnuma_config(optarg))
+ rte_exit(EXIT_FAILURE,
+ "invalid ring-numa configuration\n");
+ if (!strcmp(lgopts[opt_idx].name, "socket-num")) {
+ n = atoi(optarg);
+ if (!new_socket_id((uint8_t)n)) {
+ socket_num = (uint8_t)n;
+ } else {
+ print_invalid_socket_id_error();
+ rte_exit(EXIT_FAILURE,
+ "Invalid socket id");
+ }
+ }
+ if (!strcmp(lgopts[opt_idx].name, "mbuf-size")) {
+ n = atoi(optarg);
+ if (n > 0 && n <= 0xFFFF)
+ mbuf_data_size = (uint16_t) n;
+ else
+ rte_exit(EXIT_FAILURE,
+ "mbuf-size should be > 0 and < 65536\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "total-num-mbufs")) {
+ n = atoi(optarg);
+ if (n > 1024)
+ param_total_num_mbufs = (unsigned)n;
+ else
+ rte_exit(EXIT_FAILURE,
+ "total-num-mbufs should be > 1024\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "max-pkt-len")) {
+ n = atoi(optarg);
+ if (n >= ETHER_MIN_LEN) {
+ rx_mode.max_rx_pkt_len = (uint32_t) n;
+ if (n > ETHER_MAX_LEN)
+ rx_mode.jumbo_frame = 1;
+ } else
+ rte_exit(EXIT_FAILURE,
+ "Invalid max-pkt-len=%d - should be > %d\n",
+ n, ETHER_MIN_LEN);
+ }
+ if (!strcmp(lgopts[opt_idx].name, "pkt-filter-mode")) {
+ if (!strcmp(optarg, "signature"))
+ fdir_conf.mode =
+ RTE_FDIR_MODE_SIGNATURE;
+ else if (!strcmp(optarg, "perfect"))
+ fdir_conf.mode = RTE_FDIR_MODE_PERFECT;
+ else if (!strcmp(optarg, "perfect-mac-vlan"))
+ fdir_conf.mode = RTE_FDIR_MODE_PERFECT_MAC_VLAN;
+ else if (!strcmp(optarg, "perfect-tunnel"))
+ fdir_conf.mode = RTE_FDIR_MODE_PERFECT_TUNNEL;
+ else if (!strcmp(optarg, "none"))
+ fdir_conf.mode = RTE_FDIR_MODE_NONE;
+ else
+ rte_exit(EXIT_FAILURE,
+ "pkt-mode-invalid %s invalid - must be: "
+ "none, signature, perfect, perfect-mac-vlan"
+ " or perfect-tunnel\n",
+ optarg);
+ }
+ if (!strcmp(lgopts[opt_idx].name,
+ "pkt-filter-report-hash")) {
+ if (!strcmp(optarg, "none"))
+ fdir_conf.status =
+ RTE_FDIR_NO_REPORT_STATUS;
+ else if (!strcmp(optarg, "match"))
+ fdir_conf.status =
+ RTE_FDIR_REPORT_STATUS;
+ else if (!strcmp(optarg, "always"))
+ fdir_conf.status =
+ RTE_FDIR_REPORT_STATUS_ALWAYS;
+ else
+ rte_exit(EXIT_FAILURE,
+ "pkt-filter-report-hash %s invalid "
+ "- must be: none or match or always\n",
+ optarg);
+ }
+ if (!strcmp(lgopts[opt_idx].name, "pkt-filter-size")) {
+ if (!strcmp(optarg, "64K"))
+ fdir_conf.pballoc =
+ RTE_FDIR_PBALLOC_64K;
+ else if (!strcmp(optarg, "128K"))
+ fdir_conf.pballoc =
+ RTE_FDIR_PBALLOC_128K;
+ else if (!strcmp(optarg, "256K"))
+ fdir_conf.pballoc =
+ RTE_FDIR_PBALLOC_256K;
+ else
+ rte_exit(EXIT_FAILURE, "pkt-filter-size %s invalid -"
+ " must be: 64K or 128K or 256K\n",
+ optarg);
+ }
+ if (!strcmp(lgopts[opt_idx].name,
+ "pkt-filter-drop-queue")) {
+ n = atoi(optarg);
+ if (n >= 0)
+ fdir_conf.drop_queue = (uint8_t) n;
+ else
+ rte_exit(EXIT_FAILURE,
+ "drop queue %d invalid - must"
+ "be >= 0 \n", n);
+ }
+#ifdef RTE_LIBRTE_LATENCY_STATS
+ if (!strcmp(lgopts[opt_idx].name,
+ "latencystats")) {
+ n = atoi(optarg);
+ if (n >= 0) {
+ latencystats_lcore_id = (lcoreid_t) n;
+ latencystats_enabled = 1;
+ } else
+ rte_exit(EXIT_FAILURE,
+ "invalid lcore id %d for latencystats"
+ " must be >= 0\n", n);
+ }
+#endif
+#ifdef RTE_LIBRTE_BITRATE
+ if (!strcmp(lgopts[opt_idx].name, "bitrate-stats")) {
+ n = atoi(optarg);
+ if (n >= 0) {
+ bitrate_lcore_id = (lcoreid_t) n;
+ bitrate_enabled = 1;
+ } else
+ rte_exit(EXIT_FAILURE,
+ "invalid lcore id %d for bitrate stats"
+ " must be >= 0\n", n);
+ }
+#endif
+ if (!strcmp(lgopts[opt_idx].name, "disable-crc-strip"))
+ rx_mode.hw_strip_crc = 0;
+ if (!strcmp(lgopts[opt_idx].name, "enable-lro"))
+ rx_mode.enable_lro = 1;
+ if (!strcmp(lgopts[opt_idx].name, "enable-scatter"))
+ rx_mode.enable_scatter = 1;
+ if (!strcmp(lgopts[opt_idx].name, "enable-rx-cksum"))
+ rx_mode.hw_ip_checksum = 1;
+
+ if (!strcmp(lgopts[opt_idx].name, "disable-hw-vlan")) {
+ rx_mode.hw_vlan_filter = 0;
+ rx_mode.hw_vlan_strip = 0;
+ rx_mode.hw_vlan_extend = 0;
+ }
+
+ if (!strcmp(lgopts[opt_idx].name,
+ "disable-hw-vlan-filter"))
+ rx_mode.hw_vlan_filter = 0;
+
+ if (!strcmp(lgopts[opt_idx].name,
+ "disable-hw-vlan-strip"))
+ rx_mode.hw_vlan_strip = 0;
+
+ if (!strcmp(lgopts[opt_idx].name,
+ "disable-hw-vlan-extend"))
+ rx_mode.hw_vlan_extend = 0;
+
+ if (!strcmp(lgopts[opt_idx].name, "enable-drop-en"))
+ rx_drop_en = 1;
+
+ if (!strcmp(lgopts[opt_idx].name, "disable-rss"))
+ rss_hf = 0;
+ if (!strcmp(lgopts[opt_idx].name, "port-topology")) {
+ if (!strcmp(optarg, "paired"))
+ port_topology = PORT_TOPOLOGY_PAIRED;
+ else if (!strcmp(optarg, "chained"))
+ port_topology = PORT_TOPOLOGY_CHAINED;
+ else if (!strcmp(optarg, "loop"))
+ port_topology = PORT_TOPOLOGY_LOOP;
+ else
+ rte_exit(EXIT_FAILURE, "port-topology %s invalid -"
+ " must be: paired or chained \n",
+ optarg);
+ }
+ if (!strcmp(lgopts[opt_idx].name, "forward-mode"))
+ set_pkt_forwarding_mode(optarg);
+ if (!strcmp(lgopts[opt_idx].name, "rss-ip"))
+ rss_hf = ETH_RSS_IP;
+ if (!strcmp(lgopts[opt_idx].name, "rss-udp"))
+ rss_hf = ETH_RSS_UDP;
+ if (!strcmp(lgopts[opt_idx].name, "rxq")) {
+ n = atoi(optarg);
+ if (n >= 0 && n <= (int) MAX_QUEUE_ID)
+ nb_rxq = (queueid_t) n;
+ else
+ rte_exit(EXIT_FAILURE, "rxq %d invalid - must be"
+ " >= 0 && <= %d\n", n,
+ (int) MAX_QUEUE_ID);
+ }
+ if (!strcmp(lgopts[opt_idx].name, "txq")) {
+ n = atoi(optarg);
+ if (n >= 0 && n <= (int) MAX_QUEUE_ID)
+ nb_txq = (queueid_t) n;
+ else
+ rte_exit(EXIT_FAILURE, "txq %d invalid - must be"
+ " >= 0 && <= %d\n", n,
+ (int) MAX_QUEUE_ID);
+ }
+ if (!nb_rxq && !nb_txq) {
+ rte_exit(EXIT_FAILURE, "Either rx or tx queues should "
+ "be non-zero\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "burst")) {
+ n = atoi(optarg);
+ if ((n >= 1) && (n <= MAX_PKT_BURST))
+ nb_pkt_per_burst = (uint16_t) n;
+ else
+ rte_exit(EXIT_FAILURE,
+ "burst must >= 1 and <= %d]",
+ MAX_PKT_BURST);
+ }
+ if (!strcmp(lgopts[opt_idx].name, "mbcache")) {
+ n = atoi(optarg);
+ if ((n >= 0) &&
+ (n <= RTE_MEMPOOL_CACHE_MAX_SIZE))
+ mb_mempool_cache = (uint16_t) n;
+ else
+ rte_exit(EXIT_FAILURE,
+ "mbcache must be >= 0 and <= %d\n",
+ RTE_MEMPOOL_CACHE_MAX_SIZE);
+ }
+ if (!strcmp(lgopts[opt_idx].name, "txfreet")) {
+ n = atoi(optarg);
+ if (n >= 0)
+ tx_free_thresh = (int16_t)n;
+ else
+ rte_exit(EXIT_FAILURE, "txfreet must be >= 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "txrst")) {
+ n = atoi(optarg);
+ if (n >= 0)
+ tx_rs_thresh = (int16_t)n;
+ else
+ rte_exit(EXIT_FAILURE, "txrst must be >= 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "txqflags")) {
+ char *end = NULL;
+ n = strtoul(optarg, &end, 16);
+ if (n >= 0)
+ txq_flags = (int32_t)n;
+ else
+ rte_exit(EXIT_FAILURE,
+ "txqflags must be >= 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "rxd")) {
+ n = atoi(optarg);
+ if (n > 0) {
+ if (rx_free_thresh >= n)
+ rte_exit(EXIT_FAILURE,
+ "rxd must be > "
+ "rx_free_thresh(%d)\n",
+ (int)rx_free_thresh);
+ else
+ nb_rxd = (uint16_t) n;
+ } else
+ rte_exit(EXIT_FAILURE,
+ "rxd(%d) invalid - must be > 0\n",
+ n);
+ }
+ if (!strcmp(lgopts[opt_idx].name, "txd")) {
+ n = atoi(optarg);
+ if (n > 0)
+ nb_txd = (uint16_t) n;
+ else
+ rte_exit(EXIT_FAILURE, "txd must be in > 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "txpt")) {
+ n = atoi(optarg);
+ if (n >= 0)
+ tx_pthresh = (int8_t)n;
+ else
+ rte_exit(EXIT_FAILURE, "txpt must be >= 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "txht")) {
+ n = atoi(optarg);
+ if (n >= 0)
+ tx_hthresh = (int8_t)n;
+ else
+ rte_exit(EXIT_FAILURE, "txht must be >= 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "txwt")) {
+ n = atoi(optarg);
+ if (n >= 0)
+ tx_wthresh = (int8_t)n;
+ else
+ rte_exit(EXIT_FAILURE, "txwt must be >= 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "rxpt")) {
+ n = atoi(optarg);
+ if (n >= 0)
+ rx_pthresh = (int8_t)n;
+ else
+ rte_exit(EXIT_FAILURE, "rxpt must be >= 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "rxht")) {
+ n = atoi(optarg);
+ if (n >= 0)
+ rx_hthresh = (int8_t)n;
+ else
+ rte_exit(EXIT_FAILURE, "rxht must be >= 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "rxwt")) {
+ n = atoi(optarg);
+ if (n >= 0)
+ rx_wthresh = (int8_t)n;
+ else
+ rte_exit(EXIT_FAILURE, "rxwt must be >= 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "rxfreet")) {
+ n = atoi(optarg);
+ if (n >= 0)
+ rx_free_thresh = (int16_t)n;
+ else
+ rte_exit(EXIT_FAILURE, "rxfreet must be >= 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "tx-queue-stats-mapping")) {
+ if (parse_queue_stats_mapping_config(optarg, TX)) {
+ rte_exit(EXIT_FAILURE,
+ "invalid TX queue statistics mapping config entered\n");
+ }
+ }
+ if (!strcmp(lgopts[opt_idx].name, "rx-queue-stats-mapping")) {
+ if (parse_queue_stats_mapping_config(optarg, RX)) {
+ rte_exit(EXIT_FAILURE,
+ "invalid RX queue statistics mapping config entered\n");
+ }
+ }
+ if (!strcmp(lgopts[opt_idx].name, "txpkts")) {
+ unsigned seg_lengths[RTE_MAX_SEGS_PER_PKT];
+ unsigned int nb_segs;
+
+ nb_segs = parse_item_list(optarg, "txpkt segments",
+ RTE_MAX_SEGS_PER_PKT, seg_lengths, 0);
+ if (nb_segs > 0)
+ set_tx_pkt_segments(seg_lengths, nb_segs);
+ else
+ rte_exit(EXIT_FAILURE, "bad txpkts\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "no-flush-rx"))
+ no_flush_rx = 1;
+ if (!strcmp(lgopts[opt_idx].name, "disable-link-check"))
+ no_link_check = 1;
+ if (!strcmp(lgopts[opt_idx].name, "no-lsc-interrupt"))
+ lsc_interrupt = 0;
+ if (!strcmp(lgopts[opt_idx].name, "no-rmv-interrupt"))
+ rmv_interrupt = 0;
+ if (!strcmp(lgopts[opt_idx].name, "print-event"))
+ if (parse_event_printing_config(optarg, 1)) {
+ rte_exit(EXIT_FAILURE,
+ "invalid print-event argument\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "mask-event"))
+ if (parse_event_printing_config(optarg, 0)) {
+ rte_exit(EXIT_FAILURE,
+ "invalid mask-event argument\n");
+ }
+
+ break;
+ case 'h':
+ usage(argv[0]);
+ rte_exit(EXIT_SUCCESS, "Displayed help\n");
+ break;
+ default:
+ usage(argv[0]);
+ rte_exit(EXIT_FAILURE,
+ "Command line is incomplete or incorrect\n");
+ break;
+ }
+ }
+}
diff --git a/src/seastar/dpdk/app/test-pmd/rxonly.c b/src/seastar/dpdk/app/test-pmd/rxonly.c
new file mode 100644
index 00000000..dcd1d85c
--- /dev/null
+++ b/src/seastar/dpdk/app/test-pmd/rxonly.c
@@ -0,0 +1,249 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_cycles.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_memzone.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_memory.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_string_fns.h>
+#include <rte_ip.h>
+#include <rte_udp.h>
+#include <rte_net.h>
+#include <rte_flow.h>
+
+#include "testpmd.h"
+
+static inline void
+print_ether_addr(const char *what, struct ether_addr *eth_addr)
+{
+ char buf[ETHER_ADDR_FMT_SIZE];
+ ether_format_addr(buf, ETHER_ADDR_FMT_SIZE, eth_addr);
+ printf("%s%s", what, buf);
+}
+
+/*
+ * Received a burst of packets.
+ */
+static void
+pkt_burst_receive(struct fwd_stream *fs)
+{
+ struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+ struct rte_mbuf *mb;
+ struct ether_hdr *eth_hdr;
+ uint16_t eth_type;
+ uint64_t ol_flags;
+ uint16_t nb_rx;
+ uint16_t i, packet_type;
+ uint16_t is_encapsulation;
+ char buf[256];
+ struct rte_net_hdr_lens hdr_lens;
+ uint32_t sw_packet_type;
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ uint64_t start_tsc;
+ uint64_t end_tsc;
+ uint64_t core_cycles;
+
+ start_tsc = rte_rdtsc();
+#endif
+
+ /*
+ * Receive a burst of packets.
+ */
+ nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst,
+ nb_pkt_per_burst);
+ if (unlikely(nb_rx == 0))
+ return;
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->rx_burst_stats.pkt_burst_spread[nb_rx]++;
+#endif
+ fs->rx_packets += nb_rx;
+
+ /*
+ * Dump each received packet if verbose_level > 0.
+ */
+ if (verbose_level > 0)
+ printf("port %u/queue %u: received %u packets\n",
+ (unsigned) fs->rx_port,
+ (unsigned) fs->rx_queue,
+ (unsigned) nb_rx);
+ for (i = 0; i < nb_rx; i++) {
+ mb = pkts_burst[i];
+ if (verbose_level == 0) {
+ rte_pktmbuf_free(mb);
+ continue;
+ }
+ eth_hdr = rte_pktmbuf_mtod(mb, struct ether_hdr *);
+ eth_type = RTE_BE_TO_CPU_16(eth_hdr->ether_type);
+ ol_flags = mb->ol_flags;
+ packet_type = mb->packet_type;
+ is_encapsulation = RTE_ETH_IS_TUNNEL_PKT(packet_type);
+
+ print_ether_addr(" src=", &eth_hdr->s_addr);
+ print_ether_addr(" - dst=", &eth_hdr->d_addr);
+ printf(" - type=0x%04x - length=%u - nb_segs=%d",
+ eth_type, (unsigned) mb->pkt_len,
+ (int)mb->nb_segs);
+ if (ol_flags & PKT_RX_RSS_HASH) {
+ printf(" - RSS hash=0x%x", (unsigned) mb->hash.rss);
+ printf(" - RSS queue=0x%x",(unsigned) fs->rx_queue);
+ }
+ if (ol_flags & PKT_RX_FDIR) {
+ printf(" - FDIR matched ");
+ if (ol_flags & PKT_RX_FDIR_ID)
+ printf("ID=0x%x",
+ mb->hash.fdir.hi);
+ else if (ol_flags & PKT_RX_FDIR_FLX)
+ printf("flex bytes=0x%08x %08x",
+ mb->hash.fdir.hi, mb->hash.fdir.lo);
+ else
+ printf("hash=0x%x ID=0x%x ",
+ mb->hash.fdir.hash, mb->hash.fdir.id);
+ }
+ if (ol_flags & PKT_RX_VLAN_STRIPPED)
+ printf(" - VLAN tci=0x%x", mb->vlan_tci);
+ if (ol_flags & PKT_RX_QINQ_STRIPPED)
+ printf(" - QinQ VLAN tci=0x%x, VLAN tci outer=0x%x",
+ mb->vlan_tci, mb->vlan_tci_outer);
+ if (mb->packet_type) {
+ rte_get_ptype_name(mb->packet_type, buf, sizeof(buf));
+ printf(" - hw ptype: %s", buf);
+ }
+ sw_packet_type = rte_net_get_ptype(mb, &hdr_lens,
+ RTE_PTYPE_ALL_MASK);
+ rte_get_ptype_name(sw_packet_type, buf, sizeof(buf));
+ printf(" - sw ptype: %s", buf);
+ if (sw_packet_type & RTE_PTYPE_L2_MASK)
+ printf(" - l2_len=%d", hdr_lens.l2_len);
+ if (sw_packet_type & RTE_PTYPE_L3_MASK)
+ printf(" - l3_len=%d", hdr_lens.l3_len);
+ if (sw_packet_type & RTE_PTYPE_L4_MASK)
+ printf(" - l4_len=%d", hdr_lens.l4_len);
+ if (sw_packet_type & RTE_PTYPE_TUNNEL_MASK)
+ printf(" - tunnel_len=%d", hdr_lens.tunnel_len);
+ if (sw_packet_type & RTE_PTYPE_INNER_L2_MASK)
+ printf(" - inner_l2_len=%d", hdr_lens.inner_l2_len);
+ if (sw_packet_type & RTE_PTYPE_INNER_L3_MASK)
+ printf(" - inner_l3_len=%d", hdr_lens.inner_l3_len);
+ if (sw_packet_type & RTE_PTYPE_INNER_L4_MASK)
+ printf(" - inner_l4_len=%d", hdr_lens.inner_l4_len);
+ if (is_encapsulation) {
+ struct ipv4_hdr *ipv4_hdr;
+ struct ipv6_hdr *ipv6_hdr;
+ struct udp_hdr *udp_hdr;
+ uint8_t l2_len;
+ uint8_t l3_len;
+ uint8_t l4_len;
+ uint8_t l4_proto;
+ struct vxlan_hdr *vxlan_hdr;
+
+ l2_len = sizeof(struct ether_hdr);
+
+ /* Do not support ipv4 option field */
+ if (RTE_ETH_IS_IPV4_HDR(packet_type)) {
+ l3_len = sizeof(struct ipv4_hdr);
+ ipv4_hdr = rte_pktmbuf_mtod_offset(mb,
+ struct ipv4_hdr *,
+ l2_len);
+ l4_proto = ipv4_hdr->next_proto_id;
+ } else {
+ l3_len = sizeof(struct ipv6_hdr);
+ ipv6_hdr = rte_pktmbuf_mtod_offset(mb,
+ struct ipv6_hdr *,
+ l2_len);
+ l4_proto = ipv6_hdr->proto;
+ }
+ if (l4_proto == IPPROTO_UDP) {
+ udp_hdr = rte_pktmbuf_mtod_offset(mb,
+ struct udp_hdr *,
+ l2_len + l3_len);
+ l4_len = sizeof(struct udp_hdr);
+ vxlan_hdr = rte_pktmbuf_mtod_offset(mb,
+ struct vxlan_hdr *,
+ l2_len + l3_len + l4_len);
+
+ printf(" - VXLAN packet: packet type =%d, "
+ "Destination UDP port =%d, VNI = %d",
+ packet_type, RTE_BE_TO_CPU_16(udp_hdr->dst_port),
+ rte_be_to_cpu_32(vxlan_hdr->vx_vni) >> 8);
+ }
+ }
+ printf(" - Receive queue=0x%x", (unsigned) fs->rx_queue);
+ printf("\n");
+ rte_get_rx_ol_flag_list(mb->ol_flags, buf, sizeof(buf));
+ printf(" ol_flags: %s\n", buf);
+ rte_pktmbuf_free(mb);
+ }
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ end_tsc = rte_rdtsc();
+ core_cycles = (end_tsc - start_tsc);
+ fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles);
+#endif
+}
+
+struct fwd_engine rx_only_engine = {
+ .fwd_mode_name = "rxonly",
+ .port_fwd_begin = NULL,
+ .port_fwd_end = NULL,
+ .packet_fwd = pkt_burst_receive,
+};
diff --git a/src/seastar/dpdk/app/test-pmd/testpmd.c b/src/seastar/dpdk/app/test-pmd/testpmd.c
new file mode 100644
index 00000000..d1041afa
--- /dev/null
+++ b/src/seastar/dpdk/app/test-pmd/testpmd.c
@@ -0,0 +1,2362 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <errno.h>
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <rte_common.h>
+#include <rte_errno.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_cycles.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_memzone.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_alarm.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_mempool.h>
+#include <rte_malloc.h>
+#include <rte_mbuf.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_dev.h>
+#include <rte_string_fns.h>
+#ifdef RTE_LIBRTE_PMD_XENVIRT
+#include <rte_eth_xenvirt.h>
+#endif
+#ifdef RTE_LIBRTE_PDUMP
+#include <rte_pdump.h>
+#endif
+#include <rte_flow.h>
+#include <rte_metrics.h>
+#ifdef RTE_LIBRTE_BITRATE
+#include <rte_bitrate.h>
+#endif
+#ifdef RTE_LIBRTE_LATENCY_STATS
+#include <rte_latencystats.h>
+#endif
+
+#include "testpmd.h"
+
+uint16_t verbose_level = 0; /**< Silent by default. */
+
+/* use master core for command line ? */
+uint8_t interactive = 0;
+uint8_t auto_start = 0;
+char cmdline_filename[PATH_MAX] = {0};
+
+/*
+ * NUMA support configuration.
+ * When set, the NUMA support attempts to dispatch the allocation of the
+ * RX and TX memory rings, and of the DMA memory buffers (mbufs) for the
+ * probed ports among the CPU sockets 0 and 1.
+ * Otherwise, all memory is allocated from CPU socket 0.
+ */
+uint8_t numa_support = 1; /**< numa enabled by default */
+
+/*
+ * In UMA mode,all memory is allocated from socket 0 if --socket-num is
+ * not configured.
+ */
+uint8_t socket_num = UMA_NO_CONFIG;
+
+/*
+ * Use ANONYMOUS mapped memory (might be not physically continuous) for mbufs.
+ */
+uint8_t mp_anon = 0;
+
+/*
+ * Record the Ethernet address of peer target ports to which packets are
+ * forwarded.
+ * Must be instantiated with the ethernet addresses of peer traffic generator
+ * ports.
+ */
+struct ether_addr peer_eth_addrs[RTE_MAX_ETHPORTS];
+portid_t nb_peer_eth_addrs = 0;
+
+/*
+ * Probed Target Environment.
+ */
+struct rte_port *ports; /**< For all probed ethernet ports. */
+portid_t nb_ports; /**< Number of probed ethernet ports. */
+struct fwd_lcore **fwd_lcores; /**< For all probed logical cores. */
+lcoreid_t nb_lcores; /**< Number of probed logical cores. */
+
+/*
+ * Test Forwarding Configuration.
+ * nb_fwd_lcores <= nb_cfg_lcores <= nb_lcores
+ * nb_fwd_ports <= nb_cfg_ports <= nb_ports
+ */
+lcoreid_t nb_cfg_lcores; /**< Number of configured logical cores. */
+lcoreid_t nb_fwd_lcores; /**< Number of forwarding logical cores. */
+portid_t nb_cfg_ports; /**< Number of configured ports. */
+portid_t nb_fwd_ports; /**< Number of forwarding ports. */
+
+unsigned int fwd_lcores_cpuids[RTE_MAX_LCORE]; /**< CPU ids configuration. */
+portid_t fwd_ports_ids[RTE_MAX_ETHPORTS]; /**< Port ids configuration. */
+
+struct fwd_stream **fwd_streams; /**< For each RX queue of each port. */
+streamid_t nb_fwd_streams; /**< Is equal to (nb_ports * nb_rxq). */
+
+/*
+ * Forwarding engines.
+ */
+struct fwd_engine * fwd_engines[] = {
+ &io_fwd_engine,
+ &mac_fwd_engine,
+ &mac_swap_engine,
+ &flow_gen_engine,
+ &rx_only_engine,
+ &tx_only_engine,
+ &csum_fwd_engine,
+ &icmp_echo_engine,
+#ifdef RTE_LIBRTE_IEEE1588
+ &ieee1588_fwd_engine,
+#endif
+ NULL,
+};
+
+struct fwd_config cur_fwd_config;
+struct fwd_engine *cur_fwd_eng = &io_fwd_engine; /**< IO mode by default. */
+uint32_t retry_enabled;
+uint32_t burst_tx_delay_time = BURST_TX_WAIT_US;
+uint32_t burst_tx_retry_num = BURST_TX_RETRIES;
+
+uint16_t mbuf_data_size = DEFAULT_MBUF_DATA_SIZE; /**< Mbuf data space size. */
+uint32_t param_total_num_mbufs = 0; /**< number of mbufs in all pools - if
+ * specified on command-line. */
+
+/*
+ * Configuration of packet segments used by the "txonly" processing engine.
+ */
+uint16_t tx_pkt_length = TXONLY_DEF_PACKET_LEN; /**< TXONLY packet length. */
+uint16_t tx_pkt_seg_lengths[RTE_MAX_SEGS_PER_PKT] = {
+ TXONLY_DEF_PACKET_LEN,
+};
+uint8_t tx_pkt_nb_segs = 1; /**< Number of segments in TXONLY packets */
+
+enum tx_pkt_split tx_pkt_split = TX_PKT_SPLIT_OFF;
+/**< Split policy for packets to TX. */
+
+uint16_t nb_pkt_per_burst = DEF_PKT_BURST; /**< Number of packets per burst. */
+uint16_t mb_mempool_cache = DEF_MBUF_CACHE; /**< Size of mbuf mempool cache. */
+
+/* current configuration is in DCB or not,0 means it is not in DCB mode */
+uint8_t dcb_config = 0;
+
+/* Whether the dcb is in testing status */
+uint8_t dcb_test = 0;
+
+/*
+ * Configurable number of RX/TX queues.
+ */
+queueid_t nb_rxq = 1; /**< Number of RX queues per port. */
+queueid_t nb_txq = 1; /**< Number of TX queues per port. */
+
+/*
+ * Configurable number of RX/TX ring descriptors.
+ */
+#define RTE_TEST_RX_DESC_DEFAULT 128
+#define RTE_TEST_TX_DESC_DEFAULT 512
+uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; /**< Number of RX descriptors. */
+uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; /**< Number of TX descriptors. */
+
+#define RTE_PMD_PARAM_UNSET -1
+/*
+ * Configurable values of RX and TX ring threshold registers.
+ */
+
+int8_t rx_pthresh = RTE_PMD_PARAM_UNSET;
+int8_t rx_hthresh = RTE_PMD_PARAM_UNSET;
+int8_t rx_wthresh = RTE_PMD_PARAM_UNSET;
+
+int8_t tx_pthresh = RTE_PMD_PARAM_UNSET;
+int8_t tx_hthresh = RTE_PMD_PARAM_UNSET;
+int8_t tx_wthresh = RTE_PMD_PARAM_UNSET;
+
+/*
+ * Configurable value of RX free threshold.
+ */
+int16_t rx_free_thresh = RTE_PMD_PARAM_UNSET;
+
+/*
+ * Configurable value of RX drop enable.
+ */
+int8_t rx_drop_en = RTE_PMD_PARAM_UNSET;
+
+/*
+ * Configurable value of TX free threshold.
+ */
+int16_t tx_free_thresh = RTE_PMD_PARAM_UNSET;
+
+/*
+ * Configurable value of TX RS bit threshold.
+ */
+int16_t tx_rs_thresh = RTE_PMD_PARAM_UNSET;
+
+/*
+ * Configurable value of TX queue flags.
+ */
+int32_t txq_flags = RTE_PMD_PARAM_UNSET;
+
+/*
+ * Receive Side Scaling (RSS) configuration.
+ */
+uint64_t rss_hf = ETH_RSS_IP; /* RSS IP by default. */
+
+/*
+ * Port topology configuration
+ */
+uint16_t port_topology = PORT_TOPOLOGY_PAIRED; /* Ports are paired by default */
+
+/*
+ * Avoids to flush all the RX streams before starts forwarding.
+ */
+uint8_t no_flush_rx = 0; /* flush by default */
+
+/*
+ * Avoids to check link status when starting/stopping a port.
+ */
+uint8_t no_link_check = 0; /* check by default */
+
+/*
+ * Enable link status change notification
+ */
+uint8_t lsc_interrupt = 1; /* enabled by default */
+
+/*
+ * Enable device removal notification.
+ */
+uint8_t rmv_interrupt = 1; /* enabled by default */
+
+/*
+ * Display or mask ether events
+ * Default to all events except VF_MBOX
+ */
+uint32_t event_print_mask = (UINT32_C(1) << RTE_ETH_EVENT_UNKNOWN) |
+ (UINT32_C(1) << RTE_ETH_EVENT_INTR_LSC) |
+ (UINT32_C(1) << RTE_ETH_EVENT_QUEUE_STATE) |
+ (UINT32_C(1) << RTE_ETH_EVENT_INTR_RESET) |
+ (UINT32_C(1) << RTE_ETH_EVENT_MACSEC) |
+ (UINT32_C(1) << RTE_ETH_EVENT_INTR_RMV);
+
+/*
+ * NIC bypass mode configuration options.
+ */
+#ifdef RTE_NIC_BYPASS
+
+/* The NIC bypass watchdog timeout. */
+uint32_t bypass_timeout = RTE_BYPASS_TMT_OFF;
+
+#endif
+
+#ifdef RTE_LIBRTE_LATENCY_STATS
+
+/*
+ * Set when latency stats is enabled in the commandline
+ */
+uint8_t latencystats_enabled;
+
+/*
+ * Lcore ID to serive latency statistics.
+ */
+lcoreid_t latencystats_lcore_id = -1;
+
+#endif
+
+/*
+ * Ethernet device configuration.
+ */
+struct rte_eth_rxmode rx_mode = {
+ .max_rx_pkt_len = ETHER_MAX_LEN, /**< Default maximum frame length. */
+ .split_hdr_size = 0,
+ .header_split = 0, /**< Header Split disabled. */
+ .hw_ip_checksum = 0, /**< IP checksum offload disabled. */
+ .hw_vlan_filter = 1, /**< VLAN filtering enabled. */
+ .hw_vlan_strip = 1, /**< VLAN strip enabled. */
+ .hw_vlan_extend = 0, /**< Extended VLAN disabled. */
+ .jumbo_frame = 0, /**< Jumbo Frame Support disabled. */
+ .hw_strip_crc = 1, /**< CRC stripping by hardware enabled. */
+};
+
+struct rte_fdir_conf fdir_conf = {
+ .mode = RTE_FDIR_MODE_NONE,
+ .pballoc = RTE_FDIR_PBALLOC_64K,
+ .status = RTE_FDIR_REPORT_STATUS,
+ .mask = {
+ .vlan_tci_mask = 0x0,
+ .ipv4_mask = {
+ .src_ip = 0xFFFFFFFF,
+ .dst_ip = 0xFFFFFFFF,
+ },
+ .ipv6_mask = {
+ .src_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
+ .dst_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
+ },
+ .src_port_mask = 0xFFFF,
+ .dst_port_mask = 0xFFFF,
+ .mac_addr_byte_mask = 0xFF,
+ .tunnel_type_mask = 1,
+ .tunnel_id_mask = 0xFFFFFFFF,
+ },
+ .drop_queue = 127,
+};
+
+volatile int test_done = 1; /* stop packet forwarding when set to 1. */
+
+struct queue_stats_mappings tx_queue_stats_mappings_array[MAX_TX_QUEUE_STATS_MAPPINGS];
+struct queue_stats_mappings rx_queue_stats_mappings_array[MAX_RX_QUEUE_STATS_MAPPINGS];
+
+struct queue_stats_mappings *tx_queue_stats_mappings = tx_queue_stats_mappings_array;
+struct queue_stats_mappings *rx_queue_stats_mappings = rx_queue_stats_mappings_array;
+
+uint16_t nb_tx_queue_stats_mappings = 0;
+uint16_t nb_rx_queue_stats_mappings = 0;
+
+unsigned int num_sockets = 0;
+unsigned int socket_ids[RTE_MAX_NUMA_NODES];
+
+#ifdef RTE_LIBRTE_BITRATE
+/* Bitrate statistics */
+struct rte_stats_bitrates *bitrate_data;
+lcoreid_t bitrate_lcore_id;
+uint8_t bitrate_enabled;
+#endif
+
+/* Forward function declarations */
+static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port);
+static void check_all_ports_link_status(uint32_t port_mask);
+static void eth_event_callback(uint8_t port_id,
+ enum rte_eth_event_type type,
+ void *param);
+
+/*
+ * Check if all the ports are started.
+ * If yes, return positive value. If not, return zero.
+ */
+static int all_ports_started(void);
+
+/*
+ * Helper function to check if socket is allready discovered.
+ * If yes, return positive value. If not, return zero.
+ */
+int
+new_socket_id(unsigned int socket_id)
+{
+ unsigned int i;
+
+ for (i = 0; i < num_sockets; i++) {
+ if (socket_ids[i] == socket_id)
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * Setup default configuration.
+ */
+static void
+set_default_fwd_lcores_config(void)
+{
+ unsigned int i;
+ unsigned int nb_lc;
+ unsigned int sock_num;
+
+ nb_lc = 0;
+ for (i = 0; i < RTE_MAX_LCORE; i++) {
+ sock_num = rte_lcore_to_socket_id(i);
+ if (new_socket_id(sock_num)) {
+ if (num_sockets >= RTE_MAX_NUMA_NODES) {
+ rte_exit(EXIT_FAILURE,
+ "Total sockets greater than %u\n",
+ RTE_MAX_NUMA_NODES);
+ }
+ socket_ids[num_sockets++] = sock_num;
+ }
+ if (!rte_lcore_is_enabled(i))
+ continue;
+ if (i == rte_get_master_lcore())
+ continue;
+ fwd_lcores_cpuids[nb_lc++] = i;
+ }
+ nb_lcores = (lcoreid_t) nb_lc;
+ nb_cfg_lcores = nb_lcores;
+ nb_fwd_lcores = 1;
+}
+
+static void
+set_def_peer_eth_addrs(void)
+{
+ portid_t i;
+
+ for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
+ peer_eth_addrs[i].addr_bytes[0] = ETHER_LOCAL_ADMIN_ADDR;
+ peer_eth_addrs[i].addr_bytes[5] = i;
+ }
+}
+
+static void
+set_default_fwd_ports_config(void)
+{
+ portid_t pt_id;
+
+ for (pt_id = 0; pt_id < nb_ports; pt_id++)
+ fwd_ports_ids[pt_id] = pt_id;
+
+ nb_cfg_ports = nb_ports;
+ nb_fwd_ports = nb_ports;
+}
+
+void
+set_def_fwd_config(void)
+{
+ set_default_fwd_lcores_config();
+ set_def_peer_eth_addrs();
+ set_default_fwd_ports_config();
+}
+
+/*
+ * Configuration initialisation done once at init time.
+ */
+static void
+mbuf_pool_create(uint16_t mbuf_seg_size, unsigned nb_mbuf,
+ unsigned int socket_id)
+{
+ char pool_name[RTE_MEMPOOL_NAMESIZE];
+ struct rte_mempool *rte_mp = NULL;
+ uint32_t mb_size;
+
+ mb_size = sizeof(struct rte_mbuf) + mbuf_seg_size;
+ mbuf_poolname_build(socket_id, pool_name, sizeof(pool_name));
+
+ RTE_LOG(INFO, USER1,
+ "create a new mbuf pool <%s>: n=%u, size=%u, socket=%u\n",
+ pool_name, nb_mbuf, mbuf_seg_size, socket_id);
+
+#ifdef RTE_LIBRTE_PMD_XENVIRT
+ rte_mp = rte_mempool_gntalloc_create(pool_name, nb_mbuf, mb_size,
+ (unsigned) mb_mempool_cache,
+ sizeof(struct rte_pktmbuf_pool_private),
+ rte_pktmbuf_pool_init, NULL,
+ rte_pktmbuf_init, NULL,
+ socket_id, 0);
+#endif
+
+ /* if the former XEN allocation failed fall back to normal allocation */
+ if (rte_mp == NULL) {
+ if (mp_anon != 0) {
+ rte_mp = rte_mempool_create_empty(pool_name, nb_mbuf,
+ mb_size, (unsigned) mb_mempool_cache,
+ sizeof(struct rte_pktmbuf_pool_private),
+ socket_id, 0);
+ if (rte_mp == NULL)
+ goto err;
+
+ if (rte_mempool_populate_anon(rte_mp) == 0) {
+ rte_mempool_free(rte_mp);
+ rte_mp = NULL;
+ goto err;
+ }
+ rte_pktmbuf_pool_init(rte_mp, NULL);
+ rte_mempool_obj_iter(rte_mp, rte_pktmbuf_init, NULL);
+ } else {
+ /* wrapper to rte_mempool_create() */
+ rte_mp = rte_pktmbuf_pool_create(pool_name, nb_mbuf,
+ mb_mempool_cache, 0, mbuf_seg_size, socket_id);
+ }
+ }
+
+err:
+ if (rte_mp == NULL) {
+ rte_exit(EXIT_FAILURE,
+ "Creation of mbuf pool for socket %u failed: %s\n",
+ socket_id, rte_strerror(rte_errno));
+ } else if (verbose_level > 0) {
+ rte_mempool_dump(stdout, rte_mp);
+ }
+}
+
+/*
+ * Check given socket id is valid or not with NUMA mode,
+ * if valid, return 0, else return -1
+ */
+static int
+check_socket_id(const unsigned int socket_id)
+{
+ static int warning_once = 0;
+
+ if (new_socket_id(socket_id)) {
+ if (!warning_once && numa_support)
+ printf("Warning: NUMA should be configured manually by"
+ " using --port-numa-config and"
+ " --ring-numa-config parameters along with"
+ " --numa.\n");
+ warning_once = 1;
+ return -1;
+ }
+ return 0;
+}
+
+static void
+init_config(void)
+{
+ portid_t pid;
+ struct rte_port *port;
+ struct rte_mempool *mbp;
+ unsigned int nb_mbuf_per_pool;
+ lcoreid_t lc_id;
+ uint8_t port_per_socket[RTE_MAX_NUMA_NODES];
+
+ memset(port_per_socket,0,RTE_MAX_NUMA_NODES);
+
+ if (numa_support) {
+ memset(port_numa, NUMA_NO_CONFIG, RTE_MAX_ETHPORTS);
+ memset(rxring_numa, NUMA_NO_CONFIG, RTE_MAX_ETHPORTS);
+ memset(txring_numa, NUMA_NO_CONFIG, RTE_MAX_ETHPORTS);
+ }
+
+ /* Configuration of logical cores. */
+ fwd_lcores = rte_zmalloc("testpmd: fwd_lcores",
+ sizeof(struct fwd_lcore *) * nb_lcores,
+ RTE_CACHE_LINE_SIZE);
+ if (fwd_lcores == NULL) {
+ rte_exit(EXIT_FAILURE, "rte_zmalloc(%d (struct fwd_lcore *)) "
+ "failed\n", nb_lcores);
+ }
+ for (lc_id = 0; lc_id < nb_lcores; lc_id++) {
+ fwd_lcores[lc_id] = rte_zmalloc("testpmd: struct fwd_lcore",
+ sizeof(struct fwd_lcore),
+ RTE_CACHE_LINE_SIZE);
+ if (fwd_lcores[lc_id] == NULL) {
+ rte_exit(EXIT_FAILURE, "rte_zmalloc(struct fwd_lcore) "
+ "failed\n");
+ }
+ fwd_lcores[lc_id]->cpuid_idx = lc_id;
+ }
+
+ RTE_ETH_FOREACH_DEV(pid) {
+ port = &ports[pid];
+ rte_eth_dev_info_get(pid, &port->dev_info);
+
+ if (numa_support) {
+ if (port_numa[pid] != NUMA_NO_CONFIG)
+ port_per_socket[port_numa[pid]]++;
+ else {
+ uint32_t socket_id = rte_eth_dev_socket_id(pid);
+
+ /* if socket_id is invalid, set to 0 */
+ if (check_socket_id(socket_id) < 0)
+ socket_id = 0;
+ port_per_socket[socket_id]++;
+ }
+ }
+
+ /* set flag to initialize port/queue */
+ port->need_reconfig = 1;
+ port->need_reconfig_queues = 1;
+ }
+
+ /*
+ * Create pools of mbuf.
+ * If NUMA support is disabled, create a single pool of mbuf in
+ * socket 0 memory by default.
+ * Otherwise, create a pool of mbuf in the memory of sockets 0 and 1.
+ *
+ * Use the maximum value of nb_rxd and nb_txd here, then nb_rxd and
+ * nb_txd can be configured at run time.
+ */
+ if (param_total_num_mbufs)
+ nb_mbuf_per_pool = param_total_num_mbufs;
+ else {
+ nb_mbuf_per_pool = RTE_TEST_RX_DESC_MAX +
+ (nb_lcores * mb_mempool_cache) +
+ RTE_TEST_TX_DESC_MAX + MAX_PKT_BURST;
+ nb_mbuf_per_pool *= RTE_MAX_ETHPORTS;
+ }
+
+ if (numa_support) {
+ uint8_t i;
+
+ for (i = 0; i < num_sockets; i++)
+ mbuf_pool_create(mbuf_data_size, nb_mbuf_per_pool,
+ socket_ids[i]);
+ } else {
+ if (socket_num == UMA_NO_CONFIG)
+ mbuf_pool_create(mbuf_data_size, nb_mbuf_per_pool, 0);
+ else
+ mbuf_pool_create(mbuf_data_size, nb_mbuf_per_pool,
+ socket_num);
+ }
+
+ init_port_config();
+
+ /*
+ * Records which Mbuf pool to use by each logical core, if needed.
+ */
+ for (lc_id = 0; lc_id < nb_lcores; lc_id++) {
+ mbp = mbuf_pool_find(
+ rte_lcore_to_socket_id(fwd_lcores_cpuids[lc_id]));
+
+ if (mbp == NULL)
+ mbp = mbuf_pool_find(0);
+ fwd_lcores[lc_id]->mbp = mbp;
+ }
+
+ /* Configuration of packet forwarding streams. */
+ if (init_fwd_streams() < 0)
+ rte_exit(EXIT_FAILURE, "FAIL from init_fwd_streams()\n");
+
+ fwd_config_setup();
+}
+
+
+void
+reconfig(portid_t new_port_id, unsigned socket_id)
+{
+ struct rte_port *port;
+
+ /* Reconfiguration of Ethernet ports. */
+ port = &ports[new_port_id];
+ rte_eth_dev_info_get(new_port_id, &port->dev_info);
+
+ /* set flag to initialize port/queue */
+ port->need_reconfig = 1;
+ port->need_reconfig_queues = 1;
+ port->socket_id = socket_id;
+
+ init_port_config();
+}
+
+
+int
+init_fwd_streams(void)
+{
+ portid_t pid;
+ struct rte_port *port;
+ streamid_t sm_id, nb_fwd_streams_new;
+ queueid_t q;
+
+ /* set socket id according to numa or not */
+ RTE_ETH_FOREACH_DEV(pid) {
+ port = &ports[pid];
+ if (nb_rxq > port->dev_info.max_rx_queues) {
+ printf("Fail: nb_rxq(%d) is greater than "
+ "max_rx_queues(%d)\n", nb_rxq,
+ port->dev_info.max_rx_queues);
+ return -1;
+ }
+ if (nb_txq > port->dev_info.max_tx_queues) {
+ printf("Fail: nb_txq(%d) is greater than "
+ "max_tx_queues(%d)\n", nb_txq,
+ port->dev_info.max_tx_queues);
+ return -1;
+ }
+ if (numa_support) {
+ if (port_numa[pid] != NUMA_NO_CONFIG)
+ port->socket_id = port_numa[pid];
+ else {
+ port->socket_id = rte_eth_dev_socket_id(pid);
+
+ /* if socket_id is invalid, set to 0 */
+ if (check_socket_id(port->socket_id) < 0)
+ port->socket_id = 0;
+ }
+ }
+ else {
+ if (socket_num == UMA_NO_CONFIG)
+ port->socket_id = 0;
+ else
+ port->socket_id = socket_num;
+ }
+ }
+
+ q = RTE_MAX(nb_rxq, nb_txq);
+ if (q == 0) {
+ printf("Fail: Cannot allocate fwd streams as number of queues is 0\n");
+ return -1;
+ }
+ nb_fwd_streams_new = (streamid_t)(nb_ports * q);
+ if (nb_fwd_streams_new == nb_fwd_streams)
+ return 0;
+ /* clear the old */
+ if (fwd_streams != NULL) {
+ for (sm_id = 0; sm_id < nb_fwd_streams; sm_id++) {
+ if (fwd_streams[sm_id] == NULL)
+ continue;
+ rte_free(fwd_streams[sm_id]);
+ fwd_streams[sm_id] = NULL;
+ }
+ rte_free(fwd_streams);
+ fwd_streams = NULL;
+ }
+
+ /* init new */
+ nb_fwd_streams = nb_fwd_streams_new;
+ fwd_streams = rte_zmalloc("testpmd: fwd_streams",
+ sizeof(struct fwd_stream *) * nb_fwd_streams, RTE_CACHE_LINE_SIZE);
+ if (fwd_streams == NULL)
+ rte_exit(EXIT_FAILURE, "rte_zmalloc(%d (struct fwd_stream *)) "
+ "failed\n", nb_fwd_streams);
+
+ for (sm_id = 0; sm_id < nb_fwd_streams; sm_id++) {
+ fwd_streams[sm_id] = rte_zmalloc("testpmd: struct fwd_stream",
+ sizeof(struct fwd_stream), RTE_CACHE_LINE_SIZE);
+ if (fwd_streams[sm_id] == NULL)
+ rte_exit(EXIT_FAILURE, "rte_zmalloc(struct fwd_stream)"
+ " failed\n");
+ }
+
+ return 0;
+}
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+static void
+pkt_burst_stats_display(const char *rx_tx, struct pkt_burst_stats *pbs)
+{
+ unsigned int total_burst;
+ unsigned int nb_burst;
+ unsigned int burst_stats[3];
+ uint16_t pktnb_stats[3];
+ uint16_t nb_pkt;
+ int burst_percent[3];
+
+ /*
+ * First compute the total number of packet bursts and the
+ * two highest numbers of bursts of the same number of packets.
+ */
+ total_burst = 0;
+ burst_stats[0] = burst_stats[1] = burst_stats[2] = 0;
+ pktnb_stats[0] = pktnb_stats[1] = pktnb_stats[2] = 0;
+ for (nb_pkt = 0; nb_pkt < MAX_PKT_BURST; nb_pkt++) {
+ nb_burst = pbs->pkt_burst_spread[nb_pkt];
+ if (nb_burst == 0)
+ continue;
+ total_burst += nb_burst;
+ if (nb_burst > burst_stats[0]) {
+ burst_stats[1] = burst_stats[0];
+ pktnb_stats[1] = pktnb_stats[0];
+ burst_stats[0] = nb_burst;
+ pktnb_stats[0] = nb_pkt;
+ }
+ }
+ if (total_burst == 0)
+ return;
+ burst_percent[0] = (burst_stats[0] * 100) / total_burst;
+ printf(" %s-bursts : %u [%d%% of %d pkts", rx_tx, total_burst,
+ burst_percent[0], (int) pktnb_stats[0]);
+ if (burst_stats[0] == total_burst) {
+ printf("]\n");
+ return;
+ }
+ if (burst_stats[0] + burst_stats[1] == total_burst) {
+ printf(" + %d%% of %d pkts]\n",
+ 100 - burst_percent[0], pktnb_stats[1]);
+ return;
+ }
+ burst_percent[1] = (burst_stats[1] * 100) / total_burst;
+ burst_percent[2] = 100 - (burst_percent[0] + burst_percent[1]);
+ if ((burst_percent[1] == 0) || (burst_percent[2] == 0)) {
+ printf(" + %d%% of others]\n", 100 - burst_percent[0]);
+ return;
+ }
+ printf(" + %d%% of %d pkts + %d%% of others]\n",
+ burst_percent[1], (int) pktnb_stats[1], burst_percent[2]);
+}
+#endif /* RTE_TEST_PMD_RECORD_BURST_STATS */
+
+static void
+fwd_port_stats_display(portid_t port_id, struct rte_eth_stats *stats)
+{
+ struct rte_port *port;
+ uint8_t i;
+
+ static const char *fwd_stats_border = "----------------------";
+
+ port = &ports[port_id];
+ printf("\n %s Forward statistics for port %-2d %s\n",
+ fwd_stats_border, port_id, fwd_stats_border);
+
+ if ((!port->rx_queue_stats_mapping_enabled) && (!port->tx_queue_stats_mapping_enabled)) {
+ printf(" RX-packets: %-14"PRIu64" RX-dropped: %-14"PRIu64"RX-total: "
+ "%-"PRIu64"\n",
+ stats->ipackets, stats->imissed,
+ (uint64_t) (stats->ipackets + stats->imissed));
+
+ if (cur_fwd_eng == &csum_fwd_engine)
+ printf(" Bad-ipcsum: %-14"PRIu64" Bad-l4csum: %-14"PRIu64" \n",
+ port->rx_bad_ip_csum, port->rx_bad_l4_csum);
+ if ((stats->ierrors + stats->rx_nombuf) > 0) {
+ printf(" RX-error: %-"PRIu64"\n", stats->ierrors);
+ printf(" RX-nombufs: %-14"PRIu64"\n", stats->rx_nombuf);
+ }
+
+ printf(" TX-packets: %-14"PRIu64" TX-dropped: %-14"PRIu64"TX-total: "
+ "%-"PRIu64"\n",
+ stats->opackets, port->tx_dropped,
+ (uint64_t) (stats->opackets + port->tx_dropped));
+ }
+ else {
+ printf(" RX-packets: %14"PRIu64" RX-dropped:%14"PRIu64" RX-total:"
+ "%14"PRIu64"\n",
+ stats->ipackets, stats->imissed,
+ (uint64_t) (stats->ipackets + stats->imissed));
+
+ if (cur_fwd_eng == &csum_fwd_engine)
+ printf(" Bad-ipcsum:%14"PRIu64" Bad-l4csum:%14"PRIu64"\n",
+ port->rx_bad_ip_csum, port->rx_bad_l4_csum);
+ if ((stats->ierrors + stats->rx_nombuf) > 0) {
+ printf(" RX-error:%"PRIu64"\n", stats->ierrors);
+ printf(" RX-nombufs: %14"PRIu64"\n",
+ stats->rx_nombuf);
+ }
+
+ printf(" TX-packets: %14"PRIu64" TX-dropped:%14"PRIu64" TX-total:"
+ "%14"PRIu64"\n",
+ stats->opackets, port->tx_dropped,
+ (uint64_t) (stats->opackets + port->tx_dropped));
+ }
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ if (port->rx_stream)
+ pkt_burst_stats_display("RX",
+ &port->rx_stream->rx_burst_stats);
+ if (port->tx_stream)
+ pkt_burst_stats_display("TX",
+ &port->tx_stream->tx_burst_stats);
+#endif
+
+ if (port->rx_queue_stats_mapping_enabled) {
+ printf("\n");
+ for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) {
+ printf(" Stats reg %2d RX-packets:%14"PRIu64
+ " RX-errors:%14"PRIu64
+ " RX-bytes:%14"PRIu64"\n",
+ i, stats->q_ipackets[i], stats->q_errors[i], stats->q_ibytes[i]);
+ }
+ printf("\n");
+ }
+ if (port->tx_queue_stats_mapping_enabled) {
+ for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) {
+ printf(" Stats reg %2d TX-packets:%14"PRIu64
+ " TX-bytes:%14"PRIu64"\n",
+ i, stats->q_opackets[i], stats->q_obytes[i]);
+ }
+ }
+
+ printf(" %s--------------------------------%s\n",
+ fwd_stats_border, fwd_stats_border);
+}
+
+static void
+fwd_stream_stats_display(streamid_t stream_id)
+{
+ struct fwd_stream *fs;
+ static const char *fwd_top_stats_border = "-------";
+
+ fs = fwd_streams[stream_id];
+ if ((fs->rx_packets == 0) && (fs->tx_packets == 0) &&
+ (fs->fwd_dropped == 0))
+ return;
+ printf("\n %s Forward Stats for RX Port=%2d/Queue=%2d -> "
+ "TX Port=%2d/Queue=%2d %s\n",
+ fwd_top_stats_border, fs->rx_port, fs->rx_queue,
+ fs->tx_port, fs->tx_queue, fwd_top_stats_border);
+ printf(" RX-packets: %-14u TX-packets: %-14u TX-dropped: %-14u",
+ fs->rx_packets, fs->tx_packets, fs->fwd_dropped);
+
+ /* if checksum mode */
+ if (cur_fwd_eng == &csum_fwd_engine) {
+ printf(" RX- bad IP checksum: %-14u Rx- bad L4 checksum: "
+ "%-14u\n", fs->rx_bad_ip_csum, fs->rx_bad_l4_csum);
+ }
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ pkt_burst_stats_display("RX", &fs->rx_burst_stats);
+ pkt_burst_stats_display("TX", &fs->tx_burst_stats);
+#endif
+}
+
+static void
+flush_fwd_rx_queues(void)
+{
+ struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+ portid_t rxp;
+ portid_t port_id;
+ queueid_t rxq;
+ uint16_t nb_rx;
+ uint16_t i;
+ uint8_t j;
+ uint64_t prev_tsc = 0, diff_tsc, cur_tsc, timer_tsc = 0;
+ uint64_t timer_period;
+
+ /* convert to number of cycles */
+ timer_period = rte_get_timer_hz(); /* 1 second timeout */
+
+ for (j = 0; j < 2; j++) {
+ for (rxp = 0; rxp < cur_fwd_config.nb_fwd_ports; rxp++) {
+ for (rxq = 0; rxq < nb_rxq; rxq++) {
+ port_id = fwd_ports_ids[rxp];
+ /**
+ * testpmd can stuck in the below do while loop
+ * if rte_eth_rx_burst() always returns nonzero
+ * packets. So timer is added to exit this loop
+ * after 1sec timer expiry.
+ */
+ prev_tsc = rte_rdtsc();
+ do {
+ nb_rx = rte_eth_rx_burst(port_id, rxq,
+ pkts_burst, MAX_PKT_BURST);
+ for (i = 0; i < nb_rx; i++)
+ rte_pktmbuf_free(pkts_burst[i]);
+
+ cur_tsc = rte_rdtsc();
+ diff_tsc = cur_tsc - prev_tsc;
+ timer_tsc += diff_tsc;
+ } while ((nb_rx > 0) &&
+ (timer_tsc < timer_period));
+ timer_tsc = 0;
+ }
+ }
+ rte_delay_ms(10); /* wait 10 milli-seconds before retrying */
+ }
+}
+
+static void
+run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd)
+{
+ struct fwd_stream **fsm;
+ streamid_t nb_fs;
+ streamid_t sm_id;
+#ifdef RTE_LIBRTE_BITRATE
+ uint64_t tics_per_1sec;
+ uint64_t tics_datum;
+ uint64_t tics_current;
+ uint8_t idx_port, cnt_ports;
+
+ cnt_ports = rte_eth_dev_count();
+ tics_datum = rte_rdtsc();
+ tics_per_1sec = rte_get_timer_hz();
+#endif
+ fsm = &fwd_streams[fc->stream_idx];
+ nb_fs = fc->stream_nb;
+ do {
+ for (sm_id = 0; sm_id < nb_fs; sm_id++)
+ (*pkt_fwd)(fsm[sm_id]);
+#ifdef RTE_LIBRTE_BITRATE
+ if (bitrate_enabled != 0 &&
+ bitrate_lcore_id == rte_lcore_id()) {
+ tics_current = rte_rdtsc();
+ if (tics_current - tics_datum >= tics_per_1sec) {
+ /* Periodic bitrate calculation */
+ for (idx_port = 0;
+ idx_port < cnt_ports;
+ idx_port++)
+ rte_stats_bitrate_calc(bitrate_data,
+ idx_port);
+ tics_datum = tics_current;
+ }
+ }
+#endif
+#ifdef RTE_LIBRTE_LATENCY_STATS
+ if (latencystats_enabled != 0 &&
+ latencystats_lcore_id == rte_lcore_id())
+ rte_latencystats_update();
+#endif
+
+ } while (! fc->stopped);
+}
+
+static int
+start_pkt_forward_on_core(void *fwd_arg)
+{
+ run_pkt_fwd_on_lcore((struct fwd_lcore *) fwd_arg,
+ cur_fwd_config.fwd_eng->packet_fwd);
+ return 0;
+}
+
+/*
+ * Run the TXONLY packet forwarding engine to send a single burst of packets.
+ * Used to start communication flows in network loopback test configurations.
+ */
+static int
+run_one_txonly_burst_on_core(void *fwd_arg)
+{
+ struct fwd_lcore *fwd_lc;
+ struct fwd_lcore tmp_lcore;
+
+ fwd_lc = (struct fwd_lcore *) fwd_arg;
+ tmp_lcore = *fwd_lc;
+ tmp_lcore.stopped = 1;
+ run_pkt_fwd_on_lcore(&tmp_lcore, tx_only_engine.packet_fwd);
+ return 0;
+}
+
+/*
+ * Launch packet forwarding:
+ * - Setup per-port forwarding context.
+ * - launch logical cores with their forwarding configuration.
+ */
+static void
+launch_packet_forwarding(lcore_function_t *pkt_fwd_on_lcore)
+{
+ port_fwd_begin_t port_fwd_begin;
+ unsigned int i;
+ unsigned int lc_id;
+ int diag;
+
+ port_fwd_begin = cur_fwd_config.fwd_eng->port_fwd_begin;
+ if (port_fwd_begin != NULL) {
+ for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++)
+ (*port_fwd_begin)(fwd_ports_ids[i]);
+ }
+ for (i = 0; i < cur_fwd_config.nb_fwd_lcores; i++) {
+ lc_id = fwd_lcores_cpuids[i];
+ if ((interactive == 0) || (lc_id != rte_lcore_id())) {
+ fwd_lcores[i]->stopped = 0;
+ diag = rte_eal_remote_launch(pkt_fwd_on_lcore,
+ fwd_lcores[i], lc_id);
+ if (diag != 0)
+ printf("launch lcore %u failed - diag=%d\n",
+ lc_id, diag);
+ }
+ }
+}
+
+/*
+ * Launch packet forwarding configuration.
+ */
+void
+start_packet_forwarding(int with_tx_first)
+{
+ port_fwd_begin_t port_fwd_begin;
+ port_fwd_end_t port_fwd_end;
+ struct rte_port *port;
+ unsigned int i;
+ portid_t pt_id;
+ streamid_t sm_id;
+
+ if (strcmp(cur_fwd_eng->fwd_mode_name, "rxonly") == 0 && !nb_rxq)
+ rte_exit(EXIT_FAILURE, "rxq are 0, cannot use rxonly fwd mode\n");
+
+ if (strcmp(cur_fwd_eng->fwd_mode_name, "txonly") == 0 && !nb_txq)
+ rte_exit(EXIT_FAILURE, "txq are 0, cannot use txonly fwd mode\n");
+
+ if ((strcmp(cur_fwd_eng->fwd_mode_name, "rxonly") != 0 &&
+ strcmp(cur_fwd_eng->fwd_mode_name, "txonly") != 0) &&
+ (!nb_rxq || !nb_txq))
+ rte_exit(EXIT_FAILURE,
+ "Either rxq or txq are 0, cannot use %s fwd mode\n",
+ cur_fwd_eng->fwd_mode_name);
+
+ if (all_ports_started() == 0) {
+ printf("Not all ports were started\n");
+ return;
+ }
+ if (test_done == 0) {
+ printf("Packet forwarding already started\n");
+ return;
+ }
+
+ if (init_fwd_streams() < 0) {
+ printf("Fail from init_fwd_streams()\n");
+ return;
+ }
+
+ if(dcb_test) {
+ for (i = 0; i < nb_fwd_ports; i++) {
+ pt_id = fwd_ports_ids[i];
+ port = &ports[pt_id];
+ if (!port->dcb_flag) {
+ printf("In DCB mode, all forwarding ports must "
+ "be configured in this mode.\n");
+ return;
+ }
+ }
+ if (nb_fwd_lcores == 1) {
+ printf("In DCB mode,the nb forwarding cores "
+ "should be larger than 1.\n");
+ return;
+ }
+ }
+ test_done = 0;
+
+ if(!no_flush_rx)
+ flush_fwd_rx_queues();
+
+ fwd_config_setup();
+ pkt_fwd_config_display(&cur_fwd_config);
+ rxtx_config_display();
+
+ for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) {
+ pt_id = fwd_ports_ids[i];
+ port = &ports[pt_id];
+ rte_eth_stats_get(pt_id, &port->stats);
+ port->tx_dropped = 0;
+
+ map_port_queue_stats_mapping_registers(pt_id, port);
+ }
+ for (sm_id = 0; sm_id < cur_fwd_config.nb_fwd_streams; sm_id++) {
+ fwd_streams[sm_id]->rx_packets = 0;
+ fwd_streams[sm_id]->tx_packets = 0;
+ fwd_streams[sm_id]->fwd_dropped = 0;
+ fwd_streams[sm_id]->rx_bad_ip_csum = 0;
+ fwd_streams[sm_id]->rx_bad_l4_csum = 0;
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ memset(&fwd_streams[sm_id]->rx_burst_stats, 0,
+ sizeof(fwd_streams[sm_id]->rx_burst_stats));
+ memset(&fwd_streams[sm_id]->tx_burst_stats, 0,
+ sizeof(fwd_streams[sm_id]->tx_burst_stats));
+#endif
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ fwd_streams[sm_id]->core_cycles = 0;
+#endif
+ }
+ if (with_tx_first) {
+ port_fwd_begin = tx_only_engine.port_fwd_begin;
+ if (port_fwd_begin != NULL) {
+ for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++)
+ (*port_fwd_begin)(fwd_ports_ids[i]);
+ }
+ while (with_tx_first--) {
+ launch_packet_forwarding(
+ run_one_txonly_burst_on_core);
+ rte_eal_mp_wait_lcore();
+ }
+ port_fwd_end = tx_only_engine.port_fwd_end;
+ if (port_fwd_end != NULL) {
+ for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++)
+ (*port_fwd_end)(fwd_ports_ids[i]);
+ }
+ }
+ launch_packet_forwarding(start_pkt_forward_on_core);
+}
+
+void
+stop_packet_forwarding(void)
+{
+ struct rte_eth_stats stats;
+ struct rte_port *port;
+ port_fwd_end_t port_fwd_end;
+ int i;
+ portid_t pt_id;
+ streamid_t sm_id;
+ lcoreid_t lc_id;
+ uint64_t total_recv;
+ uint64_t total_xmit;
+ uint64_t total_rx_dropped;
+ uint64_t total_tx_dropped;
+ uint64_t total_rx_nombuf;
+ uint64_t tx_dropped;
+ uint64_t rx_bad_ip_csum;
+ uint64_t rx_bad_l4_csum;
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ uint64_t fwd_cycles;
+#endif
+ static const char *acc_stats_border = "+++++++++++++++";
+
+ if (test_done) {
+ printf("Packet forwarding not started\n");
+ return;
+ }
+ printf("Telling cores to stop...");
+ for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++)
+ fwd_lcores[lc_id]->stopped = 1;
+ printf("\nWaiting for lcores to finish...\n");
+ rte_eal_mp_wait_lcore();
+ port_fwd_end = cur_fwd_config.fwd_eng->port_fwd_end;
+ if (port_fwd_end != NULL) {
+ for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) {
+ pt_id = fwd_ports_ids[i];
+ (*port_fwd_end)(pt_id);
+ }
+ }
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ fwd_cycles = 0;
+#endif
+ for (sm_id = 0; sm_id < cur_fwd_config.nb_fwd_streams; sm_id++) {
+ if (cur_fwd_config.nb_fwd_streams >
+ cur_fwd_config.nb_fwd_ports) {
+ fwd_stream_stats_display(sm_id);
+ ports[fwd_streams[sm_id]->tx_port].tx_stream = NULL;
+ ports[fwd_streams[sm_id]->rx_port].rx_stream = NULL;
+ } else {
+ ports[fwd_streams[sm_id]->tx_port].tx_stream =
+ fwd_streams[sm_id];
+ ports[fwd_streams[sm_id]->rx_port].rx_stream =
+ fwd_streams[sm_id];
+ }
+ tx_dropped = ports[fwd_streams[sm_id]->tx_port].tx_dropped;
+ tx_dropped = (uint64_t) (tx_dropped +
+ fwd_streams[sm_id]->fwd_dropped);
+ ports[fwd_streams[sm_id]->tx_port].tx_dropped = tx_dropped;
+
+ rx_bad_ip_csum =
+ ports[fwd_streams[sm_id]->rx_port].rx_bad_ip_csum;
+ rx_bad_ip_csum = (uint64_t) (rx_bad_ip_csum +
+ fwd_streams[sm_id]->rx_bad_ip_csum);
+ ports[fwd_streams[sm_id]->rx_port].rx_bad_ip_csum =
+ rx_bad_ip_csum;
+
+ rx_bad_l4_csum =
+ ports[fwd_streams[sm_id]->rx_port].rx_bad_l4_csum;
+ rx_bad_l4_csum = (uint64_t) (rx_bad_l4_csum +
+ fwd_streams[sm_id]->rx_bad_l4_csum);
+ ports[fwd_streams[sm_id]->rx_port].rx_bad_l4_csum =
+ rx_bad_l4_csum;
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ fwd_cycles = (uint64_t) (fwd_cycles +
+ fwd_streams[sm_id]->core_cycles);
+#endif
+ }
+ total_recv = 0;
+ total_xmit = 0;
+ total_rx_dropped = 0;
+ total_tx_dropped = 0;
+ total_rx_nombuf = 0;
+ for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) {
+ pt_id = fwd_ports_ids[i];
+
+ port = &ports[pt_id];
+ rte_eth_stats_get(pt_id, &stats);
+ stats.ipackets -= port->stats.ipackets;
+ port->stats.ipackets = 0;
+ stats.opackets -= port->stats.opackets;
+ port->stats.opackets = 0;
+ stats.ibytes -= port->stats.ibytes;
+ port->stats.ibytes = 0;
+ stats.obytes -= port->stats.obytes;
+ port->stats.obytes = 0;
+ stats.imissed -= port->stats.imissed;
+ port->stats.imissed = 0;
+ stats.oerrors -= port->stats.oerrors;
+ port->stats.oerrors = 0;
+ stats.rx_nombuf -= port->stats.rx_nombuf;
+ port->stats.rx_nombuf = 0;
+
+ total_recv += stats.ipackets;
+ total_xmit += stats.opackets;
+ total_rx_dropped += stats.imissed;
+ total_tx_dropped += port->tx_dropped;
+ total_rx_nombuf += stats.rx_nombuf;
+
+ fwd_port_stats_display(pt_id, &stats);
+ }
+ printf("\n %s Accumulated forward statistics for all ports"
+ "%s\n",
+ acc_stats_border, acc_stats_border);
+ printf(" RX-packets: %-14"PRIu64" RX-dropped: %-14"PRIu64"RX-total: "
+ "%-"PRIu64"\n"
+ " TX-packets: %-14"PRIu64" TX-dropped: %-14"PRIu64"TX-total: "
+ "%-"PRIu64"\n",
+ total_recv, total_rx_dropped, total_recv + total_rx_dropped,
+ total_xmit, total_tx_dropped, total_xmit + total_tx_dropped);
+ if (total_rx_nombuf > 0)
+ printf(" RX-nombufs: %-14"PRIu64"\n", total_rx_nombuf);
+ printf(" %s++++++++++++++++++++++++++++++++++++++++++++++"
+ "%s\n",
+ acc_stats_border, acc_stats_border);
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ if (total_recv > 0)
+ printf("\n CPU cycles/packet=%u (total cycles="
+ "%"PRIu64" / total RX packets=%"PRIu64")\n",
+ (unsigned int)(fwd_cycles / total_recv),
+ fwd_cycles, total_recv);
+#endif
+ printf("\nDone.\n");
+ test_done = 1;
+}
+
+void
+dev_set_link_up(portid_t pid)
+{
+ if (rte_eth_dev_set_link_up((uint8_t)pid) < 0)
+ printf("\nSet link up fail.\n");
+}
+
+void
+dev_set_link_down(portid_t pid)
+{
+ if (rte_eth_dev_set_link_down((uint8_t)pid) < 0)
+ printf("\nSet link down fail.\n");
+}
+
+static int
+all_ports_started(void)
+{
+ portid_t pi;
+ struct rte_port *port;
+
+ RTE_ETH_FOREACH_DEV(pi) {
+ port = &ports[pi];
+ /* Check if there is a port which is not started */
+ if ((port->port_status != RTE_PORT_STARTED) &&
+ (port->slave_flag == 0))
+ return 0;
+ }
+
+ /* No port is not started */
+ return 1;
+}
+
+int
+all_ports_stopped(void)
+{
+ portid_t pi;
+ struct rte_port *port;
+
+ RTE_ETH_FOREACH_DEV(pi) {
+ port = &ports[pi];
+ if ((port->port_status != RTE_PORT_STOPPED) &&
+ (port->slave_flag == 0))
+ return 0;
+ }
+
+ return 1;
+}
+
+int
+port_is_started(portid_t port_id)
+{
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return 0;
+
+ if (ports[port_id].port_status != RTE_PORT_STARTED)
+ return 0;
+
+ return 1;
+}
+
+static int
+port_is_closed(portid_t port_id)
+{
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return 0;
+
+ if (ports[port_id].port_status != RTE_PORT_CLOSED)
+ return 0;
+
+ return 1;
+}
+
+int
+start_port(portid_t pid)
+{
+ int diag, need_check_link_status = -1;
+ portid_t pi;
+ queueid_t qi;
+ struct rte_port *port;
+ struct ether_addr mac_addr;
+ enum rte_eth_event_type event_type;
+
+ if (port_id_is_invalid(pid, ENABLED_WARN))
+ return 0;
+
+ if(dcb_config)
+ dcb_test = 1;
+ RTE_ETH_FOREACH_DEV(pi) {
+ if (pid != pi && pid != (portid_t)RTE_PORT_ALL)
+ continue;
+
+ need_check_link_status = 0;
+ port = &ports[pi];
+ if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_STOPPED,
+ RTE_PORT_HANDLING) == 0) {
+ printf("Port %d is now not stopped\n", pi);
+ continue;
+ }
+
+ if (port->need_reconfig > 0) {
+ port->need_reconfig = 0;
+
+ printf("Configuring Port %d (socket %u)\n", pi,
+ port->socket_id);
+ /* configure port */
+ diag = rte_eth_dev_configure(pi, nb_rxq, nb_txq,
+ &(port->dev_conf));
+ if (diag != 0) {
+ if (rte_atomic16_cmpset(&(port->port_status),
+ RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0)
+ printf("Port %d can not be set back "
+ "to stopped\n", pi);
+ printf("Fail to configure port %d\n", pi);
+ /* try to reconfigure port next time */
+ port->need_reconfig = 1;
+ return -1;
+ }
+ }
+ if (port->need_reconfig_queues > 0) {
+ port->need_reconfig_queues = 0;
+ /* setup tx queues */
+ for (qi = 0; qi < nb_txq; qi++) {
+ if ((numa_support) &&
+ (txring_numa[pi] != NUMA_NO_CONFIG))
+ diag = rte_eth_tx_queue_setup(pi, qi,
+ nb_txd,txring_numa[pi],
+ &(port->tx_conf));
+ else
+ diag = rte_eth_tx_queue_setup(pi, qi,
+ nb_txd,port->socket_id,
+ &(port->tx_conf));
+
+ if (diag == 0)
+ continue;
+
+ /* Fail to setup tx queue, return */
+ if (rte_atomic16_cmpset(&(port->port_status),
+ RTE_PORT_HANDLING,
+ RTE_PORT_STOPPED) == 0)
+ printf("Port %d can not be set back "
+ "to stopped\n", pi);
+ printf("Fail to configure port %d tx queues\n", pi);
+ /* try to reconfigure queues next time */
+ port->need_reconfig_queues = 1;
+ return -1;
+ }
+ /* setup rx queues */
+ for (qi = 0; qi < nb_rxq; qi++) {
+ if ((numa_support) &&
+ (rxring_numa[pi] != NUMA_NO_CONFIG)) {
+ struct rte_mempool * mp =
+ mbuf_pool_find(rxring_numa[pi]);
+ if (mp == NULL) {
+ printf("Failed to setup RX queue:"
+ "No mempool allocation"
+ " on the socket %d\n",
+ rxring_numa[pi]);
+ return -1;
+ }
+
+ diag = rte_eth_rx_queue_setup(pi, qi,
+ nb_rxd,rxring_numa[pi],
+ &(port->rx_conf),mp);
+ } else {
+ struct rte_mempool *mp =
+ mbuf_pool_find(port->socket_id);
+ if (mp == NULL) {
+ printf("Failed to setup RX queue:"
+ "No mempool allocation"
+ " on the socket %d\n",
+ port->socket_id);
+ return -1;
+ }
+ diag = rte_eth_rx_queue_setup(pi, qi,
+ nb_rxd,port->socket_id,
+ &(port->rx_conf), mp);
+ }
+ if (diag == 0)
+ continue;
+
+ /* Fail to setup rx queue, return */
+ if (rte_atomic16_cmpset(&(port->port_status),
+ RTE_PORT_HANDLING,
+ RTE_PORT_STOPPED) == 0)
+ printf("Port %d can not be set back "
+ "to stopped\n", pi);
+ printf("Fail to configure port %d rx queues\n", pi);
+ /* try to reconfigure queues next time */
+ port->need_reconfig_queues = 1;
+ return -1;
+ }
+ }
+
+ for (event_type = RTE_ETH_EVENT_UNKNOWN;
+ event_type < RTE_ETH_EVENT_MAX;
+ event_type++) {
+ diag = rte_eth_dev_callback_register(pi,
+ event_type,
+ eth_event_callback,
+ NULL);
+ if (diag) {
+ printf("Failed to setup even callback for event %d\n",
+ event_type);
+ return -1;
+ }
+ }
+
+ /* start port */
+ if (rte_eth_dev_start(pi) < 0) {
+ printf("Fail to start port %d\n", pi);
+
+ /* Fail to setup rx queue, return */
+ if (rte_atomic16_cmpset(&(port->port_status),
+ RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0)
+ printf("Port %d can not be set back to "
+ "stopped\n", pi);
+ continue;
+ }
+
+ if (rte_atomic16_cmpset(&(port->port_status),
+ RTE_PORT_HANDLING, RTE_PORT_STARTED) == 0)
+ printf("Port %d can not be set into started\n", pi);
+
+ rte_eth_macaddr_get(pi, &mac_addr);
+ printf("Port %d: %02X:%02X:%02X:%02X:%02X:%02X\n", pi,
+ mac_addr.addr_bytes[0], mac_addr.addr_bytes[1],
+ mac_addr.addr_bytes[2], mac_addr.addr_bytes[3],
+ mac_addr.addr_bytes[4], mac_addr.addr_bytes[5]);
+
+ /* at least one port started, need checking link status */
+ need_check_link_status = 1;
+ }
+
+ if (need_check_link_status == 1 && !no_link_check)
+ check_all_ports_link_status(RTE_PORT_ALL);
+ else if (need_check_link_status == 0)
+ printf("Please stop the ports first\n");
+
+ printf("Done\n");
+ return 0;
+}
+
+void
+stop_port(portid_t pid)
+{
+ portid_t pi;
+ struct rte_port *port;
+ int need_check_link_status = 0;
+
+ if (dcb_test) {
+ dcb_test = 0;
+ dcb_config = 0;
+ }
+
+ if (port_id_is_invalid(pid, ENABLED_WARN))
+ return;
+
+ printf("Stopping ports...\n");
+
+ RTE_ETH_FOREACH_DEV(pi) {
+ if (pid != pi && pid != (portid_t)RTE_PORT_ALL)
+ continue;
+
+ if (port_is_forwarding(pi) != 0 && test_done == 0) {
+ printf("Please remove port %d from forwarding configuration.\n", pi);
+ continue;
+ }
+
+ if (port_is_bonding_slave(pi)) {
+ printf("Please remove port %d from bonded device.\n", pi);
+ continue;
+ }
+
+ port = &ports[pi];
+ if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_STARTED,
+ RTE_PORT_HANDLING) == 0)
+ continue;
+
+ rte_eth_dev_stop(pi);
+
+ if (rte_atomic16_cmpset(&(port->port_status),
+ RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0)
+ printf("Port %d can not be set into stopped\n", pi);
+ need_check_link_status = 1;
+ }
+ if (need_check_link_status && !no_link_check)
+ check_all_ports_link_status(RTE_PORT_ALL);
+
+ printf("Done\n");
+}
+
+void
+close_port(portid_t pid)
+{
+ portid_t pi;
+ struct rte_port *port;
+
+ if (port_id_is_invalid(pid, ENABLED_WARN))
+ return;
+
+ printf("Closing ports...\n");
+
+ RTE_ETH_FOREACH_DEV(pi) {
+ if (pid != pi && pid != (portid_t)RTE_PORT_ALL)
+ continue;
+
+ if (port_is_forwarding(pi) != 0 && test_done == 0) {
+ printf("Please remove port %d from forwarding configuration.\n", pi);
+ continue;
+ }
+
+ if (port_is_bonding_slave(pi)) {
+ printf("Please remove port %d from bonded device.\n", pi);
+ continue;
+ }
+
+ port = &ports[pi];
+ if (rte_atomic16_cmpset(&(port->port_status),
+ RTE_PORT_CLOSED, RTE_PORT_CLOSED) == 1) {
+ printf("Port %d is already closed\n", pi);
+ continue;
+ }
+
+ if (rte_atomic16_cmpset(&(port->port_status),
+ RTE_PORT_STOPPED, RTE_PORT_HANDLING) == 0) {
+ printf("Port %d is now not stopped\n", pi);
+ continue;
+ }
+
+ if (port->flow_list)
+ port_flow_flush(pi);
+ rte_eth_dev_close(pi);
+
+ if (rte_atomic16_cmpset(&(port->port_status),
+ RTE_PORT_HANDLING, RTE_PORT_CLOSED) == 0)
+ printf("Port %d cannot be set to closed\n", pi);
+ }
+
+ printf("Done\n");
+}
+
+void
+attach_port(char *identifier)
+{
+ portid_t pi = 0;
+ unsigned int socket_id;
+
+ printf("Attaching a new port...\n");
+
+ if (identifier == NULL) {
+ printf("Invalid parameters are specified\n");
+ return;
+ }
+
+ if (rte_eth_dev_attach(identifier, &pi))
+ return;
+
+ socket_id = (unsigned)rte_eth_dev_socket_id(pi);
+ /* if socket_id is invalid, set to 0 */
+ if (check_socket_id(socket_id) < 0)
+ socket_id = 0;
+ reconfig(pi, socket_id);
+ rte_eth_promiscuous_enable(pi);
+
+ nb_ports = rte_eth_dev_count();
+
+ ports[pi].port_status = RTE_PORT_STOPPED;
+
+ printf("Port %d is attached. Now total ports is %d\n", pi, nb_ports);
+ printf("Done\n");
+}
+
+void
+detach_port(uint8_t port_id)
+{
+ char name[RTE_ETH_NAME_MAX_LEN];
+
+ printf("Detaching a port...\n");
+
+ if (!port_is_closed(port_id)) {
+ printf("Please close port first\n");
+ return;
+ }
+
+ if (ports[port_id].flow_list)
+ port_flow_flush(port_id);
+
+ if (rte_eth_dev_detach(port_id, name))
+ return;
+
+ nb_ports = rte_eth_dev_count();
+
+ printf("Port '%s' is detached. Now total ports is %d\n",
+ name, nb_ports);
+ printf("Done\n");
+ return;
+}
+
+void
+pmd_test_exit(void)
+{
+ portid_t pt_id;
+
+ if (test_done == 0)
+ stop_packet_forwarding();
+
+ if (ports != NULL) {
+ no_link_check = 1;
+ RTE_ETH_FOREACH_DEV(pt_id) {
+ printf("\nShutting down port %d...\n", pt_id);
+ fflush(stdout);
+ stop_port(pt_id);
+ close_port(pt_id);
+ }
+ }
+ printf("\nBye...\n");
+}
+
+typedef void (*cmd_func_t)(void);
+struct pmd_test_command {
+ const char *cmd_name;
+ cmd_func_t cmd_func;
+};
+
+#define PMD_TEST_CMD_NB (sizeof(pmd_test_menu) / sizeof(pmd_test_menu[0]))
+
+/* Check the link status of all ports in up to 9s, and print them finally */
+static void
+check_all_ports_link_status(uint32_t port_mask)
+{
+#define CHECK_INTERVAL 100 /* 100ms */
+#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
+ uint8_t portid, count, all_ports_up, print_flag = 0;
+ struct rte_eth_link link;
+
+ printf("Checking link statuses...\n");
+ fflush(stdout);
+ for (count = 0; count <= MAX_CHECK_TIME; count++) {
+ all_ports_up = 1;
+ RTE_ETH_FOREACH_DEV(portid) {
+ if ((port_mask & (1 << portid)) == 0)
+ continue;
+ memset(&link, 0, sizeof(link));
+ rte_eth_link_get_nowait(portid, &link);
+ /* print link status if flag set */
+ if (print_flag == 1) {
+ if (link.link_status)
+ printf("Port %d Link Up - speed %u "
+ "Mbps - %s\n", (uint8_t)portid,
+ (unsigned)link.link_speed,
+ (link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
+ ("full-duplex") : ("half-duplex\n"));
+ else
+ printf("Port %d Link Down\n",
+ (uint8_t)portid);
+ continue;
+ }
+ /* clear all_ports_up flag if any link down */
+ if (link.link_status == ETH_LINK_DOWN) {
+ all_ports_up = 0;
+ break;
+ }
+ }
+ /* after finally printing all link status, get out */
+ if (print_flag == 1)
+ break;
+
+ if (all_ports_up == 0) {
+ fflush(stdout);
+ rte_delay_ms(CHECK_INTERVAL);
+ }
+
+ /* set the print_flag if all ports up or timeout */
+ if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
+ print_flag = 1;
+ }
+
+ if (lsc_interrupt)
+ break;
+ }
+}
+
+static void
+rmv_event_callback(void *arg)
+{
+ struct rte_eth_dev *dev;
+ struct rte_devargs *da;
+ char name[32] = "";
+ uint8_t port_id = (intptr_t)arg;
+
+ RTE_ETH_VALID_PORTID_OR_RET(port_id);
+ dev = &rte_eth_devices[port_id];
+ da = dev->device->devargs;
+
+ stop_port(port_id);
+ close_port(port_id);
+ if (da->type == RTE_DEVTYPE_VIRTUAL)
+ snprintf(name, sizeof(name), "%s", da->virt.drv_name);
+ else if (da->type == RTE_DEVTYPE_WHITELISTED_PCI)
+ rte_pci_device_name(&da->pci.addr, name, sizeof(name));
+ printf("removing device %s\n", name);
+ rte_eal_dev_detach(name);
+ dev->state = RTE_ETH_DEV_UNUSED;
+}
+
+/* This function is used by the interrupt thread */
+static void
+eth_event_callback(uint8_t port_id, enum rte_eth_event_type type, void *param)
+{
+ static const char * const event_desc[] = {
+ [RTE_ETH_EVENT_UNKNOWN] = "Unknown",
+ [RTE_ETH_EVENT_INTR_LSC] = "LSC",
+ [RTE_ETH_EVENT_QUEUE_STATE] = "Queue state",
+ [RTE_ETH_EVENT_INTR_RESET] = "Interrupt reset",
+ [RTE_ETH_EVENT_VF_MBOX] = "VF Mbox",
+ [RTE_ETH_EVENT_MACSEC] = "MACsec",
+ [RTE_ETH_EVENT_INTR_RMV] = "device removal",
+ [RTE_ETH_EVENT_MAX] = NULL,
+ };
+
+ RTE_SET_USED(param);
+
+ if (type >= RTE_ETH_EVENT_MAX) {
+ fprintf(stderr, "\nPort %" PRIu8 ": %s called upon invalid event %d\n",
+ port_id, __func__, type);
+ fflush(stderr);
+ } else if (event_print_mask & (UINT32_C(1) << type)) {
+ printf("\nPort %" PRIu8 ": %s event\n", port_id,
+ event_desc[type]);
+ fflush(stdout);
+ }
+
+ switch (type) {
+ case RTE_ETH_EVENT_INTR_RMV:
+ if (rte_eal_alarm_set(100000,
+ rmv_event_callback, (void *)(intptr_t)port_id))
+ fprintf(stderr, "Could not set up deferred device removal\n");
+ break;
+ default:
+ break;
+ }
+}
+
+static int
+set_tx_queue_stats_mapping_registers(uint8_t port_id, struct rte_port *port)
+{
+ uint16_t i;
+ int diag;
+ uint8_t mapping_found = 0;
+
+ for (i = 0; i < nb_tx_queue_stats_mappings; i++) {
+ if ((tx_queue_stats_mappings[i].port_id == port_id) &&
+ (tx_queue_stats_mappings[i].queue_id < nb_txq )) {
+ diag = rte_eth_dev_set_tx_queue_stats_mapping(port_id,
+ tx_queue_stats_mappings[i].queue_id,
+ tx_queue_stats_mappings[i].stats_counter_id);
+ if (diag != 0)
+ return diag;
+ mapping_found = 1;
+ }
+ }
+ if (mapping_found)
+ port->tx_queue_stats_mapping_enabled = 1;
+ return 0;
+}
+
+static int
+set_rx_queue_stats_mapping_registers(uint8_t port_id, struct rte_port *port)
+{
+ uint16_t i;
+ int diag;
+ uint8_t mapping_found = 0;
+
+ for (i = 0; i < nb_rx_queue_stats_mappings; i++) {
+ if ((rx_queue_stats_mappings[i].port_id == port_id) &&
+ (rx_queue_stats_mappings[i].queue_id < nb_rxq )) {
+ diag = rte_eth_dev_set_rx_queue_stats_mapping(port_id,
+ rx_queue_stats_mappings[i].queue_id,
+ rx_queue_stats_mappings[i].stats_counter_id);
+ if (diag != 0)
+ return diag;
+ mapping_found = 1;
+ }
+ }
+ if (mapping_found)
+ port->rx_queue_stats_mapping_enabled = 1;
+ return 0;
+}
+
+static void
+map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port)
+{
+ int diag = 0;
+
+ diag = set_tx_queue_stats_mapping_registers(pi, port);
+ if (diag != 0) {
+ if (diag == -ENOTSUP) {
+ port->tx_queue_stats_mapping_enabled = 0;
+ printf("TX queue stats mapping not supported port id=%d\n", pi);
+ }
+ else
+ rte_exit(EXIT_FAILURE,
+ "set_tx_queue_stats_mapping_registers "
+ "failed for port id=%d diag=%d\n",
+ pi, diag);
+ }
+
+ diag = set_rx_queue_stats_mapping_registers(pi, port);
+ if (diag != 0) {
+ if (diag == -ENOTSUP) {
+ port->rx_queue_stats_mapping_enabled = 0;
+ printf("RX queue stats mapping not supported port id=%d\n", pi);
+ }
+ else
+ rte_exit(EXIT_FAILURE,
+ "set_rx_queue_stats_mapping_registers "
+ "failed for port id=%d diag=%d\n",
+ pi, diag);
+ }
+}
+
+static void
+rxtx_port_config(struct rte_port *port)
+{
+ port->rx_conf = port->dev_info.default_rxconf;
+ port->tx_conf = port->dev_info.default_txconf;
+
+ /* Check if any RX/TX parameters have been passed */
+ if (rx_pthresh != RTE_PMD_PARAM_UNSET)
+ port->rx_conf.rx_thresh.pthresh = rx_pthresh;
+
+ if (rx_hthresh != RTE_PMD_PARAM_UNSET)
+ port->rx_conf.rx_thresh.hthresh = rx_hthresh;
+
+ if (rx_wthresh != RTE_PMD_PARAM_UNSET)
+ port->rx_conf.rx_thresh.wthresh = rx_wthresh;
+
+ if (rx_free_thresh != RTE_PMD_PARAM_UNSET)
+ port->rx_conf.rx_free_thresh = rx_free_thresh;
+
+ if (rx_drop_en != RTE_PMD_PARAM_UNSET)
+ port->rx_conf.rx_drop_en = rx_drop_en;
+
+ if (tx_pthresh != RTE_PMD_PARAM_UNSET)
+ port->tx_conf.tx_thresh.pthresh = tx_pthresh;
+
+ if (tx_hthresh != RTE_PMD_PARAM_UNSET)
+ port->tx_conf.tx_thresh.hthresh = tx_hthresh;
+
+ if (tx_wthresh != RTE_PMD_PARAM_UNSET)
+ port->tx_conf.tx_thresh.wthresh = tx_wthresh;
+
+ if (tx_rs_thresh != RTE_PMD_PARAM_UNSET)
+ port->tx_conf.tx_rs_thresh = tx_rs_thresh;
+
+ if (tx_free_thresh != RTE_PMD_PARAM_UNSET)
+ port->tx_conf.tx_free_thresh = tx_free_thresh;
+
+ if (txq_flags != RTE_PMD_PARAM_UNSET)
+ port->tx_conf.txq_flags = txq_flags;
+}
+
+void
+init_port_config(void)
+{
+ portid_t pid;
+ struct rte_port *port;
+
+ RTE_ETH_FOREACH_DEV(pid) {
+ port = &ports[pid];
+ port->dev_conf.rxmode = rx_mode;
+ port->dev_conf.fdir_conf = fdir_conf;
+ if (nb_rxq > 1) {
+ port->dev_conf.rx_adv_conf.rss_conf.rss_key = NULL;
+ port->dev_conf.rx_adv_conf.rss_conf.rss_hf = rss_hf;
+ } else {
+ port->dev_conf.rx_adv_conf.rss_conf.rss_key = NULL;
+ port->dev_conf.rx_adv_conf.rss_conf.rss_hf = 0;
+ }
+
+ if (port->dcb_flag == 0) {
+ if( port->dev_conf.rx_adv_conf.rss_conf.rss_hf != 0)
+ port->dev_conf.rxmode.mq_mode = ETH_MQ_RX_RSS;
+ else
+ port->dev_conf.rxmode.mq_mode = ETH_MQ_RX_NONE;
+ }
+
+ rxtx_port_config(port);
+
+ rte_eth_macaddr_get(pid, &port->eth_addr);
+
+ map_port_queue_stats_mapping_registers(pid, port);
+#ifdef RTE_NIC_BYPASS
+ rte_eth_dev_bypass_init(pid);
+#endif
+
+ if (lsc_interrupt &&
+ (rte_eth_devices[pid].data->dev_flags &
+ RTE_ETH_DEV_INTR_LSC))
+ port->dev_conf.intr_conf.lsc = 1;
+ if (rmv_interrupt &&
+ (rte_eth_devices[pid].data->dev_flags &
+ RTE_ETH_DEV_INTR_RMV))
+ port->dev_conf.intr_conf.rmv = 1;
+ }
+}
+
+void set_port_slave_flag(portid_t slave_pid)
+{
+ struct rte_port *port;
+
+ port = &ports[slave_pid];
+ port->slave_flag = 1;
+}
+
+void clear_port_slave_flag(portid_t slave_pid)
+{
+ struct rte_port *port;
+
+ port = &ports[slave_pid];
+ port->slave_flag = 0;
+}
+
+uint8_t port_is_bonding_slave(portid_t slave_pid)
+{
+ struct rte_port *port;
+
+ port = &ports[slave_pid];
+ return port->slave_flag;
+}
+
+const uint16_t vlan_tags[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31
+};
+
+static int
+get_eth_dcb_conf(struct rte_eth_conf *eth_conf,
+ enum dcb_mode_enable dcb_mode,
+ enum rte_eth_nb_tcs num_tcs,
+ uint8_t pfc_en)
+{
+ uint8_t i;
+
+ /*
+ * Builds up the correct configuration for dcb+vt based on the vlan tags array
+ * given above, and the number of traffic classes available for use.
+ */
+ if (dcb_mode == DCB_VT_ENABLED) {
+ struct rte_eth_vmdq_dcb_conf *vmdq_rx_conf =
+ &eth_conf->rx_adv_conf.vmdq_dcb_conf;
+ struct rte_eth_vmdq_dcb_tx_conf *vmdq_tx_conf =
+ &eth_conf->tx_adv_conf.vmdq_dcb_tx_conf;
+
+ /* VMDQ+DCB RX and TX configurations */
+ vmdq_rx_conf->enable_default_pool = 0;
+ vmdq_rx_conf->default_pool = 0;
+ vmdq_rx_conf->nb_queue_pools =
+ (num_tcs == ETH_4_TCS ? ETH_32_POOLS : ETH_16_POOLS);
+ vmdq_tx_conf->nb_queue_pools =
+ (num_tcs == ETH_4_TCS ? ETH_32_POOLS : ETH_16_POOLS);
+
+ vmdq_rx_conf->nb_pool_maps = vmdq_rx_conf->nb_queue_pools;
+ for (i = 0; i < vmdq_rx_conf->nb_pool_maps; i++) {
+ vmdq_rx_conf->pool_map[i].vlan_id = vlan_tags[i];
+ vmdq_rx_conf->pool_map[i].pools =
+ 1 << (i % vmdq_rx_conf->nb_queue_pools);
+ }
+ for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++) {
+ vmdq_rx_conf->dcb_tc[i] = i;
+ vmdq_tx_conf->dcb_tc[i] = i;
+ }
+
+ /* set DCB mode of RX and TX of multiple queues */
+ eth_conf->rxmode.mq_mode = ETH_MQ_RX_VMDQ_DCB;
+ eth_conf->txmode.mq_mode = ETH_MQ_TX_VMDQ_DCB;
+ } else {
+ struct rte_eth_dcb_rx_conf *rx_conf =
+ &eth_conf->rx_adv_conf.dcb_rx_conf;
+ struct rte_eth_dcb_tx_conf *tx_conf =
+ &eth_conf->tx_adv_conf.dcb_tx_conf;
+
+ rx_conf->nb_tcs = num_tcs;
+ tx_conf->nb_tcs = num_tcs;
+
+ for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++) {
+ rx_conf->dcb_tc[i] = i % num_tcs;
+ tx_conf->dcb_tc[i] = i % num_tcs;
+ }
+ eth_conf->rxmode.mq_mode = ETH_MQ_RX_DCB_RSS;
+ eth_conf->rx_adv_conf.rss_conf.rss_hf = rss_hf;
+ eth_conf->txmode.mq_mode = ETH_MQ_TX_DCB;
+ }
+
+ if (pfc_en)
+ eth_conf->dcb_capability_en =
+ ETH_DCB_PG_SUPPORT | ETH_DCB_PFC_SUPPORT;
+ else
+ eth_conf->dcb_capability_en = ETH_DCB_PG_SUPPORT;
+
+ return 0;
+}
+
+int
+init_port_dcb_config(portid_t pid,
+ enum dcb_mode_enable dcb_mode,
+ enum rte_eth_nb_tcs num_tcs,
+ uint8_t pfc_en)
+{
+ struct rte_eth_conf port_conf;
+ struct rte_port *rte_port;
+ int retval;
+ uint16_t i;
+
+ rte_port = &ports[pid];
+
+ memset(&port_conf, 0, sizeof(struct rte_eth_conf));
+ /* Enter DCB configuration status */
+ dcb_config = 1;
+
+ /*set configuration of DCB in vt mode and DCB in non-vt mode*/
+ retval = get_eth_dcb_conf(&port_conf, dcb_mode, num_tcs, pfc_en);
+ if (retval < 0)
+ return retval;
+ port_conf.rxmode.hw_vlan_filter = 1;
+
+ /**
+ * Write the configuration into the device.
+ * Set the numbers of RX & TX queues to 0, so
+ * the RX & TX queues will not be setup.
+ */
+ (void)rte_eth_dev_configure(pid, 0, 0, &port_conf);
+
+ rte_eth_dev_info_get(pid, &rte_port->dev_info);
+
+ /* If dev_info.vmdq_pool_base is greater than 0,
+ * the queue id of vmdq pools is started after pf queues.
+ */
+ if (dcb_mode == DCB_VT_ENABLED &&
+ rte_port->dev_info.vmdq_pool_base > 0) {
+ printf("VMDQ_DCB multi-queue mode is nonsensical"
+ " for port %d.", pid);
+ return -1;
+ }
+
+ /* Assume the ports in testpmd have the same dcb capability
+ * and has the same number of rxq and txq in dcb mode
+ */
+ if (dcb_mode == DCB_VT_ENABLED) {
+ if (rte_port->dev_info.max_vfs > 0) {
+ nb_rxq = rte_port->dev_info.nb_rx_queues;
+ nb_txq = rte_port->dev_info.nb_tx_queues;
+ } else {
+ nb_rxq = rte_port->dev_info.max_rx_queues;
+ nb_txq = rte_port->dev_info.max_tx_queues;
+ }
+ } else {
+ /*if vt is disabled, use all pf queues */
+ if (rte_port->dev_info.vmdq_pool_base == 0) {
+ nb_rxq = rte_port->dev_info.max_rx_queues;
+ nb_txq = rte_port->dev_info.max_tx_queues;
+ } else {
+ nb_rxq = (queueid_t)num_tcs;
+ nb_txq = (queueid_t)num_tcs;
+
+ }
+ }
+ rx_free_thresh = 64;
+
+ memcpy(&rte_port->dev_conf, &port_conf, sizeof(struct rte_eth_conf));
+
+ rxtx_port_config(rte_port);
+ /* VLAN filter */
+ rte_port->dev_conf.rxmode.hw_vlan_filter = 1;
+ for (i = 0; i < RTE_DIM(vlan_tags); i++)
+ rx_vft_set(pid, vlan_tags[i], 1);
+
+ rte_eth_macaddr_get(pid, &rte_port->eth_addr);
+ map_port_queue_stats_mapping_registers(pid, rte_port);
+
+ rte_port->dcb_flag = 1;
+
+ return 0;
+}
+
+static void
+init_port(void)
+{
+ /* Configuration of Ethernet ports. */
+ ports = rte_zmalloc("testpmd: ports",
+ sizeof(struct rte_port) * RTE_MAX_ETHPORTS,
+ RTE_CACHE_LINE_SIZE);
+ if (ports == NULL) {
+ rte_exit(EXIT_FAILURE,
+ "rte_zmalloc(%d struct rte_port) failed\n",
+ RTE_MAX_ETHPORTS);
+ }
+}
+
+static void
+force_quit(void)
+{
+ pmd_test_exit();
+ prompt_exit();
+}
+
+static void
+signal_handler(int signum)
+{
+ if (signum == SIGINT || signum == SIGTERM) {
+ printf("\nSignal %d received, preparing to exit...\n",
+ signum);
+#ifdef RTE_LIBRTE_PDUMP
+ /* uninitialize packet capture framework */
+ rte_pdump_uninit();
+#endif
+#ifdef RTE_LIBRTE_LATENCY_STATS
+ rte_latencystats_uninit();
+#endif
+ force_quit();
+ /* exit with the expected status */
+ signal(signum, SIG_DFL);
+ kill(getpid(), signum);
+ }
+}
+
+int
+main(int argc, char** argv)
+{
+ int diag;
+ uint8_t port_id;
+
+ signal(SIGINT, signal_handler);
+ signal(SIGTERM, signal_handler);
+
+ diag = rte_eal_init(argc, argv);
+ if (diag < 0)
+ rte_panic("Cannot init EAL\n");
+
+#ifdef RTE_LIBRTE_PDUMP
+ /* initialize packet capture framework */
+ rte_pdump_init(NULL);
+#endif
+
+ nb_ports = (portid_t) rte_eth_dev_count();
+ if (nb_ports == 0)
+ RTE_LOG(WARNING, EAL, "No probed ethernet devices\n");
+
+ /* allocate port structures, and init them */
+ init_port();
+
+ set_def_fwd_config();
+ if (nb_lcores == 0)
+ rte_panic("Empty set of forwarding logical cores - check the "
+ "core mask supplied in the command parameters\n");
+
+ /* Bitrate/latency stats disabled by default */
+#ifdef RTE_LIBRTE_BITRATE
+ bitrate_enabled = 0;
+#endif
+#ifdef RTE_LIBRTE_LATENCY_STATS
+ latencystats_enabled = 0;
+#endif
+
+ argc -= diag;
+ argv += diag;
+ if (argc > 1)
+ launch_args_parse(argc, argv);
+
+ if (!nb_rxq && !nb_txq)
+ printf("Warning: Either rx or tx queues should be non-zero\n");
+
+ if (nb_rxq > 1 && nb_rxq > nb_txq)
+ printf("Warning: nb_rxq=%d enables RSS configuration, "
+ "but nb_txq=%d will prevent to fully test it.\n",
+ nb_rxq, nb_txq);
+
+ init_config();
+ if (start_port(RTE_PORT_ALL) != 0)
+ rte_exit(EXIT_FAILURE, "Start ports failed\n");
+
+ /* set all ports to promiscuous mode by default */
+ RTE_ETH_FOREACH_DEV(port_id)
+ rte_eth_promiscuous_enable(port_id);
+
+ /* Init metrics library */
+ rte_metrics_init(rte_socket_id());
+
+#ifdef RTE_LIBRTE_LATENCY_STATS
+ if (latencystats_enabled != 0) {
+ int ret = rte_latencystats_init(1, NULL);
+ if (ret)
+ printf("Warning: latencystats init()"
+ " returned error %d\n", ret);
+ printf("Latencystats running on lcore %d\n",
+ latencystats_lcore_id);
+ }
+#endif
+
+ /* Setup bitrate stats */
+#ifdef RTE_LIBRTE_BITRATE
+ if (bitrate_enabled != 0) {
+ bitrate_data = rte_stats_bitrate_create();
+ if (bitrate_data == NULL)
+ rte_exit(EXIT_FAILURE,
+ "Could not allocate bitrate data.\n");
+ rte_stats_bitrate_reg(bitrate_data);
+ }
+#endif
+
+#ifdef RTE_LIBRTE_CMDLINE
+ if (strlen(cmdline_filename) != 0)
+ cmdline_read_from_file(cmdline_filename);
+
+ if (interactive == 1) {
+ if (auto_start) {
+ printf("Start automatic packet forwarding\n");
+ start_packet_forwarding(0);
+ }
+ prompt();
+ pmd_test_exit();
+ } else
+#endif
+ {
+ char c;
+ int rc;
+
+ printf("No commandline core given, start packet forwarding\n");
+ start_packet_forwarding(0);
+ printf("Press enter to exit\n");
+ rc = read(0, &c, 1);
+ pmd_test_exit();
+ if (rc < 0)
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/src/seastar/dpdk/app/test-pmd/testpmd.h b/src/seastar/dpdk/app/test-pmd/testpmd.h
new file mode 100644
index 00000000..e6c43ba0
--- /dev/null
+++ b/src/seastar/dpdk/app/test-pmd/testpmd.h
@@ -0,0 +1,663 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TESTPMD_H_
+#define _TESTPMD_H_
+
+#define RTE_PORT_ALL (~(portid_t)0x0)
+
+#define RTE_TEST_RX_DESC_MAX 2048
+#define RTE_TEST_TX_DESC_MAX 2048
+
+#define RTE_PORT_STOPPED (uint16_t)0
+#define RTE_PORT_STARTED (uint16_t)1
+#define RTE_PORT_CLOSED (uint16_t)2
+#define RTE_PORT_HANDLING (uint16_t)3
+
+/*
+ * It is used to allocate the memory for hash key.
+ * The hash key size is NIC dependent.
+ */
+#define RSS_HASH_KEY_LENGTH 64
+
+/*
+ * Default size of the mbuf data buffer to receive standard 1518-byte
+ * Ethernet frames in a mono-segment memory buffer.
+ */
+#define DEFAULT_MBUF_DATA_SIZE RTE_MBUF_DEFAULT_BUF_SIZE
+/**< Default size of mbuf data buffer. */
+
+/*
+ * The maximum number of segments per packet is used when creating
+ * scattered transmit packets composed of a list of mbufs.
+ */
+#define RTE_MAX_SEGS_PER_PKT 255 /**< nb_segs is a 8-bit unsigned char. */
+
+#define MAX_PKT_BURST 512
+#define DEF_PKT_BURST 32
+
+#define DEF_MBUF_CACHE 250
+
+#define RTE_CACHE_LINE_SIZE_ROUNDUP(size) \
+ (RTE_CACHE_LINE_SIZE * ((size + RTE_CACHE_LINE_SIZE - 1) / RTE_CACHE_LINE_SIZE))
+
+#define NUMA_NO_CONFIG 0xFF
+#define UMA_NO_CONFIG 0xFF
+
+typedef uint8_t lcoreid_t;
+typedef uint8_t portid_t;
+typedef uint16_t queueid_t;
+typedef uint16_t streamid_t;
+
+#define MAX_QUEUE_ID ((1 << (sizeof(queueid_t) * 8)) - 1)
+
+enum {
+ PORT_TOPOLOGY_PAIRED,
+ PORT_TOPOLOGY_CHAINED,
+ PORT_TOPOLOGY_LOOP,
+};
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+/**
+ * The data structure associated with RX and TX packet burst statistics
+ * that are recorded for each forwarding stream.
+ */
+struct pkt_burst_stats {
+ unsigned int pkt_burst_spread[MAX_PKT_BURST];
+};
+#endif
+
+/**
+ * The data structure associated with a forwarding stream between a receive
+ * port/queue and a transmit port/queue.
+ */
+struct fwd_stream {
+ /* "read-only" data */
+ portid_t rx_port; /**< port to poll for received packets */
+ queueid_t rx_queue; /**< RX queue to poll on "rx_port" */
+ portid_t tx_port; /**< forwarding port of received packets */
+ queueid_t tx_queue; /**< TX queue to send forwarded packets */
+ streamid_t peer_addr; /**< index of peer ethernet address of packets */
+
+ unsigned int retry_enabled;
+
+ /* "read-write" results */
+ unsigned int rx_packets; /**< received packets */
+ unsigned int tx_packets; /**< received packets transmitted */
+ unsigned int fwd_dropped; /**< received packets not forwarded */
+ unsigned int rx_bad_ip_csum ; /**< received packets has bad ip checksum */
+ unsigned int rx_bad_l4_csum ; /**< received packets has bad l4 checksum */
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ uint64_t core_cycles; /**< used for RX and TX processing */
+#endif
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ struct pkt_burst_stats rx_burst_stats;
+ struct pkt_burst_stats tx_burst_stats;
+#endif
+};
+
+/** Offload IP checksum in csum forward engine */
+#define TESTPMD_TX_OFFLOAD_IP_CKSUM 0x0001
+/** Offload UDP checksum in csum forward engine */
+#define TESTPMD_TX_OFFLOAD_UDP_CKSUM 0x0002
+/** Offload TCP checksum in csum forward engine */
+#define TESTPMD_TX_OFFLOAD_TCP_CKSUM 0x0004
+/** Offload SCTP checksum in csum forward engine */
+#define TESTPMD_TX_OFFLOAD_SCTP_CKSUM 0x0008
+/** Offload outer IP checksum in csum forward engine for recognized tunnels */
+#define TESTPMD_TX_OFFLOAD_OUTER_IP_CKSUM 0x0010
+/** Parse tunnel in csum forward engine. If set, dissect tunnel headers
+ * of rx packets. If not set, treat inner headers as payload. */
+#define TESTPMD_TX_OFFLOAD_PARSE_TUNNEL 0x0020
+/** Insert VLAN header in forward engine */
+#define TESTPMD_TX_OFFLOAD_INSERT_VLAN 0x0040
+/** Insert double VLAN header in forward engine */
+#define TESTPMD_TX_OFFLOAD_INSERT_QINQ 0x0080
+/** Offload MACsec in forward engine */
+#define TESTPMD_TX_OFFLOAD_MACSEC 0x0100
+
+/** Descriptor for a single flow. */
+struct port_flow {
+ size_t size; /**< Allocated space including data[]. */
+ struct port_flow *next; /**< Next flow in list. */
+ struct port_flow *tmp; /**< Temporary linking. */
+ uint32_t id; /**< Flow rule ID. */
+ struct rte_flow *flow; /**< Opaque flow object returned by PMD. */
+ struct rte_flow_attr attr; /**< Attributes. */
+ struct rte_flow_item *pattern; /**< Pattern. */
+ struct rte_flow_action *actions; /**< Actions. */
+ uint8_t data[]; /**< Storage for pattern/actions. */
+};
+
+/**
+ * The data structure associated with each port.
+ */
+struct rte_port {
+ struct rte_eth_dev_info dev_info; /**< PCI info + driver name */
+ struct rte_eth_conf dev_conf; /**< Port configuration. */
+ struct ether_addr eth_addr; /**< Port ethernet address */
+ struct rte_eth_stats stats; /**< Last port statistics */
+ uint64_t tx_dropped; /**< If no descriptor in TX ring */
+ struct fwd_stream *rx_stream; /**< Port RX stream, if unique */
+ struct fwd_stream *tx_stream; /**< Port TX stream, if unique */
+ unsigned int socket_id; /**< For NUMA support */
+ uint16_t tx_ol_flags;/**< TX Offload Flags (TESTPMD_TX_OFFLOAD...). */
+ uint16_t tso_segsz; /**< Segmentation offload MSS for non-tunneled packets. */
+ uint16_t tunnel_tso_segsz; /**< Segmentation offload MSS for tunneled pkts. */
+ uint16_t tx_vlan_id;/**< The tag ID */
+ uint16_t tx_vlan_id_outer;/**< The outer tag ID */
+ void *fwd_ctx; /**< Forwarding mode context */
+ uint64_t rx_bad_ip_csum; /**< rx pkts with bad ip checksum */
+ uint64_t rx_bad_l4_csum; /**< rx pkts with bad l4 checksum */
+ uint8_t tx_queue_stats_mapping_enabled;
+ uint8_t rx_queue_stats_mapping_enabled;
+ volatile uint16_t port_status; /**< port started or not */
+ uint8_t need_reconfig; /**< need reconfiguring port or not */
+ uint8_t need_reconfig_queues; /**< need reconfiguring queues or not */
+ uint8_t rss_flag; /**< enable rss or not */
+ uint8_t dcb_flag; /**< enable dcb */
+ struct rte_eth_rxconf rx_conf; /**< rx configuration */
+ struct rte_eth_txconf tx_conf; /**< tx configuration */
+ struct ether_addr *mc_addr_pool; /**< pool of multicast addrs */
+ uint32_t mc_addr_nb; /**< nb. of addr. in mc_addr_pool */
+ uint8_t slave_flag; /**< bonding slave port */
+ struct port_flow *flow_list; /**< Associated flows. */
+};
+
+/**
+ * The data structure associated with each forwarding logical core.
+ * The logical cores are internally numbered by a core index from 0 to
+ * the maximum number of logical cores - 1.
+ * The system CPU identifier of all logical cores are setup in a global
+ * CPU id. configuration table.
+ */
+struct fwd_lcore {
+ struct rte_mempool *mbp; /**< The mbuf pool to use by this core */
+ streamid_t stream_idx; /**< index of 1st stream in "fwd_streams" */
+ streamid_t stream_nb; /**< number of streams in "fwd_streams" */
+ lcoreid_t cpuid_idx; /**< index of logical core in CPU id table */
+ queueid_t tx_queue; /**< TX queue to send forwarded packets */
+ volatile char stopped; /**< stop forwarding when set */
+};
+
+/*
+ * Forwarding mode operations:
+ * - IO forwarding mode (default mode)
+ * Forwards packets unchanged.
+ *
+ * - MAC forwarding mode
+ * Set the source and the destination Ethernet addresses of packets
+ * before forwarding them.
+ *
+ * - IEEE1588 forwarding mode
+ * Check that received IEEE1588 Precise Time Protocol (PTP) packets are
+ * filtered and timestamped by the hardware.
+ * Forwards packets unchanged on the same port.
+ * Check that sent IEEE1588 PTP packets are timestamped by the hardware.
+ */
+typedef void (*port_fwd_begin_t)(portid_t pi);
+typedef void (*port_fwd_end_t)(portid_t pi);
+typedef void (*packet_fwd_t)(struct fwd_stream *fs);
+
+struct fwd_engine {
+ const char *fwd_mode_name; /**< Forwarding mode name. */
+ port_fwd_begin_t port_fwd_begin; /**< NULL if nothing special to do. */
+ port_fwd_end_t port_fwd_end; /**< NULL if nothing special to do. */
+ packet_fwd_t packet_fwd; /**< Mandatory. */
+};
+
+#define BURST_TX_WAIT_US 1
+#define BURST_TX_RETRIES 64
+
+extern uint32_t burst_tx_delay_time;
+extern uint32_t burst_tx_retry_num;
+
+extern struct fwd_engine io_fwd_engine;
+extern struct fwd_engine mac_fwd_engine;
+extern struct fwd_engine mac_swap_engine;
+extern struct fwd_engine flow_gen_engine;
+extern struct fwd_engine rx_only_engine;
+extern struct fwd_engine tx_only_engine;
+extern struct fwd_engine csum_fwd_engine;
+extern struct fwd_engine icmp_echo_engine;
+#ifdef RTE_LIBRTE_IEEE1588
+extern struct fwd_engine ieee1588_fwd_engine;
+#endif
+
+extern struct fwd_engine * fwd_engines[]; /**< NULL terminated array. */
+
+/**
+ * Forwarding Configuration
+ *
+ */
+struct fwd_config {
+ struct fwd_engine *fwd_eng; /**< Packet forwarding mode. */
+ streamid_t nb_fwd_streams; /**< Nb. of forward streams to process. */
+ lcoreid_t nb_fwd_lcores; /**< Nb. of logical cores to launch. */
+ portid_t nb_fwd_ports; /**< Nb. of ports involved. */
+};
+
+/**
+ * DCB mode enable
+ */
+enum dcb_mode_enable
+{
+ DCB_VT_ENABLED,
+ DCB_ENABLED
+};
+
+#define MAX_TX_QUEUE_STATS_MAPPINGS 1024 /* MAX_PORT of 32 @ 32 tx_queues/port */
+#define MAX_RX_QUEUE_STATS_MAPPINGS 4096 /* MAX_PORT of 32 @ 128 rx_queues/port */
+
+struct queue_stats_mappings {
+ uint8_t port_id;
+ uint16_t queue_id;
+ uint8_t stats_counter_id;
+} __rte_cache_aligned;
+
+extern struct queue_stats_mappings tx_queue_stats_mappings_array[];
+extern struct queue_stats_mappings rx_queue_stats_mappings_array[];
+
+/* Assign both tx and rx queue stats mappings to the same default values */
+extern struct queue_stats_mappings *tx_queue_stats_mappings;
+extern struct queue_stats_mappings *rx_queue_stats_mappings;
+
+extern uint16_t nb_tx_queue_stats_mappings;
+extern uint16_t nb_rx_queue_stats_mappings;
+
+/* globals used for configuration */
+extern uint16_t verbose_level; /**< Drives messages being displayed, if any. */
+extern uint8_t interactive;
+extern uint8_t auto_start;
+extern char cmdline_filename[PATH_MAX]; /**< offline commands file */
+extern uint8_t numa_support; /**< set by "--numa" parameter */
+extern uint16_t port_topology; /**< set by "--port-topology" parameter */
+extern uint8_t no_flush_rx; /**<set by "--no-flush-rx" parameter */
+extern uint8_t mp_anon; /**< set by "--mp-anon" parameter */
+extern uint8_t no_link_check; /**<set by "--disable-link-check" parameter */
+extern volatile int test_done; /* stop packet forwarding when set to 1. */
+extern uint8_t lsc_interrupt; /**< disabled by "--no-lsc-interrupt" parameter */
+extern uint8_t rmv_interrupt; /**< disabled by "--no-rmv-interrupt" parameter */
+extern uint32_t event_print_mask;
+/**< set by "--print-event xxxx" and "--mask-event xxxx parameters */
+
+#ifdef RTE_NIC_BYPASS
+extern uint32_t bypass_timeout; /**< Store the NIC bypass watchdog timeout */
+#endif
+
+/*
+ * Store specified sockets on which memory pool to be used by ports
+ * is allocated.
+ */
+uint8_t port_numa[RTE_MAX_ETHPORTS];
+
+/*
+ * Store specified sockets on which RX ring to be used by ports
+ * is allocated.
+ */
+uint8_t rxring_numa[RTE_MAX_ETHPORTS];
+
+/*
+ * Store specified sockets on which TX ring to be used by ports
+ * is allocated.
+ */
+uint8_t txring_numa[RTE_MAX_ETHPORTS];
+
+extern uint8_t socket_num;
+
+/*
+ * Configuration of logical cores:
+ * nb_fwd_lcores <= nb_cfg_lcores <= nb_lcores
+ */
+extern lcoreid_t nb_lcores; /**< Number of logical cores probed at init time. */
+extern lcoreid_t nb_cfg_lcores; /**< Number of configured logical cores. */
+extern lcoreid_t nb_fwd_lcores; /**< Number of forwarding logical cores. */
+extern unsigned int fwd_lcores_cpuids[RTE_MAX_LCORE];
+extern unsigned int num_sockets;
+extern unsigned int socket_ids[RTE_MAX_NUMA_NODES];
+
+/*
+ * Configuration of Ethernet ports:
+ * nb_fwd_ports <= nb_cfg_ports <= nb_ports
+ */
+extern portid_t nb_ports; /**< Number of ethernet ports probed at init time. */
+extern portid_t nb_cfg_ports; /**< Number of configured ports. */
+extern portid_t nb_fwd_ports; /**< Number of forwarding ports. */
+extern portid_t fwd_ports_ids[RTE_MAX_ETHPORTS];
+extern struct rte_port *ports;
+
+extern struct rte_eth_rxmode rx_mode;
+extern uint64_t rss_hf;
+
+extern queueid_t nb_rxq;
+extern queueid_t nb_txq;
+
+extern uint16_t nb_rxd;
+extern uint16_t nb_txd;
+
+extern int16_t rx_free_thresh;
+extern int8_t rx_drop_en;
+extern int16_t tx_free_thresh;
+extern int16_t tx_rs_thresh;
+extern int32_t txq_flags;
+
+extern uint8_t dcb_config;
+extern uint8_t dcb_test;
+extern enum dcb_queue_mapping_mode dcb_q_mapping;
+
+extern uint16_t mbuf_data_size; /**< Mbuf data space size. */
+extern uint32_t param_total_num_mbufs;
+
+
+#ifdef RTE_LIBRTE_LATENCY_STATS
+extern uint8_t latencystats_enabled;
+extern lcoreid_t latencystats_lcore_id;
+#endif
+
+#ifdef RTE_LIBRTE_BITRATE
+extern lcoreid_t bitrate_lcore_id;
+extern uint8_t bitrate_enabled;
+#endif
+
+extern struct rte_fdir_conf fdir_conf;
+
+/*
+ * Configuration of packet segments used by the "txonly" processing engine.
+ */
+#define TXONLY_DEF_PACKET_LEN 64
+extern uint16_t tx_pkt_length; /**< Length of TXONLY packet */
+extern uint16_t tx_pkt_seg_lengths[RTE_MAX_SEGS_PER_PKT]; /**< Seg. lengths */
+extern uint8_t tx_pkt_nb_segs; /**< Number of segments in TX packets */
+
+enum tx_pkt_split {
+ TX_PKT_SPLIT_OFF,
+ TX_PKT_SPLIT_ON,
+ TX_PKT_SPLIT_RND,
+};
+
+extern enum tx_pkt_split tx_pkt_split;
+
+extern uint16_t nb_pkt_per_burst;
+extern uint16_t mb_mempool_cache;
+extern int8_t rx_pthresh;
+extern int8_t rx_hthresh;
+extern int8_t rx_wthresh;
+extern int8_t tx_pthresh;
+extern int8_t tx_hthresh;
+extern int8_t tx_wthresh;
+
+extern struct fwd_config cur_fwd_config;
+extern struct fwd_engine *cur_fwd_eng;
+extern uint32_t retry_enabled;
+extern struct fwd_lcore **fwd_lcores;
+extern struct fwd_stream **fwd_streams;
+
+extern portid_t nb_peer_eth_addrs; /**< Number of peer ethernet addresses. */
+extern struct ether_addr peer_eth_addrs[RTE_MAX_ETHPORTS];
+
+extern uint32_t burst_tx_delay_time; /**< Burst tx delay time(us) for mac-retry. */
+extern uint32_t burst_tx_retry_num; /**< Burst tx retry number for mac-retry. */
+
+static inline unsigned int
+lcore_num(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < RTE_MAX_LCORE; ++i)
+ if (fwd_lcores_cpuids[i] == rte_lcore_id())
+ return i;
+
+ rte_panic("lcore_id of current thread not found in fwd_lcores_cpuids\n");
+}
+
+static inline struct fwd_lcore *
+current_fwd_lcore(void)
+{
+ return fwd_lcores[lcore_num()];
+}
+
+/* Mbuf Pools */
+static inline void
+mbuf_poolname_build(unsigned int sock_id, char* mp_name, int name_size)
+{
+ snprintf(mp_name, name_size, "mbuf_pool_socket_%u", sock_id);
+}
+
+static inline struct rte_mempool *
+mbuf_pool_find(unsigned int sock_id)
+{
+ char pool_name[RTE_MEMPOOL_NAMESIZE];
+
+ mbuf_poolname_build(sock_id, pool_name, sizeof(pool_name));
+ return rte_mempool_lookup((const char *)pool_name);
+}
+
+/**
+ * Read/Write operations on a PCI register of a port.
+ */
+static inline uint32_t
+port_pci_reg_read(struct rte_port *port, uint32_t reg_off)
+{
+ void *reg_addr;
+ uint32_t reg_v;
+
+ reg_addr = (void *)
+ ((char *)port->dev_info.pci_dev->mem_resource[0].addr +
+ reg_off);
+ reg_v = *((volatile uint32_t *)reg_addr);
+ return rte_le_to_cpu_32(reg_v);
+}
+
+#define port_id_pci_reg_read(pt_id, reg_off) \
+ port_pci_reg_read(&ports[(pt_id)], (reg_off))
+
+static inline void
+port_pci_reg_write(struct rte_port *port, uint32_t reg_off, uint32_t reg_v)
+{
+ void *reg_addr;
+
+ reg_addr = (void *)
+ ((char *)port->dev_info.pci_dev->mem_resource[0].addr +
+ reg_off);
+ *((volatile uint32_t *)reg_addr) = rte_cpu_to_le_32(reg_v);
+}
+
+#define port_id_pci_reg_write(pt_id, reg_off, reg_value) \
+ port_pci_reg_write(&ports[(pt_id)], (reg_off), (reg_value))
+
+/* Prototypes */
+unsigned int parse_item_list(char* str, const char* item_name,
+ unsigned int max_items,
+ unsigned int *parsed_items, int check_unique_values);
+void launch_args_parse(int argc, char** argv);
+void cmdline_read_from_file(const char *filename);
+void prompt(void);
+void prompt_exit(void);
+void nic_stats_display(portid_t port_id);
+void nic_stats_clear(portid_t port_id);
+void nic_xstats_display(portid_t port_id);
+void nic_xstats_clear(portid_t port_id);
+void nic_stats_mapping_display(portid_t port_id);
+void port_infos_display(portid_t port_id);
+void port_offload_cap_display(portid_t port_id);
+void rx_queue_infos_display(portid_t port_idi, uint16_t queue_id);
+void tx_queue_infos_display(portid_t port_idi, uint16_t queue_id);
+void fwd_lcores_config_display(void);
+void pkt_fwd_config_display(struct fwd_config *cfg);
+void rxtx_config_display(void);
+void fwd_config_setup(void);
+void set_def_fwd_config(void);
+void reconfig(portid_t new_port_id, unsigned socket_id);
+int init_fwd_streams(void);
+
+void port_mtu_set(portid_t port_id, uint16_t mtu);
+void port_reg_bit_display(portid_t port_id, uint32_t reg_off, uint8_t bit_pos);
+void port_reg_bit_set(portid_t port_id, uint32_t reg_off, uint8_t bit_pos,
+ uint8_t bit_v);
+void port_reg_bit_field_display(portid_t port_id, uint32_t reg_off,
+ uint8_t bit1_pos, uint8_t bit2_pos);
+void port_reg_bit_field_set(portid_t port_id, uint32_t reg_off,
+ uint8_t bit1_pos, uint8_t bit2_pos, uint32_t value);
+void port_reg_display(portid_t port_id, uint32_t reg_off);
+void port_reg_set(portid_t port_id, uint32_t reg_off, uint32_t value);
+int port_flow_validate(portid_t port_id,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item *pattern,
+ const struct rte_flow_action *actions);
+int port_flow_create(portid_t port_id,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item *pattern,
+ const struct rte_flow_action *actions);
+int port_flow_destroy(portid_t port_id, uint32_t n, const uint32_t *rule);
+int port_flow_flush(portid_t port_id);
+int port_flow_query(portid_t port_id, uint32_t rule,
+ enum rte_flow_action_type action);
+void port_flow_list(portid_t port_id, uint32_t n, const uint32_t *group);
+
+void rx_ring_desc_display(portid_t port_id, queueid_t rxq_id, uint16_t rxd_id);
+void tx_ring_desc_display(portid_t port_id, queueid_t txq_id, uint16_t txd_id);
+
+int set_fwd_lcores_list(unsigned int *lcorelist, unsigned int nb_lc);
+int set_fwd_lcores_mask(uint64_t lcoremask);
+void set_fwd_lcores_number(uint16_t nb_lc);
+
+void set_fwd_ports_list(unsigned int *portlist, unsigned int nb_pt);
+void set_fwd_ports_mask(uint64_t portmask);
+void set_fwd_ports_number(uint16_t nb_pt);
+int port_is_forwarding(portid_t port_id);
+
+void rx_vlan_strip_set(portid_t port_id, int on);
+void rx_vlan_strip_set_on_queue(portid_t port_id, uint16_t queue_id, int on);
+
+void rx_vlan_filter_set(portid_t port_id, int on);
+void rx_vlan_all_filter_set(portid_t port_id, int on);
+int rx_vft_set(portid_t port_id, uint16_t vlan_id, int on);
+void vlan_extend_set(portid_t port_id, int on);
+void vlan_tpid_set(portid_t port_id, enum rte_vlan_type vlan_type,
+ uint16_t tp_id);
+void tx_vlan_set(portid_t port_id, uint16_t vlan_id);
+void tx_qinq_set(portid_t port_id, uint16_t vlan_id, uint16_t vlan_id_outer);
+void tx_vlan_reset(portid_t port_id);
+void tx_vlan_pvid_set(portid_t port_id, uint16_t vlan_id, int on);
+
+void set_qmap(portid_t port_id, uint8_t is_rx, uint16_t queue_id, uint8_t map_value);
+
+void set_verbose_level(uint16_t vb_level);
+void set_tx_pkt_segments(unsigned *seg_lengths, unsigned nb_segs);
+void show_tx_pkt_segments(void);
+void set_tx_pkt_split(const char *name);
+void set_nb_pkt_per_burst(uint16_t pkt_burst);
+char *list_pkt_forwarding_modes(void);
+char *list_pkt_forwarding_retry_modes(void);
+void set_pkt_forwarding_mode(const char *fwd_mode);
+void start_packet_forwarding(int with_tx_first);
+void stop_packet_forwarding(void);
+void dev_set_link_up(portid_t pid);
+void dev_set_link_down(portid_t pid);
+void init_port_config(void);
+void set_port_slave_flag(portid_t slave_pid);
+void clear_port_slave_flag(portid_t slave_pid);
+uint8_t port_is_bonding_slave(portid_t slave_pid);
+
+int init_port_dcb_config(portid_t pid, enum dcb_mode_enable dcb_mode,
+ enum rte_eth_nb_tcs num_tcs,
+ uint8_t pfc_en);
+int start_port(portid_t pid);
+void stop_port(portid_t pid);
+void close_port(portid_t pid);
+void attach_port(char *identifier);
+void detach_port(uint8_t port_id);
+int all_ports_stopped(void);
+int port_is_started(portid_t port_id);
+void pmd_test_exit(void);
+void fdir_get_infos(portid_t port_id);
+void fdir_set_flex_mask(portid_t port_id,
+ struct rte_eth_fdir_flex_mask *cfg);
+void fdir_set_flex_payload(portid_t port_id,
+ struct rte_eth_flex_payload_cfg *cfg);
+void port_rss_reta_info(portid_t port_id,
+ struct rte_eth_rss_reta_entry64 *reta_conf,
+ uint16_t nb_entries);
+
+void set_vf_traffic(portid_t port_id, uint8_t is_rx, uint16_t vf, uint8_t on);
+
+int set_queue_rate_limit(portid_t port_id, uint16_t queue_idx, uint16_t rate);
+int set_vf_rate_limit(portid_t port_id, uint16_t vf, uint16_t rate,
+ uint64_t q_msk);
+
+void port_rss_hash_conf_show(portid_t port_id, char rss_info[],
+ int show_rss_key);
+void port_rss_hash_key_update(portid_t port_id, char rss_type[],
+ uint8_t *hash_key, uint hash_key_len);
+void get_syn_filter(uint8_t port_id);
+void get_ethertype_filter(uint8_t port_id, uint16_t index);
+void get_2tuple_filter(uint8_t port_id, uint16_t index);
+void get_5tuple_filter(uint8_t port_id, uint16_t index);
+int rx_queue_id_is_invalid(queueid_t rxq_id);
+int tx_queue_id_is_invalid(queueid_t txq_id);
+
+/* Functions to manage the set of filtered Multicast MAC addresses */
+void mcast_addr_add(uint8_t port_id, struct ether_addr *mc_addr);
+void mcast_addr_remove(uint8_t port_id, struct ether_addr *mc_addr);
+void port_dcb_info_display(uint8_t port_id);
+
+uint8_t *open_ddp_package_file(const char *file_path, uint32_t *size);
+int close_ddp_package_file(uint8_t *buf);
+
+enum print_warning {
+ ENABLED_WARN = 0,
+ DISABLED_WARN
+};
+int port_id_is_invalid(portid_t port_id, enum print_warning warning);
+int new_socket_id(unsigned int socket_id);
+
+/*
+ * Work-around of a compilation error with ICC on invocations of the
+ * rte_be_to_cpu_16() function.
+ */
+#ifdef __GCC__
+#define RTE_BE_TO_CPU_16(be_16_v) rte_be_to_cpu_16((be_16_v))
+#define RTE_CPU_TO_BE_16(cpu_16_v) rte_cpu_to_be_16((cpu_16_v))
+#else
+#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+#define RTE_BE_TO_CPU_16(be_16_v) (be_16_v)
+#define RTE_CPU_TO_BE_16(cpu_16_v) (cpu_16_v)
+#else
+#define RTE_BE_TO_CPU_16(be_16_v) \
+ (uint16_t) ((((be_16_v) & 0xFF) << 8) | ((be_16_v) >> 8))
+#define RTE_CPU_TO_BE_16(cpu_16_v) \
+ (uint16_t) ((((cpu_16_v) & 0xFF) << 8) | ((cpu_16_v) >> 8))
+#endif
+#endif /* __GCC__ */
+
+#endif /* _TESTPMD_H_ */
diff --git a/src/seastar/dpdk/app/test-pmd/txonly.c b/src/seastar/dpdk/app/test-pmd/txonly.c
new file mode 100644
index 00000000..8b1a2afc
--- /dev/null
+++ b/src/seastar/dpdk/app/test-pmd/txonly.c
@@ -0,0 +1,339 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_cycles.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_memzone.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_memory.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_memcpy.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_udp.h>
+#include <rte_string_fns.h>
+#include <rte_flow.h>
+
+#include "testpmd.h"
+
+#define UDP_SRC_PORT 1024
+#define UDP_DST_PORT 1024
+
+#define IP_SRC_ADDR ((192U << 24) | (168 << 16) | (0 << 8) | 1)
+#define IP_DST_ADDR ((192U << 24) | (168 << 16) | (0 << 8) | 2)
+
+#define IP_DEFTTL 64 /* from RFC 1340. */
+#define IP_VERSION 0x40
+#define IP_HDRLEN 0x05 /* default IP header length == five 32-bits words. */
+#define IP_VHL_DEF (IP_VERSION | IP_HDRLEN)
+
+static struct ipv4_hdr pkt_ip_hdr; /**< IP header of transmitted packets. */
+static struct udp_hdr pkt_udp_hdr; /**< UDP header of transmitted packets. */
+
+static void
+copy_buf_to_pkt_segs(void* buf, unsigned len, struct rte_mbuf *pkt,
+ unsigned offset)
+{
+ struct rte_mbuf *seg;
+ void *seg_buf;
+ unsigned copy_len;
+
+ seg = pkt;
+ while (offset >= seg->data_len) {
+ offset -= seg->data_len;
+ seg = seg->next;
+ }
+ copy_len = seg->data_len - offset;
+ seg_buf = rte_pktmbuf_mtod_offset(seg, char *, offset);
+ while (len > copy_len) {
+ rte_memcpy(seg_buf, buf, (size_t) copy_len);
+ len -= copy_len;
+ buf = ((char*) buf + copy_len);
+ seg = seg->next;
+ seg_buf = rte_pktmbuf_mtod(seg, char *);
+ }
+ rte_memcpy(seg_buf, buf, (size_t) len);
+}
+
+static inline void
+copy_buf_to_pkt(void* buf, unsigned len, struct rte_mbuf *pkt, unsigned offset)
+{
+ if (offset + len <= pkt->data_len) {
+ rte_memcpy(rte_pktmbuf_mtod_offset(pkt, char *, offset),
+ buf, (size_t) len);
+ return;
+ }
+ copy_buf_to_pkt_segs(buf, len, pkt, offset);
+}
+
+static void
+setup_pkt_udp_ip_headers(struct ipv4_hdr *ip_hdr,
+ struct udp_hdr *udp_hdr,
+ uint16_t pkt_data_len)
+{
+ uint16_t *ptr16;
+ uint32_t ip_cksum;
+ uint16_t pkt_len;
+
+ /*
+ * Initialize UDP header.
+ */
+ pkt_len = (uint16_t) (pkt_data_len + sizeof(struct udp_hdr));
+ udp_hdr->src_port = rte_cpu_to_be_16(UDP_SRC_PORT);
+ udp_hdr->dst_port = rte_cpu_to_be_16(UDP_DST_PORT);
+ udp_hdr->dgram_len = RTE_CPU_TO_BE_16(pkt_len);
+ udp_hdr->dgram_cksum = 0; /* No UDP checksum. */
+
+ /*
+ * Initialize IP header.
+ */
+ pkt_len = (uint16_t) (pkt_len + sizeof(struct ipv4_hdr));
+ ip_hdr->version_ihl = IP_VHL_DEF;
+ ip_hdr->type_of_service = 0;
+ ip_hdr->fragment_offset = 0;
+ ip_hdr->time_to_live = IP_DEFTTL;
+ ip_hdr->next_proto_id = IPPROTO_UDP;
+ ip_hdr->packet_id = 0;
+ ip_hdr->total_length = RTE_CPU_TO_BE_16(pkt_len);
+ ip_hdr->src_addr = rte_cpu_to_be_32(IP_SRC_ADDR);
+ ip_hdr->dst_addr = rte_cpu_to_be_32(IP_DST_ADDR);
+
+ /*
+ * Compute IP header checksum.
+ */
+ ptr16 = (unaligned_uint16_t*) ip_hdr;
+ ip_cksum = 0;
+ ip_cksum += ptr16[0]; ip_cksum += ptr16[1];
+ ip_cksum += ptr16[2]; ip_cksum += ptr16[3];
+ ip_cksum += ptr16[4];
+ ip_cksum += ptr16[6]; ip_cksum += ptr16[7];
+ ip_cksum += ptr16[8]; ip_cksum += ptr16[9];
+
+ /*
+ * Reduce 32 bit checksum to 16 bits and complement it.
+ */
+ ip_cksum = ((ip_cksum & 0xFFFF0000) >> 16) +
+ (ip_cksum & 0x0000FFFF);
+ if (ip_cksum > 65535)
+ ip_cksum -= 65535;
+ ip_cksum = (~ip_cksum) & 0x0000FFFF;
+ if (ip_cksum == 0)
+ ip_cksum = 0xFFFF;
+ ip_hdr->hdr_checksum = (uint16_t) ip_cksum;
+}
+
+/*
+ * Transmit a burst of multi-segments packets.
+ */
+static void
+pkt_burst_transmit(struct fwd_stream *fs)
+{
+ struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+ struct rte_port *txp;
+ struct rte_mbuf *pkt;
+ struct rte_mbuf *pkt_seg;
+ struct rte_mempool *mbp;
+ struct ether_hdr eth_hdr;
+ uint16_t nb_tx;
+ uint16_t nb_pkt;
+ uint16_t vlan_tci, vlan_tci_outer;
+ uint32_t retry;
+ uint64_t ol_flags = 0;
+ uint8_t i;
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ uint64_t start_tsc;
+ uint64_t end_tsc;
+ uint64_t core_cycles;
+#endif
+ uint32_t nb_segs, pkt_len;
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ start_tsc = rte_rdtsc();
+#endif
+
+ mbp = current_fwd_lcore()->mbp;
+ txp = &ports[fs->tx_port];
+ vlan_tci = txp->tx_vlan_id;
+ vlan_tci_outer = txp->tx_vlan_id_outer;
+ if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_INSERT_VLAN)
+ ol_flags = PKT_TX_VLAN_PKT;
+ if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_INSERT_QINQ)
+ ol_flags |= PKT_TX_QINQ_PKT;
+ if (txp->tx_ol_flags & TESTPMD_TX_OFFLOAD_MACSEC)
+ ol_flags |= PKT_TX_MACSEC;
+ for (nb_pkt = 0; nb_pkt < nb_pkt_per_burst; nb_pkt++) {
+ pkt = rte_mbuf_raw_alloc(mbp);
+ if (pkt == NULL) {
+ nomore_mbuf:
+ if (nb_pkt == 0)
+ return;
+ break;
+ }
+
+ /*
+ * Using raw alloc is good to improve performance,
+ * but some consumers may use the headroom and so
+ * decrement data_off. We need to make sure it is
+ * reset to default value.
+ */
+ rte_pktmbuf_reset_headroom(pkt);
+ pkt->data_len = tx_pkt_seg_lengths[0];
+ pkt_seg = pkt;
+ if (tx_pkt_split == TX_PKT_SPLIT_RND)
+ nb_segs = random() % tx_pkt_nb_segs + 1;
+ else
+ nb_segs = tx_pkt_nb_segs;
+ pkt_len = pkt->data_len;
+ for (i = 1; i < nb_segs; i++) {
+ pkt_seg->next = rte_mbuf_raw_alloc(mbp);
+ if (pkt_seg->next == NULL) {
+ pkt->nb_segs = i;
+ rte_pktmbuf_free(pkt);
+ goto nomore_mbuf;
+ }
+ pkt_seg = pkt_seg->next;
+ pkt_seg->data_len = tx_pkt_seg_lengths[i];
+ pkt_len += pkt_seg->data_len;
+ }
+ pkt_seg->next = NULL; /* Last segment of packet. */
+
+ /*
+ * Initialize Ethernet header.
+ */
+ ether_addr_copy(&peer_eth_addrs[fs->peer_addr],&eth_hdr.d_addr);
+ ether_addr_copy(&ports[fs->tx_port].eth_addr, &eth_hdr.s_addr);
+ eth_hdr.ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
+
+ /*
+ * Copy headers in first packet segment(s).
+ */
+ copy_buf_to_pkt(&eth_hdr, sizeof(eth_hdr), pkt, 0);
+ copy_buf_to_pkt(&pkt_ip_hdr, sizeof(pkt_ip_hdr), pkt,
+ sizeof(struct ether_hdr));
+ copy_buf_to_pkt(&pkt_udp_hdr, sizeof(pkt_udp_hdr), pkt,
+ sizeof(struct ether_hdr) +
+ sizeof(struct ipv4_hdr));
+
+ /*
+ * Complete first mbuf of packet and append it to the
+ * burst of packets to be transmitted.
+ */
+ pkt->nb_segs = nb_segs;
+ pkt->pkt_len = pkt_len;
+ pkt->ol_flags = ol_flags;
+ pkt->vlan_tci = vlan_tci;
+ pkt->vlan_tci_outer = vlan_tci_outer;
+ pkt->l2_len = sizeof(struct ether_hdr);
+ pkt->l3_len = sizeof(struct ipv4_hdr);
+ pkts_burst[nb_pkt] = pkt;
+ }
+ nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_pkt);
+ /*
+ * Retry if necessary
+ */
+ if (unlikely(nb_tx < nb_pkt) && fs->retry_enabled) {
+ retry = 0;
+ while (nb_tx < nb_pkt && retry++ < burst_tx_retry_num) {
+ rte_delay_us(burst_tx_delay_time);
+ nb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue,
+ &pkts_burst[nb_tx], nb_pkt - nb_tx);
+ }
+ }
+ fs->tx_packets += nb_tx;
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->tx_burst_stats.pkt_burst_spread[nb_tx]++;
+#endif
+ if (unlikely(nb_tx < nb_pkt)) {
+ if (verbose_level > 0 && fs->fwd_dropped == 0)
+ printf("port %d tx_queue %d - drop "
+ "(nb_pkt:%u - nb_tx:%u)=%u packets\n",
+ fs->tx_port, fs->tx_queue,
+ (unsigned) nb_pkt, (unsigned) nb_tx,
+ (unsigned) (nb_pkt - nb_tx));
+ fs->fwd_dropped += (nb_pkt - nb_tx);
+ do {
+ rte_pktmbuf_free(pkts_burst[nb_tx]);
+ } while (++nb_tx < nb_pkt);
+ }
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ end_tsc = rte_rdtsc();
+ core_cycles = (end_tsc - start_tsc);
+ fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles);
+#endif
+}
+
+static void
+tx_only_begin(__attribute__((unused)) portid_t pi)
+{
+ uint16_t pkt_data_len;
+
+ pkt_data_len = (uint16_t) (tx_pkt_length - (sizeof(struct ether_hdr) +
+ sizeof(struct ipv4_hdr) +
+ sizeof(struct udp_hdr)));
+ setup_pkt_udp_ip_headers(&pkt_ip_hdr, &pkt_udp_hdr, pkt_data_len);
+}
+
+struct fwd_engine tx_only_engine = {
+ .fwd_mode_name = "txonly",
+ .port_fwd_begin = tx_only_begin,
+ .port_fwd_end = NULL,
+ .packet_fwd = pkt_burst_transmit,
+};