1..  SPDX-License-Identifier: BSD-3-Clause
2    Copyright(c) 2017 Intel Corporation.
3
4Event Ethernet Tx Adapter Library
5=================================
6
7The DPDK Eventdev API allows the application to use an event driven programming
8model for packet processing in which the event device distributes events
9referencing packets to the application cores in a dynamic load balanced fashion
10while handling atomicity and packet ordering. Event adapters provide the interface
11between the ethernet, crypto and timer devices and the event device. Event adapter
12APIs enable common application code by abstracting PMD specific capabilities.
13The Event ethernet Tx adapter provides configuration and data path APIs for the
14transmit stage of the application allowing the same application code to use eventdev
15PMD support or in its absence, a common implementation.
16
17In the common implementation, the application enqueues mbufs to the adapter
18which runs as a rte_service function. The service function dequeues events
19from its event port and transmits the mbufs referenced by these events.
20
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 Tx queues,
28finally the adapter is started and the application can start enqueuing mbufs
29to it.
30
31Creating an Adapter Instance
32~~~~~~~~~~~~~~~~~~~~~~~~~~~~
33
34An adapter instance is created using ``rte_event_eth_tx_adapter_create()``. This
35function is passed the event device to be associated with the adapter and port
36configuration for the adapter to setup an event port if the adapter needs to use
37a service function.
38
39If the application desires to have finer control of eventdev port configuration,
40it can use the ``rte_event_eth_tx_adapter_create_ext()`` function. The
41``rte_event_eth_tx_adapter_create_ext()`` function is passed a callback function.
42The callback function is invoked if the adapter needs to use a service function
43and needs to create an event port for it. The callback is expected to fill the
44``struct rte_event_eth_tx_adapter_conf`` structure passed to it.
45
46.. code-block:: c
47
48        struct rte_event_dev_info dev_info;
49        struct rte_event_port_conf tx_p_conf = {0};
50
51        err = rte_event_dev_info_get(id, &dev_info);
52
53        tx_p_conf.new_event_threshold = dev_info.max_num_events;
54        tx_p_conf.dequeue_depth = dev_info.max_event_port_dequeue_depth;
55        tx_p_conf.enqueue_depth = dev_info.max_event_port_enqueue_depth;
56
57        err = rte_event_eth_tx_adapter_create(id, dev_id, &tx_p_conf);
58
59Adding Tx Queues to the Adapter Instance
60~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
61
62Ethdev Tx queues are added to the instance using the
63``rte_event_eth_tx_adapter_queue_add()`` function. A queue value
64of -1 is used to indicate all queues within a device.
65
66.. code-block:: c
67
68        int err = rte_event_eth_tx_adapter_queue_add(id,
69						     eth_dev_id,
70						     q);
71
72Querying Adapter Capabilities
73~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
74
75The ``rte_event_eth_tx_adapter_caps_get()`` function allows
76the application to query the adapter capabilities for an eventdev and ethdev
77combination. Currently, the only capability flag defined is
78``RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT``, the application can
79query this flag to determine if a service function is associated with the
80adapter and retrieve its service identifier using the
81``rte_event_eth_tx_adapter_service_id_get()`` API.
82
83
84.. code-block:: c
85
86        int err = rte_event_eth_tx_adapter_caps_get(dev_id, eth_dev_id, &cap);
87
88        if (!(cap & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT))
89                err = rte_event_eth_tx_adapter_service_id_get(id, &service_id);
90
91Linking a Queue to the Adapter's Event Port
92~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
93
94If the adapter uses a service function as described in the previous section, the
95application is required to link a queue to the adapter's event port. The adapter's
96event port can be obtained using the ``rte_event_eth_tx_adapter_event_port_get()``
97function. The queue can be configured with the ``RTE_EVENT_QUEUE_CFG_SINGLE_LINK``
98since it is linked to a single event port.
99
100Configuring the Service Function
101~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
102
103If the adapter uses a service function, the application can assign
104a service core to the service function as shown below.
105
106.. code-block:: c
107
108        if (rte_event_eth_tx_adapter_service_id_get(id, &service_id) == 0)
109                rte_service_map_lcore_set(service_id, TX_CORE_ID);
110
111Starting the Adapter Instance
112~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
113
114The application calls ``rte_event_eth_tx_adapter_start()`` to start the adapter.
115This function calls the start callback of the eventdev PMD if supported,
116and the ``rte_service_run_state_set()`` to enable the service function if one exists.
117
118Enqueuing Packets to the Adapter
119~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
120
121The application needs to notify the adapter about the transmit port and queue used
122to send the packet. The transmit port is set in the ``struct rte mbuf::port`` field
123and the transmit queue is set using the ``rte_event_eth_tx_adapter_txq_set()``
124function.
125
126If the eventdev PMD supports the ``RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT``
127capability for a given ethernet device, the application should use the
128``rte_event_eth_tx_adapter_enqueue()`` function to enqueue packets to the adapter.
129
130If the adapter uses a service function for the ethernet device then the application
131should use the ``rte_event_enqueue_burst()`` function.
132
133.. code-block:: c
134
135	struct rte_event event;
136
137	if (cap & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT) {
138
139		event.mbuf = m;
140		eq_flags = 0;
141
142		m->port = tx_port;
143		rte_event_eth_tx_adapter_txq_set(m, tx_queue_id);
144
145		rte_event_eth_tx_adapter_enqueue(dev_id, ev_port, &event, 1, eq_flags);
146	} else {
147
148		event.queue_id = qid; /* event queue linked to adapter port */
149		event.op = RTE_EVENT_OP_NEW;
150		event.event_type = RTE_EVENT_TYPE_CPU;
151		event.sched_type = RTE_SCHED_TYPE_ATOMIC;
152		event.mbuf = m;
153
154		m->port = tx_port;
155		rte_event_eth_tx_adapter_txq_set(m, tx_queue_id);
156
157		rte_event_enqueue_burst(dev_id, ev_port, &event, 1);
158	}
159
160Getting Adapter Statistics
161~~~~~~~~~~~~~~~~~~~~~~~~~~
162
163The  ``rte_event_eth_tx_adapter_stats_get()`` function reports counters defined
164in struct ``rte_event_eth_tx_adapter_stats``. The counter values are the sum of
165the counts from the eventdev PMD callback if the callback is supported, and
166the counts maintained by the service function, if one exists.
167