自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

TCP窗口縮放、時(shí)間戳和SACK

運(yùn)維 系統(tǒng)運(yùn)維
Linux TCP 協(xié)議棧具有無數(shù)個(gè)可以更改其行為的 sysctl 旋鈕。 這包括可用于接收或發(fā)送操作的內(nèi)存量、套接字的最大數(shù)量、可選的特性和協(xié)議擴(kuò)展。

[[345810]]

Linux TCP 協(xié)議棧具有無數(shù)個(gè)可以更改其行為的 sysctl 旋鈕。 這包括可用于接收或發(fā)送操作的內(nèi)存量、套接字的最大數(shù)量、可選的特性和協(xié)議擴(kuò)展。

有很多文章出于各種“性能調(diào)優(yōu)”或“安全性”原因,建議禁用 TCP 擴(kuò)展,比如時(shí)間戳或選擇性確認(rèn)Selective ACKnowledgments(SACK)。

本文提供了這些擴(kuò)展功能的背景,為什么會(huì)默認(rèn)啟用,它們之間是如何關(guān)聯(lián)的,以及為什么通常情況下將它們關(guān)閉是個(gè)壞主意。

TCP 窗口縮放

TCP 可以承受的數(shù)據(jù)傳輸速率受到幾個(gè)因素的限制。其中包括:

  • 往返時(shí)間Round trip time(RTT)。

    這是數(shù)據(jù)包到達(dá)目的地并返回回復(fù)所花費(fèi)的時(shí)間。越低越好。

  • 所涉及的網(wǎng)絡(luò)路徑的最低鏈路速度。

  • 丟包頻率。

  • 新數(shù)據(jù)可用于傳輸?shù)乃俣取?/p>

    例如,CPU 需要能夠以足夠快的速度將數(shù)據(jù)傳遞到網(wǎng)絡(luò)適配器。如果 CPU 需要首先加密數(shù)據(jù),則適配器可能必須等待新數(shù)據(jù)。同樣地,如果磁盤存儲(chǔ)不能足夠快地讀取數(shù)據(jù),則磁盤存儲(chǔ)可能會(huì)成為瓶頸。

  • TCP 接收窗口的最大可能大小。

    接收窗口決定了 TCP 在必須等待接收方報(bào)告接收到該數(shù)據(jù)之前可以傳輸多少數(shù)據(jù)(以字節(jié)為單位)。這是由接收方宣布的。接收方將在讀取并確認(rèn)接收到傳入數(shù)據(jù)時(shí)不斷更新此值。接收窗口的當(dāng)前值包含在 TCP 報(bào)頭 中,它是 TCP 發(fā)送的每個(gè)數(shù)據(jù)段的一部分。因此,只要發(fā)送方接收到來自對等方的確認(rèn),它就知道當(dāng)前的接收窗口。這意味著往返時(shí)間(RTT)越長,發(fā)送方獲得接收窗口更新所需的時(shí)間就越長。

TCP 的未確認(rèn)(正在傳輸)數(shù)據(jù)被限制為最多 64KB。在大多數(shù)網(wǎng)絡(luò)場景中,這甚至還不足以維持一個(gè)像樣的數(shù)據(jù)速率。讓我們看看一些例子。

理論數(shù)據(jù)速率

在往返時(shí)間(RTT)為 100 毫秒的情況下,TCP 每秒最多可以傳輸 640KB。在延遲為 1 秒的情況下,最大理論數(shù)據(jù)速率降至只有 64KB/s。

這是因?yàn)榻邮沾翱诘脑?。一旦發(fā)送了 64KB 的數(shù)據(jù),接收窗口就已經(jīng)滿了。發(fā)送方必須等待,直到對等方通知它應(yīng)用程序已經(jīng)讀取了至少一部分?jǐn)?shù)據(jù)。

發(fā)送的第一個(gè)段會(huì)把 TCP 窗口縮減去該段的大小。在接收窗口值的更新信息可用之前,需要往返一次。當(dāng)更新以 1 秒的延遲到達(dá)時(shí),即使鏈路有足夠的可用帶寬,也會(huì)導(dǎo)致 64KB 的限制。

