xref: /dpdk/doc/guides/prog_guide/eventdev/event_ethernet_rx_adapter.rst (revision 41dd9a6bc2d9c6e20e139ad713cc9d172572dd43)
1..  SPDX-License-Identifier: BSD-3-Clause
2    Copyright(c) 2017 Intel Corporation.
3
4Event Ethernet Rx Adapter Library
5=================================
6
7The DPDK Eventdev API allows the application to use an event driven programming
8model for packet processing. In this model, the application polls an event
9device port for receiving events that reference packets instead of polling Rx
10queues of ethdev ports. Packet transfer between ethdev and the event device can
11be supported in hardware or require a software thread to receive packets from
12the ethdev port using ethdev poll mode APIs and enqueue these as events to the
13event device using the eventdev API. Both transfer mechanisms may be present on
14the same platform depending on the particular combination of the ethdev and
15the event device.
16
17The Event Ethernet Rx Adapter library is intended for the application code to
18configure both transfer mechanisms using a common API. A capability API allows
19the eventdev PMD to advertise features supported for a given ethdev and allows
20the application to perform configuration as per supported features.
21
22API Walk-through
23----------------
24
25This section will introduce the reader to the adapter API. The
26application has to first instantiate an adapter which is associated with
27a single eventdev, next the adapter instance is configured with Rx queues
28that are either polled by a SW thread or linked using hardware support. Finally
29the adapter is started.
30
31For SW based packet transfers from ethdev to eventdev, the adapter uses a
32DPDK service function and the application is also required to assign a core to
33the service function.
34
35Creating an Adapter Instance
36~~~~~~~~~~~~~~~~~~~~~~~~~~~~
37
38An adapter instance is created using ``rte_event_eth_rx_adapter_create()``. This
39function is passed the event device to be associated with the adapter and port
40configuration for the adapter to setup an event port if the adapter needs to use
41a service function.
42
43.. code-block:: c
44
45        int err;
46        uint8_t dev_id;
47        struct rte_event_dev_info dev_info;
48        struct rte_event_port_conf rx_p_conf;
49
50        err = rte_event_dev_info_get(id, &dev_info);
51
52        rx_p_conf.new_event_threshold = dev_info.max_num_events;
53        rx_p_conf.dequeue_depth = dev_info.max_event_port_dequeue_depth;
54        rx_p_conf.enqueue_depth = dev_info.max_event_port_enqueue_depth;
55        err = rte_event_eth_rx_adapter_create(id, dev_id, &rx_p_conf);
56
57If the application desires to have finer control of eventdev port allocation
58and setup, it can use the ``rte_event_eth_rx_adapter_create_ext()`` function.
59The ``rte_event_eth_rx_adapter_create_ext()`` function is passed a callback
60function. The callback function is invoked if the adapter needs to use a
61service function and needs to create an event port for it. The callback is
62expected to fill the ``struct rte_event_eth_rx_adapter_conf structure``
63passed to it.
64
65If the application desires to control the event buffer size at adapter level,
66it can use the ``rte_event_eth_rx_adapter_create_with_params()`` api. The event
67buffer size is specified using ``struct rte_event_eth_rx_adapter_params::
68event_buf_size``. To configure the event buffer size at queue level, the boolean
69flag ``struct rte_event_eth_rx_adapter_params::use_queue_event_buf`` need to be
70set to true. The function is passed the event device to be associated with
71the adapter and port configuration for the adapter to setup an event port
72if the adapter needs to use a service function.
73
74If the application desires to control both the event port allocation and event
75buffer size, ``rte_event_eth_rx_adapter_create_ext_with_params()`` can be used.
76
77Event device configuration for service based adapter
78~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
79
80When ``rte_event_eth_rx_adapter_create()`` or
81``rte_event_eth_rx_adapter_create_with_params()`` is used for creating
82adapter instance, ``rte_event_dev_config::nb_event_ports`` is
83automatically incremented and the event device is reconfigured
84with the additional event port during service initialization.
85This event device reconfigure logic also increments the
86``rte_event_dev_config::nb_single_link_event_port_queues``
87parameter if the adapter event port config is of type
88``RTE_EVENT_PORT_CFG_SINGLE_LINK``.
89
90Application no longer needs to account for the
91``rte_event_dev_config::nb_event_ports`` and
92``rte_event_dev_config::nb_single_link_event_port_queues``
93parameters required for eth Rx adapter in the event device configuration,
94when the adapter is created using the above-mentioned APIs.
95
96Adding Rx Queues to the Adapter Instance
97~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
98
99Ethdev Rx queues are added to the instance using the
100``rte_event_eth_rx_adapter_queue_add()`` function. Configuration for the Rx
101queue is passed in using a ``struct rte_event_eth_rx_adapter_queue_conf``
102parameter. Event information for packets from this Rx queue is encoded in the
103``ev`` field of ``struct rte_event_eth_rx_adapter_queue_conf``. The
104servicing_weight member of the struct  rte_event_eth_rx_adapter_queue_conf
105is the relative polling frequency of the Rx queue and is applicable when the
106adapter uses a service core function. The applications can configure queue
107event buffer size in ``struct rte_event_eth_rx_adapter_queue_conf::event_buf_size``
108parameter.
109
110.. code-block:: c
111
112        ev.queue_id = 0;
113        ev.sched_type = RTE_SCHED_TYPE_ATOMIC;
114        ev.priority = 0;
115
116        queue_config.rx_queue_flags = 0;
117        queue_config.ev = ev;
118        queue_config.servicing_weight = 1;
119        queue_config.event_buf_size = 1024;
120
121        err = rte_event_eth_rx_adapter_queue_add(id,
122                                                eth_dev_id,
123                                                0, &queue_config);
124
125Querying Adapter Capabilities
126~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
127
128The ``rte_event_eth_rx_adapter_caps_get()`` function allows
129the application to query the adapter capabilities for an eventdev and ethdev
130combination. For e.g, if the ``RTE_EVENT_ETH_RX_ADAPTER_CAP_OVERRIDE_FLOW_ID``
131is set, the application can override the adapter generated flow ID in the event
132using ``rx_queue_flags`` field in ``struct rte_event_eth_rx_adapter_queue_conf``
133which is passed as a parameter to the ``rte_event_eth_rx_adapter_queue_add()``
134function.
135
136.. code-block:: c
137
138        err = rte_event_eth_rx_adapter_caps_get(dev_id, eth_dev_id, &cap);
139
140        queue_config.rx_queue_flags = 0;
141        if (cap & RTE_EVENT_ETH_RX_ADAPTER_CAP_OVERRIDE_FLOW_ID) {
142                ev.flow_id = 1;
143                queue_config.rx_queue_flags =
144                        RTE_EVENT_ETH_RX_ADAPTER_QUEUE_FLOW_ID_VALID;
145        }
146
147Configuring the Service Function
148~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
149
150If the adapter uses a service function, the application is required to assign
151a service core to the service function as show below.
152
153.. code-block:: c
154
155        uint32_t service_id;
156
157        if (rte_event_eth_rx_adapter_service_id_get(0, &service_id) == 0)
158                rte_service_map_lcore_set(service_id, RX_CORE_ID);
159
160Starting the Adapter Instance
161~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
162
163The application calls ``rte_event_eth_rx_adapter_start()`` to start the adapter.
164This function calls the start callbacks of the eventdev PMDs for hardware based
165eventdev-ethdev connections and ``rte_service_run_state_set()`` to enable the
166service function if one exists.
167
168.. Note::
169
170         The eventdev to which the event_eth_rx_adapter is connected needs to
171         be started before calling rte_event_eth_rx_adapter_start().
172
173Getting Adapter Statistics
174~~~~~~~~~~~~~~~~~~~~~~~~~~
175
176The  ``rte_event_eth_rx_adapter_stats_get()`` function reports counters defined
177in struct ``rte_event_eth_rx_adapter_stats``. The received packet and
178enqueued event counts are a sum of the counts from the eventdev PMD callbacks
179if the callback is supported, and the counts maintained by the service function,
180if one exists. The service function also maintains a count of cycles for which
181it was not able to enqueue to the event device.
182
183Getting Adapter queue config
184~~~~~~~~~~~~~~~~~~~~~~~~~~~~
185
186The  ``rte_event_eth_rx_adapter_queue_conf_get()`` function reports
187flags for handling received packets, event queue identifier, scheduler type,
188event priority, polling frequency of the receive queue and flow identifier
189in struct ``rte_event_eth_rx_adapter_queue_conf``.
190
191Set/Get adapter runtime configuration parameters
192~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
193
194The runtime configuration parameters of adapter can be set/get using
195``rte_event_eth_rx_adapter_runtime_params_set()`` and
196``rte_event_eth_rx_adapter_runtime_params_get()`` respectively.
197The parameters that can be set/get are defined in
198``struct rte_event_eth_rx_adapter_runtime_params``.
199
200Getting and resetting Adapter queue stats
201~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
202
203The ``rte_event_eth_rx_adapter_queue_stats_get()`` function reports
204adapter queue counters defined in struct ``rte_event_eth_rx_adapter_queue_stats``.
205This function reports queue level stats only when queue level event buffer is
206used otherwise it returns -EINVAL.
207
208The ``rte_event_eth_rx_adapter_queue_stats_reset`` function can be used to
209reset queue level stats when queue level event buffer is in use.
210
211Getting Adapter Instance ID
212~~~~~~~~~~~~~~~~~~~~~~~~~~~
213
214The ``rte_event_eth_rx_adapter_instance_get()`` function reports
215Rx adapter instance ID for a specified ethernet device ID and Rx queue index.
216
217Interrupt Based Rx Queues
218~~~~~~~~~~~~~~~~~~~~~~~~~~
219
220The service core function is typically set up to poll ethernet Rx queues for
221packets. Certain queues may have low packet rates and it would be more
222efficient to enable the Rx queue interrupt and read packets after receiving
223the interrupt.
224
225The servicing_weight member of struct rte_event_eth_rx_adapter_queue_conf
226is applicable when the adapter uses a service core function. The application
227has to enable Rx queue interrupts when configuring the ethernet device
228using the ``rte_eth_dev_configure()`` function and then use a servicing_weight
229of zero when adding the Rx queue to the adapter.
230
231The adapter creates a thread blocked on the interrupt, on an interrupt this
232thread enqueues the port id and the queue id to a ring buffer. The adapter
233service function dequeues the port id and queue id from the ring buffer,
234invokes the ``rte_eth_rx_burst()`` to receive packets on the queue and
235converts the received packets to events in the same manner as packets
236received on a polled Rx queue. The interrupt thread is affinitized to the same
237CPUs as the lcores of the Rx adapter service function, if the Rx adapter
238service function has not been mapped to any lcores, the interrupt thread
239is mapped to the main lcore.
240
241Rx Callback for SW Rx Adapter
242~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
243
244For SW based packet transfers, i.e., when the
245``RTE_EVENT_ETH_RX_ADAPTER_CAP_INTERNAL_PORT`` is not set in the adapter's
246capabilities flags for a particular ethernet device, the service function
247temporarily enqueues mbufs to an event buffer before batch enqueuing these
248to the event device. If the buffer fills up, the service function stops
249dequeuing packets from the ethernet device. The application may want to
250monitor the buffer fill level and instruct the service function to selectively
251enqueue packets to the event device. The application may also use some other
252criteria to decide which packets should enter the event device even when
253the event buffer fill level is low. The
254``rte_event_eth_rx_adapter_cb_register()`` function allow the application
255to register a callback that selects which packets to enqueue to the event
256device.
257
258Rx event vectorization
259~~~~~~~~~~~~~~~~~~~~~~
260
261The event devices, ethernet device pairs which support the capability
262``RTE_EVENT_ETH_RX_ADAPTER_CAP_EVENT_VECTOR`` can aggregate packets based on
263flow characteristics and generate a ``rte_event`` containing ``rte_event_vector``
264whose event type is either ``RTE_EVENT_TYPE_ETHDEV_VECTOR`` or
265``RTE_EVENT_TYPE_ETH_RX_ADAPTER_VECTOR``.
266The maximum, minimum vector sizes and timeouts vary based on the device
267capability and can be queried using
268``rte_event_eth_rx_adapter_vector_limits_get``.
269The Rx adapter additionally might include useful data such as ethernet device
270port and queue identifier in the ``rte_event_vector::port`` and
271``rte_event_vector::queue`` and mark ``rte_event_vector::attr_valid`` as true.
272The aggregation size and timeout are configurable at a queue level by setting
273``rte_event_eth_rx_adapter_queue_conf::vector_sz``,
274``rte_event_eth_rx_adapter_queue_conf::vector_timeout_ns`` and
275``rte_event_eth_rx_adapter_queue_conf::vector_mp`` when adding queues using
276``rte_event_eth_rx_adapter_queue_add``.
277
278A loop processing ``rte_event_vector`` containing mbufs is shown below.
279
280.. code-block:: c
281
282        event = rte_event_dequeue_burst(event_dev, event_port, &event,
283                                        1, 0);
284        if (!event)
285                continue;
286
287        switch (ev.event_type) {
288        case RTE_EVENT_TYPE_ETH_RX_ADAPTER_VECTOR:
289        case RTE_EVENT_TYPE_ETHDEV_VECTOR:
290                struct rte_mbufs **mbufs;
291
292                mbufs = (struct rte_mbufs **)ev[i].vec->mbufs;
293                for (i = 0; i < ev.vec->nb_elem; i++) {
294                        /* Process each mbuf. */
295                }
296        break;
297        case default:
298                /* Handle other event_types. */
299        }
300
301Rx event vectorization for SW Rx adapter
302~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
303
304For SW based event vectorization, i.e., when the
305``RTE_EVENT_ETH_RX_ADAPTER_CAP_INTERNAL_PORT`` is not set in the adapter's
306capabilities flags for a particular ethernet device, the service function
307creates a single event vector flow for all the mbufs arriving on the given
308Rx queue.
309The 20-bit event flow identifier is set to 12-bits of Rx queue identifier
310and 8-bits of ethernet device identifier.
311Flow identifier is formatted as follows:
312
313.. code-block:: console
314
315    19      12,11            0
316    +---------+--------------+
317    | port_id |   queue_id   |
318    +---------+--------------+
319