Have you ever been in the middle of a phone conversation when, suddenly, there is a loss of signal and you can’t hear the person on the other end? What do you do next? Tell the speaker the start and end of the part of the conversation that you didn’t hear?
Well, computers communicate the same way with a TCP acknowledgement option called Selective Acknowledgement.
TCP protocol utilizes retransmissions when packets are lost or damaged. The original TCP acknowledgement system can’t handle multiple segments that are lost; it only acknowledges the last successfully received segment (before the loss), which then leads to the retransmission of data that has been already received by the receiver. This is obviously unnecessary, as it is a waste of time and causes network congestion that could’ve easily been avoided. This is where Selective Acknowledgment, or SACK, is most beneficial.
Here is where Selective Acknowledgment, or SACK, is most beneficial.
SACK is the method of resending only the necessary packets that never reached the receiver. In return, this improves the network’s performance, as fewer packets being retransmitted means a more efficient use of bandwidth. This is especially noticeable for connections using large TCP window sizes.
Without SACK, in the case of packet loss, the receiver would send a Duplicate Acknowledgment (DUP ACK) saying that it has only received data up to a specific segment. The sender would then resend all of the following segments of data, even if the receiver already received most of them. This would cause the receiver to get duplicates of some of the data, which is a waste of resources.
There are two types of SACK options. The first, the SACK-Permitted Option, is only present in the SYN packet and informs the both sides of the connection that it can receive the SACK option, which is a part of the initial connection.
Below is a graphic representation of SACK-permitted Option from RFC 2018; this shows the TCP kind and length that is relative to SACK that is sent during initial connection.
The second type of SACK is the Option format. This is when the receiver gives the sender detailed knowledge of which data has been received, which in return allows the sender to retransmit the missing pieces of data. This will be sent when there is lost data during a packet transfer.
Here we see a graphic representation of the Option format from RFC 2018.
Now take a look at this step-by-step explanation of the SACK process.
Sender sends 10 segments of data, each containing 100 bytes of data, to a receiver starting with a sequence number of 1000.
The receiver receives segments 1 through 4 and 6 through 10.
The receiver then realizes that it is missing some data and sends a TCP ACK segment back to the sender, with a SACK option specifying a left edge of 1400 and a right edge of 1500.
The sender then retransmits the 5th segment back to the receiver all by itself.
The receiver receives the 5th segment and sends an acknowledgement packet to the sender informing them that they have now received all of the segments.
Now, let’s dig deeper into the concept of SACK with a real world example captured by Wireshark. Here’s an example of a SYN Packet showing the SACK Permitted Option with a Kind of 4 and a Length of 2. See the last two lines of the capture below.
This shows that my computer, the source, was letting the server, the destination host, know that it has SACK enabled. Therefore, the server knows that the source can ask for specific segments of data. If the server support SACK, it needs to include the SACK Permitted Option in the SYN-ACK.
Now, here’s a later packet from the source (computer) showing an actual SACK option with the left edge of the block of data not received specified as 18225, and the right edge of the block of data not received specified as 18620. See the last section of lines in the capture below:
As you can see, that informs the destination host of the specific bytes of data that were lost. With SACK, the server now knows that it only has to resend the sequence numbers 18225 to 18620, which saved time and resources as a result.
Some problems have arrived since the early adaptation of SACK. For example, it’s possible for a receiver to receive packets out of order due to some unknown network connectivity problems. This would result in the sender retransmitting the skipped packet out, which will slow down the rate of data delivery.
Since then, there has been an extension implemented to SACK which has introduced duplicate selective acknowledgment, or D-SACK, in RFC 2883. Some of these improvements include proper reporting of duplicate and/or out-of-order segments. This allows the sender to figure out the order of packets received by the receiver and in return understand when it has retransmitted an unnecessary packet.
Unfortunately, the SACK option is not mandatory and is only used when both ends of the TCP connection support it. Luckily, all major recent TCP stacks now support it.
SACK is important because it allows for a more robust packet retransmission, allowing the sender to be notified of what pieces of data made it to the receiver when there is packet loss and the retransmission of duplicate packets with D-SACK. This promotes less network congestion and better handling of packets, thus allowing a faster rate of data delivery.