From d95b63b8c177b77f804278b4d8e8f8757e11b0fb Mon Sep 17 00:00:00 2001 From: Libor Peltan <libor.peltan@nic.cz> Date: Mon, 20 Sep 2021 18:50:24 +0200 Subject: [PATCH] xdp-tcp: honor foreign TCP window size --- src/libknot/xdp/msg.h | 2 ++ src/libknot/xdp/protocols.h | 5 +++++ src/libknot/xdp/tcp.c | 4 ++-- src/libknot/xdp/tcp.h | 1 + tests/libknot/test_xdp_tcp.c | 2 ++ 5 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/libknot/xdp/msg.h b/src/libknot/xdp/msg.h index 83652f9866..d972738dc3 100644 --- a/src/libknot/xdp/msg.h +++ b/src/libknot/xdp/msg.h @@ -52,6 +52,8 @@ typedef struct knot_xdp_msg { uint32_t seqno; uint32_t ackno; uint16_t mss; + uint16_t win; + uint8_t win_scale; } knot_xdp_msg_t; /*! @} */ diff --git a/src/libknot/xdp/protocols.h b/src/libknot/xdp/protocols.h index 7b9829e1df..5f4bcb3990 100644 --- a/src/libknot/xdp/protocols.h +++ b/src/libknot/xdp/protocols.h @@ -76,6 +76,7 @@ inline static void *prot_read_tcp(void *data, knot_xdp_msg_t *msg, uint16_t *src msg->seqno = be32toh(tcp->seq); msg->ackno = be32toh(tcp->ack_seq); + msg->win = be16toh(tcp->window); *src_port = tcp->source; *dst_port = tcp->dest; @@ -98,6 +99,10 @@ inline static void *prot_read_tcp(void *data, knot_xdp_msg_t *msg, uint16_t *src msg->mss = be16toh(msg->mss); } + if (opts[0] == PROT_TCP_OPT_WSC && opts[1] == PROT_TCP_OPT_LEN_WSC) { + msg->win_scale = opts[2]; + } + opts += opts[1]; } diff --git a/src/libknot/xdp/tcp.c b/src/libknot/xdp/tcp.c index 94e78c47e6..1bf31106ac 100644 --- a/src/libknot/xdp/tcp.c +++ b/src/libknot/xdp/tcp.c @@ -167,8 +167,6 @@ static int tcp_table_add(knot_xdp_msg_t *msg, uint64_t hash, knot_tcp_table_t *t c->ackno = msg->ackno; c->acked = msg->ackno; - c->window_size = 65536; // FIXME - c->last_active = get_timestamp(); add_tail(tcp_table_timeout(table), tcp_conn_node(c)); @@ -227,6 +225,7 @@ int knot_tcp_recv(knot_tcp_relay_t *relays, knot_xdp_msg_t *msgs, uint32_t count conn->seqno = knot_tcp_next_seqno(msg); memcpy(conn->last_eth_rem, msg->eth_from, sizeof(conn->last_eth_rem)); memcpy(conn->last_eth_loc, msg->eth_to, sizeof(conn->last_eth_loc)); + conn->window_size = (uint32_t)msg->win * (1LU << conn->window_scale); conn->last_active = get_timestamp(); rem_node(tcp_conn_node(conn)); @@ -270,6 +269,7 @@ int knot_tcp_recv(knot_tcp_relay_t *relays, knot_xdp_msg_t *msgs, uint32_t count conn->state = XDP_TCP_ESTABLISHING; conn->seqno++; conn->mss = MAX(msg->mss, 536); // minimal MSS, most importantly not zero! + conn->window_scale = msg->win_scale; if (!synack) { conn->acked = dnssec_random_uint32_t(); conn->ackno = conn->acked; diff --git a/src/libknot/xdp/tcp.h b/src/libknot/xdp/tcp.h index 8836470543..a8d8fc5fc8 100644 --- a/src/libknot/xdp/tcp.h +++ b/src/libknot/xdp/tcp.h @@ -65,6 +65,7 @@ typedef struct knot_tcp_conn { uint8_t last_eth_rem[ETH_ALEN]; uint8_t last_eth_loc[ETH_ALEN]; uint16_t mss; + uint8_t window_scale; uint32_t seqno; uint32_t ackno; uint32_t acked; diff --git a/tests/libknot/test_xdp_tcp.c b/tests/libknot/test_xdp_tcp.c index 4d3f7303e1..09a1525b31 100644 --- a/tests/libknot/test_xdp_tcp.c +++ b/tests/libknot/test_xdp_tcp.c @@ -507,6 +507,7 @@ void test_obufs(void) size_t DATA_LEN = 65535; // with 2-byte len prefix, this is > 64k == window_size uint8_t *data = calloc(DATA_LEN, 1); rl.conn->mss = TEST_MSS; + rl.conn->window_size = 65536; send2_mss = TEST_MSS; int ret = knot_tcp_reply_data(&rl, test_table, data, DATA_LEN), i = 0; @@ -538,6 +539,7 @@ void test_obufs(void) prepare_seqack(&msg, 0, TEST_MSS); ret = knot_tcp_recv(&rl, &msg, 1, test_table, NULL); is_int(KNOT_EOK, ret, "obufs: ACKed data"); + rl.conn->window_size = 65536; struct tcp_outbuf *surv_ob = rl.conn->outbufs.bufs; ok(surv_ob != NULL, "obufs: unACKed survived"); ok(surv_ob->next == NULL, "obufs: just one survived"); -- GitLab