net/virtio-user: fix multiple queues fail in server mode
authorZhiyong Yang <zhiyong.yang@intel.com>
Fri, 11 May 2018 03:31:37 +0000 (11:31 +0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Mon, 14 May 2018 21:31:53 +0000 (22:31 +0100)
This patch fixes multiple queues failure when virtio-user works in
server mode.

This patch adds feature negotiation in the processing of virtio-user
connection and enables multiple-queue pairs.

Fixes: bd8f50a45d0f ("net/virtio-user: support server mode")
Cc: stable@dpdk.org
Signed-off-by: Zhiyong Yang <zhiyong.yang@intel.com>
Reviewed-by: Tiwei Bie <tiwei.bie@intel.com>
drivers/net/virtio/virtio_user/vhost_user.c
drivers/net/virtio/virtio_user/virtio_user_dev.c
drivers/net/virtio/virtio_user/virtio_user_dev.h
drivers/net/virtio/virtio_user_ethdev.c

index 573ef07..ef6e43d 100644 (file)
@@ -287,6 +287,9 @@ vhost_user_sock(struct virtio_user_dev *dev,
 
        PMD_DRV_LOG(INFO, "%s", vhost_msg_strings[req]);
 
+       if (dev->is_server && vhostfd < 0)
+               return -1;
+
        msg.request = req;
        msg.flags = VHOST_USER_VERSION;
        msg.size = 0;
index 6522bec..992a687 100644 (file)
@@ -486,7 +486,7 @@ virtio_user_dev_uninit(struct virtio_user_dev *dev)
                unlink(dev->path);
 }
 
-static uint8_t
+uint8_t
 virtio_user_handle_mq(struct virtio_user_dev *dev, uint16_t q_pairs)
 {
        uint16_t i;
@@ -498,11 +498,17 @@ virtio_user_handle_mq(struct virtio_user_dev *dev, uint16_t q_pairs)
                return -1;
        }
 
-       for (i = 0; i < q_pairs; ++i)
-               ret |= dev->ops->enable_qp(dev, i, 1);
-       for (i = q_pairs; i < dev->max_queue_pairs; ++i)
-               ret |= dev->ops->enable_qp(dev, i, 0);
-
+       /* Server mode can't enable queue pairs if vhostfd is invalid,
+        * always return 0 in this case.
+        */
+       if (dev->vhostfd >= 0) {
+               for (i = 0; i < q_pairs; ++i)
+                       ret |= dev->ops->enable_qp(dev, i, 1);
+               for (i = q_pairs; i < dev->max_queue_pairs; ++i)
+                       ret |= dev->ops->enable_qp(dev, i, 0);
+       } else if (!dev->is_server) {
+               ret = ~0;
+       }
        dev->queue_pairs = q_pairs;
 
        return ret;
index cadff0c..d2d4cb8 100644 (file)
@@ -50,4 +50,5 @@ int virtio_user_dev_init(struct virtio_user_dev *dev, char *path, int queues,
                         int cq, int queue_size, const char *mac, char **ifname);
 void virtio_user_dev_uninit(struct virtio_user_dev *dev);
 void virtio_user_handle_cq(struct virtio_user_dev *dev, uint16_t queue_idx);
+uint8_t virtio_user_handle_mq(struct virtio_user_dev *dev, uint16_t q_pairs);
 #endif
index 8eab909..1c102ca 100644 (file)
@@ -30,6 +30,7 @@ virtio_user_server_reconnect(struct virtio_user_dev *dev)
        int ret;
        int flag;
        int connectfd;
+       uint64_t features = dev->device_features;
        struct rte_eth_dev *eth_dev = &rte_eth_devices[dev->port_id];
 
        connectfd = accept(dev->listenfd, NULL, NULL);
@@ -37,6 +38,25 @@ virtio_user_server_reconnect(struct virtio_user_dev *dev)
                return -1;
 
        dev->vhostfd = connectfd;
+       if (dev->ops->send_request(dev, VHOST_USER_GET_FEATURES,
+                                  &dev->device_features) < 0) {
+               PMD_INIT_LOG(ERR, "get_features failed: %s",
+                            strerror(errno));
+               return -1;
+       }
+
+       features &= ~dev->device_features;
+       /* For following bits, vhost-user doesn't really need to know */
+       features &= ~(1ull << VIRTIO_NET_F_MAC);
+       features &= ~(1ull << VIRTIO_NET_F_CTRL_VLAN);
+       features &= ~(1ull << VIRTIO_NET_F_CTRL_MAC_ADDR);
+       features &= ~(1ull << VIRTIO_NET_F_STATUS);
+       if (features)
+               PMD_INIT_LOG(ERR, "WARNING: Some features 0x%" PRIx64 " are not supported by vhost-user!",
+                            features);
+
+       dev->features &= dev->device_features;
+
        flag = fcntl(connectfd, F_GETFD);
        fcntl(connectfd, F_SETFL, flag | O_NONBLOCK);
 
@@ -44,6 +64,13 @@ virtio_user_server_reconnect(struct virtio_user_dev *dev)
        if (ret < 0)
                return -1;
 
+       if (dev->queue_pairs > 1) {
+               ret = virtio_user_handle_mq(dev, dev->queue_pairs);
+               if (ret != 0) {
+                       PMD_INIT_LOG(ERR, "Fails to enable multi-queue pairs!");
+                       return -1;
+               }
+       }
        if (eth_dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC) {
                if (rte_intr_disable(eth_dev->intr_handle) < 0) {
                        PMD_DRV_LOG(ERR, "interrupt disable failed");