On Wed, Jul 09, 2025 at 07:47:45PM +0200, Eugenio Pérez wrote:
As pasta cannot modify the TCP sent buffers until vhost-kernel does not use them anymore, we need a way to report the caller the buffers that can be overriden.
Let's start by following the same pattern as in tap write(2): wait until pasta can override the buffers. We can add async cleaning on top.
Signed-off-by: Eugenio Pérez
--- tap.c | 26 ++++++++++++++++++++++++++ tap.h | 1 + 2 files changed, 27 insertions(+) diff --git a/tap.c b/tap.c index 7ccac86..55357e3 100644 --- a/tap.c +++ b/tap.c @@ -128,6 +128,11 @@ static struct { /* Number of free descriptors */ uint16_t num_free;
+ /* Last used_idx in the used ring. + * Duplicate here allows to check for proper vhost usage, and avoid + * false sharing between pasta and kernel. */ + uint16_t shadow_used_idx; + /* Last used idx processed */ uint16_t last_used_idx;
@@ -467,6 +472,27 @@ static void vhost_kick(struct vring_used *used, int kick_fd) { eventfd_write(kick_fd, 1); }
+/* n = target */ +void tap_free_old_xmit(size_t n)
This function is introduced without either a caller or a descriptive comment. That makes it pretty hard to review - I'm not sure what it is supposed to be doing.
+{ + size_t r = 0; + + while (r < n) { + uint16_t used_idx = vqs[1].last_used_idx; + if (vqs[1].shadow_used_idx == used_idx) { + vqs[1].shadow_used_idx = le16toh(*(volatile uint16_t*)&vring_used_1.used.idx); + + if (vqs[1].shadow_used_idx == used_idx) + continue; + } + + /* assert in-order */ + assert(vring_used_1.used.ring[used_idx % VHOST_NDESCS].id == vring_avail_1.avail.ring[used_idx % VHOST_NDESCS]); + vqs[1].num_free += vqs[1].ndescs[used_idx % VHOST_NDESCS]; + vqs[1].last_used_idx++; + r++; + } +}
/** * tap_send_frames_vhost() - Send multiple frames to the pasta tap diff --git a/tap.h b/tap.h index e924dfb..7ca0fb0 100644 --- a/tap.h +++ b/tap.h @@ -112,6 +112,7 @@ void tap_icmp6_send(const struct ctx *c, const struct in6_addr *src, const struct in6_addr *dst, const void *in, size_t l4len); void tap_send_single(const struct ctx *c, const void *data, size_t l2len, bool vhost); +void tap_free_old_xmit(size_t n); size_t tap_send_frames(const struct ctx *c, const struct iovec *iov, size_t bufs_per_frame, size_t nframes, bool vhost); void eth_update_mac(struct ethhdr *eh,
-- David Gibson (he or they) | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you, not the other way | around. http://www.ozlabs.org/~dgibson