What is TCP Window Scaling?
In the TCP header, the window size field is of size 16 bits. Using this field TCP users (client or server) can advertise a maximum of 216 = 65536 bytes or 64 KiB as its buffer size to its other end-user. But modern endpoint devices (e.g., phones, tabs, PCs, etc) have much more memory available in their buffers. This 16-bit field was enough during the initial design of the TCP in the 1980s. But today memory is cheaper and the network is very fast hence situation is different. Therefore, if the endpoint has more than 64 KiB memory available in its buffer for a TCP connection, how does it convey this information to the peer endpoint using that same 16-bit window size field?
There are two possible solutions:
1. Increase the window size field from 16 bits to 30 bits. But this is practically not possible. It is impossible to update this field in all the devices which are using the TCP across the globe.
2. Change the definition of window size. Use the scale factor to convey 30 bits window size using only 16 bits field in the TCP header. This is called window scaling.
What is TCP window scaling?
It solves the scalability issue with ‘receiver window’ or ‘advertised window’ or ‘user buffer‘ without increasing the size of the ‘Window’ field (which is 16 bits) in the TCP header. It expands the ‘definition’ of the Window field to 32 bits and then uses a ‘scale factor to carry this 32-bit value in the 16-bit window field of the TCP header. The scale factor is carried in a new TCP option called ‘Window Scale’.
There is an options field in the TCP header which was designed to accommodate all the future optimizations in the TCP. Window scaling also makes use of that option. The client first shares its scaling factor with the server in the SYN packet. When the server receives the scaling factor of the client in the ‘SYN’ packet; then it sends its scaling factor using the same option field in the ‘SYN+ACK‘ packet which is an acknowledgment packet for the connection request made by the client. There is the strict constraint that a ‘Window Scale’ option received on any other packet (except the SYN packet sent by the client first) should be ignored by the server (server should not share its scaling factor first).
Let say client sends SYN packet to server and says that its scaling factor = 2 and receives scaling factor of receiver in ‘SYN+ACK’ packet from receiver.
Now in next packet sender tells its window size = 200 bytes.
Then Server will calculate the real buffer size available at client as: window_size * 22 = 800 bytes.
Client first finds its real buffer size = 800 bytes then it right shifts(reduces) this value 2 times and stores in window size in header and shares with server.
When server receives scaling factor and window size then it left shifts(multiplies) this value 2 times to get real value of client buffer size.
There is one point to be noted when the client shares its scaling factor in the SYN packet to the server then this scaling factor is not applicable on that packet. It will be applicable only when the server accepts it and shares its scaling factor in the SYN+ACK packet. The scaling factor is applicable to the next packet onwards once the client and server both know each other’s scaling factor in advance. Next packet onwards they don’t send scaling factor in each packet.
Can we change the window scaling factor?
It is quite possible to update the window scaling factor. When the client contacts the server again in the future, it can again specify its window scaling factor to the server, and as a reply server will also share its window scaling factor in the SYN+ACK packet. Now, what if the TFO is enabled? Yes, then also a client can share its updated window scaling factor to the server in the SYN packet itself along with the GET request. As a reply to this, the server will also share its current window scaling factor in the ACK packet along with the data for the GET request. One more way is there to update the window scaling factor. Client should delete its cookies first. When cookies are deleted then initial 3 way handshake will take place and then itself client can share its new window scaling factor.
The scale factor is carried in a new TCP option called ‘Window Scale’. “shift. cnt” carries the scaling value. If shift. cnt = 2 then window size field value is left-shifted 2 times to get the real buffer size. Therefore, Scale factor = 2shift.cnt. The ‘shift. cnt’ is limited to 14. Thus, the maximum window size that can be advertised with this option is 230 = 1 GiB.
16 bits can be stored in window size field. Maximum of 14 bits can be stored in shift.cnt variable. Thus total bits advertised = 16+14 = 30
If the ‘shift. cnt’ value is greater than 14, the TCP will log the error but still use ‘14’ instead of the larger value specified in the ‘Window Scale’ option. Remember! the scaling factor applies only to the ‘Window Size’ field of the TCP header and not to the ‘variables’ that store ‘window values’ in the local machines.
Linux command lines:
Checking the default setting of TCP Window Scaling in the Linux Kernel
$ sysctl net.ipv4.tcp_window_scaling
Expected Output (it means that TCP Window Scaling is enabled):
$ net.ipv4.tcp_window_scaling = 1
Disable TCP Window Scaling (not recommended, but try it to learn and re-enable)
$ sudo sysctl -w net.ipv4.tcp_window_scaling=0
$ net.ipv4.tcp_window_scaling = 0
Please Login to comment...