| Internet-Draft | standard-cc-analysis | October 2026 |
| Nishida | Expires 25 April 2027 | [Page] |
The IETF currently has three Standards Track specifications of loss-based congestion control: Reno-based congestion control for TCP (RFC 5681), its counterpart for QUIC (RFC 9002), and CUBIC (RFC 9438), which updates RFC 5681. They are intended to follow the same congestion control principles, but they differ in their mechanisms, parameters, and normative requirements, and these differences have not been reconciled with each other. This document identifies such differences, summarizes whether and how each of them is documented in the specifications, and asks the IETF to determine for each difference whether to work toward convergence or accept it as is.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 25 April 2027.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
[RFC5681] specifies Reno-based congestion control and it has been referred as the standard document from IETF that outlines congestion control principle of the Internet. Since then, IETF has published two more Standards Track congestion control specifications; [RFC9002] as Reno-based congestion control for QUIC [RFC9000] and [RFC9438] as CUBIC congestion control, which updates RFC5681. We believe all transport protocols should share the same congestion control principle so that they can share network resources mostly fairly. In our study, these specifications mostly follow the principles described in [RFC5681], however, there are certain differences in their schemes, constant values, and normative requirements.¶
This document focuses on the congestion control schemes specified in Standards Track RFCs. Other schemes, such as BBR [I-D.ietf-ccwg-bbr], which is still under discussion in the IETF and is intended for Experimental status, are out of scope.¶
RFC9438 notes that "it is not obvious" whether CUBIC's differences from previous Standards Track congestion control go beyond the general principles in [RFC2914]. This illustrates that there is currently no concrete reference for where the standard congestion control schemes agree or differ. Some differences are documented in the specifications together with their rationale, while others are not acknowledged in any of them, such as the differences in the response to ECN signals and in the normative strength of the same safeguard between RFC9002 and RFC9438. We believe these differences should be understood and, where appropriate, resolved, as they affect the consistency of congestion control across transport protocols and the evaluation of new congestion control algorithms against the standard ones.¶
This document does not provide evaluations of the performance impacts of these differences. Some differences described in the document might be proved to be negligible in further analysis, while others may need to be updated to avoid conflicts between the standards.¶
This document asks the working group to review the differences summarized in Section 4, and to determine for each of them whether the specifications should work toward convergence or accept it as is, and if convergence is needed, in which documents.¶
We think there are the following differences between RFC9002 and RFC5681.¶
RFC5681 specifies the upper bound of Initial Window (IW) in segments, depending on SMSS: 4 segments if SMSS is at most 1095 bytes, 3 segments if SMSS is larger than 1095 bytes and at most 2190 bytes, and 2 segments otherwise. This is based on [RFC3390], which specifies the upper bound as min(4*MSS, max(2*MSS, 4380 bytes)); for the common SMSS of 1460 bytes, both give 3 segments (4380 bytes).¶
RFC9002 recommends an IW of 10 times max_datagram_size, limited to the larger of 14720 bytes or twice max_datagram_size, following [RFC6928]. The 14720-byte limit only takes effect when max_datagram_size exceeds 1472 bytes, so on typical paths the IW is simply 10 datagrams (e.g., 12000 bytes for 1200-byte datagrams).¶
[RFC6928] allows TCP to use a similar IW of min(10*MSS, max(2*MSS, 14600 bytes)), but it is an Experimental specification and is not reflected in RFC5681.¶
RFC5681 specifies Loss Window Size to be 1 segment while RFC9002 uses 2 segments for it. As Section 4.8 in RFC9002 describes, using 2 segments for Loss Window can reduce the chance of waiting for a PTO and avoid additional delays caused by delayed ack algorithm. However, this could mean when an RFC5681 connection and an RFC9002 connection experience a timeout at the same time (RTO in TCP, persistent congestion in QUIC), the RFC9002 connection can recover congestion window size more than 2 times faster than the RFC5681 connection. RFC9438 follows RFC5681 in this respect, as it reduces the congestion window in the same way as RFC5681 upon a timeout (Section 4.8 of RFC9438).¶
RFC5681 and RFC9438 base the slow-start threshold after packet loss on FlightSize, while RFC9002 bases it on congestion window.¶
In RFC5681, a sender sets the slow-start threshold based on FlightSize, as it requires the slow-start threshold to be set to no more than max(FlightSize / 2, 2*SMSS) (Section 3.1 of RFC5681). RFC5681 also states:¶
" Implementation Note: An easy mistake to make is to simply use cwnd, rather than FlightSize, which in some implementations may incidentally increase well beyond rwnd. "¶
We presume this note stemmed from the fact that there were some implementations which increment congestion window on every acknowledgment even though receiver's window was fully subscribed in the past.¶
In contrast, RFC9002 requires a sender to set the slow-start threshold to the half value of the congestion window when packet loss is detected (Section 7.3.2 of RFC9002). RFC9438 sets the slow-start threshold to FlightSize multiplied by β (0.7) by default, but also allows to use congestion window instead of FlightSize (Section 4.6 of RFC9438).¶
For a sender that fully utilizes its congestion window, FlightSize and congestion window are nearly equal, and the two give similar results. For a rate-limited sender, however, FlightSize can be much smaller than congestion window, and RFC9002 sets a higher slow-start threshold than RFC5681. The safeguard described below prevents congestion window from growing while it is underutilized, but it does not reduce it. RFC5681 recommends reducing congestion window to the restart window when the sender has not sent data for longer than the retransmission timeout (Section 4.1 of RFC5681), while RFC9002 has no such mechanism, so an RFC9002 sender may calculate the slow-start threshold from a congestion window that was validated long before.¶
When congestion window is used as the base, both RFC9002 and RFC9438 rely on a safeguard that prevents congestion window from growing while it is underutilized, so that the slow-start threshold is not calculated from a congestion window that has grown larger than the amount of data the network has actually carried. However, the two specifications describe this safeguard differently:¶
RFC9438 uses FlightSize by default for QUIC as well as TCP, which shows that QUIC does not require congestion window here. RFC9002 does not mention that its choice differs from RFC5681.¶
In RFC9002, when a sender is in slow start, the congestion window increases by the number of bytes acknowledged on each acknowledgment segment arrival. On the other hand, RFC5681 increases congestion window by at most 1 full segment. RFC5681 mentions RFC3465 [RFC3465] which uses similar method to RFC9002, however RFC5681 does not recommend to use it. In addition, RFC3465 defines the limited factor: L which controls the aggressiveness of the algorithm. RFC3465 recommends to use L=2. This means it can allow to increase congestion window by at most 2 full segments. This logic in RFC5681 is overridden by [RFC9406] when hystart++ is activated in the connection. When hystart++ is enabled, as long as some packet pacing mechanisms are used in the connection, congestion window can be increased by the amount of acknowledged data in an ACK packet like RFC9002. However, the increase of congestion window per ACK is limited to 8 SMSS if there is no pacing. The performance differences in this logic will be more visible in the presence of stretch ACKs.¶
The gist of the loss recovery algorithm in RFC5681 is to retransmit all lost segments found in the previous round trip and once all of them have been acknowledged, it migrates to Congestion Avoidance from Recovery period. The detailed algorithms are specified in [RFC6582] and [RFC6675].¶
On the other hand, RFC9002 specifies the ends of Recovery period as when one of any packets sent during the Recovery period is acknowledged. This means RFC9002 can end Recovery period even not all lost segments in the previous round trip has been successfully retransmitted. Moreover, it can end Recovery period even if some segments have been lost during Recovery period as long as one or more packets have been acknowledged.¶
As Section 4.3 of RFC9002 describes, this difference makes RFC9002 respond to repeated losses more often than RFC5681. Because both reduce their congestion windows only once per recovery period, RFC9002 reduces its congestion window once for every round trip that experiences loss, while RFC5681 may reduce it only once across multiple round trips, for example when a segment is lost multiple times in a row. RFC9002 attributes this difference to the protocol differences between QUIC and TCP (Section 4.3 of RFC9002).¶
Another aspect of the loss recovery in RFC9002 is persistent congestion that is equivalent to TCP's RTO. In RFC9002, data sender establishes persistent congestion only when all sent packets are lost for a long enough duration. This period is equivalent to the duration for an RTO and two TLPs[RFC8985] in TCP. This will mean RFC9002 reduces congestion window to minimal value only when there is a extreme severe congestion. On the other hand, RFC5681 has more chances for RTOs as it gets RTOs when fast retransmission/fast recovery scheme doesn't work due to insufficient number of acknowledgments.¶
In RFC9002, in addition to acknowledgment-based loss detection scheme which is also defined in RFC5681, it specifies another loss detection scheme similar to RACK-TLP[RFC8985]. Although RACK-TCP is a standard document, RFC5681 has no description for it.¶
RFC9002 follows most of the parts of [RFC6298] which defines the standard algorithm of retransmission timer computations and managements for TCP. However, it does not follow 1 sec for minimal RTO values in RFC6298 as it does not specify minimal RTO. This might not be a major problem because it is known that various TCP implementations already adopt lower values for minimal RTO. In addition, QUIC has more explicit mechanism to identify spurious RTOs than TCP, hence we believe there is no risk for large-scale network issues in this. However, the impacts for not having minimum RTO is still an important research topic for the performance and efficiency of transport protocols.¶
RFC5681 does not itself specify a response to Explicit Congestion Notification; it defers entirely to [RFC3168], which requires a TCP sender that receives an ECN-Echo (ECE) ACK to treat it just as a packet drop, halving cwnd and reducing ssthresh in the same way as on loss. RFC9002 instead specifies its own response to a CE increase in Section 7.1, and treats it identically to loss throughout its congestion control state machine: a CE increase causes a sender to exit slow start and enter a recovery period in the same way as a lost packet (Sections 7.3.1 and 7.3.2 of RFC9002, Figure 1).¶
Both RFC3168 and RFC9002 intend that a sender reduce its congestion window at most once per round trip in response to CE, to avoid reacting multiple times to congestion signals from a single window of data. However, they specify this intent very differently. RFC9002 makes it part of its normative state machine: once a recovery period starts, whether from loss or from a CE increase, it suppresses further reduction from either cause until a packet sent during the recovery period is acknowledged (Section 7.3.2 of RFC9002), and Appendix B of RFC9002 gives this as executable pseudocode. RFC3168 states the same once-per-window intent only in lower case: "TCP should not react to congestion indications more than once every window of data" (Section 6.1.2 of RFC3168). RFC9438 relies on this RFC3168 text for CUBIC's response to ECE and does not restate the rule in its own normative language.¶
RFC9438 explicitly requires a CUBIC sender to keep reducing cwnd on each ECE-indicated congestion event until it reaches a floor of 1 SMSS, and to then fall back on a retransmission timer with exponential backoff (Section 4.6 of RFC9438). RFC3168 reaches the same floor by a different route: its general rule reduces cwnd by half at most once per window of data in response to CE (Section 6.1.2 of RFC3168), which drives cwnd toward 1 MSS under sustained marking, and RFC3168 separately specifies the timer-reset behavior once cwnd has reached that floor. RFC9002 has no equivalent handoff to a backoff timer: its minimum congestion window is 2 * max_datagram_size regardless of whether a reduction was caused by loss or a CE increase, a CE increase by itself never triggers persistent congestion (Section 7.6 of RFC9002), and a CE-marked ACK is still a received acknowledgment, so it does not arm or back off the probe timeout described in Section 6.2 of RFC9002 either. Consequently, a sustained CE signal without any packet loss holds an RFC9002 sender's congestion window at 2 * max_datagram_size indefinitely, with no mechanism to reduce the sending rate further. RFC9002 also cites [RFC8311], which permits congestion responses other than the one specified in RFC3168, so this is not by itself a departure from RFC3168; however, no document currently reconciles the resulting difference in behavior between RFC9438 and RFC9002 under persistent CE marking without loss.¶
None of RFC5681, RFC9002, or RFC9438 discusses how its own response to CE compares with the other two.¶
We think the following points in the CUBIC specification can cause differences behavior from RFC5681.¶
The CUBIC specification [RFC9438] uses 0.7 for Multiplicative Window Decrease factor while RFC5681 uses 0.5. We think the rationale for using 0.5 in RFC5681 is derived from the following sentences in [Jac88], hence we presume using 0.7 instead will not be too aggressive to lead to a congestion collapse. However, it can still be more aggressive than RFC5681 which may cause unfair resource sharing.¶
" We usually run our nets with ρ ≤ 0.5 so it’s probable that there are now exactly two conversations sharing the bandwidth. I.e., you should reduce your window by half because the bandwidth available to you has been reduced by half. And, if there are more than two conversations sharing the bandwidth, halving your window is conservative "¶
In order to compensate the aggressiveness by using the aggressive decrease factor, CUBIC uses "Reno-friendly model" which employs slower window growth rate in low BDP environments. We will discuss the validity of the model in the following section, however, even if the model is valid, CUBIC can be more aggressive than RFC5681 in some situations. For example, when there are a congestion that can last several round trips, CUBIC reduces congestion window by 30% every round trip while RFC5681 reduces it by half. In this situation, the window decrease rate for CUBIC will be mostly the half of RFC5681's. In addition, during Recovery period, CUBIC transmits data with 70% of the previous congestion window size while RFC5681 uses 50% of it.¶
Another example is that congestion window size can be much larger than network capacity during slow start and CUBIC's high decrease factor may have more impacts than RFC5681. For example, let's say network capacity is 100Mbps and a TCP sender's congestion window size at a certain round trip allows to transfer data at 99Mbps, which is lower than the capacity. If this sender is in slow-start, the congestion window size may glow to transfer data at 198Mbps in the next round trip and can cause many packet losses. In case of RFC5681, congestion window will be reduced by half in the following round trip and transfer rate will be 99Mbps. However, in case of CUBIC, the transfer rate will be 138.6Mbps which still exceeds the network capacity. This would mean CUBIC can saturate network for two round trips in this example while RFC5681 does only for one round trip. However, this might be a pathological example since many recent transport stacks support pacing mechanism and [HyStart] or [RFC9406] to mitigate the overshooting during slow-start.¶
CUBIC employs Reno-friendly model which is designed to be fair to RFC5681 in low BDP environments. The model in CUBIC is derived from [FHP00] and it is based on AIMD congestion control as same as RFC5681, but adopts different increase factor α and multiplicative factor β. In RFC5681, α is 1.0 and β is 0.5. This means RFC5681 increases congestion window by about 1 segment per round-trip time when a transport protocol is in congestion avoidance and reduces congestion window by half when packet losses are detected. In the meantime, in [RFC9438], α is around 0.529 and β is 0.7. Hence, CUBIC reduces congestion window less than RFC5681 at packet loss, but at the same time, it reduces the window growth rate so that the performance of CUBIC and RFC5681 will be mostly the same.¶
We explain the rationale behind the values for α and β for CUBIC in Appendix "Appendix A: Deriving increase factor for CUBIC from AIMD model", but the important point for using these values is that it is based on the following two presumptions.¶
Although the first presumption can be considered as a common situation, the second presumption will not be a common one as there should be various patterns in packet losses. Moreover, in this model, CUBIC increases congestion window by 0.529 segments per round-trip time, which means CUBIC adds one segment to its flight roughly every two round trips while RFC5681 does so every round trip, because a transport protocol usually does not send a segment until it has at least one full segment space available in congestion window. This makes harder to establish the second presumption even more.¶
This might be a relatively minor point that do not have significant impacts on overall performance of the model, however, more detailed analysis with realistic packet dynamics will be desirable. A recent report on this point shows that the model in CUBIC looks mostly fair to RFC5681 in low BDP environments [AIMD-friendliness].¶
Table 1 summarizes the differences described in this document, together with where the specifications document them. We ask the working group to determine for each difference whether the specifications should work toward convergence or accept it as is. Differences that are not documented in any of the specifications may be unintentional, and we believe they should be discussed first.¶
| # | Difference | Section | Summary | Documented in |
|---|---|---|---|---|
| 1 | Initial window | 2.1 | 2-4 segments (RFC5681) vs 10 datagrams (RFC9002) | RFC9002, Sec. 7.2, following RFC6928 |
| 2 | Minimum window after timeout | 2.2 | 1 segment (RFC5681, RFC9438) vs 2 datagrams (RFC9002) | RFC9002, Sec. 4.8 |
| 3 | Basis of ssthresh after loss | 2.3 | FlightSize (RFC5681, RFC9438) vs cwnd (RFC9002) | Not documented |
| 4 | Safeguard for underutilized cwnd | 2.3 | Recommended (RFC9002) vs required (RFC9438); pacing exception only in RFC9002 | Not documented |
| 5 | cwnd after an idle period | 2.3 | Restart window (RFC5681) vs no mechanism (RFC9002) | Not documented |
| 6 | Slow-start increase per ACK | 2.4 | At most SMSS (RFC5681) vs bytes acknowledged (RFC9002) | Not documented |
| 7 | End of recovery period | 2.5 | Lost segment acknowledged (RFC5681) vs packet sent in recovery acknowledged (RFC9002) | RFC9002, Sec. 4.3 and 7.3.2 |
| 8 | Congestion window collapse on timeout | 2.5 | On RTO (RFC5681) vs on persistent congestion (RFC9002) | RFC9002, Sec. 4.7 |
| 9 | Time-based loss detection | 2.6 | Not in RFC5681 (RFC8985 for TCP); threshold 9/8 (RFC9002) vs 5/4 (RFC8985) | RFC9002, Sec. 6.1 and 6.1.2 |
| 10 | Minimum timeout | 2.7 | 1 second (RFC6298) vs peer's max_ack_delay (RFC9002) | RFC9002, Sec. 4.7 |
| 11 | Response to ECN-CE | 2.8 | Once-per-RTT rule informal (RFC3168) vs normative (RFC9002); 1 SMSS then timer backoff (RFC9438) vs 2 datagrams (RFC9002) | Not documented |
| 12 | Multiplicative decrease factor | 3.1 | 0.5 (RFC5681) vs 0.7 (RFC9438) | RFC9438, Sec. 3.4 and 4.6 |
| 13 | Reno-friendly increase factor | 3.2 | 1 (RFC5681) vs about 0.529 (RFC9438) | RFC9438, Sec. 4.3 |
This document does not specify any protocol or mechanism. Security considerations will be discussed in a future version of this document, based on feedback from the working group.¶
This document has no IANA actions.¶
The author would like to thank the members of the CCWG and TCPM working groups for their feedback.¶
This appendix derives the increase factor α used in the Reno-friendly model of CUBIC from a simple AIMD model. RFC9438 gives the value of α using the average window formula in [FHP00] (Section 4.3 of RFC9438). This appendix derives the same value by comparing the congestion epochs of the two AIMD models, in order to make the assumptions behind the model explicit. In particular, equation (2) below requires that the two models have the same congestion epoch, which corresponds to the second presumption discussed in Section 3.2: both connections lose packets at the same time.¶
We define AIMD(α, β) as AIMD congestion control that uses an increase parameter α and a decrease parameter β. Hence, AIMD(1, 0.5) represents congestion control described in RFC5681 while CUBIC can be expressed as AIMD(α, β) where β=0.7. We also define Wmax as the congestion window size that can fully utilize network capacity.¶
At first, it is clear that β=0.7 is more aggressive than β=0.5 when there is no other traffic. As cwnd growth is linear, if there's enough long time for the data transfer, the average congestion window for β =0.5 will be (1.0 + 0.5)/2 = 0.75 Wmax and it will be (1.0 + 0.7)/2 = 0.85 Wmax for β=0.7. Hence, it is obvious that this model does not aim for the cases where there's no other traffic.¶
The choice of (α, β) for CUBIC is designed to be fair only when it competes with AIMD(1.0, 0.5). Here, we define W1 as the max window size for AIMD(1.0, 0.5) and W2 as the max window size for CUBIC's AIMD(α=X, β =0.7) when they compete each other. In this situation, AIMD(1.0, 0.5) model oscillates between 0.5 W1 and 1.0 W1 in a congestion epoch. CUBIC's AIMD (α=X, β =0.7) model oscillates between 0.7 W2 and 1.0 W2 in the same congestion epoch. When these two models have the same loss ratio, it should satisfy the following equation (1).¶
(1.0 + 0.5) W1 = (1.0 + 0.7) W2 (1)¶
Also, in one congestion epoch, (α=1.0, β =0.5) increases congestion window by 0.5 W1 while (α=X, β =0.7) increases 0.3 W2. The length of congestion epoch for AIMD(1.0, 0.5) can be expressed as 0.5 W1/1.0 and it will be expressed as 0.3 W2 /X for AIMD(α=X, β =0.7). Because AIMD(1.0, 0.5) and AIMD(α=X, β =0.7) should have the same congestion epoch when they compete equally, it should satisfy the following equation (2).¶
0.5 W1 / 1.0 = 0.3 W2 / X (2)¶
From equations (1) and (2), we get X=0.529.¶
The contents in this documents are the individual contributions from the authors and do not relate to the authors' positions at their affiliations.¶