15630257fSFerruh Yigit..  SPDX-License-Identifier: BSD-3-Clause
25630257fSFerruh Yigit    Copyright(c) 2010-2014 Intel Corporation.
3d0dff9baSBernard Iremonger
4d0dff9baSBernard IremongerKernel NIC Interface Sample Application
5d0dff9baSBernard Iremonger=======================================
6d0dff9baSBernard Iremonger
7e0c7c473SSiobhan ButlerThe Kernel NIC Interface (KNI) is a DPDK control plane solution that
8d0dff9baSBernard Iremongerallows userspace applications to exchange packets with the kernel networking stack.
9e0c7c473SSiobhan ButlerTo accomplish this, DPDK userspace applications use an IOCTL call
10d0dff9baSBernard Iremongerto request the creation of a KNI virtual device in the Linux* kernel.
11e0c7c473SSiobhan ButlerThe IOCTL call provides interface information and the DPDK's physical address space,
12d0dff9baSBernard Iremongerwhich is re-mapped into the kernel address space by the KNI kernel loadable module
13d0dff9baSBernard Iremongerthat saves the information to a virtual device context.
14e0c7c473SSiobhan ButlerThe DPDK creates FIFO queues for packet ingress and egress
15d0dff9baSBernard Iremongerto the kernel module for each device allocated.
16d0dff9baSBernard Iremonger
17d0dff9baSBernard IremongerThe KNI kernel loadable module is a standard net driver,
18e0c7c473SSiobhan Butlerwhich upon receiving the IOCTL call access the DPDK's FIFO queue to
19e0c7c473SSiobhan Butlerreceive/transmit packets from/to the DPDK userspace application.
20e0c7c473SSiobhan ButlerThe FIFO queues contain pointers to data packets in the DPDK. This:
21d0dff9baSBernard Iremonger
22d0dff9baSBernard Iremonger*   Provides a faster mechanism to interface with the kernel net stack and eliminates system calls
23d0dff9baSBernard Iremonger
2489247e1aSStephen Hemminger*   Facilitates the DPDK using standard Linux* userspace net tools (tshark, rsync, and so on)
25d0dff9baSBernard Iremonger
26d0dff9baSBernard Iremonger*   Eliminate the copy_to_user and copy_from_user operations on packets.
27d0dff9baSBernard Iremonger
28d0dff9baSBernard IremongerThe Kernel NIC Interface sample application is a simple example that demonstrates the use
29e0c7c473SSiobhan Butlerof the DPDK to create a path for packets to go through the Linux* kernel.
30e0c7c473SSiobhan ButlerThis is done by creating one or more kernel net devices for each of the DPDK ports.
3189247e1aSStephen HemmingerThe application allows the use of standard Linux tools (ethtool, iproute, tshark) with the DPDK ports and
32e0c7c473SSiobhan Butleralso the exchange of packets between the DPDK application and the Linux* kernel.
33d0dff9baSBernard Iremonger
34724beb91SDan GoraThe Kernel NIC Interface sample application requires that the
35724beb91SDan GoraKNI kernel module ``rte_kni`` be loaded into the kernel.  See
36724beb91SDan Gora:doc:`../prog_guide/kernel_nic_interface` for more information on loading
37724beb91SDan Gorathe ``rte_kni`` kernel module.
38724beb91SDan Gora
39d0dff9baSBernard IremongerOverview
40d0dff9baSBernard Iremonger--------
41d0dff9baSBernard Iremonger
42724beb91SDan GoraThe Kernel NIC Interface sample application ``kni`` allocates one or more
43724beb91SDan GoraKNI interfaces for each physical NIC port.  For each physical NIC port,
44724beb91SDan Gora``kni`` uses two DPDK threads in user space; one thread reads from the port and
45724beb91SDan Gorawrites to the corresponding KNI interfaces and the other thread reads from
46724beb91SDan Gorathe KNI interfaces and writes the data unmodified to the physical NIC port.
47d0dff9baSBernard Iremonger
48724beb91SDan GoraIt is recommended to configure one KNI interface for each physical NIC port.
49724beb91SDan GoraThe application can be configured with more than one KNI interface for
50724beb91SDan Goraeach physical NIC port for performance testing or it can work together with
51724beb91SDan GoraVMDq support in future.
52724beb91SDan Gora
53724beb91SDan GoraThe packet flow through the Kernel NIC Interface application is as shown
54724beb91SDan Gorain the following figure.
55d0dff9baSBernard Iremonger
564a22e6eeSJohn McNamara.. _figure_kernel_nic:
57d0dff9baSBernard Iremonger
584a22e6eeSJohn McNamara.. figure:: img/kernel_nic.*
59d0dff9baSBernard Iremonger
604a22e6eeSJohn McNamara   Kernel NIC Application Packet Flow
61d0dff9baSBernard Iremonger
62724beb91SDan GoraIf link monitoring is enabled with the ``-m`` command line flag, one
63724beb91SDan Goraadditional pthread is launched which will check the link status of each
64724beb91SDan Goraphysical NIC port and will update the carrier status of the corresponding
65724beb91SDan GoraKNI interface(s) to match the physical NIC port's state.  This means that
66724beb91SDan Gorathe KNI interface(s) will be disabled automatically when the Ethernet link
67724beb91SDan Goragoes down and enabled when the Ethernet link goes up.
68724beb91SDan Gora
69724beb91SDan GoraIf link monitoring is enabled, the ``rte_kni`` kernel module should be loaded
70724beb91SDan Gorasuch that the :ref:`default carrier state <kni_default_carrier_state>` is
71724beb91SDan Goraset to *off*.  This ensures that the KNI interface is only enabled *after*
72724beb91SDan Gorathe Ethernet link of the corresponding NIC port has reached the linkup state.
73724beb91SDan Gora
74724beb91SDan GoraIf link monitoring is not enabled, the ``rte_kni`` kernel module should be
75724beb91SDan Goraloaded with the :ref:`default carrier state <kni_default_carrier_state>`
76724beb91SDan Goraset to *on*.  This sets the carrier state of the KNI interfaces to *on*
77724beb91SDan Gorawhen the KNI interfaces are enabled without regard to the actual link state
78724beb91SDan Goraof the corresponding NIC port.  This is useful for testing in loopback
79724beb91SDan Goramode where the NIC port may not be physically connected to anything.
80724beb91SDan Gora
81d0dff9baSBernard IremongerCompiling the Application
82d0dff9baSBernard Iremonger-------------------------
83d0dff9baSBernard Iremonger
847cacb056SHerakliusz LipiecTo compile the sample application see :doc:`compiling`.
85d0dff9baSBernard Iremonger
86724beb91SDan GoraThe application is located in the ``examples/kni`` sub-directory.
87d0dff9baSBernard Iremonger
88d0dff9baSBernard Iremonger.. note::
89d0dff9baSBernard Iremonger
90218c4e68SBruce Richardson        This application is intended as a linux only.
91d0dff9baSBernard Iremonger
92724beb91SDan GoraRunning the kni Example Application
93724beb91SDan Gora-----------------------------------
94d0dff9baSBernard Iremonger
95724beb91SDan GoraThe ``kni`` example application requires a number of command line options:
96d0dff9baSBernard Iremonger
97d0dff9baSBernard Iremonger.. code-block:: console
98d0dff9baSBernard Iremonger
99*e2a94f9aSCiara Power    dpdk-kni [EAL options] -- -p PORTMASK --config="(port,lcore_rx,lcore_tx[,lcore_kthread,...])[,(port,lcore_rx,lcore_tx[,lcore_kthread,...])]" [-P] [-m]
100d0dff9baSBernard Iremonger
101d0dff9baSBernard IremongerWhere:
102d0dff9baSBernard Iremonger
103724beb91SDan Gora*   ``-p PORTMASK``:
104d0dff9baSBernard Iremonger
105724beb91SDan Gora    Hexadecimal bitmask of ports to configure.
106d0dff9baSBernard Iremonger
107724beb91SDan Gora*   ``--config="(port,lcore_rx,lcore_tx[,lcore_kthread,...])[,(port,lcore_rx,lcore_tx[,lcore_kthread,...])]"``:
108d0dff9baSBernard Iremonger
109724beb91SDan Gora    Determines which lcores the Rx and Tx DPDK tasks, and (optionally)
110724beb91SDan Gora    the KNI kernel thread(s) are bound to for each physical port.
111d0dff9baSBernard Iremonger
112724beb91SDan Gora*   ``-P``:
113d0dff9baSBernard Iremonger
114724beb91SDan Gora    Optional flag to set all ports to promiscuous mode so that packets are
115724beb91SDan Gora    accepted regardless of the packet's Ethernet MAC destination address.
116724beb91SDan Gora    Without this option, only packets with the Ethernet MAC destination
117724beb91SDan Gora    address set to the Ethernet address of the port are accepted.
118d0dff9baSBernard Iremonger
119724beb91SDan Gora*   ``-m``:
120724beb91SDan Gora
121724beb91SDan Gora    Optional flag to enable monitoring and updating of the Ethernet
122724beb91SDan Gora    carrier state.  With this option set, a thread will be started which
123724beb91SDan Gora    will periodically check the Ethernet link status of the physical
124724beb91SDan Gora    Ethernet ports and set the carrier state of the corresponding KNI
125724beb91SDan Gora    network interface to match it.  This means that the KNI interface will
126724beb91SDan Gora    be disabled automatically when the Ethernet link goes down and enabled
127724beb91SDan Gora    when the Ethernet link goes up.
128724beb91SDan Gora
129724beb91SDan GoraRefer to *DPDK Getting Started Guide* for general information on running
130724beb91SDan Goraapplications and the Environment Abstraction Layer (EAL) options.
131724beb91SDan Gora
132724beb91SDan GoraThe ``-c coremask`` or ``-l corelist`` parameter of the EAL options must
133724beb91SDan Gorainclude the lcores specified by ``lcore_rx`` and ``lcore_tx`` for each port,
134724beb91SDan Gorabut does not need to include lcores specified by ``lcore_kthread`` as those
135724beb91SDan Goracores are used to pin the kernel threads in the ``rte_kni`` kernel module.
136724beb91SDan Gora
137724beb91SDan GoraThe ``--config`` parameter must include a set of
138724beb91SDan Gora``(port,lcore_rx,lcore_tx,[lcore_kthread,...])`` values for each physical
139724beb91SDan Goraport specified in the ``-p PORTMASK`` parameter.
140724beb91SDan Gora
141724beb91SDan GoraThe optional ``lcore_kthread`` lcore ID parameter in ``--config`` can be
142724beb91SDan Goraspecified zero, one or more times for each physical port.
143724beb91SDan Gora
144724beb91SDan GoraIf no lcore ID is specified for ``lcore_kthread``, one KNI interface will
145724beb91SDan Gorabe created for the physical port ``port`` and the KNI kernel thread(s)
146724beb91SDan Gorawill have no specific core affinity.
147724beb91SDan Gora
148724beb91SDan GoraIf one or more lcore IDs are specified for ``lcore_kthread``, a KNI interface
149724beb91SDan Gorawill be created for each lcore ID specified, bound to the physical port
150724beb91SDan Gora``port``.  If the ``rte_kni`` kernel module is loaded in :ref:`multiple
151724beb91SDan Gorakernel thread <kni_kernel_thread_mode>` mode, a kernel thread will be created
152724beb91SDan Gorafor each KNI interface and bound to the specified core.  If the ``rte_kni``
153724beb91SDan Gorakernel module is loaded in :ref:`single kernel thread <kni_kernel_thread_mode>`
154724beb91SDan Goramode, only one kernel thread is started for all KNI interfaces.  The kernel
155724beb91SDan Gorathread will be bound to the first ``lcore_kthread`` lcore ID specified.
156724beb91SDan Gora
157724beb91SDan GoraExample Configurations
158724beb91SDan Gora~~~~~~~~~~~~~~~~~~~~~~~
159724beb91SDan Gora
160724beb91SDan GoraThe following commands will first load the ``rte_kni`` kernel module in
161724beb91SDan Gora:ref:`multiple kernel thread <kni_kernel_thread_mode>` mode.  The ``kni``
162724beb91SDan Goraapplication is then started using two ports;  Port 0 uses lcore 4 for the
163724beb91SDan GoraRx task, lcore 6 for the Tx task, and will create a single KNI interface
164724beb91SDan Gora``vEth0_0`` with the kernel thread bound to lcore 8.  Port 1 uses lcore
165724beb91SDan Gora5 for the Rx task, lcore 7 for the Tx task, and will create a single KNI
166724beb91SDan Gorainterface ``vEth1_0`` with the kernel thread bound to lcore 9.
167d0dff9baSBernard Iremonger
168d0dff9baSBernard Iremonger.. code-block:: console
169d0dff9baSBernard Iremonger
170724beb91SDan Gora    # rmmod rte_kni
171*e2a94f9aSCiara Power    # insmod <build_dir>/kernel/linux/kni/rte_kni.ko kthread_mode=multiple
172*e2a94f9aSCiara Power    # ./<build-dir>/examples/dpdk-kni -l 4-7 -n 4 -- -P -p 0x3 -m --config="(0,4,6,8),(1,5,7,9)"
173724beb91SDan Gora
174724beb91SDan GoraThe following example is identical, except an additional ``lcore_kthread``
175724beb91SDan Goracore is specified per physical port.  In this case, ``kni`` will create
176724beb91SDan Gorafour KNI interfaces: ``vEth0_0``/``vEth0_1`` bound to physical port 0 and
177724beb91SDan Gora``vEth1_0``/``vEth1_1`` bound to physical port 1.
178724beb91SDan Gora
179724beb91SDan GoraThe kernel thread for each interface will be bound as follows:
180724beb91SDan Gora
181724beb91SDan Gora    * ``vEth0_0`` - bound to lcore 8.
182724beb91SDan Gora    * ``vEth0_1`` - bound to lcore 10.
183724beb91SDan Gora    * ``vEth1_0`` - bound to lcore 9.
184724beb91SDan Gora    * ``vEth1_1`` - bound to lcore 11
185724beb91SDan Gora
186724beb91SDan Gora.. code-block:: console
187724beb91SDan Gora
188724beb91SDan Gora    # rmmod rte_kni
189*e2a94f9aSCiara Power    # insmod <build_dir>/kernel/linux/kni/rte_kni.ko kthread_mode=multiple
190*e2a94f9aSCiara Power    # ./<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)"
191724beb91SDan Gora
192724beb91SDan GoraThe following example can be used to test the interface between the ``kni``
193724beb91SDan Goratest application and the ``rte_kni`` kernel module.  In this example,
194724beb91SDan Gorathe ``rte_kni`` kernel module is loaded in :ref:`single kernel thread
195724beb91SDan Goramode <kni_kernel_thread_mode>`, :ref:`loopback mode <kni_loopback_mode>`
196724beb91SDan Goraenabled, and the :ref:`default carrier state <kni_default_carrier_state>`
197724beb91SDan Gorais set to *on* so that the corresponding physical NIC port does not have
198724beb91SDan Gorato be connected in order to use the KNI interface.  One KNI interface
199724beb91SDan Gora``vEth0_0`` is created for port 0 and one KNI interface ``vEth1_0`` is
200724beb91SDan Goracreated for port 1.  Since ``rte_kni`` is loaded in "single kernel thread"
201724beb91SDan Goramode, the one kernel thread is bound to lcore 8.
202724beb91SDan Gora
203724beb91SDan GoraSince the physical NIC ports are not being used, link monitoring can be
204724beb91SDan Goradisabled by **not** specifying the ``-m`` flag to ``kni``:
205724beb91SDan Gora
206724beb91SDan Gora.. code-block:: console
207724beb91SDan Gora
208724beb91SDan Gora    # rmmod rte_kni
209*e2a94f9aSCiara Power    # insmod <build_dir>/kernel/linux/kni/rte_kni.ko lo_mode=lo_mode_fifo carrier=on
210*e2a94f9aSCiara Power    # ./<build-dir>/examples/dpdk-kni -l 4-7 -n 4 -- -P -p 0x3 --config="(0,4,6,8),(1,5,7,9)"
211d0dff9baSBernard Iremonger
212d0dff9baSBernard IremongerKNI Operations
213d0dff9baSBernard Iremonger--------------
214d0dff9baSBernard Iremonger
215724beb91SDan GoraOnce the ``kni`` application is started, the user can use the normal
216724beb91SDan GoraLinux commands to manage the KNI interfaces as if they were any other
217724beb91SDan GoraLinux network interface.
218d0dff9baSBernard Iremonger
219724beb91SDan GoraEnable KNI interface and assign an IP address:
220d0dff9baSBernard Iremonger
221d0dff9baSBernard Iremonger.. code-block:: console
222d0dff9baSBernard Iremonger
22389247e1aSStephen Hemminger    # ip addr add dev vEth0_0 192.168.0.1
224d0dff9baSBernard Iremonger
225724beb91SDan GoraShow KNI interface configuration and statistics:
226d0dff9baSBernard Iremonger
227d0dff9baSBernard Iremonger.. code-block:: console
228d0dff9baSBernard Iremonger
22989247e1aSStephen Hemminger    # ip -s -d addr show vEth0_0
230d0dff9baSBernard Iremonger
231724beb91SDan GoraThe user can also check and reset the packet statistics inside the ``kni``
232724beb91SDan Goraapplication by sending the app the USR1 and USR2 signals:
233724beb91SDan Gora
234724beb91SDan Gora.. code-block:: console
235724beb91SDan Gora
236724beb91SDan Gora    # Print statistics
23789247e1aSStephen Hemminger    # pkill -USR1 kni
238724beb91SDan Gora
239724beb91SDan Gora    # Zero statistics
24089247e1aSStephen Hemminger    # pkill -USR2 kni
241724beb91SDan Gora
242724beb91SDan GoraDump network traffic:
243d0dff9baSBernard Iremonger
244d0dff9baSBernard Iremonger.. code-block:: console
245d0dff9baSBernard Iremonger
24689247e1aSStephen Hemminger    # tshark -n -i vEth0_0
247d0dff9baSBernard Iremonger
248724beb91SDan GoraThe normal Linux commands can also be used to change the MAC address and
249724beb91SDan GoraMTU size used by the physical NIC which corresponds to the KNI interface.
250724beb91SDan GoraHowever, if more than one KNI interface is configured for a physical port,
251724beb91SDan Gorathese commands will only work on the first KNI interface for that port.
252724beb91SDan Gora
2531cfe212eSHemant AgrawalChange the MAC address:
2541cfe212eSHemant Agrawal
2551cfe212eSHemant Agrawal.. code-block:: console
2561cfe212eSHemant Agrawal
25789247e1aSStephen Hemminger    # ip link set dev vEth0_0 lladdr 0C:01:02:03:04:08
2581cfe212eSHemant Agrawal
259724beb91SDan GoraChange the MTU size:
260724beb91SDan Gora
261724beb91SDan Gora.. code-block:: console
262724beb91SDan Gora
26389247e1aSStephen Hemminger    # ip link set dev vEth0_0 mtu 1450
26489247e1aSStephen Hemminger
26589247e1aSStephen HemmingerLimited ethtool support:
26689247e1aSStephen Hemminger
26789247e1aSStephen Hemminger.. code-block:: console
26889247e1aSStephen Hemminger
26989247e1aSStephen Hemminger    # ethtool -i vEth0_0
270724beb91SDan Gora
271724beb91SDan GoraWhen the ``kni`` application is closed, all the KNI interfaces are deleted
272724beb91SDan Gorafrom the Linux kernel.
273d0dff9baSBernard Iremonger
274d0dff9baSBernard IremongerExplanation
275d0dff9baSBernard Iremonger-----------
276d0dff9baSBernard Iremonger
277d0dff9baSBernard IremongerThe following sections provide some explanation of code.
278d0dff9baSBernard Iremonger
279d0dff9baSBernard IremongerInitialization
280d0dff9baSBernard Iremonger~~~~~~~~~~~~~~
281d0dff9baSBernard Iremonger
282513b0723SMauricio Vasquez BSetup of mbuf pool, driver and queues is similar to the setup done in the :doc:`l2_forward_real_virtual`..
283d0dff9baSBernard IremongerIn addition, one or more kernel NIC interfaces are allocated for each
284d0dff9baSBernard Iremongerof the configured ports according to the command line parameters.
285d0dff9baSBernard Iremonger
28605096a8bSThomas MonjalonThe code for allocating the kernel NIC interfaces for a specific port is
28705096a8bSThomas Monjalonin the function ``kni_alloc``.
288d0dff9baSBernard Iremonger
289d0dff9baSBernard IremongerThe other step in the initialization process that is unique to this sample application
290d0dff9baSBernard Iremongeris the association of each port with lcores for RX, TX and kernel threads.
291d0dff9baSBernard Iremonger
292d0dff9baSBernard Iremonger*   One lcore to read from the port and write to the associated one or more KNI devices
293d0dff9baSBernard Iremonger
294d0dff9baSBernard Iremonger*   Another lcore to read from one or more KNI devices and write to the port
295d0dff9baSBernard Iremonger
296d0dff9baSBernard Iremonger*   Other lcores for pinning the kernel threads on one by one
297d0dff9baSBernard Iremonger
29805096a8bSThomas MonjalonThis is done by using the ``kni_port_params_array[]`` array, which is indexed by the port ID.
29905096a8bSThomas MonjalonThe code is in the function ``parse_config``.
300d0dff9baSBernard Iremonger
301d0dff9baSBernard IremongerPacket Forwarding
302d0dff9baSBernard Iremonger~~~~~~~~~~~~~~~~~
303d0dff9baSBernard Iremonger
304d0dff9baSBernard IremongerAfter the initialization steps are completed, the main_loop() function is run on each lcore.
305d0dff9baSBernard IremongerThis function first checks the lcore_id against the user provided lcore_rx and lcore_tx
306d0dff9baSBernard Iremongerto see if this lcore is reading from or writing to kernel NIC interfaces.
307d0dff9baSBernard Iremonger
30805096a8bSThomas MonjalonFor the case that reads from a NIC port and writes to the kernel NIC interfaces (``kni_ingress``),
309d0dff9baSBernard Iremongerthe packet reception is the same as in L2 Forwarding sample application
310513b0723SMauricio Vasquez B(see :ref:`l2_fwd_app_rx_tx_packets`).
311724beb91SDan GoraThe packet transmission is done by sending mbufs into the kernel NIC interfaces by ``rte_kni_tx_burst()``.
312d0dff9baSBernard IremongerThe KNI library automatically frees the mbufs after the kernel successfully copied the mbufs.
313d0dff9baSBernard Iremonger
31405096a8bSThomas MonjalonFor the other case that reads from kernel NIC interfaces
31505096a8bSThomas Monjalonand writes to a physical NIC port (``kni_egress``),
31605096a8bSThomas Monjalonpackets are retrieved by reading mbufs from kernel NIC interfaces by ``rte_kni_rx_burst()``.
317d0dff9baSBernard IremongerThe packet transmission is the same as in the L2 Forwarding sample application
318513b0723SMauricio Vasquez B(see :ref:`l2_fwd_app_rx_tx_packets`).
319