為了充分利用一個(gè)具有幾毫秒延遲的快速網(wǎng)絡(luò),必須有一個(gè)比傳統(tǒng) TCP 支持的窗口更大的窗口。“64KB 限制”是協(xié)議規(guī)范的產(chǎn)物:TCP 頭只為接收窗口大小保留了 16 個(gè)位。這允許接收窗口最大為 64KB。在 TCP 協(xié)議最初設(shè)計(jì)時(shí),這個(gè)大小并沒有被視為一個(gè)限制。

不幸的是,想通過僅僅更改 TCP 頭來支持更大的最大窗口值是不可能的。如果這樣做就意味著 TCP 的所有實(shí)現(xiàn)都必須同時(shí)更新,否則它們將無法相互理解。為了解決這個(gè)問題,我們改變了對接收窗口值的解釋。

“窗口縮放選項(xiàng)”允許你改變這個(gè)解釋,同時(shí)保持與現(xiàn)有實(shí)現(xiàn)的兼容性。

TCP 選項(xiàng):向后兼容的協(xié)議擴(kuò)展

TCP 支持可選擴(kuò)展。這允許使用新特性增強(qiáng)協(xié)議,而無需立即更新所有實(shí)現(xiàn)。當(dāng) TCP 發(fā)起方連接到對等方時(shí),它還會(huì)發(fā)送一個(gè)支持的擴(kuò)展列表。所有擴(kuò)展都遵循相同的格式:一個(gè)唯一的選項(xiàng)號(hào),后跟選項(xiàng)的長度以及選項(xiàng)數(shù)據(jù)本身。

TCP 響應(yīng)方檢查連接請求中包含的所有選項(xiàng)號(hào)。如果它遇到一個(gè)不能理解的選項(xiàng)號(hào),則會(huì)跳過 該選項(xiàng)號(hào)附帶的“長度”字節(jié)的數(shù)據(jù),并檢查下一個(gè)選項(xiàng)號(hào)。響應(yīng)方忽略了從答復(fù)中無法理解的內(nèi)容。這使發(fā)送方和接收方都?jí)蚶斫馑С值墓策x項(xiàng)集。

使用窗口縮放時(shí),選項(xiàng)數(shù)據(jù)總是由單個(gè)數(shù)字組成。

窗口縮放選項(xiàng)

  1. Window Scale option (WSopt): Kind: 3, Length: 3
  2.     +---------+---------+---------+
  3.     | Kind=3  |Length=3 |shift.cnt|
  4.     +---------+---------+---------+
  5.          1         1         1

窗口縮放 選項(xiàng)告訴對等方,應(yīng)該使用給定的數(shù)字縮放 TCP 標(biāo)頭中的接收窗口值,以獲取實(shí)際大小。

例如,一個(gè)宣告窗口縮放因子為 7 的 TCP 發(fā)起方試圖指示響應(yīng)方,任何將來攜帶接收窗口值為 512 的數(shù)據(jù)包實(shí)際上都會(huì)宣告 65536 字節(jié)的窗口。增加了 128 倍(2^7)。這將允許最大為 8MB 的 TCP 窗口。

不能理解此選項(xiàng)的 TCP 響應(yīng)方將會(huì)忽略它,為響應(yīng)連接請求而發(fā)送的 TCP 數(shù)據(jù)包(SYN-ACK)不會(huì)包含該窗口縮放選項(xiàng)。在這種情況下,雙方只能使用 64k 的窗口大小。幸運(yùn)的是,默認(rèn)情況下,幾乎每個(gè) TCP 棧都支持并默認(rèn)啟用了此選項(xiàng),包括 Linux。

響應(yīng)方包括了它自己所需的縮放因子。兩個(gè)對等方可以使用不同的因子。宣布縮放因子為 0 也是合法的。這意味著對等方應(yīng)該如實(shí)處理它接收到的接收窗口值,但它允許應(yīng)答方向上的縮放值,然后接收方可以使用更大的接收窗口。

