BUG/MINOR: quic: Wrong use of now_ms timestamps (cubic algo)

As now_ms may wrap, one must use the ticks API to protect the cubic congestion
control algorithm implementation from side effects due to this.

Furthermore to make the cubic congestion control algorithm more readable and easy
to maintain, adding a new state ("in recovery period" QUIC_CC_ST_RP new enum) helps
in reaching this goal. Implement quic_cc_cubic_rp_cb() which is the callback for
this new state.

Must be backported to 2.7 and 2.6.
This commit is contained in:
Frédéric Lécaille 2023-03-21 11:54:02 +01:00
parent 6549f53fb6
commit d7243318c4
3 changed files with 38 additions and 18 deletions

View File

@ -44,6 +44,8 @@ enum quic_cc_algo_state_type {
QUIC_CC_ST_SS,
/* Congestion avoidance. */
QUIC_CC_ST_CA,
/* Recovery period. */
QUIC_CC_ST_RP,
};
enum quic_cc_event_type {

View File

@ -43,6 +43,8 @@ static inline const char *quic_cc_state_str(enum quic_cc_algo_state_type state)
return "ss";
case QUIC_CC_ST_CA:
return "ca";
case QUIC_CC_ST_RP:
return "rp";
default:
return "unknown";
}

View File

@ -189,6 +189,7 @@ static void quic_enter_recovery(struct quic_cc *cc)
}
path->cwnd = (CUBIC_BETA * path->cwnd) >> CUBIC_BETA_SCALE_SHIFT;
c->ssthresh = QUIC_MAX(path->cwnd, path->min_cwnd);
cc->algo->state = QUIC_CC_ST_RP;
}
/* Congestion slow-start callback. */
@ -200,10 +201,6 @@ static void quic_cc_cubic_ss_cb(struct quic_cc *cc, struct quic_cc_event *ev)
TRACE_ENTER(QUIC_EV_CONN_CC, cc->qc, ev);
switch (ev->type) {
case QUIC_CC_EVT_ACK:
/* Do not increase the congestion window in recovery period. */
if (ev->ack.time_sent <= c->recovery_start_time)
goto out;
path->cwnd += ev->ack.acked;
/* Exit to congestion avoidance if slow start threshold is reached. */
if (path->cwnd >= c->ssthresh)
@ -211,10 +208,6 @@ static void quic_cc_cubic_ss_cb(struct quic_cc *cc, struct quic_cc_event *ev)
break;
case QUIC_CC_EVT_LOSS:
/* Do not decrease the congestion window when already in recovery period. */
if (ev->loss.time_sent <= c->recovery_start_time)
goto out;
quic_enter_recovery(cc);
/* Exit to congestion avoidance. */
cc->algo->state = QUIC_CC_ST_CA;
@ -232,22 +225,12 @@ static void quic_cc_cubic_ss_cb(struct quic_cc *cc, struct quic_cc_event *ev)
/* Congestion avoidance callback. */
static void quic_cc_cubic_ca_cb(struct quic_cc *cc, struct quic_cc_event *ev)
{
struct cubic *c = quic_cc_priv(cc);
TRACE_ENTER(QUIC_EV_CONN_CC, cc->qc, ev);
switch (ev->type) {
case QUIC_CC_EVT_ACK:
/* Do not increase the congestion window when already in recovery period. */
if (ev->ack.time_sent <= c->recovery_start_time)
goto out;
quic_cubic_update(cc, ev->ack.acked);
break;
case QUIC_CC_EVT_LOSS:
/* Do not decrease the congestion window when already in recovery period. */
if (ev->loss.time_sent <= c->recovery_start_time)
goto out;
quic_enter_recovery(cc);
break;
case QUIC_CC_EVT_ECN_CE:
@ -259,10 +242,43 @@ static void quic_cc_cubic_ca_cb(struct quic_cc *cc, struct quic_cc_event *ev)
TRACE_LEAVE(QUIC_EV_CONN_CC, cc->qc, NULL, cc);
}
/* Recovery period callback */
static void quic_cc_cubic_rp_cb(struct quic_cc *cc, struct quic_cc_event *ev)
{
struct cubic *c = quic_cc_priv(cc);
TRACE_ENTER(QUIC_EV_CONN_CC, cc->qc, ev);
BUG_ON(!tick_isset(c->recovery_start_time));
switch (ev->type) {
case QUIC_CC_EVT_ACK:
/* RFC 9022 7.3.2. Recovery
* A recovery period ends and the sender enters congestion avoidance when a
* packet sent during the recovery period is acknowledged.
*/
if (tick_is_le(ev->ack.time_sent, c->recovery_start_time))
goto leave;
cc->algo->state = QUIC_CC_ST_CA;
c->recovery_start_time = TICK_ETERNITY;
break;
case QUIC_CC_EVT_LOSS:
break;
case QUIC_CC_EVT_ECN_CE:
/* TODO */
break;
}
leave:
TRACE_LEAVE(QUIC_EV_CONN_CC, cc->qc, NULL, cc);
}
static void (*quic_cc_cubic_state_cbs[])(struct quic_cc *cc,
struct quic_cc_event *ev) = {
[QUIC_CC_ST_SS] = quic_cc_cubic_ss_cb,
[QUIC_CC_ST_CA] = quic_cc_cubic_ca_cb,
[QUIC_CC_ST_RP] = quic_cc_cubic_rp_cb,
};
static void quic_cc_cubic_event(struct quic_cc *cc, struct quic_cc_event *ev)