From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 9419DA0565 for ; Mon, 2 Mar 2020 01:00:40 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id B02821C08C; Mon, 2 Mar 2020 01:00:39 +0100 (CET) Received: from valinux.co.jp (vagw.valinux.co.jp [210.128.90.14]) by dpdk.org (Postfix) with ESMTP id 64FB11C06B for ; Mon, 2 Mar 2020 01:00:38 +0100 (CET) Received: by valinux.co.jp (Postfix, from userid 1000) id 882A7240CEE; Mon, 2 Mar 2020 09:00:37 +0900 (JST) From: Itsuro Oda To: spp@dpdk.org, ferruh.yigit@intel.com, yasufum.o@gmail.com Date: Mon, 2 Mar 2020 09:00:35 +0900 Message-Id: <20200302000037.30578-2-oda@valinux.co.jp> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200302000037.30578-1-oda@valinux.co.jp> References: <20200226020245.3037-1-oda@valinux.co.jp> <20200302000037.30578-1-oda@valinux.co.jp> Subject: [spp] [PATCH v3 1/3] vdev_test: simple tool to perform packet forwarding for vdev X-BeenThere: spp@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Soft Patch Panel List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: spp-bounces@dpdk.org Sender: "spp" vdev_test is a simple tool to perform packet forwarding for virtual ethernet devices. It is mainly to test pipe PMD because testpmd can not be secondary process but vdev_test can be. Signed-off-by: Itsuro Oda --- tools/vdev_test/Makefile | 25 ++++ tools/vdev_test/vdev_test.c | 235 ++++++++++++++++++++++++++++++++++++ 2 files changed, 260 insertions(+) create mode 100644 tools/vdev_test/Makefile create mode 100644 tools/vdev_test/vdev_test.c diff --git a/tools/vdev_test/Makefile b/tools/vdev_test/Makefile new file mode 100644 index 0000000..aabd9c4 --- /dev/null +++ b/tools/vdev_test/Makefile @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2020 Nippon Telegraph and Telephone Corporation + +ifeq ($(RTE_SDK),) +$(error "Please define RTE_SDK environment variable") +endif + +# Default target, can be overridden by command line or environment +RTE_TARGET ?= x86_64-native-linuxapp-gcc + +include $(RTE_SDK)/mk/rte.vars.mk + +# binary name +APP = vdev_test + +# all source are stored in SRCS-y +SRCS-y := vdev_test.c + +CFLAGS += -O3 +CFLAGS += $(WERROR_FLAGS) + +SPP_DRIVERS_DIR = $(BASE_OUTPUT)/src/drivers +EXTRA_LDLIBS = -L$(SPP_DRIVERS_DIR)/vhost -L$(SPP_DRIVERS_DIR)/pipe --whole-archive -lrte_pmd_spp_vhost -lrte_pmd_spp_pipe --no-whole-archive + +include $(RTE_SDK)/mk/rte.extapp.mk diff --git a/tools/vdev_test/vdev_test.c b/tools/vdev_test/vdev_test.c new file mode 100644 index 0000000..138b67c --- /dev/null +++ b/tools/vdev_test/vdev_test.c @@ -0,0 +1,235 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2019 Nippon Telegraph and Telephone Corporation + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define RING_SIZE 128 +#define BURST_SIZE 32 +#define NUM_MBUFS 8191 +#define MBUF_CACHE_SIZE 512 + +#define PKTMBUF_POOL_NAME "MProc_pktmbuf_pool" + +static int tx_first; +static char *device; +static char *devargs; +static int force_quit; + +static struct option lopts[] = { + {"send", no_argument, &tx_first, 1}, + {"create", required_argument, NULL, 'c'}, + {NULL, 0, 0, 0} +}; + +static const struct rte_eth_conf port_conf_default = { + .rxmode = { .max_rx_pkt_len = RTE_ETHER_MAX_LEN } +}; + +static int +parse_args(int argc, char *argv[]) +{ + int c; + + while ((c = getopt_long(argc, argv, "", lopts, NULL)) != -1) { + switch (c) { + case 0: + /* long option */ + break; + case 'c': + /* --create */ + devargs = optarg; + break; + default: + /* invalid option */ + return -1; + } + } + + if (optind != argc - 1) + return -1; + + device = argv[optind]; + + return 0; +} + +static void +signal_handler(int signum) +{ + printf("signel %d received\n", signum); + force_quit = 1; +} + +int +main(int argc, char *argv[]) +{ + int ret; + uint16_t port_id; + uint16_t nb_ports; + struct rte_mempool *mbuf_pool = NULL; + struct rte_mbuf *m; + uint16_t nb_tx; + struct rte_mbuf *bufs[BURST_SIZE]; + uint16_t nb_rx; + struct rte_eth_conf port_conf = port_conf_default; + struct rte_eth_stats stats; + struct timeval t0, t1; + long total; + uint16_t buf; + int i; + + ret = rte_eal_init(argc, argv); + if (ret < 0) + rte_exit(EXIT_FAILURE, "EAL initialization failed\n"); + argc -= ret; + argv += ret; + + ret = parse_args(argc, argv); + if (ret < 0) { + rte_exit(EXIT_FAILURE, + "usage: vdev_test -- " + "[--send] [--create devargs] vdev\n"); + } + printf("device: %s tx_first: %d devargs: %s\n", device, + tx_first, devargs); + + if (strncmp("spp_pipe", device, 8) == 0) { + if (rte_eal_process_type() != RTE_PROC_SECONDARY) + rte_exit(EXIT_FAILURE, "must be secondary\n"); + } + + if (devargs) { + /* --create */ + ret = rte_eth_dev_get_port_by_name(device, &port_id); + if (ret == 0) + rte_exit(EXIT_FAILURE, + "%s already exists.\n", device); + for (i = 0; i < 3; i++) { + ret = rte_eal_hotplug_add("vdev", device, devargs); + if (ret == 0) + break; + sleep(1); + } + if (ret < 0) + rte_exit(EXIT_FAILURE, + "%s %s create failed.\n", device, devargs); + } + + ret = rte_eth_dev_get_port_by_name(device, &port_id); + if (ret < 0) + rte_exit(EXIT_FAILURE, "device not found\n"); + + printf("port_id: %u\n", (unsigned int)port_id); + + nb_ports = rte_eth_dev_count_avail(); + /* just information */ + printf("num port: %u\n", (unsigned int)nb_ports); + + if (rte_eal_process_type() == RTE_PROC_SECONDARY) { + mbuf_pool = rte_mempool_lookup(PKTMBUF_POOL_NAME); + } else { + mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS, + MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, + rte_socket_id()); + } + if (mbuf_pool == NULL) + rte_exit(EXIT_FAILURE, "Cannot get mbuf pool\n"); + + if (strncmp("virtio_user", device, 11) == 0) + port_conf.intr_conf.lsc = 1; + + ret = rte_eth_dev_configure(port_id, 1, 1, &port_conf); + if (ret != 0) + rte_exit(EXIT_FAILURE, "rte_eth_dev_configure failed\n"); + + ret = rte_eth_rx_queue_setup(port_id, 0, RING_SIZE, + rte_eth_dev_socket_id(port_id), NULL, mbuf_pool); + if (ret < 0) + rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup failed\n"); + + ret = rte_eth_tx_queue_setup(port_id, 0, RING_SIZE, + rte_eth_dev_socket_id(port_id), NULL); + if (ret < 0) + rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup failed\n"); + + ret = rte_eth_dev_start(port_id); + if (ret < 0) + rte_exit(EXIT_FAILURE, "rte_eth_dev_start failed\n"); + + force_quit = 0; + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); + + if (tx_first) { + /* send a packet */ + m = rte_pktmbuf_alloc(mbuf_pool); + if (m == NULL) { + fprintf(stderr, "rte_pktmbuf_alloc failed\n"); + goto out; + } + if (rte_pktmbuf_append(m, RTE_ETHER_MIN_LEN) == NULL) { + fprintf(stderr, "rte_pktmbuf_append failed\n"); + goto out; + } + + nb_tx = rte_eth_tx_burst(port_id, 0, &m, 1); + if (nb_tx != 1) { + fprintf(stderr, "can not send a packet\n"); + rte_pktmbuf_free(m); + goto out; + } + printf("send a packet\n"); + gettimeofday(&t0, NULL); + } + + /* receive and send a packet */ + while (!force_quit) { + nb_rx = rte_eth_rx_burst(port_id, 0, bufs, BURST_SIZE); + if (nb_rx > 0) { + nb_tx = rte_eth_tx_burst(port_id, 0, bufs, nb_rx); + for (buf = nb_tx; buf < nb_rx; buf++) + rte_pktmbuf_free(bufs[buf]); + } + } + + gettimeofday(&t1, NULL); + + ret = rte_eth_stats_get(port_id, &stats); + if (ret == 0) { + printf("ipackets: %lu\n", stats.ipackets); + printf("opackets: %lu\n", stats.opackets); + printf("ierrors: %lu\n", stats.ierrors); + printf("oerrors: %lu\n", stats.oerrors); + if (tx_first) { + total = (t1.tv_sec - t0.tv_sec) * 1000000 + + t1.tv_usec - t0.tv_usec; + printf("%ld us: %.2f packet/s\n", total, + (double)stats.ipackets / total * 1000000); + } + } + +out: + rte_eth_dev_stop(port_id); + rte_eth_dev_close(port_id); + + if (devargs) + rte_eal_hotplug_remove("vdev", device); + + return 0; +} -- 2.17.1