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;