diff options
author | Stefano Brivio <sbrivio@redhat.com> | 2021-09-26 23:38:22 +0200 |
---|---|---|
committer | Stefano Brivio <sbrivio@redhat.com> | 2021-09-27 01:28:02 +0200 |
commit | dd581730e54b934f80d5b6a820136707dc71c664 (patch) | |
tree | c58b140d407f4b308e1fc1d21703b444ea34cabd /tcp.c | |
parent | dfc451319034f594037822b3193a30fa5715175f (diff) | |
download | passt-dd581730e54b934f80d5b6a820136707dc71c664.tar passt-dd581730e54b934f80d5b6a820136707dc71c664.tar.gz passt-dd581730e54b934f80d5b6a820136707dc71c664.tar.bz2 passt-dd581730e54b934f80d5b6a820136707dc71c664.tar.lz passt-dd581730e54b934f80d5b6a820136707dc71c664.tar.xz passt-dd581730e54b934f80d5b6a820136707dc71c664.tar.zst passt-dd581730e54b934f80d5b6a820136707dc71c664.zip |
tap: Completely de-serialise input message batches
Until now, messages would be passed to protocol handlers in a single
batch only if they happened to be dequeued in a row. Packets
interleaved between different connections would result in multiple
calls to the same protocol handler for a single connection.
Instead, keep track of incoming packet descriptors, arrange them in
sequences, and call protocol handlers only as we completely sorted
input messages in batches.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Diffstat (limited to 'tcp.c')
-rw-r--r-- | tcp.c | 26 |
1 files changed, 11 insertions, 15 deletions
@@ -333,6 +333,7 @@ #include <sys/random.h> #include <sys/socket.h> #include <sys/types.h> +#include <sys/uio.h> #include <unistd.h> #include <linux/ip.h> #include <linux/ipv6.h> @@ -645,7 +646,7 @@ static struct mmsghdr tcp_l2_mh_tap [TCP_TAP_FRAMES] = { }; /* sendmsg() to socket */ -static struct iovec tcp_tap_iov [TAP_MSGS]; +static struct iovec tcp_tap_iov [UIO_MAXIOV]; /* Bitmap, activity monitoring needed for connection via tap */ static uint8_t tcp_act[MAX_TAP_CONNS / 8] = { 0 }; @@ -1968,7 +1969,7 @@ out_restore_iov: * @now: Current timestamp */ static void tcp_data_from_tap(struct ctx *c, struct tcp_tap_conn *conn, - struct tap_msg *msg, int count, + struct tap_l4_msg *msg, int count, struct timespec *now) { int i, iov_i, ack = 0, fin = 0, retr = 0, keep = -1; @@ -1979,10 +1980,13 @@ static void tcp_data_from_tap(struct ctx *c, struct tcp_tap_conn *conn, ssize_t len; for (i = 0, iov_i = 0; i < count; i++) { - struct tcphdr *th = (struct tcphdr *)msg[i].l4h; uint32_t seq, seq_offset, ack_seq; - size_t len = msg[i].l4_len, off; + struct tcphdr *th; char *data; + size_t off; + + th = (struct tcphdr *)(pkt_buf + msg[i].pkt_buf_offset); + len = msg[i].l4_len; if (len < sizeof(*th)) { tcp_rst(c, conn); @@ -2152,19 +2156,11 @@ out: * Return: count of consumed packets */ int tcp_tap_handler(struct ctx *c, int af, void *addr, - struct tap_msg *msg, int count, struct timespec *now) + struct tap_l4_msg *msg, int count, struct timespec *now) { - struct tcphdr *th = (struct tcphdr *)msg[0].l4h; - size_t len = msg[0].l4_len, off; + struct tcphdr *th = (struct tcphdr *)(pkt_buf + msg[0].pkt_buf_offset); + uint16_t len = msg[0].l4_len; struct tcp_tap_conn *conn; - int ws; - - if (len < sizeof(*th)) - return 1; - - off = th->doff * 4; - if (off < sizeof(*th) || off > len) - return 1; conn = tcp_hash_lookup(c, af, addr, htons(th->source), htons(th->dest)); if (!conn) { |