Introduction
Flow control stops a sender from overrunning its receiver. It does nothing for the routers in between: if many senders together offer more traffic than a link can carry, router queues fill, packets are dropped, senders retransmit, and the network can spend its capacity on retransmissions (congestion collapse). TCP therefore keeps a second window, the congestion window cwnd, and permits at most new bytes. Already-sent data may temporarily exceed a reduced window.
In the classic loss-based Tahoe/Reno model used here, without ECN, TCP infers congestion from loss rather than explicit network congestion notifications. The loss indications considered here are a retransmission timeout or three duplicate ACKs. It probes for capacity by growing cwnd and backs off sharply on loss: exponential growth in slow start, linear growth in congestion avoidance (additive increase), and a cut on loss (multiplicative decrease). TCP Tahoe and TCP Reno differ in what they do after three duplicate ACKs.
Prerequisites
- TCP Flow Control: the receive window, the sender's window, and the bound .
Core concepts
State variables
| Variable | Meaning |
|---|---|
| cwnd | Congestion window: how much the sender lets itself have in flight |
| ssthresh | Slow-start threshold: below it, slow start; at or above it, congestion avoidance |
| MSS | Maximum segment size; cwnd and ssthresh are counted in MSS units (RFC 5681 counts bytes) |
Slow start
Start with a small window (the examples here start at 1 MSS; RFC 5681 allows an initial window of 2 to 4 segments depending on MSS). For each ACK of new data, cwnd grows by 1 MSS. Since a window of segments returns ACKs in one RTT, cwnd doubles every RTT: 1, 2, 4, 8, ... The name is historical; the growth is exponential.
Congestion avoidance
Once cwnd ssthresh, cwnd grows by about 1 MSS per RTT (per ACK by ): linear growth.
Reaction to loss
| Event | ssthresh | cwnd | Then |
|---|---|---|---|
| Timeout (Tahoe and Reno) | 1 | Slow start | |
| Three duplicate ACKs, Tahoe | 1 | Fast retransmit, then slow start | |
| Three duplicate ACKs, Reno | ssthresh (after fast recovery) | Fast retransmit, fast recovery, then congestion avoidance |
FlightSize is the amount of outstanding data, which in the per-RTT model equals the current cwnd.
Fast retransmit. Three duplicate ACKs (four ACKs with the same number) mean later segments are arriving, so one segment is probably lost but the path still works: retransmit it at once, without waiting for the timer.
Fast recovery (Reno). After fast retransmit, set cwnd = ssthresh + 3 MSS (the three segments that left the network), add 1 MSS for each further duplicate ACK, and when the ACK for new data arrives, set cwnd = ssthresh and continue in congestion avoidance. A timeout is treated as more serious than three duplicate ACKs, because nothing is getting through.
Conventions for round-by-round problems
The tables use the following conventions; a question that states others overrides them.
- Time is counted in transmission rounds (RTTs); cwnd is in MSS and constant within a round.
- In slow start the next cwnd is : growth stops at ssthresh rather than overshooting it.
- When cwnd ssthresh, the next cwnd is cwnd + 1.
- A loss event in a round sets ssthresh = (at least 2), using that round's cwnd, and determines the next round's cwnd: 1 after a timeout or Tahoe triple duplicate ACK, ssthresh after a Reno triple duplicate ACK. Fast recovery's temporary inflation is not shown.
How it works: Tahoe and Reno, round by round
Initial cwnd = 1, ssthresh = 16. Three duplicate ACKs occur in round 9 and a timeout in round 13.
| Round | Tahoe cwnd | Tahoe ssthresh | Reno cwnd | Reno ssthresh | Event |
|---|---|---|---|---|---|
| 1 | 1 | 16 | 1 | 16 | |
| 2 | 2 | 16 | 2 | 16 | |
| 3 | 4 | 16 | 4 | 16 | |
| 4 | 8 | 16 | 8 | 16 | |
| 5 | 16 | 16 | 16 | 16 | reaches ssthresh |
| 6 | 17 | 16 | 17 | 16 | |
| 7 | 18 | 16 | 18 | 16 | |
| 8 | 19 | 16 | 19 | 16 | |
| 9 | 20 | 16 | 20 | 16 | 3 duplicate ACKs |
| 10 | 1 | 10 | 10 | 10 | |
| 11 | 2 | 10 | 11 | 10 | |
| 12 | 4 | 10 | 12 | 10 | |
| 13 | 8 | 10 | 13 | 10 | timeout |
| 14 | 1 | 4 | 1 | 6 | |
| 15 | 2 | 4 | 2 | 6 | |
| 16 | 4 | 4 | 4 | 6 | |
| 17 | 5 | 4 | 6 | 6 | |
| 18 | 6 | 4 | 7 | 6 | |
| 19 | 7 | 4 | 8 | 6 | |
| 20 | 8 | 4 | 9 | 6 |
After round 9 both set ssthresh = 10; Tahoe restarts at 1, Reno continues from 10. At the timeout in round 13 the two have different windows (8 and 13), so they get different thresholds, 4 and , and then both restart at 1.

