Update the repository with the changes made since the last LKML review.

This commit is contained in:
Lukas Prause
2026-09-30 12:47:22 +02:00
parent 64d0e54f87
commit 174cc731de
2 changed files with 83 additions and 38 deletions
+70 -33
View File
@@ -88,10 +88,17 @@ static u32 beta_scale __read_mostly;
static u64 cube_factor __read_mostly; static u64 cube_factor __read_mostly;
/* Note parameters that are used for precomputing scale factors are read-only */ /* Note parameters that are used for precomputing scale factors are read-only */
static int beta_param_set(const char *val, const struct kernel_param *kp);
static const struct kernel_param_ops beta_param_ops = {
.set = beta_param_set,
.get = param_get_int,
};
module_param_cb(beta, &beta_param_ops, &beta, 0644);
MODULE_PARM_DESC(beta, "beta for multiplicative increase");
module_param(fast_convergence, int, 0644); module_param(fast_convergence, int, 0644);
MODULE_PARM_DESC(fast_convergence, "turn on/off fast convergence"); MODULE_PARM_DESC(fast_convergence, "turn on/off fast convergence");
module_param(beta, int, 0644);
MODULE_PARM_DESC(beta, "beta for multiplicative increase");
module_param(initial_ssthresh, int, 0644); module_param(initial_ssthresh, int, 0644);
MODULE_PARM_DESC(initial_ssthresh, "initial value of slow start threshold"); MODULE_PARM_DESC(initial_ssthresh, "initial value of slow start threshold");
module_param(bic_scale, int, 0444); module_param(bic_scale, int, 0444);
@@ -100,6 +107,26 @@ MODULE_PARM_DESC(bic_scale,
module_param(tcp_friendliness, int, 0644); module_param(tcp_friendliness, int, 0644);
MODULE_PARM_DESC(tcp_friendliness, "turn on/off tcp friendliness"); MODULE_PARM_DESC(tcp_friendliness, "turn on/off tcp friendliness");
/* Check & set the new beta parameter candidate value.
*/
static int beta_param_set(const char *val, const struct kernel_param *kp)
{
int beta_candidate;
int ret = kstrtoint(val, 10, &beta_candidate);
if (ret)
return ret;
if (beta_candidate <= 0 || beta_candidate >= BICTCP_BETA_SCALE) {
pr_err_once("TCP ROCCET: beta must be between 0 and %d\n",
BICTCP_BETA_SCALE);
return -EINVAL;
}
return param_set_int(val, kp);
}
/* Used to check certain roccet parameters used in `param_precompute` in order /* Used to check certain roccet parameters used in `param_precompute` in order
* to avoid invalid scale-related calculations. This validates the specified * to avoid invalid scale-related calculations. This validates the specified
* parameters or rejects them. * parameters or rejects them.
@@ -170,6 +197,7 @@ static void roccet_reset(struct sock *sk, struct roccettcp *ca)
ca->last_rtt = U32_MAX; ca->last_rtt = U32_MAX;
ca->roccet_last_event_time_us = 0; ca->roccet_last_event_time_us = 0;
ca->last_event_time_set = false;
ca->ack_rate_last_rate = 0; ca->ack_rate_last_rate = 0;
/* Initialize to current time to avoid an /* Initialize to current time to avoid an
@@ -186,6 +214,7 @@ static void roccet_reset(struct sock *sk, struct roccettcp *ca)
ca->state = LAUNCH; ca->state = LAUNCH;
ca->probe_min_rtt_until = 0; ca->probe_min_rtt_until = 0;
ca->refill_until = 0; ca->refill_until = 0;
ca->rtt_probe_timers_set = false;
ca->initial_limit_reached = false; ca->initial_limit_reached = false;
ca->is_in_initial_launch = false; ca->is_in_initial_launch = false;
@@ -357,6 +386,7 @@ static void roccet_congestion_event(struct sock *sk, u32 now)
ca->epoch_start = 0; ca->epoch_start = 0;
ca->roccet_last_event_time_us = now; ca->roccet_last_event_time_us = now;
ca->last_event_time_set = true;
if (ca->state == RTT_PROBE) { if (ca->state == RTT_PROBE) {
/* In case we are in RTT_PROBE, continue with this state, as /* In case we are in RTT_PROBE, continue with this state, as
@@ -402,8 +432,8 @@ static void roccet_enter_min_rtt_probe(struct sock *sk, u32 now)
/* If probing is already set, there was a mix up. /* If probing is already set, there was a mix up.
* Continue anyway so we can recover. * Continue anyway so we can recover.
*/ */
if (ca->probe_min_rtt_until > 0) if (ca->rtt_probe_timers_set)
pr_warn_once("ROCCET: Probing time should not be set"); pr_warn_once("ROCCET: Probing time should not be set when entering RTT Probe");
/* Safeguard for an "infinite" probe. This should logically never /* Safeguard for an "infinite" probe. This should logically never
* happen but still safeguard it. * happen but still safeguard it.
@@ -427,9 +457,9 @@ static void roccet_enter_min_rtt_probe(struct sock *sk, u32 now)
* we set the cwnd to its previous value after probing. * we set the cwnd to its previous value after probing.
*/ */
if (!tcp_is_cwnd_limited(sk)) if (!tcp_is_cwnd_limited(sk))
probe_cwnd = max(tcp_snd_cwnd(tp) / 3, TCP_INIT_CWND); probe_cwnd = max(tcp_snd_cwnd(tp) / 3, 1);
else else
probe_cwnd = max(tcp_snd_cwnd(tp) / 2, TCP_INIT_CWND); probe_cwnd = max(tcp_snd_cwnd(tp) / 2, 1);
ca->probe_min_rtt_until = now + interval; ca->probe_min_rtt_until = now + interval;
ca->cwnd_before_min_rtt_probe = tcp_snd_cwnd(tp); ca->cwnd_before_min_rtt_probe = tcp_snd_cwnd(tp);
@@ -446,6 +476,7 @@ static void roccet_enter_min_rtt_probe(struct sock *sk, u32 now)
* For this we use the previous cwnd for another probing interval. * For this we use the previous cwnd for another probing interval.
*/ */
ca->refill_until = ca->probe_min_rtt_until + interval; ca->refill_until = ca->probe_min_rtt_until + interval;
ca->rtt_probe_timers_set = true; /* Now both timers are set. */
/* Now we know that ca->probe_min_rtt_until < ca->refill_until /* Now we know that ca->probe_min_rtt_until < ca->refill_until
* and we advance to the next state of the probing phase. * and we advance to the next state of the probing phase.
@@ -453,7 +484,6 @@ static void roccet_enter_min_rtt_probe(struct sock *sk, u32 now)
* Wrap-arounds of these values are handled by the relevant * Wrap-arounds of these values are handled by the relevant
* if-conditions. * if-conditions.
*/ */
ca->state = RTT_PROBE; ca->state = RTT_PROBE;
} }
@@ -470,25 +500,26 @@ static void roccet_min_rtt_probe(struct sock *sk, u32 now)
* probe_min_rtt_until wrap-arounds are handled by the time_before32 * probe_min_rtt_until wrap-arounds are handled by the time_before32
* check. * check.
*/ */
if (ca->probe_min_rtt_until == 0) if (!ca->rtt_probe_timers_set)
pr_warn_once("ROCCET: Probing time should be set"); pr_warn_once("ROCCET: Probing time should be set");
else if (time_before32(now, ca->probe_min_rtt_until)) else if (time_before32(now, ca->probe_min_rtt_until))
/* No state change if we are in the probing interval. */ /* No state change if we are in the probing interval. */
return; return;
else if (time_after32(now, ca->refill_until))
/* If the interval has passed we likely just entered the refill /* If the probe_min_rtt_until interval has passed we likely
* interval, so go into RTT_PROBE_REFILL. * just entered the refill interval, so go into
* If we are not in the interval, something went wrong and we should * RTT_PROBE_REFILL. If we are not in the refill_until
* quickly exit the probing phase. * interval, something went wrong and we should quickly exit
* the probing phase.
* *
* Wraps-arounds of refill_until are caught by the time_after32 check. * Wraps-arounds of refill_until are caught by the time_after32
* check.
*/ */
if (time_after32(now, ca->refill_until))
pr_warn_once("ROCCET: Skipped refill interval."); pr_warn_once("ROCCET: Skipped refill interval.");
/* Reset cwnd to refill the pipe and consequently clear the stored /* Reset cwnd to refill the pipe and consequently clear the stored
* window. * window.
* Also perform sanity check. THis should never happen. * Also perform sanity check. This should never happen.
*/ */
if (ca->cwnd_before_min_rtt_probe == 0) if (ca->cwnd_before_min_rtt_probe == 0)
pr_warn_once("ROCCET: cwnd_before_min_rtt_probe is 0 during RTT_PROBE."); pr_warn_once("ROCCET: cwnd_before_min_rtt_probe is 0 during RTT_PROBE.");
@@ -618,14 +649,6 @@ static void bictcp_update(struct roccettcp *ca, u32 cwnd,
} }
} }
/* In case there are any ACKs left over from LAUNCH,
* apply them after the new epoch-reset
*/
if (ca->ack_carry_over) {
ca->ack_cnt += ca->ack_carry_over;
ca->ack_carry_over = 0;
}
/* cubic function - calc */ /* cubic function - calc */
/* calculate c * time^3 / rtt, /* calculate c * time^3 / rtt,
* while considering overflow in calculation of time^3 * while considering overflow in calculation of time^3
@@ -722,15 +745,14 @@ static void roccet_launch_update(struct sock *sk, u32 acked)
/* Halving the cwnd will undo the previous step of slow /* Halving the cwnd will undo the previous step of slow
* start. Which is fine since the pipe is already full. * start. Which is fine since the pipe is already full.
*/ */
tcp_snd_cwnd_set(tp, max(tcp_snd_cwnd(tp) / 2, tcp_snd_cwnd_set(tp, max(tcp_snd_cwnd(tp) / 2, 1));
TCP_INIT_CWND));
} else { } else {
tcp_snd_cwnd_set(tp, max(tcp_snd_cwnd(tp) - tcp_snd_cwnd_set(tp, max(tcp_snd_cwnd(tp) -
(tcp_snd_cwnd(tp) / 3), (tcp_snd_cwnd(tp) / 3), 1));
TCP_INIT_CWND));
} }
tp->snd_ssthresh = tcp_snd_cwnd(tp); tp->snd_ssthresh = tcp_snd_cwnd(tp);
ca->roccet_last_event_time_us = now; ca->roccet_last_event_time_us = now;
ca->last_event_time_set = true;
ca->state = ORBITER; ca->state = ORBITER;
return; return;
} }
@@ -763,7 +785,7 @@ static void roccet_orbiter_update(struct sock *sk, u32 acked)
u32 roccet_xj, jitter, sent, received; u32 roccet_xj, jitter, sent, received;
/* Enter DRAIN when roccet was recently triggered */ /* Enter DRAIN when roccet was recently triggered */
if (ca->roccet_last_event_time_us && if (ca->last_event_time_set &&
time_before32(now, ca->roccet_last_event_time_us + time_before32(now, ca->roccet_last_event_time_us +
100 * USEC_PER_MSEC)) { 100 * USEC_PER_MSEC)) {
ca->state = DRAIN; ca->state = DRAIN;
@@ -850,6 +872,14 @@ static void roccet_orbiter_update(struct sock *sk, u32 acked)
if (!tcp_is_cwnd_limited(sk) || sent_more_than_acked) if (!tcp_is_cwnd_limited(sk) || sent_more_than_acked)
return; return;
/* In case there are any ACKs left over from LAUNCH,
* apply them now.
*/
if (ca->ack_carry_over) {
acked += ca->ack_carry_over;
ca->ack_carry_over = 0;
}
bictcp_update(ca, tcp_snd_cwnd(tp), acked); bictcp_update(ca, tcp_snd_cwnd(tp), acked);
tcp_cong_avoid_ai(tp, max(1, ca->cnt), acked); tcp_cong_avoid_ai(tp, max(1, ca->cnt), acked);
} }
@@ -952,6 +982,7 @@ static void roccet_handle_state_transitions(struct roccettcp *ca,
(ca->state != RTT_PROBE && ca->state != RTT_PROBE_REFILL)) { (ca->state != RTT_PROBE && ca->state != RTT_PROBE_REFILL)) {
ca->probe_min_rtt_until = 0; ca->probe_min_rtt_until = 0;
ca->refill_until = 0; ca->refill_until = 0;
ca->rtt_probe_timers_set = false;
} }
} }
@@ -967,7 +998,7 @@ static void roccet_state(struct sock *sk, u8 new_state)
if (new_state == TCP_CA_Loss) { if (new_state == TCP_CA_Loss) {
roccet_reset(sk, ca); roccet_reset(sk, ca);
tcp_snd_cwnd_set(tp, TCP_INIT_CWND); tcp_snd_cwnd_set(tp, 1);
} else if (new_state == TCP_CA_CWR) { } else if (new_state == TCP_CA_CWR) {
/* Handle CWR as ROCCET congestion event, /* Handle CWR as ROCCET congestion event,
* however afterwards always set Wmax to the current cwnd. * however afterwards always set Wmax to the current cwnd.
@@ -1064,9 +1095,15 @@ static void roccet_drain_update(struct sock *sk, u32 now)
struct tcp_sock *tp = tcp_sk(sk); struct tcp_sock *tp = tcp_sk(sk);
struct roccettcp *ca = inet_csk_ca(sk); struct roccettcp *ca = inet_csk_ca(sk);
if (ca->roccet_last_event_time_us && /* If we are in DRAIN, ca->roccet_last_event_time_us has to be set.
time_after32(now, ca->roccet_last_event_time_us + * If more than 100 ms have passed after a roccet event, exit DRAIN.
100 * USEC_PER_MSEC)) { * The between check is here to handle idle-times and timer-wraps.
* It is ok if we "accidentally" exit DRAIN in such an occasion.
*/
if (!time_between32(now, ca->roccet_last_event_time_us
- 100 * USEC_PER_MSEC,
ca->roccet_last_event_time_us
+ 100 * USEC_PER_MSEC)) {
if (tcp_in_slow_start(tp)) if (tcp_in_slow_start(tp))
ca->state = LAUNCH; ca->state = LAUNCH;
else else
+10 -2
View File
@@ -54,6 +54,10 @@ struct roccettcp {
u32 interval_snd_seq_start; u32 interval_snd_seq_start;
u32 interval_una_seq_start; u32 interval_una_seq_start;
u32 ack_carry_over; /* Used to carry over leftover acks from
* LAUNCH to ORBITER
*/
u32 ack_rate_last_rate_time; /* Timestamp of the last ACK-rate */ u32 ack_rate_last_rate_time; /* Timestamp of the last ACK-rate */
u16 ack_rate_last_rate; /* Last ACK-rate */ u16 ack_rate_last_rate; /* Last ACK-rate */
u16 ack_rate_curr_rate; /* Current ACK-rate */ u16 ack_rate_curr_rate; /* Current ACK-rate */
@@ -69,8 +73,12 @@ struct roccettcp {
bool is_in_initial_launch: 1; /* true if the connection is in bool is_in_initial_launch: 1; /* true if the connection is in
* the initial launch phase. * the initial launch phase.
*/ */
u32 ack_carry_over; /* Used to carry over leftover acks from bool last_event_time_set: 1; /* true if the last event time
* LAUNCH to ORBITER * has been set/initialized.
*/
bool rtt_probe_timers_set: 1; /* true if refill_until and
* probe_min_rtt_until are currently
* set.
*/ */
}; };