Skip to content

Commit 694e1d4

Browse files
committed
congestion: saturate CUBIC window increment to avoid overflow
1 parent c8ad7e6 commit 694e1d4

2 files changed

Lines changed: 24 additions & 2 deletions

File tree

quinn-proto/src/congestion/cubic.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,9 @@ impl Controller for Cubic {
146146
let cubic_inc =
147147
(w_cubic - cubic_cwnd as f64) / cubic_cwnd as f64 * self.current_mtu as f64;
148148

149-
cubic_cwnd += cubic_inc as u64;
149+
// w_cubic grows cubically with the time since the last congestion
150+
// event and can exceed `u64::MAX` after a long lossless period.
151+
cubic_cwnd = cubic_cwnd.saturating_add(cubic_inc as u64);
150152
}
151153

152154
// Update the increment and increase cwnd by MSS.
@@ -296,4 +298,24 @@ mod tests {
296298
assert_eq!(cubic.ssthresh, (window as f64 * BETA_CUBIC) as u64);
297299
assert_eq!(cubic.window, cubic.ssthresh);
298300
}
301+
302+
#[test]
303+
fn congestion_avoidance_does_not_overflow_after_long_lossless_period() {
304+
let now = Instant::now();
305+
let rtt = RttEstimator::new(Duration::from_millis(100));
306+
let config = Arc::new(CubicConfig::default());
307+
let mut cubic = Cubic::new(config, now, BASE_DATAGRAM_SIZE as u16);
308+
309+
// Put CUBIC directly into congestion avoidance.
310+
cubic.ssthresh = cubic.window;
311+
cubic.recovery_start_time = Some(now);
312+
let window = cubic.window;
313+
314+
// After ten days without a congestion event, w_cubic exceeds u64::MAX.
315+
// Before this fix, computing the window increment overflowed.
316+
let later = now + Duration::from_secs(10 * 24 * 60 * 60);
317+
cubic.on_ack(later, later, BASE_DATAGRAM_SIZE, false, &rtt);
318+
319+
assert_eq!(cubic.window, window + BASE_DATAGRAM_SIZE);
320+
}
299321
}

quinn-proto/src/connection/paths.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ pub struct RttEstimator {
294294
}
295295

296296
impl RttEstimator {
297-
fn new(initial_rtt: Duration) -> Self {
297+
pub(crate) fn new(initial_rtt: Duration) -> Self {
298298
Self {
299299
latest: initial_rtt,
300300
smoothed: None,

0 commit comments

Comments
 (0)