From: Wenwu Ma <wenwux.ma@intel.com>
To: maxime.coquelin@redhat.com, chenbo.xia@intel.com, dev@dpdk.org
Cc: jiayu.hu@intel.com, yinan.wang@intel.com, xingguang.he@intel.com,
weix.ling@intel.com, Wenwu Ma <wenwux.ma@intel.com>
Subject: [PATCH] vhost: support sync copy when data buffer is small
Date: Mon, 11 Apr 2022 13:38:36 +0000 [thread overview]
Message-ID: <20220411133836.200783-1-wenwux.ma@intel.com> (raw)
In async datapath, if the length of data buffer
is less than 256, the data will be copied by CPU
instead of DMA.
Signed-off-by: Wenwu Ma <wenwux.ma@intel.com>
---
lib/vhost/vhost.h | 6 ++-
lib/vhost/virtio_net.c | 96 ++++++++++++++++++++++++++++++------------
2 files changed, 73 insertions(+), 29 deletions(-)
diff --git a/lib/vhost/vhost.h b/lib/vhost/vhost.h
index 9209558465..d0da53aa46 100644
--- a/lib/vhost/vhost.h
+++ b/lib/vhost/vhost.h
@@ -125,8 +125,10 @@ struct vring_used_elem_packed {
* iovec
*/
struct vhost_iovec {
- void *src_addr;
- void *dst_addr;
+ void *src_io_addr;
+ void *dst_io_addr;
+ void *src_virt_addr;
+ void *dst_virt_addr;
size_t len;
};
diff --git a/lib/vhost/virtio_net.c b/lib/vhost/virtio_net.c
index 3085905d17..46f35ac05f 100644
--- a/lib/vhost/virtio_net.c
+++ b/lib/vhost/virtio_net.c
@@ -26,6 +26,8 @@
#define MAX_BATCH_LEN 256
+#define CPU_COPY_THRESHOLD_LEN 256
+
/* DMA device copy operation tracking array. */
struct async_dma_info dma_copy_track[RTE_DMADEV_DEFAULT_MAX];
@@ -61,28 +63,37 @@ vhost_async_dma_transfer_one(struct virtio_net *dev, struct vhost_virtqueue *vq,
int copy_idx = 0;
uint32_t nr_segs = pkt->nr_segs;
uint16_t i;
+ bool is_cpu_copy = true;
if (rte_dma_burst_capacity(dma_id, vchan_id) < nr_segs)
return -1;
for (i = 0; i < nr_segs; i++) {
- copy_idx = rte_dma_copy(dma_id, vchan_id, (rte_iova_t)iov[i].src_addr,
- (rte_iova_t)iov[i].dst_addr, iov[i].len, RTE_DMA_OP_FLAG_LLC);
- /**
- * Since all memory is pinned and DMA vChannel
- * ring has enough space, failure should be a
- * rare case. If failure happens, it means DMA
- * device encounters serious errors; in this
- * case, please stop async data-path and check
- * what has happened to DMA device.
- */
- if (unlikely(copy_idx < 0)) {
- if (!vhost_async_dma_copy_log) {
- VHOST_LOG_DATA(ERR, "(%s) DMA copy failed for channel %d:%u\n",
+ if (iov[i].len > CPU_COPY_THRESHOLD_LEN) {
+ copy_idx = rte_dma_copy(dma_id, vchan_id,
+ (rte_iova_t)iov[i].src_io_addr,
+ (rte_iova_t)iov[i].dst_io_addr,
+ iov[i].len, RTE_DMA_OP_FLAG_LLC);
+ /**
+ * Since all memory is pinned and DMA vChannel
+ * ring has enough space, failure should be a
+ * rare case. If failure happens, it means DMA
+ * device encounters serious errors; in this
+ * case, please stop async data-path and check
+ * what has happened to DMA device.
+ */
+ if (unlikely(copy_idx < 0)) {
+ if (!vhost_async_dma_copy_log) {
+ VHOST_LOG_DATA(ERR,
+ "(%s) DMA copy failed for channel %d:%u\n",
dev->ifname, dma_id, vchan_id);
- vhost_async_dma_copy_log = true;
+ vhost_async_dma_copy_log = true;
+ }
+ return -1;
}
- return -1;
+ is_cpu_copy = false;
+ } else {
+ rte_memcpy(iov[i].dst_virt_addr, iov[i].src_virt_addr, iov[i].len);
}
}
@@ -90,7 +101,13 @@ vhost_async_dma_transfer_one(struct virtio_net *dev, struct vhost_virtqueue *vq,
* Only store packet completion flag address in the last copy's
* slot, and other slots are set to NULL.
*/
- dma_info->pkts_cmpl_flag_addr[copy_idx & ring_mask] = &vq->async->pkts_cmpl_flag[flag_idx];
+ if (is_cpu_copy == false) {
+ dma_info->pkts_cmpl_flag_addr[copy_idx & ring_mask] =
+ &vq->async->pkts_cmpl_flag[flag_idx];
+ } else {
+ vq->async->pkts_cmpl_flag[flag_idx] = true;
+ nr_segs = 0;
+ }
return nr_segs;
}
@@ -123,6 +140,19 @@ vhost_async_dma_transfer(struct virtio_net *dev, struct vhost_virtqueue *vq,
rte_spinlock_unlock(&dma_info->dma_lock);
+ if (unlikely(ret < 0 && pkt_idx > 0)) {
+ do {
+ head_idx = (head_idx == 0) ? vq->size : head_idx - 1;
+ if (vq->async->pkts_cmpl_flag[head_idx] == false)
+ break;
+
+ pkt_idx--;
+ vq->async->pkts_cmpl_flag[head_idx] = false;
+ if (pkt_idx == 0)
+ break;
+ } while (1);
+ }
+
return pkt_idx;
}
@@ -943,7 +973,7 @@ async_iter_initialize(struct virtio_net *dev, struct vhost_async *async)
static __rte_always_inline int
async_iter_add_iovec(struct virtio_net *dev, struct vhost_async *async,
- void *src, void *dst, size_t len)
+ void *io_src, void *io_dst, void *virt_src, void *virt_dst, size_t len)
{
struct vhost_iov_iter *iter;
struct vhost_iovec *iovec;
@@ -962,8 +992,10 @@ async_iter_add_iovec(struct virtio_net *dev, struct vhost_async *async,
iter = async->iov_iter + async->iter_idx;
iovec = async->iovec + async->iovec_idx;
- iovec->src_addr = src;
- iovec->dst_addr = dst;
+ iovec->src_io_addr = io_src;
+ iovec->dst_io_addr = io_dst;
+ iovec->src_virt_addr = virt_src;
+ iovec->dst_virt_addr = virt_dst;
iovec->len = len;
iter->nr_segs++;
@@ -999,12 +1031,13 @@ async_iter_reset(struct vhost_async *async)
static __rte_always_inline int
async_fill_seg(struct virtio_net *dev, struct vhost_virtqueue *vq,
struct rte_mbuf *m, uint32_t mbuf_offset,
- uint64_t buf_iova, uint32_t cpy_len, bool to_desc)
+ uint64_t buf_addr, uint64_t buf_iova, uint32_t cpy_len, bool to_desc)
{
struct vhost_async *async = vq->async;
uint64_t mapped_len;
uint32_t buf_offset = 0;
- void *src, *dst;
+ void *io_src, *io_dst;
+ void *virt_src, *virt_dst;
void *host_iova;
while (cpy_len) {
@@ -1016,16 +1049,23 @@ async_fill_seg(struct virtio_net *dev, struct vhost_virtqueue *vq,
return -1;
}
+
if (to_desc) {
- src = (void *)(uintptr_t)rte_pktmbuf_iova_offset(m, mbuf_offset);
- dst = host_iova;
+ io_src = (void *)(uintptr_t)rte_pktmbuf_iova_offset(m, mbuf_offset);
+ io_dst = host_iova;
+
+ virt_src = rte_pktmbuf_mtod_offset(m, void *, mbuf_offset);
+ virt_dst = (void *)(buf_addr + buf_offset);
} else {
- src = host_iova;
- dst = (void *)(uintptr_t)rte_pktmbuf_iova_offset(m, mbuf_offset);
+ io_src = host_iova;
+ io_dst = (void *)(uintptr_t)rte_pktmbuf_iova_offset(m, mbuf_offset);
+
+ virt_src = (void *)(buf_addr + buf_offset);
+ virt_dst = rte_pktmbuf_mtod_offset(m, void *, mbuf_offset);
}
- if (unlikely(async_iter_add_iovec(dev, async, src, dst,
- (size_t)mapped_len)))
+ if (unlikely(async_iter_add_iovec(dev, async, io_src, io_dst,
+ virt_src, virt_dst, (size_t)mapped_len)))
return -1;
cpy_len -= (uint32_t)mapped_len;
@@ -1169,6 +1209,7 @@ mbuf_to_desc(struct virtio_net *dev, struct vhost_virtqueue *vq,
if (is_async) {
if (async_fill_seg(dev, vq, m, mbuf_offset,
+ buf_addr + buf_offset,
buf_iova + buf_offset, cpy_len, true) < 0)
goto error;
} else {
@@ -2562,6 +2603,7 @@ desc_to_mbuf(struct virtio_net *dev, struct vhost_virtqueue *vq,
if (is_async) {
if (async_fill_seg(dev, vq, m, mbuf_offset,
+ buf_addr + buf_offset,
buf_iova + buf_offset, cpy_len, false) < 0)
goto error;
} else {
--
2.25.1
next reply other threads:[~2022-04-11 5:40 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-04-11 13:38 Wenwu Ma [this message]
2022-04-19 9:10 ` Maxime Coquelin
2022-05-23 0:38 ` Hu, Jiayu
2022-05-23 8:49 ` Maxime Coquelin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220411133836.200783-1-wenwux.ma@intel.com \
--to=wenwux.ma@intel.com \
--cc=chenbo.xia@intel.com \
--cc=dev@dpdk.org \
--cc=jiayu.hu@intel.com \
--cc=maxime.coquelin@redhat.com \
--cc=weix.ling@intel.com \
--cc=xingguang.he@intel.com \
--cc=yinan.wang@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).