Monday, May 18, 2015

TCP SACK Demystified

In this blogtorial, we will briefly explore TCP SACK (Selective Acknowledgement) option and the benefits of using TCP Selective Acknowledgement. TCP SACK is negotiated in the initial 3-way TCP handshake and both parties must agree to use this option or TCP SACK will not be permitted.

Let's walk through an example and observe what happens when SACK is not enabled.



Notice that although the receiver successfully received Packets 4,5,6, and 7 the server still had to retransmit Packets 4,5,6 and 7. This is because the receiver had no way of informing the sender of the successfully received packets.

Now let's walk through the same example with SACK enabled. 



Only the dropped packet (SEQ 3 in this case) had to be retransmitted so we are not wasting bandwidth retransmitting successfully received packets. 

Example of a file transfer with and without TCP SACK enabled.



 01:21 root@arwin# scp /tmp/1.txt arwin@ithitman_server1:/tmp/  
 1.txt           100%  49MB  1.1MB/s  00:46 #### TCP SACK disabled…  

 ---------------------------------------------------------------------------------
 ---------------------------------------------------------------------------------

 01:22 root@arwin# scp /tmp/1.txt arwin@ithitman_server1::/tmp/  
 1.txt           100%  49MB  3.1MB/s  00:16 #### TCP SACK enabled … 3 times better performance   


Here is another view on what is happening under the hood when TCP SACK is enabled. 


Bytes 200-299 and Bytes 500-599 is dropped ... only the dropped bytes are transmitted. 


*LB = Left Block Edge
*RB = Right Block Edge
Footnotes about SACK: 

TCP minimum header size is 20 bytes and max header size with TCP options is 60 bytes which means we have 40 bytes left over for SACK. Each SACK message will take up 8 x N + 2 bytes (N is the number of blocks being described) which means we can specify up to 4 blocks. 

It is allowed by the RFC for the receiver to discard data that was originally SACK'd. For this purpose, sender must keep all transmitted data in the buffer until an ACK is received for the transmitted segments. 

It is allowed by the RFC for the senders to discard data that was originally SACK'd but have not been ACK'd yet, if the sender runs out of buffer space. However this behavior is frowned upon and depends on the TCP implementation of the sender. 

If TCP options are used such as TCP TimeStamp then less blocks can be specified with SACK. If you are interested in further reading please see RFC 1072 and RFC 2018.

Many more articles to come so ....

Please subscribe/comment/+1 if you like my posts as it keeps me motivated to write more and spread the knowledge.