From bd32d6234cad2af5bc220c6976aa84a758131427 Mon Sep 17 00:00:00 2001 From: Mohammed Hawari Date: Wed, 30 Oct 2024 19:17:07 +0100 Subject: virtio: introduce the consistent-qp feature 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 Type: improvement --- src/vnet/devices/tap/cli.c | 2 ++ src/vnet/devices/tap/tap.c | 3 +++ src/vnet/devices/tap/tap.h | 19 ++++++++++--------- src/vnet/devices/virtio/cli.c | 2 ++ src/vnet/devices/virtio/pci.c | 7 ++++--- src/vnet/devices/virtio/pci.h | 3 ++- src/vnet/devices/virtio/virtio.c | 7 +++++-- src/vnet/devices/virtio/virtio.h | 1 + 8 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/vnet/devices/tap/cli.c b/src/vnet/devices/tap/cli.c index 5c676d32d60..5738ef237b6 100644 --- a/src/vnet/devices/tap/cli.c +++ b/src/vnet/devices/tap/cli.c @@ -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; diff --git a/src/vnet/devices/tap/tap.c b/src/vnet/devices/tap/tap.c index b0b0a3af13f..bb91200a525 100644 --- a/src/vnet/devices/tap/tap.c +++ b/src/vnet/devices/tap/tap.c @@ -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) diff --git a/src/vnet/devices/tap/tap.h b/src/vnet/devices/tap/tap.h index 1df2fb7e1ad..66f5576c5be 100644 --- a/src/vnet/devices/tap/tap.h +++ b/src/vnet/devices/tap/tap.h @@ -22,15 +22,16 @@ #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 { diff --git a/src/vnet/devices/virtio/cli.c b/src/vnet/devices/virtio/cli.c index c4364600722..34c74ac91ac 100644 --- a/src/vnet/devices/virtio/cli.c +++ b/src/vnet/devices/virtio/cli.c @@ -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); diff --git a/src/vnet/devices/virtio/pci.c b/src/vnet/devices/virtio/pci.c index 140cdb94153..9562bdc6369 100644 --- a/src/vnet/devices/virtio/pci.c +++ b/src/vnet/devices/virtio/pci.c @@ -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 = diff --git a/src/vnet/devices/virtio/pci.h b/src/vnet/devices/virtio/pci.h index 745ad6fce87..59778533316 100644 --- a/src/vnet/devices/virtio/pci.h +++ b/src/vnet/devices/virtio/pci.h @@ -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 { diff --git a/src/vnet/devices/virtio/virtio.c b/src/vnet/devices/virtio/virtio.c index 840936a43ff..682ec32ceff 100644 --- a/src/vnet/devices/virtio/virtio.c +++ b/src/vnet/devices/virtio/virtio.c @@ -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); diff --git a/src/vnet/devices/virtio/virtio.h b/src/vnet/devices/virtio/virtio.h index a8e258884a4..fb72051ce45 100644 --- a/src/vnet/devices/virtio/virtio.h +++ b/src/vnet/devices/virtio/virtio.h @@ -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 -- cgit 1.2.3-korg