From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 60896A00C3; Tue, 20 Sep 2022 17:52:12 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 3F7DE40DFB; Tue, 20 Sep 2022 17:52:12 +0200 (CEST) Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by mails.dpdk.org (Postfix) with ESMTP id 1FD444069B for ; Tue, 20 Sep 2022 17:52:09 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1663689130; x=1695225130; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=S8Vd0a2FDWfWX2q5QJSaL5WbSWrVV+llVDFGHC0uSE4=; b=WTu4m4QJSpNwI4WRTiO7YbREr/yRcpOmdzY2sU7rdDyXjzmcQO8p/fwz T/fNdw/hsz7YHOdIEgyXGucb8hY3rRKA0aHVyNzM51mPM5BUe5ReCKGsB 6VHyPa7xsb/Q2RZ3ikahU1gp2Z+V/OLJWRnartJB+GJM1lLXqs8eJhoCO OS97R5kUgSJaiGY+c+h6+TZS3ly6FwfKu6Sn9LyVMVODuNkD/YrArnbwG /OW9YiawtO7DwtUPPVYUrezPPuBM6LHuE2SAmWAk2dTNLSByd5anvTHTZ cbsbEZPRWnjxzOQU1rBZ2nuFGInPnVnnXrHoErnP0Y116nuYrnAZTbUvr g==; X-IronPort-AV: E=McAfee;i="6500,9779,10476"; a="279463717" X-IronPort-AV: E=Sophos;i="5.93,331,1654585200"; d="scan'208";a="279463717" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Sep 2022 08:52:08 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.93,331,1654585200"; d="scan'208";a="652145874" Received: from silpixa00401385.ir.intel.com ([10.237.214.41]) by orsmga001.jf.intel.com with ESMTP; 20 Sep 2022 08:52:04 -0700 From: Bruce Richardson To: dev@dpdk.org Cc: Bruce Richardson Subject: [PATCH v2] examples/kni: remove deprecated kni example Date: Tue, 20 Sep 2022 16:51:56 +0100 Message-Id: <20220920155156.480170-1-bruce.richardson@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220920151453.374127-1-bruce.richardson@intel.com> References: <20220920151453.374127-1-bruce.richardson@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org 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 --- 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 `_: * 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//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 `_ 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 `_ 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 ` 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 ` -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 ` 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 ` -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 ` 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 /kernel/linux/kni/rte_kni.ko kthread_mode=multiple - # .//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 /kernel/linux/kni/rte_kni.ko kthread_mode=multiple - # .//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 `, :ref:`loopback mode ` -enabled, and the :ref:`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 /kernel/linux/kni/rte_kni.ko lo_mode=lo_mode_fifo carrier=on - # .//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 -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* 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