前言
在RFC2581中已經定義了TCP的快速重傳(fast retransmit)和快速恢復(fast recovery)算法,也稱基本Reno算法,但是該算法的啟用僅僅導致一個數據包的重傳。因此,當多個數據包從一個數據視窗中丟失並且觸發快速重傳和快速恢復算法時,問題就會產生。在這種情況下,如果SACK選項可用,TCP傳送端在快速恢復期間就有足夠的信息來決定重傳哪個數據包,不重傳哪個數據包。而本文的算法是對不支持使用TCP選擇確認(SACK)選項的TCP連線適用。
該算法先在RFC2582中定義,後來在RFC3782中重新定義。
算法描述
在一個視窗內的多個包丟失的情況下,傳送方會收到接收方對重傳的數據確認(此時已經進入快速重傳算法),如果是一個包丟失,接收方確認的是重傳算法啟動前的所有包,而如果是多個包丟失,則不會確認重傳前的所有包,此情況稱為部分確認。
Newreno算法和RFC2581中的算法的差異在於在步驟1中引入“恢復(recover)”變數;步驟5中對於部分確認或新的確認;以及在步驟1和步驟6的附加部分中避免多次快速重傳處理。
recover變數的初始化值為初始的傳送序列號。
NewReno算法處理步驟:
1) 三個重複的ACK確認
第3個重複的ACK確認到達而且傳送方未進入快速恢復處理時,檢查累計的確認值是否大於recover變數, 是則轉步驟1A,否則轉1B:
1A) 調用快速重傳:
設定慢啟動閾值(slow start threshold, ssthresh)為:
ssthresh = max (FlightSize / 2, 2*smss)
其中FlightSize表示已經傳送但還沒有被確認的數據量
然後將傳送在最大序列號值保存在recover變數中,轉步驟2;
1B) 不調用快速重傳:
不進入快速重傳和快速恢復處理,不改變ssthresh,不用執行步驟2,3
2) 進入快速重傳
重傳丟失的包然後設定擁塞視窗CWnd=ssthresh + 3*SMSS,擴大擁塞視窗;
3) 快速恢復
在快速恢復階段,對於所接收到的每個重複的ACK包,擁塞視窗遞增SMSS,擴大擁塞視窗;
4) 快速恢復繼續
傳送一個數據段,如果新的cwnd和接收端的通知視窗的值允許的話
5) 當一個確認新數據的ACK到達時,此ACK可能是由步驟2中的重傳引發的確認,或者是由稍後的一次重傳引起的,分完整確認和部分確認兩種情況:
完整確認:
此ACK確認了所有數據的序列號括了recover記錄的序列號,則此ACK確認了所有中間丟失的數據包,此時調整cwnd或者為(1) min(ssthresh, FlightSize + SMSS);或者(2) ssthresh 來縮小cwnd,結束快速恢復。
部分確認:
如果這個ACK不確認所有並包含到“recover”的數據的話,就產生一個部分ACK。在此種情況下,重傳第一個沒有確認的數據段。按確認的新數據量來減小擁塞視窗,如果這個部分確認確認了至少一個MSS的新數據,則加回一個MSS。如果cwnd的新值允許的話,傳送一個新數據段。這個“部分視窗縮減”試圖確定當快速恢復最終結束時,大約ssthresh數量的數據還在向網路中傳送。此情況下不退出快速恢復過程。對在快速恢復期間第一個到達的部分ACK,也要重設重傳定時器。
6) 重傳逾時
重傳逾時後,將傳送的最大序列號保存在recover變數中,結束快速恢復過程。
結論
NewReno算法的前提是用於不支持SACK的TCP實現,效果比基本Reno算法會好一些,但現在不支持SACK的TCP實現已經很少了,因此顯得意義也不是很大了。
參考
中國源碼:www.yuanma.org