TCP congestion window simulator

TCP limits how much it sends with a congestion window that doubles in slow start, grows by one segment per round trip in congestion avoidance, and shrinks when packets are lost. Enter the threshold and the rounds where losses happen, and get the window round by round for Tahoe or Reno.

Rounds
24
Largest cwnd
23
Segments sent
293
TCP version
Slow start past ssthresh
After 3 duplicate ACKs
ssthresh floor
Congestion window by round (segments)
0612193 duptimeout123456789101112131415161718192021222324

cwndssthreshslow start

Slow start in rounds 1 to 4; congestion avoidance in rounds 5 to 19; slow start in rounds 20 to 22; congestion avoidance in rounds 23 to 24.

is sent in round 7.
Round by round
RoundcwndssthreshPhaseSegments
1116slow start1–1
2216slow start2–3
3416slow start4–7
4816slow start8–15
51616avoidance16–31
61716avoidance32–48
71816avoidance49–66
81916avoidance67–85
92016avoidance86–105
102116avoidance106–126
112216avoidance127–148
122316avoidance, 3 dup ACKs149–171
131111avoidance172–182
141211avoidance183–194
151311avoidance195–207
161411avoidance208–221
171511avoidance222–236
181611avoidance237–252
191711avoidance, timeout253–269
2018slow start270–270
2128slow start271–272
2248slow start273–276
2388avoidance277–284
2498avoidance285–293
  1. 2Slow start: cwnd doubles, 1 × 2 = 2.
  2. 3Slow start: cwnd doubles, 2 × 2 = 4.
  3. 4Slow start: cwnd doubles, 4 × 2 = 8.
  4. 13Three duplicate ACKs in round 12: Reno halves, ssthresh = 11, cwnd = 11 = 11, and continues in congestion avoidance.
  5. 20A timeout in round 19: ssthresh = 17 / 2 = 8, cwnd = 1, slow start again.

How to use the simulator

Set the initial congestion window (usually 1 segment in exercises), the initial slow-start threshold, the number of rounds, and the rounds at whose end a loss is detected, for example "12 dup, 19 timeout". A round is one round trip, in which the sender transmits a full window. The chart shades slow start, the table lists cwnd, ssthresh and the segment numbers sent in every round, and you can ask which round sends a given segment.

  • Switch between Tahoe and Reno to see the difference a triple duplicate ACK makes.
  • Hover a row of the table for the reason the window changed.
  • "Copy answer" gives the table and the phase intervals as text; "Copy link" saves the exercise.

What is congestion control?

A TCP sender may have at most the smaller of two windows unacknowledged: the receiver's advertised window, which protects the receiver, and the congestion window (cwnd), which protects the network. The sender has no direct signal of how much the path can carry, so it probes: it raises cwnd while data gets through and cuts it when a loss suggests a queue somewhere has overflowed.

The rule at the heart of it is additive increase, multiplicative decrease (AIMD): grow by a constant amount per round trip, halve on loss. Chiu and Jain showed in 1989 that this combination drives flows sharing a link towards a fair and efficient share.

Slow start and congestion avoidance

In slow start, cwnd increases by one segment for every segment acknowledged, so it doubles each round trip: 1, 2, 4, 8 and so on. Despite the name this is fast, exponential growth, and it ends when cwnd reaches the slow-start threshold (ssthresh). From there, congestion avoidance adds about one segment per round trip. The threshold remembers roughly where trouble started last time: it is set to half the window whenever a loss is detected.

Losses: Tahoe and Reno

A sender learns of a loss in two ways. A retransmission timeout means nothing has come back for a long time, a sign of heavy congestion. Three duplicate ACKs mean later segments are arriving while one is missing, so the network is still delivering.

  • TCP Tahoe treats both the same: ssthresh = cwnd / 2, cwnd = 1, slow start again.
  • TCP Reno does the same after a timeout. After three duplicate ACKs it retransmits at once (fast retransmit), sets ssthresh = cwnd / 2 and continues from there in congestion avoidance (fast recovery), instead of collapsing to one segment.

With a loss detected by duplicate ACKs every 10 rounds over 60 rounds, starting from ssthresh 32, Tahoe's window fell to 1 after each loss and it sent 659 segments; Reno's never fell below 9 and it sent 1,036.

