cc: CUBIC - AIMD approach for tcp friendly window
- Update based on https://github.com/NTAP/rfc8312bis/pull/24
- Fix congestion avoidance test
diff --git a/src/recovery/cubic.rs b/src/recovery/cubic.rs
index 808f58e..6d20952 100644
--- a/src/recovery/cubic.rs
+++ b/src/recovery/cubic.rs
@@ -58,6 +58,10 @@
const C: f64 = 0.4;
+/// Default value of alpha_aimd in the beginning of congestion avoidance.
+// const ALPHA_AIMD: f64 = 3.0 * (1.0 - BETA_CUBIC) / (1.0 + BETA_CUBIC);
+const ALPHA_AIMD: f64 = BETA_CUBIC;
+
/// CUBIC State Variables.
///
/// We need to keep those variables across the connection.
@@ -70,6 +74,10 @@
w_last_max: f64,
+ w_est: f64,
+
+ alpha_aimd: f64,
+
// Used in CUBIC fix (see on_packet_sent())
last_sent_time: Option<Instant>,
@@ -99,14 +107,11 @@
max_datagram_size as f64
}
- // W_est(t) = w_max * beta_cubic + 3 * (1 - beta_cubic) / (1 + beta_cubic) *
- // (t / RTT) (Eq. 4)
- fn w_est(&self, t: Duration, rtt: Duration, max_datagram_size: usize) -> f64 {
- let w_max = self.w_max / max_datagram_size as f64;
- (w_max * BETA_CUBIC +
- 3.0 * (1.0 - BETA_CUBIC) / (1.0 + BETA_CUBIC) * t.as_secs_f64() /
- rtt.as_secs_f64()) *
- max_datagram_size as f64
+ // W_est = W_est + alpha_aimd * (segments_acked / cwnd) (Eq. 4)
+ fn w_est_inc(
+ &self, acked: usize, cwnd: usize, max_datagram_size: usize,
+ ) -> f64 {
+ self.alpha_aimd * (acked as f64 / cwnd as f64) * max_datagram_size as f64
}
}
@@ -211,6 +216,9 @@
if r.cubic_state.w_max == 0.0 {
r.cubic_state.w_max = r.congestion_window as f64;
r.cubic_state.k = 0.0;
+
+ r.cubic_state.w_est = r.congestion_window as f64;
+ r.cubic_state.alpha_aimd = ALPHA_AIMD;
}
} else {
match r.congestion_recovery_start_time {
@@ -223,6 +231,9 @@
r.cubic_state.w_max = r.congestion_window as f64;
r.cubic_state.k = 0.0;
+
+ r.cubic_state.w_est = r.congestion_window as f64;
+ r.cubic_state.alpha_aimd = ALPHA_AIMD;
},
}
}
@@ -236,14 +247,23 @@
let target = f64::max(target, r.congestion_window as f64);
let target = f64::min(target, r.congestion_window as f64 * 1.5);
- // w_est(t)
- let w_est = r.cubic_state.w_est(t, r.min_rtt, r.max_datagram_size);
+ // Update w_est.
+ let w_est_inc = r.cubic_state.w_est_inc(
+ packet.size,
+ r.congestion_window,
+ r.max_datagram_size,
+ );
+ r.cubic_state.w_est += w_est_inc;
let mut cubic_cwnd = r.congestion_window;
- if r.cubic_state.w_cubic(t, r.max_datagram_size) < w_est {
- // TCP friendly region.
- cubic_cwnd = cmp::max(cubic_cwnd, w_est as usize);
+ if r.cubic_state.w_cubic(t, r.max_datagram_size) < r.cubic_state.w_est {
+ // AIMD friendly region (W_cubic(t) < W_est)
+ cubic_cwnd = cmp::max(cubic_cwnd, r.cubic_state.w_est as usize);
+
+ if r.cubic_state.w_est >= r.cubic_state.w_max {
+ r.cubic_state.alpha_aimd = 1.0;
+ }
} else {
// Concave region or convex region use same increment.
let cubic_inc =
@@ -318,6 +338,9 @@
r.cubic_state.cwnd_inc =
(r.cubic_state.cwnd_inc as f64 * BETA_CUBIC) as usize;
+ r.cubic_state.w_est = r.congestion_window as f64;
+ r.cubic_state.alpha_aimd = ALPHA_AIMD;
+
if r.hystart.in_lss(epoch) {
r.hystart.congestion_event();
}
@@ -496,9 +519,7 @@
// During Congestion Avoidance, it will take
// 5 ACKs to increase cwnd by 1 MSS.
- // TODO: However, current W_est(t) is using old RFC one,
- // it grows too fast, so using 3 here.
- for _ in 0..3 {
+ for _ in 0..5 {
let acked = vec![Acked {
pkt_num: 0,
// To exit from recovery