Multi-queue requires VIRTIO_NET_F_MQ and VIRTIO_NET_F_CTRL_VQ in feature negotiation. Mainly two changes in virtio-user device emulation layer. - Multi-queue requires ctrl-queue. So ctrl-queue will by enabled automatically when multi-queue is specified. - Provide a method virtio_user_enable_queue_pair() for virtio-user driver to enable/disable queues.
Note: Do not support multiple queue for vhost kernel backend. Signed-off-by: Jianfeng Tan <jianfeng.tan at intel.com> --- drivers/net/virtio/virtio_user/virtio_user_dev.c | 65 ++++++++++++++++++++---- drivers/net/virtio/virtio_user/virtio_user_dev.h | 2 + 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.c b/drivers/net/virtio/virtio_user/virtio_user_dev.c index a8e58c0..ea0d4c4 100644 --- a/drivers/net/virtio/virtio_user/virtio_user_dev.c +++ b/drivers/net/virtio/virtio_user/virtio_user_dev.c @@ -136,11 +136,14 @@ virtio_user_start_device(struct virtio_user_hw *hw) } } - /* After setup all virtqueues, we need to set_features so that - * these features can be set into each virtqueue in vhost side. - * And before that, make sure VIRTIO_NET_F_MAC is stripped. + /* After setup all virtqueues, we need to set_features so that these + * features can be set into each virtqueue in vhost side. And before + * that, make sure VHOST_USER_F_PROTOCOL_FEATURES is added if mq is + * enabled, and VIRTIO_NET_F_MAC is stripped. */ features = hw->features; + if (hw->type == VHOST_USER && hw->max_queue_pairs > 1) + features |= VHOST_USER_MQ; features &= ~(1ull << VIRTIO_NET_F_MAC); ret = vhost_call(hw->vhostfd, hw->type, VHOST_MSG_SET_FEATURES, &features); @@ -161,6 +164,18 @@ error: return -1; } +int +virtio_user_enable_queue_pair(struct virtio_user_hw *hw, + unsigned pair_idx, int enable) +{ + int r = -1; + + if (hw->type == VHOST_USER) + r = vhost_user_enable_queue_pair(hw->vhostfd, pair_idx, enable); + + return r; +} + int virtio_user_stop_device(struct virtio_user_hw *hw) { return vhost_call(hw->vhostfd, hw->type, VHOST_MSG_RESET_OWNER, NULL); @@ -188,7 +203,7 @@ static inline void parse_mac(struct virtio_user_hw *hw, const char *mac) static int virtio_vdev_init(struct rte_eth_dev_data *data, char *path, - int queues, int nb_cq __rte_unused, + int queues, int enable_ctrl_q, int queue_size, const char *mac, char *ifname) { struct stat s; @@ -204,8 +219,6 @@ virtio_vdev_init(struct rte_eth_dev_data *data, char *path, uhw->vhostfd = -1; uhw->tapfd = -1; - /* TODO: cq */ - if (stat(uhw->path, &s) < 0) { PMD_INIT_LOG(ERR, "stat: %s failed, %s", uhw->path, strerror(errno)); @@ -243,9 +256,36 @@ virtio_vdev_init(struct rte_eth_dev_data *data, char *path, } if (uhw->mac_specified) uhw->features |= (1ull << VIRTIO_NET_F_MAC); - /* disable it until we support CQ */ - uhw->features &= ~(1ull << VIRTIO_NET_F_CTRL_VQ); - uhw->features &= ~(1ull << VIRTIO_NET_F_CTRL_RX); + + if (!enable_ctrl_q) { + uhw->features &= ~(1ull << VIRTIO_NET_F_CTRL_VQ); + /* Also disable features depends on VIRTIO_NET_F_CTRL_VQ */ + uhw->features &= ~(1ull << VIRTIO_NET_F_CTRL_RX); + uhw->features &= ~(1ull << VIRTIO_NET_F_CTRL_VLAN); + uhw->features &= ~(1ull << VIRTIO_NET_F_GUEST_ANNOUNCE); + uhw->features &= ~(1ull << VIRTIO_NET_F_MQ); + uhw->features &= ~(1ull << VIRTIO_NET_F_CTRL_MAC_ADDR); + } else { + /* vhost user backend does not need to know ctrl-q, so + * actually we need add this bit into features. However, + * DPDK vhost-user does send features with this bit, so we + * check it instead of OR it for now. + */ + if (!(uhw->features & (1ull << VIRTIO_NET_F_CTRL_VQ))) + PMD_INIT_LOG(INFO, "vhost does not support ctrl-q"); + } + + if (uhw->max_queue_pairs > 1) { + if (uhw->type == VHOST_KERNEL) { + PMD_INIT_LOG(ERR, "MQ not supported for vhost kernel"); + return -1; + } + + if (!(uhw->features & VHOST_USER_MQ)) { + PMD_INIT_LOG(ERR, "MQ not supported by the backend"); + return -1; + } + } return 0; @@ -411,6 +451,13 @@ rte_virtio_user_pmd_devinit(const char *name, const char *params) if (rte_kvargs_count(kvlist, VIRTIO_USER_ARG_CQ_NUM) == 1) rte_kvargs_process(kvlist, VIRTIO_USER_ARG_CQ_NUM, &get_integer_arg, &nb_cq); + else if (queues > 1) + nb_cq = 1; + + if (queues > 1 && nb_cq == 0) { + PMD_INIT_LOG(ERR, "multi-q requires ctrl-q"); + goto end; + } eth_dev = virtio_user_eth_dev_alloc(name); if (!eth_dev) { diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.h b/drivers/net/virtio/virtio_user/virtio_user_dev.h index bc4dc1a..1834a6e 100644 --- a/drivers/net/virtio/virtio_user/virtio_user_dev.h +++ b/drivers/net/virtio/virtio_user/virtio_user_dev.h @@ -55,6 +55,8 @@ struct virtio_user_hw { int virtio_user_start_device(struct virtio_user_hw *hw); int virtio_user_stop_device(struct virtio_user_hw *hw); +int virtio_user_enable_queue_pair(struct virtio_user_hw *hw, + unsigned pair_idx, int enable); const struct virtio_pci_ops vdev_ops; -- 2.1.4