<?xml version="1.0" encoding="UTF-8"?>
  <?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
  <!-- generated by https://github.com/cabo/kramdown-rfc2629 version 1.2.10 -->

<!DOCTYPE rfc SYSTEM "rfc2629.dtd" [
]>

<?rfc toc="yes"?>
<?rfc sortrefs="yes"?>
<?rfc symrefs="yes"?>
<?rfc docmapping="yes"?>

<rfc ipr="trust200902" docName="draft-ietf-quic-recovery-19" category="std">

  <front>
    <title abbrev="QUIC Loss Detection">QUIC Loss Detection and Congestion Control</title>

    <author initials="J." surname="Iyengar" fullname="Jana Iyengar" role="editor">
      <organization>Fastly</organization>
      <address>
        <email>jri.ietf@gmail.com</email>
      </address>
    </author>
    <author initials="I." surname="Swett" fullname="Ian Swett" role="editor">
      <organization>Google</organization>
      <address>
        <email>ianswett@google.com</email>
      </address>
    </author>

    <date year="2019" month="March" day="11"/>

    <area>Transport</area>
    <workgroup>QUIC</workgroup>
    

    <abstract>


<t>This document describes loss detection and congestion control mechanisms for
QUIC.</t>



    </abstract>


    <note title="Note to Readers">


<t>Discussion of this draft takes place on the QUIC working group mailing list
(quic@ietf.org), which is archived at
<eref target="https://mailarchive.ietf.org/arch/search/?email_list=quic">https://mailarchive.ietf.org/arch/search/?email_list=quic</eref>.</t>

<t>Working Group information can be found at <eref target="https://github.com/quicwg">https://github.com/quicwg</eref>; source
code and issues list for this draft can be found at
<eref target="https://github.com/quicwg/base-drafts/labels/-recovery">https://github.com/quicwg/base-drafts/labels/-recovery</eref>.</t>


    </note>


  </front>

  <middle>


<section anchor="introduction" title="Introduction">

<t>QUIC is a new multiplexed and secure transport atop UDP.  QUIC builds on decades
of transport and security experience, and implements mechanisms that make it
attractive as a modern general-purpose transport.  The QUIC protocol is
described in <xref target="QUIC-TRANSPORT"/>.</t>

<t>QUIC implements the spirit of existing TCP loss recovery mechanisms, described
in RFCs, various Internet-drafts, and also those prevalent in the Linux TCP
implementation.  This document describes QUIC congestion control and loss
recovery, and where applicable, attributes the TCP equivalent in RFCs,
Internet-drafts, academic papers, and/or TCP implementations.</t>

</section>
<section anchor="conventions-and-definitions" title="Conventions and Definitions">

<t>The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”,
“SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this
document are to be interpreted as described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/>
when, and only when, they appear in all capitals, as shown here.</t>

<t>Definitions of terms that are used in this document:</t>

<t><list style="hanging">
  <t hangText='ACK-only:'>
  Any packet containing only one or more ACK frame(s).</t>
  <t hangText='In-flight:'>
  Packets are considered in-flight when they have been sent
and neither acknowledged nor declared lost, and they are not
ACK-only.</t>
  <t hangText='Ack-eliciting Frames:'>
  All frames besides ACK or PADDING are considered ack-eliciting.</t>
  <t hangText='Ack-eliciting Packets:'>
  Packets that contain ack-eliciting frames elicit an ACK from the receiver
within the maximum ack delay and are called ack-eliciting packets.</t>
  <t hangText='Crypto Packets:'>
  Packets containing CRYPTO data sent in Initial or Handshake
packets.</t>
  <t hangText='Out-of-order Packets:'>
  Packets that do not increase the largest received packet number for its
packet number space by exactly one. Packets arrive out of order
when earlier packets are lost or delayed.</t>
</list></t>

</section>
<section anchor="design-of-the-quic-transmission-machinery" title="Design of the QUIC Transmission Machinery">

<t>All transmissions in QUIC are sent with a packet-level header, which indicates
the encryption level and includes a packet sequence number (referred to below as
a packet number).  The encryption level indicates the packet number space, as
described in <xref target="QUIC-TRANSPORT"/>.  Packet numbers never repeat within a packet
number space for the lifetime of a connection.  Packet numbers monotonically
increase within a space, preventing ambiguity.</t>

<t>This design obviates the need for disambiguating between transmissions and
retransmissions and eliminates significant complexity from QUIC’s interpretation
of TCP loss detection mechanisms.</t>

<t>QUIC packets can contain multiple frames of different types. The recovery
mechanisms ensure that data and frames that need reliable delivery are
acknowledged or declared lost and sent in new packets as necessary. The types
of frames contained in a packet affect recovery and congestion control logic:</t>

<t><list style="symbols">
  <t>All packets are acknowledged, though packets that contain no
ack-eliciting frames are only acknowledged along with ack-eliciting
packets.</t>
  <t>Long header packets that contain CRYPTO frames are critical to the
performance of the QUIC handshake and use shorter timers for
acknowledgement and retransmission.</t>
  <t>Packets that contain only ACK frames do not count toward congestion control
limits and are not considered in-flight.</t>
  <t>PADDING frames cause packets to contribute toward bytes in flight without
directly causing an acknowledgment to be sent.</t>
</list></t>

<section anchor="relevant-differences-between-quic-and-tcp" title="Relevant Differences Between QUIC and TCP">

<t>Readers familiar with TCP’s loss detection and congestion control will find
algorithms here that parallel well-known TCP ones. Protocol differences between
QUIC and TCP however contribute to algorithmic differences. We briefly describe
these protocol differences below.</t>

<section anchor="separate-packet-number-spaces" title="Separate Packet Number Spaces">

<t>QUIC uses separate packet number spaces for each encryption level, except 0-RTT
and all generations of 1-RTT keys use the same packet number space.  Separate
packet number spaces ensures acknowledgement of packets sent with one level of
encryption will not cause spurious retransmission of packets sent with a
different encryption level.  Congestion control and round-trip time (RTT)
measurement are unified across packet number spaces.</t>

</section>
<section anchor="monotonically-increasing-packet-numbers" title="Monotonically Increasing Packet Numbers">

<t>TCP conflates transmission order at the sender with delivery order at the
receiver, which results in retransmissions of the same data carrying the same
sequence number, and consequently leads to “retransmission ambiguity”.  QUIC
separates the two: QUIC uses a packet number to indicate transmission order,
and any application data is sent in one or more streams, with delivery order
determined by stream offsets encoded within STREAM frames.</t>

<t>QUIC’s packet number is strictly increasing within a packet number space,
and directly encodes transmission order.  A higher packet number signifies
that the packet was sent later, and a lower packet number signifies that
the packet was sent earlier.  When a packet containing ack-eliciting
frames is detected lost, QUIC rebundles necessary frames in a new packet
with a new packet number, removing ambiguity about which packet is
acknowledged when an ACK is received.  Consequently, more accurate RTT
measurements can be made, spurious retransmissions are trivially detected, and
mechanisms such as Fast Retransmit can be applied universally, based only on
packet number.</t>

<t>This design point significantly simplifies loss detection mechanisms for QUIC.
Most TCP mechanisms implicitly attempt to infer transmission ordering based on
TCP sequence numbers - a non-trivial task, especially when TCP timestamps are
not available.</t>

</section>
<section anchor="no-reneging" title="No Reneging">

<t>QUIC ACKs contain information that is similar to TCP SACK, but QUIC does not
allow any acked packet to be reneged, greatly simplifying implementations on
both sides and reducing memory pressure on the sender.</t>

</section>
<section anchor="more-ack-ranges" title="More ACK Ranges">

<t>QUIC supports many ACK ranges, opposed to TCP’s 3 SACK ranges.  In high loss
environments, this speeds recovery, reduces spurious retransmits, and ensures
forward progress without relying on timeouts.</t>

</section>
<section anchor="explicit-correction-for-delayed-acks" title="Explicit Correction For Delayed ACKs">

<t>QUIC ACKs explicitly encode the delay incurred at the receiver between when a
packet is received and when the corresponding ACK is sent.  This allows the
receiver of the ACK to adjust for receiver delays, specifically the delayed ack
timer, when estimating the path RTT.  This mechanism also allows a receiver to
measure and report the delay from when a packet was received by the OS kernel,
which is useful in receivers which may incur delays such as context-switch
latency before a userspace QUIC receiver processes a received packet.</t>

</section>
</section>
</section>
<section anchor="generating-acknowledgements" title="Generating Acknowledgements">

<t>QUIC SHOULD delay sending acknowledgements in response to packets, but MUST NOT
excessively delay acknowledgements of ack-eliciting packets. Specifically,
implementations MUST attempt to enforce a maximum ack delay to avoid causing
the peer spurious timeouts.  The maximum ack delay is communicated in the
<spanx style="verb">max_ack_delay</spanx> transport parameter and the default value is 25ms.</t>

<t>An acknowledgement SHOULD be sent immediately upon receipt of a second
ack-eliciting packet. QUIC recovery algorithms do not assume the peer sends
an ACK immediately when receiving a second ack-eliciting packet.</t>

<t>In order to accelerate loss recovery and reduce timeouts, the receiver SHOULD
send an immediate ACK after it receives an out-of-order packet. It could send
immediate ACKs for in-order packets for a period of time that SHOULD NOT exceed
1/8 RTT unless more out-of-order packets arrive. If every packet arrives out-of-
order, then an immediate ACK SHOULD be sent for every received packet.</t>

<t>Similarly, packets marked with the ECN Congestion Experienced (CE) codepoint in
the IP header SHOULD be acknowledged immediately, to reduce the peer’s response
time to congestion events.</t>

<t>As an optimization, a receiver MAY process multiple packets before sending any
ACK frames in response.  In this case the receiver can determine whether an
immediate or delayed acknowledgement should be generated after processing
incoming packets.</t>

<section anchor="crypto-handshake-data" title="Crypto Handshake Data">

<t>In order to quickly complete the handshake and avoid spurious retransmissions
due to crypto retransmission timeouts, crypto packets SHOULD use a very short
ack delay, such as the local timer granularity.  ACK frames MAY be sent
immediately when the crypto stack indicates all data for that packet number
space has been received.</t>

</section>
<section anchor="ack-ranges" title="ACK Ranges">

<t>When an ACK frame is sent, one or more ranges of acknowledged packets are
included.  Including older packets reduces the chance of spurious retransmits
caused by losing previously sent ACK frames, at the cost of larger ACK frames.</t>

<t>ACK frames SHOULD always acknowledge the most recently received packets, and the
more out-of-order the packets are, the more important it is to send an updated
ACK frame quickly, to prevent the peer from declaring a packet as lost and
spuriously retransmitting the frames it contains.</t>

<t>Below is one recommended approach for determining what packets to include in an
ACK frame.</t>

</section>
<section anchor="receiver-tracking-of-ack-frames" title="Receiver Tracking of ACK Frames">

<t>When a packet containing an ACK frame is sent, the largest acknowledged in that
frame may be saved.  When a packet containing an ACK frame is acknowledged, the
receiver can stop acknowledging packets less than or equal to the largest
acknowledged in the sent ACK frame.</t>

