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