[dpdk-dev] [PATCH v2 7/7] net/virtio_user: enable multiqueue with vhost kernel
Jianfeng Tan
jianfeng.tan at intel.com
Fri Dec 23 08:14:26 CET 2016
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 <jianfeng.tan at intel.com>
---
drivers/net/virtio/virtio_user/vhost_kernel.c | 67 +++++++++++++++++++++---
drivers/net/virtio/virtio_user/virtio_user_dev.c | 1 +
2 files changed, 62 insertions(+), 6 deletions(-)
diff --git a/drivers/net/virtio/virtio_user/vhost_kernel.c b/drivers/net/virtio/virtio_user/vhost_kernel.c
index fb3c454..67b382e 100644
--- a/drivers/net/virtio/virtio_user/vhost_kernel.c
+++ b/drivers/net/virtio/virtio_user/vhost_kernel.c
@@ -203,6 +203,29 @@ static const uint64_t host_offloads_mask =
(1ULL << VIRTIO_NET_F_HOST_TSO6);
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,
void *arg)
@@ -210,6 +233,8 @@ vhost_kernel_ioctl(struct virtio_user_dev *dev,
int i, ret = -1;
uint64_t req_kernel;
struct vhost_memory_kernel *vm = NULL;
+ int vhostfd;
+ unsigned int queue_sel;
req_kernel = vhost_req_user_to_kernel[req];
@@ -229,13 +254,33 @@ vhost_kernel_ioctl(struct virtio_user_dev *dev,
*(uint64_t *)arg &= ~host_offloads_mask;
}
- for (i = 0; i < VHOST_KERNEL_MAX_QUEUES; ++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 < VHOST_KERNEL_MAX_QUEUES; ++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) {
@@ -245,6 +290,12 @@ vhost_kernel_ioctl(struct virtio_user_dev *dev,
*/
*((uint64_t *)arg) |= guest_offloads_mask;
*((uint64_t *)arg) |= 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)
@@ -320,6 +371,7 @@ vhost_kernel_enable_queue_pair(struct virtio_user_dev *dev,
TUN_F_TSO6 |
TUN_F_TSO_ECN |
TUN_F_UFO;
+ int req_mq = (dev->max_queue_pairs > 1);
vhostfd = dev->vhostfds[pair_idx];
@@ -373,6 +425,9 @@ vhost_kernel_enable_queue_pair(struct virtio_user_dev *dev,
goto error;
}
+ if (req_mq)
+ ifr.ifr_flags |= IFF_MULTI_QUEUE;
+
if (dev->ifname)
strncpy(ifr.ifr_name, dev->ifname, IFNAMSIZ);
else
diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.c b/drivers/net/virtio/virtio_user/virtio_user_dev.c
index c718b85..241f5bb 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);
--
2.7.4
More information about the dev
mailing list