Flow Control: Sliding Window, Go Back N and Selective Repeat

Transport Layer · 30 min

Core CS · Computer Networks

One frame at a time is correct, and it wastes ninety-seven per cent of the link

Send a frame, wait for its acknowledgement, send the next. Nothing is ever lost and nothing overruns the receiver. On a 1 Mbps link with a 20 ms delay it moves 24 kbps, and buying ten times the bandwidth changes that to 25 kbps. The fix is a window, and the two ways of repairing a hole in that window are the pair every interviewer reverses.

Lose the same frame under Go-Back-N and Selective Repeat, side by side
Flow control stops a fast sender from overrunning a slow receiver, and it is not congestion control. Flow control protects one receiver’s buffer and the receiver sets the limit. Congestion control protects the network between you and it, and the network never tells you anything directly. A sliding window is how the receiver’s limit gets written down: a range of frames the sender may have unacknowledged at once.

01 The idea

Protect the receiver, not the network

A server with 32 GB of memory sends to a sensor with 8 KB of buffer. The link is fine, the routers are idle, nothing is congested, and the sensor still loses data, because bytes arrive faster than its application reads them and the buffer fills. That is the problem flow control solves, and it is worth being blunt about the boundary before anything else. Flow control is end to end: the receiver tells the sender how much it may send, and the sender obeys. Congestion control is a different problem with an identical symptom. There the receiver is perfectly happy and the queue inside some router along the path is overflowing, so the sender has to infer the limit from lost packets and rising delay, because no router sends it a message. TCP runs both at once and keeps two separate numbers for them. A sender that respects only the receiver will melt the network; a sender that respects only the network will still overrun the receiver.

The simplest protocol that does flow control correctly is stop-and-wait. Send one frame. Do nothing until its acknowledgement comes back. Then send the next. The receiver controls the sender exactly, because the sender cannot move without permission, and one buffer is enough at each end. It is correct, it is three lines long, and on any link with real distance in it the sender spends almost all of its time doing nothing. Section 02 puts numbers on that, and the numbers are worse than most students expect.

The repair is pipelining: allow several frames to be unacknowledged at the same time, so the sender keeps transmitting while the earlier frames are still in the air. How many? Exactly enough to keep sending until the first acknowledgement gets back, which is the bandwidth-delay product from the earlier module, measured in frames rather than bits. That number is the window size, and it is the whole reason the window exists. Nothing about pipelining is a performance trick bolted on afterwards; it is the direct answer to the question “how much data fits in the pipe”.

A sliding window is how that allowance is bookkept. The sender keeps a range of sequence numbers it is allowed to transmit without waiting, from the oldest unacknowledged frame up to the window size. The receiver keeps a range it is willing to accept. When an acknowledgement arrives the sender’s range slides forward past the frames now known to be safe, which is where the name comes from: the window never grows or shrinks on its own, it moves.

Then one frame goes missing, and the protocol has to decide what to do about everything that was already in flight behind it. There are exactly two sane answers, and they are the two protocols this lesson is really about. Go-Back-N makes the receiver simple and the sender wasteful: the receiver refuses anything out of order, so the sender resends the lost frame and every frame after it. Selective Repeat makes the receiver clever and the sender frugal: the receiver holds the out-of-order frames in a buffer, so only the lost frame is sent again. Both are called ARQ, Automatic Repeat reQuest, meaning loss is repaired by retransmission driven by acknowledgements and timers rather than by adding redundancy to the data.

Stop-and-wait is correct and unusable, so you let N frames be unacknowledged at once and size N from the bandwidth-delay product. Everything after that is one question: when frame k is lost, do you resend everything from k onward, or only k? Go-Back-N picks the first and pays in link capacity. Selective Repeat picks the second and pays in receiver memory.
Transmission delay TtTime to push all the bits of one frame onto the wire: frame size / bandwidth. A 1,000-bit frame on a 1 Mbps link takes 1 ms. It shrinks when you buy a faster link, and it is the only part of the delay that does.
Propagation delay TpTime for one bit to travel from one end to the other: distance / signal speed, around 2 × 10⁸ metres per second in copper or fibre. It depends on how far apart the two ends are and on nothing else. Bandwidth does not touch it.
The ratio a, and the pipea = Tp / Tt, so a is how many frame-times fit inside one one-way trip. The bandwidth-delay product is bandwidth × RTT, the number of bits that fit in the link at once, and dividing it by the frame size gives the same story in frames.

