Gonzalo Murillo
Azure Rapid Response Team - Escalation Engineer @ Microsoft
发布日期: 2014 年 11 月 13 日
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 HTTP, Telnet, 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!
No alt text provided for this image
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)
No alt text provided for this image
Image source: http://spectrum.ieee.org/computing/networks/osi-the-internet-that-wasnt
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 as TCP/IP.
IP is a protocol in the Internet layer serving the transport layer.On the other side TCP 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'.
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 on TCP protocol, as it is the relevant protocol for explaining Delayed ACK.
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.
The structure of the TCP header is as follows:
No alt text provided for this image
There is a 32 bits (4 bytes) field in the TCP header that is known as the sequence number. There is also another 32 bits field for the ACK number and 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. If not, then it is acknowledging several.
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.
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 ACK can 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 an ACK 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 right ACK sequence number to acknowledge the segment (piggybacking).
So delayed ACK is basically a bet.
No alt text provided for this image
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 TCP segment 200 ms (or the Delayed ACK timer value).
One particular bad scenario is when Nagle´s Algorithm is in place together with Delayed ACK.
Fortunately in those scenarios Delayed ACK can be disabled or tuned.
For disabling Delayed ACK in Windows you need to set the registry key TcpAckFrequency to 1
http://support.microsoft.com/kb/328890
You can also tune the maximum number of pending ACKs in Windows XP/2003/Vista/2008/7:
[HKEY_LOCAL_MACHINE \SYSTEM \CurrentControlSet \Services \Tcpip \Parameters \Interfaces \{Adapter-id}]
TcpAckFrequency = 2 (Default=2, 1=Disables delayed ACK, 2-n = If n outstanding ACKs before timed interval, sent ACK)
More info: MS KB Q328890
More info: MS KB 815230 (XP/2003 needs hotfix or SP2 for it to work)
More info: MS KB 935458 (Vista/2008 needs hotfix or SP1 for it to work)
More info: MS KB 2020559 (Applies also to Win7/Win2008 R2)
Windows 2000/XP/2003:
[HKEY_LOCAL_MACHINE \SYSTEM \CurrentControlSet \Services \Tcpip \Parameters \Interfaces \{Adapter-id}]
TcpDelAckTicks = 1 (Default=2, 0=Disables delayed ACK, 1-6 = 100-600 ms)
More Info MS KB Q311833 (Win2000 requires SP3)
More Info MS KB Q321098
More Info MS KB Q321169
Hope you enjoyed this article about Delayed ACK and that you have now a better understanding of it.
48
4 条评论
赞
评论
分享
RIdwan Ganiyu
RIdwan Ganiyu
Thanks Gonzalo Murillo, this was helpful.
赞 回复
3 个月
Khushbu Kareliya
Khushbu Kareliya
That's a great explanation for Delayed ACK. Thank you @Gonzalo Murillo
赞 回复 赞 (1)
1 年
Diego Palopoli
Diego Palopoli
Astonishing article! Thanks a lot for your clear explanation Gonzalo.
Just a question, is there any "easy" way to confirm that a server-client application is being impacted by this particular configuration (delayed ack + Nagle´s Algorithm -> afar it is a default setting for AIX and Linux OS)? Maybe tcpcump? Or is it something to modify and validate for improvements?
赞 回复 赞 (2)
5 年
Jon Z.
Jon Z.
https://www.dynatrace.com/blog/understanding-application-performance-on-the-network-chattiness-application-windowing/ You might find this interesting.
赞 回复 赞 (1)
4 年
查看更多评论