Compare commits

..

1 Commits

3 changed files with 28 additions and 10 deletions

View File

@@ -11,10 +11,11 @@ The congestion avoidance phase, called ORBITER, uses
CUBIC's window growth function and adds, based on RTT CUBIC's window growth function and adds, based on RTT
and ACK rate, congestion events. and ACK rate, congestion events.
A peer-reviewed paper on TCP ROCCET will be presented at the WONS 2026 conference. NOTE: A paper for TCP ROCCET is currently under review.
A draft of the paper is available here: Paper draft:
https://arxiv.org/abs/2510.25281 https://arxiv.org/abs/2510.25281
The oldest Linux kernel version we tested with ROCCET is 6.1.
## Setup ## Setup

View File

@@ -129,7 +129,8 @@ static inline void roccettcp_reset(struct roccettcp *ca)
ca->bw_limit.next_check = 0; ca->bw_limit.next_check = 0;
ca->curr_min_rtt_timed.rtt = ~0U; ca->curr_min_rtt_timed.rtt = ~0U;
ca->curr_min_rtt_timed.time = ~0U; ca->curr_min_rtt_timed.time = ~0U;
ca->ece_received = 0; ca->ece_srrtt = 0;
ca->ece_cwnd = 2;
} }
static inline void update_min_rtt(struct sock *sk) static inline void update_min_rtt(struct sock *sk)
@@ -425,6 +426,15 @@ __bpf_kfunc static void roccettcp_cong_avoid(struct sock *sk, u32 ack,
update_min_rtt(sk); update_min_rtt(sk);
update_srrtt(sk); update_srrtt(sk);
/* Reset ECE handling if we already have more bandwidth
* than we received the last ECE.
*/
if(ca->ece_srrtt > 0){
if(tcp_snd_cwnd(tp) >= ca->ece_cwnd){
ca->ece_srrtt = 0;
}
}
/* ROCCET drain. /* ROCCET drain.
* Do not increase the cwnd for 100ms after a roccet congestion event * Do not increase the cwnd for 100ms after a roccet congestion event
*/ */
@@ -492,9 +502,13 @@ __bpf_kfunc static void roccettcp_cong_avoid(struct sock *sk, u32 ack,
if (roccet_xj < sr_rtt_upper_bound) if (roccet_xj < sr_rtt_upper_bound)
roccet_xj = sr_rtt_upper_bound; roccet_xj = sr_rtt_upper_bound;
if (ca->curr_srRTT > roccet_xj && (bw_limit_detect || ca->ece_received)) { /* This is true if we recently received an ECE bit.
if(ca->ece_received) * Therefore we should respect the srRTT at this piont.
ca->ece_received = 0; */
if(ca->ece_srrtt < roccet_xj && ca->ece_srrtt > 0)
roccet_xj = ca->ece_srrtt;
if (ca->curr_srRTT > roccet_xj && (bw_limit_detect || ca->ece_srrtt > 0)) {
ca->epoch_start = 0; ca->epoch_start = 0;
ca->roccet_last_event_time_us = now; ca->roccet_last_event_time_us = now;
ca->cnt = 100 * tcp_snd_cwnd(tp); ca->cnt = 100 * tcp_snd_cwnd(tp);
@@ -585,13 +599,15 @@ __bpf_kfunc static void roccettcp_acked(struct sock *sk,
__bpf_kfunc static void roccet_in_ack_event(struct sock *sk, u32 flags) __bpf_kfunc static void roccet_in_ack_event(struct sock *sk, u32 flags)
{ {
struct tcp_sock *tp = tcp_sk(sk);
struct roccettcp *ca = inet_csk_ca(sk); struct roccettcp *ca = inet_csk_ca(sk);
/* Handle ECE bit. /* Handle ECE bit.
* Pocessing of ECE events is done in roccettcp_cong_avoid() * Pocessing of ECE events is done in roccettcp_cong_avoid()
*/ */
if (flags & CA_ACK_ECE) { if (flags & CA_ACK_ECE) {
ca->ece_received = 1; ca->ece_srrtt = ca->curr_srRTT;
ca->ece_cwnd = tcp_snd_cwnd(tp);
} }
} }

View File

@@ -40,7 +40,8 @@ struct roccettcp {
u32 curr_rtt; /* the minimum rtt of current round */ u32 curr_rtt; /* the minimum rtt of current round */
u32 roccet_last_event_time_us; /* The last time ROCCET was triggered */ u32 roccet_last_event_time_us; /* The last time ROCCET was triggered */
u32 ece_received; /* Set to true if an ECE bit was received */ u32 ece_cwnd; /* The cwnd when a ECE bit was received */
u32 ece_srrtt; /* The srRTT whent the ECE was received */
u32 curr_min_rtt; /* The current observed minRTT */ u32 curr_min_rtt; /* The current observed minRTT */
struct TimedRTT curr_min_rtt_timed; /* The current observed minRTT with struct TimedRTT curr_min_rtt_timed; /* The current observed minRTT with
the timestamp when it was observed */ the timestamp when it was observed */