<t>In cases without ACK frame loss, this algorithm allows for a minimum of 1 RTT
of reordering. In cases with ACK frame loss and reordering, this approach does
not guarantee that every acknowledgement is seen by the sender before it is no
longer included in the ACK frame. Packets could be received out of order and
all subsequent ACK frames containing them could be lost. In this case, the
loss recovery algorithm may cause spurious retransmits, but the sender will
continue making forward progress.</t>

</section>
</section>
<section anchor="computing-the-rtt-estimate" title="Computing the RTT estimate">

<t>Round-trip time (RTT) is calculated when an ACK frame arrives by
computing the difference between the current time and the time the largest
acked packet was sent.  An RTT sample MUST NOT be taken for a packet that
is not newly acknowledged or not ack-eliciting.</t>

<t>When RTT is calculated, the ack delay field from the ACK frame SHOULD be limited
to the max_ack_delay specified by the peer.  Limiting ack_delay to max_ack_delay
ensures a peer specifying an extremely small max_ack_delay doesn’t cause more
spurious timeouts than a peer that correctly specifies max_ack_delay. It SHOULD
be subtracted from the RTT as long as the result is larger than the min_rtt.
If the result is smaller than the min_rtt, the RTT should be used, but the
ack delay field should be ignored.</t>

<t>A sender calculates both smoothed RTT (SRTT) and RTT variance (RTTVAR) similar
to those specified in <xref target="RFC6298"/>, see <xref target="on-ack-received"/>.</t>

<t>A sender takes an RTT sample when an ACK frame is received that acknowledges a
larger packet number than before (see <xref target="on-ack-received"/>).  A sender will take
multiple RTT samples per RTT when multiple such ACK frames are received within
an RTT.  When multiple samples are generated within an RTT, the smoothed RTT and
RTT variance could retain inadequate history, as suggested in <xref target="RFC6298"/>.
Changing these computations is currently an open research question.</t>

<t>min_rtt is the minimum RTT measured over the connection, prior to adjusting by
ack delay.  Ignoring ack delay for min RTT prevents intentional or unintentional
underestimation of min RTT, which in turn prevents underestimating smoothed RTT.</t>

</section>
<section anchor="loss-detection" title="Loss Detection">

<t>QUIC senders use both ack information and timeouts to detect lost packets, and
this section provides a description of these algorithms.</t>

<t>If a packet is lost, the QUIC transport needs to recover from that loss, such
as by retransmitting the data, sending an updated frame, or abandoning the
frame.  For more information, see Section 13.2 of <xref target="QUIC-TRANSPORT"/>.</t>

<section anchor="ack-loss-detection" title="Acknowledgement-based Detection">

<t>Acknowledgement-based loss detection implements the spirit of TCP’s Fast
Retransmit <xref target="RFC5681"/>, Early Retransmit <xref target="RFC5827"/>, FACK <xref target="FACK"/>, SACK loss
recovery <xref target="RFC6675"/>, and RACK <xref target="RACK"/>. This section
provides an overview of how these algorithms are implemented in QUIC.</t>

<t>A packet is declared lost if it meets all the following conditions:</t>

<t><list style="symbols">
  <t>The packet is unacknowledged, in-flight, and was sent prior to an
acknowledged packet.</t>
  <t>Either its packet number is kPacketThreshold smaller than an acknowledged
packet (<xref target="packet-threshold"/>), or it was sent long enough in the past
(<xref target="time-threshold"/>).</t>
</list></t>

<t>The acknowledgement indicates that a packet sent later was delivered, while the
packet and time thresholds provide some tolerance for packet reordering.</t>

<t>Spuriously declaring packets as lost leads to unnecessary retransmissions and
may result in degraded performance due to the actions of the congestion
controller upon detecting loss.  Implementations that detect spurious
retransmissions and increase the reordering threshold in packets or time MAY
choose to start with smaller initial reordering thresholds to minimize recovery
latency.</t>

<section anchor="packet-threshold" title="Packet Threshold">

<t>The RECOMMENDED initial value for the packet reordering threshold
(kPacketThreshold) is 3, based on best practices for TCP loss detection
<xref target="RFC5681"/> <xref target="RFC6675"/>.</t>

<t>Some networks may exhibit higher degrees of reordering, causing a sender to
detect spurious losses.  Implementers MAY use algorithms developed for TCP, such
as TCP-NCR <xref target="RFC4653"/>, to improve QUIC’s reordering resilience.</t>

</section>
<section anchor="time-threshold" title="Time Threshold">

<t>Once a later packet has been acknowledged, an endpoint SHOULD declare an earlier
packet lost if it was sent a threshold amount of time in the past. The time
threshold is computed as kTimeThreshold * max(SRTT, latest_RTT).
If packets sent prior to the largest acknowledged packet cannot yet be declared
lost, then a timer SHOULD be set for the remaining time.</t>

<t>The RECOMMENDED time threshold (kTimeThreshold), expressed as a round-trip time
multiplier, is 9/8.</t>

<t>Using max(SRTT, latest_RTT) protects from the two following cases:</t>

<t><list style="symbols">
  <t>the latest RTT sample is lower than the SRTT, perhaps due to reordering where
the acknowledgement encountered a shorter path;</t>
  <t>the latest RTT sample is higher than the SRTT, perhaps due to a sustained
increase in the actual RTT, but the smoothed SRTT has not yet caught up.</t>
</list></t>

<t>Implementations MAY experiment with absolute thresholds, thresholds from
previous connections, adaptive thresholds, or including RTT variance.  Smaller
thresholds reduce reordering resilience and increase spurious retransmissions,
and larger thresholds increase loss detection delay.</t>

</section>
</section>
<section anchor="crypto-retransmission-timeout" title="Crypto Retransmission Timeout">

<t>Data in CRYPTO frames is critical to QUIC transport and crypto negotiation, so a
more aggressive timeout is used to retransmit it.</t>

<t>The initial crypto retransmission timeout SHOULD be set to twice the initial
RTT.</t>

<t>At the beginning, there are no prior RTT samples within a connection.  Resumed
connections over the same network SHOULD use the previous connection’s final
smoothed RTT value as the resumed connection’s initial RTT.  If no previous RTT
is available, or if the network changes, the initial RTT SHOULD be set to 100ms.
When an acknowledgement is received, a new RTT is computed and the timer
SHOULD be set for twice the newly computed smoothed RTT.</t>

<t>When a crypto packet is sent, the sender MUST set a timer for the crypto
timeout period.  This timer MUST be updated when a new crypto packet is sent.
Upon timeout, the sender MUST retransmit all unacknowledged CRYPTO data if
possible.</t>

<t>Until the server has validated the client’s address on the path, the amount of
data it can send is limited, as specified in <xref target="QUIC-TRANSPORT"/>.  If not all
unacknowledged CRYPTO data can be sent, then all unacknowledged CRYPTO data sent
in Initial packets should be retransmitted.  If no data can be sent, then no
alarm should be armed until data has been received from the client.</t>

<t>Because the server could be blocked until more packets are received, the client
MUST start the crypto retransmission timer even if there is no unacknowledged
CRYPTO data.  If the timer expires and the client has no CRYPTO data to
retransmit and does not have Handshake keys, it SHOULD send an Initial packet in
a UDP datagram of at least 1200 bytes.  If the client has Handshake keys, it
SHOULD send a Handshake packet.</t>

<t>On each consecutive expiration of the crypto timer without receiving an
acknowledgement for a new packet, the sender SHOULD double the crypto
retransmission timeout and set a timer for this period.</t>

<t>When crypto packets are in flight, the probe timer (<xref target="pto"/>) is not active.</t>

<section anchor="retry-and-version-negotiation" title="Retry and Version Negotiation">

<t>A Retry or Version Negotiation packet causes a client to send another Initial
packet, effectively restarting the connection process and resetting congestion
control and loss recovery state, including resetting any pending timers.  Either
packet indicates that the Initial was received but not processed.  Neither
packet can be treated as an acknowledgment for the Initial.</t>

<t>The client MAY however compute an RTT estimate to the server as the time period
from when the first Initial was sent to when a Retry or a Version Negotiation
packet is received.  The client MAY use this value to seed the RTT estimator for
a subsequent connection attempt to the server.</t>

</section>
<section anchor="discarding-packets" title="Discarding Keys and Packet State">

<t>When packet protection keys are discarded (see Section 4.9 of <xref target="QUIC-TLS"/>), all
packets that were sent with those keys can no longer be acknowledged because
their acknowledgements cannot be processed anymore. The sender MUST discard
all recovery state associated with those packets and MUST remove them from
the count of bytes in flight.</t>

<t>Endpoints stop sending and receiving Initial packets once they start exchanging
Handshake packets (see Section 17.2.2.1 of <xref target="QUIC-TRANSPORT"/>). At this point,
recovery state for all in-flight Initial packets is discarded.</t>

<t>When 0-RTT is rejected, recovery state for all in-flight 0-RTT packets is
discarded.</t>

<t>If a server accepts 0-RTT, but does not buffer 0-RTT packets that arrive
before Initial packets, early 0-RTT packets will be declared lost, but that
is expected to be infrequent.</t>

<t>It is expected that keys are discarded after packets encrypted with them would
be acknowledged or declared lost.  Initial secrets however might be destroyed
sooner, as soon as handshake keys are available (see Section 4.10 of
<xref target="QUIC-TLS"/>).</t>

</section>
</section>
<section anchor="pto" title="Probe Timeout">

<t>A Probe Timeout (PTO) triggers a probe packet when ack-eliciting data is in
flight but an acknowledgement is not received within the expected period of
time.  A PTO enables a connection to recover from loss of tail packets or acks.
The PTO algorithm used in QUIC implements the reliability functions of Tail Loss
Probe <xref target="TLP"/> <xref target="RACK"/>, RTO <xref target="RFC5681"/> and
F-RTO algorithms for TCP <xref target="RFC5682"/>, and the timeout computation is based on
TCP’s retransmission timeout period <xref target="RFC6298"/>.</t>

<section anchor="computing-pto" title="Computing PTO">

<t>When an ack-eliciting packet is transmitted, the sender schedules a timer for
the PTO period as follows:</t>

<figure><artwork><![CDATA[
PTO = smoothed_rtt + max(4*rttvar, kGranularity) + max_ack_delay
]]></artwork></figure>

<t>kGranularity, smoothed_rtt, rttvar, and max_ack_delay are defined in
<xref target="ld-consts-of-interest"/> and <xref target="ld-vars-of-interest"/>.</t>

<t>The PTO period is the amount of time that a sender ought to wait for an
acknowledgement of a sent packet.  This time period includes the estimated
network roundtrip-time (smoothed_rtt), the variance in the estimate (4*rttvar),
and max_ack_delay, to account for the maximum time by which a receiver might
delay sending an acknowledgement.</t>

<t>The PTO value MUST be set to at least kGranularity, to avoid the timer expiring
immediately.</t>

