1d30ea906Sjfb8856606..  SPDX-License-Identifier: BSD-3-Clause
2d30ea906Sjfb8856606    Copyright(c) 2010-2014 Intel Corporation.
3a9643ea8Slogwang
4a9643ea8SlogwangKernel NIC Interface Sample Application
5a9643ea8Slogwang=======================================
6a9643ea8Slogwang
7a9643ea8SlogwangThe Kernel NIC Interface (KNI) is a DPDK control plane solution that
8a9643ea8Slogwangallows userspace applications to exchange packets with the kernel networking stack.
9a9643ea8SlogwangTo accomplish this, DPDK userspace applications use an IOCTL call
10a9643ea8Slogwangto request the creation of a KNI virtual device in the Linux* kernel.
11a9643ea8SlogwangThe IOCTL call provides interface information and the DPDK's physical address space,
12a9643ea8Slogwangwhich is re-mapped into the kernel address space by the KNI kernel loadable module
13a9643ea8Slogwangthat saves the information to a virtual device context.
14a9643ea8SlogwangThe DPDK creates FIFO queues for packet ingress and egress
15a9643ea8Slogwangto the kernel module for each device allocated.
16a9643ea8Slogwang
17a9643ea8SlogwangThe KNI kernel loadable module is a standard net driver,
18a9643ea8Slogwangwhich upon receiving the IOCTL call access the DPDK's FIFO queue to
19a9643ea8Slogwangreceive/transmit packets from/to the DPDK userspace application.
20a9643ea8SlogwangThe FIFO queues contain pointers to data packets in the DPDK. This:
21a9643ea8Slogwang
22a9643ea8Slogwang*   Provides a faster mechanism to interface with the kernel net stack and eliminates system calls
23a9643ea8Slogwang
244418919fSjohnjiang*   Facilitates the DPDK using standard Linux* userspace net tools (tshark, rsync, and so on)
25a9643ea8Slogwang
26a9643ea8Slogwang*   Eliminate the copy_to_user and copy_from_user operations on packets.
27a9643ea8Slogwang
28a9643ea8SlogwangThe Kernel NIC Interface sample application is a simple example that demonstrates the use
29a9643ea8Slogwangof the DPDK to create a path for packets to go through the Linux* kernel.
30a9643ea8SlogwangThis is done by creating one or more kernel net devices for each of the DPDK ports.
314418919fSjohnjiangThe application allows the use of standard Linux tools (ethtool, iproute, tshark) with the DPDK ports and
32a9643ea8Slogwangalso the exchange of packets between the DPDK application and the Linux* kernel.
33a9643ea8Slogwang
34d30ea906Sjfb8856606The Kernel NIC Interface sample application requires that the
35d30ea906Sjfb8856606KNI kernel module ``rte_kni`` be loaded into the kernel.  See
36d30ea906Sjfb8856606:doc:`../prog_guide/kernel_nic_interface` for more information on loading
37d30ea906Sjfb8856606the ``rte_kni`` kernel module.
38d30ea906Sjfb8856606
39a9643ea8SlogwangOverview
40a9643ea8Slogwang--------
41a9643ea8Slogwang
42d30ea906Sjfb8856606The Kernel NIC Interface sample application ``kni`` allocates one or more
43d30ea906Sjfb8856606KNI interfaces for each physical NIC port.  For each physical NIC port,
44d30ea906Sjfb8856606``kni`` uses two DPDK threads in user space; one thread reads from the port and
45d30ea906Sjfb8856606writes to the corresponding KNI interfaces and the other thread reads from
46d30ea906Sjfb8856606the KNI interfaces and writes the data unmodified to the physical NIC port.
47a9643ea8Slogwang
48d30ea906Sjfb8856606It is recommended to configure one KNI interface for each physical NIC port.
49d30ea906Sjfb8856606The application can be configured with more than one KNI interface for
50d30ea906Sjfb8856606each physical NIC port for performance testing or it can work together with
51d30ea906Sjfb8856606VMDq support in future.
52d30ea906Sjfb8856606
53d30ea906Sjfb8856606The packet flow through the Kernel NIC Interface application is as shown
54d30ea906Sjfb8856606in the following figure.
55a9643ea8Slogwang
56a9643ea8Slogwang.. _figure_kernel_nic:
57a9643ea8Slogwang
58a9643ea8Slogwang.. figure:: img/kernel_nic.*
59a9643ea8Slogwang
60a9643ea8Slogwang   Kernel NIC Application Packet Flow
61a9643ea8Slogwang
62d30ea906Sjfb8856606If link monitoring is enabled with the ``-m`` command line flag, one
63d30ea906Sjfb8856606additional pthread is launched which will check the link status of each
64d30ea906Sjfb8856606physical NIC port and will update the carrier status of the corresponding
65d30ea906Sjfb8856606KNI interface(s) to match the physical NIC port's state.  This means that
66d30ea906Sjfb8856606the KNI interface(s) will be disabled automatically when the Ethernet link
67d30ea906Sjfb8856606goes down and enabled when the Ethernet link goes up.
68d30ea906Sjfb8856606
69d30ea906Sjfb8856606If link monitoring is enabled, the ``rte_kni`` kernel module should be loaded
70d30ea906Sjfb8856606such that the :ref:`default carrier state <kni_default_carrier_state>` is
71d30ea906Sjfb8856606set to *off*.  This ensures that the KNI interface is only enabled *after*
72d30ea906Sjfb8856606the Ethernet link of the corresponding NIC port has reached the linkup state.
73d30ea906Sjfb8856606
74d30ea906Sjfb8856606If link monitoring is not enabled, the ``rte_kni`` kernel module should be
75d30ea906Sjfb8856606loaded with the :ref:`default carrier state <kni_default_carrier_state>`
76d30ea906Sjfb8856606set to *on*.  This sets the carrier state of the KNI interfaces to *on*
77d30ea906Sjfb8856606when the KNI interfaces are enabled without regard to the actual link state
78d30ea906Sjfb8856606of the corresponding NIC port.  This is useful for testing in loopback
79d30ea906Sjfb8856606mode where the NIC port may not be physically connected to anything.
80d30ea906Sjfb8856606
81a9643ea8SlogwangCompiling the Application
82a9643ea8Slogwang-------------------------
83a9643ea8Slogwang
842bfe3f2eSlogwangTo compile the sample application see :doc:`compiling`.
85a9643ea8Slogwang
86d30ea906Sjfb8856606The application is located in the ``examples/kni`` sub-directory.
87a9643ea8Slogwang
88a9643ea8Slogwang.. note::
89a9643ea8Slogwang
904418919fSjohnjiang        This application is intended as a linux only.
91a9643ea8Slogwang
92d30ea906Sjfb8856606Running the kni Example Application
93d30ea906Sjfb8856606-----------------------------------
94a9643ea8Slogwang
95d30ea906Sjfb8856606The ``kni`` example application requires a number of command line options:
96a9643ea8Slogwang
97a9643ea8Slogwang.. code-block:: console
98a9643ea8Slogwang
99*2d9fd380Sjfb8856606    dpdk-kni [EAL options] -- -p PORTMASK --config="(port,lcore_rx,lcore_tx[,lcore_kthread,...])[,(port,lcore_rx,lcore_tx[,lcore_kthread,...])]" [-P] [-m]
100a9643ea8Slogwang
101a9643ea8SlogwangWhere:
102a9643ea8Slogwang
103d30ea906Sjfb8856606*   ``-p PORTMASK``:
104a9643ea8Slogwang
105d30ea906Sjfb8856606    Hexadecimal bitmask of ports to configure.
106a9643ea8Slogwang
107d30ea906Sjfb8856606*   ``--config="(port,lcore_rx,lcore_tx[,lcore_kthread,...])[,(port,lcore_rx,lcore_tx[,lcore_kthread,...])]"``:
108a9643ea8Slogwang
109d30ea906Sjfb8856606    Determines which lcores the Rx and Tx DPDK tasks, and (optionally)
110d30ea906Sjfb8856606    the KNI kernel thread(s) are bound to for each physical port.
111a9643ea8Slogwang
112d30ea906Sjfb8856606*   ``-P``:
113a9643ea8Slogwang
114d30ea906Sjfb8856606    Optional flag to set all ports to promiscuous mode so that packets are
115d30ea906Sjfb8856606    accepted regardless of the packet's Ethernet MAC destination address.
116d30ea906Sjfb8856606    Without this option, only packets with the Ethernet MAC destination
117d30ea906Sjfb8856606    address set to the Ethernet address of the port are accepted.
118a9643ea8Slogwang
119d30ea906Sjfb8856606*   ``-m``:
120d30ea906Sjfb8856606
121d30ea906Sjfb8856606    Optional flag to enable monitoring and updating of the Ethernet
122d30ea906Sjfb8856606    carrier state.  With this option set, a thread will be started which
123d30ea906Sjfb8856606    will periodically check the Ethernet link status of the physical
124d30ea906Sjfb8856606    Ethernet ports and set the carrier state of the corresponding KNI
125d30ea906Sjfb8856606    network interface to match it.  This means that the KNI interface will
126d30ea906Sjfb8856606    be disabled automatically when the Ethernet link goes down and enabled
127d30ea906Sjfb8856606    when the Ethernet link goes up.
128d30ea906Sjfb8856606
129d30ea906Sjfb8856606Refer to *DPDK Getting Started Guide* for general information on running
130d30ea906Sjfb8856606applications and the Environment Abstraction Layer (EAL) options.
131d30ea906Sjfb8856606
132d30ea906Sjfb8856606The ``-c coremask`` or ``-l corelist`` parameter of the EAL options must
133d30ea906Sjfb8856606include the lcores specified by ``lcore_rx`` and ``lcore_tx`` for each port,
134d30ea906Sjfb8856606but does not need to include lcores specified by ``lcore_kthread`` as those
135d30ea906Sjfb8856606cores are used to pin the kernel threads in the ``rte_kni`` kernel module.
136d30ea906Sjfb8856606
137d30ea906Sjfb8856606The ``--config`` parameter must include a set of
138d30ea906Sjfb8856606``(port,lcore_rx,lcore_tx,[lcore_kthread,...])`` values for each physical
139d30ea906Sjfb8856606port specified in the ``-p PORTMASK`` parameter.
140d30ea906Sjfb8856606
141d30ea906Sjfb8856606The optional ``lcore_kthread`` lcore ID parameter in ``--config`` can be
142d30ea906Sjfb8856606specified zero, one or more times for each physical port.
143d30ea906Sjfb8856606
144d30ea906Sjfb8856606If no lcore ID is specified for ``lcore_kthread``, one KNI interface will
145d30ea906Sjfb8856606be created for the physical port ``port`` and the KNI kernel thread(s)
146d30ea906Sjfb8856606will have no specific core affinity.
147d30ea906Sjfb8856606
148d30ea906Sjfb8856606If one or more lcore IDs are specified for ``lcore_kthread``, a KNI interface
149d30ea906Sjfb8856606will be created for each lcore ID specified, bound to the physical port
150d30ea906Sjfb8856606``port``.  If the ``rte_kni`` kernel module is loaded in :ref:`multiple
151d30ea906Sjfb8856606kernel thread <kni_kernel_thread_mode>` mode, a kernel thread will be created
152d30ea906Sjfb8856606for each KNI interface and bound to the specified core.  If the ``rte_kni``
153d30ea906Sjfb8856606kernel module is loaded in :ref:`single kernel thread <kni_kernel_thread_mode>`
154d30ea906Sjfb8856606mode, only one kernel thread is started for all KNI interfaces.  The kernel
155d30ea906Sjfb8856606thread will be bound to the first ``lcore_kthread`` lcore ID specified.
156d30ea906Sjfb8856606
157d30ea906Sjfb8856606Example Configurations
158d30ea906Sjfb8856606~~~~~~~~~~~~~~~~~~~~~~~
159d30ea906Sjfb8856606
160d30ea906Sjfb8856606The following commands will first load the ``rte_kni`` kernel module in
161d30ea906Sjfb8856606:ref:`multiple kernel thread <kni_kernel_thread_mode>` mode.  The ``kni``
162d30ea906Sjfb8856606application is then started using two ports;  Port 0 uses lcore 4 for the
163d30ea906Sjfb8856606Rx task, lcore 6 for the Tx task, and will create a single KNI interface
164d30ea906Sjfb8856606``vEth0_0`` with the kernel thread bound to lcore 8.  Port 1 uses lcore
165d30ea906Sjfb88566065 for the Rx task, lcore 7 for the Tx task, and will create a single KNI
166d30ea906Sjfb8856606interface ``vEth1_0`` with the kernel thread bound to lcore 9.
167a9643ea8Slogwang
168a9643ea8Slogwang.. code-block:: console
169a9643ea8Slogwang
170d30ea906Sjfb8856606    # rmmod rte_kni
171*2d9fd380Sjfb8856606    # insmod <build_dir>/kernel/linux/kni/rte_kni.ko kthread_mode=multiple
172*2d9fd380Sjfb8856606    # ./<build-dir>/examples/dpdk-kni -l 4-7 -n 4 -- -P -p 0x3 -m --config="(0,4,6,8),(1,5,7,9)"
173d30ea906Sjfb8856606
174d30ea906Sjfb8856606The following example is identical, except an additional ``lcore_kthread``
175d30ea906Sjfb8856606core is specified per physical port.  In this case, ``kni`` will create
176d30ea906Sjfb8856606four KNI interfaces: ``vEth0_0``/``vEth0_1`` bound to physical port 0 and
177d30ea906Sjfb8856606``vEth1_0``/``vEth1_1`` bound to physical port 1.
178d30ea906Sjfb8856606
179d30ea906Sjfb8856606The kernel thread for each interface will be bound as follows:
180d30ea906Sjfb8856606
181d30ea906Sjfb8856606    * ``vEth0_0`` - bound to lcore 8.
182d30ea906Sjfb8856606    * ``vEth0_1`` - bound to lcore 10.
183d30ea906Sjfb8856606    * ``vEth1_0`` - bound to lcore 9.
184d30ea906Sjfb8856606    * ``vEth1_1`` - bound to lcore 11
185d30ea906Sjfb8856606
186d30ea906Sjfb8856606.. code-block:: console
187d30ea906Sjfb8856606
188d30ea906Sjfb8856606    # rmmod rte_kni
189*2d9fd380Sjfb8856606    # insmod <build_dir>/kernel/linux/kni/rte_kni.ko kthread_mode=multiple
190*2d9fd380Sjfb8856606    # ./<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)"
191d30ea906Sjfb8856606
192d30ea906Sjfb8856606The following example can be used to test the interface between the ``kni``
193d30ea906Sjfb8856606test application and the ``rte_kni`` kernel module.  In this example,
194d30ea906Sjfb8856606the ``rte_kni`` kernel module is loaded in :ref:`single kernel thread
195d30ea906Sjfb8856606mode <kni_kernel_thread_mode>`, :ref:`loopback mode <kni_loopback_mode>`
196d30ea906Sjfb8856606enabled, and the :ref:`default carrier state <kni_default_carrier_state>`
197d30ea906Sjfb8856606is set to *on* so that the corresponding physical NIC port does not have
198d30ea906Sjfb8856606to be connected in order to use the KNI interface.  One KNI interface
199d30ea906Sjfb8856606``vEth0_0`` is created for port 0 and one KNI interface ``vEth1_0`` is
200d30ea906Sjfb8856606created for port 1.  Since ``rte_kni`` is loaded in "single kernel thread"
201d30ea906Sjfb8856606mode, the one kernel thread is bound to lcore 8.
202d30ea906Sjfb8856606
203d30ea906Sjfb8856606Since the physical NIC ports are not being used, link monitoring can be
204d30ea906Sjfb8856606disabled by **not** specifying the ``-m`` flag to ``kni``:
205d30ea906Sjfb8856606
206d30ea906Sjfb8856606.. code-block:: console
207d30ea906Sjfb8856606
208d30ea906Sjfb8856606    # rmmod rte_kni
209*2d9fd380Sjfb8856606    # insmod <build_dir>/kernel/linux/kni/rte_kni.ko lo_mode=lo_mode_fifo carrier=on
210*2d9fd380Sjfb8856606    # ./<build-dir>/examples/dpdk-kni -l 4-7 -n 4 -- -P -p 0x3 --config="(0,4,6,8),(1,5,7,9)"
211a9643ea8Slogwang
212a9643ea8SlogwangKNI Operations
213a9643ea8Slogwang--------------
214a9643ea8Slogwang
215d30ea906Sjfb8856606Once the ``kni`` application is started, the user can use the normal
216d30ea906Sjfb8856606Linux commands to manage the KNI interfaces as if they were any other
217d30ea906Sjfb8856606Linux network interface.
218a9643ea8Slogwang
219d30ea906Sjfb8856606Enable KNI interface and assign an IP address:
220a9643ea8Slogwang
221a9643ea8Slogwang.. code-block:: console
222a9643ea8Slogwang
2234418919fSjohnjiang    # ip addr add dev vEth0_0 192.168.0.1
224a9643ea8Slogwang
225d30ea906Sjfb8856606Show KNI interface configuration and statistics:
226d30ea906Sjfb8856606
227d30ea906Sjfb8856606.. code-block:: console
228d30ea906Sjfb8856606
2294418919fSjohnjiang    # ip -s -d addr show vEth0_0
230d30ea906Sjfb8856606
231d30ea906Sjfb8856606The user can also check and reset the packet statistics inside the ``kni``
232d30ea906Sjfb8856606application by sending the app the USR1 and USR2 signals:
233d30ea906Sjfb8856606
234d30ea906Sjfb8856606.. code-block:: console
235d30ea906Sjfb8856606
236d30ea906Sjfb8856606    # Print statistics
2374418919fSjohnjiang    # pkill -USR1 kni
238d30ea906Sjfb8856606
239d30ea906Sjfb8856606    # Zero statistics
2404418919fSjohnjiang    # pkill -USR2 kni
241d30ea906Sjfb8856606
242d30ea906Sjfb8856606Dump network traffic:
243d30ea906Sjfb8856606
244d30ea906Sjfb8856606.. code-block:: console
245d30ea906Sjfb8856606
2464418919fSjohnjiang    # tshark -n -i vEth0_0
247d30ea906Sjfb8856606
248d30ea906Sjfb8856606The normal Linux commands can also be used to change the MAC address and
249d30ea906Sjfb8856606MTU size used by the physical NIC which corresponds to the KNI interface.
250d30ea906Sjfb8856606However, if more than one KNI interface is configured for a physical port,
251d30ea906Sjfb8856606these commands will only work on the first KNI interface for that port.
252d30ea906Sjfb8856606
253d30ea906Sjfb8856606Change the MAC address:
254d30ea906Sjfb8856606
255d30ea906Sjfb8856606.. code-block:: console
256d30ea906Sjfb8856606
2574418919fSjohnjiang    # ip link set dev vEth0_0 lladdr 0C:01:02:03:04:08
258d30ea906Sjfb8856606
259d30ea906Sjfb8856606Change the MTU size:
260d30ea906Sjfb8856606
261d30ea906Sjfb8856606.. code-block:: console
262d30ea906Sjfb8856606
2634418919fSjohnjiang    # ip link set dev vEth0_0 mtu 1450
264d30ea906Sjfb8856606
2654418919fSjohnjiangLimited ethtool support:
266a9643ea8Slogwang
267a9643ea8Slogwang.. code-block:: console
268a9643ea8Slogwang
2694418919fSjohnjiang    # ethtool -i vEth0_0
270a9643ea8Slogwang
271d30ea906Sjfb8856606When the ``kni`` application is closed, all the KNI interfaces are deleted
272d30ea906Sjfb8856606from the Linux kernel.
273a9643ea8Slogwang
274a9643ea8SlogwangExplanation
275a9643ea8Slogwang-----------
276a9643ea8Slogwang
277a9643ea8SlogwangThe following sections provide some explanation of code.
278a9643ea8Slogwang
279a9643ea8SlogwangInitialization
280a9643ea8Slogwang~~~~~~~~~~~~~~
281a9643ea8Slogwang
282a9643ea8SlogwangSetup of mbuf pool, driver and queues is similar to the setup done in the :doc:`l2_forward_real_virtual`..
283a9643ea8SlogwangIn addition, one or more kernel NIC interfaces are allocated for each
284a9643ea8Slogwangof the configured ports according to the command line parameters.
285a9643ea8Slogwang
286d30ea906Sjfb8856606The code for allocating the kernel NIC interfaces for a specific port is
287d30ea906Sjfb8856606in the function ``kni_alloc``.
288a9643ea8Slogwang
289a9643ea8SlogwangThe other step in the initialization process that is unique to this sample application
290a9643ea8Slogwangis the association of each port with lcores for RX, TX and kernel threads.
291a9643ea8Slogwang
292a9643ea8Slogwang*   One lcore to read from the port and write to the associated one or more KNI devices
293a9643ea8Slogwang
294a9643ea8Slogwang*   Another lcore to read from one or more KNI devices and write to the port
295a9643ea8Slogwang
296a9643ea8Slogwang*   Other lcores for pinning the kernel threads on one by one
297a9643ea8Slogwang
298d30ea906Sjfb8856606This is done by using the ``kni_port_params_array[]`` array, which is indexed by the port ID.
299d30ea906Sjfb8856606The code is in the function ``parse_config``.
300a9643ea8Slogwang
301a9643ea8SlogwangPacket Forwarding
302a9643ea8Slogwang~~~~~~~~~~~~~~~~~
303a9643ea8Slogwang
304a9643ea8SlogwangAfter the initialization steps are completed, the main_loop() function is run on each lcore.
305a9643ea8SlogwangThis function first checks the lcore_id against the user provided lcore_rx and lcore_tx
306a9643ea8Slogwangto see if this lcore is reading from or writing to kernel NIC interfaces.
307a9643ea8Slogwang
308d30ea906Sjfb8856606For the case that reads from a NIC port and writes to the kernel NIC interfaces (``kni_ingress``),
309a9643ea8Slogwangthe packet reception is the same as in L2 Forwarding sample application
310a9643ea8Slogwang(see :ref:`l2_fwd_app_rx_tx_packets`).
311d30ea906Sjfb8856606The packet transmission is done by sending mbufs into the kernel NIC interfaces by ``rte_kni_tx_burst()``.
312a9643ea8SlogwangThe KNI library automatically frees the mbufs after the kernel successfully copied the mbufs.
313a9643ea8Slogwang
314d30ea906Sjfb8856606For the other case that reads from kernel NIC interfaces
315d30ea906Sjfb8856606and writes to a physical NIC port (``kni_egress``),
316d30ea906Sjfb8856606packets are retrieved by reading mbufs from kernel NIC interfaces by ``rte_kni_rx_burst()``.
317a9643ea8SlogwangThe packet transmission is the same as in the L2 Forwarding sample application
318a9643ea8Slogwang(see :ref:`l2_fwd_app_rx_tx_packets`).
319