與 SACK 或 TCP 時(shí)間戳不同,窗口縮放選項(xiàng)僅出現(xiàn)在 TCP 連接的前兩個(gè)數(shù)據(jù)包中,之后無法更改。也不可能通過查看不包含初始連接三次握手的連接的數(shù)據(jù)包捕獲來確定縮放因子。

支持的最大縮放因子為 14。這將允許 TCP 窗口的大小高達(dá) 1GB。

窗口縮放的缺點(diǎn)

在非常特殊的情況下,它可能導(dǎo)致數(shù)據(jù)損壞。但在你禁用該選項(xiàng)之前,要知道通常情況下是不可能損壞的。還有一種解決方案可以防止這種情況。不幸的是,有些人在沒有意識(shí)到它與窗口縮放的關(guān)系的情況下禁用了該解決方案。首先,讓我們看一下需要解決的實(shí)際問題。想象以下事件序列:

  1. 發(fā)送方發(fā)送段:s_1、s_2、s_3、... s_n。
  2. 接收方看到:s_1、s_3、... s_n,并發(fā)送對 s_1 的確認(rèn)。
  3. 發(fā)送方認(rèn)為 s_2 丟失,然后再次發(fā)送。它還發(fā)送了段 s_n+1 中包含的新數(shù)據(jù)。
  4. 接收方然后看到:s_2、s_n+1,s_2:數(shù)據(jù)包 s_2 被接收兩次。

當(dāng)發(fā)送方過早觸發(fā)重新傳輸時(shí),可能會(huì)發(fā)生這種情況。在正常情況下,即使使用窗口縮放,這種錯(cuò)誤的重傳也絕不會(huì)成為問題。接收方將只丟棄重復(fù)項(xiàng)。

從舊數(shù)據(jù)到新數(shù)據(jù)

TCP 序列號(hào)最多可以為 4GB。如果它變得大于此值,則該序列會(huì)回繞到 0,然后再次增加。這本身不是問題,但是如果這種問題發(fā)生得足夠快,則上述情況可能會(huì)造成歧義。

如果在正確的時(shí)刻發(fā)生回繞,則序列號(hào) s_2(重新發(fā)送的數(shù)據(jù)包)可能已經(jīng)大于 s_n+1。因此,在最后的步驟(4)中,接收方可以將其解釋為:s_2、s_n+1、s_n+m,即它可以將 “舊” 數(shù)據(jù)包 s_2 視為包含新數(shù)據(jù)。

通常,這不會(huì)發(fā)生,因?yàn)榧词乖诟邘掓溄由希?ldquo;回繞”也只會(huì)每隔幾秒鐘或幾分鐘發(fā)生一次。原始數(shù)據(jù)包和不需要的重傳的數(shù)據(jù)包之間的間隔將小得多。

例如,對于 50MB/s 的傳輸速度,重復(fù)項(xiàng)要遲到一分鐘以上才會(huì)成為問題。序列號(hào)的回繞速度沒有快到讓小的延遲會(huì)導(dǎo)致這個(gè)問題。

一旦 TCP 達(dá)到 “GB/s” 的吞吐率,序列號(hào)的回繞速度就會(huì)非???,以至于即使只有幾毫秒的延遲也可能會(huì)造成 TCP 無法檢測出的重復(fù)項(xiàng)。通過解決接收窗口太小的問題,TCP 現(xiàn)在可以用于以前無法實(shí)現(xiàn)的網(wǎng)絡(luò)速度,這會(huì)產(chǎn)生一個(gè)新的,盡管很少見的問題。為了在 RTT 非常低的環(huán)境中安全使用 GB/s 的速度,接收方必須能夠檢測到這些舊的重復(fù)項(xiàng),而不必僅依賴序列號(hào)。

TCP 時(shí)間戳

最佳截止日期

用最簡單的術(shù)語來說,TCP 時(shí)間戳只是在數(shù)據(jù)包上添加時(shí)間戳,以解決由非??焖俚男蛄刑?hào)回繞引起的歧義。如果一個(gè)段看起來包含新數(shù)據(jù),但其時(shí)間戳早于上一個(gè)在接收窗口內(nèi)的數(shù)據(jù)包,則該序列號(hào)已被重新回繞,而“新”數(shù)據(jù)包實(shí)際上是一個(gè)較舊的重復(fù)項(xiàng)。這解決了即使在極端情況下重傳的歧義。

