aboutgitcodebugslistschat
path: root/tcp_splice.c
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2024-02-28 22:25:15 +1100
committerStefano Brivio <sbrivio@redhat.com>2024-02-29 09:48:13 +0100
commitee677e0a42c434787bf02cb715d76612a6550c21 (patch)
treef2203a5ac7771768e9c30d622036f58299e7b99d /tcp_splice.c
parent4c2d923b121329b5366d0053d6b2336ae71bed60 (diff)
downloadpasst-ee677e0a42c434787bf02cb715d76612a6550c21.tar
passt-ee677e0a42c434787bf02cb715d76612a6550c21.tar.gz
passt-ee677e0a42c434787bf02cb715d76612a6550c21.tar.bz2
passt-ee677e0a42c434787bf02cb715d76612a6550c21.tar.lz
passt-ee677e0a42c434787bf02cb715d76612a6550c21.tar.xz
passt-ee677e0a42c434787bf02cb715d76612a6550c21.tar.zst
passt-ee677e0a42c434787bf02cb715d76612a6550c21.zip
tcp_splice: Improve logic deciding when to splice
This makes several tweaks to improve the logic which decides whether we're able to use the splice method for a new connection. * Rather than only calling tcp_splice_conn_from_sock() in pasta mode, we check for pasta mode within it, better localising the checks. * Previously if we got a connection from a non-loopback address we'd always fall back to the "tap" path, even if the connection was on a socket in the namespace. If we did get a non-loopback address on a namespace socket, something has gone wrong and the "tap" path certainly won't be able to handle it. Report the error and close, rather than passing it along to tap. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Diffstat (limited to 'tcp_splice.c')
-rw-r--r--tcp_splice.c48
1 files changed, 34 insertions, 14 deletions
diff --git a/tcp_splice.c b/tcp_splice.c
index a202715..45b9b29 100644
--- a/tcp_splice.c
+++ b/tcp_splice.c
@@ -431,14 +431,44 @@ bool tcp_splice_conn_from_sock(const struct ctx *c,
sa_family_t af;
uint8_t pif1;
- ASSERT(c->mode == MODE_PASTA);
-
- inany_from_sockaddr(&src, &srcport, sa);
- if (!inany_is_loopback(&src))
+ if (c->mode != MODE_PASTA)
return false;
+ inany_from_sockaddr(&src, &srcport, sa);
af = inany_v4(&src) ? AF_INET : AF_INET6;
+ switch (ref.pif) {
+ case PIF_SPLICE:
+ if (!inany_is_loopback(&src)) {
+ char str[INANY_ADDRSTRLEN];
+
+ /* We can't use flow_err() etc. because we haven't set
+ * the flow type yet
+ */
+ warn("Bad source address %s for splice, closing",
+ inany_ntop(&src, str, sizeof(str)));
+
+ /* We *don't* want to fall back to tap */
+ flow_alloc_cancel(flow);
+ return true;
+ }
+
+ pif1 = PIF_HOST;
+ dstport += c->tcp.fwd_out.delta[dstport];
+ break;
+
+ case PIF_HOST:
+ if (!inany_is_loopback(&src))
+ return false;
+
+ pif1 = PIF_SPLICE;
+ dstport += c->tcp.fwd_in.delta[dstport];
+ break;
+
+ default:
+ return false;
+ }
+
conn = FLOW_START(flow, FLOW_TCP_SPLICE, tcp_splice, 0);
conn->flags = af == AF_INET ? 0 : SPLICE_V6;
@@ -450,16 +480,6 @@ bool tcp_splice_conn_from_sock(const struct ctx *c,
if (setsockopt(s0, SOL_TCP, TCP_QUICKACK, &((int){ 1 }), sizeof(int)))
flow_trace(conn, "failed to set TCP_QUICKACK on %i", s0);
- if (ref.pif == PIF_SPLICE) {
- pif1 = PIF_HOST;
- dstport += c->tcp.fwd_out.delta[dstport];
- } else {
- ASSERT(ref.pif == PIF_HOST);
-
- pif1 = PIF_SPLICE;
- dstport += c->tcp.fwd_in.delta[dstport];
- }
-
if (tcp_splice_connect(c, conn, af, pif1, dstport))
conn_flag(c, conn, CLOSING);