<t>When a PTO timer expires, the sender probes the network as described in the next
section. The PTO period MUST be set to twice its current value. This exponential
reduction in the sender’s rate is important because the PTOs might be caused by
loss of packets or acknowledgements due to severe congestion.</t>

<t>A sender computes its PTO timer every time an ack-eliciting packet is sent. A
sender might choose to optimize this by setting the timer fewer times if it
knows that more ack-eliciting packets will be sent within a short period of
time.</t>

</section>
<section anchor="sending-probe-packets" title="Sending Probe Packets">

<t>When a PTO timer expires, the sender MUST send one ack-eliciting packet as a
probe. A sender MAY send up to two ack-eliciting packets, to avoid an expensive
consecutive PTO expiration due to a single packet loss.</t>

<t>Consecutive PTO periods increase exponentially, and as a result, connection
recovery latency increases exponentially as packets continue to be dropped in
the network.  Sending two packets on PTO expiration increases resilience to
packet drops, thus reducing the probability of consecutive PTO events.</t>

<t>Probe packets sent on a PTO MUST be ack-eliciting.  A probe packet SHOULD carry
new data when possible.  A probe packet MAY carry retransmitted unacknowledged
data when new data is unavailable, when flow control does not permit new data to
be sent, or to opportunistically reduce loss recovery delay.  Implementations
MAY use alternate strategies for determining the content of probe packets,
including sending new or retransmitted data based on the application’s
priorities.</t>

<t>When the PTO timer expires multiple times and new data cannot be sent,
implementations must choose between sending the same payload every time
or sending different payloads.  Sending the same payload may be simpler
and ensures the highest priority frames arrive first.  Sending different
payloads each time reduces the chances of spurious retransmission.</t>

<t>When a PTO timer expires, new or previously-sent data may not be available to
send and packets may still be in flight.  A sender can be blocked from sending
new data in the future if packets are left in flight.  Under these conditions, a
sender SHOULD mark any packets still in flight as lost.  If a sender wishes to
establish delivery of packets still in flight, it MAY send an ack-eliciting
packet and re-arm the PTO timer instead.</t>

</section>
<section anchor="pto-loss" title="Loss Detection">

<t>Delivery or loss of packets in flight is established when an ACK frame is
received that newly acknowledges one or more packets.</t>

<t>A PTO timer expiration event does not indicate packet loss and MUST NOT cause
prior unacknowledged packets to be marked as lost. When an acknowledgement
is received that newly acknowledges packets, loss detection proceeds as
dictated by packet and time threshold mechanisms, see <xref target="ack-loss-detection"/>.</t>

</section>
</section>
<section anchor="discussion" title="Discussion">

<t>The majority of constants were derived from best common practices among widely
deployed TCP implementations on the internet.  Exceptions follow.</t>

<t>A shorter delayed ack time of 25ms was chosen because longer delayed acks can
delay loss recovery and for the small number of connections where less than
packet per 25ms is delivered, acking every packet is beneficial to congestion
control and loss recovery.</t>

<t>The default initial RTT of 100ms was chosen because it is slightly higher than
both the median and mean min_rtt typically observed on the public internet.</t>

</section>
</section>
<section anchor="congestion-control" title="Congestion Control">

<t>QUIC’s congestion control is based on TCP NewReno <xref target="RFC6582"/>.  NewReno is a
congestion window based congestion control.  QUIC specifies the congestion
window in bytes rather than packets due to finer control and the ease of
appropriate byte counting <xref target="RFC3465"/>.</t>

<t>QUIC hosts MUST NOT send packets if they would increase bytes_in_flight (defined
in <xref target="vars-of-interest"/>) beyond the available congestion window, unless the
packet is a probe packet sent after a PTO timer expires, as described in
<xref target="pto"/>.</t>

<t>Implementations MAY use other congestion control algorithms, such as
Cubic <xref target="RFC8312"/>, and endpoints MAY use different algorithms from one another.
The signals QUIC provides for congestion control are generic and are designed
to support different algorithms.</t>

<section anchor="congestion-ecn" title="Explicit Congestion Notification">

<t>If a path has been verified to support ECN, QUIC treats a Congestion Experienced
codepoint in the IP header as a signal of congestion. This document specifies an
endpoint’s response when its peer receives packets with the Congestion
Experienced codepoint.  As discussed in <xref target="RFC8311"/>, endpoints are permitted to
experiment with other response functions.</t>

</section>
<section anchor="slow-start" title="Slow Start">

<t>QUIC begins every connection in slow start and exits slow start upon loss or
upon increase in the ECN-CE counter. QUIC re-enters slow start anytime the
congestion window is less than ssthresh, which typically only occurs after an
PTO. While in slow start, QUIC increases the congestion window by the number of
bytes acknowledged when each acknowledgment is processed.</t>

</section>
<section anchor="congestion-avoidance" title="Congestion Avoidance">

<t>Slow start exits to congestion avoidance.  Congestion avoidance in NewReno
uses an additive increase multiplicative decrease (AIMD) approach that
increases the congestion window by one maximum packet size per
congestion window acknowledged.  When a loss is detected, NewReno halves
the congestion window and sets the slow start threshold to the new
congestion window.</t>

</section>
<section anchor="recovery-period" title="Recovery Period">

<t>Recovery is a period of time beginning with detection of a lost packet or an
increase in the ECN-CE counter. Because QUIC does not retransmit packets,
it defines the end of recovery as a packet sent after the start of recovery
being acknowledged. This is slightly different from TCP’s definition of
recovery, which ends when the lost packet that started recovery is acknowledged.</t>

<t>The recovery period limits congestion window reduction to once per round trip.
During recovery, the congestion window remains unchanged irrespective of new
losses or increases in the ECN-CE counter.</t>

</section>
<section anchor="ignoring-loss-of-undecryptable-packets" title="Ignoring Loss of Undecryptable Packets">

<t>During the handshake, some packet protection keys might not be
available when a packet arrives. In particular, Handshake and 0-RTT packets
cannot be processed until the Initial packets arrive, and 1-RTT packets
cannot be processed until the handshake completes.  Endpoints MAY
ignore the loss of Handshake, 0-RTT, and 1-RTT packets that might arrive before
the peer has packet protection keys to process those packets.</t>

</section>
<section anchor="probe-timeout" title="Probe Timeout">

<t>Probe packets MUST NOT be blocked by the congestion controller.  A sender MUST
however count these packets as being additionally in flight, since these packets
add network load without establishing packet loss.  Note that sending probe
packets might cause the sender’s bytes in flight to exceed the congestion window
until an acknowledgement is received that establishes loss or delivery of
packets.</t>

</section>
<section anchor="persistent-congestion" title="Persistent Congestion">

<t>When an ACK frame is received that establishes loss of all in-flight packets
sent over a long enough period of time, the network is considered to be
experiencing persistent congestion.  Commonly, this can be established by
consecutive PTOs, but since the PTO timer is reset when a new ack-eliciting
packet is sent, an explicit duration must be used to account for those cases
where PTOs do not occur or are substantially delayed.  This duration is the
equivalent of kPersistentCongestionThreshold consecutive PTOs, and is computed
as follows:
~~~
(smoothed_rtt + 4 * rttvar + max_ack_delay) *
    ((2 ^ kPersistentCongestionThreshold) - 1)
~~~</t>

<t>For example, assume:</t>

<t>smoothed_rtt = 1
  rttvar = 0
  max_ack_delay = 0
  kPersistentCongestionThreshold = 2</t>

<t>If an eck-eliciting packet is sent at time = 0, the following scenario would
illustrate persistent congestion:</t>

<texttable>
      <ttcol align='left'>t=0</ttcol>
      <ttcol align='left'>Send Pkt #1 (App Data)</ttcol>
      <c>t=1</c>
      <c>Send Pkt #2 (PTO 1)</c>
      <c>t=3</c>
      <c>Send Pkt #3 (PTO 2)</c>
      <c>t=7</c>
      <c>Send Pkt #4 (PTO 3)</c>
      <c>t=8</c>
      <c>Recv ACK of Pkt #4</c>
</texttable>

<t>The first three packets are determined to be lost when the ACK of packet 4 is
received at t=8.  The congestion period is calculated as the time between the
oldest and newest lost packets: (3 - 0) = 3.  The duration for persistent
congestion is equal to: (1 * ((2 ^ kPersistentCongestionThreshold) - 1)) = 3.
Because the threshold was reached and because none of the packets between the
oldest and the newest packets are acknowledged, the network is considered to
have experienced persistent congestion.</t>

<t>When persistent congestion is established, the sender’s congestion window MUST
be reduced to the minimum congestion window (kMinimumWindow).  This response of
collapsing the congestion window on persistent congestion is functionally
similar to a sender’s response on a Retransmission Timeout (RTO) in TCP
<xref target="RFC5681"/> after Tail Loss Probes (TLP) <xref target="TLP"/>.</t>

</section>
<section anchor="pacing" title="Pacing">

<t>This document does not specify a pacer, but it is RECOMMENDED that a sender pace
sending of all in-flight packets based on input from the congestion
controller. For example, a pacer might distribute the congestion window over
the SRTT when used with a window-based controller, and a pacer might use the
rate estimate of a rate-based controller.</t>

<t>An implementation should take care to architect its congestion controller to
work well with a pacer.  For instance, a pacer might wrap the congestion
controller and control the availability of the congestion window, or a pacer
might pace out packets handed to it by the congestion controller. Timely
delivery of ACK frames is important for efficient loss recovery. Packets
containing only ACK frames should therefore not be paced, to avoid delaying
their delivery to the peer.</t>

<t>As an example of a well-known and publicly available implementation of a flow
pacer, implementers are referred to the Fair Queue packet scheduler (fq qdisc)
in Linux (3.11 onwards).</t>

</section>
<section anchor="sending-data-after-an-idle-period" title="Sending data after an idle period">

<t>A sender becomes idle if it ceases to send data and has no bytes in flight.  A
sender’s congestion window MUST NOT increase while it is idle.</t>

<t>When sending data after becoming idle, a sender MUST reset its congestion window
to the initial congestion window (see Section 4.1 of <xref target="RFC5681"/>), unless it
paces the sending of packets. A sender MAY retain its congestion window if it
paces the sending of any packets in excess of the initial congestion window.</t>

<t>A sender MAY implement alternate mechanisms to update its congestion window
after idle periods, such as those proposed for TCP in <xref target="RFC7661"/>.</t>

</section>
<section anchor="application-limited-sending" title="Application Limited Sending">

<t>The congestion window should not be increased in slow start or congestion
avoidance when it is not fully utilized.  The congestion window could be
under-utilized due to insufficient application data or flow control credit.</t>

<t>A sender that paces packets (see <xref target="pacing"/>) might delay sending packets
and not fully utilize the congestion window due to this delay. A sender
should not consider itself application limited if it would have fully
utilized the congestion window without pacing delay.</t>

</section>
</section>
<section anchor="security-considerations" title="Security Considerations">

<section anchor="congestion-signals" title="Congestion Signals">

