TCP系列28—窗口管理&流控—2、延遲ACK(Delayed Acknowledgments)


一、簡介

之前的內容中我們多次提到延遲ACK(Delayed Ack),延遲ACK是在RFC1122協議中定義的,協議指出,一個TCP實現應該實現延遲ACK,但是ACK不能被過度延遲,協議給出延遲ACK的最大時間為0.5s。如果發送端連續發送最大的數據報文,那么沒兩個數據報文就需要回復一次ACK。延遲ACK主要目的是等待接收者應用層接收到數據處理后有可能會發送一個響應,這樣ACK報文就可以和這個響應報文一起發送了,這樣減少了網絡中的數據包的同時,也降低了主機的負載處理壓力。

二、linux實現概述

Linux在實現上有個延遲ACK定時器,這個定時器的定時時間保存在一個ato變量,這個ato的默認值為40ms,但是會動態調整,例如對於非交互式應用如果延遲ACK定時器超時的時候,ato變量的值就會倍增。但是延遲ACK定時器的最大定時時間為0.5s。與延遲ACK對應,linux還有一個quick ACK模式,這種quick ack模式下就會對每個數據包都回復一個ACK。在連接初始建立時候、收包間隔大於RTO時、收到不在接收窗內的報文的時候等場景下就會進入quck ack模式,進入quick ack模式的時候,會把quick ack計數器初始化為16(也有可能是小於16的某個值),這就是說隨后的16個數據包都不采用延遲ACK。

具體到延遲ACK判斷的時候,需要同時滿足幾個條件,如當前已經收到的但是還沒有回復ACK確認包的報文小於接收MSS、當前沒有處於quick ACK模式、當前緩存中沒有先前接收的亂序報文、當前延遲ACK的超時時間大於ato/4等條件

對於上面MSS的判斷條件,linux采用保守的方法來估計對端的發送MSS(即本端的接收MSS,在linux內核中以rcv_mss變量維護),初始化的時候,首先會在SYN報文中的MSS值、SYN-ACK報文中的MSS值、接收窗口的一半、536bytes中取一個最小值,然后在這個最小值和88bytes中取一個最大值,即為接收MSS值,隨后在這個TCP連接上面收到新的數據包的時候,一旦發現這個數據包比之前的接收MSS值大,就會把接收MSS值更新為這個數據包的大小。根據MSS這個判斷條件,在TCP高速傳輸的時候,一般都是以MSS發送數據,因此延遲ACK時候會每兩個報文回復一個ACK確認包。

quick ACK模式可以通過socket編程接口TCP_QUICKACK選項進行設置,但是這個設置只是設置了一個quick ACK模式的切換,隨后TCP的內部處理還可能會切換quick ACK模式。也可以通過路由表永久設置打開quick ACK 模式,例如下面就設置了127.0.0.1這條路由開啟quick ACK。

 
 
 
         
  1. ******@Inspiron:~$ sudo ip route change local 127.0.0.1 dev lo quickack 1
  2. ******@Inspiron:~$ ip route show table all| grep 'local 127.0.0.1'
  3. local 127.0.0.1 dev lo  table local  scope host  quickack 1

上面只是根據linux實現代碼概述了一下延遲ACK的實現,還有一些偏僻細節並沒有提到,感興趣的自行參考linux的實現代碼。下面我們根據上面的描述來看一個延遲ACK的wireshark示例。

三、wireshark示例

我們通過一個綜合實例來看一下延遲ACK模式的處理,示例圖中高亮的數據包是我標記出來的以方便查看,並非是wireshark自動標記的異常包。在后面介紹其他內容后我們還會穿插延遲ACK的示例。

1、綜合示例

首先在連接初始建立的時候,按照上面描述會進入quick ACK模式,quick ACK計數器初始化為16,連接初始建立進入quick ACK的目的主要是加速初始慢啟動過程。從下圖可以看到,從第三個數據包開始,client沒發送一個TCP報文,server端就會立即回復ACK確認包。另外從圖中可以看到此時client的SYN包中MSS為62,server端SYN-ACK報文中的MSS為65495,server端的接收窗口大小為43690,此時初始化接收MSS過程為,先計算min(62-12, 65495-12, 43690/2, 576)=62bytes,因為linux內部維護的MSS扣除了TSopt選項的12bytes,所以min計算中需要對兩端通告的MSS先減12。接着計算max(62, 88)=88bytes,即此時server端認為接收MSS為88byte。一旦后面進入延遲ACK模式后,如果接收的還沒有回復ACK確認的報文總大小超過88bytes的時候就會立即回復ACK報文。