02 Worked example

Forty-one milliseconds, of which the sender works for one

One link, worked end to end. This is the scene for the rest of the lesson. Bandwidth 1 Mbps, frames of 1,000 bits, one-way propagation delay 20 ms. Acknowledgements are tiny, so their own transmission time is ignored, which is the standard assumption and the one every exam question makes. Read left to right and check each arithmetic step as you go.

1 · Push the frame outThe sender is busy for Tt = 1000 / 1,000,000 s = 1 ms. That is the only interval in this whole cycle in which the link carries anything of yours.
2 · Wait for the last bitThe last bit still has to cross: Tp = 20 ms. The frame is fully received at 1 + 20 = 21 ms. The sender has been idle since t = 1 ms.
3 · The acknowledgement returnsAnother 20 ms back. It lands at 21 + 20 = 41 ms, and only now may the sender start frame two. One cycle is Tt + 2Tp.
4 · Count the idle timeBusy 1 ms out of 41. a = Tp/Tt = 20/1 = 20, and U = 1/(1 + 2a) = 1/41 = 2.44%. Throughput is 1000 bits / 41 ms = 24.4 kbps on a 1 Mbps link.
5 · Fill the pipeAllow N frames unacknowledged at once: U = min(1, N/(1 + 2a)). Here N = 41 makes it 1. The pipe holds 1 Mbps × 40 ms = 40,000 bits, which is 40 frames, plus the one being sent.

The highlighted node is the one to slow down on, because it is where the formula stops being something to memorise. U = Tt / (Tt + 2Tp) is nothing more than “busy time over cycle time”. Divide the top and bottom by Tt and you get 1 / (1 + 2Tp/Tt), which is 1 / (1 + 2a). That is the entire derivation, and it means a is the only thing that matters: a is how many frame-times fit into one one-way flight, so 2a is how many frame-times the sender wastes staring at the wire per frame it sends.

Now do the thing that makes the point land. Keep the same frames and the same 20 ms, and upgrade the link to 10 Mbps. Tt falls to 1000 / 10,000,000 s = 0.1 ms, so a = 20 / 0.1 = 200 and U = 1/401 = 0.249%. Throughput is 1000 bits / 40.1 ms = 24.94 kbps. You paid for ten times the bandwidth and moved from 24.4 kbps to 24.9 kbps, a gain of two per cent. Under stop-and-wait the sender is not limited by bandwidth at all. It is limited by how long it agrees to wait, and no cheque you write changes 20 ms of physics.

Node 5 is the fix, and the number in it is the bandwidth-delay product wearing different clothes. The round trip is 2 × 20 = 40 ms, and 1 Mbps × 40 ms = 40,000 bits of link standing empty. At 1,000 bits per frame that is 40 frames of empty pipe, so the sender needs 40 more frames in flight plus the one it is currently transmitting: N = 41, which is exactly 1 + 2a. The two routes to 41 are the same statement, and being able to produce it either way is what an interviewer is checking.

Hold on to 41. Section 03 needs a sequence number field wide enough to label 41 outstanding frames, and it turns out that Go-Back-N and Selective Repeat need different widths for the same window, which is the single most reversible fact in this topic. The console in section 04 shrinks the scene to a window of 4 over eight frames so that you can count every transmission by hand; the mechanism is identical, only the numbers are small enough to check.

03 Mechanics

The two ARQ strategies, and where their window limits come from

