I have been doing some reading into TCP Receive Window (RWIN), Maximum Segment Size (MSS) and Maximum Transmission Unit (MTU). Right off the bat I have some questions and I need a power user's help!

The following questions are based on my using of Wireshark with a Win7 client to view the frames in a TCP stream:

  1. Where do you look (in the TCP stream) to find the RWIN in use? Is it the SYN, SYN-ACK, or ACK? I am under the impression it is in the SYN packet of the 3-way handshake.
  2. What is the remote machine saying by a "Window Size Value" of 16425, and a "Calculated window size" of 65700 (Wireshark states a scaling factor of 4, i.e. 16425 * 4 = 65700) in the ACK packet?
  3. Which machine dictates the RWIN value used during transmission - the client or remote machine?
  4. As per TCP connection termination there is a FIN-ACK which indicates the remote machine wants to terminate the connection followed by an ACK from the client and then an RST-ACK again by the client thus closing the connection. Does the RWIN value in the FIN-ACK and ACK packets during this termination process have any significance because they are very different from the RWIN values stated in the 3-way handshake?

I have some more questions but answer here may have a bearing on them so I shall wait for some answers first :)

Thanks. QF


OK...easy parts first.

MTU is the Maximum Transmission Unit on a network link. Basically, this specifies how big of a packet that the local network link can handle...this is a "Layer 2" size (commonly Ethernet), so IP, TCP, UDP and other headers count against this value. Pretty straightforward.

MSS is Maximum Segment Size. This is a TCP value that is sent in SYN packets (both SYN and SYN/ACK). It specifies the amount of data that can be contained in a TCP segment. Its a TCP level item, so if an IP packet gets fragmented in transit, the MSS refers to the amount of data in the TCP segment of the re-assembled packet. Slight less straightforward, but still pretty easy to figure out.

Now things get complex.

RWIN is the TCP Receive WINdow. It is a value specified by receiver-side of a TCP connection in the "Window Size" field of the TCP header. The window is constantly adjusting its size in the duration of a TCP connection. There is a window for each direction of the TCP connection. The endpoints of a TCP will not be perfectly in sync with each other as to what the current window size of a direction of the TCP connection for the duration of the TCP connection.

OK, so remember that TCP represents a bytestream of data. An endpoint will have a buffer of memory in the OS for receiving TCP data for a connection. That buffer is represented (at least notionally) by the Window Size. As data gets put into the buffer, the window size will shrink, and as data is read off the buffer by the application, the window size will grow.

The sending side of the TCP connection will not transmit more data than the window size until it gets ACKnowledgement packets back that grow the window size.

OK...getting a bit more in depth, here...

Let's consider a hypothetical one-sided data transmission with a buffer size in the receiver of 10 bytes. At the beginning of the connection, the window size will be 10.

The sender sends a segment with 5 bytes of data in it. The sender now thinks the window is 5 bytes in size (its still holding onto those 5 sent bytes in case it needs to retransmit them, until an ACKnowledgement is received for them). The receiver has not yet received the packet, so it still thinks its window size is 10 bytes.

The sender then sends a segment with 3 bytes of data in it. The sender thinks the window is now 2 bytes in size (10 - 5 = 5, 5 - 3 = 2). The receiver still hasn't received any packets so it still thinks the window size is 10. The sender is now holding onto 8 bytes of data for potential retransmission.

The receiver receives the first segment, it stores the data into the buffer and sends out an ACKnowledgement. Its important to note that the OS has received the data and is acknowledging its receipt, but that the application still doesn't have the data. The acknowledgement will have an ACK of 5 (relative to the initial sequence numbers that were chosen) and a window size of 5 (because the data is still sitting in the buffer taking of 5 bytes of the 10 byte buffer).

The sender gets the acknowledgement of the 5 bytes, so it can toss the first 5 bytes that it was holding onto for retransmission because it knows they have reached the receiver successfully. Its still holding onto the other 3 bytes from the second segment, though because they have not yet been acknowledged. The sender sees that the window size sent by the receiver is 5, but that represents 5 bytes from the acknowledgement number. The sender knows that it has already sent another 3 bytes that it hasn't gotten an acknowledgement for, so it still thinks the window size is 2 bytes.

The sender now sends out a segment with 2 bytes of data in it. It now sees a TCP window of zero, meaning it cannot send any more data until the receiver opens up the window further. The sender is again holding onto 5 bytes of data for potential retransmission (the 3 from the second segment, and the 2 from the third segment).

The receiver receives the second segment with 3 bytes in it. It now has 8 bytes of data in its buffer. It sends an ACKnowledgement packet with a Acknowledgement number of 8 (relative to the Initial Sequence number), and a window size of 2. Those 8 bytes of data are still sitting in the OS buffer.

Now, the application reads 7 bytes of data from the buffer. The buffer now has 1 byte of data in it. The overall window size was 10, but with one byte of data in it, that leaves 9 bytes available, so the receiver sends a packet with an acknowledgement number of 8 (because no new data has been received), but the window size is now 9 (versus the 2 it was previously). This is the way the window gets grown so the sender can send more data.

The sender gets the ACK of the 8 bytes with the window size of 2. The sender can toss the 3 bytes of data from the 2nd segment, but it has already sent another 2 bytes, and the window size in that packet is 2, so the sender still sees a zero sized window and can't send any more data.

The receiver gets the 3rd segment with the 2 bytes in it. Puts the 2 bytes into the buffer, leaving 7 bytes free. Its sends a packet with an ACK of 10 (5 + 3 + 2), and a window size of 7.

The sender gets the ACK with the acknowledgement number of 8 and window size of 9. It has already sent 10 bytes total, so it still sees two bytes outstanding, so it sees a window size of 7 (9 - 2).

The sender only has 5 more bytes to send. That fits completely in the window size, so it sends the 5 bytes. It now sees a window size of 2, but it doesn't really matter because it has no more data to send. It now is holding onto 7 bytes of data for potential retransmission.

The sender gets the ACK with an acknowledgement number of 10 and window size of 7. It tosses the 2 bytes from the 3rd segment, still has 5 bytes its holding onto for potential retransmission.

The receiver gets the 4th segment with the 5 bytes of data, adds that data to its buffer (not containing 8 bytes), sends an ACK with acknowledgement number of 15 and a window size of 2.

The application then reads the 8 bytes sitting in the buffer so the buffer is now empty. The receiver sends an ACK with acknowledgement number of 15 and a window size back at the full 10.

The sender gets the ACK with acknowledgement number of 15 and window size 2. It can now toss the last of the data that it was holding onto for potential retransmission. It knows that all of its data has gotten to the receiver. It doesn't really care about the window size of 2 since it has no more data to send anyway.

The sender gets the last ACK with the acknowledgement number of 15 and window size 10.

OK, that's it for the hypothetical...hopefully that helps you understand how the receive window works and is handled by either side. The same sort of thing is going on using the sequence numbers, acknowledgement numbers and window size for any data going the other way on the TCP connection.

The RWIN values in packets with FIN bits should have the same significance. Can you give an example of what you're seeing in wireshark so we can help interpret them?

  • I haven't forgot to reply, I'm in the middle of some revision for upcoming exams and haven't the time to make a meaningful reply. That said I am still keen to maintain this thread so I should have a meaty enough reply for you by next weekend! Thanks for what you've wrote too. – I_lost_my_last_account May 11 '13 at 16:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.