diff --git a/doc/configuration.txt b/doc/configuration.txt index e723305ba..4e38936f2 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -1414,6 +1414,7 @@ The following keywords are supported in the "global" section : - tune.pool-low-fd-ratio - tune.pt.zero-copy-forwarding - tune.quic.cc-hystart + - tune.quic.disable-udp-gso - tune.quic.frontend.conn-tx-buffers.limit - tune.quic.frontend.glitches-threshold - tune.quic.frontend.max-idle-timeout @@ -3770,6 +3771,12 @@ tune.quic.cc-hystart { on | off } QUIC connections used as a replacement for the slow start phase of congestion control algorithms which may cause high packet loss. It is disabled by default. +tune.quic.disable-udp-gso + Disable UDP GSO emission. This kernel feature allows to emit multiple + datagrams via a single system call which is more efficient for large + transfer. It may be useful to disable it on developers suggestion when + suspecting an issue on emission. + tune.quic.frontend.conn-tx-buffers.limit This settings defines the maximum number of buffers allocated for a QUIC connection on data emission. By default, it is set to 30. QUIC buffers are diff --git a/include/haproxy/global-t.h b/include/haproxy/global-t.h index 6e66a1d81..f4d87b7a1 100644 --- a/include/haproxy/global-t.h +++ b/include/haproxy/global-t.h @@ -85,6 +85,7 @@ #define GTUNE_LISTENER_MQ_OPT (1<<28) #define GTUNE_LISTENER_MQ_ANY (GTUNE_LISTENER_MQ_FAIR | GTUNE_LISTENER_MQ_OPT) #define GTUNE_QUIC_CC_HYSTART (1<<29) +#define GTUNE_QUIC_NO_UDP_GSO (1<<30) #define NO_ZERO_COPY_FWD 0x0001 /* Globally disable zero-copy FF */ #define NO_ZERO_COPY_FWD_PT 0x0002 /* disable zero-copy FF for PT (recv & send are disabled automatically) */ diff --git a/src/cfgparse-quic.c b/src/cfgparse-quic.c index 4a23bf20e..97c515acf 100644 --- a/src/cfgparse-quic.c +++ b/src/cfgparse-quic.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -259,6 +260,29 @@ static int cfg_parse_quic_tune_setting(char **args, int section_type, return 0; } +static int cfg_parse_quic_tune_setting0(char **args, int section_type, + struct proxy *curpx, + const struct proxy *defpx, + const char *file, int line, char **err) +{ + int prefix_len = strlen("tune.quic."); + const char *suffix; + + if (too_many_args(0, args, err, NULL)) + return -1; + + suffix = args[0] + prefix_len; + if (strcmp(suffix, "disable-udp-gso") == 0) { + global.tune.options |= GTUNE_QUIC_NO_UDP_GSO; + } + else { + memprintf(err, "'%s' keyword unhandled (please report this bug).", args[0]); + return -1; + } + + return 0; +} + /* config parser for global "tune.quic.* {on|off}" */ static int cfg_parse_quic_tune_on_off(char **args, int section_type, struct proxy *curpx, const struct proxy *defpx, const char *file, int line, @@ -308,6 +332,7 @@ static struct cfg_kw_list cfg_kws = {ILH, { { CFG_GLOBAL, "tune.quic.max-frame-loss", cfg_parse_quic_tune_setting }, { CFG_GLOBAL, "tune.quic.reorder-ratio", cfg_parse_quic_tune_setting }, { CFG_GLOBAL, "tune.quic.retry-threshold", cfg_parse_quic_tune_setting }, + { CFG_GLOBAL, "tune.quic.disable-udp-gso", cfg_parse_quic_tune_setting0 }, { CFG_GLOBAL, "tune.quic.zero-copy-fwd-send", cfg_parse_quic_tune_on_off }, { 0, NULL, NULL } }}; diff --git a/src/proto_quic.c b/src/proto_quic.c index 2e5ad6480..96d33fe5a 100644 --- a/src/proto_quic.c +++ b/src/proto_quic.c @@ -555,6 +555,28 @@ static int quic_test_socketopts(struct listener *l) #endif } + /* Check for UDP GSO support. */ + if (!(global.tune.options & GTUNE_QUIC_NO_UDP_GSO)) { + if (fdtest < 0) { + fdtest = socket(rx->proto->fam->sock_domain, + rx->proto->sock_type, rx->proto->sock_prot); + if (fdtest < 0) + goto err; + } + +#ifdef UDP_SEGMENT + if (setsockopt(fdtest, SOL_UDP, UDP_SEGMENT, &zero, sizeof(zero))) { + ha_alert("Your platform does not support UDP GSO. " + "This will be automatically disabled for QUIC transfer.\n"); + global.tune.options |= GTUNE_QUIC_NO_UDP_GSO; + } +#else + ha_alert("Your platform does not support UDP GSO. " + "This will be automatically disabled for QUIC transfer.\n"); + global.tune.options |= GTUNE_QUIC_NO_UDP_GSO; +#endif + } + close(fdtest); return ERR_NONE;