skip to content

In TCP, what problem does congestion control solve, and why is the receiver's advertised window alone not enough to prevent it?

level: juniorimportance: must knowfreq 58%

answer

  1. the path, not the peer
  2. router queues overflow and drop
  3. congestion collapse
  4. a second, sender-side window
  5. the smaller of two windows

basics

~20 s

TCP congestion control stops senders from overloading the network path between two hosts. The receiver's advertised window only protects the receiver's buffer, so the sender keeps its own congestion window and sends no more than the smaller of the two.

solid answer

~40 s

The receiver advertises `rwnd` to say how much buffer *it* has free, but it knows nothing about the routers in between. A fast receiver behind a slow bottleneck link would let a sender push data that queues and drops at that router, and the retransmissions add even more load: the spiral RFC 896 named **congestion collapse**. So the sender keeps a second, private limit, the congestion window `cwnd`, which it grows while data is acknowledged and cuts when it sees a congestion signal: a lost segment or, with ECN (RFC 3168), a Congestion Experienced mark. RFC 5681 states the rule: never send data beyond the highest acknowledged sequence number plus `min(cwnd, rwnd)`. RFC 9293 makes slow start, congestion avoidance and exponential RTO backoff mandatory for every TCP.

go deeper

for a junior

Recall that the receiver's window protects the receiver and the congestion window protects the network, and that the sender uses the smaller of the two.

for a middle

Explain congestion collapse as a feedback spiral of drops and retransmissions, and name the signals a sender uses to infer congestion: loss and ECN marks.

for a senior

Be ready to say which window is binding in a real transfer, for example a fast receiver behind a slow bottleneck versus a fast path to a slow-reading application.

for a principal

Frame congestion control as a shared-resource contract among independent senders: why endpoint inference won over router-supplied rates, and what that costs in probing and latency.

## Two different things can be overwhelmed A TCP sender can overrun two separate resources, and TCP protects them with two separate mechanisms: - **The receiver.** Its socket buffer has finite space. The receiver tells the sender how much it can still accept by advertising a **receive window** (`rwnd`) in every segment. That is **flow control**, and it is the receiver's own statement about itself. - **The network path.** Between the two hosts sit links and routers with their own capacity and their own queues. The slowest link on the path, the **bottleneck**, decides how fast data can really move. The receiver cannot see that link, so `rwnd` says nothing about it. A receiver on a fast local network can advertise a large window while the path to it crosses a much slower link. If the sender trusted `rwnd` alone, it would send at whatever rate the receiver's buffer allowed, far faster than the bottleneck can forward. ## What congestion collapse is RFC 896 described what happens when senders ignore the path, calling it **congestion collapse**: 1. Senders inject more data than the bottleneck can forward, so the router's queue fills. 2. Once the queue is full, the router drops arriving packets. 3. The senders see missing acknowledgments and retransmit, which adds more packets to an already overloaded link. 4. The link stays busy carrying duplicates and data that will be dropped further along, so the useful throughput falls even though the link is fully loaded. The network is busy, but little of the work is useful. Congestion control exists to keep the total load near what the path can carry, so that this spiral never starts. ## The congestion window RFC 5681, the current Standards Track specification of TCP congestion control, gives the sender a state variable, the **congestion window** (`cwnd`). Its definition is the key rule: > a TCP MUST NOT send data with a sequence number higher than the sum of the highest acknowledged sequence number and the minimum of `cwnd` and `rwnd`. | | `rwnd` (receive window) | `cwnd` (congestion window) | |---|---|---| | Protects | the receiver's buffer | the network path | | Who decides it | the receiver | the sender | | Carried on the wire? | yes, in the TCP header's window field | no, it is local sender state | | Changes when | the receiving application reads or falls behind | ACKs arrive, or congestion is detected | | Owning mechanism | flow control | congestion control | In RFC 5681 both windows are measured in **bytes**. Whichever is smaller is the binding limit at that moment: early in a connection `cwnd` usually is, while a slow-reading application makes `rwnd` the limit instead. ## How the sender learns about congestion Classic TCP gets no rate from the network. It infers congestion at the endpoints from two signals: - **Loss.** A segment that goes missing is taken as evidence that a queue overflowed. Loss shows up as duplicate acknowledgments or as a retransmission timeout. - **ECN marks.** With Explicit Congestion Notification (RFC 3168), a router doing active queue management can set the Congestion Experienced mark on a packet instead of dropping it. The receiver echoes it back with the TCP `ECE` flag, and the sender answers with `CWR` once it has reduced its window. RFC 3168 requires the reaction to be essentially the same as the reaction to a single dropped packet. RFC 9293 says a TCP SHOULD implement ECN. Neither signal says how much capacity exists. The sender has to **probe**: grow `cwnd` while things go well, and cut it when a signal arrives. ## The algorithms that manage cwnd RFC 9293 (MUST-19) requires every TCP to implement **slow start**, **congestion avoidance** and **exponential backoff of the RTO**, precisely to avoid creating congestion collapse. RFC 5681 specifies four intertwined algorithms: 1. **Slow start** grows `cwnd` quickly from a small initial window. 2. **Congestion avoidance** grows it by about one segment per round trip once it nears the last known safe size. 3. **Fast retransmit** resends a segment after three duplicate ACKs. 4. **Fast recovery** cuts the window without restarting from one segment. RFC 9293 also allows alternative algorithms, such as CUBIC (RFC 9438), provided they conform to the IETF's congestion-control guidance. ## Common confusions - Flow control and congestion control are different: one protects a host, the other the network. - `cwnd` is never sent in a header; only `rwnd` is. - Congestion control is not optional in a conforming TCP, even though reliability alone could be achieved by retransmission.

  • Does a router tell a TCP sender how much bandwidth is available?
    No. Classic TCP infers congestion only at the endpoints: a lost segment, or, with ECN (RFC 3168), a Congestion Experienced mark that the receiver echoes back with the `ECE` flag. Neither signal carries a rate, so the sender still probes by growing `cwnd` and cuts it when a signal arrives.
  • If `rwnd` is 64 KB and `cwnd` is 20 KB, how much unacknowledged data may the sender have outstanding?
    At most 20 KB. RFC 5681 limits the sender to the highest acknowledged sequence number plus `min(cwnd, rwnd)`. Here the path is the constraint; if the receiving application stopped reading and `rwnd` fell below 20 KB, the receiver would become the constraint instead.

The receiver's window is the size of the car park at the destination; the congestion window is the driver's own judgement of how many cars the road can take right now. A huge empty car park does not widen a jammed road, so each driver meters cars onto the road by watching for jams.

saying these in an interview costs you the question

  • Flow control and congestion control are the same mechanism under two names.
  • The receiver's advertised window tells the sender how fast the network path is.
  • Routers send TCP an explicit rate saying how fast it may transmit.
  • Congestion control is optional because retransmission already makes TCP reliable.
  • The congestion window is advertised by the receiver in the TCP header.