但是,該擴(kuò)展不僅僅是檢測舊數(shù)據(jù)包。TCP 時(shí)間戳的另一個(gè)主要功能是更精確的往返時(shí)間測量(RTTm)。

需要準(zhǔn)確的 RTT 估算

當(dāng)兩個(gè)對等方都支持時(shí)間戳?xí)r,每個(gè) TCP 段都攜帶兩個(gè)附加數(shù)字:時(shí)間戳值和回顯時(shí)間戳。

  1. TCP Timestamp option (TSopt): Kind: 8, Length: 10
  2. +-------+----+----------------+-----------------+
  3. |Kind=8 | 10 |TS Value (TSval)|EchoReply (TSecr)|
  4. +-------+----+----------------+-----------------+
  5.     1      1         4                4

準(zhǔn)確的 RTT 估算對于 TCP 性能至關(guān)重要。TCP 會(huì)自動(dòng)重新發(fā)送未確認(rèn)的數(shù)據(jù)。重傳由計(jì)時(shí)器觸發(fā):如果超時(shí),則 TCP 會(huì)將尚未收到確認(rèn)的一個(gè)或多個(gè)數(shù)據(jù)包視為丟失。然后再發(fā)送一次。

但是,“尚未得到確認(rèn)” 并不意味著該段已丟失。也有可能是接收方到目前為止沒有發(fā)送確認(rèn),或者確認(rèn)仍在傳輸中。這就造成了一個(gè)兩難的困境:TCP 必須等待足夠長的時(shí)間,才能讓這種輕微的延遲變得無關(guān)緊要,但它也不能等待太久。

低網(wǎng)絡(luò)延遲 VS 高網(wǎng)絡(luò)延遲

在延遲較高的網(wǎng)絡(luò)中,如果計(jì)時(shí)器觸發(fā)過快,TCP 經(jīng)常會(huì)將時(shí)間和帶寬浪費(fèi)在不必要的重發(fā)上。

然而,在延遲較低的網(wǎng)絡(luò)中,等待太長時(shí)間會(huì)導(dǎo)致真正發(fā)生數(shù)據(jù)包丟失時(shí)吞吐量降低。因此,在低延遲網(wǎng)絡(luò)中,計(jì)時(shí)器應(yīng)該比高延遲網(wǎng)絡(luò)中更早到期。所以,TCP 重傳超時(shí)不能使用固定常量值作為超時(shí)。它需要根據(jù)其在網(wǎng)絡(luò)中所經(jīng)歷的延遲來調(diào)整該值。

往返時(shí)間的測量

TCP 選擇基于預(yù)期的往返時(shí)間(RTT)的重傳超時(shí)。RTT 事先是未知的。它是通過測量發(fā)送的段與 TCP 接收到該段所承載數(shù)據(jù)的確認(rèn)之間的增量來估算的。

由于多種因素使其而變得復(fù)雜。

  • 出于性能原因,TCP 不會(huì)為收到的每個(gè)數(shù)據(jù)包生成新的確認(rèn)。它等待的時(shí)間非常短:如果有更多的數(shù)據(jù)段到達(dá),則可以通過單個(gè) ACK 數(shù)據(jù)包確認(rèn)其接收。這稱為“累積確認(rèn)”cumulative ACK。
  • 往返時(shí)間并不恒定。這是有多種因素造成的。例如,客戶端可能是一部移動(dòng)電話,隨其移動(dòng)而切換到不同的基站。也可能是當(dāng)鏈路或 CPU 的利用率提高時(shí),數(shù)據(jù)包交換花費(fèi)了更長的時(shí)間。
  • 必須重新發(fā)送的數(shù)據(jù)包在計(jì)算過程中必須被忽略。這是因?yàn)榘l(fā)送方無法判斷重傳數(shù)據(jù)段的 ACK 是在確認(rèn)原來的傳輸數(shù)據(jù)(畢竟已到達(dá))還是在確認(rèn)重傳數(shù)據(jù)。

