1ac8f7ebf3ba34f32acf3a4328b4138cb22f1b47
[deb_dpdk.git] / doc / guides / prog_guide / poll_mode_drv.rst
1 ..  BSD LICENSE
2     Copyright(c) 2010-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 .. _Poll_Mode_Driver:
32
33 Poll Mode Driver
34 ================
35
36 The DPDK includes 1 Gigabit, 10 Gigabit and 40 Gigabit and para virtualized virtio Poll Mode Drivers.
37
38 A Poll Mode Driver (PMD) consists of APIs, provided through the BSD driver running in user space,
39 to configure the devices and their respective queues.
40 In addition, a PMD accesses the RX and TX descriptors directly without any interrupts
41 (with the exception of Link Status Change interrupts) to quickly receive,
42 process and deliver packets in the user's application.
43 This section describes the requirements of the PMDs,
44 their global design principles and proposes a high-level architecture and a generic external API for the Ethernet PMDs.
45
46 Requirements and Assumptions
47 ----------------------------
48
49 The DPDK environment for packet processing applications allows for two models, run-to-completion and pipe-line:
50
51 *   In the *run-to-completion*  model, a specific port's RX descriptor ring is polled for packets through an API.
52     Packets are then processed on the same core and placed on a port's TX descriptor ring through an API for transmission.
53
54 *   In the *pipe-line*  model, one core polls one or more port's RX descriptor ring through an API.
55     Packets are received and passed to another core via a ring.
56     The other core continues to process the packet which then may be placed on a port's TX descriptor ring through an API for transmission.
57
58 In a synchronous run-to-completion model,
59 each logical core assigned to the DPDK executes a packet processing loop that includes the following steps:
60
61 *   Retrieve input packets through the PMD receive API
62
63 *   Process each received packet one at a time, up to its forwarding
64
65 *   Send pending output packets through the PMD transmit API
66
67 Conversely, in an asynchronous pipe-line model, some logical cores may be dedicated to the retrieval of received packets and
68 other logical cores to the processing of previously received packets.
69 Received packets are exchanged between logical cores through rings.
70 The loop for packet retrieval includes the following steps:
71
72 *   Retrieve input packets through the PMD receive API
73
74 *   Provide received packets to processing lcores through packet queues
75
76 The loop for packet processing includes the following steps:
77
78 *   Retrieve the received packet from the packet queue
79
80 *   Process the received packet, up to its retransmission if forwarded
81
82 To avoid any unnecessary interrupt processing overhead, the execution environment must not use any asynchronous notification mechanisms.
83 Whenever needed and appropriate, asynchronous communication should be introduced as much as possible through the use of rings.
84
85 Avoiding lock contention is a key issue in a multi-core environment.
86 To address this issue, PMDs are designed to work with per-core private resources as much as possible.
87 For example, a PMD maintains a separate transmit queue per-core, per-port, if the PMD is not ``DEV_TX_OFFLOAD_MT_LOCKFREE`` capable.
88 In the same way, every receive queue of a port is assigned to and polled by a single logical core (lcore).
89
90 To comply with Non-Uniform Memory Access (NUMA), memory management is designed to assign to each logical core
91 a private buffer pool in local memory to minimize remote memory access.
92 The configuration of packet buffer pools should take into account the underlying physical memory architecture in terms of DIMMS,
93 channels and ranks.
94 The application must ensure that appropriate parameters are given at memory pool creation time.
95 See :ref:`Mempool Library <Mempool_Library>`.
96
97 Design Principles
98 -----------------
99
100 The API and architecture of the Ethernet* PMDs are designed with the following guidelines in mind.
101
102 PMDs must help global policy-oriented decisions to be enforced at the upper application level.
103 Conversely, NIC PMD functions should not impede the benefits expected by upper-level global policies,
104 or worse prevent such policies from being applied.
105
106 For instance, both the receive and transmit functions of a PMD have a maximum number of packets/descriptors to poll.
107 This allows a run-to-completion processing stack to statically fix or
108 to dynamically adapt its overall behavior through different global loop policies, such as:
109
110 *   Receive, process immediately and transmit packets one at a time in a piecemeal fashion.
111
112 *   Receive as many packets as possible, then process all received packets, transmitting them immediately.
113
114 *   Receive a given maximum number of packets, process the received packets, accumulate them and finally send all accumulated packets to transmit.
115
116 To achieve optimal performance, overall software design choices and pure software optimization techniques must be considered and
117 balanced against available low-level hardware-based optimization features (CPU cache properties, bus speed, NIC PCI bandwidth, and so on).
118 The case of packet transmission is an example of this software/hardware tradeoff issue when optimizing burst-oriented network packet processing engines.
119 In the initial case, the PMD could export only an rte_eth_tx_one function to transmit one packet at a time on a given queue.
120 On top of that, one can easily build an rte_eth_tx_burst function that loops invoking the rte_eth_tx_one function to transmit several packets at a time.
121 However, an rte_eth_tx_burst function is effectively implemented by the PMD to minimize the driver-level transmit cost per packet through the following optimizations:
122
123 *   Share among multiple packets the un-amortized cost of invoking the rte_eth_tx_one function.
124
125 *   Enable the rte_eth_tx_burst function to take advantage of burst-oriented hardware features (prefetch data in cache, use of NIC head/tail registers)
126     to minimize the number of CPU cycles per packet, for example by avoiding unnecessary read memory accesses to ring transmit descriptors,
127     or by systematically using arrays of pointers that exactly fit cache line boundaries and sizes.
128
129 *   Apply burst-oriented software optimization techniques to remove operations that would otherwise be unavoidable, such as ring index wrap back management.
130
131 Burst-oriented functions are also introduced via the API for services that are intensively used by the PMD.
132 This applies in particular to buffer allocators used to populate NIC rings, which provide functions to allocate/free several buffers at a time.
133 For example, an mbuf_multiple_alloc function returning an array of pointers to rte_mbuf buffers which speeds up the receive poll function of the PMD when
134 replenishing multiple descriptors of the receive ring.
135
136 Logical Cores, Memory and NIC Queues Relationships
137 --------------------------------------------------
138
139 The DPDK supports NUMA allowing for better performance when a processor's logical cores and interfaces utilize its local memory.
140 Therefore, mbuf allocation associated with local PCIe* interfaces should be allocated from memory pools created in the local memory.
141 The buffers should, if possible, remain on the local processor to obtain the best performance results and RX and TX buffer descriptors
142 should be populated with mbufs allocated from a mempool allocated from local memory.
143
144 The run-to-completion model also performs better if packet or data manipulation is in local memory instead of a remote processors memory.
145 This is also true for the pipe-line model provided all logical cores used are located on the same processor.
146
147 Multiple logical cores should never share receive or transmit queues for interfaces since this would require global locks and hinder performance.
148
149 If the PMD is ``DEV_TX_OFFLOAD_MT_LOCKFREE`` capable, multiple threads can invoke ``rte_eth_tx_burst()``
150 concurrently on the same tx queue without SW lock. This PMD feature found in some NICs and useful in the following use cases:
151
152 *  Remove explicit spinlock in some applications where lcores are not mapped to Tx queues with 1:1 relation.
153
154 *  In the eventdev use case, avoid dedicating a separate TX core for transmitting and thus
155    enables more scaling as all workers can send the packets.
156
157 See `Hardware Offload`_ for ``DEV_TX_OFFLOAD_MT_LOCKFREE`` capability probing details.
158
159 Device Identification and Configuration
160 ---------------------------------------
161
162 Device Identification
163 ~~~~~~~~~~~~~~~~~~~~~
164
165 Each NIC port is uniquely designated by its (bus/bridge, device, function) PCI
166 identifiers assigned by the PCI probing/enumeration function executed at DPDK initialization.
167 Based on their PCI identifier, NIC ports are assigned two other identifiers:
168
169 *   A port index used to designate the NIC port in all functions exported by the PMD API.
170
171 *   A port name used to designate the port in console messages, for administration or debugging purposes.
172     For ease of use, the port name includes the port index.
173
174 Device Configuration
175 ~~~~~~~~~~~~~~~~~~~~
176
177 The configuration of each NIC port includes the following operations:
178
179 *   Allocate PCI resources
180
181 *   Reset the hardware (issue a Global Reset) to a well-known default state
182
183 *   Set up the PHY and the link
184
185 *   Initialize statistics counters
186
187 The PMD API must also export functions to start/stop the all-multicast feature of a port and functions to set/unset the port in promiscuous mode.
188
189 Some hardware offload features must be individually configured at port initialization through specific configuration parameters.
190 This is the case for the Receive Side Scaling (RSS) and Data Center Bridging (DCB) features for example.
191
192 On-the-Fly Configuration
193 ~~~~~~~~~~~~~~~~~~~~~~~~
194
195 All device features that can be started or stopped "on the fly" (that is, without stopping the device) do not require the PMD API to export dedicated functions for this purpose.
196
197 All that is required is the mapping address of the device PCI registers to implement the configuration of these features in specific functions outside of the drivers.
198
199 For this purpose,
200 the PMD API exports a function that provides all the information associated with a device that can be used to set up a given device feature outside of the driver.
201 This includes the PCI vendor identifier, the PCI device identifier, the mapping address of the PCI device registers, and the name of the driver.
202
203 The main advantage of this approach is that it gives complete freedom on the choice of the API used to configure, to start, and to stop such features.
204
205 As an example, refer to the configuration of the IEEE1588 feature for the IntelĀ® 82576 Gigabit Ethernet Controller and
206 the IntelĀ® 82599 10 Gigabit Ethernet Controller controllers in the testpmd application.
207
208 Other features such as the L3/L4 5-Tuple packet filtering feature of a port can be configured in the same way.
209 Ethernet* flow control (pause frame) can be configured on the individual port.
210 Refer to the testpmd source code for details.
211 Also, L4 (UDP/TCP/ SCTP) checksum offload by the NIC can be enabled for an individual packet as long as the packet mbuf is set up correctly. See `Hardware Offload`_ for details.
212
213 Configuration of Transmit Queues
214 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
215
216 Each transmit queue is independently configured with the following information:
217
218 *   The number of descriptors of the transmit ring
219
220 *   The socket identifier used to identify the appropriate DMA memory zone from which to allocate the transmit ring in NUMA architectures
221
222 *   The values of the Prefetch, Host and Write-Back threshold registers of the transmit queue
223
224 *   The *minimum* transmit packets to free threshold (tx_free_thresh).
225     When the number of descriptors used to transmit packets exceeds this threshold, the network adaptor should be checked to see if it has written back descriptors.
226     A value of 0 can be passed during the TX queue configuration to indicate the default value should be used.
227     The default value for tx_free_thresh is 32.
228     This ensures that the PMD does not search for completed descriptors until at least 32 have been processed by the NIC for this queue.
229
230 *   The *minimum*  RS bit threshold. The minimum number of transmit descriptors to use before setting the Report Status (RS) bit in the transmit descriptor.
231     Note that this parameter may only be valid for Intel 10 GbE network adapters.
232     The RS bit is set on the last descriptor used to transmit a packet if the number of descriptors used since the last RS bit setting,
233     up to the first descriptor used to transmit the packet, exceeds the transmit RS bit threshold (tx_rs_thresh).
234     In short, this parameter controls which transmit descriptors are written back to host memory by the network adapter.
235     A value of 0 can be passed during the TX queue configuration to indicate that the default value should be used.
236     The default value for tx_rs_thresh is 32.
237     This ensures that at least 32 descriptors are used before the network adapter writes back the most recently used descriptor.
238     This saves upstream PCIe* bandwidth resulting from TX descriptor write-backs.
239     It is important to note that the TX Write-back threshold (TX wthresh) should be set to 0 when tx_rs_thresh is greater than 1.
240     Refer to the IntelĀ® 82599 10 Gigabit Ethernet Controller Datasheet for more details.
241
242 The following constraints must be satisfied for tx_free_thresh and tx_rs_thresh:
243
244 *   tx_rs_thresh must be greater than 0.
245
246 *   tx_rs_thresh must be less than the size of the ring minus 2.
247
248 *   tx_rs_thresh must be less than or equal to tx_free_thresh.
249
250 *   tx_free_thresh must be greater than 0.
251
252 *   tx_free_thresh must be less than the size of the ring minus 3.
253
254 *   For optimal performance, TX wthresh should be set to 0 when tx_rs_thresh is greater than 1.
255
256 One descriptor in the TX ring is used as a sentinel to avoid a hardware race condition, hence the maximum threshold constraints.
257
258 .. note::
259
260     When configuring for DCB operation, at port initialization, both the number of transmit queues and the number of receive queues must be set to 128.
261
262 Free Tx mbuf on Demand
263 ~~~~~~~~~~~~~~~~~~~~~~
264
265 Many of the drivers do not release the mbuf back to the mempool, or local cache,
266 immediately after the packet has been transmitted.
267 Instead, they leave the mbuf in their Tx ring and
268 either perform a bulk release when the ``tx_rs_thresh`` has been crossed
269 or free the mbuf when a slot in the Tx ring is needed.
270
271 An application can request the driver to release used mbufs with the ``rte_eth_tx_done_cleanup()`` API.
272 This API requests the driver to release mbufs that are no longer in use,
273 independent of whether or not the ``tx_rs_thresh`` has been crossed.
274 There are two scenarios when an application may want the mbuf released immediately:
275
276 * When a given packet needs to be sent to multiple destination interfaces
277   (either for Layer 2 flooding or Layer 3 multi-cast).
278   One option is to make a copy of the packet or a copy of the header portion that needs to be manipulated.
279   A second option is to transmit the packet and then poll the ``rte_eth_tx_done_cleanup()`` API
280   until the reference count on the packet is decremented.
281   Then the same packet can be transmitted to the next destination interface.
282   The application is still responsible for managing any packet manipulations needed
283   between the different destination interfaces, but a packet copy can be avoided.
284   This API is independent of whether the packet was transmitted or dropped,
285   only that the mbuf is no longer in use by the interface.
286
287 * Some applications are designed to make multiple runs, like a packet generator.
288   For performance reasons and consistency between runs,
289   the application may want to reset back to an initial state
290   between each run, where all mbufs are returned to the mempool.
291   In this case, it can call the ``rte_eth_tx_done_cleanup()`` API
292   for each destination interface it has been using
293   to request it to release of all its used mbufs.
294
295 To determine if a driver supports this API, check for the *Free Tx mbuf on demand* feature
296 in the *Network Interface Controller Drivers* document.
297
298 Hardware Offload
299 ~~~~~~~~~~~~~~~~
300
301 Depending on driver capabilities advertised by
302 ``rte_eth_dev_info_get()``, the PMD may support hardware offloading
303 feature like checksumming, TCP segmentation, VLAN insertion or
304 lockfree multithreaded TX burst on the same TX queue.
305
306 The support of these offload features implies the addition of dedicated
307 status bit(s) and value field(s) into the rte_mbuf data structure, along
308 with their appropriate handling by the receive/transmit functions
309 exported by each PMD. The list of flags and their precise meaning is
310 described in the mbuf API documentation and in the in :ref:`Mbuf Library
311 <Mbuf_Library>`, section "Meta Information".
312
313 Poll Mode Driver API
314 --------------------
315
316 Generalities
317 ~~~~~~~~~~~~
318
319 By default, all functions exported by a PMD are lock-free functions that are assumed
320 not to be invoked in parallel on different logical cores to work on the same target object.
321 For instance, a PMD receive function cannot be invoked in parallel on two logical cores to poll the same RX queue of the same port.
322 Of course, this function can be invoked in parallel by different logical cores on different RX queues.
323 It is the responsibility of the upper-level application to enforce this rule.
324
325 If needed, parallel accesses by multiple logical cores to shared queues can be explicitly protected by dedicated inline lock-aware functions
326 built on top of their corresponding lock-free functions of the PMD API.
327
328 Generic Packet Representation
329 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
330
331 A packet is represented by an rte_mbuf structure, which is a generic metadata structure containing all necessary housekeeping information.
332 This includes fields and status bits corresponding to offload hardware features, such as checksum computation of IP headers or VLAN tags.
333
334 The rte_mbuf data structure includes specific fields to represent, in a generic way, the offload features provided by network controllers.
335 For an input packet, most fields of the rte_mbuf structure are filled in by the PMD receive function with the information contained in the receive descriptor.
336 Conversely, for output packets, most fields of rte_mbuf structures are used by the PMD transmit function to initialize transmit descriptors.
337
338 The mbuf structure is fully described in the :ref:`Mbuf Library <Mbuf_Library>` chapter.
339
340 Ethernet Device API
341 ~~~~~~~~~~~~~~~~~~~
342
343 The Ethernet device API exported by the Ethernet PMDs is described in the *DPDK API Reference*.
344
345 Extended Statistics API
346 ~~~~~~~~~~~~~~~~~~~~~~~
347
348 The extended statistics API allows a PMD to expose all statistics that are
349 available to it, including statistics that are unique to the device.
350 Each statistic has three properties ``name``, ``id`` and ``value``:
351
352 * ``name``: A human readable string formatted by the scheme detailed below.
353 * ``id``: An integer that represents only that statistic.
354 * ``value``: A unsigned 64-bit integer that is the value of the statistic.
355
356 Note that extended statistic identifiers are
357 driver-specific, and hence might not be the same for different ports.
358 The API consists of various ``rte_eth_xstats_*()`` functions, and allows an
359 application to be flexible in how it retrieves statistics.
360
361 Scheme for Human Readable Names
362 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
363
364 A naming scheme exists for the strings exposed to clients of the API. This is
365 to allow scraping of the API for statistics of interest. The naming scheme uses
366 strings split by a single underscore ``_``. The scheme is as follows:
367
368 * direction
369 * detail 1
370 * detail 2
371 * detail n
372 * unit
373
374 Examples of common statistics xstats strings, formatted to comply to the scheme
375 proposed above:
376
377 * ``rx_bytes``
378 * ``rx_crc_errors``
379 * ``tx_multicast_packets``
380
381 The scheme, although quite simple, allows flexibility in presenting and reading
382 information from the statistic strings. The following example illustrates the
383 naming scheme:``rx_packets``. In this example, the string is split into two
384 components. The first component ``rx`` indicates that the statistic is
385 associated with the receive side of the NIC.  The second component ``packets``
386 indicates that the unit of measure is packets.
387
388 A more complicated example: ``tx_size_128_to_255_packets``. In this example,
389 ``tx`` indicates transmission, ``size``  is the first detail, ``128`` etc are
390 more details, and ``packets`` indicates that this is a packet counter.
391
392 Some additions in the metadata scheme are as follows:
393
394 * If the first part does not match ``rx`` or ``tx``, the statistic does not
395   have an affinity with either receive of transmit.
396
397 * If the first letter of the second part is ``q`` and this ``q`` is followed
398   by a number, this statistic is part of a specific queue.
399
400 An example where queue numbers are used is as follows: ``tx_q7_bytes`` which
401 indicates this statistic applies to queue number 7, and represents the number
402 of transmitted bytes on that queue.
403
404 API Design
405 ^^^^^^^^^^
406
407 The xstats API uses the ``name``, ``id``, and ``value`` to allow performant
408 lookup of specific statistics. Performant lookup means two things;
409
410 * No string comparisons with the ``name`` of the statistic in fast-path
411 * Allow requesting of only the statistics of interest
412
413 The API ensures these requirements are met by mapping the ``name`` of the
414 statistic to a unique ``id``, which is used as a key for lookup in the fast-path.
415 The API allows applications to request an array of ``id`` values, so that the
416 PMD only performs the required calculations. Expected usage is that the
417 application scans the ``name`` of each statistic, and caches the ``id``
418 if it has an interest in that statistic. On the fast-path, the integer can be used
419 to retrieve the actual ``value`` of the statistic that the ``id`` represents.
420
421 API Functions
422 ^^^^^^^^^^^^^
423
424 The API is built out of a small number of functions, which can be used to
425 retrieve the number of statistics and the names, IDs and values of those
426 statistics.
427
428 * ``rte_eth_xstats_get_names_by_id()``: returns the names of the statistics. When given a
429   ``NULL`` parameter the function returns the number of statistics that are available.
430
431 * ``rte_eth_xstats_get_id_by_name()``: Searches for the statistic ID that matches
432   ``xstat_name``. If found, the ``id`` integer is set.
433
434 * ``rte_eth_xstats_get_by_id()``: Fills in an array of ``uint64_t`` values
435   with matching the provided ``ids`` array. If the ``ids`` array is NULL, it
436   returns all statistics that are available.
437
438
439 Application Usage
440 ^^^^^^^^^^^^^^^^^
441
442 Imagine an application that wants to view the dropped packet count. If no
443 packets are dropped, the application does not read any other metrics for
444 performance reasons. If packets are dropped, the application has a particular
445 set of statistics that it requests. This "set" of statistics allows the app to
446 decide what next steps to perform. The following code-snippets show how the
447 xstats API can be used to achieve this goal.
448
449 First step is to get all statistics names and list them:
450
451 .. code-block:: c
452
453     struct rte_eth_xstat_name *xstats_names;
454     uint64_t *values;
455     int len, i;
456
457     /* Get number of stats */
458     len = rte_eth_xstats_get_names_by_id(port_id, NULL, NULL, 0);
459     if (len < 0) {
460         printf("Cannot get xstats count\n");
461         goto err;
462     }
463
464     xstats_names = malloc(sizeof(struct rte_eth_xstat_name) * len);
465     if (xstats_names == NULL) {
466         printf("Cannot allocate memory for xstat names\n");
467         goto err;
468     }
469
470     /* Retrieve xstats names, passing NULL for IDs to return all statistics */
471     if (len != rte_eth_xstats_get_names_by_id(port_id, xstats_names, NULL, len)) {
472         printf("Cannot get xstat names\n");
473         goto err;
474     }
475
476     values = malloc(sizeof(values) * len);
477     if (values == NULL) {
478         printf("Cannot allocate memory for xstats\n");
479         goto err;
480     }
481
482     /* Getting xstats values */
483     if (len != rte_eth_xstats_get_by_id(port_id, NULL, values, len)) {
484         printf("Cannot get xstat values\n");
485         goto err;
486     }
487
488     /* Print all xstats names and values */
489     for (i = 0; i < len; i++) {
490         printf("%s: %"PRIu64"\n", xstats_names[i].name, values[i]);
491     }
492
493 The application has access to the names of all of the statistics that the PMD
494 exposes. The application can decide which statistics are of interest, cache the
495 ids of those statistics by looking up the name as follows:
496
497 .. code-block:: c
498
499     uint64_t id;
500     uint64_t value;
501     const char *xstat_name = "rx_errors";
502
503     if(!rte_eth_xstats_get_id_by_name(port_id, xstat_name, &id)) {
504         rte_eth_xstats_get_by_id(port_id, &id, &value, 1);
505         printf("%s: %"PRIu64"\n", xstat_name, value);
506     }
507     else {
508         printf("Cannot find xstats with a given name\n");
509         goto err;
510     }
511
512 The API provides flexibility to the application so that it can look up multiple
513 statistics using an array containing multiple ``id`` numbers. This reduces the
514 function call overhead of retrieving statistics, and makes lookup of multiple
515 statistics simpler for the application.
516
517 .. code-block:: c
518
519     #define APP_NUM_STATS 4
520     /* application cached these ids previously; see above */
521     uint64_t ids_array[APP_NUM_STATS] = {3,4,7,21};
522     uint64_t value_array[APP_NUM_STATS];
523
524     /* Getting multiple xstats values from array of IDs */
525     rte_eth_xstats_get_by_id(port_id, ids_array, value_array, APP_NUM_STATS);
526
527     uint32_t i;
528     for(i = 0; i < APP_NUM_STATS; i++) {
529         printf("%d: %"PRIu64"\n", ids_array[i], value_array[i]);
530     }
531
532
533 This array lookup API for xstats allows the application create multiple
534 "groups" of statistics, and look up the values of those IDs using a single API
535 call. As an end result, the application is able to achieve its goal of
536 monitoring a single statistic ("rx_errors" in this case), and if that shows
537 packets being dropped, it can easily retrieve a "set" of statistics using the
538 IDs array parameter to ``rte_eth_xstats_get_by_id`` function.