MINOR: quic: activate UDP GSO for QUIC if supported

Add a startup test for GSO support in quic_test_socketopts() and
automatically activate it in qc_prep_pkts() when building datagrams as
big as MTU.

Also define a new config option tune.quic.disable-udp-gso. This is
useful to prevent warning on older platform or to debug an issue which
may be related to GSO.
This commit is contained in:
Amaury Denoyelle 2024-05-30 14:49:25 +02:00
parent 5bddf39fb2
commit 35470d5185
4 changed files with 55 additions and 0 deletions

View File

@ -1414,6 +1414,7 @@ The following keywords are supported in the "global" section :
- tune.pool-low-fd-ratio - tune.pool-low-fd-ratio
- tune.pt.zero-copy-forwarding - tune.pt.zero-copy-forwarding
- tune.quic.cc-hystart - tune.quic.cc-hystart
- tune.quic.disable-udp-gso
- tune.quic.frontend.conn-tx-buffers.limit - tune.quic.frontend.conn-tx-buffers.limit
- tune.quic.frontend.glitches-threshold - tune.quic.frontend.glitches-threshold
- tune.quic.frontend.max-idle-timeout - 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 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. 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 <number> tune.quic.frontend.conn-tx-buffers.limit <number>
This settings defines the maximum number of buffers allocated for a QUIC 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 connection on data emission. By default, it is set to 30. QUIC buffers are

View File

@ -85,6 +85,7 @@
#define GTUNE_LISTENER_MQ_OPT (1<<28) #define GTUNE_LISTENER_MQ_OPT (1<<28)
#define GTUNE_LISTENER_MQ_ANY (GTUNE_LISTENER_MQ_FAIR | GTUNE_LISTENER_MQ_OPT) #define GTUNE_LISTENER_MQ_ANY (GTUNE_LISTENER_MQ_FAIR | GTUNE_LISTENER_MQ_OPT)
#define GTUNE_QUIC_CC_HYSTART (1<<29) #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 0x0001 /* Globally disable zero-copy FF */
#define NO_ZERO_COPY_FWD_PT 0x0002 /* disable zero-copy FF for PT (recv & send are disabled automatically) */ #define NO_ZERO_COPY_FWD_PT 0x0002 /* disable zero-copy FF for PT (recv & send are disabled automatically) */

View File

@ -1,5 +1,6 @@
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <netinet/udp.h>
#include <haproxy/api.h> #include <haproxy/api.h>
#include <haproxy/cfgparse.h> #include <haproxy/cfgparse.h>
@ -259,6 +260,29 @@ static int cfg_parse_quic_tune_setting(char **args, int section_type,
return 0; 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}" */ /* config parser for global "tune.quic.* {on|off}" */
static int cfg_parse_quic_tune_on_off(char **args, int section_type, struct proxy *curpx, 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, 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.max-frame-loss", cfg_parse_quic_tune_setting },
{ CFG_GLOBAL, "tune.quic.reorder-ratio", 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.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 }, { CFG_GLOBAL, "tune.quic.zero-copy-fwd-send", cfg_parse_quic_tune_on_off },
{ 0, NULL, NULL } { 0, NULL, NULL }
}}; }};

View File

@ -555,6 +555,28 @@ static int quic_test_socketopts(struct listener *l)
#endif #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); close(fdtest);
return ERR_NONE; return ERR_NONE;