From: Jianfeng Tan Date: Fri, 13 Jan 2017 12:18:40 +0000 (+0000) Subject: net/virtio-user: enable multiqueue with kernel vhost X-Git-Tag: spdx-start~5157 X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=be7a4707f7872e08a4c9e4ab80a2cd23c3930cc5;p=dpdk.git net/virtio-user: enable multiqueue with kernel vhost With vhost kernel, to enable multiqueue, we need backend device in kernel support multiqueue feature. Specifically, with tap as the backend, as linux/Documentation/networking/tuntap.txt shows, we check if tap supports IFF_MULTI_QUEUE feature. And for vhost kernel, each queue pair has a vhost fd, and with a tap fd binding this vhost fd. All tap fds are set with the same tap interface name. Signed-off-by: Jianfeng Tan Acked-by: Yuanhan Liu --- diff --git a/drivers/net/virtio/virtio_user/vhost_kernel.c b/drivers/net/virtio/virtio_user/vhost_kernel.c index aeb5075b82..9b6637d6a2 100644 --- a/drivers/net/virtio/virtio_user/vhost_kernel.c +++ b/drivers/net/virtio/virtio_user/vhost_kernel.c @@ -187,6 +187,29 @@ prepare_vhost_memory_kernel(void) (1ULL << VIRTIO_NET_F_HOST_TSO6) | \ (1ULL << VIRTIO_NET_F_CSUM)) +static int +tap_supporte_mq(void) +{ + int tapfd; + unsigned int tap_features; + + tapfd = open(PATH_NET_TUN, O_RDWR); + if (tapfd < 0) { + PMD_DRV_LOG(ERR, "fail to open %s: %s", + PATH_NET_TUN, strerror(errno)); + return -1; + } + + if (ioctl(tapfd, TUNGETFEATURES, &tap_features) == -1) { + PMD_DRV_LOG(ERR, "TUNGETFEATURES failed: %s", strerror(errno)); + close(tapfd); + return -1; + } + + close(tapfd); + return tap_features & IFF_MULTI_QUEUE; +} + static int vhost_kernel_ioctl(struct virtio_user_dev *dev, enum vhost_user_request req, @@ -196,6 +219,8 @@ vhost_kernel_ioctl(struct virtio_user_dev *dev, unsigned int i; uint64_t req_kernel; struct vhost_memory_kernel *vm = NULL; + int vhostfd; + unsigned int queue_sel; PMD_DRV_LOG(INFO, "%s", vhost_msg_strings[req]); @@ -215,15 +240,37 @@ vhost_kernel_ioctl(struct virtio_user_dev *dev, /* VHOST kernel does not know about below flags */ *(uint64_t *)arg &= ~VHOST_KERNEL_GUEST_OFFLOADS_MASK; *(uint64_t *)arg &= ~VHOST_KERNEL_HOST_OFFLOADS_MASK; + + *(uint64_t *)arg &= ~(1ULL << VIRTIO_NET_F_MQ); } - for (i = 0; i < dev->max_queue_pairs; ++i) { - if (dev->vhostfds[i] < 0) - continue; + switch (req_kernel) { + case VHOST_SET_VRING_NUM: + case VHOST_SET_VRING_ADDR: + case VHOST_SET_VRING_BASE: + case VHOST_GET_VRING_BASE: + case VHOST_SET_VRING_KICK: + case VHOST_SET_VRING_CALL: + queue_sel = *(unsigned int *)arg; + vhostfd = dev->vhostfds[queue_sel / 2]; + *(unsigned int *)arg = queue_sel % 2; + PMD_DRV_LOG(DEBUG, "vhostfd=%d, index=%u", + vhostfd, *(unsigned int *)arg); + break; + default: + vhostfd = -1; + } + if (vhostfd == -1) { + for (i = 0; i < dev->max_queue_pairs; ++i) { + if (dev->vhostfds[i] < 0) + continue; - ret = ioctl(dev->vhostfds[i], req_kernel, arg); - if (ret < 0) - break; + ret = ioctl(dev->vhostfds[i], req_kernel, arg); + if (ret < 0) + break; + } + } else { + ret = ioctl(vhostfd, req_kernel, arg); } if (!ret && req_kernel == VHOST_GET_FEATURES) { @@ -233,6 +280,12 @@ vhost_kernel_ioctl(struct virtio_user_dev *dev, */ *((uint64_t *)arg) |= VHOST_KERNEL_GUEST_OFFLOADS_MASK; *((uint64_t *)arg) |= VHOST_KERNEL_HOST_OFFLOADS_MASK; + + /* vhost_kernel will not declare this feature, but it does + * support multi-queue. + */ + if (tap_supporte_mq()) + *(uint64_t *)arg |= (1ull << VIRTIO_NET_F_MQ); } if (vm) @@ -305,6 +358,7 @@ vhost_kernel_enable_queue_pair(struct virtio_user_dev *dev, int hdr_size; int vhostfd; int tapfd; + int req_mq = (dev->max_queue_pairs > 1); vhostfd = dev->vhostfds[pair_idx]; @@ -324,7 +378,7 @@ vhost_kernel_enable_queue_pair(struct virtio_user_dev *dev, else hdr_size = sizeof(struct virtio_net_hdr); - tapfd = vhost_kernel_open_tap(&dev->ifname, hdr_size); + tapfd = vhost_kernel_open_tap(&dev->ifname, hdr_size, req_mq); if (tapfd < 0) { PMD_DRV_LOG(ERR, "fail to open tap for vhost kernel"); return -1; diff --git a/drivers/net/virtio/virtio_user/vhost_kernel_tap.c b/drivers/net/virtio/virtio_user/vhost_kernel_tap.c index cdb5c3c180..f585de8c33 100644 --- a/drivers/net/virtio/virtio_user/vhost_kernel_tap.c +++ b/drivers/net/virtio/virtio_user/vhost_kernel_tap.c @@ -44,7 +44,7 @@ #include "../virtio_logs.h" int -vhost_kernel_open_tap(char **p_ifname, int hdr_size) +vhost_kernel_open_tap(char **p_ifname, int hdr_size, int req_mq) { unsigned int tap_features; int sndbuf = INT_MAX; @@ -91,6 +91,9 @@ vhost_kernel_open_tap(char **p_ifname, int hdr_size) goto error; } + if (req_mq) + ifr.ifr_flags |= IFF_MULTI_QUEUE; + if (*p_ifname) strncpy(ifr.ifr_name, *p_ifname, IFNAMSIZ); else diff --git a/drivers/net/virtio/virtio_user/vhost_kernel_tap.h b/drivers/net/virtio/virtio_user/vhost_kernel_tap.h index 8535116c96..eae340ccbf 100644 --- a/drivers/net/virtio/virtio_user/vhost_kernel_tap.h +++ b/drivers/net/virtio/virtio_user/vhost_kernel_tap.h @@ -64,4 +64,4 @@ /* Constants */ #define PATH_NET_TUN "/dev/net/tun" -int vhost_kernel_open_tap(char **p_ifname, int hdr_size); +int vhost_kernel_open_tap(char **p_ifname, int hdr_size, int req_mq); diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.c b/drivers/net/virtio/virtio_user/virtio_user_dev.c index ae0824cd29..6617bc8e7e 100644 --- a/drivers/net/virtio/virtio_user/virtio_user_dev.c +++ b/drivers/net/virtio/virtio_user/virtio_user_dev.c @@ -93,6 +93,7 @@ virtio_user_kick_queue(struct virtio_user_dev *dev, uint32_t queue_sel) state.num = vring->num; dev->ops->send_request(dev, VHOST_USER_SET_VRING_NUM, &state); + state.index = queue_sel; state.num = 0; /* no reservation */ dev->ops->send_request(dev, VHOST_USER_SET_VRING_BASE, &state);