From: Frédéric Lécaille Date: Mon, 13 Nov 2023 14:50:53 +0000 (+0100) Subject: MINOR: quic: Add a max window parameter to congestion control algorithms X-Git-Tag: v2.9-dev10~82 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=028a55a1d0749ab5b9be86431b03007c38c83d5e;p=thirdparty%2Fhaproxy.git MINOR: quic: Add a max window parameter to congestion control algorithms Add a new ->max_cwnd member to bind_conf struct to store the maximum congestion control window value for each QUIC binding. Modify the "quic-cc-algo" keyword parsing to add an optional parameter to its value: the maximum congestion window value between parentheses as follows: ex: quic-cc-algo cubic(10m) This value must be bounded, greater than 10k and smaller than 1g. --- diff --git a/include/haproxy/listener-t.h b/include/haproxy/listener-t.h index 93856db55a..c1ab05111c 100644 --- a/include/haproxy/listener-t.h +++ b/include/haproxy/listener-t.h @@ -186,6 +186,7 @@ struct bind_conf { #ifdef USE_QUIC struct quic_transport_params quic_params; /* QUIC transport parameters. */ struct quic_cc_algo *quic_cc_algo; /* QUIC control congestion algorithm */ + size_t max_cwnd; /* QUIC maximumu congestion control window size (kB) */ enum quic_sock_mode quic_mode; /* QUIC socket allocation strategy */ #endif struct proxy *frontend; /* the frontend all these listeners belong to, or NULL */ diff --git a/src/cfgparse-quic.c b/src/cfgparse-quic.c index a49a468236..6ca83c8123 100644 --- a/src/cfgparse-quic.c +++ b/src/cfgparse-quic.c @@ -1,3 +1,4 @@ +#include #include #include @@ -20,34 +21,89 @@ static int bind_parse_quic_cc_algo(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err) { struct quic_cc_algo *cc_algo; + const char *newreno = "newrno"; + const char *cubic = "cubic"; + const char *nocc = "nocc"; + const char *algo = NULL; char *arg; if (!*args[cur_arg + 1]) { memprintf(err, "'%s' : missing control congestion algorithm", args[cur_arg]); - return ERR_ALERT | ERR_FATAL; + goto fail; } arg = args[cur_arg + 1]; - if (strcmp(arg, "newreno") == 0) - cc_algo = &quic_cc_algo_nr; - else if (strcmp(arg, "cubic") == 0) - cc_algo = &quic_cc_algo_cubic; - else if (strlen(arg) >= 6 && strncmp(arg, "nocc-", 5) == 0) { + if (strncmp(arg, newreno, strlen(newreno)) == 0) { + /* newreno */ + algo = newreno; + cc_algo = &quic_cc_algo_nr; + arg += strlen(newreno); + } + else if (strncmp(arg, cubic, strlen(cubic)) == 0) { + /* cubic */ + algo = cubic; + cc_algo = &quic_cc_algo_cubic; + arg += strlen(cubic); + } + else if (strncmp(arg, nocc, strlen(nocc)) == 0) { + /* nocc */ if (!experimental_directives_allowed) { - ha_alert("'%s' algo is experimental, must be allowed via a global 'expose-experimental-directives'\n", arg); - return ERR_ALERT | ERR_FATAL; + ha_alert("'%s' algo is experimental, must be allowed via a global " + "'expose-experimental-directives'\n", arg); + goto fail; } - cc_algo = &quic_cc_algo_nocc; - quic_cc_nocc_fixed_cwnd = atoi(arg + 5); + algo = nocc; + cc_algo = &quic_cc_algo_nocc; + arg += strlen(nocc); } else { - memprintf(err, "'%s' : unknown control congestion algorithm", args[cur_arg]); - return ERR_ALERT | ERR_FATAL; + memprintf(err, "'%s' : unknown control congestion algorithm", args[cur_arg + 1]); + goto fail; + } + + if (*arg++ == '(') { + unsigned long cwnd; + char *end_opt; + + errno = 0; + cwnd = strtoul(arg, &end_opt, 0); + if (end_opt == arg || errno != 0) { + memprintf(err, "'%s' : could not parse congestion window value", args[cur_arg + 1]); + goto fail; + } + + if (*end_opt == 'k') { + cwnd <<= 10; + end_opt++; + } + else if (*end_opt == 'm') { + cwnd <<= 20; + end_opt++; + } + else if (*end_opt == 'g') { + memprintf(err, "'%s' : should be smaller than 1g", args[cur_arg + 1]); + goto fail; + } + + if (*end_opt != ')') { + memprintf(err, "'%s' : expects %s()", args[cur_arg + 1], algo); + goto fail; + } + + if (cwnd < 10240 || cwnd >= (4UL << 30)) { + memprintf(err, "'%s' : should be greater than 10k and smaller than 4g", args[cur_arg + 1]); + goto fail; + } + + conf->max_cwnd = cwnd; } conf->quic_cc_algo = cc_algo; return 0; + + fail: + return ERR_ALERT | ERR_FATAL; } static int bind_parse_quic_socket(char **args, int cur_arg, struct proxy *px, diff --git a/src/listener.c b/src/listener.c index 64d3aa038f..bde09cc70d 100644 --- a/src/listener.c +++ b/src/listener.c @@ -1954,6 +1954,8 @@ struct bind_conf *bind_conf_alloc(struct proxy *fe, const char *file, #ifdef USE_QUIC /* Use connection socket for QUIC by default. */ bind_conf->quic_mode = QUIC_SOCK_MODE_CONN; + bind_conf->max_cwnd = + global.tune.bufsize * global.tune.quic_streams_buf; #endif LIST_INIT(&bind_conf->listeners);