From 47dff5be52dcfdbb02024f658c9cff0f1ca31e8c Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Thu, 27 Nov 2025 16:25:42 +0100 Subject: [PATCH] MINOR: quic: implement cc-algo server keyword Extend QUIC server configuration so that congestion algorithm and maximum window size can be set on the server line. This can be achieved using quic-cc-algo keyword with a syntax similar to a bind line. This should be backported up to 3.3 as this feature is considered as necessary for full QUIC backend support. Note that this relies on the serie of previous commits which should be picked first. --- doc/configuration.txt | 14 ++++++++++++-- include/haproxy/server-t.h | 2 ++ src/cfgparse-quic.c | 24 ++++++++++++++++++++++++ src/quic_conn.c | 9 +++++++-- src/server.c | 10 ++++++++++ 5 files changed, 55 insertions(+), 4 deletions(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index 173acf321..016941bdb 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -4834,7 +4834,7 @@ tune.quic.fe.cc.max-win-size The default value is 480k. - See also the "quic-cc-algo" bind option. + See also the "quic-cc-algo" bind and server options. tune.quic.frontend.default-max-window-size (deprecated) This keyword has been deprecated in 3.3 and will be removed in 3.5. It is @@ -5022,7 +5022,7 @@ tune.quic.fe.tx.pacing { on | off } 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. + See also the "quic-cc-algo" bind and server options. tune.quic.disable-tx-pacing (deprecated) This keyword has been deprecated in 3.3 and will be removed in 3.5. It is @@ -18822,6 +18822,16 @@ proto See also "ws" to use an alternative protocol for websocket streams. +quic-cc-algo { cubic | newreno | bbr | nocc }[()] + This is a QUIC specific setting to select the congestion control algorithm + for any connection targetting this server. They are similar to those used by + TCP. See the bind option with a similar name for a complete description of + all customization options. + + Default value: cubic + + See also: "tune.quic.be.tx.pacing" and "tune.quic.be.cc.max-win-size" + redir May be used in the following contexts: http diff --git a/include/haproxy/server-t.h b/include/haproxy/server-t.h index 2d4f3a07d..a665e4e43 100644 --- a/include/haproxy/server-t.h +++ b/include/haproxy/server-t.h @@ -514,6 +514,8 @@ struct server { } ssl_ctx; #ifdef USE_QUIC struct quic_transport_params quic_params; /* QUIC transport parameters */ + const struct quic_cc_algo *quic_cc_algo; /* QUIC control congestion algorithm */ + size_t quic_max_cwnd; /* QUIC maximum congestion control window size (kB) */ #endif struct path_parameters path_params; /* Connection parameters for that server */ struct resolv_srvrq *srvrq; /* Pointer representing the DNS SRV requeest, if any */ diff --git a/src/cfgparse-quic.c b/src/cfgparse-quic.c index a7bf47f40..7ac88f390 100644 --- a/src/cfgparse-quic.c +++ b/src/cfgparse-quic.c @@ -234,6 +234,24 @@ static int bind_parse_quic_socket(char **args, int cur_arg, struct proxy *px, return 0; } +/* parse "quic-cc-algo" bind keyword */ +static int srv_parse_quic_cc_algo(char **args, int *cur_arg, struct proxy *px, + struct server *srv, char **err) +{ + const struct quic_cc_algo *cc_algo = NULL; + + cc_algo = parse_cc_algo(args, *cur_arg, err, &srv->quic_max_cwnd); + if (!cc_algo) + goto fail; + + out: + srv->quic_cc_algo = cc_algo; + return 0; + + fail: + return ERR_ALERT | ERR_FATAL; +} + static struct bind_kw_list bind_kws = { "QUIC", { }, { { "quic-force-retry", bind_parse_quic_force_retry, 0 }, { "quic-cc-algo", bind_parse_quic_cc_algo, 1 }, @@ -243,6 +261,12 @@ static struct bind_kw_list bind_kws = { "QUIC", { }, { INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws); +static struct srv_kw_list srv_kws = { "QUIC", { }, { + { "quic-cc-algo", srv_parse_quic_cc_algo, 1 }, +}}; + +INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws); + /* parse "tune.quic.fe.sock-per-conn", accepts "default-on" or "force-off" */ static int cfg_parse_quic_tune_sock_per_conn(char **args, int section_type, struct proxy *curpx, diff --git a/src/quic_conn.c b/src/quic_conn.c index 08fde6795..7ae359918 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -1133,6 +1133,7 @@ struct quic_conn *qc_new_conn(void *target, struct server *srv = objt_server(target); struct proxy *prx = l ? l->bind_conf->frontend : __objt_server(target)->proxy; const struct quic_cc_algo *cc_algo = NULL; + size_t max_cwnd; unsigned int next_actconn = 0, next_sslconn = 0, next_handshake = 0; TRACE_ENTER(QUIC_EV_CONN_INIT); @@ -1234,6 +1235,7 @@ struct quic_conn *qc_new_conn(void *target, /* QUIC Server (or listener). */ if (l) { cc_algo = l->bind_conf->quic_cc_algo; + max_cwnd = l->bind_conf->max_cwnd; qc->flags = 0; @@ -1252,6 +1254,9 @@ struct quic_conn *qc_new_conn(void *target, } /* QUIC Client (outgoing connection to servers) */ else { + cc_algo = srv->quic_cc_algo; + max_cwnd = srv->quic_max_cwnd; + qc->flags = QUIC_FL_CONN_IS_BACK|QUIC_FL_CONN_PEER_VALIDATED_ADDR; /* Duplicate GSO status on server to connection */ if (HA_ATOMIC_LOAD(&srv->flags) & SRV_F_UDP_GSO_NOTSUPP) @@ -1347,8 +1352,8 @@ struct quic_conn *qc_new_conn(void *target, /* Only one path at this time (multipath not supported) */ qc->path = &qc->paths[0]; quic_cc_path_init(qc->path, peer_addr->ss_family == AF_INET, - l ? l->bind_conf->max_cwnd : quic_tune.be.cc_max_win_size, - cc_algo ? cc_algo : default_quic_cc_algo, qc); + max_cwnd, cc_algo ? cc_algo : default_quic_cc_algo, + qc); if (local_addr) memcpy(&qc->local_addr, local_addr, sizeof(qc->local_addr)); diff --git a/src/server.c b/src/server.c index 988a83fb0..b6109db85 100644 --- a/src/server.c +++ b/src/server.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -2886,6 +2887,10 @@ void srv_settings_init(struct server *srv) srv->uweight = srv->iweight = 1; +#ifdef USE_QUIC + srv->quic_max_cwnd = quic_tune.be.cc_max_win_size; +#endif + LIST_INIT(&srv->pp_tlvs); } @@ -3043,6 +3048,11 @@ void srv_settings_cpy(struct server *srv, const struct server *src, int srv_tmpl srv->max_idle_conns = src->max_idle_conns; srv->max_reuse = src->max_reuse; +#ifdef USE_QUIC + srv->quic_cc_algo = src->quic_cc_algo; + srv->quic_max_cwnd = src->quic_max_cwnd; +#endif + if (srv_tmpl) srv->srvrq = src->srvrq; -- 2.47.3