diff options
author | David Gibson <david@gibson.dropbear.id.au> | 2022-11-17 16:58:52 +1100 |
---|---|---|
committer | Stefano Brivio <sbrivio@redhat.com> | 2022-11-25 01:35:22 +0100 |
commit | d909fda1e81979da12ed4ab8b2f2a18fba756a07 (patch) | |
tree | 10598d5ebd35e5a454e860ecd66b838c1f7c563c /tcp_splice.c | |
parent | 356c6e0677072f1a6cfe9b5d0648d89ab6fd5523 (diff) | |
download | passt-d909fda1e81979da12ed4ab8b2f2a18fba756a07.tar passt-d909fda1e81979da12ed4ab8b2f2a18fba756a07.tar.gz passt-d909fda1e81979da12ed4ab8b2f2a18fba756a07.tar.bz2 passt-d909fda1e81979da12ed4ab8b2f2a18fba756a07.tar.lz passt-d909fda1e81979da12ed4ab8b2f2a18fba756a07.tar.xz passt-d909fda1e81979da12ed4ab8b2f2a18fba756a07.tar.zst passt-d909fda1e81979da12ed4ab8b2f2a18fba756a07.zip |
tcp: Use the same sockets to listen for spliced and non-spliced connections
In pasta mode, tcp_sock_init[46]() create separate sockets to listen for
spliced connections (these are bound to localhost) and non-spliced
connections (these are bound to the host address). This introduces a
subtle behavioural difference between pasta and passt: by default, pasta
will listen only on a single host address, whereas passt will listen on
all addresses (0.0.0.0 or ::). This also prevents us using some additional
optimizations that only work with the unspecified (0.0.0.0 or ::) address.
However, it turns out we don't need to do this. We can splice a connection
if and only if it originates from the loopback address. Currently we
ensure this by having the "spliced" listening sockets listening only on
loopback. Instead, defer the decision about whether to splice a connection
until after accept(), by checking if the connection was made from the
loopback address.
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.c | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/tcp_splice.c b/tcp_splice.c index 2fd88ec..356d194 100644 --- a/tcp_splice.c +++ b/tcp_splice.c @@ -502,30 +502,48 @@ static void tcp_splice_dir(struct tcp_splice_conn *conn, int ref_sock, } /** - * tcp_splice_conn_from_sock() - Initialize state for spliced connection + * tcp_splice_conn_from_sock() - Attempt to init state for a spliced connection * @c: Execution context * @ref: epoll reference of listening socket * @conn: connection structure to initialize * @s: Accepted socket + * @sa: Peer address of connection * + * Return: true if able to create a spliced connection, false otherwise * #syscalls:pasta setsockopt */ -void tcp_splice_conn_from_sock(struct ctx *c, union epoll_ref ref, - struct tcp_splice_conn *conn, int s) +bool tcp_splice_conn_from_sock(struct ctx *c, union epoll_ref ref, + struct tcp_splice_conn *conn, int s, + const struct sockaddr *sa) { assert(c->mode == MODE_PASTA); + if (ref.r.p.tcp.tcp.v6) { + const struct sockaddr_in6 *sa6; + + sa6 = (const struct sockaddr_in6 *)sa; + if (!IN6_IS_ADDR_LOOPBACK(&sa6->sin6_addr)) + return false; + conn->flags = SPLICE_V6; + } else { + const struct sockaddr_in *sa4 = (const struct sockaddr_in *)sa; + if (!IN4_IS_ADDR_LOOPBACK(&sa4->sin_addr)) + return false; + conn->flags = 0; + } + if (setsockopt(s, SOL_TCP, TCP_QUICKACK, &((int){ 1 }), sizeof(int))) trace("TCP (spliced): failed to set TCP_QUICKACK on %i", s); conn->c.spliced = true; c->tcp.splice_conn_count++; conn->a = s; - conn->flags = ref.r.p.tcp.tcp.v6 ? SPLICE_V6 : 0; if (tcp_splice_new(c, conn, ref.r.p.tcp.tcp.index, ref.r.p.tcp.tcp.outbound)) conn_flag(c, conn, CLOSING); + + return true; } /** |