passt: Relicense to GPL 2.0, or any later version
In practical terms, passt doesn't benefit from the additional
protection offered by the AGPL over the GPL, because it's not
suitable to be executed over a computer network.
Further, restricting the distribution under the version 3 of the GPL
wouldn't provide any practical advantage either, as long as the passt
codebase is concerned, and might cause unnecessary compatibility
dilemmas.
Change licensing terms to the GNU General Public License Version 2,
or any later version, with written permission from all current and
past contributors, namely: myself, David Gibson, Laine Stump, Andrea
Bolognani, Paul Holzinger, Richard W.M. Jones, Chris Kuhn, Florian
Weimer, Giuseppe Scrivano, Stefan Hajnoczi, and Vasiliy Ulyanov.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
2023-04-05 20:11:44 +02:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-or-later
|
2022-11-17 06:58:43 +01:00
|
|
|
* Copyright Red Hat
|
|
|
|
* Author: Stefano Brivio <sbrivio@redhat.com>
|
|
|
|
* Author: David Gibson <david@gibson.dropbear.id.au>
|
|
|
|
*
|
|
|
|
* TCP connection tracking data structures, used by tcp.c and
|
|
|
|
* tcp_splice.c. Shouldn't be included in non-TCP code.
|
|
|
|
*/
|
|
|
|
#ifndef TCP_CONN_H
|
|
|
|
#define TCP_CONN_H
|
|
|
|
|
2022-11-17 06:58:44 +01:00
|
|
|
/**
|
|
|
|
* struct tcp_conn_common - Common fields for spliced and non-spliced
|
|
|
|
* @spliced: Is this a spliced connection?
|
|
|
|
*/
|
|
|
|
struct tcp_conn_common {
|
|
|
|
bool spliced :1;
|
|
|
|
};
|
|
|
|
|
|
|
|
extern const char *tcp_common_flag_str[];
|
|
|
|
|
2022-11-17 06:58:43 +01:00
|
|
|
/**
|
|
|
|
* struct tcp_tap_conn - Descriptor for a TCP connection (not spliced)
|
2022-11-17 06:58:44 +01:00
|
|
|
* @c: Fields common with tcp_splice_conn
|
2023-08-22 07:29:58 +02:00
|
|
|
* @in_epoll: Is the connection in the epoll set?
|
2022-11-17 06:58:43 +01:00
|
|
|
* @next_index: Connection index of next item in hash chain, -1 for none
|
|
|
|
* @tap_mss: MSS advertised by tap/guest, rounded to 2 ^ TCP_MSS_BITS
|
|
|
|
* @sock: Socket descriptor number
|
|
|
|
* @events: Connection events, implying connection states
|
|
|
|
* @timer: timerfd descriptor for timeout events
|
|
|
|
* @flags: Connection flags representing internal attributes
|
|
|
|
* @retrans: Number of retransmissions occurred due to ACK_TIMEOUT
|
|
|
|
* @ws_from_tap: Window scaling factor advertised from tap/guest
|
|
|
|
* @ws_to_tap: Window scaling factor advertised to tap/guest
|
|
|
|
* @sndbuf: Sending buffer in kernel, rounded to 2 ^ SNDBUF_BITS
|
|
|
|
* @seq_dup_ack_approx: Last duplicate ACK number sent to tap
|
2023-08-22 07:29:54 +02:00
|
|
|
* @faddr: Guest side forwarding address (guest's remote address)
|
|
|
|
* @eport: Guest side endpoint port (guest's local port)
|
|
|
|
* @fport: Guest side forwarding port (guest's remote port)
|
2022-11-17 06:58:43 +01:00
|
|
|
* @wnd_from_tap: Last window size from tap, unscaled (as received)
|
|
|
|
* @wnd_to_tap: Sending window advertised to tap, unscaled (as sent)
|
|
|
|
* @seq_to_tap: Next sequence for packets to tap
|
|
|
|
* @seq_ack_from_tap: Last ACK number received from tap
|
|
|
|
* @seq_from_tap: Next sequence for packets from tap (not actually sent)
|
|
|
|
* @seq_ack_to_tap: Last ACK number sent to tap
|
|
|
|
* @seq_init_from_tap: Initial sequence number from tap
|
|
|
|
*/
|
|
|
|
struct tcp_tap_conn {
|
2022-11-17 06:58:44 +01:00
|
|
|
/* Must be first element to match tcp_splice_conn */
|
|
|
|
struct tcp_conn_common c;
|
|
|
|
|
2023-08-22 07:29:58 +02:00
|
|
|
bool in_epoll :1;
|
2022-11-17 06:58:43 +01:00
|
|
|
int next_index :TCP_CONN_INDEX_BITS + 2;
|
|
|
|
|
|
|
|
#define TCP_RETRANS_BITS 3
|
|
|
|
unsigned int retrans :TCP_RETRANS_BITS;
|
2023-02-27 03:30:01 +01:00
|
|
|
#define TCP_MAX_RETRANS MAX_FROM_BITS(TCP_RETRANS_BITS)
|
2022-11-17 06:58:43 +01:00
|
|
|
|
|
|
|
#define TCP_WS_BITS 4 /* RFC 7323 */
|
|
|
|
#define TCP_WS_MAX 14
|
|
|
|
unsigned int ws_from_tap :TCP_WS_BITS;
|
|
|
|
unsigned int ws_to_tap :TCP_WS_BITS;
|
|
|
|
|
|
|
|
|
2023-08-11 07:12:21 +02:00
|
|
|
int sock :FD_REF_BITS;
|
2022-11-17 06:58:43 +01:00
|
|
|
|
|
|
|
uint8_t events;
|
|
|
|
#define CLOSED 0
|
|
|
|
#define SOCK_ACCEPTED BIT(0) /* implies SYN sent to tap */
|
|
|
|
#define TAP_SYN_RCVD BIT(1) /* implies socket connecting */
|
|
|
|
#define TAP_SYN_ACK_SENT BIT( 3) /* implies socket connected */
|
|
|
|
#define ESTABLISHED BIT(2)
|
|
|
|
#define SOCK_FIN_RCVD BIT( 3)
|
|
|
|
#define SOCK_FIN_SENT BIT( 4)
|
|
|
|
#define TAP_FIN_RCVD BIT( 5)
|
|
|
|
#define TAP_FIN_SENT BIT( 6)
|
|
|
|
#define TAP_FIN_ACKED BIT( 7)
|
|
|
|
|
|
|
|
#define CONN_STATE_BITS /* Setting these clears other flags */ \
|
|
|
|
(SOCK_ACCEPTED | TAP_SYN_RCVD | ESTABLISHED)
|
|
|
|
|
|
|
|
|
2023-08-11 07:12:21 +02:00
|
|
|
int timer :FD_REF_BITS;
|
2022-11-17 06:58:43 +01:00
|
|
|
|
|
|
|
uint8_t flags;
|
|
|
|
#define STALLED BIT(0)
|
|
|
|
#define LOCAL BIT(1)
|
tcp: Don't use TCP_WINDOW_CLAMP
On the L2 tap side, we see TCP headers and know the TCP window that the
ultimate receiver is advertising. In order to avoid unnecessary buffering
within passt/pasta (or by the kernel on passt/pasta's behalf) we attempt
to advertise that window back to the original sock-side sender using
TCP_WINDOW_CLAMP.
However, TCP_WINDOW_CLAMP just doesn't work like this. Prior to kernel
commit 3aa7857fe1d7 ("tcp: enable mid stream window clamp"), it simply
had no effect on established sockets. After that commit, it does affect
established sockets but doesn't behave the way we need:
* It appears to be designed only to shrink the window, not to allow it to
re-expand.
* More importantly, that commit has a serious bug where if the
setsockopt() is made when the existing kernel advertised window for the
socket happens to be zero, it will now become locked at zero, stopping
any further data from being received on the socket.
Since this has never worked as intended, simply remove it. It might be
possible to re-implement the intended behaviour by manipulating SO_RCVBUF,
so we leave a comment to that effect.
This kernel bug is the underlying cause of both the linked passt bug and
the linked podman bug. We attempted to fix this before with passt commit
d3192f67 ("tcp: Force TCP_WINDOW_CLAMP before resetting STALLED flag").
However while that commit masked the bug for some cases, it didn't really
address the problem.
Fixes: d3192f67c492 ("tcp: Force TCP_WINDOW_CLAMP before resetting STALLED flag")
Link: https://github.com/containers/podman/issues/20170
Link: https://bugs.passt.top/show_bug.cgi?id=74
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
2023-11-09 10:54:00 +01:00
|
|
|
#define ACTIVE_CLOSE BIT(2)
|
|
|
|
#define ACK_TO_TAP_DUE BIT(3)
|
|
|
|
#define ACK_FROM_TAP_DUE BIT(4)
|
2022-11-17 06:58:43 +01:00
|
|
|
|
|
|
|
|
|
|
|
#define TCP_MSS_BITS 14
|
|
|
|
unsigned int tap_mss :TCP_MSS_BITS;
|
|
|
|
#define MSS_SET(conn, mss) (conn->tap_mss = (mss >> (16 - TCP_MSS_BITS)))
|
|
|
|
#define MSS_GET(conn) (conn->tap_mss << (16 - TCP_MSS_BITS))
|
|
|
|
|
|
|
|
|
|
|
|
#define SNDBUF_BITS 24
|
|
|
|
unsigned int sndbuf :SNDBUF_BITS;
|
|
|
|
#define SNDBUF_SET(conn, bytes) (conn->sndbuf = ((bytes) >> (32 - SNDBUF_BITS)))
|
|
|
|
#define SNDBUF_GET(conn) (conn->sndbuf << (32 - SNDBUF_BITS))
|
|
|
|
|
|
|
|
uint8_t seq_dup_ack_approx;
|
|
|
|
|
|
|
|
|
2023-08-22 07:29:54 +02:00
|
|
|
union inany_addr faddr;
|
|
|
|
in_port_t eport;
|
|
|
|
in_port_t fport;
|
2022-11-17 06:58:43 +01:00
|
|
|
|
|
|
|
uint16_t wnd_from_tap;
|
|
|
|
uint16_t wnd_to_tap;
|
|
|
|
|
|
|
|
uint32_t seq_to_tap;
|
|
|
|
uint32_t seq_ack_from_tap;
|
|
|
|
uint32_t seq_from_tap;
|
|
|
|
uint32_t seq_ack_to_tap;
|
|
|
|
uint32_t seq_init_from_tap;
|
|
|
|
};
|
|
|
|
|
2023-11-07 03:42:46 +01:00
|
|
|
#define SIDES 2
|
2022-11-17 06:58:43 +01:00
|
|
|
/**
|
|
|
|
* struct tcp_splice_conn - Descriptor for a spliced TCP connection
|
2022-11-17 06:58:44 +01:00
|
|
|
* @c: Fields common with tcp_tap_conn
|
2023-08-22 07:29:58 +02:00
|
|
|
* @in_epoll: Is the connection in the epoll set?
|
2023-11-07 03:42:46 +01:00
|
|
|
* @s: File descriptor for sockets
|
|
|
|
* @pipe: File descriptors for pipes
|
2022-11-17 06:58:43 +01:00
|
|
|
* @events: Events observed/actions performed on connection
|
|
|
|
* @flags: Connection flags (attributes, not events)
|
2023-11-07 03:42:46 +01:00
|
|
|
* @read: Bytes read (not fully written to other side in one shot)
|
|
|
|
* @written: Bytes written (not fully written from one other side read)
|
2022-11-17 06:58:43 +01:00
|
|
|
*/
|
|
|
|
struct tcp_splice_conn {
|
2022-11-17 06:58:44 +01:00
|
|
|
/* Must be first element to match tcp_tap_conn */
|
|
|
|
struct tcp_conn_common c;
|
|
|
|
|
2023-08-22 07:29:58 +02:00
|
|
|
bool in_epoll :1;
|
2023-11-07 03:42:46 +01:00
|
|
|
int s[SIDES];
|
|
|
|
int pipe[SIDES][2];
|
2022-11-17 06:58:43 +01:00
|
|
|
|
|
|
|
uint8_t events;
|
|
|
|
#define SPLICE_CLOSED 0
|
|
|
|
#define SPLICE_CONNECT BIT(0)
|
|
|
|
#define SPLICE_ESTABLISHED BIT(1)
|
2023-11-07 03:42:46 +01:00
|
|
|
#define OUT_WAIT_0 BIT(2)
|
|
|
|
#define OUT_WAIT_1 BIT(3)
|
|
|
|
#define FIN_RCVD_0 BIT(4)
|
|
|
|
#define FIN_RCVD_1 BIT(5)
|
|
|
|
#define FIN_SENT_0 BIT(6)
|
|
|
|
#define FIN_SENT_1 BIT(7)
|
2022-11-17 06:58:43 +01:00
|
|
|
|
|
|
|
uint8_t flags;
|
|
|
|
#define SPLICE_V6 BIT(0)
|
2023-11-07 03:42:46 +01:00
|
|
|
#define RCVLOWAT_SET_0 BIT(1)
|
|
|
|
#define RCVLOWAT_SET_1 BIT(2)
|
|
|
|
#define RCVLOWAT_ACT_0 BIT(3)
|
|
|
|
#define RCVLOWAT_ACT_1 BIT(4)
|
2022-11-17 06:58:49 +01:00
|
|
|
#define CLOSING BIT(5)
|
2022-11-17 06:58:43 +01:00
|
|
|
|
2023-11-07 03:42:46 +01:00
|
|
|
uint32_t read[SIDES];
|
|
|
|
uint32_t written[SIDES];
|
2022-11-17 06:58:43 +01:00
|
|
|
};
|
|
|
|
|
2022-11-17 06:58:44 +01:00
|
|
|
/**
|
|
|
|
* union tcp_conn - Descriptor for a TCP connection (spliced or non-spliced)
|
|
|
|
* @c: Fields common between all variants
|
|
|
|
* @tap: Fields specific to non-spliced connections
|
|
|
|
* @splice: Fields specific to spliced connections
|
|
|
|
*/
|
|
|
|
union tcp_conn {
|
|
|
|
struct tcp_conn_common c;
|
|
|
|
struct tcp_tap_conn tap;
|
|
|
|
struct tcp_splice_conn splice;
|
|
|
|
};
|
|
|
|
|
2022-11-17 06:58:46 +01:00
|
|
|
/* TCP connections */
|
|
|
|
extern union tcp_conn tc[];
|
|
|
|
|
2023-02-14 00:48:21 +01:00
|
|
|
/* Socket pools */
|
|
|
|
#define TCP_SOCK_POOL_SIZE 32
|
|
|
|
|
|
|
|
extern int init_sock_pool4 [TCP_SOCK_POOL_SIZE];
|
|
|
|
extern int init_sock_pool6 [TCP_SOCK_POOL_SIZE];
|
|
|
|
|
2023-09-29 07:50:19 +02:00
|
|
|
void tcp_splice_conn_update(const struct ctx *c, struct tcp_splice_conn *new);
|
2022-11-17 06:58:46 +01:00
|
|
|
void tcp_table_compact(struct ctx *c, union tcp_conn *hole);
|
2022-11-19 09:29:54 +01:00
|
|
|
void tcp_splice_destroy(struct ctx *c, union tcp_conn *conn_union);
|
|
|
|
void tcp_splice_timer(struct ctx *c, union tcp_conn *conn_union);
|
2023-02-14 00:48:22 +01:00
|
|
|
int tcp_conn_pool_sock(int pool[]);
|
2023-02-14 00:48:23 +01:00
|
|
|
int tcp_conn_new_sock(const struct ctx *c, sa_family_t af);
|
2023-02-14 00:48:21 +01:00
|
|
|
void tcp_sock_refill_pool(const struct ctx *c, int pool[], int af);
|
|
|
|
void tcp_splice_refill(const struct ctx *c);
|
2022-11-17 06:58:46 +01:00
|
|
|
|
2022-11-17 06:58:43 +01:00
|
|
|
#endif /* TCP_CONN_H */
|