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 219EBA32A2 for ; Thu, 24 Oct 2019 15:34:56 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 421C11EAB5; Thu, 24 Oct 2019 15:34:45 +0200 (CEST) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by dpdk.org (Postfix) with ESMTP id 904BD1EA9D; Thu, 24 Oct 2019 15:34:36 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 24 Oct 2019 06:34:35 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.68,224,1569308400"; d="scan'208";a="228514264" Received: from silpixa00399953.ir.intel.com (HELO silpixa00399953.ger.corp.intel.com) ([10.237.223.218]) by fmsmga002.fm.intel.com with ESMTP; 24 Oct 2019 06:34:34 -0700 From: Ciara Power To: dev@dpdk.org Cc: techboard@dpdk.org, Bruce Richardson Date: Thu, 24 Oct 2019 14:31:41 +0100 Message-Id: <20191024133145.12246-3-ciara.power@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191024133145.12246-1-ciara.power@intel.com> References: <20191003131918.30970-1-bruce.richardson@intel.com> <20191024133145.12246-1-ciara.power@intel.com> Subject: [dpdk-dev] [PATCH v2 2/6] examples/exception_path: remove example from DPDK X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Bruce Richardson The example app shows the use of TUN/TAP with DPDK, but DPDK has a built-in TAP PMD, so this example is obsolete and so can be removed. Signed-off-by: Bruce Richardson Acked-by: Stephen Hemminger Acked-by: Hemant Agrawal --- MAINTAINERS | 3 - doc/guides/sample_app_ug/exception_path.rst | 281 ---------- doc/guides/sample_app_ug/index.rst | 1 - examples/Makefile | 1 - examples/exception_path/Makefile | 57 -- examples/exception_path/main.c | 589 -------------------- examples/exception_path/meson.build | 11 - examples/meson.build | 2 +- 8 files changed, 1 insertion(+), 944 deletions(-) delete mode 100644 doc/guides/sample_app_ug/exception_path.rst delete mode 100644 examples/exception_path/Makefile delete mode 100644 examples/exception_path/main.c delete mode 100644 examples/exception_path/meson.build diff --git a/MAINTAINERS b/MAINTAINERS index b3d9aaddd..330a4d77d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1427,9 +1427,6 @@ Other Example Applications F: examples/ethtool/ F: doc/guides/sample_app_ug/ethtool.rst -F: examples/exception_path/ -F: doc/guides/sample_app_ug/exception_path.rst - M: Marko Kovacevic F: examples/fips_validation/ F: doc/guides/sample_app_ug/fips_validation.rst diff --git a/doc/guides/sample_app_ug/exception_path.rst b/doc/guides/sample_app_ug/exception_path.rst deleted file mode 100644 index a5590870c..000000000 --- a/doc/guides/sample_app_ug/exception_path.rst +++ /dev/null @@ -1,281 +0,0 @@ -.. SPDX-License-Identifier: BSD-3-Clause - Copyright(c) 2010-2014 Intel Corporation. - -Exception Path Sample Application -================================= - -The Exception Path sample application is a simple example that demonstrates the use of the DPDK -to set up an exception path for packets to go through the Linux* kernel. -This is done by using virtual TAP network interfaces. -These can be read from and written to by the DPDK application and -appear to the kernel as a standard network interface. - -Overview --------- - -The application creates two threads for each NIC port being used. -One thread reads from the port and writes the data unmodified to a thread-specific TAP interface. -The second thread reads from a TAP interface and writes the data unmodified to the NIC port. - -The packet flow through the exception path application is as shown in the following figure. - -.. _figure_exception_path_example: - -.. figure:: img/exception_path_example.* - - Packet Flow - - -To make throughput measurements, kernel bridges must be setup to forward data between the bridges appropriately. - -Compiling the Application -------------------------- - -To compile the sample application see :doc:`compiling`. - -The application is located in the ``exception_path`` sub-directory. - -Running the Application ------------------------ - -The application requires a number of command line options: - -.. code-block:: console - - .build/exception_path [EAL options] -- -p PORTMASK -i IN_CORES -o OUT_CORES - -where: - -* -p PORTMASK: A hex bitmask of ports to use - -* -i IN_CORES: A hex bitmask of cores which read from NIC - -* -o OUT_CORES: A hex bitmask of cores which write to NIC - -Refer to the *DPDK Getting Started Guide* for general information on running applications -and the Environment Abstraction Layer (EAL) options. - -The number of bits set in each bitmask must be the same. -The coremask -c or the corelist -l parameter of the EAL options should include IN_CORES and OUT_CORES. -The same bit must not be set in IN_CORES and OUT_CORES. -The affinities between ports and cores are set beginning with the least significant bit of each mask, that is, -the port represented by the lowest bit in PORTMASK is read from by the core represented by the lowest bit in IN_CORES, -and written to by the core represented by the lowest bit in OUT_CORES. - -For example to run the application with two ports and four cores: - -.. code-block:: console - - ./build/exception_path -l 0-3 -n 4 -- -p 3 -i 3 -o c - -Getting Statistics -~~~~~~~~~~~~~~~~~~ - -While the application is running, statistics on packets sent and -received can be displayed by sending the SIGUSR1 signal to the application from another terminal: - -.. code-block:: console - - killall -USR1 exception_path - -The statistics can be reset by sending a SIGUSR2 signal in a similar way. - -Explanation ------------ - -The following sections provide some explanation of the code. - -Initialization -~~~~~~~~~~~~~~ - -Setup of the mbuf pool, driver and queues is similar to the setup done in the :ref:`l2_fwd_app_real_and_virtual`. -In addition, the TAP interfaces must also be created. -A TAP interface is created for each lcore that is being used. -The code for creating the TAP interface is as follows: - -.. code-block:: c - - /* - * Create a tap network interface, or use existing one with same name. - * If name[0]='\0' then a name is automatically assigned and returned in name. - */ - - static int tap_create(char *name) - { - struct ifreq ifr; - int fd, ret; - - fd = open("/dev/net/tun", O_RDWR); - if (fd < 0) - return fd; - - memset(&ifr, 0, sizeof(ifr)); - - /* TAP device without packet information */ - - ifr.ifr_flags = IFF_TAP | IFF_NO_PI; - if (name && *name) - rte_snprinf(ifr.ifr_name, IFNAMSIZ, name); - - ret = ioctl(fd, TUNSETIFF, (void *) &ifr); - - if (ret < 0) { - close(fd); - return ret; - - } - - if (name) - snprintf(name, IFNAMSIZ, ifr.ifr_name); - - return fd; - } - -The other step in the initialization process that is unique to this sample application -is the association of each port with two cores: - -* One core to read from the port and write to a TAP interface - -* A second core to read from a TAP interface and write to the port - -This is done using an array called port_ids[], which is indexed by the lcore IDs. -The population of this array is shown below: - -.. code-block:: c - - tx_port = 0; - rx_port = 0; - - RTE_LCORE_FOREACH(i) { - if (input_cores_mask & (1ULL << i)) { - /* Skip ports that are not enabled */ - while ((ports_mask & (1 << rx_port)) == 0) { - rx_port++; - if (rx_port > (sizeof(ports_mask) * 8)) - goto fail; /* not enough ports */ - } - port_ids[i] = rx_port++; - } else if (output_cores_mask & (1ULL << i)) { - /* Skip ports that are not enabled */ - while ((ports_mask & (1 << tx_port)) == 0) { - tx_port++; - if (tx_port > (sizeof(ports_mask) * 8)) - goto fail; /* not enough ports */ - } - port_ids[i] = tx_port++; - } - } - -Packet Forwarding -~~~~~~~~~~~~~~~~~ - -After the initialization steps are complete, the main_loop() function is run on each lcore. -This function first checks the lcore_id against the user provided input_cores_mask and output_cores_mask to see -if this core is reading from or writing to a TAP interface. - -For the case that reads from a NIC port, the packet reception is the same as in the L2 Forwarding sample application -(see :ref:`l2_fwd_app_rx_tx_packets`). -The packet transmission is done by calling write() with the file descriptor of the appropriate TAP interface -and then explicitly freeing the mbuf back to the pool. - -.. code-block:: c - - /* Loop forever reading from NIC and writing to tap */ - - for (;;) { - struct rte_mbuf *pkts_burst[PKT_BURST_SZ]; - unsigned i; - - const unsigned nb_rx = rte_eth_rx_burst(port_ids[lcore_id], 0, pkts_burst, PKT_BURST_SZ); - - lcore_stats[lcore_id].rx += nb_rx; - - for (i = 0; likely(i < nb_rx); i++) { - struct rte_mbuf *m = pkts_burst[i]; - int ret = write(tap_fd, rte_pktmbuf_mtod(m, void*), - - rte_pktmbuf_data_len(m)); - rte_pktmbuf_free(m); - if (unlikely(ret<0)) - lcore_stats[lcore_id].dropped++; - else - lcore_stats[lcore_id].tx++; - } - } - -For the other case that reads from a TAP interface and writes to a NIC port, -packets are retrieved by doing a read() from the file descriptor of the appropriate TAP interface. -This fills in the data into the mbuf, then other fields are set manually. -The packet can then be transmitted as normal. - -.. code-block:: c - - /* Loop forever reading from tap and writing to NIC */ - - for (;;) { - int ret; - struct rte_mbuf *m = rte_pktmbuf_alloc(pktmbuf_pool); - - if (m == NULL) - continue; - - ret = read(tap_fd, m->pkt.data, MAX_PACKET_SZ); lcore_stats[lcore_id].rx++; - if (unlikely(ret < 0)) { - FATAL_ERROR("Reading from %s interface failed", tap_name); - } - - m->pkt.nb_segs = 1; - m->pkt.next = NULL; - m->pkt.data_len = (uint16_t)ret; - - ret = rte_eth_tx_burst(port_ids[lcore_id], 0, &m, 1); - if (unlikely(ret < 1)) { - rte_pktmuf_free(m); - lcore_stats[lcore_id].dropped++; - } - else { - lcore_stats[lcore_id].tx++; - } - } - -To set up loops for measuring throughput, TAP interfaces can be connected using bridging. -The steps to do this are described in the section that follows. - -Managing TAP Interfaces and Bridges -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The Exception Path sample application creates TAP interfaces with names of the format tap_dpdk_nn, -where nn is the lcore ID. These TAP interfaces need to be configured for use: - -.. code-block:: console - - ifconfig tap_dpdk_00 up - -To set up a bridge between two interfaces so that packets sent to one interface can be read from another, -use the brctl tool: - -.. code-block:: console - - brctl addbr "br0" - brctl addif br0 tap_dpdk_00 - brctl addif br0 tap_dpdk_03 - ifconfig br0 up - -The TAP interfaces created by this application exist only when the application is running, -so the steps above need to be repeated each time the application is run. -To avoid this, persistent TAP interfaces can be created using openvpn: - -.. code-block:: console - - openvpn --mktun --dev tap_dpdk_00 - -If this method is used, then the steps above have to be done only once and -the same TAP interfaces can be reused each time the application is run. -To remove bridges and persistent TAP interfaces, the following commands are used: - -.. code-block:: console - - ifconfig br0 down - brctl delbr br0 - openvpn --rmtun --dev tap_dpdk_00 - diff --git a/doc/guides/sample_app_ug/index.rst b/doc/guides/sample_app_ug/index.rst index f23f8f59e..076346a60 100644 --- a/doc/guides/sample_app_ug/index.rst +++ b/doc/guides/sample_app_ug/index.rst @@ -12,7 +12,6 @@ Sample Applications User Guides compiling cmd_line ethtool - exception_path hello_world skeleton rxtx_callbacks diff --git a/examples/Makefile b/examples/Makefile index de11dd487..c756497d1 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -17,7 +17,6 @@ ifeq ($(CONFIG_RTE_LIBRTE_POWER),y) DIRS-$(CONFIG_RTE_LIBRTE_DISTRIBUTOR) += distributor endif DIRS-y += ethtool -DIRS-y += exception_path DIRS-$(CONFIG_RTE_LIBRTE_EFD) += server_node_efd DIRS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += fips_validation DIRS-$(CONFIG_RTE_LIBRTE_FLOW_CLASSIFY) += flow_classify diff --git a/examples/exception_path/Makefile b/examples/exception_path/Makefile deleted file mode 100644 index 90c7f133a..000000000 --- a/examples/exception_path/Makefile +++ /dev/null @@ -1,57 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2010-2014 Intel Corporation - -# binary name -APP = exception_path - -# all source are stored in SRCS-y -SRCS-y := main.c - -# Build using pkg-config variables if possible -ifeq ($(shell pkg-config --exists libdpdk && echo 0),0) - -all: shared -.PHONY: shared static -shared: build/$(APP)-shared - ln -sf $(APP)-shared build/$(APP) -static: build/$(APP)-static - ln -sf $(APP)-static build/$(APP) - -PKGCONF=pkg-config --define-prefix - -PC_FILE := $(shell $(PKGCONF) --path libdpdk) -CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk) -LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk) -LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk) - -build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build - $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED) - -build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build - $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC) - -build: - @mkdir -p $@ - -.PHONY: clean -clean: - rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared - test -d build && rmdir -p build || true - -else - -ifeq ($(RTE_SDK),) -$(error "Please define RTE_SDK environment variable") -endif - -# Default target, detect a build directory, by looking for a path with a .config -RTE_TARGET ?= $(notdir $(abspath $(dir $(firstword $(wildcard $(RTE_SDK)/*/.config))))) - -include $(RTE_SDK)/mk/rte.vars.mk - -CFLAGS += -O3 -CFLAGS += $(WERROR_FLAGS) - -include $(RTE_SDK)/mk/rte.extapp.mk - -endif diff --git a/examples/exception_path/main.c b/examples/exception_path/main.c deleted file mode 100644 index 0d79e5a24..000000000 --- a/examples/exception_path/main.c +++ /dev/null @@ -1,589 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#ifdef RTE_EXEC_ENV_LINUX -#include -#endif -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef APP_MAX_LCORE -#if (RTE_MAX_LCORE > 64) -#define APP_MAX_LCORE 64 -#else -#define APP_MAX_LCORE RTE_MAX_LCORE -#endif -#endif - -/* Macros for printing using RTE_LOG */ -#define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1 -#define FATAL_ERROR(fmt, args...) rte_exit(EXIT_FAILURE, fmt "\n", ##args) -#define PRINT_INFO(fmt, args...) RTE_LOG(INFO, APP, fmt "\n", ##args) - -/* Max ports than can be used (each port is associated with two lcores) */ -#define MAX_PORTS (APP_MAX_LCORE / 2) - -/* Max size of a single packet */ -#define MAX_PACKET_SZ (2048) - -/* Size of the data buffer in each mbuf */ -#define MBUF_DATA_SZ (MAX_PACKET_SZ + RTE_PKTMBUF_HEADROOM) - -/* Number of mbufs in mempool that is created */ -#define NB_MBUF 8192 - -/* How many packets to attempt to read from NIC in one go */ -#define PKT_BURST_SZ 32 - -/* How many objects (mbufs) to keep in per-lcore mempool cache */ -#define MEMPOOL_CACHE_SZ PKT_BURST_SZ - -/* Number of RX ring descriptors */ -#define NB_RXD 1024 - -/* Number of TX ring descriptors */ -#define NB_TXD 1024 - -/* - * RX and TX Prefetch, Host, and Write-back threshold values should be - * carefully set for optimal performance. Consult the network - * controller's datasheet and supporting DPDK documentation for guidance - * on how these parameters should be set. - */ - -/* Options for configuring ethernet port */ -static struct rte_eth_conf port_conf = { - .txmode = { - .mq_mode = ETH_MQ_TX_NONE, - }, -}; - -/* Mempool for mbufs */ -static struct rte_mempool * pktmbuf_pool = NULL; - -/* Mask of enabled ports */ -static uint32_t ports_mask = 0; - -/* Mask of cores that read from NIC and write to tap */ -static uint64_t input_cores_mask = 0; - -/* Mask of cores that read from tap and write to NIC */ -static uint64_t output_cores_mask = 0; - -/* Array storing port_id that is associated with each lcore */ -static uint16_t port_ids[APP_MAX_LCORE]; - -/* Structure type for recording lcore-specific stats */ -struct stats { - uint64_t rx; - uint64_t tx; - uint64_t dropped; -} __rte_cache_aligned; - -/* Array of lcore-specific stats */ -static struct stats lcore_stats[APP_MAX_LCORE]; - -/* Print out statistics on packets handled */ -static void -print_stats(void) -{ - unsigned i; - - printf("\n**Exception-Path example application statistics**\n" - "======= ====== ============ ============ ===============\n" - " Lcore Port RX TX Dropped on TX\n" - "------- ------ ------------ ------------ ---------------\n"); - RTE_LCORE_FOREACH(i) { - /* limit ourselves to application supported cores only */ - if (i >= APP_MAX_LCORE) - break; - printf("%6u %7u %13"PRIu64" %13"PRIu64" %16"PRIu64"\n", - i, (unsigned)port_ids[i], - lcore_stats[i].rx, lcore_stats[i].tx, - lcore_stats[i].dropped); - } - printf("======= ====== ============ ============ ===============\n"); -} - -/* Custom handling of signals to handle stats */ -static void -signal_handler(int signum) -{ - /* When we receive a USR1 signal, print stats */ - if (signum == SIGUSR1) { - print_stats(); - } - - /* When we receive a USR2 signal, reset stats */ - if (signum == SIGUSR2) { - memset(&lcore_stats, 0, sizeof(lcore_stats)); - printf("\n**Statistics have been reset**\n"); - return; - } -} - -#ifdef RTE_EXEC_ENV_LINUX -/* - * Create a tap network interface, or use existing one with same name. - * If name[0]='\0' then a name is automatically assigned and returned in name. - */ -static int tap_create(char *name) -{ - struct ifreq ifr; - int fd, ret; - - fd = open("/dev/net/tun", O_RDWR); - if (fd < 0) - return fd; - - memset(&ifr, 0, sizeof(ifr)); - - /* TAP device without packet information */ - ifr.ifr_flags = IFF_TAP | IFF_NO_PI; - - if (name && *name) - strlcpy(ifr.ifr_name, name, IFNAMSIZ); - - ret = ioctl(fd, TUNSETIFF, (void *) &ifr); - if (ret < 0) { - close(fd); - return ret; - } - - if (name) - strlcpy(name, ifr.ifr_name, IFNAMSIZ); - - return fd; -} -#else -/* - * Find a free tap network interface, or create a new one. - * The name is automatically assigned and returned in name. - */ -static int tap_create(char *name) -{ - int i, fd = -1; - char devname[PATH_MAX]; - - for (i = 0; i < 255; i++) { - snprintf(devname, sizeof(devname), "/dev/tap%d", i); - fd = open(devname, O_RDWR); - if (fd >= 0 || errno != EBUSY) - break; - } - - if (name) - snprintf(name, IFNAMSIZ, "tap%d", i); - - return fd; -} -#endif - -/* Main processing loop */ -static int -main_loop(__attribute__((unused)) void *arg) -{ - const unsigned lcore_id = rte_lcore_id(); - char tap_name[IFNAMSIZ]; - int tap_fd; - - if ((1ULL << lcore_id) & input_cores_mask) { - /* Create new tap interface */ - snprintf(tap_name, IFNAMSIZ, "tap_dpdk_%.2u", lcore_id); - tap_fd = tap_create(tap_name); - if (tap_fd < 0) - FATAL_ERROR("Could not create tap interface \"%s\" (%d)", - tap_name, tap_fd); - - PRINT_INFO("Lcore %u is reading from port %u and writing to %s", - lcore_id, (unsigned)port_ids[lcore_id], tap_name); - fflush(stdout); - /* Loop forever reading from NIC and writing to tap */ - for (;;) { - struct rte_mbuf *pkts_burst[PKT_BURST_SZ]; - unsigned i; - const unsigned nb_rx = - rte_eth_rx_burst(port_ids[lcore_id], 0, - pkts_burst, PKT_BURST_SZ); - lcore_stats[lcore_id].rx += nb_rx; - for (i = 0; likely(i < nb_rx); i++) { - struct rte_mbuf *m = pkts_burst[i]; - /* Ignore return val from write() */ - int ret = write(tap_fd, - rte_pktmbuf_mtod(m, void*), - rte_pktmbuf_data_len(m)); - rte_pktmbuf_free(m); - if (unlikely(ret < 0)) - lcore_stats[lcore_id].dropped++; - else - lcore_stats[lcore_id].tx++; - } - } - } - else if ((1ULL << lcore_id) & output_cores_mask) { - /* Create new tap interface */ - snprintf(tap_name, IFNAMSIZ, "tap_dpdk_%.2u", lcore_id); - tap_fd = tap_create(tap_name); - if (tap_fd < 0) - FATAL_ERROR("Could not create tap interface \"%s\" (%d)", - tap_name, tap_fd); - - PRINT_INFO("Lcore %u is reading from %s and writing to port %u", - lcore_id, tap_name, (unsigned)port_ids[lcore_id]); - fflush(stdout); - /* Loop forever reading from tap and writing to NIC */ - for (;;) { - int ret; - struct rte_mbuf *m = rte_pktmbuf_alloc(pktmbuf_pool); - if (m == NULL) - continue; - - ret = read(tap_fd, rte_pktmbuf_mtod(m, void *), - MAX_PACKET_SZ); - lcore_stats[lcore_id].rx++; - if (unlikely(ret < 0)) { - FATAL_ERROR("Reading from %s interface failed", - tap_name); - } - m->nb_segs = 1; - m->next = NULL; - m->pkt_len = (uint16_t)ret; - m->data_len = (uint16_t)ret; - ret = rte_eth_tx_burst(port_ids[lcore_id], 0, &m, 1); - if (unlikely(ret < 1)) { - rte_pktmbuf_free(m); - lcore_stats[lcore_id].dropped++; - } - else { - lcore_stats[lcore_id].tx++; - } - } - } - else { - PRINT_INFO("Lcore %u has nothing to do", lcore_id); - return 0; - } - /* - * Tap file is closed automatically when program exits. Putting close() - * here will cause the compiler to give an error about unreachable code. - */ -} - -/* Display usage instructions */ -static void -print_usage(const char *prgname) -{ - PRINT_INFO("\nUsage: %s [EAL options] -- -p PORTMASK -i IN_CORES -o OUT_CORES\n" - " -p PORTMASK: hex bitmask of ports to use\n" - " -i IN_CORES: hex bitmask of cores which read from NIC\n" - " -o OUT_CORES: hex bitmask of cores which write to NIC", - prgname); -} - -/* Convert string to unsigned number. 0 is returned if error occurs */ -static uint64_t -parse_unsigned(const char *portmask) -{ - char *end = NULL; - uint64_t num; - - num = strtoull(portmask, &end, 16); - if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) - return 0; - - return (uint64_t)num; -} - -/* Record affinities between ports and lcores in global port_ids[] array */ -static void -setup_port_lcore_affinities(void) -{ - unsigned long i; - uint16_t tx_port = 0; - uint16_t rx_port = 0; - - /* Setup port_ids[] array, and check masks were ok */ - for (i = 0; i < APP_MAX_LCORE; i++) { - if (!rte_lcore_is_enabled(i)) - continue; - if (input_cores_mask & (1ULL << i)) { - /* Skip ports that are not enabled */ - while ((ports_mask & (1 << rx_port)) == 0) { - rx_port++; - if (rx_port > (sizeof(ports_mask) * 8)) - goto fail; /* not enough ports */ - } - - port_ids[i] = rx_port++; - } else if (output_cores_mask & (1ULL << (i & 0x3f))) { - /* Skip ports that are not enabled */ - while ((ports_mask & (1 << tx_port)) == 0) { - tx_port++; - if (tx_port > (sizeof(ports_mask) * 8)) - goto fail; /* not enough ports */ - } - - port_ids[i] = tx_port++; - } - } - - if (rx_port != tx_port) - goto fail; /* uneven number of cores in masks */ - - if (ports_mask & (~((1 << rx_port) - 1))) - goto fail; /* unused ports */ - - return; -fail: - FATAL_ERROR("Invalid core/port masks specified on command line"); -} - -/* Parse the arguments given in the command line of the application */ -static void -parse_args(int argc, char **argv) -{ - int opt; - const char *prgname = argv[0]; - - /* Disable printing messages within getopt() */ - opterr = 0; - - /* Parse command line */ - while ((opt = getopt(argc, argv, "i:o:p:")) != EOF) { - switch (opt) { - case 'i': - input_cores_mask = parse_unsigned(optarg); - break; - case 'o': - output_cores_mask = parse_unsigned(optarg); - break; - case 'p': - ports_mask = parse_unsigned(optarg); - break; - default: - print_usage(prgname); - FATAL_ERROR("Invalid option specified"); - } - } - - /* Check that options were parsed ok */ - if (input_cores_mask == 0) { - print_usage(prgname); - FATAL_ERROR("IN_CORES not specified correctly"); - } - if (output_cores_mask == 0) { - print_usage(prgname); - FATAL_ERROR("OUT_CORES not specified correctly"); - } - if (ports_mask == 0) { - print_usage(prgname); - FATAL_ERROR("PORTMASK not specified correctly"); - } - - setup_port_lcore_affinities(); -} - -/* Initialise a single port on an Ethernet device */ -static void -init_port(uint16_t port) -{ - int ret; - uint16_t nb_rxd = NB_RXD; - uint16_t nb_txd = NB_TXD; - struct rte_eth_dev_info dev_info; - struct rte_eth_rxconf rxq_conf; - struct rte_eth_txconf txq_conf; - struct rte_eth_conf local_port_conf = port_conf; - - /* Initialise device and RX/TX queues */ - PRINT_INFO("Initialising port %u ...", port); - fflush(stdout); - rte_eth_dev_info_get(port, &dev_info); - if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) - local_port_conf.txmode.offloads |= - DEV_TX_OFFLOAD_MBUF_FAST_FREE; - ret = rte_eth_dev_configure(port, 1, 1, &local_port_conf); - if (ret < 0) - FATAL_ERROR("Could not configure port%u (%d)", port, ret); - - ret = rte_eth_dev_adjust_nb_rx_tx_desc(port, &nb_rxd, &nb_txd); - if (ret < 0) - FATAL_ERROR("Could not adjust number of descriptors for port%u (%d)", - port, ret); - - rxq_conf = dev_info.default_rxconf; - rxq_conf.offloads = local_port_conf.rxmode.offloads; - ret = rte_eth_rx_queue_setup(port, 0, nb_rxd, - rte_eth_dev_socket_id(port), - &rxq_conf, - pktmbuf_pool); - if (ret < 0) - FATAL_ERROR("Could not setup up RX queue for port%u (%d)", - port, ret); - - txq_conf = dev_info.default_txconf; - txq_conf.offloads = local_port_conf.txmode.offloads; - ret = rte_eth_tx_queue_setup(port, 0, nb_txd, - rte_eth_dev_socket_id(port), - &txq_conf); - if (ret < 0) - FATAL_ERROR("Could not setup up TX queue for port%u (%d)", - port, ret); - - ret = rte_eth_dev_start(port); - if (ret < 0) - FATAL_ERROR("Could not start port%u (%d)", port, ret); - - rte_eth_promiscuous_enable(port); -} - -/* 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 */ - uint16_t portid; - uint8_t count, all_ports_up, print_flag = 0; - struct rte_eth_link link; - - printf("\nChecking link status"); - 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", - portid, link.link_speed, - (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? - ("full-duplex") : ("half-duplex\n")); - else - printf("Port %d Link Down\n", 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) { - printf("."); - 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; - printf("done\n"); - } - } -} - -/* Initialise ports/queues etc. and start main loop on each core */ -int -main(int argc, char** argv) -{ - int ret; - unsigned i,high_port; - uint16_t nb_sys_ports, port; - - /* Associate signal_hanlder function with USR signals */ - signal(SIGUSR1, signal_handler); - signal(SIGUSR2, signal_handler); - - /* Initialise EAL */ - ret = rte_eal_init(argc, argv); - if (ret < 0) - FATAL_ERROR("Could not initialise EAL (%d)", ret); - argc -= ret; - argv += ret; - - /* Parse application arguments (after the EAL ones) */ - parse_args(argc, argv); - - /* Create the mbuf pool */ - pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF, - MEMPOOL_CACHE_SZ, 0, MBUF_DATA_SZ, rte_socket_id()); - if (pktmbuf_pool == NULL) { - FATAL_ERROR("Could not initialise mbuf pool"); - return -1; - } - - /* Get number of ports found in scan */ - nb_sys_ports = rte_eth_dev_count_avail(); - if (nb_sys_ports == 0) - FATAL_ERROR("No supported Ethernet device found"); - /* Find highest port set in portmask */ - for (high_port = (sizeof(ports_mask) * 8) - 1; - (high_port != 0) && !(ports_mask & (1 << high_port)); - high_port--) - ; /* empty body */ - if (high_port > nb_sys_ports) - FATAL_ERROR("Port mask requires more ports than available"); - - /* Initialise each port */ - RTE_ETH_FOREACH_DEV(port) { - /* Skip ports that are not enabled */ - if ((ports_mask & (1 << port)) == 0) { - continue; - } - init_port(port); - } - check_all_ports_link_status(ports_mask); - - /* Launch per-lcore function on every lcore */ - rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER); - RTE_LCORE_FOREACH_SLAVE(i) { - if (rte_eal_wait_lcore(i) < 0) - return -1; - } - - return 0; -} diff --git a/examples/exception_path/meson.build b/examples/exception_path/meson.build deleted file mode 100644 index c34e11e36..000000000 --- a/examples/exception_path/meson.build +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2017 Intel Corporation - -# meson file, for building this example as part of a main DPDK build. -# -# To build this example as a standalone application with an already-installed -# DPDK instance, use 'make' - -sources = files( - 'main.c' -) diff --git a/examples/meson.build b/examples/meson.build index a046b74ad..4663d9dea 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -13,7 +13,7 @@ all_examples = [ 'bbdev_app', 'bond', 'bpf', 'cmdline', 'distributor', 'ethtool', - 'eventdev_pipeline', 'exception_path', + 'eventdev_pipeline', 'fips_validation', 'flow_classify', 'flow_filtering', 'helloworld', 'ip_fragmentation', 'ip_pipeline', -- 2.17.1