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