To ease packed ring layout integration, this patch makes
the dequeue path to re-use buffer vectors implemented for
enqueue path.

Doing this, copy_desc_to_mbuf() is now ring layout type
agnostic.

Signed-off-by: Maxime Coquelin <maxime.coque...@redhat.com>
---
 lib/librte_vhost/virtio_net.c | 143 ++++++++++--------------------------------
 1 file changed, 33 insertions(+), 110 deletions(-)

diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c
index ec4bcc400..4816e8003 100644
--- a/lib/librte_vhost/virtio_net.c
+++ b/lib/librte_vhost/virtio_net.c
@@ -750,11 +750,9 @@ put_zmbuf(struct zcopy_mbuf *zmbuf)
 
 static __rte_always_inline int
 copy_desc_to_mbuf(struct virtio_net *dev, struct vhost_virtqueue *vq,
-                 struct vring_desc *descs, uint16_t max_desc,
-                 struct rte_mbuf *m, uint16_t desc_idx,
-                 struct rte_mempool *mbuf_pool)
+                 struct buf_vector *buf_vec, uint16_t nr_vec,
+                 struct rte_mbuf *m, struct rte_mempool *mbuf_pool)
 {
-       struct vring_desc *desc;
        uint64_t desc_addr, desc_gaddr;
        uint32_t desc_avail, desc_offset;
        uint32_t mbuf_avail, mbuf_offset;
@@ -764,24 +762,18 @@ copy_desc_to_mbuf(struct virtio_net *dev, struct 
vhost_virtqueue *vq,
        struct virtio_net_hdr tmp_hdr;
        struct virtio_net_hdr *hdr = NULL;
        /* A counter to avoid desc dead loop chain */
-       uint32_t nr_desc = 1;
+       uint16_t vec_idx = 0;
        struct batch_copy_elem *batch_copy = vq->batch_copy_elems;
        int error = 0;
 
-       desc = &descs[desc_idx];
-       if (unlikely((desc->len < dev->vhost_hlen)) ||
-                       (desc->flags & VRING_DESC_F_INDIRECT)) {
-               error = -1;
-               goto out;
-       }
-
-       desc_chunck_len = desc->len;
-       desc_gaddr = desc->addr;
+       desc_chunck_len = buf_vec[vec_idx].buf_len;
+       desc_gaddr = buf_vec[vec_idx].buf_addr;
        desc_addr = vhost_iova_to_vva(dev,
                                        vq, desc_gaddr,
                                        &desc_chunck_len,
                                        VHOST_ACCESS_RO);
-       if (unlikely(!desc_addr)) {
+       if (unlikely(buf_vec[vec_idx].buf_len < dev->vhost_hlen ||
+                               !desc_addr)) {
                error = -1;
                goto out;
        }
@@ -828,16 +820,12 @@ copy_desc_to_mbuf(struct virtio_net *dev, struct 
vhost_virtqueue *vq,
         * for Tx: the first for storing the header, and others
         * for storing the data.
         */
-       if (likely((desc->len == dev->vhost_hlen) &&
-                  (desc->flags & VRING_DESC_F_NEXT) != 0)) {
-               desc = &descs[desc->next];
-               if (unlikely(desc->flags & VRING_DESC_F_INDIRECT)) {
-                       error = -1;
+       if (likely(buf_vec[vec_idx].buf_len == dev->vhost_hlen)) {
+               if (unlikely(++vec_idx >= nr_vec))
                        goto out;
-               }
 
-               desc_chunck_len = desc->len;
-               desc_gaddr = desc->addr;
+               desc_chunck_len = buf_vec[vec_idx].buf_len;
+               desc_gaddr = buf_vec[vec_idx].buf_addr;
                desc_addr = vhost_iova_to_vva(dev,
                                                        vq, desc_gaddr,
                                                        &desc_chunck_len,
@@ -848,10 +836,9 @@ copy_desc_to_mbuf(struct virtio_net *dev, struct 
vhost_virtqueue *vq,
                }
 
                desc_offset = 0;
-               desc_avail  = desc->len;
-               nr_desc    += 1;
+               desc_avail  = buf_vec[vec_idx].buf_len;
        } else {
-               desc_avail  = desc->len - dev->vhost_hlen;
+               desc_avail  = buf_vec[vec_idx].buf_len - dev->vhost_hlen;
 
                if (unlikely(desc_chunck_len < dev->vhost_hlen)) {
                        desc_chunck_len = desc_avail;
@@ -906,7 +893,8 @@ copy_desc_to_mbuf(struct virtio_net *dev, struct 
vhost_virtqueue *vq,
                        if (likely(cpy_len > MAX_BATCH_LEN ||
                                   vq->batch_copy_nb_elems >= vq->size ||
                                   (hdr && cur == m) ||
-                                  desc->len != desc_chunck_len)) {
+                                  buf_vec[vec_idx].buf_len !=
+                                               desc_chunck_len)) {
                                rte_memcpy(rte_pktmbuf_mtod_offset(cur, void *,
                                                                   mbuf_offset),
                                           (void *)((uintptr_t)(desc_addr +
@@ -933,22 +921,11 @@ copy_desc_to_mbuf(struct virtio_net *dev, struct 
vhost_virtqueue *vq,
 
                /* This desc reaches to its end, get the next one */
                if (desc_avail == 0) {
-                       if ((desc->flags & VRING_DESC_F_NEXT) == 0)
+                       if (++vec_idx >= nr_vec)
                                break;
 
-                       if (unlikely(desc->next >= max_desc ||
-                                    ++nr_desc > max_desc)) {
-                               error = -1;
-                               goto out;
-                       }
-                       desc = &descs[desc->next];
-                       if (unlikely(desc->flags & VRING_DESC_F_INDIRECT)) {
-                               error = -1;
-                               goto out;
-                       }
-
-                       desc_chunck_len = desc->len;
-                       desc_gaddr = desc->addr;
+                       desc_chunck_len = buf_vec[vec_idx].buf_len;
+                       desc_gaddr = buf_vec[vec_idx].buf_addr;
                        desc_addr = vhost_iova_to_vva(dev,
                                                        vq, desc_gaddr,
                                                        &desc_chunck_len,
@@ -961,7 +938,7 @@ copy_desc_to_mbuf(struct virtio_net *dev, struct 
vhost_virtqueue *vq,
                        rte_prefetch0((void *)(uintptr_t)desc_addr);
 
                        desc_offset = 0;
-                       desc_avail  = desc->len;
+                       desc_avail  = buf_vec[vec_idx].buf_len;
 
                        PRINT_PACKET(dev, (uintptr_t)desc_addr,
                                        (uint32_t)desc_chunck_len, 0);
@@ -1085,11 +1062,8 @@ rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
        struct virtio_net *dev;
        struct rte_mbuf *rarp_mbuf = NULL;
        struct vhost_virtqueue *vq;
-       uint32_t desc_indexes[MAX_PKT_BURST];
-       uint32_t used_idx;
        uint32_t i = 0;
        uint16_t free_entries;
-       uint16_t avail_idx;
 
        dev = get_device(vid);
        if (!dev)
@@ -1135,7 +1109,6 @@ rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
                        next = TAILQ_NEXT(zmbuf, next);
 
                        if (mbuf_is_consumed(zmbuf->mbuf)) {
-                               used_idx = vq->last_used_idx++ & (vq->size - 1);
                                update_shadow_used_ring(vq, zmbuf->desc_idx, 0);
                                nr_updated += 1;
 
@@ -1182,89 +1155,43 @@ rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
        }
 
        free_entries = *((volatile uint16_t *)&vq->avail->idx) -
-                       vq->last_avail_idx;
+               vq->last_avail_idx;
        if (free_entries == 0)
                goto out;
 
        VHOST_LOG_DEBUG(VHOST_DATA, "(%d) %s\n", dev->vid, __func__);
 
-       /* Prefetch available and used ring */
-       avail_idx = vq->last_avail_idx & (vq->size - 1);
-       used_idx  = vq->last_used_idx  & (vq->size - 1);
-       rte_prefetch0(&vq->avail->ring[avail_idx]);
-       rte_prefetch0(&vq->used->ring[used_idx]);
-
        count = RTE_MIN(count, MAX_PKT_BURST);
        count = RTE_MIN(count, free_entries);
        VHOST_LOG_DEBUG(VHOST_DATA, "(%d) about to dequeue %u buffers\n",
                        dev->vid, count);
 
-       /* Retrieve all of the head indexes first to avoid caching issues. */
        for (i = 0; i < count; i++) {
-               avail_idx = (vq->last_avail_idx + i) & (vq->size - 1);
-               used_idx  = (vq->last_used_idx  + i) & (vq->size - 1);
-               desc_indexes[i] = vq->avail->ring[avail_idx];
-
-               if (likely(dev->dequeue_zero_copy == 0))
-                       update_shadow_used_ring(vq, desc_indexes[i], 0);
-       }
-
-       /* Prefetch descriptor index. */
-       rte_prefetch0(&vq->desc[desc_indexes[0]]);
-       for (i = 0; i < count; i++) {
-               struct vring_desc *desc, *idesc = NULL;
-               uint16_t sz, idx;
-               uint64_t dlen;
+               struct buf_vector buf_vec[BUF_VECTOR_MAX];
+               uint16_t head_idx, dummy_len;
+               uint32_t nr_vec = 0;
                int err;
 
-               if (likely(i + 1 < count))
-                       rte_prefetch0(&vq->desc[desc_indexes[i + 1]]);
-
-               if (vq->desc[desc_indexes[i]].flags & VRING_DESC_F_INDIRECT) {
-                       dlen = vq->desc[desc_indexes[i]].len;
-                       desc = (struct vring_desc *)(uintptr_t)
-                               vhost_iova_to_vva(dev, vq,
-                                               vq->desc[desc_indexes[i]].addr,
-                                               &dlen,
-                                               VHOST_ACCESS_RO);
-                       if (unlikely(!desc))
-                               break;
-
-                       if (unlikely(dlen < vq->desc[desc_indexes[i]].len)) {
-                               /*
-                                * The indirect desc table is not contiguous
-                                * in process VA space, we have to copy it.
-                                */
-                               idesc = alloc_copy_ind_table(dev, vq,
-                                               &vq->desc[desc_indexes[i]]);
-                               if (unlikely(!idesc))
-                                       break;
-
-                               desc = idesc;
-                       }
+               if (unlikely(fill_vec_buf(dev, vq,
+                                               vq->last_avail_idx + i,
+                                               &nr_vec, buf_vec,
+                                               &head_idx, &dummy_len) < 0))
+                       break;
 
-                       rte_prefetch0(desc);
-                       sz = vq->desc[desc_indexes[i]].len / sizeof(*desc);
-                       idx = 0;
-               } else {
-                       desc = vq->desc;
-                       sz = vq->size;
-                       idx = desc_indexes[i];
-               }
+               if (likely(dev->dequeue_zero_copy == 0))
+                       update_shadow_used_ring(vq, head_idx, 0);
 
                pkts[i] = rte_pktmbuf_alloc(mbuf_pool);
                if (unlikely(pkts[i] == NULL)) {
                        RTE_LOG(ERR, VHOST_DATA,
                                "Failed to allocate memory for mbuf.\n");
-                       free_ind_table(idesc);
                        break;
                }
 
-               err = copy_desc_to_mbuf(dev, vq, desc, sz, pkts[i], idx,
-                                       mbuf_pool);
+               err = copy_desc_to_mbuf(dev, vq, buf_vec, nr_vec, pkts[i],
+                               mbuf_pool);
                if (unlikely(err)) {
                        rte_pktmbuf_free(pkts[i]);
-                       free_ind_table(idesc);
                        break;
                }
 
@@ -1274,11 +1201,10 @@ rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
                        zmbuf = get_zmbuf(vq);
                        if (!zmbuf) {
                                rte_pktmbuf_free(pkts[i]);
-                               free_ind_table(idesc);
                                break;
                        }
                        zmbuf->mbuf = pkts[i];
-                       zmbuf->desc_idx = desc_indexes[i];
+                       zmbuf->desc_idx = head_idx;
 
                        /*
                         * Pin lock the mbuf; we will check later to see
@@ -1291,9 +1217,6 @@ rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
                        vq->nr_zmbuf += 1;
                        TAILQ_INSERT_TAIL(&vq->zmbuf_list, zmbuf, next);
                }
-
-               if (unlikely(!!idesc))
-                       free_ind_table(idesc);
        }
        vq->last_avail_idx += i;
 
-- 
2.14.4

Reply via email to