From bd6e98193a0b08aca30045e80fc4e22ecd480163 Mon Sep 17 00:00:00 2001 From: Bruce Richardson Date: Fri, 25 Oct 2019 10:56:05 +0100 Subject: [PATCH] examples/l3fwd-vf: remove example The main l3fwd app should work with both PF and VF devices, so remove the VF-only l3fwd example. Signed-off-by: Bruce Richardson 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 - .../sample_app_ug/l3_forward_virtual.rst | 98 -- examples/Makefile | 1 - examples/l3fwd-vf/Makefile | 62 - examples/l3fwd-vf/main.c | 1077 ----------------- examples/l3fwd-vf/meson.build | 12 - examples/meson.build | 2 +- 9 files changed, 2 insertions(+), 1255 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 320b0b94a0..3ed168e3aa 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1495,9 +1495,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/rel_notes/release_19_11.rst b/doc/guides/rel_notes/release_19_11.rst index 71c6fac38c..76a49e8af4 100644 --- a/doc/guides/rel_notes/release_19_11.rst +++ b/doc/guides/rel_notes/release_19_11.rst @@ -261,6 +261,7 @@ Removed Items * The following sample applications have been removed in this release: * Exception Path + * L3 Forwarding in a Virtualization Environment * vhost-scsi diff --git a/doc/guides/sample_app_ug/index.rst b/doc/guides/sample_app_ug/index.rst index e33f425745..1334a50076 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 21eab8da39..0000000000 --- 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 bac65cbfc6..0940b4be16 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 7b186a23cb..0000000000 --- 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 ff6c9e2f1e..0000000000 --- a/examples/l3fwd-vf/main.c +++ /dev/null @@ -1,1077 +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); - - ret = rte_eth_macaddr_get(portid, &ports_eth_addr[portid]); - if (ret < 0) - rte_exit(EXIT_FAILURE, - "Cannot get MAC address: err=%d, port=%d\n", - ret, 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 226286e744..0000000000 --- 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 3f045ed932..20b788a2c2 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', -- 2.20.1