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

Reply via email to