diff options
| author | Laurent Vivier <lvivier@redhat.com> | 2026-02-23 15:10:27 +0100 |
|---|---|---|
| committer | Stefano Brivio <sbrivio@redhat.com> | 2026-02-24 12:06:03 +0100 |
| commit | 8636c73a5f1af1fa066a55e48a020852339dfe6e (patch) | |
| tree | 2b41265e0a88579afb5c3f8c16b5e95ef1ebb048 | |
| parent | de5b69491fdd95bd7d997a4b7c2972bd3ceb1101 (diff) | |
| download | passt-8636c73a5f1af1fa066a55e48a020852339dfe6e.tar passt-8636c73a5f1af1fa066a55e48a020852339dfe6e.tar.gz passt-8636c73a5f1af1fa066a55e48a020852339dfe6e.tar.bz2 passt-8636c73a5f1af1fa066a55e48a020852339dfe6e.tar.lz passt-8636c73a5f1af1fa066a55e48a020852339dfe6e.tar.xz passt-8636c73a5f1af1fa066a55e48a020852339dfe6e.tar.zst passt-8636c73a5f1af1fa066a55e48a020852339dfe6e.zip | |
tcp_vu, udp_vu: Account for virtio net header in minimum frame size
In the vhost-user paths, the buffers provided by the virtio queue
include the virtio net header (VNET_HLEN) prepended to the Ethernet
frame. The minimum size checks using ETH_ZLEN must therefore account
for this additional header length, otherwise we underestimate the
minimum buffer size needed.
Use ETH_ZLEN + VNET_HLEN instead of bare ETH_ZLEN in vu_collect()
calls and the corresponding ASSERT() checks.
In tcp_vu_prepare(), revert the ASSERT to just check for hdrlen,
because at that point iov[0].iov_len has been trimmed to the actual
received data size plus headers.
Fixes: 0cb8f9003654 ("tcp, udp: Pad batched frames for vhost-user modes to 60 bytes (802.3 minimum)")
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
| -rw-r--r-- | tcp_vu.c | 8 | ||||
| -rw-r--r-- | udp_vu.c | 2 |
2 files changed, 5 insertions, 5 deletions
@@ -90,12 +90,12 @@ int tcp_vu_send_flag(const struct ctx *c, struct tcp_tap_conn *conn, int flags) vu_set_element(&flags_elem[0], NULL, &flags_iov[0]); elem_cnt = vu_collect(vdev, vq, &flags_elem[0], 1, - MAX(hdrlen + sizeof(*opts), ETH_ZLEN), NULL); + MAX(hdrlen + sizeof(*opts), ETH_ZLEN + VNET_HLEN), NULL); if (elem_cnt != 1) return -1; ASSERT(flags_elem[0].in_sg[0].iov_len >= - MAX(hdrlen + sizeof(*opts), ETH_ZLEN)); + MAX(hdrlen + sizeof(*opts), ETH_ZLEN + VNET_HLEN)); vu_set_vnethdr(vdev, flags_elem[0].in_sg[0].iov_base, 1); @@ -209,7 +209,7 @@ static ssize_t tcp_vu_sock_recv(const struct ctx *c, struct vu_virtq *vq, cnt = vu_collect(vdev, vq, &elem[elem_cnt], VIRTQUEUE_MAX_SIZE - elem_cnt, - MAX(MIN(mss, fillsize) + hdrlen, ETH_ZLEN), + MAX(MIN(mss, fillsize) + hdrlen, ETH_ZLEN + VNET_HLEN), &frame_size); if (cnt == 0) break; @@ -303,7 +303,7 @@ static void tcp_vu_prepare(const struct ctx *c, struct tcp_tap_conn *conn, /* we guess the first iovec provided by the guest can embed * all the headers needed by L2 frame, including any padding */ - ASSERT(iov[0].iov_len >= MAX(hdrlen, ETH_ZLEN)); + ASSERT(iov[0].iov_len >= hdrlen); eh = vu_eth(base); @@ -97,7 +97,7 @@ static int udp_vu_sock_recv(const struct ctx *c, struct vu_virtq *vq, int s, return -1; /* reserve space for the headers */ - ASSERT(iov_vu[0].iov_len >= MAX(hdrlen, ETH_ZLEN)); + ASSERT(iov_vu[0].iov_len >= MAX(hdrlen, ETH_ZLEN + VNET_HLEN)); iov_vu[0].iov_base = (char *)iov_vu[0].iov_base + hdrlen; iov_vu[0].iov_len -= hdrlen; |
