xref: /dpdk/doc/guides/sample_app_ug/l2_forward_real_virtual.rst (revision 8750576fb2a9a067ffbcce4bab6481f3bfa47097)
15630257fSFerruh Yigit..  SPDX-License-Identifier: BSD-3-Clause
25630257fSFerruh Yigit    Copyright(c) 2010-2014 Intel Corporation.
3d0dff9baSBernard Iremonger
4d0dff9baSBernard IremongerL2 Forwarding Sample Application (in Real and Virtualized Environments)
5d0dff9baSBernard Iremonger=======================================================================
6d0dff9baSBernard Iremonger
7*8750576fSNandini PersadThe L2 Forwarding sample application is an example of packet processing
8*8750576fSNandini Persadusing the Data Plane Development Kit (DPDK).
9*8750576fSNandini PersadIt also takes advantage of Single Root I/O Virtualization (SR-IOV) features
10*8750576fSNandini Persadin a virtualized environment.
11d0dff9baSBernard Iremonger
12d0dff9baSBernard Iremonger.. note::
13d0dff9baSBernard Iremonger
14d0dff9baSBernard Iremonger    Please note that previously a separate L2 Forwarding in Virtualized Environments sample application was used,
15e0c7c473SSiobhan Butler    however, in later DPDK versions these sample applications have been merged.
16d0dff9baSBernard Iremonger
17d0dff9baSBernard IremongerOverview
18d0dff9baSBernard Iremonger--------
19d0dff9baSBernard Iremonger
20d0dff9baSBernard IremongerThe L2 Forwarding sample application, which can operate in real and virtualized environments,
21d0dff9baSBernard Iremongerperforms L2 forwarding for each packet that is received on an RX_PORT.
22*8750576fSNandini PersadThe destination port is the adjacent port from the enabled portmask
23*8750576fSNandini Persadif: the first four ports are enabled (portmask 0xf),
24d0dff9baSBernard Iremongerports 1 and 2 forward into each other, and ports 3 and 4 forward into each other.
25*8750576fSNandini PersadAlso, if MAC address updating is enabled, the MAC addresses are affected as follows:
26d0dff9baSBernard Iremonger
27d0dff9baSBernard Iremonger*   The source MAC address is replaced by the TX_PORT MAC address
28d0dff9baSBernard Iremonger
29d0dff9baSBernard Iremonger*   The destination MAC address is replaced by  02:00:00:00:00:TX_PORT_ID
30d0dff9baSBernard Iremonger
31cf435a07SMaxime CoquelinThis application can be used to benchmark performance using a traffic-generator, as shown in the :numref:`figure_l2_fwd_benchmark_setup`,
32cf435a07SMaxime Coquelinor in a virtualized environment as shown in :numref:`figure_l2_fwd_virtenv_benchmark_setup`.
33d0dff9baSBernard Iremonger
344a22e6eeSJohn McNamara.. _figure_l2_fwd_benchmark_setup:
35d0dff9baSBernard Iremonger
364a22e6eeSJohn McNamara.. figure:: img/l2_fwd_benchmark_setup.*
37d0dff9baSBernard Iremonger
384a22e6eeSJohn McNamara   Performance Benchmark Setup (Basic Environment)
39d0dff9baSBernard Iremonger
404a22e6eeSJohn McNamara.. _figure_l2_fwd_virtenv_benchmark_setup:
41d0dff9baSBernard Iremonger
424a22e6eeSJohn McNamara.. figure:: img/l2_fwd_virtenv_benchmark_setup.*
43d0dff9baSBernard Iremonger
444a22e6eeSJohn McNamara   Performance Benchmark Setup (Virtualized Environment)
45d0dff9baSBernard Iremonger
46cf435a07SMaxime CoquelinThis application may be used for basic VM to VM communication as shown in :numref:`figure_l2_fwd_vm2vm`,
47cf435a07SMaxime Coquelinwhen MAC addresses updating is disabled.
48cf435a07SMaxime Coquelin
49cf435a07SMaxime Coquelin.. _figure_l2_fwd_vm2vm:
50cf435a07SMaxime Coquelin
51cf435a07SMaxime Coquelin.. figure:: img/l2_fwd_vm2vm.*
52cf435a07SMaxime Coquelin
53cf435a07SMaxime Coquelin   Virtual Machine to Virtual Machine communication.
54cf435a07SMaxime Coquelin
55cf435a07SMaxime CoquelinThe L2 Forwarding application can also be used as a starting point for developing a new application based on the DPDK.
56cf435a07SMaxime Coquelin
57513b0723SMauricio Vasquez B.. _l2_fwd_vf_setup:
58d0dff9baSBernard Iremonger
59d0dff9baSBernard IremongerVirtual Function Setup Instructions
60d0dff9baSBernard Iremonger~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
61d0dff9baSBernard Iremonger
62d0dff9baSBernard IremongerThis application can use the virtual function available in the system and
63d0dff9baSBernard Iremongertherefore can be used in a virtual machine without passing through
64d0dff9baSBernard Iremongerthe whole Network Device into a guest machine in a virtualized scenario.
65d0dff9baSBernard IremongerThe virtual functions can be enabled in the host machine or the hypervisor with the respective physical function driver.
66d0dff9baSBernard Iremonger
67d0dff9baSBernard IremongerFor example, in a Linux* host machine, it is possible to enable a virtual function using the following command:
68d0dff9baSBernard Iremonger
69d0dff9baSBernard Iremonger.. code-block:: console
70d0dff9baSBernard Iremonger
71d0dff9baSBernard Iremonger    modprobe ixgbe max_vfs=2,2
72d0dff9baSBernard Iremonger
73d0dff9baSBernard IremongerThis command enables two Virtual Functions on each of Physical Function of the NIC,
74d0dff9baSBernard Iremongerwith two physical ports in the PCI configuration space.
75d0dff9baSBernard IremongerIt is important to note that enabled Virtual Function 0 and 2 would belong to Physical Function 0
76d0dff9baSBernard Iremongerand Virtual Function 1 and 3 would belong to Physical Function 1,
77*8750576fSNandini Persadin this case, enabling a total of four Virtual Functions.
78d0dff9baSBernard Iremonger
79d0dff9baSBernard IremongerCompiling the Application
80d0dff9baSBernard Iremonger-------------------------
81d0dff9baSBernard Iremonger
82*8750576fSNandini PersadTo compile the sample application, see :doc:`compiling`.
83d0dff9baSBernard Iremonger
847cacb056SHerakliusz LipiecThe application is located in the ``l2fwd`` sub-directory.
85d0dff9baSBernard Iremonger
86d0dff9baSBernard IremongerRunning the Application
87d0dff9baSBernard Iremonger-----------------------
88d0dff9baSBernard Iremonger
89d0dff9baSBernard IremongerThe application requires a number of command line options:
90d0dff9baSBernard Iremonger
91d0dff9baSBernard Iremonger.. code-block:: console
92d0dff9baSBernard Iremonger
93e2a94f9aSCiara Power    ./<build_dir>/examples/dpdk-l2fwd [EAL options] -- -p PORTMASK
94b54403fdSSarosh Arif                                   [-P]
95fa19eb20SVamsi Attunuru                                   [-q NQ]
96fa19eb20SVamsi Attunuru                                   --[no-]mac-updating
97fa19eb20SVamsi Attunuru                                   [--portmap="(port, port)[,(port, port)]"]
98d0dff9baSBernard Iremonger
99d0dff9baSBernard Iremongerwhere,
100d0dff9baSBernard Iremonger
101d0dff9baSBernard Iremonger*   p PORTMASK: A hexadecimal bitmask of the ports to configure
102d0dff9baSBernard Iremonger
103b54403fdSSarosh Arif*   P: Optional, set all ports to promiscuous mode
104b54403fdSSarosh Arif    so that packets are accepted regardless of the MAC destination address.
105b54403fdSSarosh Arif    Without this option, only packets with the MAC destination address
106b54403fdSSarosh Arif    set to the Ethernet address of the port are accepted.
107b54403fdSSarosh Arif
108885807aeSStephen Hemminger*   q NQ: Maximum number of queues per lcore (default is 1)
109d0dff9baSBernard Iremonger
110fa19eb20SVamsi Attunuru*   --[no-]mac-updating: Enable or disable MAC addresses updating (enabled by default)
111fa19eb20SVamsi Attunuru
112fa19eb20SVamsi Attunuru*   --portmap="(port,port)[,(port,port)]": Determines forwarding ports mapping.
113cf435a07SMaxime Coquelin
114218c4e68SBruce RichardsonTo run the application in linux environment with 4 lcores, 16 ports and 8 RX queues per lcore and MAC address
115cf435a07SMaxime Coquelinupdating enabled, issue the command:
116d0dff9baSBernard Iremonger
117d0dff9baSBernard Iremonger.. code-block:: console
118d0dff9baSBernard Iremonger
119e2a94f9aSCiara Power    $ ./<build_dir>/examples/dpdk-l2fwd -l 0-3 -n 4 -- -q 8 -p ffff
120d0dff9baSBernard Iremonger
121fa19eb20SVamsi AttunuruTo run the application in linux environment with 4 lcores, 4 ports, 8 RX queues
122fa19eb20SVamsi Attunuruper lcore, to forward RX traffic of ports 0 & 1 on ports 2 & 3 respectively and
123fa19eb20SVamsi Attunuruvice versa, issue the command:
124fa19eb20SVamsi Attunuru
125fa19eb20SVamsi Attunuru.. code-block:: console
126fa19eb20SVamsi Attunuru
127e2a94f9aSCiara Power    $ ./<build_dir>/examples/dpdk-l2fwd -l 0-3 -n 4 -- -q 8 -p f --portmap="(0,2)(1,3)"
128fa19eb20SVamsi Attunuru
129e0c7c473SSiobhan ButlerRefer to the *DPDK Getting Started Guide* for general information on running applications
130d0dff9baSBernard Iremongerand the Environment Abstraction Layer (EAL) options.
131d0dff9baSBernard Iremonger
132d0dff9baSBernard IremongerExplanation
133d0dff9baSBernard Iremonger-----------
134d0dff9baSBernard Iremonger
135*8750576fSNandini PersadThe following sections provide explanation of the code.
136d0dff9baSBernard Iremonger
137513b0723SMauricio Vasquez B.. _l2_fwd_app_cmd_arguments:
138513b0723SMauricio Vasquez B
139d0dff9baSBernard IremongerCommand Line Arguments
140d0dff9baSBernard Iremonger~~~~~~~~~~~~~~~~~~~~~~
141d0dff9baSBernard Iremonger
142*8750576fSNandini PersadThe L2 Forwarding sample application takes specific parameters
143*8750576fSNandini Persadand Environment Abstraction Layer (EAL) arguments.
144*8750576fSNandini PersadThe preferred way to parse parameters is to use the ``getopt()`` function
145d0dff9baSBernard Iremongersince it is part of a well-defined and portable library.
146d0dff9baSBernard Iremonger
147*8750576fSNandini PersadThe parsing of arguments is done in the ``l2fwd_parse_args()`` function.
148*8750576fSNandini PersadThis method of argument parsing is not described here.
149*8750576fSNandini PersadRefer to the *glibc getopt(3)* main page for details.
150d0dff9baSBernard Iremonger
151d0dff9baSBernard IremongerEAL arguments are parsed first, then application-specific arguments.
152d0dff9baSBernard IremongerThis is done at the beginning of the main() function:
153d0dff9baSBernard Iremonger
1549a212dc0SConor Fogarty.. literalinclude:: ../../../examples/l2fwd/main.c
1559a212dc0SConor Fogarty    :language: c
1569a212dc0SConor Fogarty    :start-after: Init EAL. 8<
1579a212dc0SConor Fogarty    :end-before: >8 End of init EAL.
1589a212dc0SConor Fogarty    :dedent: 1
159d0dff9baSBernard Iremonger
160513b0723SMauricio Vasquez B.. _l2_fwd_app_mbuf_init:
161513b0723SMauricio Vasquez B
162d0dff9baSBernard IremongerMbuf Pool Initialization
163d0dff9baSBernard Iremonger~~~~~~~~~~~~~~~~~~~~~~~~
164d0dff9baSBernard Iremonger
165d0dff9baSBernard IremongerOnce the arguments are parsed, the mbuf pool is created.
166d0dff9baSBernard IremongerThe mbuf pool contains a set of mbuf objects that will be used by the driver
167d0dff9baSBernard Iremongerand the application to store network packet data:
168d0dff9baSBernard Iremonger
1699a212dc0SConor Fogarty.. literalinclude:: ../../../examples/l2fwd/main.c
1709a212dc0SConor Fogarty    :language: c
1719a212dc0SConor Fogarty    :start-after: Create the mbuf pool. 8<
1729a212dc0SConor Fogarty    :end-before: >8 End of create the mbuf pool.
1739a212dc0SConor Fogarty    :dedent: 1
174d0dff9baSBernard Iremonger
175d0dff9baSBernard IremongerThe rte_mempool is a generic structure used to handle pools of objects.
1765a11168dSHemant AgrawalIn this case, it is necessary to create a pool that will be used by the driver.
177*8750576fSNandini PersadThe number of allocated pkt mbufs is ``NB_MBUF``,
178*8750576fSNandini Persadwith a data room size of ``RTE_MBUF_DEFAULT_BUF_SIZE`` each.
179d0dff9baSBernard IremongerA per-lcore cache of 32 mbufs is kept.
180d0dff9baSBernard IremongerThe memory is allocated in NUMA socket 0,
181d0dff9baSBernard Iremongerbut it is possible to extend this code to allocate one mbuf pool per socket.
182d0dff9baSBernard Iremonger
183*8750576fSNandini PersadThe ``rte_pktmbuf_pool_create()`` function uses the default mbuf pool
184*8750576fSNandini Persadand mbuf initializers, respectively ``rte_pktmbuf_pool_init()`` and ``rte_pktmbuf_init()``.
1855a11168dSHemant AgrawalAn advanced application may want to use the mempool API to create the
1865a11168dSHemant Agrawalmbuf pool with more control.
187d0dff9baSBernard Iremonger
188513b0723SMauricio Vasquez B.. _l2_fwd_app_dvr_init:
189513b0723SMauricio Vasquez B
190d0dff9baSBernard IremongerDriver Initialization
191d0dff9baSBernard Iremonger~~~~~~~~~~~~~~~~~~~~~
192d0dff9baSBernard Iremonger
193*8750576fSNandini PersadThe main part of the code in the ``main()`` function relates to the initialization of the driver.
194*8750576fSNandini PersadTo fully understand this code, it is recommended to study the chapters related to the Poll Mode Driver
195e0c7c473SSiobhan Butlerin the *DPDK Programmer's Guide* - Rel 1.4 EAR and the *DPDK API Reference*.
196d0dff9baSBernard Iremonger
1979a212dc0SConor Fogarty.. literalinclude:: ../../../examples/l2fwd/main.c
1989a212dc0SConor Fogarty    :language: c
1999a212dc0SConor Fogarty    :start-after: Initialization of the driver. 8<
2009a212dc0SConor Fogarty    :end-before: >8 End of initialization of the driver.
2019a212dc0SConor Fogarty    :dedent: 1
202d0dff9baSBernard Iremonger
203d0dff9baSBernard IremongerThe next step is to configure the RX and TX queues.
204d0dff9baSBernard IremongerFor each port, there is only one RX queue (only one lcore is able to poll a given port).
205d0dff9baSBernard IremongerThe number of TX queues depends on the number of available lcores.
206*8750576fSNandini PersadThe ``rte_eth_dev_configure()`` function is used to configure the number of queues for a port:
207d0dff9baSBernard Iremonger
2089a212dc0SConor Fogarty.. literalinclude:: ../../../examples/l2fwd/main.c
2099a212dc0SConor Fogarty    :language: c
2109a212dc0SConor Fogarty    :start-after: Configure the number of queues for a port.
2119a212dc0SConor Fogarty    :end-before: >8 End of configuration of the number of queues for a port.
2129a212dc0SConor Fogarty    :dedent: 2
213d0dff9baSBernard Iremonger
214513b0723SMauricio Vasquez B.. _l2_fwd_app_rx_init:
215513b0723SMauricio Vasquez B
216d0dff9baSBernard IremongerRX Queue Initialization
217d0dff9baSBernard Iremonger~~~~~~~~~~~~~~~~~~~~~~~
218d0dff9baSBernard Iremonger
219*8750576fSNandini PersadThe application uses one lcore to poll one or several ports depending on the ``-q`` option,
220d0dff9baSBernard Iremongerwhich specifies the number of queues per lcore.
221d0dff9baSBernard Iremonger
222*8750576fSNandini PersadFor example, if the user specifies ``-q 4``,
223*8750576fSNandini Persadthe application is able to poll four ports with one lcore.
224*8750576fSNandini PersadIf there are 16 ports on the target (and if the portmask argument is ``-p ffff``),
225d0dff9baSBernard Iremongerthe application will need four lcores to poll all the ports.
226d0dff9baSBernard Iremonger
2279a212dc0SConor Fogarty.. literalinclude:: ../../../examples/l2fwd/main.c
2289a212dc0SConor Fogarty    :language: c
2299a212dc0SConor Fogarty    :start-after: RX queue setup. 8<
2309a212dc0SConor Fogarty    :end-before: >8 End of RX queue setup.
2319a212dc0SConor Fogarty    :dedent: 2
232d0dff9baSBernard Iremonger
233d0dff9baSBernard IremongerThe list of queues that must be polled for a given lcore is stored in a private structure called struct lcore_queue_conf.
234d0dff9baSBernard Iremonger
2359a212dc0SConor Fogarty.. literalinclude:: ../../../examples/l2fwd/main.c
2369a212dc0SConor Fogarty    :language: c
2379a212dc0SConor Fogarty    :start-after: List of queues to be polled for a given lcore. 8<
2389a212dc0SConor Fogarty    :end-before: >8 End of list of queues to be polled for a given lcore.
239d0dff9baSBernard Iremonger
240*8750576fSNandini PersadThe values ``n_rx_port`` and ``rx_port_list[]`` are used in the main packet processing loop
241513b0723SMauricio Vasquez B(see :ref:`l2_fwd_app_rx_tx_packets`).
242d0dff9baSBernard Iremonger
243513b0723SMauricio Vasquez B.. _l2_fwd_app_tx_init:
244513b0723SMauricio Vasquez B
245d0dff9baSBernard IremongerTX Queue Initialization
246d0dff9baSBernard Iremonger~~~~~~~~~~~~~~~~~~~~~~~
247d0dff9baSBernard Iremonger
248*8750576fSNandini PersadEach lcore should be able to transmit on any port.
249*8750576fSNandini PersadFor each port, a single TX queue is initialized.
250d0dff9baSBernard Iremonger
2519a212dc0SConor Fogarty.. literalinclude:: ../../../examples/l2fwd/main.c
2529a212dc0SConor Fogarty    :language: c
2539a212dc0SConor Fogarty    :start-after: Init one TX queue on each port. 8<
2549a212dc0SConor Fogarty    :end-before: >8 End of init one TX queue on each port.
2559a212dc0SConor Fogarty    :dedent: 2
256d0dff9baSBernard Iremonger
257513b0723SMauricio Vasquez B.. _l2_fwd_app_rx_tx_packets:
258513b0723SMauricio Vasquez B
259d0dff9baSBernard IremongerReceive, Process and Transmit Packets
260d0dff9baSBernard Iremonger~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
261d0dff9baSBernard Iremonger
262*8750576fSNandini PersadIn the ``l2fwd_main_loop()`` function,
263*8750576fSNandini Persadthe main task is to read ingress packets from the RX queues.
264d0dff9baSBernard IremongerThis is done using the following code:
265d0dff9baSBernard Iremonger
2669a212dc0SConor Fogarty.. literalinclude:: ../../../examples/l2fwd/main.c
2679a212dc0SConor Fogarty    :language: c
2689a212dc0SConor Fogarty    :start-after: Read packet from RX queues. 8<
2699a212dc0SConor Fogarty    :end-before: >8 End of read packet from RX queues.
2709a212dc0SConor Fogarty    :dedent: 2
271d0dff9baSBernard Iremonger
272*8750576fSNandini PersadPackets are read in a burst of size ``MAX_PKT_BURST``.
273*8750576fSNandini PersadThe ``rte_eth_rx_burst()`` function writes the mbuf pointers
274*8750576fSNandini Persadin a local table and returns the number of available mbufs in the table.
275d0dff9baSBernard Iremonger
276*8750576fSNandini PersadThen, each mbuf in the table is processed by the ``l2fwd_simple_forward()`` function.
277*8750576fSNandini PersadThe processing is very simple: process the TX port from the RX port,
278*8750576fSNandini Persadthen replace the source and destination MAC addresses if MAC address updating is enabled.
279d0dff9baSBernard Iremonger
280d0dff9baSBernard Iremonger.. note::
281d0dff9baSBernard Iremonger
282d0dff9baSBernard Iremonger    In the following code, one line for getting the output port requires some explanation.
283d0dff9baSBernard Iremonger
284*8750576fSNandini PersadDuring the initialization process, a static array of destination ports (``l2fwd_dst_ports[]``)
285*8750576fSNandini Persadis filled such that for each source port,
286d0dff9baSBernard Iremongera destination port is assigned that is either the next or previous enabled port from the portmask.
287*8750576fSNandini PersadNaturally, the number of ports in the portmask must be even.
288*8750576fSNandini PersadOtherwise, the application exits.
289d0dff9baSBernard Iremonger
2909a212dc0SConor Fogarty.. literalinclude:: ../../../examples/l2fwd/main.c
2919a212dc0SConor Fogarty    :language: c
2929a212dc0SConor Fogarty    :start-after: Simple forward. 8<
2939a212dc0SConor Fogarty    :end-before: >8 End of simple forward.
294d0dff9baSBernard Iremonger
295d0dff9baSBernard Iremonger
296*8750576fSNandini PersadAt this point, the packet is sent using the ``l2fwd_send_packet(m, dst_port)`` function.
297d0dff9baSBernard IremongerFor this test application, the processing is exactly the same for all packets arriving on the same RX port.
298*8750576fSNandini PersadTherefore, it would have been possible to call the ``l2fwd_send_burst()`` function
299*8750576fSNandini Persaddirectly from the main loop
300d0dff9baSBernard Iremongerto send all the received packets on the same TX port,
301d0dff9baSBernard Iremongerusing the burst-oriented send function, which is more efficient.
302d0dff9baSBernard Iremonger
303*8750576fSNandini PersadHowever, in real-life applications (such as L3 routing),
304d0dff9baSBernard Iremongerpacket N is not necessarily forwarded on the same port as packet N-1.
305*8750576fSNandini PersadThe application is implemented to illustrate this
306*8750576fSNandini Persadso the same approach can be reused in a more complex application.
307d0dff9baSBernard Iremonger
308*8750576fSNandini PersadThe ``l2fwd_send_packet()`` function stores the packet in a per-lcore and per-txport table.
309*8750576fSNandini PersadIf the table is full, the whole packets table is transmitted
310*8750576fSNandini Persadusing the ``l2fwd_send_burst()`` function:
311d0dff9baSBernard Iremonger
3129a212dc0SConor Fogarty.. literalinclude:: ../../../examples/l2fwd-crypto/main.c
3139a212dc0SConor Fogarty    :language: c
3149a212dc0SConor Fogarty    :start-after: Enqueue packets for TX and prepare them to be sent. 8<
3159a212dc0SConor Fogarty    :end-before: >8 End of Enqueuing packets for TX.
316d0dff9baSBernard Iremonger
317d0dff9baSBernard IremongerTo ensure that no packets remain in the tables, each lcore does a draining of TX queue in its main loop.
318*8750576fSNandini PersadThis technique introduces some latency when there are not many packets to send.
319*8750576fSNandini PersadHowever it improves performance:
320d0dff9baSBernard Iremonger
3219a212dc0SConor Fogarty.. literalinclude:: ../../../examples/l2fwd/main.c
3229a212dc0SConor Fogarty    :language: c
3239a212dc0SConor Fogarty    :start-after: Drains TX queue in its main loop. 8<
3249a212dc0SConor Fogarty    :end-before: >8 End of draining TX queue.
3259a212dc0SConor Fogarty    :dedent: 2
326