From 9bfe9b9e213a468b6864be056c0ca72c404b4b11 Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Thu, 31 Jul 2025 18:20:30 +0200 Subject: [PATCH] MINOR: quic: split Tx options for FE/BE usage This patch is similar to the previous one, except that it is focused on Tx QUIC settings. It is now possible to toggle GSO and pacing on frontend and backend sides independently. As with previous patch, option are renamed to use "fe/be" unified prefixes. This is part of the current serie of commits which unify QUI settings. Older options are deprecated and will be removed on 3.5 release. --- doc/configuration.txt | 62 ++++++++++++++++++++++------------- include/haproxy/quic_tune-t.h | 6 ++-- src/cfgparse-quic.c | 41 ++++++++++++++++++++--- src/cfgparse.c | 2 +- src/mux_quic.c | 2 +- src/proto_quic.c | 6 ++-- src/quic_tx.c | 2 +- 7 files changed, 85 insertions(+), 36 deletions(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index 6a164bb3e..7edb9d2e3 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -1893,16 +1893,19 @@ The following keywords are supported in the "global" section : - tune.quic.be.cc.max-frame-loss - tune.quic.be.cc.reorder-ratio - tune.quic.be.sec.glitches-threshold + - tune.quic.be.tx.pacing + - tune.quic.be.tx.udp-gso - tune.quic.cc.cubic.min-losses (deprecated) - tune.quic.cc-hystart (deprecated) - - tune.quic.disable-tx-pacing - - tune.quic.disable-udp-gso + - tune.quic.disable-tx-pacing (deprecated) + - tune.quic.disable-udp-gso (deprecated) - tune.quic.fe.cc.cubic-min-losses - tune.quic.fe.cc.hystart - tune.quic.fe.cc.max-frame-loss - tune.quic.fe.cc.reorder-ratio - tune.quic.fe.sec.glitches-threshold - - tune.quic.frontend.glitches-threshold (deprecated) + - tune.quic.fe.tx.pacing + - tune.quic.fe.tx.udp-gso - tune.quic.frontend.max-data-size - tune.quic.frontend.max-idle-timeout - tune.quic.frontend.max-streams-bidi @@ -4697,22 +4700,6 @@ tune.pt.zero-copy-forwarding { on | off } See also: tune.disable-zero-copy-forwarding, option splice-auto, option splice-request and option splice-response -tune.quic.disable-tx-pacing - Disables pacing support for QUIC emission. The purpose of pacing is to smooth - emission of data to reduce network losses. In most scenario, it will - significantly improve network throughput by avoiding retransmissions. - However, it can be useful to deactivate it for networks with very high - bandwidth/low latency characteristics to prevent unwanted delay and reduce - CPU consumption. - - See also the "quic-cc-algo" bind option. - -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.be.cc.cubic-min-losses tune.quic.fe.cc.cubic-min-losses Defines how many lost packets are needed for the Cubic congestion control @@ -4793,6 +4780,35 @@ tune.quic.frontend.glitches-threshold (deprecated) part of the streamlining process apply on QUIC configuration. If used, this setting will only be applied on frontend connections. +tune.quic.be.tx.pacing { on | off } +tune.quic.fe.tx.pacing { on | off } + Enables ('on') or disables ('off') pacing support for QUIC emission. By + default, it is active. The purpose of pacing is to smooth emission of data to + reduce network losses. In most scenario, it will significantly improve + network throughput by avoiding retransmissions. However, it can be useful to + deactivate it for networks with very high bandwidth/low latency + characteristics to prevent unwanted delay and reduce CPU consumption. + + See also the "quic-cc-algo" bind option. + +tune.quic.disable-tx-pacing (deprecated) + This keyword has been deprecated in 3.3 and will be removed in 3.5. It is + part of the streamlining process apply on QUIC configuration. If used, this + setting will only be applied on frontend connections. + +tune.quic.be.tx.udp-gso { on | off } +tune.quic.fe.tx.udp-gso { on | off } + Enables ('on') or disables ('off') UDP GSO support for QUIC emission. By + default, it is active. 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.disable-udp-gso (deprecated) + This keyword has been deprecated in 3.3 and will be removed in 3.5. It is + part of the streamlining process apply on QUIC configuration. If used, this + setting will only be applied on frontend connections. + tune.quic.frontend.max-data-size This setting is the hard limit for the number of data bytes in flight over a QUIC frontend connection. It is reused as the value for the initial_max_data @@ -17110,10 +17126,10 @@ quic-cc-algo { cubic | newreno | bbr | nocc }[()] similar to those used by TCP. Pacing is activated on top of the congestion algorithm to reduce loss and - improve throughput. It can be turned off via "tune.quic.disable-tx-pacing" - global keyword. In most cases, pacing should remain activated, especially - when using BBR as it relies on it to work as expected. Using BBR without - pacing may cause slowdowns or high loss rates during transfers. + improve throughput. It can be turned off via "tune.quic.fe.tx.pacing" global + keyword. In most cases, pacing should remain activated, especially when using + BBR as it relies on it to work as expected. Using BBR without pacing may + cause slowdowns or high loss rates during transfers. Default value: cubic diff --git a/include/haproxy/quic_tune-t.h b/include/haproxy/quic_tune-t.h index 8a6ba9137..cb84bf7ac 100644 --- a/include/haproxy/quic_tune-t.h +++ b/include/haproxy/quic_tune-t.h @@ -15,11 +15,11 @@ #define QUIC_TUNE_FE_LISTEN_OFF 0x00000001 -#define QUIC_TUNE_NO_PACING 0x00000001 -#define QUIC_TUNE_NO_UDP_GSO 0x00000002 #define QUIC_TUNE_SOCK_PER_CONN 0x00000004 -#define QUIC_TUNE_FB_CC_HYSTART 0x00000001 +#define QUIC_TUNE_FB_TX_PACING 0x00000001 +#define QUIC_TUNE_FB_TX_UDP_GSO 0x00000002 +#define QUIC_TUNE_FB_CC_HYSTART 0x00000004 struct quic_tune { struct { diff --git a/src/cfgparse-quic.c b/src/cfgparse-quic.c index 15fc94322..143483434 100644 --- a/src/cfgparse-quic.c +++ b/src/cfgparse-quic.c @@ -27,10 +27,12 @@ struct quic_tune quic_tune = { .fe = { .cc_max_frame_loss = QUIC_DFLT_CC_MAX_FRAME_LOSS, .cc_reorder_ratio = QUIC_DFLT_CC_REORDER_RATIO, + .fb_opts = QUIC_TUNE_FB_TX_PACING|QUIC_TUNE_FB_TX_UDP_GSO, }, .be = { .cc_max_frame_loss = QUIC_DFLT_CC_MAX_FRAME_LOSS, .cc_reorder_ratio = QUIC_DFLT_CC_REORDER_RATIO, + .fb_opts = QUIC_TUNE_FB_TX_PACING|QUIC_TUNE_FB_TX_UDP_GSO, }, }; @@ -420,6 +422,7 @@ static int cfg_parse_quic_tune_setting0(char **args, int section_type, const struct proxy *defpx, const char *file, int line, char **err) { + int ret = 0; int prefix_len = strlen("tune.quic."); const char *suffix; @@ -428,17 +431,23 @@ static int cfg_parse_quic_tune_setting0(char **args, int section_type, suffix = args[0] + prefix_len; if (strcmp(suffix, "disable-tx-pacing") == 0) { - quic_tune.options |= QUIC_TUNE_NO_PACING; + memprintf(err, "'%s' is deprecated in 3.3 and will be removed in 3.5. " + "Please use the newer keyword syntax 'tune.quic.fe.tx.pacing'.", args[0]); + quic_tune.fe.fb_opts &= ~QUIC_TUNE_FB_TX_PACING; + ret = 1; } else if (strcmp(suffix, "disable-udp-gso") == 0) { - quic_tune.options |= QUIC_TUNE_NO_UDP_GSO; + memprintf(err, "'%s' is deprecated in 3.3 and will be removed in 3.5. " + "Please use the newer keyword syntax 'tune.quic.fe.tx.udp-gso'.", args[0]); + quic_tune.fe.fb_opts &= ~QUIC_TUNE_FB_TX_UDP_GSO; + ret = 1; } else { memprintf(err, "'%s' keyword unhandled (please report this bug).", args[0]); return -1; } - return 0; + return ret; } /* config parser for global "tune.quic.* {on|off}" */ @@ -485,6 +494,24 @@ static int cfg_parse_quic_tune_on_off(char **args, int section_type, struct prox else *ptr &= ~QUIC_TUNE_FB_CC_HYSTART; } + else if (strcmp(suffix, "be.tx.pacing") == 0 || + strcmp(suffix, "fe.tx.pacing") == 0) { + uint *ptr = (suffix[0] == 'b') ? &quic_tune.be.fb_opts : + &quic_tune.fe.fb_opts; + if (on) + *ptr |= QUIC_TUNE_FB_TX_PACING; + else + *ptr &= ~QUIC_TUNE_FB_TX_PACING; + } + else if (strcmp(suffix, "be.tx.udp-gso") == 0 || + strcmp(suffix, "fe.tx.udp-gso") == 0) { + uint *ptr = (suffix[0] == 'b') ? &quic_tune.be.fb_opts : + &quic_tune.fe.fb_opts; + if (on) + *ptr |= QUIC_TUNE_FB_TX_UDP_GSO; + else + *ptr &= ~QUIC_TUNE_FB_TX_UDP_GSO; + } else if (strcmp(suffix, "cc-hystart") == 0) { memprintf(err, "'%s' is deprecated in 3.3 and will be removed in 3.5. " "Please use the newer keyword syntax 'tune.quic.fe.cc.hystart'.", args[0]); @@ -508,8 +535,6 @@ static struct cfg_kw_list cfg_kws = {ILH, { { CFG_GLOBAL, "tune.quic.frontend.default-max-window-size", cfg_parse_quic_tune_setting }, { CFG_GLOBAL, "tune.quic.frontend.stream-data-ratio", cfg_parse_quic_tune_setting }, { CFG_GLOBAL, "tune.quic.retry-threshold", cfg_parse_quic_tune_setting }, - { CFG_GLOBAL, "tune.quic.disable-tx-pacing", cfg_parse_quic_tune_setting0 }, - { 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.fe.cc.cubic-min-losses", cfg_parse_quic_tune_setting }, @@ -517,16 +542,22 @@ static struct cfg_kw_list cfg_kws = {ILH, { { CFG_GLOBAL, "tune.quic.fe.cc.max-frame-loss", cfg_parse_quic_tune_setting }, { CFG_GLOBAL, "tune.quic.fe.cc.reorder-ratio", cfg_parse_quic_tune_setting }, { CFG_GLOBAL, "tune.quic.fe.sec.glitches-threshold", cfg_parse_quic_tune_setting }, + { CFG_GLOBAL, "tune.quic.fe.tx.pacing", cfg_parse_quic_tune_on_off }, + { CFG_GLOBAL, "tune.quic.fe.tx.udp-gso", cfg_parse_quic_tune_on_off }, { CFG_GLOBAL, "tune.quic.be.cc.cubic-min-losses", cfg_parse_quic_tune_setting }, { CFG_GLOBAL, "tune.quic.be.cc.hystart", cfg_parse_quic_tune_on_off }, { CFG_GLOBAL, "tune.quic.be.cc.max-frame-loss", cfg_parse_quic_tune_setting }, { CFG_GLOBAL, "tune.quic.be.cc.reorder-ratio", cfg_parse_quic_tune_setting }, { CFG_GLOBAL, "tune.quic.be.sec.glitches-threshold", cfg_parse_quic_tune_setting }, + { CFG_GLOBAL, "tune.quic.be.tx.pacing", cfg_parse_quic_tune_on_off }, + { CFG_GLOBAL, "tune.quic.be.tx.udp-gso", cfg_parse_quic_tune_on_off }, /* legacy options */ { CFG_GLOBAL, "tune.quic.cc-hystart", cfg_parse_quic_tune_on_off }, { CFG_GLOBAL, "tune.quic.cc.cubic.min-losses", cfg_parse_quic_tune_setting }, + { CFG_GLOBAL, "tune.quic.disable-tx-pacing", cfg_parse_quic_tune_setting0 }, + { CFG_GLOBAL, "tune.quic.disable-udp-gso", cfg_parse_quic_tune_setting0 }, { CFG_GLOBAL, "tune.quic.frontend.glitches-threshold", 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 }, diff --git a/src/cfgparse.c b/src/cfgparse.c index b7cbdbd95..de1b03e5a 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -2978,7 +2978,7 @@ init_proxies_list_stage1: bind_conf->quic_cc_algo : default_quic_cc_algo; if (!(cc_algo->flags & QUIC_CC_ALGO_FL_OPT_PACING) && - quic_tune.options & QUIC_TUNE_NO_PACING) { + !(quic_tune.fe.fb_opts & QUIC_TUNE_FB_TX_PACING)) { ha_warning("Binding [%s:%d] for %s %s: using the selected congestion algorithm without pacing may cause slowdowns or high loss rates during transfers.\n", bind_conf->file, bind_conf->line, proxy_type_str(curproxy), curproxy->id); diff --git a/src/mux_quic.c b/src/mux_quic.c index 02713b4ff..3d9e6b5a9 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -43,7 +43,7 @@ static void qmux_ctrl_room(struct qc_stream_desc *, uint64_t room); /* Returns true if pacing should be used for connection. */ static int qcc_is_pacing_active(const struct connection *conn) { - return !(quic_tune.options & QUIC_TUNE_NO_PACING); + return quic_tune_conn_test(QUIC_TUNE_FB_TX_PACING, conn); } /* Free instance and its inner data storage attached to stream. */ diff --git a/src/proto_quic.c b/src/proto_quic.c index f7a1e2492..fe8faec4d 100644 --- a/src/proto_quic.c +++ b/src/proto_quic.c @@ -780,7 +780,8 @@ static int quic_test_socketopts(void) } /* Check for UDP GSO support. */ - if (!(quic_tune.options & QUIC_TUNE_NO_UDP_GSO)) { + if ((quic_tune.fe.fb_opts & QUIC_TUNE_FB_TX_UDP_GSO) || + (quic_tune.be.fb_opts & QUIC_TUNE_FB_TX_UDP_GSO)) { ret = quic_test_gso(); if (ret < 0) { goto err; @@ -788,7 +789,8 @@ static int quic_test_socketopts(void) else if (!ret) { ha_diag_warning("Your platform does not support UDP GSO. " "This will be automatically disabled for QUIC transfer.\n"); - quic_tune.options |= QUIC_TUNE_NO_UDP_GSO; + quic_tune.fe.fb_opts &= ~QUIC_TUNE_FB_TX_UDP_GSO; + quic_tune.be.fb_opts &= ~QUIC_TUNE_FB_TX_UDP_GSO; } } diff --git a/src/quic_tx.c b/src/quic_tx.c index 1b6497b43..22caf5b20 100644 --- a/src/quic_tx.c +++ b/src/quic_tx.c @@ -810,7 +810,7 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf, /* Everything sent. Continue within the same datagram. */ prv_pkt = cur_pkt; } - else if (!(quic_tune.options & QUIC_TUNE_NO_UDP_GSO) && + else if (quic_tune_test(QUIC_TUNE_FB_TX_UDP_GSO, qc) && !(qc->flags & QUIC_FL_CONN_UDP_GSO_EIO) && dglen == qc->path->mtu && (char *)end < b_wrap(buf) &&