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 <jianfeng.tan@intel.com> Acked-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
This commit is contained in:
parent
5e97e42025
commit
be7a4707f7
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user