CUBIC for Fast and Long-Distance Networks
Extracted elements (29)
C=0.4 was chosen based on the observation that at RTT=0.01s CUBIC with C≤0.4 achieves exactly the same average window as Reno (Reno-friendly), while C=4 becomes more aggressive. Tables 1–2 show CUBIC with C=0.4 is substantially more Reno-friendly than HSTCP across all tested loss rates.
CUBIC does not increase its congestion window if a flow is application-limited. The time variable t in W_cubic(t) explicitly excludes idle or rate-limited periods; otherwise, W_cubic would be unreasonably high after restarting, causing overshoot.
CUBIC is designed to behave like Reno in networks with short RTTs and small BDPs (the Reno-friendly region). When the cubic function would increase cwnd less aggressively than Reno, CUBIC simply follows Reno's window size, ensuring at least the same throughput as Reno in those environments.
CUBIC sets β_cubic to 0.7 rather than Reno's 0.5 to balance scalability and convergence speed. The higher value improves scalability but slows convergence under low statistical multiplexing; this tradeoff is acceptable because the modern Internet is more asynchronous with less frequent loss synchronizations under high multiplexing.
CUBIC uses both the concave and convex profiles of a cubic function for window growth rather than a purely convex increase. This keeps the window nearly constant around the remembered W_max, promoting stability and high utilization while avoiding the packet bursts at the saturation point that purely convex functions cause.
As a loss-based algorithm, CUBIC suffers in networks where packet loss is not a good indicator of bandwidth utilization, such as wireless or mobile networks. CUBIC can also fill large drop-tail buffers more quickly than Reno; proper queue sizing and AQM (RFC 7567) can mitigate this.
CUBIC can also be used as a default congestion controller for other transport protocols such as QUIC (RFC 9000) and SCTP (RFC 9260), not only for TCP.
CUBIC requires only sender-side changes and works correctly with Reno receivers. It does not require any changes at receivers or routers, making incremental deployment straightforward.
This document updates RFC 5681 Section 3 by replacing the restriction limiting cwnd increments to at most SMSS per RTT with a normative reference to RFC 5033 guideline (1), which permits CUBIC's occasionally more aggressive cwnd increases during congestion avoidance and slow start.
A QUIC sender that uses a cwnd value (rather than flight_size) to calculate new cwnd and ssthresh after detecting a congestion event is REQUIRED to apply similar mechanisms as defined in RFC 9002.
C SHOULD be set to 0.4 to balance Reno-friendliness and aggressiveness of window increase. It is NOT RECOMMENDED to set C to a very low value such as 0.04, as CUBIC with a low C cannot efficiently use bandwidth in fast and long-distance networks.
CUBIC MUST continue to reduce cwnd in response to ECN-Echo ACKs until cwnd reaches 1 SMSS. If congestion persists at cwnd = 1 SMSS, the sender MUST reduce its sending rate further using a retransmission timer with exponential backoff.
Fast convergence SHOULD be implemented in multi-flow environments. In environments with only a single CUBIC flow and no other traffic, fast convergence SHOULD be disabled.
Implementations using cwnd (rather than flight_size) to calculate new ssthresh MUST use other measures to prevent cwnd from growing when bytes in flight is smaller than cwnd, to avoid using an arbitrarily high cwnd when congestion is detected.
In the concave region (cwnd < W_max, not Reno-friendly), cwnd MUST be incremented by (target − cwnd) / cwnd for each received new ACK, where target is W_cubic(t + RTT) as computed in Section 4.2.
In the convex region (cwnd ≥ W_max, not Reno-friendly), cwnd MUST be incremented by (target − cwnd) / cwnd for each received new ACK. This "maximum probing phase" very slowly probes for a new W_max.
The elapsed time t in W_cubic(t) MUST NOT include periods during which cwnd has not been updated due to application-limited behavior, to prevent an artificially inflated target after idle periods.
Upon detecting packet loss, the sender MUST reduce cwnd and ssthresh immediately upon entering loss recovery. β_cubic SHOULD be set to 0.7; ssthresh = flight_size * β_cubic, and cwnd is reduced to max(ssthresh, 2) on loss or max(ssthresh, 1) on ECN-Echo.
When cwnd ≤ ssthresh, CUBIC MUST employ a slow start algorithm. CUBIC SHOULD use HyStart++ (RFC 9406) or MAY use Reno slow start in rare cases where HyStart++ is not suitable.
When W_cubic(t) < W_est (the Reno-friendly region), cwnd SHOULD be set to W_est at each reception of a new ACK during congestion avoidance.
Fast convergence: when a congestion event occurs and cwnd < W_max (indicating the saturation point is shrinking), W_max is further reduced to cwnd*(1+β_cubic)/2 before applying the multiplicative decrease, lengthening the time this flow needs to recover and giving new flows more room to grow.
For spurious fast retransmits, a CUBIC implementation MAY save state (cwnd, cwnd_prior, ssthresh, W_max, K, t_epoch, W_est) before reducing the window. If the loss is confirmed spurious and current cwnd < cwnd_prior, these saved values MAY be restored to recover performance.
In the Reno-friendly region, W_est estimates the Reno congestion window via W_est += α_cubic * (segments_acked / cwnd), where α_cubic = 3*(1−β_cubic)/(1+β_cubic). Once W_est ≥ cwnd_prior, α_cubic SHOULD be set to 1 to match Reno's AIMD(1, 0.5) increment rate.
K is computed as the cube root of (W_max − cwnd_epoch) / C, representing the time needed to grow from the congestion-avoidance starting window back to W_max. Upon a timeout, K is set to 0 and W_max is set to cwnd at the start of the congestion avoidance stage.
On each new ACK in congestion avoidance, target = W_cubic(t+RTT) bounded below by cwnd (non-decreasing) and above by 1.5*cwnd (below the slow-start rate). CUBIC then picks the maximum of W_cubic(t) and W_est as the effective window.
On timeout, CUBIC follows Reno's cwnd reduction but sets ssthresh using β_cubic. The subsequent congestion avoidance uses W_cubic(t) with K=0 and W_max = cwnd at the start of congestion avoidance; W_est is also initialized to that cwnd for the Reno-friendly region.
The CUBIC window increase function is W_cubic(t) = C*(t−K)^3 + W_max, where t is elapsed time from the start of the current congestion avoidance stage, K is the time to grow back to W_max, C is the aggressiveness constant, and W_max is the window at the last congestion event.
When CUBIC exits the first slow start via HyStart++ without packet loss, W_max is undefined; CUBIC sets cwnd_prior = cwnd, switches to congestion avoidance, and uses W_cubic(t) with K=0 and W_max set to the congestion window at the start of congestion avoidance.
CUBIC makes no changes to the underlying security of a transport protocol and inherits the general security concerns of RFC 5681. An attacker can drop or inject ACKs to force the CUBIC implementation to reduce its bandwidth or to mask congestion; these attacks are not new to CUBIC and are inherent to TCP.