in quic/s2n-quic-transport/src/recovery/manager/tests.rs [311:511]
fn on_ack_frame() {
let space = PacketNumberSpace::ApplicationData;
let mut manager = ServerManager::new(space);
let packet_bytes = 128;
let ecn = ExplicitCongestionNotification::default();
let mut path_manager = helper_generate_path_manager(Duration::from_millis(10));
let mut context = MockContext::new(&mut path_manager);
let mut publisher = Publisher::snapshot();
// Start the pto backoff at 2 so we can tell if it was reset
context.path_mut().pto_backoff = 2;
let time_sent = time::now() + Duration::from_secs(10);
// Send packets 1 to 10
for i in 1..=10 {
manager.on_packet_sent(
space.new_packet_number(VarInt::from_u8(i)),
transmission::Outcome {
ack_elicitation: AckElicitation::Eliciting,
is_congestion_controlled: true,
bytes_sent: packet_bytes,
bytes_progressed: 0,
},
time_sent,
ecn,
transmission::Mode::Normal,
None,
&mut context,
&mut publisher,
);
}
assert_eq!(manager.sent_packets.iter().count(), 10);
// Ack packets 1 to 3
let ack_receive_time = time_sent + Duration::from_millis(500);
ack_packets(
1..=3,
ack_receive_time,
&mut context,
&mut manager,
None,
&mut publisher,
);
assert_eq!(context.path().congestion_controller.lost_bytes, 0);
assert_eq!(context.path().congestion_controller.on_rtt_update, 1);
assert_eq!(context.path().pto_backoff, INITIAL_PTO_BACKOFF);
assert_eq!(manager.sent_packets.iter().count(), 7);
assert_eq!(
manager.largest_acked_packet,
Some(space.new_packet_number(VarInt::from_u8(3)))
);
assert_eq!(context.on_packet_ack_count, 1);
assert_eq!(context.on_new_packet_ack_count, 1);
assert_eq!(context.validate_packet_ack_count, 1);
assert_eq!(context.on_packet_loss_count, 0);
assert_eq!(
context.path().rtt_estimator.latest_rtt(),
Duration::from_millis(500)
);
assert_eq!(1, context.on_rtt_update_count);
assert_eq!(0, context.on_mtu_update_count);
// Reset the pto backoff to 2 so we can tell if it was reset
context.path_mut().pto_backoff = 2;
// Acknowledging already acked packets
let ack_receive_time = ack_receive_time + Duration::from_secs(1);
ack_packets(
1..=3,
ack_receive_time,
&mut context,
&mut manager,
None,
&mut publisher,
);
//= https://www.rfc-editor.org/rfc/rfc9002#section-5.1
//= type=test
//# An RTT sample MUST NOT be generated on receiving an ACK frame that
//# does not newly acknowledge at least one ack-eliciting packet.
// Acknowledging already acked packets does not call on_new_packet_ack or change RTT
assert_eq!(context.path().congestion_controller.lost_bytes, 0);
assert_eq!(context.path().congestion_controller.on_rtt_update, 1);
assert_eq!(context.path().pto_backoff, 2);
assert_eq!(context.on_packet_ack_count, 2);
assert_eq!(context.on_new_packet_ack_count, 1);
assert_eq!(context.validate_packet_ack_count, 2);
assert_eq!(context.on_packet_loss_count, 0);
assert_eq!(
context.path().rtt_estimator.latest_rtt(),
Duration::from_millis(500)
);
assert_eq!(1, context.on_rtt_update_count);
assert_eq!(0, context.on_mtu_update_count);
// Ack packets 7 to 9 (4 - 6 will be considered lost)
let ack_receive_time = ack_receive_time + Duration::from_secs(1);
ack_packets(
7..=9,
ack_receive_time,
&mut context,
&mut manager,
None,
&mut publisher,
);
assert_eq!(
context.path().congestion_controller.lost_bytes,
(packet_bytes * 3) as u32
);
assert_eq!(context.path().pto_backoff, INITIAL_PTO_BACKOFF);
assert_eq!(context.on_packet_ack_count, 3);
assert_eq!(context.on_new_packet_ack_count, 2);
assert_eq!(context.validate_packet_ack_count, 3);
assert_eq!(context.on_packet_loss_count, 3);
assert_eq!(
context.path().rtt_estimator.latest_rtt(),
Duration::from_millis(2500)
);
assert_eq!(2, context.on_rtt_update_count);
assert_eq!(0, context.on_mtu_update_count);
// Ack packet 10, but with a path that is not peer validated
let path_id = unsafe { path::Id::new(0) };
context.path_manager[path_id] = Path::new(
Default::default(),
connection::PeerId::TEST_ID,
connection::LocalId::TEST_ID,
context.path().rtt_estimator,
MockCongestionController::default(),
false,
mtu::Config::default(),
ANTI_AMPLIFICATION_MULTIPLIER,
);
context.path_manager.activate_path_for_test(path_id);
context.path_mut().pto_backoff = 2;
let ack_receive_time = ack_receive_time + Duration::from_millis(500);
ack_packets(
10..=10,
ack_receive_time,
&mut context,
&mut manager,
None,
&mut publisher,
);
assert_eq!(context.path().congestion_controller.on_rtt_update, 1);
assert_eq!(context.path().pto_backoff, 2);
assert_eq!(context.on_packet_ack_count, 4);
assert_eq!(context.on_new_packet_ack_count, 3);
assert_eq!(context.validate_packet_ack_count, 4);
assert_eq!(context.on_packet_loss_count, 3);
assert_eq!(
context.path().rtt_estimator.latest_rtt(),
Duration::from_millis(3000)
);
assert_eq!(3, context.on_rtt_update_count);
assert_eq!(0, context.on_mtu_update_count);
// Send and ack a non ack eliciting packet
manager.on_packet_sent(
space.new_packet_number(VarInt::from_u8(11)),
transmission::Outcome {
ack_elicitation: AckElicitation::NonEliciting,
is_congestion_controlled: true,
bytes_sent: packet_bytes,
bytes_progressed: 0,
},
time_sent,
ecn,
transmission::Mode::Normal,
None,
&mut context,
&mut publisher,
);
ack_packets(
11..=11,
ack_receive_time,
&mut context,
&mut manager,
None,
&mut publisher,
);
assert_eq!(context.path().congestion_controller.lost_bytes, 0);
assert_eq!(context.path().congestion_controller.on_rtt_update, 1);
assert_eq!(context.on_packet_ack_count, 5);
assert_eq!(context.on_new_packet_ack_count, 4);
assert_eq!(context.validate_packet_ack_count, 5);
assert_eq!(context.on_packet_loss_count, 3);
// RTT remains unchanged
assert_eq!(
context.path().rtt_estimator.latest_rtt(),
Duration::from_millis(3000)
);
assert_eq!(3, context.on_rtt_update_count);
assert_eq!(0, context.on_mtu_update_count);
}