DPDK patches and discussions
 help / color / mirror / Atom feed
* [PATCH] examples/kni: remove deprecated kni example
@ 2022-09-20 15:14 Bruce Richardson
  2022-09-20 15:25 ` Stephen Hemminger
  2022-09-20 15:51 ` [PATCH v2] " Bruce Richardson
  0 siblings, 2 replies; 6+ messages in thread
From: Bruce Richardson @ 2022-09-20 15:14 UTC (permalink / raw)
  To: dev; +Cc: Bruce Richardson

As part of the agreed process for deprecating KNI in DPDK, the example
app is scheduled for removal as part of the 22.11 release.

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
 doc/guides/rel_notes/deprecation.rst          |    1 -
 doc/guides/sample_app_ug/index.rst            |    1 -
 .../sample_app_ug/kernel_nic_interface.rst    |  318 -----
 examples/kni/Makefile                         |   52 -
 examples/kni/main.c                           | 1140 -----------------
 examples/kni/meson.build                      |   13 -
 examples/meson.build                          |    1 -
 7 files changed, 1526 deletions(-)
 delete mode 100644 doc/guides/sample_app_ug/kernel_nic_interface.rst
 delete mode 100644 examples/kni/Makefile
 delete mode 100644 examples/kni/main.c
 delete mode 100644 examples/kni/meson.build

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index c1975d6c3e..2ded2d69d1 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -70,7 +70,6 @@ Deprecation Notices
   and `refinement <http://mails.dpdk.org/archives/dev/2022-June/243596.html>`_:
 
   * Some deprecation warnings will be added in DPDK 22.11.
-  * The KNI example application will be removed from DPDK 22.11.
   * The KNI kernel module, library and PMD will be removed from the DPDK 23.11.
 
 * lib: will fix extending some enum/define breaking the ABI. There are multiple
diff --git a/doc/guides/sample_app_ug/index.rst b/doc/guides/sample_app_ug/index.rst
index cc9fae1e8c..6e1e83d7d7 100644
--- a/doc/guides/sample_app_ug/index.rst
+++ b/doc/guides/sample_app_ug/index.rst
@@ -20,7 +20,6 @@ Sample Applications User Guides
     ip_frag
     ipv4_multicast
     ip_reassembly
-    kernel_nic_interface
     keep_alive
     dma
     l2_forward_crypto
