xref: /dpdk/doc/guides/sample_app_ug/dma.rst (revision 8750576fb2a9a067ffbcce4bab6481f3bfa47097)
1bb4141dbSKevin Laatz..  SPDX-License-Identifier: BSD-3-Clause
2bb4141dbSKevin Laatz    Copyright(c) 2019-2021 Intel Corporation.
3bb4141dbSKevin Laatz
4bb4141dbSKevin Laatz.. include:: <isonum.txt>
5bb4141dbSKevin Laatz
6bb4141dbSKevin LaatzPacket copying using DMAdev library
7bb4141dbSKevin Laatz===================================
8bb4141dbSKevin Laatz
9bb4141dbSKevin LaatzOverview
10bb4141dbSKevin Laatz--------
11bb4141dbSKevin Laatz
12bb4141dbSKevin LaatzThis sample is intended as a demonstration of the basic components of a DPDK
13*8750576fSNandini Persadforwarding application and an example of how to use the DMAdev API to make a packet
14bb4141dbSKevin Laatzcopy application.
15bb4141dbSKevin Laatz
16*8750576fSNandini PersadAlso, while forwarding, the MAC addresses are affected as follows:
17bb4141dbSKevin Laatz
18bb4141dbSKevin Laatz*   The source MAC address is replaced by the TX port MAC address
19bb4141dbSKevin Laatz
20bb4141dbSKevin Laatz*   The destination MAC address is replaced by  02:00:00:00:00:TX_PORT_ID
21bb4141dbSKevin Laatz
22bb4141dbSKevin LaatzThis application can be used to compare performance of using software packet
23bb4141dbSKevin Laatzcopy with copy done using a DMA device for different sizes of packets.
24bb4141dbSKevin LaatzThe example will print out statistics each second. The stats shows
25bb4141dbSKevin Laatzreceived/send packets and packets dropped or failed to copy.
26bb4141dbSKevin Laatz
27bb4141dbSKevin LaatzCompiling the Application
28bb4141dbSKevin Laatz-------------------------
29bb4141dbSKevin Laatz
30*8750576fSNandini PersadTo compile the sample application, see :doc:`compiling`.
31bb4141dbSKevin Laatz
32bb4141dbSKevin LaatzThe application is located in the ``dma`` sub-directory.
33bb4141dbSKevin Laatz
34bb4141dbSKevin Laatz
35bb4141dbSKevin LaatzRunning the Application
36bb4141dbSKevin Laatz-----------------------
37bb4141dbSKevin Laatz
38bb4141dbSKevin LaatzIn order to run the hardware copy application, the copying device
39bb4141dbSKevin Laatzneeds to be bound to user-space IO driver.
40bb4141dbSKevin Laatz
41*8750576fSNandini PersadRefer to the :doc:`../prog_guide/dmadev` for information on using the library.
42bb4141dbSKevin Laatz
43bb4141dbSKevin LaatzThe application requires a number of command line options:
44bb4141dbSKevin Laatz
45bb4141dbSKevin Laatz.. code-block:: console
46bb4141dbSKevin Laatz
47269f0274SConor Walsh    ./<build_dir>/examples/dpdk-dma [EAL options] -- [-p MASK] [-q NQ] [-s RS] [-c <sw|hw>]
48bb4141dbSKevin Laatz        [--[no-]mac-updating] [-b BS] [-f FS] [-i SI]
49bb4141dbSKevin Laatz
50bb4141dbSKevin Laatzwhere,
51bb4141dbSKevin Laatz
52bb4141dbSKevin Laatz*   p MASK: A hexadecimal bitmask of the ports to configure (default is all)
53bb4141dbSKevin Laatz
54bb4141dbSKevin Laatz*   q NQ: Number of Rx queues used per port equivalent to DMA channels
55bb4141dbSKevin Laatz    per port (default is 1)
56bb4141dbSKevin Laatz
57bb4141dbSKevin Laatz*   c CT: Performed packet copy type: software (sw) or hardware using
58bb4141dbSKevin Laatz    DMA (hw) (default is hw)
59bb4141dbSKevin Laatz
60bb4141dbSKevin Laatz*   s RS: Size of dmadev descriptor ring for hardware copy mode or rte_ring for
61bb4141dbSKevin Laatz    software copy mode (default is 2048)
62bb4141dbSKevin Laatz
63bb4141dbSKevin Laatz*   --[no-]mac-updating: Whether MAC address of packets should be changed
64bb4141dbSKevin Laatz    or not (default is mac-updating)
65bb4141dbSKevin Laatz
66bb4141dbSKevin Laatz*   b BS: set the DMA batch size
67bb4141dbSKevin Laatz
68bb4141dbSKevin Laatz*   f FS: set the max frame size
69bb4141dbSKevin Laatz
70bb4141dbSKevin Laatz*   i SI: set the interval, in second, between statistics prints (default is 1)
71bb4141dbSKevin Laatz
72*8750576fSNandini PersadThe application can be launched in various configurations depending on the
73bb4141dbSKevin Laatzprovided parameters. The app can use up to 2 lcores: one of them receives
74bb4141dbSKevin Laatzincoming traffic and makes a copy of each packet. The second lcore then
75*8750576fSNandini Persadupdates the MAC address and sends the copy. If one lcore per port is used,
76*8750576fSNandini Persadboth operations are done sequentially. For each configuration, an additional
77bb4141dbSKevin Laatzlcore is needed since the main lcore does not handle traffic but is
78bb4141dbSKevin Laatzresponsible for configuration, statistics printing and safe shutdown of
79bb4141dbSKevin Laatzall ports and devices.
80bb4141dbSKevin Laatz
81bb4141dbSKevin LaatzThe application can use a maximum of 8 ports.
82bb4141dbSKevin Laatz
83bb4141dbSKevin LaatzTo run the application in a Linux environment with 3 lcores (the main lcore,
84bb4141dbSKevin Laatzplus two forwarding cores), a single port (port 0), software copying and MAC
85bb4141dbSKevin Laatzupdating issue the command:
86bb4141dbSKevin Laatz
87bb4141dbSKevin Laatz.. code-block:: console
88bb4141dbSKevin Laatz
89bb4141dbSKevin Laatz    $ ./<build_dir>/examples/dpdk-dma -l 0-2 -n 2 -- -p 0x1 --mac-updating -c sw
90bb4141dbSKevin Laatz
91bb4141dbSKevin LaatzTo run the application in a Linux environment with 2 lcores (the main lcore,
92bb4141dbSKevin Laatzplus one forwarding core), 2 ports (ports 0 and 1), hardware copying and no MAC
93bb4141dbSKevin Laatzupdating issue the command:
94bb4141dbSKevin Laatz
95bb4141dbSKevin Laatz.. code-block:: console
96bb4141dbSKevin Laatz
97bb4141dbSKevin Laatz    $ ./<build_dir>/examples/dpdk-dma -l 0-1 -n 1 -- -p 0x3 --no-mac-updating -c hw
98bb4141dbSKevin Laatz
99bb4141dbSKevin LaatzRefer to the *DPDK Getting Started Guide* for general information on
100bb4141dbSKevin Laatzrunning applications and the Environment Abstraction Layer (EAL) options.
101bb4141dbSKevin Laatz
102bb4141dbSKevin LaatzExplanation
103bb4141dbSKevin Laatz-----------
104bb4141dbSKevin Laatz
105bb4141dbSKevin LaatzThe following sections provide an explanation of the main components of the
106bb4141dbSKevin Laatzcode.
107bb4141dbSKevin Laatz
108bb4141dbSKevin LaatzAll DPDK library functions used in the sample code are prefixed with
109bb4141dbSKevin Laatz``rte_`` and are explained in detail in the *DPDK API Documentation*.
110bb4141dbSKevin Laatz
111bb4141dbSKevin Laatz
112bb4141dbSKevin LaatzThe Main Function
113bb4141dbSKevin Laatz~~~~~~~~~~~~~~~~~
114bb4141dbSKevin Laatz
115bb4141dbSKevin LaatzThe ``main()`` function performs the initialization and calls the execution
116bb4141dbSKevin Laatzthreads for each lcore.
117bb4141dbSKevin Laatz
118bb4141dbSKevin LaatzThe first task is to initialize the Environment Abstraction Layer (EAL).
119bb4141dbSKevin LaatzThe ``argc`` and ``argv`` arguments are provided to the ``rte_eal_init()``
120bb4141dbSKevin Laatzfunction. The value returned is the number of parsed arguments:
121bb4141dbSKevin Laatz
122bb4141dbSKevin Laatz.. literalinclude:: ../../../examples/dma/dmafwd.c
123bb4141dbSKevin Laatz    :language: c
124bb4141dbSKevin Laatz    :start-after: Init EAL. 8<
125bb4141dbSKevin Laatz    :end-before: >8 End of init EAL.
126bb4141dbSKevin Laatz    :dedent: 1
127bb4141dbSKevin Laatz
128bb4141dbSKevin Laatz
129bb4141dbSKevin LaatzThe ``main()`` also allocates a mempool to hold the mbufs (Message Buffers)
130bb4141dbSKevin Laatzused by the application:
131bb4141dbSKevin Laatz
132bb4141dbSKevin Laatz.. literalinclude:: ../../../examples/dma/dmafwd.c
133bb4141dbSKevin Laatz    :language: c
134bb4141dbSKevin Laatz    :start-after: Allocates mempool to hold the mbufs. 8<
135bb4141dbSKevin Laatz    :end-before: >8 End of allocates mempool to hold the mbufs.
136bb4141dbSKevin Laatz    :dedent: 1
137bb4141dbSKevin Laatz
138bb4141dbSKevin LaatzMbufs are the packet buffer structure used by DPDK. They are explained in
139bb4141dbSKevin Laatzdetail in the "Mbuf Library" section of the *DPDK Programmer's Guide*.
140bb4141dbSKevin Laatz
141bb4141dbSKevin LaatzThe ``main()`` function also initializes the ports:
142bb4141dbSKevin Laatz
143bb4141dbSKevin Laatz.. literalinclude:: ../../../examples/dma/dmafwd.c
144bb4141dbSKevin Laatz    :language: c
145bb4141dbSKevin Laatz    :start-after: Initialize each port. 8<
146bb4141dbSKevin Laatz    :end-before: >8 End of initializing each port.
147bb4141dbSKevin Laatz    :dedent: 1
148bb4141dbSKevin Laatz
149bb4141dbSKevin LaatzEach port is configured using ``port_init()`` function. The Ethernet
150bb4141dbSKevin Laatzports are configured with local settings using the ``rte_eth_dev_configure()``
151bb4141dbSKevin Laatzfunction and the ``port_conf`` struct. The RSS is enabled so that
152bb4141dbSKevin Laatzmultiple Rx queues could be used for packet receiving and copying by
153bb4141dbSKevin Laatzmultiple DMA channels per port:
154bb4141dbSKevin Laatz
155bb4141dbSKevin Laatz.. literalinclude:: ../../../examples/dma/dmafwd.c
156bb4141dbSKevin Laatz    :language: c
157bb4141dbSKevin Laatz    :start-after: Configuring port to use RSS for multiple RX queues. 8<
158bb4141dbSKevin Laatz    :end-before: >8 End of configuring port to use RSS for multiple RX queues.
159bb4141dbSKevin Laatz    :dedent: 1
160bb4141dbSKevin Laatz
161*8750576fSNandini PersadFor this example, the ports are set up with the number of Rx queues provided
162bb4141dbSKevin Laatzwith -q option and 1 Tx queue using the ``rte_eth_rx_queue_setup()``
163bb4141dbSKevin Laatzand ``rte_eth_tx_queue_setup()`` functions.
164bb4141dbSKevin Laatz
165bb4141dbSKevin LaatzThe Ethernet port is then started:
166bb4141dbSKevin Laatz
167bb4141dbSKevin Laatz.. literalinclude:: ../../../examples/dma/dmafwd.c
168bb4141dbSKevin Laatz    :language: c
169bb4141dbSKevin Laatz    :start-after: Start device. 8<
170bb4141dbSKevin Laatz    :end-before: >8 End of starting device.
171bb4141dbSKevin Laatz    :dedent: 1
172bb4141dbSKevin Laatz
173bb4141dbSKevin Laatz
174*8750576fSNandini PersadFinally, the Rx port is set in promiscuous mode:
175bb4141dbSKevin Laatz
176bb4141dbSKevin Laatz.. literalinclude:: ../../../examples/dma/dmafwd.c
177bb4141dbSKevin Laatz    :language: c
178bb4141dbSKevin Laatz    :start-after: RX port is set in promiscuous mode. 8<
179bb4141dbSKevin Laatz    :end-before: >8 End of RX port is set in promiscuous mode.
180bb4141dbSKevin Laatz    :dedent: 1
181bb4141dbSKevin Laatz
182bb4141dbSKevin Laatz
183*8750576fSNandini PersadAfter that, each port application assigns resources needed.
184bb4141dbSKevin Laatz
185bb4141dbSKevin Laatz.. literalinclude:: ../../../examples/dma/dmafwd.c
186bb4141dbSKevin Laatz    :language: c
187bb4141dbSKevin Laatz    :start-after: Assigning each port resources. 8<
188bb4141dbSKevin Laatz    :end-before: >8 End of assigning each port resources.
189bb4141dbSKevin Laatz    :dedent: 1
190bb4141dbSKevin Laatz
191bb4141dbSKevin LaatzRing structures are assigned for exchanging packets between lcores for both SW
192bb4141dbSKevin Laatzand HW copy modes.
193bb4141dbSKevin Laatz
194bb4141dbSKevin Laatz.. literalinclude:: ../../../examples/dma/dmafwd.c
195bb4141dbSKevin Laatz    :language: c
196bb4141dbSKevin Laatz    :start-after: Assign ring structures for packet exchanging. 8<
197bb4141dbSKevin Laatz    :end-before: >8 End of assigning ring structures for packet exchanging.
198bb4141dbSKevin Laatz    :dedent: 0
199bb4141dbSKevin Laatz
200bb4141dbSKevin Laatz
201bb4141dbSKevin LaatzWhen using hardware copy each Rx queue of the port is assigned a DMA device
202bb4141dbSKevin Laatz(``assign_dmadevs()``) using DMAdev library API functions:
203bb4141dbSKevin Laatz
204bb4141dbSKevin Laatz.. literalinclude:: ../../../examples/dma/dmafwd.c
205bb4141dbSKevin Laatz    :language: c
206bb4141dbSKevin Laatz    :start-after: Using dmadev API functions. 8<
207bb4141dbSKevin Laatz    :end-before: >8 End of using dmadev API functions.
208bb4141dbSKevin Laatz    :dedent: 0
209bb4141dbSKevin Laatz
210bb4141dbSKevin Laatz
211bb4141dbSKevin LaatzThe initialization of hardware device is done by ``rte_dma_configure()`` and
212bb4141dbSKevin Laatz``rte_dma_vchan_setup()`` functions using the ``rte_dma_conf`` and
213bb4141dbSKevin Laatz``rte_dma_vchan_conf`` structs. After configuration the device is started
214bb4141dbSKevin Laatzusing ``rte_dma_start()`` function. Each of the above operations is done in
215bb4141dbSKevin Laatz``configure_dmadev_queue()``.
216bb4141dbSKevin Laatz
217bb4141dbSKevin Laatz.. literalinclude:: ../../../examples/dma/dmafwd.c
218bb4141dbSKevin Laatz    :language: c
219bb4141dbSKevin Laatz    :start-after: Configuration of device. 8<
220bb4141dbSKevin Laatz    :end-before: >8 End of configuration of device.
221bb4141dbSKevin Laatz    :dedent: 0
222bb4141dbSKevin Laatz
223bb4141dbSKevin LaatzIf initialization is successful, memory for hardware device
224bb4141dbSKevin Laatzstatistics is allocated.
225bb4141dbSKevin Laatz
226*8750576fSNandini PersadFinally, the ``main()`` function starts all packet handling lcores and starts
227bb4141dbSKevin Laatzprinting stats in a loop on the main lcore. The application can be
228bb4141dbSKevin Laatzinterrupted and closed using ``Ctrl-C``. The main lcore waits for
229bb4141dbSKevin Laatzall worker lcores to finish, deallocates resources and exits.
230bb4141dbSKevin Laatz
231bb4141dbSKevin LaatzThe processing lcores launching function are described below.
232bb4141dbSKevin Laatz
233bb4141dbSKevin LaatzThe Lcores Launching Functions
234bb4141dbSKevin Laatz~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
235bb4141dbSKevin Laatz
236bb4141dbSKevin LaatzAs described above, ``main()`` function invokes ``start_forwarding_cores()``
237bb4141dbSKevin Laatzfunction in order to start processing for each lcore:
238bb4141dbSKevin Laatz
239bb4141dbSKevin Laatz.. literalinclude:: ../../../examples/dma/dmafwd.c
240bb4141dbSKevin Laatz    :language: c
241bb4141dbSKevin Laatz    :start-after: Start processing for each lcore. 8<
242bb4141dbSKevin Laatz    :end-before: >8 End of starting to process for each lcore.
243bb4141dbSKevin Laatz    :dedent: 0
244bb4141dbSKevin Laatz
245bb4141dbSKevin LaatzThe function launches Rx/Tx processing functions on configured lcores
246bb4141dbSKevin Laatzusing ``rte_eal_remote_launch()``. The configured ports, their number
247bb4141dbSKevin Laatzand number of assigned lcores are stored in user-defined
248bb4141dbSKevin Laatz``rxtx_transmission_config`` struct:
249bb4141dbSKevin Laatz
250bb4141dbSKevin Laatz.. literalinclude:: ../../../examples/dma/dmafwd.c
251bb4141dbSKevin Laatz    :language: c
252bb4141dbSKevin Laatz    :start-after: Configuring ports and number of assigned lcores in struct. 8<
253bb4141dbSKevin Laatz    :end-before: >8 End of configuration of ports and number of assigned lcores.
254bb4141dbSKevin Laatz    :dedent: 0
255bb4141dbSKevin Laatz
256bb4141dbSKevin LaatzThe structure is initialized in 'main()' function with the values
257bb4141dbSKevin Laatzcorresponding to ports and lcores configuration provided by the user.
258bb4141dbSKevin Laatz
259bb4141dbSKevin LaatzThe Lcores Processing Functions
260bb4141dbSKevin Laatz~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
261bb4141dbSKevin Laatz
262bb4141dbSKevin LaatzFor receiving packets on each port, the ``dma_rx_port()`` function is used.
263bb4141dbSKevin LaatzThe function receives packets on each configured Rx queue. Depending on the
264bb4141dbSKevin Laatzmode the user chose, it will enqueue packets to DMA channels and
265bb4141dbSKevin Laatzthen invoke copy process (hardware copy), or perform software copy of each
266bb4141dbSKevin Laatzpacket using ``pktmbuf_sw_copy()`` function and enqueue them to an rte_ring:
267bb4141dbSKevin Laatz
268bb4141dbSKevin Laatz.. literalinclude:: ../../../examples/dma/dmafwd.c
269bb4141dbSKevin Laatz    :language: c
270bb4141dbSKevin Laatz    :start-after: Receive packets on one port and enqueue to dmadev or rte_ring. 8<
271bb4141dbSKevin Laatz    :end-before: >8 End of receive packets on one port and enqueue to dmadev or rte_ring.
272bb4141dbSKevin Laatz    :dedent: 0
273bb4141dbSKevin Laatz
274bb4141dbSKevin LaatzThe packets are received in burst mode using ``rte_eth_rx_burst()``
275*8750576fSNandini Persadfunction. When using hardware copy mode the packets are enqueued in the
276bb4141dbSKevin Laatzcopying device's buffer using ``dma_enqueue_packets()`` which calls
277bb4141dbSKevin Laatz``rte_dma_copy()``. When all received packets are in the
278*8750576fSNandini Persadbuffer, the copy operations are started by calling ``rte_dma_submit()``.
279bb4141dbSKevin LaatzFunction ``rte_dma_copy()`` operates on physical address of
280bb4141dbSKevin Laatzthe packet. Structure ``rte_mbuf`` contains only physical address to
281*8750576fSNandini Persadstart of the data buffer (``buf_iova``). Thus, the ``rte_pktmbuf_iova()`` API is
282bb4141dbSKevin Laatzused to get the address of the start of the data within the mbuf.
283bb4141dbSKevin Laatz
284bb4141dbSKevin Laatz.. literalinclude:: ../../../examples/dma/dmafwd.c
285bb4141dbSKevin Laatz    :language: c
286bb4141dbSKevin Laatz    :start-after: Receive packets on one port and enqueue to dmadev or rte_ring. 8<
287bb4141dbSKevin Laatz    :end-before: >8 End of receive packets on one port and enqueue to dmadev or rte_ring.
288bb4141dbSKevin Laatz    :dedent: 0
289bb4141dbSKevin Laatz
290bb4141dbSKevin Laatz
291bb4141dbSKevin LaatzOnce the copies have been completed (this includes gathering the completions in
292bb4141dbSKevin LaatzHW copy mode), the copied packets are enqueued to the ``rx_to_tx_ring``, which
293*8750576fSNandini Persadis used to pass the packets to the Tx function.
294bb4141dbSKevin Laatz
295bb4141dbSKevin LaatzAll completed copies are processed by ``dma_tx_port()`` function. This function
296*8750576fSNandini Persaddequeues copied packets from the ``rx_to_tx_ring``. Then, each packet MAC address is changed
297*8750576fSNandini Persadif it was enabled. After that, copies are sent in burst mode using ``rte_eth_tx_burst()``.
298bb4141dbSKevin Laatz
299bb4141dbSKevin Laatz
300bb4141dbSKevin Laatz.. literalinclude:: ../../../examples/dma/dmafwd.c
301bb4141dbSKevin Laatz    :language: c
302bb4141dbSKevin Laatz    :start-after: Transmit packets from dmadev/rte_ring for one port. 8<
303bb4141dbSKevin Laatz    :end-before: >8 End of transmitting packets from dmadev.
304bb4141dbSKevin Laatz    :dedent: 0
305bb4141dbSKevin Laatz
306bb4141dbSKevin LaatzThe Packet Copying Functions
307bb4141dbSKevin Laatz~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
308bb4141dbSKevin Laatz
309*8750576fSNandini PersadIn order to perform SW packet copy, there are user-defined functions to the first copy
310bb4141dbSKevin Laatzthe packet metadata (``pktmbuf_metadata_copy()``) and then the packet data
311bb4141dbSKevin Laatz(``pktmbuf_sw_copy()``):
312bb4141dbSKevin Laatz
313bb4141dbSKevin Laatz.. literalinclude:: ../../../examples/dma/dmafwd.c
314bb4141dbSKevin Laatz    :language: c
315bb4141dbSKevin Laatz    :start-after: Perform packet copy there is a user-defined function. 8<
316bb4141dbSKevin Laatz    :end-before: >8 End of perform packet copy there is a user-defined function.
317bb4141dbSKevin Laatz    :dedent: 0
318bb4141dbSKevin Laatz
319bb4141dbSKevin LaatzThe metadata in this example is copied from ``rx_descriptor_fields1`` marker of
320bb4141dbSKevin Laatz``rte_mbuf`` struct up to ``buf_len`` member.
321bb4141dbSKevin Laatz
322bb4141dbSKevin LaatzIn order to understand why software packet copying is done as shown
323*8750576fSNandini Persadabove, please refer to the :doc:`../prog_guide/mbuf_lib`.
324