Networking · Congestion Control
RTT Fairness: Why Shorter Paths Win and How Algorithms Compensate
Two flows on the same bottleneck with different round trips do not get equal shares, and the bias is a direct consequence of the control law. The fixes trade that bias against stability.
The convergence result behind additive increase and multiplicative decrease assumes that all flows share the same capacity and the same round trip. The first assumption is approximately true when flows share a bottleneck link: the capacity is the link’s, and every flow sees it. The second is false in every real network. A connection from a nearby server has a round trip of a few milliseconds; a connection to another continent has one of a hundred. Both may traverse the same congested link, and the control law treats them differently for reasons that have nothing to do with how much capacity each needs.
The bias is not a tuning defect. It follows from the arithmetic of the increase rule, and it can be derived in a few lines. Understanding the derivation is what makes the various remedies legible, because each one attacks a specific term.
Where the bias comes from
In congestion avoidance a flow increases its window by one segment per round trip. That is the rule, and it is expressed in round trips precisely so that it is independent of the window size. But “per round trip” is a rate in wall-clock time that depends on the round trip: a flow with a 10 ms round trip performs a hundred increase steps per second, and a flow with a 100 ms round trip performs ten.
AIMD’s equilibrium is the point at which the increase per unit time balances the loss rate. For two
flows sharing a bottleneck, both lose packets at a rate proportional to their sending rate, so both
have the same loss probability p. The window each flow sustains is set by the square-root law from
the sawtooth analysis:
W ≈ sqrt(3 / (2 p)) (mean window, segments, Reno)
throughput ≈ W * MSS / RTT
The window is the same for both flows because it depends only on the loss probability, which they share. The throughput is not, because it divides by the round trip. The short-RTT flow’s throughput is larger by the ratio of the two round trips. On a 10 ms versus 100 ms pair, the short flow gets ten times the capacity of the long one.
That is the entire mechanism, and it is worth pausing on how counterintuitive it is. The window — the amount of data each flow keeps in the network — is equal. The rate is unequal. A short-RTT flow turns its window over ten times as often, so it delivers ten times the data with the same buffer occupancy and the same loss rate. The fairness measure that matters for the network, buffer occupancy, is equal; the fairness measure that matters for users, throughput, is not.
The aggregate effect on a link is easy to state. If n flows share a bottleneck and each has round
trip T_i, the equilibrium shares are proportional to 1/T_i, so the sum of the shares is the
capacity:
share_i = (1/T_i) / Σ_j (1/T_j)
A link carrying a mix of local and distant traffic allocates most of its capacity to the local traffic, and the distant flows’ users experience the path as much slower than its capacity suggests.
Why this is a stability problem as well
The bias has a second consequence that is less often stated. A flow with a very large round trip has a very small window under this equilibrium, and a small window has few packets per round trip. With fewer than about four segments in flight, a single loss leaves too few packets to generate the three duplicate acknowledgements needed for fast retransmit, so the flow recovers by timeout rather than by fast recovery. A timeout collapses the window to one segment and restarts slow start, which on a long path takes many round trips to recover from.
The result is that long-RTT flows do not merely get a small share; they spend much of their time in slow start after timeouts, and their effective share is smaller still. The transition is sharp: a flow whose window falls below the threshold at which duplicate ACKs are generated switches from the mild halving regime to the severe timeout regime, and the equilibrium calculation above no longer describes it at all. The mechanism of duplicate acknowledgement recovery is covered separately, and its interaction with RTT is why long-path performance degrades faster than the square-root law predicts.
There is also a fairness problem in the opposite direction when the flows do not share a bottleneck. Two flows with different round trips and different bottlenecks do not compete at all, and the question of their relative shares is meaningless. Fairness is only defined among flows that share a constrained resource, which is why the measurement of fairness requires knowing the topology, not just the throughputs.
The remedies and what each one costs
Four families of remedies exist, and they differ in which term of the equilibrium they change.
Make the increase proportional to the round trip. If a flow increases its window by T segments
per round trip instead of by one, then the increase per unit time becomes T/T = 1 segment per
second, independent of T. The equilibrium window becomes proportional to T, and the throughput
becomes equal. This is the direct fix, and it is what the “TCP-friendly” scaling in some high-speed
variants does. The cost is that a flow with a large round trip now increases much faster per round
trip, so its window swing between losses is larger and its burstiness is greater. On a path with a
large bandwidth-delay product, that swing is what forces deep buffers.
Change the growth function to depend on time since the last loss rather than on acknowledgements.
CUBIC, described by Ha, Rhee, and Xu, replaces the linear increase with a cubic function of the time
elapsed since the last window reduction. The window grows as C(t - K)³ + W_max, where W_max is the
window at the last reduction and K is the time the cubic takes to return to it. Because the growth
is a function of elapsed time, two flows that have been running for the same duration have the same
window regardless of their round trips, which removes the bias in the region where both are far from
their last loss. The function is also concave then convex: slow near W_max, which keeps the flow
close to the window it last found sustainable, and fast when far below it, which recovers quickly
after a loss. The RTT independence holds for the growth term, not for the loss term; flows with
different round trips still see losses at different times, so the equality is approximate.
Measure and compensate explicitly. An algorithm can estimate its own round trip and scale its increase by that estimate relative to a reference. This is what the delay-based algorithms do implicitly, since their target is expressed in bytes of queue rather than in packets per round trip. The difficulty is that the estimate is contaminated by the queue, as described in the base RTT problem, so the compensation is only as good as the estimate.
Abandon per-flow fairness as the goal. A shared bottleneck can enforce shares directly by scheduling per-flow queues rather than a single FIFO, which makes each flow’s share a property of the scheduler rather than of its control law. This is the approach of flow-queue AQM in active queue management, and it is the only one of the four that works without cooperation from the endpoints. The cost is per-flow state in the router and a scheduler that must classify every packet.
High-bandwidth paths and the loss-rate wall
The RTT bias is one of two problems that high-bandwidth long-delay paths present. The other is the loss-rate requirement, and it is worth stating numerically because it explains why the field moved away from loss-based control rather than merely adjusting it.
From the square-root law, sustaining a rate R with segment size MSS, round trip RTT, and loss
probability p requires:
p ≈ (1.22 * MSS / (R * RTT))²
For a 10 Gbit/s path with a 100 ms round trip and 1500-byte segments, the bandwidth-delay product is
125 MB, so the window must be about 83,000 segments, and the permitted loss probability works out to
roughly 2 × 10^-10 — about one lost packet in five billion. A loss rate that low is below what most
links deliver even without congestion, since a single faulty interface or a single policer can
produce a higher rate than that. A sender using one segment per round trip as its increase therefore
cannot reach the capacity on such a path, because the equilibrium it needs is below the floor set by
non-congestive loss.
Scaling the increase helps, and it is what the high-speed variants of the 2000s changed: a larger increment per round trip raises the equilibrium window for a given loss rate, so the loss rate the sender can tolerate falls. What scaling does not change is the sender’s behaviour toward everything else at the bottleneck. The increase is what determines how much capacity a flow takes from a competing standard flow, so a variant that reaches a high rate by increasing faster also takes capacity from Reno flows in proportion, and it does so with larger bursts, because the absolute swing between two losses grows with the window. The trade is aggressiveness for throughput, against competitors rather than against the path.
The two real escapes are to stop using loss as the primary signal, which is the model-based approach of delivery rate and pacing, or to make the signal proportional rather than binary, which is the marking-based approach taken in data-center fabrics and described in proportional response to marks.
Measuring fairness honestly
Claims about fairness are easy to make and hard to support, and the definitions matter more than the numbers.
The standard measure is Jain’s fairness index, (Σx_i)² / (n Σx_i²), which is 1 when all shares are
equal and 1/n when one flow takes everything. It is scale-free, which is convenient, and it
penalizes inequality in a specific way: the index falls slowly for small deviations and steeply once
one flow dominates. A link with shares (0.5, 0.25, 0.25) scores about 0.89; a link with
(0.9, 0.05, 0.05) scores about 0.41.
The measure that matters for users is not the share but the completion time, and the two can disagree. A short flow that finishes quickly is not harmed by a long flow getting a larger share if the link is not saturated during the short flow’s lifetime. Fairness indices computed on aggregate throughput over a long interval hide the transient behavior that determines whether an interactive connection feels responsive. The relevant question is usually whether a flow’s share is enough to complete its transfer within its deadline, which is a question about the minimum share over time rather than the average.
Finally, fairness among flows is not the same as fairness among users. A user with ten connections gets ten times the share of a user with one, under any per-flow scheme. The per-flow abstraction is a choice, and it is the right one only because it is the finest granularity a network can enforce without trusting the endpoints.
References
- Analysis of the Increase and Decrease Algorithms for Congestion Avoidance in Computer Networks — Chiu and Jain, Computer Networks and ISDN Systems 17(1), 1989
- CUBIC: A New TCP-Friendly High-Speed TCP Variant — Ha, Rhee, Xu; ACM SIGOPS Operating Systems Review 42(5), 2008
- TCP Congestion Control — IETF
- The Macroscopic Behavior of the TCP Congestion Avoidance Algorithm — Mathis, Semke, Mahdavi, Ott; ACM SIGCOMM Computer Communication Review 27(3), 1997