in quic/s2n-quic-core/src/recovery/hybrid_slow_start.rs [389:554]
fn on_rtt_update_with_hystartplus_1() {
let mut slow_start = HybridSlowStart::new(10);
// use hystart++
slow_start.use_hystart_plus_plus = true;
assert_eq!(slow_start.sample_count, 0);
let time_zero = NoopClock.get_time() + Duration::from_secs(10);
// -- Round 1 --
// t=0-9: Send packet #1-10
let time_of_last_sent_packet = time_zero + Duration::from_millis(9);
// t=10: Acknowledge packets #1-7 all with RTT 200
for i in 0..=6 {
slow_start.on_rtt_update(
1000.0,
time_zero + Duration::from_millis(i),
time_of_last_sent_packet,
Duration::from_millis(200),
);
assert_eq!(slow_start.cur_min_rtt, Some(Duration::from_millis(200)));
}
// This round will end when packet #10 is acknowledged
assert_eq!(
slow_start.rtt_round_end_time,
Some(time_of_last_sent_packet)
);
// t=11: Acknowledge packet #8 with RTT 100
slow_start.on_rtt_update(
1000.0,
time_zero + Duration::from_millis(7),
time_of_last_sent_packet,
Duration::from_millis(100),
);
// The current minimum should now be 100
assert_eq!(slow_start.cur_min_rtt, Some(Duration::from_millis(100)));
// t=11: Acknowledge packet #9 with RTT 50
slow_start.on_rtt_update(
1000.0,
time_zero + Duration::from_millis(8),
time_of_last_sent_packet,
Duration::from_millis(50),
);
// The current minimum is still 100 because we've already collected N_SAMPLING samples
assert_eq!(slow_start.cur_min_rtt, Some(Duration::from_millis(100)));
// -- Round 2 --
// t=20-29: Send packet #11-20
let time_of_last_sent_packet = time_zero + Duration::from_millis(29);
// t=30: Acknowledge packet #10 with RTT 400, ending the first round and starting the second
slow_start.on_rtt_update(
1000.0,
time_zero + Duration::from_millis(9),
time_of_last_sent_packet,
Duration::from_millis(400),
);
// The last minimum is saved in last_min_rtt
assert_eq!(slow_start.last_min_rtt, Some(Duration::from_millis(100)));
// The current minimum is now 400 because we've started a new round
assert_eq!(slow_start.cur_min_rtt, Some(Duration::from_millis(400)));
// This round will end when packet #20 is acknowledged
assert_eq!(
slow_start.rtt_round_end_time,
Some(time_of_last_sent_packet)
);
// t=31: Acknowledge packets #11-16 all with RTT 500
for i in 20..=25 {
slow_start.on_rtt_update(
1000.0,
time_zero + Duration::from_millis(i),
time_of_last_sent_packet,
Duration::from_millis(500),
);
assert_eq!(slow_start.cur_min_rtt, Some(Duration::from_millis(400)));
}
// t=32: Acknowledge packet #17, the 8th sample in Round 2
slow_start.on_rtt_update(
2000.0,
time_zero + Duration::from_millis(27),
time_of_last_sent_packet,
Duration::from_millis(112),
);
assert_eq!(slow_start.last_min_rtt, Some(Duration::from_millis(100)));
assert_eq!(slow_start.cur_min_rtt, Some(Duration::from_millis(112)));
// The last ack was the 8th sample, but since the min rtt increased below the threshold,
// the slow start threshold remains the same
assert_delta!(slow_start.threshold, f32::MAX, 0.001);
// -- Round 3 --
// t=40-49: Send packet #21-30
let time_of_last_sent_packet = time_zero + Duration::from_millis(49);
// t=50: Acknowledge packets 21-27
for i in 40..=46 {
slow_start.on_rtt_update(
1000.0,
time_zero + Duration::from_millis(i),
time_of_last_sent_packet,
Duration::from_millis(500),
);
assert_eq!(slow_start.cur_min_rtt, Some(Duration::from_millis(500)));
}
// t=51: Acknowledge packet 28, the 8th sample in Round 3
slow_start.on_rtt_update(
5000.0,
time_zero + Duration::from_millis(38),
time_of_last_sent_packet,
Duration::from_millis(126),
);
assert_eq!(slow_start.last_min_rtt, Some(Duration::from_millis(112)));
assert_eq!(slow_start.cur_min_rtt, Some(Duration::from_millis(126)));
// The last ack was the 8th sample, and since the min rtt increased above the threshold,
// the slow start cssthreshold was set to the current congestion window
// Also, cssbaseline is cur_min_rtt and ss_growth_divisor is 4.0
assert_delta!(slow_start.css_threshold, 5000.0, 0.001);
assert_eq!(slow_start.css_baseline_min_rtt, Duration::from_millis(126));
assert_delta!(slow_start.ss_growth_divisor, 4.0, 0.001);
// -- Round 4 --
// t=50-59: Send packet #31-40
// first round for CSS
let time_of_last_sent_packet = time_zero + Duration::from_millis(69);
// t=60: Acknowledge packets 31-37
for i in 60..=66 {
slow_start.on_rtt_update(
1000.0,
time_zero + Duration::from_millis(i),
time_of_last_sent_packet,
Duration::from_millis(500),
);
assert_eq!(slow_start.cur_min_rtt, Some(Duration::from_millis(500)));
}
// t=51: Acknowledge packet 38, the 8th sample in Round 4
slow_start.on_rtt_update(
5000.0,
time_zero + Duration::from_millis(38),
time_of_last_sent_packet,
Duration::from_millis(130),
);
let cwnd_increment = slow_start.cwnd_increment(1000);
assert_delta!(cwnd_increment, 250.0, 0.001);
assert_eq!(slow_start.last_min_rtt, Some(Duration::from_millis(126)));
assert_eq!(slow_start.css_baseline_min_rtt, Duration::from_millis(126));
assert_eq!(slow_start.cur_min_rtt, Some(Duration::from_millis(130)));
// because the cur_min_rtt is bigger than css_baseline_min_rtt, CSS phase should continue
assert_eq!(slow_start.css_count, 1);
}