]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: implement cc-algo server keyword
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 27 Nov 2025 15:25:42 +0000 (16:25 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 1 Dec 2025 14:53:58 +0000 (15:53 +0100)
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
include/haproxy/server-t.h
src/cfgparse-quic.c
src/quic_conn.c
src/server.c

index 173acf321a384fc8c72d5a24965d8b6a3772cd02..016941bdb500807113b3834a83f593685f43aa0a 100644 (file)
@@ -4834,7 +4834,7 @@ tune.quic.fe.cc.max-win-size <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 <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 <name>
 
   See also "ws" to use an alternative protocol for websocket streams.
 
+quic-cc-algo { cubic | newreno | bbr | nocc }[(<args,...>)]
+  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 <prefix>
   May be used in the following contexts: http
 
index 2d4f3a07d13402c98bc7afbc1f45aa40d4a9207d..a665e4e43a0e15e28ccbad972fabdce62449fc2f 100644 (file)
@@ -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 */
index a7bf47f406c4fc5fe1e7df80fd5dc09efea58a55..7ac88f390c7f0768a5d335211085003f168280af 100644 (file)
@@ -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,
index 08fde6795db22ac3e762a6f8e1b4f12687c6b7f3..7ae359918f99a88489ea0520dbcf469d761e12f2 100644 (file)
@@ -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));
index 988a83fb08a11794683c997c5b50d95a24d9c7dc..b6109db85973055dec87e3cc243a016242a3d061 100644 (file)
@@ -40,6 +40,7 @@
 #include <haproxy/proxy.h>
 #include <haproxy/queue.h>
 #include <haproxy/quic_tp.h>
+#include <haproxy/quic_tune.h>
 #include <haproxy/resolvers.h>
 #include <haproxy/sample.h>
 #include <haproxy/sc_strm.h>
@@ -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;