<t>Congestion control fundamentally involves the consumption of signals – both
loss and ECN codepoints – from unauthenticated entities.  On-path attackers can
spoof or alter these signals.  An attacker can cause endpoints to reduce their
sending rate by dropping packets, or alter send rate by changing ECN codepoints.</t>

</section>
<section anchor="traffic-analysis" title="Traffic Analysis">

<t>Packets that carry only ACK frames can be heuristically identified by observing
packet size.  Acknowledgement patterns may expose information about link
characteristics or application behavior.  Endpoints can use PADDING frames or
bundle acknowledgments with other frames to reduce leaked information.</t>

</section>
<section anchor="misreporting-ecn-markings" title="Misreporting ECN Markings">

<t>A receiver can misreport ECN markings to alter the congestion response of a
sender.  Suppressing reports of ECN-CE markings could cause a sender to
increase their send rate.  This increase could result in congestion and loss.</t>

<t>A sender MAY attempt to detect suppression of reports by marking occasional
packets that they send with ECN-CE.  If a packet marked with ECN-CE is not
reported as having been marked when the packet is acknowledged, the sender
SHOULD then disable ECN for that path.</t>

<t>Reporting additional ECN-CE markings will cause a sender to reduce their sending
rate, which is similar in effect to advertising reduced connection flow control
limits and so no advantage is gained by doing so.</t>

<t>Endpoints choose the congestion controller that they use.  Though congestion
controllers generally treat reports of ECN-CE markings as equivalent to loss
<xref target="RFC8311"></xref>, the exact response for each controller could be different.  Failure
to correctly respond to information about ECN markings is therefore difficult to
detect.</t>

</section>
</section>
<section anchor="iana-considerations" title="IANA Considerations">

<t>This document has no IANA actions.  Yet.</t>

</section>


  </middle>

  <back>

    <references title='Normative References'>

<reference anchor="QUIC-TRANSPORT" >
  <front>
    <title>QUIC: A UDP-Based Multiplexed and Secure Transport</title>
    <author initials="J." surname="Iyengar" fullname="Jana Iyengar" role="editor">
      <organization>Fastly</organization>
    </author>
    <author initials="M." surname="Thomson" fullname="Martin Thomson" role="editor">
      <organization>Mozilla</organization>
    </author>
    <date year="2019" month="March" day="11"/>
  </front>
  <seriesInfo name="Internet-Draft" value="draft-ietf-quic-transport-19"/>
</reference>
<reference anchor="QUIC-TLS" >
  <front>
    <title>Using TLS to Secure QUIC</title>
    <author initials="M." surname="Thomson" fullname="Martin Thomson" role="editor">
      <organization>Mozilla</organization>
    </author>
    <author initials="S." surname="Turner" fullname="Sean Turner" role="editor">
      <organization>sn3rd</organization>
    </author>
    <date year="2019" month="March" day="11"/>
  </front>
  <seriesInfo name="Internet-Draft" value="draft-ietf-quic-tls-19"/>
</reference>




<reference  anchor="RFC2119" target='https://www.rfc-editor.org/info/rfc2119'>
<front>
<title>Key words for use in RFCs to Indicate Requirement Levels</title>
<author initials='S.' surname='Bradner' fullname='S. Bradner'><organization /></author>
<date year='1997' month='March' />
<abstract><t>In many standards track documents several words are used to signify the requirements in the specification.  These words are often capitalized. This document defines these words as they should be interpreted in IETF documents.  This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t></abstract>
</front>
<seriesInfo name='BCP' value='14'/>
<seriesInfo name='RFC' value='2119'/>
<seriesInfo name='DOI' value='10.17487/RFC2119'/>
</reference>



<reference  anchor="RFC8174" target='https://www.rfc-editor.org/info/rfc8174'>
<front>
<title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
<author initials='B.' surname='Leiba' fullname='B. Leiba'><organization /></author>
<date year='2017' month='May' />
<abstract><t>RFC 2119 specifies common key words that may be used in protocol  specifications.  This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the  defined special meanings.</t></abstract>
</front>
<seriesInfo name='BCP' value='14'/>
<seriesInfo name='RFC' value='8174'/>
<seriesInfo name='DOI' value='10.17487/RFC8174'/>
</reference>



<reference  anchor="RFC8311" target='https://www.rfc-editor.org/info/rfc8311'>
<front>
<title>Relaxing Restrictions on Explicit Congestion Notification (ECN) Experimentation</title>
<author initials='D.' surname='Black' fullname='D. Black'><organization /></author>
<date year='2018' month='January' />
<abstract><t>This memo updates RFC 3168, which specifies Explicit Congestion Notification (ECN) as an alternative to packet drops for indicating network congestion to endpoints.  It relaxes restrictions in RFC 3168 that hinder experimentation towards benefits beyond just removal of loss.  This memo summarizes the anticipated areas of experimentation and updates RFC 3168 to enable experimentation in these areas.  An Experimental RFC in the IETF document stream is required to take advantage of any of these enabling updates.  In addition, this memo makes related updates to the ECN specifications for RTP in RFC 6679 and for the Datagram Congestion Control Protocol (DCCP) in RFCs 4341, 4342, and 5622.  This memo also records the conclusion of the ECN nonce experiment in RFC 3540 and provides the rationale for reclassification of RFC 3540 from Experimental to Historic; this reclassification enables new experimental use of the ECT(1) codepoint.</t></abstract>
</front>
<seriesInfo name='RFC' value='8311'/>
<seriesInfo name='DOI' value='10.17487/RFC8311'/>
</reference>




    </references>

    <references title='Informative References'>

<reference anchor="FACK" >
  <front>
    <title>Forward Acknowledgement: Refining TCP Congestion Control</title>
    <author initials="M." surname="Mathis">
      <organization></organization>
    </author>
    <author initials="J." surname="Mahdavi">
      <organization></organization>
    </author>
    <date year="1996" month="August"/>
  </front>
  <seriesInfo name="ACM SIGCOMM" value=""/>
</reference>




<reference  anchor="RFC6298" target='https://www.rfc-editor.org/info/rfc6298'>
<front>
<title>Computing TCP's Retransmission Timer</title>
<author initials='V.' surname='Paxson' fullname='V. Paxson'><organization /></author>
<author initials='M.' surname='Allman' fullname='M. Allman'><organization /></author>
<author initials='J.' surname='Chu' fullname='J. Chu'><organization /></author>
<author initials='M.' surname='Sargent' fullname='M. Sargent'><organization /></author>
<date year='2011' month='June' />
<abstract><t>This document defines the standard algorithm that Transmission Control Protocol (TCP) senders are required to use to compute and manage their retransmission timer.  It expands on the discussion in Section 4.2.3.1 of RFC 1122 and upgrades the requirement of supporting the algorithm from a SHOULD to a MUST.  This document obsoletes RFC 2988.   [STANDARDS-TRACK]</t></abstract>
</front>
<seriesInfo name='RFC' value='6298'/>
<seriesInfo name='DOI' value='10.17487/RFC6298'/>
</reference>



<reference  anchor="RFC5681" target='https://www.rfc-editor.org/info/rfc5681'>
<front>
<title>TCP Congestion Control</title>
<author initials='M.' surname='Allman' fullname='M. Allman'><organization /></author>
<author initials='V.' surname='Paxson' fullname='V. Paxson'><organization /></author>
<author initials='E.' surname='Blanton' fullname='E. Blanton'><organization /></author>
<date year='2009' month='September' />
<abstract><t>This document defines TCP's four intertwined congestion control algorithms: slow start, congestion avoidance, fast retransmit, and fast recovery.  In addition, the document specifies how TCP should begin transmission after a relatively long idle period, as well as discussing various acknowledgment generation methods.  This document obsoletes RFC 2581.  [STANDARDS-TRACK]</t></abstract>
</front>
<seriesInfo name='RFC' value='5681'/>
<seriesInfo name='DOI' value='10.17487/RFC5681'/>
</reference>



<reference  anchor="RFC5827" target='https://www.rfc-editor.org/info/rfc5827'>
<front>
<title>Early Retransmit for TCP and Stream Control Transmission Protocol (SCTP)</title>
<author initials='M.' surname='Allman' fullname='M. Allman'><organization /></author>
<author initials='K.' surname='Avrachenkov' fullname='K. Avrachenkov'><organization /></author>
<author initials='U.' surname='Ayesta' fullname='U. Ayesta'><organization /></author>
<author initials='J.' surname='Blanton' fullname='J. Blanton'><organization /></author>
<author initials='P.' surname='Hurtig' fullname='P. Hurtig'><organization /></author>
<date year='2010' month='May' />
<abstract><t>This document proposes a new mechanism for TCP and Stream Control Transmission Protocol (SCTP) that can be used to recover lost segments when a connection's congestion window is small.  The &quot;Early Retransmit&quot; mechanism allows the transport to reduce, in certain special circumstances, the number of duplicate acknowledgments required to trigger a fast retransmission.  This allows the transport to use fast retransmit to recover segment losses that would otherwise require a lengthy retransmission timeout.  [STANDARDS-TRACK]</t></abstract>
</front>
<seriesInfo name='RFC' value='5827'/>
<seriesInfo name='DOI' value='10.17487/RFC5827'/>
</reference>



<reference  anchor="RFC6675" target='https://www.rfc-editor.org/info/rfc6675'>
<front>
<title>A Conservative Loss Recovery Algorithm Based on Selective Acknowledgment (SACK) for TCP</title>
<author initials='E.' surname='Blanton' fullname='E. Blanton'><organization /></author>
<author initials='M.' surname='Allman' fullname='M. Allman'><organization /></author>
<author initials='L.' surname='Wang' fullname='L. Wang'><organization /></author>
<author initials='I.' surname='Jarvinen' fullname='I. Jarvinen'><organization /></author>
<author initials='M.' surname='Kojo' fullname='M. Kojo'><organization /></author>
<author initials='Y.' surname='Nishida' fullname='Y. Nishida'><organization /></author>
<date year='2012' month='August' />
<abstract><t>This document presents a conservative loss recovery algorithm for TCP that is based on the use of the selective acknowledgment (SACK) TCP option.  The algorithm presented in this document conforms to the spirit of the current congestion control specification (RFC 5681), but allows TCP senders to recover more effectively when multiple segments are lost from a single flight of data. This document obsoletes RFC 3517 and describes changes from it.   [STANDARDS-TRACK]</t></abstract>
</front>
<seriesInfo name='RFC' value='6675'/>
<seriesInfo name='DOI' value='10.17487/RFC6675'/>
</reference>



<reference anchor="RACK">
<front>
<title>RACK: a time-based fast loss detection algorithm for TCP</title>

<author initials='Y' surname='Cheng' fullname='Yuchung Cheng'>
    <organization />
</author>

<author initials='N' surname='Cardwell' fullname='Neal Cardwell'>
    <organization />
</author>

<author initials='N' surname='Dukkipati' fullname='Nandita Dukkipati'>
    <organization />
</author>

<author initials='P' surname='Jha' fullname='Priyaranjan Jha'>
    <organization />
</author>

<date month='July' day='2' year='2018' />

