diff --git a/draft-ietf-quic-recovery.md b/draft-ietf-quic-recovery.md index 792ed16741..cb5861ce8c 100644 --- a/draft-ietf-quic-recovery.md +++ b/draft-ietf-quic-recovery.md @@ -1504,6 +1504,13 @@ ssthresh: the mode is slow start and the window grows by the number of bytes acknowledged. +first_rtt_sample: +: The time that the first RTT sample was obtained. + +pc_lost: +: Lost packets from all packet number spaces that are used in determining + persistent congestion. + ## Initialization @@ -1515,6 +1522,7 @@ congestion_window = kInitialWindow bytes_in_flight = 0 congestion_recovery_start_time = 0 ssthresh = infinite +first_rtt_sample = 0 for pn_space in [ Initial, Handshake, ApplicationData ]: ecn_ce_counters[pn_space] = 0 ~~~ @@ -1541,19 +1549,25 @@ InCongestionRecovery(sent_time): return sent_time <= congestion_recovery_start_time OnPacketsAcked(acked_packets): + if (first_rtt_sample == 0): + first_rtt_sample = now() + for acked_packet in acked_packets: OnPacketAcked(acked_packet) OnPacketAcked(acked_packet): // Remove from bytes_in_flight. bytes_in_flight -= acked_packet.sent_bytes + // Do not increase congestion_window if application // limited or flow control limited. if (IsAppOrFlowControlLimited()) return + // Do not increase congestion window in recovery period. if (InCongestionRecovery(acked_packet.time_sent)): return + if (congestion_window < ssthresh): // Slow start. congestion_window += acked_packet.sent_bytes @@ -1605,26 +1619,37 @@ ProcessECN(ack, pn_space): Invoked when DetectAndRemoveLostPackets deems packets lost. ~~~ -InPersistentCongestion(largest_lost): - // Persistent congestion cannot be declared on the - // first RTT sample. - if (is first RTT sample): - return false +InPersistentCongestion(lost_packets): + // Consider lost packets across all packet number spaces. + pc_lost.append(lost_packets) + + // Disregard packets sent prior to getting an RTT sample. + assert(first_rtt_sample != 0) + for lost in pc_lost: + if lost.time_sent <= first_rtt_sample: + pc_lost.remove(lost) + + // Find the duration of the largest contiguous set of lost + // packets that starts and ends with an ack-eliciting packet. + // Note: Indexing pc_lost by time_sent rather than packet + // number might simplify implementation. + pc_duration = FindLargestLossPeriod(pc_lost) + + // Declare persistent congestion if these packets span + // a period longer than the persistent congestion period. pto = smoothed_rtt + max(4 * rttvar, kGranularity) + max_ack_delay - congestion_period = pto * kPersistentCongestionThreshold - // Determine if all packets in the time period before the - // largest newly lost packet, including the edges and - // across all packet number spaces, are marked lost. - return AreAllPacketsLost(largest_lost, congestion_period) + return pc_duration > pto * kPersistentCongestionThreshold OnPacketsLost(lost_packets): // Remove lost packets from bytes_in_flight. for lost_packet in lost_packets: bytes_in_flight -= lost_packet.sent_bytes OnCongestionEvent(lost_packets.largest().time_sent) - // Collapse congestion window if persistent congestion - if (InPersistentCongestion(lost_packets.largest())): + + // Collapse congestion window on persistent congestion. + if (InPersistentCongestion(lost_packets)): + pc_lost.clear() congestion_window = kMinimumWindow ~~~