skip to content

Why does a TCP Reno flow take minutes to regain its window on a 1 Gbps, 100 ms path after one loss, and how does CUBIC's growth change that?

level: seniorimportance: nice to knowfreq 18%

answer

  1. bandwidth times delay, in packets
  2. one segment per round trip
  3. thousands of round trips
  4. growth by time, not by RTT
  5. plateau at the old maximum

basics

~20 s

A 1 Gbps, 100 ms path needs about 8,333 full-sized packets in flight; after halving, Reno adds one segment per round trip, so it needs about 4,167 round trips, roughly 7 minutes. CUBIC cuts less and regrows along a time-based cubic curve.

solid answer

~50 s

The bandwidth-delay product is 1 Gbps x 0.1 s = 12.5 MB, about **8,333 packets** of 1500 bytes. After one loss Reno halves to about 4,167, then congestion avoidance adds **one segment per round trip**, so it needs about 4,167 round trips, around **7 minutes**, to refill the path. RFC 9438 computes that Reno needs a loss rate of about 2 x 10^-8 to average 1 Gbps there. **CUBIC** (RFC 9438) reduces only to 0.7 and grows along `W_cubic(t) = C*(t-K)^3 + W_max` with `C = 0.4`: fast at first, flattening near the old maximum `W_max`, then probing beyond it. Because growth depends on **elapsed time** rather than round trips, it regains the window in tens of seconds on this path and is less RTT-unfair. On short-RTT or small-BDP paths it falls back to Reno-like growth.

go deeper

for a junior

Recall that bandwidth times delay tells you how much data must be in flight, and that Reno grows by only one segment per round trip after a loss.

for a middle

Compute a path's BDP in packets and the number of round trips Reno needs to regain half of it.

for a senior

Use the recovery arithmetic to explain why one long-distance flow underperforms, and describe CUBIC's concave-then-convex curve and its 0.7 reduction.

for a principal

Weigh CUBIC's faster recovery against slower convergence between flows and deeper queues, and when a single-flow design should use parallel flows or a different algorithm.

## The size of the pipe The **bandwidth-delay product** (BDP) is how much data must be in flight to keep a path full: - 1 Gbps x 100 ms = 10^8 bits = **12.5 MB**. - With 1500-byte packets that is about **8,333 packets**, the figure RFC 9438's Table 3 lists as the average window for 1000 Mbps at a 0.1 s RTT. To run at full rate a sender needs `cwnd` near 8,333 segments. Getting there once is not the problem; slow start does it in roughly a dozen round trips. The problem is getting back after each loss. ## Reno's recovery arithmetic Reno-style congestion control (RFC 5681) reacts to a loss detected by duplicate ACKs by halving, then grows in **congestion avoidance** by about one full-sized segment per round trip: 1. Window before the loss: about 8,333 segments. 2. After the multiplicative decrease: about 4,167 segments. 3. Segments to regain: about 4,167. 4. At one segment per 100 ms round trip: about 4,167 round trips, **about 417 seconds, roughly 7 minutes**. For the average to stay near 1 Gbps, the flow must therefore go minutes between losses. RFC 9438 puts the required loss rate for Reno at 1000 Mbps at about **2.0 x 10^-8**, around one loss per fifty million packets, and at 10 Gbps about 2.0 x 10^-10. Any real path loses packets more often than that, so a single Reno flow averages well below capacity. RFC 9438 describes this low utilization over fast, long-distance networks as the problem CUBIC was designed to fix, and notes it applies to every standard with the same linear increase. ## CUBIC's window function CUBIC keeps slow start, fast retransmit and fast recovery but changes two things. **A gentler cut.** On a congestion event CUBIC records the window as `W_max` and reduces with a multiplicative decrease factor `beta_cubic` = **0.7** rather than 0.5. **Growth by elapsed time.** In congestion avoidance the target window follows: - `W_cubic(t) = C * (t - K)^3 + W_max` - `t` is the time in seconds since the current congestion avoidance stage began; - `C` = **0.4** (RFC 9438 SHOULD); - `K` = the cube root of `(W_max - cwnd_epoch) / C`, the time the curve takes to climb back to `W_max`. The curve is **concave** up to `W_max`: fast at first, flattening as it nears the level where the last loss happened, so the window sits near the known good size for a long time. Past `K` it turns **convex** and accelerates, probing for capacity that may have appeared. ## The same path under CUBIC 1. `W_max` about 8,333 segments; after the 0.7 reduction `cwnd_epoch` is about 5,833. 2. Gap: about 2,500 segments. 3. `K` = cube root of (2,500 / 0.4) = cube root of 6,250, about **18.4 seconds**. | | Reno (RFC 5681) | CUBIC (RFC 9438) | |---|---|---| | Window after loss | about 4,167 segments | about 5,833 segments | | Growth rule | +1 segment per RTT | cubic in elapsed time | | Time back to the old maximum | about 417 s | about 18.4 s | | Loss rate needed for 1 Gbps | about 2.0 x 10^-8 | about 6.3 x 10^-7 | ## Fairness and friendliness - **RTT-fairness.** Reno's growth is per round trip, so a flow with a shorter RTT grows faster and takes more of a shared bottleneck. CUBIC's increase rate is independent of RTT outside its Reno-friendly region, which RFC 9438 describes as giving a throughput ratio linear in the inverse RTT ratio. - **Reno-friendly region.** On short-RTT or small-BDP paths, where Reno already performs well, CUBIC tracks an estimate of what Reno would do and uses that when it is larger, so it is at least as fast as Reno and matches it where Reno already does well. - **The cost.** The 0.7 factor slows convergence between competing flows, and RFC 9438 notes CUBIC fills deep drop-tail buffers faster than Reno because it is still loss-based.

  • Why does raising the receive window not fix Reno's slow recovery on this path?
    Because `rwnd` is only a ceiling. Once the receiver allows 8,333 segments, the binding limit after a loss is the halved `cwnd`, and congestion avoidance regrows it by one segment per round trip regardless of how large `rwnd` is.
  • Is CUBIC more aggressive than Reno on a 10 ms LAN path?
    Not meaningfully. RFC 9438's tables show that at short RTTs CUBIC's average window matches Reno's over most loss rates, because in the Reno-friendly region it follows its estimate of Reno's window. The advantage appears on large-BDP paths, where Reno's linear growth is too slow.

saying these in an interview costs you the question

  • After a loss, Reno doubles back to full speed within a few round trips.
  • CUBIC grows by one segment per RTT, just more often than Reno.
  • CUBIC cuts its window to 0.3 of its size after a loss.
  • A larger receive window alone lets Reno fill a high-BDP path.
  • Reno's recovery time after a loss is the same in seconds whatever the RTT.