Octet

Why was TCP window scaling needed, and how does it work?

Show the answer

Say this first

The window field is 16 bits, so without help the receive window tops out at 65,535 bytes. At 100 ms RTT that caps one flow at about 5.2 Mbit/s whatever the link speed. The window scale option (RFC 7323) is sent in the SYN and SYN-ACK with a shift count from 0 to 14; after the handshake each side multiplies the window field by 2 to the power of the peer's shift, up to about 1 GiB. Both sides must offer it, or neither side scales.

Go deeper

Example

A Linux host with default buffers sends wscale 7 in its SYN. Later its segments show win 502. The real window is 502 x 128 = 64,256 bytes. Each side picks its own shift from its maximum receive buffer, so the two values can differ.

Rules worth saying

  • Only in SYN and SYN-ACK. The factor cannot change during the connection.
  • If the client sends it and the SYN-ACK does not, scaling is off in both directions.
  • The maximum shift is 14, so the largest window is 65,535 x 16,384, about 1 GiB.

Where it goes wrong

  • A capture that starts mid-connection. Wireshark cannot know the factor and shows the raw field; it labels the scaling factor -1 (unknown). Capture from the SYN.
  • A middlebox that strips or rewrites the option. The connection works but every flow is capped at 64 KB per RTT. Captures on both sides of the device show the option disappearing.
  • An application that sets SO_RCVBUF. On Linux that fixes the buffer and turns off receive autotuning for that socket, which can leave the window far smaller than the path needs.

Traps

  • Reading win 502 in tcpdump as 502 bytes. tcpdump prints the raw field; multiply by the agreed scale.
How did you do?Book 5.2 Reliable Byte Stream (TCP)Book 1.5 Performance