Four tables, in the order the questions come. First the three protocols side by side. Read the last two columns together, because they are the trade: Go-Back-N buys a one-frame receiver by spending link capacity on every loss, and Selective Repeat buys minimal retransmission by spending memory on every connection whether it loses anything or not.

ProtocolSender windowReceiver windowAcknowledgementOn one lost frameReceiver bufferUtilisation
Stop-and-wait 11 One per frame Resend that frame 1 frame 1 / (1 + 2a)
Go-Back-N W ≤ 2ᵐ − 11 Cumulative resend it and every frame after it 1 frame min(1, W / (1 + 2a))
Selective Repeat W ≤ 2ᵐ / 2W Individual resend only that frame W frames, plus sorting min(1, W / (1 + 2a))

The acknowledgement convention, stated once so nothing later is ambiguous. In this lesson a Go-Back-N ACK n means everything up to and including frame n has arrived, which is why one acknowledgement can cover several frames and why a lost acknowledgement is harmless as long as a later one gets through. A Selective Repeat ACK n means frame n specifically has arrived and says nothing about its neighbours, so every acknowledgement matters and a lost one costs a retransmission. Some textbooks number the Go-Back-N acknowledgement by the frame the receiver wants next rather than the last one it got, which shifts every number by one. TCP does it that way: its acknowledgement number is the next byte expected, so an ACK of 5001 means bytes up to 5000 arrived. Say out loud which convention you are using and no interviewer will mark you down; assume silently and you will be told you are off by one.

Second, the utilisation numbers, because “stop-and-wait is bad” is not an answer and “a is 200 so you get a quarter of one per cent” is. Every row is computed from Tt = frame bits / bandwidth and U = 1/(1 + 2a), and the last column is the window that would make U = 1.

LinkFrameTtTpaStop-and-wait UThroughputWindow to fill it
1 Gbps LAN, 1 km12,000 bits12 µs5 µs0.42 54.5%545 Mbps2 frames
1 Mbps, 20 ms (section 02)1,000 bits1 ms20 ms20 2.44%24.4 kbps41 frames
Same link at 10 Mbps1,000 bits0.1 ms20 ms200 0.249%24.9 kbps401 frames
Geostationary satellite, 1 Mbps1,000 bits1 ms270 ms270 0.185%1.85 kbps541 frames

Read row one against row three. On the 1 Gbps LAN one kilometre long, stop-and-wait already reaches 54.5 per cent, because a is below 1: the frame takes longer to push onto the wire than it takes to cross it, so the link is genuinely busy most of the time and a window of 2 finishes the job. Now take a link a hundred times slower, 10 Mbps, and stretch it over 20 ms. The same protocol reaches a quarter of one per cent and needs 401 frames in flight to recover, which is worse by a factor of more than two hundred. Bandwidth went down and the problem got dramatically worse, so bandwidth is not what decides this. The interesting question is never “is stop-and-wait slow” but “what is a here”.

Third, the sequence-number limits, which are the two facts students most often reverse and most often assert without a reason. A sequence number field of m bits can only count 0 to 2ᵐ − 1 and then wraps. The table walks the exact failure that follows if the window is one too wide, using m = 2 so the whole sequence space is 0 1 2 3 and you can hold it in your head.

StepGo-Back-N with m = 2, W = 4Selective Repeat with m = 2, W = 3
1 Sender fills its windowSends frames 0 1 2 3Sends frames 0 1 2
2 They all arriveReceiver delivers all four, now expects sequence number 0 againReceiver delivers all three, receive window becomes {3, 0, 1}
3 Every acknowledgement is lostsender learns nothingsender learns nothing
4 Timer expires, sender retransmitsResends the old frame 0Resends the old frame 0
5 The receiver decidesit was expecting 0, so it accepts the duplicate as new data0 is inside {3, 0, 1}, so it buffers the duplicate as new data
The fixW ≤ 2ᵐ − 1 = 3, so the receiver is expecting 3 and rejects the old 0W ≤ 2ᵐ / 2 = 2, so the window is {2, 3} and the old 0 is outside it

