[PATCH v2 0/5] Cleanups to tcp socket pool handling
This is a bit of a diversion from what I'm notionally working on at the moment. While thinking about what we'd need to use the IP_TRANSPARENT socket option to broaden the cases where we can "splice", I noticed some inelegancies in how we handle the pool of pre-opened sockets in the TCP code, and well, here we are. This makes a number of cleanups to the handling of these pools. Most notably, tcp_splice_connect() now has simpler semantics: it now always runs in the init namespace, and is always given a pre-opened socket (which could be in the guest ns). Changes since v1: * Rebased * Improved wording of some commit messages David Gibson (5): tcp: Make a helper to refill each socket pool tcp: Split init and ns cases for tcp_sock_refill() tcp: Move socket pool declarations around tcp: Split pool lookup from creating new sockets in tcp_conn_new_sock() tcp: Improve handling of fallback if socket pool is empty on new splice tcp.c | 138 ++++++++++++++++++------------------------------- tcp.h | 2 - tcp_conn.h | 12 ++++- tcp_splice.c | 141 ++++++++++++++++++++++++++------------------------- 4 files changed, 132 insertions(+), 161 deletions(-) -- 2.39.1
tcp_sock_refill() contains two near-identical loops to refill the IPv4
and IPv6 socket pools. In addition, if we get an error on the IPv4
pool we exit early and won't attempt to refill the IPv6 pool. At
least theoretically, these are independent from each other and there's
value to filling up either pool without the other. So, there's no
strong reason to give up on one because the other failed.
Address both of these with a helper function 'tcp_sock_refill_pool()' to
refill a single given pool.
Signed-off-by: David Gibson
With the creation of the tcp_sock_refill_pool() helper, the ns==true and
ns==false paths for tcp_sock_refill() now have almost nothing in common.
Split the two versions into tcp_sock_refill_init() and tcp_sock_refill_ns()
functions.
Signed-off-by: David Gibson
tcp_splice.c has some explicit extern declarations to access the
socket pools. This is pretty dangerous - if we changed the type of
these variables in tcp.c, we'd have tcp.c and tcp_splice.c using the
same memory in different ways with no compiler error. So, move the
extern declarations to tcp_conn.h so they're visible to both tcp.c and
tcp_splice.c, but not the rest of pasta.
In fact the pools for the guest namespace are necessarily only used by
tcp_splice.c - we have no sockets on the guest side if we're not
splicing. So move those declarations and the functions that deal
exclusively with them to tcp_splice.c
Signed-off-by: David Gibson
tcp_conn_new_sock() first looks for a socket in a pre-opened pool, then if
that's empty creates a new socket in the init namespace. Both parts of
this are duplicated in other places: the pool lookup logic is duplicated in
tcp_splice_new(), and the socket opening logic is duplicated in
tcp_sock_refill_pool().
Split the function into separate parts so we can remove both these
duplications.
Signed-off-by: David Gibson
When creating a new spliced connection, we need to get a socket in the
other ns from the originating one. To avoid excessive ns switches we
usually get these from a pool refilled on a timer. However, if the pool
runs out we need a fallback. Currently that's done by passing -1 as the
socket to tcp_splice_connnect() and running it in the target ns.
This means that tcp_splice_connect() itself needs to have different cases
depending on whether it's given an existing socket or not, which is
a separate concern from what it's mostly doing. We change it to require
a suitable open socket to be passed in, and ensuring in the caller that we
have one.
This requires adding the fallback paths to the caller, tcp_splice_new().
We use slightly different approaches for a socket in the init ns versus the
guest ns.
This also means that we no longer need to run tcp_splice_connect() itself
in the guest ns, which allows us to remove a bunch of boilerplate code.
Signed-off-by: David Gibson
On Tue, 14 Feb 2023 10:48:18 +1100
David Gibson
This is a bit of a diversion from what I'm notionally working on at the moment. While thinking about what we'd need to use the IP_TRANSPARENT socket option to broaden the cases where we can "splice", I noticed some inelegancies in how we handle the pool of pre-opened sockets in the TCP code, and well, here we are.
This makes a number of cleanups to the handling of these pools. Most notably, tcp_splice_connect() now has simpler semantics: it now always runs in the init namespace, and is always given a pre-opened socket (which could be in the guest ns).
Changes since v1: * Rebased * Improved wording of some commit messages
David Gibson (5): tcp: Make a helper to refill each socket pool tcp: Split init and ns cases for tcp_sock_refill() tcp: Move socket pool declarations around tcp: Split pool lookup from creating new sockets in tcp_conn_new_sock() tcp: Improve handling of fallback if socket pool is empty on new splice
Applied too. -- Stefano
participants (2)
-
David Gibson
-
Stefano Brivio