Congestion Control
How Senders Sense and Respond to a Saturated Link
Congestion control is fundamentally a distributed control problem: thousands of independent senders share a network with no central coordinator, yet they must collectively keep the offered load near each bottleneck's capacity. The classic solution, embodied in TCP, is the additive-increase/multiplicative-decrease (AIMD) loop. Each acknowledged round trip the sender raises its congestion window (cwnd) by roughly one segment; on detecting a loss it halves the window. This sawtooth probes for spare bandwidth gently while backing off sharply when the network signals trouble, and it can be shown to converge to a fair, stable equilibrium when many flows share a link.
The trigger for that back-off matters enormously over RF links. Loss-based algorithms (Reno, NewReno, CUBIC) infer congestion from dropped packets, which works on fiber where loss almost always means a full queue. On a microwave or cellular backhaul span, fading and interference drop packets even when no router is congested, so a loss-based flow needlessly halves its rate and underutilizes the link. Delay-based and model-based schemes such as BBR sidestep this by estimating the bottleneck bandwidth and minimum round-trip time directly, pacing packets at the measured delivery rate rather than filling buffers until something is lost.
The other half of the system lives in the routers. Instead of letting a tail-drop buffer fill to the brim (the cause of bufferbloat), active queue management (AQM) algorithms like CoDel and PIE watch the standing queue delay and signal congestion early, either dropping a packet or setting an ECN bit once delay exceeds a small target. Pairing a modern endpoint algorithm with AQM at the radio aggregation point keeps queues short, which is what preserves low latency for voice, video, and control traffic riding over the same backhaul.
Governing Equations
Increase: cwnd ← cwnd + 1 | Decrease on loss: cwnd ← β × cwnd (β ≈ 0.5 Reno, 0.7 CUBIC)
Steady-state throughput (Mathis model):
T ≈ (MSS / RTT) × (C / √p) bytes/s
Bandwidth-delay product (in-flight target):
BDP = BW × RTTmin → optimal cwnd ≈ BDP
Where MSS = maximum segment size, RTT = round-trip time, p = loss probability, C ≈ 1.22, BW = bottleneck bandwidth. Example: 100 Mbps link, RTTmin = 20 ms → BDP ≈ 250 kB; at p = 10−4, MSS = 1460 B, a single Reno flow on a 50 ms path averages near 29 Mbps.
Congestion Control Algorithm Comparison
| Algorithm | Signal Used | Window Decrease | Behavior on Wireless Loss | Best Use |
|---|---|---|---|---|
| Reno / NewReno | Triple-dup ACK, timeout | × 0.5 | Over-reacts (halves) | Legacy, low-BDP paths |
| CUBIC | Packet loss (cubic growth) | × 0.7 | Over-reacts, but recovers fast | High-BDP fiber/LTE default |
| BBR | Bottleneck BW + RTT model | Rate-based, no halving | Tolerant (loss not a signal) | Lossy wireless, satellite |
| Vegas | RTT increase (delay) | Proportional to queue | Tolerant | Low-latency, controlled nets |
| DCTCP | ECN mark fraction | Proportional to marks | N/A (data center) | Data-center fabrics |
Frequently Asked Questions
How does TCP congestion control differ from flow control?
Flow control protects the receiver via the advertised window (rwnd), preventing a fast sender from overrunning a slow application's buffer. Congestion control protects the network in between via the congestion window (cwnd), the sender's estimate of how much data the path can hold without overflowing router queues. The sender transmits min(cwnd, rwnd); cwnd is adjusted from feedback such as duplicate ACKs, timeouts, or ECN marks, while rwnd is simply reported by the receiver. On a congested wireless backhaul, cwnd is almost always the limit.
Why does TCP congestion control behave poorly over wireless links?
Loss-based algorithms like Reno and CUBIC assume loss means congestion and halve the window. On a radio link, packets are often lost to fading, interference, or bit errors rather than queue overflow, so the sender cuts its rate even though the path is not congested. A link with 1% random loss can cap a single Reno flow far below the available bandwidth. Fixes include link-layer ARQ/HARQ to hide radio losses, ECN so routers mark instead of drop, and model-based algorithms such as BBR that estimate bottleneck bandwidth and RTT directly.
What is bufferbloat and how does active queue management fix it?
Bufferbloat is the high, variable latency that appears when oversized buffers fill during congestion. A loss-based sender keeps growing its window until a drop occurs, so a buffer holding seconds of traffic sits nearly full, adding hundreds of milliseconds of delay even when throughput looks fine. AQM schemes such as CoDel and PIE break this by signaling congestion early, dropping or ECN-marking once standing queue delay exceeds a target (CoDel uses 5 ms over a 100 ms interval). Queues stay short and latency low, which is critical for real-time traffic on RF backhaul.