Why the two limits differ, in one sentence each. Go-Back-N has a receive window of one, so the only thing that must stay unambiguous is the single number the receiver is waiting for. Leaving one sequence number unused is enough to guarantee that a stale frame never equals it, hence 2ᵐ − 1. Selective Repeat has a receive window of W, and after the receiver slides forward its new window can overlap the sender’s old one in sequence space; keeping the two disjoint requires the old and new windows together to fit in 2ᵐ, which is W + W ≤ 2ᵐ, hence W ≤ 2ᵐ/2. Apply this to section 02: a window of 41 needs m = 6 under Go-Back-N, because 2⁶ − 1 = 63 ≥ 41 while 2⁵ − 1 = 31 is too small, and it needs m = 7 under Selective Repeat, because 2⁶/2 = 32 is too small and 2⁷/2 = 64 ≥ 41. Same window, one more bit of header, purely because the receiver buffers.

The failure is silent, which is what makes it an interview question. Nothing in step 5 raises an error. The frame is not corrupt, the checksum passes, the sequence number is one the receiver was willing to accept. The application receives a byte range twice, or receives old data in the middle of new data, and the bug surfaces days later as corrupted content with no packet loss anywhere in the logs. A protocol that is one off in its window bound looks perfect until the exact combination of a full window and a lost acknowledgement batch occurs.

Fourth, what TCP actually does, because everything above is the frame-level model and TCP is the thing you will be asked about. TCP counts in bytes, not frames, and its window is advertised by the receiver rather than agreed in advance.

MechanismWhat it isThe numberWhat goes wrong without it
Receive window (rwnd) The receiver puts its current free buffer space in the Window field of every segment it sends, so the allowance is refreshed on every acknowledgement rather than fixed at setup. 16-bit field, 0 to 65,535 bytes The sender guesses, and a slow application on the receiving side loses data.
The sender’s real limit Two independent limits apply at once and the tighter one wins. The receive window is flow control; the congestion window is congestion control; unacknowledged bytes already on the wire count against both. usable = min(rwnd, cwnd) − bytes in flight Obeying only rwnd floods the network; obeying only cwnd floods the receiver.
Zero window and the probe A full receiver advertises 0 and the sender stops. The window update that reopens it is a pure acknowledgement, which is never retransmitted, so if it is lost both ends wait forever. The sender therefore runs a persist timer and sends a window probe, a segment carrying one byte, purely to force a fresh advertisement back. rwnd = 0 stops the sender dead a permanent deadlock on a healthy connection
Silly window syndrome The connection settles into moving a handful of bytes per segment, so the headers cost far more than the data. Fixed from both ends: the receiver refuses to advertise a window until it can offer a full segment or half its buffer, and the sender holds a small write back while earlier small data is still unacknowledged, which is Nagle’s algorithm. 40 bytes of TCP and IPv4 header for 1 byte of data The link is busy and almost nothing useful crosses it.
Window scale option A 16-bit field cannot express a modern pipe, so RFC 7323 adds a left-shift factor negotiated in the opening handshake and applied to every later advertisement. shift 0 to 14, up to 1,073,725,440 bytes Throughput caps at 65,535 bytes per RTT however fast the link is.

Where TCP sits between the two protocols. Plain TCP acknowledges cumulatively, exactly like Go-Back-N, and a strict Go-Back-N sender would retransmit the whole window on a loss. Real stacks do not, because the selective acknowledgement option, RFC 2018, lets the receiver report the blocks it did receive above the gap, so the sender resends only the hole. That makes deployed TCP behave like Selective Repeat over a Go-Back-N-shaped acknowledgement format. It is worth saying in an interview in one clause: the exam answer is that TCP acknowledgements are cumulative, and the honest addition is that SACK is negotiated on essentially every connection you will ever open.

05 Cheat sheet

Everything you can be asked to state in ten seconds