最后一點(diǎn)很重要:當(dāng) TCP 忙于從丟失中恢復(fù)時(shí),它可能僅接收到重傳段的 ACK。這樣,它就無法在此恢復(fù)階段測量(更新)RTT。所以,它無法調(diào)整重傳超時(shí),然后超時(shí)將以指數(shù)級(jí)增長。那是一種非常具體的情況(它假設(shè)其他機(jī)制,如快速重傳或 SACK 不起作用)。但是,使用 TCP 時(shí)間戳,即使在這種情況下也會(huì)進(jìn)行 RTT 評估。

如果使用了擴(kuò)展,則對等方將從 TCP 段的擴(kuò)展空間中讀取時(shí)間戳值并將其存儲(chǔ)在本地。然后,它將該值作為 “回顯時(shí)間戳” 放入發(fā)回的所有數(shù)據(jù)段中。

因此,該選項(xiàng)帶有兩個(gè)時(shí)間戳:它的發(fā)送方自己的時(shí)間戳和它從對等方收到的最新時(shí)間戳。原始發(fā)送方使用 “回顯時(shí)間戳” 來計(jì)算 RTT。它是當(dāng)前時(shí)間戳?xí)r鐘與 “回顯時(shí)間戳” 中所反映的值之間的增量。

時(shí)間戳的其他用途

TCP 時(shí)間戳甚至還有除 PAWS(防止序列號(hào)回繞Protection Against Wrapped Sequences) 和 RTT 測量以外的其他用途。例如,可以檢測是否不需要重發(fā)。如果該確認(rèn)攜帶較舊的回顯時(shí)間戳,則該確認(rèn)針對的是初始數(shù)據(jù)包,而不是重新發(fā)送的數(shù)據(jù)包。

TCP 時(shí)間戳的另一個(gè)更晦澀的用例與 TCP syn cookie 功能有關(guān)。

在服務(wù)器端建立 TCP 連接

當(dāng)連接請求到達(dá)的速度快于服務(wù)器應(yīng)用程序可以接受新的傳入連接的速度時(shí),連接積壓最終將達(dá)到其極限。這可能是由于系統(tǒng)配置錯(cuò)誤或應(yīng)用程序中的錯(cuò)誤引起的。當(dāng)一個(gè)或多個(gè)客戶端發(fā)送連接請求而不對 “SYN ACK” 響應(yīng)做出反應(yīng)時(shí),也會(huì)發(fā)生這種情況。這將用不完整的連接填充連接隊(duì)列。這些條目需要幾秒鐘才會(huì)超時(shí)。這被稱為“同步泛洪攻擊”syn flood attack。

TCP 時(shí)間戳和 TCP Syn Cookie

即使隊(duì)列已滿,某些 TCP 協(xié)議棧也允許繼續(xù)接受新連接。發(fā)生這種情況時(shí),Linux 內(nèi)核將在系統(tǒng)日志中打印一條突出的消息:

端口 P 上可能發(fā)生 SYN 泛洪。正在發(fā)送 Cookie。檢查 SNMP 計(jì)數(shù)器。

此機(jī)制將完全繞過連接隊(duì)列。通常存儲(chǔ)在連接隊(duì)列中的信息被編碼到 SYN/ACK 響應(yīng) TCP 序列號(hào)中。當(dāng) ACK 返回時(shí),可以根據(jù)序列號(hào)重建隊(duì)列條目。

序列號(hào)只有有限的空間來存儲(chǔ)信息。因此,使用 “TCP Syn Cookie” 機(jī)制建立的連接不能支持 TCP 選項(xiàng)。

但是,對兩個(gè)對等點(diǎn)都通用的 TCP 選項(xiàng)可以存儲(chǔ)在時(shí)間戳中。ACK 數(shù)據(jù)包在回顯時(shí)間戳字段中反映了該值,這也允許恢復(fù)已達(dá)成共識(shí)的 TCP 選項(xiàng)。否則,cookie 連接受標(biāo)準(zhǔn)的 64KB 接收窗口限制。