接着我們看到從No36報文開始,server並不會對每個收到的TCP報文立即回復ACK了,即進入了延遲ACK模式。而之前的No4-No35共32個報文,包含16個client發過來的數據報文,16個server端回復的ACK報文,正好與quick ACK的初始值16對應。接着從No36開始,server端收到No36的時候判斷已經推出了快速ACK模式同時其他條件也滿足需要延遲ACK,啟動延遲ACK定時器,定時時間為40ms,但是server端在接收到No38報文的時候發現累計沒有回復ACK確認包的總數據量為120bytes超過了接收88bytes的接收MSS,因此立即回復了ACK確認包並取消延遲ACK定時器(根據編譯內核時候的配置也可能並不取消延遲ACK定時器,但是延遲ACK定時器超時后會判斷當前ACK已經發送而不再重復發送ACK)。隨后的No40-No43和No44-No47報文的處理流程與No36-No39類似不在重復描述

接着從No48報文開始,報文長度變為20bytes,這樣要超過88bytes的接收MSS就需要5個報文,可以從圖中看出,server端正是在接收到No48-No52共五個報文100bytes后才觸發了No53的ACK回復。可以看出No53和No48之間大約是12ms,並不是延遲ACK超時觸發的No53確認包回復。接着注意在No58處server端收到長度為150byte的數據包,server更新接收MSS為max(當前接收MSS, 150)=150bytes。接着從No60報文開始可以看到需要連續4個40bytes的報文才會立即觸發ACK回復(注意與上面接收MSS為88bytes,報文長度同為40bytes時候需要3個報文觸發ACK的場景進行對比)。

我們接着看No70-No73四個數據包總長度為140bytes低於150bytes的接收MSS,因此並沒能觸發ACK回復,最終延遲ACK定時器超時,回復No74確認包。此時ato更新為80ms,但是收到No75數據包的時候,ato又更新為60ms(ato更新這塊有點羅嗦,已經超出了本文的范圍,所以知道這個東西會更新就行了,想深入的可以去看代碼),因此延遲ACK定時器設置為60ms。No75-No78四個數據包總共120bytes沒有超過接收MSS,因此最終延遲ACK定時器超時,回復No79確認包,但是我們看到No79和No75之間時間差大約為58ms,與預期的60ms有些差距,原因是ubuntu16.04編譯內核默認的宏CONFIG_HZ=250,即1s為250tick,這個tick是TCP模塊使用的最小時間單位,即4ms,因此定時的時候有可能最大有4ms的誤差。可以從自行添加的內核log中確認此時的ACK延遲定時器為60ms。這個定時器誤差在TCP模塊中的其他各種定時器中也是可能會出現的。接下來No80-No84五個數據包總共為145bytes,沒有滿足150bytes的接收MSS,但是從圖中可以看到No84仍然立即觸發了ACK回復,原因是server端接收到No84數據包后,發現當前ato為40ms,距離觸發延遲ACK定時器的時間已經不足ato/4了,因此立即觸發了No85的ACK確認包。接着No86和No87直接同樣是延遲ACK超時。

接着因為No88與上一個數據包No86之間的時間差超過了RTO的值,server端重新進入quick ACK模式,並把quick ACK計數器初始化為16,對接下來的16個數據包立即回復ACK確認包,如下圖所示

2、通過路由表設置quick ACK模式

當執行下面語句設置quick ACK后,重新執行上面的程序,不會再出現延遲ACK的情況,限於篇幅不再附wireshark截圖,感興趣的可以自行去git下載

 
 
 
         
  1. sudo ip route change local 127.0.0.1 dev lo quickack 1

3、TLP與延遲ACK交互

在低時延場景下,TLP與延遲ACK交互可能會造成無效重傳,示例請參考后面SWS介紹文中的wireshark示例。


補充說明:

1、在MAC OS上可以通過設置net.inet.tcp.delayed_ack來配置延遲ACK,設置為0表示禁止延遲ACK,設置為1表示總是延遲ACK,設置為2表示每兩個數據包回復一個ACK,設置為3標識系統自動探測回復ACK的時機

2、windows可以通過在HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\IG條目下設置TcpAckFrequency參數來配置延遲ACK,可以通過TcpdelAckTicks來設置延遲ACK定時器的定時時間










免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM