From: Amaury Denoyelle Date: Thu, 20 Mar 2025 09:41:53 +0000 (+0100) Subject: MINOR: quic: define max-stream-data configuration as a ratio X-Git-Tag: v3.2-dev9~54 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cf9e40bd8a1414ad2135e04ed8764effadc96be8;p=thirdparty%2Fhaproxy.git MINOR: quic: define max-stream-data configuration as a ratio --- diff --git a/doc/configuration.txt b/doc/configuration.txt index b928fa3db..bc5104b79 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -1694,6 +1694,7 @@ The following keywords are supported in the "global" section : - tune.quic.frontend.max-data-size - tune.quic.frontend.max-idle-timeout - tune.quic.frontend.max-streams-bidi + - tune.quic.frontend.stream-data-ratio - tune.quic.frontend.default-max-window-size - tune.quic.max-frame-loss - tune.quic.reorder-ratio @@ -4349,6 +4350,9 @@ tune.quic.frontend.max-data-size This can be increased for example if a backend application relies on massive uploads over high latency networks. + See also: "tune.quic.frontend.max-streams-bidi", + "tune.quic.frontend.stream-data-ratio" + tune.quic.frontend.max-idle-timeout Sets the QUIC max_idle_timeout transport parameters in milliseconds for frontends which determines the period of time after which a connection silently @@ -4366,7 +4370,32 @@ tune.quic.frontend.max-streams-bidi will be authorized to open. This determines the number of concurrent client requests. - The default value is 100. + The default value is 100. Note that if you reduces it, it can restrict the + buffering capabilities of streams on receive, which would result in poor + upload throughput. It can be corrected by increasing + tune.quic.frontend.max-data-size setting. + + See also: "tune.quic.frontend.max-data-size", + "tune.quic.frontend.stream-data-ratio" + +tune.quic.frontend.stream-data-ratio <0..100, in percent> + This setting allows to configure the hard limit of the number of data bytes + in flight over each stream. It is expressed as a percentage relative to + "tune.quic.frontend.max-data-size" setting, with the result rounded up to + bufsize. + + The default value is 90. This is suitable with the most frequent web + scenario, where uploads is performed only for one or a few streams, whereas + the rest are used for download only. If max-data-size connection limit + remains at a reasonable level, it ensures that only a portion of opened + streams can allocate to their maximum capacity. + + In the case of an application using many uploading streams in parallel and + suffering from unfairness between these streams, it can make sense to reduce + this ratio, to increase fairness and reduce the per-stream bandwidth. + + See also: "tune.quic.frontend.max-data-size", + "tune.quic.frontend.max-streams-bidi" tune.quic.frontend.default-max-window-size Sets the default maximum window size for the congestion controller of a diff --git a/include/haproxy/global-t.h b/include/haproxy/global-t.h index 3aa2c1edf..e54a388a1 100644 --- a/include/haproxy/global-t.h +++ b/include/haproxy/global-t.h @@ -216,6 +216,7 @@ struct global { unsigned int quic_frontend_max_data; unsigned int quic_frontend_max_streams_bidi; size_t quic_frontend_max_window_size; + unsigned int quic_frontend_stream_data_ratio; unsigned int quic_retry_threshold; unsigned int quic_reorder_ratio; unsigned int quic_max_frame_loss; diff --git a/include/haproxy/mux_quic.h b/include/haproxy/mux_quic.h index b39fdfd9c..a2a1ecfb8 100644 --- a/include/haproxy/mux_quic.h +++ b/include/haproxy/mux_quic.h @@ -51,9 +51,6 @@ static inline int qmux_stream_rx_bufsz(void) return global.tune.bufsize - NCB_RESERVED_SZ; } -/* Number of buffers usable on Rx per QCS instance. */ -#define QMUX_STREAM_RX_BUF_FACTOR 90 - /* Bit shift to get the stream sub ID for internal use which is obtained * shifting the stream IDs by this value, knowing that the * QCS_ID_TYPE_SHIFT less significant bits identify the stream ID diff --git a/include/haproxy/quic_conn-t.h b/include/haproxy/quic_conn-t.h index 7ed715610..92dd60ae6 100644 --- a/include/haproxy/quic_conn-t.h +++ b/include/haproxy/quic_conn-t.h @@ -100,6 +100,9 @@ typedef unsigned long long ull; /* Default congestion window size. 480 kB, equivalent to the legacy value which was 30*bufsize */ #define QUIC_DFLT_MAX_WINDOW_SIZE 491520 +/* Default ratio applied for max-stream-data-bidi-remote derived from max-data */ +#define QUIC_DFLT_FRONT_STREAM_DATA_RATIO 90 + /* * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 diff --git a/include/haproxy/quic_tp-t.h b/include/haproxy/quic_tp-t.h index 489744182..61cd5b41e 100644 --- a/include/haproxy/quic_tp-t.h +++ b/include/haproxy/quic_tp-t.h @@ -44,6 +44,7 @@ struct tp_version_information { #define QUIC_TP_DFLT_FRONT_MAX_IDLE_TIMEOUT 30000 /* milliseconds */ #define QUIC_TP_DFLT_FRONT_MAX_STREAMS_BIDI 100 #define QUIC_TP_DFLT_BACK_MAX_IDLE_TIMEOUT 30000 /* milliseconds */ +#define QUIC_TP_DFLT_FRONT_STREAM_DATA_RATIO 90 /* Types of QUIC transport parameters */ #define QUIC_TP_ORIGINAL_DESTINATION_CONNECTION_ID 0x00 diff --git a/src/cfgparse-quic.c b/src/cfgparse-quic.c index 01ff6dd69..3b7c6df2e 100644 --- a/src/cfgparse-quic.c +++ b/src/cfgparse-quic.c @@ -330,6 +330,13 @@ static int cfg_parse_quic_tune_setting(char **args, int section_type, global.tune.quic_frontend_max_window_size = cwnd; } + else if (strcmp(suffix, "frontend.stream-data-ratio") == 0) { + if (arg < 1 || arg > 100) { + memprintf(err, "'%s' expects an integer argument between 1 and 100.", args[0]); + return -1; + } + global.tune.quic_frontend_stream_data_ratio = arg; + } else if (strcmp(suffix, "max-frame-loss") == 0) global.tune.quic_max_frame_loss = arg; else if (strcmp(suffix, "reorder-ratio") == 0) { @@ -424,6 +431,7 @@ static struct cfg_kw_list cfg_kws = {ILH, { { CFG_GLOBAL, "tune.quic.frontend.max-streams-bidi", cfg_parse_quic_tune_setting }, { CFG_GLOBAL, "tune.quic.frontend.max-idle-timeout", cfg_parse_quic_time }, { CFG_GLOBAL, "tune.quic.frontend.default-max-window-size", cfg_parse_quic_tune_setting }, + { CFG_GLOBAL, "tune.quic.frontend.stream-data-ratio", cfg_parse_quic_tune_setting }, { CFG_GLOBAL, "tune.quic.max-frame-loss", cfg_parse_quic_tune_setting }, { CFG_GLOBAL, "tune.quic.reorder-ratio", cfg_parse_quic_tune_setting }, { CFG_GLOBAL, "tune.quic.retry-threshold", cfg_parse_quic_tune_setting }, diff --git a/src/haproxy.c b/src/haproxy.c index 6b1c6ce55..8b59bb6af 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -199,6 +199,7 @@ struct global global = { .quic_frontend_max_data = 0, .quic_frontend_max_streams_bidi = QUIC_TP_DFLT_FRONT_MAX_STREAMS_BIDI, .quic_frontend_max_window_size = QUIC_DFLT_MAX_WINDOW_SIZE, + .quic_frontend_stream_data_ratio = QUIC_DFLT_FRONT_STREAM_DATA_RATIO, .quic_reorder_ratio = QUIC_DFLT_REORDER_RATIO, .quic_retry_threshold = QUIC_DFLT_RETRY_THRESHOLD, .quic_max_frame_loss = QUIC_DFLT_MAX_FRAME_LOSS, diff --git a/src/quic_tp.c b/src/quic_tp.c index 8cb50c326..03d5b12c3 100644 --- a/src/quic_tp.c +++ b/src/quic_tp.c @@ -76,8 +76,13 @@ void quic_transport_params_init(struct quic_transport_params *p, int server) else p->initial_max_data = max_streams_bidi * stream_rx_bufsz; - /* Set remote streams flow-control data limit. */ - p->initial_max_stream_data_bidi_remote = stream_rx_bufsz * QMUX_STREAM_RX_BUF_FACTOR; + /* Set remote streams flow-control data limit. This is calculated as a + * ratio from max-data, then rounded up to bufsize. + */ + p->initial_max_stream_data_bidi_remote = + p->initial_max_data * global.tune.quic_frontend_stream_data_ratio / 100; + p->initial_max_stream_data_bidi_remote = + stream_rx_bufsz * ((p->initial_max_stream_data_bidi_remote + (stream_rx_bufsz - 1)) / stream_rx_bufsz); /* Set remaining flow-control data limit. Local bidi streams are unused * on server side. Uni streams are only used for control exchange, so