<abstract><t>This document presents a new TCP loss detection algorithm called RACK ("Recent ACKnowledgment").  RACK uses the notion of time, instead of packet or sequence counts, to detect losses, for modern TCP implementations that can support per-packet timestamps and the selective acknowledgment (SACK) option.  It is intended to replace the conventional DUPACK threshold approach and its variants, as well as other nonstandard approaches.</t></abstract>

</front>

<seriesInfo name='Internet-Draft' value='draft-ietf-tcpm-rack-04' />
<format type='TXT'
        target='http://www.ietf.org/internet-drafts/draft-ietf-tcpm-rack-04.txt' />
</reference>



<reference  anchor="RFC4653" target='https://www.rfc-editor.org/info/rfc4653'>
<front>
<title>Improving the Robustness of TCP to Non-Congestion Events</title>
<author initials='S.' surname='Bhandarkar' fullname='S. Bhandarkar'><organization /></author>
<author initials='A. L. N.' surname='Reddy' fullname='A. L. N. Reddy'><organization /></author>
<author initials='M.' surname='Allman' fullname='M. Allman'><organization /></author>
<author initials='E.' surname='Blanton' fullname='E. Blanton'><organization /></author>
<date year='2006' month='August' />
<abstract><t>This document specifies Non-Congestion Robustness (NCR) for TCP.  In the absence of explicit congestion notification from the network, TCP uses loss as an indication of congestion.  One of the ways TCP detects loss is using the arrival of three duplicate acknowledgments. However, this heuristic is not always correct, notably in the case when network paths reorder segments (for whatever reason), resulting in degraded performance.  TCP-NCR is designed to mitigate this degraded performance by increasing the number of duplicate acknowledgments required to trigger loss recovery, based on the current state of the connection, in an effort to better disambiguate true segment loss from segment reordering.  This document specifies the changes to TCP, as well as the costs and benefits of these modifications.  This memo defines an Experimental Protocol for the Internet community.</t></abstract>
</front>
<seriesInfo name='RFC' value='4653'/>
<seriesInfo name='DOI' value='10.17487/RFC4653'/>
</reference>



<reference anchor="TLP">
<front>
<title>Tail Loss Probe (TLP): An Algorithm for Fast Recovery of Tail Losses</title>

<author initials='N' surname='Dukkipati' fullname='Nandita Dukkipati'>
    <organization />
</author>

<author initials='N' surname='Cardwell' fullname='Neal Cardwell'>
    <organization />
</author>

<author initials='Y' surname='Cheng' fullname='Yuchung Cheng'>
    <organization />
</author>

<author initials='M' surname='Mathis' fullname='Matt Mathis'>
    <organization />
</author>

<date month='February' day='25' year='2013' />

<abstract><t>Retransmission timeouts are detrimental to application latency, especially for short transfers such as Web transactions where timeouts can often take longer than all of the rest of a transaction. The primary cause of retransmission timeouts are lost segments at the tail of transactions.  This document describes an experimental algorithm for TCP to quickly recover lost segments at the end of transactions or when an entire window of data or acknowledgments are lost.  Tail Loss Probe (TLP) is a sender-only algorithm that allows the transport to recover tail losses through fast recovery as opposed to lengthy retransmission timeouts.  If a connection is not receiving any acknowledgments for a certain period of time, TLP transmits the last unacknowledged segment (loss probe).  In the event of a tail loss in the original transmissions, the acknowledgment from the loss probe triggers SACK/FACK based fast recovery.  TLP effectively avoids long timeouts and thereby improves TCP performance.</t></abstract>

</front>

<seriesInfo name='Internet-Draft' value='draft-dukkipati-tcpm-tcp-loss-probe-01' />
<format type='TXT'
        target='http://www.ietf.org/internet-drafts/draft-dukkipati-tcpm-tcp-loss-probe-01.txt' />
</reference>



<reference  anchor="RFC5682" target='https://www.rfc-editor.org/info/rfc5682'>
<front>
<title>Forward RTO-Recovery (F-RTO): An Algorithm for Detecting Spurious Retransmission Timeouts with TCP</title>
<author initials='P.' surname='Sarolahti' fullname='P. Sarolahti'><organization /></author>
<author initials='M.' surname='Kojo' fullname='M. Kojo'><organization /></author>
<author initials='K.' surname='Yamamoto' fullname='K. Yamamoto'><organization /></author>
<author initials='M.' surname='Hata' fullname='M. Hata'><organization /></author>
<date year='2009' month='September' />
<abstract><t>The purpose of this document is to move the F-RTO (Forward RTO-Recovery) functionality for TCP in RFC 4138 from Experimental to Standards Track status.  The F-RTO support for Stream Control Transmission Protocol (SCTP) in RFC 4138 remains with Experimental status.  See Appendix B for the differences between this document and RFC 4138.</t><t>Spurious retransmission timeouts cause suboptimal TCP performance because they often result in unnecessary retransmission of the last window of data.  This document describes the F-RTO detection algorithm for detecting spurious TCP retransmission timeouts.  F-RTO is a TCP sender-only algorithm that does not require any TCP options to operate.  After retransmitting the first unacknowledged segment triggered by a timeout, the F-RTO algorithm of the TCP sender monitors the incoming acknowledgments to determine whether the timeout was spurious.  It then decides whether to send new segments or retransmit unacknowledged segments.  The algorithm effectively helps to avoid additional unnecessary retransmissions and thereby improves TCP performance in the case of a spurious timeout.  [STANDARDS-TRACK]</t></abstract>
</front>
<seriesInfo name='RFC' value='5682'/>
<seriesInfo name='DOI' value='10.17487/RFC5682'/>
</reference>



<reference  anchor="RFC6582" target='https://www.rfc-editor.org/info/rfc6582'>
<front>
<title>The NewReno Modification to TCP's Fast Recovery Algorithm</title>
<author initials='T.' surname='Henderson' fullname='T. Henderson'><organization /></author>
<author initials='S.' surname='Floyd' fullname='S. Floyd'><organization /></author>
<author initials='A.' surname='Gurtov' fullname='A. Gurtov'><organization /></author>
<author initials='Y.' surname='Nishida' fullname='Y. Nishida'><organization /></author>
<date year='2012' month='April' />
<abstract><t>RFC 5681 documents the following four intertwined TCP congestion control algorithms: slow start, congestion avoidance, fast retransmit, and fast recovery.  RFC 5681 explicitly allows certain modifications of these algorithms, including modifications that use the TCP Selective Acknowledgment (SACK) option (RFC 2883), and modifications that respond to &quot;partial acknowledgments&quot; (ACKs that cover new data, but not all the data outstanding when loss was detected) in the absence of SACK.  This document describes a specific algorithm for responding to partial acknowledgments, referred to as &quot;NewReno&quot;.  This response to partial acknowledgments was first proposed by Janey Hoe.  This document obsoletes RFC 3782.  [STANDARDS-TRACK]</t></abstract>
</front>
<seriesInfo name='RFC' value='6582'/>
<seriesInfo name='DOI' value='10.17487/RFC6582'/>
</reference>



<reference  anchor="RFC3465" target='https://www.rfc-editor.org/info/rfc3465'>
<front>
<title>TCP Congestion Control with Appropriate Byte Counting (ABC)</title>
<author initials='M.' surname='Allman' fullname='M. Allman'><organization /></author>
<date year='2003' month='February' />
<abstract><t>This document proposes a small modification to the way TCP increases its congestion window.  Rather than the traditional method of increasing the congestion window by a constant amount for each arriving acknowledgment, the document suggests basing the increase on the number of previously unacknowledged bytes each ACK covers.  This change improves the performance of TCP, as well as closes a security hole TCP receivers can use to induce the sender into increasing the sending rate too rapidly. This memo defines an Experimental Protocol for the Internet community.</t></abstract>
</front>
<seriesInfo name='RFC' value='3465'/>
<seriesInfo name='DOI' value='10.17487/RFC3465'/>
</reference>



<reference  anchor="RFC8312" target='https://www.rfc-editor.org/info/rfc8312'>
<front>
<title>CUBIC for Fast Long-Distance Networks</title>
<author initials='I.' surname='Rhee' fullname='I. Rhee'><organization /></author>
<author initials='L.' surname='Xu' fullname='L. Xu'><organization /></author>
<author initials='S.' surname='Ha' fullname='S. Ha'><organization /></author>
<author initials='A.' surname='Zimmermann' fullname='A. Zimmermann'><organization /></author>
<author initials='L.' surname='Eggert' fullname='L. Eggert'><organization /></author>
<author initials='R.' surname='Scheffenegger' fullname='R. Scheffenegger'><organization /></author>
<date year='2018' month='February' />
<abstract><t>CUBIC is an extension to the current TCP standards.  It differs from the current TCP standards only in the congestion control algorithm on the sender side.  In particular, it uses a cubic function instead of a linear window increase function of the current TCP standards to improve scalability and stability under fast and long-distance networks.  CUBIC and its predecessor algorithm have been adopted as defaults by Linux and have been used for many years.  This document provides a specification of CUBIC to enable third-party implementations and to solicit community feedback through experimentation on the performance of CUBIC.</t></abstract>
</front>
<seriesInfo name='RFC' value='8312'/>
<seriesInfo name='DOI' value='10.17487/RFC8312'/>
</reference>



<reference  anchor="RFC7661" target='https://www.rfc-editor.org/info/rfc7661'>
<front>
<title>Updating TCP to Support Rate-Limited Traffic</title>
<author initials='G.' surname='Fairhurst' fullname='G. Fairhurst'><organization /></author>
<author initials='A.' surname='Sathiaseelan' fullname='A. Sathiaseelan'><organization /></author>
<author initials='R.' surname='Secchi' fullname='R. Secchi'><organization /></author>
<date year='2015' month='October' />
<abstract><t>This document provides a mechanism to address issues that arise when TCP is used for traffic that exhibits periods where the sending rate is limited by the application rather than the congestion window.  It provides an experimental update to TCP that allows a TCP sender to restart quickly following a rate-limited interval.  This method is expected to benefit applications that send rate-limited traffic using TCP while also providing an appropriate response if congestion is experienced.</t><t>This document also evaluates the Experimental specification of TCP Congestion Window Validation (CWV) defined in RFC 2861 and concludes that RFC 2861 sought to address important issues but failed to deliver a widely used solution.  This document therefore reclassifies the status of RFC 2861 from Experimental to Historic.  This document obsoletes RFC 2861.</t></abstract>
</front>
<seriesInfo name='RFC' value='7661'/>
<seriesInfo name='DOI' value='10.17487/RFC7661'/>
</reference>



