擁塞控制是TCP通信的每一方需要執行的一系列行為,這些行為有特定算法規定,用於防止網絡因為大規模的通信負載而癱瘓。其基本方法是當有理由認為網絡即將進入擁塞狀態(或已由於擁塞而出現路由丟包情況)時減緩TCP傳輸。TCP擁塞控制的關鍵點自傲與怎樣准確的判斷何時需要減緩且如何減緩TCP傳輸,以及何時恢復其原有速度。
注意: M(_x) 表示M的下標是x ,m(^k) 表示m的K次方。
減緩TCP發送
第15章提到,根據接收方剩余緩存空間大小,在TCP頭部設置通告窗口大小字段,該數值是TCP發送方調節發送速率的依據,當接收速率和網絡傳輸速率過慢時,便需要降低發送速率。為實現上述操作,基於對網絡傳輸能力的估計,可以在發送端引入一個窗口控制變量,確保發送窗口大小不超過接收端接收能力和網絡傳輸能力,即TCP發送端的發送速率為兩者取較小值。
反映網絡傳輸能力的變量稱為擁塞窗口,記作cwnd。因此發送端實際可用窗口W就是接收端窗口awnd和擁塞窗口cwnd的較小值:
W = min(cwnd,awnd)
然而實際情況更顯復雜,因為網絡和接收端情況會隨時間變化,awnd和cwnd值也就會隨之變化。另外,由於缺少顯示擁塞的明確信號,TCP發送端無法直接獲取cwnd的准確值。因此,W、cwnd、awnd的值都需要根據經驗設定並需動態調節。W的值不能過大或過小,我們希望其接近帶寬延遲積(BDP),也稱為最佳窗口大小。W反映網絡中可存儲的待發數據量大小,其計算值等於RTT與鏈路中最小通行速率的乘積。
TCP擁塞控制的一些算法
當一個新的TCP連接之初,還無法獲知可用的傳輸資源,所以cwnd的初始值也無法確定(除第14章提到的目的度量達到緩存信息的情況外)。而awnd則可以通過與接收端完成一個數據包交換即可確定。所以,想要獲取cwnd最佳值的唯一方法是以越來越快的速率不斷發送數據,知道出現數據丟包(或網絡擁塞)為止。由於考慮到不影響網絡傳輸的性能,通常采用特定算法來避免過快的傳輸啟動,傳輸會以慢速啟動發送,直至穩定傳輸后才會運行相應的其他算法。
TCP擁塞控制操作是基於數據包守恆原理運行的:
由於傳輸能力有限,數據包(Pb)會適時地"伸展"。接收方以一定間隔(Pt)接收到數據包后,會陸續(以Ar為間隔)生成相應的ACK,以一定的發送間隔(Ab)返回給發送方。當ACK陸續(以As為間隔)到達發送端時,其達到提供了一個信號或者說"ACK時鍾",表明發送端可以繼續發送數據。在穩定傳輸狀態下,整個系統可"自同步"控制。
慢啟動
在傳輸初始階段,由於未知網絡傳輸能力,需要緩慢探測可用傳輸資源,防止短時間內大量數據注入導致擁塞。慢啟動算法正是針對這一問題而設計,在數據傳輸之初或者重傳計時器檢測到丟包后,需要執行慢啟動 [RFC5682]。
TCP以發送一定數目的數據段開始慢啟動(在SYN交換之后),稱為初始窗口(IW)。IW的值初始設為一個SMSS,但在[RFC5682]中設為一個稍大的值,計算公式如下:
IW = 2*(SMSS)且小於等於2個數據段(當SMSS > 2190字節) IW = 3*(SMSS)且小於等於3個數據段(當 2190 ≥ SMSS > 1095字節) IW = 4*(SMSS)且小於等於4個數據段(其他)
假設沒有出現丟包情況且每個數據包都有相應的ACK,第一個數據段的ACK到達說明可發送一個新的數據段。每接收到一個"正確的ACK"(即沒出現丟包情況正確返回的數據接收響應ACK),慢啟動算法會以min(N,SMSS)來增加cwnd值,N指的是在未經確認的傳輸數據中能通過"正確的ACK"確認的字節數。
為簡單計算,以TCP連接初始的cwnd = 1 SMSS為例,接收到一個數據段的ACK后,cwnd值增加到2,接着發送兩個數據段,如果成功接收並返回相應的ACK,cwnd由2變4,4變8,以此類推。在k輪后,W值為 W = 2的k次方,即 k = log2W,需要k個RTT時間操作窗口才能達到W大小。
有一種情況,假設某個TCP連接中接收方的通知窗口非常大,這時cwnd就是影響發送速率的主要因素。如前所述,cwnd會隨着RTT呈指數增長,最終cwnd會增至很大,大量數據包的發送回導致網絡癱瘓。當發生這種情況時,cwnd將大幅度減小(減至原來的一半)。這是TCP由慢啟動階段至擁塞避免階段的轉折點,與cwnd和慢啟動閾值(ssthresh)相關。
經典慢啟動操作如圖:
沒有ACK延時情況下,每接收到一個正確的ACK就意味着發送方可以發送兩個新的數據包(左)。這會使得發送方窗口隨時間呈指數增長(右,上方曲線)。當發生ACK延時,如每隔一個數據包生成一個ACK,cwnd仍以指數增長,但增幅較小(右,下方曲線)。
擁塞避免
慢啟動一旦達到閾值,便是意味着連接可以進入"下個階段"了。"下個階段"指的是為了得到更多的傳輸資源而不致影響其他連接傳輸的數據傳輸,這個階段TCP實現擁塞避免算法。
擁塞避免階段,cwnd每次的增長值近似於成功傳輸的數據段大小,這種隨時間線性增長方式與慢啟動的指數增長相比緩慢得多。每接收一個新的ACK,cwnd會做一下的更新:
cwnd(_k+1) = cwnd(_t) + SMSS * SMSS/cwnd(_t)
分析上式,假設cwnd(_0) = k * SMSS 字節分為k段發送,在接收到第一個ACK后,cwnd的值增長了1/k倍:
cwnd(_1) = cwnd(_0) + SMSS * SMSS/cwnd(_0) = k * SMSS + SMSS * (SMSS/(k * SMSS)) = k * SMSS + (1/k) * SMSS = (k + (1/k)) * SMSS = cwnd(_0) + (1/k) * SMSS
隨着每個新的ACK到達,cwnd會有相應的小幅增長(取決於上式中的k值),整體增長率呈現輕微的次線性。
若沒有ACK延時發生,每接收一個正確的ACK,就意味着發送方可繼續發送1/W個新的數據包。發送窗口隨時間近似呈線性增長(右,上方曲線)。當有ACK延時,如每隔一個數據包生成一個ACK,cwnd仍近似呈線性增長,只是增幅較小(右,下方曲線)。
慢啟動和擁塞避免的選擇及應用
在通常操作中,某個TCP連接總是選擇運行慢啟動和擁塞避免中的一個,不會出現兩者同時進行的情況,而決定使用慢啟動還是擁塞避免的則是正確提到的慢啟動閾值:
當 cwnd < ssthresh 時,使用慢啟動; 當 cwnd > ssthresh 時,執行擁塞避免; 當 cwnd = ssthresh 時,兩者皆可。
有趣的是,慢啟動閾值居然是動態得到的值。慢啟動閾值的初始值可任意設定,這會使得TCP總是以慢啟動狀態開始傳輸。當有重傳情況發生,ssthresh會按下式改變:
ssthresh = max(在外數據值/2, 2 * SMSS) (ssthresh-公式)
注意,在微軟最近("下一代")TCP/IP協議中,上述等式變為 ssthresh = max(min(cwnd,awnd)/2, 2 * SMSS)[NB08]。
慢啟動和擁塞避免組成了TCP擁塞控制算法的部分:
Tahoe(4.2版本的BSD,伯克利軟件版本)包含了一個TCP版本,它在連接之初處於慢啟動階段,若檢測到丟包,不論由於超時還是快速重傳,都會重新進入慢啟動狀態。有丟包情況發生時,Tahoe簡單的將cwnd減為初始值以達到慢啟動目的,直至cwnd增長為ssthresh。這種方法對於較大BDP的鏈路會使得帶寬利用率低下,因為TCP發送方經重新慢啟動,回歸到的還是未丟包狀態。
Reno(4.3版本的BSD)中的快速恢復機制就是為解決Tohoe的帶寬利用率低下問題而提出的。針對不同的丟包情況,重新考慮是否需要重回慢啟動狀態。若是由重復ACK引起的丟包(會引發快速重傳),cwnd值將被設為上一個ssthresh(即減半),而非初始值。該算法得到了廣泛應用並成為"標准TCP"的基礎。
標准TCP及對其算法的改進
"標准"TCP的構成依然存在爭議,但上述算法都屬於標准TCP。[RFC5681]描述了TCP規范並不要求嚴格使用上述精確算法,TCP實現過程僅利用其核心思想。總結[RFC5681]中的結合算法,在TCP連接建立之初,首先是慢啟動階段(cwnd = IW),ssthresh通常取一較大值(至少為awnd)。當接收到一個正確的ACK時,cwnd會相應更新:
cwnd += SMSS (若 cwnd < ssthresh) 慢啟動 cwnd += SMSS * SMSS/cwnd (若 cwnd > ssthresh) 擁塞避免
當收到三次重復ACK時,會執行以下行為:
1. ssthresh 更新為大於等式(ssthresh-公式)中的值。
2. 啟用快速重傳算法,將cwnd設為(ssthresh + 3 * SMSS)。
3. 每接收一個重復ACK,cwnd值暫時增加 1 SMSS。
4. 當接收到一個正確的ACK,將cwnd重設為ssthresh。
步驟2和3構成了快速恢復。步驟2設置cwnd大小,首先cwnd通常會被減為之前值的一半,考慮到每接收一個重復ACK,就意味着相應的數據包已成功傳輸,cwnd值會相應的暫時增大。步驟3維持cwnd的增大過程,使得發送方可以繼續發送新的數據包(在不超過awnd的情況下)。步驟4假設TCP已完成恢復階段,所以對cwnd的臨時膨脹進行消除。
標准TCP算法在傳輸控制領域做出了重大貢獻,尤其針對網絡擁塞崩潰這一難題取得了顯著效果。然而,仍然可以找到值得改進的地方。考慮到TCP的普遍使用性,越來越多的研究致力於使TCP在更廣泛的環境里更好地工作,下面就是一些改進。
NewReno是Reno算法的改進:Reno中的快速恢復機制存在問題,當一個傳輸窗口出現多個數據包丟失時,一旦其中一個包重傳成功,發送方就會收到一個正確的ACK,這樣快速恢復階段中cwnd窗口的暫時膨脹就會停止,而事實上丟失的其他數據包可能並未完成重傳。NewReno對快速恢復做了改進,它記錄了上一個數據傳輸窗口的最高序列號,僅當接收到序列號不小於恢復點的ACK,才停止快速恢復階段。
采用選擇確認機制的TCP擁塞控制:在TCP引入SACK與選擇性重復之后,發送方能夠更好地確定發送哪個數據段來填補接收方的空缺。為了填補接收數據的空缺,發送方通常只發送丟失的數據段,直至完成所有重傳。SACK TCP強調擁塞管理和選擇重傳機制的分離(為避免可能出現的由於觸發重傳而導致短時間內大量數據被注入網絡),傳統TCP則將兩者結合。一種實現分離方法是除了維護窗口,TCP還負責記錄注入網絡的數據量。[RFC3517]稱其為管道(pipe)變量,以字節為單位,是對外在數據的估計值,記錄傳輸和重傳情況。假設awnd值比較大,只要不等式 cwnd - pipe ≥ SMSS成立,在任何時候SACK TCP均可發送數據。這里cwnd仍被用來限定可傳輸至網絡中的數據量,但除了窗口本身,網絡中數據量的估計值也被記錄了。
轉發確認(FACK)和速率減半:對基於Reno(包括NewReno)的TCP版本中,當快速重傳結束后cwnd值減小,發送端在前一半的RTT時間內處於等待狀態,在后一半RTT才能發送新數據。為避免前半RTT時間的等待空閑,[MM96]提出了轉發確認策略(FACK)。
轉發確認策略(FACK)包含兩部分算法:過度衰減和緩慢衰減。最終在Hoe的工作基礎上[H96]形成統一的算法,稱為速率減半。為控制算法近可能有效的運行,進一步添加了界定參數,完整的算法稱為帶界定參數的速率減半(RHBP)算法[PSCRH]。RHBP的基本操作是在一個RTT時間內,每接收2個重復ACK,TCP發送方可發送一個新數據包。為了記錄較為精確的在外數據估計值,RHBP利用SACK信息決定FACK策略:已知的最大序列號的數據到達接收方時,在外數據值加1,FACK給出的在外數據估計值不包括重傳。RHBP中區分了調整間隔(cwnd的修正階段)和恢復間隔(數據重傳階段),一旦出現丟包或其他擁塞信號就立即進入調整間隔。調整間隔結束后cwnd的最終值為:至檢測時間為止,網絡中已正確傳輸的窗口數據量的一半。
RHBP要求發送方傳輸數據需要滿足下式:
(SND.NXT - fack + retran_data + len) < cwnd
上面的等式得到了包括重傳的在外數據值,確保當繼續發送一個len長度的新數據,也不會超過cwnd。假設在FACK之前的數據已經不在網絡中(如丟失或被接收),這樣cwnd就能很好地控制SACK發送方的發送。然而由於SACK的選擇確認特性,可能導致數據包的傳輸次序過度重排。
書中也提到 "在接收窗口限制TCP連接的情況下,速率減半方法收效甚微[MM05]" 。
限制傳輸:[RFC3042]描述了其對TCP做出了微小改進,采用限制傳輸策略,TCP發送方每接收兩個連續的重復ACK,就能發送一個新數據包。這就使得網絡中的數據包維持一定數量,足以觸發快速重傳,TCP因此也可以避免長時間等待RTO而導致吞吐量性能下降。
擁塞窗口校驗:在發送操作持續一段時間后,cwnd值可能會增至一個較大值,若此時發送端需要暫停發送且暫定的時間足夠長,則之前的cwnd可能無法准確反映路徑中的擁塞狀況。[RFC2861]提出了一種擁塞窗口校驗機制(CWV)。
CWV算法如下:當需要發送新數據時,首先看距離上次發送操作是否超過一個RTO。如果超過,則更新ssthresh值,設為max(ssthresh,(3/4) * cwnd),每經一個空閑RTT時間,cwnd值就減半,但不小於 1 SMSS。
對於應用受限階段(非空閑階段),執行相似的操作:已使用的窗口大小記為W_used,更新ssthresh值,設為max(ssthresh,(3/4) * cwnd),cwnd設為cwnd和W_used的平均值。
偽RTO處理-Eifel算法
第15章中已經提到,若TCP出現突發的延時,即使沒有出現丟包,也可能造成重傳超時的假象。當出現重傳超時,TCP會調整ssthresh並將cwnd置為IW,從而進入慢啟動狀態。假如沒有出現實際丟包,在RTO之后到達的ACK會使得cwnd快速增大,但在cwnd和ssthresh值重新穩定前,仍然會有不必要的重傳,浪費傳輸資源。
針對上述問題,在14章提出了一些方法:DSACK、Eifel、F-RTO。其中任一探測方法只要結合相關響應算法,就能"還原"TCP對擁塞控制變量的操作。這里主要介紹Eifel響應算法。
Eifel響應算法用於處理重傳計時器以及重傳計時器超時后的擁塞控制操作。在首次發生超時重傳時,Eifel算法開始執行。若認為出現偽重傳情況,會撤銷對ssthresh值的修改。若因超時重傳而需改變ssthresh值,在修改前需要記錄一個特殊變量:pipe_prev。
pipe_prev = min(在外數據值,ssthresh)
然后需要運行一個檢測算法(即之前提到的檢測方法中的某個)來判斷RTO是否真實,如果出現偽重傳,則當到達一個ACK時,執行以下步驟:
1. 若接收的是包含ECN-Echo標志位的正確的ACK,停止操作;
2. cwnd = 在外數據值 + min(bytes_acked, IW);
3. ssthresh = pipe_prev。
過程整理:
在改變ssthresh值之前需要先保存pipe_prev變量,用於保存ssthresh的記錄值,以便在步驟3重設ssthresh。
步驟1針對待ECN標志位的ACK的情況,這種情況下撤銷ssthresh修改會引入不安全因素,所以算法終止。
步驟2將cwnd設置為一定值,允許不超過IW的新數據進入傳輸通道,因為即使在未知鏈路擁塞與否的狀況下,發送IW的新數據也被認為是安全的。
步驟3在真正的RTO發生前重置ssthresh,至此撤銷操作完成。
TCP友好性
TCP作為最主要的網絡傳輸協議,在傳輸路徑中經常會出現幾個TCP鏈接共享一個或多個路由的情況,然而它們並非均勻的共享帶寬資源,而是根據其他連接動態地調節分配。為避免多個TCP連接對傳輸資源的惡性競爭,提出了一種基於計算公式的速率控制方法,限制特定環境下TCP連接對帶寬資源的使用,該方法被稱為TCP友好速率控制(TFRC),它基於連接參數和環境變量實現速率限制。
TFRC使用如下公式來決定發送率:
(TEFC-公式1)
這里的X指吞吐率限制(字節/秒),s為包大小(字節,包含頭部),R是RTT(秒),p為丟包率[0,0.1],t(_RTO)為重傳超時(秒),b指一個ACK能確認的最大包個數。建議t(_RTO)設為4R,b設為1。
在擁塞避免階段,如何根據接收的無重復ACK來調整窗口大小?使用擁塞避免算法時,每接收一個正確的ACK,cwnd就會增加1/cwnd,而每當出現一次丟包,cwnd就會減半,這被稱為和氏增加/積式減少(AIMD)擁塞控制。通過將1/cwnd和1/2替換為a和b,得到AIMD等式:
cwnd(_t+1) = cwnd(_t) + a/cwnd(_t) cwnd(_t+1) = cwnd(_t) - b/cwnd(_t)
根據[FHPW00]給出的結果,上述等式得出的發送率為(以包個數/RTT為單位):
(TEFC-公式2)
對於傳統TCP,a = 1,b = 0.5,簡化得出T = 1.2/√(根號)p。
高速環境下的TCP
考慮一下,如果BDP較大的高速網絡中,使用窗口增加的算法(特別是擁塞避免算法)需要很長一段時間才能使窗口增至傳輸鏈路飽和,也就是說,即使沒有發生擁塞,TCP也不能很好的利用高速網絡。為了彌補這個不足,高速TCP(HSTCP)技術[RFC3742]指出,當擁塞窗口大於一個基礎值Low_Window時(Low_Window設置為38個MSS),應當調整標准TCP的處理方式。
[RFC3742]描述了如何修改慢啟動階段,使其在高速環境下得到運行中的擁塞窗口值。它被稱為受限的慢啟動,即減慢速度的慢啟動。其中引入一個新的參數稱為max_ssthresh,這個值表示ssthresh的最大值,而是cwnd的一個閾值:
如果cwnd <= max_ssthresh,則慢啟動階段與傳統TCP相同,
如果max_ssthresh < cwnd <= ssthresh,那么cwnd在每個RTT中最大只能增長(max_ssthresh/2)個SMSS。
具體如下:
if( cwnd <= max_ssthresh ){ cwnd = cwnd + SMSS }else{ K = int(cwnd / (0.5 * max_ssthresh)) cwnd = cwnd + int((1/K) * SMSS) }
建議max_ssthresh的初始值為100個包,或者100 * SMSS個字節。
對與HSTCP而言,在多個具有不同RTT的連接競爭帶寬時,不會直接控制這些競爭行為(稱為"RTT公平性")。但為建立可擴展的TCP及解決RTT公平性問題,也提出了一些算法。
BIC-TCP算法:該算法使用了兩種算法來修改標准TCP發送端,二分搜索增大和加法增大。
二分搜索增大算法操作過程如下:當前最小窗口是最近一次在一個完整RTT中沒有出現丟包的窗口大小,最大窗口是最近一次出現丟包時的窗口大小。預期窗口位於這兩個值之間,BIC-TCP則使用二分搜索選擇中點作為試驗窗口,依次遞歸。如果這個點依然會發生丟包,那么將它設置為最大窗口,然后繼續重復二分搜索試驗。反之依然。直到最大窗口和最小窗口的差小於一個預先設置好的閾值時才停止,這個閾值稱為最小增量。
加法增大算法操作過程則如下:當使用二分搜索增大算法時,可能會出現當前窗口大小與中間點之間差距很大。由於可能出現突然大量數據注入網絡的情況,所以在一個RTT內將窗口增大到中間點可能並不是一個好方法。這種情況下,就需要采用加法增大算法。此時增量被限制為每個RTT增加S(_max),這一增量被稱為窗口夾。一旦中間點距離試驗窗口比距離S(max)值更近時,則轉換為使用二分搜索增大算法。
總的來說,當檢測到丟包現象,窗口會使用乘法系數β來減小,而窗口增大時,首先使用加法增大算法,之后一旦確認加法增量小於S(_max)時就轉為使用二分搜索增大算法。這種組合算法稱為二進制增長,或者BI。
CUBIC算法,BIC-TCP的改進版本:使用一個高階多項式函數(具體來說是一個三次方程)來控制窗口的增大。三次方程的曲線既有凸的部分也有凹的部分,這就意味着在一些部分(凹的部分)增長比較緩慢,而在另一些部分(凸的部分)增長比較迅速。在BIC算法和CUBIC算法之前,所有TCP研究提出的都是凸的窗口增長函數。
CUBIC算法中,這個特殊的窗口增長函數如下所示:
W(t) = C(t - K)³ + W(_max)
W(t)代表在時刻t的窗口大小,C是一個常量(默認為4),t是距離最近一次窗口減小所經過的時間(以秒為單位),K是在沒有丟包情況下窗口從W增長到W(_max)所用的時間,W(_max)是最后一次調整前的窗口大小。其中K可依據以下表達式計算:
(K-公式)
其中β是積式減少的常量(默認為0.2)。CUBIC算法中的β默認為0.8。下圖是CUBIC窗口增長函數的三次方程式:
除了三次方程之外,CUBIC還有"TCP友好性"策略。當窗口太小使得CUBIC不能獲得比傳統TCP更好的性能時,它將開始工作。根據t可以得到標准TCP的窗口大小W(_tcp)(t):
當在擁塞避免階段有一個ACK到達時,如果cwnd值小於W(_tcp)(t),那么CUBIC將cwnd值設置為W(_tcp)(t),這種方法確保了CUBIC在一般的中低速網絡中的TCP友好性。
基於延遲的擁塞控制算法
當發送端不斷地向網絡中發送數據包,不斷增長的RTT值也可以作為擁塞形成的信號。新到達的數據包沒有被發送而是進入了等待隊列,這就造成了RTT值不斷增大(直到數據包最終被丟棄)。一些根據這種情況提出的擁塞控制技術成為基於延遲的擁塞控制算法。
Vagas 算法
Vagas算法於1994年被提出[BP95],它是TCP協議發布后的第一個基於延遲的擁塞控制方法,並經過了TCP協議開發組的測試。該算法首先估算了一定時間內網絡能夠傳輸的數據量,然后與實際傳輸能力進行比較。若本該傳輸的數據並沒有被傳傳輸,那么它有可能被鏈路上的某個路由器掛起,如果這種情況持續不斷發生,那么Vages發送端將降低發送速率。
在擁塞避免階段,Vages算法測量每個RTT中所傳輸的數據量,並將這個數除以網絡中觀察到的最小延遲時間。算法維護了兩個閾值α和β,當吞吐量與預期不同時,若得到的吞吐量小於α,則將擁塞窗口增大;若吞吐量大於β,則將擁塞窗口減小。吞吐量在兩閾值之間時,擁塞窗口保持不變。擁塞窗口所有的改變都是線性的,這意味着這種方法是一種和式增加/和式減少的擁塞控制策略。α和β的最小值分為設置為1和3,該設置的原因是:在網絡中至少有一個數據報緩沖區會被占用才能保持網絡資源被充分利用但如果只維護一個緩沖區,那么當有其他可用帶寬時,就需要等待額外的RTT時間,因此為了傳輸更多數據,需要多使用2個緩沖區(達到3,α的值)。此外,保持一個區間(β-α)可用保留一部分空間,使得吞吐量可用有小幅改變而不至於引發串口大小的改變。
需要注意的是,在特定情況下,Vages算法會盲目的相信前向的延遲會高於它實際的值。這種情況發送在它相反的方向產生了擁塞。在這種情況下,雖然不是發送端導致了反向擁塞,但是返回發送端的數據包(ACK)會產生延遲。這就使得在這種不是真正需要調整擁塞窗口的情況下,減小了窗口大小。這是大多數基於測量RTT來進行擁塞控制判斷的方法所共有的潛在缺陷。甚至,在反方向上嚴重的擁塞問題會導致ACK時鍾的嚴重紊亂[M92]。
FAST 算法
FAST TCP 算法是為了處理大帶寬延遲的高速網絡環境下的擁塞問題而提出的[WJLH06]。它依據預期的吞吐量和實際的吞吐量的不同、當前性能與預期值的不同來調整窗口。FAST算法會使用速率起搏(rate-pacing)技術每隔一個RTT都會更新發送率。如果測量延遲遠小於閾值時,窗口會進行較快增長,一段時間后會逐漸平緩增長;當延遲增大時則相反。
TCP Westwood 算法和 Westwood+ 算法
TCP Westwood(TCPW)算法和 Westwood+(TCPW+)算法則通過修改傳統的TCP NewReno發送端來實現對大帶寬延遲積鏈路的處理。TCPW+算法是對TCPW算法發修正,在TCPW算法中,發送端的合格速率估計(ERE)是一種對連接中可用帶寬的估計,且該估計值被不斷計算。這個速率的測量會有一個測量間隔,該間隔基於ACK的到達動態可變。當擁塞現象不明顯時,測量間隔會比較小;反之亦然。當檢測到一個數據包丟失時,TCPW不會將cwnd減半,而是計算一個估計的BDP值(ERE乘以觀察到的最小RTT),並將這個值作為新的ssthresh值。另一方面,在連接處於慢啟動階段時,使用一種靈活的探測機制適應性的反復設置ssthresh值。因此,當ssthresh值增長時,cwnd值會以指數形式增長。
復合TCP
復合TCP(CTCP)不僅依據丟包來進行窗口調整,還依據延遲的大小。可以認為它是一種標准TCP和Vages算法的結合,還包含了TSTCP可擴展的特點。
CTCP定義了一個新的窗口控制變量dwnd(延遲窗口),可以窗口大小W則變為:
W = min(cwnd + dwnd,awnd)
對cwnd值的處理與標准TCP類似,但是如果延遲允許,新加入的dwnd值會允許額外的數據包發送,在擁塞避免階段當ACKA報文到達時,cwnd值根據下面公式進行更新:
cwnd = cwnd + 1(cwnd + dwnd)
當連接建立時,使用一個變量baseRTT來表示測量到的最小RTT值,然后預期數據與實際數據的差值diff將使用如下公式進行計算:diff = W * (1 - (baseRTT/RTT))。其中RTT是估算的平滑RTT估值,diff的值估算了網絡隊列中的數據包數量(或字節數)。CTCP算法試圖將diff值保持在一個閾值內,以此保證網絡的充分利用而不至於出現擁塞,這個閾值定義為γ。對於dwnd的值控制則依據以下公式:
在第一種情況下,網絡沒有被充分利用,CTCP根據多項式 α * win(t)(^k) 增大dwnd值。這是一種多項式級的增長,而當緩沖區的占用率小於γ時,會更快速的增長。
在第二種情況下,緩沖區的占用率已經超過了閾值γ,固定值ζ表示延遲窗口的遞減速率,這就使得CTCP的RTT更具公平性。
在第三種情況下,當檢測到包丟失,則dwnd值會有自己的積式遞減系數β。
α表示平滑度默認為0.125,β表示響應性默認為0.5,k值表示速度等級被設置位0.75,γ值設為為30個數據包(根據經驗)。
相關知識
在多個TCP連接中,新的連接可能會用到相同主機之間的其他連接的信息,包括已關閉的連接或者正在處於活動狀態的其他連接。這就是相同主機間多個連接共享擁塞狀態信息。[RFC2140]描述了相關信息,其中注意區分了暫時共享(新連接與已關閉連接間的信息共享)和總體共享(新連接與其他活動連接間的信息共享)。為將此思想形成除了TCP外的新的應用協議,[RFC3124]提出了擁塞管理機制,該機制使得本地操作系統可實現相關協議來了解鏈路狀態信息,如丟包率、擁塞估計、RTT等。
龐大的內存(網絡設備中包含大量的內存和幾百萬字節的包緩沖區,多指(高端)路由器)會導致像TCP這樣的協議性能下降,這一問題被稱為緩沖區膨脹[G11][DHGSO7]。它主要存在於家用網關的上行端以及家庭或小型辦公室的接入點處,與排隊等待而產生的大量延遲有關。標准TCP協議的擁塞控制算法會在鏈路的瓶頸處將緩沖區填滿,而由於擁塞的信號(一個數據包丟失)需經很長時間才能反饋到發送端,此時在發送端和接收端之間緩存了大量數據,TCP協議也不能很好地運作。
然而針對這個問題也已經有方法解決,路由器提供一種管理列隊的相應方法稱為積極列隊管理機制(AQM)。AQM通過使用算法(如RED)來一定概率的丟棄數據包或者對數據標記ECN字段置位或者實現。
隨機早期檢測(RED)網關[FJ93]機制能夠探測擁塞情況的發生,並且控制數據包標記。這些網關實現了一種衡量平均占用時間的隊列管理方法,如果占用隊列的時間超過最小值(minthresh),並且小於最大值(maxthresh),那么這個數據包將被標記一個不斷增長的概率值。如果平均隊列占用時間超過了maxthresh,數據包將被標記一個可配置的最大概率值(MaxP),MaxP可設置為1.0,RED也可以將數據包丟棄而不是標記它們。
ECN機制主要在IP層進行操作,也可以應用於TCP以外的其他傳輸層協議,其過程如下:
1. 當一個包含ECN功能的路由器經過長時間的擁塞,接收到一個IP數據包就,它會查看IP頭中的ECN傳輸能力(ECT)標識,如果有效,負責發送數據包的傳輸層協議開啟ECN功能,然后路由器會在IP頭部設置一個已發生擁塞(CE)標識,然后繼續向下轉發數據包。若擁塞情況不會持續很長,則不好講CE標識置位,因為即使一個單獨的CE標識,傳輸協議也會做出反應。
2. 當TCP接收端發現接收到的數據包的CE標識被置位,必須將該標識發送回發送端,並且它會將每個ACK數據包的ECN-Echo(ECN回顯)位字段置位,直到接收到一個從發送端來的CWR位字段設置為1的數據包(CWR字段置位說明擁塞窗口已經降低)。
3. 當TCP發送端接收到ECN-Echo標識的數據包時,會與探測到單個數據包丟失時一樣調整cwnd值,同時還會重新設置后續數據包的CWR位字段。常規的擁塞處理方法為:調用快速重傳和快速回復算法,使TCP在丟包之前降低發送速率。
相關攻擊
早期的攻擊是利用ICMPv4 Source Quench(源抑制)報文的結構,當這些報文被發送到允許TCP協議的主機上,任何與該IP地址相連的連接都會減慢發送速率,該IP地址包含在ICMP報文中的違規數據報中。然而隨着1995年路由器不再使用Source Quench報文進行擁塞控制,該攻擊方式成為不可行。解決這種攻擊的簡單方式就是在路由器和主機上阻止ICMP Source Quench報文的傳輸。
一種更復雜、常見的攻擊方式是基於接收端的不當行為。這里描述三種攻擊(ACK分割攻擊、重復ACK欺騙攻擊、樂觀響應攻擊)形式,它們都可以使TCP發送端以一個比正常狀態更快的速率進行數據發送。
ACK分割攻擊:將原有的確認字節范圍拆分成多個ACK信號並返回給發送端,使得發送端的cwnd會比正常情況更快速增長。可通過計算每個ACK能確認的數據量來判斷是否為正確的ACK來解決這一問題。
重復ACK欺騙攻擊:該攻擊可以使發送端在快速恢復階段增長它的擁塞窗口,因為還沒有明確的方法可以將接收到的重復ACK和它們所確認的報文段相對應。使用時間戳選項可以解決這一問題,然而最好的方法是限制發送端在恢復階段的在外數據。
樂觀響應攻擊:對那些還沒有到達的報文段產生ACK,導致發送端計算出的RTT比實際的小,從而比正常情況下更快的做出反應。為防范這類攻擊,可通過定義一個可累加的隨機數使得發送數據段大小可隨時間動態改變,以此來更好地匹配數據段和它的對應ACK。當發現得到的ACK和數據段不匹配時,發送端就可以采取相應的行為。
參考:
《TCP IP 詳解卷1:協議》