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.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 <number>
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

View File

@ -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) */

View File

@ -1,5 +1,6 @@
#include <errno.h>
#include <string.h>
#include <netinet/udp.h>
#include <haproxy/api.h>
#include <haproxy/cfgparse.h>
@ -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 }
}};

View File

@ -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;