<reference  anchor="RFC6928" target='https://www.rfc-editor.org/info/rfc6928'>
<front>
<title>Increasing TCP's Initial Window</title>
<author initials='J.' surname='Chu' fullname='J. Chu'><organization /></author>
<author initials='N.' surname='Dukkipati' fullname='N. Dukkipati'><organization /></author>
<author initials='Y.' surname='Cheng' fullname='Y. Cheng'><organization /></author>
<author initials='M.' surname='Mathis' fullname='M. Mathis'><organization /></author>
<date year='2013' month='April' />
<abstract><t>This document proposes an experiment to increase the permitted TCP initial window (IW) from between 2 and 4 segments, as specified in RFC 3390, to 10 segments with a fallback to the existing recommendation when performance issues are detected.  It discusses the motivation behind the increase, the advantages and disadvantages of the higher initial window, and presents results from several large-scale experiments showing that the higher initial window improves the overall performance of many web services without resulting in a congestion collapse.  The document closes with a discussion of usage and deployment for further experimental purposes recommended by the IETF TCP Maintenance and Minor Extensions (TCPM) working group.</t></abstract>
</front>
<seriesInfo name='RFC' value='6928'/>
<seriesInfo name='DOI' value='10.17487/RFC6928'/>
</reference>




    </references>


<section anchor="loss-recovery-pseudocode" title="Loss Recovery Pseudocode">

<t>We now describe an example implementation of the loss detection mechanisms
described in <xref target="loss-detection"/>.</t>

<section anchor="tracking-sent-packets" title="Tracking Sent Packets">

<t>To correctly implement congestion control, a QUIC sender tracks every
ack-eliciting packet until the packet is acknowledged or lost.
It is expected that implementations will be able to access this information by
packet number and crypto context and store the per-packet fields
(<xref target="sent-packets-fields"/>) for loss recovery and congestion control.</t>

<t>After a packet is declared lost, it SHOULD be tracked for an amount of time
comparable to the maximum expected packet reordering, such as 1 RTT.  This
allows for detection of spurious retransmissions.</t>

<t>Sent packets are tracked for each packet number space, and ACK
processing only applies to a single space.</t>

<section anchor="sent-packets-fields" title="Sent Packet Fields">

<t><list style="hanging">
  <t hangText='packet_number:'>
  The packet number of the sent packet.</t>
  <t hangText='ack_eliciting:'>
  A boolean that indicates whether a packet is ack-eliciting.
If true, it is expected that an acknowledgement will be received,
though the peer could delay sending the ACK frame containing it
by up to the MaxAckDelay.</t>
  <t hangText='in_flight:'>
  A boolean that indicates whether the packet counts towards bytes in
flight.</t>
  <t hangText='is_crypto_packet:'>
  A boolean that indicates whether the packet contains
cryptographic handshake messages critical to the completion of the QUIC
handshake. In this version of QUIC, this includes any packet with the long
header that includes a CRYPTO frame.</t>
  <t hangText='sent_bytes:'>
  The number of bytes sent in the packet, not including UDP or IP
overhead, but including QUIC framing overhead.</t>
  <t hangText='time_sent:'>
  The time the packet was sent.</t>
</list></t>

</section>
</section>
<section anchor="ld-consts-of-interest" title="Constants of interest">

<t>Constants used in loss recovery are based on a combination of RFCs, papers, and
common practice.  Some may need to be changed or negotiated in order to better
suit a variety of environments.</t>

<t><list style="hanging">
  <t hangText='kPacketThreshold:'>
  Maximum reordering in packets before packet threshold loss detection
considers a packet lost. The RECOMMENDED value is 3.</t>
  <t hangText='kTimeThreshold:'>
  Maximum reordering in time before time threshold loss detection
considers a packet lost. Specified as an RTT multiplier. The RECOMMENDED
value is 9/8.</t>
  <t hangText='kGranularity:'>
  Timer granularity. This is a system-dependent value.  However, implementations
SHOULD use a value no smaller than 1ms.</t>
  <t hangText='kInitialRtt:'>
  The RTT used before an RTT sample is taken. The RECOMMENDED value is 100ms.</t>
  <t hangText='kPacketNumberSpace:'>
  An enum to enumerate the three packet number spaces.
~~~
enum kPacketNumberSpace {
  Initial,
  Handshake,
  ApplicationData,
}
~~~</t>
</list></t>

</section>
<section anchor="ld-vars-of-interest" title="Variables of interest">

<t>Variables required to implement the congestion control mechanisms
are described in this section.</t>

<t><list style="hanging">
  <t hangText='loss_detection_timer:'>
  Multi-modal timer used for loss detection.</t>
  <t hangText='crypto_count:'>
  The number of times all unacknowledged CRYPTO data has been
retransmitted without receiving an ack.</t>
  <t hangText='pto_count:'>
  The number of times a PTO has been sent without receiving an ack.</t>
  <t hangText='time_of_last_sent_ack_eliciting_packet:'>
  The time the most recent ack-eliciting packet was sent.</t>
  <t hangText='time_of_last_sent_crypto_packet:'>
  The time the most recent crypto packet was sent.</t>
  <t hangText='largest_acked_packet[kPacketNumberSpace]:'>
  The largest packet number acknowledged in the packet number space so far.</t>
  <t hangText='latest_rtt:'>
  The most recent RTT measurement made when receiving an ack for
a previously unacked packet.</t>
  <t hangText='smoothed_rtt:'>
  The smoothed RTT of the connection, computed as described in
<xref target="RFC6298"/></t>
  <t hangText='rttvar:'>
  The RTT variance, computed as described in <xref target="RFC6298"/></t>
  <t hangText='min_rtt:'>
  The minimum RTT seen in the connection, ignoring ack delay.</t>
  <t hangText='max_ack_delay:'>
  The maximum amount of time by which the receiver intends to delay
acknowledgments, in milliseconds.  The actual ack_delay in a
received ACK frame may be larger due to late timers, reordering,
or lost ACKs.</t>
  <t hangText='loss_time[kPacketNumberSpace]:'>
  The time at which the next packet in that packet number space will be
considered lost based on exceeding the reordering window in time.</t>
  <t hangText='sent_packets[kPacketNumberSpace]:'>
  An association of packet numbers in a packet number space to information
about them.  Described in detail above in <xref target="tracking-sent-packets"/>.</t>
</list></t>

</section>
<section anchor="initialization" title="Initialization">

<t>At the beginning of the connection, initialize the loss detection variables as
follows:</t>

<figure><artwork><![CDATA[
   loss_detection_timer.reset()
   crypto_count = 0
   pto_count = 0
   smoothed_rtt = 0
   rttvar = 0
   min_rtt = infinite
   time_of_last_sent_ack_eliciting_packet = 0
   time_of_last_sent_crypto_packet = 0
   for pn_space in [ Initial, Handshake, ApplicatonData ]:
     largest_acked_packet[pn_space] = 0
     loss_time[pn_space] = 0
]]></artwork></figure>

</section>
<section anchor="on-sending-a-packet" title="On Sending a Packet">

<t>After a packet is sent, information about the packet is stored.  The parameters
to OnPacketSent are described in detail above in <xref target="sent-packets-fields"/>.</t>

<t>Pseudocode for OnPacketSent follows:</t>

<figure><artwork><![CDATA[
 OnPacketSent(packet_number, pn_space, ack_eliciting,
              in_flight, is_crypto_packet, sent_bytes):
   sent_packets[pn_space][packet_number].packet_number =
                                            packet_number
   sent_packets[pn_space][packet_number].time_sent = now
   sent_packets[pn_space][packet_number].ack_eliciting =
                                            ack_eliciting
   sent_packets[pn_space][packet_number].in_flight = in_flight
   if (in_flight):
     if (is_crypto_packet):
       time_of_last_sent_crypto_packet = now
     if (ack_eliciting):
       time_of_last_sent_ack_eliciting_packet = now
     OnPacketSentCC(sent_bytes)
     sent_packets[pn_space][packet_number].size = sent_bytes
     SetLossDetectionTimer()
]]></artwork></figure>

</section>
<section anchor="on-ack-received" title="On Receiving an Acknowledgment">

<t>When an ACK frame is received, it may newly acknowledge any number of packets.</t>

<t>Pseudocode for OnAckReceived and UpdateRtt follow:</t>

<figure><artwork><![CDATA[
OnAckReceived(ack, pn_space):
  largest_acked_packet[pn_space] =
      max(largest_acked_packet[pn_space], ack.largest_acked)

  // If the largest acknowledged is newly acked and
  // ack-eliciting, update the RTT.
  if (sent_packets[pn_space][ack.largest_acked] &&
      sent_packets[pn_space][ack.largest_acked].ack_eliciting):
    latest_rtt =
      now - sent_packets[pn_space][ack.largest_acked].time_sent
    UpdateRtt(latest_rtt, ack.ack_delay)

  // Process ECN information if present.
  if (ACK frame contains ECN information):
      ProcessECN(ack)

  // Find all newly acked packets in this ACK frame
  newly_acked_packets = DetermineNewlyAckedPackets(ack, pn_space)
  if (newly_acked_packets.empty()):
    return

  for acked_packet in newly_acked_packets:
    OnPacketAcked(acked_packet.packet_number, pn_space)

  DetectLostPackets(pn_space)

  crypto_count = 0
  pto_count = 0

  SetLossDetectionTimer()


UpdateRtt(latest_rtt, ack_delay):
  // min_rtt ignores ack delay.
  min_rtt = min(min_rtt, latest_rtt)
  // Limit ack_delay by max_ack_delay
  ack_delay = min(ack_delay, max_ack_delay)
  // Adjust for ack delay if it's plausible.
  if (latest_rtt - min_rtt > ack_delay):
    latest_rtt -= ack_delay
  // Based on {{RFC6298}}.
  if (smoothed_rtt == 0):
    smoothed_rtt = latest_rtt
    rttvar = latest_rtt / 2
  else:
    rttvar_sample = abs(smoothed_rtt - latest_rtt)
    rttvar = 3/4 * rttvar + 1/4 * rttvar_sample
    smoothed_rtt = 7/8 * smoothed_rtt + 1/8 * latest_rtt
]]></artwork></figure>

</section>
<section anchor="on-packet-acknowledgment" title="On Packet Acknowledgment">

<t>When a packet is acknowledged for the first time, the following OnPacketAcked
function is called.  Note that a single ACK frame may newly acknowledge several
packets. OnPacketAcked must be called once for each of these newly acknowledged
packets.</t>

<t>OnPacketAcked takes two parameters: acked_packet, which is the struct detailed
in <xref target="sent-packets-fields"/>, and the packet number space that this ACK frame was
sent for.</t>

<t>Pseudocode for OnPacketAcked follows:</t>

<figure><artwork><![CDATA[
   OnPacketAcked(acked_packet, pn_space):
     if (acked_packet.ack_eliciting):
       OnPacketAckedCC(acked_packet)
     sent_packets[pn_space].remove(acked_packet.packet_number)
]]></artwork></figure>

</section>
<section anchor="setting-the-loss-detection-timer" title="Setting the Loss Detection Timer">

<t>QUIC loss detection uses a single timer for all timeout loss detection.  The
duration of the timer is based on the timer’s mode, which is set in the packet
and timer events further below.  The function SetLossDetectionTimer defined
below shows how the single timer is set.</t>

<t>This algorithm may result in the timer being set in the past, particularly if
timers wake up late. Timers set in the past SHOULD fire immediately.</t>

<t>Pseudocode for SetLossDetectionTimer follows:</t>

