TCP系列48—拥塞控制—11、FRTO拥塞撤销
一、概述
FRTO虛假超時重傳檢測我們之前重傳章節的文章已經介紹過了,這里不再重復介紹,針對后面的示例在說明兩點
1、FRTO只能用于虛假超時重傳的探測,不能用于虛假快速重傳的探測。
2、延遲ER重傳觸發的進入Recovery狀態時候,并不會立即更新cwnd。
本篇在演示FRTO的同時,還會涉及到ER超時重傳、TLP探測、SACK關閉場景下的擁塞撤銷,后面或者前面都會有針對這些場景的專門介紹文章。
一、wireshark示例
1、FRTO與ER
我們通過一個示例看一下關閉SACK時候,tcp_sack=0,FRTO虛假超時探測和擁塞撤銷的處理,同時我們需要設置關閉TSopt選項,否則Eifel探測會先于FRTO探測到虛假超時,tcp_timestamps=0,后面我們會介紹到Eifel探測。如下設置相關參數
業務場景:server端在與client端建立連接后休眠1s,然后寫入50bytes數據,接著休眠46ms,然后以3ms為間隔連續寫入6次,每次寫入50bytes。client在收到第一個數據包并回復ACK確認包后,server與client之間的RTT突然變大(RTT大約從50ms突變為300ms,例如移動終端切換場景),然后server端觸發虛假RTO超時。最終TCP流交互如下圖所示。
No1-No9:server端慢啟動過程,不再解釋,注意因為關閉了SACK功能,因此TLP功能也不會使能,因此server端在收到No7數據包的時候會重新啟動RTO定時器,后面也不會被改寫為TLP定時器。發出No9后ssthresh=15, cwnd=4, packets_out=4, sacked_out=0, ?lost_out=0, retrans_out=0。
No10:RTO超時后,server端從Open狀態切換為Loss狀態,更新prior_ssthresh=max(ssthresh, cwnd*3/4)=15, ssthresh=max(cwnd/2, 2)=2, cwnd=1,并把No5、No6、No8、No9四個數據包標記為lost,lost_out=4,接著重傳No5數據包,retrans_out=1。并且當前滿足使能FRTO的條件。
No11-No13:No11報文為client對No5的確認包,server端收到No11報文后,更新packets_out=3,?lost_out=3,retrans_out=0,發現當前使能了FRTO功能,并且No11這個報文的ack number確認了新的數據包,因此server端FRTO嘗試發出新的未發送數據包,此時cwnd=1,in_flight=3-(3+0)+0=0,因此發出一個數據包即No12,FRTO對這個ACK報文的處理結束。接著reno的慢啟動更新cwnd=2,又發出一個新數據包即No13。最終packets_out=5。
No14:server端收到No14報文后,更新packets_out=4,lost_out=2,發現No14這個確認包相比No11又確認了新的數據包,而且新確認的數據包是未曾重傳過的No6數據包,因此server端FRTO認定之前的No10重傳為虛假超時重傳,接著進行擁塞撤銷,更新cwnd=max(cwnd,2*ssthresh)=4,ssthresh = max(ssthresh,prior_ssthresh)=15,并取消No8、No9數據包的lost標記,更新lost=0,server端從Loss狀態切換為Open狀態。接著reno的慢啟動更新cwnd=5。
No15-No16:同樣是延遲到達的ACK報文,最終ssthresh=15, cwnd=7, packets_out=2, sacked_out=0, ?lost_out=0, retrans_out=0。
No17:No17是No10的確認包,是一個dup ACK,server端收到No17后更新sacked_out=1,并從Open狀態切換為Disorder狀態,此時滿足
sacked_out>0,?packets_out >= (sacked_out + 1) , packets_out < 4這幾個條件且沒有待發送的新數據,因此觸發延遲ER,設置ER定時器為RTT/4(大約為35ms)。處理完No17后ssthresh=15, cwnd=7, packets_out=2, sacked_out=1, ?lost_out=0, retrans_out=0。
No18:ER定時器超時后,server端從Disorder狀態切換到Recovery狀態,更新high_seq=351, prior_ssthresh=max(ssthresh, cwnd*3/4)=15, ssthresh=max(cwnd/2, 2)=3,并把No12數據包標記為lost,更新lost_out=1,接著重傳這個數據包,即發出No18,并更新retrans_out=1, prr_out=1。最終ssthresh=3, cwnd=7, packets_out=2, sacked_out=1, ?lost_out=1, retrans_out=1。注意ER定時器超時重傳的時候并沒有直接削減cwnd。
No19-No20:No19是一個partial ACK,更新packets_out=1, sacked_out=0, ?lost_out=0, retrans_out=0,SACK關閉場景下收到partial ACK,會立即把partial ACK的ack number對應的數據包(即No13)標記為lost,因而又更新lost_out=1,接著進入更新cwnd的流程,注意這里newly_acked_sacked=0, 因此并不會更新cwnd?,接著重傳標記為lost的數據包即No20,更新retrans_out=1,prr_out=2。
No21:No21是No13數據包的確認包,server端收到No21的時候,更新packets_out=0,lost_out=0,retrans_out=0,Ack=351=high_seq,即正好到達Recovery point,但是因為此時SACK處于關閉狀態,因此server端并不會從Recovery狀態切換到Open狀態,更新cwnd=min(cwnd, in_flight+dupthresh)=3, 最終處理完No21后,ssthresh=3, cwnd=3, packets_out=0, sacked_out=0, ?lost_out=0, retrans_out=0,?prr_delivered=0,?prr_out=2。(No21數據包的處理請參考介紹SACK關閉場景擁塞撤銷處理的文章)。
No22-No23:server端收到虛假重傳的dup ACK的確認包,最終處理完No23后,server端處于Recovery狀態,ssthresh=3, cwnd=3, packets_out=0, sacked_out=0, ?lost_out=0, retrans_out=0,?prr_delivered=0,?prr_out=2。
2、FRTO與TLP
我們會在DSACK擁塞撤銷的文章中用示例演示了server與client協商好TSopt后,如果收到不帶有TSopt選項的數據包,雖然協議建議靜默丟棄這種報文,但是linux仍然正常接收處理。這個示例我們先來看一下client如果與server協商好SACK選項后,而client側代碼bug或者其他原因導致收到亂序包后回復的dup ACK沒有攜帶SACK信息時候,server端會如何處理。同樣在執行示例前如下設置相關TCP參數:
業務場景:server端在與client端建立連接后休眠1000ms,接著以3ms為間隔,連續發送10個數據包,每個數據包的大小為50bytes,其中高亮標出的No7數據包在傳輸中丟失。client對于收到的亂序的報文回復的dup ACK確認包并不帶有SACK選項。最終如下圖所示:
No1-No12:連接建立后的擁塞避免過程,最終發出No23后,?ssthresh=4, cwnd=4,cwnd_cnt=1, packets_out=5, sacked_out=0, ?lost_out=0, retrans_out=0, fackets_out=0,server端處于Open狀態,并設置了TLP定時器,PTO=2*RTT,大約為100ms。
No13:這個dup ACK是對No8報文的回復,但是可以看到里面并沒有SACK選項,但是在三次握手的時候client和server端是協商了SACK的,因此server端在收到這種不帶有SACK選項的dup ACK的時候,并不會更新sacked_out,因此server端也并不會進入Disorder狀態。但是server端在收到這個dup ACK的時候,會先取消PTO定時器并設置成RTO定時器,然后檢查收到報文的ack number是否能取消RTO定時器,因為收到的報文ack number并沒有完整確認數據,因此仍然保留有RTO定時器的設置,接著server端在檢查如果當前有設置RTO定時器,就會嘗試取消RTO定時器設置為PTO定時器。因此收到No13后,server端最終又會重新設置PTO定時器為2*RTT,大約為100ms。
No14-No16:這幾個報文的處理與No13類似,最終收到No16后,重設PTO定時器為100ms。
No17:PTO定時器超時,觸發loss probe過程,此時緩存中有待發送的新數據,因此發出No17數據包,更新packets_out=6,并取消PTO定時器設置成RTO定時器。
No18:server端收到No18后又會把RTO定時器重設為PTO定時器,定時時間大約為100ms。
No19-No24:這幾個數據包的處理與No17、No18類似。收到No24后,重設PTO定時器,定時時間為100ms。此時?ssthresh=5, cwnd=4,cwnd_cnt=1, packets_out=9, sacked_out=0, ?lost_out=0, retrans_out=0, fackets_out=0,server端處于Open狀態,注意此時cwnd=4,in_flight=9,可以看到loss probe報文并不會受到擁塞控制cwnd的限制。
No25:當PTO定時器再次超時的時候,此時server端的緩存中已經沒有待發送的新數據包,因此重傳最后發送的數據包(即No23),注意雖然No25發生了數據包的重傳,但是TLP重傳后,server端TCP仍然會停留在Open狀態,而且并不會更新lost_out等字段,因此重傳完No25后,?ssthresh=4, cwnd=4,cwnd_cnt=1, packets_out=9, sacked_out=0, ?lost_out=0, retrans_out=0, fackets_out=0,server端TCP處于Open狀態,并且當前設置有RTO定時器。
No26:server端在收到No26這個dup ACK后的處理與No13類似,最終會把RTO定時器重設為PTO定時器,定時時間大約為100ms。
No27:No26設置的PTO定時器超時后發現當前已經有了一個TLP超時重傳(即No25),因此不會在進行TLP尾包重傳,而是設置RTO定時器,定時時間大約為250ms,最終RTO超時觸發No27重傳,此時server端由Open狀態切換為Loss狀態,發出No27后以指數回退重設RTO定時器,相關狀態變量如下,prior_ssthresh=4,?ssthresh=2, cwnd=1,cwnd_cnt=1, packets_out=9, sacked_out=0, ?lost_out=9, retrans_out=1, fackets_out=0。
No28:No28的ack number確認了未重傳的數據包,因此觸發FRTO擁塞撤銷,更新cwnd=max(cwnd,2*ssthresh)=4,ssthresh = max(ssthresh,prior_ssthresh)=4,同時server端從Loss狀態切換為Open狀態,然后在Open狀態下進入reno的擁塞避免過程,No28的ack number新確認了9個數據包,9/cwnd=2,因此更新cwnd=cwnd+2=6,cwnd_cnt=9-2*4=1,最終ssthresh=4, cwnd=6,cwnd_cnt=1, packets_out=0, sacked_out=0, ?lost_out=9, retrans_out=0, fackets_out=0
來自為知筆記(Wiz)
轉載于:https://www.cnblogs.com/lshs/p/6038792.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的TCP系列48—拥塞控制—11、FRTO拥塞撤销的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PCI-DSS-术语小结
- 下一篇: bzoj4636: 蒟蒻的数列