Every row is something you either compute in your head or say out loud without hesitating. The right-hand column is the specific wrong answer that gets written down, not a general caution.

What they askThe answerThe trap
Flow control versus congestion controlreceiver’s buffer versus the network in betweentreating them as one mechanism — TCP keeps two separate windows
Stop-and-wait utilisationU = 1 / (1 + 2a), a = Tp / Ttputting the RTT into aa uses the one-way delay; the 2 supplies the round trip
Utilisation with a window of WU = min(1, W / (1 + 2a))Forgetting the cap and reporting a utilisation above 1.
Window that fills the pipeW ≥ 1 + 2a, or BDP / frame size, plus 1dropping the +1 — the frame being transmitted is not in the pipe yet
Go-Back-N sender windowat most 2ᵐ − 12ᵐ — a full sequence space lets a stale frame be accepted as new
Go-Back-N receiver windowexactly 1Saying it buffers out-of-order frames. It does not; that is the whole difference.
Selective Repeat windowssender and receiver both at most 2ᵐ / 2reusing 2ᵐ − 1 — the Go-Back-N bound is not valid here
Acknowledgement styleGo-Back-N cumulative, Selective Repeat individualAssuming a cumulative acknowledgement is always worse. A lost one costs nothing.
What gets retransmittedGBN: the lost frame and every frame after it. SR: only the lost frame.swapping the two — the single most reversed pair in this topic
Receiver memoryGBN 1 frame, SR W frames plus reorderingForgetting that the sender buffers W frames in both.
TCP flow-control field16-bit Window in every segment, scaled per RFC 7323naming the congestion windowcwnd is never sent on the wire
What bounds a TCP sendermin(rwnd, cwnd) − bytes in flightQuoting rwnd alone, or forgetting to subtract what is already unacknowledged.
Escaping a zero windowpersist timer, then a window probewaiting for the receiver to re-advertise — that update is a pure ACK and is never retransmitted
TCP header size20 bytes without options, up to 60 withQuoting UDP’s 8 bytes, or forgetting the 20-byte IPv4 header underneath.
Different problem, different windowFlow control is one receiver telling you its free buffer space, and it arrives as an explicit number in every acknowledgement. Congestion control is the network never telling you anything, so the sender infers a limit from loss and delay. TCP obeys the smaller of the two, and a question that says “the receiver is slow” is a flow-control question however much it sounds like congestion.
Every window is a bet on the round tripThe right window is the bandwidth-delay product divided by the frame size, plus one. Below it the sender goes idle waiting; above it the extra frames only add queueing and buffer. That is why a, not bandwidth, decides whether a protocol is usable, and why the same protocol is fine on a LAN and hopeless over a satellite.
The sequence space is not freeWidening the window eventually widens the header. Go-Back-N needs 2ᵐ − 1 ≥ W and Selective Repeat needs 2ᵐ/2 ≥ W, so Selective Repeat costs a bit more sequence number for the same window. Get the bound wrong by one and nothing fails visibly; the receiver accepts a stale frame as new.

06 Where & why

The window is a live value in systems you already use

None of this is a teaching abstraction. Each of these four is a window you can print, tune, or be paged about, and two of them exist specifically because one TCP window underneath is not enough.

Linux · ss -ti
The receive window is your buffer, and the kernel resizes it for you

Run ss -ti on an open socket and you see rcv_space, wscale, cwnd and the current round-trip estimate together, which is this whole lesson printed on one line. The advertised window is derived from the receive buffer, and Linux auto-tunes that buffer between the bounds in net.ipv4.tcp_rmem as it learns the bandwidth-delay product. The classic failure is a middlebox stripping the window scale option from the handshake: the connection works, and it silently caps at 65,535 bytes per round trip forever.

HTTP/2
A second window on top, because one TCP window cannot separate streams

HTTP/2 multiplexes many requests over one TCP connection, and TCP has exactly one window for the lot, so a large download would starve everything else sharing it. HTTP/2 therefore runs its own flow control per stream and per connection, with the initial window set to 65,535 octets and credit returned by explicit WINDOW_UPDATE frames. Same mechanism as section 01, one layer up, for a problem the layer below cannot see.