<figure><artwork><![CDATA[
// Returns the earliest loss_time and the packet number
// space it's from.  Returns 0 if all times are 0.
GetEarliestLossTime():
  time = loss_time[Initial]
  space = Initial
  for pn_space in [ Handshake, ApplicatonData ]:
    if loss_time[pn_space] != 0 &&
       (time == 0 || loss_time[pn_space] < time):
      time = loss_time[pn_space];
      space = pn_space
  return time, space

SetLossDetectionTimer():
  // Don't arm timer if there are no ack-eliciting packets
  // in flight.
  if (no ack-eliciting packets in flight):
    loss_detection_timer.cancel()
    return

  loss_time, _ = GetEarliestLossTime()
  if (loss_time != 0):
    // Time threshold loss detection.
    loss_detection_timer.update(loss_time)
    return

  if (crypto packets are in flight):
    // Crypto retransmission timer.
    if (smoothed_rtt == 0):
      timeout = 2 * kInitialRtt
    else:
      timeout = 2 * smoothed_rtt
    timeout = max(timeout, kGranularity)
    timeout = timeout * (2 ^ crypto_count)
    loss_detection_timer.update(
      time_of_last_sent_crypto_packet + timeout)
    return

  // Calculate PTO duration
  timeout =
    smoothed_rtt + max(4 * rttvar, kGranularity) + max_ack_delay
  timeout = timeout * (2 ^ pto_count)

  loss_detection_timer.update(
    time_of_last_sent_ack_eliciting_packet + timeout)
]]></artwork></figure>

</section>
<section anchor="on-timeout" title="On Timeout">

<t>When the loss detection timer expires, the timer’s mode determines the action
to be performed.</t>

<t>Pseudocode for OnLossDetectionTimeout follows:</t>

<figure><artwork><![CDATA[
OnLossDetectionTimeout():
  loss_time, pn_space = GetEarliestLossTime()
  if (loss_time != 0):
    // Time threshold loss Detection
    DetectLostPackets(pn_space)
  // Retransmit crypto data if no packets were lost
  // and there are still crypto packets in flight.
  else if (crypto packets are in flight):
    // Crypto retransmission timeout.
    RetransmitUnackedCryptoData()
    crypto_count++
  else:
    // PTO
    SendOneOrTwoPackets()
    pto_count++

  SetLossDetectionTimer()
]]></artwork></figure>

</section>
<section anchor="detecting-lost-packets" title="Detecting Lost Packets">

<t>DetectLostPackets is called every time an ACK is received and operates on
the sent_packets for that packet number space. If the loss detection timer
expires and the loss_time is set, the previous largest acknowledged packet
is supplied.</t>

<t>Pseudocode for DetectLostPackets follows:</t>

<figure><artwork><![CDATA[
DetectLostPackets(pn_space):
  loss_time[pn_space] = 0
  lost_packets = {}
  loss_delay = kTimeThreshold * max(latest_rtt, smoothed_rtt)

  // Packets sent before this time are deemed lost.
  lost_send_time = now() - loss_delay

  // Packets with packet numbers before this are deemed lost.
  lost_pn = largest_acked_packet[pn_space] - kPacketThreshold

  foreach unacked in sent_packets:
    if (unacked.packet_number > largest_acked_packet[pn_space]):
      continue

    // Mark packet as lost, or set time when it should be marked.
    if (unacked.time_sent <= lost_send_time ||
        unacked.packet_number <= lost_pn):
      sent_packets.remove(unacked.packet_number)
      if (unacked.in_flight):
        lost_packets.insert(unacked)
    else:
      if (loss_time[pn_space] == 0):
        loss_time[pn_space] = unacked.time_sent + loss_delay
      else:
        loss_time[pn_space] = min(loss_time[pn_space],
                                  unacked.time_sent + loss_delay)

  // Inform the congestion controller of lost packets and
  // let it decide whether to retransmit immediately.
  if (!lost_packets.empty()):
    OnPacketsLost(lost_packets)
]]></artwork></figure>

</section>
</section>
<section anchor="congestion-control-pseudocode" title="Congestion Control Pseudocode">

<t>We now describe an example implementation of the congestion controller described
in <xref target="congestion-control"/>.</t>

<section anchor="cc-consts-of-interest" title="Constants of interest">

<t>Constants used in congestion control are based on a combination of RFCs,
papers, and common practice.  Some may need to be changed or negotiated
in order to better suit a variety of environments.</t>

<t><list style="hanging">
  <t hangText='kMaxDatagramSize:'>
  The sender’s maximum payload size. Does not include UDP or IP overhead.  The
max packet size is used for calculating initial and minimum congestion
windows. The RECOMMENDED value is 1200 bytes.</t>
  <t hangText='kInitialWindow:'>
  Default limit on the initial amount of data in flight, in bytes.  Taken from
<xref target="RFC6928"/>, but increased slightly to account for the smaller 8 byte
overhead of UDP vs 20 bytes for TCP.  The RECOMMENDED value is the minimum
of 10 * kMaxDatagramSize and max(2* kMaxDatagramSize, 14720)).</t>
  <t hangText='kMinimumWindow:'>
  Minimum congestion window in bytes. The RECOMMENDED value is
2 * kMaxDatagramSize.</t>
  <t hangText='kLossReductionFactor:'>
  Reduction in congestion window when a new loss event is detected.
The RECOMMENDED value is 0.5.</t>
  <t hangText='kPersistentCongestionThreshold:'>
  Number of consecutive PTOs required for persistent congestion to be
established.  The rationale for this threshold is to enable a sender to use
initial PTOs for aggressive probing, as TCP does with Tail Loss Probe (TLP)
<xref target="TLP"/> <xref target="RACK"/>, before establishing persistent congestion, as TCP does with
a Retransmission Timeout (RTO) <xref target="RFC5681"/>.  The RECOMMENDED value for
kPersistentCongestionThreshold is 2, which is equivalent to having two TLPs
before an RTO in TCP.</t>
</list></t>

</section>
<section anchor="vars-of-interest" title="Variables of interest">

<t>Variables required to implement the congestion control mechanisms
are described in this section.</t>

<t><list style="hanging">
  <t hangText='ecn_ce_counter:'>
  The highest value reported for the ECN-CE counter by the peer in an ACK
frame. This variable is used to detect increases in the reported ECN-CE
counter.</t>
  <t hangText='bytes_in_flight:'>
  The sum of the size in bytes of all sent packets that contain at least one
ack-eliciting or PADDING frame, and have not been acked or declared
lost. The size does not include IP or UDP overhead, but does include the QUIC
header and AEAD overhead.  Packets only containing ACK frames do not count
towards bytes_in_flight to ensure congestion control does not impede
congestion feedback.</t>
  <t hangText='congestion_window:'>
  Maximum number of bytes-in-flight that may be sent.</t>
  <t hangText='recovery_start_time:'>
  The time when QUIC first detects a loss, causing it to enter recovery.
When a packet sent after this time is acknowledged, QUIC exits recovery.</t>
  <t hangText='ssthresh:'>
  Slow start threshold in bytes.  When the congestion window is below ssthresh,
the mode is slow start and the window grows by the number of bytes
acknowledged.</t>
</list></t>

</section>
<section anchor="initialization-1" title="Initialization">

<t>At the beginning of the connection, initialize the congestion control
variables as follows:</t>

<figure><artwork><![CDATA[
   congestion_window = kInitialWindow
   bytes_in_flight = 0
   recovery_start_time = 0
   ssthresh = infinite
   ecn_ce_counter = 0
]]></artwork></figure>

</section>
<section anchor="on-packet-sent" title="On Packet Sent">

<t>Whenever a packet is sent, and it contains non-ACK frames, the packet
increases bytes_in_flight.</t>

<figure><artwork><![CDATA[
   OnPacketSentCC(bytes_sent):
     bytes_in_flight += bytes_sent
]]></artwork></figure>

</section>
<section anchor="on-packet-acknowledgement" title="On Packet Acknowledgement">

<t>Invoked from loss detection’s OnPacketAcked and is supplied with the
acked_packet from sent_packets.</t>

<figure><artwork><![CDATA[
   InRecovery(sent_time):
     return sent_time <= recovery_start_time

   OnPacketAckedCC(acked_packet):
     // Remove from bytes_in_flight.
     bytes_in_flight -= acked_packet.size
     if (InRecovery(acked_packet.time_sent)):
       // Do not increase congestion window in recovery period.
       return
     if (IsAppLimited())
       // Do not increase congestion_window if application
       // limited.
       return
     if (congestion_window < ssthresh):
       // Slow start.
       congestion_window += acked_packet.size
     else:
       // Congestion avoidance.
       congestion_window += kMaxDatagramSize * acked_packet.size
           / congestion_window
]]></artwork></figure>

</section>
<section anchor="on-new-congestion-event" title="On New Congestion Event">

<t>Invoked from ProcessECN and OnPacketsLost when a new congestion event is
detected. May start a new recovery period and reduces the congestion
window.</t>

<figure><artwork><![CDATA[
   CongestionEvent(sent_time):
     // Start a new congestion event if the sent time is larger
     // than the start time of the previous recovery epoch.
     if (!InRecovery(sent_time)):
       recovery_start_time = Now()
       congestion_window *= kLossReductionFactor
       congestion_window = max(congestion_window, kMinimumWindow)
       ssthresh = congestion_window
]]></artwork></figure>

</section>
<section anchor="process-ecn-information" title="Process ECN Information">

<t>Invoked when an ACK frame with an ECN section is received from the peer.</t>

<figure><artwork><![CDATA[
   ProcessECN(ack):
     // If the ECN-CE counter reported by the peer has increased,
     // this could be a new congestion event.
     if (ack.ce_counter > ecn_ce_counter):
       ecn_ce_counter = ack.ce_counter
       // Start a new congestion event if the last acknowledged
       // packet was sent after the start of the previous
       // recovery epoch.
       CongestionEvent(sent_packets[ack.largest_acked].time_sent)
]]></artwork></figure>

</section>
<section anchor="on-packets-lost" title="On Packets Lost">

<t>Invoked by loss detection from DetectLostPackets when new packets
are detected lost.</t>

<figure><artwork><![CDATA[
   InPersistentCongestion(largest_lost_packet):
     pto = smoothed_rtt + max(4 * rttvar, kGranularity) +
       max_ack_delay
     congestion_period =
       pto * (2 ^ kPersistentCongestionThreshold - 1)
     // Determine if all packets in the window before the
     // newest lost packet, including the edges, are marked
     // lost
     return IsWindowLost(largest_lost_packet, congestion_period)

   OnPacketsLost(lost_packets):
     // Remove lost packets from bytes_in_flight.
     for (lost_packet : lost_packets):
       bytes_in_flight -= lost_packet.size
     largest_lost_packet = lost_packets.last()

     // Start a new congestion epoch if the last lost packet
     // is past the end of the previous recovery epoch.
     CongestionEvent(largest_lost_packet.time_sent)

     // Collapse congestion window if persistent congestion
     if (InPersistentCongestion(largest_lost_packet)):
       congestion_window = kMinimumWindow
]]></artwork></figure>

