From ab6ebd70205f3587a4ecab8e5fb21100d9d99ce0 Mon Sep 17 00:00:00 2001 From: Ciara Power Date: Fri, 25 Oct 2019 10:56:08 +0100 Subject: [PATCH] examples/load_balancer: remove example 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 Acked-by: Stephen Hemminger Acked-by: Hemant Agrawal --- MAINTAINERS | 3 - doc/guides/rel_notes/release_19_11.rst | 1 + doc/guides/sample_app_ug/index.rst | 1 - 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 | 537 ---------- 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(+), 2917 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 f84ee75d28..a054355b90 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1498,9 +1498,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/rel_notes/release_19_11.rst b/doc/guides/rel_notes/release_19_11.rst index 7a6ce51401..2064ed7a2a 100644 --- a/doc/guides/rel_notes/release_19_11.rst +++ b/doc/guides/rel_notes/release_19_11.rst @@ -262,6 +262,7 @@ Removed Items * Exception Path * L3 Forwarding in a Virtualization Environment + * Load Balancer * Netmap Compatibility * Quota and Watermark * vhost-scsi diff --git a/doc/guides/sample_app_ug/index.rst b/doc/guides/sample_app_ug/index.rst index a053065e31..a57ac482f1 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/load_balancer.rst b/doc/guides/sample_app_ug/load_balancer.rst deleted file mode 100644 index 8f2abdfb84..0000000000 --- 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 3d84ebebeb..5bcf0d55a1 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 caae8a1071..0000000000 --- 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 972c85c5b8..0000000000 --- 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 7622267547..0000000000 --- a/examples/load_balancer/init.c +++ /dev/null @@ -1,537 +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; - int ret; - 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)); - ret = rte_eth_link_get_nowait(portid, &link); - if (ret < 0) { - all_ports_up = 0; - if (print_flag == 1) - printf("Port %u link get failed: %s\n", - portid, rte_strerror(-ret)); - continue; - } - /* 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); - - ret = rte_eth_dev_info_get(port, &dev_info); - if (ret != 0) - rte_panic("Error during getting device (port %u) info: %s\n", - port, strerror(-ret)); - - 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); - } - - ret = rte_eth_promiscuous_enable(port); - if (ret != 0) - rte_panic("Cannot enable promiscuous mode on port %u (%s)\n", - port, rte_strerror(-ret)); - - 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 d3dcb235db..0000000000 --- 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 9fefb62eda..0000000000 --- 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 4f7ac3999a..0000000000 --- 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 f0aad1513e..0000000000 --- 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 6716376ce4..a6acda7a79 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', -- 2.20.1