[PATCH v2 0/4] Even more flow table preliminaries
I hoped that the last batch was the last, but I was wrong. Working on UDP flow has shown up a few more things that make sense to do before taking the leap into full flow table implementation. Here's what I have so far, though there could be even more. Changes since v1: * Assorted minor style and comment changes based on Stefano's review. David Gibson (4): util: Split construction of bind socket address from the rest of sock_l4() udp: Fold checking of splice flag into udp_mmh_splice_port() udp: Rework how we divide queued datagrams between sending methods udp: Move management of udp[46]_localname into udp_splice_send() udp.c | 176 +++++++++++++++++++++++++++++++++------------------------ util.c | 123 +++++++++++++++++++++++----------------- 2 files changed, 171 insertions(+), 128 deletions(-) -- 2.45.2
sock_l4() creates, binds and otherwise prepares a new socket. It builds
the socket address to bind from separately provided address and port.
However, we have use cases coming up where it's more natural to construct
the socket address in the caller.
Prepare for this by adding sock_l4_sa() which takes a pre-constructed
socket address, and rewriting sock_l4() in terms of it.
Signed-off-by: David Gibson
udp_mmh_splice_port() is used to determine if a UDP datagram can be
"spliced" (forwarded via a socket instead of tap). We only invoke it if
the origin socket has the 'splice' flag set.
Fold the checking of the flag into the helper itself, which makes the
caller simpler. It does mean we have a loop looking for a batch of
spliceable or non-spliceable packets even in the case where the flag is
clear. This shouldn't be that expensive though, since each call to
udp_mmh_splice_port() will return without accessing memory in that case.
In any case we're going to need a similar loop in more cases with upcoming
flow table work.
Signed-off-by: David Gibson
udp_sock_handler() takes a number of datagrams from sockets that depending
on their addresses could be forwarded either to the L2 interface ("tap")
or to another socket ("spliced"). In the latter case we can also only
send packets together if they have the same source port, and therefore
are sent via the same socket.
To reduce the total number of system calls we gather contiguous batches of
datagrams with the same destination interface and socket where applicable.
The determination of what the target is is made by udp_mmh_splice_port().
It returns the source port for splice packets and -1 for "tap" packets.
We find batches by looking ahead in our queue until we find a datagram
whose "splicefrom" port doesn't match the first in our current batch.
udp_mmh_splice_port() is moderately expensive, and unfortunately we
can call it twice on the same datagram: once as the (last + 1) entry
in one batch (to check it's not in that batch), then again as the
first entry in the next batch.
Avoid this by keeping track of the "splice port" in the metadata structure,
and filling it in one entry ahead of the one we're currently considering.
This is a bit subtle, but not that hard. It will also generalise better
when we have more complex possibilities based on the flow table.
Signed-off-by: David Gibson
Mostly, udp_sock_handler() is independent of how the datagrams it processes
will be forwarded (tap or splice). However, it also updates the msg_name
fields for spliced sends, which doesn't really make sense here. Move it
into udp_splice_send() which is all about spliced sends. This does
potentially mean we'll update the field to the same value several times,
but we're going to need this in future anyway: with the extensions the
flow table allows, it might not be the same value each time after all.
Signed-off-by: David Gibson
On Fri, 14 Jun 2024 11:51:04 +1000
David Gibson
I hoped that the last batch was the last, but I was wrong. Working on UDP flow has shown up a few more things that make sense to do before taking the leap into full flow table implementation. Here's what I have so far, though there could be even more.
Changes since v1: * Assorted minor style and comment changes based on Stefano's review.
David Gibson (4): util: Split construction of bind socket address from the rest of sock_l4() udp: Fold checking of splice flag into udp_mmh_splice_port() udp: Rework how we divide queued datagrams between sending methods udp: Move management of udp[46]_localname into udp_splice_send()
udp.c | 176 +++++++++++++++++++++++++++++++++------------------------ util.c | 123 +++++++++++++++++++++++----------------- 2 files changed, 171 insertions(+), 128 deletions(-)
Applied. -- Stefano
participants (2)
-
David Gibson
-
Stefano Brivio