</section>
</section>
<section anchor="change-log" title="Change Log">

<t><list style='empty'>
  <t><spanx style="strong">RFC Editor’s Note:</spanx>  Please remove this section prior to
publication of a final version of this document.</t>
</list></t>

<t>Issue and pull request numbers are listed with a leading octothorp.</t>

<section anchor="since-draft-ietf-quic-recovery-18" title="Since draft-ietf-quic-recovery-18">

<t><list style="symbols">
  <t>Change IW byte limit to 14720 from 14600 (#2494)</t>
  <t>Update PTO calculation to match RFC6298 (#2480, #2489, #2490)</t>
  <t>Improve loss detection’s description of multiple packet number spaces and
pseudocode (#2485, #2451, #2417)</t>
  <t>Declare persistent congestion even if non-probe packets are sent and don’t
make persistent congestion more aggressive than RTO verified was (#2365,
#2244)</t>
  <t>Move pseudocode to the appendices (#2408)</t>
  <t>What to send on multiple PTOs (#2380)</t>
</list></t>

</section>
<section anchor="since-draft-ietf-quic-recovery-17" title="Since draft-ietf-quic-recovery-17">

<t><list style="symbols">
  <t>After Probe Timeout discard in-flight packets or send another (#2212, #1965)</t>
  <t>Endpoints discard initial keys as soon as handshake keys are available (#1951,
#2045)</t>
  <t>0-RTT state is discarded when 0-RTT is rejected (#2300)</t>
  <t>Loss detection timer is cancelled when ack-eliciting frames are in flight
(#2117, #2093)</t>
  <t>Packets are declared lost if they are in flight (#2104)</t>
  <t>After becoming idle, either pace packets or reset the congestion controller
(#2138, 2187)</t>
  <t>Process ECN counts before marking packets lost (#2142)</t>
  <t>Mark packets lost before resetting crypto_count and pto_count (#2208, #2209)</t>
  <t>Congestion and loss recovery state are discarded when keys are discarded
(#2327)</t>
</list></t>

</section>
<section anchor="since-draft-ietf-quic-recovery-16" title="Since draft-ietf-quic-recovery-16">

<t><list style="symbols">
  <t>Unify TLP and RTO into a single PTO; eliminate min RTO, min TLP and min crypto
timeouts; eliminate timeout validation (#2114, #2166, #2168, #1017)</t>
  <t>Redefine how congestion avoidance in terms of when the period starts (#1928,
#1930)</t>
  <t>Document what needs to be tracked for packets that are in flight (#765, #1724,
#1939)</t>
  <t>Integrate both time and packet thresholds into loss detection (#1969, #1212,
#934, #1974)</t>
  <t>Reduce congestion window after idle, unless pacing is used (#2007, #2023)</t>
  <t>Disable RTT calculation for packets that don’t elicit acknowledgment (#2060,
#2078)</t>
  <t>Limit ack_delay by max_ack_delay (#2060, #2099)</t>
  <t>Initial keys are discarded once Handshake are avaialble (#1951, #2045)</t>
  <t>Reorder ECN and loss detection in pseudocode (#2142)</t>
  <t>Only cancel loss detection timer if ack-eliciting packets are in flight
(#2093, #2117)</t>
</list></t>

</section>
<section anchor="since-draft-ietf-quic-recovery-14" title="Since draft-ietf-quic-recovery-14">

<t><list style="symbols">
  <t>Used max_ack_delay from transport params (#1796, #1782)</t>
  <t>Merge ACK and ACK_ECN (#1783)</t>
</list></t>

</section>
<section anchor="since-draft-ietf-quic-recovery-13" title="Since draft-ietf-quic-recovery-13">

<t><list style="symbols">
  <t>Corrected the lack of ssthresh reduction in CongestionEvent pseudocode (#1598)</t>
  <t>Considerations for ECN spoofing (#1426, #1626)</t>
  <t>Clarifications for PADDING and congestion control (#837, #838, #1517, #1531,
#1540)</t>
  <t>Reduce early retransmission timer to RTT/8 (#945, #1581)</t>
  <t>Packets are declared lost after an RTO is verified (#935, #1582)</t>
</list></t>

</section>
<section anchor="since-draft-ietf-quic-recovery-12" title="Since draft-ietf-quic-recovery-12">

<t><list style="symbols">
  <t>Changes to manage separate packet number spaces and encryption levels (#1190,
#1242, #1413, #1450)</t>
  <t>Added ECN feedback mechanisms and handling; new ACK_ECN frame (#804, #805,
#1372)</t>
</list></t>

</section>
<section anchor="since-draft-ietf-quic-recovery-11" title="Since draft-ietf-quic-recovery-11">

<t>No significant changes.</t>

</section>
<section anchor="since-draft-ietf-quic-recovery-10" title="Since draft-ietf-quic-recovery-10">

<t><list style="symbols">
  <t>Improved text on ack generation (#1139, #1159)</t>
  <t>Make references to TCP recovery mechanisms informational (#1195)</t>
  <t>Define time_of_last_sent_handshake_packet (#1171)</t>
  <t>Added signal from TLS the data it includes needs to be sent in a Retry packet
(#1061, #1199)</t>
  <t>Minimum RTT (min_rtt) is initialized with an infinite value (#1169)</t>
</list></t>

</section>
<section anchor="since-draft-ietf-quic-recovery-09" title="Since draft-ietf-quic-recovery-09">

<t>No significant changes.</t>

</section>
<section anchor="since-draft-ietf-quic-recovery-08" title="Since draft-ietf-quic-recovery-08">

<t><list style="symbols">
  <t>Clarified pacing and RTO (#967, #977)</t>
</list></t>

</section>
<section anchor="since-draft-ietf-quic-recovery-07" title="Since draft-ietf-quic-recovery-07">

<t><list style="symbols">
  <t>Include Ack Delay in RTO(and TLP) computations (#981)</t>
  <t>Ack Delay in SRTT computation (#961)</t>
  <t>Default RTT and Slow Start (#590)</t>
  <t>Many editorial fixes.</t>
</list></t>

</section>
<section anchor="since-draft-ietf-quic-recovery-06" title="Since draft-ietf-quic-recovery-06">

<t>No significant changes.</t>

</section>
<section anchor="since-draft-ietf-quic-recovery-05" title="Since draft-ietf-quic-recovery-05">

<t><list style="symbols">
  <t>Add more congestion control text (#776)</t>
</list></t>

</section>
<section anchor="since-draft-ietf-quic-recovery-04" title="Since draft-ietf-quic-recovery-04">

<t>No significant changes.</t>

</section>
<section anchor="since-draft-ietf-quic-recovery-03" title="Since draft-ietf-quic-recovery-03">

<t>No significant changes.</t>

</section>
<section anchor="since-draft-ietf-quic-recovery-02" title="Since draft-ietf-quic-recovery-02">

<t><list style="symbols">
  <t>Integrate F-RTO (#544, #409)</t>
  <t>Add congestion control (#545, #395)</t>
  <t>Require connection abort if a skipped packet was acknowledged (#415)</t>
  <t>Simplify RTO calculations (#142, #417)</t>
</list></t>

</section>
<section anchor="since-draft-ietf-quic-recovery-01" title="Since draft-ietf-quic-recovery-01">

<t><list style="symbols">
  <t>Overview added to loss detection</t>
  <t>Changes initial default RTT to 100ms</t>
  <t>Added time-based loss detection and fixes early retransmit</t>
  <t>Clarified loss recovery for handshake packets</t>
  <t>Fixed references and made TCP references informative</t>
</list></t>

</section>
<section anchor="since-draft-ietf-quic-recovery-00" title="Since draft-ietf-quic-recovery-00">

<t><list style="symbols">
  <t>Improved description of constants and ACK behavior</t>
</list></t>

</section>
<section anchor="since-draft-iyengar-quic-loss-recovery-01" title="Since draft-iyengar-quic-loss-recovery-01">

<t><list style="symbols">
  <t>Adopted as base for draft-ietf-quic-recovery</t>
  <t>Updated authors/editors list</t>
  <t>Added table of contents</t>
</list></t>

</section>
</section>
<section numbered="false" anchor="acknowledgments" title="Acknowledgments">

</section>


  </back>

<!-- ##markdown-source:
H4sIAC3nhlwAA8V9eXPb2JXv//dTIN1V01KHlEXJe+KeUSw78Yy3sdzTlUrl
6UEkJCEmAQYAJSuO57O/8zvLXQBQViqpep2qWCSBu5x79u1Op1PXld2yeJr9
98+vnmev67bNjouumHdlXWV5tcie19VF0fJH+rNr6qXLz86a4mr0Fbeo51W+
ovEWTX7eTcuiO5/+dVPOp00xr6+K5mY6e+IWeUdPHOzPnkz3D6ezmZvTFxd1
c/M0a7uFK9fN06xrNm13sL//ZP/A5U2RP80+NnnVruumc9d18+miqTdrWYNz
bUdLPc2XdUXj3hStW5dPsz919XyStfRCU5y39NfNSv6gNa7y9bqsLv7sXL7p
LuvmqcumLqP/yqp9mv3nXvbqpqgu8oa/kw39Z17lydd1c/E0e5m33fKGPxer
vFw+zf7SlHvY9n9c4PPevF7xrwQ4GqRYlF3dJJO92stOrouui6Z6lVfRdzzP
7+v6YlnE85QEDTzzHxf80/hErqqbVd6VV8VTR78CWtOPH47enrx/9+HjU35e
z/87/PY0O8p+Pn4//V3eFovszWbZletl8Zn+BiqcFPNNU4Rz+I7fHxwmvmyL
pizasjqvZZIse1V1RVMV3fQYiDHEj85GBYLgBX8w/N9U/x0/oVtOaeykhucx
NsebvezjZb1qCavTOd7kTVdWgx95ljf138rlMh+fxp/A65MU9j8TqC4y+jrr
agMznvzXQnjZ3gm2//p9j05zQtNsaL39EzwpCPt7v/AUbXXYLLYAFnCIEf3l
0fP/SkH8sm6u82aRHc0/VfX1slhcFKuiIjB9KM7LisH//P0It/tuDGAeUG/y
7rJs06//E19fLvKrMjq92ZMnD6f7j/tHlx09f5OdvPr983dv3jg3nU6z/Kwl
Uph3zn2kkcGrNlhntijaeVOeFW22BMddJEx6HpY9l2Vnq2J+mVdlu2ozAo0D
Nu3JDFXdFadv8X9dffqhyBdF0zp3XLbzTdtiiPo863huIFDW5Z9o0vUynxcZ
/dhdCmpmYMIAGzPiDDwJn5Zl27kd4Nt/APP26OR2J9n1ZTm/zGjIvJlf0hkR
P+ncby+7bt0+vXcP7+oPe/bSPXxxry34n39nlneKsZ9h6J9oJ7/o9L/n6f35
AwKEP2cF7XpTYZ7Mz3NRdpebMzDKexjl+uKn35B42DTzws3rRcGQLNt2AxjT
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
H/JsPM2Z4QAA

-->

</rfc>