常見誤區(qū) —— 時(shí)間戳不利于性能

不幸的是,一些指南建議禁用 TCP 時(shí)間戳,以減少內(nèi)核訪問時(shí)間戳?xí)r鐘來獲取當(dāng)前時(shí)間所需的次數(shù)。這是不正確的。如前所述,RTT 估算是 TCP 的必要部分。因此,內(nèi)核在接收/發(fā)送數(shù)據(jù)包時(shí)總是采用微秒級(jí)的時(shí)間戳。

在包處理步驟的其余部分中,Linux 會(huì)重用 RTT 估算所需的時(shí)鐘時(shí)間戳。這還避免了將時(shí)間戳添加到傳出 TCP 數(shù)據(jù)包的額外時(shí)鐘訪問。

整個(gè)時(shí)間戳選項(xiàng)在每個(gè)數(shù)據(jù)包中僅需要 10 個(gè)字節(jié)的 TCP 選項(xiàng)空間,這不會(huì)顯著減少可用于數(shù)據(jù)包有效負(fù)載的空間。

常見誤區(qū) —— 時(shí)間戳是個(gè)安全問題

一些安全審計(jì)工具和(較舊的)博客文章建議禁用 TCP 時(shí)間戳,因?yàn)閾?jù)稱它們泄露了系統(tǒng)正常運(yùn)行時(shí)間:這樣一來,便可以估算系統(tǒng)/內(nèi)核的補(bǔ)丁級(jí)別。這在過去是正確的:時(shí)間戳?xí)r鐘基于不斷增加的值,該值在每次系統(tǒng)引導(dǎo)時(shí)都以固定值開始。時(shí)間戳值可以估計(jì)機(jī)器已經(jīng)運(yùn)行了多長時(shí)間(正常運(yùn)行時(shí)間 uptime)。

從 Linux 4.12 開始,TCP 時(shí)間戳不再顯示正常運(yùn)行時(shí)間。發(fā)送的所有時(shí)間戳值都使用對等設(shè)備特定的偏移量。時(shí)間戳值也每 49 天回繞一次。

換句話說,從地址 “A” 出發(fā),或者終到地址 “A” 的連接看到的時(shí)間戳與到遠(yuǎn)程地址 “B” 的連接看到的時(shí)間戳不同。

運(yùn)行 sysctl net.ipv4.tcp_timeamp=2 以禁用隨機(jī)化偏移。這使得分析由諸如 wireshark 或 tcpdump 之類的工具記錄的數(shù)據(jù)包跟蹤變得更容易 —— 從主機(jī)發(fā)送的數(shù)據(jù)包在其 TCP 選項(xiàng)時(shí)間戳中都具有相同的時(shí)鐘基準(zhǔn)。因此,對于正常操作,默認(rèn)設(shè)置應(yīng)保持不變。

選擇性確認(rèn)

如果同一數(shù)據(jù)窗口中的多個(gè)數(shù)據(jù)包丟失了,TCP 將會(huì)出現(xiàn)問題。這是因?yàn)?TCP 確認(rèn)是累積的,但僅適用于按順序到達(dá)的數(shù)據(jù)包。例如:

  • 發(fā)送方發(fā)送段 s_1、s_2、s_3、... s_n
  • 發(fā)送方收到 s_2 的 ACK
  • 這意味著 s_1 和 s_2 都已收到,并且發(fā)送方不再需要保留這些段。
  • s_3 是否應(yīng)該重新發(fā)送? s_4 呢? s_n?

發(fā)送方等待 “重傳超時(shí)” 或 “重復(fù) ACK” 以使 s_2 到達(dá)。如果發(fā)生重傳超時(shí)或到達(dá)了 s_2 的多個(gè)重復(fù) ACK,則發(fā)送方再次發(fā)送 s_3。

如果發(fā)送方收到對 s_n 的確認(rèn),則 s_3 是唯一丟失的數(shù)據(jù)包。這是理想的情況。僅發(fā)送單個(gè)丟失的數(shù)據(jù)包。

