2 Copyright(c) 2015 Intel Corporation. All rights reserved.
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in
13 the documentation and/or other materials provided with the
15 * Neither the name of Intel Corporation nor the names of its
16 contributors may be used to endorse or promote products derived
17 from this software without specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 RX/TX Callbacks Sample Application
33 ==================================
35 The RX/TX Callbacks sample application is a packet forwarding application that
36 demonstrates the use of user defined callbacks on received and transmitted
37 packets. The application performs a simple latency check, using callbacks, to
38 determine the time packets spend within the application.
40 In the sample application a user defined callback is applied to all received
41 packets to add a timestamp. A separate callback is applied to all packets
42 prior to transmission to calculate the elapsed time, in CPU cycles.
45 Compiling the Application
46 -------------------------
48 To compile the application export the path to the DPDK source tree and go to
49 the example directory:
51 .. code-block:: console
53 export RTE_SDK=/path/to/rte_sdk
55 cd ${RTE_SDK}/examples/rxtx_callbacks
58 Set the target, for example:
60 .. code-block:: console
62 export RTE_TARGET=x86_64-native-linuxapp-gcc
64 See the *DPDK Getting Started* Guide for possible ``RTE_TARGET`` values.
66 The callbacks feature requires that the ``CONFIG_RTE_ETHDEV_RXTX_CALLBACKS``
67 setting is on in the ``config/common_`` config file that applies to the
68 target. This is generally on by default:
70 .. code-block:: console
72 CONFIG_RTE_ETHDEV_RXTX_CALLBACKS=y
74 Build the application as follows:
76 .. code-block:: console
81 Running the Application
82 -----------------------
84 To run the example in a ``linuxapp`` environment:
86 .. code-block:: console
88 ./build/rxtx_callbacks -l 1 -n 4
90 Refer to *DPDK Getting Started Guide* for general information on running
91 applications and the Environment Abstraction Layer (EAL) options.
98 The ``rxtx_callbacks`` application is mainly a simple forwarding application
99 based on the :doc:`skeleton`. See that section of the documentation for more
100 details of the forwarding part of the application.
102 The sections below explain the additional RX/TX callback code.
108 The ``main()`` function performs the application initialization and calls the
109 execution threads for each lcore. This function is effectively identical to
110 the ``main()`` function explained in :doc:`skeleton`.
112 The ``lcore_main()`` function is also identical.
114 The main difference is in the user defined ``port_init()`` function where the
115 callbacks are added. This is explained in the next section:
118 The Port Initialization Function
119 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
121 The main functional part of the port initialization is shown below with
127 port_init(uint8_t port, struct rte_mempool *mbuf_pool)
129 struct rte_eth_conf port_conf = port_conf_default;
130 const uint16_t rx_rings = 1, tx_rings = 1;
131 struct ether_addr addr;
135 if (port >= rte_eth_dev_count())
138 /* Configure the Ethernet device. */
139 retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
143 /* Allocate and set up 1 RX queue per Ethernet port. */
144 for (q = 0; q < rx_rings; q++) {
145 retval = rte_eth_rx_queue_setup(port, q, RX_RING_SIZE,
146 rte_eth_dev_socket_id(port), NULL, mbuf_pool);
151 /* Allocate and set up 1 TX queue per Ethernet port. */
152 for (q = 0; q < tx_rings; q++) {
153 retval = rte_eth_tx_queue_setup(port, q, TX_RING_SIZE,
154 rte_eth_dev_socket_id(port), NULL);
159 /* Start the Ethernet port. */
160 retval = rte_eth_dev_start(port);
164 /* Enable RX in promiscuous mode for the Ethernet device. */
165 rte_eth_promiscuous_enable(port);
168 /* Add the callbacks for RX and TX.*/
169 rte_eth_add_rx_callback(port, 0, add_timestamps, NULL);
170 rte_eth_add_tx_callback(port, 0, calc_latency, NULL);
176 The RX and TX callbacks are added to the ports/queues as function pointers:
180 rte_eth_add_rx_callback(port, 0, add_timestamps, NULL);
181 rte_eth_add_tx_callback(port, 0, calc_latency, NULL);
183 More than one callback can be added and additional information can be passed
184 to callback function pointers as a ``void*``. In the examples above ``NULL``
187 The ``add_timestamps()`` and ``calc_latency()`` functions are explained below.
190 The add_timestamps() Callback
191 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
193 The ``add_timestamps()`` callback is added to the RX port and is applied to
194 all packets received:
199 add_timestamps(uint8_t port __rte_unused, uint16_t qidx __rte_unused,
200 struct rte_mbuf **pkts, uint16_t nb_pkts, void *_ __rte_unused)
203 uint64_t now = rte_rdtsc();
205 for (i = 0; i < nb_pkts; i++)
206 pkts[i]->udata64 = now;
211 The DPDK function ``rte_rdtsc()`` is used to add a cycle count timestamp to
212 each packet (see the *cycles* section of the *DPDK API Documentation* for
216 The calc_latency() Callback
217 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
219 The ``calc_latency()`` callback is added to the TX port and is applied to all
220 packets prior to transmission:
225 calc_latency(uint8_t port __rte_unused, uint16_t qidx __rte_unused,
226 struct rte_mbuf **pkts, uint16_t nb_pkts, void *_ __rte_unused)
229 uint64_t now = rte_rdtsc();
232 for (i = 0; i < nb_pkts; i++)
233 cycles += now - pkts[i]->udata64;
235 latency_numbers.total_cycles += cycles;
236 latency_numbers.total_pkts += nb_pkts;
238 if (latency_numbers.total_pkts > (100 * 1000 * 1000ULL)) {
239 printf("Latency = %"PRIu64" cycles\n",
240 latency_numbers.total_cycles / latency_numbers.total_pkts);
242 latency_numbers.total_cycles = latency_numbers.total_pkts = 0;
248 The ``calc_latency()`` function accumulates the total number of packets and
249 the total number of cycles used. Once more than 100 million packets have been
250 transmitted the average cycle count per packet is printed out and the counters