Mathematical explanation
Slow-start time. From cwnd = 1, reaching (a power of 2 not above ssthresh) takes rounds, and sending segments in slow start takes rounds, since after rounds segments have gone.
Recovering after a timeout. Assume the pre-loss flight fills cwnd , in MSS units. Set and cwnd = 1. For powers of two , slow start takes growth rounds to reach the threshold, followed by congestion-avoidance rounds to reach . For : 4 + 16 = 20 rounds. For the old window is already reached (0 growth rounds); for , one slow-start growth round suffices. Otherwise use the stated round-by-round recurrence and minimum threshold, not this restricted closed form.
AIMD sawtooth. If a Reno flow loses one packet each time its window reaches , the window cycles linearly between and , so its average is and its throughput about .
Why AIMD. Additive increase and multiplicative decrease move competing flows towards an equal share: each decrease halves the difference between two flows' windows, while each increase leaves it unchanged.
Worked examples
Example 1: time to send a file in slow start
A file of 63 segments, cwnd starting at 1, ssthresh 64, no loss: rounds carry 1, 2, 4, 8, 16, 32 segments; , so 6 RTTs. A 64-segment file needs a seventh round for its last segment.
Example 2: back to the old window
MSS = 1 KB. A timeout occurs at cwnd = 32 KB. ssthresh = 16 KB, cwnd = 1 KB; slow start gives 1, 2, 4, 8, 16 (4 RTTs to reach 16), then 17, ..., 32 (16 RTTs). cwnd is 32 KB again 20 RTTs after the timeout.
Example 3: halving an odd window
Reno with cwnd = 13 MSS gets three duplicate ACKs. ssthresh = MSS and, after fast recovery, cwnd = 6. Under RFC 5681 in bytes, with MSS 1460 and FlightSize bytes, ssthresh = 9490 bytes = 6.5 MSS; problems in MSS units round down unless they say otherwise.
Example 4: fast-recovery window in detail
Reno, cwnd = 20 MSS, three duplicate ACKs. ssthresh = 10; cwnd = 10 + 3 = 13 while the retransmission is outstanding; two more duplicate ACKs inflate it to 15; the ACK for new data sets cwnd = 10. The per-round tables show only the final 10.
Example 5: a threshold that is not a power of 2, and a receiver window
cwnd starts at 1 MSS, ssthresh = 12 MSS, rwnd = 14 MSS, no loss; each round the sender sends segments.
| Round | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Segments sent | 1 | 2 | 4 | 8 | 12 | 13 | 14 | 14 | 14 | 14 | 14 |
Slow start stops at 12 (convention 2), congestion avoidance adds 1, and from round 7 the receiver's window of 14 is the limit. After 7 rounds 54 segments have gone, so a 100-segment file needs 11 rounds (). If a problem lets slow start overshoot (8 doubles to 16, then +1 per round), the rounds send 1, 2, 4, 8, 14, 14, and so on: 29 segments after 5 rounds and again 11 rounds for 100 segments, but the per-round values differ, so the convention must be stated.
Related material. NewReno
Reno leaves fast recovery on the first new ACK; if several segments of one window were lost, that ACK is only a partial ACK and Reno may need a timeout. NewReno (RFC 6582) stays in fast recovery until all data outstanding at the time of the loss is acknowledged, retransmitting one lost segment per partial ACK.
Important properties and observations
- Loss is the signal. Classic TCP reads every loss as congestion, which hurts on lossy wireless links.
- Self-clocking. ACKs pace new transmissions at the rate the bottleneck delivers.
- The sender uses ; whichever is smaller limits throughput.
- Timeout is harsher than duplicate ACKs in Reno: back to 1 against back to ssthresh.
Common misconceptions.
- "Slow start grows slowly." It doubles every RTT.
- "Tahoe and Reno differ on timeout." Both go to cwnd = 1 on timeout; they differ on three duplicate ACKs.
- "ssthresh is halved." ssthresh is set to max(FlightSize/2, 2 MSS), not half of the old ssthresh.
- "Three ACKs mean three duplicates." Three duplicate ACKs means four ACKs with the same number.
- "cwnd is advertised by the receiver." rwnd is; cwnd is the sender's own estimate.
GATE examination perspective
- Round-by-round tables. State the conventions; double up to ssthresh, then +1; on loss, ssthresh = max(FlightSize/2, 2 MSS) (FlightSize = cwnd only for a full flight).
- Tahoe versus Reno. Same on timeout; on three duplicate ACKs Tahoe goes to 1, Reno to the new ssthresh.
- Counting RTTs. Starting from cwnd = 1 MSS, reaching a power-of-two window not above ssthresh takes growth rounds. Sending segments wholly in slow start takes transmission rounds. Congestion avoidance grows by one MSS per growth round.
- Bytes versus segments. Convert KB windows to MSS units first; watch whether KB means 1000 or 1024.
- Receiver limit and odd thresholds. Send per round; a threshold that is not a power of 2 cuts the last slow-start step short (Example 5).
- Throughput. at any moment; on average for the sawtooth.
Summary
Sources
- A. S. Tanenbaum, D. J. Wetherall, Computer Networks, 5th ed., Pearson, 2011: Section 6.5.10 (TCP Congestion Control).
- J. F. Kurose, K. W. Ross, Computer Networking: A Top-Down Approach, 8th ed., Pearson, 2021: Sections 3.6 (Principles of Congestion Control) and 3.7.1 (Classic TCP Congestion Control).
- B. A. Forouzan, Data Communications and Networking, 5th ed., McGraw-Hill, 2013: Chapter 24 (Internet Transport-Layer Protocols).
- M. Allman, V. Paxson, E. Blanton, RFC 5681, TCP Congestion Control, 2009, Sections 3.1 (Slow Start and Congestion Avoidance, initial window, equation (4)) and 3.2 (Fast Retransmit/Fast Recovery), (consulted 2026-11-11).
- T. Henderson, S. Floyd, A. Gurtov, Y. Nishida, RFC 6582, The NewReno Modification to TCP's Fast Recovery Algorithm, 2012, (consulted 2026-11-11).