From: Amaury Denoyelle Date: Mon, 18 May 2026 06:27:32 +0000 (+0200) Subject: MINOR: quic: use stream elasticity value for initial advertisement X-Git-Tag: v3.4-dev13~20 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d21ec4c707270d5b52df5e77b25f8774f6542ac1;p=thirdparty%2Fhaproxy.git MINOR: quic: use stream elasticity value for initial advertisement When stream elasticity is active, the maximum number of concurrent bidi streams advertised via transport parameters is now reduced depending on the connection load. This is implemented via conn_calc_max_streams() which returns the value to use. This is not applied on listeners with enabled 0-RTT. Indeed, for such connections, clients are expected to reuse the previously seen transport parameters. The server on the other hand must not decrease several values on the newly advertised params, in particular for the maximum number of concurrent bidi streams. The simplest way to prevent 0-RTT failure is to not mix stream elasticity with it. Note that the 0-RTT limitation is only applied for the initial value : during the connection lifetime, stream elasticity can still be used by the MUX to dynamically reduce the stream window. This will be implemented in a future patch. --- diff --git a/doc/configuration.txt b/doc/configuration.txt index 97cd580ea..ce9cadb95 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -5727,6 +5727,10 @@ tune.streams-elasticity use lower values (120 to 200) to support 1.2 to 2 streams per connection on average at full load. + There is a limitation for QUIC listeners with enabled 0-RTT. In this case, + the initial value advertised to the peer will ignore stream elasticity and + instead rely solely on the "tune.quic.stream.max-concurrent" setting. + Monitoring the total number of active streams on backends, including queues, provides a practical indicator of a sustainable target load and helps avoid over-provisioning. diff --git a/src/proxy.c b/src/proxy.c index d328031ad..033ba5090 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -1808,6 +1808,13 @@ int proxy_finalize(struct proxy *px, int *err_code) proxy_type_str(px), px->id); *err_code |= ERR_WARN; } + + if (bind_conf->ssl_conf.early_data && conn_calc_max_streams(1)) { + ha_notice("Binding [%s:%d] for %s %s: " + "stream elasticity is ignored for initial connection settings as this is incompatible with 0-RTT.", + bind_conf->file, bind_conf->line, + proxy_type_str(px), px->id); + } } #endif /* USE_QUIC */ diff --git a/src/quic_tp.c b/src/quic_tp.c index 1dc9df07a..e85f8b58d 100644 --- a/src/quic_tp.c +++ b/src/quic_tp.c @@ -1,6 +1,7 @@ #include #include +#include #include #include #include @@ -862,6 +863,15 @@ int qc_lstnr_params_init(struct quic_conn *qc, rx_params->initial_source_connection_id.len = scidlen; TRACE_PROTO("\nRX(local) transp. params.", QUIC_EV_TRANSP_PARAMS, qc, rx_params); + /* Reduce max-streams-bidi if stream elasticity is active. This is + * ignored however if 0-RTT is configured as clients could reuse + * different transport parameters than the one advertised. + */ + if (global.tune.streams_elasticity && !qc->li->bind_conf->ssl_conf.early_data) { + rx_params->initial_max_streams_bidi = + conn_calc_max_streams(rx_params->initial_max_streams_bidi); + } + return 1; }