在TCP/IP中,快速重傳和恢復(fast retransmit and recovery,FRR)是一種擁塞控制算法,它能快速恢復丟失的數據包。沒有FRR,如果數據包丟失了,TCP將會使用定時器來要求傳輸暫停。在暫停的這段時間內,沒有新的或復制的數據包被發送。有了FRR,如果接收機接收到一個不按順序的數據段,它會立即給發送機發送一個重復確認。如果發送機接收到三個重復確認,它會假定確認件指出的數據段丟失了,並立即重傳這些丟失的數據段。有了FRR,就不會因為重傳時要求的暫停被耽誤。 當有單獨的數據包丟失時,快速重傳和恢復(FRR)能最有效地工作。當有多個數據信息包在某一段很短的時間內丟失時,它則不能很有效地工作。快速重傳快速恢復算法是在4.3BSD Reno中提出的,並在RFC 2001和RFC2581中描述。 FRR也指誤拒絕率(false rejection rate),一個在生物安全系統中使用的術語。
1. Tahoe
Tahoe算法是TCP的早期版本。它的核心思想是:讓cwnd以指數增長方式迅速逼近可用信道容量,然后
慢慢接近均衡。Tahoe包括3個基本的擁塞控制算法:慢啟動、擁塞避免、快速重傳。
我們可以看到,Tahoe不存在快速恢復算法。這也是它的不足之處。
在收到3個重復ACK或者在超時的情況下,Tahoe置cwnd為1,然后進入慢啟動階段。這一方面會引起網
絡的激烈震盪,另一方面大大降低了網絡的利用率。
也就是說,一旦發現掉包,那么cwnd就被打回原形。
沒有快速恢復算法,在恢復丟失數據包期間,不能發送新的數據包,這段時間的吞吐量為0。而實際上
如果利用這段時間來發送適量的新數據包,可以大大的提高丟包時的傳輸效率。這就是快速恢復名稱的
由來。
2. Reno
Reno與Tahoe相比,增加了快速恢復階段,也就是說,完成快速重傳后,進入了擁塞避免階段而不是慢
啟動階段。
Reno prevents the communication path from going empty after Fast Retransmit.
Reno sender uses additional incoming dup ACKs to clock subsequent outgoing packets.
算法描述:
- step1:
- if ( dupacks >= 3 ) {
- ssthresh = max( 2 , cwnd / 2 ) ;
- cwnd = ssthresh + 3 * SMSS ;
- }
- step2:重傳丟失的分組
- step3:此后每收到一個重復的ACK確認時,cwnd++
- step4:當收到對新發送數據的ACK確認時,cwnd = ssthresh,這個ACK能夠對那些在
- 丟失的分組之后,第一個重復ACK之前發送的所有包進行確認。
- step1:
- if ( dupacks >= 3 ) {
- ssthresh = max( 2 , cwnd / 2 ) ;
- cwnd = ssthresh + 3 * SMSS ;
- }
- step2:重傳丟失的分組
- step3:此后每收到一個重復的ACK確認時,cwnd++
- step4:當收到對新發送數據的ACK確認時,cwnd = ssthresh,這個ACK能夠對那些在
- 丟失的分組之后,第一個重復ACK之前發送的所有包進行確認。
在快速恢復階段,每收到重復的ACK,則cwnd加1;收到非重復ACK時,置cwnd = ssthresh,
轉入擁塞避免階段;如果發生超時重傳,則置ssthresh為當前cwnd的一半,cwnd = 1,重新進入
慢啟動階段。
Reno快速恢復階段退出條件:收到非重復ACK。
3. NewReno
Reno不能有效的處理多個分組從同一數據窗口丟失,於是有了NewReno。
NewReno修改了Reno的快速恢復算法,處理一個窗口中的多個報文段同時丟失時出現的“部分確認”
(Partial ACKs,它在快速恢復階段到達並且確認新數據,但它只確認進入快速重傳之前發送的一部分
數據)。
在這種情況下,Reno會退出快速恢復狀態,等待定時器溢出或者重復的確認ACK到達,但是NewReno
並不退出快速恢復狀態,而是:
- step1:重傳緊接着那個部分ACK之后的報文段,擁塞窗口等於其減去partial ACK的部分。
- step2:對於得到確認的新數據,cwnd++
- step3:對於第一個或每一個Partial ACK,重傳定時器復位。且每次都重置cwnd = 原cwnd / 2。
- step1:重傳緊接着那個部分ACK之后的報文段,擁塞窗口等於其減去partial ACK的部分。
- step2:對於得到確認的新數據,cwnd++
- step3:對於第一個或每一個Partial ACK,重傳定時器復位。且每次都重置cwnd = 原cwnd / 2。
NewReno算法中有變量recover,其值為檢測到丟包時的最大發送序列號。只有當recover之前的數據
報都確認完后,才能推出快速恢復,進入擁塞避免階段。
當超時時,將發送的最大序列號保存在recover變量中,結束快速恢復過程。
NewReno不支持SACK。
4. SACK
During Fast Recovery, SACK maintains a variable calledpipe that represents the estimated number
of packets outstanding in the path.
The sender only sends new or retransmitted data when the estimated number of packets in the path
is less than the congestion window. The variable pipe is incremented by one when the sender either
sends a new packet or retransmits an old packet. It is decremented by one when the sender receives
a dup ACK packet with a SACK option reporting the new data has been received at the receiver.
Use of the pipe variable decouples the decision of when to send a packet from the decision of which
packet to send.
The sender maintains a data structure, thescoreboard, that remenbers acknowledgements from
previous SACK option. When the sender is allowed to send a packet, it retransmits the next packet
from the list of packets inferred to be missing at the receiver. If there are no such packets and the
receiver's advertised window is sufficiently large, the sender sends a new packet.
When a retransmitted packet is itself dropped, the SACK implementation detects the drop with a
retransmit timeout, retransmitting the dropped packet and then slow-starting.
The sender exits Fast Recovery when a recovery acknowledgement is received acknowledging
all data that was outstanding when Fast Recovery was entered.
- step 1:
- Fast Recovery is initiated,
- pipe -1 ( for the packet assumed to have been dropped).
- pipe +1 ( for the packet retransmitted)
- cwnd = cwnd / 2
- step 2 :
- If pipe <= cwnd,sender retransmits packets inferred to be missing.
- If there are no such packets, sender sends new packets.
- step 3:
- when sender receives a dup ACK, pipe = pipe - 1
- when sender sends a new / retransmit an old packet, pipe = pipe +1
- step 4:
- For partial ACKs :pipe = pipe - 2
- (one for original dropped packet,one for retransmitted packet)
- step 5:
- all packets outstanding before Fast Recovery were ACKed,
- exit Fast Recovery.
- 當退出Fast Recovery時,cwnd同樣恢復成ssthresh,進入擁塞避免。
- step 1:
- Fast Recovery is initiated,
- pipe -1 ( for the packet assumed to have been dropped).
- pipe +1 ( for the packet retransmitted)
- cwnd = cwnd / 2
- step 2 :
- If pipe <= cwnd,sender retransmits packets inferred to be missing.
- If there are no such packets, sender sends new packets.
- step 3:
- when sender receives a dup ACK, pipe = pipe - 1
- when sender sends a new / retransmit an old packet, pipe = pipe +1
- step 4:
- For partial ACKs :pipe = pipe - 2
- (one for original dropped packet,one for retransmitted packet)
- step 5:
- all packets outstanding before Fast Recovery were ACKed,
- exit Fast Recovery.
- 當退出Fast Recovery時,cwnd同樣恢復成ssthresh,進入擁塞避免。
與Reno不同的是:
(1)when to send packet:由計算pipe變化決定,不再是計算cwnd變化。
(2)which packet to send:由SACK攜帶信息決定,反應更迅速。
問題1:在一個窗口內重復丟包會造成影響嗎?
答案:會。如果只丟一個包,那么收到非重復ACK時,就能確認完本窗口內所有的包。然后進入擁塞
避免階段。這就是Reno想達到的。
而如果丟失多個包,那么收到非重復ACK時,不能確認完本窗口內所有的包。但是,也會退出快速恢復,
進入擁塞避免階段。
這個時候可能會發生兩種情況:
(1)多次進行快速重傳和快速恢復。又發現丟包,再次進入快速重傳和快速恢復。注意,每次進入
快速重傳和快速恢復時,ssthresh和cwnd都要減半。多次丟包最終會導致ssthresh指數減小。
通過畫cwnd(t)圖可以發現,不僅這段時間吞吐量非常低,而且導致恢復完后擁塞避免的起點非常低,從
而導致之后的吞吐量也很低。
(2)經過多次快速重傳和快速恢復,接着發生傳輸超時。
那么,發生傳輸超時需要什么樣的條件呢?
1) when two packets are dropped from a window of data, the Reno sender is forced to wait for a
retransmit timeout whenever the congestion window is less than 10 packets when Fast
Recovery is initiated, and whenever the congestion window is within two packets of the receiver's
advertised window when Fast Recovery is initiated.
2) when three packets are dropped from a window of data, the Reno sender is forced to wait for
a retransmit timeout whenever the number of packets between the first and the second dropped
packets is less than 2 + 3W/4, for W the congestion window just before the Fast Retransmit.
這種情況出現的概率極大,也就是說一個窗口出現3個丟包,有大概率出現超時。當丟包時窗口大小
為15,有三個丟包,那么無論丟包的順序如何,2次FR/FR之后,總會出現超時。
超時一般是因為未確認的數據包 > 可以使用的cwnd,不能發送新的數據,而網絡中有沒有足夠的
重復ACK來觸發FR/FR。
問題2:為什么發生擁塞時,還增加cwnd?
答案:在檢測到丟包時,窗口為cwnd。這時候網絡中最多有cwnd個包(in_flight < cwnd )。每當收到
一個重復的ACK,則說明有數據包離開網絡,達到接收端了。那么,此時網絡中還可以再容納1個包。由
於發送端滑動窗口不能移動了,所以如果想保持in_flight,可以使cwnd++。
這樣一來,可以提高吞吐量。而實際上,在fast recovery期間發送的新數據包比起發生丟包的cwnd來說,
已經是大大減少了。
性能分析
Tahoe沒有快速恢復機制,在丟包后,它不僅重發了一些已經成功傳輸的數據,而且在恢復期間吞吐量
也不高。
利用SACK option攜帶的信息,我們能夠提前知道哪些數據包丟失了。NewReno每個RTT內只能恢復
一個丟失的數據包,所以如果丟失了N個數據包,那么Fast Recovery就要持續N*RTT的時間,當N比較
大時,這是一段相當長的時間。而SACK則沒有這個限制,依靠SACK option的信息,它能夠同時恢復
多個數據包,更加快速和平穩的恢復。
當發生同一窗口多個丟包時,SACK和NewReno最終都能夠較為快速和平穩的恢復過來。而Reno則經
常出現超時,然后再用慢啟動來恢復,這個時候Reno的表現就如同Tahoe,會造成已接受數據的重復
傳送。Reno恢復期間會出現吞吐量低、恢復時間長、不必要重發數據、恢復結束后閾值過低等一些問
題,嚴重的影響性能。
結論
經過上述分析我們可以看出:
It is a fundamental consequence of the absence of SACK that the sender has to choose between
the following strategies to recover from lost data:
(1)retransmitting at most one dropped packet per round-trip time
(2)retransmitting packets that might have already been successfully delivered.
Reno and New-Reno use the first strategy, and Tahoe uses the second.
With SACK, a sender can avoid unnecessary delays and retransmissions, resulting in improved
throughput.
SACK的不足
上面說了很多SACK的好話,現在來談談它的不足之處。
For a large BDP network where the number of packets are in flight, the procesing overhead of
SACK information at the end points can be quite overhelming because each SACK block invokes
a research into the large packet buffers of the sender for acked packets in the block, and every
recovery of a loss packet causes the same search at the receiver.
在BDP網絡,這個問題尤其明顯,會嚴重的消耗CPU而導致一系列問題。在一定程度上來說,此時
的SACK就像DOS攻擊一樣,每次遍歷都要消耗大量CPU,時間復雜度為O(n^2),n為packets in
flight的數量。
The system overload can cause serious problem : it can cause multiple timeouts (as even packet
retransmission and receptions are delayed) and a long period of zero throughput.
當然,這是中等規模的BDP(100~1000)或大規模的BDP網絡才需考慮的問題,對於一般的BDP而
言不會出現太大的問題。
轉載自 http://blog.csdn.net/zhangskd/article/details/7174682
https://blog.csdn.net/skc361/article/details/25893059