[dpdk-dev] [PATCH] vhost: support non multiqueue guests

alangordondewar at gmail.com alangordondewar at gmail.com
Wed Jan 31 15:42:23 CET 2018


From: Alan Dewar <alan.dewar at 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.dewar at 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



More information about the dev mailing list