virtio: introduce the consistent-qp feature 97/41797/3
authorMohammed Hawari <[email protected]>
Wed, 30 Oct 2024 18:17:07 +0000 (19:17 +0100)
committerFlorin Coras <[email protected]>
Thu, 31 Oct 2024 19:47:58 +0000 (19:47 +0000)
In certain usecases related to Linux legacy pinning of flows on queue
pairs, it is desirable that, for a given index, the rx and tx virtio
queue be handled by the same worker. This change introduces a flag for
virtio and tap interfaces that allow such a mapping.
Example with two workers rxq 0 and txq 0 on worker 0
         rxq 1 and txq 1 on worker 1
         txq 2 on main thread

Change-Id: I1b74a4788843fd1d0e8dcb4e9da30e609e088fe3
Signed-off-by: Mohammed Hawari <[email protected]>
Type: improvement

src/vnet/devices/tap/cli.c
src/vnet/devices/tap/tap.c
src/vnet/devices/tap/tap.h
src/vnet/devices/virtio/cli.c
src/vnet/devices/virtio/pci.c
src/vnet/devices/virtio/pci.h
src/vnet/devices/virtio/virtio.c
src/vnet/devices/virtio/virtio.h

index 5c676d3..5738ef2 100644 (file)
@@ -105,6 +105,8 @@ tap_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
            args.tap_flags |= TAP_FLAG_PACKED;
          else if (unformat (line_input, "in-order"))
            args.tap_flags |= TAP_FLAG_IN_ORDER;
+         else if (unformat (line_input, "consistent-qp"))
+           args.tap_flags |= TAP_FLAG_CONSISTENT_QP;
          else if (unformat (line_input, "hw-addr %U",
                             unformat_ethernet_address, args.mac_addr.bytes))
            args.mac_addr_set = 1;
index b0b0a3a..bb91200 100644 (file)
@@ -212,6 +212,9 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args)
        }
     }
 
+  if (args->tap_flags & TAP_FLAG_CONSISTENT_QP)
+    vif->consistent_qp = 1;
+
   /* if namespace is specified, all further netlink messages should be executed
    * after we change our net namespace */
   if (args->host_namespace)
index 1df2fb7..66f5576 100644 (file)
 #define MIN(x,y) (((x)<(y))?(x):(y))
 #endif
 
-#define foreach_tapv2_flags  \
-  _ (GSO, 0)                 \
-  _ (CSUM_OFFLOAD, 1)        \
-  _ (PERSIST, 2)             \
-  _ (ATTACH, 3)              \
-  _ (TUN, 4)                 \
-  _ (GRO_COALESCE, 5)        \
-  _ (PACKED, 6)              \
-  _ (IN_ORDER, 7)
+#define foreach_tapv2_flags                                                   \
+  _ (GSO, 0)                                                                  \
+  _ (CSUM_OFFLOAD, 1)                                                         \
+  _ (PERSIST, 2)                                                              \
+  _ (ATTACH, 3)                                                               \
+  _ (TUN, 4)                                                                  \
+  _ (GRO_COALESCE, 5)                                                         \
+  _ (PACKED, 6)                                                               \
+  _ (IN_ORDER, 7)                                                             \
+  _ (CONSISTENT_QP, 8)
 
 typedef enum
 {
index c436460..34c74ac 100644 (file)
@@ -64,6 +64,8 @@ virtio_pci_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
        args.bind = VIRTIO_BIND_DEFAULT;
       else if (unformat (line_input, "rss-enabled"))
        args.rss_enabled = 1;
+      else if (unformat (line_input, "consistent-qp"))
+       args.virtio_flags |= VIRTIO_FLAG_CONSISTENT_QP;
       else
        return clib_error_return (0, "unknown input `%U'",
                                  format_unformat_error, input);
index 140cdb9..9562bdc 100644 (file)
@@ -1418,9 +1418,10 @@ virtio_pci_create_if (vlib_main_t * vm, virtio_pci_create_if_args_t * args)
   if (args->virtio_flags & VIRTIO_FLAG_PACKED)
     vif->is_packed = 1;
 
-  if ((error =
-       vlib_pci_device_open (vm, (vlib_pci_addr_t *) & vif->pci_addr,
-                            virtio_pci_device_ids, &h)))
+  if (args->virtio_flags & VIRTIO_FLAG_CONSISTENT_QP)
+    vif->consistent_qp = 1;
+  if ((error = vlib_pci_device_open (vm, (vlib_pci_addr_t *) &vif->pci_addr,
+                                    virtio_pci_device_ids, &h)))
     {
       args->rv = VNET_API_ERROR_INVALID_INTERFACE;
       args->error =
index 745ad6f..5977853 100644 (file)
@@ -283,7 +283,8 @@ typedef struct _virtio_pci_func
   _ (PACKED, 3)                                                               \
   _ (IN_ORDER, 4)                                                             \
   _ (BUFFERING, 5)                                                            \
-  _ (RSS, 6)
+  _ (RSS, 6)                                                                  \
+  _ (CONSISTENT_QP, 7)
 
 typedef enum
 {
index 840936a..682ec32 100644 (file)
@@ -294,6 +294,8 @@ virtio_vring_set_tx_queues (vlib_main_t *vm, virtio_if_t *vif)
 {
   vnet_main_t *vnm = vnet_get_main ();
   vnet_virtio_vring_t *vring;
+  uword n_threads = vlib_get_n_threads ();
+  u8 consistent = vif->consistent_qp;
 
   vec_foreach (vring, vif->txq_vrings)
     {
@@ -308,10 +310,11 @@ virtio_vring_set_tx_queues (vlib_main_t *vm, virtio_if_t *vif)
       return;
     }
 
-  for (u32 j = 0; j < vlib_get_n_threads (); j++)
+  for (u32 j = 0; j < n_threads; j++)
     {
       u32 qi = vif->txq_vrings[j % vif->num_txqs].queue_index;
-      vnet_hw_if_tx_queue_assign_thread (vnm, qi, j);
+      vnet_hw_if_tx_queue_assign_thread (vnm, qi,
+                                        (j + consistent) % n_threads);
     }
 
   vnet_hw_if_update_runtime_data (vnm, vif->hw_if_index);
index a8e2588..fb72051 100644 (file)
@@ -213,6 +213,7 @@ typedef struct
   };
   const virtio_pci_func_t *virtio_pci_func;
   int is_packed;
+  u8 consistent_qp : 1;
 } virtio_if_t;
 
 typedef struct