From: Alan Dewar <alan.de...@att.com> Performance of vhost interfaces can be improved by having multiple TX/RX queue-pairs. QEMU can be told to use multiple queue-pairs for a vhost interface when starting the guest VM. The DPDK will also configure multiple queue-pairs in response to requests from QEMU.
Later when the guest VM reaches the running state, it can decide to not support the multiqueue option. This information is passed down from the guest VM to QEMU, and from QEMU to the DPDK, but the DPDK ignores it. Because the guest VM doesn't support the multiqueue option it will only initialise the first queue-pair, and in turn the DPDK will not signal that the vhost interface is up. This change allows the DPDK to signal that the vhost interface is up after only the first queue-pair is fully initialised if the guest VM does not support the multiqueue option. Signed-off-by: Alan Dewar <alan.de...@att.com> --- lib/librte_vhost/vhost.c | 6 +++--- lib/librte_vhost/vhost_user.c | 8 +++++++- lib/librte_vhost/virtio_net.c | 12 +++++++++--- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c index 1dd9adb..c952756 100644 --- a/lib/librte_vhost/vhost.c +++ b/lib/librte_vhost/vhost.c @@ -397,7 +397,7 @@ rte_vhost_get_queue_num(int vid) if (dev == NULL) return 0; - return dev->nr_vring / 2; + return (dev->features & VIRTIO_NET_F_MQ) ? (dev->nr_vring / 2) : 1; } uint16_t @@ -408,7 +408,7 @@ rte_vhost_get_vring_num(int vid) if (dev == NULL) return 0; - return dev->nr_vring; + return (dev->features & VIRTIO_NET_F_MQ) ? dev->nr_vring : 2; } int @@ -590,7 +590,7 @@ rte_vhost_rx_queue_count(int vid, uint16_t qid) if (dev == NULL) return 0; - if (unlikely(qid >= dev->nr_vring || (qid & 1) == 0)) { + if (unlikely(qid >= rte_vhost_get_vring_num(vid) || (qid & 1) == 0)) { RTE_LOG(ERR, VHOST_DATA, "(%d) %s: invalid virtqueue idx %d.\n", dev->vid, __func__, qid); return 0; diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c index 1dd1a61..d709cb6 100644 --- a/lib/librte_vhost/vhost_user.c +++ b/lib/librte_vhost/vhost_user.c @@ -773,11 +773,17 @@ virtio_is_ready(struct virtio_net *dev) { struct vhost_virtqueue *vq; uint32_t i; + uint32_t vrings_init; if (dev->nr_vring == 0) return 0; - for (i = 0; i < dev->nr_vring; i++) { + /* + * If the guest VM doesn't support the multiqueue feature, only the + * first two vrings will be fully initialised. + */ + vrings_init = (dev->features & VIRTIO_NET_F_MQ) ? dev->nr_vring : 2; + for (i = 0; i < vrings_init; i++) { vq = dev->virtqueue[i]; if (!vq_is_ready(vq)) diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c index edfab3b..ca48499 100644 --- a/lib/librte_vhost/virtio_net.c +++ b/lib/librte_vhost/virtio_net.c @@ -294,9 +294,11 @@ virtio_dev_rx(struct virtio_net *dev, uint16_t queue_id, struct vring_desc *descs; uint16_t used_idx; uint32_t i, sz; + uint16_t nr_vring; LOG_DEBUG(VHOST_DATA, "(%d) %s\n", dev->vid, __func__); - if (unlikely(!is_valid_virt_queue_idx(queue_id, 0, dev->nr_vring))) { + nr_vring = rte_vhost_get_vring_num(dev->vid); + if (unlikely(!is_valid_virt_queue_idx(queue_id, 0, nr_vring))) { RTE_LOG(ERR, VHOST_DATA, "(%d) %s: invalid virtqueue idx %d.\n", dev->vid, __func__, queue_id); return 0; @@ -619,9 +621,11 @@ virtio_dev_merge_rx(struct virtio_net *dev, uint16_t queue_id, uint16_t num_buffers; struct buf_vector buf_vec[BUF_VECTOR_MAX]; uint16_t avail_head; + uint16_t nr_vring; LOG_DEBUG(VHOST_DATA, "(%d) %s\n", dev->vid, __func__); - if (unlikely(!is_valid_virt_queue_idx(queue_id, 0, dev->nr_vring))) { + nr_vring = rte_vhost_get_vring_num(dev->vid); + if (unlikely(!is_valid_virt_queue_idx(queue_id, 0, nr_vring))) { RTE_LOG(ERR, VHOST_DATA, "(%d) %s: invalid virtqueue idx %d.\n", dev->vid, __func__, queue_id); return 0; @@ -1123,12 +1127,14 @@ rte_vhost_dequeue_burst(int vid, uint16_t queue_id, uint32_t i = 0; uint16_t free_entries; uint16_t avail_idx; + uint16_t nr_vring; dev = get_device(vid); if (!dev) return 0; - if (unlikely(!is_valid_virt_queue_idx(queue_id, 1, dev->nr_vring))) { + nr_vring = rte_vhost_get_vring_num(dev->vid); + if (unlikely(!is_valid_virt_queue_idx(queue_id, 1, nr_vring))) { RTE_LOG(ERR, VHOST_DATA, "(%d) %s: invalid virtqueue idx %d.\n", dev->vid, __func__, queue_id); return 0; -- 2.7.4