OpenSSH
Per-channel windows inside one connection

An SSH connection carries several channels at once: your shell, a port forward, an scp transfer. RFC 4254 gives each channel its own window, advertised at channel open and topped up with SSH_MSG_CHANNEL_WINDOW_ADJUST messages, so a bulk file copy cannot make your interactive shell unresponsive. If you have ever wondered why typing stays smooth during an scp over the same session, that is the reason.

Wi-Fi 6 · 802.11ax
Selective repeat implemented in silicon

Wi-Fi aggregates many subframes into one long transmission and acknowledges them with a Block Ack: a bitmap with one bit per subframe, 64 bits in the compressed form and wider in 802.11ax. That is individual acknowledgement, so only the subframes that actually failed are sent again, which is Selective Repeat with a fixed hardware window. Go-Back-N would be unusable here, because on radio a few subframes of a burst fail routinely and resending the whole burst each time would collapse the throughput.

Every one of these four exists because somebody had to answer the same two questions you answered in section 02: how much may be outstanding at once, and what happens to the rest when one piece of it goes missing. The layer changes and the arithmetic does not.

07 Interview questions

What they ask, and the pair they expect you to reverse

The reliable pattern here is a definition question, then a number, then Go-Back-N against Selective Repeat, then one deliberate trap on the window bounds. If you can say which side pays for what in each protocol, most follow-ups answer themselves. Give the reason with the rule every time; both bounds sound arbitrary until you say what would break.

