in quic/s2n-quic-transport/src/recovery/manager.rs [622:731]
fn process_new_acked_packets<Ctx: Context<Config>, Pub: event::ConnectionPublisher>(
&mut self,
newly_acked_packets: &SmallVec<
[PacketDetails<packet_info_type!()>; ACKED_PACKETS_INITIAL_CAPACITY],
>,
new_largest_packet: bool,
timestamp: Timestamp,
ecn_counts: Option<EcnCounts>,
random_generator: &mut Config::RandomGenerator,
context: &mut Ctx,
publisher: &mut Pub,
) {
//= https://www.rfc-editor.org/rfc/rfc9002#section-6.1.2
//# Once a later packet within the same packet number space has been
//# acknowledged, an endpoint SHOULD declare an earlier packet lost if it
//# was sent a threshold amount of time in the past.
self.detect_and_remove_lost_packets(timestamp, random_generator, context, publisher);
let current_path_id = context.path_id();
let is_handshake_confirmed = context.is_handshake_confirmed();
let mut current_path_acked_bytes = 0;
let mut current_path_largest_newly_acked = None;
let mut newly_acked_ecn_counts = EcnCounts::default();
for (packet_number, acked_packet_info) in newly_acked_packets {
let path = context.path_mut_by_id(acked_packet_info.path_id);
let sent_bytes = acked_packet_info.sent_bytes as usize;
newly_acked_ecn_counts.increment(acked_packet_info.ecn);
if acked_packet_info.path_id == current_path_id {
current_path_acked_bytes += sent_bytes;
if current_path_largest_newly_acked.map_or(true, |(pn, _)| packet_number > pn) {
current_path_largest_newly_acked = Some((packet_number, acked_packet_info));
}
} else if sent_bytes > 0 {
path.congestion_controller.on_ack(
acked_packet_info.time_sent,
sent_bytes,
acked_packet_info.cc_packet_info,
&path.rtt_estimator,
random_generator,
timestamp,
&mut congestion_controller::PathPublisher::new(
publisher,
acked_packet_info.path_id,
),
);
}
//= https://www.rfc-editor.org/rfc/rfc9002#section-6.2.1
//# The PTO backoff factor is reset when an acknowledgment is received,
//# except in the following case. A server might take longer to respond
//# to packets during the handshake than otherwise. To protect such a
//# server from repeated client probes, the PTO backoff is not reset at a
//# client that is not yet certain that the server has finished
//# validating the client's address. That is, a client does not reset
//# the PTO backoff factor on receiving acknowledgments in Initial
//# packets.
if path.is_peer_validated() {
path.reset_pto_backoff();
}
}
//= https://www.rfc-editor.org/rfc/rfc9002#section-6.2.1
//# A sender SHOULD restart its PTO timer every time an ack-eliciting
//# packet is sent or acknowledged,
// The pseudocode in https://www.rfc-editor.org/rfc/rfc9002.html#section-a.7 does
// not distinguish between ack-eliciting packets for determining if the PTO timer should
// be restarted. This behavior is preferred, as detect_and_remove_lost_packets() will
// cancel the loss timer, and there may still be ack eliciting packets pending that
// require a PTO timer for recovery.
self.update_pto_timer(context.active_path(), timestamp, is_handshake_confirmed);
debug_assert!(
!newly_acked_packets.is_empty(),
"this method assumes there was at least one newly-acked packet"
);
//= https://www.rfc-editor.org/rfc/rfc9000#section-13.4.2.1
//# Validating ECN counts from reordered ACK frames can result in failure.
//# An endpoint MUST NOT fail ECN validation as a result of processing an
//# ACK frame that does not increase the largest acknowledged packet number.
if new_largest_packet {
self.process_ecn(
newly_acked_ecn_counts,
ecn_counts,
timestamp,
context,
publisher,
);
}
if current_path_acked_bytes > 0 {
let (_, largest_newly_acked) = current_path_largest_newly_acked
.expect("At least some bytes were acknowledged on the current path");
let path = context.path_mut();
path.congestion_controller.on_ack(
largest_newly_acked.time_sent,
current_path_acked_bytes,
largest_newly_acked.cc_packet_info,
&path.rtt_estimator,
random_generator,
timestamp,
&mut congestion_controller::PathPublisher::new(publisher, current_path_id),
);
}
}