]> git.proxmox.com Git - ceph.git/blob - ceph/src/dpdk/doc/guides/sample_app_ug/rxtx_callbacks.rst
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / dpdk / doc / guides / sample_app_ug / rxtx_callbacks.rst
1 .. BSD LICENSE
2 Copyright(c) 2015 Intel Corporation. All rights reserved.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8
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
14 distribution.
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.
18
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.
30
31
32 RX/TX Callbacks Sample Application
33 ==================================
34
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.
39
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.
43
44
45 Compiling the Application
46 -------------------------
47
48 To compile the application export the path to the DPDK source tree and go to
49 the example directory:
50
51 .. code-block:: console
52
53 export RTE_SDK=/path/to/rte_sdk
54
55 cd ${RTE_SDK}/examples/rxtx_callbacks
56
57
58 Set the target, for example:
59
60 .. code-block:: console
61
62 export RTE_TARGET=x86_64-native-linuxapp-gcc
63
64 See the *DPDK Getting Started* Guide for possible ``RTE_TARGET`` values.
65
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:
69
70 .. code-block:: console
71
72 CONFIG_RTE_ETHDEV_RXTX_CALLBACKS=y
73
74 Build the application as follows:
75
76 .. code-block:: console
77
78 make
79
80
81 Running the Application
82 -----------------------
83
84 To run the example in a ``linuxapp`` environment:
85
86 .. code-block:: console
87
88 ./build/rxtx_callbacks -c 2 -n 4
89
90 Refer to *DPDK Getting Started Guide* for general information on running
91 applications and the Environment Abstraction Layer (EAL) options.
92
93
94
95 Explanation
96 -----------
97
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.
101
102 The sections below explain the additional RX/TX callback code.
103
104
105 The Main Function
106 ~~~~~~~~~~~~~~~~~
107
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`.
111
112 The ``lcore_main()`` function is also identical.
113
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:
116
117
118 The Port Initialization Function
119 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
120
121 The main functional part of the port initialization is shown below with
122 comments:
123
124 .. code-block:: c
125
126 static inline int
127 port_init(uint8_t port, struct rte_mempool *mbuf_pool)
128 {
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;
132 int retval;
133 uint16_t q;
134
135 if (port >= rte_eth_dev_count())
136 return -1;
137
138 /* Configure the Ethernet device. */
139 retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
140 if (retval != 0)
141 return retval;
142
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);
147 if (retval < 0)
148 return retval;
149 }
150
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);
155 if (retval < 0)
156 return retval;
157 }
158
159 /* Start the Ethernet port. */
160 retval = rte_eth_dev_start(port);
161 if (retval < 0)
162 return retval;
163
164 /* Enable RX in promiscuous mode for the Ethernet device. */
165 rte_eth_promiscuous_enable(port);
166
167
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);
171
172 return 0;
173 }
174
175
176 The RX and TX callbacks are added to the ports/queues as function pointers:
177
178 .. code-block:: c
179
180 rte_eth_add_rx_callback(port, 0, add_timestamps, NULL);
181 rte_eth_add_tx_callback(port, 0, calc_latency, NULL);
182
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``
185 is used.
186
187 The ``add_timestamps()`` and ``calc_latency()`` functions are explained below.
188
189
190 The add_timestamps() Callback
191 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
192
193 The ``add_timestamps()`` callback is added to the RX port and is applied to
194 all packets received:
195
196 .. code-block:: c
197
198 static uint16_t
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)
201 {
202 unsigned i;
203 uint64_t now = rte_rdtsc();
204
205 for (i = 0; i < nb_pkts; i++)
206 pkts[i]->udata64 = now;
207
208 return nb_pkts;
209 }
210
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
213 details).
214
215
216 The calc_latency() Callback
217 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
218
219 The ``calc_latency()`` callback is added to the TX port and is applied to all
220 packets prior to transmission:
221
222 .. code-block:: c
223
224 static uint16_t
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)
227 {
228 uint64_t cycles = 0;
229 uint64_t now = rte_rdtsc();
230 unsigned i;
231
232 for (i = 0; i < nb_pkts; i++)
233 cycles += now - pkts[i]->udata64;
234
235 latency_numbers.total_cycles += cycles;
236 latency_numbers.total_pkts += nb_pkts;
237
238 if (latency_numbers.total_pkts > (100 * 1000 * 1000ULL)) {
239 printf("Latency = %"PRIu64" cycles\n",
240 latency_numbers.total_cycles / latency_numbers.total_pkts);
241
242 latency_numbers.total_cycles = latency_numbers.total_pkts = 0;
243 }
244
245 return nb_pkts;
246 }
247
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
251 are reset.