What is flow control, and how is it different from congestion control?
Flow control stops a fast sender from overrunning a slow receiver, and it protects one thing: the receiver’s buffer. The receiver states its limit explicitly, in TCP as the window value carried in every segment it sends. Congestion control protects the network in between, where routers are queueing and nothing sends you a message, so the sender has to infer its limit from loss and rising delay. TCP runs both at once with separate state and sends the smaller of the two allowances, which is why “the receiver is slow” and “the path is busy” are two different questions even though the symptom is identical.
Explain stop-and-wait, and why nobody uses it on a long link.
Send one frame, wait for its acknowledgement, send the next. It is correct and needs one buffer at each end, but the sender is busy only for the transmission time of one frame in every Tt + 2Tp, so utilisation is 1 / (1 + 2a) where a = Tp / Tt. On the lesson link, 1 Mbps with 1,000-bit frames and 20 ms one way, a is 20 and utilisation is 1/41, about 2.4 per cent. The part worth saying out loud is that raising the bandwidth makes it worse: at 10 Mbps a becomes 200 and utilisation drops to a quarter of one per cent, while the throughput barely moves.
How do you choose the window size, and what happens if it is too big?
Size it so the sender never goes idle: it must still be transmitting when the first acknowledgement arrives, which needs W ≥ 1 + 2a, or equivalently the bandwidth-delay product divided by the frame size, plus one for the frame currently going out. Below that the link sits empty for part of every round trip and utilisation is W / (1 + 2a). Above it utilisation is already capped at 1, so the extra frames buy nothing and only add buffering at both ends and queueing in the network. There is also a hard ceiling: the window can never exceed what the sequence number field allows.
Go-Back-N against Selective Repeat, in one minute.
Both let W frames be unacknowledged at once; they differ in what the receiver does with a frame that arrives after a gap. Go-Back-N has a receive window of one, so it discards anything out of order and acknowledges cumulatively, and on a loss the sender resends the missing frame and every frame after it. Selective Repeat has a receive window of W, buffers out-of-order frames, acknowledges each one individually, and retransmits only the frame that went missing. So Go-Back-N is cheap in memory and expensive on the link, Selective Repeat is the reverse, and Selective Repeat also needs per-frame timers and reordering logic rather than one timer for the oldest unacknowledged frame.
Why is the Go-Back-N sender window at most 2 to the power m minus 1?
Because with a full sequence space the receiver cannot tell a retransmitted old frame from a brand new one. Take m = 2 and a window of 4: the sender sends 0, 1, 2, 3, all arrive, the receiver delivers them and now expects sequence number 0 again, and then every acknowledgement is lost. The sender times out and resends the old frame 0, and the receiver accepts it as new data because 0 is exactly what it was waiting for. Leaving one sequence number unused fixes it: with a window of 3 the receiver is waiting for 3, the stale 0 does not match, and it is correctly discarded.
And why is the Selective Repeat window at most half the sequence space?
Because the receiver window also moves, so the old sender window and the new receiver window must not overlap in sequence space. With m = 2 and a window of 3 the sender sends 0, 1, 2, the receiver delivers all three and its window becomes {3, 0, 1}, and if the acknowledgements are lost the retransmitted old 0 lands inside that window and is buffered as new data. Keeping the two windows disjoint needs W + W ≤ 2ᵐ, which is W ≤ 2ᵐ/2. The trap is reusing the Go-Back-N bound here: it is valid for Go-Back-N only because that receiver window is one.
Is a cumulative acknowledgement better or worse than an individual one?
Neither, they fail differently. A cumulative acknowledgement covers everything up to its number, so losing one costs nothing at all as long as a later one arrives, and it lets you send far fewer acknowledgements. Its weakness is that it cannot describe a hole: it can only say “I have everything through 1” while frames 3, 4 and 5 sit unmentioned, which is precisely what forces Go-Back-N to resend them. An individual acknowledgement can describe a hole exactly, so nothing extra is retransmitted, but each one is load-bearing and losing it triggers a retransmission of a frame that already arrived.
How does TCP actually do flow control, and where does the value live?
The receiver advertises its free buffer space in the 16-bit Window field of every segment it sends, so the allowance is refreshed on every acknowledgement rather than negotiated once. The sender may have at most min(rwnd, cwnd) bytes unacknowledged, so it subtracts what is already in flight to know what it can send right now. Two details get marks: TCP counts bytes rather than frames, and the congestion window is purely local to the sender and never appears on the wire, which is why only one of the two windows is something you can see in a packet capture.
A receiver advertises a window of zero. What happens, and what breaks if that mechanism is missing?
The sender stops sending data immediately, which is correct. The problem is getting going again: when the application finally reads, the receiver sends a window update, but that is a pure acknowledgement carrying no data, and TCP never retransmits those. If it is lost, the receiver believes it has told the sender and the sender believes the window is still zero, and the connection is deadlocked on a perfectly healthy path. The sender therefore starts a persist timer and periodically sends a window probe, a segment with one byte of data, which forces an acknowledgement carrying the current window back.
The window field is only 16 bits. Is that not a problem on a fast link?
It is, and it is fixed by the window scale option in RFC 7323. Without scaling the sender can have at most 65,535 bytes outstanding per round trip, so on a path with 100 ms round-trip time the ceiling is 65,535 × 8 / 0.1 s, about 5.24 Mbps, no matter how fast the link is. The option carries a left-shift count of 0 to 14 applied to every later advertisement, taking the maximum window to about 1 GB. It is negotiated only in the opening handshake, so if a middlebox strips it from the SYN the connection still works and silently runs at the unscaled ceiling forever.
Do you ever deal with any of this directly?
You rarely implement a window; TCP and the kernel do it, and Linux even auto-tunes the receive buffer as it measures the path. You meet it in three concrete ways. Bulk transfers that will not go faster than a few megabits over a long path are almost always window scaling missing or a receive buffer that is too small for the bandwidth-delay product. Interactive applications that feel laggy in small writes are usually Nagle’s algorithm, which is why real-time code sets TCP_NODELAY. And any protocol that multiplexes streams over one connection has to add its own flow control on top, because TCP has exactly one window for the whole connection and cannot stop one stream starving another.

08 Practice problems

Six to work on paper

