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
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;
}
}
+ 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)
#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
{
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);
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 =
_ (PACKED, 3) \
_ (IN_ORDER, 4) \
_ (BUFFERING, 5) \
- _ (RSS, 6)
+ _ (RSS, 6) \
+ _ (CONSISTENT_QP, 7)
typedef enum
{
{
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)
{
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);
};
const virtio_pci_func_t *virtio_pci_func;
int is_packed;
+ u8 consistent_qp : 1;
} virtio_if_t;
typedef struct