TCP/IP學習筆記:TCP擁塞控制


簡介

擁塞指的是

在某段時間,若對網絡中某一資源的需求超過了該資源所能提供的可用部分,網絡性能就要變壞。這種情況就叫擁塞(congestion)。

TCP模塊任務:提供網絡利用率,降低丟包率,保證網絡資源對每條數據的公平性。---- 擁塞控制

標准文檔:RFC 5681,介紹了擁塞控制4個部分:慢啟動(slow start)、擁塞避免(congestion avoidance)、快速重傳(fast retransmit)和快恢復(fast recovery)。

擁塞控制for linux算法實現,有多種:reno算法、vegas算法、cubic算法等。部分或全部實現。
查看方式(for Ubuntu 14):

$ cat /proc/sys/net/ipv4/tcp_congestion_control
cubic

我的PC是采用cubic算法。


術語介紹

擁塞控制最終受控變量:發送窗口(SWND,Send Window)。也就是說,擁塞控制算法最終是通過控制SWND大小,來進行擁塞控制的。

發送窗口

在發送端發送緩存,存在4種類型數據,其中,發送窗口SWND是指(2)和(3)

(1)已經發送並且對端確認(Sent/ACKed)---------------發送窗外 緩沖區外
(2)已經發送但未收到確認數據(Sent/UnACKed)----------發送窗內 緩沖區內
(3)允許發送但尚未發送的數據(Unsent/Inside)---------發送窗內 緩沖區內
(4)未發送暫不允許(Unsent/Outside)-----------------發送窗外 緩沖區內

發送緩存4種類別數據的示意圖

接收窗口

接收窗口 指的是TCP報文頭窗口字段,用於告訴發送端自己當前接收緩存大小。

發送者最大段大小 SMSS

MSS(Maximum Segment Size) TCP最大報文段長度(RFC 879),指的是每一個TCP報文段中的數據字段的最大長度。

TCP報文段 = 數據字段 + TCP首部(20~40Byte)
MSS = MTU - sizeof(TCPHDR) + sizeof(IPHDR)

MTU:最大傳輸單元(含TCP頭部、IP頭部);TCPHDR:TCP報文頭;IPHDR:IP報文頭。

MSS與MTU含義見下圖:

發送者最大段大小,稱為SMSS(Sender Maximum Segment Size)。

如何通告MSS?
MSS的默認值是536byte,因此對端應能接受報文段長度是536 + 20(TCP固定首部) = 556byte的TCP報文。如果想要改變MSS,就需要在TCP連接時,通過TCP報文頭可變長的選項(option)字段(1byte類型+1byte長度+不定長內容),告知對端。
注意:MSS是設置好值后,再通告對方,而非與對方協商。

SWND大小的影響

如果SWND太小,會引起明顯的網絡延遲;反之,如果SWND太大,則容易導致網絡擁塞。

既然接收窗口RWND可以控制發送窗口,為何還需要擁塞控制,而不直接用接收窗口進行控制?
雖然接收方可以通過接收通告窗口(RWND),來控制發送端SWND。但是接收方並不知道網絡擁塞情況,無法針對網絡情況進行控制。因此,發送端引入了一個稱為擁塞窗口的(Congestion Windo, CWND)的狀態變量。實際的SWND值是RWND和CWND中較小者。


慢啟動和擁塞避免

慢啟動

TCP連接建立OK后,CWND初值IW(Initial Window),大小2~4SMSS -- 發送端最多能發送IW bytes數據。
此后,發送端每收到接收端的一個確認,其CWND就按下式增加:

CWND += min(N, SMSS), 其中,N是此次確認中包含的之前未被確認的字節數   (1) 

這樣,CWND將按指數形式擴大,這就是慢啟動。
慢啟動算法理由:TCP模塊剛開始發送數據時,並不知道網絡的實際情況,需要一種試探的方式平滑地增加CWND的大小。

慢啟動門限

如果不施加其他手段,慢啟動必然使得CWND很快膨脹(慢啟動並不慢),並最終導致網絡擁塞。而慢啟動門限(slow start threadhold size, ssthresh),就是這樣一個限制:

當cwnd < ssthresh時,使用慢開始算法;
當cwnd > ssthresh時,停止慢開始算法,改用擁塞避免算法;
當cwnd = ssthresh時,既可以用慢開始算法,也可以用擁塞避免算法;

