MINOR: quic: Add a fake congestion control algorithm named "nocc"

This algorithm does nothing except initializing the congestion control window
to a fixed value. Very smart!

Modify the QUIC congestion control configuration parser to support this new
algorithm. The congestion control algorithm must be set as follows:

     quic-cc-algo nocc-<cc window size(KB))

For instance if "nocc-15" is provided as quic-cc-algo keyword value, this
will set a fixed window of 15KB.
This commit is contained in:
Frédéric Lécaille 2023-03-31 15:21:55 +02:00
parent 1cb041a6ee
commit db4bc6b4f3
4 changed files with 98 additions and 3 deletions

View File

@ -607,7 +607,7 @@ OPTIONS_OBJS += src/quic_conn.o src/mux_quic.o src/h3.o src/xprt_quic.o \
src/quic_cc_newreno.o src/quic_cc_cubic.o src/qpack-tbl.o \
src/qpack-dec.o src/hq_interop.o src/quic_stream.o \
src/h3_stats.o src/qmux_http.o src/cfgparse-quic.o \
src/cbuf.o src/quic_cc.o
src/cbuf.o src/quic_cc.o src/quic_cc_nocc.o
endif
ifneq ($(USE_LUA),)

View File

@ -37,6 +37,10 @@ extern struct quic_cc_algo quic_cc_algo_nr;
extern struct quic_cc_algo quic_cc_algo_cubic;
extern struct quic_cc_algo *default_quic_cc_algo;
/* Fake algorithm with its fixed window */
extern struct quic_cc_algo quic_cc_algo_nocc;
extern unsigned int quic_cc_nocc_fixed_cwnd;
extern unsigned long long last_ts;
enum quic_cc_algo_state_type {
@ -73,6 +77,7 @@ struct quic_cc_event {
enum quic_cc_algo_type {
QUIC_CC_ALGO_TP_NEWRENO,
QUIC_CC_ALGO_TP_CUBIC,
QUIC_CC_ALGO_TP_NOCC,
};
struct quic_cc {

View File

@ -20,16 +20,27 @@ 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;
char *arg;
if (!*args[cur_arg + 1]) {
memprintf(err, "'%s' : missing control congestion algorithm", args[cur_arg]);
return ERR_ALERT | ERR_FATAL;
}
if (strcmp(args[cur_arg + 1], "newreno") == 0)
arg = args[cur_arg + 1];
if (strcmp(arg, "newreno") == 0)
cc_algo = &quic_cc_algo_nr;
else if (strcmp(args[cur_arg + 1], "cubic") == 0)
else if (strcmp(arg, "cubic") == 0)
cc_algo = &quic_cc_algo_cubic;
else if (strlen(arg) >= 6 && strncmp(arg, "nocc-", 5) == 0) {
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;
}
cc_algo = &quic_cc_algo_nocc;
quic_cc_nocc_fixed_cwnd = atoi(arg + 5);
}
else {
memprintf(err, "'%s' : unknown control congestion algorithm", args[cur_arg]);
return ERR_ALERT | ERR_FATAL;

79
src/quic_cc_nocc.c Normal file
View File

@ -0,0 +1,79 @@
/*
* Fake congestion control algorithm which does nothing except initializing
* the congestion control window to a fixed value.
*
*/
#include <haproxy/api-t.h>
#include <haproxy/quic_conn-t.h>
#include <haproxy/trace.h>
#define TRACE_SOURCE &trace_quic
unsigned int quic_cc_nocc_fixed_cwnd;
static int quic_cc_nocc_init(struct quic_cc *cc)
{
struct quic_path *path;
path = container_of(cc, struct quic_path, cc);
path->cwnd = quic_cc_nocc_fixed_cwnd << 10;
return 1;
}
static void quic_cc_nocc_slow_start(struct quic_cc *cc)
{
}
/* Slow start callback. */
static void quic_cc_nocc_ss_cb(struct quic_cc *cc, struct quic_cc_event *ev)
{
TRACE_ENTER(QUIC_EV_CONN_CC, cc->qc);
TRACE_PROTO("CC nocc", QUIC_EV_CONN_CC, cc->qc, ev, cc);
TRACE_LEAVE(QUIC_EV_CONN_CC, cc->qc);
}
/* Congestion avoidance callback. */
static void quic_cc_nocc_ca_cb(struct quic_cc *cc, struct quic_cc_event *ev)
{
TRACE_ENTER(QUIC_EV_CONN_CC, cc->qc);
TRACE_PROTO("CC nocc", QUIC_EV_CONN_CC, cc->qc, ev, cc);
TRACE_LEAVE(QUIC_EV_CONN_CC, cc->qc);
}
/* Recovery period callback. */
static void quic_cc_nocc_rp_cb(struct quic_cc *cc, struct quic_cc_event *ev)
{
TRACE_ENTER(QUIC_EV_CONN_CC, cc->qc);
TRACE_PROTO("CC nocc", QUIC_EV_CONN_CC, cc->qc, ev, cc);
TRACE_LEAVE(QUIC_EV_CONN_CC, cc->qc);
}
static void quic_cc_nocc_state_trace(struct buffer *buf, const struct quic_cc *cc)
{
struct quic_path *path;
path = container_of(cc, struct quic_path, cc);
chunk_appendf(buf, " cwnd=%llu", (unsigned long long)path->cwnd);
}
static void (*quic_cc_nocc_state_cbs[])(struct quic_cc *cc,
struct quic_cc_event *ev) = {
[QUIC_CC_ST_SS] = quic_cc_nocc_ss_cb,
[QUIC_CC_ST_CA] = quic_cc_nocc_ca_cb,
[QUIC_CC_ST_RP] = quic_cc_nocc_rp_cb,
};
static void quic_cc_nocc_event(struct quic_cc *cc, struct quic_cc_event *ev)
{
return quic_cc_nocc_state_cbs[cc->algo->state](cc, ev);
}
struct quic_cc_algo quic_cc_algo_nocc = {
.type = QUIC_CC_ALGO_TP_NOCC,
.init = quic_cc_nocc_init,
.event = quic_cc_nocc_event,
.slow_start = quic_cc_nocc_slow_start,
.state_trace = quic_cc_nocc_state_trace,
};