Write the units next to every number in these, because bits against bytes and milliseconds against seconds is where the marks actually go. Two of the six turn on counting transmissions rather than frames, and one of them has a total that is nearly forty times the ideal.

Two thousand bits of waiting

Easy
A link runs at 4 Mbps with a one-way propagation delay of 15 ms, and frames are 2,000 bits. Under stop-and-wait give the transmission delay in milliseconds, the ratio a, the utilisation as a percentage to two decimal places, and the effective throughput in kbps.
Follow-up
The throughput is the number that surprises people. Work it out from the frame size and the full cycle time rather than by multiplying the bandwidth by the utilisation, then check that the two routes agree, because if they do not you have mixed bits with bytes somewhere.
Show the hint
Write every quantity with its unit before you divide anything, and remember that a is built from the one-way delay while the cycle contains two of them.

Fill that same pipe

Easy
For the link in the previous problem, give the smallest sender window that reaches full utilisation, then give the smallest sequence-number field width m that supports that window under Go-Back-N and under Selective Repeat. State both values of m.
Follow-up
The two answers for m are not the same, and the gap is not a rounding artefact. At one particular width one protocol just clears the window while the other falls well short and has to spend another bit, purely because of what its receiver is allowed to do.
Show the hint
Get the window first, then test candidate widths against each bound separately rather than converting one answer into the other.

Two holes, not one

Medium
Frames 0 to 9 are sent with a window of 4. Frames 3 and 6 are each lost on their first transmission and get through on any later one. Assuming the sender only times out when it has nothing it is permitted to send, give the total number of transmissions under Go-Back-N and under Selective Repeat, and the number of undamaged frames the Go-Back-N receiver discards.
Follow-up
The second loss happens while the first one is still unrepaired, so the two losses are not independent and you cannot just double a single-loss answer. Under one of the protocols the second lost frame is repaired by a recovery that was started for the first.
Show the hint
Draw the sender window as a bracket and advance it one event at a time, writing down after every event which frames are outstanding and what the receiver is waiting for.

Which window is biting

Medium
A TCP sender has an advertised receive window of 64 KB, a congestion window of 8 KB, and 5 KB of unacknowledged data in flight. Give how many bytes it may send right now and which window is the binding constraint. Then the congestion window grows to 96 KB with the receive window unchanged and nothing in flight: give the new answer and the new binding constraint.
Follow-up
The binding constraint swaps between the two halves, and the two windows are not two estimates of the same thing. Being able to say which one is biting, and therefore who is being protected, is the whole question.
Show the hint
Both parts are the same one-line expression; the work is deciding what belongs inside it and what has to be subtracted afterwards.

The buffer that is not a saving

Medium
A Selective Repeat receiver uses a window of 6 and every frame carries 1,200 bytes of data. Give the minimum receive buffer in bytes, then the minimum receive buffer a Go-Back-N receiver with the same window needs, and state what the sender must buffer in each of the two protocols.
Follow-up
“Go-Back-N needs less memory” is only half true, and the missing half is on the other side of the link. Once you have written down all four buffer figures the real trade stops being memory against memory.
Show the hint
Ask what each side must still be able to produce or reorder after a loss, and remember that a sender cannot discard a frame merely because it has been transmitted.

One byte at a time

Hard
A receiver’s application reads one byte at a time from a full 4,096-byte receive buffer while the sender writes one byte at a time, so segments carry exactly 1 byte of data. Over IPv4, give the payload fraction of one such segment, the number of segments needed to move 4,096 bytes, the total bytes actually placed on the wire, and how that compares with sending the same data in full 1,460-byte segments. Then say why neither end can detect that anything is wrong.
Follow-up
One of the four numbers you compute here has already appeared in this lesson, produced by a completely unrelated cause, and in both cases the cure is batching. Note also that this connection is behaving correctly by every rule in the lesson, which is the uncomfortable part.
Show the hint
Count the headers before you count the data, and remember there are two of them stacked under every segment.