ssthresh初始值16。只要判斷出現擁塞時,慢開始門限設為出現擁塞時發送窗口swnd的一半(但不能<2),然后把擁塞窗口cwnd重新設為1,執行慢開始算法。
目的:迅速減少主機發送到網絡中的分組數,使得發生擁塞時路由器有足夠時間把隊列中積壓的分組處理完畢。

擁塞避免算法

CWND按線性方式增加,從而減緩其擴大。RFC 5681提到2種實現方式:
1)每個RTT時間內,按(1)式計算新的CWND,而不論該RTT時間內發送端收到多少個確認。
2)每收到一對新數據的確認報文段,就按式(2)來更新CWND。

CWND += SMSS * SMSS / CWND                                        (2)

下圖粗略地描述了慢啟動和擁塞避免發生的時機和區別。此外,我們假設當前ssthresh = 16SMSS大小(實際遠不止這么大)

慢啟動和擁塞避免,都是發送端在未檢測到擁塞時,所采用的積極擁塞避免的方法。下面介紹擁塞發生時(可能發生在慢啟動階段或擁塞避免階段)擁塞控制的行為。

發送端如何判斷擁塞發生?

  • 傳輸超時,或者說TCP重傳定時器溢出; ---- 擁塞避免
  • 接收到連續3個重復的確認報文; ---- 快速重傳,快速恢復

擁塞控制對這兩種情況有不同的處理方式。第一種情況,仍然使用慢啟動和擁塞避免;第二種情況,則使用快速重傳和快速回復(如果真的發生擁塞)。

如果發送端檢測到擁塞發生是由於傳輸超時,即上述第一種情況,那么它將執行重傳並做如下調整:

ssthresh = max(FlightSize / 2, 2 * SMSS)             (3)
CWMD <= SMSS

其中,FlightSize是已經發送但未收到確認的字節數。這樣調整后,CWMD將小於SMSS,那么必然小於新的慢啟動門限值ssthresh(根據式(3),ssthresh一定不小於SMSS的2倍),故而擁塞控制再次進入慢啟動階段。

何為TCP超時重傳?
TCP服務必須能夠重傳超時時間內未收到確認TCP報文段。為此,TCP模塊為每個TCP報文段都維護一個重傳定時器,該定時器在TCP報文段第一次被發送時啟動。如果超時時間內未收到對方的應答,TCP模塊將重傳TCP報文段並重置定時器。

所謂超時,是指定時器 > 最大往返時間RTT。
RTT是指一個數據報發送到目的地,然后到發送方收到確認所需的時間,這是測量RTT。發送報文和確認報文並非數量上的一一對應,可能發送多次,確認一次,也可能是一一對應。


快速重傳和快速恢復

如何通過接收到重復的確認報文段,判斷網絡是否真的發生擁塞?
發送端接收到重復的確認報文段可能情形:TCP報文段丟失,接收端收到亂序TCP報文段並重排等。

擁塞控制算法需要判斷當收到重復的確認報文段時,網絡是否真的發生了擁塞,或者說TCP報文段是否真的丟失了。具體做法:
發送端如果連續收到3個重復的確認報文段,就認為擁塞發生了。然后它啟用快速重傳和快速恢復算法來處理擁塞,過程如下:

1)當收到第3個重復的確認報文段時,按(3)式計算ssthresh,然后立即重傳丟失的報文,而不是等到重傳計時器超時,這稱為快速重傳。並按式(4)設置CWND

CWND = ssthresh + 3 * SMSS                             (4)

2)每次收到1個重復的確認時,設置CWND = CWND + SMSS,而非從慢開始算法的cwnd=1開始。此時,發送端可以發生新的TCP報文段(如果新的CWND允許的話)

3)當收到新數據的確認時,設置CWND = ssthresh(ssthresh是新的慢啟動門限值,由第一步計算得到)

步驟1)稱為快速重傳,步驟2)3)稱為快速恢復。快速重傳和快速恢復完成之后,擁塞控制將恢復到擁塞避免階段。這點由第3)步操作可得知。


總結

擁塞控制對象:發送窗口SWND. SWND <= min(RWND, CWND)
網絡出現超時 => 采用慢開始算法 + 擁塞避免算法;
網絡出現重傳 => 快速恢復算法;


參考

[1]謝希仁. 計算機網絡.第5版[M]. 電子工業出版社, 2008.
[2]游雙. Linux高性能服務器編程[M]. 機械工業出版社, 2013.
[3]Postel J . Transmission control protocol; rfc793[J]. Rfc, 1981.(RFC793)
[4]Тезисы, Статусдокумента, Авторскиеправа, et al. RFC 5681 TCP Congestion Control. 1996.(RFC5681)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM