DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [RFC] examples: remove l3fwd-vf example
@ 2015-07-14  7:57 Jingjing Wu
  2015-07-14  8:20 ` Jayakumar, Muthurajan
  2015-07-14 14:50 ` Zhang, Helin
  0 siblings, 2 replies; 15+ messages in thread
From: Jingjing Wu @ 2015-07-14  7:57 UTC (permalink / raw)
  To: dev

Because VF multi-queues can be supported, l3fwd can run on vf.
Suggest to remove the l3fwd-vf example.

Signed-off-by: jingjing.wu <jingjing.wu@intel.com>
---
 doc/guides/sample_app_ug/index.rst              |    1 -
 doc/guides/sample_app_ug/l3_forward_virtual.rst |  158 ----
 examples/l3fwd-vf/Makefile                      |   56 --
 examples/l3fwd-vf/main.c                        | 1092 -----------------------
 4 files changed, 1307 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

diff --git a/doc/guides/sample_app_ug/index.rst b/doc/guides/sample_app_ug/index.rst
index e1a0c56..bcccb41 100644
--- a/doc/guides/sample_app_ug/index.rst
+++ b/doc/guides/sample_app_ug/index.rst
@@ -54,7 +54,6 @@ Sample Applications User Guide
     l3_forward
     l3_forward_power_man
     l3_forward_access_ctrl
-    l3_forward_virtual
     link_status_intr
     load_balancer
     multi_process
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 f40643a..0000000
--- a/doc/guides/sample_app_ug/l3_forward_virtual.rst
+++ /dev/null
@@ -1,158 +0,0 @@
-..  BSD LICENSE
-    Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions
-    are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in
-    the documentation and/or other materials provided with the
-    distribution.
-    * Neither the name of Intel Corporation nor the names of its
-    contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-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 L3 forwarding application
-(see Chapter 10 "L3 Forwarding Sample Application" for more information).
-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 Section 9.1.1 "Virtual Function Setup Instructions" for virtualized test case setup.
-
-Compiling the Application
--------------------------
-
-To compile the application:
-
-#.  Go to the sample application directory:
-
-    .. code-block:: console
-
-        export RTE_SDK=/path/to/rte_sdk
-        cd ${RTE_SDK}/examples/l3fwd-vf
-
-#.  Set the target (a default target is used if not specified). For example:
-
-    .. code-block:: console
-
-        export RTE_TARGET=x86_64-native-linuxapp-gcc
-
-    See the *DPDK Getting Started Guide* for possible RTE_TARGET values.
-
-#.  Build the application:
-
-    .. code-block:: console
-
-        make
-
-.. note::
-
-    The compiled application is written to the build subdirectory.
-    To have the application written to a different location,
-    the O=/path/to/build/directory option may be specified in the make command.
-
-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 where cores 0,2,4,6, 8, and 10 appear on socket 0,
-while cores 1,3,5,7,9, and 11 appear on socket 1.
-Let's say that the programmer wants to use memory from both NUMA nodes,
-the platform has only two ports and the programmer wants to use one core from each processor socket to do the packet processing
-since only one Rx/Tx queue pair can be used in virtualization mode.
-
-To enable L3 forwarding between two ports, using one core from each processor,
-while also taking advantage of local memory accesses by optimizing around NUMA,
-the programmer can pin to the appropriate cores and allocate memory from the appropriate NUMA node.
-This is achieved using the following command:
-
-.. code-block:: console
-
-   ./build/l3fwd-vf -c 0x03 -n 3 -- -p 0x3 --config="(0,0,0),(1,0,1)"
-
-In this command:
-
-*   The -c option enables cores 0 and 1
-
-*   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.
-    Logic to enable multiple RX queues using RSS and to allocate memory from the correct NUMA nodes
-    is included in the application and is done transparently.
-    The following table shows the mapping in this example:
-
-    +----------+-----------+-----------+------------------------------------+
-    | **Port** | **Queue** | **lcore** | **Description**                    |
-    |          |           |           |                                    |
-    +==========+===========+===========+====================================+
-    | 0        | 0         | 0         | Map queue 0 from port 0 to lcore 0 |
-    |          |           |           |                                    |
-    +----------+-----------+-----------+------------------------------------+
-    | 1        | 1         | 1         | Map queue 0 from port 1 to lcore 1 |
-    |          |           |           |                                    |
-    +----------+-----------+-----------+------------------------------------+
-
-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 Section 10.4 "Explanation" for more information.
diff --git a/examples/l3fwd-vf/Makefile b/examples/l3fwd-vf/Makefile
deleted file mode 100644
index d97611c..0000000
--- a/examples/l3fwd-vf/Makefile
+++ /dev/null
@@ -1,56 +0,0 @@
-#   BSD LICENSE
-#
-#   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
-#   All rights reserved.
-#
-#   Redistribution and use in source and binary forms, with or without
-#   modification, are permitted provided that the following conditions
-#   are met:
-#
-#     * Redistributions of source code must retain the above copyright
-#       notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above copyright
-#       notice, this list of conditions and the following disclaimer in
-#       the documentation and/or other materials provided with the
-#       distribution.
-#     * Neither the name of Intel Corporation nor the names of its
-#       contributors may be used to endorse or promote products derived
-#       from this software without specific prior written permission.
-#
-#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-ifeq ($(RTE_SDK),)
-$(error "Please define RTE_SDK environment variable")
-endif
-
-# Default target, can be overriden by command line or environment
-RTE_TARGET ?= x86_64-native-linuxapp-gcc
-
-include $(RTE_SDK)/mk/rte.vars.mk
-
-# binary name
-APP = l3fwd-vf
-
-# all source are stored in SRCS-y
-SRCS-y := main.c
-
-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
diff --git a/examples/l3fwd-vf/main.c b/examples/l3fwd-vf/main.c
deleted file mode 100644
index ccbb02f..0000000
--- a/examples/l3fwd-vf/main.c
+++ /dev/null
@@ -1,1092 +0,0 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
- *   All rights reserved.
- *
- *   Redistribution and use in source and binary forms, with or without
- *   modification, are permitted provided that the following conditions
- *   are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in
- *       the documentation and/or other materials provided with the
- *       distribution.
- *     * Neither the name of Intel Corporation nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <string.h>
-#include <sys/queue.h>
-#include <stdarg.h>
-#include <errno.h>
-#include <getopt.h>
-#include <signal.h>
-
-#include <rte_common.h>
-#include <rte_byteorder.h>
-#include <rte_log.h>
-#include <rte_memory.h>
-#include <rte_memcpy.h>
-#include <rte_memzone.h>
-#include <rte_eal.h>
-#include <rte_per_lcore.h>
-#include <rte_launch.h>
-#include <rte_atomic.h>
-#include <rte_spinlock.h>
-#include <rte_cycles.h>
-#include <rte_prefetch.h>
-#include <rte_lcore.h>
-#include <rte_per_lcore.h>
-#include <rte_branch_prediction.h>
-#include <rte_interrupts.h>
-#include <rte_pci.h>
-#include <rte_random.h>
-#include <rte_debug.h>
-#include <rte_ether.h>
-#include <rte_ethdev.h>
-#include <rte_ring.h>
-#include <rte_mempool.h>
-#include <rte_mbuf.h>
-#include <rte_ip.h>
-#include <rte_tcp.h>
-#include <rte_udp.h>
-#include <rte_string_fns.h>
-
-#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 <rte_hash.h>
-#elif (APP_LOOKUP_METHOD == APP_LOOKUP_LPM)
-#include <rte_lpm.h>
-#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*RTE_TEST_RX_DESC_DEFAULT +							\
-				nb_ports*nb_lcores*MAX_PKT_BURST +											\
-				nb_ports*n_tx_queue*RTE_TEST_TX_DESC_DEFAULT +								\
-				nb_lcores*MEMPOOL_CACHE_SIZE),												\
-				(unsigned)8192)
-
-/*
- * 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.
- */
-#define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. */
-#define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */
-#define RX_WTHRESH 4 /**< Default values of RX write-back threshold reg. */
-
-/*
- * 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.
- */
-#define TX_PTHRESH 36 /**< Default values of TX prefetch threshold reg. */
-#define TX_HTHRESH 0  /**< Default values of TX host threshold reg. */
-#define TX_WTHRESH 0  /**< Default values of TX write-back threshold reg. */
-
-#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 128
-#define RTE_TEST_TX_DESC_DEFAULT 512
-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 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 {
-	uint8_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 {
-	uint8_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 = ETHER_MAX_LEN,
-		.split_hdr_size = 0,
-		.header_split   = 0, /**< Header Split disabled */
-		.hw_ip_checksum = 1, /**< IP checksum offload enabled */
-		.hw_vlan_filter = 0, /**< VLAN filtering disabled */
-		.jumbo_frame    = 0, /**< Jumbo Frame Support disabled */
-		.hw_strip_crc   = 0, /**< CRC stripped by hardware */
-	},
-	.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_MACHINE_CPUFLAG_SSE4_2
-#include <rte_hash_crc.h>
-#define DEFAULT_HASH_FUNC       rte_hash_crc
-#else
-#include <rte_jhash.h>
-#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[] = {
-	{{IPv4(100,10,0,1), IPv4(200,10,0,1), 101, 11, IPPROTO_TCP}, 0},
-	{{IPv4(100,20,0,2), IPv4(200,20,0,2), 102, 12, IPPROTO_TCP}, 1},
-	{{IPv4(100,30,0,3), IPv4(200,30,0,3), 103, 13, IPPROTO_TCP}, 2},
-	{{IPv4(100,40,0,4), 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,
-	.bucket_entries = 4,
-	.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[] = {
-	{IPv4(1,1,1,0), 24, 0},
-	{IPv4(2,1,1,0), 24, 1},
-	{IPv4(3,1,1,0), 24, 2},
-	{IPv4(4,1,1,0), 24, 3},
-	{IPv4(5,1,1,0), 24, 4},
-	{IPv4(6,1,1,0), 24, 5},
-	{IPv4(7,1,1,0), 24, 6},
-	{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, uint8_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, uint8_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 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 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 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 uint8_t
-get_dst_port(struct ipv4_hdr *ipv4_hdr,  uint8_t portid, lookup_struct_t * l3fwd_lookup_struct)
-{
-	struct ipv4_5tuple key;
-	struct tcp_hdr *tcp;
-	struct 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 tcp_hdr *)((unsigned char *) ipv4_hdr +
-					sizeof(struct 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 udp_hdr *)((unsigned char *) ipv4_hdr +
-					sizeof(struct 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 (uint8_t)((ret < 0)? portid : l3fwd_out_if[ret]);
-}
-#endif
-
-#if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM)
-static inline uint8_t
-get_dst_port(struct ipv4_hdr *ipv4_hdr,  uint8_t portid, lookup_struct_t * l3fwd_lookup_struct)
-{
-	uint8_t next_hop;
-
-	return (uint8_t) ((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, uint8_t portid, lookup_struct_t * l3fwd_lookup_struct)
-{
-	struct ether_hdr *eth_hdr;
-	struct ipv4_hdr *ipv4_hdr;
-	void *tmp;
-	uint8_t dst_port;
-
-	eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);
-
-	ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct ipv4_hdr *,
-					   sizeof(struct 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 = &eth_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 */
-	ether_addr_copy(&ports_eth_addr[dst_port], &eth_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 portid, queueid;
-	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=%hhu 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(const unsigned nb_ports)
-{
-	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 (portid >= nb_ports) {
-			printf("port %u is not present on the board\n", portid);
-			return -1;
-		}
-	}
-	return 0;
-}
-
-static uint8_t
-get_port_n_rx_queues(const uint8_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)
-{
-	uint8_t portid;
-	uint8_t nb_ports = rte_eth_dev_count();
-
-	/* When we receive a SIGINT signal */
-	if (signum == SIGINT) {
-		for (portid = 0; portid < nb_ports; 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 = (uint8_t)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 = 0; /* reset getopt lib */
-	return ret;
-}
-
-static void
-print_ethaddr(const char *name, const struct ether_addr *eth_addr)
-{
-	char buf[ETHER_ADDR_FMT_SIZE];
-	ether_format_addr(buf, 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];
-
-	/* create the LPM table */
-	snprintf(s, sizeof(s), "L3FWD_LPM_%d", socketid);
-	l3fwd_lookup_struct[socketid] = rte_lpm_create(s, socketid,
-				L3FWD_LPM_MAX_RULES, 0);
-	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;
-	unsigned lcore_id;
-	uint32_t nb_lcores;
-	uint16_t n_tx_queue;
-	uint8_t portid, 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();
-	if (nb_ports > RTE_MAX_ETHPORTS)
-		nb_ports = RTE_MAX_ETHPORTS;
-
-	if (check_port_config(nb_ports) < 0)
-		rte_exit(EXIT_FAILURE, "check_port_config failed\n");
-
-	nb_lcores = rte_lcore_count();
-
-	/* initialize all ports */
-	for (portid = 0; portid < nb_ports; portid++) {
-		/* 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 );
-		ret = rte_eth_dev_configure(portid, nb_rx_queue, n_tx_queue, &port_conf);
-		if (ret < 0)
-			rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%d\n",
-				ret, portid);
-
-		rte_eth_macaddr_get(portid, &ports_eth_addr[portid]);
-		print_ethaddr(" Address:", &ports_eth_addr[portid]);
-		printf(", ");
-
-		ret = init_mem(NB_MBUF);
-		if (ret < 0)
-			rte_exit(EXIT_FAILURE, "init_mem failed\n");
-
-		/* init one TX queue */
-		socketid = (uint8_t)rte_lcore_to_socket_id(rte_get_master_lcore());
-
-		printf("txq=%d,%d,%d ", portid, 0, socketid);
-		fflush(stdout);
-
-		rte_eth_dev_info_get(portid, &dev_info);
-		txconf = &dev_info.default_txconf;
-		if (port_conf.rxmode.jumbo_frame)
-			txconf->txq_flags = 0;
-		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++) {
-		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);
-
-			ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd,
-						socketid, NULL,
-						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 */
-	for (portid = 0; portid < nb_ports; 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;
-}
-- 
2.4.0

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [dpdk-dev] [RFC] examples: remove l3fwd-vf example
  2015-07-14  7:57 [dpdk-dev] [RFC] examples: remove l3fwd-vf example Jingjing Wu
@ 2015-07-14  8:20 ` Jayakumar, Muthurajan
  2015-07-14  8:28   ` Thomas Monjalon
  2015-07-14 14:50 ` Zhang, Helin
  1 sibling, 1 reply; 15+ messages in thread
From: Jayakumar, Muthurajan @ 2015-07-14  8:20 UTC (permalink / raw)
  To: Wu, Jingjing, dev

Can you please share as what is the benefit of removing l3fwd-vf example?
Customers have been using this very much.
Please let me know what is the disadvantage of keeping l3fwd-vf.

Thanks 
M Jay
http://dpdk.readthedocs.org/en/latest/

-----Original Message-----
From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Jingjing Wu
Sent: Tuesday, July 14, 2015 12:57 AM
To: dev@dpdk.org
Subject: [dpdk-dev] [RFC] examples: remove l3fwd-vf example

Because VF multi-queues can be supported, l3fwd can run on vf.
Suggest to remove the l3fwd-vf example.

Signed-off-by: jingjing.wu <jingjing.wu@intel.com>
---
 doc/guides/sample_app_ug/index.rst              |    1 -
 doc/guides/sample_app_ug/l3_forward_virtual.rst |  158 ----
 examples/l3fwd-vf/Makefile                      |   56 --
 examples/l3fwd-vf/main.c                        | 1092 -----------------------
 4 files changed, 1307 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

diff --git a/doc/guides/sample_app_ug/index.rst b/doc/guides/sample_app_ug/index.rst
index e1a0c56..bcccb41 100644
--- a/doc/guides/sample_app_ug/index.rst
+++ b/doc/guides/sample_app_ug/index.rst
@@ -54,7 +54,6 @@ Sample Applications User Guide
     l3_forward
     l3_forward_power_man
     l3_forward_access_ctrl
-    l3_forward_virtual
     link_status_intr
     load_balancer
     multi_process
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 f40643a..0000000
--- a/doc/guides/sample_app_ug/l3_forward_virtual.rst
+++ /dev/null
@@ -1,158 +0,0 @@
-..  BSD LICENSE
-    Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions
-    are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in
-    the documentation and/or other materials provided with the
-    distribution.
-    * Neither the name of Intel Corporation nor the names of its
-    contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-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 L3 forwarding application -(see Chapter 10 "L3 Forwarding Sample Application" for more information).
-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 Section 9.1.1 "Virtual Function Setup Instructions" for virtualized test case setup.
-
-Compiling the Application
--------------------------
-
-To compile the application:
-
-#.  Go to the sample application directory:
-
-    .. code-block:: console
-
-        export RTE_SDK=/path/to/rte_sdk
-        cd ${RTE_SDK}/examples/l3fwd-vf
-
-#.  Set the target (a default target is used if not specified). For example:
-
-    .. code-block:: console
-
-        export RTE_TARGET=x86_64-native-linuxapp-gcc
-
-    See the *DPDK Getting Started Guide* for possible RTE_TARGET values.
-
-#.  Build the application:
-
-    .. code-block:: console
-
-        make
-
-.. note::
-
-    The compiled application is written to the build subdirectory.
-    To have the application written to a different location,
-    the O=/path/to/build/directory option may be specified in the make command.
-
-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 where cores 0,2,4,6, 8, and 10 appear on socket 0, -while cores 1,3,5,7,9, and 11 appear on socket 1.
-Let's say that the programmer wants to use memory from both NUMA nodes, -the platform has only two ports and the programmer wants to use one core from each processor socket to do the packet processing -since only one Rx/Tx queue pair can be used in virtualization mode.
-
-To enable L3 forwarding between two ports, using one core from each processor, -while also taking advantage of local memory accesses by optimizing around NUMA, -the programmer can pin to the appropriate cores and allocate memory from the appropriate NUMA node.
-This is achieved using the following command:
-
-.. code-block:: console
-
-   ./build/l3fwd-vf -c 0x03 -n 3 -- -p 0x3 --config="(0,0,0),(1,0,1)"
-
-In this command:
-
-*   The -c option enables cores 0 and 1
-
-*   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.
-    Logic to enable multiple RX queues using RSS and to allocate memory from the correct NUMA nodes
-    is included in the application and is done transparently.
-    The following table shows the mapping in this example:
-
-    +----------+-----------+-----------+------------------------------------+
-    | **Port** | **Queue** | **lcore** | **Description**                    |
-    |          |           |           |                                    |
-    +==========+===========+===========+====================================+
-    | 0        | 0         | 0         | Map queue 0 from port 0 to lcore 0 |
-    |          |           |           |                                    |
-    +----------+-----------+-----------+------------------------------------+
-    | 1        | 1         | 1         | Map queue 0 from port 1 to lcore 1 |
-    |          |           |           |                                    |
-    +----------+-----------+-----------+------------------------------------+
-
-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 Section 10.4 "Explanation" for more information.
diff --git a/examples/l3fwd-vf/Makefile b/examples/l3fwd-vf/Makefile deleted file mode 100644 index d97611c..0000000
--- a/examples/l3fwd-vf/Makefile
+++ /dev/null
@@ -1,56 +0,0 @@
-#   BSD LICENSE
-#
-#   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
-#   All rights reserved.
-#
-#   Redistribution and use in source and binary forms, with or without
-#   modification, are permitted provided that the following conditions
-#   are met:
-#
-#     * Redistributions of source code must retain the above copyright
-#       notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above copyright
-#       notice, this list of conditions and the following disclaimer in
-#       the documentation and/or other materials provided with the
-#       distribution.
-#     * Neither the name of Intel Corporation nor the names of its
-#       contributors may be used to endorse or promote products derived
-#       from this software without specific prior written permission.
-#
-#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-ifeq ($(RTE_SDK),)
-$(error "Please define RTE_SDK environment variable") -endif
-
-# Default target, can be overriden by command line or environment -RTE_TARGET ?= x86_64-native-linuxapp-gcc
-
-include $(RTE_SDK)/mk/rte.vars.mk
-
-# binary name
-APP = l3fwd-vf
-
-# all source are stored in SRCS-y
-SRCS-y := main.c
-
-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
diff --git a/examples/l3fwd-vf/main.c b/examples/l3fwd-vf/main.c deleted file mode 100644 index ccbb02f..0000000
--- a/examples/l3fwd-vf/main.c
+++ /dev/null
@@ -1,1092 +0,0 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
- *   All rights reserved.
- *
- *   Redistribution and use in source and binary forms, with or without
- *   modification, are permitted provided that the following conditions
- *   are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in
- *       the documentation and/or other materials provided with the
- *       distribution.
- *     * Neither the name of Intel Corporation nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/types.h>
-#include <string.h>
-#include <sys/queue.h>
-#include <stdarg.h>
-#include <errno.h>
-#include <getopt.h>
-#include <signal.h>
-
-#include <rte_common.h>
-#include <rte_byteorder.h>
-#include <rte_log.h>
-#include <rte_memory.h>
-#include <rte_memcpy.h>
-#include <rte_memzone.h>
-#include <rte_eal.h>
-#include <rte_per_lcore.h>
-#include <rte_launch.h>
-#include <rte_atomic.h>
-#include <rte_spinlock.h>
-#include <rte_cycles.h>
-#include <rte_prefetch.h>
-#include <rte_lcore.h>
-#include <rte_per_lcore.h>
-#include <rte_branch_prediction.h>
-#include <rte_interrupts.h>
-#include <rte_pci.h>
-#include <rte_random.h>
-#include <rte_debug.h>
-#include <rte_ether.h>
-#include <rte_ethdev.h>
-#include <rte_ring.h>
-#include <rte_mempool.h>
-#include <rte_mbuf.h>
-#include <rte_ip.h>
-#include <rte_tcp.h>
-#include <rte_udp.h>
-#include <rte_string_fns.h>
-
-#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 <rte_hash.h> -#elif (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) -#include <rte_lpm.h> -#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*RTE_TEST_RX_DESC_DEFAULT +							\
-				nb_ports*nb_lcores*MAX_PKT_BURST +											\
-				nb_ports*n_tx_queue*RTE_TEST_TX_DESC_DEFAULT +								\
-				nb_lcores*MEMPOOL_CACHE_SIZE),												\
-				(unsigned)8192)
-
-/*
- * 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.
- */
-#define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. */ -#define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */ -#define RX_WTHRESH 4 /**< Default values of RX write-back threshold reg. */
-
-/*
- * 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.
- */
-#define TX_PTHRESH 36 /**< Default values of TX prefetch threshold reg. */ -#define TX_HTHRESH 0  /**< Default values of TX host threshold reg. */ -#define TX_WTHRESH 0  /**< Default values of TX write-back threshold reg. */
-
-#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 128
-#define RTE_TEST_TX_DESC_DEFAULT 512
-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 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 {
-	uint8_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 {
-	uint8_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 = ETHER_MAX_LEN,
-		.split_hdr_size = 0,
-		.header_split   = 0, /**< Header Split disabled */
-		.hw_ip_checksum = 1, /**< IP checksum offload enabled */
-		.hw_vlan_filter = 0, /**< VLAN filtering disabled */
-		.jumbo_frame    = 0, /**< Jumbo Frame Support disabled */
-		.hw_strip_crc   = 0, /**< CRC stripped by hardware */
-	},
-	.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_MACHINE_CPUFLAG_SSE4_2
-#include <rte_hash_crc.h>
-#define DEFAULT_HASH_FUNC       rte_hash_crc
-#else
-#include <rte_jhash.h>
-#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[] = {
-	{{IPv4(100,10,0,1), IPv4(200,10,0,1), 101, 11, IPPROTO_TCP}, 0},
-	{{IPv4(100,20,0,2), IPv4(200,20,0,2), 102, 12, IPPROTO_TCP}, 1},
-	{{IPv4(100,30,0,3), IPv4(200,30,0,3), 103, 13, IPPROTO_TCP}, 2},
-	{{IPv4(100,40,0,4), 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,
-	.bucket_entries = 4,
-	.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[] = {
-	{IPv4(1,1,1,0), 24, 0},
-	{IPv4(2,1,1,0), 24, 1},
-	{IPv4(3,1,1,0), 24, 2},
-	{IPv4(4,1,1,0), 24, 3},
-	{IPv4(5,1,1,0), 24, 4},
-	{IPv4(6,1,1,0), 24, 5},
-	{IPv4(7,1,1,0), 24, 6},
-	{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, uint8_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, uint8_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 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 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 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 uint8_t
-get_dst_port(struct ipv4_hdr *ipv4_hdr,  uint8_t portid, lookup_struct_t * l3fwd_lookup_struct) -{
-	struct ipv4_5tuple key;
-	struct tcp_hdr *tcp;
-	struct 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 tcp_hdr *)((unsigned char *) ipv4_hdr +
-					sizeof(struct 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 udp_hdr *)((unsigned char *) ipv4_hdr +
-					sizeof(struct 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 (uint8_t)((ret < 0)? portid : l3fwd_out_if[ret]);
-}
-#endif
-
-#if (APP_LOOKUP_METHOD == APP_LOOKUP_LPM) -static inline uint8_t -get_dst_port(struct ipv4_hdr *ipv4_hdr,  uint8_t portid, lookup_struct_t * l3fwd_lookup_struct) -{
-	uint8_t next_hop;
-
-	return (uint8_t) ((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, uint8_t portid, lookup_struct_t * l3fwd_lookup_struct) -{
-	struct ether_hdr *eth_hdr;
-	struct ipv4_hdr *ipv4_hdr;
-	void *tmp;
-	uint8_t dst_port;
-
-	eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);
-
-	ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct ipv4_hdr *,
-					   sizeof(struct 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 = &eth_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 */
-	ether_addr_copy(&ports_eth_addr[dst_port], &eth_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 portid, queueid;
-	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=%hhu 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(const unsigned nb_ports) -{
-	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 (portid >= nb_ports) {
-			printf("port %u is not present on the board\n", portid);
-			return -1;
-		}
-	}
-	return 0;
-}
-
-static uint8_t
-get_port_n_rx_queues(const uint8_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) -{
-	uint8_t portid;
-	uint8_t nb_ports = rte_eth_dev_count();
-
-	/* When we receive a SIGINT signal */
-	if (signum == SIGINT) {
-		for (portid = 0; portid < nb_ports; 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 = (uint8_t)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 = 0; /* reset getopt lib */
-	return ret;
-}
-
-static void
-print_ethaddr(const char *name, const struct ether_addr *eth_addr) -{
-	char buf[ETHER_ADDR_FMT_SIZE];
-	ether_format_addr(buf, 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];
-
-	/* create the LPM table */
-	snprintf(s, sizeof(s), "L3FWD_LPM_%d", socketid);
-	l3fwd_lookup_struct[socketid] = rte_lpm_create(s, socketid,
-				L3FWD_LPM_MAX_RULES, 0);
-	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;
-	unsigned lcore_id;
-	uint32_t nb_lcores;
-	uint16_t n_tx_queue;
-	uint8_t portid, 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();
-	if (nb_ports > RTE_MAX_ETHPORTS)
-		nb_ports = RTE_MAX_ETHPORTS;
-
-	if (check_port_config(nb_ports) < 0)
-		rte_exit(EXIT_FAILURE, "check_port_config failed\n");
-
-	nb_lcores = rte_lcore_count();
-
-	/* initialize all ports */
-	for (portid = 0; portid < nb_ports; portid++) {
-		/* 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 );
-		ret = rte_eth_dev_configure(portid, nb_rx_queue, n_tx_queue, &port_conf);
-		if (ret < 0)
-			rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%d\n",
-				ret, portid);
-
-		rte_eth_macaddr_get(portid, &ports_eth_addr[portid]);
-		print_ethaddr(" Address:", &ports_eth_addr[portid]);
-		printf(", ");
-
-		ret = init_mem(NB_MBUF);
-		if (ret < 0)
-			rte_exit(EXIT_FAILURE, "init_mem failed\n");
-
-		/* init one TX queue */
-		socketid = (uint8_t)rte_lcore_to_socket_id(rte_get_master_lcore());
-
-		printf("txq=%d,%d,%d ", portid, 0, socketid);
-		fflush(stdout);
-
-		rte_eth_dev_info_get(portid, &dev_info);
-		txconf = &dev_info.default_txconf;
-		if (port_conf.rxmode.jumbo_frame)
-			txconf->txq_flags = 0;
-		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++) {
-		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);
-
-			ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd,
-						socketid, NULL,
-						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 */
-	for (portid = 0; portid < nb_ports; 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;
-}
--
2.4.0

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [dpdk-dev] [RFC] examples: remove l3fwd-vf example
  2015-07-14  8:20 ` Jayakumar, Muthurajan
@ 2015-07-14  8:28   ` Thomas Monjalon
  2015-07-15  0:54     ` Wu, Jingjing
  0 siblings, 1 reply; 15+ messages in thread
From: Thomas Monjalon @ 2015-07-14  8:28 UTC (permalink / raw)
  To: Jayakumar, Muthurajan; +Cc: dev

2015-07-14 08:20, Jayakumar, Muthurajan:
> Can you please share as what is the benefit of removing l3fwd-vf example?
> Customers have been using this very much.
> Please let me know what is the disadvantage of keeping l3fwd-vf.

What is the benefit of keeping an example which can be replaced?

"Because VF multi-queues can be supported, l3fwd can run on vf."

Removing some code is a nice goal from a maintenance point of view.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [dpdk-dev] [RFC] examples: remove l3fwd-vf example
  2015-07-14  7:57 [dpdk-dev] [RFC] examples: remove l3fwd-vf example Jingjing Wu
  2015-07-14  8:20 ` Jayakumar, Muthurajan
@ 2015-07-14 14:50 ` Zhang, Helin
  2015-07-22 10:30   ` Thomas Monjalon
  1 sibling, 1 reply; 15+ messages in thread
From: Zhang, Helin @ 2015-07-14 14:50 UTC (permalink / raw)
  To: Wu, Jingjing, dev



> -----Original Message-----
> From: Wu, Jingjing
> Sent: Tuesday, July 14, 2015 12:57 AM
> To: dev@dpdk.org
> Cc: Wu, Jingjing; Zhang, Helin; Xu, Qian Q
> Subject: [RFC] examples: remove l3fwd-vf example
> 
> Because VF multi-queues can be supported, l3fwd can run on vf.
> Suggest to remove the l3fwd-vf example.
Totally agree with this!
But we need the confirmation from validation guys of that l3fwd works quite well on VF with all NICs (e.g. i350, 82599, x550, xl710, and fm10k).

- Helin

> 
> Signed-off-by: jingjing.wu <jingjing.wu@intel.com>
> ---

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [dpdk-dev] [RFC] examples: remove l3fwd-vf example
  2015-07-14  8:28   ` Thomas Monjalon
@ 2015-07-15  0:54     ` Wu, Jingjing
  0 siblings, 0 replies; 15+ messages in thread
From: Wu, Jingjing @ 2015-07-15  0:54 UTC (permalink / raw)
  To: Thomas Monjalon, Jayakumar, Muthurajan; +Cc: dev



> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Tuesday, July 14, 2015 4:28 PM
> To: Jayakumar, Muthurajan
> Cc: dev@dpdk.org; Wu, Jingjing
> Subject: Re: [dpdk-dev] [RFC] examples: remove l3fwd-vf example
> 
> 2015-07-14 08:20, Jayakumar, Muthurajan:
> > Can you please share as what is the benefit of removing l3fwd-vf example?
> > Customers have been using this very much.
> > Please let me know what is the disadvantage of keeping l3fwd-vf.
> 
> What is the benefit of keeping an example which can be replaced?
> 
> "Because VF multi-queues can be supported, l3fwd can run on vf."
> 
> Removing some code is a nice goal from a maintenance point of view.

Yes, the l3fwd-vf example is almost the same as l3fwd, it is just used when VF can only support one queue.
Because VF multi-queues is supported, l3fwd running on vf is a better choice. 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [dpdk-dev] [RFC] examples: remove l3fwd-vf example
  2015-07-14 14:50 ` Zhang, Helin
@ 2015-07-22 10:30   ` Thomas Monjalon
  2015-07-22 14:51     ` Zhang, Helin
  0 siblings, 1 reply; 15+ messages in thread
From: Thomas Monjalon @ 2015-07-22 10:30 UTC (permalink / raw)
  To: Zhang, Helin; +Cc: dev

2015-07-14 14:50, Zhang, Helin:
> From: Wu, Jingjing
> > Because VF multi-queues can be supported, l3fwd can run on vf.
> > Suggest to remove the l3fwd-vf example.
> Totally agree with this!
> But we need the confirmation from validation guys of that l3fwd works
> quite well on VF with all NICs (e.g. i350, 82599, x550, xl710, and fm10k).

Helin, any new from validation?

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [dpdk-dev] [RFC] examples: remove l3fwd-vf example
  2015-07-22 10:30   ` Thomas Monjalon
@ 2015-07-22 14:51     ` Zhang, Helin
  2015-07-22 15:01       ` Ananyev, Konstantin
                         ` (2 more replies)
  0 siblings, 3 replies; 15+ messages in thread
From: Zhang, Helin @ 2015-07-22 14:51 UTC (permalink / raw)
  To: Thomas Monjalon, Liu, Yong, Cao, Waterman; +Cc: dev

Marvin/Waterman

Could you help to check if l3fwd is good enough for all cases (1g/10/40g, PF and VF, single queue/multiple queue)?
We aim to remove l3fwd-vf to reduce an example application which is not so necessary.
Thank you!

Regards,
Helin

> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Wednesday, July 22, 2015 3:30 AM
> To: Zhang, Helin
> Cc: dev@dpdk.org; Wu, Jingjing
> Subject: Re: [dpdk-dev] [RFC] examples: remove l3fwd-vf example
> 
> 2015-07-14 14:50, Zhang, Helin:
> > From: Wu, Jingjing
> > > Because VF multi-queues can be supported, l3fwd can run on vf.
> > > Suggest to remove the l3fwd-vf example.
> > Totally agree with this!
> > But we need the confirmation from validation guys of that l3fwd works
> > quite well on VF with all NICs (e.g. i350, 82599, x550, xl710, and fm10k).
> 
> Helin, any new from validation?

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [dpdk-dev] [RFC] examples: remove l3fwd-vf example
  2015-07-22 14:51     ` Zhang, Helin
@ 2015-07-22 15:01       ` Ananyev, Konstantin
  2015-08-03 16:54       ` Thomas Monjalon
  2015-08-04 17:06       ` Qiu, Michael
  2 siblings, 0 replies; 15+ messages in thread
From: Ananyev, Konstantin @ 2015-07-22 15:01 UTC (permalink / raw)
  To: Zhang, Helin, Thomas Monjalon, Liu, Yong, Cao, Waterman; +Cc: dev

As I remember, the problem is that inside l3fwd each I/O lcore tries to claim a TX queue on each port in use for itself
(to avoid any synchronisation overhead).
Obviously on some legacy (and virtual) devices this is not possible.
On l3fwd-vf, several lcores share the same TX queue.
(synchronisation is done on port basis right now, i.e. only one tx queue per port is always used). 
Konstantin

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Zhang, Helin
> Sent: Wednesday, July 22, 2015 3:51 PM
> To: Thomas Monjalon; Liu, Yong; Cao, Waterman
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [RFC] examples: remove l3fwd-vf example
> 
> Marvin/Waterman
> 
> Could you help to check if l3fwd is good enough for all cases (1g/10/40g, PF and VF, single queue/multiple queue)?
> We aim to remove l3fwd-vf to reduce an example application which is not so necessary.
> Thank you!
> 
> Regards,
> Helin
> 
> > -----Original Message-----
> > From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> > Sent: Wednesday, July 22, 2015 3:30 AM
> > To: Zhang, Helin
> > Cc: dev@dpdk.org; Wu, Jingjing
> > Subject: Re: [dpdk-dev] [RFC] examples: remove l3fwd-vf example
> >
> > 2015-07-14 14:50, Zhang, Helin:
> > > From: Wu, Jingjing
> > > > Because VF multi-queues can be supported, l3fwd can run on vf.
> > > > Suggest to remove the l3fwd-vf example.
> > > Totally agree with this!
> > > But we need the confirmation from validation guys of that l3fwd works
> > > quite well on VF with all NICs (e.g. i350, 82599, x550, xl710, and fm10k).
> >
> > Helin, any new from validation?

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [dpdk-dev] [RFC] examples: remove l3fwd-vf example
  2015-07-22 14:51     ` Zhang, Helin
  2015-07-22 15:01       ` Ananyev, Konstantin
@ 2015-08-03 16:54       ` Thomas Monjalon
  2015-08-03 17:02         ` Zhang, Helin
  2015-08-04 17:06       ` Qiu, Michael
  2 siblings, 1 reply; 15+ messages in thread
From: Thomas Monjalon @ 2015-08-03 16:54 UTC (permalink / raw)
  To: Zhang, Helin; +Cc: dev

Any news?
Can we remove it from version 2.1?

2015-07-22 14:51, Zhang, Helin:
> Marvin/Waterman
> 
> Could you help to check if l3fwd is good enough for all cases (1g/10/40g, PF and VF, single queue/multiple queue)?
> We aim to remove l3fwd-vf to reduce an example application which is not so necessary.
> Thank you!
> 
> Regards,
> Helin
> 
> > -----Original Message-----
> > From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> > Sent: Wednesday, July 22, 2015 3:30 AM
> > To: Zhang, Helin
> > Cc: dev@dpdk.org; Wu, Jingjing
> > Subject: Re: [dpdk-dev] [RFC] examples: remove l3fwd-vf example
> > 
> > 2015-07-14 14:50, Zhang, Helin:
> > > From: Wu, Jingjing
> > > > Because VF multi-queues can be supported, l3fwd can run on vf.
> > > > Suggest to remove the l3fwd-vf example.
> > > Totally agree with this!
> > > But we need the confirmation from validation guys of that l3fwd works
> > > quite well on VF with all NICs (e.g. i350, 82599, x550, xl710, and fm10k).
> > 
> > Helin, any new from validation?

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [dpdk-dev] [RFC] examples: remove l3fwd-vf example
  2015-08-03 16:54       ` Thomas Monjalon
@ 2015-08-03 17:02         ` Zhang, Helin
  2015-08-03 17:08           ` Thomas Monjalon
  0 siblings, 1 reply; 15+ messages in thread
From: Zhang, Helin @ 2015-08-03 17:02 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev

I don't think so, as l3fwd cannot support all cases quite well at this moment.
Can we targeting to do that in R2.2?

Regards,
Helin

> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Monday, August 3, 2015 9:55 AM
> To: Zhang, Helin
> Cc: Liu, Yong; Cao, Waterman; dev@dpdk.org; Wu, Jingjing
> Subject: Re: [dpdk-dev] [RFC] examples: remove l3fwd-vf example
> 
> Any news?
> Can we remove it from version 2.1?
> 
> 2015-07-22 14:51, Zhang, Helin:
> > Marvin/Waterman
> >
> > Could you help to check if l3fwd is good enough for all cases (1g/10/40g, PF and
> VF, single queue/multiple queue)?
> > We aim to remove l3fwd-vf to reduce an example application which is not so
> necessary.
> > Thank you!
> >
> > Regards,
> > Helin
> >
> > > -----Original Message-----
> > > From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> > > Sent: Wednesday, July 22, 2015 3:30 AM
> > > To: Zhang, Helin
> > > Cc: dev@dpdk.org; Wu, Jingjing
> > > Subject: Re: [dpdk-dev] [RFC] examples: remove l3fwd-vf example
> > >
> > > 2015-07-14 14:50, Zhang, Helin:
> > > > From: Wu, Jingjing
> > > > > Because VF multi-queues can be supported, l3fwd can run on vf.
> > > > > Suggest to remove the l3fwd-vf example.
> > > > Totally agree with this!
> > > > But we need the confirmation from validation guys of that l3fwd
> > > > works quite well on VF with all NICs (e.g. i350, 82599, x550, xl710, and
> fm10k).
> > >
> > > Helin, any new from validation?
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [dpdk-dev] [RFC] examples: remove l3fwd-vf example
  2015-08-03 17:02         ` Zhang, Helin
@ 2015-08-03 17:08           ` Thomas Monjalon
  0 siblings, 0 replies; 15+ messages in thread
From: Thomas Monjalon @ 2015-08-03 17:08 UTC (permalink / raw)
  To: Zhang, Helin; +Cc: dev

2015-08-03 17:02, Zhang, Helin:
> I don't think so, as l3fwd cannot support all cases quite well at this moment.
> Can we targeting to do that in R2.2?

OK, thanks

> > -----Original Message-----
> > From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> > Sent: Monday, August 3, 2015 9:55 AM
> > To: Zhang, Helin
> > Cc: Liu, Yong; Cao, Waterman; dev@dpdk.org; Wu, Jingjing
> > Subject: Re: [dpdk-dev] [RFC] examples: remove l3fwd-vf example
> > 
> > Any news?
> > Can we remove it from version 2.1?
> > 
> > 2015-07-22 14:51, Zhang, Helin:
> > > Marvin/Waterman
> > >
> > > Could you help to check if l3fwd is good enough for all cases (1g/10/40g, PF and
> > VF, single queue/multiple queue)?
> > > We aim to remove l3fwd-vf to reduce an example application which is not so
> > necessary.
> > > Thank you!
> > >
> > > Regards,
> > > Helin

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [dpdk-dev] [RFC] examples: remove l3fwd-vf example
  2015-07-22 14:51     ` Zhang, Helin
  2015-07-22 15:01       ` Ananyev, Konstantin
  2015-08-03 16:54       ` Thomas Monjalon
@ 2015-08-04 17:06       ` Qiu, Michael
  2015-08-04 17:12         ` Ananyev, Konstantin
  2 siblings, 1 reply; 15+ messages in thread
From: Qiu, Michael @ 2015-08-04 17:06 UTC (permalink / raw)
  To: Zhang, Helin, Thomas Monjalon, Liu, Yong, Cao, Waterman; +Cc: dev

Actually, l3fwd works fine with fm10k vf.

I don't know what's the exact reason of l3fwd-vf still in DPDK, at least we could make full support for vf in l3fwd instead of another sample with most code are the same compare with l3fwd.

Thanks,
Michael

On 2015/7/22 7:51, Zhang, Helin wrote:

Marvin/Waterman

Could you help to check if l3fwd is good enough for all cases (1g/10/40g, PF and VF, single queue/multiple queue)?
We aim to remove l3fwd-vf to reduce an example application which is not so necessary.
Thank you!

Regards,
Helin



-----Original Message-----
From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
Sent: Wednesday, July 22, 2015 3:30 AM
To: Zhang, Helin
Cc: dev@dpdk.org<mailto:dev@dpdk.org>; Wu, Jingjing
Subject: Re: [dpdk-dev] [RFC] examples: remove l3fwd-vf example

2015-07-14 14:50, Zhang, Helin:


From: Wu, Jingjing


Because VF multi-queues can be supported, l3fwd can run on vf.
Suggest to remove the l3fwd-vf example.


Totally agree with this!
But we need the confirmation from validation guys of that l3fwd works
quite well on VF with all NICs (e.g. i350, 82599, x550, xl710, and fm10k).



Helin, any new from validation?

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [dpdk-dev] [RFC] examples: remove l3fwd-vf example
  2015-08-04 17:06       ` Qiu, Michael
@ 2015-08-04 17:12         ` Ananyev, Konstantin
  2016-04-20 10:46           ` Thomas Monjalon
  0 siblings, 1 reply; 15+ messages in thread
From: Ananyev, Konstantin @ 2015-08-04 17:12 UTC (permalink / raw)
  To: Qiu, Michael, Zhang, Helin, Thomas Monjalon, Liu, Yong, Cao, Waterman; +Cc: dev



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Qiu, Michael
> Sent: Tuesday, August 04, 2015 6:06 PM
> To: Zhang, Helin; Thomas Monjalon; Liu, Yong; Cao, Waterman
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [RFC] examples: remove l3fwd-vf example
> 
> Actually, l3fwd works fine with fm10k vf.
> 
> I don't know what's the exact reason of l3fwd-vf still in DPDK, at least we could make full support for vf in l3fwd instead of another
> sample with most code are the same compare with l3fwd.

Right now, l3fwd is not able to work properly for cases where number of forwarding  lcores 
exceeds number of tx queues on any active port.
As an example: 
2 forwarding lcores and a port with just 1 TX queue (e1000 legacy device).

 To make l3fwd work for such cases you need to add some sort of synchronisation on TX path.
 Which means one of 2 ways:
 either introduce different TX path into l3fwd (one with sync if legacy/virual device is used, another without)
 and select it on process startup/config phase,
 or sync overhead for fastpath.

Konstantin

> 
> Thanks,
> Michael
> 
> On 2015/7/22 7:51, Zhang, Helin wrote:
> 
> Marvin/Waterman
> 
> Could you help to check if l3fwd is good enough for all cases (1g/10/40g, PF and VF, single queue/multiple queue)?
> We aim to remove l3fwd-vf to reduce an example application which is not so necessary.
> Thank you!
> 
> Regards,
> Helin
> 
> 
> 
> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Wednesday, July 22, 2015 3:30 AM
> To: Zhang, Helin
> Cc: dev@dpdk.org<mailto:dev@dpdk.org>; Wu, Jingjing
> Subject: Re: [dpdk-dev] [RFC] examples: remove l3fwd-vf example
> 
> 2015-07-14 14:50, Zhang, Helin:
> 
> 
> From: Wu, Jingjing
> 
> 
> Because VF multi-queues can be supported, l3fwd can run on vf.
> Suggest to remove the l3fwd-vf example.
> 
> 
> Totally agree with this!
> But we need the confirmation from validation guys of that l3fwd works
> quite well on VF with all NICs (e.g. i350, 82599, x550, xl710, and fm10k).
> 
> 
> 
> Helin, any new from validation?
> 
> 
> 
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [dpdk-dev] [RFC] examples: remove l3fwd-vf example
  2015-08-04 17:12         ` Ananyev, Konstantin
@ 2016-04-20 10:46           ` Thomas Monjalon
  2016-04-20 11:16             ` Ananyev, Konstantin
  0 siblings, 1 reply; 15+ messages in thread
From: Thomas Monjalon @ 2016-04-20 10:46 UTC (permalink / raw)
  To: Ananyev, Konstantin
  Cc: Qiu, Michael, Zhang, Helin, Liu, Yong, Cao, Waterman, dev

2015-08-04 17:12, Ananyev, Konstantin:
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Qiu, Michael
> > Actually, l3fwd works fine with fm10k vf.
> > 
> > I don't know what's the exact reason of l3fwd-vf still in DPDK,
> > at least we could make full support for vf in l3fwd instead of another
> > sample with most code are the same compare with l3fwd.
> 
> Right now, l3fwd is not able to work properly for cases where number of forwarding  lcores 
> exceeds number of tx queues on any active port.
> As an example: 
> 2 forwarding lcores and a port with just 1 TX queue (e1000 legacy device).
> 
>  To make l3fwd work for such cases you need to add some sort of synchronisation on TX path.
>  Which means one of 2 ways:
>  either introduce different TX path into l3fwd (one with sync if legacy/virual device is used, another without)
>  and select it on process startup/config phase,
>  or sync overhead for fastpath.

Any news about removing l3fwd-vf example?

l3fwd has been reworked but l3fwd-power, l3fwd-vf and l3fwd-thread are
still based on the old l3fwd with APP_LOOKUP_METHOD compile-time flag.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [dpdk-dev] [RFC] examples: remove l3fwd-vf example
  2016-04-20 10:46           ` Thomas Monjalon
@ 2016-04-20 11:16             ` Ananyev, Konstantin
  0 siblings, 0 replies; 15+ messages in thread
From: Ananyev, Konstantin @ 2016-04-20 11:16 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: Qiu, Michael, Zhang, Helin, Liu, Yong, Cao, Waterman, dev


Hi Thomas,

> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Wednesday, April 20, 2016 11:47 AM
> To: Ananyev, Konstantin
> Cc: Qiu, Michael; Zhang, Helin; Liu, Yong; Cao, Waterman; dev@dpdk.org
> Subject: Re: [dpdk-dev] [RFC] examples: remove l3fwd-vf example
> 
> 2015-08-04 17:12, Ananyev, Konstantin:
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Qiu, Michael
> > > Actually, l3fwd works fine with fm10k vf.
> > >
> > > I don't know what's the exact reason of l3fwd-vf still in DPDK,
> > > at least we could make full support for vf in l3fwd instead of another
> > > sample with most code are the same compare with l3fwd.
> >
> > Right now, l3fwd is not able to work properly for cases where number of forwarding  lcores
> > exceeds number of tx queues on any active port.
> > As an example:
> > 2 forwarding lcores and a port with just 1 TX queue (e1000 legacy device).
> >
> >  To make l3fwd work for such cases you need to add some sort of synchronisation on TX path.
> >  Which means one of 2 ways:
> >  either introduce different TX path into l3fwd (one with sync if legacy/virual device is used, another without)
> >  and select it on process startup/config phase,
> >  or sync overhead for fastpath.
> 
> Any news about removing l3fwd-vf example?
> 
> l3fwd has been reworked but l3fwd-power, l3fwd-vf and l3fwd-thread are
> still based on the old l3fwd with APP_LOOKUP_METHOD compile-time flag.

As far as I know, no-one from Intel side is working on it right now.
Konstantin  

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2016-04-20 11:16 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-14  7:57 [dpdk-dev] [RFC] examples: remove l3fwd-vf example Jingjing Wu
2015-07-14  8:20 ` Jayakumar, Muthurajan
2015-07-14  8:28   ` Thomas Monjalon
2015-07-15  0:54     ` Wu, Jingjing
2015-07-14 14:50 ` Zhang, Helin
2015-07-22 10:30   ` Thomas Monjalon
2015-07-22 14:51     ` Zhang, Helin
2015-07-22 15:01       ` Ananyev, Konstantin
2015-08-03 16:54       ` Thomas Monjalon
2015-08-03 17:02         ` Zhang, Helin
2015-08-03 17:08           ` Thomas Monjalon
2015-08-04 17:06       ` Qiu, Michael
2015-08-04 17:12         ` Ananyev, Konstantin
2016-04-20 10:46           ` Thomas Monjalon
2016-04-20 11:16             ` Ananyev, Konstantin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).