Conventions that change the answer

Exercises model TCP round by round, and they simplify in different ways. Check which your course uses:

  • Reaching ssthresh in slow start. If doubling would pass ssthresh, some solutions stop at ssthresh and others double past it before switching to linear growth.
  • The window after three duplicate ACKs. RFC 5681's fast recovery sets cwnd to ssthresh + 3 segments while recovering and back to ssthresh afterwards; round-level exercises show either value.
  • The floor on ssthresh. RFC 5681 sets ssthresh to at least two segments; small textbook examples often ignore it.
  • Which round the loss is in. Here a loss "in round n" is detected at the end of round n, so round n + 1 already has the new window.

CUBIC and BBR

Reno grows by one segment per round trip, which is far too slow on fast, long paths: refilling a large window after a halving takes thousands of round trips. CUBIC, standardised in RFC 9438 and the default in Linux and Windows, grows the window as a cubic function of the time since the last loss, W(t) = C(t − K)³ + Wmax with C = 0.4, reducing it to 0.7 Wmax on a loss. It returns to the previous maximum after K = ∛(Wmax · 0.3 / 0.4) seconds, whatever the round trip:

Window before the loss (segments)CUBIC: KReno, 10 ms round tripReno, 100 ms round trip
102.0 s0.1 s0.5 s
1004.2 s0.5 s5.0 s
1,0009.1 s5.0 s50.0 s
10,00019.6 s50.0 s500.0 s

Google's BBR takes a different approach: rather than treating loss as the signal, it estimates the path's bottleneck bandwidth and minimum round-trip time and paces sending to match, which avoids filling buffers in the first place.

History

In October 1986 the early Internet suffered the first of a series of congestion collapses, during which, Van Jacobson reported, throughput between Lawrence Berkeley Laboratory and UC Berkeley fell from 32 kbit/s to 40 bit/s. Jacobson and Michael Karels's 1988 paper "Congestion Avoidance and Control" introduced slow start, congestion avoidance and better retransmit timers, shipped in 4.3BSD Tahoe; fast recovery followed in 4.3BSD Reno. The algorithms were standardised as RFC 2001 in 1997 and are now RFC 5681.

TCP congestion control questions and answers

How does TCP slow start work?

A new connection starts with a small congestion window (cwnd) and adds one segment for every segment acknowledged, so the window doubles every round trip. It keeps doubling until it reaches the slow-start threshold (ssthresh) or a loss happens, then switches to congestion avoidance.

What is the difference between TCP Tahoe and TCP Reno?

Both halve ssthresh on a loss. Tahoe also drops cwnd to one segment and slow-starts again, whatever the cause. Reno does that only after a timeout; on three duplicate ACKs it uses fast recovery, halving cwnd and continuing in congestion avoidance. With a loss every 10 rounds for 60 rounds, Reno sent 1,036 segments to Tahoe’s 659 in this page’s model.

What happens to cwnd and ssthresh after a timeout?

ssthresh is set to half the current window (RFC 5681 says half the data in flight, and at least two segments), cwnd goes back to one segment, and the sender slow-starts again. Because slow start ends at the new ssthresh, the window climbs quickly to half its old size and then grows by one segment per round trip.

Why does Reno add 3 to cwnd after three duplicate ACKs?

Each duplicate ACK means a segment has left the network, so during fast recovery Reno inflates the window by one segment per duplicate ACK, three for the three that triggered it, and deflates it to ssthresh when new data is acknowledged. Some textbooks show cwnd = ssthresh + 3 at that point, others show cwnd = ssthresh; this page lets you choose.

In which round is the nth segment sent?

Add up cwnd round by round from the first round: the round in which the running total reaches n is the one that sends segment n. The simulator does this for you: type the segment number under the table.

What congestion control do operating systems use today?

Not Reno. Linux and Windows default to CUBIC (RFC 9438), which grows the window as a cubic function of the time since the last loss, so recovery does not depend on the round-trip time. With 1,000 segments in flight before a loss, CUBIC returns to that window 9.1 s after the loss whatever the round trip; Reno, adding one segment per round trip, needs 50 s at a 100 ms round trip. Google’s BBR instead models the path’s bandwidth and round-trip time rather than reacting to loss.

Further reading

Published Updated