如果發(fā)送方收到的確認(rèn)段小于 s_n,例如 s_4,則意味著丟失了多個(gè)數(shù)據(jù)包。發(fā)送方也需要重傳下一個(gè)數(shù)據(jù)段。

重傳策略

可能只是重復(fù)相同的序列:重新發(fā)送下一個(gè)數(shù)據(jù)包,直到接收方指示它已處理了直至 s_n 的所有數(shù)據(jù)包為止。這種方法的問題在于,它需要一個(gè) RTT,直到發(fā)送方知道接下來必須重新發(fā)送的數(shù)據(jù)包為止。盡管這種策略可以避免不必要的重傳,但要等到 TCP 重新發(fā)送整個(gè)數(shù)據(jù)窗口后,它可能要花幾秒鐘甚至更長的時(shí)間。

另一種方法是一次重新發(fā)送幾個(gè)數(shù)據(jù)包。當(dāng)丟失了幾個(gè)數(shù)據(jù)包時(shí),此方法可使 TCP 恢復(fù)更快。在上面的示例中,TCP 重新發(fā)送了 s_3、s_4、s_5、...,但是只能確保已丟失 s_3。

從延遲的角度來看,這兩種策略都不是最佳的。如果只有一個(gè)數(shù)據(jù)包需要重新發(fā)送,第一種策略是快速的,但是當(dāng)多個(gè)數(shù)據(jù)包丟失時(shí),它花費(fèi)的時(shí)間太長。

即使必須重新發(fā)送多個(gè)數(shù)據(jù)包,第二個(gè)也是快速的,但是以浪費(fèi)帶寬為代價(jià)。此外,這樣的 TCP 發(fā)送方在進(jìn)行不必要的重傳時(shí)可能已經(jīng)發(fā)送了新數(shù)據(jù)。

通過可用信息,TCP 無法知道丟失了哪些數(shù)據(jù)包。這就是 TCP 選擇性確認(rèn)(SACK)的用武之地了。就像窗口縮放和時(shí)間戳一樣,它是另一個(gè)可選的但非常有用的 TCP 特性。

SACK 選項(xiàng)

  1.    TCP Sack-Permitted Option: Kind: 4, Length 2
  2.    +---------+---------+
  3.    | Kind=4  | Length=2|
  4.    +---------+---------+

支持此擴(kuò)展的發(fā)送方在連接請求中包括 “允許 SACK” 選項(xiàng)。如果兩個(gè)端點(diǎn)都支持該擴(kuò)展,則檢測到數(shù)據(jù)流中丟失數(shù)據(jù)包的對等方可以將此信息通知發(fā)送方。

  1.    TCP SACK Option: Kind: 5, Length: Variable
  2.                      +--------+--------+
  3.                      | Kind=5 | Length |
  4.    +--------+--------+--------+--------+
  5.    |      Left Edge of 1st Block       |
  6.    +--------+--------+--------+--------+
  7.    |      Right Edge of 1st Block      |
  8.    +--------+--------+--------+--------+
  9.    |                                   |
  10.    /            . . .                  /
  11.    |                                   |
  12.    +--------+--------+--------+--------+
  13.    |      Left Edge of nth Block       |
  14.    +--------+--------+--------+--------+
  15.    |      Right Edge of nth Block      |
  16.    +--------+--------+--------+--------+

接收方遇到 s_2 后跟 s_5 ... s_n,則在發(fā)送對 s_2 的確認(rèn)時(shí)將包括一個(gè) SACK 塊:

  1.                 +--------+-------+
  2.                 | Kind=5 |   10  |
  3. +--------+------+--------+-------+
  4. | Left edge: s_5                 |
  5. +--------+--------+-------+------+
  6. | Right edge: s_n                |
  7. +--------+-------+-------+-------+

這告訴發(fā)送方到 s_2 的段都是按順序到達(dá)的,但也讓發(fā)送方知道段 s_5 至 s_n 也已收到。然后,發(fā)送方可以重新發(fā)送那兩個(gè)數(shù)據(jù)包(s_3、s_4),并繼續(xù)發(fā)送新數(shù)據(jù)。

神話般的無損網(wǎng)絡(luò)