diff --git a/doc/guides/sample_app_ug/kernel_nic_interface.rst b/doc/guides/sample_app_ug/kernel_nic_interface.rst
deleted file mode 100644
index ef441cc1e5..0000000000
--- a/doc/guides/sample_app_ug/kernel_nic_interface.rst
+++ /dev/null
@@ -1,318 +0,0 @@
-..  SPDX-License-Identifier: BSD-3-Clause
-    Copyright(c) 2010-2014 Intel Corporation.
-
-Kernel NIC Interface Sample Application
-=======================================
-
-The Kernel NIC Interface (KNI) is a DPDK control plane solution that
-allows userspace applications to exchange packets with the kernel networking stack.
-To accomplish this, DPDK userspace applications use an IOCTL call
-to request the creation of a KNI virtual device in the Linux* kernel.
-The IOCTL call provides interface information and the DPDK's physical address space,
-which is re-mapped into the kernel address space by the KNI kernel loadable module
-that saves the information to a virtual device context.
-The DPDK creates FIFO queues for packet ingress and egress
-to the kernel module for each device allocated.
-
-The KNI kernel loadable module is a standard net driver,
-which upon receiving the IOCTL call access the DPDK's FIFO queue to
-receive/transmit packets from/to the DPDK userspace application.
-The FIFO queues contain pointers to data packets in the DPDK. This:
-
-*   Provides a faster mechanism to interface with the kernel net stack and eliminates system calls
-
-*   Facilitates the DPDK using standard Linux* userspace net tools (tshark, rsync, and so on)
-
-*   Eliminate the copy_to_user and copy_from_user operations on packets.
-
-The Kernel NIC Interface sample application is a simple example that demonstrates the use
-of the DPDK to create a path for packets to go through the Linux* kernel.
-This is done by creating one or more kernel net devices for each of the DPDK ports.
-The application allows the use of standard Linux tools (ethtool, iproute, tshark) with the DPDK ports and
-also the exchange of packets between the DPDK application and the Linux* kernel.
-
-The Kernel NIC Interface sample application requires that the
-KNI kernel module ``rte_kni`` be loaded into the kernel.  See
-:doc:`../prog_guide/kernel_nic_interface` for more information on loading
-the ``rte_kni`` kernel module.
-
-Overview
---------
-
-The Kernel NIC Interface sample application ``kni`` allocates one or more
-KNI interfaces for each physical NIC port.  For each physical NIC port,
-``kni`` uses two DPDK threads in user space; one thread reads from the port and
-writes to the corresponding KNI interfaces and the other thread reads from
-the KNI interfaces and writes the data unmodified to the physical NIC port.
-
-It is recommended to configure one KNI interface for each physical NIC port.
-The application can be configured with more than one KNI interface for
-each physical NIC port for performance testing or it can work together with
-VMDq support in future.
-
-The packet flow through the Kernel NIC Interface application is as shown
-in the following figure.
-
-.. _figure_kernel_nic:
-
-.. figure:: img/kernel_nic.*
-
-   Kernel NIC Application Packet Flow
-
-If link monitoring is enabled with the ``-m`` command line flag, one
-additional pthread is launched which will check the link status of each
-physical NIC port and will update the carrier status of the corresponding
-KNI interface(s) to match the physical NIC port's state.  This means that
-the KNI interface(s) will be disabled automatically when the Ethernet link
-goes down and enabled when the Ethernet link goes up.
-
-If link monitoring is enabled, the ``rte_kni`` kernel module should be loaded
-such that the :ref:`default carrier state <kni_default_carrier_state>` is
-set to *off*.  This ensures that the KNI interface is only enabled *after*
-the Ethernet link of the corresponding NIC port has reached the linkup state.
-
-If link monitoring is not enabled, the ``rte_kni`` kernel module should be
-loaded with the :ref:`default carrier state <kni_default_carrier_state>`
-set to *on*.  This sets the carrier state of the KNI interfaces to *on*
-when the KNI interfaces are enabled without regard to the actual link state
-of the corresponding NIC port.  This is useful for testing in loopback
-mode where the NIC port may not be physically connected to anything.
-
-Compiling the Application
--------------------------
-
-To compile the sample application see :doc:`compiling`.
-
-The application is located in the ``examples/kni`` sub-directory.
-
-.. note::
-
-        This application is intended as a linux only.
-
-Running the kni Example Application
------------------------------------
-
-The ``kni`` example application requires a number of command line options:
-
-.. code-block:: console
-
-    dpdk-kni [EAL options] -- -p PORTMASK --config="(port,lcore_rx,lcore_tx[,lcore_kthread,...])[,(port,lcore_rx,lcore_tx[,lcore_kthread,...])]" [-P] [-m]
-
-Where:
-
-*   ``-p PORTMASK``:
-
-    Hexadecimal bitmask of ports to configure.
-
-*   ``--config="(port,lcore_rx,lcore_tx[,lcore_kthread,...])[,(port,lcore_rx,lcore_tx[,lcore_kthread,...])]"``:
-
-    Determines which lcores the Rx and Tx DPDK tasks, and (optionally)
-    the KNI kernel thread(s) are bound to for each physical port.
-
-*   ``-P``:
-
-    Optional flag to set all ports to promiscuous mode so that packets are
-    accepted regardless of the packet's Ethernet MAC destination address.
-    Without this option, only packets with the Ethernet MAC destination
-    address set to the Ethernet address of the port are accepted.
-
-*   ``-m``:
-
-    Optional flag to enable monitoring and updating of the Ethernet
-    carrier state.  With this option set, a thread will be started which
-    will periodically check the Ethernet link status of the physical
-    Ethernet ports and set the carrier state of the corresponding KNI
-    network interface to match it.  This means that the KNI interface will
-    be disabled automatically when the Ethernet link goes down and enabled
-    when the Ethernet link goes up.
-
-Refer to *DPDK Getting Started Guide* for general information on running
-applications and the Environment Abstraction Layer (EAL) options.
-
-The ``-c coremask`` or ``-l corelist`` parameter of the EAL options must
-include the lcores specified by ``lcore_rx`` and ``lcore_tx`` for each port,
-but does not need to include lcores specified by ``lcore_kthread`` as those
-cores are used to pin the kernel threads in the ``rte_kni`` kernel module.
-
-The ``--config`` parameter must include a set of
-``(port,lcore_rx,lcore_tx,[lcore_kthread,...])`` values for each physical
-port specified in the ``-p PORTMASK`` parameter.
-
-The optional ``lcore_kthread`` lcore ID parameter in ``--config`` can be
-specified zero, one or more times for each physical port.
-
-If no lcore ID is specified for ``lcore_kthread``, one KNI interface will
-be created for the physical port ``port`` and the KNI kernel thread(s)
-will have no specific core affinity.
-
-If one or more lcore IDs are specified for ``lcore_kthread``, a KNI interface
-will be created for each lcore ID specified, bound to the physical port
-``port``.  If the ``rte_kni`` kernel module is loaded in :ref:`multiple
-kernel thread <kni_kernel_thread_mode>` mode, a kernel thread will be created
-for each KNI interface and bound to the specified core.  If the ``rte_kni``
-kernel module is loaded in :ref:`single kernel thread <kni_kernel_thread_mode>`
-mode, only one kernel thread is started for all KNI interfaces.  The kernel
-thread will be bound to the first ``lcore_kthread`` lcore ID specified.
-
-Example Configurations
-~~~~~~~~~~~~~~~~~~~~~~~
-
-The following commands will first load the ``rte_kni`` kernel module in
-:ref:`multiple kernel thread <kni_kernel_thread_mode>` mode.  The ``kni``
-application is then started using two ports;  Port 0 uses lcore 4 for the
-Rx task, lcore 6 for the Tx task, and will create a single KNI interface
-``vEth0_0`` with the kernel thread bound to lcore 8.  Port 1 uses lcore
-5 for the Rx task, lcore 7 for the Tx task, and will create a single KNI
-interface ``vEth1_0`` with the kernel thread bound to lcore 9.
-
-.. code-block:: console
-
-    # rmmod rte_kni
-    # insmod <build_dir>/kernel/linux/kni/rte_kni.ko kthread_mode=multiple
-    # ./<build-dir>/examples/dpdk-kni -l 4-7 -n 4 -- -P -p 0x3 -m --config="(0,4,6,8),(1,5,7,9)"
-
-The following example is identical, except an additional ``lcore_kthread``
-core is specified per physical port.  In this case, ``kni`` will create
-four KNI interfaces: ``vEth0_0``/``vEth0_1`` bound to physical port 0 and
-``vEth1_0``/``vEth1_1`` bound to physical port 1.
-
-The kernel thread for each interface will be bound as follows:
-
-    * ``vEth0_0`` - bound to lcore 8.
-    * ``vEth0_1`` - bound to lcore 10.
-    * ``vEth1_0`` - bound to lcore 9.
-    * ``vEth1_1`` - bound to lcore 11
-
-.. code-block:: console
-
-    # rmmod rte_kni
-    # insmod <build_dir>/kernel/linux/kni/rte_kni.ko kthread_mode=multiple
-    # ./<build-dir>/examples/dpdk-kni -l 4-7 -n 4 -- -P -p 0x3 -m --config="(0,4,6,8,10),(1,5,7,9,11)"
-
-The following example can be used to test the interface between the ``kni``
-test application and the ``rte_kni`` kernel module.  In this example,
-the ``rte_kni`` kernel module is loaded in :ref:`single kernel thread
-mode <kni_kernel_thread_mode>`, :ref:`loopback mode <kni_loopback_mode>`
-enabled, and the :ref:`default carrier state <kni_default_carrier_state>`
-is set to *on* so that the corresponding physical NIC port does not have
-to be connected in order to use the KNI interface.  One KNI interface
-``vEth0_0`` is created for port 0 and one KNI interface ``vEth1_0`` is
-created for port 1.  Since ``rte_kni`` is loaded in "single kernel thread"
-mode, the one kernel thread is bound to lcore 8.
-
-Since the physical NIC ports are not being used, link monitoring can be
-disabled by **not** specifying the ``-m`` flag to ``kni``:
-
-.. code-block:: console
-
-    # rmmod rte_kni
-    # insmod <build_dir>/kernel/linux/kni/rte_kni.ko lo_mode=lo_mode_fifo carrier=on
-    # ./<build-dir>/examples/dpdk-kni -l 4-7 -n 4 -- -P -p 0x3 --config="(0,4,6,8),(1,5,7,9)"
-
-KNI Operations
---------------
-
-Once the ``kni`` application is started, the user can use the normal
-Linux commands to manage the KNI interfaces as if they were any other
-Linux network interface.
-
-Enable KNI interface and assign an IP address:
-
-.. code-block:: console
-
-    # ip addr add dev vEth0_0 192.168.0.1
-
-Show KNI interface configuration and statistics:
-
-.. code-block:: console
-
-    # ip -s -d addr show vEth0_0
-
-The user can also check and reset the packet statistics inside the ``kni``
-application by sending the app the USR1 and USR2 signals:
-
-.. code-block:: console
-
-    # Print statistics
-    # pkill -USR1 kni
-
-    # Zero statistics
-    # pkill -USR2 kni
-
-Dump network traffic:
-
-.. code-block:: console
-
-    # tshark -n -i vEth0_0
-
-The normal Linux commands can also be used to change the MAC address and
-MTU size used by the physical NIC which corresponds to the KNI interface.
-However, if more than one KNI interface is configured for a physical port,
-these commands will only work on the first KNI interface for that port.
-
-Change the MAC address:
-
-.. code-block:: console
-
-    # ip link set dev vEth0_0 lladdr 0C:01:02:03:04:08
-
-Change the MTU size:
-
-.. code-block:: console
-
-    # ip link set dev vEth0_0 mtu 1450
-
-Limited ethtool support:
-
-.. code-block:: console
-
-    # ethtool -i vEth0_0
-
-When the ``kni`` application is closed, all the KNI interfaces are deleted
-from the Linux kernel.
-
-Explanation
------------
-
-The following sections provide some explanation of code.
-
-Initialization
-~~~~~~~~~~~~~~
-
-Setup of mbuf pool, driver and queues is similar to the setup done in the :doc:`l2_forward_real_virtual`..
-In addition, one or more kernel NIC interfaces are allocated for each
-of the configured ports according to the command line parameters.
-
-The code for allocating the kernel NIC interfaces for a specific port is
-in the function ``kni_alloc``.
-
-The other step in the initialization process that is unique to this sample application
-is the association of each port with lcores for RX, TX and kernel threads.
-
-*   One lcore to read from the port and write to the associated one or more KNI devices
-
-*   Another lcore to read from one or more KNI devices and write to the port
-
-*   Other lcores for pinning the kernel threads on one by one
-
-This is done by using the ``kni_port_params_array[]`` array, which is indexed by the port ID.
-The code is in the function ``parse_config``.
-
-Packet Forwarding
-~~~~~~~~~~~~~~~~~
-
-After the initialization steps are completed, the main_loop() function is run on each lcore.
-This function first checks the lcore_id against the user provided lcore_rx and lcore_tx
-to see if this lcore is reading from or writing to kernel NIC interfaces.
-
-For the case that reads from a NIC port and writes to the kernel NIC interfaces (``kni_ingress``),
-the packet reception is the same as in L2 Forwarding sample application
-(see :ref:`l2_fwd_app_rx_tx_packets`).
-The packet transmission is done by sending mbufs into the kernel NIC interfaces by ``rte_kni_tx_burst()``.
-The KNI library automatically frees the mbufs after the kernel successfully copied the mbufs.
-
-For the other case that reads from kernel NIC interfaces
-and writes to a physical NIC port (``kni_egress``),
-packets are retrieved by reading mbufs from kernel NIC interfaces by ``rte_kni_rx_burst()``.
-The packet transmission is the same as in the L2 Forwarding sample application
-(see :ref:`l2_fwd_app_rx_tx_packets`).
diff --git a/examples/kni/Makefile b/examples/kni/Makefile
deleted file mode 100644
index 753cb96f5f..0000000000
--- a/examples/kni/Makefile
+++ /dev/null
@@ -1,52 +0,0 @@
-# SPDX-License-Identifier: BSD-3-Clause
-# Copyright(c) 2010-2014 Intel Corporation
-
-# binary name
-APP = kni
-
-# all source are stored in SRCS-y
-SRCS-y := main.c
-
-PKGCONF ?= pkg-config
-
-# Build using pkg-config variables if possible
-ifneq ($(shell $(PKGCONF) --exists libdpdk && echo 0),0)
-$(error "no installation of DPDK found")
-endif
-
-all: shared
-.PHONY: shared static
-shared: build/$(APP)-shared
-	ln -sf $(APP)-shared build/$(APP)
-static: build/$(APP)-static
-	ln -sf $(APP)-static build/$(APP)
-
-PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
-CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
-CFLAGS += -DALLOW_EXPERIMENTAL_API
-LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
-
-ifeq ($(MAKECMDGOALS),static)
-# check for broken pkg-config
-ifeq ($(shell echo $(LDFLAGS_STATIC) | grep 'whole-archive.*l:lib.*no-whole-archive'),)
-$(warning "pkg-config output list does not contain drivers between 'whole-archive'/'no-whole-archive' flags.")
-$(error "Cannot generate statically-linked binaries with this version of pkg-config")
-endif
-endif
-
-LDFLAGS += -pthread
-
-build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
-	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
-
-build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build
-	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC)
-
-build:
-	@mkdir -p $@
-
-.PHONY: clean
-clean:
-	rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared
-	test -d build && rmdir -p build || true
diff --git a/examples/kni/main.c b/examples/kni/main.c
deleted file mode 100644
index e99ef5c38a..0000000000
--- a/examples/kni/main.c
+++ /dev/null
@@ -1,1140 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2014 Intel Corporation
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <string.h>
-#include <sys/queue.h>
-#include <stdarg.h>
-#include <errno.h>
-#include <getopt.h>
-
-#include <netinet/in.h>
-#include <linux/if.h>
-#include <linux/if_tun.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-#include <signal.h>
-
-#include <rte_common.h>
-#include <rte_log.h>
-#include <rte_memory.h>
-#include <rte_memcpy.h>
-#include <rte_eal.h>
-#include <rte_per_lcore.h>
-#include <rte_launch.h>
-#include <rte_lcore.h>
-#include <rte_branch_prediction.h>
-#include <rte_interrupts.h>
-#include <rte_bus_pci.h>
-#include <rte_debug.h>
-#include <rte_ether.h>
-#include <rte_ethdev.h>
-#include <rte_mempool.h>
-#include <rte_mbuf.h>
-#include <rte_string_fns.h>
-#include <rte_cycles.h>
-#include <rte_malloc.h>
-#include <rte_kni.h>
-
-/* Macros for printing using RTE_LOG */
-#define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1
-
-/* Max size of a single packet */
-#define MAX_PACKET_SZ           2048
-
-/* Size of the data buffer in each mbuf */
-#define MBUF_DATA_SZ (MAX_PACKET_SZ + RTE_PKTMBUF_HEADROOM)
-
-/* Number of mbufs in mempool that is created */
-#define NB_MBUF                 (8192 * 16)
-
-/* How many packets to attempt to read from NIC in one go */
-#define PKT_BURST_SZ            32
-
-/* How many objects (mbufs) to keep in per-lcore mempool cache */
-#define MEMPOOL_CACHE_SZ        PKT_BURST_SZ
-
-/* Number of RX ring descriptors */
-#define NB_RXD                  1024
-
-/* Number of TX ring descriptors */
-#define NB_TXD                  1024
-
-/* Total octets in ethernet header */
-#define KNI_ENET_HEADER_SIZE    14
-
-/* Total octets in the FCS */
-#define KNI_ENET_FCS_SIZE       4
-
-#define KNI_US_PER_SECOND       1000000
-#define KNI_SECOND_PER_DAY      86400
-
-#define KNI_MAX_KTHREAD 32
-/*
- * Structure of port parameters
- */
-struct kni_port_params {
-	uint16_t port_id;/* Port ID */
-	unsigned lcore_rx; /* lcore ID for RX */
-	unsigned lcore_tx; /* lcore ID for TX */
-	uint32_t nb_lcore_k; /* Number of lcores for KNI multi kernel threads */
-	uint32_t nb_kni; /* Number of KNI devices to be created */
-	unsigned lcore_k[KNI_MAX_KTHREAD]; /* lcore ID list for kthreads */
-	struct rte_kni *kni[KNI_MAX_KTHREAD]; /* KNI context pointers */
-} __rte_cache_aligned;
-
-static struct kni_port_params *kni_port_params_array[RTE_MAX_ETHPORTS];
-
-
-/* Options for configuring ethernet port */
-static struct rte_eth_conf port_conf = {
-	.txmode = {
-		.mq_mode = RTE_ETH_MQ_TX_NONE,
-	},
-};
-
-/* Mempool for mbufs */
-static struct rte_mempool * pktmbuf_pool = NULL;
-
-/* Mask of enabled ports */
-static uint32_t ports_mask = 0;
-/* Ports set in promiscuous mode off by default. */
-static int promiscuous_on = 0;
-/* Monitor link status continually. off by default. */
-static int monitor_links;
-
-/* Structure type for recording kni interface specific stats */
-struct kni_interface_stats {
-	/* number of pkts received from NIC, and sent to KNI */
-	uint64_t rx_packets;
-
-	/* number of pkts received from NIC, but failed to send to KNI */
-	uint64_t rx_dropped;
-
-	/* number of pkts received from KNI, and sent to NIC */
-	uint64_t tx_packets;
-
-	/* number of pkts received from KNI, but failed to send to NIC */
-	uint64_t tx_dropped;
-};
-
-/* kni device statistics array */
-static struct kni_interface_stats kni_stats[RTE_MAX_ETHPORTS];
-
-static int kni_change_mtu(uint16_t port_id, unsigned int new_mtu);
-static int kni_config_network_interface(uint16_t port_id, uint8_t if_up);
-static int kni_config_mac_address(uint16_t port_id, uint8_t mac_addr[]);
-
-static uint32_t kni_stop;
-static uint32_t kni_pause;
-
-/* Print out statistics on packets handled */
-static void
-print_stats(void)
-{
-	uint16_t i;
-
-	printf("\n**KNI example application statistics**\n"
-	       "======  ==============  ============  ============  ============  ============\n"
-	       " Port    Lcore(RX/TX)    rx_packets    rx_dropped    tx_packets    tx_dropped\n"
-	       "------  --------------  ------------  ------------  ------------  ------------\n");
-	for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
-		if (!kni_port_params_array[i])
-			continue;
-
-		printf("%7d %10u/%2u %13"PRIu64" %13"PRIu64" %13"PRIu64" "
-							"%13"PRIu64"\n", i,
-					kni_port_params_array[i]->lcore_rx,
-					kni_port_params_array[i]->lcore_tx,
-						kni_stats[i].rx_packets,
-						kni_stats[i].rx_dropped,
-						kni_stats[i].tx_packets,
-						kni_stats[i].tx_dropped);
-	}
-	printf("======  ==============  ============  ============  ============  ============\n");
-
-	fflush(stdout);
-}
-
-/* Custom handling of signals to handle stats and kni processing */
-static void
-signal_handler(int signum)
-{
-	/* When we receive a USR1 signal, print stats */
-	if (signum == SIGUSR1) {
-		print_stats();
-	}
-
-	/* When we receive a USR2 signal, reset stats */
-	if (signum == SIGUSR2) {
-		memset(&kni_stats, 0, sizeof(kni_stats));
-		printf("\n** Statistics have been reset **\n");
-		return;
-	}
-
-	/*
-	 * When we receive a RTMIN or SIGINT or SIGTERM signal,
-	 * stop kni processing
-	 */
-	if (signum == SIGRTMIN || signum == SIGINT || signum == SIGTERM) {
-		printf("\nSIGRTMIN/SIGINT/SIGTERM received. "
-			"KNI processing stopping.\n");
-		__atomic_fetch_add(&kni_stop, 1, __ATOMIC_RELAXED);
-		return;
-        }
-}
-
-static void
-kni_burst_free_mbufs(struct rte_mbuf **pkts, unsigned num)
-{
-	unsigned i;
-
-	if (pkts == NULL)
-		return;
-
-	for (i = 0; i < num; i++) {
-		rte_pktmbuf_free(pkts[i]);
-		pkts[i] = NULL;
-	}
-}
-
-/**
- * Interface to burst rx and enqueue mbufs into rx_q
- */
-static void
-kni_ingress(struct kni_port_params *p)
-{
-	uint8_t i;
-	uint16_t port_id;
-	unsigned nb_rx, num;
-	uint32_t nb_kni;
-	struct rte_mbuf *pkts_burst[PKT_BURST_SZ];
-
-	if (p == NULL)
-		return;
-
-	nb_kni = p->nb_kni;
-	port_id = p->port_id;
-	for (i = 0; i < nb_kni; i++) {
-		/* Burst rx from eth */
-		nb_rx = rte_eth_rx_burst(port_id, 0, pkts_burst, PKT_BURST_SZ);
-		if (unlikely(nb_rx > PKT_BURST_SZ)) {
-			RTE_LOG(ERR, APP, "Error receiving from eth\n");
-			return;
-		}
-		/* Burst tx to kni */
-		num = rte_kni_tx_burst(p->kni[i], pkts_burst, nb_rx);
-		if (num)
-			kni_stats[port_id].rx_packets += num;
-
-		rte_kni_handle_request(p->kni[i]);
-		if (unlikely(num < nb_rx)) {
-			/* Free mbufs not tx to kni interface */
-			kni_burst_free_mbufs(&pkts_burst[num], nb_rx - num);
-			kni_stats[port_id].rx_dropped += nb_rx - num;
-		}
-	}
-}
-
-/**
- * Interface to dequeue mbufs from tx_q and burst tx
- */
-static void
-kni_egress(struct kni_port_params *p)
-{
-	uint8_t i;
-	uint16_t port_id;
-	unsigned nb_tx, num;
-	uint32_t nb_kni;
-	struct rte_mbuf *pkts_burst[PKT_BURST_SZ];
-
-	if (p == NULL)
-		return;
-
-	nb_kni = p->nb_kni;
-	port_id = p->port_id;
-	for (i = 0; i < nb_kni; i++) {
-		/* Burst rx from kni */
-		num = rte_kni_rx_burst(p->kni[i], pkts_burst, PKT_BURST_SZ);
-		if (unlikely(num > PKT_BURST_SZ)) {
-			RTE_LOG(ERR, APP, "Error receiving from KNI\n");
-			return;
-		}
-		/* Burst tx to eth */
-		nb_tx = rte_eth_tx_burst(port_id, 0, pkts_burst, (uint16_t)num);
-		if (nb_tx)
-			kni_stats[port_id].tx_packets += nb_tx;
-		if (unlikely(nb_tx < num)) {
-			/* Free mbufs not tx to NIC */
-			kni_burst_free_mbufs(&pkts_burst[nb_tx], num - nb_tx);
-			kni_stats[port_id].tx_dropped += num - nb_tx;
-		}
-	}
-}
-
-static int
-main_loop(__rte_unused void *arg)
-{
-	uint16_t i;
-	int32_t f_stop;
-	int32_t f_pause;
-	const unsigned lcore_id = rte_lcore_id();
-	enum lcore_rxtx {
-		LCORE_NONE,
-		LCORE_RX,
-		LCORE_TX,
-		LCORE_MAX
-	};
-	enum lcore_rxtx flag = LCORE_NONE;
-
-	RTE_ETH_FOREACH_DEV(i) {
-		if (!kni_port_params_array[i])
-			continue;
-		if (kni_port_params_array[i]->lcore_rx == (uint8_t)lcore_id) {
-			flag = LCORE_RX;
-			break;
-		} else if (kni_port_params_array[i]->lcore_tx ==
-						(uint8_t)lcore_id) {
-			flag = LCORE_TX;
-			break;
-		}
-	}
-
-	if (flag == LCORE_RX) {
-		RTE_LOG(INFO, APP, "Lcore %u is reading from port %d\n",
-					kni_port_params_array[i]->lcore_rx,
-					kni_port_params_array[i]->port_id);
-		while (1) {
-			f_stop = __atomic_load_n(&kni_stop, __ATOMIC_RELAXED);
-			f_pause = __atomic_load_n(&kni_pause, __ATOMIC_RELAXED);
-			if (f_stop)
-				break;
-			if (f_pause)
-				continue;
-			kni_ingress(kni_port_params_array[i]);
-		}
-	} else if (flag == LCORE_TX) {
-		RTE_LOG(INFO, APP, "Lcore %u is writing to port %d\n",
-					kni_port_params_array[i]->lcore_tx,
-					kni_port_params_array[i]->port_id);
-		while (1) {
-			f_stop = __atomic_load_n(&kni_stop, __ATOMIC_RELAXED);
-			f_pause = __atomic_load_n(&kni_pause, __ATOMIC_RELAXED);
-			if (f_stop)
-				break;
-			if (f_pause)
-				continue;
-			kni_egress(kni_port_params_array[i]);
-		}
-	} else
-		RTE_LOG(INFO, APP, "Lcore %u has nothing to do\n", lcore_id);
-
-	return 0;
-}
-
-/* Display usage instructions */
-static void
-print_usage(const char *prgname)
-{
-	RTE_LOG(INFO, APP, "\nUsage: %s [EAL options] -- -p PORTMASK -P -m "
-		   "[--config (port,lcore_rx,lcore_tx,lcore_kthread...)"
-		   "[,(port,lcore_rx,lcore_tx,lcore_kthread...)]]\n"
-		   "    -p PORTMASK: hex bitmask of ports to use\n"
-		   "    -P : enable promiscuous mode\n"
-		   "    -m : enable monitoring of port carrier state\n"
-		   "    --config (port,lcore_rx,lcore_tx,lcore_kthread...): "
-		   "port and lcore configurations\n",
-	           prgname);
-}
-
-/* Convert string to unsigned number. 0 is returned if error occurs */
-static uint32_t
-parse_unsigned(const char *portmask)
-{
-	char *end = NULL;
-	unsigned long num;
-
-	num = strtoul(portmask, &end, 16);
-	if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0'))
-		return 0;
-
-	return (uint32_t)num;
-}
-
-static void
-print_config(void)
-{
-	uint32_t i, j;
-	struct kni_port_params **p = kni_port_params_array;
-
-	for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
-		if (!p[i])
-			continue;
-		RTE_LOG(DEBUG, APP, "Port ID: %d\n", p[i]->port_id);
-		RTE_LOG(DEBUG, APP, "Rx lcore ID: %u, Tx lcore ID: %u\n",
-					p[i]->lcore_rx, p[i]->lcore_tx);
-		for (j = 0; j < p[i]->nb_lcore_k; j++)
-			RTE_LOG(DEBUG, APP, "Kernel thread lcore ID: %u\n",
-							p[i]->lcore_k[j]);
-	}
-}
-
-static int
-parse_config(const char *arg)
-{
-	const char *p, *p0 = arg;
-	char s[256], *end;
-	unsigned size;
-	enum fieldnames {
-		FLD_PORT = 0,
-		FLD_LCORE_RX,
-		FLD_LCORE_TX,
-		_NUM_FLD = KNI_MAX_KTHREAD + 3,
-	};
-	int i, j, nb_token;
-	char *str_fld[_NUM_FLD];
-	unsigned long int_fld[_NUM_FLD];
-	uint16_t port_id, nb_kni_port_params = 0;
-
-	memset(&kni_port_params_array, 0, sizeof(kni_port_params_array));
-	while (((p = strchr(p0, '(')) != NULL) &&
-		nb_kni_port_params < RTE_MAX_ETHPORTS) {
-		p++;
-		if ((p0 = strchr(p, ')')) == NULL)
-			goto fail;
-		size = p0 - p;
-		if (size >= sizeof(s)) {
-			printf("Invalid config parameters\n");
-			goto fail;
-		}
-		snprintf(s, sizeof(s), "%.*s", size, p);
-		nb_token = rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',');
-		if (nb_token <= FLD_LCORE_TX) {
-			printf("Invalid config parameters\n");
-			goto fail;
-		}
-		for (i = 0; i < nb_token; i++) {
-			errno = 0;
-			int_fld[i] = strtoul(str_fld[i], &end, 0);
-			if (errno != 0 || end == str_fld[i]) {
-				printf("Invalid config parameters\n");
-				goto fail;
-			}
-		}
-
-		i = 0;
-		port_id = int_fld[i++];
-		if (port_id >= RTE_MAX_ETHPORTS) {
-			printf("Port ID %d could not exceed the maximum %d\n",
-						port_id, RTE_MAX_ETHPORTS);
-			goto fail;
-		}
-		if (kni_port_params_array[port_id]) {
-			printf("Port %d has been configured\n", port_id);
-			goto fail;
-		}
-		kni_port_params_array[port_id] =
-			rte_zmalloc("KNI_port_params",
-				    sizeof(struct kni_port_params), RTE_CACHE_LINE_SIZE);
-		kni_port_params_array[port_id]->port_id = port_id;
-		kni_port_params_array[port_id]->lcore_rx =
-					(uint8_t)int_fld[i++];
-		kni_port_params_array[port_id]->lcore_tx =
-					(uint8_t)int_fld[i++];
-		if (kni_port_params_array[port_id]->lcore_rx >= RTE_MAX_LCORE ||
-		kni_port_params_array[port_id]->lcore_tx >= RTE_MAX_LCORE) {
-			printf("lcore_rx %u or lcore_tx %u ID could not "
-						"exceed the maximum %u\n",
-				kni_port_params_array[port_id]->lcore_rx,
-				kni_port_params_array[port_id]->lcore_tx,
-						(unsigned)RTE_MAX_LCORE);
-			goto fail;
-		}
-		for (j = 0; i < nb_token && j < KNI_MAX_KTHREAD; i++, j++)
-			kni_port_params_array[port_id]->lcore_k[j] =
-						(uint8_t)int_fld[i];
-		kni_port_params_array[port_id]->nb_lcore_k = j;
-	}
-	print_config();
-
-	return 0;
-
-fail:
-	for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
-		if (kni_port_params_array[i]) {
-			rte_free(kni_port_params_array[i]);
-			kni_port_params_array[i] = NULL;
-		}
-	}
-
-	return -1;
-}
-
-static int
-validate_parameters(uint32_t portmask)
-{
-	uint32_t i;
-
-	if (!portmask) {
-		printf("No port configured in port mask\n");
-		return -1;
-	}
-
-	for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
-		if (((portmask & (1 << i)) && !kni_port_params_array[i]) ||
-			(!(portmask & (1 << i)) && kni_port_params_array[i]))
-			rte_exit(EXIT_FAILURE, "portmask is not consistent "
-				"to port ids specified in --config\n");
-
-		if (kni_port_params_array[i] && !rte_lcore_is_enabled(\
-			(unsigned)(kni_port_params_array[i]->lcore_rx)))
-			rte_exit(EXIT_FAILURE, "lcore id %u for "
-					"port %d receiving not enabled\n",
-					kni_port_params_array[i]->lcore_rx,
-					kni_port_params_array[i]->port_id);
-
-		if (kni_port_params_array[i] && !rte_lcore_is_enabled(\
-			(unsigned)(kni_port_params_array[i]->lcore_tx)))
-			rte_exit(EXIT_FAILURE, "lcore id %u for "
-					"port %d transmitting not enabled\n",
-					kni_port_params_array[i]->lcore_tx,
-					kni_port_params_array[i]->port_id);
-
-	}
-
-	return 0;
-}
-
-#define CMDLINE_OPT_CONFIG  "config"
-
-/* Parse the arguments given in the command line of the application */
-static int
-parse_args(int argc, char **argv)
-{
-	int opt, longindex, ret = 0;
-	const char *prgname = argv[0];
-	static struct option longopts[] = {
-		{CMDLINE_OPT_CONFIG, required_argument, NULL, 0},
-		{NULL, 0, NULL, 0}
-	};
-
-	/* Disable printing messages within getopt() */
-	opterr = 0;
-
-	/* Parse command line */
-	while ((opt = getopt_long(argc, argv, "p:Pm", longopts,
-						&longindex)) != EOF) {
-		switch (opt) {
-		case 'p':
-			ports_mask = parse_unsigned(optarg);
-			break;
-		case 'P':
-			promiscuous_on = 1;
-			break;
-		case 'm':
-			monitor_links = 1;
-			break;
-		case 0:
-			if (!strncmp(longopts[longindex].name,
-				     CMDLINE_OPT_CONFIG,
-				     sizeof(CMDLINE_OPT_CONFIG))) {
-				ret = parse_config(optarg);
-				if (ret) {
-					printf("Invalid config\n");
-					print_usage(prgname);
-					return -1;
-				}
-			}
-			break;
-		default:
-			print_usage(prgname);
-			rte_exit(EXIT_FAILURE, "Invalid option specified\n");
-		}
-	}
-
-	/* Check that options were parsed ok */
-	if (validate_parameters(ports_mask) < 0) {
-		print_usage(prgname);
-		rte_exit(EXIT_FAILURE, "Invalid parameters\n");
-	}
-
-	return ret;
-}
-
-/* Initialize KNI subsystem */
-static void
-init_kni(void)
-{
-	unsigned int num_of_kni_ports = 0, i;
-	struct kni_port_params **params = kni_port_params_array;
-
-	/* Calculate the maximum number of KNI interfaces that will be used */
-	for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
-		if (kni_port_params_array[i]) {
-			num_of_kni_ports += (params[i]->nb_lcore_k ?
-				params[i]->nb_lcore_k : 1);
-		}
-	}
-
-	/* Invoke rte KNI init to preallocate the ports */
-	rte_kni_init(num_of_kni_ports);
-}
-
-/* Initialise a single port on an Ethernet device */
-static void
-init_port(uint16_t port)
-{
-	int ret;
-	uint16_t nb_rxd = NB_RXD;
-	uint16_t nb_txd = NB_TXD;
-	struct rte_eth_dev_info dev_info;
-	struct rte_eth_rxconf rxq_conf;
-	struct rte_eth_txconf txq_conf;
-	struct rte_eth_conf local_port_conf = port_conf;
-
-	/* Initialise device and RX/TX queues */
-	RTE_LOG(INFO, APP, "Initialising port %u ...\n", (unsigned)port);
-	fflush(stdout);
-
-	ret = rte_eth_dev_info_get(port, &dev_info);
-	if (ret != 0)
-		rte_exit(EXIT_FAILURE,
-			"Error during getting device (port %u) info: %s\n",
-			port, strerror(-ret));
-
-	if (dev_info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE)
-		local_port_conf.txmode.offloads |=
-			RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE;
-	ret = rte_eth_dev_configure(port, 1, 1, &local_port_conf);
-	if (ret < 0)
-		rte_exit(EXIT_FAILURE, "Could not configure port%u (%d)\n",
-		            (unsigned)port, ret);
-
-	ret = rte_eth_dev_adjust_nb_rx_tx_desc(port, &nb_rxd, &nb_txd);
-	if (ret < 0)
-		rte_exit(EXIT_FAILURE, "Could not adjust number of descriptors "
-				"for port%u (%d)\n", (unsigned)port, ret);
-
-	rxq_conf = dev_info.default_rxconf;
-	rxq_conf.offloads = local_port_conf.rxmode.offloads;
-	ret = rte_eth_rx_queue_setup(port, 0, nb_rxd,
-		rte_eth_dev_socket_id(port), &rxq_conf, pktmbuf_pool);
-	if (ret < 0)
-		rte_exit(EXIT_FAILURE, "Could not setup up RX queue for "
-				"port%u (%d)\n", (unsigned)port, ret);
-
-	txq_conf = dev_info.default_txconf;
-	txq_conf.offloads = local_port_conf.txmode.offloads;
-	ret = rte_eth_tx_queue_setup(port, 0, nb_txd,
-		rte_eth_dev_socket_id(port), &txq_conf);
-	if (ret < 0)
-		rte_exit(EXIT_FAILURE, "Could not setup up TX queue for "
-				"port%u (%d)\n", (unsigned)port, ret);
-
-	ret = rte_eth_dev_start(port);
-	if (ret < 0)
-		rte_exit(EXIT_FAILURE, "Could not start port%u (%d)\n",
-						(unsigned)port, ret);
-
-	if (promiscuous_on) {
-		ret = rte_eth_promiscuous_enable(port);
-		if (ret != 0)
-			rte_exit(EXIT_FAILURE,
-				"Could not enable promiscuous mode for port%u: %s\n",
-				port, rte_strerror(-ret));
-	}
-}
-
-/* Check the link status of all ports in up to 9s, and print them finally */
-static void
-check_all_ports_link_status(uint32_t port_mask)
-{
-#define CHECK_INTERVAL 100 /* 100ms */
-#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
-	uint16_t portid;
-	uint8_t count, all_ports_up, print_flag = 0;
-	struct rte_eth_link link;
-	int ret;
-	char link_status_text[RTE_ETH_LINK_MAX_STR_LEN];
-
-	printf("\nChecking link status\n");
-	fflush(stdout);
-	for (count = 0; count <= MAX_CHECK_TIME; count++) {
-		all_ports_up = 1;
-		RTE_ETH_FOREACH_DEV(portid) {
-			if ((port_mask & (1 << portid)) == 0)
-				continue;
-			memset(&link, 0, sizeof(link));
-			ret = rte_eth_link_get_nowait(portid, &link);
-			if (ret < 0) {
-				all_ports_up = 0;
-				if (print_flag == 1)
-					printf("Port %u link get failed: %s\n",
-						portid, rte_strerror(-ret));
-				continue;
-			}
-			/* print link status if flag set */
-			if (print_flag == 1) {
-				rte_eth_link_to_str(link_status_text,
-					sizeof(link_status_text), &link);
-				printf("Port %d %s\n", portid,
-					link_status_text);
-				continue;
-			}
-			/* clear all_ports_up flag if any link down */
-			if (link.link_status == RTE_ETH_LINK_DOWN) {
-				all_ports_up = 0;
-				break;
-			}
-		}
-		/* after finally printing all link status, get out */
-		if (print_flag == 1)
-			break;
-
-		if (all_ports_up == 0) {
-			printf(".");
-			fflush(stdout);
-			rte_delay_ms(CHECK_INTERVAL);
-		}
-
-		/* set the print_flag if all ports up or timeout */
-		if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
-			print_flag = 1;
-			printf("done\n");
-		}
-	}
-}
-
-static void
-log_link_state(struct rte_kni *kni, int prev, struct rte_eth_link *link)
-{
-	char link_status_text[RTE_ETH_LINK_MAX_STR_LEN];
-	if (kni == NULL || link == NULL)
-		return;
-
-	rte_eth_link_to_str(link_status_text, sizeof(link_status_text), link);
-	if (prev != link->link_status)
-		RTE_LOG(INFO, APP, "%s NIC %s\n",
-			rte_kni_get_name(kni),
-			link_status_text);
-}
-
-/*
- * Monitor the link status of all ports and update the
- * corresponding KNI interface(s)
- */
-static void *
-monitor_all_ports_link_status(void *arg)
-{
-	uint16_t portid;
-	struct rte_eth_link link;
-	unsigned int i;
-	struct kni_port_params **p = kni_port_params_array;
-	int prev;
-	(void) arg;
-	int ret;
-
-	while (monitor_links) {
-		rte_delay_ms(500);
-		RTE_ETH_FOREACH_DEV(portid) {
-			if ((ports_mask & (1 << portid)) == 0)
-				continue;
-			memset(&link, 0, sizeof(link));
-			ret = rte_eth_link_get_nowait(portid, &link);
-			if (ret < 0) {
-				RTE_LOG(ERR, APP,
-					"Get link failed (port %u): %s\n",
-					portid, rte_strerror(-ret));
-				continue;
-			}
-			for (i = 0; i < p[portid]->nb_kni; i++) {
-				prev = rte_kni_update_link(p[portid]->kni[i],
-						link.link_status);
-				log_link_state(p[portid]->kni[i], prev, &link);
-			}
-		}
-	}
-	return NULL;
-}
-
-static int
-kni_change_mtu_(uint16_t port_id, unsigned int new_mtu)
-{
-	int ret;
-	uint16_t nb_rxd = NB_RXD;
-	uint16_t nb_txd = NB_TXD;
-	struct rte_eth_conf conf;
-	struct rte_eth_dev_info dev_info;
-	struct rte_eth_rxconf rxq_conf;
-	struct rte_eth_txconf txq_conf;
-
-	if (!rte_eth_dev_is_valid_port(port_id)) {
-		RTE_LOG(ERR, APP, "Invalid port id %d\n", port_id);
-		return -EINVAL;
-	}
-
-	RTE_LOG(INFO, APP, "Change MTU of port %d to %u\n", port_id, new_mtu);
-
-	/* Stop specific port */
-	ret = rte_eth_dev_stop(port_id);
-	if (ret != 0) {
-		RTE_LOG(ERR, APP, "Failed to stop port %d: %s\n",
-			port_id, rte_strerror(-ret));
-		return ret;
-	}
-
-	memcpy(&conf, &port_conf, sizeof(conf));
-
-	conf.rxmode.mtu = new_mtu;
-	ret = rte_eth_dev_configure(port_id, 1, 1, &conf);
-	if (ret < 0) {
-		RTE_LOG(ERR, APP, "Fail to reconfigure port %d\n", port_id);
-		return ret;
-	}
-
-	ret = rte_eth_dev_adjust_nb_rx_tx_desc(port_id, &nb_rxd, &nb_txd);
-	if (ret < 0)
-		rte_exit(EXIT_FAILURE, "Could not adjust number of descriptors "
-				"for port%u (%d)\n", (unsigned int)port_id,
-				ret);
-
-	ret = rte_eth_dev_info_get(port_id, &dev_info);
-	if (ret != 0) {
-		RTE_LOG(ERR, APP,
-			"Error during getting device (port %u) info: %s\n",
-			port_id, strerror(-ret));
-
-		return ret;
-	}
-
-	rxq_conf = dev_info.default_rxconf;
-	rxq_conf.offloads = conf.rxmode.offloads;
-	ret = rte_eth_rx_queue_setup(port_id, 0, nb_rxd,
-		rte_eth_dev_socket_id(port_id), &rxq_conf, pktmbuf_pool);
-	if (ret < 0) {
-		RTE_LOG(ERR, APP, "Fail to setup Rx queue of port %d\n",
-				port_id);
-		return ret;
-	}
-
-	txq_conf = dev_info.default_txconf;
-	txq_conf.offloads = conf.txmode.offloads;
-	ret = rte_eth_tx_queue_setup(port_id, 0, nb_txd,
-		rte_eth_dev_socket_id(port_id), &txq_conf);
-	if (ret < 0) {
-		RTE_LOG(ERR, APP, "Fail to setup Tx queue of port %d\n",
-				port_id);
-		return ret;
-	}
-
-	/* Restart specific port */
-	ret = rte_eth_dev_start(port_id);
-	if (ret < 0) {
-		RTE_LOG(ERR, APP, "Fail to restart port %d\n", port_id);
-		return ret;
-	}
-
-	return 0;
-}
-
-/* Callback for request of changing MTU */
-static int
-kni_change_mtu(uint16_t port_id, unsigned int new_mtu)
-{
-	int ret;
-
-	__atomic_fetch_add(&kni_pause, 1, __ATOMIC_RELAXED);
-	ret =  kni_change_mtu_(port_id, new_mtu);
-	__atomic_fetch_sub(&kni_pause, 1, __ATOMIC_RELAXED);
-
-	return ret;
-}
-
-/* Callback for request of configuring network interface up/down */
-static int
-kni_config_network_interface(uint16_t port_id, uint8_t if_up)
-{
-	int ret = 0;
-
-	if (!rte_eth_dev_is_valid_port(port_id)) {
-		RTE_LOG(ERR, APP, "Invalid port id %d\n", port_id);
-		return -EINVAL;
-	}
-
-	RTE_LOG(INFO, APP, "Configure network interface of %d %s\n",
-					port_id, if_up ? "up" : "down");
-
-	__atomic_fetch_add(&kni_pause, 1, __ATOMIC_RELAXED);
-
-	if (if_up != 0) { /* Configure network interface up */
-		ret = rte_eth_dev_stop(port_id);
-		if (ret != 0) {
-			RTE_LOG(ERR, APP, "Failed to stop port %d: %s\n",
-				port_id, rte_strerror(-ret));
-			__atomic_fetch_sub(&kni_pause, 1, __ATOMIC_RELAXED);
-			return ret;
-		}
-		ret = rte_eth_dev_start(port_id);
-	} else { /* Configure network interface down */
-		ret = rte_eth_dev_stop(port_id);
-		if (ret != 0) {
-			RTE_LOG(ERR, APP, "Failed to stop port %d: %s\n",
-				port_id, rte_strerror(-ret));
-			__atomic_fetch_sub(&kni_pause, 1, __ATOMIC_RELAXED);
-			return ret;
-		}
-	}
-
-	__atomic_fetch_sub(&kni_pause, 1, __ATOMIC_RELAXED);
-
-	if (ret < 0)
-		RTE_LOG(ERR, APP, "Failed to start port %d\n", port_id);
-
-	return ret;
-}
-
-static void
-print_ethaddr(const char *name, struct rte_ether_addr *mac_addr)
-{
-	char buf[RTE_ETHER_ADDR_FMT_SIZE];
-	rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, mac_addr);
-	RTE_LOG(INFO, APP, "\t%s%s\n", name, buf);
-}
-
-/* Callback for request of configuring mac address */
-static int
-kni_config_mac_address(uint16_t port_id, uint8_t mac_addr[])
-{
-	int ret = 0;
-
-	if (!rte_eth_dev_is_valid_port(port_id)) {
-		RTE_LOG(ERR, APP, "Invalid port id %d\n", port_id);
-		return -EINVAL;
-	}
-
-	RTE_LOG(INFO, APP, "Configure mac address of %d\n", port_id);
-	print_ethaddr("Address:", (struct rte_ether_addr *)mac_addr);
-
-	ret = rte_eth_dev_default_mac_addr_set(port_id,
-					(struct rte_ether_addr *)mac_addr);
-	if (ret < 0)
-		RTE_LOG(ERR, APP, "Failed to config mac_addr for port %d\n",
-			port_id);
-
-	return ret;
-}
-
-static int
-kni_alloc(uint16_t port_id)
-{
-	uint8_t i;
-	struct rte_kni *kni;
-	struct rte_kni_conf conf;
-	struct kni_port_params **params = kni_port_params_array;
-	int ret;
-
-	if (port_id >= RTE_MAX_ETHPORTS || !params[port_id])
-		return -1;
-
-	params[port_id]->nb_kni = params[port_id]->nb_lcore_k ?
-				params[port_id]->nb_lcore_k : 1;
-
-	for (i = 0; i < params[port_id]->nb_kni; i++) {
-		/* Clear conf at first */
-		memset(&conf, 0, sizeof(conf));
-		if (params[port_id]->nb_lcore_k) {
-			snprintf(conf.name, RTE_KNI_NAMESIZE,
-					"vEth%u_%u", port_id, i);
-			conf.core_id = params[port_id]->lcore_k[i];
-			conf.force_bind = 1;
-		} else
-			snprintf(conf.name, RTE_KNI_NAMESIZE,
-						"vEth%u", port_id);
-		conf.group_id = port_id;
-		conf.mbuf_size = MAX_PACKET_SZ;
-		/*
-		 * The first KNI device associated to a port
-		 * is the main, for multiple kernel thread
-		 * environment.
-		 */
-		if (i == 0) {
-			struct rte_kni_ops ops;
-			struct rte_eth_dev_info dev_info;
-
-			ret = rte_eth_dev_info_get(port_id, &dev_info);
-			if (ret != 0)
-				rte_exit(EXIT_FAILURE,
-					"Error during getting device (port %u) info: %s\n",
-					port_id, strerror(-ret));
-
-			/* Get the interface default mac address */
-			ret = rte_eth_macaddr_get(port_id,
-				(struct rte_ether_addr *)&conf.mac_addr);
-			if (ret != 0)
-				rte_exit(EXIT_FAILURE,
-					"Failed to get MAC address (port %u): %s\n",
-					port_id, rte_strerror(-ret));
-
-			rte_eth_dev_get_mtu(port_id, &conf.mtu);
-
-			conf.min_mtu = dev_info.min_mtu;
-			conf.max_mtu = dev_info.max_mtu;
-
-			memset(&ops, 0, sizeof(ops));
-			ops.port_id = port_id;
-			ops.change_mtu = kni_change_mtu;
-			ops.config_network_if = kni_config_network_interface;
-			ops.config_mac_address = kni_config_mac_address;
-
-			kni = rte_kni_alloc(pktmbuf_pool, &conf, &ops);
-		} else
-			kni = rte_kni_alloc(pktmbuf_pool, &conf, NULL);
-
-		if (!kni)
-			rte_exit(EXIT_FAILURE, "Fail to create kni for "
-						"port: %d\n", port_id);
-		params[port_id]->kni[i] = kni;
-	}
-
-	return 0;
-}
-
-static int
-kni_free_kni(uint16_t port_id)
-{
-	uint8_t i;
-	int ret;
-	struct kni_port_params **p = kni_port_params_array;
-
-	if (port_id >= RTE_MAX_ETHPORTS || !p[port_id])
-		return -1;
-
-	for (i = 0; i < p[port_id]->nb_kni; i++) {
-		if (rte_kni_release(p[port_id]->kni[i]))
-			printf("Fail to release kni\n");
-		p[port_id]->kni[i] = NULL;
-	}
-	ret = rte_eth_dev_stop(port_id);
-	if (ret != 0)
-		RTE_LOG(ERR, APP, "Failed to stop port %d: %s\n",
-			port_id, rte_strerror(-ret));
-	rte_eth_dev_close(port_id);
-
-	return 0;
-}
-
-/* Initialise ports/queues etc. and start main loop on each core */
-int
-main(int argc, char** argv)
-{
-	int ret;
-	uint16_t nb_sys_ports, port;
-	unsigned i;
-	void *retval;
-	pthread_t kni_link_tid;
-	int pid;
-
-	/* Associate signal_handler function with USR signals */
-	signal(SIGUSR1, signal_handler);
-	signal(SIGUSR2, signal_handler);
-	signal(SIGRTMIN, signal_handler);
-	signal(SIGINT, signal_handler);
-	signal(SIGTERM, signal_handler);
-
-	/* Initialise EAL */
-	ret = rte_eal_init(argc, argv);
-	if (ret < 0)
-		rte_exit(EXIT_FAILURE, "Could not initialise EAL (%d)\n", ret);
-	argc -= ret;
-	argv += ret;
-
-	/* Parse application arguments (after the EAL ones) */
-	ret = parse_args(argc, argv);
-	if (ret < 0)
-		rte_exit(EXIT_FAILURE, "Could not parse input parameters\n");
-
-	/* Create the mbuf pool */
-	pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF,
-		MEMPOOL_CACHE_SZ, 0, MBUF_DATA_SZ, rte_socket_id());
-	if (pktmbuf_pool == NULL) {
-		rte_exit(EXIT_FAILURE, "Could not initialise mbuf pool\n");
-		return -1;
-	}
-
-	/* Get number of ports found in scan */
-	nb_sys_ports = rte_eth_dev_count_avail();
-	if (nb_sys_ports == 0)
-		rte_exit(EXIT_FAILURE, "No supported Ethernet device found\n");
-
-	/* Check if the configured port ID is valid */
-	for (i = 0; i < RTE_MAX_ETHPORTS; i++)
-		if (kni_port_params_array[i] && !rte_eth_dev_is_valid_port(i))
-			rte_exit(EXIT_FAILURE, "Configured invalid "
-						"port ID %u\n", i);
-
-	/* Initialize KNI subsystem */
-	init_kni();
-
-	/* Initialise each port */
-	RTE_ETH_FOREACH_DEV(port) {
-		/* Skip ports that are not enabled */
-		if (!(ports_mask & (1 << port)))
-			continue;
-		init_port(port);
-
-		if (port >= RTE_MAX_ETHPORTS)
-			rte_exit(EXIT_FAILURE, "Can not use more than "
-				"%d ports for kni\n", RTE_MAX_ETHPORTS);
-
-		kni_alloc(port);
-	}
-	check_all_ports_link_status(ports_mask);
-
-	pid = getpid();
-	RTE_LOG(INFO, APP, "========================\n");
-	RTE_LOG(INFO, APP, "KNI Running\n");
-	RTE_LOG(INFO, APP, "kill -SIGUSR1 %d\n", pid);
-	RTE_LOG(INFO, APP, "    Show KNI Statistics.\n");
-	RTE_LOG(INFO, APP, "kill -SIGUSR2 %d\n", pid);
-	RTE_LOG(INFO, APP, "    Zero KNI Statistics.\n");
-	RTE_LOG(INFO, APP, "========================\n");
-	fflush(stdout);
-
-	ret = rte_ctrl_thread_create(&kni_link_tid,
-				     "KNI link status check", NULL,
-				     monitor_all_ports_link_status, NULL);
-	if (ret < 0)
-		rte_exit(EXIT_FAILURE,
-			"Could not create link status thread!\n");
-
-	/* Launch per-lcore function on every lcore */
-	rte_eal_mp_remote_launch(main_loop, NULL, CALL_MAIN);
-	RTE_LCORE_FOREACH_WORKER(i) {
-		if (rte_eal_wait_lcore(i) < 0)
-			return -1;
-	}
-	monitor_links = 0;
-	pthread_join(kni_link_tid, &retval);
-
-	/* Release resources */
-	RTE_ETH_FOREACH_DEV(port) {
-		if (!(ports_mask & (1 << port)))
-			continue;
-		kni_free_kni(port);
-	}
-	for (i = 0; i < RTE_MAX_ETHPORTS; i++)
-		if (kni_port_params_array[i]) {
-			rte_free(kni_port_params_array[i]);
-			kni_port_params_array[i] = NULL;
-		}
-
-	/* clean up the EAL */
-	rte_eal_cleanup();
-
-	return 0;
-}
diff --git a/examples/kni/meson.build b/examples/kni/meson.build
deleted file mode 100644
index 6bd4eb50e6..0000000000
--- a/examples/kni/meson.build
+++ /dev/null
@@ -1,13 +0,0 @@
-# SPDX-License-Identifier: BSD-3-Clause
-# Copyright(c) 2017 Intel Corporation
-
-# meson file, for building this example as part of a main DPDK build.
-#
-# To build this example as a standalone application with an already-installed
-# DPDK instance, use 'make'
-
-deps += ['kni', 'bus_pci']
-sources = files(
-        'main.c',
-)
-allow_experimental_apis = true
diff --git a/examples/meson.build b/examples/meson.build
index 81e93799f2..6968c09252 100644
--- a/examples/meson.build
+++ b/examples/meson.build
@@ -24,7 +24,6 @@ all_examples = [
         'ip_reassembly',
         'ipsec-secgw',
         'ipv4_multicast',
-        'kni',
         'l2fwd',
         'l2fwd-cat',
         'l2fwd-crypto',
-- 
2.34.1


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

* Re: [PATCH] examples/kni: remove deprecated kni example
  2022-09-20 15:14 [PATCH] examples/kni: remove deprecated kni example Bruce Richardson
@ 2022-09-20 15:25 ` Stephen Hemminger
  2022-09-20 15:51 ` [PATCH v2] " Bruce Richardson
  1 sibling, 0 replies; 6+ messages in thread
From: Stephen Hemminger @ 2022-09-20 15:25 UTC (permalink / raw)
  To: Bruce Richardson; +Cc: dev

On Tue, 20 Sep 2022 16:14:53 +0100
Bruce Richardson <bruce.richardson@intel.com> wrote:

> As part of the agreed process for deprecating KNI in DPDK, the example
> app is scheduled for removal as part of the 22.11 release.
> 
> Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>

And as expected, no one will notice until it is gone!

Acked-by: Stephen Hemminger <stephen@networkplumber.org>

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

* [PATCH v2] examples/kni: remove deprecated kni example
  2022-09-20 15:14 [PATCH] examples/kni: remove deprecated kni example Bruce Richardson
  2022-09-20 15:25 ` Stephen Hemminger
@ 2022-09-20 15:51 ` Bruce Richardson
  2022-10-03 16:11   ` Thomas Monjalon
  1 sibling, 1 reply; 6+ messages in thread
From: Bruce Richardson @ 2022-09-20 15:51 UTC (permalink / raw)
  To: dev; +Cc: Bruce Richardson

As part of the agreed process for deprecating KNI in DPDK, the example
app is scheduled for removal as part of the 22.11 release.

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
V2: Correct old release note links to KNI guide by referencing older doc
---
 doc/guides/rel_notes/deprecation.rst          |    1 -
 doc/guides/rel_notes/release_18_11.rst        |    4 +-
 doc/guides/sample_app_ug/index.rst            |    1 -
 .../sample_app_ug/kernel_nic_interface.rst    |  318 -----
 examples/kni/Makefile                         |   52 -
 examples/kni/main.c                           | 1140 -----------------
 examples/kni/meson.build                      |   13 -
 examples/meson.build                          |    1 -
 8 files changed, 2 insertions(+), 1528 deletions(-)
 delete mode 100644 doc/guides/sample_app_ug/kernel_nic_interface.rst
 delete mode 100644 examples/kni/Makefile
 delete mode 100644 examples/kni/main.c
 delete mode 100644 examples/kni/meson.build

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index c1975d6c3e..2ded2d69d1 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -70,7 +70,6 @@ Deprecation Notices
   and `refinement <http://mails.dpdk.org/archives/dev/2022-June/243596.html>`_:

   * Some deprecation warnings will be added in DPDK 22.11.
-  * The KNI example application will be removed from DPDK 22.11.
   * The KNI kernel module, library and PMD will be removed from the DPDK 23.11.

 * lib: will fix extending some enum/define breaking the ABI. There are multiple
diff --git a/doc/guides/rel_notes/release_18_11.rst b/doc/guides/rel_notes/release_18_11.rst
index be52bf0803..708bc9d4dd 100644
--- a/doc/guides/rel_notes/release_18_11.rst
+++ b/doc/guides/rel_notes/release_18_11.rst
@@ -265,7 +265,7 @@ New Features
   carrier state is set to ``on`` via ``rte_kni_update_link`` or
   by writing ``1`` to ``/sys/devices/virtual/net/<iface>/carrier``.
   In previous versions the default carrier state was left undefined.
-  See :doc:`../prog_guide/kernel_nic_interface` for more information.
+  See `Kernel NIC Interface <https://doc.dpdk.org/guides-18.11/sample_app_ug/kernel_nic_interface.html>`_ for more information.

   Also added the new API function ``rte_kni_update_link()`` to allow the user
   to set the carrier state of the KNI kernel network interface.
@@ -273,7 +273,7 @@ New Features
   Also added a new command line flag ``-m`` to the KNI sample application to
   monitor and automatically reflect the physical NIC carrier state to the
   KNI kernel network interface with the new ``rte_kni_update_link()`` API.
-  See :doc:`../sample_app_ug/kernel_nic_interface` for more information.
+  See `Kernel NIC Interface <https://doc.dpdk.org/guides-18.11/sample_app_ug/kernel_nic_interface.html>`_ for more information.

 * **Added ability to switch queue deferred start flag on testpmd app.**

diff --git a/doc/guides/sample_app_ug/index.rst b/doc/guides/sample_app_ug/index.rst
index cc9fae1e8c..6e1e83d7d7 100644
--- a/doc/guides/sample_app_ug/index.rst
+++ b/doc/guides/sample_app_ug/index.rst
@@ -20,7 +20,6 @@ Sample Applications User Guides
     ip_frag
     ipv4_multicast
     ip_reassembly
-    kernel_nic_interface
     keep_alive
     dma
     l2_forward_crypto
diff --git a/doc/guides/sample_app_ug/kernel_nic_interface.rst b/doc/guides/sample_app_ug/kernel_nic_interface.rst
deleted file mode 100644
index ef441cc1e5..0000000000
--- a/doc/guides/sample_app_ug/kernel_nic_interface.rst
+++ /dev/null
@@ -1,318 +0,0 @@
-..  SPDX-License-Identifier: BSD-3-Clause
-    Copyright(c) 2010-2014 Intel Corporation.
-
-Kernel NIC Interface Sample Application
-=======================================
-
-The Kernel NIC Interface (KNI) is a DPDK control plane solution that
-allows userspace applications to exchange packets with the kernel networking stack.
-To accomplish this, DPDK userspace applications use an IOCTL call
-to request the creation of a KNI virtual device in the Linux* kernel.
-The IOCTL call provides interface information and the DPDK's physical address space,
-which is re-mapped into the kernel address space by the KNI kernel loadable module
-that saves the information to a virtual device context.
-The DPDK creates FIFO queues for packet ingress and egress
-to the kernel module for each device allocated.
-
-The KNI kernel loadable module is a standard net driver,
-which upon receiving the IOCTL call access the DPDK's FIFO queue to
-receive/transmit packets from/to the DPDK userspace application.
-The FIFO queues contain pointers to data packets in the DPDK. This:
-
-*   Provides a faster mechanism to interface with the kernel net stack and eliminates system calls
-
-*   Facilitates the DPDK using standard Linux* userspace net tools (tshark, rsync, and so on)
-
-*   Eliminate the copy_to_user and copy_from_user operations on packets.
-
-The Kernel NIC Interface sample application is a simple example that demonstrates the use
-of the DPDK to create a path for packets to go through the Linux* kernel.
-This is done by creating one or more kernel net devices for each of the DPDK ports.
-The application allows the use of standard Linux tools (ethtool, iproute, tshark) with the DPDK ports and
-also the exchange of packets between the DPDK application and the Linux* kernel.
-
-The Kernel NIC Interface sample application requires that the
-KNI kernel module ``rte_kni`` be loaded into the kernel.  See
-:doc:`../prog_guide/kernel_nic_interface` for more information on loading
-the ``rte_kni`` kernel module.
-
-Overview
---------
-
-The Kernel NIC Interface sample application ``kni`` allocates one or more
-KNI interfaces for each physical NIC port.  For each physical NIC port,
-``kni`` uses two DPDK threads in user space; one thread reads from the port and
-writes to the corresponding KNI interfaces and the other thread reads from
-the KNI interfaces and writes the data unmodified to the physical NIC port.
-
-It is recommended to configure one KNI interface for each physical NIC port.
-The application can be configured with more than one KNI interface for
-each physical NIC port for performance testing or it can work together with
-VMDq support in future.
-
-The packet flow through the Kernel NIC Interface application is as shown
-in the following figure.
-
-.. _figure_kernel_nic:
-
-.. figure:: img/kernel_nic.*
-
-   Kernel NIC Application Packet Flow
-
-If link monitoring is enabled with the ``-m`` command line flag, one
-additional pthread is launched which will check the link status of each
-physical NIC port and will update the carrier status of the corresponding
-KNI interface(s) to match the physical NIC port's state.  This means that
-the KNI interface(s) will be disabled automatically when the Ethernet link
-goes down and enabled when the Ethernet link goes up.
-
-If link monitoring is enabled, the ``rte_kni`` kernel module should be loaded
-such that the :ref:`default carrier state <kni_default_carrier_state>` is
-set to *off*.  This ensures that the KNI interface is only enabled *after*
-the Ethernet link of the corresponding NIC port has reached the linkup state.
-
-If link monitoring is not enabled, the ``rte_kni`` kernel module should be
-loaded with the :ref:`default carrier state <kni_default_carrier_state>`
-set to *on*.  This sets the carrier state of the KNI interfaces to *on*
-when the KNI interfaces are enabled without regard to the actual link state
-of the corresponding NIC port.  This is useful for testing in loopback
-mode where the NIC port may not be physically connected to anything.
-
-Compiling the Application
--------------------------
-
-To compile the sample application see :doc:`compiling`.
-
-The application is located in the ``examples/kni`` sub-directory.
-
-.. note::
-
-        This application is intended as a linux only.
-
-Running the kni Example Application
------------------------------------
-
-The ``kni`` example application requires a number of command line options:
-
-.. code-block:: console
-
-    dpdk-kni [EAL options] -- -p PORTMASK --config="(port,lcore_rx,lcore_tx[,lcore_kthread,...])[,(port,lcore_rx,lcore_tx[,lcore_kthread,...])]" [-P] [-m]
-
-Where:
-
-*   ``-p PORTMASK``:
-
-    Hexadecimal bitmask of ports to configure.
-
-*   ``--config="(port,lcore_rx,lcore_tx[,lcore_kthread,...])[,(port,lcore_rx,lcore_tx[,lcore_kthread,...])]"``:
-
-    Determines which lcores the Rx and Tx DPDK tasks, and (optionally)
-    the KNI kernel thread(s) are bound to for each physical port.
-
-*   ``-P``:
-
-    Optional flag to set all ports to promiscuous mode so that packets are
-    accepted regardless of the packet's Ethernet MAC destination address.
-    Without this option, only packets with the Ethernet MAC destination
-    address set to the Ethernet address of the port are accepted.
-
-*   ``-m``:
-
-    Optional flag to enable monitoring and updating of the Ethernet
-    carrier state.  With this option set, a thread will be started which
-    will periodically check the Ethernet link status of the physical
-    Ethernet ports and set the carrier state of the corresponding KNI
-    network interface to match it.  This means that the KNI interface will
-    be disabled automatically when the Ethernet link goes down and enabled
-    when the Ethernet link goes up.
-
-Refer to *DPDK Getting Started Guide* for general information on running
-applications and the Environment Abstraction Layer (EAL) options.
-
-The ``-c coremask`` or ``-l corelist`` parameter of the EAL options must
-include the lcores specified by ``lcore_rx`` and ``lcore_tx`` for each port,
-but does not need to include lcores specified by ``lcore_kthread`` as those
-cores are used to pin the kernel threads in the ``rte_kni`` kernel module.
-
-The ``--config`` parameter must include a set of
-``(port,lcore_rx,lcore_tx,[lcore_kthread,...])`` values for each physical
-port specified in the ``-p PORTMASK`` parameter.
-
-The optional ``lcore_kthread`` lcore ID parameter in ``--config`` can be
-specified zero, one or more times for each physical port.
-
-If no lcore ID is specified for ``lcore_kthread``, one KNI interface will
-be created for the physical port ``port`` and the KNI kernel thread(s)
-will have no specific core affinity.
-
-If one or more lcore IDs are specified for ``lcore_kthread``, a KNI interface
-will be created for each lcore ID specified, bound to the physical port
-``port``.  If the ``rte_kni`` kernel module is loaded in :ref:`multiple
-kernel thread <kni_kernel_thread_mode>` mode, a kernel thread will be created
-for each KNI interface and bound to the specified core.  If the ``rte_kni``
-kernel module is loaded in :ref:`single kernel thread <kni_kernel_thread_mode>`
-mode, only one kernel thread is started for all KNI interfaces.  The kernel
-thread will be bound to the first ``lcore_kthread`` lcore ID specified.
-
-Example Configurations
-~~~~~~~~~~~~~~~~~~~~~~~
-
-The following commands will first load the ``rte_kni`` kernel module in
-:ref:`multiple kernel thread <kni_kernel_thread_mode>` mode.  The ``kni``
-application is then started using two ports;  Port 0 uses lcore 4 for the
-Rx task, lcore 6 for the Tx task, and will create a single KNI interface
-``vEth0_0`` with the kernel thread bound to lcore 8.  Port 1 uses lcore
-5 for the Rx task, lcore 7 for the Tx task, and will create a single KNI
-interface ``vEth1_0`` with the kernel thread bound to lcore 9.
-
-.. code-block:: console
-
-    # rmmod rte_kni
-    # insmod <build_dir>/kernel/linux/kni/rte_kni.ko kthread_mode=multiple
-    # ./<build-dir>/examples/dpdk-kni -l 4-7 -n 4 -- -P -p 0x3 -m --config="(0,4,6,8),(1,5,7,9)"
-
-The following example is identical, except an additional ``lcore_kthread``
-core is specified per physical port.  In this case, ``kni`` will create
-four KNI interfaces: ``vEth0_0``/``vEth0_1`` bound to physical port 0 and
-``vEth1_0``/``vEth1_1`` bound to physical port 1.
-
-The kernel thread for each interface will be bound as follows:
-
-    * ``vEth0_0`` - bound to lcore 8.
-    * ``vEth0_1`` - bound to lcore 10.
-    * ``vEth1_0`` - bound to lcore 9.
-    * ``vEth1_1`` - bound to lcore 11
-
-.. code-block:: console
-
-    # rmmod rte_kni
-    # insmod <build_dir>/kernel/linux/kni/rte_kni.ko kthread_mode=multiple
-    # ./<build-dir>/examples/dpdk-kni -l 4-7 -n 4 -- -P -p 0x3 -m --config="(0,4,6,8,10),(1,5,7,9,11)"
-
-The following example can be used to test the interface between the ``kni``
-test application and the ``rte_kni`` kernel module.  In this example,
-the ``rte_kni`` kernel module is loaded in :ref:`single kernel thread
-mode <kni_kernel_thread_mode>`, :ref:`loopback mode <kni_loopback_mode>`
-enabled, and the :ref:`default carrier state <kni_default_carrier_state>`
-is set to *on* so that the corresponding physical NIC port does not have
-to be connected in order to use the KNI interface.  One KNI interface
-``vEth0_0`` is created for port 0 and one KNI interface ``vEth1_0`` is
-created for port 1.  Since ``rte_kni`` is loaded in "single kernel thread"
-mode, the one kernel thread is bound to lcore 8.
-
-Since the physical NIC ports are not being used, link monitoring can be
-disabled by **not** specifying the ``-m`` flag to ``kni``:
-
-.. code-block:: console
-
-    # rmmod rte_kni
-    # insmod <build_dir>/kernel/linux/kni/rte_kni.ko lo_mode=lo_mode_fifo carrier=on
-    # ./<build-dir>/examples/dpdk-kni -l 4-7 -n 4 -- -P -p 0x3 --config="(0,4,6,8),(1,5,7,9)"
-
-KNI Operations
---------------
-
-Once the ``kni`` application is started, the user can use the normal
-Linux commands to manage the KNI interfaces as if they were any other
-Linux network interface.
-
-Enable KNI interface and assign an IP address:
-
-.. code-block:: console
-
-    # ip addr add dev vEth0_0 192.168.0.1
-
-Show KNI interface configuration and statistics:
-
-.. code-block:: console
-
-    # ip -s -d addr show vEth0_0
-
-The user can also check and reset the packet statistics inside the ``kni``
-application by sending the app the USR1 and USR2 signals:
-
-.. code-block:: console
-
-    # Print statistics
-    # pkill -USR1 kni
-
-    # Zero statistics
-    # pkill -USR2 kni
-
-Dump network traffic:
-
-.. code-block:: console
-
-    # tshark -n -i vEth0_0
-
-The normal Linux commands can also be used to change the MAC address and
-MTU size used by the physical NIC which corresponds to the KNI interface.
-However, if more than one KNI interface is configured for a physical port,
-these commands will only work on the first KNI interface for that port.
-
-Change the MAC address:
-
-.. code-block:: console
-
-    # ip link set dev vEth0_0 lladdr 0C:01:02:03:04:08
-
-Change the MTU size:
-
-.. code-block:: console
-
-    # ip link set dev vEth0_0 mtu 1450
-
-Limited ethtool support:
-
-.. code-block:: console
-
-    # ethtool -i vEth0_0
-
-When the ``kni`` application is closed, all the KNI interfaces are deleted
-from the Linux kernel.
-
-Explanation
------------
-
-The following sections provide some explanation of code.
-
-Initialization
-~~~~~~~~~~~~~~
-
-Setup of mbuf pool, driver and queues is similar to the setup done in the :doc:`l2_forward_real_virtual`..
-In addition, one or more kernel NIC interfaces are allocated for each
-of the configured ports according to the command line parameters.
-
-The code for allocating the kernel NIC interfaces for a specific port is
-in the function ``kni_alloc``.
-
-The other step in the initialization process that is unique to this sample application
-is the association of each port with lcores for RX, TX and kernel threads.
-
-*   One lcore to read from the port and write to the associated one or more KNI devices
-
-*   Another lcore to read from one or more KNI devices and write to the port
-
-*   Other lcores for pinning the kernel threads on one by one
-
-This is done by using the ``kni_port_params_array[]`` array, which is indexed by the port ID.
-The code is in the function ``parse_config``.
-
-Packet Forwarding
-~~~~~~~~~~~~~~~~~
-
-After the initialization steps are completed, the main_loop() function is run on each lcore.
-This function first checks the lcore_id against the user provided lcore_rx and lcore_tx
-to see if this lcore is reading from or writing to kernel NIC interfaces.
-
-For the case that reads from a NIC port and writes to the kernel NIC interfaces (``kni_ingress``),
-the packet reception is the same as in L2 Forwarding sample application
-(see :ref:`l2_fwd_app_rx_tx_packets`).
-The packet transmission is done by sending mbufs into the kernel NIC interfaces by ``rte_kni_tx_burst()``.
-The KNI library automatically frees the mbufs after the kernel successfully copied the mbufs.
-
-For the other case that reads from kernel NIC interfaces
-and writes to a physical NIC port (``kni_egress``),
-packets are retrieved by reading mbufs from kernel NIC interfaces by ``rte_kni_rx_burst()``.
-The packet transmission is the same as in the L2 Forwarding sample application
-(see :ref:`l2_fwd_app_rx_tx_packets`).
diff --git a/examples/kni/Makefile b/examples/kni/Makefile
deleted file mode 100644
index 753cb96f5f..0000000000
--- a/examples/kni/Makefile
+++ /dev/null
@@ -1,52 +0,0 @@
-# SPDX-License-Identifier: BSD-3-Clause
-# Copyright(c) 2010-2014 Intel Corporation
-
-# binary name
-APP = kni
-
-# all source are stored in SRCS-y
-SRCS-y := main.c
-
-PKGCONF ?= pkg-config
-
-# Build using pkg-config variables if possible
-ifneq ($(shell $(PKGCONF) --exists libdpdk && echo 0),0)
-$(error "no installation of DPDK found")
-endif
-
-all: shared
-.PHONY: shared static
-shared: build/$(APP)-shared
-	ln -sf $(APP)-shared build/$(APP)
-static: build/$(APP)-static
-	ln -sf $(APP)-static build/$(APP)
-
-PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
-CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
-CFLAGS += -DALLOW_EXPERIMENTAL_API
-LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
-
-ifeq ($(MAKECMDGOALS),static)
-# check for broken pkg-config
-ifeq ($(shell echo $(LDFLAGS_STATIC) | grep 'whole-archive.*l:lib.*no-whole-archive'),)
-$(warning "pkg-config output list does not contain drivers between 'whole-archive'/'no-whole-archive' flags.")
-$(error "Cannot generate statically-linked binaries with this version of pkg-config")
-endif
-endif
-
-LDFLAGS += -pthread
-
-build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
-	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
-
-build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build
-	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC)
-
-build:
-	@mkdir -p $@
-
-.PHONY: clean
-clean:
-	rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared
-	test -d build && rmdir -p build || true
diff --git a/examples/kni/main.c b/examples/kni/main.c
deleted file mode 100644
index e99ef5c38a..0000000000
--- a/examples/kni/main.c
+++ /dev/null
@@ -1,1140 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2014 Intel Corporation
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <string.h>
-#include <sys/queue.h>
-#include <stdarg.h>
-#include <errno.h>
-#include <getopt.h>
-
-#include <netinet/in.h>
-#include <linux/if.h>
-#include <linux/if_tun.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-#include <signal.h>
-
-#include <rte_common.h>
-#include <rte_log.h>
-#include <rte_memory.h>
-#include <rte_memcpy.h>
-#include <rte_eal.h>
-#include <rte_per_lcore.h>
-#include <rte_launch.h>
-#include <rte_lcore.h>
-#include <rte_branch_prediction.h>
-#include <rte_interrupts.h>
-#include <rte_bus_pci.h>
-#include <rte_debug.h>
-#include <rte_ether.h>
-#include <rte_ethdev.h>
-#include <rte_mempool.h>
-#include <rte_mbuf.h>
-#include <rte_string_fns.h>
-#include <rte_cycles.h>
-#include <rte_malloc.h>
-#include <rte_kni.h>
-
-/* Macros for printing using RTE_LOG */
-#define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1
-
-/* Max size of a single packet */
-#define MAX_PACKET_SZ           2048
-
-/* Size of the data buffer in each mbuf */
-#define MBUF_DATA_SZ (MAX_PACKET_SZ + RTE_PKTMBUF_HEADROOM)
-
-/* Number of mbufs in mempool that is created */
-#define NB_MBUF                 (8192 * 16)
-
-/* How many packets to attempt to read from NIC in one go */
-#define PKT_BURST_SZ            32
-
-/* How many objects (mbufs) to keep in per-lcore mempool cache */
-#define MEMPOOL_CACHE_SZ        PKT_BURST_SZ
-
-/* Number of RX ring descriptors */
-#define NB_RXD                  1024
-
-/* Number of TX ring descriptors */
-#define NB_TXD                  1024
-
-/* Total octets in ethernet header */
-#define KNI_ENET_HEADER_SIZE    14
-
-/* Total octets in the FCS */
-#define KNI_ENET_FCS_SIZE       4
-
-#define KNI_US_PER_SECOND       1000000
-#define KNI_SECOND_PER_DAY      86400
-
-#define KNI_MAX_KTHREAD 32
-/*
- * Structure of port parameters
- */
-struct kni_port_params {
-	uint16_t port_id;/* Port ID */
-	unsigned lcore_rx; /* lcore ID for RX */
-	unsigned lcore_tx; /* lcore ID for TX */
-	uint32_t nb_lcore_k; /* Number of lcores for KNI multi kernel threads */
-	uint32_t nb_kni; /* Number of KNI devices to be created */
-	unsigned lcore_k[KNI_MAX_KTHREAD]; /* lcore ID list for kthreads */
-	struct rte_kni *kni[KNI_MAX_KTHREAD]; /* KNI context pointers */
-} __rte_cache_aligned;
-
-static struct kni_port_params *kni_port_params_array[RTE_MAX_ETHPORTS];
-
-
-/* Options for configuring ethernet port */
-static struct rte_eth_conf port_conf = {
-	.txmode = {
-		.mq_mode = RTE_ETH_MQ_TX_NONE,
-	},
-};
-
-/* Mempool for mbufs */
-static struct rte_mempool * pktmbuf_pool = NULL;
-
-/* Mask of enabled ports */
-static uint32_t ports_mask = 0;
-/* Ports set in promiscuous mode off by default. */
-static int promiscuous_on = 0;
-/* Monitor link status continually. off by default. */
-static int monitor_links;
-
-/* Structure type for recording kni interface specific stats */
-struct kni_interface_stats {
-	/* number of pkts received from NIC, and sent to KNI */
-	uint64_t rx_packets;
-
-	/* number of pkts received from NIC, but failed to send to KNI */
-	uint64_t rx_dropped;
-
-	/* number of pkts received from KNI, and sent to NIC */
-	uint64_t tx_packets;
-
-	/* number of pkts received from KNI, but failed to send to NIC */
-	uint64_t tx_dropped;
-};
-
-/* kni device statistics array */
-static struct kni_interface_stats kni_stats[RTE_MAX_ETHPORTS];
-
-static int kni_change_mtu(uint16_t port_id, unsigned int new_mtu);
-static int kni_config_network_interface(uint16_t port_id, uint8_t if_up);
-static int kni_config_mac_address(uint16_t port_id, uint8_t mac_addr[]);
-
-static uint32_t kni_stop;
-static uint32_t kni_pause;
-
-/* Print out statistics on packets handled */
-static void
-print_stats(void)
-{
-	uint16_t i;
-
-	printf("\n**KNI example application statistics**\n"
-	       "======  ==============  ============  ============  ============  ============\n"
-	       " Port    Lcore(RX/TX)    rx_packets    rx_dropped    tx_packets    tx_dropped\n"
-	       "------  --------------  ------------  ------------  ------------  ------------\n");
-	for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
-		if (!kni_port_params_array[i])
-			continue;
-
-		printf("%7d %10u/%2u %13"PRIu64" %13"PRIu64" %13"PRIu64" "
-							"%13"PRIu64"\n", i,
-					kni_port_params_array[i]->lcore_rx,
-					kni_port_params_array[i]->lcore_tx,
-						kni_stats[i].rx_packets,
-						kni_stats[i].rx_dropped,
-						kni_stats[i].tx_packets,
-						kni_stats[i].tx_dropped);
-	}
-	printf("======  ==============  ============  ============  ============  ============\n");
-
-	fflush(stdout);
-}
-
-/* Custom handling of signals to handle stats and kni processing */
-static void
-signal_handler(int signum)
-{
-	/* When we receive a USR1 signal, print stats */
-	if (signum == SIGUSR1) {
-		print_stats();
-	}
-
-	/* When we receive a USR2 signal, reset stats */
-	if (signum == SIGUSR2) {
-		memset(&kni_stats, 0, sizeof(kni_stats));
-		printf("\n** Statistics have been reset **\n");
-		return;
-	}
-
-	/*
-	 * When we receive a RTMIN or SIGINT or SIGTERM signal,
-	 * stop kni processing
-	 */
-	if (signum == SIGRTMIN || signum == SIGINT || signum == SIGTERM) {
-		printf("\nSIGRTMIN/SIGINT/SIGTERM received. "
-			"KNI processing stopping.\n");
-		__atomic_fetch_add(&kni_stop, 1, __ATOMIC_RELAXED);
-		return;
-        }
-}
-
-static void
-kni_burst_free_mbufs(struct rte_mbuf **pkts, unsigned num)
-{
-	unsigned i;
-
-	if (pkts == NULL)
-		return;
-
-	for (i = 0; i < num; i++) {
-		rte_pktmbuf_free(pkts[i]);
-		pkts[i] = NULL;
-	}
-}
-
-/**
- * Interface to burst rx and enqueue mbufs into rx_q
- */
-static void
-kni_ingress(struct kni_port_params *p)
-{
-	uint8_t i;
-	uint16_t port_id;
-	unsigned nb_rx, num;
-	uint32_t nb_kni;
-	struct rte_mbuf *pkts_burst[PKT_BURST_SZ];
-
-	if (p == NULL)
-		return;
-
-	nb_kni = p->nb_kni;
-	port_id = p->port_id;
-	for (i = 0; i < nb_kni; i++) {
-		/* Burst rx from eth */
-		nb_rx = rte_eth_rx_burst(port_id, 0, pkts_burst, PKT_BURST_SZ);
-		if (unlikely(nb_rx > PKT_BURST_SZ)) {
-			RTE_LOG(ERR, APP, "Error receiving from eth\n");
-			return;
-		}
-		/* Burst tx to kni */
-		num = rte_kni_tx_burst(p->kni[i], pkts_burst, nb_rx);
-		if (num)
-			kni_stats[port_id].rx_packets += num;
-
-		rte_kni_handle_request(p->kni[i]);
-		if (unlikely(num < nb_rx)) {
-			/* Free mbufs not tx to kni interface */
-			kni_burst_free_mbufs(&pkts_burst[num], nb_rx - num);
-			kni_stats[port_id].rx_dropped += nb_rx - num;
-		}
-	}
-}
-
-/**
- * Interface to dequeue mbufs from tx_q and burst tx
- */
-static void
-kni_egress(struct kni_port_params *p)
-{
-	uint8_t i;
-	uint16_t port_id;
-	unsigned nb_tx, num;
-	uint32_t nb_kni;
-	struct rte_mbuf *pkts_burst[PKT_BURST_SZ];
-
-	if (p == NULL)
-		return;
-
-	nb_kni = p->nb_kni;
-	port_id = p->port_id;
-	for (i = 0; i < nb_kni; i++) {
-		/* Burst rx from kni */
-		num = rte_kni_rx_burst(p->kni[i], pkts_burst, PKT_BURST_SZ);
-		if (unlikely(num > PKT_BURST_SZ)) {
-			RTE_LOG(ERR, APP, "Error receiving from KNI\n");
-			return;
-		}
-		/* Burst tx to eth */
-		nb_tx = rte_eth_tx_burst(port_id, 0, pkts_burst, (uint16_t)num);
-		if (nb_tx)
-			kni_stats[port_id].tx_packets += nb_tx;
-		if (unlikely(nb_tx < num)) {
-			/* Free mbufs not tx to NIC */
-			kni_burst_free_mbufs(&pkts_burst[nb_tx], num - nb_tx);
-			kni_stats[port_id].tx_dropped += num - nb_tx;
-		}
-	}
-}
-
-static int
-main_loop(__rte_unused void *arg)
-{
-	uint16_t i;
-	int32_t f_stop;
-	int32_t f_pause;
-	const unsigned lcore_id = rte_lcore_id();
-	enum lcore_rxtx {
-		LCORE_NONE,
-		LCORE_RX,
-		LCORE_TX,
-		LCORE_MAX
-	};
-	enum lcore_rxtx flag = LCORE_NONE;
-
-	RTE_ETH_FOREACH_DEV(i) {
-		if (!kni_port_params_array[i])
-			continue;
-		if (kni_port_params_array[i]->lcore_rx == (uint8_t)lcore_id) {
-			flag = LCORE_RX;
-			break;
-		} else if (kni_port_params_array[i]->lcore_tx ==
-						(uint8_t)lcore_id) {
-			flag = LCORE_TX;
-			break;
-		}
-	}
-
-	if (flag == LCORE_RX) {
-		RTE_LOG(INFO, APP, "Lcore %u is reading from port %d\n",
-					kni_port_params_array[i]->lcore_rx,
-					kni_port_params_array[i]->port_id);
-		while (1) {
-			f_stop = __atomic_load_n(&kni_stop, __ATOMIC_RELAXED);
-			f_pause = __atomic_load_n(&kni_pause, __ATOMIC_RELAXED);
-			if (f_stop)
-				break;
-			if (f_pause)
-				continue;
-			kni_ingress(kni_port_params_array[i]);
-		}
-	} else if (flag == LCORE_TX) {
-		RTE_LOG(INFO, APP, "Lcore %u is writing to port %d\n",
-					kni_port_params_array[i]->lcore_tx,
-					kni_port_params_array[i]->port_id);
-		while (1) {
-			f_stop = __atomic_load_n(&kni_stop, __ATOMIC_RELAXED);
-			f_pause = __atomic_load_n(&kni_pause, __ATOMIC_RELAXED);
-			if (f_stop)
-				break;
-			if (f_pause)
-				continue;
-			kni_egress(kni_port_params_array[i]);
-		}
-	} else
-		RTE_LOG(INFO, APP, "Lcore %u has nothing to do\n", lcore_id);
-
-	return 0;
-}
-
-/* Display usage instructions */
-static void
-print_usage(const char *prgname)
-{
-	RTE_LOG(INFO, APP, "\nUsage: %s [EAL options] -- -p PORTMASK -P -m "
-		   "[--config (port,lcore_rx,lcore_tx,lcore_kthread...)"
-		   "[,(port,lcore_rx,lcore_tx,lcore_kthread...)]]\n"
-		   "    -p PORTMASK: hex bitmask of ports to use\n"
-		   "    -P : enable promiscuous mode\n"
-		   "    -m : enable monitoring of port carrier state\n"
-		   "    --config (port,lcore_rx,lcore_tx,lcore_kthread...): "
-		   "port and lcore configurations\n",
-	           prgname);
-}
-
-/* Convert string to unsigned number. 0 is returned if error occurs */
-static uint32_t
-parse_unsigned(const char *portmask)
-{
-	char *end = NULL;
-	unsigned long num;
-
-	num = strtoul(portmask, &end, 16);
-	if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0'))
-		return 0;
-
-	return (uint32_t)num;
-}
-
-static void
-print_config(void)
-{
-	uint32_t i, j;
-	struct kni_port_params **p = kni_port_params_array;
-
-	for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
-		if (!p[i])
-			continue;
-		RTE_LOG(DEBUG, APP, "Port ID: %d\n", p[i]->port_id);
-		RTE_LOG(DEBUG, APP, "Rx lcore ID: %u, Tx lcore ID: %u\n",
-					p[i]->lcore_rx, p[i]->lcore_tx);
-		for (j = 0; j < p[i]->nb_lcore_k; j++)
-			RTE_LOG(DEBUG, APP, "Kernel thread lcore ID: %u\n",
-							p[i]->lcore_k[j]);
-	}
-}
-
-static int
-parse_config(const char *arg)
-{
-	const char *p, *p0 = arg;
-	char s[256], *end;
-	unsigned size;
-	enum fieldnames {
-		FLD_PORT = 0,
-		FLD_LCORE_RX,
-		FLD_LCORE_TX,
-		_NUM_FLD = KNI_MAX_KTHREAD + 3,
-	};
-	int i, j, nb_token;
-	char *str_fld[_NUM_FLD];
-	unsigned long int_fld[_NUM_FLD];
-	uint16_t port_id, nb_kni_port_params = 0;
-
-	memset(&kni_port_params_array, 0, sizeof(kni_port_params_array));
-	while (((p = strchr(p0, '(')) != NULL) &&
-		nb_kni_port_params < RTE_MAX_ETHPORTS) {
-		p++;
-		if ((p0 = strchr(p, ')')) == NULL)
-			goto fail;
-		size = p0 - p;
-		if (size >= sizeof(s)) {
-			printf("Invalid config parameters\n");
-			goto fail;
-		}
-		snprintf(s, sizeof(s), "%.*s", size, p);
-		nb_token = rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',');
-		if (nb_token <= FLD_LCORE_TX) {
-			printf("Invalid config parameters\n");
-			goto fail;
-		}
-		for (i = 0; i < nb_token; i++) {
-			errno = 0;
-			int_fld[i] = strtoul(str_fld[i], &end, 0);
-			if (errno != 0 || end == str_fld[i]) {
-				printf("Invalid config parameters\n");
-				goto fail;
-			}
-		}
-
-		i = 0;
-		port_id = int_fld[i++];
-		if (port_id >= RTE_MAX_ETHPORTS) {
-			printf("Port ID %d could not exceed the maximum %d\n",
-						port_id, RTE_MAX_ETHPORTS);
-			goto fail;
-		}
-		if (kni_port_params_array[port_id]) {
-			printf("Port %d has been configured\n", port_id);
-			goto fail;
-		}
-		kni_port_params_array[port_id] =
-			rte_zmalloc("KNI_port_params",
-				    sizeof(struct kni_port_params), RTE_CACHE_LINE_SIZE);
-		kni_port_params_array[port_id]->port_id = port_id;
-		kni_port_params_array[port_id]->lcore_rx =
-					(uint8_t)int_fld[i++];
-		kni_port_params_array[port_id]->lcore_tx =
-					(uint8_t)int_fld[i++];
-		if (kni_port_params_array[port_id]->lcore_rx >= RTE_MAX_LCORE ||
-		kni_port_params_array[port_id]->lcore_tx >= RTE_MAX_LCORE) {
-			printf("lcore_rx %u or lcore_tx %u ID could not "
-						"exceed the maximum %u\n",
-				kni_port_params_array[port_id]->lcore_rx,
-				kni_port_params_array[port_id]->lcore_tx,
-						(unsigned)RTE_MAX_LCORE);
-			goto fail;
-		}
-		for (j = 0; i < nb_token && j < KNI_MAX_KTHREAD; i++, j++)
-			kni_port_params_array[port_id]->lcore_k[j] =
-						(uint8_t)int_fld[i];
-		kni_port_params_array[port_id]->nb_lcore_k = j;
-	}
-	print_config();
-
-	return 0;
-
-fail:
-	for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
-		if (kni_port_params_array[i]) {
-			rte_free(kni_port_params_array[i]);
-			kni_port_params_array[i] = NULL;
-		}
-	}
-
-	return -1;
-}
-
-static int
-validate_parameters(uint32_t portmask)
-{
-	uint32_t i;
-
-	if (!portmask) {
-		printf("No port configured in port mask\n");
-		return -1;
-	}
-
-	for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
-		if (((portmask & (1 << i)) && !kni_port_params_array[i]) ||
-			(!(portmask & (1 << i)) && kni_port_params_array[i]))
-			rte_exit(EXIT_FAILURE, "portmask is not consistent "
-				"to port ids specified in --config\n");
-
-		if (kni_port_params_array[i] && !rte_lcore_is_enabled(\
-			(unsigned)(kni_port_params_array[i]->lcore_rx)))
-			rte_exit(EXIT_FAILURE, "lcore id %u for "
-					"port %d receiving not enabled\n",
-					kni_port_params_array[i]->lcore_rx,
-					kni_port_params_array[i]->port_id);
-
-		if (kni_port_params_array[i] && !rte_lcore_is_enabled(\
-			(unsigned)(kni_port_params_array[i]->lcore_tx)))
-			rte_exit(EXIT_FAILURE, "lcore id %u for "
-					"port %d transmitting not enabled\n",
-					kni_port_params_array[i]->lcore_tx,
-					kni_port_params_array[i]->port_id);
-
-	}
-
-	return 0;
-}
-
-#define CMDLINE_OPT_CONFIG  "config"
-
-/* Parse the arguments given in the command line of the application */
-static int
-parse_args(int argc, char **argv)
-{
-	int opt, longindex, ret = 0;
-	const char *prgname = argv[0];
-	static struct option longopts[] = {
-		{CMDLINE_OPT_CONFIG, required_argument, NULL, 0},
-		{NULL, 0, NULL, 0}
-	};
-
-	/* Disable printing messages within getopt() */
-	opterr = 0;
-
-	/* Parse command line */
-	while ((opt = getopt_long(argc, argv, "p:Pm", longopts,
-						&longindex)) != EOF) {
-		switch (opt) {
-		case 'p':
-			ports_mask = parse_unsigned(optarg);
-			break;
-		case 'P':
-			promiscuous_on = 1;
-			break;
-		case 'm':
-			monitor_links = 1;
-			break;
-		case 0:
-			if (!strncmp(longopts[longindex].name,
-				     CMDLINE_OPT_CONFIG,
-				     sizeof(CMDLINE_OPT_CONFIG))) {
-				ret = parse_config(optarg);
-				if (ret) {
-					printf("Invalid config\n");
-					print_usage(prgname);
-					return -1;
-				}
-			}
-			break;
-		default:
-			print_usage(prgname);
-			rte_exit(EXIT_FAILURE, "Invalid option specified\n");
-		}
-	}
-
-	/* Check that options were parsed ok */
-	if (validate_parameters(ports_mask) < 0) {
-		print_usage(prgname);
-		rte_exit(EXIT_FAILURE, "Invalid parameters\n");
-	}
-
-	return ret;
-}
-
-/* Initialize KNI subsystem */
-static void
-init_kni(void)
-{
-	unsigned int num_of_kni_ports = 0, i;
-	struct kni_port_params **params = kni_port_params_array;
-
-	/* Calculate the maximum number of KNI interfaces that will be used */
-	for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
-		if (kni_port_params_array[i]) {
-			num_of_kni_ports += (params[i]->nb_lcore_k ?
-				params[i]->nb_lcore_k : 1);
-		}
-	}
-
-	/* Invoke rte KNI init to preallocate the ports */
-	rte_kni_init(num_of_kni_ports);
-}
-
-/* Initialise a single port on an Ethernet device */
-static void
-init_port(uint16_t port)
-{
-	int ret;
-	uint16_t nb_rxd = NB_RXD;
-	uint16_t nb_txd = NB_TXD;
-	struct rte_eth_dev_info dev_info;
-	struct rte_eth_rxconf rxq_conf;
-	struct rte_eth_txconf txq_conf;
-	struct rte_eth_conf local_port_conf = port_conf;
-
-	/* Initialise device and RX/TX queues */
-	RTE_LOG(INFO, APP, "Initialising port %u ...\n", (unsigned)port);
-	fflush(stdout);
-
-	ret = rte_eth_dev_info_get(port, &dev_info);
-	if (ret != 0)
-		rte_exit(EXIT_FAILURE,
-			"Error during getting device (port %u) info: %s\n",
-			port, strerror(-ret));
-
-	if (dev_info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE)
-		local_port_conf.txmode.offloads |=
-			RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE;
-	ret = rte_eth_dev_configure(port, 1, 1, &local_port_conf);
-	if (ret < 0)
-		rte_exit(EXIT_FAILURE, "Could not configure port%u (%d)\n",
-		            (unsigned)port, ret);
-
-	ret = rte_eth_dev_adjust_nb_rx_tx_desc(port, &nb_rxd, &nb_txd);
-	if (ret < 0)
-		rte_exit(EXIT_FAILURE, "Could not adjust number of descriptors "
-				"for port%u (%d)\n", (unsigned)port, ret);
-
-	rxq_conf = dev_info.default_rxconf;
-	rxq_conf.offloads = local_port_conf.rxmode.offloads;
-	ret = rte_eth_rx_queue_setup(port, 0, nb_rxd,
-		rte_eth_dev_socket_id(port), &rxq_conf, pktmbuf_pool);
-	if (ret < 0)
-		rte_exit(EXIT_FAILURE, "Could not setup up RX queue for "
-				"port%u (%d)\n", (unsigned)port, ret);
-
-	txq_conf = dev_info.default_txconf;
-	txq_conf.offloads = local_port_conf.txmode.offloads;
-	ret = rte_eth_tx_queue_setup(port, 0, nb_txd,
-		rte_eth_dev_socket_id(port), &txq_conf);
-	if (ret < 0)
-		rte_exit(EXIT_FAILURE, "Could not setup up TX queue for "
-				"port%u (%d)\n", (unsigned)port, ret);
-
-	ret = rte_eth_dev_start(port);
-	if (ret < 0)
-		rte_exit(EXIT_FAILURE, "Could not start port%u (%d)\n",
-						(unsigned)port, ret);
-
-	if (promiscuous_on) {
-		ret = rte_eth_promiscuous_enable(port);
-		if (ret != 0)
-			rte_exit(EXIT_FAILURE,
-				"Could not enable promiscuous mode for port%u: %s\n",
-				port, rte_strerror(-ret));
-	}
-}
-
-/* Check the link status of all ports in up to 9s, and print them finally */
-static void
-check_all_ports_link_status(uint32_t port_mask)
-{
-#define CHECK_INTERVAL 100 /* 100ms */
-#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
-	uint16_t portid;
-	uint8_t count, all_ports_up, print_flag = 0;
-	struct rte_eth_link link;
-	int ret;
-	char link_status_text[RTE_ETH_LINK_MAX_STR_LEN];
-
-	printf("\nChecking link status\n");
-	fflush(stdout);
-	for (count = 0; count <= MAX_CHECK_TIME; count++) {
-		all_ports_up = 1;
-		RTE_ETH_FOREACH_DEV(portid) {
-			if ((port_mask & (1 << portid)) == 0)
-				continue;
-			memset(&link, 0, sizeof(link));
-			ret = rte_eth_link_get_nowait(portid, &link);
-			if (ret < 0) {
-				all_ports_up = 0;
-				if (print_flag == 1)
-					printf("Port %u link get failed: %s\n",
-						portid, rte_strerror(-ret));
-				continue;
-			}
-			/* print link status if flag set */
-			if (print_flag == 1) {
-				rte_eth_link_to_str(link_status_text,
-					sizeof(link_status_text), &link);
-				printf("Port %d %s\n", portid,
-					link_status_text);
-				continue;
-			}
-			/* clear all_ports_up flag if any link down */
-			if (link.link_status == RTE_ETH_LINK_DOWN) {
-				all_ports_up = 0;
-				break;
-			}
-		}
-		/* after finally printing all link status, get out */
-		if (print_flag == 1)
-			break;
-
-		if (all_ports_up == 0) {
-			printf(".");
-			fflush(stdout);
-			rte_delay_ms(CHECK_INTERVAL);
-		}
-
-		/* set the print_flag if all ports up or timeout */
-		if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
-			print_flag = 1;
-			printf("done\n");
-		}
-	}
-}
-
-static void
-log_link_state(struct rte_kni *kni, int prev, struct rte_eth_link *link)
-{
-	char link_status_text[RTE_ETH_LINK_MAX_STR_LEN];
-	if (kni == NULL || link == NULL)
-		return;
-
-	rte_eth_link_to_str(link_status_text, sizeof(link_status_text), link);
-	if (prev != link->link_status)
-		RTE_LOG(INFO, APP, "%s NIC %s\n",
-			rte_kni_get_name(kni),
-			link_status_text);
-}
-
-/*
- * Monitor the link status of all ports and update the
- * corresponding KNI interface(s)
- */
-static void *
-monitor_all_ports_link_status(void *arg)
-{
-	uint16_t portid;
-	struct rte_eth_link link;
-	unsigned int i;
-	struct kni_port_params **p = kni_port_params_array;
-	int prev;
-	(void) arg;
-	int ret;
-
-	while (monitor_links) {
-		rte_delay_ms(500);
-		RTE_ETH_FOREACH_DEV(portid) {
-			if ((ports_mask & (1 << portid)) == 0)
-				continue;
-			memset(&link, 0, sizeof(link));
-			ret = rte_eth_link_get_nowait(portid, &link);
-			if (ret < 0) {
-				RTE_LOG(ERR, APP,
-					"Get link failed (port %u): %s\n",
-					portid, rte_strerror(-ret));
-				continue;
-			}
-			for (i = 0; i < p[portid]->nb_kni; i++) {
-				prev = rte_kni_update_link(p[portid]->kni[i],
-						link.link_status);
-				log_link_state(p[portid]->kni[i], prev, &link);
-			}
-		}
-	}
-	return NULL;
-}
-
-static int
-kni_change_mtu_(uint16_t port_id, unsigned int new_mtu)
-{
-	int ret;
-	uint16_t nb_rxd = NB_RXD;
-	uint16_t nb_txd = NB_TXD;
-	struct rte_eth_conf conf;
-	struct rte_eth_dev_info dev_info;
-	struct rte_eth_rxconf rxq_conf;
-	struct rte_eth_txconf txq_conf;
-
-	if (!rte_eth_dev_is_valid_port(port_id)) {
-		RTE_LOG(ERR, APP, "Invalid port id %d\n", port_id);
-		return -EINVAL;
-	}
-
-	RTE_LOG(INFO, APP, "Change MTU of port %d to %u\n", port_id, new_mtu);
-
-	/* Stop specific port */
-	ret = rte_eth_dev_stop(port_id);
-	if (ret != 0) {
-		RTE_LOG(ERR, APP, "Failed to stop port %d: %s\n",
-			port_id, rte_strerror(-ret));
-		return ret;
-	}
-
-	memcpy(&conf, &port_conf, sizeof(conf));
-
-	conf.rxmode.mtu = new_mtu;
-	ret = rte_eth_dev_configure(port_id, 1, 1, &conf);
-	if (ret < 0) {
-		RTE_LOG(ERR, APP, "Fail to reconfigure port %d\n", port_id);
-		return ret;
-	}
-
-	ret = rte_eth_dev_adjust_nb_rx_tx_desc(port_id, &nb_rxd, &nb_txd);
-	if (ret < 0)
-		rte_exit(EXIT_FAILURE, "Could not adjust number of descriptors "
-				"for port%u (%d)\n", (unsigned int)port_id,
-				ret);
-
-	ret = rte_eth_dev_info_get(port_id, &dev_info);
-	if (ret != 0) {
-		RTE_LOG(ERR, APP,
-			"Error during getting device (port %u) info: %s\n",
-			port_id, strerror(-ret));
-
-		return ret;
-	}
-
-	rxq_conf = dev_info.default_rxconf;
-	rxq_conf.offloads = conf.rxmode.offloads;
-	ret = rte_eth_rx_queue_setup(port_id, 0, nb_rxd,
-		rte_eth_dev_socket_id(port_id), &rxq_conf, pktmbuf_pool);
-	if (ret < 0) {
-		RTE_LOG(ERR, APP, "Fail to setup Rx queue of port %d\n",
-				port_id);
-		return ret;
-	}
-
-	txq_conf = dev_info.default_txconf;
-	txq_conf.offloads = conf.txmode.offloads;
-	ret = rte_eth_tx_queue_setup(port_id, 0, nb_txd,
-		rte_eth_dev_socket_id(port_id), &txq_conf);
-	if (ret < 0) {
-		RTE_LOG(ERR, APP, "Fail to setup Tx queue of port %d\n",
-				port_id);
-		return ret;
-	}
-
-	/* Restart specific port */
-	ret = rte_eth_dev_start(port_id);
-	if (ret < 0) {
-		RTE_LOG(ERR, APP, "Fail to restart port %d\n", port_id);
-		return ret;
-	}
-
-	return 0;
-}
-
-/* Callback for request of changing MTU */
-static int
-kni_change_mtu(uint16_t port_id, unsigned int new_mtu)
-{
-	int ret;
-
-	__atomic_fetch_add(&kni_pause, 1, __ATOMIC_RELAXED);
-	ret =  kni_change_mtu_(port_id, new_mtu);
-	__atomic_fetch_sub(&kni_pause, 1, __ATOMIC_RELAXED);
-
-	return ret;
-}
-
-/* Callback for request of configuring network interface up/down */
-static int
-kni_config_network_interface(uint16_t port_id, uint8_t if_up)
-{
-	int ret = 0;
-
-	if (!rte_eth_dev_is_valid_port(port_id)) {
-		RTE_LOG(ERR, APP, "Invalid port id %d\n", port_id);
-		return -EINVAL;
-	}
-
-	RTE_LOG(INFO, APP, "Configure network interface of %d %s\n",
-					port_id, if_up ? "up" : "down");
-
-	__atomic_fetch_add(&kni_pause, 1, __ATOMIC_RELAXED);
-
-	if (if_up != 0) { /* Configure network interface up */
-		ret = rte_eth_dev_stop(port_id);
-		if (ret != 0) {
-			RTE_LOG(ERR, APP, "Failed to stop port %d: %s\n",
-				port_id, rte_strerror(-ret));
-			__atomic_fetch_sub(&kni_pause, 1, __ATOMIC_RELAXED);
-			return ret;
-		}
-		ret = rte_eth_dev_start(port_id);
-	} else { /* Configure network interface down */
-		ret = rte_eth_dev_stop(port_id);
-		if (ret != 0) {
-			RTE_LOG(ERR, APP, "Failed to stop port %d: %s\n",
-				port_id, rte_strerror(-ret));
-			__atomic_fetch_sub(&kni_pause, 1, __ATOMIC_RELAXED);
-			return ret;
-		}
-	}
-
-	__atomic_fetch_sub(&kni_pause, 1, __ATOMIC_RELAXED);
-
-	if (ret < 0)
-		RTE_LOG(ERR, APP, "Failed to start port %d\n", port_id);
-
-	return ret;
-}
-
-static void
-print_ethaddr(const char *name, struct rte_ether_addr *mac_addr)
-{
-	char buf[RTE_ETHER_ADDR_FMT_SIZE];
-	rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, mac_addr);
-	RTE_LOG(INFO, APP, "\t%s%s\n", name, buf);
-}
-
-/* Callback for request of configuring mac address */
-static int
-kni_config_mac_address(uint16_t port_id, uint8_t mac_addr[])
-{
-	int ret = 0;
-
-	if (!rte_eth_dev_is_valid_port(port_id)) {
-		RTE_LOG(ERR, APP, "Invalid port id %d\n", port_id);
-		return -EINVAL;
-	}
-
-	RTE_LOG(INFO, APP, "Configure mac address of %d\n", port_id);
-	print_ethaddr("Address:", (struct rte_ether_addr *)mac_addr);
-
-	ret = rte_eth_dev_default_mac_addr_set(port_id,
-					(struct rte_ether_addr *)mac_addr);
-	if (ret < 0)
-		RTE_LOG(ERR, APP, "Failed to config mac_addr for port %d\n",
-			port_id);
-
-	return ret;
-}
-
-static int
-kni_alloc(uint16_t port_id)
-{
-	uint8_t i;
-	struct rte_kni *kni;
-	struct rte_kni_conf conf;
-	struct kni_port_params **params = kni_port_params_array;
-	int ret;
-
-	if (port_id >= RTE_MAX_ETHPORTS || !params[port_id])
-		return -1;
-
-	params[port_id]->nb_kni = params[port_id]->nb_lcore_k ?
-				params[port_id]->nb_lcore_k : 1;
-
-	for (i = 0; i < params[port_id]->nb_kni; i++) {
-		/* Clear conf at first */
-		memset(&conf, 0, sizeof(conf));
-		if (params[port_id]->nb_lcore_k) {
-			snprintf(conf.name, RTE_KNI_NAMESIZE,
-					"vEth%u_%u", port_id, i);
-			conf.core_id = params[port_id]->lcore_k[i];
-			conf.force_bind = 1;
-		} else
-			snprintf(conf.name, RTE_KNI_NAMESIZE,
-						"vEth%u", port_id);
-		conf.group_id = port_id;
-		conf.mbuf_size = MAX_PACKET_SZ;
-		/*
-		 * The first KNI device associated to a port
-		 * is the main, for multiple kernel thread
-		 * environment.
-		 */
-		if (i == 0) {
-			struct rte_kni_ops ops;
-			struct rte_eth_dev_info dev_info;
-
-			ret = rte_eth_dev_info_get(port_id, &dev_info);
-			if (ret != 0)
-				rte_exit(EXIT_FAILURE,
-					"Error during getting device (port %u) info: %s\n",
-					port_id, strerror(-ret));
-
-			/* Get the interface default mac address */
-			ret = rte_eth_macaddr_get(port_id,
-				(struct rte_ether_addr *)&conf.mac_addr);
-			if (ret != 0)
-				rte_exit(EXIT_FAILURE,
-					"Failed to get MAC address (port %u): %s\n",
-					port_id, rte_strerror(-ret));
-
-			rte_eth_dev_get_mtu(port_id, &conf.mtu);
-
-			conf.min_mtu = dev_info.min_mtu;
-			conf.max_mtu = dev_info.max_mtu;
-
-			memset(&ops, 0, sizeof(ops));
-			ops.port_id = port_id;
-			ops.change_mtu = kni_change_mtu;
-			ops.config_network_if = kni_config_network_interface;
-			ops.config_mac_address = kni_config_mac_address;
-
-			kni = rte_kni_alloc(pktmbuf_pool, &conf, &ops);
-		} else
-			kni = rte_kni_alloc(pktmbuf_pool, &conf, NULL);
-
-		if (!kni)
-			rte_exit(EXIT_FAILURE, "Fail to create kni for "
-						"port: %d\n", port_id);
-		params[port_id]->kni[i] = kni;
-	}
-
-	return 0;
-}
-
-static int
-kni_free_kni(uint16_t port_id)
-{
-	uint8_t i;
-	int ret;
-	struct kni_port_params **p = kni_port_params_array;
-
-	if (port_id >= RTE_MAX_ETHPORTS || !p[port_id])
-		return -1;
-
-	for (i = 0; i < p[port_id]->nb_kni; i++) {
-		if (rte_kni_release(p[port_id]->kni[i]))
-			printf("Fail to release kni\n");
-		p[port_id]->kni[i] = NULL;
-	}
-	ret = rte_eth_dev_stop(port_id);
-	if (ret != 0)
-		RTE_LOG(ERR, APP, "Failed to stop port %d: %s\n",
-			port_id, rte_strerror(-ret));
-	rte_eth_dev_close(port_id);
-
-	return 0;
-}
-
-/* Initialise ports/queues etc. and start main loop on each core */
-int
-main(int argc, char** argv)
-{
-	int ret;
-	uint16_t nb_sys_ports, port;
-	unsigned i;
-	void *retval;
-	pthread_t kni_link_tid;
-	int pid;
-
-	/* Associate signal_handler function with USR signals */
-	signal(SIGUSR1, signal_handler);
-	signal(SIGUSR2, signal_handler);
-	signal(SIGRTMIN, signal_handler);
-	signal(SIGINT, signal_handler);
-	signal(SIGTERM, signal_handler);
-
-	/* Initialise EAL */
-	ret = rte_eal_init(argc, argv);
-	if (ret < 0)
-		rte_exit(EXIT_FAILURE, "Could not initialise EAL (%d)\n", ret);
-	argc -= ret;
-	argv += ret;
-
-	/* Parse application arguments (after the EAL ones) */
-	ret = parse_args(argc, argv);
-	if (ret < 0)
-		rte_exit(EXIT_FAILURE, "Could not parse input parameters\n");
-
-	/* Create the mbuf pool */
-	pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF,
-		MEMPOOL_CACHE_SZ, 0, MBUF_DATA_SZ, rte_socket_id());
-	if (pktmbuf_pool == NULL) {
-		rte_exit(EXIT_FAILURE, "Could not initialise mbuf pool\n");
-		return -1;
-	}
-
-	/* Get number of ports found in scan */
-	nb_sys_ports = rte_eth_dev_count_avail();
-	if (nb_sys_ports == 0)
-		rte_exit(EXIT_FAILURE, "No supported Ethernet device found\n");
-
-	/* Check if the configured port ID is valid */
-	for (i = 0; i < RTE_MAX_ETHPORTS; i++)
-		if (kni_port_params_array[i] && !rte_eth_dev_is_valid_port(i))
-			rte_exit(EXIT_FAILURE, "Configured invalid "
-						"port ID %u\n", i);
-
-	/* Initialize KNI subsystem */
-	init_kni();
-
-	/* Initialise each port */
-	RTE_ETH_FOREACH_DEV(port) {
-		/* Skip ports that are not enabled */
-		if (!(ports_mask & (1 << port)))
-			continue;
-		init_port(port);
-
-		if (port >= RTE_MAX_ETHPORTS)
-			rte_exit(EXIT_FAILURE, "Can not use more than "
-				"%d ports for kni\n", RTE_MAX_ETHPORTS);
-
-		kni_alloc(port);
-	}
-	check_all_ports_link_status(ports_mask);
-
-	pid = getpid();
-	RTE_LOG(INFO, APP, "========================\n");
-	RTE_LOG(INFO, APP, "KNI Running\n");
-	RTE_LOG(INFO, APP, "kill -SIGUSR1 %d\n", pid);
-	RTE_LOG(INFO, APP, "    Show KNI Statistics.\n");
-	RTE_LOG(INFO, APP, "kill -SIGUSR2 %d\n", pid);
-	RTE_LOG(INFO, APP, "    Zero KNI Statistics.\n");
-	RTE_LOG(INFO, APP, "========================\n");
-	fflush(stdout);
-
-	ret = rte_ctrl_thread_create(&kni_link_tid,
-				     "KNI link status check", NULL,
-				     monitor_all_ports_link_status, NULL);
-	if (ret < 0)
-		rte_exit(EXIT_FAILURE,
-			"Could not create link status thread!\n");
-
-	/* Launch per-lcore function on every lcore */
-	rte_eal_mp_remote_launch(main_loop, NULL, CALL_MAIN);
-	RTE_LCORE_FOREACH_WORKER(i) {
-		if (rte_eal_wait_lcore(i) < 0)
-			return -1;
-	}
-	monitor_links = 0;
-	pthread_join(kni_link_tid, &retval);
-
-	/* Release resources */
-	RTE_ETH_FOREACH_DEV(port) {
-		if (!(ports_mask & (1 << port)))
-			continue;
-		kni_free_kni(port);
-	}
-	for (i = 0; i < RTE_MAX_ETHPORTS; i++)
-		if (kni_port_params_array[i]) {
-			rte_free(kni_port_params_array[i]);
-			kni_port_params_array[i] = NULL;
-		}
-
-	/* clean up the EAL */
-	rte_eal_cleanup();
-
-	return 0;
-}
diff --git a/examples/kni/meson.build b/examples/kni/meson.build
deleted file mode 100644
index 6bd4eb50e6..0000000000
--- a/examples/kni/meson.build
+++ /dev/null
@@ -1,13 +0,0 @@
-# SPDX-License-Identifier: BSD-3-Clause
-# Copyright(c) 2017 Intel Corporation
-
-# meson file, for building this example as part of a main DPDK build.
-#
-# To build this example as a standalone application with an already-installed
-# DPDK instance, use 'make'
-
-deps += ['kni', 'bus_pci']
-sources = files(
-        'main.c',
-)
-allow_experimental_apis = true
diff --git a/examples/meson.build b/examples/meson.build
index 81e93799f2..6968c09252 100644
--- a/examples/meson.build
+++ b/examples/meson.build
@@ -24,7 +24,6 @@ all_examples = [
         'ip_reassembly',
         'ipsec-secgw',
         'ipv4_multicast',
-        'kni',
         'l2fwd',
         'l2fwd-cat',
         'l2fwd-crypto',
--
2.34.1


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

* Re: [PATCH v2] examples/kni: remove deprecated kni example
  2022-09-20 15:51 ` [PATCH v2] " Bruce Richardson
@ 2022-10-03 16:11   ` Thomas Monjalon
  2022-10-03 16:47     ` Stephen Hemminger
  0 siblings, 1 reply; 6+ messages in thread
From: Thomas Monjalon @ 2022-10-03 16:11 UTC (permalink / raw)
  To: Bruce Richardson; +Cc: dev

20/09/2022 17:51, Bruce Richardson:
> As part of the agreed process for deprecating KNI in DPDK, the example
> app is scheduled for removal as part of the 22.11 release.
> 
> Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> ---
> V2: Correct old release note links to KNI guide by referencing older doc

Acked-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Thomas Monjalon <thomas@monjalon.net>

Applied, thanks.





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

* Re: [PATCH v2] examples/kni: remove deprecated kni example
  2022-10-03 16:11   ` Thomas Monjalon
@ 2022-10-03 16:47     ` Stephen Hemminger
  2022-10-03 17:09       ` Thomas Monjalon
  0 siblings, 1 reply; 6+ messages in thread
From: Stephen Hemminger @ 2022-10-03 16:47 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: Bruce Richardson, dev

On Mon, 03 Oct 2022 18:11:08 +0200
Thomas Monjalon <thomas@monjalon.net> wrote:

> 20/09/2022 17:51, Bruce Richardson:
> > As part of the agreed process for deprecating KNI in DPDK, the example
> > app is scheduled for removal as part of the 22.11 release.
> > 
> > Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> > ---
> > V2: Correct old release note links to KNI guide by referencing older doc  
> 
> Acked-by: Stephen Hemminger <stephen@networkplumber.org>
> Acked-by: Thomas Monjalon <thomas@monjalon.net>
> 
> Applied, thanks.

What about many of the other places that refer or use KNI?
The packet framework, port library and ip_pipeline all have kni hooks.

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

* Re: [PATCH v2] examples/kni: remove deprecated kni example
  2022-10-03 16:47     ` Stephen Hemminger
@ 2022-10-03 17:09       ` Thomas Monjalon
  0 siblings, 0 replies; 6+ messages in thread
From: Thomas Monjalon @ 2022-10-03 17:09 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: Bruce Richardson, dev

03/10/2022 18:47, Stephen Hemminger:
> On Mon, 03 Oct 2022 18:11:08 +0200
> Thomas Monjalon <thomas@monjalon.net> wrote:
> 
> > 20/09/2022 17:51, Bruce Richardson:
> > > As part of the agreed process for deprecating KNI in DPDK, the example
> > > app is scheduled for removal as part of the 22.11 release.
> > > 
> > > Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> > > ---
> > > V2: Correct old release note links to KNI guide by referencing older doc  
> > 
> > Acked-by: Stephen Hemminger <stephen@networkplumber.org>
> > Acked-by: Thomas Monjalon <thomas@monjalon.net>
> > 
> > Applied, thanks.
> 
> What about many of the other places that refer or use KNI?
> The packet framework, port library and ip_pipeline all have kni hooks.

This was only removing the example.
Someone needs to work on the other parts.
And we should add some warning at build time and runtime for KNI
in this release 22.11, as announced in the deprecation page.

Volunteer?



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

end of thread, other threads:[~2022-10-03 17:09 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-20 15:14 [PATCH] examples/kni: remove deprecated kni example Bruce Richardson
2022-09-20 15:25 ` Stephen Hemminger
2022-09-20 15:51 ` [PATCH v2] " Bruce Richardson
2022-10-03 16:11   ` Thomas Monjalon
2022-10-03 16:47     ` Stephen Hemminger
2022-10-03 17:09       ` Thomas Monjalon

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).