From 1d96d6e0246abd7d00c17590f85261a2fcd33a9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20L=C3=A9caille?= Date: Mon, 23 May 2022 16:38:14 +0200 Subject: [PATCH] MINOR: quic: Tunable "max_idle_timeout" transport parameter Add two tunable settings both for backends and frontends "max_idle_timeout" QUIC transport parameter, "tune.quic.frontend.max-idle-timeout" and "tune.quic.backend.max-idle-timeout" respectively. cfg_parse_quic_time() has been implemented to parse a time value thanks to parse_time_err(). It should be reused for any tunable time value to be parsed. Add the documentation for this tunable setting only for frontend. --- doc/configuration.txt | 15 +++++++++++ include/haproxy/global-t.h | 2 ++ include/haproxy/quic_tp-t.h | 2 ++ src/cfgparse-quic.c | 50 +++++++++++++++++++++++++++++++++++++ src/haproxy.c | 3 +++ src/quic_tp.c | 5 +++- 6 files changed, 76 insertions(+), 1 deletion(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index ac5f866bd9..d95b0f348d 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -1119,6 +1119,7 @@ The following keywords are supported in the "global" section : - tune.pool-high-fd-ratio - tune.pool-low-fd-ratio - tune.quic.conn-buf-limit + - tune.quic.frontend.max-idle-timeout - tune.quic.retry-threshold - tune.rcvbuf.client - tune.rcvbuf.server @@ -2939,6 +2940,20 @@ tune.quic.conn-buf-limit and memory consumption and can be adjusted according to an estimated round time-trip. +tune.quic.frontend.max-idle-timeout + Warning: QUIC support in HAProxy is currently experimental. Configuration may + change without deprecation in the future. + + Sets the QUIC max_idle_timeout transport parameters in milliseconds for + frontends which determines the period of time after which a connection silently + closes if it has remained inactive during an effective period of time deduced + from the two max_idle_timeout values announced by the two endpoints: + - the minimum of the two values if both are not null, + - the maximum if only one of them is not null, + - if both values are null, this feature is disabled. + + The default value is 30000. + tune.quic.retry-threshold Warning: QUIC support in HAProxy is currently experimental. Configuration may change without deprecation in the future. diff --git a/include/haproxy/global-t.h b/include/haproxy/global-t.h index 3544622d3d..b32950a7e3 100644 --- a/include/haproxy/global-t.h +++ b/include/haproxy/global-t.h @@ -158,6 +158,8 @@ struct global { int pool_high_count; /* max number of opened fd before we start killing idle connections when creating new connections */ unsigned short idle_timer; /* how long before an empty buffer is considered idle (ms) */ #ifdef USE_QUIC + unsigned int quic_backend_max_idle_timeout; + unsigned int quic_frontend_max_idle_timeout; unsigned int quic_retry_threshold; unsigned int quic_streams_buf; #endif /* USE_QUIC */ diff --git a/include/haproxy/quic_tp-t.h b/include/haproxy/quic_tp-t.h index 36dd376518..6648c6cf92 100644 --- a/include/haproxy/quic_tp-t.h +++ b/include/haproxy/quic_tp-t.h @@ -30,6 +30,8 @@ struct tp_preferred_address { #define QUIC_DFLT_MAX_UDP_PAYLOAD_SIZE 65527 /* bytes */ #define QUIC_DFLT_ACK_DELAY_COMPONENT 3 /* milliseconds */ #define QUIC_DFLT_MAX_ACK_DELAY 25 /* milliseconds */ +#define QUIC_DFLT_FRONT_MAX_IDLE_TIMEOUT 30000 /* milliseconds */ +#define QUIC_DFLT_BACK_MAX_IDLE_TIMEOUT 30000 /* milliseconds */ #define QUIC_ACTIVE_CONNECTION_ID_LIMIT 2 /* number of connections */ /* Types of QUIC transport parameters */ diff --git a/src/cfgparse-quic.c b/src/cfgparse-quic.c index db637e0800..f4ded90d5a 100644 --- a/src/cfgparse-quic.c +++ b/src/cfgparse-quic.c @@ -1,3 +1,5 @@ +#include + #include #include #include @@ -18,6 +20,52 @@ static struct bind_kw_list bind_kws = { "QUIC", { }, { INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws); +/* Must be used to parse tune.quic.* setting which requires a time + * as value. + * Return -1 on alert, or 0 if succeeded. + */ +static int cfg_parse_quic_time(char **args, int section_type, + struct proxy *curpx, + const struct proxy *defpx, + const char *file, int line, char **err) +{ + unsigned int time; + const char *res, *name, *value; + int prefix_len = strlen("tune.quic."); + + if (too_many_args(1, args, err, NULL)) + return -1; + + name = args[0]; + value = args[1]; + res = parse_time_err(value, &time, TIME_UNIT_MS); + if (res == PARSE_TIME_OVER) { + memprintf(err, "timer overflow in argument '%s' to '%s' " + "(maximum value is 2147483647 ms or ~24.8 days)", value, name); + return -1; + } + else if (res == PARSE_TIME_UNDER) { + memprintf(err, "timer underflow in argument '%s' to '%s' " + "(minimum non-null value is 1 ms)", value, name); + return -1; + } + else if (res) { + memprintf(err, "unexpected character '%c' in '%s'", *res, name); + return -1; + } + + if (strcmp(name + prefix_len, "frontend.max-idle-timeout") == 0) + global.tune.quic_frontend_max_idle_timeout = time; + else if (strcmp(name + prefix_len, "backend.max-idle-timeout") == 0) + global.tune.quic_backend_max_idle_timeout = time; + else { + memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]); + return -1; + } + + return 0; +} + /* Parse any tune.quic.* setting with strictly positive integer values. * Return -1 on alert, or 0 if succeeded. */ @@ -53,7 +101,9 @@ static int cfg_parse_quic_tune_setting(char **args, int section_type, } static struct cfg_kw_list cfg_kws = {ILH, { + { CFG_GLOBAL, "tune.quic.backend.max-idle-timeou", cfg_parse_quic_time }, { CFG_GLOBAL, "tune.quic.conn-buf-limit", cfg_parse_quic_tune_setting }, + { CFG_GLOBAL, "tune.quic.frontend.max-idle-timeout", cfg_parse_quic_time }, { CFG_GLOBAL, "tune.quic.retry-threshold", cfg_parse_quic_tune_setting }, { 0, NULL, NULL } }}; diff --git a/src/haproxy.c b/src/haproxy.c index 203897b737..a112c233a4 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -115,6 +115,7 @@ #include #include #include +#include #include #include #include @@ -205,6 +206,8 @@ struct global global = { .idle_timer = 1000, /* 1 second */ #endif #ifdef USE_QUIC + .quic_backend_max_idle_timeout = QUIC_DFLT_BACK_MAX_IDLE_TIMEOUT, + .quic_frontend_max_idle_timeout = QUIC_DFLT_FRONT_MAX_IDLE_TIMEOUT, .quic_retry_threshold = QUIC_DFLT_RETRY_THRESHOLD, .quic_streams_buf = 30, #endif /* USE_QUIC */ diff --git a/src/quic_tp.c b/src/quic_tp.c index 23a1ff7255..c1e8437f7f 100644 --- a/src/quic_tp.c +++ b/src/quic_tp.c @@ -51,7 +51,10 @@ void quic_transport_params_init(struct quic_transport_params *p, int server) /* Set RFC default values for unspecified parameters. */ quic_dflt_transport_params_cpy(p); - p->max_idle_timeout = 30000; + if (server) + p->max_idle_timeout = global.tune.quic_frontend_max_idle_timeout; + else + p->max_idle_timeout = global.tune.quic_backend_max_idle_timeout; p->initial_max_streams_bidi = max_streams_bidi; p->initial_max_streams_uni = max_streams_uni;