From patchwork Thu Oct 3 13:19:13 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bruce Richardson X-Patchwork-Id: 60492 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id F2D531C0DB; Thu, 3 Oct 2019 15:19:33 +0200 (CEST) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by dpdk.org (Postfix) with ESMTP id 3CB1F1C0D8; Thu, 3 Oct 2019 15:19:31 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 03 Oct 2019 06:19:30 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.67,252,1566889200"; d="scan'208";a="185910445" Received: from silpixa00399126.ir.intel.com (HELO silpixa00399126.ger.corp.intel.com) ([10.237.223.2]) by orsmga008.jf.intel.com with ESMTP; 03 Oct 2019 06:19:28 -0700 From: Bruce Richardson To: dev@dpdk.org Cc: techboard@dpdk.org, Bruce Richardson Date: Thu, 3 Oct 2019 14:19:13 +0100 Message-Id: <20191003131918.30970-2-bruce.richardson@intel.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191003131918.30970-1-bruce.richardson@intel.com> References: <20191003131918.30970-1-bruce.richardson@intel.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH 1/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" 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 --- MAINTAINERS | 3 - doc/guides/sample_app_ug/exception_path.rst | 281 ---------- doc/guides/sample_app_ug/index.rst | 1 - doc/guides/sample_app_ug/intro.rst | 2 +- examples/Makefile | 1 - examples/exception_path/Makefile | 57 -- examples/exception_path/main.c | 589 -------------------- examples/exception_path/meson.build | 11 - examples/meson.build | 2 +- 9 files changed, 2 insertions(+), 945 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/doc/guides/sample_app_ug/intro.rst b/doc/guides/sample_app_ug/intro.rst index 90704194a..7299253bf 100644 --- a/doc/guides/sample_app_ug/intro.rst +++ b/doc/guides/sample_app_ug/intro.rst @@ -39,7 +39,7 @@ applications that are available in the examples directory of DPDK: +---------------------------------------+--------------------------------------+ | Ethtool | Precision Time Protocol (PTP) Client | +---------------------------------------+--------------------------------------+ - | Exception Path | Quality of Service (QoS) Metering | + | | Quality of Service (QoS) Metering | +---------------------------------------+--------------------------------------+ | Hello World | QoS Scheduler | +---------------------------------------+--------------------------------------+ 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', From patchwork Thu Oct 3 13:19:14 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bruce Richardson X-Patchwork-Id: 60493 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id CA5B51C10E; Thu, 3 Oct 2019 15:19:36 +0200 (CEST) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by dpdk.org (Postfix) with ESMTP id 518471C0D8; Thu, 3 Oct 2019 15:19:33 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 03 Oct 2019 06:19:32 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.67,252,1566889200"; d="scan'208";a="185910485" Received: from silpixa00399126.ir.intel.com (HELO silpixa00399126.ger.corp.intel.com) ([10.237.223.2]) by orsmga008.jf.intel.com with ESMTP; 03 Oct 2019 06:19:30 -0700 From: Bruce Richardson To: dev@dpdk.org Cc: techboard@dpdk.org, Bruce Richardson Date: Thu, 3 Oct 2019 14:19:14 +0100 Message-Id: <20191003131918.30970-3-bruce.richardson@intel.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191003131918.30970-1-bruce.richardson@intel.com> References: <20191003131918.30970-1-bruce.richardson@intel.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH 2/6] examples/l3fwd-vf: 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" The main l3fwd app should work with both PF and VF devices, so remove the VF-only l3fwd example. Signed-off-by: Bruce Richardson --- MAINTAINERS | 3 - doc/guides/sample_app_ug/index.rst | 1 - .../sample_app_ug/l3_forward_virtual.rst | 98 -- examples/Makefile | 1 - examples/l3fwd-vf/Makefile | 62 - examples/l3fwd-vf/main.c | 1072 ----------------- examples/l3fwd-vf/meson.build | 12 - examples/meson.build | 2 +- 8 files changed, 1 insertion(+), 1250 deletions(-) delete mode 100644 doc/guides/sample_app_ug/l3_forward_virtual.rst delete mode 100644 examples/l3fwd-vf/Makefile delete mode 100644 examples/l3fwd-vf/main.c delete mode 100644 examples/l3fwd-vf/meson.build diff --git a/MAINTAINERS b/MAINTAINERS index 330a4d77d..92c3f6af4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1458,9 +1458,6 @@ F: examples/l2fwd-cat/ F: examples/l3fwd/ F: doc/guides/sample_app_ug/l3_forward.rst -F: examples/l3fwd-vf/ -F: doc/guides/sample_app_ug/l3_forward_virtual.rst - F: examples/link_status_interrupt/ F: doc/guides/sample_app_ug/link_status_intr.rst diff --git a/doc/guides/sample_app_ug/index.rst b/doc/guides/sample_app_ug/index.rst index 076346a60..d212f81fe 100644 --- a/doc/guides/sample_app_ug/index.rst +++ b/doc/guides/sample_app_ug/index.rst @@ -29,7 +29,6 @@ Sample Applications User Guides l3_forward l3_forward_power_man l3_forward_access_ctrl - l3_forward_virtual link_status_intr load_balancer server_node_efd diff --git a/doc/guides/sample_app_ug/l3_forward_virtual.rst b/doc/guides/sample_app_ug/l3_forward_virtual.rst deleted file mode 100644 index 21eab8da3..000000000 --- a/doc/guides/sample_app_ug/l3_forward_virtual.rst +++ /dev/null @@ -1,98 +0,0 @@ -.. SPDX-License-Identifier: BSD-3-Clause - Copyright(c) 2010-2014 Intel Corporation. - -L3 Forwarding in a Virtualization Environment Sample Application -================================================================ - -The L3 Forwarding in a Virtualization Environment sample application is a simple example of packet processing using the DPDK. -The application performs L3 forwarding that takes advantage of Single Root I/O Virtualization (SR-IOV) features -in a virtualized environment. - -Overview --------- - -The application demonstrates the use of the hash and LPM libraries in the DPDK to implement packet forwarding. -The initialization and run-time paths are very similar to those of the :doc:`l3_forward`. -The forwarding decision is taken based on information read from the input packet. - -The lookup method is either hash-based or LPM-based and is selected at compile time. -When the selected lookup method is hash-based, a hash object is used to emulate the flow classification stage. -The hash object is used in correlation with the flow table to map each input packet to its flow at runtime. - -The hash lookup key is represented by the DiffServ 5-tuple composed of the following fields read from the input packet: -Source IP Address, Destination IP Address, Protocol, Source Port and Destination Port. -The ID of the output interface for the input packet is read from the identified flow table entry. -The set of flows used by the application is statically configured and loaded into the hash at initialization time. -When the selected lookup method is LPM based, an LPM object is used to emulate the forwarding stage for IPv4 packets. -The LPM object is used as the routing table to identify the next hop for each input packet at runtime. - -The LPM lookup key is represented by the Destination IP Address field read from the input packet. -The ID of the output interface for the input packet is the next hop returned by the LPM lookup. -The set of LPM rules used by the application is statically configured and loaded into the LPM object at the initialization time. - -.. note:: - - Please refer to :ref:`l2_fwd_vf_setup` for virtualized test case setup. - -Compiling the Application -------------------------- - -To compile the sample application see :doc:`compiling`. - -The application is located in the ``l3fwd-vf`` sub-directory. - -Running the Application ------------------------ - -The application has a number of command line options: - -.. code-block:: console - - ./build/l3fwd-vf [EAL options] -- -p PORTMASK --config(port,queue,lcore)[,(port,queue,lcore)] [--no-numa] - -where, - -* --p PORTMASK: Hexadecimal bitmask of ports to configure - -* --config (port,queue,lcore)[,(port,queue,lcore]: determines which queues from which ports are mapped to which cores - -* --no-numa: optional, disables numa awareness - -For example, consider a dual processor socket platform with 8 physical cores, where cores 0-7 and 16-23 appear on socket 0, -while cores 8-15 and 24-31 appear on socket 1. - -To enable L3 forwarding between two ports, assuming that both ports are in the same socket, using two cores, cores 1 and 2, -(which are in the same socket too), use the following command: - -.. code-block:: console - - ./build/l3fwd-vf -l 1,2 -n 4 -- -p 0x3 --config="(0,0,1),(1,0,2)" - -In this command: - -* The -l option enables cores 1 and 2 - -* The -p option enables ports 0 and 1 - -* The --config option enables one queue on each port and maps each (port,queue) pair to a specific core. - The following table shows the mapping in this example: - - +----------+-----------+-----------+------------------------------------+ - | **Port** | **Queue** | **lcore** | **Description** | - | | | | | - +==========+===========+===========+====================================+ - | 0 | 0 | 1 | Map queue 0 from port 0 to lcore 1 | - | | | | | - +----------+-----------+-----------+------------------------------------+ - | 1 | 0 | 2 | Map queue 0 from port 1 to lcore 2 | - | | | | | - +----------+-----------+-----------+------------------------------------+ - -Refer to the *DPDK Getting Started Guide* for general information on running applications -and the Environment Abstraction Layer (EAL) options. - -Explanation ------------ - -The operation of this application is similar to that of the basic L3 Forwarding Sample Application. -See :ref:`l3_fwd_explanation` for more information. diff --git a/examples/Makefile b/examples/Makefile index c756497d1..5dd8a72e5 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -46,7 +46,6 @@ endif DIRS-$(CONFIG_RTE_LIBRTE_ACL) += l3fwd-acl ifeq ($(CONFIG_RTE_LIBRTE_LPM)$(CONFIG_RTE_LIBRTE_HASH),yy) DIRS-$(CONFIG_RTE_LIBRTE_POWER) += l3fwd-power -DIRS-y += l3fwd-vf endif DIRS-y += link_status_interrupt DIRS-$(CONFIG_RTE_LIBRTE_LPM) += load_balancer diff --git a/examples/l3fwd-vf/Makefile b/examples/l3fwd-vf/Makefile deleted file mode 100644 index 7b186a23c..000000000 --- a/examples/l3fwd-vf/Makefile +++ /dev/null @@ -1,62 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2010-2014 Intel Corporation - -# binary name -APP = l3fwd-vf - -# 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 # Build using legacy build system - -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 $(USER_FLAGS) -CFLAGS += $(WERROR_FLAGS) - -# workaround for a gcc bug with noreturn attribute -# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603 -ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) -CFLAGS_main.o += -Wno-return-type -endif - -include $(RTE_SDK)/mk/rte.extapp.mk -endif diff --git a/examples/l3fwd-vf/main.c b/examples/l3fwd-vf/main.c deleted file mode 100644 index 572e74cf5..000000000 --- a/examples/l3fwd-vf/main.c +++ /dev/null @@ -1,1072 +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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define APP_LOOKUP_EXACT_MATCH 0 -#define APP_LOOKUP_LPM 1 -#define DO_RFC_1812_CHECKS - -//#define APP_LOOKUP_METHOD APP_LOOKUP_EXACT_MATCH -#ifndef APP_LOOKUP_METHOD -#define APP_LOOKUP_METHOD APP_LOOKUP_LPM -#endif - -#if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) -#include -#elif (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) -#include -#else -#error "APP_LOOKUP_METHOD set to incorrect value" -#endif - -#define RTE_LOGTYPE_L3FWD RTE_LOGTYPE_USER1 - -#define MEMPOOL_CACHE_SIZE 256 - -/* - * This expression is used to calculate the number of mbufs needed depending on user input, taking - * into account memory for rx and tx hardware rings, cache per lcore and mtable per port per lcore. - * RTE_MAX is used to ensure that NB_MBUF never goes below a minimum value of 8192 - */ - -#define NB_MBUF RTE_MAX ( \ - (nb_ports*nb_rx_queue*nb_rxd + \ - nb_ports*nb_lcores*MAX_PKT_BURST + \ - nb_ports*n_tx_queue*nb_txd + \ - nb_lcores*MEMPOOL_CACHE_SIZE), \ - (unsigned)8192) - -#define MAX_PKT_BURST 32 -#define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ - -#define NB_SOCKETS 8 - -#define SOCKET0 0 - -/* Configure how many packets ahead to prefetch, when reading packets */ -#define PREFETCH_OFFSET 3 - -/* - * Configurable number of RX/TX ring descriptors - */ -#define RTE_TEST_RX_DESC_DEFAULT 1024 -#define RTE_TEST_TX_DESC_DEFAULT 1024 -static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; -static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; - -/* ethernet addresses of ports */ -static struct rte_ether_addr ports_eth_addr[RTE_MAX_ETHPORTS]; - -/* mask of enabled ports */ -static uint32_t enabled_port_mask = 0; -static int numa_on = 1; /**< NUMA is enabled by default. */ - -struct mbuf_table { - uint16_t len; - struct rte_mbuf *m_table[MAX_PKT_BURST]; -}; - -struct lcore_rx_queue { - uint16_t port_id; - uint8_t queue_id; -} __rte_cache_aligned; - -#define MAX_RX_QUEUE_PER_LCORE 16 -#define MAX_TX_QUEUE_PER_PORT 1 -#define MAX_RX_QUEUE_PER_PORT 1 - -#define MAX_LCORE_PARAMS 1024 -struct lcore_params { - uint16_t port_id; - uint8_t queue_id; - uint8_t lcore_id; -} __rte_cache_aligned; - -static struct lcore_params lcore_params_array[MAX_LCORE_PARAMS]; -static struct lcore_params lcore_params_array_default[] = { - {0, 0, 2}, - {0, 1, 2}, - {0, 2, 2}, - {1, 0, 2}, - {1, 1, 2}, - {1, 2, 2}, - {2, 0, 2}, - {3, 0, 3}, - {3, 1, 3}, -}; - -static struct lcore_params * lcore_params = lcore_params_array_default; -static uint16_t nb_lcore_params = sizeof(lcore_params_array_default) / - sizeof(lcore_params_array_default[0]); - -static struct rte_eth_conf port_conf = { - .rxmode = { - .mq_mode = ETH_MQ_RX_RSS, - .max_rx_pkt_len = RTE_ETHER_MAX_LEN, - .split_hdr_size = 0, - .offloads = DEV_RX_OFFLOAD_CHECKSUM, - }, - .rx_adv_conf = { - .rss_conf = { - .rss_key = NULL, - .rss_hf = ETH_RSS_IP, - }, - }, - .txmode = { - .mq_mode = ETH_MQ_TX_NONE, - }, -}; - -static struct rte_mempool * pktmbuf_pool[NB_SOCKETS]; - - -#if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) - -#ifdef RTE_ARCH_X86 -#include -#define DEFAULT_HASH_FUNC rte_hash_crc -#else -#include -#define DEFAULT_HASH_FUNC rte_jhash -#endif - -struct ipv4_5tuple { - uint32_t ip_dst; - uint32_t ip_src; - uint16_t port_dst; - uint16_t port_src; - uint8_t proto; -} __attribute__((__packed__)); - -struct l3fwd_route { - struct ipv4_5tuple key; - uint8_t if_out; -}; - -static struct l3fwd_route l3fwd_route_array[] = { - {{RTE_IPV4(100,10,0,1), RTE_IPV4(200,10,0,1), 101, 11, IPPROTO_TCP}, 0}, - {{RTE_IPV4(100,20,0,2), RTE_IPV4(200,20,0,2), 102, 12, IPPROTO_TCP}, 1}, - {{RTE_IPV4(100,30,0,3), RTE_IPV4(200,30,0,3), 103, 13, IPPROTO_TCP}, 2}, - {{RTE_IPV4(100,40,0,4), RTE_IPV4(200,40,0,4), 104, 14, IPPROTO_TCP}, 3}, -}; - -typedef struct rte_hash lookup_struct_t; -static lookup_struct_t *l3fwd_lookup_struct[NB_SOCKETS]; - -#define L3FWD_HASH_ENTRIES 1024 -struct rte_hash_parameters l3fwd_hash_params = { - .name = "l3fwd_hash_0", - .entries = L3FWD_HASH_ENTRIES, - .key_len = sizeof(struct ipv4_5tuple), - .hash_func = DEFAULT_HASH_FUNC, - .hash_func_init_val = 0, - .socket_id = SOCKET0, -}; - -#define L3FWD_NUM_ROUTES \ - (sizeof(l3fwd_route_array) / sizeof(l3fwd_route_array[0])) - -static uint8_t l3fwd_out_if[L3FWD_HASH_ENTRIES] __rte_cache_aligned; -#endif - -#if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) -struct l3fwd_route { - uint32_t ip; - uint8_t depth; - uint8_t if_out; -}; - -static struct l3fwd_route l3fwd_route_array[] = { - {RTE_IPV4(1,1,1,0), 24, 0}, - {RTE_IPV4(2,1,1,0), 24, 1}, - {RTE_IPV4(3,1,1,0), 24, 2}, - {RTE_IPV4(4,1,1,0), 24, 3}, - {RTE_IPV4(5,1,1,0), 24, 4}, - {RTE_IPV4(6,1,1,0), 24, 5}, - {RTE_IPV4(7,1,1,0), 24, 6}, - {RTE_IPV4(8,1,1,0), 24, 7}, -}; - -#define L3FWD_NUM_ROUTES \ - (sizeof(l3fwd_route_array) / sizeof(l3fwd_route_array[0])) - -#define L3FWD_LPM_MAX_RULES 1024 - -typedef struct rte_lpm lookup_struct_t; -static lookup_struct_t *l3fwd_lookup_struct[NB_SOCKETS]; -#endif - -struct lcore_conf { - uint16_t n_rx_queue; - struct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE]; - uint16_t tx_queue_id; - struct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS]; - lookup_struct_t * lookup_struct; -} __rte_cache_aligned; - -static struct lcore_conf lcore_conf[RTE_MAX_LCORE]; -static rte_spinlock_t spinlock_conf[RTE_MAX_ETHPORTS] = {RTE_SPINLOCK_INITIALIZER}; -/* Send burst of packets on an output interface */ -static inline int -send_burst(struct lcore_conf *qconf, uint16_t n, uint16_t port) -{ - struct rte_mbuf **m_table; - int ret; - uint16_t queueid; - - queueid = qconf->tx_queue_id; - m_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table; - - rte_spinlock_lock(&spinlock_conf[port]); - ret = rte_eth_tx_burst(port, queueid, m_table, n); - rte_spinlock_unlock(&spinlock_conf[port]); - - if (unlikely(ret < n)) { - do { - rte_pktmbuf_free(m_table[ret]); - } while (++ret < n); - } - - return 0; -} - -/* Enqueue a single packet, and send burst if queue is filled */ -static inline int -send_single_packet(struct rte_mbuf *m, uint16_t port) -{ - uint32_t lcore_id; - uint16_t len; - struct lcore_conf *qconf; - - lcore_id = rte_lcore_id(); - - qconf = &lcore_conf[lcore_id]; - len = qconf->tx_mbufs[port].len; - qconf->tx_mbufs[port].m_table[len] = m; - len++; - - /* enough pkts to be sent */ - if (unlikely(len == MAX_PKT_BURST)) { - send_burst(qconf, MAX_PKT_BURST, port); - len = 0; - } - - qconf->tx_mbufs[port].len = len; - return 0; -} - -#ifdef DO_RFC_1812_CHECKS -static inline int -is_valid_ipv4_pkt(struct rte_ipv4_hdr *pkt, uint32_t link_len) -{ - /* From http://www.rfc-editor.org/rfc/rfc1812.txt section 5.2.2 */ - /* - * 1. The packet length reported by the Link Layer must be large - * enough to hold the minimum length legal IP datagram (20 bytes). - */ - if (link_len < sizeof(struct rte_ipv4_hdr)) - return -1; - - /* 2. The IP checksum must be correct. */ - /* this is checked in H/W */ - - /* - * 3. The IP version number must be 4. If the version number is not 4 - * then the packet may be another version of IP, such as IPng or - * ST-II. - */ - if (((pkt->version_ihl) >> 4) != 4) - return -3; - /* - * 4. The IP header length field must be large enough to hold the - * minimum length legal IP datagram (20 bytes = 5 words). - */ - if ((pkt->version_ihl & 0xf) < 5) - return -4; - - /* - * 5. The IP total length field must be large enough to hold the IP - * datagram header, whose length is specified in the IP header length - * field. - */ - if (rte_cpu_to_be_16(pkt->total_length) < sizeof(struct rte_ipv4_hdr)) - return -5; - - return 0; -} -#endif - -#if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) -static void -print_key(struct ipv4_5tuple key) -{ - printf("IP dst = %08x, IP src = %08x, port dst = %d, port src = %d, proto = %d\n", - (unsigned)key.ip_dst, (unsigned)key.ip_src, key.port_dst, key.port_src, key.proto); -} - -static inline uint16_t -get_dst_port(struct rte_ipv4_hdr *ipv4_hdr, uint16_t portid, - lookup_struct_t *l3fwd_lookup_struct) -{ - struct ipv4_5tuple key; - struct rte_tcp_hdr *tcp; - struct rte_udp_hdr *udp; - int ret = 0; - - key.ip_dst = rte_be_to_cpu_32(ipv4_hdr->dst_addr); - key.ip_src = rte_be_to_cpu_32(ipv4_hdr->src_addr); - key.proto = ipv4_hdr->next_proto_id; - - switch (ipv4_hdr->next_proto_id) { - case IPPROTO_TCP: - tcp = (struct rte_tcp_hdr *)((unsigned char *) ipv4_hdr + - sizeof(struct rte_ipv4_hdr)); - key.port_dst = rte_be_to_cpu_16(tcp->dst_port); - key.port_src = rte_be_to_cpu_16(tcp->src_port); - break; - - case IPPROTO_UDP: - udp = (struct rte_udp_hdr *)((unsigned char *) ipv4_hdr + - sizeof(struct rte_ipv4_hdr)); - key.port_dst = rte_be_to_cpu_16(udp->dst_port); - key.port_src = rte_be_to_cpu_16(udp->src_port); - break; - - default: - key.port_dst = 0; - key.port_src = 0; - } - - /* Find destination port */ - ret = rte_hash_lookup(l3fwd_lookup_struct, (const void *)&key); - return ((ret < 0) ? portid : l3fwd_out_if[ret]); -} -#endif - -#if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) -static inline uint32_t -get_dst_port(struct rte_ipv4_hdr *ipv4_hdr, uint16_t portid, - lookup_struct_t *l3fwd_lookup_struct) -{ - uint32_t next_hop; - - return ((rte_lpm_lookup(l3fwd_lookup_struct, - rte_be_to_cpu_32(ipv4_hdr->dst_addr), &next_hop) == 0) ? - next_hop : portid); -} -#endif - -static inline void -l3fwd_simple_forward(struct rte_mbuf *m, uint16_t portid, - lookup_struct_t *l3fwd_lookup_struct) -{ - struct rte_ether_hdr *eth_hdr; - struct rte_ipv4_hdr *ipv4_hdr; - void *tmp; - uint16_t dst_port; - - eth_hdr = rte_pktmbuf_mtod(m, struct rte_ether_hdr *); - - ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct rte_ipv4_hdr *, - sizeof(struct rte_ether_hdr)); - -#ifdef DO_RFC_1812_CHECKS - /* Check to make sure the packet is valid (RFC1812) */ - if (is_valid_ipv4_pkt(ipv4_hdr, m->pkt_len) < 0) { - rte_pktmbuf_free(m); - return; - } -#endif - - dst_port = get_dst_port(ipv4_hdr, portid, l3fwd_lookup_struct); - if (dst_port >= RTE_MAX_ETHPORTS || (enabled_port_mask & 1 << dst_port) == 0) - dst_port = portid; - - /* 02:00:00:00:00:xx */ - tmp = ð_hdr->d_addr.addr_bytes[0]; - *((uint64_t *)tmp) = 0x000000000002 + ((uint64_t)dst_port << 40); - -#ifdef DO_RFC_1812_CHECKS - /* Update time to live and header checksum */ - --(ipv4_hdr->time_to_live); - ++(ipv4_hdr->hdr_checksum); -#endif - - /* src addr */ - rte_ether_addr_copy(&ports_eth_addr[dst_port], ð_hdr->s_addr); - - send_single_packet(m, dst_port); - -} - -/* main processing loop */ -static int -main_loop(__attribute__((unused)) void *dummy) -{ - struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; - unsigned lcore_id; - uint64_t prev_tsc, diff_tsc, cur_tsc; - int i, j, nb_rx; - uint8_t queueid; - uint16_t portid; - struct lcore_conf *qconf; - const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; - - prev_tsc = 0; - - lcore_id = rte_lcore_id(); - qconf = &lcore_conf[lcore_id]; - - if (qconf->n_rx_queue == 0) { - RTE_LOG(INFO, L3FWD, "lcore %u has nothing to do\n", lcore_id); - return 0; - } - - RTE_LOG(INFO, L3FWD, "entering main loop on lcore %u\n", lcore_id); - - for (i = 0; i < qconf->n_rx_queue; i++) { - - portid = qconf->rx_queue_list[i].port_id; - queueid = qconf->rx_queue_list[i].queue_id; - RTE_LOG(INFO, L3FWD, " --lcoreid=%u portid=%u rxqueueid=%hhu\n", - lcore_id, portid, queueid); - } - - while (1) { - - cur_tsc = rte_rdtsc(); - - /* - * TX burst queue drain - */ - diff_tsc = cur_tsc - prev_tsc; - if (unlikely(diff_tsc > drain_tsc)) { - - /* - * This could be optimized (use queueid instead of - * portid), but it is not called so often - */ - for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { - if (qconf->tx_mbufs[portid].len == 0) - continue; - send_burst(&lcore_conf[lcore_id], - qconf->tx_mbufs[portid].len, - portid); - qconf->tx_mbufs[portid].len = 0; - } - - prev_tsc = cur_tsc; - } - - /* - * Read packet from RX queues - */ - for (i = 0; i < qconf->n_rx_queue; ++i) { - - portid = qconf->rx_queue_list[i].port_id; - queueid = qconf->rx_queue_list[i].queue_id; - nb_rx = rte_eth_rx_burst(portid, queueid, pkts_burst, MAX_PKT_BURST); - - /* Prefetch first packets */ - for (j = 0; j < PREFETCH_OFFSET && j < nb_rx; j++) { - rte_prefetch0(rte_pktmbuf_mtod( - pkts_burst[j], void *)); - } - - /* Prefetch and forward already prefetched packets */ - for (j = 0; j < (nb_rx - PREFETCH_OFFSET); j++) { - rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[ - j + PREFETCH_OFFSET], void *)); - l3fwd_simple_forward(pkts_burst[j], portid, qconf->lookup_struct); - } - - /* Forward remaining prefetched packets */ - for (; j < nb_rx; j++) { - l3fwd_simple_forward(pkts_burst[j], portid, qconf->lookup_struct); - } - } - } -} - -static int -check_lcore_params(void) -{ - uint8_t queue, lcore; - uint16_t i; - int socketid; - - for (i = 0; i < nb_lcore_params; ++i) { - queue = lcore_params[i].queue_id; - if (queue >= MAX_RX_QUEUE_PER_PORT) { - printf("invalid queue number: %hhu\n", queue); - return -1; - } - lcore = lcore_params[i].lcore_id; - if (!rte_lcore_is_enabled(lcore)) { - printf("error: lcore %hhu is not enabled in lcore mask\n", lcore); - return -1; - } - if ((socketid = rte_lcore_to_socket_id(lcore) != 0) && - (numa_on == 0)) { - printf("warning: lcore %hhu is on socket %d with numa off \n", - lcore, socketid); - } - } - return 0; -} - -static int -check_port_config(void) -{ - unsigned portid; - uint16_t i; - - for (i = 0; i < nb_lcore_params; ++i) { - portid = lcore_params[i].port_id; - if ((enabled_port_mask & (1 << portid)) == 0) { - printf("port %u is not enabled in port mask\n", portid); - return -1; - } - if (!rte_eth_dev_is_valid_port(portid)) { - printf("port %u is not present on the board\n", portid); - return -1; - } - } - return 0; -} - -static uint8_t -get_port_n_rx_queues(const uint16_t port) -{ - int queue = -1; - uint16_t i; - - for (i = 0; i < nb_lcore_params; ++i) { - if (lcore_params[i].port_id == port && lcore_params[i].queue_id > queue) - queue = lcore_params[i].queue_id; - } - return (uint8_t)(++queue); -} - -static int -init_lcore_rx_queues(void) -{ - uint16_t i, nb_rx_queue; - uint8_t lcore; - - for (i = 0; i < nb_lcore_params; ++i) { - lcore = lcore_params[i].lcore_id; - nb_rx_queue = lcore_conf[lcore].n_rx_queue; - if (nb_rx_queue >= MAX_RX_QUEUE_PER_LCORE) { - printf("error: too many queues (%u) for lcore: %u\n", - (unsigned)nb_rx_queue + 1, (unsigned)lcore); - return -1; - } else { - lcore_conf[lcore].rx_queue_list[nb_rx_queue].port_id = - lcore_params[i].port_id; - lcore_conf[lcore].rx_queue_list[nb_rx_queue].queue_id = - lcore_params[i].queue_id; - lcore_conf[lcore].n_rx_queue++; - } - } - return 0; -} - -/* display usage */ -static void -print_usage(const char *prgname) -{ - printf ("%s [EAL options] -- -p PORTMASK" - " [--config (port,queue,lcore)[,(port,queue,lcore]]\n" - " -p PORTMASK: hexadecimal bitmask of ports to configure\n" - " --config (port,queue,lcore): rx queues configuration\n" - " --no-numa: optional, disable numa awareness\n", - prgname); -} - -/* Custom handling of signals to handle process terminal */ -static void -signal_handler(int signum) -{ - uint16_t portid; - - /* When we receive a SIGINT signal */ - if (signum == SIGINT) { - RTE_ETH_FOREACH_DEV(portid) { - /* skip ports that are not enabled */ - if ((enabled_port_mask & (1 << portid)) == 0) - continue; - rte_eth_dev_close(portid); - } - } - rte_exit(EXIT_SUCCESS, "\n User forced exit\n"); -} -static int -parse_portmask(const char *portmask) -{ - char *end = NULL; - unsigned long pm; - - /* parse hexadecimal string */ - pm = strtoul(portmask, &end, 16); - if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) - return -1; - - if (pm == 0) - return -1; - - return pm; -} - -static int -parse_config(const char *q_arg) -{ - char s[256]; - const char *p, *p0 = q_arg; - char *end; - enum fieldnames { - FLD_PORT = 0, - FLD_QUEUE, - FLD_LCORE, - _NUM_FLD - }; - unsigned long int_fld[_NUM_FLD]; - char *str_fld[_NUM_FLD]; - int i; - unsigned size; - - nb_lcore_params = 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; - } - if (nb_lcore_params >= MAX_LCORE_PARAMS) { - printf("exceeded max number of lcore params: %hu\n", - nb_lcore_params); - return -1; - } - lcore_params_array[nb_lcore_params].port_id = int_fld[FLD_PORT]; - lcore_params_array[nb_lcore_params].queue_id = (uint8_t)int_fld[FLD_QUEUE]; - lcore_params_array[nb_lcore_params].lcore_id = (uint8_t)int_fld[FLD_LCORE]; - ++nb_lcore_params; - } - lcore_params = lcore_params_array; - return 0; -} - -/* Parse the argument given in the command line of the application */ -static int -parse_args(int argc, char **argv) -{ - int opt, ret; - char **argvopt; - int option_index; - char *prgname = argv[0]; - static struct option lgopts[] = { - {"config", 1, 0, 0}, - {"no-numa", 0, 0, 0}, - {NULL, 0, 0, 0} - }; - - argvopt = argv; - - while ((opt = getopt_long(argc, argvopt, "p:", - lgopts, &option_index)) != EOF) { - - switch (opt) { - /* portmask */ - case 'p': - enabled_port_mask = parse_portmask(optarg); - if (enabled_port_mask == 0) { - printf("invalid portmask\n"); - print_usage(prgname); - return -1; - } - break; - - /* long options */ - case 0: - if (!strcmp(lgopts[option_index].name, "config")) { - ret = parse_config(optarg); - if (ret) { - printf("invalid config\n"); - print_usage(prgname); - return -1; - } - } - - if (!strcmp(lgopts[option_index].name, "no-numa")) { - printf("numa is disabled \n"); - numa_on = 0; - } - break; - - default: - print_usage(prgname); - return -1; - } - } - - if (optind >= 0) - argv[optind-1] = prgname; - - ret = optind-1; - optind = 1; /* reset getopt lib */ - return ret; -} - -static void -print_ethaddr(const char *name, const struct rte_ether_addr *eth_addr) -{ - char buf[RTE_ETHER_ADDR_FMT_SIZE]; - rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr); - printf("%s%s", name, buf); -} - -#if (APP_LOOKUP_METHOD == APP_LOOKUP_EXACT_MATCH) -static void -setup_hash(int socketid) -{ - unsigned i; - int ret; - char s[64]; - - /* create hashes */ - snprintf(s, sizeof(s), "l3fwd_hash_%d", socketid); - l3fwd_hash_params.name = s; - l3fwd_hash_params.socket_id = socketid; - l3fwd_lookup_struct[socketid] = rte_hash_create(&l3fwd_hash_params); - if (l3fwd_lookup_struct[socketid] == NULL) - rte_exit(EXIT_FAILURE, "Unable to create the l3fwd hash on " - "socket %d\n", socketid); - - /* populate the hash */ - for (i = 0; i < L3FWD_NUM_ROUTES; i++) { - ret = rte_hash_add_key (l3fwd_lookup_struct[socketid], - (void *) &l3fwd_route_array[i].key); - if (ret < 0) { - rte_exit(EXIT_FAILURE, "Unable to add entry %u to the" - "l3fwd hash on socket %d\n", i, socketid); - } - l3fwd_out_if[ret] = l3fwd_route_array[i].if_out; - printf("Hash: Adding key\n"); - print_key(l3fwd_route_array[i].key); - } -} -#endif - -#if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) -static void -setup_lpm(int socketid) -{ - unsigned i; - int ret; - char s[64]; - - struct rte_lpm_config lpm_ipv4_config; - - lpm_ipv4_config.max_rules = L3FWD_LPM_MAX_RULES; - lpm_ipv4_config.number_tbl8s = 256; - lpm_ipv4_config.flags = 0; - - /* create the LPM table */ - snprintf(s, sizeof(s), "L3FWD_LPM_%d", socketid); - l3fwd_lookup_struct[socketid] = - rte_lpm_create(s, socketid, &lpm_ipv4_config); - if (l3fwd_lookup_struct[socketid] == NULL) - rte_exit(EXIT_FAILURE, "Unable to create the l3fwd LPM table" - " on socket %d\n", socketid); - - /* populate the LPM table */ - for (i = 0; i < L3FWD_NUM_ROUTES; i++) { - ret = rte_lpm_add(l3fwd_lookup_struct[socketid], - l3fwd_route_array[i].ip, - l3fwd_route_array[i].depth, - l3fwd_route_array[i].if_out); - - if (ret < 0) { - rte_exit(EXIT_FAILURE, "Unable to add entry %u to the " - "l3fwd LPM table on socket %d\n", - i, socketid); - } - - printf("LPM: Adding route 0x%08x / %d (%d)\n", - (unsigned)l3fwd_route_array[i].ip, - l3fwd_route_array[i].depth, - l3fwd_route_array[i].if_out); - } -} -#endif - -static int -init_mem(unsigned nb_mbuf) -{ - struct lcore_conf *qconf; - int socketid; - unsigned lcore_id; - char s[64]; - - for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { - if (rte_lcore_is_enabled(lcore_id) == 0) - continue; - - if (numa_on) - socketid = rte_lcore_to_socket_id(lcore_id); - else - socketid = 0; - - if (socketid >= NB_SOCKETS) { - rte_exit(EXIT_FAILURE, "Socket %d of lcore %u is out of range %d\n", - socketid, lcore_id, NB_SOCKETS); - } - if (pktmbuf_pool[socketid] == NULL) { - snprintf(s, sizeof(s), "mbuf_pool_%d", socketid); - pktmbuf_pool[socketid] = rte_pktmbuf_pool_create(s, - nb_mbuf, MEMPOOL_CACHE_SIZE, 0, - RTE_MBUF_DEFAULT_BUF_SIZE, socketid); - if (pktmbuf_pool[socketid] == NULL) - rte_exit(EXIT_FAILURE, "Cannot init mbuf pool on socket %d\n", socketid); - else - printf("Allocated mbuf pool on socket %d\n", socketid); - -#if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) - setup_lpm(socketid); -#else - setup_hash(socketid); -#endif - } - qconf = &lcore_conf[lcore_id]; - qconf->lookup_struct = l3fwd_lookup_struct[socketid]; - } - return 0; -} - -int -main(int argc, char **argv) -{ - struct lcore_conf *qconf; - struct rte_eth_dev_info dev_info; - struct rte_eth_txconf *txconf; - int ret; - unsigned nb_ports; - uint16_t queueid, portid; - unsigned lcore_id; - uint32_t nb_lcores; - uint16_t n_tx_queue; - uint8_t nb_rx_queue, queue, socketid; - - signal(SIGINT, signal_handler); - /* init EAL */ - ret = rte_eal_init(argc, argv); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Invalid EAL parameters\n"); - argc -= ret; - argv += ret; - - /* parse application arguments (after the EAL ones) */ - ret = parse_args(argc, argv); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Invalid L3FWD-VF parameters\n"); - - if (check_lcore_params() < 0) - rte_exit(EXIT_FAILURE, "check_lcore_params failed\n"); - - ret = init_lcore_rx_queues(); - if (ret < 0) - rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n"); - - nb_ports = rte_eth_dev_count_avail(); - - if (check_port_config() < 0) - rte_exit(EXIT_FAILURE, "check_port_config failed\n"); - - nb_lcores = rte_lcore_count(); - - /* initialize all ports */ - RTE_ETH_FOREACH_DEV(portid) { - struct rte_eth_conf local_port_conf = port_conf; - - /* skip ports that are not enabled */ - if ((enabled_port_mask & (1 << portid)) == 0) { - printf("\nSkipping disabled port %d\n", portid); - continue; - } - - /* init port */ - printf("Initializing port %d ... ", portid ); - fflush(stdout); - - /* must always equal(=1) */ - nb_rx_queue = get_port_n_rx_queues(portid); - n_tx_queue = MAX_TX_QUEUE_PER_PORT; - - printf("Creating queues: nb_rxq=%d nb_txq=%u... ", - nb_rx_queue, (unsigned)1 ); - - rte_eth_dev_info_get(portid, &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; - - local_port_conf.rx_adv_conf.rss_conf.rss_hf &= - dev_info.flow_type_rss_offloads; - if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != - port_conf.rx_adv_conf.rss_conf.rss_hf) { - printf("Port %u modified RSS hash function based on hardware support," - "requested:%#"PRIx64" configured:%#"PRIx64"\n", - portid, - port_conf.rx_adv_conf.rss_conf.rss_hf, - local_port_conf.rx_adv_conf.rss_conf.rss_hf); - } - - ret = rte_eth_dev_configure(portid, nb_rx_queue, - n_tx_queue, &local_port_conf); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%d\n", - ret, portid); - - ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd, - &nb_txd); - if (ret < 0) - rte_exit(EXIT_FAILURE, - "Cannot adjust number of descriptors: err=%d, port=%d\n", - ret, portid); - - rte_eth_macaddr_get(portid, &ports_eth_addr[portid]); - print_ethaddr(" Address:", &ports_eth_addr[portid]); - printf(", "); - - ret = init_mem(NB_MBUF); - if (ret < 0) - rte_exit(EXIT_FAILURE, "init_mem failed\n"); - - /* init one TX queue */ - socketid = (uint8_t)rte_lcore_to_socket_id(rte_get_master_lcore()); - - printf("txq=%d,%d,%d ", portid, 0, socketid); - fflush(stdout); - - txconf = &dev_info.default_txconf; - txconf->offloads = local_port_conf.txmode.offloads; - ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, - socketid, txconf); - if (ret < 0) - rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup: err=%d, " - "port=%d\n", ret, portid); - - printf("\n"); - } - - for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { - struct rte_eth_rxconf rxq_conf; - - if (rte_lcore_is_enabled(lcore_id) == 0) - continue; - qconf = &lcore_conf[lcore_id]; - qconf->tx_queue_id = 0; - - printf("\nInitializing rx queues on lcore %u ... ", lcore_id ); - fflush(stdout); - /* init RX queues */ - for(queue = 0; queue < qconf->n_rx_queue; ++queue) { - portid = qconf->rx_queue_list[queue].port_id; - queueid = qconf->rx_queue_list[queue].queue_id; - - if (numa_on) - socketid = (uint8_t)rte_lcore_to_socket_id(lcore_id); - else - socketid = 0; - - printf("rxq=%d,%d,%d ", portid, queueid, socketid); - fflush(stdout); - - rte_eth_dev_info_get(portid, &dev_info); - rxq_conf = dev_info.default_rxconf; - rxq_conf.offloads = port_conf.rxmode.offloads; - ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd, - socketid, &rxq_conf, - pktmbuf_pool[socketid]); - if (ret < 0) - rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup: err=%d," - "port=%d\n", ret, portid); - } - } - printf("\n"); - - /* start ports */ - RTE_ETH_FOREACH_DEV(portid) { - if ((enabled_port_mask & (1 << portid)) == 0) { - continue; - } - /* Start device */ - ret = rte_eth_dev_start(portid); - if (ret < 0) - rte_exit(EXIT_FAILURE, "rte_eth_dev_start: err=%d, port=%d\n", - ret, portid); - - printf("done: Port %d\n", portid); - - } - - /* launch per-lcore init on every lcore */ - rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER); - RTE_LCORE_FOREACH_SLAVE(lcore_id) { - if (rte_eal_wait_lcore(lcore_id) < 0) - return -1; - } - - return 0; -} diff --git a/examples/l3fwd-vf/meson.build b/examples/l3fwd-vf/meson.build deleted file mode 100644 index 226286e74..000000000 --- a/examples/l3fwd-vf/meson.build +++ /dev/null @@ -1,12 +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' - -deps += ['lpm', 'hash'] -sources = files( - 'main.c' -) diff --git a/examples/meson.build b/examples/meson.build index 4663d9dea..81ac8199a 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -23,7 +23,7 @@ all_examples = [ 'l2fwd-crypto', 'l2fwd-jobstats', 'l2fwd-keepalive', 'l3fwd', 'l3fwd-acl', 'l3fwd-power', - 'l3fwd-vf', 'link_status_interrupt', + 'link_status_interrupt', 'load_balancer', 'multi_process/client_server_mp/mp_client', 'multi_process/client_server_mp/mp_server', From patchwork Thu Oct 3 13:19:15 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bruce Richardson X-Patchwork-Id: 60494 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 0D6A51C10F; Thu, 3 Oct 2019 15:19:53 +0200 (CEST) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by dpdk.org (Postfix) with ESMTP id 447F11C10F; Thu, 3 Oct 2019 15:19:51 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 03 Oct 2019 06:19:50 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.67,252,1566889200"; d="scan'208";a="185910562" Received: from silpixa00399126.ir.intel.com (HELO silpixa00399126.ger.corp.intel.com) ([10.237.223.2]) by orsmga008.jf.intel.com with ESMTP; 03 Oct 2019 06:19:47 -0700 From: Bruce Richardson To: dev@dpdk.org Cc: techboard@dpdk.org, Ciara Power Date: Thu, 3 Oct 2019 14:19:15 +0100 Message-Id: <20191003131918.30970-4-bruce.richardson@intel.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191003131918.30970-1-bruce.richardson@intel.com> References: <20191003131918.30970-1-bruce.richardson@intel.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH 3/6] examples/quota-watermark: 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: Ciara Power Original DPDK rings code had explicit support for a single watermark per-ring, but more recent releases of DPDK had a more general mechanism where each enqueue or dequeue call could return the remaining elements/free-slots in the ring. Therefore, this example is not as relevant as before and can be removed. Signed-off-by: Ciara Power --- MAINTAINERS | 3 - doc/guides/sample_app_ug/index.rst | 1 - doc/guides/sample_app_ug/intro.rst | 2 +- doc/guides/sample_app_ug/quota_watermark.rst | 465 ------------------- examples/Makefile | 1 - examples/meson.build | 2 +- examples/quota_watermark/Makefile | 16 - examples/quota_watermark/include/conf.h | 19 - examples/quota_watermark/meson.build | 10 - examples/quota_watermark/qw/Makefile | 22 - examples/quota_watermark/qw/args.c | 78 ---- examples/quota_watermark/qw/args.h | 12 - examples/quota_watermark/qw/init.c | 164 ------- examples/quota_watermark/qw/init.h | 14 - examples/quota_watermark/qw/main.c | 365 --------------- examples/quota_watermark/qw/main.h | 31 -- examples/quota_watermark/qwctl/Makefile | 22 - examples/quota_watermark/qwctl/commands.c | 196 -------- examples/quota_watermark/qwctl/commands.h | 12 - examples/quota_watermark/qwctl/qwctl.c | 67 --- examples/quota_watermark/qwctl/qwctl.h | 12 - 21 files changed, 2 insertions(+), 1512 deletions(-) delete mode 100644 doc/guides/sample_app_ug/quota_watermark.rst delete mode 100644 examples/quota_watermark/Makefile delete mode 100644 examples/quota_watermark/include/conf.h delete mode 100644 examples/quota_watermark/meson.build delete mode 100644 examples/quota_watermark/qw/Makefile delete mode 100644 examples/quota_watermark/qw/args.c delete mode 100644 examples/quota_watermark/qw/args.h delete mode 100644 examples/quota_watermark/qw/init.c delete mode 100644 examples/quota_watermark/qw/init.h delete mode 100644 examples/quota_watermark/qw/main.c delete mode 100644 examples/quota_watermark/qw/main.h delete mode 100644 examples/quota_watermark/qwctl/Makefile delete mode 100644 examples/quota_watermark/qwctl/commands.c delete mode 100644 examples/quota_watermark/qwctl/commands.h delete mode 100644 examples/quota_watermark/qwctl/qwctl.c delete mode 100644 examples/quota_watermark/qwctl/qwctl.h diff --git a/MAINTAINERS b/MAINTAINERS index 92c3f6af4..7be363327 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1474,9 +1474,6 @@ F: doc/guides/sample_app_ug/performance_thread.rst F: examples/ptpclient/ -F: examples/quota_watermark/ -F: doc/guides/sample_app_ug/quota_watermark.rst - M: Bruce Richardson M: John McNamara F: examples/rxtx_callbacks/ diff --git a/doc/guides/sample_app_ug/index.rst b/doc/guides/sample_app_ug/index.rst index d212f81fe..dafe8553f 100644 --- a/doc/guides/sample_app_ug/index.rst +++ b/doc/guides/sample_app_ug/index.rst @@ -36,7 +36,6 @@ Sample Applications User Guides multi_process qos_metering qos_scheduler - quota_watermark timer packet_ordering vmdq_dcb_forwarding diff --git a/doc/guides/sample_app_ug/intro.rst b/doc/guides/sample_app_ug/intro.rst index 7299253bf..6e0af6301 100644 --- a/doc/guides/sample_app_ug/intro.rst +++ b/doc/guides/sample_app_ug/intro.rst @@ -43,7 +43,7 @@ applications that are available in the examples directory of DPDK: +---------------------------------------+--------------------------------------+ | Hello World | QoS Scheduler | +---------------------------------------+--------------------------------------+ - | Internet Protocol (IP) Fragmentation | Quota and Watermark | + | Internet Protocol (IP) Fragmentation | | +---------------------------------------+--------------------------------------+ | IP Pipeline | RX/TX Callbacks | +---------------------------------------+--------------------------------------+ diff --git a/doc/guides/sample_app_ug/quota_watermark.rst b/doc/guides/sample_app_ug/quota_watermark.rst deleted file mode 100644 index 125e6fb73..000000000 --- a/doc/guides/sample_app_ug/quota_watermark.rst +++ /dev/null @@ -1,465 +0,0 @@ -.. SPDX-License-Identifier: BSD-3-Clause - Copyright(c) 2010-2017 Intel Corporation. - -Quota and Watermark Sample Application -====================================== - -The Quota and Watermark sample application is a simple example of packet -processing using Data Plane Development Kit (DPDK) that showcases the use -of a quota as the maximum number of packets enqueue/dequeue at a time and -low and high thresholds, or watermarks, to signal low and high ring usage -respectively. - -Additionally, it shows how the thresholds can be used to feedback congestion notifications to data producers by -temporarily stopping processing overloaded rings and sending Ethernet flow control frames. - -This sample application is split in two parts: - -* qw - The core quota and watermark sample application - -* qwctl - A command line tool to alter quota and watermarks while qw is running - -Overview --------- - -The Quota and Watermark sample application performs forwarding for each packet that is received on a given port. -The destination port is the adjacent port from the enabled port mask, that is, -if the first four ports are enabled (port mask 0xf), ports 0 and 1 forward into each other, -and ports 2 and 3 forward into each other. -The MAC addresses of the forwarded Ethernet frames are not affected. - -Internally, packets are pulled from the ports by the master logical core and put on a variable length processing pipeline, -each stage of which being connected by rings, as shown in :numref:`figure_pipeline_overview`. - -.. _figure_pipeline_overview: - -.. figure:: img/pipeline_overview.* - - Pipeline Overview - - -An adjustable quota value controls how many packets are being moved through the pipeline per enqueue and dequeue. -Adjustable threshold values associated with the rings control a back-off mechanism that -tries to prevent the pipeline from being overloaded by: - -* Stopping enqueuing on rings for which the usage has crossed the high watermark threshold - -* Sending Ethernet pause frames - -* Only resuming enqueuing on a ring once its usage goes below a global low watermark threshold - -This mechanism allows congestion notifications to go up the ring pipeline and -eventually lead to an Ethernet flow control frame being send to the source. - -On top of serving as an example of quota and watermark usage, -this application can be used to benchmark ring based processing pipelines performance using a traffic- generator, -as shown in :numref:`figure_ring_pipeline_perf_setup`. - -.. _figure_ring_pipeline_perf_setup: - -.. figure:: img/ring_pipeline_perf_setup.* - - Ring-based Processing Pipeline Performance Setup - -Compiling the Application -------------------------- - -To compile the sample application see :doc:`compiling`. - -The application is located in the ``quota_watermark`` sub-directory. - -Running the Application ------------------------ - -The core application, qw, has to be started first. - -Once it is up and running, one can alter quota and watermarks while it runs using the control application, qwctl. - -Running the Core Application -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The application requires a single command line option: - -.. code-block:: console - - ./qw/build/qw [EAL options] -- -p PORTMASK - -where, - --p PORTMASK: A hexadecimal bitmask of the ports to configure - -To run the application in a linux environment with four logical cores and ports 0 and 2, -issue the following command: - -.. code-block:: console - - ./qw/build/qw -l 0-3 -n 4 -- -p 5 - -Refer to the *DPDK Getting Started Guide* for general information on running applications and -the Environment Abstraction Layer (EAL) options. - -Running the Control Application -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The control application requires a number of command line options: - -.. code-block:: console - - ./qwctl/build/qwctl [EAL options] --proc-type=secondary - -The --proc-type=secondary option is necessary for the EAL to properly initialize the control application to -use the same huge pages as the core application and thus be able to access its rings. - -To run the application in a linux environment on logical core 0, issue the following command: - -.. code-block:: console - - ./qwctl/build/qwctl -l 0 -n 4 --proc-type=secondary - -Refer to the *DPDK Getting Started* Guide for general information on running applications and -the Environment Abstraction Layer (EAL) options. - -qwctl is an interactive command line that let the user change variables in a running instance of qw. -The help command gives a list of available commands: - -.. code-block:: console - - $ qwctl > help - -Code Overview -------------- - -The following sections provide a quick guide to the application's source code. - -Core Application - qw -~~~~~~~~~~~~~~~~~~~~~ - -EAL and Drivers Setup -^^^^^^^^^^^^^^^^^^^^^ - -The EAL arguments are parsed at the beginning of the main() function: - -.. code-block:: c - - ret = rte_eal_init(argc, argv); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Cannot initialize EAL\n"); - - argc -= ret; - argv += ret; - -Then, a call to init_dpdk(), defined in init.c, is made to initialize the poll mode drivers: - -.. code-block:: c - - void - init_dpdk(void) - { - int ret; - - /* Bind the drivers to usable devices */ - - ret = rte_pci_probe(); - if (ret < 0) - rte_exit(EXIT_FAILURE, "rte_pci_probe(): error %d\n", ret); - - if (rte_eth_dev_count_avail() < 2) - rte_exit(EXIT_FAILURE, "Not enough Ethernet port available\n"); - } - -To fully understand this code, it is recommended to study the chapters that relate to the *Poll Mode Driver* -in the *DPDK Getting Started Guide* and the *DPDK API Reference*. - -Shared Variables Setup -^^^^^^^^^^^^^^^^^^^^^^ - -The quota and high and low watermark shared variables are put into an rte_memzone using a call to setup_shared_variables(): - -.. code-block:: c - - void - setup_shared_variables(void) - { - const struct rte_memzone *qw_memzone; - - qw_memzone = rte_memzone_reserve(QUOTA_WATERMARK_MEMZONE_NAME, - 3 * sizeof(int), rte_socket_id(), 0); - if (qw_memzone == NULL) - rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno)); - - quota = qw_memzone->addr; - low_watermark = (unsigned int *) qw_memzone->addr + 1; - high_watermark = (unsigned int *) qw_memzone->addr + 2; - } - -These three variables are initialized to a default value in main() and -can be changed while qw is running using the qwctl control program. - -Application Arguments -^^^^^^^^^^^^^^^^^^^^^ - -The qw application only takes one argument: a port mask that specifies which ports should be used by the application. -At least two ports are needed to run the application and there should be an even number of ports given in the port mask. - -The port mask parsing is done in parse_qw_args(), defined in args.c. - -Mbuf Pool Initialization -^^^^^^^^^^^^^^^^^^^^^^^^ - -Once the application's arguments are parsed, an mbuf pool is created. -It contains a set of mbuf objects that are used by the driver and the application to store network packets: - -.. code-block:: c - - /* Create a pool of mbuf to store packets */ - mbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", MBUF_PER_POOL, 32, 0, - MBUF_DATA_SIZE, rte_socket_id()); - - if (mbuf_pool == NULL) - rte_panic("%s\n", rte_strerror(rte_errno)); - -The rte_mempool is a generic structure used to handle pools of objects. -In this case, it is necessary to create a pool that will be used by the driver. - -The number of allocated pkt mbufs is MBUF_PER_POOL, with a data room size -of MBUF_DATA_SIZE each. -A per-lcore cache of 32 mbufs is kept. -The memory is allocated in on the master lcore's socket, but it is possible to extend this code to allocate one mbuf pool per socket. - -The rte_pktmbuf_pool_create() function uses the default mbuf pool and mbuf -initializers, respectively rte_pktmbuf_pool_init() and rte_pktmbuf_init(). -An advanced application may want to use the mempool API to create the -mbuf pool with more control. - -Ports Configuration and Pairing -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Each port in the port mask is configured and a corresponding ring is created in the master lcore's array of rings. -This ring is the first in the pipeline and will hold the packets directly coming from the port. - -.. code-block:: c - - for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) - if (is_bit_set(port_id, portmask)) { - configure_eth_port(port_id); - init_ring(master_lcore_id, port_id); - } - - pair_ports(); - -The configure_eth_port() and init_ring() functions are used to configure a port and a ring respectively and are defined in init.c. -They make use of the DPDK APIs defined in rte_eth.h and rte_ring.h. - -pair_ports() builds the port_pairs[] array so that its key-value pairs are a mapping between reception and transmission ports. -It is defined in init.c. - -Logical Cores Assignment -^^^^^^^^^^^^^^^^^^^^^^^^ - -The application uses the master logical core to poll all the ports for new packets and enqueue them on a ring associated with the port. - -Each logical core except the last runs pipeline_stage() after a ring for each used port is initialized on that core. -pipeline_stage() on core X dequeues packets from core X-1's rings and enqueue them on its own rings. See :numref:`figure_threads_pipelines`. - -.. code-block:: c - - /* Start pipeline_stage() on all the available slave lcore but the last */ - - for (lcore_id = 0 ; lcore_id < last_lcore_id; lcore_id++) { - if (rte_lcore_is_enabled(lcore_id) && lcore_id != master_lcore_id) { - for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) - if (is_bit_set(port_id, portmask)) - init_ring(lcore_id, port_id); - - rte_eal_remote_launch(pipeline_stage, NULL, lcore_id); - } - } - -The last available logical core runs send_stage(), -which is the last stage of the pipeline dequeuing packets from the last ring in the pipeline and -sending them out on the destination port setup by pair_ports(). - -.. code-block:: c - - /* Start send_stage() on the last slave core */ - - rte_eal_remote_launch(send_stage, NULL, last_lcore_id); - -Receive, Process and Transmit Packets -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. _figure_threads_pipelines: - -.. figure:: img/threads_pipelines.* - - Threads and Pipelines - - -In the receive_stage() function running on the master logical core, -the main task is to read ingress packets from the RX ports and enqueue them -on the port's corresponding first ring in the pipeline. -This is done using the following code: - -.. code-block:: c - - lcore_id = rte_lcore_id(); - - /* Process each port round robin style */ - - for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) { - if (!is_bit_set(port_id, portmask)) - continue; - - ring = rings[lcore_id][port_id]; - - if (ring_state[port_id] != RING_READY) { - if (rte_ring_count(ring) > *low_watermark) - continue; - else - ring_state[port_id] = RING_READY; - } - - /* Enqueue received packets on the RX ring */ - nb_rx_pkts = rte_eth_rx_burst(port_id, 0, pkts, - (uint16_t) *quota); - ret = rte_ring_enqueue_bulk(ring, (void *) pkts, - nb_rx_pkts, &free); - if (RING_SIZE - free > *high_watermark) { - ring_state[port_id] = RING_OVERLOADED; - send_pause_frame(port_id, 1337); - } - - if (ret == 0) { - - /* - * Return mbufs to the pool, - * effectively dropping packets - */ - for (i = 0; i < nb_rx_pkts; i++) - rte_pktmbuf_free(pkts[i]); - } - } - -For each port in the port mask, the corresponding ring's pointer is fetched into ring and that ring's state is checked: - -* If it is in the RING_READY state, \*quota packets are grabbed from the port and put on the ring. - Should this operation make the ring's usage cross its high watermark, - the ring is marked as overloaded and an Ethernet flow control frame is sent to the source. - -* If it is not in the RING_READY state, this port is ignored until the ring's usage crosses the \*low_watermark value. - -The pipeline_stage() function's task is to process and move packets from the preceding pipeline stage. -This thread is running on most of the logical cores to create and arbitrarily long pipeline. - -.. code-block:: c - - lcore_id = rte_lcore_id(); - - previous_lcore_id = get_previous_lcore_id(lcore_id); - - for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) { - if (!is_bit_set(port_id, portmask)) - continue; - - tx = rings[lcore_id][port_id]; - rx = rings[previous_lcore_id][port_id]; - - if (ring_state[port_id] != RING_READY) { - if (rte_ring_count(tx) > *low_watermark) - continue; - else - ring_state[port_id] = RING_READY; - } - - /* Dequeue up to quota mbuf from rx */ - nb_dq_pkts = rte_ring_dequeue_burst(rx, pkts, - *quota, NULL); - if (unlikely(nb_dq_pkts < 0)) - continue; - - /* Enqueue them on tx */ - ret = rte_ring_enqueue_bulk(tx, pkts, - nb_dq_pkts, &free); - if (RING_SIZE - free > *high_watermark) - ring_state[port_id] = RING_OVERLOADED; - - if (ret == 0) { - - /* - * Return mbufs to the pool, - * effectively dropping packets - */ - for (i = 0; i < nb_dq_pkts; i++) - rte_pktmbuf_free(pkts[i]); - } - } - -The thread's logic works mostly like receive_stage(), -except that packets are moved from ring to ring instead of port to ring. - -In this example, no actual processing is done on the packets, -but pipeline_stage() is an ideal place to perform any processing required by the application. - -Finally, the send_stage() function's task is to read packets from the last ring in a pipeline and -send them on the destination port defined in the port_pairs[] array. -It is running on the last available logical core only. - -.. code-block:: c - - lcore_id = rte_lcore_id(); - - previous_lcore_id = get_previous_lcore_id(lcore_id); - - for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) { - if (!is_bit_set(port_id, portmask)) continue; - - dest_port_id = port_pairs[port_id]; - tx = rings[previous_lcore_id][port_id]; - - if (rte_ring_empty(tx)) continue; - - /* Dequeue packets from tx and send them */ - - nb_dq_pkts = rte_ring_dequeue_burst(tx, (void *) tx_pkts, *quota); - nb_tx_pkts = rte_eth_tx_burst(dest_port_id, 0, tx_pkts, nb_dq_pkts); - } - -For each port in the port mask, up to \*quota packets are pulled from the last ring in its pipeline and -sent on the destination port paired with the current port. - -Control Application - qwctl -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The qwctl application uses the rte_cmdline library to provide the user with an interactive command line that -can be used to modify and inspect parameters in a running qw application. -Those parameters are the global quota and low_watermark value as well as each ring's built-in high watermark. - -Command Definitions -^^^^^^^^^^^^^^^^^^^ - -The available commands are defined in commands.c. - -It is advised to use the cmdline sample application user guide as a reference for everything related to the rte_cmdline library. - -Accessing Shared Variables -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The setup_shared_variables() function retrieves the shared variables quota and -low_watermark from the rte_memzone previously created by qw. - -.. code-block:: c - - static void - setup_shared_variables(void) - { - const struct rte_memzone *qw_memzone; - - qw_memzone = rte_memzone_lookup(QUOTA_WATERMARK_MEMZONE_NAME); - if (qw_memzone == NULL) - rte_exit(EXIT_FAILURE, "Couldn't find memzone\n"); - - quota = qw_memzone->addr; - - low_watermark = (unsigned int *) qw_memzone->addr + 1; - high_watermark = (unsigned int *) qw_memzone->addr + 2; - } diff --git a/examples/Makefile b/examples/Makefile index 5dd8a72e5..02ff86534 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -59,7 +59,6 @@ endif DIRS-$(CONFIG_RTE_LIBRTE_IEEE1588) += ptpclient DIRS-$(CONFIG_RTE_LIBRTE_METER) += qos_meter DIRS-$(CONFIG_RTE_LIBRTE_SCHED) += qos_sched -DIRS-y += quota_watermark DIRS-$(CONFIG_RTE_ETHDEV_RXTX_CALLBACKS) += rxtx_callbacks DIRS-y += service_cores DIRS-y += skeleton diff --git a/examples/meson.build b/examples/meson.build index 81ac8199a..6c26fffb4 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -33,7 +33,7 @@ all_examples = [ 'netmap_compat', 'ntb', 'packet_ordering', 'performance-thread', 'ptpclient', 'qos_meter', 'qos_sched', - 'quota_watermark', 'rxtx_callbacks', + 'rxtx_callbacks', 'server_node_efd', 'service_cores', 'skeleton', 'tep_termination', 'timer', 'vdpa', diff --git a/examples/quota_watermark/Makefile b/examples/quota_watermark/Makefile deleted file mode 100644 index 8ef053198..000000000 --- a/examples/quota_watermark/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2010-2014 Intel Corporation - -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 - -DIRS-$(CONFIG_RTE_EXEC_ENV_LINUX) += qw -DIRS-$(CONFIG_RTE_EXEC_ENV_LINUX) += qwctl - -include $(RTE_SDK)/mk/rte.extsubdir.mk diff --git a/examples/quota_watermark/include/conf.h b/examples/quota_watermark/include/conf.h deleted file mode 100644 index 4f29aa64b..000000000 --- a/examples/quota_watermark/include/conf.h +++ /dev/null @@ -1,19 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation - */ - -#ifndef _CONF_H_ -#define _CONF_H_ - -#define RING_SIZE 1024 -#define MAX_PKT_QUOTA 64 - -#define RX_DESC_PER_QUEUE 1024 -#define TX_DESC_PER_QUEUE 1024 - -#define MBUF_DATA_SIZE RTE_MBUF_DEFAULT_BUF_SIZE -#define MBUF_PER_POOL 8192 - -#define QUOTA_WATERMARK_MEMZONE_NAME "qw_global_vars" - -#endif /* _CONF_H_ */ diff --git a/examples/quota_watermark/meson.build b/examples/quota_watermark/meson.build deleted file mode 100644 index c370d7476..000000000 --- a/examples/quota_watermark/meson.build +++ /dev/null @@ -1,10 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2018 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' - -# Example app currently unsupported by meson build -build = false diff --git a/examples/quota_watermark/qw/Makefile b/examples/quota_watermark/qw/Makefile deleted file mode 100644 index 3f10f01c3..000000000 --- a/examples/quota_watermark/qw/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2010-2014 Intel Corporation - -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 - -# binary name -APP = qw - -# all source are stored in SRCS-y -SRCS-y := args.c init.c main.c - -CFLAGS += -O3 -DQW_SOFTWARE_FC -CFLAGS += $(WERROR_FLAGS) - -include $(RTE_SDK)/mk/rte.extapp.mk diff --git a/examples/quota_watermark/qw/args.c b/examples/quota_watermark/qw/args.c deleted file mode 100644 index a750ec258..000000000 --- a/examples/quota_watermark/qw/args.c +++ /dev/null @@ -1,78 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation - */ - -#include -#include -#include - -#include -#include - -#include "args.h" - - -unsigned int portmask = 0; - - -static void -usage(const char *prgname) -{ - fprintf(stderr, "Usage: %s [EAL args] -- -p \n" - "-p PORTMASK: hexadecimal bitmask of NIC ports to configure\n", - prgname); -} - -static unsigned long -parse_portmask(const char *portmask_str) -{ - return strtoul(portmask_str, NULL, 16); -} - -static void -check_core_count(void) -{ - if (rte_lcore_count() < 3) - rte_exit(EXIT_FAILURE, - "At least 3 cores need to be passed in the coremask\n"); -} - -static void -check_portmask_value(unsigned int portmask) -{ - unsigned int port_nb = 0; - - port_nb = __builtin_popcount(portmask); - - if (port_nb == 0) - rte_exit(EXIT_FAILURE, - "At least 2 ports need to be passed in the portmask\n"); - - if (port_nb % 2 != 0) - rte_exit(EXIT_FAILURE, - "An even number of ports is required in the portmask\n"); -} - -int -parse_qw_args(int argc, char **argv) -{ - int opt; - - while ((opt = getopt(argc, argv, "h:p:")) != -1) { - switch (opt) { - case 'h': - usage(argv[0]); - break; - case 'p': - portmask = parse_portmask(optarg); - break; - default: - usage(argv[0]); - } - } - - check_core_count(); - check_portmask_value(portmask); - - return 0; -} diff --git a/examples/quota_watermark/qw/args.h b/examples/quota_watermark/qw/args.h deleted file mode 100644 index ab777db01..000000000 --- a/examples/quota_watermark/qw/args.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation - */ - -#ifndef _ARGS_H_ -#define _ARGS_H_ - -extern unsigned int portmask; - -int parse_qw_args(int argc, char **argv); - -#endif /* _ARGS_H_ */ diff --git a/examples/quota_watermark/qw/init.c b/examples/quota_watermark/qw/init.c deleted file mode 100644 index 5a0f64f45..000000000 --- a/examples/quota_watermark/qw/init.c +++ /dev/null @@ -1,164 +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 "args.h" -#include "init.h" -#include "main.h" -#include "../include/conf.h" - - -static struct rte_eth_conf port_conf = { - .rxmode = { - .split_hdr_size = 0, - }, - .txmode = { - .mq_mode = ETH_DCB_NONE, - }, -}; - -static struct rte_eth_fc_conf fc_conf = { - .mode = RTE_FC_TX_PAUSE, - .high_water = 80 * 510 / 100, - .low_water = 60 * 510 / 100, - .pause_time = 1337, - .send_xon = 0, -}; - - -void configure_eth_port(uint16_t port_id) -{ - int ret; - uint16_t nb_rxd = RX_DESC_PER_QUEUE; - uint16_t nb_txd = TX_DESC_PER_QUEUE; - struct rte_eth_rxconf rxq_conf; - struct rte_eth_txconf txq_conf; - struct rte_eth_dev_info dev_info; - struct rte_eth_conf local_port_conf = port_conf; - - rte_eth_dev_stop(port_id); - - rte_eth_dev_info_get(port_id, &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_id, 1, 1, &local_port_conf); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Cannot configure port %u (error %d)\n", - (unsigned int) port_id, ret); - - ret = rte_eth_dev_adjust_nb_rx_tx_desc(port_id, &nb_rxd, &nb_txd); - if (ret < 0) - rte_exit(EXIT_FAILURE, - "Cannot adjust number of descriptors for port %u (error %d)\n", - (unsigned int) port_id, ret); - - /* Initialize the port's RX queue */ - rxq_conf = dev_info.default_rxconf; - rxq_conf.offloads = local_port_conf.rxmode.offloads; - ret = rte_eth_rx_queue_setup(port_id, 0, nb_rxd, - rte_eth_dev_socket_id(port_id), - &rxq_conf, - mbuf_pool); - if (ret < 0) - rte_exit(EXIT_FAILURE, - "Failed to setup RX queue on port %u (error %d)\n", - (unsigned int) port_id, ret); - - /* Initialize the port's TX queue */ - txq_conf = dev_info.default_txconf; - txq_conf.offloads = local_port_conf.txmode.offloads; - ret = rte_eth_tx_queue_setup(port_id, 0, nb_txd, - rte_eth_dev_socket_id(port_id), - &txq_conf); - if (ret < 0) - rte_exit(EXIT_FAILURE, - "Failed to setup TX queue on port %u (error %d)\n", - (unsigned int) port_id, ret); - - /* Initialize the port's flow control */ - ret = rte_eth_dev_flow_ctrl_set(port_id, &fc_conf); - if (ret < 0) - rte_exit(EXIT_FAILURE, - "Failed to setup hardware flow control on port %u (error %d)\n", - (unsigned int) port_id, ret); - - /* Start the port */ - ret = rte_eth_dev_start(port_id); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Failed to start port %u (error %d)\n", - (unsigned int) port_id, ret); - - /* Put it in promiscuous mode */ - rte_eth_promiscuous_enable(port_id); -} - -void -init_dpdk(void) -{ - if (rte_eth_dev_count_avail() < 2) - rte_exit(EXIT_FAILURE, "Not enough ethernet port available\n"); -} - -void init_ring(int lcore_id, uint16_t port_id) -{ - struct rte_ring *ring; - char ring_name[RTE_RING_NAMESIZE]; - - snprintf(ring_name, RTE_RING_NAMESIZE, - "core%d_port%d", lcore_id, port_id); - ring = rte_ring_create(ring_name, RING_SIZE, rte_socket_id(), - RING_F_SP_ENQ | RING_F_SC_DEQ); - - if (ring == NULL) - rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno)); - - *high_watermark = 80 * RING_SIZE / 100; - - rings[lcore_id][port_id] = ring; -} - -void -pair_ports(void) -{ - uint16_t i, j; - - /* Pair ports with their "closest neighbour" in the portmask */ - for (i = 0; i < RTE_MAX_ETHPORTS; i++) - if (is_bit_set(i, portmask)) - for (j = i + 1; j < RTE_MAX_ETHPORTS; j++) - if (is_bit_set(j, portmask)) { - port_pairs[i] = j; - port_pairs[j] = i; - i = j; - break; - } -} - -void -setup_shared_variables(void) -{ - const struct rte_memzone *qw_memzone; - - qw_memzone = rte_memzone_reserve(QUOTA_WATERMARK_MEMZONE_NAME, - 3 * sizeof(int), rte_socket_id(), 0); - if (qw_memzone == NULL) - rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno)); - - quota = qw_memzone->addr; - low_watermark = (unsigned int *) qw_memzone->addr + 1; - high_watermark = (unsigned int *) qw_memzone->addr + 2; -} diff --git a/examples/quota_watermark/qw/init.h b/examples/quota_watermark/qw/init.h deleted file mode 100644 index e0c90df72..000000000 --- a/examples/quota_watermark/qw/init.h +++ /dev/null @@ -1,14 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation - */ - -#ifndef _INIT_H_ -#define _INIT_H_ - -void configure_eth_port(uint16_t port_id); -void init_dpdk(void); -void init_ring(int lcore_id, uint16_t port_id); -void pair_ports(void); -void setup_shared_variables(void); - -#endif /* _INIT_H_ */ diff --git a/examples/quota_watermark/qw/main.c b/examples/quota_watermark/qw/main.c deleted file mode 100644 index a61360b99..000000000 --- a/examples/quota_watermark/qw/main.c +++ /dev/null @@ -1,365 +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 - -#include "args.h" -#include "main.h" -#include "init.h" -#include "../include/conf.h" - - -#ifdef QW_SOFTWARE_FC -#define SEND_PAUSE_FRAME(port_id, duration) send_pause_frame(port_id, duration) -#else -#define SEND_PAUSE_FRAME(port_id, duration) do { } while(0) -#endif - -#define ETHER_TYPE_FLOW_CONTROL 0x8808 - -struct ether_fc_frame { - uint16_t opcode; - uint16_t param; -} __attribute__((__packed__)); - - -int *quota; -unsigned int *low_watermark; -unsigned int *high_watermark; - -uint16_t port_pairs[RTE_MAX_ETHPORTS]; - -struct rte_ring *rings[RTE_MAX_LCORE][RTE_MAX_ETHPORTS]; -struct rte_mempool *mbuf_pool; - - -static void send_pause_frame(uint16_t port_id, uint16_t duration) -{ - struct rte_mbuf *mbuf; - struct ether_fc_frame *pause_frame; - struct rte_ether_hdr *hdr; - struct rte_ether_addr mac_addr; - - RTE_LOG_DP(DEBUG, USER1, - "Sending PAUSE frame (duration=%d) on port %d\n", - duration, port_id); - - /* Get a mbuf from the pool */ - mbuf = rte_pktmbuf_alloc(mbuf_pool); - if (unlikely(mbuf == NULL)) - return; - - /* Prepare a PAUSE frame */ - hdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr *); - pause_frame = (struct ether_fc_frame *) &hdr[1]; - - rte_eth_macaddr_get(port_id, &mac_addr); - rte_ether_addr_copy(&mac_addr, &hdr->s_addr); - - void *tmp = &hdr->d_addr.addr_bytes[0]; - *((uint64_t *)tmp) = 0x010000C28001ULL; - - hdr->ether_type = rte_cpu_to_be_16(ETHER_TYPE_FLOW_CONTROL); - - pause_frame->opcode = rte_cpu_to_be_16(0x0001); - pause_frame->param = rte_cpu_to_be_16(duration); - - mbuf->pkt_len = 60; - mbuf->data_len = 60; - - rte_eth_tx_burst(port_id, 0, &mbuf, 1); -} - -/** - * Get the previous enabled lcore ID - * - * @param lcore_id - * The current lcore ID. - * @return - * The previous enabled lcore_id or -1 if not found. - */ -static unsigned int -get_previous_lcore_id(unsigned int lcore_id) -{ - int i; - - for (i = lcore_id - 1; i >= 0; i--) - if (rte_lcore_is_enabled(i)) - return i; - - return -1; -} - -/** - * Get the last enabled lcore ID - * - * @return - * The last enabled lcore_id. - */ -static unsigned int -get_last_lcore_id(void) -{ - int i; - - for (i = RTE_MAX_LCORE; i >= 0; i--) - if (rte_lcore_is_enabled(i)) - return i; - - return 0; -} - -static void -receive_stage(__attribute__((unused)) void *args) -{ - int i, ret; - - uint16_t port_id; - uint16_t nb_rx_pkts; - - unsigned int lcore_id; - unsigned int free; - - struct rte_mbuf *pkts[MAX_PKT_QUOTA]; - struct rte_ring *ring; - enum ring_state ring_state[RTE_MAX_ETHPORTS] = { RING_READY }; - - lcore_id = rte_lcore_id(); - - RTE_LOG(INFO, USER1, - "%s() started on core %u\n", __func__, lcore_id); - - while (1) { - - /* Process each port round robin style */ - for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) { - - if (!is_bit_set(port_id, portmask)) - continue; - - ring = rings[lcore_id][port_id]; - - if (ring_state[port_id] != RING_READY) { - if (rte_ring_count(ring) > *low_watermark) - continue; - else - ring_state[port_id] = RING_READY; - } - - /* Enqueue received packets on the RX ring */ - nb_rx_pkts = rte_eth_rx_burst(port_id, 0, pkts, - (uint16_t) *quota); - ret = rte_ring_enqueue_bulk(ring, (void *) pkts, - nb_rx_pkts, &free); - if (RING_SIZE - free > *high_watermark) { - ring_state[port_id] = RING_OVERLOADED; - send_pause_frame(port_id, 1337); - } - - if (ret == 0) { - - /* - * Return mbufs to the pool, - * effectively dropping packets - */ - for (i = 0; i < nb_rx_pkts; i++) - rte_pktmbuf_free(pkts[i]); - } - } - } -} - -static int -pipeline_stage(__attribute__((unused)) void *args) -{ - int i, ret; - int nb_dq_pkts; - - uint16_t port_id; - - unsigned int lcore_id, previous_lcore_id; - unsigned int free; - - void *pkts[MAX_PKT_QUOTA]; - struct rte_ring *rx, *tx; - enum ring_state ring_state[RTE_MAX_ETHPORTS] = { RING_READY }; - - lcore_id = rte_lcore_id(); - previous_lcore_id = get_previous_lcore_id(lcore_id); - - RTE_LOG(INFO, USER1, - "%s() started on core %u - processing packets from core %u\n", - __func__, lcore_id, previous_lcore_id); - - while (1) { - - for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) { - - if (!is_bit_set(port_id, portmask)) - continue; - - tx = rings[lcore_id][port_id]; - rx = rings[previous_lcore_id][port_id]; - - if (ring_state[port_id] != RING_READY) { - if (rte_ring_count(tx) > *low_watermark) - continue; - else - ring_state[port_id] = RING_READY; - } - - /* Dequeue up to quota mbuf from rx */ - nb_dq_pkts = rte_ring_dequeue_burst(rx, pkts, - *quota, NULL); - if (unlikely(nb_dq_pkts < 0)) - continue; - - /* Enqueue them on tx */ - ret = rte_ring_enqueue_bulk(tx, pkts, - nb_dq_pkts, &free); - if (RING_SIZE - free > *high_watermark) - ring_state[port_id] = RING_OVERLOADED; - - if (ret == 0) { - - /* - * Return mbufs to the pool, - * effectively dropping packets - */ - for (i = 0; i < nb_dq_pkts; i++) - rte_pktmbuf_free(pkts[i]); - } - } - } - - return 0; -} - -static int -send_stage(__attribute__((unused)) void *args) -{ - uint16_t nb_dq_pkts; - - uint16_t port_id; - uint16_t dest_port_id; - - unsigned int lcore_id, previous_lcore_id; - - struct rte_ring *tx; - struct rte_mbuf *tx_pkts[MAX_PKT_QUOTA]; - - lcore_id = rte_lcore_id(); - previous_lcore_id = get_previous_lcore_id(lcore_id); - - RTE_LOG(INFO, USER1, - "%s() started on core %u - processing packets from core %u\n", - __func__, lcore_id, previous_lcore_id); - - while (1) { - - /* Process each ring round robin style */ - for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) { - - if (!is_bit_set(port_id, portmask)) - continue; - - dest_port_id = port_pairs[port_id]; - tx = rings[previous_lcore_id][port_id]; - - if (rte_ring_empty(tx)) - continue; - - /* Dequeue packets from tx and send them */ - nb_dq_pkts = (uint16_t) rte_ring_dequeue_burst(tx, - (void *) tx_pkts, *quota, NULL); - rte_eth_tx_burst(dest_port_id, 0, tx_pkts, nb_dq_pkts); - - /* TODO: Check if nb_dq_pkts == nb_tx_pkts? */ - } - } - - return 0; -} - -int -main(int argc, char **argv) -{ - int ret; - unsigned int lcore_id, master_lcore_id, last_lcore_id; - - uint16_t port_id; - - rte_log_set_global_level(RTE_LOG_INFO); - - ret = rte_eal_init(argc, argv); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Cannot initialize EAL\n"); - - argc -= ret; - argv += ret; - - init_dpdk(); - setup_shared_variables(); - - *quota = 32; - *low_watermark = 60 * RING_SIZE / 100; - - last_lcore_id = get_last_lcore_id(); - master_lcore_id = rte_get_master_lcore(); - - /* Parse the application's arguments */ - ret = parse_qw_args(argc, argv); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Invalid quota/watermark argument(s)\n"); - - /* Create a pool of mbuf to store packets */ - mbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", MBUF_PER_POOL, 32, 0, - MBUF_DATA_SIZE, rte_socket_id()); - if (mbuf_pool == NULL) - rte_panic("%s\n", rte_strerror(rte_errno)); - - for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) - if (is_bit_set(port_id, portmask)) { - configure_eth_port(port_id); - init_ring(master_lcore_id, port_id); - } - - pair_ports(); - - /* - * Start pipeline_connect() on all the available slave lcores - * but the last - */ - for (lcore_id = 0 ; lcore_id < last_lcore_id; lcore_id++) { - if (rte_lcore_is_enabled(lcore_id) && - lcore_id != master_lcore_id) { - - for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) - if (is_bit_set(port_id, portmask)) - init_ring(lcore_id, port_id); - - rte_eal_remote_launch(pipeline_stage, - NULL, lcore_id); - } - } - - /* Start send_stage() on the last slave core */ - rte_eal_remote_launch(send_stage, NULL, last_lcore_id); - - /* Start receive_stage() on the master core */ - receive_stage(NULL); - - return 0; -} diff --git a/examples/quota_watermark/qw/main.h b/examples/quota_watermark/qw/main.h deleted file mode 100644 index 9903ddc8c..000000000 --- a/examples/quota_watermark/qw/main.h +++ /dev/null @@ -1,31 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation - */ - -#ifndef _MAIN_H_ -#define _MAIN_H_ - -#include "../include/conf.h" - -enum ring_state { - RING_READY, - RING_OVERLOADED, -}; - -extern int *quota; -extern unsigned int *low_watermark; -extern unsigned int *high_watermark; - -extern uint16_t port_pairs[RTE_MAX_ETHPORTS]; - -extern struct rte_ring *rings[RTE_MAX_LCORE][RTE_MAX_ETHPORTS]; -extern struct rte_mempool *mbuf_pool; - - -static inline int -is_bit_set(int i, unsigned int mask) -{ - return (1 << i) & mask; -} - -#endif /* _MAIN_H_ */ diff --git a/examples/quota_watermark/qwctl/Makefile b/examples/quota_watermark/qwctl/Makefile deleted file mode 100644 index a40f28025..000000000 --- a/examples/quota_watermark/qwctl/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2010-2014 Intel Corporation - -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 - -# binary name -APP = qwctl - -# all source are stored in SRCS-y -SRCS-y := commands.c qwctl.c - -CFLAGS += -O3 -CFLAGS += $(WERROR_FLAGS) - -include $(RTE_SDK)/mk/rte.extapp.mk diff --git a/examples/quota_watermark/qwctl/commands.c b/examples/quota_watermark/qwctl/commands.c deleted file mode 100644 index a1c646b9f..000000000 --- a/examples/quota_watermark/qwctl/commands.c +++ /dev/null @@ -1,196 +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 "qwctl.h" -#include "../include/conf.h" - - -/** - * help command - */ - -struct cmd_help_tokens { - cmdline_fixed_string_t verb; -}; - -cmdline_parse_token_string_t cmd_help_verb = - TOKEN_STRING_INITIALIZER(struct cmd_help_tokens, verb, "help"); - -static void -cmd_help_handler(__attribute__((unused)) void *parsed_result, - struct cmdline *cl, - __attribute__((unused)) void *data) -{ - cmdline_printf(cl, "Available commands:\n" - "- help\n" - "- set [ring_name|variable] \n" - "- show [ring_name|variable]\n" - "\n" - "Available variables:\n" - "- low_watermark\n" - "- quota\n" - "- ring names follow the core%%u_port%%u format\n"); -} - -cmdline_parse_inst_t cmd_help = { - .f = cmd_help_handler, - .data = NULL, - .help_str = "show help", - .tokens = { - (void *) &cmd_help_verb, - NULL, - }, -}; - - -/** - * set command - */ - -struct cmd_set_tokens { - cmdline_fixed_string_t verb; - cmdline_fixed_string_t variable; - uint32_t value; -}; - -cmdline_parse_token_string_t cmd_set_verb = - TOKEN_STRING_INITIALIZER(struct cmd_set_tokens, verb, "set"); - -cmdline_parse_token_string_t cmd_set_variable = - TOKEN_STRING_INITIALIZER(struct cmd_set_tokens, variable, NULL); - -cmdline_parse_token_num_t cmd_set_value = - TOKEN_NUM_INITIALIZER(struct cmd_set_tokens, value, UINT32); - -static void -cmd_set_handler(__attribute__((unused)) void *parsed_result, - struct cmdline *cl, - __attribute__((unused)) void *data) -{ - struct cmd_set_tokens *tokens = parsed_result; - struct rte_ring *ring; - - if (!strcmp(tokens->variable, "quota")) { - - if (tokens->value > 0 && tokens->value <= MAX_PKT_QUOTA) - *quota = tokens->value; - else - cmdline_printf(cl, "quota must be between 1 and %u\n", - MAX_PKT_QUOTA); - } - - else if (!strcmp(tokens->variable, "low_watermark")) { - - if (tokens->value <= 100) - *low_watermark = tokens->value * RING_SIZE / 100; - else - cmdline_printf(cl, - "low_watermark must be between 0%% and 100%%\n"); - } - - else { - - ring = rte_ring_lookup(tokens->variable); - if (ring == NULL) - cmdline_printf(cl, "Cannot find ring \"%s\"\n", - tokens->variable); - else - if (tokens->value >= *low_watermark * 100 / RING_SIZE - && tokens->value <= 100) - *high_watermark = tokens->value * - RING_SIZE / 100; - else - cmdline_printf(cl, - "ring high watermark must be between %u%% and 100%%\n", - *low_watermark * 100 / RING_SIZE); - } -} - -cmdline_parse_inst_t cmd_set = { - .f = cmd_set_handler, - .data = NULL, - .help_str = "Set a variable value", - .tokens = { - (void *) &cmd_set_verb, - (void *) &cmd_set_variable, - (void *) &cmd_set_value, - NULL, - }, -}; - - -/** - * show command - */ - -struct cmd_show_tokens { - cmdline_fixed_string_t verb; - cmdline_fixed_string_t variable; -}; - -cmdline_parse_token_string_t cmd_show_verb = - TOKEN_STRING_INITIALIZER(struct cmd_show_tokens, verb, "show"); - -cmdline_parse_token_string_t cmd_show_variable = - TOKEN_STRING_INITIALIZER(struct cmd_show_tokens, - variable, NULL); - - -static void -cmd_show_handler(__attribute__((unused)) void *parsed_result, - struct cmdline *cl, - __attribute__((unused)) void *data) -{ - struct cmd_show_tokens *tokens = parsed_result; - struct rte_ring *ring; - - if (!strcmp(tokens->variable, "quota")) - cmdline_printf(cl, "Global quota: %d\n", *quota); - - else if (!strcmp(tokens->variable, "low_watermark")) - cmdline_printf(cl, "Global low_watermark: %u\n", - *low_watermark); - - else { - - ring = rte_ring_lookup(tokens->variable); - if (ring == NULL) - cmdline_printf(cl, "Cannot find ring \"%s\"\n", - tokens->variable); - else - rte_ring_dump(stdout, ring); - } -} - -cmdline_parse_inst_t cmd_show = { - .f = cmd_show_handler, - .data = NULL, - .help_str = "Show a variable value", - .tokens = { - (void *) &cmd_show_verb, - (void *) &cmd_show_variable, - NULL, - }, -}; - - -cmdline_parse_ctx_t qwctl_ctx[] = { - (cmdline_parse_inst_t *)&cmd_help, - (cmdline_parse_inst_t *)&cmd_set, - (cmdline_parse_inst_t *)&cmd_show, - NULL, -}; diff --git a/examples/quota_watermark/qwctl/commands.h b/examples/quota_watermark/qwctl/commands.h deleted file mode 100644 index 4a4e97475..000000000 --- a/examples/quota_watermark/qwctl/commands.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation - */ - -#ifndef _COMMANDS_H_ -#define _COMMANDS_H_ - -#include - -extern cmdline_parse_ctx_t qwctl_ctx[]; - -#endif /* _COMMANDS_H_ */ diff --git a/examples/quota_watermark/qwctl/qwctl.c b/examples/quota_watermark/qwctl/qwctl.c deleted file mode 100644 index 2f7914c80..000000000 --- a/examples/quota_watermark/qwctl/qwctl.c +++ /dev/null @@ -1,67 +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 -#include - - -#include "qwctl.h" -#include "commands.h" -#include "../include/conf.h" - - -int *quota; -unsigned int *low_watermark; -unsigned int *high_watermark; - - -static void -setup_shared_variables(void) -{ - const struct rte_memzone *qw_memzone; - - qw_memzone = rte_memzone_lookup(QUOTA_WATERMARK_MEMZONE_NAME); - if (qw_memzone == NULL) - rte_exit(EXIT_FAILURE, "Couldn't find memzone\n"); - - quota = qw_memzone->addr; - low_watermark = (unsigned int *) qw_memzone->addr + 1; - high_watermark = (unsigned int *) qw_memzone->addr + 2; -} - -int main(int argc, char **argv) -{ - int ret; - struct cmdline *cl; - - rte_log_set_global_level(RTE_LOG_INFO); - - ret = rte_eal_init(argc, argv); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Cannot initialize EAL\n"); - - setup_shared_variables(); - - cl = cmdline_stdin_new(qwctl_ctx, "qwctl> "); - if (cl == NULL) - rte_exit(EXIT_FAILURE, "Cannot create cmdline instance\n"); - - cmdline_interact(cl); - cmdline_stdin_exit(cl); - - return 0; -} diff --git a/examples/quota_watermark/qwctl/qwctl.h b/examples/quota_watermark/qwctl/qwctl.h deleted file mode 100644 index 2a4559388..000000000 --- a/examples/quota_watermark/qwctl/qwctl.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation - */ - -#ifndef _MAIN_H_ -#define _MAIN_H_ - -extern int *quota; -extern unsigned int *low_watermark; -extern unsigned int *high_watermark; - -#endif /* _MAIN_H_ */ From patchwork Thu Oct 3 13:19:16 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bruce Richardson X-Patchwork-Id: 60495 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id CC48C1C127; Thu, 3 Oct 2019 15:19:56 +0200 (CEST) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by dpdk.org (Postfix) with ESMTP id 39EEF1C11A; Thu, 3 Oct 2019 15:19:54 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 03 Oct 2019 06:19:53 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.67,252,1566889200"; d="scan'208";a="185910570" Received: from silpixa00399126.ir.intel.com (HELO silpixa00399126.ger.corp.intel.com) ([10.237.223.2]) by orsmga008.jf.intel.com with ESMTP; 03 Oct 2019 06:19:51 -0700 From: Bruce Richardson To: dev@dpdk.org Cc: techboard@dpdk.org, Ciara Power Date: Thu, 3 Oct 2019 14:19:16 +0100 Message-Id: <20191003131918.30970-5-bruce.richardson@intel.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191003131918.30970-1-bruce.richardson@intel.com> References: <20191003131918.30970-1-bruce.richardson@intel.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH 4/6] examples/netmap-compat: 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: Ciara Power Rather than providing a shim layer on top of netmap, we should instead encourage users to create apps using the DPDK APIs directly. Signed-off-by: Ciara Power --- MAINTAINERS | 3 - doc/guides/sample_app_ug/index.rst | 1 - doc/guides/sample_app_ug/intro.rst | 2 +- .../sample_app_ug/netmap_compatibility.rst | 130 --- examples/Makefile | 1 - examples/meson.build | 2 +- examples/netmap_compat/Makefile | 22 - examples/netmap_compat/bridge/Makefile | 35 - examples/netmap_compat/bridge/bridge.c | 343 ------- examples/netmap_compat/lib/compat_netmap.c | 899 ------------------ examples/netmap_compat/lib/compat_netmap.h | 51 - examples/netmap_compat/meson.build | 10 - examples/netmap_compat/netmap/netmap.h | 289 ------ examples/netmap_compat/netmap/netmap_user.h | 95 -- 14 files changed, 2 insertions(+), 1881 deletions(-) delete mode 100644 doc/guides/sample_app_ug/netmap_compatibility.rst delete mode 100644 examples/netmap_compat/Makefile delete mode 100644 examples/netmap_compat/bridge/Makefile delete mode 100644 examples/netmap_compat/bridge/bridge.c delete mode 100644 examples/netmap_compat/lib/compat_netmap.c delete mode 100644 examples/netmap_compat/lib/compat_netmap.h delete mode 100644 examples/netmap_compat/meson.build delete mode 100644 examples/netmap_compat/netmap/netmap.h delete mode 100644 examples/netmap_compat/netmap/netmap_user.h diff --git a/MAINTAINERS b/MAINTAINERS index 7be363327..6b9fa4dc2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1464,9 +1464,6 @@ F: doc/guides/sample_app_ug/link_status_intr.rst F: examples/load_balancer/ F: doc/guides/sample_app_ug/load_balancer.rst -F: examples/netmap_compat/ -F: doc/guides/sample_app_ug/netmap_compatibility.rst - L-threads - EXPERIMENTAL M: John McNamara F: examples/performance-thread/ diff --git a/doc/guides/sample_app_ug/index.rst b/doc/guides/sample_app_ug/index.rst index dafe8553f..5f4924df6 100644 --- a/doc/guides/sample_app_ug/index.rst +++ b/doc/guides/sample_app_ug/index.rst @@ -43,7 +43,6 @@ Sample Applications User Guides vhost_scsi vhost_crypto vdpa - netmap_compatibility ip_pipeline test_pipeline eventdev_pipeline diff --git a/doc/guides/sample_app_ug/intro.rst b/doc/guides/sample_app_ug/intro.rst index 6e0af6301..39af887da 100644 --- a/doc/guides/sample_app_ug/intro.rst +++ b/doc/guides/sample_app_ug/intro.rst @@ -31,7 +31,7 @@ applications that are available in the examples directory of DPDK: .. table:: **Some of the DPDK Sample applications** +---------------------------------------+--------------------------------------+ - | Bonding | Netmap Compatibility | + | Bonding | | +---------------------------------------+--------------------------------------+ | Command Line | Packet Ordering | +---------------------------------------+--------------------------------------+ diff --git a/doc/guides/sample_app_ug/netmap_compatibility.rst b/doc/guides/sample_app_ug/netmap_compatibility.rst deleted file mode 100644 index 219613e2a..000000000 --- a/doc/guides/sample_app_ug/netmap_compatibility.rst +++ /dev/null @@ -1,130 +0,0 @@ -.. SPDX-License-Identifier: BSD-3-Clause - Copyright(c) 2010-2014 Intel Corporation. - -Netmap Compatibility Sample Application -======================================= - -Introduction ------------- - -The Netmap compatibility library provides a minimal set of APIs to give programs written against the Netmap APIs -the ability to be run, with minimal changes to their source code, using the DPDK to perform the actual packet I/O. - -Since Netmap applications use regular system calls, like ``open()``, ``ioctl()`` and -``mmap()`` to communicate with the Netmap kernel module performing the packet I/O, -the ``compat_netmap`` library provides a set of similar APIs to use in place of those system calls, -effectively turning a Netmap application into a DPDK application. - -The provided library is currently minimal and doesn't support all the features that Netmap supports, -but is enough to run simple applications, such as the bridge example detailed below. - -Knowledge of Netmap is required to understand the rest of this section. -Please refer to the Netmap distribution for details about Netmap. - -Available APIs --------------- - -The library provides the following drop-in replacements for system calls usually used in Netmap applications: - -* ``rte_netmap_close()`` - -* ``rte_netmap_ioctl()`` - -* ``rte_netmap_open()`` - -* ``rte_netmap_mmap()`` - -* ``rte_netmap_poll()`` - -They use the same signature as their libc counterparts, and can be used as drop-in replacements in most cases. - -Caveats -------- - -Given the difference between the way Netmap and the DPDK approach packet I/O, -there are caveats and limitations to be aware of when trying to use the ``compat_netmap`` library, the most important of these are listed below. -These may change as the library is updated: - -* Any system call that can potentially affect file descriptors cannot be used with a descriptor returned by the ``rte_netmap_open()`` function. - -Note that: - -* The ``rte_netmap_mmap()`` function merely returns the address of a DPDK memzone. - The address, length, flags, offset, and other arguments are ignored. - -* The ``rte_netmap_poll()`` function only supports infinite (negative) or zero time outs. - It effectively turns calls to the ``poll()`` system call made in a Netmap application into polling of the DPDK ports, - changing the semantics of the usual POSIX defined poll. - -* Not all of Netmap's features are supported: host rings, - slot flags and so on are not supported or are simply not relevant in the DPDK model. - -* The Netmap manual page states that "*a device obtained through /dev/netmap also supports the ioctl supported by network devices*". - This is not the case with this compatibility layer. - -* The Netmap kernel module exposes a sysfs interface to change some internal parameters, such as the size of the shared memory region. - This interface is not available when using this compatibility layer. - -Porting Netmap Applications ---------------------------- - -Porting Netmap applications typically involves two major steps: - -* Changing the system calls to use their ``compat_netmap`` library counterparts. - -* Adding further DPDK initialization code. - -Since the ``compat_netmap`` functions have the same signature as the usual libc calls, the change is trivial in most cases. - -The usual DPDK initialization code involving ``rte_eal_init()`` and ``rte_pci_probe()`` -has to be added to the Netmap application in the same way it is used in all other DPDK sample applications. -Please refer to the *DPDK Programmer's Guide* and example source code for details about initialization. - -In addition of the regular DPDK initialization code, -the ported application needs to call initialization functions for the ``compat_netmap`` library, -namely ``rte_netmap_init()`` and ``rte_netmap_init_port()``. - -These two initialization functions take ``compat_netmap`` specific data structures as parameters: -``struct rte_netmap_conf`` and ``struct rte_netmap_port_conf``. -The structures' fields are Netmap related and are self-explanatory for developers familiar with Netmap. -They are defined in ``$RTE_SDK/examples/netmap_compat/lib/compat_netmap.h``. - -The bridge application is an example largely based on the bridge example shipped with the Netmap distribution. -It shows how a minimal Netmap application with minimal and straightforward source code changes can be run on top of the DPDK. -Please refer to ``$RTE_SDK/examples/netmap_compat/bridge/bridge.c`` for an example of a ported application. - -Compiling the Application -------------------------- - -To compile the sample application see :doc:`compiling`. - -The application is located in the ``netmap_compat`` sub-directory. - -Running the "bridge" Sample Application ---------------------------------------- - -The application requires a single command line option: - -.. code-block:: console - - ./build/bridge [EAL options] -- -i INTERFACE_A [-i INTERFACE_B] - -where, - -* ``-i INTERFACE``: Interface (DPDK port number) to use. - - If a single ``-i`` parameter is given, the interface will send back all the traffic it receives. - If two ``-i`` parameters are given, the two interfaces form a bridge, - where traffic received on one interface is replicated and sent to the other interface. - -For example, to run the application in a linux environment using port 0 and 2: - -.. code-block:: console - - ./build/bridge [EAL options] -- -i 0 -i 2 - -Refer to the *DPDK Getting Started Guide for Linux* for general information on running applications and -the Environment Abstraction Layer (EAL) options. - -Note that unlike a traditional bridge or the ``l2fwd`` sample application, no MAC address changes are done on the frames. -Do not forget to take this into account when configuring a traffic generators and testing this sample application. diff --git a/examples/Makefile b/examples/Makefile index 02ff86534..6bba09ce9 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -50,7 +50,6 @@ endif DIRS-y += link_status_interrupt DIRS-$(CONFIG_RTE_LIBRTE_LPM) += load_balancer DIRS-y += multi_process -DIRS-y += netmap_compat/bridge DIRS-y += ntb DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += packet_ordering ifeq ($(CONFIG_RTE_ARCH_X86_64),y) diff --git a/examples/meson.build b/examples/meson.build index 6c26fffb4..f0356f2a1 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -30,7 +30,7 @@ all_examples = [ 'multi_process/hotplug_mp', 'multi_process/simple_mp', 'multi_process/symmetric_mp', - 'netmap_compat', 'ntb', 'packet_ordering', + 'ntb', 'packet_ordering', 'performance-thread', 'ptpclient', 'qos_meter', 'qos_sched', 'rxtx_callbacks', diff --git a/examples/netmap_compat/Makefile b/examples/netmap_compat/Makefile deleted file mode 100644 index b9f78d173..000000000 --- a/examples/netmap_compat/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2010-2014 Intel Corporation - -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 -unexport RTE_SRCDIR RTE_OUTPUT RTE_EXTMK - -DIRS-y += bridge - -.PHONY: all clean $(DIRS-y) - -all: $(DIRS-y) -clean: $(DIRS-y) - -$(DIRS-y): - $(MAKE) -C $@ $(MAKECMDGOALS) O=$(RTE_OUTPUT) diff --git a/examples/netmap_compat/bridge/Makefile b/examples/netmap_compat/bridge/Makefile deleted file mode 100644 index 7ed30e57b..000000000 --- a/examples/netmap_compat/bridge/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2010-2014 Intel Corporation - -ifeq ($(RTE_SDK),) -$(error "Please define the 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 - -ifneq ($(CONFIG_RTE_EXEC_ENV_LINUX),y) -$(info This application can only operate in a linux environment, \ -please change the definition of the RTE_TARGET environment variable) -all: -clean: -else - -# binary name -APP = bridge - -# for compat_netmap.c -VPATH := $(SRCDIR)/../lib - -# all source are stored in SRCS-y -SRCS-y := bridge.c -SRCS-y += compat_netmap.c - -CFLAGS += -O3 -I$(SRCDIR)/../lib -I$(SRCDIR)/../netmap -CFLAGS += $(WERROR_FLAGS) - -include $(RTE_SDK)/mk/rte.extapp.mk - -endif diff --git a/examples/netmap_compat/bridge/bridge.c b/examples/netmap_compat/bridge/bridge.c deleted file mode 100644 index d40e163b0..000000000 --- a/examples/netmap_compat/bridge/bridge.c +++ /dev/null @@ -1,343 +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 -#include -#include "compat_netmap.h" - - -#define BUF_SIZE RTE_MBUF_DEFAULT_DATAROOM -#define MBUF_DATA_SIZE (BUF_SIZE + RTE_PKTMBUF_HEADROOM) - -#define MBUF_PER_POOL 8192 - -struct rte_eth_conf eth_conf = { - .rxmode = { - .split_hdr_size = 0, - }, - .txmode = { - .mq_mode = ETH_MQ_TX_NONE, - }, -}; - -#define MAX_QUEUE_NUM 1 -#define RX_QUEUE_NUM 1 -#define TX_QUEUE_NUM 1 - -#define MAX_DESC_NUM 0x400 -#define RX_DESC_NUM 0x100 -#define TX_DESC_NUM 0x200 - -#define RX_SYNC_NUM 0x20 -#define TX_SYNC_NUM 0x20 - -struct rte_netmap_port_conf port_conf = { - .eth_conf = ð_conf, - .socket_id = SOCKET_ID_ANY, - .nr_tx_rings = TX_QUEUE_NUM, - .nr_rx_rings = RX_QUEUE_NUM, - .nr_tx_slots = TX_DESC_NUM, - .nr_rx_slots = RX_DESC_NUM, - .tx_burst = TX_SYNC_NUM, - .rx_burst = RX_SYNC_NUM, -}; - -struct rte_netmap_conf netmap_conf = { - .socket_id = SOCKET_ID_ANY, - .max_bufsz = BUF_SIZE, - .max_rings = MAX_QUEUE_NUM, - .max_slots = MAX_DESC_NUM, -}; - -static int stop = 0; - -#define MAX_PORT_NUM 2 - -struct netmap_port { - int fd; - struct netmap_if *nmif; - struct netmap_ring *rx_ring; - struct netmap_ring *tx_ring; - const char *str; - uint8_t id; -}; - -static struct { - uint32_t num; - struct netmap_port p[MAX_PORT_NUM]; - void *mem; -} ports; - -static void -usage(const char *prgname) -{ - fprintf(stderr, "Usage: %s [EAL args] -- [OPTION]...\n" - "-h, --help \t Show this help message and exit\n" - "-i INTERFACE_A \t Interface (DPDK port number) to use\n" - "[ -i INTERFACE_B \t Interface (DPDK port number) to use ]\n", - prgname); -} - -static uint8_t -parse_portid(const char *portid_str) -{ - char *end; - unsigned id; - - id = strtoul(portid_str, &end, 10); - - if (end == portid_str || *end != '\0' || id > RTE_MAX_ETHPORTS) - rte_exit(EXIT_FAILURE, "Invalid port number\n"); - - return (uint8_t) id; -} - -static int -parse_args(int argc, char **argv) -{ - int opt; - - while ((opt = getopt(argc, argv, "hi:")) != -1) { - switch (opt) { - case 'h': - usage(argv[0]); - rte_exit(EXIT_SUCCESS, "exiting..."); - break; - case 'i': - if (ports.num >= RTE_DIM(ports.p)) { - usage(argv[0]); - rte_exit(EXIT_FAILURE, "configs with %u " - "ports are not supported\n", - ports.num + 1); - - } - - ports.p[ports.num].str = optarg; - ports.p[ports.num].id = parse_portid(optarg); - ports.num++; - break; - default: - usage(argv[0]); - rte_exit(EXIT_FAILURE, "invalid option: %c\n", opt); - } - } - - return 0; -} - -static void sigint_handler(__rte_unused int sig) -{ - stop = 1; - signal(SIGINT, SIG_DFL); -} - -static void move(int n, struct netmap_ring *rx, struct netmap_ring *tx) -{ - uint32_t tmp; - - while (n-- > 0) { - tmp = tx->slot[tx->cur].buf_idx; - - tx->slot[tx->cur].buf_idx = rx->slot[rx->cur].buf_idx; - tx->slot[tx->cur].len = rx->slot[rx->cur].len; - tx->slot[tx->cur].flags |= NS_BUF_CHANGED; - tx->cur = NETMAP_RING_NEXT(tx, tx->cur); - tx->avail--; - - rx->slot[rx->cur].buf_idx = tmp; - rx->slot[rx->cur].flags |= NS_BUF_CHANGED; - rx->cur = NETMAP_RING_NEXT(rx, rx->cur); - rx->avail--; - } -} - -static int -netmap_port_open(uint32_t idx) -{ - int err; - struct netmap_port *port; - struct nmreq req; - - port = ports.p + idx; - - port->fd = rte_netmap_open("/dev/netmap", O_RDWR); - - strlcpy(req.nr_name, port->str, sizeof(req.nr_name)); - req.nr_version = NETMAP_API; - req.nr_ringid = 0; - - err = rte_netmap_ioctl(port->fd, NIOCGINFO, &req); - if (err) { - printf("[E] NIOCGINFO ioctl failed (error %d)\n", err); - return err; - } - - strlcpy(req.nr_name, port->str, sizeof(req.nr_name)); - req.nr_version = NETMAP_API; - req.nr_ringid = 0; - - err = rte_netmap_ioctl(port->fd, NIOCREGIF, &req); - if (err) { - printf("[E] NIOCREGIF ioctl failed (error %d)\n", err); - return err; - } - - /* mmap only once. */ - if (ports.mem == NULL) - ports.mem = rte_netmap_mmap(NULL, req.nr_memsize, - PROT_WRITE | PROT_READ, MAP_PRIVATE, port->fd, 0); - - if (ports.mem == MAP_FAILED) { - printf("[E] NETMAP mmap failed for fd: %d)\n", port->fd); - return -ENOMEM; - } - - port->nmif = NETMAP_IF(ports.mem, req.nr_offset); - - port->tx_ring = NETMAP_TXRING(port->nmif, 0); - port->rx_ring = NETMAP_RXRING(port->nmif, 0); - - return 0; -} - - -int main(int argc, char *argv[]) -{ - int err, ret; - uint32_t i, pmsk; - struct nmreq req; - struct pollfd pollfd[MAX_PORT_NUM]; - struct rte_mempool *pool; - struct netmap_ring *rx_ring, *tx_ring; - - ret = rte_eal_init(argc, argv); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Cannot initialize EAL\n"); - - argc -= ret; - argv += ret; - - parse_args(argc, argv); - - if (ports.num == 0) - rte_exit(EXIT_FAILURE, "no ports specified\n"); - - if (rte_eth_dev_count_avail() < 1) - rte_exit(EXIT_FAILURE, "Not enough ethernet ports available\n"); - - pool = rte_pktmbuf_pool_create("mbuf_pool", MBUF_PER_POOL, 32, 0, - MBUF_DATA_SIZE, rte_socket_id()); - if (pool == NULL) - rte_exit(EXIT_FAILURE, "Couldn't create mempool\n"); - - netmap_conf.socket_id = rte_socket_id(); - err = rte_netmap_init(&netmap_conf); - - if (err < 0) - rte_exit(EXIT_FAILURE, - "Couldn't initialize librte_compat_netmap\n"); - else - printf("librte_compat_netmap initialized\n"); - - port_conf.pool = pool; - port_conf.socket_id = rte_socket_id(); - - for (i = 0; i != ports.num; i++) { - - err = rte_netmap_init_port(ports.p[i].id, &port_conf); - if (err < 0) - rte_exit(EXIT_FAILURE, "Couldn't setup port %hhu\n", - ports.p[i].id); - - rte_eth_promiscuous_enable(ports.p[i].id); - } - - for (i = 0; i != ports.num; i++) { - - err = netmap_port_open(i); - if (err) { - rte_exit(EXIT_FAILURE, "Couldn't set port %hhu " - "under NETMAP control\n", - ports.p[i].id); - } - else - printf("Port %hhu now in Netmap mode\n", ports.p[i].id); - } - - memset(pollfd, 0, sizeof(pollfd)); - - for (i = 0; i != ports.num; i++) { - pollfd[i].fd = ports.p[i].fd; - pollfd[i].events = POLLIN | POLLOUT; - } - - signal(SIGINT, sigint_handler); - - pmsk = ports.num - 1; - - printf("Bridge up and running!\n"); - - while (!stop) { - uint32_t n_pkts; - - pollfd[0].revents = 0; - pollfd[1].revents = 0; - - ret = rte_netmap_poll(pollfd, ports.num, 0); - if (ret < 0) { - stop = 1; - printf("[E] poll returned with error %d\n", ret); - } - - if (((pollfd[0].revents | pollfd[1].revents) & POLLERR) != 0) { - printf("POLLERR!\n"); - } - - if ((pollfd[0].revents & POLLIN) != 0 && - (pollfd[pmsk].revents & POLLOUT) != 0) { - - rx_ring = ports.p[0].rx_ring; - tx_ring = ports.p[pmsk].tx_ring; - - n_pkts = RTE_MIN(rx_ring->avail, tx_ring->avail); - move(n_pkts, rx_ring, tx_ring); - } - - if (pmsk != 0 && (pollfd[pmsk].revents & POLLIN) != 0 && - (pollfd[0].revents & POLLOUT) != 0) { - - rx_ring = ports.p[pmsk].rx_ring; - tx_ring = ports.p[0].tx_ring; - - n_pkts = RTE_MIN(rx_ring->avail, tx_ring->avail); - move(n_pkts, rx_ring, tx_ring); - } - } - - printf("Bridge stopped!\n"); - - for (i = 0; i != ports.num; i++) { - err = rte_netmap_ioctl(ports.p[i].fd, NIOCUNREGIF, &req); - if (err) { - printf("[E] NIOCUNREGIF ioctl failed (error %d)\n", - err); - } - else - printf("Port %hhu unregistered from Netmap mode\n", ports.p[i].id); - - rte_netmap_close(ports.p[i].fd); - } - return 0; -} diff --git a/examples/netmap_compat/lib/compat_netmap.c b/examples/netmap_compat/lib/compat_netmap.c deleted file mode 100644 index 10a437943..000000000 --- a/examples/netmap_compat/lib/compat_netmap.c +++ /dev/null @@ -1,899 +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 -#include -#include -#include -#include -#include -#include - -#include "compat_netmap.h" - -struct netmap_port { - struct rte_mempool *pool; - struct netmap_if *nmif; - struct rte_eth_conf eth_conf; - struct rte_eth_txconf tx_conf; - struct rte_eth_rxconf rx_conf; - int32_t socket_id; - uint16_t nr_tx_rings; - uint16_t nr_rx_rings; - uint32_t nr_tx_slots; - uint32_t nr_rx_slots; - uint16_t tx_burst; - uint16_t rx_burst; - uint32_t fd; -}; - -struct fd_port { - uint32_t port; -}; - -#ifndef POLLRDNORM -#define POLLRDNORM 0x0040 -#endif - -#ifndef POLLWRNORM -#define POLLWRNORM 0x0100 -#endif - -#define FD_PORT_FREE UINT32_MAX -#define FD_PORT_RSRV (FD_PORT_FREE - 1) - -struct netmap_state { - struct rte_netmap_conf conf; - uintptr_t buf_start; - void *mem; - uint32_t mem_sz; - uint32_t netif_memsz; -}; - - -#define COMPAT_NETMAP_MAX_NOFILE (2 * RTE_MAX_ETHPORTS) -#define COMPAT_NETMAP_MAX_BURST 64 -#define COMPAT_NETMAP_MAX_PKT_PER_SYNC (2 * COMPAT_NETMAP_MAX_BURST) - -static struct netmap_port ports[RTE_MAX_ETHPORTS]; -static struct netmap_state netmap; - -static struct fd_port fd_port[COMPAT_NETMAP_MAX_NOFILE]; -static const int next_fd_start = RLIMIT_NOFILE + 1; -static rte_spinlock_t netmap_lock; - -#define IDX_TO_FD(x) ((x) + next_fd_start) -#define FD_TO_IDX(x) ((x) - next_fd_start) -#define FD_VALID(x) ((x) >= next_fd_start && \ - (x) < (typeof (x))(RTE_DIM(fd_port) + next_fd_start)) - -#define PORT_NUM_RINGS (2 * netmap.conf.max_rings) -#define PORT_NUM_SLOTS (PORT_NUM_RINGS * netmap.conf.max_slots) - -#define BUF_IDX(port, ring, slot) \ - (((port) * PORT_NUM_RINGS + (ring)) * netmap.conf.max_slots + \ - (slot)) - -#define NETMAP_IF_RING_OFS(rid, rings, slots) ({\ - struct netmap_if *_if; \ - struct netmap_ring *_rg; \ - sizeof(*_if) + \ - (rings) * sizeof(_if->ring_ofs[0]) + \ - (rid) * sizeof(*_rg) + \ - (slots) * sizeof(_rg->slot[0]); \ - }) - -static void netmap_unregif(uint32_t idx, uint32_t port); - - -static int32_t -ifname_to_portid(const char *ifname, uint16_t *port) -{ - char *endptr; - uint64_t portid; - - errno = 0; - portid = strtoul(ifname, &endptr, 10); - if (endptr == ifname || *endptr != '\0' || - portid >= RTE_DIM(ports) || errno != 0) - return -EINVAL; - - *port = portid; - return 0; -} - -/** - * Given a dpdk mbuf, fill in the Netmap slot in ring r and its associated - * buffer with the data held by the mbuf. - * Note that mbuf chains are not supported. - */ -static void -mbuf_to_slot(struct rte_mbuf *mbuf, struct netmap_ring *r, uint32_t index) -{ - char *data; - uint16_t length; - - data = rte_pktmbuf_mtod(mbuf, char *); - length = rte_pktmbuf_data_len(mbuf); - - if (length > r->nr_buf_size) - length = 0; - - r->slot[index].len = length; - rte_memcpy(NETMAP_BUF(r, r->slot[index].buf_idx), data, length); -} - -/** - * Given a Netmap ring and a slot index for that ring, construct a dpdk mbuf - * from the data held in the buffer associated with the slot. - * Allocation/deallocation of the dpdk mbuf are the responsibility of the - * caller. - * Note that mbuf chains are not supported. - */ -static void -slot_to_mbuf(struct netmap_ring *r, uint32_t index, struct rte_mbuf *mbuf) -{ - char *data; - uint16_t length; - - rte_pktmbuf_reset(mbuf); - length = r->slot[index].len; - data = rte_pktmbuf_append(mbuf, length); - - if (data != NULL) - rte_memcpy(data, NETMAP_BUF(r, r->slot[index].buf_idx), length); -} - -static int32_t -fd_reserve(void) -{ - uint32_t i; - - for (i = 0; i != RTE_DIM(fd_port) && fd_port[i].port != FD_PORT_FREE; - i++) - ; - - if (i == RTE_DIM(fd_port)) - return -ENOMEM; - - fd_port[i].port = FD_PORT_RSRV; - return IDX_TO_FD(i); -} - -static int32_t -fd_release(int32_t fd) -{ - uint32_t idx, port; - - idx = FD_TO_IDX(fd); - - if (!FD_VALID(fd) || (port = fd_port[idx].port) == FD_PORT_FREE) - return -EINVAL; - - /* if we still have a valid port attached, release the port */ - if (port < RTE_DIM(ports) && ports[port].fd == idx) { - netmap_unregif(idx, port); - } - - fd_port[idx].port = FD_PORT_FREE; - return 0; -} - -static int -check_nmreq(struct nmreq *req, uint16_t *port) -{ - int32_t rc; - uint16_t portid; - - if (req == NULL) - return -EINVAL; - - if (req->nr_version != NETMAP_API) { - req->nr_version = NETMAP_API; - return -EINVAL; - } - - if ((rc = ifname_to_portid(req->nr_name, &portid)) != 0) { - RTE_LOG(ERR, USER1, "Invalid interface name:\"%s\" " - "in NIOCGINFO call\n", req->nr_name); - return rc; - } - - if (ports[portid].pool == NULL) { - RTE_LOG(ERR, USER1, "Misconfigured portid %u\n", portid); - return -EINVAL; - } - - *port = portid; - return 0; -} - -/** - * Simulate a Netmap NIOCGINFO ioctl: given a struct nmreq holding an interface - * name (a port number in our case), fill the struct nmreq in with advisory - * information about the interface: number of rings and their size, total memory - * required in the map, ... - * Those are preconfigured using rte_eth_{,tx,rx}conf and - * rte_netmap_port_conf structures - * and calls to rte_netmap_init_port() in the Netmap application. - */ -static int -ioctl_niocginfo(__rte_unused int fd, void * param) -{ - uint16_t portid; - struct nmreq *req; - int32_t rc; - - req = (struct nmreq *)param; - if ((rc = check_nmreq(req, &portid)) != 0) - return rc; - - req->nr_tx_rings = (uint16_t)(ports[portid].nr_tx_rings - 1); - req->nr_rx_rings = (uint16_t)(ports[portid].nr_rx_rings - 1); - req->nr_tx_slots = ports[portid].nr_tx_slots; - req->nr_rx_slots = ports[portid].nr_rx_slots; - - /* in current implementation we have all NETIFs shared aone region. */ - req->nr_memsize = netmap.mem_sz; - req->nr_offset = 0; - - return 0; -} - -static void -netmap_ring_setup(struct netmap_ring *ring, uint16_t port, uint32_t ringid, - uint32_t num_slots) -{ - uint32_t j; - - ring->buf_ofs = netmap.buf_start - (uintptr_t)ring; - ring->num_slots = num_slots; - ring->cur = 0; - ring->reserved = 0; - ring->nr_buf_size = netmap.conf.max_bufsz; - ring->flags = 0; - ring->ts.tv_sec = 0; - ring->ts.tv_usec = 0; - - for (j = 0; j < ring->num_slots; j++) { - ring->slot[j].buf_idx = BUF_IDX(port, ringid, j); - ring->slot[j].len = 0; - ring->flags = 0; - } -} - -static int -netmap_regif(struct nmreq *req, uint32_t idx, uint16_t port) -{ - struct netmap_if *nmif; - struct netmap_ring *ring; - uint32_t i, slots, start_ring; - int32_t rc; - - if (ports[port].fd < RTE_DIM(fd_port)) { - RTE_LOG(ERR, USER1, "port %u already in use by fd: %u\n", - port, IDX_TO_FD(ports[port].fd)); - return -EBUSY; - } - if (fd_port[idx].port != FD_PORT_RSRV) { - RTE_LOG(ERR, USER1, "fd: %u is misconfigured\n", - IDX_TO_FD(idx)); - return -EBUSY; - } - - nmif = ports[port].nmif; - - /* setup netmap_if fields. */ - memset(nmif, 0, netmap.netif_memsz); - - /* only ALL rings supported right now. */ - if (req->nr_ringid != 0) - return -EINVAL; - - strlcpy(nmif->ni_name, req->nr_name, sizeof(nmif->ni_name)); - nmif->ni_version = req->nr_version; - - /* Netmap uses ni_(r|t)x_rings + 1 */ - nmif->ni_rx_rings = ports[port].nr_rx_rings - 1; - nmif->ni_tx_rings = ports[port].nr_tx_rings - 1; - - /* - * Setup TX rings and slots. - * Refer to the comments in netmap.h for details - */ - - slots = 0; - for (i = 0; i < nmif->ni_tx_rings + 1; i++) { - - nmif->ring_ofs[i] = NETMAP_IF_RING_OFS(i, - PORT_NUM_RINGS, slots); - - ring = NETMAP_TXRING(nmif, i); - netmap_ring_setup(ring, port, i, ports[port].nr_tx_slots); - ring->avail = ring->num_slots; - - slots += ports[port].nr_tx_slots; - } - - /* - * Setup RX rings and slots. - * Refer to the comments in netmap.h for details - */ - - start_ring = i; - - for (; i < nmif->ni_rx_rings + 1 + start_ring; i++) { - - nmif->ring_ofs[i] = NETMAP_IF_RING_OFS(i, - PORT_NUM_RINGS, slots); - - ring = NETMAP_RXRING(nmif, (i - start_ring)); - netmap_ring_setup(ring, port, i, ports[port].nr_rx_slots); - ring->avail = 0; - - slots += ports[port].nr_rx_slots; - } - - if ((rc = rte_eth_dev_start(port)) < 0) { - RTE_LOG(ERR, USER1, - "Couldn't start ethernet device %s (error %d)\n", - req->nr_name, rc); - return rc; - } - - /* setup fdi <--> port relationtip. */ - ports[port].fd = idx; - fd_port[idx].port = port; - - req->nr_memsize = netmap.mem_sz; - req->nr_offset = (uintptr_t)nmif - (uintptr_t)netmap.mem; - - return 0; -} - -/** - * Simulate a Netmap NIOCREGIF ioctl: - */ -static int -ioctl_niocregif(int32_t fd, void * param) -{ - uint16_t portid; - int32_t rc; - uint32_t idx; - struct nmreq *req; - - req = (struct nmreq *)param; - if ((rc = check_nmreq(req, &portid)) != 0) - return rc; - - idx = FD_TO_IDX(fd); - - rte_spinlock_lock(&netmap_lock); - rc = netmap_regif(req, idx, portid); - rte_spinlock_unlock(&netmap_lock); - - return rc; -} - -static void -netmap_unregif(uint32_t idx, uint32_t port) -{ - fd_port[idx].port = FD_PORT_RSRV; - ports[port].fd = UINT32_MAX; - rte_eth_dev_stop(port); -} - -/** - * Simulate a Netmap NIOCUNREGIF ioctl: put an interface running in Netmap - * mode back in "normal" mode. In our case, we just stop the port associated - * with this file descriptor. - */ -static int -ioctl_niocunregif(int fd) -{ - uint32_t idx, port; - int32_t rc; - - idx = FD_TO_IDX(fd); - - rte_spinlock_lock(&netmap_lock); - - port = fd_port[idx].port; - if (port < RTE_DIM(ports) && ports[port].fd == idx) { - netmap_unregif(idx, port); - rc = 0; - } else { - RTE_LOG(ERR, USER1, - "%s: %d is not associated with valid port\n", - __func__, fd); - rc = -EINVAL; - } - - rte_spinlock_unlock(&netmap_lock); - return rc; -} - -/** - * A call to rx_sync_ring will try to fill a Netmap RX ring with as many - * packets as it can hold coming from its dpdk port. - */ -static inline int -rx_sync_ring(struct netmap_ring *ring, uint16_t port, uint16_t ring_number, - uint16_t max_burst) -{ - int32_t i, n_rx; - uint16_t burst_size; - uint32_t cur_slot, n_free_slots; - struct rte_mbuf *rx_mbufs[COMPAT_NETMAP_MAX_BURST]; - - n_free_slots = ring->num_slots - (ring->avail + ring->reserved); - n_free_slots = RTE_MIN(n_free_slots, max_burst); - cur_slot = (ring->cur + ring->avail) & (ring->num_slots - 1); - - while (n_free_slots) { - burst_size = (uint16_t)RTE_MIN(n_free_slots, RTE_DIM(rx_mbufs)); - - /* receive up to burst_size packets from the NIC's queue */ - n_rx = rte_eth_rx_burst(port, ring_number, rx_mbufs, - burst_size); - - if (n_rx == 0) - return 0; - if (unlikely(n_rx < 0)) - return -1; - - /* Put those n_rx packets in the Netmap structures */ - for (i = 0; i < n_rx ; i++) { - mbuf_to_slot(rx_mbufs[i], ring, cur_slot); - rte_pktmbuf_free(rx_mbufs[i]); - cur_slot = NETMAP_RING_NEXT(ring, cur_slot); - } - - /* Update the Netmap ring structure to reflect the change */ - ring->avail += n_rx; - n_free_slots -= n_rx; - } - - return 0; -} - -static inline int -rx_sync_if(uint32_t port) -{ - uint16_t burst; - uint32_t i, rc; - struct netmap_if *nifp; - struct netmap_ring *r; - - nifp = ports[port].nmif; - burst = ports[port].rx_burst; - rc = 0; - - for (i = 0; i < nifp->ni_rx_rings + 1; i++) { - r = NETMAP_RXRING(nifp, i); - rx_sync_ring(r, port, (uint16_t)i, burst); - rc += r->avail; - } - - return rc; -} - -/** - * Simulate a Netmap NIOCRXSYNC ioctl: - */ -static int -ioctl_niocrxsync(int fd) -{ - uint32_t idx, port; - - idx = FD_TO_IDX(fd); - if ((port = fd_port[idx].port) < RTE_DIM(ports) && - ports[port].fd == idx) { - return rx_sync_if(fd_port[idx].port); - } else { - return -EINVAL; - } -} - -/** - * A call to tx_sync_ring will try to empty a Netmap TX ring by converting its - * buffers into rte_mbufs and sending them out on the rings's dpdk port. - */ -static int -tx_sync_ring(struct netmap_ring *ring, uint16_t port, uint16_t ring_number, - struct rte_mempool *pool, uint16_t max_burst) -{ - uint32_t i, n_tx; - uint16_t burst_size; - uint32_t cur_slot, n_used_slots; - struct rte_mbuf *tx_mbufs[COMPAT_NETMAP_MAX_BURST]; - - n_used_slots = ring->num_slots - ring->avail; - n_used_slots = RTE_MIN(n_used_slots, max_burst); - cur_slot = (ring->cur + ring->avail) & (ring->num_slots - 1); - - while (n_used_slots) { - burst_size = (uint16_t)RTE_MIN(n_used_slots, RTE_DIM(tx_mbufs)); - - for (i = 0; i < burst_size; i++) { - tx_mbufs[i] = rte_pktmbuf_alloc(pool); - if (tx_mbufs[i] == NULL) - goto err; - - slot_to_mbuf(ring, cur_slot, tx_mbufs[i]); - cur_slot = NETMAP_RING_NEXT(ring, cur_slot); - } - - n_tx = rte_eth_tx_burst(port, ring_number, tx_mbufs, - burst_size); - - /* Update the Netmap ring structure to reflect the change */ - ring->avail += n_tx; - n_used_slots -= n_tx; - - /* Return the mbufs that failed to transmit to their pool */ - if (unlikely(n_tx != burst_size)) { - for (i = n_tx; i < burst_size; i++) - rte_pktmbuf_free(tx_mbufs[i]); - break; - } - } - - return 0; - -err: - for (; i == 0; --i) - rte_pktmbuf_free(tx_mbufs[i]); - - RTE_LOG(ERR, USER1, - "Couldn't get mbuf from mempool is the mempool too small?\n"); - return -1; -} - -static int -tx_sync_if(uint32_t port) -{ - uint16_t burst; - uint32_t i, rc; - struct netmap_if *nifp; - struct netmap_ring *r; - struct rte_mempool *mp; - - nifp = ports[port].nmif; - mp = ports[port].pool; - burst = ports[port].tx_burst; - rc = 0; - - for (i = 0; i < nifp->ni_tx_rings + 1; i++) { - r = NETMAP_TXRING(nifp, i); - tx_sync_ring(r, port, (uint16_t)i, mp, burst); - rc += r->avail; - } - - return rc; -} - -/** - * Simulate a Netmap NIOCTXSYNC ioctl: - */ -static inline int -ioctl_nioctxsync(int fd) -{ - uint32_t idx, port; - - idx = FD_TO_IDX(fd); - if ((port = fd_port[idx].port) < RTE_DIM(ports) && - ports[port].fd == idx) { - return tx_sync_if(fd_port[idx].port); - } else { - return -EINVAL; - } -} - -/** - * Give the library a mempool of rte_mbufs with which it can do the - * rte_mbuf <--> netmap slot conversions. - */ -int -rte_netmap_init(const struct rte_netmap_conf *conf) -{ - size_t buf_ofs, nmif_sz, sz; - size_t port_rings, port_slots, port_bufs; - uint32_t i, port_num; - - port_num = RTE_MAX_ETHPORTS; - port_rings = 2 * conf->max_rings; - port_slots = port_rings * conf->max_slots; - port_bufs = port_slots; - - nmif_sz = NETMAP_IF_RING_OFS(port_rings, port_rings, port_slots); - sz = nmif_sz * port_num; - - buf_ofs = RTE_ALIGN_CEIL(sz, RTE_CACHE_LINE_SIZE); - sz = buf_ofs + port_bufs * conf->max_bufsz * port_num; - - if (sz > UINT32_MAX || - (netmap.mem = rte_zmalloc_socket(__func__, sz, - RTE_CACHE_LINE_SIZE, conf->socket_id)) == NULL) { - RTE_LOG(ERR, USER1, "%s: failed to allocate %zu bytes\n", - __func__, sz); - return -ENOMEM; - } - - netmap.mem_sz = sz; - netmap.netif_memsz = nmif_sz; - netmap.buf_start = (uintptr_t)netmap.mem + buf_ofs; - netmap.conf = *conf; - - rte_spinlock_init(&netmap_lock); - - /* Mark all ports as unused and set NETIF pointer. */ - for (i = 0; i != RTE_DIM(ports); i++) { - ports[i].fd = UINT32_MAX; - ports[i].nmif = (struct netmap_if *) - ((uintptr_t)netmap.mem + nmif_sz * i); - } - - /* Mark all fd_ports as unused. */ - for (i = 0; i != RTE_DIM(fd_port); i++) { - fd_port[i].port = FD_PORT_FREE; - } - - return 0; -} - - -int -rte_netmap_init_port(uint16_t portid, const struct rte_netmap_port_conf *conf) -{ - int32_t ret; - uint16_t i; - uint16_t rx_slots, tx_slots; - struct rte_eth_rxconf rxq_conf; - struct rte_eth_txconf txq_conf; - struct rte_eth_dev_info dev_info; - - if (conf == NULL || - portid >= RTE_DIM(ports) || - conf->nr_tx_rings > netmap.conf.max_rings || - conf->nr_rx_rings > netmap.conf.max_rings) { - RTE_LOG(ERR, USER1, "%s(%u): invalid parameters\n", - __func__, portid); - return -EINVAL; - } - - rx_slots = (uint16_t)rte_align32pow2(conf->nr_rx_slots); - tx_slots = (uint16_t)rte_align32pow2(conf->nr_tx_slots); - - if (tx_slots > netmap.conf.max_slots || - rx_slots > netmap.conf.max_slots) { - RTE_LOG(ERR, USER1, "%s(%u): invalid parameters\n", - __func__, portid); - return -EINVAL; - } - - rte_eth_dev_info_get(portid, &dev_info); - if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) - conf->eth_conf->txmode.offloads |= - DEV_TX_OFFLOAD_MBUF_FAST_FREE; - ret = rte_eth_dev_configure(portid, conf->nr_rx_rings, - conf->nr_tx_rings, conf->eth_conf); - - if (ret < 0) { - RTE_LOG(ERR, USER1, "Couldn't configure port %u\n", portid); - return ret; - } - - ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &rx_slots, &tx_slots); - - if (ret < 0) { - RTE_LOG(ERR, USER1, - "Couldn't ot adjust number of descriptors for port %u\n", - portid); - return ret; - } - - rxq_conf = dev_info.default_rxconf; - rxq_conf.offloads = conf->eth_conf->rxmode.offloads; - txq_conf = dev_info.default_txconf; - txq_conf.offloads = conf->eth_conf->txmode.offloads; - for (i = 0; i < conf->nr_tx_rings; i++) { - ret = rte_eth_tx_queue_setup(portid, i, tx_slots, - conf->socket_id, &txq_conf); - - if (ret < 0) { - RTE_LOG(ERR, USER1, - "fail to configure TX queue %u of port %u\n", - i, portid); - return ret; - } - - ret = rte_eth_rx_queue_setup(portid, i, rx_slots, - conf->socket_id, &rxq_conf, conf->pool); - - if (ret < 0) { - RTE_LOG(ERR, USER1, - "fail to configure RX queue %u of port %u\n", - i, portid); - return ret; - } - } - - /* copy config to the private storage. */ - ports[portid].eth_conf = conf->eth_conf[0]; - ports[portid].pool = conf->pool; - ports[portid].socket_id = conf->socket_id; - ports[portid].nr_tx_rings = conf->nr_tx_rings; - ports[portid].nr_rx_rings = conf->nr_rx_rings; - ports[portid].nr_tx_slots = tx_slots; - ports[portid].nr_rx_slots = rx_slots; - ports[portid].tx_burst = conf->tx_burst; - ports[portid].rx_burst = conf->rx_burst; - - return 0; -} - -int -rte_netmap_close(__rte_unused int fd) -{ - int32_t rc; - - rte_spinlock_lock(&netmap_lock); - rc = fd_release(fd); - rte_spinlock_unlock(&netmap_lock); - - if (rc < 0) { - errno =-rc; - rc = -1; - } - return rc; -} - -int rte_netmap_ioctl(int fd, uint32_t op, void *param) -{ - int ret; - - if (!FD_VALID(fd)) { - errno = EBADF; - return -1; - } - - switch (op) { - - case NIOCGINFO: - ret = ioctl_niocginfo(fd, param); - break; - - case NIOCREGIF: - ret = ioctl_niocregif(fd, param); - break; - - case NIOCUNREGIF: - ret = ioctl_niocunregif(fd); - break; - - case NIOCRXSYNC: - ret = ioctl_niocrxsync(fd); - break; - - case NIOCTXSYNC: - ret = ioctl_nioctxsync(fd); - break; - - default: - ret = -ENOTTY; - } - - if (ret < 0) { - errno = -ret; - ret = -1; - } else { - ret = 0; - } - - return ret; -} - -void * -rte_netmap_mmap(void *addr, size_t length, - int prot, int flags, int fd, off_t offset) -{ - static const int cprot = PROT_WRITE | PROT_READ; - - if (!FD_VALID(fd) || length + offset > netmap.mem_sz || - (prot & cprot) != cprot || - ((flags & MAP_FIXED) != 0 && addr != NULL)) { - - errno = EINVAL; - return MAP_FAILED; - } - - return (void *)((uintptr_t)netmap.mem + (uintptr_t)offset); -} - -/** - * Return a "fake" file descriptor with a value above RLIMIT_NOFILE so that - * any attempt to use that file descriptor with the usual API will fail. - */ -int -rte_netmap_open(__rte_unused const char *pathname, __rte_unused int flags) -{ - int fd; - - rte_spinlock_lock(&netmap_lock); - fd = fd_reserve(); - rte_spinlock_unlock(&netmap_lock); - - if (fd < 0) { - errno = -fd; - fd = -1; - } - return fd; -} - -/** - * Doesn't support timeout other than 0 or infinite (negative) timeout - */ -int -rte_netmap_poll(struct pollfd *fds, nfds_t nfds, int timeout) -{ - int32_t count_it, ret; - uint32_t i, idx, port; - uint32_t want_rx, want_tx; - - if (timeout > 0) - return -1; - - ret = 0; - do { - for (i = 0; i < nfds; i++) { - - count_it = 0; - - if (!FD_VALID(fds[i].fd) || fds[i].events == 0) { - fds[i].revents = 0; - continue; - } - - idx = FD_TO_IDX(fds[i].fd); - if ((port = fd_port[idx].port) >= RTE_DIM(ports) || - ports[port].fd != idx) { - - fds[i].revents |= POLLERR; - ret++; - continue; - } - - want_rx = fds[i].events & (POLLIN | POLLRDNORM); - want_tx = fds[i].events & (POLLOUT | POLLWRNORM); - - if (want_rx && rx_sync_if(port) > 0) { - fds[i].revents = (uint16_t) - (fds[i].revents | want_rx); - count_it = 1; - } - if (want_tx && tx_sync_if(port) > 0) { - fds[i].revents = (uint16_t) - (fds[i].revents | want_tx); - count_it = 1; - } - - ret += count_it; - } - } - while ((ret == 0 && timeout < 0) || timeout); - - return ret; -} diff --git a/examples/netmap_compat/lib/compat_netmap.h b/examples/netmap_compat/lib/compat_netmap.h deleted file mode 100644 index 12b618b68..000000000 --- a/examples/netmap_compat/lib/compat_netmap.h +++ /dev/null @@ -1,51 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation - */ - -#ifndef _RTE_COMPAT_NETMAP_H_ - -#include -#include -#include - -#include -#include - -#include "netmap.h" -#include "netmap_user.h" - -/** - * One can overwrite Netmap macros here as needed - */ - -struct rte_netmap_conf { - int32_t socket_id; - uint32_t max_rings; /* number of rings(queues) per netmap_if(port) */ - uint32_t max_slots; /* number of slots(descriptors) per netmap ring. */ - uint16_t max_bufsz; /* size of each netmap buffer. */ -}; - -struct rte_netmap_port_conf { - struct rte_eth_conf *eth_conf; - struct rte_mempool *pool; - int32_t socket_id; - uint16_t nr_tx_rings; - uint16_t nr_rx_rings; - uint32_t nr_tx_slots; - uint32_t nr_rx_slots; - uint16_t tx_burst; - uint16_t rx_burst; -}; - -int rte_netmap_init(const struct rte_netmap_conf *conf); -int rte_netmap_init_port(uint16_t portid, - const struct rte_netmap_port_conf *conf); - -int rte_netmap_close(int fd); -int rte_netmap_ioctl(int fd, uint32_t op, void *param); -int rte_netmap_open(const char *pathname, int flags); -int rte_netmap_poll(struct pollfd *fds, nfds_t nfds, int timeout); -void *rte_netmap_mmap(void *addr, size_t length, int prot, int flags, int fd, - off_t offset); - -#endif /* _RTE_COMPAT_NETMAP_H_ */ diff --git a/examples/netmap_compat/meson.build b/examples/netmap_compat/meson.build deleted file mode 100644 index c370d7476..000000000 --- a/examples/netmap_compat/meson.build +++ /dev/null @@ -1,10 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2018 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' - -# Example app currently unsupported by meson build -build = false diff --git a/examples/netmap_compat/netmap/netmap.h b/examples/netmap_compat/netmap/netmap.h deleted file mode 100644 index 677c8a9fb..000000000 --- a/examples/netmap_compat/netmap/netmap.h +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (C) 2011 Matteo Landi, Luigi Rizzo. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. 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. - * - * 3. Neither the name of the authors nor the names of their contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY MATTEO LANDI 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 MATTEO LANDI 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. - */ - -/* - * $FreeBSD: head/sys/net/netmap.h 231198 2012-02-08 11:43:29Z luigi $ - * $Id: netmap.h 10879 2012-04-12 22:48:59Z luigi $ - * - * Definitions of constants and the structures used by the netmap - * framework, for the part visible to both kernel and userspace. - * Detailed info on netmap is available with "man netmap" or at - * - * http://info.iet.unipi.it/~luigi/netmap/ - */ - -#ifndef _NET_NETMAP_H_ -#define _NET_NETMAP_H_ - -/* - * --- Netmap data structures --- - * - * The data structures used by netmap are shown below. Those in - * capital letters are in an mmapp()ed area shared with userspace, - * while others are private to the kernel. - * Shared structures do not contain pointers but only memory - * offsets, so that addressing is portable between kernel and userspace. - - - softc -+----------------+ -| standard fields| -| if_pspare[0] ----------+ -+----------------+ | - | -+----------------+<------+ -|(netmap_adapter)| -| | netmap_kring -| tx_rings *--------------------------------->+---------------+ -| | netmap_kring | ring *---------. -| rx_rings *--------->+---------------+ | nr_hwcur | | -+----------------+ | ring *--------. | nr_hwavail | V - | nr_hwcur | | | selinfo | | - | nr_hwavail | | +---------------+ . - | selinfo | | | ... | . - +---------------+ | |(ntx+1 entries)| - | .... | | | | - |(nrx+1 entries)| | +---------------+ - | | | - KERNEL +---------------+ | - | - ==================================================================== - | - USERSPACE | NETMAP_RING - +---->+-------------+ - / | cur | - NETMAP_IF (nifp, one per file desc.) / | avail | - +---------------+ / | buf_ofs | - | ni_tx_rings | / +=============+ - | ni_rx_rings | / | buf_idx | slot[0] - | | / | len, flags | - | | / +-------------+ - +===============+ / | buf_idx | slot[1] - | txring_ofs[0] | (rel.to nifp)--' | len, flags | - | txring_ofs[1] | +-------------+ - (num_rings+1 entries) (nr_num_slots entries) - | txring_ofs[n] | | buf_idx | slot[n-1] - +---------------+ | len, flags | - | rxring_ofs[0] | +-------------+ - | rxring_ofs[1] | - (num_rings+1 entries) - | txring_ofs[n] | - +---------------+ - - * The private descriptor ('softc' or 'adapter') of each interface - * is extended with a "struct netmap_adapter" containing netmap-related - * info (see description in dev/netmap/netmap_kernel.h. - * Among other things, tx_rings and rx_rings point to the arrays of - * "struct netmap_kring" which in turn reache the various - * "struct netmap_ring", shared with userspace. - - * The NETMAP_RING is the userspace-visible replica of the NIC ring. - * Each slot has the index of a buffer, its length and some flags. - * In user space, the buffer address is computed as - * (char *)ring + buf_ofs + index*NETMAP_BUF_SIZE - * In the kernel, buffers do not necessarily need to be contiguous, - * and the virtual and physical addresses are derived through - * a lookup table. - * To associate a different buffer to a slot, applications must - * write the new index in buf_idx, and set NS_BUF_CHANGED flag to - * make sure that the kernel updates the hardware ring as needed. - * - * Normally the driver is not requested to report the result of - * transmissions (this can dramatically speed up operation). - * However the user may request to report completion by setting - * NS_REPORT. - */ -struct netmap_slot { - uint32_t buf_idx; /* buffer index */ - uint16_t len; /* packet length, to be copied to/from the hw ring */ - uint16_t flags; /* buf changed, etc. */ -#define NS_BUF_CHANGED 0x0001 /* must resync the map, buffer changed */ -#define NS_REPORT 0x0002 /* ask the hardware to report results - * e.g. by generating an interrupt - */ -}; - -/* - * Netmap representation of a TX or RX ring (also known as "queue"). - * This is a queue implemented as a fixed-size circular array. - * At the software level, two fields are important: avail and cur. - * - * In TX rings: - * avail indicates the number of slots available for transmission. - * It is updated by the kernel after every netmap system call. - * It MUST BE decremented by the application when it appends a - * packet. - * cur indicates the slot to use for the next packet - * to send (i.e. the "tail" of the queue). - * It MUST BE incremented by the application before - * netmap system calls to reflect the number of newly - * sent packets. - * It is checked by the kernel on netmap system calls - * (normally unmodified by the kernel unless invalid). - * - * The kernel side of netmap uses two additional fields in its own - * private ring structure, netmap_kring: - * nr_hwcur is a copy of nr_cur on an NIOCTXSYNC. - * nr_hwavail is the number of slots known as available by the - * hardware. It is updated on an INTR (inc by the - * number of packets sent) and on a NIOCTXSYNC - * (decrease by nr_cur - nr_hwcur) - * A special case, nr_hwavail is -1 if the transmit - * side is idle (no pending transmits). - * - * In RX rings: - * avail is the number of packets available (possibly 0). - * It MUST BE decremented by the application when it consumes - * a packet, and it is updated to nr_hwavail on a NIOCRXSYNC - * cur indicates the first slot that contains a packet not - * processed yet (the "head" of the queue). - * It MUST BE incremented by the software when it consumes - * a packet. - * reserved indicates the number of buffers before 'cur' - * that the application has still in use. Normally 0, - * it MUST BE incremented by the application when it - * does not return the buffer immediately, and decremented - * when the buffer is finally freed. - * - * The kernel side of netmap uses two additional fields in the kring: - * nr_hwcur is a copy of nr_cur on an NIOCRXSYNC - * nr_hwavail is the number of packets available. It is updated - * on INTR (inc by the number of new packets arrived) - * and on NIOCRXSYNC (decreased by nr_cur - nr_hwcur). - * - * DATA OWNERSHIP/LOCKING: - * The netmap_ring is owned by the user program and it is only - * accessed or modified in the upper half of the kernel during - * a system call. - * - * The netmap_kring is only modified by the upper half of the kernel. - */ -struct netmap_ring { - /* - * nr_buf_base_ofs is meant to be used through macros. - * It contains the offset of the buffer region from this - * descriptor. - */ - ssize_t buf_ofs; - uint32_t num_slots; /* number of slots in the ring. */ - uint32_t avail; /* number of usable slots */ - uint32_t cur; /* 'current' r/w position */ - uint32_t reserved; /* not refilled before current */ - - uint16_t nr_buf_size; - uint16_t flags; -#define NR_TIMESTAMP 0x0002 /* set timestamp on *sync() */ - - struct timeval ts; /* time of last *sync() */ - - /* the slots follow. This struct has variable size */ - struct netmap_slot slot[0]; /* array of slots. */ -}; - - -/* - * Netmap representation of an interface and its queue(s). - * There is one netmap_if for each file descriptor on which we want - * to select/poll. We assume that on each interface has the same number - * of receive and transmit queues. - * select/poll operates on one or all pairs depending on the value of - * nmr_queueid passed on the ioctl. - */ -struct netmap_if { - char ni_name[IFNAMSIZ]; /* name of the interface. */ - u_int ni_version; /* API version, currently unused */ - u_int ni_rx_rings; /* number of rx rings */ - u_int ni_tx_rings; /* if zero, same as ni_rx_rings */ - /* - * The following array contains the offset of each netmap ring - * from this structure. The first ni_tx_queues+1 entries refer - * to the tx rings, the next ni_rx_queues+1 refer to the rx rings - * (the last entry in each block refers to the host stack rings). - * The area is filled up by the kernel on NIOCREG, - * and then only read by userspace code. - */ - ssize_t ring_ofs[0]; -}; - -#ifndef NIOCREGIF -/* - * ioctl names and related fields - * - * NIOCGINFO takes a struct ifreq, the interface name is the input, - * the outputs are number of queues and number of descriptor - * for each queue (useful to set number of threads etc.). - * - * NIOCREGIF takes an interface name within a struct ifreq, - * and activates netmap mode on the interface (if possible). - * - * NIOCUNREGIF unregisters the interface associated to the fd. - * - * NIOCTXSYNC, NIOCRXSYNC synchronize tx or rx queues, - * whose identity is set in NIOCREGIF through nr_ringid - */ - -/* - * struct nmreq overlays a struct ifreq - */ -struct nmreq { - char nr_name[IFNAMSIZ]; - uint32_t nr_version; /* API version */ -#define NETMAP_API 3 /* current version */ - uint32_t nr_offset; /* nifp offset in the shared region */ - uint32_t nr_memsize; /* size of the shared region */ - uint32_t nr_tx_slots; /* slots in tx rings */ - uint32_t nr_rx_slots; /* slots in rx rings */ - uint16_t nr_tx_rings; /* number of tx rings */ - uint16_t nr_rx_rings; /* number of rx rings */ - uint16_t nr_ringid; /* ring(s) we care about */ -#define NETMAP_HW_RING 0x4000 /* low bits indicate one hw ring */ -#define NETMAP_SW_RING 0x2000 /* process the sw ring */ -#define NETMAP_NO_TX_POLL 0x1000 /* no automatic txsync on poll */ -#define NETMAP_RING_MASK 0xfff /* the ring number */ - uint16_t spare1; - uint32_t spare2[4]; -}; - -/* - * FreeBSD uses the size value embedded in the _IOWR to determine - * how much to copy in/out. So we need it to match the actual - * data structure we pass. We put some spares in the structure - * to ease compatibility with other versions - */ -#define NIOCGINFO _IOWR('i', 145, struct nmreq) /* return IF info */ -#define NIOCREGIF _IOWR('i', 146, struct nmreq) /* interface register */ -#define NIOCUNREGIF _IO('i', 147) /* interface unregister */ -#define NIOCTXSYNC _IO('i', 148) /* sync tx queues */ -#define NIOCRXSYNC _IO('i', 149) /* sync rx queues */ -#endif /* !NIOCREGIF */ - -#endif /* _NET_NETMAP_H_ */ diff --git a/examples/netmap_compat/netmap/netmap_user.h b/examples/netmap_compat/netmap/netmap_user.h deleted file mode 100644 index f369592e3..000000000 --- a/examples/netmap_compat/netmap/netmap_user.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2011 Matteo Landi, Luigi Rizzo. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. 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. - * - * 3. Neither the name of the authors nor the names of their contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY MATTEO LANDI 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 MATTEO LANDI 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. - */ - -/* - * $FreeBSD: head/sys/net/netmap_user.h 231198 2012-02-08 11:43:29Z luigi $ - * $Id: netmap_user.h 10879 2012-04-12 22:48:59Z luigi $ - * - * This header contains the macros used to manipulate netmap structures - * and packets in userspace. See netmap(4) for more information. - * - * The address of the struct netmap_if, say nifp, is computed from the - * value returned from ioctl(.., NIOCREG, ...) and the mmap region: - * ioctl(fd, NIOCREG, &req); - * mem = mmap(0, ... ); - * nifp = NETMAP_IF(mem, req.nr_nifp); - * (so simple, we could just do it manually) - * - * From there: - * struct netmap_ring *NETMAP_TXRING(nifp, index) - * struct netmap_ring *NETMAP_RXRING(nifp, index) - * we can access ring->nr_cur, ring->nr_avail, ring->nr_flags - * - * ring->slot[i] gives us the i-th slot (we can access - * directly plen, flags, bufindex) - * - * char *buf = NETMAP_BUF(ring, index) returns a pointer to - * the i-th buffer - * - * Since rings are circular, we have macros to compute the next index - * i = NETMAP_RING_NEXT(ring, i); - */ - -#ifndef _NET_NETMAP_USER_H_ -#define _NET_NETMAP_USER_H_ - -#define NETMAP_IF(b, o) (struct netmap_if *)((char *)(b) + (o)) - -#define NETMAP_TXRING(nifp, index) \ - ((struct netmap_ring *)((char *)(nifp) + \ - (nifp)->ring_ofs[index] ) ) - -#define NETMAP_RXRING(nifp, index) \ - ((struct netmap_ring *)((char *)(nifp) + \ - (nifp)->ring_ofs[index + (nifp)->ni_tx_rings + 1] ) ) - -#define NETMAP_BUF(ring, index) \ - ((char *)(ring) + (ring)->buf_ofs + ((index)*(ring)->nr_buf_size)) - -#define NETMAP_BUF_IDX(ring, buf) \ - ( ((char *)(buf) - ((char *)(ring) + (ring)->buf_ofs) ) / \ - (ring)->nr_buf_size ) - -#define NETMAP_RING_NEXT(r, i) \ - ((i)+1 == (r)->num_slots ? 0 : (i) + 1 ) - -#define NETMAP_RING_FIRST_RESERVED(r) \ - ( (r)->cur < (r)->reserved ? \ - (r)->cur + (r)->num_slots - (r)->reserved : \ - (r)->cur - (r)->reserved ) - -/* - * Return 1 if the given tx ring is empty. - */ -#define NETMAP_TX_RING_EMPTY(r) ((r)->avail >= (r)->num_slots - 1) - -#endif /* _NET_NETMAP_USER_H_ */ From patchwork Thu Oct 3 13:19:17 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bruce Richardson X-Patchwork-Id: 60496 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 038771C133; Thu, 3 Oct 2019 15:20:01 +0200 (CEST) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by dpdk.org (Postfix) with ESMTP id D8D801C12A; Thu, 3 Oct 2019 15:19:57 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 03 Oct 2019 06:19:57 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.67,252,1566889200"; d="scan'208";a="185910580" Received: from silpixa00399126.ir.intel.com (HELO silpixa00399126.ger.corp.intel.com) ([10.237.223.2]) by orsmga008.jf.intel.com with ESMTP; 03 Oct 2019 06:19:54 -0700 From: Bruce Richardson To: dev@dpdk.org Cc: techboard@dpdk.org, Ciara Power Date: Thu, 3 Oct 2019 14:19:17 +0100 Message-Id: <20191003131918.30970-6-bruce.richardson@intel.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191003131918.30970-1-bruce.richardson@intel.com> References: <20191003131918.30970-1-bruce.richardson@intel.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH 5/6] examples/load_balancer: 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: Ciara Power This example can be removed because DPDK now has a range of libraries, especially rte_eventdev, that did not exist previously for load balancing, making this less relevant. Also, modern NIC cards have greater ability to do load balancing, e.g. using RSS, over a wider range of fields than earlier cards did. Signed-off-by: Ciara Power --- MAINTAINERS | 3 - doc/guides/sample_app_ug/index.rst | 1 - doc/guides/sample_app_ug/intro.rst | 2 +- doc/guides/sample_app_ug/load_balancer.rst | 201 ---- examples/Makefile | 1 - examples/load_balancer/Makefile | 62 -- examples/load_balancer/config.c | 1030 -------------------- examples/load_balancer/init.c | 520 ---------- examples/load_balancer/main.c | 76 -- examples/load_balancer/main.h | 351 ------- examples/load_balancer/meson.build | 12 - examples/load_balancer/runtime.c | 642 ------------ examples/meson.build | 1 - 13 files changed, 1 insertion(+), 2901 deletions(-) delete mode 100644 doc/guides/sample_app_ug/load_balancer.rst delete mode 100644 examples/load_balancer/Makefile delete mode 100644 examples/load_balancer/config.c delete mode 100644 examples/load_balancer/init.c delete mode 100644 examples/load_balancer/main.c delete mode 100644 examples/load_balancer/main.h delete mode 100644 examples/load_balancer/meson.build delete mode 100644 examples/load_balancer/runtime.c diff --git a/MAINTAINERS b/MAINTAINERS index 6b9fa4dc2..3db771bd7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1461,9 +1461,6 @@ F: doc/guides/sample_app_ug/l3_forward.rst F: examples/link_status_interrupt/ F: doc/guides/sample_app_ug/link_status_intr.rst -F: examples/load_balancer/ -F: doc/guides/sample_app_ug/load_balancer.rst - L-threads - EXPERIMENTAL M: John McNamara F: examples/performance-thread/ diff --git a/doc/guides/sample_app_ug/index.rst b/doc/guides/sample_app_ug/index.rst index 5f4924df6..191eebb56 100644 --- a/doc/guides/sample_app_ug/index.rst +++ b/doc/guides/sample_app_ug/index.rst @@ -30,7 +30,6 @@ Sample Applications User Guides l3_forward_power_man l3_forward_access_ctrl link_status_intr - load_balancer server_node_efd service_cores multi_process diff --git a/doc/guides/sample_app_ug/intro.rst b/doc/guides/sample_app_ug/intro.rst index 39af887da..981e50f94 100644 --- a/doc/guides/sample_app_ug/intro.rst +++ b/doc/guides/sample_app_ug/intro.rst @@ -61,7 +61,7 @@ applications that are available in the examples directory of DPDK: +---------------------------------------+--------------------------------------+ | Link Status Interrupt | VMDQ Forwarding | +---------------------------------------+--------------------------------------+ - | Load Balancer | VMDQ and DCB Forwarding | + | | VMDQ and DCB Forwarding | +---------------------------------------+--------------------------------------+ | Multi-process | VM Power Management | +---------------------------------------+--------------------------------------+ diff --git a/doc/guides/sample_app_ug/load_balancer.rst b/doc/guides/sample_app_ug/load_balancer.rst deleted file mode 100644 index 8f2abdfb8..000000000 --- a/doc/guides/sample_app_ug/load_balancer.rst +++ /dev/null @@ -1,201 +0,0 @@ -.. SPDX-License-Identifier: BSD-3-Clause - Copyright(c) 2010-2014 Intel Corporation. - -Load Balancer Sample Application -================================ - -The Load Balancer sample application demonstrates the concept of isolating the packet I/O task -from the application-specific workload. -Depending on the performance target, -a number of logical cores (lcores) are dedicated to handle the interaction with the NIC ports (I/O lcores), -while the rest of the lcores are dedicated to performing the application processing (worker lcores). -The worker lcores are totally oblivious to the intricacies of the packet I/O activity and -use the NIC-agnostic interface provided by software rings to exchange packets with the I/O cores. - -Overview --------- - -The architecture of the Load Balance application is presented in the following figure. - -.. _figure_load_bal_app_arch: - -.. figure:: img/load_bal_app_arch.* - - Load Balancer Application Architecture - - -For the sake of simplicity, the diagram illustrates a specific case of two I/O RX and two I/O TX lcores off loading the packet I/O -overhead incurred by four NIC ports from four worker cores, with each I/O lcore handling RX/TX for two NIC ports. - -I/O RX Logical Cores -~~~~~~~~~~~~~~~~~~~~ - -Each I/O RX lcore performs packet RX from its assigned NIC RX rings and then distributes the received packets to the worker threads. -The application allows each I/O RX lcore to communicate with any of the worker threads, -therefore each (I/O RX lcore, worker lcore) pair is connected through a dedicated single producer - single consumer software ring. - -The worker lcore to handle the current packet is determined by reading a predefined 1-byte field from the input packet: - -worker_id = packet[load_balancing_field] % n_workers - -Since all the packets that are part of the same traffic flow are expected to have the same value for the load balancing field, -this scheme also ensures that all the packets that are part of the same traffic flow are directed to the same worker lcore (flow affinity) -in the same order they enter the system (packet ordering). - -I/O TX Logical Cores -~~~~~~~~~~~~~~~~~~~~ - -Each I/O lcore owns the packet TX for a predefined set of NIC ports. To enable each worker thread to send packets to any NIC TX port, -the application creates a software ring for each (worker lcore, NIC TX port) pair, -with each I/O TX core handling those software rings that are associated with NIC ports that it handles. - -Worker Logical Cores -~~~~~~~~~~~~~~~~~~~~ - -Each worker lcore reads packets from its set of input software rings and -routes them to the NIC ports for transmission by dispatching them to output software rings. -The routing logic is LPM based, with all the worker threads sharing the same LPM rules. - -Compiling the Application -------------------------- - -To compile the sample application see :doc:`compiling`. - -The application is located in the ``load_balancer`` sub-directory. - -Running the Application ------------------------ - -To successfully run the application, -the command line used to start the application has to be in sync with the traffic flows configured on the traffic generator side. - -For examples of application command lines and traffic generator flows, please refer to the DPDK Test Report. -For more details on how to set up and run the sample applications provided with DPDK package, -please refer to the *DPDK Getting Started Guide*. - -Explanation ------------ - -Application Configuration -~~~~~~~~~~~~~~~~~~~~~~~~~ - -The application run-time configuration is done through the application command line parameters. -Any parameter that is not specified as mandatory is optional, -with the default value hard-coded in the main.h header file from the application folder. - -The list of application command line parameters is listed below: - -#. --rx "(PORT, QUEUE, LCORE), ...": The list of NIC RX ports and queues handled by the I/O RX lcores. - This parameter also implicitly defines the list of I/O RX lcores. This is a mandatory parameter. - -#. --tx "(PORT, LCORE), ... ": The list of NIC TX ports handled by the I/O TX lcores. - This parameter also implicitly defines the list of I/O TX lcores. - This is a mandatory parameter. - -#. --w "LCORE, ...": The list of the worker lcores. This is a mandatory parameter. - -#. --lpm "IP / PREFIX => PORT; ...": The list of LPM rules used by the worker lcores for packet forwarding. - This is a mandatory parameter. - -#. --rsz "A, B, C, D": Ring sizes: - - #. A = The size (in number of buffer descriptors) of each of the NIC RX rings read by the I/O RX lcores. - - #. B = The size (in number of elements) of each of the software rings used by the I/O RX lcores to send packets to worker lcores. - - #. C = The size (in number of elements) of each of the software rings used by the worker lcores to send packets to I/O TX lcores. - - #. D = The size (in number of buffer descriptors) of each of the NIC TX rings written by I/O TX lcores. - -#. --bsz "(A, B), (C, D), (E, F)": Burst sizes: - - #. A = The I/O RX lcore read burst size from NIC RX. - - #. B = The I/O RX lcore write burst size to the output software rings. - - #. C = The worker lcore read burst size from the input software rings. - - #. D = The worker lcore write burst size to the output software rings. - - #. E = The I/O TX lcore read burst size from the input software rings. - - #. F = The I/O TX lcore write burst size to the NIC TX. - -#. --pos-lb POS: The position of the 1-byte field within the input packet used by the I/O RX lcores - to identify the worker lcore for the current packet. - This field needs to be within the first 64 bytes of the input packet. - -The infrastructure of software rings connecting I/O lcores and worker lcores is built by the application -as a result of the application configuration provided by the user through the application command line parameters. - -A specific lcore performing the I/O RX role for a specific set of NIC ports can also perform the I/O TX role -for the same or a different set of NIC ports. -A specific lcore cannot perform both the I/O role (either RX or TX) and the worker role during the same session. - -Example: - -.. code-block:: console - - ./load_balancer -l 3-7 -n 4 -- --rx "(0,0,3),(1,0,3)" --tx "(0,3),(1,3)" --w "4,5,6,7" --lpm "1.0.0.0/24=>0; 1.0.1.0/24=>1;" --pos-lb 29 - -There is a single I/O lcore (lcore 3) that handles RX and TX for two NIC ports (ports 0 and 1) that -handles packets to/from four worker lcores (lcores 4, 5, 6 and 7) that -are assigned worker IDs 0 to 3 (worker ID for lcore 4 is 0, for lcore 5 is 1, for lcore 6 is 2 and for lcore 7 is 3). - -Assuming that all the input packets are IPv4 packets with no VLAN label and the source IP address of the current packet is A.B.C.D, -the worker lcore for the current packet is determined by byte D (which is byte 29). -There are two LPM rules that are used by each worker lcore to route packets to the output NIC ports. - -The following table illustrates the packet flow through the system for several possible traffic flows: - -+------------+----------------+-----------------+------------------------------+--------------+ -| **Flow #** | **Source** | **Destination** | **Worker ID (Worker lcore)** | **Output** | -| | **IP Address** | **IP Address** | | **NIC Port** | -| | | | | | -+============+================+=================+==============================+==============+ -| 1 | 0.0.0.0 | 1.0.0.1 | 0 (4) | 0 | -| | | | | | -+------------+----------------+-----------------+------------------------------+--------------+ -| 2 | 0.0.0.1 | 1.0.1.2 | 1 (5) | 1 | -| | | | | | -+------------+----------------+-----------------+------------------------------+--------------+ -| 3 | 0.0.0.14 | 1.0.0.3 | 2 (6) | 0 | -| | | | | | -+------------+----------------+-----------------+------------------------------+--------------+ -| 4 | 0.0.0.15 | 1.0.1.4 | 3 (7) | 1 | -| | | | | | -+------------+----------------+-----------------+------------------------------+--------------+ - -NUMA Support -~~~~~~~~~~~~ - -The application has built-in performance enhancements for the NUMA case: - -#. One buffer pool per each CPU socket. - -#. One LPM table per each CPU socket. - -#. Memory for the NIC RX or TX rings is allocated on the same socket with the lcore handling the respective ring. - -In the case where multiple CPU sockets are used in the system, -it is recommended to enable at least one lcore to fulfill the I/O role for the NIC ports that -are directly attached to that CPU socket through the PCI Express* bus. -It is always recommended to handle the packet I/O with lcores from the same CPU socket as the NICs. - -Depending on whether the I/O RX lcore (same CPU socket as NIC RX), -the worker lcore and the I/O TX lcore (same CPU socket as NIC TX) handling a specific input packet, -are on the same or different CPU sockets, the following run-time scenarios are possible: - -#. AAA: The packet is received, processed and transmitted without going across CPU sockets. - -#. AAB: The packet is received and processed on socket A, - but as it has to be transmitted on a NIC port connected to socket B, - the packet is sent to socket B through software rings. - -#. ABB: The packet is received on socket A, but as it has to be processed by a worker lcore on socket B, - the packet is sent to socket B through software rings. - The packet is transmitted by a NIC port connected to the same CPU socket as the worker lcore that processed it. - -#. ABC: The packet is received on socket A, it is processed by an lcore on socket B, - then it has to be transmitted out by a NIC connected to socket C. - The performance price for crossing the CPU socket boundary is paid twice for this packet. diff --git a/examples/Makefile b/examples/Makefile index 6bba09ce9..62d0865c5 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -48,7 +48,6 @@ ifeq ($(CONFIG_RTE_LIBRTE_LPM)$(CONFIG_RTE_LIBRTE_HASH),yy) DIRS-$(CONFIG_RTE_LIBRTE_POWER) += l3fwd-power endif DIRS-y += link_status_interrupt -DIRS-$(CONFIG_RTE_LIBRTE_LPM) += load_balancer DIRS-y += multi_process DIRS-y += ntb DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += packet_ordering diff --git a/examples/load_balancer/Makefile b/examples/load_balancer/Makefile deleted file mode 100644 index caae8a107..000000000 --- a/examples/load_balancer/Makefile +++ /dev/null @@ -1,62 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2010-2014 Intel Corporation - -# binary name -APP = load_balancer - -# all source are stored in SRCS-y -SRCS-y := main.c config.c init.c runtime.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 # Build using legacy build system - -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 -g -CFLAGS += $(WERROR_FLAGS) - -# workaround for a gcc bug with noreturn attribute -# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603 -ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) -CFLAGS_main.o += -Wno-return-type -endif - -include $(RTE_SDK)/mk/rte.extapp.mk -endif diff --git a/examples/load_balancer/config.c b/examples/load_balancer/config.c deleted file mode 100644 index 972c85c5b..000000000 --- a/examples/load_balancer/config.c +++ /dev/null @@ -1,1030 +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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "main.h" - -struct app_params app; - -static const char usage[] = -" \n" -" load_balancer -- \n" -" \n" -"Application manadatory parameters: \n" -" --rx \"(PORT, QUEUE, LCORE), ...\" : List of NIC RX ports and queues \n" -" handled by the I/O RX lcores \n" -" --tx \"(PORT, LCORE), ...\" : List of NIC TX ports handled by the I/O TX \n" -" lcores \n" -" --w \"LCORE, ...\" : List of the worker lcores \n" -" --lpm \"IP / PREFIX => PORT; ...\" : List of LPM rules used by the worker \n" -" lcores for packet forwarding \n" -" \n" -"Application optional parameters: \n" -" --rsz \"A, B, C, D\" : Ring sizes \n" -" A = Size (in number of buffer descriptors) of each of the NIC RX \n" -" rings read by the I/O RX lcores (default value is %u) \n" -" B = Size (in number of elements) of each of the SW rings used by the\n" -" I/O RX lcores to send packets to worker lcores (default value is\n" -" %u) \n" -" C = Size (in number of elements) of each of the SW rings used by the\n" -" worker lcores to send packets to I/O TX lcores (default value is\n" -" %u) \n" -" D = Size (in number of buffer descriptors) of each of the NIC TX \n" -" rings written by I/O TX lcores (default value is %u) \n" -" --bsz \"(A, B), (C, D), (E, F)\" : Burst sizes \n" -" A = I/O RX lcore read burst size from NIC RX (default value is %u) \n" -" B = I/O RX lcore write burst size to output SW rings (default value \n" -" is %u) \n" -" C = Worker lcore read burst size from input SW rings (default value \n" -" is %u) \n" -" D = Worker lcore write burst size to output SW rings (default value \n" -" is %u) \n" -" E = I/O TX lcore read burst size from input SW rings (default value \n" -" is %u) \n" -" F = I/O TX lcore write burst size to NIC TX (default value is %u) \n" -" --pos-lb POS : Position of the 1-byte field within the input packet used by\n" -" the I/O RX lcores to identify the worker lcore for the current \n" -" packet (default value is %u) \n"; - -void -app_print_usage(void) -{ - printf(usage, - APP_DEFAULT_NIC_RX_RING_SIZE, - APP_DEFAULT_RING_RX_SIZE, - APP_DEFAULT_RING_TX_SIZE, - APP_DEFAULT_NIC_TX_RING_SIZE, - APP_DEFAULT_BURST_SIZE_IO_RX_READ, - APP_DEFAULT_BURST_SIZE_IO_RX_WRITE, - APP_DEFAULT_BURST_SIZE_WORKER_READ, - APP_DEFAULT_BURST_SIZE_WORKER_WRITE, - APP_DEFAULT_BURST_SIZE_IO_TX_READ, - APP_DEFAULT_BURST_SIZE_IO_TX_WRITE, - APP_DEFAULT_IO_RX_LB_POS - ); -} - -#ifndef APP_ARG_RX_MAX_CHARS -#define APP_ARG_RX_MAX_CHARS 4096 -#endif - -#ifndef APP_ARG_RX_MAX_TUPLES -#define APP_ARG_RX_MAX_TUPLES 128 -#endif - -static int -str_to_unsigned_array( - const char *s, size_t sbuflen, - char separator, - unsigned num_vals, - unsigned *vals) -{ - char str[sbuflen+1]; - char *splits[num_vals]; - char *endptr = NULL; - int i, num_splits = 0; - - /* copy s so we don't modify original string */ - strlcpy(str, s, sizeof(str)); - num_splits = rte_strsplit(str, sizeof(str), splits, num_vals, separator); - - errno = 0; - for (i = 0; i < num_splits; i++) { - vals[i] = strtoul(splits[i], &endptr, 0); - if (errno != 0 || *endptr != '\0') - return -1; - } - - return num_splits; -} - -static int -str_to_unsigned_vals( - const char *s, - size_t sbuflen, - char separator, - unsigned num_vals, ...) -{ - unsigned i, vals[num_vals]; - va_list ap; - - num_vals = str_to_unsigned_array(s, sbuflen, separator, num_vals, vals); - - va_start(ap, num_vals); - for (i = 0; i < num_vals; i++) { - unsigned *u = va_arg(ap, unsigned *); - *u = vals[i]; - } - va_end(ap); - return num_vals; -} - -static int -parse_arg_rx(const char *arg) -{ - const char *p0 = arg, *p = arg; - uint32_t n_tuples; - - if (strnlen(arg, APP_ARG_RX_MAX_CHARS + 1) == APP_ARG_RX_MAX_CHARS + 1) { - return -1; - } - - n_tuples = 0; - while ((p = strchr(p0,'(')) != NULL) { - struct app_lcore_params *lp; - uint32_t port, queue, lcore, i; - - p0 = strchr(p++, ')'); - if ((p0 == NULL) || - (str_to_unsigned_vals(p, p0 - p, ',', 3, &port, &queue, &lcore) != 3)) { - return -2; - } - - /* Enable port and queue for later initialization */ - if ((port >= APP_MAX_NIC_PORTS) || (queue >= APP_MAX_RX_QUEUES_PER_NIC_PORT)) { - return -3; - } - if (app.nic_rx_queue_mask[port][queue] != 0) { - return -4; - } - app.nic_rx_queue_mask[port][queue] = 1; - - /* Check and assign (port, queue) to I/O lcore */ - if (rte_lcore_is_enabled(lcore) == 0) { - return -5; - } - - if (lcore >= APP_MAX_LCORES) { - return -6; - } - lp = &app.lcore_params[lcore]; - if (lp->type == e_APP_LCORE_WORKER) { - return -7; - } - lp->type = e_APP_LCORE_IO; - const size_t n_queues = RTE_MIN(lp->io.rx.n_nic_queues, - RTE_DIM(lp->io.rx.nic_queues)); - for (i = 0; i < n_queues; i ++) { - if ((lp->io.rx.nic_queues[i].port == port) && - (lp->io.rx.nic_queues[i].queue == queue)) { - return -8; - } - } - if (lp->io.rx.n_nic_queues >= APP_MAX_NIC_RX_QUEUES_PER_IO_LCORE) { - return -9; - } - lp->io.rx.nic_queues[lp->io.rx.n_nic_queues].port = port; - lp->io.rx.nic_queues[lp->io.rx.n_nic_queues].queue = (uint8_t) queue; - lp->io.rx.n_nic_queues ++; - - n_tuples ++; - if (n_tuples > APP_ARG_RX_MAX_TUPLES) { - return -10; - } - } - - if (n_tuples == 0) { - return -11; - } - - return 0; -} - -#ifndef APP_ARG_TX_MAX_CHARS -#define APP_ARG_TX_MAX_CHARS 4096 -#endif - -#ifndef APP_ARG_TX_MAX_TUPLES -#define APP_ARG_TX_MAX_TUPLES 128 -#endif - -static int -parse_arg_tx(const char *arg) -{ - const char *p0 = arg, *p = arg; - uint32_t n_tuples; - - if (strnlen(arg, APP_ARG_TX_MAX_CHARS + 1) == APP_ARG_TX_MAX_CHARS + 1) { - return -1; - } - - n_tuples = 0; - while ((p = strchr(p0,'(')) != NULL) { - struct app_lcore_params *lp; - uint32_t port, lcore, i; - - p0 = strchr(p++, ')'); - if ((p0 == NULL) || - (str_to_unsigned_vals(p, p0 - p, ',', 2, &port, &lcore) != 2)) { - return -2; - } - - /* Enable port and queue for later initialization */ - if (port >= APP_MAX_NIC_PORTS) { - return -3; - } - if (app.nic_tx_port_mask[port] != 0) { - return -4; - } - app.nic_tx_port_mask[port] = 1; - - /* Check and assign (port, queue) to I/O lcore */ - if (rte_lcore_is_enabled(lcore) == 0) { - return -5; - } - - if (lcore >= APP_MAX_LCORES) { - return -6; - } - lp = &app.lcore_params[lcore]; - if (lp->type == e_APP_LCORE_WORKER) { - return -7; - } - lp->type = e_APP_LCORE_IO; - const size_t n_ports = RTE_MIN(lp->io.tx.n_nic_ports, - RTE_DIM(lp->io.tx.nic_ports)); - for (i = 0; i < n_ports; i ++) { - if (lp->io.tx.nic_ports[i] == port) { - return -8; - } - } - if (lp->io.tx.n_nic_ports >= APP_MAX_NIC_TX_PORTS_PER_IO_LCORE) { - return -9; - } - lp->io.tx.nic_ports[lp->io.tx.n_nic_ports] = port; - lp->io.tx.n_nic_ports ++; - - n_tuples ++; - if (n_tuples > APP_ARG_TX_MAX_TUPLES) { - return -10; - } - } - - if (n_tuples == 0) { - return -11; - } - - return 0; -} - -#ifndef APP_ARG_W_MAX_CHARS -#define APP_ARG_W_MAX_CHARS 4096 -#endif - -#ifndef APP_ARG_W_MAX_TUPLES -#define APP_ARG_W_MAX_TUPLES APP_MAX_WORKER_LCORES -#endif - -static int -parse_arg_w(const char *arg) -{ - const char *p = arg; - uint32_t n_tuples; - - if (strnlen(arg, APP_ARG_W_MAX_CHARS + 1) == APP_ARG_W_MAX_CHARS + 1) { - return -1; - } - - n_tuples = 0; - while (*p != 0) { - struct app_lcore_params *lp; - uint32_t lcore; - - errno = 0; - lcore = strtoul(p, NULL, 0); - if (errno != 0) { - return -2; - } - - /* Check and enable worker lcore */ - if (rte_lcore_is_enabled(lcore) == 0) { - return -3; - } - - if (lcore >= APP_MAX_LCORES) { - return -4; - } - lp = &app.lcore_params[lcore]; - if (lp->type == e_APP_LCORE_IO) { - return -5; - } - lp->type = e_APP_LCORE_WORKER; - - n_tuples ++; - if (n_tuples > APP_ARG_W_MAX_TUPLES) { - return -6; - } - - p = strchr(p, ','); - if (p == NULL) { - break; - } - p ++; - } - - if (n_tuples == 0) { - return -7; - } - - if ((n_tuples & (n_tuples - 1)) != 0) { - return -8; - } - - return 0; -} - -#ifndef APP_ARG_LPM_MAX_CHARS -#define APP_ARG_LPM_MAX_CHARS 4096 -#endif - -static int -parse_arg_lpm(const char *arg) -{ - const char *p = arg, *p0; - - if (strnlen(arg, APP_ARG_LPM_MAX_CHARS + 1) == APP_ARG_TX_MAX_CHARS + 1) { - return -1; - } - - while (*p != 0) { - uint32_t ip_a, ip_b, ip_c, ip_d, ip, depth, if_out; - char *endptr; - - p0 = strchr(p, '/'); - if ((p0 == NULL) || - (str_to_unsigned_vals(p, p0 - p, '.', 4, &ip_a, &ip_b, &ip_c, &ip_d) != 4)) { - return -2; - } - - p = p0 + 1; - errno = 0; - depth = strtoul(p, &endptr, 0); - if (errno != 0 || *endptr != '=') { - return -3; - } - p = strchr(p, '>'); - if (p == NULL) { - return -4; - } - if_out = strtoul(++p, &endptr, 0); - if (errno != 0 || (*endptr != '\0' && *endptr != ';')) { - return -5; - } - - if ((ip_a >= 256) || (ip_b >= 256) || (ip_c >= 256) || (ip_d >= 256) || - (depth == 0) || (depth >= 32) || - (if_out >= APP_MAX_NIC_PORTS)) { - return -6; - } - ip = (ip_a << 24) | (ip_b << 16) | (ip_c << 8) | ip_d; - - if (app.n_lpm_rules >= APP_MAX_LPM_RULES) { - return -7; - } - app.lpm_rules[app.n_lpm_rules].ip = ip; - app.lpm_rules[app.n_lpm_rules].depth = (uint8_t) depth; - app.lpm_rules[app.n_lpm_rules].if_out = (uint8_t) if_out; - app.n_lpm_rules ++; - - p = strchr(p, ';'); - if (p == NULL) { - return -8; - } - p ++; - } - - if (app.n_lpm_rules == 0) { - return -9; - } - - return 0; -} - -static int -app_check_lpm_table(void) -{ - uint32_t rule; - - /* For each rule, check that the output I/F is enabled */ - for (rule = 0; rule < app.n_lpm_rules; rule ++) - { - uint32_t port = app.lpm_rules[rule].if_out; - - if (app.nic_tx_port_mask[port] == 0) { - return -1; - } - } - - return 0; -} - -static int -app_check_every_rx_port_is_tx_enabled(void) -{ - uint16_t port; - - for (port = 0; port < APP_MAX_NIC_PORTS; port ++) { - if ((app_get_nic_rx_queues_per_port(port) > 0) && (app.nic_tx_port_mask[port] == 0)) { - return -1; - } - } - - return 0; -} - -#ifndef APP_ARG_RSZ_CHARS -#define APP_ARG_RSZ_CHARS 63 -#endif - -static int -parse_arg_rsz(const char *arg) -{ - if (strnlen(arg, APP_ARG_RSZ_CHARS + 1) == APP_ARG_RSZ_CHARS + 1) { - return -1; - } - - if (str_to_unsigned_vals(arg, APP_ARG_RSZ_CHARS, ',', 4, - &app.nic_rx_ring_size, - &app.ring_rx_size, - &app.ring_tx_size, - &app.nic_tx_ring_size) != 4) - return -2; - - - if ((app.nic_rx_ring_size == 0) || - (app.nic_tx_ring_size == 0) || - (app.ring_rx_size == 0) || - (app.ring_tx_size == 0)) { - return -3; - } - - return 0; -} - -#ifndef APP_ARG_BSZ_CHARS -#define APP_ARG_BSZ_CHARS 63 -#endif - -static int -parse_arg_bsz(const char *arg) -{ - const char *p = arg, *p0; - if (strnlen(arg, APP_ARG_BSZ_CHARS + 1) == APP_ARG_BSZ_CHARS + 1) { - return -1; - } - - p0 = strchr(p++, ')'); - if ((p0 == NULL) || - (str_to_unsigned_vals(p, p0 - p, ',', 2, &app.burst_size_io_rx_read, &app.burst_size_io_rx_write) != 2)) { - return -2; - } - - p = strchr(p0, '('); - if (p == NULL) { - return -3; - } - - p0 = strchr(p++, ')'); - if ((p0 == NULL) || - (str_to_unsigned_vals(p, p0 - p, ',', 2, &app.burst_size_worker_read, &app.burst_size_worker_write) != 2)) { - return -4; - } - - p = strchr(p0, '('); - if (p == NULL) { - return -5; - } - - p0 = strchr(p++, ')'); - if ((p0 == NULL) || - (str_to_unsigned_vals(p, p0 - p, ',', 2, &app.burst_size_io_tx_read, &app.burst_size_io_tx_write) != 2)) { - return -6; - } - - if ((app.burst_size_io_rx_read == 0) || - (app.burst_size_io_rx_write == 0) || - (app.burst_size_worker_read == 0) || - (app.burst_size_worker_write == 0) || - (app.burst_size_io_tx_read == 0) || - (app.burst_size_io_tx_write == 0)) { - return -7; - } - - if ((app.burst_size_io_rx_read > APP_MBUF_ARRAY_SIZE) || - (app.burst_size_io_rx_write > APP_MBUF_ARRAY_SIZE) || - (app.burst_size_worker_read > APP_MBUF_ARRAY_SIZE) || - (app.burst_size_worker_write > APP_MBUF_ARRAY_SIZE) || - ((2 * app.burst_size_io_tx_read) > APP_MBUF_ARRAY_SIZE) || - (app.burst_size_io_tx_write > APP_MBUF_ARRAY_SIZE)) { - return -8; - } - - return 0; -} - -#ifndef APP_ARG_NUMERICAL_SIZE_CHARS -#define APP_ARG_NUMERICAL_SIZE_CHARS 15 -#endif - -static int -parse_arg_pos_lb(const char *arg) -{ - uint32_t x; - char *endpt; - - if (strnlen(arg, APP_ARG_NUMERICAL_SIZE_CHARS + 1) == APP_ARG_NUMERICAL_SIZE_CHARS + 1) { - return -1; - } - - errno = 0; - x = strtoul(arg, &endpt, 10); - if (errno != 0 || endpt == arg || *endpt != '\0'){ - return -2; - } - - if (x >= 64) { - return -3; - } - - app.pos_lb = (uint8_t) x; - - return 0; -} - -/* Parse the argument given in the command line of the application */ -int -app_parse_args(int argc, char **argv) -{ - int opt, ret; - char **argvopt; - int option_index; - char *prgname = argv[0]; - static struct option lgopts[] = { - {"rx", 1, 0, 0}, - {"tx", 1, 0, 0}, - {"w", 1, 0, 0}, - {"lpm", 1, 0, 0}, - {"rsz", 1, 0, 0}, - {"bsz", 1, 0, 0}, - {"pos-lb", 1, 0, 0}, - {NULL, 0, 0, 0} - }; - uint32_t arg_w = 0; - uint32_t arg_rx = 0; - uint32_t arg_tx = 0; - uint32_t arg_lpm = 0; - uint32_t arg_rsz = 0; - uint32_t arg_bsz = 0; - uint32_t arg_pos_lb = 0; - - argvopt = argv; - - while ((opt = getopt_long(argc, argvopt, "", - lgopts, &option_index)) != EOF) { - - switch (opt) { - /* long options */ - case 0: - if (!strcmp(lgopts[option_index].name, "rx")) { - arg_rx = 1; - ret = parse_arg_rx(optarg); - if (ret) { - printf("Incorrect value for --rx argument (%d)\n", ret); - return -1; - } - } - if (!strcmp(lgopts[option_index].name, "tx")) { - arg_tx = 1; - ret = parse_arg_tx(optarg); - if (ret) { - printf("Incorrect value for --tx argument (%d)\n", ret); - return -1; - } - } - if (!strcmp(lgopts[option_index].name, "w")) { - arg_w = 1; - ret = parse_arg_w(optarg); - if (ret) { - printf("Incorrect value for --w argument (%d)\n", ret); - return -1; - } - } - if (!strcmp(lgopts[option_index].name, "lpm")) { - arg_lpm = 1; - ret = parse_arg_lpm(optarg); - if (ret) { - printf("Incorrect value for --lpm argument (%d)\n", ret); - return -1; - } - } - if (!strcmp(lgopts[option_index].name, "rsz")) { - arg_rsz = 1; - ret = parse_arg_rsz(optarg); - if (ret) { - printf("Incorrect value for --rsz argument (%d)\n", ret); - return -1; - } - } - if (!strcmp(lgopts[option_index].name, "bsz")) { - arg_bsz = 1; - ret = parse_arg_bsz(optarg); - if (ret) { - printf("Incorrect value for --bsz argument (%d)\n", ret); - return -1; - } - } - if (!strcmp(lgopts[option_index].name, "pos-lb")) { - arg_pos_lb = 1; - ret = parse_arg_pos_lb(optarg); - if (ret) { - printf("Incorrect value for --pos-lb argument (%d)\n", ret); - return -1; - } - } - break; - - default: - return -1; - } - } - - /* Check that all mandatory arguments are provided */ - if ((arg_rx == 0) || (arg_tx == 0) || (arg_w == 0) || (arg_lpm == 0)){ - printf("Not all mandatory arguments are present\n"); - return -1; - } - - /* Assign default values for the optional arguments not provided */ - if (arg_rsz == 0) { - app.nic_rx_ring_size = APP_DEFAULT_NIC_RX_RING_SIZE; - app.nic_tx_ring_size = APP_DEFAULT_NIC_TX_RING_SIZE; - app.ring_rx_size = APP_DEFAULT_RING_RX_SIZE; - app.ring_tx_size = APP_DEFAULT_RING_TX_SIZE; - } - - if (arg_bsz == 0) { - app.burst_size_io_rx_read = APP_DEFAULT_BURST_SIZE_IO_RX_READ; - app.burst_size_io_rx_write = APP_DEFAULT_BURST_SIZE_IO_RX_WRITE; - app.burst_size_io_tx_read = APP_DEFAULT_BURST_SIZE_IO_TX_READ; - app.burst_size_io_tx_write = APP_DEFAULT_BURST_SIZE_IO_TX_WRITE; - app.burst_size_worker_read = APP_DEFAULT_BURST_SIZE_WORKER_READ; - app.burst_size_worker_write = APP_DEFAULT_BURST_SIZE_WORKER_WRITE; - } - - if (arg_pos_lb == 0) { - app.pos_lb = APP_DEFAULT_IO_RX_LB_POS; - } - - /* Check cross-consistency of arguments */ - if ((ret = app_check_lpm_table()) < 0) { - printf("At least one LPM rule is inconsistent (%d)\n", ret); - return -1; - } - if (app_check_every_rx_port_is_tx_enabled() < 0) { - printf("On LPM lookup miss, packet is sent back on the input port.\n"); - printf("At least one RX port is not enabled for TX.\n"); - return -2; - } - - if (optind >= 0) - argv[optind - 1] = prgname; - - ret = optind - 1; - optind = 1; /* reset getopt lib */ - return ret; -} - -int -app_get_nic_rx_queues_per_port(uint16_t port) -{ - uint32_t i, count; - - if (port >= APP_MAX_NIC_PORTS) { - return -1; - } - - count = 0; - for (i = 0; i < APP_MAX_RX_QUEUES_PER_NIC_PORT; i ++) { - if (app.nic_rx_queue_mask[port][i] == 1) { - count ++; - } - } - - return count; -} - -int -app_get_lcore_for_nic_rx(uint16_t port, uint8_t queue, uint32_t *lcore_out) -{ - uint32_t lcore; - - for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { - struct app_lcore_params_io *lp = &app.lcore_params[lcore].io; - uint32_t i; - - if (app.lcore_params[lcore].type != e_APP_LCORE_IO) { - continue; - } - - const size_t n_queues = RTE_MIN(lp->rx.n_nic_queues, - RTE_DIM(lp->rx.nic_queues)); - for (i = 0; i < n_queues; i ++) { - if ((lp->rx.nic_queues[i].port == port) && - (lp->rx.nic_queues[i].queue == queue)) { - *lcore_out = lcore; - return 0; - } - } - } - - return -1; -} - -int -app_get_lcore_for_nic_tx(uint16_t port, uint32_t *lcore_out) -{ - uint32_t lcore; - - for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { - struct app_lcore_params_io *lp = &app.lcore_params[lcore].io; - uint32_t i; - - if (app.lcore_params[lcore].type != e_APP_LCORE_IO) { - continue; - } - - const size_t n_ports = RTE_MIN(lp->tx.n_nic_ports, - RTE_DIM(lp->tx.nic_ports)); - for (i = 0; i < n_ports; i ++) { - if (lp->tx.nic_ports[i] == port) { - *lcore_out = lcore; - return 0; - } - } - } - - return -1; -} - -int -app_is_socket_used(uint32_t socket) -{ - uint32_t lcore; - - for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { - if (app.lcore_params[lcore].type == e_APP_LCORE_DISABLED) { - continue; - } - - if (socket == rte_lcore_to_socket_id(lcore)) { - return 1; - } - } - - return 0; -} - -uint32_t -app_get_lcores_io_rx(void) -{ - uint32_t lcore, count; - - count = 0; - for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { - struct app_lcore_params_io *lp_io = &app.lcore_params[lcore].io; - - if ((app.lcore_params[lcore].type != e_APP_LCORE_IO) || - (lp_io->rx.n_nic_queues == 0)) { - continue; - } - - count ++; - } - - return count; -} - -uint32_t -app_get_lcores_worker(void) -{ - uint32_t lcore, count; - - count = 0; - for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { - if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) { - continue; - } - - count ++; - } - - if (count > APP_MAX_WORKER_LCORES) { - rte_panic("Algorithmic error (too many worker lcores)\n"); - return 0; - } - - return count; -} - -void -app_print_params(void) -{ - unsigned port, queue, lcore, rule, i, j; - - /* Print NIC RX configuration */ - printf("NIC RX ports: "); - for (port = 0; port < APP_MAX_NIC_PORTS; port ++) { - uint32_t n_rx_queues = app_get_nic_rx_queues_per_port(port); - - if (n_rx_queues == 0) { - continue; - } - - printf("%u (", port); - for (queue = 0; queue < APP_MAX_RX_QUEUES_PER_NIC_PORT; queue ++) { - if (app.nic_rx_queue_mask[port][queue] == 1) { - printf("%u ", queue); - } - } - printf(") "); - } - printf(";\n"); - - /* Print I/O lcore RX params */ - for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { - struct app_lcore_params_io *lp = &app.lcore_params[lcore].io; - - if ((app.lcore_params[lcore].type != e_APP_LCORE_IO) || - (lp->rx.n_nic_queues == 0)) { - continue; - } - - printf("I/O lcore %u (socket %u): ", lcore, rte_lcore_to_socket_id(lcore)); - - printf("RX ports "); - for (i = 0; i < lp->rx.n_nic_queues; i ++) { - printf("(%u, %u) ", - (unsigned) lp->rx.nic_queues[i].port, - (unsigned) lp->rx.nic_queues[i].queue); - } - printf("; "); - - printf("Output rings "); - for (i = 0; i < lp->rx.n_rings; i ++) { - printf("%p ", lp->rx.rings[i]); - } - printf(";\n"); - } - - /* Print worker lcore RX params */ - for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { - struct app_lcore_params_worker *lp = &app.lcore_params[lcore].worker; - - if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) { - continue; - } - - printf("Worker lcore %u (socket %u) ID %u: ", - lcore, - rte_lcore_to_socket_id(lcore), - (unsigned)lp->worker_id); - - printf("Input rings "); - for (i = 0; i < lp->n_rings_in; i ++) { - printf("%p ", lp->rings_in[i]); - } - - printf(";\n"); - } - - printf("\n"); - - /* Print NIC TX configuration */ - printf("NIC TX ports: "); - for (port = 0; port < APP_MAX_NIC_PORTS; port ++) { - if (app.nic_tx_port_mask[port] == 1) { - printf("%u ", port); - } - } - printf(";\n"); - - /* Print I/O TX lcore params */ - for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { - struct app_lcore_params_io *lp = &app.lcore_params[lcore].io; - uint32_t n_workers = app_get_lcores_worker(); - - if ((app.lcore_params[lcore].type != e_APP_LCORE_IO) || - (lp->tx.n_nic_ports == 0)) { - continue; - } - - printf("I/O lcore %u (socket %u): ", lcore, rte_lcore_to_socket_id(lcore)); - - printf("Input rings per TX port "); - for (i = 0; i < lp->tx.n_nic_ports; i ++) { - port = lp->tx.nic_ports[i]; - - printf("%u (", port); - for (j = 0; j < n_workers; j ++) { - printf("%p ", lp->tx.rings[port][j]); - } - printf(") "); - - } - - printf(";\n"); - } - - /* Print worker lcore TX params */ - for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { - struct app_lcore_params_worker *lp = &app.lcore_params[lcore].worker; - - if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) { - continue; - } - - printf("Worker lcore %u (socket %u) ID %u: \n", - lcore, - rte_lcore_to_socket_id(lcore), - (unsigned)lp->worker_id); - - printf("Output rings per TX port "); - for (port = 0; port < APP_MAX_NIC_PORTS; port ++) { - if (lp->rings_out[port] != NULL) { - printf("%u (%p) ", port, lp->rings_out[port]); - } - } - - printf(";\n"); - } - - /* Print LPM rules */ - printf("LPM rules: \n"); - for (rule = 0; rule < app.n_lpm_rules; rule ++) { - uint32_t ip = app.lpm_rules[rule].ip; - uint8_t depth = app.lpm_rules[rule].depth; - uint8_t if_out = app.lpm_rules[rule].if_out; - - printf("\t%u: %u.%u.%u.%u/%u => %u;\n", - rule, - (unsigned) (ip & 0xFF000000) >> 24, - (unsigned) (ip & 0x00FF0000) >> 16, - (unsigned) (ip & 0x0000FF00) >> 8, - (unsigned) ip & 0x000000FF, - (unsigned) depth, - (unsigned) if_out - ); - } - - /* Rings */ - printf("Ring sizes: NIC RX = %u; Worker in = %u; Worker out = %u; NIC TX = %u;\n", - (unsigned) app.nic_rx_ring_size, - (unsigned) app.ring_rx_size, - (unsigned) app.ring_tx_size, - (unsigned) app.nic_tx_ring_size); - - /* Bursts */ - printf("Burst sizes: I/O RX (rd = %u, wr = %u); Worker (rd = %u, wr = %u); I/O TX (rd = %u, wr = %u)\n", - (unsigned) app.burst_size_io_rx_read, - (unsigned) app.burst_size_io_rx_write, - (unsigned) app.burst_size_worker_read, - (unsigned) app.burst_size_worker_write, - (unsigned) app.burst_size_io_tx_read, - (unsigned) app.burst_size_io_tx_write); -} diff --git a/examples/load_balancer/init.c b/examples/load_balancer/init.c deleted file mode 100644 index 3ab7d0211..000000000 --- a/examples/load_balancer/init.c +++ /dev/null @@ -1,520 +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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "main.h" - -static struct rte_eth_conf port_conf = { - .rxmode = { - .mq_mode = ETH_MQ_RX_RSS, - .split_hdr_size = 0, - .offloads = DEV_RX_OFFLOAD_CHECKSUM, - }, - .rx_adv_conf = { - .rss_conf = { - .rss_key = NULL, - .rss_hf = ETH_RSS_IP, - }, - }, - .txmode = { - .mq_mode = ETH_MQ_TX_NONE, - }, -}; - -static void -app_assign_worker_ids(void) -{ - uint32_t lcore, worker_id; - - /* Assign ID for each worker */ - worker_id = 0; - for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { - struct app_lcore_params_worker *lp_worker = &app.lcore_params[lcore].worker; - - if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) { - continue; - } - - lp_worker->worker_id = worker_id; - worker_id ++; - } -} - -static void -app_init_mbuf_pools(void) -{ - unsigned socket, lcore; - - /* Init the buffer pools */ - for (socket = 0; socket < APP_MAX_SOCKETS; socket ++) { - char name[32]; - if (app_is_socket_used(socket) == 0) { - continue; - } - - snprintf(name, sizeof(name), "mbuf_pool_%u", socket); - printf("Creating the mbuf pool for socket %u ...\n", socket); - app.pools[socket] = rte_pktmbuf_pool_create( - name, APP_DEFAULT_MEMPOOL_BUFFERS, - APP_DEFAULT_MEMPOOL_CACHE_SIZE, - 0, APP_DEFAULT_MBUF_DATA_SIZE, socket); - if (app.pools[socket] == NULL) { - rte_panic("Cannot create mbuf pool on socket %u\n", socket); - } - } - - for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { - if (app.lcore_params[lcore].type == e_APP_LCORE_DISABLED) { - continue; - } - - socket = rte_lcore_to_socket_id(lcore); - app.lcore_params[lcore].pool = app.pools[socket]; - } -} - -static void -app_init_lpm_tables(void) -{ - unsigned socket, lcore; - - /* Init the LPM tables */ - for (socket = 0; socket < APP_MAX_SOCKETS; socket ++) { - char name[32]; - uint32_t rule; - - if (app_is_socket_used(socket) == 0) { - continue; - } - - struct rte_lpm_config lpm_config; - - lpm_config.max_rules = APP_MAX_LPM_RULES; - lpm_config.number_tbl8s = 256; - lpm_config.flags = 0; - snprintf(name, sizeof(name), "lpm_table_%u", socket); - printf("Creating the LPM table for socket %u ...\n", socket); - app.lpm_tables[socket] = rte_lpm_create( - name, - socket, - &lpm_config); - if (app.lpm_tables[socket] == NULL) { - rte_panic("Unable to create LPM table on socket %u\n", socket); - } - - for (rule = 0; rule < app.n_lpm_rules; rule ++) { - int ret; - - ret = rte_lpm_add(app.lpm_tables[socket], - app.lpm_rules[rule].ip, - app.lpm_rules[rule].depth, - app.lpm_rules[rule].if_out); - - if (ret < 0) { - rte_panic("Unable to add entry %u (%x/%u => %u) to the LPM table on socket %u (%d)\n", - (unsigned) rule, - (unsigned) app.lpm_rules[rule].ip, - (unsigned) app.lpm_rules[rule].depth, - (unsigned) app.lpm_rules[rule].if_out, - socket, - ret); - } - } - - } - - for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { - if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) { - continue; - } - - socket = rte_lcore_to_socket_id(lcore); - app.lcore_params[lcore].worker.lpm_table = app.lpm_tables[socket]; - } -} - -static void -app_init_rings_rx(void) -{ - unsigned lcore; - - /* Initialize the rings for the RX side */ - for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { - struct app_lcore_params_io *lp_io = &app.lcore_params[lcore].io; - unsigned socket_io, lcore_worker; - - if ((app.lcore_params[lcore].type != e_APP_LCORE_IO) || - (lp_io->rx.n_nic_queues == 0)) { - continue; - } - - socket_io = rte_lcore_to_socket_id(lcore); - - for (lcore_worker = 0; lcore_worker < APP_MAX_LCORES; lcore_worker ++) { - char name[32]; - struct app_lcore_params_worker *lp_worker = &app.lcore_params[lcore_worker].worker; - struct rte_ring *ring = NULL; - - if (app.lcore_params[lcore_worker].type != e_APP_LCORE_WORKER) { - continue; - } - - printf("Creating ring to connect I/O lcore %u (socket %u) with worker lcore %u ...\n", - lcore, - socket_io, - lcore_worker); - snprintf(name, sizeof(name), "app_ring_rx_s%u_io%u_w%u", - socket_io, - lcore, - lcore_worker); - ring = rte_ring_create( - name, - app.ring_rx_size, - socket_io, - RING_F_SP_ENQ | RING_F_SC_DEQ); - if (ring == NULL) { - rte_panic("Cannot create ring to connect I/O core %u with worker core %u\n", - lcore, - lcore_worker); - } - - lp_io->rx.rings[lp_io->rx.n_rings] = ring; - lp_io->rx.n_rings ++; - - lp_worker->rings_in[lp_worker->n_rings_in] = ring; - lp_worker->n_rings_in ++; - } - } - - for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { - struct app_lcore_params_io *lp_io = &app.lcore_params[lcore].io; - - if ((app.lcore_params[lcore].type != e_APP_LCORE_IO) || - (lp_io->rx.n_nic_queues == 0)) { - continue; - } - - if (lp_io->rx.n_rings != app_get_lcores_worker()) { - rte_panic("Algorithmic error (I/O RX rings)\n"); - } - } - - for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { - struct app_lcore_params_worker *lp_worker = &app.lcore_params[lcore].worker; - - if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) { - continue; - } - - if (lp_worker->n_rings_in != app_get_lcores_io_rx()) { - rte_panic("Algorithmic error (worker input rings)\n"); - } - } -} - -static void -app_init_rings_tx(void) -{ - unsigned lcore; - - /* Initialize the rings for the TX side */ - for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { - struct app_lcore_params_worker *lp_worker = &app.lcore_params[lcore].worker; - unsigned port; - - if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) { - continue; - } - - for (port = 0; port < APP_MAX_NIC_PORTS; port ++) { - char name[32]; - struct app_lcore_params_io *lp_io = NULL; - struct rte_ring *ring; - uint32_t socket_io, lcore_io; - - if (app.nic_tx_port_mask[port] == 0) { - continue; - } - - if (app_get_lcore_for_nic_tx(port, &lcore_io) < 0) { - rte_panic("Algorithmic error (no I/O core to handle TX of port %u)\n", - port); - } - - lp_io = &app.lcore_params[lcore_io].io; - socket_io = rte_lcore_to_socket_id(lcore_io); - - printf("Creating ring to connect worker lcore %u with TX port %u (through I/O lcore %u) (socket %u) ...\n", - lcore, port, (unsigned)lcore_io, (unsigned)socket_io); - snprintf(name, sizeof(name), "app_ring_tx_s%u_w%u_p%u", socket_io, lcore, port); - ring = rte_ring_create( - name, - app.ring_tx_size, - socket_io, - RING_F_SP_ENQ | RING_F_SC_DEQ); - if (ring == NULL) { - rte_panic("Cannot create ring to connect worker core %u with TX port %u\n", - lcore, - port); - } - - lp_worker->rings_out[port] = ring; - lp_io->tx.rings[port][lp_worker->worker_id] = ring; - } - } - - for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) { - struct app_lcore_params_io *lp_io = &app.lcore_params[lcore].io; - unsigned i; - - if ((app.lcore_params[lcore].type != e_APP_LCORE_IO) || - (lp_io->tx.n_nic_ports == 0)) { - continue; - } - - for (i = 0; i < lp_io->tx.n_nic_ports; i ++){ - unsigned port, j; - - port = lp_io->tx.nic_ports[i]; - for (j = 0; j < app_get_lcores_worker(); j ++) { - if (lp_io->tx.rings[port][j] == NULL) { - rte_panic("Algorithmic error (I/O TX rings)\n"); - } - } - } - } -} - -/* Check the link status of all ports in up to 9s, and print them finally */ -static void -check_all_ports_link_status(uint16_t port_num, 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; - uint32_t n_rx_queues, n_tx_queues; - - printf("\nChecking link status"); - fflush(stdout); - for (count = 0; count <= MAX_CHECK_TIME; count++) { - all_ports_up = 1; - for (portid = 0; portid < port_num; portid++) { - if ((port_mask & (1 << portid)) == 0) - continue; - n_rx_queues = app_get_nic_rx_queues_per_port(portid); - n_tx_queues = app.nic_tx_port_mask[portid]; - if ((n_rx_queues == 0) && (n_tx_queues == 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 %uMbps - %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"); - } - } -} - -static void -app_init_nics(void) -{ - unsigned socket; - uint32_t lcore; - uint16_t port; - uint8_t queue; - int ret; - uint32_t n_rx_queues, n_tx_queues; - - /* Init NIC ports and queues, then start the ports */ - for (port = 0; port < APP_MAX_NIC_PORTS; port ++) { - struct rte_mempool *pool; - uint16_t nic_rx_ring_size; - uint16_t nic_tx_ring_size; - struct rte_eth_rxconf rxq_conf; - struct rte_eth_txconf txq_conf; - struct rte_eth_dev_info dev_info; - struct rte_eth_conf local_port_conf = port_conf; - - n_rx_queues = app_get_nic_rx_queues_per_port(port); - n_tx_queues = app.nic_tx_port_mask[port]; - - if ((n_rx_queues == 0) && (n_tx_queues == 0)) { - continue; - } - - /* Init port */ - printf("Initializing NIC port %u ...\n", port); - 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; - - local_port_conf.rx_adv_conf.rss_conf.rss_hf &= - dev_info.flow_type_rss_offloads; - if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != - port_conf.rx_adv_conf.rss_conf.rss_hf) { - printf("Port %u modified RSS hash function based on hardware support," - "requested:%#"PRIx64" configured:%#"PRIx64"\n", - port, - port_conf.rx_adv_conf.rss_conf.rss_hf, - local_port_conf.rx_adv_conf.rss_conf.rss_hf); - } - - ret = rte_eth_dev_configure( - port, - (uint8_t) n_rx_queues, - (uint8_t) n_tx_queues, - &local_port_conf); - if (ret < 0) { - rte_panic("Cannot init NIC port %u (%d)\n", port, ret); - } - rte_eth_promiscuous_enable(port); - - nic_rx_ring_size = app.nic_rx_ring_size; - nic_tx_ring_size = app.nic_tx_ring_size; - ret = rte_eth_dev_adjust_nb_rx_tx_desc( - port, &nic_rx_ring_size, &nic_tx_ring_size); - if (ret < 0) { - rte_panic("Cannot adjust number of descriptors for port %u (%d)\n", - port, ret); - } - app.nic_rx_ring_size = nic_rx_ring_size; - app.nic_tx_ring_size = nic_tx_ring_size; - - rxq_conf = dev_info.default_rxconf; - rxq_conf.offloads = local_port_conf.rxmode.offloads; - /* Init RX queues */ - for (queue = 0; queue < APP_MAX_RX_QUEUES_PER_NIC_PORT; queue ++) { - if (app.nic_rx_queue_mask[port][queue] == 0) { - continue; - } - - app_get_lcore_for_nic_rx(port, queue, &lcore); - socket = rte_lcore_to_socket_id(lcore); - pool = app.lcore_params[lcore].pool; - - printf("Initializing NIC port %u RX queue %u ...\n", - port, queue); - ret = rte_eth_rx_queue_setup( - port, - queue, - (uint16_t) app.nic_rx_ring_size, - socket, - &rxq_conf, - pool); - if (ret < 0) { - rte_panic("Cannot init RX queue %u for port %u (%d)\n", - queue, port, ret); - } - } - - txq_conf = dev_info.default_txconf; - txq_conf.offloads = local_port_conf.txmode.offloads; - /* Init TX queues */ - if (app.nic_tx_port_mask[port] == 1) { - app_get_lcore_for_nic_tx(port, &lcore); - socket = rte_lcore_to_socket_id(lcore); - printf("Initializing NIC port %u TX queue 0 ...\n", - port); - ret = rte_eth_tx_queue_setup( - port, - 0, - (uint16_t) app.nic_tx_ring_size, - socket, - &txq_conf); - if (ret < 0) { - rte_panic("Cannot init TX queue 0 for port %d (%d)\n", - port, - ret); - } - } - - /* Start port */ - ret = rte_eth_dev_start(port); - if (ret < 0) { - rte_panic("Cannot start port %d (%d)\n", port, ret); - } - } - - check_all_ports_link_status(APP_MAX_NIC_PORTS, (~0x0)); -} - -void -app_init(void) -{ - app_assign_worker_ids(); - app_init_mbuf_pools(); - app_init_lpm_tables(); - app_init_rings_rx(); - app_init_rings_tx(); - app_init_nics(); - - printf("Initialization completed.\n"); -} diff --git a/examples/load_balancer/main.c b/examples/load_balancer/main.c deleted file mode 100644 index d3dcb235d..000000000 --- a/examples/load_balancer/main.c +++ /dev/null @@ -1,76 +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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "main.h" - -int -main(int argc, char **argv) -{ - uint32_t lcore; - int ret; - - /* Init EAL */ - ret = rte_eal_init(argc, argv); - if (ret < 0) - return -1; - argc -= ret; - argv += ret; - - /* Parse application arguments (after the EAL ones) */ - ret = app_parse_args(argc, argv); - if (ret < 0) { - app_print_usage(); - return -1; - } - - /* Init */ - app_init(); - app_print_params(); - - /* Launch per-lcore init on every lcore */ - rte_eal_mp_remote_launch(app_lcore_main_loop, NULL, CALL_MASTER); - RTE_LCORE_FOREACH_SLAVE(lcore) { - if (rte_eal_wait_lcore(lcore) < 0) { - return -1; - } - } - - return 0; -} diff --git a/examples/load_balancer/main.h b/examples/load_balancer/main.h deleted file mode 100644 index 9fefb62ed..000000000 --- a/examples/load_balancer/main.h +++ /dev/null @@ -1,351 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation - */ - -#ifndef _MAIN_H_ -#define _MAIN_H_ - -/* Logical cores */ -#ifndef APP_MAX_SOCKETS -#define APP_MAX_SOCKETS 2 -#endif - -#ifndef APP_MAX_LCORES -#define APP_MAX_LCORES RTE_MAX_LCORE -#endif - -#ifndef APP_MAX_NIC_PORTS -#define APP_MAX_NIC_PORTS RTE_MAX_ETHPORTS -#endif - -#ifndef APP_MAX_RX_QUEUES_PER_NIC_PORT -#define APP_MAX_RX_QUEUES_PER_NIC_PORT 128 -#endif - -#ifndef APP_MAX_TX_QUEUES_PER_NIC_PORT -#define APP_MAX_TX_QUEUES_PER_NIC_PORT 128 -#endif - -#ifndef APP_MAX_IO_LCORES -#if (APP_MAX_LCORES > 16) -#define APP_MAX_IO_LCORES 16 -#else -#define APP_MAX_IO_LCORES APP_MAX_LCORES -#endif -#endif -#if (APP_MAX_IO_LCORES > APP_MAX_LCORES) -#error "APP_MAX_IO_LCORES is too big" -#endif - -#ifndef APP_MAX_NIC_RX_QUEUES_PER_IO_LCORE -#define APP_MAX_NIC_RX_QUEUES_PER_IO_LCORE 16 -#endif - -#ifndef APP_MAX_NIC_TX_PORTS_PER_IO_LCORE -#define APP_MAX_NIC_TX_PORTS_PER_IO_LCORE 16 -#endif -#if (APP_MAX_NIC_TX_PORTS_PER_IO_LCORE > APP_MAX_NIC_PORTS) -#error "APP_MAX_NIC_TX_PORTS_PER_IO_LCORE too big" -#endif - -#ifndef APP_MAX_WORKER_LCORES -#if (APP_MAX_LCORES > 16) -#define APP_MAX_WORKER_LCORES 16 -#else -#define APP_MAX_WORKER_LCORES APP_MAX_LCORES -#endif -#endif -#if (APP_MAX_WORKER_LCORES > APP_MAX_LCORES) -#error "APP_MAX_WORKER_LCORES is too big" -#endif - - -/* Mempools */ -#ifndef APP_DEFAULT_MBUF_DATA_SIZE -#define APP_DEFAULT_MBUF_DATA_SIZE RTE_MBUF_DEFAULT_BUF_SIZE -#endif - -#ifndef APP_DEFAULT_MEMPOOL_BUFFERS -#define APP_DEFAULT_MEMPOOL_BUFFERS 8192 * 4 -#endif - -#ifndef APP_DEFAULT_MEMPOOL_CACHE_SIZE -#define APP_DEFAULT_MEMPOOL_CACHE_SIZE 256 -#endif - -/* LPM Tables */ -#ifndef APP_MAX_LPM_RULES -#define APP_MAX_LPM_RULES 1024 -#endif - -/* NIC RX */ -#ifndef APP_DEFAULT_NIC_RX_RING_SIZE -#define APP_DEFAULT_NIC_RX_RING_SIZE 1024 -#endif - -/* - * 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. - */ -#ifndef APP_DEFAULT_NIC_RX_PTHRESH -#define APP_DEFAULT_NIC_RX_PTHRESH 8 -#endif - -#ifndef APP_DEFAULT_NIC_RX_HTHRESH -#define APP_DEFAULT_NIC_RX_HTHRESH 8 -#endif - -#ifndef APP_DEFAULT_NIC_RX_WTHRESH -#define APP_DEFAULT_NIC_RX_WTHRESH 4 -#endif - -#ifndef APP_DEFAULT_NIC_RX_FREE_THRESH -#define APP_DEFAULT_NIC_RX_FREE_THRESH 64 -#endif - -#ifndef APP_DEFAULT_NIC_RX_DROP_EN -#define APP_DEFAULT_NIC_RX_DROP_EN 0 -#endif - -/* NIC TX */ -#ifndef APP_DEFAULT_NIC_TX_RING_SIZE -#define APP_DEFAULT_NIC_TX_RING_SIZE 1024 -#endif - -/* - * These default values are optimized for use with the Intel(R) 82599 10 GbE - * Controller and the DPDK ixgbe PMD. Consider using other values for other - * network controllers and/or network drivers. - */ -#ifndef APP_DEFAULT_NIC_TX_PTHRESH -#define APP_DEFAULT_NIC_TX_PTHRESH 36 -#endif - -#ifndef APP_DEFAULT_NIC_TX_HTHRESH -#define APP_DEFAULT_NIC_TX_HTHRESH 0 -#endif - -#ifndef APP_DEFAULT_NIC_TX_WTHRESH -#define APP_DEFAULT_NIC_TX_WTHRESH 0 -#endif - -#ifndef APP_DEFAULT_NIC_TX_FREE_THRESH -#define APP_DEFAULT_NIC_TX_FREE_THRESH 0 -#endif - -#ifndef APP_DEFAULT_NIC_TX_RS_THRESH -#define APP_DEFAULT_NIC_TX_RS_THRESH 0 -#endif - -/* Software Rings */ -#ifndef APP_DEFAULT_RING_RX_SIZE -#define APP_DEFAULT_RING_RX_SIZE 1024 -#endif - -#ifndef APP_DEFAULT_RING_TX_SIZE -#define APP_DEFAULT_RING_TX_SIZE 1024 -#endif - -/* Bursts */ -#ifndef APP_MBUF_ARRAY_SIZE -#define APP_MBUF_ARRAY_SIZE 512 -#endif - -#ifndef APP_DEFAULT_BURST_SIZE_IO_RX_READ -#define APP_DEFAULT_BURST_SIZE_IO_RX_READ 144 -#endif -#if (APP_DEFAULT_BURST_SIZE_IO_RX_READ > APP_MBUF_ARRAY_SIZE) -#error "APP_DEFAULT_BURST_SIZE_IO_RX_READ is too big" -#endif - -#ifndef APP_DEFAULT_BURST_SIZE_IO_RX_WRITE -#define APP_DEFAULT_BURST_SIZE_IO_RX_WRITE 144 -#endif -#if (APP_DEFAULT_BURST_SIZE_IO_RX_WRITE > APP_MBUF_ARRAY_SIZE) -#error "APP_DEFAULT_BURST_SIZE_IO_RX_WRITE is too big" -#endif - -#ifndef APP_DEFAULT_BURST_SIZE_IO_TX_READ -#define APP_DEFAULT_BURST_SIZE_IO_TX_READ 144 -#endif -#if (APP_DEFAULT_BURST_SIZE_IO_TX_READ > APP_MBUF_ARRAY_SIZE) -#error "APP_DEFAULT_BURST_SIZE_IO_TX_READ is too big" -#endif - -#ifndef APP_DEFAULT_BURST_SIZE_IO_TX_WRITE -#define APP_DEFAULT_BURST_SIZE_IO_TX_WRITE 144 -#endif -#if (APP_DEFAULT_BURST_SIZE_IO_TX_WRITE > APP_MBUF_ARRAY_SIZE) -#error "APP_DEFAULT_BURST_SIZE_IO_TX_WRITE is too big" -#endif - -#ifndef APP_DEFAULT_BURST_SIZE_WORKER_READ -#define APP_DEFAULT_BURST_SIZE_WORKER_READ 144 -#endif -#if ((2 * APP_DEFAULT_BURST_SIZE_WORKER_READ) > APP_MBUF_ARRAY_SIZE) -#error "APP_DEFAULT_BURST_SIZE_WORKER_READ is too big" -#endif - -#ifndef APP_DEFAULT_BURST_SIZE_WORKER_WRITE -#define APP_DEFAULT_BURST_SIZE_WORKER_WRITE 144 -#endif -#if (APP_DEFAULT_BURST_SIZE_WORKER_WRITE > APP_MBUF_ARRAY_SIZE) -#error "APP_DEFAULT_BURST_SIZE_WORKER_WRITE is too big" -#endif - -/* Load balancing logic */ -#ifndef APP_DEFAULT_IO_RX_LB_POS -#define APP_DEFAULT_IO_RX_LB_POS 29 -#endif -#if (APP_DEFAULT_IO_RX_LB_POS >= 64) -#error "APP_DEFAULT_IO_RX_LB_POS is too big" -#endif - -struct app_mbuf_array { - struct rte_mbuf *array[APP_MBUF_ARRAY_SIZE]; - uint32_t n_mbufs; -}; - -enum app_lcore_type { - e_APP_LCORE_DISABLED = 0, - e_APP_LCORE_IO, - e_APP_LCORE_WORKER -}; - -struct app_lcore_params_io { - /* I/O RX */ - struct { - /* NIC */ - struct { - uint16_t port; - uint8_t queue; - } nic_queues[APP_MAX_NIC_RX_QUEUES_PER_IO_LCORE]; - uint32_t n_nic_queues; - - /* Rings */ - struct rte_ring *rings[APP_MAX_WORKER_LCORES]; - uint32_t n_rings; - - /* Internal buffers */ - struct app_mbuf_array mbuf_in; - struct app_mbuf_array mbuf_out[APP_MAX_WORKER_LCORES]; - uint8_t mbuf_out_flush[APP_MAX_WORKER_LCORES]; - - /* Stats */ - uint32_t nic_queues_count[APP_MAX_NIC_RX_QUEUES_PER_IO_LCORE]; - uint32_t nic_queues_iters[APP_MAX_NIC_RX_QUEUES_PER_IO_LCORE]; - uint32_t rings_count[APP_MAX_WORKER_LCORES]; - uint32_t rings_iters[APP_MAX_WORKER_LCORES]; - } rx; - - /* I/O TX */ - struct { - /* Rings */ - struct rte_ring *rings[APP_MAX_NIC_PORTS][APP_MAX_WORKER_LCORES]; - - /* NIC */ - uint16_t nic_ports[APP_MAX_NIC_TX_PORTS_PER_IO_LCORE]; - uint32_t n_nic_ports; - - /* Internal buffers */ - struct app_mbuf_array mbuf_out[APP_MAX_NIC_TX_PORTS_PER_IO_LCORE]; - uint8_t mbuf_out_flush[APP_MAX_NIC_TX_PORTS_PER_IO_LCORE]; - - /* Stats */ - uint32_t rings_count[APP_MAX_NIC_PORTS][APP_MAX_WORKER_LCORES]; - uint32_t rings_iters[APP_MAX_NIC_PORTS][APP_MAX_WORKER_LCORES]; - uint32_t nic_ports_count[APP_MAX_NIC_TX_PORTS_PER_IO_LCORE]; - uint32_t nic_ports_iters[APP_MAX_NIC_TX_PORTS_PER_IO_LCORE]; - } tx; -}; - -struct app_lcore_params_worker { - /* Rings */ - struct rte_ring *rings_in[APP_MAX_IO_LCORES]; - uint32_t n_rings_in; - struct rte_ring *rings_out[APP_MAX_NIC_PORTS]; - - /* LPM table */ - struct rte_lpm *lpm_table; - uint32_t worker_id; - - /* Internal buffers */ - struct app_mbuf_array mbuf_in; - struct app_mbuf_array mbuf_out[APP_MAX_NIC_PORTS]; - uint8_t mbuf_out_flush[APP_MAX_NIC_PORTS]; - - /* Stats */ - uint32_t rings_in_count[APP_MAX_IO_LCORES]; - uint32_t rings_in_iters[APP_MAX_IO_LCORES]; - uint32_t rings_out_count[APP_MAX_NIC_PORTS]; - uint32_t rings_out_iters[APP_MAX_NIC_PORTS]; -}; - -struct app_lcore_params { - union { - struct app_lcore_params_io io; - struct app_lcore_params_worker worker; - }; - enum app_lcore_type type; - struct rte_mempool *pool; -} __rte_cache_aligned; - -struct app_lpm_rule { - uint32_t ip; - uint8_t depth; - uint8_t if_out; -}; - -struct app_params { - /* lcore */ - struct app_lcore_params lcore_params[APP_MAX_LCORES]; - - /* NIC */ - uint8_t nic_rx_queue_mask[APP_MAX_NIC_PORTS][APP_MAX_RX_QUEUES_PER_NIC_PORT]; - uint8_t nic_tx_port_mask[APP_MAX_NIC_PORTS]; - - /* mbuf pools */ - struct rte_mempool *pools[APP_MAX_SOCKETS]; - - /* LPM tables */ - struct rte_lpm *lpm_tables[APP_MAX_SOCKETS]; - struct app_lpm_rule lpm_rules[APP_MAX_LPM_RULES]; - uint32_t n_lpm_rules; - - /* rings */ - uint32_t nic_rx_ring_size; - uint32_t nic_tx_ring_size; - uint32_t ring_rx_size; - uint32_t ring_tx_size; - - /* burst size */ - uint32_t burst_size_io_rx_read; - uint32_t burst_size_io_rx_write; - uint32_t burst_size_io_tx_read; - uint32_t burst_size_io_tx_write; - uint32_t burst_size_worker_read; - uint32_t burst_size_worker_write; - - /* load balancing */ - uint8_t pos_lb; -} __rte_cache_aligned; - -extern struct app_params app; - -int app_parse_args(int argc, char **argv); -void app_print_usage(void); -void app_init(void); -int app_lcore_main_loop(void *arg); - -int app_get_nic_rx_queues_per_port(uint16_t port); -int app_get_lcore_for_nic_rx(uint16_t port, uint8_t queue, - uint32_t *lcore_out); -int app_get_lcore_for_nic_tx(uint16_t port, uint32_t *lcore_out); -int app_is_socket_used(uint32_t socket); -uint32_t app_get_lcores_io_rx(void); -uint32_t app_get_lcores_worker(void); -void app_print_params(void); - -#endif /* _MAIN_H_ */ diff --git a/examples/load_balancer/meson.build b/examples/load_balancer/meson.build deleted file mode 100644 index 4f7ac3999..000000000 --- a/examples/load_balancer/meson.build +++ /dev/null @@ -1,12 +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' - -deps += 'lpm' -sources = files( - 'config.c', 'init.c', 'main.c', 'runtime.c' -) diff --git a/examples/load_balancer/runtime.c b/examples/load_balancer/runtime.c deleted file mode 100644 index f0aad1513..000000000 --- a/examples/load_balancer/runtime.c +++ /dev/null @@ -1,642 +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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "main.h" - -#ifndef APP_LCORE_IO_FLUSH -#define APP_LCORE_IO_FLUSH 1000000 -#endif - -#ifndef APP_LCORE_WORKER_FLUSH -#define APP_LCORE_WORKER_FLUSH 1000000 -#endif - -#ifndef APP_STATS -#define APP_STATS 1000000 -#endif - -#define APP_IO_RX_DROP_ALL_PACKETS 0 -#define APP_WORKER_DROP_ALL_PACKETS 0 -#define APP_IO_TX_DROP_ALL_PACKETS 0 - -#ifndef APP_IO_RX_PREFETCH_ENABLE -#define APP_IO_RX_PREFETCH_ENABLE 1 -#endif - -#ifndef APP_WORKER_PREFETCH_ENABLE -#define APP_WORKER_PREFETCH_ENABLE 1 -#endif - -#ifndef APP_IO_TX_PREFETCH_ENABLE -#define APP_IO_TX_PREFETCH_ENABLE 1 -#endif - -#if APP_IO_RX_PREFETCH_ENABLE -#define APP_IO_RX_PREFETCH0(p) rte_prefetch0(p) -#define APP_IO_RX_PREFETCH1(p) rte_prefetch1(p) -#else -#define APP_IO_RX_PREFETCH0(p) -#define APP_IO_RX_PREFETCH1(p) -#endif - -#if APP_WORKER_PREFETCH_ENABLE -#define APP_WORKER_PREFETCH0(p) rte_prefetch0(p) -#define APP_WORKER_PREFETCH1(p) rte_prefetch1(p) -#else -#define APP_WORKER_PREFETCH0(p) -#define APP_WORKER_PREFETCH1(p) -#endif - -#if APP_IO_TX_PREFETCH_ENABLE -#define APP_IO_TX_PREFETCH0(p) rte_prefetch0(p) -#define APP_IO_TX_PREFETCH1(p) rte_prefetch1(p) -#else -#define APP_IO_TX_PREFETCH0(p) -#define APP_IO_TX_PREFETCH1(p) -#endif - -static inline void -app_lcore_io_rx_buffer_to_send ( - struct app_lcore_params_io *lp, - uint32_t worker, - struct rte_mbuf *mbuf, - uint32_t bsz) -{ - uint32_t pos; - int ret; - - pos = lp->rx.mbuf_out[worker].n_mbufs; - lp->rx.mbuf_out[worker].array[pos ++] = mbuf; - if (likely(pos < bsz)) { - lp->rx.mbuf_out[worker].n_mbufs = pos; - return; - } - - ret = rte_ring_sp_enqueue_bulk( - lp->rx.rings[worker], - (void **) lp->rx.mbuf_out[worker].array, - bsz, - NULL); - - if (unlikely(ret == 0)) { - uint32_t k; - for (k = 0; k < bsz; k ++) { - struct rte_mbuf *m = lp->rx.mbuf_out[worker].array[k]; - rte_pktmbuf_free(m); - } - } - - lp->rx.mbuf_out[worker].n_mbufs = 0; - lp->rx.mbuf_out_flush[worker] = 0; - -#if APP_STATS - lp->rx.rings_iters[worker] ++; - if (likely(ret == 0)) { - lp->rx.rings_count[worker] ++; - } - if (unlikely(lp->rx.rings_iters[worker] == APP_STATS)) { - unsigned lcore = rte_lcore_id(); - - printf("\tI/O RX %u out (worker %u): enq success rate = %.2f\n", - lcore, - (unsigned)worker, - ((double) lp->rx.rings_count[worker]) / ((double) lp->rx.rings_iters[worker])); - lp->rx.rings_iters[worker] = 0; - lp->rx.rings_count[worker] = 0; - } -#endif -} - -static inline void -app_lcore_io_rx( - struct app_lcore_params_io *lp, - uint32_t n_workers, - uint32_t bsz_rd, - uint32_t bsz_wr, - uint8_t pos_lb) -{ - struct rte_mbuf *mbuf_1_0, *mbuf_1_1, *mbuf_2_0, *mbuf_2_1; - uint8_t *data_1_0, *data_1_1 = NULL; - uint32_t i; - - for (i = 0; i < lp->rx.n_nic_queues; i ++) { - uint16_t port = lp->rx.nic_queues[i].port; - uint8_t queue = lp->rx.nic_queues[i].queue; - uint32_t n_mbufs, j; - - n_mbufs = rte_eth_rx_burst( - port, - queue, - lp->rx.mbuf_in.array, - (uint16_t) bsz_rd); - - if (unlikely(n_mbufs == 0)) { - continue; - } - -#if APP_STATS - lp->rx.nic_queues_iters[i] ++; - lp->rx.nic_queues_count[i] += n_mbufs; - if (unlikely(lp->rx.nic_queues_iters[i] == APP_STATS)) { - struct rte_eth_stats stats; - unsigned lcore = rte_lcore_id(); - - rte_eth_stats_get(port, &stats); - - printf("I/O RX %u in (NIC port %u): NIC drop ratio = %.2f avg burst size = %.2f\n", - lcore, - port, - (double) stats.imissed / (double) (stats.imissed + stats.ipackets), - ((double) lp->rx.nic_queues_count[i]) / ((double) lp->rx.nic_queues_iters[i])); - lp->rx.nic_queues_iters[i] = 0; - lp->rx.nic_queues_count[i] = 0; - } -#endif - -#if APP_IO_RX_DROP_ALL_PACKETS - for (j = 0; j < n_mbufs; j ++) { - struct rte_mbuf *pkt = lp->rx.mbuf_in.array[j]; - rte_pktmbuf_free(pkt); - } - - continue; -#endif - - mbuf_1_0 = lp->rx.mbuf_in.array[0]; - mbuf_1_1 = lp->rx.mbuf_in.array[1]; - data_1_0 = rte_pktmbuf_mtod(mbuf_1_0, uint8_t *); - if (likely(n_mbufs > 1)) { - data_1_1 = rte_pktmbuf_mtod(mbuf_1_1, uint8_t *); - } - - mbuf_2_0 = lp->rx.mbuf_in.array[2]; - mbuf_2_1 = lp->rx.mbuf_in.array[3]; - APP_IO_RX_PREFETCH0(mbuf_2_0); - APP_IO_RX_PREFETCH0(mbuf_2_1); - - for (j = 0; j + 3 < n_mbufs; j += 2) { - struct rte_mbuf *mbuf_0_0, *mbuf_0_1; - uint8_t *data_0_0, *data_0_1; - uint32_t worker_0, worker_1; - - mbuf_0_0 = mbuf_1_0; - mbuf_0_1 = mbuf_1_1; - data_0_0 = data_1_0; - data_0_1 = data_1_1; - - mbuf_1_0 = mbuf_2_0; - mbuf_1_1 = mbuf_2_1; - data_1_0 = rte_pktmbuf_mtod(mbuf_2_0, uint8_t *); - data_1_1 = rte_pktmbuf_mtod(mbuf_2_1, uint8_t *); - APP_IO_RX_PREFETCH0(data_1_0); - APP_IO_RX_PREFETCH0(data_1_1); - - mbuf_2_0 = lp->rx.mbuf_in.array[j+4]; - mbuf_2_1 = lp->rx.mbuf_in.array[j+5]; - APP_IO_RX_PREFETCH0(mbuf_2_0); - APP_IO_RX_PREFETCH0(mbuf_2_1); - - worker_0 = data_0_0[pos_lb] & (n_workers - 1); - worker_1 = data_0_1[pos_lb] & (n_workers - 1); - - app_lcore_io_rx_buffer_to_send(lp, worker_0, mbuf_0_0, bsz_wr); - app_lcore_io_rx_buffer_to_send(lp, worker_1, mbuf_0_1, bsz_wr); - } - - /* Handle the last 1, 2 (when n_mbufs is even) or 3 (when n_mbufs is odd) packets */ - for ( ; j < n_mbufs; j += 1) { - struct rte_mbuf *mbuf; - uint8_t *data; - uint32_t worker; - - mbuf = mbuf_1_0; - mbuf_1_0 = mbuf_1_1; - mbuf_1_1 = mbuf_2_0; - mbuf_2_0 = mbuf_2_1; - - data = rte_pktmbuf_mtod(mbuf, uint8_t *); - - APP_IO_RX_PREFETCH0(mbuf_1_0); - - worker = data[pos_lb] & (n_workers - 1); - - app_lcore_io_rx_buffer_to_send(lp, worker, mbuf, bsz_wr); - } - } -} - -static inline void -app_lcore_io_rx_flush(struct app_lcore_params_io *lp, uint32_t n_workers) -{ - uint32_t worker; - - for (worker = 0; worker < n_workers; worker ++) { - int ret; - - if (likely((lp->rx.mbuf_out_flush[worker] == 0) || - (lp->rx.mbuf_out[worker].n_mbufs == 0))) { - lp->rx.mbuf_out_flush[worker] = 1; - continue; - } - - ret = rte_ring_sp_enqueue_bulk( - lp->rx.rings[worker], - (void **) lp->rx.mbuf_out[worker].array, - lp->rx.mbuf_out[worker].n_mbufs, - NULL); - - if (unlikely(ret == 0)) { - uint32_t k; - for (k = 0; k < lp->rx.mbuf_out[worker].n_mbufs; k ++) { - struct rte_mbuf *pkt_to_free = lp->rx.mbuf_out[worker].array[k]; - rte_pktmbuf_free(pkt_to_free); - } - } - - lp->rx.mbuf_out[worker].n_mbufs = 0; - lp->rx.mbuf_out_flush[worker] = 1; - } -} - -static inline void -app_lcore_io_tx( - struct app_lcore_params_io *lp, - uint32_t n_workers, - uint32_t bsz_rd, - uint32_t bsz_wr) -{ - uint32_t worker; - - for (worker = 0; worker < n_workers; worker ++) { - uint32_t i; - - for (i = 0; i < lp->tx.n_nic_ports; i ++) { - uint16_t port = lp->tx.nic_ports[i]; - struct rte_ring *ring = lp->tx.rings[port][worker]; - uint32_t n_mbufs, n_pkts; - int ret; - - n_mbufs = lp->tx.mbuf_out[port].n_mbufs; - ret = rte_ring_sc_dequeue_bulk( - ring, - (void **) &lp->tx.mbuf_out[port].array[n_mbufs], - bsz_rd, - NULL); - - if (unlikely(ret == 0)) - continue; - - n_mbufs += bsz_rd; - -#if APP_IO_TX_DROP_ALL_PACKETS - { - uint32_t j; - APP_IO_TX_PREFETCH0(lp->tx.mbuf_out[port].array[0]); - APP_IO_TX_PREFETCH0(lp->tx.mbuf_out[port].array[1]); - - for (j = 0; j < n_mbufs; j ++) { - if (likely(j < n_mbufs - 2)) { - APP_IO_TX_PREFETCH0(lp->tx.mbuf_out[port].array[j + 2]); - } - - rte_pktmbuf_free(lp->tx.mbuf_out[port].array[j]); - } - - lp->tx.mbuf_out[port].n_mbufs = 0; - - continue; - } -#endif - - if (unlikely(n_mbufs < bsz_wr)) { - lp->tx.mbuf_out[port].n_mbufs = n_mbufs; - continue; - } - - n_pkts = rte_eth_tx_burst( - port, - 0, - lp->tx.mbuf_out[port].array, - (uint16_t) n_mbufs); - -#if APP_STATS - lp->tx.nic_ports_iters[port] ++; - lp->tx.nic_ports_count[port] += n_pkts; - if (unlikely(lp->tx.nic_ports_iters[port] == APP_STATS)) { - unsigned lcore = rte_lcore_id(); - - printf("\t\t\tI/O TX %u out (port %u): avg burst size = %.2f\n", - lcore, - port, - ((double) lp->tx.nic_ports_count[port]) / ((double) lp->tx.nic_ports_iters[port])); - lp->tx.nic_ports_iters[port] = 0; - lp->tx.nic_ports_count[port] = 0; - } -#endif - - if (unlikely(n_pkts < n_mbufs)) { - uint32_t k; - for (k = n_pkts; k < n_mbufs; k ++) { - struct rte_mbuf *pkt_to_free = lp->tx.mbuf_out[port].array[k]; - rte_pktmbuf_free(pkt_to_free); - } - } - lp->tx.mbuf_out[port].n_mbufs = 0; - lp->tx.mbuf_out_flush[port] = 0; - } - } -} - -static inline void -app_lcore_io_tx_flush(struct app_lcore_params_io *lp) -{ - uint16_t port; - uint32_t i; - - for (i = 0; i < lp->tx.n_nic_ports; i++) { - uint32_t n_pkts; - - port = lp->tx.nic_ports[i]; - if (likely((lp->tx.mbuf_out_flush[port] == 0) || - (lp->tx.mbuf_out[port].n_mbufs == 0))) { - lp->tx.mbuf_out_flush[port] = 1; - continue; - } - - n_pkts = rte_eth_tx_burst( - port, - 0, - lp->tx.mbuf_out[port].array, - (uint16_t) lp->tx.mbuf_out[port].n_mbufs); - - if (unlikely(n_pkts < lp->tx.mbuf_out[port].n_mbufs)) { - uint32_t k; - for (k = n_pkts; k < lp->tx.mbuf_out[port].n_mbufs; k ++) { - struct rte_mbuf *pkt_to_free = lp->tx.mbuf_out[port].array[k]; - rte_pktmbuf_free(pkt_to_free); - } - } - - lp->tx.mbuf_out[port].n_mbufs = 0; - lp->tx.mbuf_out_flush[port] = 1; - } -} - -static void -app_lcore_main_loop_io(void) -{ - uint32_t lcore = rte_lcore_id(); - struct app_lcore_params_io *lp = &app.lcore_params[lcore].io; - uint32_t n_workers = app_get_lcores_worker(); - uint64_t i = 0; - - uint32_t bsz_rx_rd = app.burst_size_io_rx_read; - uint32_t bsz_rx_wr = app.burst_size_io_rx_write; - uint32_t bsz_tx_rd = app.burst_size_io_tx_read; - uint32_t bsz_tx_wr = app.burst_size_io_tx_write; - - uint8_t pos_lb = app.pos_lb; - - for ( ; ; ) { - if (APP_LCORE_IO_FLUSH && (unlikely(i == APP_LCORE_IO_FLUSH))) { - if (likely(lp->rx.n_nic_queues > 0)) { - app_lcore_io_rx_flush(lp, n_workers); - } - - if (likely(lp->tx.n_nic_ports > 0)) { - app_lcore_io_tx_flush(lp); - } - - i = 0; - } - - if (likely(lp->rx.n_nic_queues > 0)) { - app_lcore_io_rx(lp, n_workers, bsz_rx_rd, bsz_rx_wr, pos_lb); - } - - if (likely(lp->tx.n_nic_ports > 0)) { - app_lcore_io_tx(lp, n_workers, bsz_tx_rd, bsz_tx_wr); - } - - i ++; - } -} - -static inline void -app_lcore_worker( - struct app_lcore_params_worker *lp, - uint32_t bsz_rd, - uint32_t bsz_wr) -{ - uint32_t i; - - for (i = 0; i < lp->n_rings_in; i ++) { - struct rte_ring *ring_in = lp->rings_in[i]; - uint32_t j; - int ret; - - ret = rte_ring_sc_dequeue_bulk( - ring_in, - (void **) lp->mbuf_in.array, - bsz_rd, - NULL); - - if (unlikely(ret == 0)) - continue; - -#if APP_WORKER_DROP_ALL_PACKETS - for (j = 0; j < bsz_rd; j ++) { - struct rte_mbuf *pkt = lp->mbuf_in.array[j]; - rte_pktmbuf_free(pkt); - } - - continue; -#endif - - APP_WORKER_PREFETCH1(rte_pktmbuf_mtod(lp->mbuf_in.array[0], unsigned char *)); - APP_WORKER_PREFETCH0(lp->mbuf_in.array[1]); - - for (j = 0; j < bsz_rd; j ++) { - struct rte_mbuf *pkt; - struct rte_ipv4_hdr *ipv4_hdr; - uint32_t ipv4_dst, pos; - uint32_t port; - - if (likely(j < bsz_rd - 1)) { - APP_WORKER_PREFETCH1(rte_pktmbuf_mtod(lp->mbuf_in.array[j+1], unsigned char *)); - } - if (likely(j < bsz_rd - 2)) { - APP_WORKER_PREFETCH0(lp->mbuf_in.array[j+2]); - } - - pkt = lp->mbuf_in.array[j]; - ipv4_hdr = rte_pktmbuf_mtod_offset( - pkt, struct rte_ipv4_hdr *, - sizeof(struct rte_ether_hdr)); - ipv4_dst = rte_be_to_cpu_32(ipv4_hdr->dst_addr); - - if (unlikely(rte_lpm_lookup(lp->lpm_table, ipv4_dst, &port) != 0)) { - port = pkt->port; - } - - pos = lp->mbuf_out[port].n_mbufs; - - lp->mbuf_out[port].array[pos ++] = pkt; - if (likely(pos < bsz_wr)) { - lp->mbuf_out[port].n_mbufs = pos; - continue; - } - - ret = rte_ring_sp_enqueue_bulk( - lp->rings_out[port], - (void **) lp->mbuf_out[port].array, - bsz_wr, - NULL); - -#if APP_STATS - lp->rings_out_iters[port] ++; - if (ret > 0) { - lp->rings_out_count[port] += 1; - } - if (lp->rings_out_iters[port] == APP_STATS){ - printf("\t\tWorker %u out (NIC port %u): enq success rate = %.2f\n", - (unsigned) lp->worker_id, - port, - ((double) lp->rings_out_count[port]) / ((double) lp->rings_out_iters[port])); - lp->rings_out_iters[port] = 0; - lp->rings_out_count[port] = 0; - } -#endif - - if (unlikely(ret == 0)) { - uint32_t k; - for (k = 0; k < bsz_wr; k ++) { - struct rte_mbuf *pkt_to_free = lp->mbuf_out[port].array[k]; - rte_pktmbuf_free(pkt_to_free); - } - } - - lp->mbuf_out[port].n_mbufs = 0; - lp->mbuf_out_flush[port] = 0; - } - } -} - -static inline void -app_lcore_worker_flush(struct app_lcore_params_worker *lp) -{ - uint32_t port; - - for (port = 0; port < APP_MAX_NIC_PORTS; port ++) { - int ret; - - if (unlikely(lp->rings_out[port] == NULL)) { - continue; - } - - if (likely((lp->mbuf_out_flush[port] == 0) || - (lp->mbuf_out[port].n_mbufs == 0))) { - lp->mbuf_out_flush[port] = 1; - continue; - } - - ret = rte_ring_sp_enqueue_bulk( - lp->rings_out[port], - (void **) lp->mbuf_out[port].array, - lp->mbuf_out[port].n_mbufs, - NULL); - - if (unlikely(ret == 0)) { - uint32_t k; - for (k = 0; k < lp->mbuf_out[port].n_mbufs; k ++) { - struct rte_mbuf *pkt_to_free = lp->mbuf_out[port].array[k]; - rte_pktmbuf_free(pkt_to_free); - } - } - - lp->mbuf_out[port].n_mbufs = 0; - lp->mbuf_out_flush[port] = 1; - } -} - -static void -app_lcore_main_loop_worker(void) { - uint32_t lcore = rte_lcore_id(); - struct app_lcore_params_worker *lp = &app.lcore_params[lcore].worker; - uint64_t i = 0; - - uint32_t bsz_rd = app.burst_size_worker_read; - uint32_t bsz_wr = app.burst_size_worker_write; - - for ( ; ; ) { - if (APP_LCORE_WORKER_FLUSH && (unlikely(i == APP_LCORE_WORKER_FLUSH))) { - app_lcore_worker_flush(lp); - i = 0; - } - - app_lcore_worker(lp, bsz_rd, bsz_wr); - - i ++; - } -} - -int -app_lcore_main_loop(__attribute__((unused)) void *arg) -{ - struct app_lcore_params *lp; - unsigned lcore; - - lcore = rte_lcore_id(); - lp = &app.lcore_params[lcore]; - - if (lp->type == e_APP_LCORE_IO) { - printf("Logical core %u (I/O) main loop.\n", lcore); - app_lcore_main_loop_io(); - } - - if (lp->type == e_APP_LCORE_WORKER) { - printf("Logical core %u (worker %u) main loop.\n", - lcore, - (unsigned) lp->worker.worker_id); - app_lcore_main_loop_worker(); - } - - return 0; -} diff --git a/examples/meson.build b/examples/meson.build index f0356f2a1..e4580f74a 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -24,7 +24,6 @@ all_examples = [ 'l2fwd-keepalive', 'l3fwd', 'l3fwd-acl', 'l3fwd-power', 'link_status_interrupt', - 'load_balancer', 'multi_process/client_server_mp/mp_client', 'multi_process/client_server_mp/mp_server', 'multi_process/hotplug_mp', From patchwork Thu Oct 3 13:19:18 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bruce Richardson X-Patchwork-Id: 60497 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id DF32B1C190; Thu, 3 Oct 2019 15:20:04 +0200 (CEST) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by dpdk.org (Postfix) with ESMTP id 6E14C1C0D7; Thu, 3 Oct 2019 15:19:59 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 03 Oct 2019 06:19:58 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.67,252,1566889200"; d="scan'208";a="185910587" Received: from silpixa00399126.ir.intel.com (HELO silpixa00399126.ger.corp.intel.com) ([10.237.223.2]) by orsmga008.jf.intel.com with ESMTP; 03 Oct 2019 06:19:57 -0700 From: Bruce Richardson To: dev@dpdk.org Cc: techboard@dpdk.org, Bruce Richardson Date: Thu, 3 Oct 2019 14:19:18 +0100 Message-Id: <20191003131918.30970-7-bruce.richardson@intel.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191003131918.30970-1-bruce.richardson@intel.com> References: <20191003131918.30970-1-bruce.richardson@intel.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH 6/6] doc: close up gaps in sample app guide table 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" Following the removal of some sample applications, close up the gaps introduced in the table so that it is formatted nicely for the next release. Signed-off-by: Bruce Richardson --- doc/guides/sample_app_ug/intro.rst | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/doc/guides/sample_app_ug/intro.rst b/doc/guides/sample_app_ug/intro.rst index 981e50f94..dcfe70db2 100644 --- a/doc/guides/sample_app_ug/intro.rst +++ b/doc/guides/sample_app_ug/intro.rst @@ -31,37 +31,33 @@ applications that are available in the examples directory of DPDK: .. table:: **Some of the DPDK Sample applications** +---------------------------------------+--------------------------------------+ - | Bonding | | + | Bonding | Packet Ordering | +---------------------------------------+--------------------------------------+ - | Command Line | Packet Ordering | + | Command Line | Performance Thread | +---------------------------------------+--------------------------------------+ - | Distributor | Performance Thread | + | Distributor | Precision Time Protocol (PTP) Client | +---------------------------------------+--------------------------------------+ - | Ethtool | Precision Time Protocol (PTP) Client | - +---------------------------------------+--------------------------------------+ - | | Quality of Service (QoS) Metering | + | Ethtool | Quality of Service (QoS) Metering | +---------------------------------------+--------------------------------------+ | Hello World | QoS Scheduler | +---------------------------------------+--------------------------------------+ - | Internet Protocol (IP) Fragmentation | | - +---------------------------------------+--------------------------------------+ - | IP Pipeline | RX/TX Callbacks | + | Internet Protocol (IP) Fragmentation | RX/TX Callbacks | +---------------------------------------+--------------------------------------+ - | IP Reassembly | Server node EFD | + | IP Pipeline | Server node EFD | +---------------------------------------+--------------------------------------+ - | IPsec Security Gateway | Basic Forwarding/Skeleton App | + | IP Reassembly | Basic Forwarding/Skeleton App | +---------------------------------------+--------------------------------------+ - | IPv4 multicast | Tunnel End Point (TEP) termination | + | IPsec Security Gateway | Tunnel End Point (TEP) termination | +---------------------------------------+--------------------------------------+ - | Kernel NIC Interface | Timer | + | IPv4 multicast | Timer | +---------------------------------------+--------------------------------------+ - | Network Layer 2 Forwarding + variants | Vhost | + | Kernel NIC Interface | Vhost | +---------------------------------------+--------------------------------------+ - | Network Layer 3 Forwarding + variants | Vhost Xen | + | Network Layer 2 Forwarding + variants | Vhost Xen | +---------------------------------------+--------------------------------------+ - | Link Status Interrupt | VMDQ Forwarding | + | Network Layer 3 Forwarding + variants | VMDQ Forwarding | +---------------------------------------+--------------------------------------+ - | | VMDQ and DCB Forwarding | + | Link Status Interrupt | VMDQ and DCB Forwarding | +---------------------------------------+--------------------------------------+ | Multi-process | VM Power Management | +---------------------------------------+--------------------------------------+