From c35e61a9e3a48dfd9f5b522cf711704eec8fab71 Mon Sep 17 00:00:00 2001 From: Benjamin Saunders Date: Tue, 2 Nov 2021 19:11:34 -0700 Subject: [PATCH] Don't enter persistent congestion without an RTT sample MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RFC 9002 ยง7.6.2: [..] a prior RTT sample existed when these two packets were sent. --- quinn-proto/src/connection/mod.rs | 11 ++++++++++- quinn-proto/src/connection/paths.rs | 8 +++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/quinn-proto/src/connection/mod.rs b/quinn-proto/src/connection/mod.rs index 8e448c938..6b0e92956 100644 --- a/quinn-proto/src/connection/mod.rs +++ b/quinn-proto/src/connection/mod.rs @@ -1159,6 +1159,10 @@ impl Connection { }; let rtt = instant_saturating_sub(now, self.spaces[space].largest_acked_packet_sent); self.path.rtt.update(ack_delay, rtt); + if self.path.first_packet_after_rtt_sample.is_none() { + self.path.first_packet_after_rtt_sample = + Some((space, self.spaces[space].next_packet_number)); + } } // Must be called before crypto/pto_count are clobbered @@ -1338,7 +1342,12 @@ impl Connection { Some(start) if info.time_sent - start > congestion_period => { in_persistent_congestion = true; } - None => { + // Persistent congestion must start after the first RTT sample + None if self + .path + .first_packet_after_rtt_sample + .map_or(false, |x| x < (pn_space, packet)) => + { persistent_congestion_start = Some(info.time_sent); } _ => {} diff --git a/quinn-proto/src/connection/paths.rs b/quinn-proto/src/connection/paths.rs index 42891ef31..bb32ff418 100644 --- a/quinn-proto/src/connection/paths.rs +++ b/quinn-proto/src/connection/paths.rs @@ -1,7 +1,7 @@ use std::{cmp, net::SocketAddr, time::Duration, time::Instant}; use super::pacing::Pacer; -use crate::{congestion, INITIAL_MAX_UDP_PAYLOAD_SIZE, TIMER_GRANULARITY}; +use crate::{congestion, packet::SpaceId, INITIAL_MAX_UDP_PAYLOAD_SIZE, TIMER_GRANULARITY}; /// Description of a particular network path pub struct PathData { @@ -25,6 +25,10 @@ pub struct PathData { /// Total size of all UDP datagrams received on this path pub total_recvd: u64, pub max_udp_payload_size: u16, + /// Packet number of the first packet sent after an RTT sample was collected on this path + /// + /// Used in persistent congestion determination. + pub first_packet_after_rtt_sample: Option<(SpaceId, u64)>, } impl PathData { @@ -52,6 +56,7 @@ impl PathData { total_sent: 0, total_recvd: 0, max_udp_payload_size: INITIAL_MAX_UDP_PAYLOAD_SIZE, + first_packet_after_rtt_sample: None, } } @@ -75,6 +80,7 @@ impl PathData { total_sent: 0, total_recvd: 0, max_udp_payload_size: prev.max_udp_payload_size, + first_packet_after_rtt_sample: prev.first_packet_after_rtt_sample, } }