What is Delayed ACK and how can it be a bottleneck

Before explaining what Delayed ACK is, lets start by clarifying some concepts.TCP/IP is used to refer to two different things. On one side TCP/IP is a suite of protocols that rule the Internet containing protocols like HTTPTelnet,ICMP,SSH and many others. On the other side TCP/IP is also a pair of protocols themselves. TCP as a protocol in the transport layer, and IP as a protocol in the Internet Access Layer.
Both TCP and IP protocols where invented by the fathers of the Internet: Vint Cerf and Bob Kahn. Thanks fathers of the Internet!html


TCP/IP, as a suite of protocols which includes the protocols TCP and IP, does not follow strictly the OSI model based in 7 layers. 

Instead a four layer (simpler) approach known as Internet model is followed (see below)ios


Image source: http://spectrum.ieee.org/computing/networks/osi-the-internet-that-wasntapp

The four layers of the Internet model are: Network Access, Internet, Transport and Application. As the Internet model is simpler than the OSI model, one layer in the Internet model corresponds to several layers in the OSI model. This is true except for the layers Internet and Transport where both models are basically the same. 

TCP and IP are the rock stars protocols of the suite of protocols known asTCP/IP.ide

IP is a protocol in the Internet layer serving the transport layer.On the other sideTCP is one protocol in the transport layer. There is another famous protocol in the transport layer called UDP. The function of TCP or Transmission Control Protocol as per Wikipedia is 'to provide a reliable, ordered and error-checked delivery of a stream of octets (bytes) between programs running on computers connected to a local area network, intranet or the public Internet'.ui

UDP, in contrast with TCP, is a transport protocol with no guarantee of delivery, ordering, or duplicate protection. There are some scenarios where UDP is better than TCP (for example VoIP), but TCP is by far much more used. Lets focus onTCP protocol, as it is the relevant protocol for explaining Delayed ACK.this

As TCP needs to guarantee the delivery of the segments, every segment being sent from the source (client) to the destination (server) needs to be acknowledged.spa

The structure of the TCP header is as follows:code

There is a 32 bits (4 bytes) field in the TCP header that is known as thesequence number. There is also another 32 bits field for the ACK numberand 9 bits for flags. One of the flags is a bit for ACK that must be set to 1 for indicating that the segment transmitted contains an acknowledgment of one or more segments already received. How many segments are acknowledged will depend on the ACK number value. If the ACK number is the same that the sequence number of the last segment +1, then is acknowledging only one segment. If not, then it is acknowledging several.orm

How data is transmitted and acknowledged in TCP:

Lets imagine that a host A is sending a segment to a host B which contains 1000 bytes of data. Suppose that the initial sequence number of the segment is 10.server

Once the host in destination receives the segment, it will take the sequence number (10) and will add 1000 (the number of bytes received) to that sequence number.

10+1000=1010

Then when host B wants to acknowledge the reception of that segment to A, it will send a segment back containing an ACK number of 1011 and the ACK flag bit turned on.

Please not that the ACK number is 1011 instead of 1010. 

This is basically saying:

Hey! I have received until byte 1010, please next time you communicate with me start with a segment whose sequence number is 1011. Apart from that, an ACKcan be pure if contains no data and is just for acknowledging one or more segments, or it can be not pure when apart from the ACK it contains data that is sent back from destination to source (this technique is know as piggybacking.

Sending a pure ACK is an opportunity lost; is the lost opportunity of sending anACK with data, instead of just a simple bit of information. In that sense it has an opportunity cost. Why? Because of the protocol overhead.

Remember that sending 1 bit of information does not only require 1 bit of information transmitted over the network, but that bit of information plus size of the headers.
The headers in TCP/IP are normally 40 bytes, so for sending 1 bit of payload, we are using 41 bytes!.

Bad thing right? Yes, too much overhead!

Delayed ACK to the rescue

Delayed ACK was invented to reduce the number of ACKs required to acknowledge the segments, so protocol overhead is reduced.
The specification can be found here: https://tools.ietf.org/html/rfc1122

Basically Delayed ACK is the destination retaining the ACK segment a period of time (200 ms in Microsoft Windows by default), expecting one of two things to happen:

1) That a new segment will arrive that will also require acknowledge, so we can ACK two segments in one pure ACK instead of in two separate ACKs; avoiding that way to transmit over the network 41 extra bytes. 

2) That, perhaps, before the ACK timer expires, the destination will need to send some data back to the source in which we can include the ACK bit and the rightACK sequence number to acknowledge the segment (piggybacking).

So delayed ACK is basically a bet.


Is the bet of destination saying "I bet 200 ms (or the value of the delayed ACK timer) that a new packet will arrive before the delayed ACK timer expires, or that we will need to send our own data back to the sender before 200 ms (in which we can include an ACK bit flag enabled). If I win, I save 41 bytes of the extra ACK I am avoiding. If I loose I lost a maximum of 200 ms

To illustrate the behaviour I have coded in a pseudo language derived from C a"Delayed ACK Algorithm"

Obviously it is not real implementation, is just an example to clarify things.

segment_received=0;
ack_delayed_timer=200;
timer=0;

while(connection_open)
{

while(timer<ack_delayed_timer)

if(there_is_a_segment_from_source())
segment_received++;

// If is the first segment, but there is data to be send back to source
// then we can add the ACK flag in that segment - piggybacking

if(segment_received==1 && is_possible_piggy_back())
{
piggy_back(sequence_number_of_the_last_segment+1); // ACK within the data
segment_received=0;
timer=0;
break;
}


// if 2 consecutive segments are received, we send a pure ACK

if(segment_received==2)
{
send_pure_ack(sequence_number_of_the_last_segment+1);
segment_received=0;
timer=0;
break;
}


sleep(1ms); 
timer++;

} //end while timer<ack_delayed_timer

// We could be here because the timer has expired without receiving a second segment so send a pure ACK, or because a break (ACK already sent)

if(timer==200)
{
send_pure_ack(sequence_number_of_the_last_segment+1);
segment_received=0;
timer=0;
}

} // end while connection open

Practical Example:

Segment 1 arrives to destination. Destination starts the ACK timer of 200 ms. Before the timer expires…

Segment 2 arrives. Destination sends a pure ACK as this is the second segment pending ACK in the queue.

Segment 3 arrives. Destination starts the ACK timer of 200 ms. Before the timer expires…
A packet with data needs to be send from destination to source. A non pure ACK(piggy-backed) is encapsulated with the answer and send back from B to A .

Segment 4 arrives. Destination starts the ACK timer of 200 ms. Timer expires…Destination sends a pure ACK.

There are, however some scenarios where Delayed ACK harms mores than heals.

Imagine that the source does not send more data if segments already transmitted are not acknowledged. In this case we are delaying each transmission of a TCPsegment 200 ms (or the Delayed ACK timer value).

One particular bad scenario is when Nagle´s Algorithm is in place together withDelayed ACK.

Fortunately in those scenarios Delayed ACK can be disabled or tuned.