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.
This commit is contained in:
Amaury Denoyelle 2025-11-27 16:25:42 +01:00
parent 4f43abd731
commit 47dff5be52
5 changed files with 55 additions and 4 deletions

View 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

View 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 */

View 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,

View 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));

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