@@ -182,3 +182,19 @@ mbufs are destined to the same ethernet port and queue by setting the bit
``rte_event_vector::queue``.
If ``rte_event_vector::attr_valid`` is not set then the Tx adapter should peek
into each mbuf and transmit them to the requested ethernet port and queue pair.
+
+Queue start/stop
+~~~~~~~~~~~~~~~~
+
+The Tx adapter can be configured to start/stop enqueueing of packets to a NIC
+queue using ``rte_event_eth_tx_adapter_queue_start()`` and
+``rte_event_eth_tx_adapter_queue_stop()`` respectively. By default the queue
+is in start state.
+
+Start function enables the Tx Adapter runtime to start enqueueing packets
+to the Tx queue.
+
+Stop function stops the Tx Adapter runtime function from enqueueing any
+packets to the assiciated Tx queue. This API also frees any packets that
+it may have buffered for this queue. All inflight packets destined to the
+queue are freed by the adapter runtime until the queue is started again.
@@ -30,6 +30,14 @@ New Features
Added ``rte_event_eth_tx_adapter_instance_get`` to get the Tx adapter instance id for specified
ethernet device id and Tx queue index.
+
+* **Added Tx adapter queue start/stop API**
+
+ Added ``rte_event_eth_tx_adapter_queue_start`` to start enqueueing packets to the Tx queue by
+ Tx adapter.
+ Added ``rte_event_eth_tx_adapter_queue_stop`` to stop the Tx Adapter from transmitting any
+ packets to the Tx queue.
+
.. This section should contain new features added in this release.
Sample format:
@@ -1294,6 +1294,43 @@ typedef int (*eventdev_eth_tx_adapter_stats_reset_t)(uint8_t id,
typedef int (*eventdev_eth_tx_adapter_instance_get_t)
(uint16_t eth_dev_id, uint16_t tx_queue_id, uint8_t *txa_inst_id);
+/**
+ * Start a Tx queue that is assigned to Tx adapter instance
+ *
+ * @param id
+ * Adapter identifier
+ *
+ * @param eth_dev_id
+ * Port identifier of Ethernet device
+ *
+ * @param tx_queue_id
+ * Ethernet device Tx queue index
+ *
+ * @return
+ * - 0: Success
+ * - <0: Error code on failure
+ */
+typedef int (*eventdev_eth_tx_adapter_queue_start)
+ (uint8_t id, uint16_t eth_dev_id, uint16_t tx_queue_id);
+
+/**
+ * Stop a Tx queue that is assigned to Tx adapter instance
+ *
+ * @param id
+ * Adapter identifier
+ *
+ * @param eth_dev_id
+ * Port identifier of Ethernet device
+ *
+ * @param tx_queue_id
+ * Ethernet device Tx queue index
+ *
+ * @return
+ * - 0: Success
+ * - <0: Error code on failure
+ */
+typedef int (*eventdev_eth_tx_adapter_queue_stop)
+ (uint8_t id, uint16_t eth_dev_id, uint16_t tx_queue_id);
/** Event device operations function pointer table */
struct eventdev_ops {
@@ -1409,6 +1446,10 @@ struct eventdev_ops {
/**< Reset eth Tx adapter statistics */
eventdev_eth_tx_adapter_instance_get_t eth_tx_adapter_instance_get;
/**< Get Tx adapter instance id for Tx queue */
+ eventdev_eth_tx_adapter_queue_start eth_tx_adapter_queue_start;
+ /**< Start Tx queue assigned to Tx adapter instance */
+ eventdev_eth_tx_adapter_queue_stop eth_tx_adapter_queue_stop;
+ /**< Stop Tx queue assigned to Tx adapter instance */
eventdev_selftest dev_selftest;
/**< Start eventdev Selftest */
@@ -47,6 +47,12 @@
#define txa_dev_instance_get(id) \
txa_evdev(id)->dev_ops->eth_tx_adapter_instance_get
+#define txa_dev_queue_start(id) \
+ txa_evdev(id)->dev_ops->eth_tx_adapter_queue_start
+
+#define txa_dev_queue_stop(id) \
+ txa_evdev(id)->dev_ops->eth_tx_adapter_queue_stop
+
#define RTE_EVENT_ETH_TX_ADAPTER_ID_VALID_OR_ERR_RET(id, retval) \
do { \
if (!txa_valid_id(id)) { \
@@ -94,6 +100,8 @@ struct txa_retry {
struct txa_service_queue_info {
/* Queue has been added */
uint8_t added;
+ /* Queue is stopped */
+ bool stopped;
/* Retry callback argument */
struct txa_retry txa_retry;
/* Tx buffer */
@@ -556,7 +564,7 @@ txa_process_event_vector(struct txa_service_data *txa,
port = vec->port;
queue = vec->queue;
tqi = txa_service_queue(txa, port, queue);
- if (unlikely(tqi == NULL || !tqi->added)) {
+ if (unlikely(tqi == NULL || !tqi->added || tqi->stopped)) {
rte_pktmbuf_free_bulk(mbufs, vec->nb_elem);
rte_mempool_put(rte_mempool_from_obj(vec), vec);
return 0;
@@ -570,7 +578,8 @@ txa_process_event_vector(struct txa_service_data *txa,
port = mbufs[i]->port;
queue = rte_event_eth_tx_adapter_txq_get(mbufs[i]);
tqi = txa_service_queue(txa, port, queue);
- if (unlikely(tqi == NULL || !tqi->added)) {
+ if (unlikely(tqi == NULL || !tqi->added ||
+ tqi->stopped)) {
rte_pktmbuf_free(mbufs[i]);
continue;
}
@@ -607,7 +616,8 @@ txa_service_tx(struct txa_service_data *txa, struct rte_event *ev,
queue = rte_event_eth_tx_adapter_txq_get(m);
tqi = txa_service_queue(txa, port, queue);
- if (unlikely(tqi == NULL || !tqi->added)) {
+ if (unlikely(tqi == NULL || !tqi->added ||
+ tqi->stopped)) {
rte_pktmbuf_free(m);
continue;
}
@@ -671,7 +681,8 @@ txa_service_func(void *args)
for (q = 0; q < dev->data->nb_tx_queues; q++) {
tqi = txa_service_queue(txa, i, q);
- if (unlikely(tqi == NULL || !tqi->added))
+ if (unlikely(tqi == NULL || !tqi->added ||
+ tqi->stopped))
continue;
nb_tx += rte_eth_tx_buffer_flush(i, q,
@@ -866,6 +877,7 @@ txa_service_queue_add(uint8_t id,
tqi->tx_buf = tb;
tqi->added = 1;
+ tqi->stopped = false;
tdi->nb_queues++;
txa->nb_queues++;
@@ -884,6 +896,20 @@ txa_service_queue_add(uint8_t id,
return -1;
}
+static inline void
+txa_txq_buffer_drain(struct txa_service_queue_info *tqi)
+{
+ struct rte_eth_dev_tx_buffer *b;
+ uint16_t i;
+
+ b = tqi->tx_buf;
+
+ for (i = 0; i < b->length; i++)
+ rte_pktmbuf_free(b->pkts[i]);
+
+ b->length = 0;
+}
+
static int
txa_service_queue_del(uint8_t id,
const struct rte_eth_dev *dev,
@@ -929,6 +955,8 @@ txa_service_queue_del(uint8_t id,
if (tqi == NULL || !tqi->added)
goto ret_unlock;
+ /* Drain the buffered mbufs */
+ txa_txq_buffer_drain(tqi);
tb = tqi->tx_buf;
tqi->added = 0;
tqi->tx_buf = NULL;
@@ -1319,3 +1347,79 @@ rte_event_eth_tx_adapter_instance_get(uint16_t eth_dev_id,
return -EINVAL;
}
+
+static int
+txa_queue_state_set(uint16_t eth_dev_id, uint16_t tx_queue_id, bool state)
+{
+ struct txa_service_data *txa;
+ struct txa_service_queue_info *tqi;
+ uint8_t txa_inst_id;
+ int ret;
+ uint32_t caps = 0;
+
+ /* Below API already does validation of input parameters.
+ * Hence skipping the validation here.
+ */
+ ret = rte_event_eth_tx_adapter_instance_get(eth_dev_id,
+ tx_queue_id,
+ &txa_inst_id);
+ if (ret < 0)
+ return -EINVAL;
+
+ TXA_CHECK_OR_ERR_RET(txa_inst_id);
+
+ txa = txa_service_id_to_data(txa_inst_id);
+ ret = rte_event_eth_tx_adapter_caps_get(txa->eventdev_id,
+ eth_dev_id,
+ &caps);
+ if (ret < 0)
+ return -EINVAL;
+
+ if (state == true) {
+ if (caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT) {
+ ret = txa_dev_queue_start(txa_inst_id) ?
+ txa_dev_queue_start(txa_inst_id)(txa_inst_id,
+ eth_dev_id,
+ tx_queue_id) : 0;
+ return ret;
+ }
+ rte_spinlock_lock(&txa->tx_lock);
+ tqi = txa_service_queue(txa, eth_dev_id, tx_queue_id);
+ if (unlikely(tqi == NULL || !tqi->added)) {
+ rte_spinlock_unlock(&txa->tx_lock);
+ return -EINVAL;
+ }
+ tqi->stopped = false;
+ rte_spinlock_unlock(&txa->tx_lock);
+ } else {
+ if (caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT) {
+ ret = txa_dev_queue_stop(txa_inst_id) ?
+ txa_dev_queue_stop(txa_inst_id)(txa_inst_id,
+ eth_dev_id,
+ tx_queue_id) : 0;
+ return ret;
+ }
+ rte_spinlock_lock(&txa->tx_lock);
+ tqi = txa_service_queue(txa, eth_dev_id, tx_queue_id);
+ if (unlikely(tqi == NULL || !tqi->added)) {
+ rte_spinlock_unlock(&txa->tx_lock);
+ return -EINVAL;
+ }
+ txa_txq_buffer_drain(tqi);
+ tqi->stopped = true;
+ rte_spinlock_unlock(&txa->tx_lock);
+ }
+ return 0;
+}
+
+int
+rte_event_eth_tx_adapter_queue_start(uint16_t eth_dev_id, uint16_t tx_queue_id)
+{
+ return txa_queue_state_set(eth_dev_id, tx_queue_id, true);
+}
+
+int
+rte_event_eth_tx_adapter_queue_stop(uint16_t eth_dev_id, uint16_t tx_queue_id)
+{
+ return txa_queue_state_set(eth_dev_id, tx_queue_id, false);
+}
@@ -35,6 +35,8 @@
* - rte_event_eth_tx_adapter_event_port_get()
* - rte_event_eth_tx_adapter_service_id_get()
* - rte_event_eth_tx_adapter_instance_get()
+ * - rte_event_eth_tx_adapter_queue_start()
+ * - rte_event_eth_tx_adapter_queue_stop()
*
* The application creates the adapter using
* rte_event_eth_tx_adapter_create() or rte_event_eth_tx_adapter_create_ext().
@@ -446,6 +448,43 @@ int
rte_event_eth_tx_adapter_instance_get(uint16_t eth_dev_id,
uint16_t tx_queue_id,
uint8_t *txa_inst_id);
+/**
+ * Enables the Tx Adapter to start enqueueing packets to the
+ * Tx queue.
+ *
+ * This function is provided so that the application can
+ * resuming enqueueing events that reference packets for
+ * <eth_dev_id, tx_queue_id> after calling
+ * rte_event_eth_tx_adapter_queue_stop()
+ *
+ * @param eth_dev_id
+ * Port identifier of Ethernet device.
+ * @param tx_queue_id
+ * Ethernet device transmit queue index.
+ * @return
+ * - 0: Success
+ * - <0: Error code on failure
+ */
+__rte_experimental
+int
+rte_event_eth_tx_adapter_queue_start(uint16_t eth_dev_id, uint16_t tx_queue_id);
+
+/**
+ * Stops the Tx Adapter from transmitting any mbufs to the
+ * <eth_dev_id, tx_queue_id>. The Tx Adapter also frees any mbufs
+ * that it may have buffered for this queue.
+ *
+ * @param eth_dev_id
+ * Port identifier of Ethernet device.
+ * @param tx_queue_id
+ * Ethernet device transmit queue index.
+ * @return
+ * - 0: Success
+ * - <0: Error code on failure
+ */
+__rte_experimental
+int
+rte_event_eth_tx_adapter_queue_stop(uint16_t eth_dev_id, uint16_t tx_queue_id);
#ifdef __cplusplus
}
@@ -116,6 +116,8 @@ EXPERIMENTAL {
# added in 22.11
rte_event_eth_rx_adapter_instance_get;
rte_event_eth_tx_adapter_instance_get;
+ rte_event_eth_tx_adapter_queue_start;
+ rte_event_eth_tx_adapter_queue_stop;
};
INTERNAL {