dev: add option to assign one rx and one tx queue per thread 37/43637/5
authorDamjan Marion <[email protected]>
Wed, 23 Jul 2025 12:42:33 +0000 (12:42 +0000)
committerOle Tr�an <[email protected]>
Tue, 2 Sep 2025 12:26:44 +0000 (12:26 +0000)
queue 0 -> main
queue 1 -> thread 1 (worker 0)
queue 2 -> thread 2 (worker 1)

etc...

example startup.conf entry:

devices {
  dev pci/0002:04:00.0 {
    port 0 {
      name eth2
      flags queue-per-thread
    }
  }
}

Type: improvement
Change-Id: Ia1c216905c5e4368a0e2e47688fd87348be20106
Signed-off-by: Damjan Marion <[email protected]>
src/vnet/dev/api.c
src/vnet/dev/dev.h
src/vnet/dev/dev_api.c
src/vnet/dev/port.c
src/vnet/dev/queue.c
src/vnet/dev/types.h

index b27e84b..55c3de3 100644 (file)
@@ -199,6 +199,15 @@ vnet_dev_api_create_port_if (vlib_main_t *vm,
       return VNET_DEV_ERR_NOT_SUPPORTED;
     }
 
+  if (args->flags.e & VNET_DEV_PORT_F_QUEUE_PER_THREAD)
+    {
+      if (args->num_rx_queues)
+       return VNET_DEV_ERR_INVALID_NUM_RX_QUEUES;
+      if (args->num_tx_queues)
+       return VNET_DEV_ERR_INVALID_NUM_TX_QUEUES;
+      args->num_rx_queues = args->num_tx_queues = n_threads;
+    }
+
   if (args->num_rx_queues)
     {
       if (args->num_rx_queues > port->attr.max_rx_queues)
@@ -240,6 +249,7 @@ vnet_dev_api_create_port_if (vlib_main_t *vm,
   clib_memcpy (a.name, args->intf_name, sizeof (a.name));
   a.default_is_intr_mode = default_is_intr_mode;
   a.consistent_qp = (args->flags.n & VNET_DEV_PORT_F_CONSISTENT_QP) != 0;
+  a.queue_per_thread = (args->flags.n & VNET_DEV_PORT_F_QUEUE_PER_THREAD) != 0;
 
   rv = vnet_dev_process_call_port_op_with_ptr (vm, port,
                                               vnet_dev_port_if_create, &a);
index 7e0a3f2..2a72cb2 100644 (file)
@@ -621,6 +621,7 @@ typedef struct
   u16 txq_sz;
   u8 default_is_intr_mode : 1;
   u8 consistent_qp : 1;
+  u8 queue_per_thread : 1;
 
   /* return */
   u32 sw_if_index;
@@ -665,8 +666,11 @@ vnet_dev_port_op_with_ptr_t vnet_dev_port_if_create;
 vnet_dev_port_op_t vnet_dev_port_if_remove;
 
 /* queue.c */
-vnet_dev_rv_t vnet_dev_rx_queue_alloc (vlib_main_t *, vnet_dev_port_t *, u16);
-vnet_dev_rv_t vnet_dev_tx_queue_alloc (vlib_main_t *, vnet_dev_port_t *, u16);
+vnet_dev_rv_t vnet_dev_rx_queue_alloc (vlib_main_t *, vnet_dev_port_t *, u16,
+                                      vnet_dev_queue_id_t,
+                                      clib_thread_index_t);
+vnet_dev_rv_t vnet_dev_tx_queue_alloc (vlib_main_t *, vnet_dev_port_t *, u16,
+                                      vnet_dev_queue_id_t);
 vnet_dev_rx_queue_op_no_rv_t vnet_dev_rx_queue_free;
 vnet_dev_tx_queue_op_no_rv_t vnet_dev_tx_queue_free;
 void vnet_dev_rx_queue_add_counters (vlib_main_t *, vnet_dev_rx_queue_t *,
index 5e9ac50..2804817 100644 (file)
@@ -23,6 +23,10 @@ static u16 vnet_dev_api_msg_id_base;
 foreach_vnet_dev_flag;
 #undef _
 
+#ifndef VL_API_DEV_PORT_FLAG_QUEUE_PER_THREAD
+#define VL_API_DEV_PORT_FLAG_QUEUE_PER_THREAD VNET_DEV_PORT_F_QUEUE_PER_THREAD
+#endif
+
 #define _(b, n, d)                                                            \
   STATIC_ASSERT ((int) VL_API_DEV_PORT_FLAG_##n == (int) VNET_DEV_PORT_F_##n, \
                 "");
index e538b89..c03a560 100644 (file)
@@ -608,11 +608,27 @@ vnet_dev_port_if_create (vlib_main_t *vm, vnet_dev_port_t *port, void *ptr)
     a->num_rx_queues, a->rxq_sz, a->num_tx_queues, a->txq_sz);
 
   for (int i = 0; i < ifs->num_rx_queues; i++)
-    if ((rv = vnet_dev_rx_queue_alloc (vm, port, ifs->rxq_sz)) != VNET_DEV_OK)
-      goto error;
+    {
+      clib_thread_index_t ti = 0;
+      if (n_threads > 1)
+       {
+         if (!a->queue_per_thread)
+           {
+             ti = dm->next_rx_queue_thread++;
+             if (dm->next_rx_queue_thread >= n_threads)
+               dm->next_rx_queue_thread = 0;
+           }
+         else
+           ti = i;
+       }
+      if ((rv = vnet_dev_rx_queue_alloc (vm, port, ifs->rxq_sz, i, ti)) !=
+         VNET_DEV_OK)
+       goto error;
+    }
 
   for (u32 i = 0; i < ifs->num_tx_queues; i++)
-    if ((rv = vnet_dev_tx_queue_alloc (vm, port, ifs->txq_sz)) != VNET_DEV_OK)
+    if ((rv = vnet_dev_tx_queue_alloc (vm, port, ifs->txq_sz, i)) !=
+       VNET_DEV_OK)
       goto error;
 
   for (ti = 0; ti < n_threads; ti++)
index 57ed3dc..c70bf8f 100644 (file)
@@ -29,13 +29,12 @@ vnet_dev_rx_queue_free (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq)
 
 vnet_dev_rv_t
 vnet_dev_rx_queue_alloc (vlib_main_t *vm, vnet_dev_port_t *port,
-                        u16 queue_size)
+                        u16 queue_size, vnet_dev_queue_id_t qid,
+                        clib_thread_index_t ti)
 {
-  vnet_dev_main_t *dm = &vnet_dev_main;
   vnet_dev_rx_queue_t *rxq, **qp;
   vnet_dev_t *dev = port->dev;
   vnet_dev_rv_t rv = VNET_DEV_OK;
-  u16 n_threads = vlib_get_n_threads ();
 
   vnet_dev_port_validate (vm, port);
 
@@ -54,15 +53,10 @@ vnet_dev_rx_queue_alloc (vlib_main_t *vm, vnet_dev_port_t *port,
   rxq->index = qp - port->rx_queues;
 
   /* default queue id - can be changed by driver */
-  rxq->queue_id = qp - port->rx_queues;
+  rxq->queue_id = qid;
   ASSERT (rxq->queue_id < port->attr.max_rx_queues);
 
-  if (n_threads > 1)
-    {
-      rxq->rx_thread_index = dm->next_rx_queue_thread++;
-      if (dm->next_rx_queue_thread >= n_threads)
-       dm->next_rx_queue_thread = 1;
-    }
+  rxq->rx_thread_index = ti;
 
   if (port->rx_queue_ops.alloc)
     rv = port->rx_queue_ops.alloc (vm, rxq);
@@ -122,7 +116,7 @@ vnet_dev_tx_queue_free (vlib_main_t *vm, vnet_dev_tx_queue_t *txq)
 
 vnet_dev_rv_t
 vnet_dev_tx_queue_alloc (vlib_main_t *vm, vnet_dev_port_t *port,
-                        u16 queue_size)
+                        u16 queue_size, vnet_dev_queue_id_t qid)
 {
   vnet_dev_tx_queue_t *txq, **qp;
   vnet_dev_t *dev = port->dev;
@@ -142,8 +136,7 @@ vnet_dev_tx_queue_alloc (vlib_main_t *vm, vnet_dev_port_t *port,
   txq->size = queue_size;
   txq->index = qp - port->tx_queues;
 
-  /* default queue id - can be changed by driver */
-  txq->queue_id = qp - port->tx_queues;
+  txq->queue_id = qid;
   ASSERT (txq->queue_id < port->attr.max_tx_queues);
 
   if (port->tx_queue_ops.alloc)
index 24799ac..0562b3a 100644 (file)
@@ -51,7 +51,8 @@ typedef union
 /* do not change bit assignments - API dependency */
 #define foreach_vnet_dev_port_flag                                            \
   _ (0, INTERRUPT_MODE, "enable interrupt mode")                              \
-  _ (1, CONSISTENT_QP, "consistent queue pairs")
+  _ (1, CONSISTENT_QP, "consistent queue pairs")                              \
+  _ (2, QUEUE_PER_THREAD, "one rx and one tx queue per thread (inc main)")
 
 typedef union
 {