On Fri, Dec 05, 2025 at 01:51:53AM +0100, Stefano Brivio wrote: > IEEE 802.3 requires a minimum frame payload of 46 bytes, without a > 802.1Q tag. Add padding for the simple tap_send_single() case using > a zero-filled 60-byte buffer and copying data to it if needed. > > In theory, we could add a further element in the iovec array, say: > > uint8_t padding[ETH_ZLEN] = { 0 }; > struct iovec iov[3]; > > ... > > if (l2len < ETH_ZLEN) { > iov[iovcnt].iov_base = (void *)padding; > iov[iovcnt].iov_len = ETH_ZLEN - l2len; > iovcnt++; > } > > and avoid a copy, but that would substantially complicate the > vhost-user path, and it's questionable whether passing a reference > to a further buffer actually causes lower overhead than the simple > copy. > > Link: https://bugs.passt.top/show_bug.cgi?id=166 > Signed-off-by: Stefano Brivio > Reviewed-by: Laurent Vivier Reviewed-by: David Gibson > --- > tap.c | 11 ++++++++++- > 1 file changed, 10 insertions(+), 1 deletion(-) > > diff --git a/tap.c b/tap.c > index 44b0644..e3ea61c 100644 > --- a/tap.c > +++ b/tap.c > @@ -130,9 +130,18 @@ unsigned long tap_l2_max_len(const struct ctx *c) > */ > void tap_send_single(const struct ctx *c, const void *data, size_t l2len) > { > - uint32_t vnet_len = htonl(l2len); > + uint8_t padded[ETH_ZLEN] = { 0 }; > struct iovec iov[2]; > size_t iovcnt = 0; > + uint32_t vnet_len; > + > + if (l2len < ETH_ZLEN) { > + memcpy(padded, data, l2len); > + data = padded; > + l2len = ETH_ZLEN; > + } > + > + vnet_len = htonl(l2len); > > switch (c->mode) { > case MODE_PASST: > -- > 2.43.0 > -- 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