From a023cc05ce3f3f4ec6e8ef8b6deef724f896dc1d Mon Sep 17 00:00:00 2001 From: Libor Peltan <libor.peltan@nic.cz> Date: Fri, 8 Oct 2021 11:52:46 +0200 Subject: [PATCH] xdp-tcp: allow configuring separate SYN table --- doc/reference.rst | 11 +++++++++++ src/knot/conf/base.c | 3 +++ src/knot/conf/base.h | 1 + src/knot/conf/schema.c | 1 + src/knot/conf/schema.h | 1 + src/knot/server/xdp-handler.c | 27 ++++++++++++++++++++++++++- tests/knot/test_confio.c | 1 + 7 files changed, 44 insertions(+), 1 deletion(-) diff --git a/doc/reference.rst b/doc/reference.rst index c38a44b846..eb7f620db9 100644 --- a/doc/reference.rst +++ b/doc/reference.rst @@ -521,6 +521,7 @@ Various options related to XDP listening, especially TCP. listen: STR[@INT] | ADDR[@INT] ... tcp: BOOL tcp-max-clients: INT + tcp-max-syn-clients: INT tcp-inbuf-max-size: SIZE tcp-idle-close-timeout: TIME tcp-idle-reset-timeout: TIME @@ -599,6 +600,16 @@ A maximum number of TCP clients connected in parallel. *Default:* 1000000 (one million) +.. _xdp_tcp-max-syn-clients: + +tcp-max-syn-clients +------------------- + +If set to non-zero, clients in SYN state are handled separately and +this is the limit of their number in parallel. + +*Default:* 0 + .. _xdp_tcp-inbuf-max-size: tcp-inbuf-max-size diff --git a/src/knot/conf/base.c b/src/knot/conf/base.c index ed43bfb3d5..8a7cfee9f6 100644 --- a/src/knot/conf/base.c +++ b/src/knot/conf/base.c @@ -192,6 +192,9 @@ static void init_cache( val = conf_get(conf, C_XDP, C_TCP_MAX_CLIENTS); conf->cache.xdp_tcp_max_clients = conf_int(&val); + val = conf_get(conf, C_XDP, C_TCP_SYN_CLIENTS); + conf->cache.xdp_tcp_syn_clients = conf_int(&val); + val = conf_get(conf, C_XDP, C_TCP_INBUF_MAX_SIZE); conf->cache.xdp_tcp_inbuf_max_size = conf_int(&val); diff --git a/src/knot/conf/base.h b/src/knot/conf/base.h index 76bc613606..2d1967f971 100644 --- a/src/knot/conf/base.h +++ b/src/knot/conf/base.h @@ -133,6 +133,7 @@ typedef struct { size_t srv_bg_threads; size_t srv_tcp_max_clients; size_t xdp_tcp_max_clients; + size_t xdp_tcp_syn_clients; size_t xdp_tcp_inbuf_max_size; uint32_t xdp_tcp_idle_close; uint32_t xdp_tcp_idle_reset; diff --git a/src/knot/conf/schema.c b/src/knot/conf/schema.c index c27261d420..e1c490ab7e 100644 --- a/src/knot/conf/schema.c +++ b/src/knot/conf/schema.c @@ -243,6 +243,7 @@ static const yp_item_t desc_xdp[] = { { C_LISTEN, YP_TADDR, YP_VADDR = { 53 }, YP_FMULTI, { check_xdp_listen } }, { C_TCP, YP_TBOOL, YP_VNONE }, { C_TCP_MAX_CLIENTS, YP_TINT, YP_VINT = { 0, INT32_MAX, 1000000 } }, + { C_TCP_SYN_CLIENTS, YP_TINT, YP_VINT = { 0, INT32_MAX, 0 } }, { C_TCP_INBUF_MAX_SIZE, YP_TINT, YP_VINT = { MEGA(1), SSIZE_MAX, MEGA(100), YP_SSIZE } }, { C_TCP_IDLE_CLOSE, YP_TINT, YP_VINT = { 1, INT32_MAX, 10, YP_STIME } }, { C_TCP_IDLE_RESET, YP_TINT, YP_VINT = { 1, INT32_MAX, 20, YP_STIME } }, diff --git a/src/knot/conf/schema.h b/src/knot/conf/schema.h index bee119a7ee..ded593b293 100644 --- a/src/knot/conf/schema.h +++ b/src/knot/conf/schema.h @@ -130,6 +130,7 @@ #define C_TCP_INBUF_MAX_SIZE "\x12""tcp-inbuf-max-size" #define C_TCP_IO_TIMEOUT "\x0E""tcp-io-timeout" #define C_TCP_MAX_CLIENTS "\x0F""tcp-max-clients" +#define C_TCP_SYN_CLIENTS "\x13""tcp-max-syn-clients" #define C_TCP_RESEND "\x12""tcp-resend-timeout" #define C_TCP_REUSEPORT "\x0D""tcp-reuseport" #define C_TCP_RMT_IO_TIMEOUT "\x15""tcp-remote-io-timeout" diff --git a/src/knot/server/xdp-handler.c b/src/knot/server/xdp-handler.c index 9839963c2b..f6f3e51f1a 100644 --- a/src/knot/server/xdp-handler.c +++ b/src/knot/server/xdp-handler.c @@ -36,9 +36,11 @@ typedef struct xdp_handle_ctx { uint32_t msg_recv_count; uint32_t msg_udp_count; knot_tcp_table_t *tcp_table; + knot_tcp_table_t *syn_table; bool tcp; size_t tcp_max_conns; + size_t tcp_syn_conns; size_t tcp_max_inbufs; size_t tcp_max_obufs; uint32_t tcp_idle_close; // In microseconds. @@ -67,6 +69,7 @@ void xdp_handle_reconfigure(xdp_handle_ctx_t *ctx) conf_t *pconf = conf(); ctx->tcp = pconf->cache.xdp_tcp; ctx->tcp_max_conns = pconf->cache.xdp_tcp_max_clients / pconf->cache.srv_xdp_threads; + ctx->tcp_syn_conns = pconf->cache.xdp_tcp_syn_clients / pconf->cache.srv_xdp_threads; ctx->tcp_max_inbufs = pconf->cache.xdp_tcp_inbuf_max_size / pconf->cache.srv_xdp_threads; ctx->tcp_max_obufs = pconf->cache.xdp_tcp_inbuf_max_size / pconf->cache.srv_xdp_threads; // FIXME another setting for outbuf!! ctx->tcp_idle_close = pconf->cache.xdp_tcp_idle_close * 1000000; @@ -78,6 +81,7 @@ void xdp_handle_reconfigure(xdp_handle_ctx_t *ctx) void xdp_handle_free(xdp_handle_ctx_t *ctx) { knot_tcp_table_free(ctx->tcp_table); + knot_tcp_table_free(ctx->syn_table); free(ctx); } @@ -98,6 +102,13 @@ xdp_handle_ctx_t *xdp_handle_init(knot_xdp_socket_t *xdp_sock) xdp_handle_free(ctx); return NULL; } + if (ctx->tcp_syn_conns > 0) { + ctx->syn_table = knot_tcp_table_new(ctx->tcp_syn_conns, ctx->tcp_table); + if (ctx->syn_table == NULL) { + xdp_handle_free(ctx); + return NULL; + } + } } return ctx; @@ -185,7 +196,7 @@ static void handle_udp(xdp_handle_ctx_t *ctx, knot_layer_t *layer, static void handle_tcp(xdp_handle_ctx_t *ctx, knot_layer_t *layer, knotd_qdata_params_t *params) { - int ret = knot_tcp_recv(ctx->relays, ctx->msg_recv, ctx->msg_recv_count, ctx->tcp_table, NULL); + int ret = knot_tcp_recv(ctx->relays, ctx->msg_recv, ctx->msg_recv_count, ctx->tcp_table, ctx->syn_table); if (ret != KNOT_EOK) { log_notice("TCP, failed to process some packets (%s)", knot_strerror(ret)); return; @@ -278,6 +289,20 @@ void xdp_handle_sweep(xdp_handle_ctx_t *ctx) ret = knot_tcp_send(ctx->sock, sweep_relays, XDP_BATCHLEN, XDP_BATCHLEN); } knot_tcp_cleanup(ctx->tcp_table, sweep_relays, XDP_BATCHLEN); + if (ret != KNOT_EOK) { + break; + } + + if (ctx->syn_table == NULL) { + continue; + } + ret = knot_tcp_sweep(ctx->syn_table, ctx->tcp_idle_close, ctx->tcp_idle_reset, + UINT32_MAX, ctx->tcp_syn_conns, SIZE_MAX, SIZE_MAX, + sweep_relays, XDP_BATCHLEN, &total_close, &total_reset); + if (ret == KNOT_EOK) { + ret = knot_tcp_send(ctx->sock, sweep_relays, XDP_BATCHLEN, XDP_BATCHLEN); + } + knot_tcp_cleanup(ctx->syn_table, sweep_relays, XDP_BATCHLEN); } while (ret == KNOT_EOK && prev_reset < total_reset); if (total_close > 0 || total_reset > 0) { diff --git a/tests/knot/test_confio.c b/tests/knot/test_confio.c index 03ee7a0920..12a9db272c 100644 --- a/tests/knot/test_confio.c +++ b/tests/knot/test_confio.c @@ -991,6 +991,7 @@ static const yp_item_t desc_server[] = { static const yp_item_t desc_xdp[] = { { C_TCP, YP_TBOOL, YP_VNONE }, { C_TCP_MAX_CLIENTS, YP_TINT, YP_VNONE }, + { C_TCP_SYN_CLIENTS, YP_TINT, YP_VNONE }, { C_TCP_INBUF_MAX_SIZE, YP_TINT, YP_VNONE }, { C_TCP_IDLE_CLOSE, YP_TINT, YP_VNONE }, { C_TCP_IDLE_RESET, YP_TINT, YP_VNONE }, -- GitLab