TCP系列52—擁塞控制—1五、前向重傳與RACK重傳擁塞控制處理對比

1、概述linux

這裏主要簡單分析一個丟包重傳並恢復的場景,經過不一樣的設置讓這個相同的場景分別觸發RACK重傳和前向重傳,經過對比說明如下問題:tcp

  1. Forward Retransmit能夠產生只有重傳標記的數據包,也能夠產生同時具備重傳標記和SACK標記的數據包,注意這裏說的這些數據包是沒有Lost標記的,這是前向重傳與以前介紹的快速重傳及其變種的差別,進而會對in_flight的統計產生影響。spa

  2. Recovery狀態,FACK會利用一個dup ACK來前向標記丟失的數據包。code

  3. RACK能夠利用重傳在時間域來標記丟失的數據包,而重傳報文和初傳報文在系列號空間重疊,所以傳統的基於系列號空間的標記方法不能利用重傳標記丟失的數據包。orm

  4. RACK並無實現協議中的"reordering settling"定時器。server

  5. RACK目前linux4.4限制只能在Recovery狀態或者Loss狀態下使用,可是時間域標記的RACK在原理上與傳統的系列號空間標記Lost的原理是相互獨立的,因此RACK實際上也能夠單獨使用blog


RACK重傳和前向重傳的基本原理前面已經介紹過,這裏再也不重複介紹。ip


2、wireshark示例ci


業務場景:server端創建鏈接後休眠1s,而後以3ms爲間隔連續寫入9個數據包,每一個數據包的大小都是50bytes。client正常接收到了第1個數據包和第8個數據包,另外第6個數據包的重傳client也沒有接收到。下面兩個示例中,我黑底白字高亮標記出來的數據包是傳輸過程當中丟失的數據包。路由設置以下路由

 
 
 
 
 
******@Inspiron:~$ sudo ip route add local 127.0.0.2 dev lo congctl reno initcwnd 12 ssthresh lock 30     #參考本系列destination metric文章******@Inspiron:~$ sudo ethtool -K lo tso off gso off  #關閉tso gso以方便觀察cwnd變化

快速恢復過程當中擁塞窗口cwnd的PRR更新過程前面已經介紹過屢次了,再也不詳細逐包解釋,重點關注sack標記的變化、RACK利用重傳標記lost等相關點。

一、Forward Retransmit

設置tcp_recovery=0關閉RACK重傳,咱們先來看一下前向重傳的效果。

No1-No3:client與server端三次握手創建鏈接。初始ssthresh=30,初始cwnd爲12,擁塞控制處於Open狀態。

No4-No12:server端在休眠1000ms後,連續發送9個數據包,每一個數據包的發送間隔爲3ms,其中只有No4和No11數據包順利到達client端,其他數據包丟失。

No13:client對於No4報文響應,確認接收到了No4,server端更新cwnd=13。

No14-No15:No14是對應No11報文的ACK確認包,能夠看到這是一個dup ACK,此時fackets_out=7,dupthresh=3,fackets_out-dupthresh=4。所以server端把No五、No六、No七、No8這四個數據包標記爲lost。接着server端先重傳No5數據包,發出No15後,packets_out=8,sacked_out=1, lost_out=4, retrans_out=1,ssthresh=6,cwnd = 4,server端直接從Open狀態切換到Discovery狀態。

No16-No18:server端收到No16這個確認包後,擁塞控制進行更新,容許server端發出兩個數據包,所以server端接着重傳No6和No7數據包,即對應No17和No18,packets_out=7,sacked_out=1, lost_out=3, retrans_out=2,ssthresh=6,cwnd = 5。

No19-No21:server端收到No19後,擁塞窗口更新後,所以server端重傳No8數據包,即對應No20,此時cwnd還容許發出新的數據包,可是被標記爲lost的4個數據包都已經進行了重傳,同時server端也沒有新數據等待發送,所以server端進行前向重傳,重傳No9數據包,對應No21。注意這裏No21報文並無被標記爲lost狀態,可是前向重傳後,No21會被標記爲Retrans,這就意味着着一個數據包要統計爲兩個in_flight,這是前向重傳與其餘重傳方式的差別點。發出No21後,packets_out=6,sacked_out=1, lost_out=2, retrans_out=3,ssthresh=6,cwnd = 6。注意這裏retrans_out已經比lost_out高了。

No22-No23:server端收到No22後,cwnd更新容許發出一個數據包,此時繼續前向重傳No10數據包,對應No23,傳輸完No23後packets_out=5,sacked_out=1, lost_out=1, retrans_out=3,ssthresh=6,cwnd = 6。

No24:server端在收到這兩個數據包的時候已經沒有等待發送的新數據了,而前向重傳已經傳到了最高的SACK塊,雖然No12數據包也丟失了,可是No12是系列號空間的尾包不會觸發前向重傳,所以server端cwnd更新後雖然容許傳輸數據包,可是TCP暫時沒有能夠傳輸的數據包。No24是partial ACK會重啓RTO定時器,定時時間大約爲250ms。packets_out=4,sacked_out=1, lost_out=0, retrans_out=2,ssthresh=6,cwnd = 6。

No25:No25經過SACK確認了前向重傳的No23數據包,這時候No23數據包的狀態則是同時具備Retrans和Sack標記,另外注意這個確認包是一個dup ACK,FACK下這個dup ACK會觸發繼續向前標記一個lost數據包,所以server端會把No9報文標記爲lost,而後嘗試重傳的時候,發現實際No9數據包已經重傳過了,所以再也不進行重傳嘗試。最終packets_out=4,sacked_out=2, lost_out=1, retrans_out=2,ssthresh=6,cwnd = 4。

No26-No33:No24處設置的RTO定時器超時後,server端TCP進入loss狀態,並把尾包No11也標記爲loss狀態,No10由於已經被SACK確認,所以不會標記爲lost。接着server端進行RTO超時恢復過程,並在最後關閉鏈接。


二、rack

設置tcp_recovery=1打開RACK重傳後,咱們先來看一下RACK重傳的效果,注意與前向重傳對比。

No1-No15:與上面示例類似,再也不重複介紹

No16-No18:No16這個報文確認了No15這個重傳報文,No15報文發出的時間點爲1.123581s,server端在收到No16這個報文的時候,RACK會把1.122581s以前發送的還未被ack number或者SACK確認的數據包標記爲lost,所以No九、No十、No12報文都會被標記爲lost狀態,能夠RACK的一個重大改進是能夠利用重傳報文來標記lost了。cwnd更新後,server端發出兩個數據包No17和No18。發出No18後packets_out=7,sacked_out=1, lost_out=6, retrans_out=2,ssthresh=6,cwnd = 2。

No19-No24:No19-No21這一組和No22-No24的處理都是相似的,收到partial ACK後,更新cwnd=in_flight + 2,而後發出兩個新的數據包,這種場景前面介紹過屢次,再也不贅言。

No25:server端在收到No25報文後,重啓RTO定時器,定時時間大約爲250ms。

No26-No27:注意這兩個報文經過SACK確認了No23和No24,雖然No23和No4都位於丟失的No21後面,可是三個數據發送的時間差並無達到1ms,所以RACK不能標記No21丟失。

No28-No33:RTO定時器超時後,這裏能夠看到linux實現的RACK並無實現"reordering settling"定時器功能,server端進入Loss狀態,恢復後關閉了TCP鏈接。






相關文章
相關標籤/搜索