[PATCH v2 0/7] Rework UDP buffers
Laurent recently reworked the TCP buffer handling to be split into various pieces tracked by iovecs. We'll want that for various future changes. This series makes a similar split for UDP buffers, which we'll want in order to allow dual-stack UDP sockets, amongst other things. This is based on my earlier series of cleanups for the TCP buffer handling. Changes since v1: * Rebase on v2 of the TCP iov and buffer handling cleanups * Rename udp_payload and udp_meta structures to _t for more consistency with tcp.c * Other minor changes based on Stefano's review David Gibson (7): test: Allow sftp via vsock-ssh in tests udp: Split tap-bound UDP packets into multiple buffers using io vector udp: Combine initialisation of IPv4 and IPv6 iovs udp: Explicitly set checksum in guest-bound UDP headers udp: Share payload buffers between IPv4 and IPv6 udp: Use the same buffer for the L2 header for all frames udp: Single buffer for IPv4, IPv6 headers and metadata tap.h | 38 ------ test/passt.mbuto | 6 +- udp.c | 299 +++++++++++++++++++++++------------------------ 3 files changed, 152 insertions(+), 191 deletions(-) -- 2.44.0
During some debugging recently, I wanted to extact a file from a test
guest and found it was tricky, since the ssh-over-vsock setup we had didn't
allow sftp/scp. We can fix this by adding a line to the guest side sshd
config from mbuto. While we're there correct an inaccurate comment.
Signed-off-by: David Gibson
When sending to the tap device, currently we assemble the headers and
payload into a single contiguous buffer. Those are described by a single
struct iovec, then a batch of frames is sent to the device with
tap_send_frames().
In order to better integrate the IPv4 and IPv6 paths, we want the IP
header in a different buffer that might not be contiguous with the
payload. To prepare for that, split the UDP packet into an iovec of
buffers. We use the same split that Laurent recently introduced for
TCP for convenience.
This removes the last use of tap_hdr_len_(), tap_frame_base() and
tap_frame_len(), so remove those too.
Signed-off-by: David Gibson
We're going to introduce more sharing between the IPv4 and IPv6 buffer
structures. Prepare for this by combinng the initialisation functions.
While we're at it remove the misleading "sock" from the name since these
initialise both tap side and sock side structures.
Signed-off-by: David Gibson
For IPv4, UDP checksums are optional and can just be set to 0.
udp_update_hdr4() ignores the checksum field entirely. Since these are set
to 0 during startup, this works as intended for now.
However, we'd like to share payload and UDP header buffers betweem IPv4 and
IPv6, which does calculate UDP checksums. Therefore, for robustness, we
should explicitly set the checksum field to 0 for guest-bound UDP packets.
In the tap_udp4_send() slow path, however, we do allow IPv4 UDP checksums
to be calculated as a compile time option. For consistency, use the same
thing in the udp_update_hdr4() path, which will typically initialize to 0,
but calculate a real checksum if configured to do so.
Signed-off-by: David Gibson
Currently the IPv4 and IPv6 paths unnecessarily use different buffers for
the UDP payload. Now that we're handling the various pieces of the UDP
packets with an iov, we can split the payload part of the buffers off into
its own array shared between IPv4 and IPv6. As well as saving a little
memory, this allows the payload buffers to be neatly page aligned.
With the buffers merged, udp[46]_l2_iov_sock contain exactly the same thing
as each other and can also be merged. Likewise udp[46]_iov_splice can be
merged together.
Signed-off-by: David Gibson
Currently each tap-bound frame buffer has room for its own ethernet header.
However the ethernet header is always the same for such frames, so now
that we're indirectly referencing the ethernet header via iov, we can use
a single buffer for all of them.
Signed-off-by: David Gibson
Currently we have separate arrays for IPv4 and IPv6 which contain the
headers for guest-bound packets, and also the originating socket address.
We can combine these into a single array of "metadata" structures with
space for both pre-cooked IPv4 and IPv6 headers, as well as shared space
for the tap specific header and socket address (using sockaddr_inany).
Because we're using IOVs to separately address the pieces of each frame,
these structures don't need to be packed to keep the headers contiguous
so we can more naturally arrange for the alignment we want.
Signed-off-by: David Gibson
On Wed, 1 May 2024 18:31:03 +1000
David Gibson
Laurent recently reworked the TCP buffer handling to be split into various pieces tracked by iovecs. We'll want that for various future changes. This series makes a similar split for UDP buffers, which we'll want in order to allow dual-stack UDP sockets, amongst other things.
This is based on my earlier series of cleanups for the TCP buffer handling.
Changes since v1: * Rebase on v2 of the TCP iov and buffer handling cleanups * Rename udp_payload and udp_meta structures to _t for more consistency with tcp.c * Other minor changes based on Stefano's review
David Gibson (7): test: Allow sftp via vsock-ssh in tests udp: Split tap-bound UDP packets into multiple buffers using io vector udp: Combine initialisation of IPv4 and IPv6 iovs udp: Explicitly set checksum in guest-bound UDP headers udp: Share payload buffers between IPv4 and IPv6 udp: Use the same buffer for the L2 header for all frames udp: Single buffer for IPv4, IPv6 headers and metadata
Applied. -- Stefano
participants (2)
-
David Gibson
-
Stefano Brivio