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