從理論上講,如果連接不會(huì)丟包,那么 SACK 就沒有任何優(yōu)勢?;蛘哌B接具有如此低的延遲,甚至等待一個(gè)完整的 RTT 都無關(guān)緊要。

在實(shí)踐中,無損行為幾乎是不可能保證的。即使網(wǎng)絡(luò)及其所有交換機(jī)和路由器具有足夠的帶寬和緩沖區(qū)空間,數(shù)據(jù)包仍然可能丟失:

  • 主機(jī)操作系統(tǒng)可能面臨內(nèi)存壓力并丟棄數(shù)據(jù)包。請記住,一臺(tái)主機(jī)可能同時(shí)處理數(shù)萬個(gè)數(shù)據(jù)包流。
  • CPU 可能無法足夠快地消耗掉來自網(wǎng)絡(luò)接口的傳入數(shù)據(jù)包。這會(huì)導(dǎo)致網(wǎng)絡(luò)適配器本身中的數(shù)據(jù)包丟失。
  • 如果 TCP 時(shí)間戳不可用,即使一個(gè)非常小的 RTT 的連接也可能在丟失恢復(fù)期間暫時(shí)停止。

使用 SACK 不會(huì)增加 TCP 數(shù)據(jù)包的大小,除非連接遇到數(shù)據(jù)包丟失。因此,幾乎沒有理由禁用此功能。幾乎所有的 TCP 協(xié)議棧都支持 SACK —— 它通常只在不進(jìn)行 TCP 批量數(shù)據(jù)傳輸?shù)牡凸?IOT 類的設(shè)備上才不存在。

當(dāng) Linux 系統(tǒng)接受來自此類設(shè)備的連接時(shí),TCP 會(huì)自動(dòng)為受影響的連接禁用 SACK。

總結(jié)

本文中研究的三個(gè) TCP 擴(kuò)展都與 TCP 性能有關(guān),最好都保留其默認(rèn)設(shè)置:啟用。

TCP 握手可確保僅使用雙方都可以理解的擴(kuò)展,因此,永遠(yuǎn)不需因?yàn)閷Φ确娇赡懿恢С侄纸迷摂U(kuò)展。

關(guān)閉這些擴(kuò)展會(huì)導(dǎo)致嚴(yán)重的性能損失,尤其是 TCP 窗口縮放和 SACK。可以禁用 TCP 時(shí)間戳而不會(huì)立即造成不利影響,但是現(xiàn)在沒有令人信服的理由這樣做了。啟用它們還可以支持 TCP 選項(xiàng),即使在 SYN cookie 生效時(shí)也是如此。 

責(zé)任編輯:龐桂玉 來源: Linux中國
相關(guān)推薦

2014-06-26 09:24:04

TCP

2023-11-10 16:28:02

TCP窗口

2023-08-11 07:44:40

TCP滑動(dòng)窗口數(shù)據(jù)

2024-07-09 09:08:36

golang簽名參數(shù)簽名時(shí)間

2013-03-26 09:04:16

iOS時(shí)間戳與時(shí)間相互轉(zhuǎn)化

2009-11-23 17:50:01

PHP時(shí)間戳

2009-11-23 17:31:49

PHP時(shí)間戳

2020-08-13 08:43:24

TCP固定窗口滑動(dòng)窗口

2017-10-20 12:13:11

數(shù)據(jù)庫PostgreSQL時(shí)間戳

2015-01-15 09:21:24

TCP窗口

2009-12-08 13:54:31

PHP時(shí)間戳函數(shù)

2023-11-10 15:29:28

GIMP圖像

2013-11-18 10:04:31

TCP 滑動(dòng)窗口

2010-04-27 13:31:31

2024-08-28 13:09:50

2024-04-15 09:40:38

Python時(shí)間戳time模塊

2018-09-06 10:48:51

TCPUDP協(xié)議

2021-08-25 09:38:16

鴻蒙HarmonyOS應(yīng)用

2019-03-12 10:46:17

TCP協(xié)議算法

2009-08-16 19:25:12

linux中touchtouch命令參數(shù)linux命令行參數(shù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)