> -----Original Message----- > From: Maxime Coquelin <maxime.coque...@redhat.com> > Sent: Friday, March 31, 2023 11:43 PM > To: dev@dpdk.org; david.march...@redhat.com; Xia, Chenbo > <chenbo....@intel.com>; m...@redhat.com; f...@redhat.com; > jasow...@redhat.com; Liang, Cunming <cunming.li...@intel.com>; Xie, Yongji > <xieyon...@bytedance.com>; echau...@redhat.com; epere...@redhat.com; > amore...@redhat.com > Cc: Maxime Coquelin <maxime.coque...@redhat.com> > Subject: [RFC 27/27] vhost: add multiqueue support to VDUSE > > This patch enables control queue support in order to > support multiqueue. > > Signed-off-by: Maxime Coquelin <maxime.coque...@redhat.com> > --- > lib/vhost/vduse.c | 69 ++++++++++++++++++++++++++++++++++++++++++----- > 1 file changed, 63 insertions(+), 6 deletions(-) > > diff --git a/lib/vhost/vduse.c b/lib/vhost/vduse.c > index 1cd04b4872..135e78fc35 100644 > --- a/lib/vhost/vduse.c > +++ b/lib/vhost/vduse.c > @@ -21,6 +21,7 @@ > #include "iotlb.h" > #include "vduse.h" > #include "vhost.h" > +#include "virtio_net_ctrl.h" > > #define VHOST_VDUSE_API_VERSION 0 > #define VDUSE_CTRL_PATH "/dev/vduse/control" > @@ -31,7 +32,9 @@ > (1ULL << VIRTIO_RING_F_INDIRECT_DESC) | \ > (1ULL << VIRTIO_RING_F_EVENT_IDX) | \ > (1ULL << VIRTIO_F_IN_ORDER) | \ > - (1ULL << VIRTIO_F_IOMMU_PLATFORM)) > + (1ULL << VIRTIO_F_IOMMU_PLATFORM) | \ > + (1ULL << VIRTIO_NET_F_CTRL_VQ) | \ > + (1ULL << VIRTIO_NET_F_MQ)) > > struct vduse { > struct fdset fdset; > @@ -127,6 +130,25 @@ static struct vhost_backend_ops vduse_backend_ops = { > .inject_irq = vduse_inject_irq, > }; > > +static void > +vduse_control_queue_event(int fd, void *arg, int *remove __rte_unused) > +{ > + struct virtio_net *dev = arg; > + uint64_t buf; > + int ret; > + > + ret = read(fd, &buf, sizeof(buf)); > + if (ret < 0) { > + VHOST_LOG_CONFIG(dev->ifname, ERR, "Failed to read control > queue event: %s\n", > + strerror(errno)); > + return; > + } > + > + VHOST_LOG_CONFIG(dev->ifname, DEBUG, "Control queue kicked\n"); > + if (virtio_net_ctrl_handle(dev)) > + VHOST_LOG_CONFIG(dev->ifname, ERR, "Failed to handle ctrl > request\n"); > +} > + > static void > vduse_vring_setup(struct virtio_net *dev, unsigned int index) > { > @@ -192,6 +214,18 @@ vduse_vring_setup(struct virtio_net *dev, unsigned > int index) > vq->kickfd = VIRTIO_UNINITIALIZED_EVENTFD; > return; > } > + > + if (vq == dev->cvq) { > + vhost_enable_guest_notification(dev, vq, 1); > + ret = fdset_add(&vduse.fdset, vq->kickfd, > vduse_control_queue_event, NULL, dev); > + if (ret) { > + VHOST_LOG_CONFIG(dev->ifname, ERR, > + "Failed to setup kickfd handler for > VQ %u: %s\n", > + index, strerror(errno)); > + close(vq->kickfd); > + vq->kickfd = VIRTIO_UNINITIALIZED_EVENTFD; > + } > + } > } > > static void > @@ -236,6 +270,9 @@ vduse_device_start(struct virtio_net *dev) > for (i = 0; i < dev->nr_vring; i++) { > struct vhost_virtqueue *vq = dev->virtqueue[i]; > > + if (vq == dev->cvq) > + continue; > + > if (dev->notify_ops->vring_state_changed) > dev->notify_ops->vring_state_changed(dev->vid, i, vq- > >enabled); > } > @@ -315,8 +352,9 @@ vduse_device_create(const char *path) > { > int control_fd, dev_fd, vid, ret; > pthread_t fdset_tid; > - uint32_t i; > + uint32_t i, max_queue_pairs; > struct virtio_net *dev; > + struct virtio_net_config vnet_config = { 0 }; > uint64_t ver = VHOST_VDUSE_API_VERSION; > struct vduse_dev_config *dev_config = NULL; > const char *name = path + strlen("/dev/vduse/"); > @@ -357,22 +395,33 @@ vduse_device_create(const char *path) > goto out_ctrl_close; > } > > - dev_config = malloc(offsetof(struct vduse_dev_config, config)); > + dev_config = malloc(offsetof(struct vduse_dev_config, config) + > + sizeof(vnet_config)); > if (!dev_config) { > VHOST_LOG_CONFIG(name, ERR, "Failed to allocate VDUSE > config\n"); > ret = -1; > goto out_ctrl_close; > } > > + ret = rte_vhost_driver_get_queue_num(path, &max_queue_pairs); > + if (ret < 0) { > + VHOST_LOG_CONFIG(name, ERR, "Failed to get max queue pairs\n"); > + goto out_free; > + } > + > + VHOST_LOG_CONFIG(path, INFO, "VDUSE max queue pairs: %u\n", > max_queue_pairs); > + > + vnet_config.max_virtqueue_pairs = max_queue_pairs; > memset(dev_config, 0, sizeof(struct vduse_dev_config)); > > strncpy(dev_config->name, name, VDUSE_NAME_MAX - 1); > dev_config->device_id = VIRTIO_ID_NET; > dev_config->vendor_id = 0; > dev_config->features = VDUSE_NET_SUPPORTED_FEATURES; > - dev_config->vq_num = 2; > + dev_config->vq_num = max_queue_pairs * 2 + 1; /* Includes ctrl queue > */ > dev_config->vq_align = sysconf(_SC_PAGE_SIZE); > - dev_config->config_size = 0; > + dev_config->config_size = sizeof(struct virtio_net_config); > + memcpy(dev_config->config, &vnet_config, sizeof(vnet_config)); > > ret = ioctl(control_fd, VDUSE_CREATE_DEV, dev_config); > if (ret < 0) { > @@ -407,7 +456,7 @@ vduse_device_create(const char *path) > dev->vduse_dev_fd = dev_fd; > vhost_setup_virtio_net(dev->vid, true, true, true, true); > > - for (i = 0; i < 2; i++) { > + for (i = 0; i < max_queue_pairs * 2 + 1; i++) { > struct vduse_vq_config vq_cfg = { 0 }; > > ret = alloc_vring_queue(dev, i); > @@ -426,6 +475,8 @@ vduse_device_create(const char *path) > } > } > > + dev->cvq = dev->virtqueue[max_queue_pairs * 2]; > + > ret = fdset_add(&vduse.fdset, dev->vduse_dev_fd, > vduse_events_handler, NULL, dev); > if (ret) { > VHOST_LOG_CONFIG(name, ERR, "Failed to add fd %d to vduse > fdset\n", > @@ -471,6 +522,12 @@ vduse_device_destroy(const char *path) > if (vid == RTE_MAX_VHOST_DEVICE) > return -1; > > + if (dev->cvq && dev->cvq->kickfd >= 0) { > + fdset_del(&vduse.fdset, dev->cvq->kickfd); > + close(dev->cvq->kickfd); > + dev->cvq->kickfd = VIRTIO_UNINITIALIZED_EVENTFD; > + } > + > fdset_del(&vduse.fdset, dev->vduse_dev_fd); > > if (dev->vduse_dev_fd >= 0) { > -- > 2.39.2
Reviewed-by: Chenbo Xia <chenbo....@intel.com>