mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-07 07:37:02 +02:00
MEDIUM: quic: limit global Tx memory
Define a new settings tune.quic.frontend.max-tot-window. It contains a size argument which can be used to set a limit on the sum of all QUIC connections congestion window. This is applied both on quic_cc_path_set() and quic_cc_path_inc(). Note that this limitation cannot reduce a congestion window more than the minimal limit which is set to 2 datagrams.
This commit is contained in:
parent
e841164a44
commit
0f9b3daf98
@ -1697,6 +1697,7 @@ The following keywords are supported in the "global" section :
|
|||||||
- tune.quic.frontend.max-data-size
|
- tune.quic.frontend.max-data-size
|
||||||
- tune.quic.frontend.max-idle-timeout
|
- tune.quic.frontend.max-idle-timeout
|
||||||
- tune.quic.frontend.max-streams-bidi
|
- tune.quic.frontend.max-streams-bidi
|
||||||
|
- tune.quic.frontend.max-tx-mem
|
||||||
- tune.quic.frontend.stream-data-ratio
|
- tune.quic.frontend.stream-data-ratio
|
||||||
- tune.quic.frontend.default-max-window-size
|
- tune.quic.frontend.default-max-window-size
|
||||||
- tune.quic.max-frame-loss
|
- tune.quic.max-frame-loss
|
||||||
@ -4446,6 +4447,14 @@ tune.quic.frontend.max-streams-bidi <number>
|
|||||||
See also: "tune.quic.frontend.max-data-size",
|
See also: "tune.quic.frontend.max-data-size",
|
||||||
"tune.quic.frontend.stream-data-ratio"
|
"tune.quic.frontend.stream-data-ratio"
|
||||||
|
|
||||||
|
tune.quic.frontend.max-tx-mem <size>
|
||||||
|
Sets the maximum amount of memory usable by QUIC stack at the transport layer
|
||||||
|
for emission. This serves both as a limit of in flight bytes and multiplexer
|
||||||
|
output buffers. Note that to prevent threads contention this limit is not
|
||||||
|
strictly enforced so it can be exceeded on some occasions. Also, each
|
||||||
|
connection will always be able to use a window of at least 2 datagrams, so a
|
||||||
|
proper maxconn should be used in conjunction.
|
||||||
|
|
||||||
tune.quic.frontend.stream-data-ratio <0..100, in percent>
|
tune.quic.frontend.stream-data-ratio <0..100, in percent>
|
||||||
This setting allows to configure the hard limit of the number of data bytes
|
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
|
in flight over each stream. It is expressed as a percentage relative to
|
||||||
|
@ -645,4 +645,13 @@
|
|||||||
#define FWLC_MIN_FREE_ENTRIES 500
|
#define FWLC_MIN_FREE_ENTRIES 500
|
||||||
#endif /* FWLC_MIN_FREE_ENTRIES */
|
#endif /* FWLC_MIN_FREE_ENTRIES */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* QUIC
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Memory usage in bytes on Tx side, 0 for unlimited. */
|
||||||
|
#ifndef QUIC_MAX_TX_MEM
|
||||||
|
#define QUIC_MAX_TX_MEM 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* _HAPROXY_DEFAULTS_H */
|
#endif /* _HAPROXY_DEFAULTS_H */
|
||||||
|
@ -217,6 +217,7 @@ struct global {
|
|||||||
unsigned int quic_frontend_glitches_threshold;
|
unsigned int quic_frontend_glitches_threshold;
|
||||||
unsigned int quic_frontend_max_data;
|
unsigned int quic_frontend_max_data;
|
||||||
unsigned int quic_frontend_max_streams_bidi;
|
unsigned int quic_frontend_max_streams_bidi;
|
||||||
|
uint64_t quic_frontend_max_tx_mem;
|
||||||
size_t quic_frontend_max_window_size;
|
size_t quic_frontend_max_window_size;
|
||||||
unsigned int quic_frontend_stream_data_ratio;
|
unsigned int quic_frontend_stream_data_ratio;
|
||||||
unsigned int quic_retry_threshold;
|
unsigned int quic_retry_threshold;
|
||||||
|
@ -316,6 +316,17 @@ static int cfg_parse_quic_tune_setting(char **args, int section_type,
|
|||||||
}
|
}
|
||||||
else if (strcmp(suffix, "frontend.max-streams-bidi") == 0)
|
else if (strcmp(suffix, "frontend.max-streams-bidi") == 0)
|
||||||
global.tune.quic_frontend_max_streams_bidi = arg;
|
global.tune.quic_frontend_max_streams_bidi = arg;
|
||||||
|
else if (strcmp(suffix, "frontend.max-tx-mem") == 0) {
|
||||||
|
ullong max_mem;
|
||||||
|
|
||||||
|
if ((errptr = parse_size_err(args[1], &max_mem))) {
|
||||||
|
memprintf(err, "'%s': unexpected character '%c' in size argument '%s'.",
|
||||||
|
args[0], *errptr, args[1]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
global.tune.quic_frontend_max_tx_mem = max_mem;
|
||||||
|
}
|
||||||
else if (strcmp(suffix, "frontend.default-max-window-size") == 0) {
|
else if (strcmp(suffix, "frontend.default-max-window-size") == 0) {
|
||||||
unsigned long cwnd;
|
unsigned long cwnd;
|
||||||
char *end_opt;
|
char *end_opt;
|
||||||
@ -430,6 +441,7 @@ static struct cfg_kw_list cfg_kws = {ILH, {
|
|||||||
{ CFG_GLOBAL, "tune.quic.frontend.max-data-size", cfg_parse_quic_tune_setting },
|
{ CFG_GLOBAL, "tune.quic.frontend.max-data-size", cfg_parse_quic_tune_setting },
|
||||||
{ CFG_GLOBAL, "tune.quic.frontend.max-streams-bidi", cfg_parse_quic_tune_setting },
|
{ 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.max-idle-timeout", cfg_parse_quic_time },
|
||||||
|
{ CFG_GLOBAL, "tune.quic.frontend.max-tx-mem", cfg_parse_quic_tune_setting },
|
||||||
{ CFG_GLOBAL, "tune.quic.frontend.default-max-window-size", cfg_parse_quic_tune_setting },
|
{ 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.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.max-frame-loss", cfg_parse_quic_tune_setting },
|
||||||
|
@ -199,6 +199,7 @@ struct global global = {
|
|||||||
.quic_frontend_max_idle_timeout = QUIC_TP_DFLT_FRONT_MAX_IDLE_TIMEOUT,
|
.quic_frontend_max_idle_timeout = QUIC_TP_DFLT_FRONT_MAX_IDLE_TIMEOUT,
|
||||||
.quic_frontend_max_data = 0,
|
.quic_frontend_max_data = 0,
|
||||||
.quic_frontend_max_streams_bidi = QUIC_TP_DFLT_FRONT_MAX_STREAMS_BIDI,
|
.quic_frontend_max_streams_bidi = QUIC_TP_DFLT_FRONT_MAX_STREAMS_BIDI,
|
||||||
|
.quic_frontend_max_tx_mem = QUIC_MAX_TX_MEM,
|
||||||
.quic_frontend_max_window_size = QUIC_DFLT_MAX_WINDOW_SIZE,
|
.quic_frontend_max_window_size = QUIC_DFLT_MAX_WINDOW_SIZE,
|
||||||
.quic_frontend_stream_data_ratio = QUIC_DFLT_FRONT_STREAM_DATA_RATIO,
|
.quic_frontend_stream_data_ratio = QUIC_DFLT_FRONT_STREAM_DATA_RATIO,
|
||||||
.quic_reorder_ratio = QUIC_DFLT_REORDER_RATIO,
|
.quic_reorder_ratio = QUIC_DFLT_REORDER_RATIO,
|
||||||
|
@ -78,6 +78,22 @@ static int quic_cwnd_may_increase(const struct quic_cc_path *path)
|
|||||||
return 2 * path->in_flight >= path->cwnd || path->cwnd < 16384;
|
return 2 * path->in_flight >= path->cwnd || path->cwnd < 16384;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Calculate ratio of free memory relative to the maximum configured limit. */
|
||||||
|
static int quic_cc_max_win_ratio(void)
|
||||||
|
{
|
||||||
|
uint64_t tot, free = 0;
|
||||||
|
int ratio = 100;
|
||||||
|
|
||||||
|
if (global.tune.quic_frontend_max_tx_mem) {
|
||||||
|
tot = cshared_read(&quic_mem_diff);
|
||||||
|
if (global.tune.quic_frontend_max_tx_mem > tot)
|
||||||
|
free = global.tune.quic_frontend_max_tx_mem - tot;
|
||||||
|
ratio = free * 100 / global.tune.quic_frontend_max_tx_mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ratio;
|
||||||
|
}
|
||||||
|
|
||||||
/* Restore congestion window for <path> to its minimal value. */
|
/* Restore congestion window for <path> to its minimal value. */
|
||||||
void quic_cc_path_reset(struct quic_cc_path *path)
|
void quic_cc_path_reset(struct quic_cc_path *path)
|
||||||
{
|
{
|
||||||
@ -90,8 +106,9 @@ void quic_cc_path_reset(struct quic_cc_path *path)
|
|||||||
void quic_cc_path_set(struct quic_cc_path *path, uint64_t val)
|
void quic_cc_path_set(struct quic_cc_path *path, uint64_t val)
|
||||||
{
|
{
|
||||||
const uint64_t old = path->cwnd;
|
const uint64_t old = path->cwnd;
|
||||||
|
const uint64_t limit_max = path->limit_max * quic_cc_max_win_ratio() / 100;
|
||||||
|
|
||||||
path->cwnd = QUIC_MIN(val, path->limit_max);
|
path->cwnd = QUIC_MIN(val, limit_max);
|
||||||
path->cwnd = QUIC_MAX(path->cwnd, path->limit_min);
|
path->cwnd = QUIC_MAX(path->cwnd, path->limit_min);
|
||||||
cshared_add(&quic_mem_diff, path->cwnd - old);
|
cshared_add(&quic_mem_diff, path->cwnd - old);
|
||||||
|
|
||||||
@ -105,9 +122,11 @@ void quic_cc_path_set(struct quic_cc_path *path, uint64_t val)
|
|||||||
void quic_cc_path_inc(struct quic_cc_path *path, uint64_t val)
|
void quic_cc_path_inc(struct quic_cc_path *path, uint64_t val)
|
||||||
{
|
{
|
||||||
const uint64_t old = path->cwnd;
|
const uint64_t old = path->cwnd;
|
||||||
|
uint64_t limit_max;
|
||||||
|
|
||||||
if (quic_cwnd_may_increase(path)) {
|
if (quic_cwnd_may_increase(path)) {
|
||||||
path->cwnd = QUIC_MIN(path->cwnd + val, path->limit_max);
|
limit_max = path->limit_max * quic_cc_max_win_ratio() / 100;
|
||||||
|
path->cwnd = QUIC_MIN(path->cwnd + val, limit_max);
|
||||||
path->cwnd = QUIC_MAX(path->cwnd, path->limit_min);
|
path->cwnd = QUIC_MAX(path->cwnd, path->limit_min);
|
||||||
cshared_add(&quic_mem_diff, path->cwnd - old);
|
cshared_add(&quic_mem_diff, path->cwnd - old);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user