TCP系列17—重傳—7、SACK下的重傳


 

        我們之前介紹SACK選項的時候說過,SACK可以把接收端系列號空間的洞反映給發送端,因此發送端可以更充分的理解接收端的情況,而進行更好的重傳恢復過程。這種過程有時候也叫做advanced loss recovery

一、數據接收端SACK行為

我們通過一個wireshark示例來說明接收端的SACK行為:

 

如上圖,為了方便在info列中查看SACK信息,我把info列中TSopt的信息隱藏了,同時把源地址列和目的地址列一起隱藏了。client依次發送P1(1-6)、P2(25-30)、P3(13-18)、P4(37-42)、P5(49-54)、P6(7-12)、P7(31-36)、P8(19-24)、P9(43-48)其中括號中的數字為相對系列號,接收端SACK行為簡述如下(詳細的可以參考原始的wireshark文件)

  1. 接收端在接收到P1后回復的No5確認包中不包含SACK信息

  2. 在接收到P2后回復的No7確認包中包含的SACK塊為(25-31)

  3. 接收端在接收到P3后回復No9確認包,包含的SACK塊為(13-19),(25-31)

  4. 接收端在接收到P4后回復No11確認包,包含的SACK信息為(37-43),(13-19),(25-31)

  5. 接收端在接收到P5后回復No13確認包,包含的SACK信息為(49-55),(37-43),(13-19),上圖截圖中對應的SACK信息就是這個確認包的信息

  6. 接收端在接收到P6后回復No15確認包,包含的SACK信息為(49-55),(37-43),(25-31)

  7. 接收端在接收到P7后回復No17確認包,包含的SACK信息為(25-43),(49-55)

  8. 接收端在接收到P8后回復No19確認包,包含的SACK信息為(49-55)

  9. 接收端在接收到P9后回復No21確認包,接收端系列號空間中不再存在洞,因為這個確認包中不再包含SACK信息。

上面的每個ACK確認包都會包含一個TSopt的選項,從上面第5點可以看到,在ACK確認包包含有TSopt選項的時候,最后只能包含3個SACK塊,此時TCP頭長已經到達60bytes的最大值不能在容納更多的SACK塊了。

另外注意就是SACK塊是按照最新形成的洞信息倒序排列的。每個ACK報文中可以攜帶多個SACK塊的原因是因為ACK確認包有可能會丟包,但是ACK報文不消耗系列號因此不會進行重傳,因此接收端通過多個ACK報文中冗余的SACK塊信息來提高SACK信息傳輸的可靠性。

二、數據發送端SACK行為

TCP連接要利用SACK信息還需要發送端根據接收到的SACK信息執行選擇性重傳(selective retransmisson或者叫做selective repeat)。首先根據SACK信息來填充洞,然后在傳遞新數據(RFC6675),但是具體實現上可能會有一些差異。另外按照RFC2018,當TCP初始化一個RTO超時重傳的時候需要清空SACK信息,但是RFC6675認為RTO超時保留SACK信息也是有一定必要性的。RFC2018還要求發送端只有收到TCP頭中的累計ack number的時候才能釋放對應的發送緩存,而不能根據SACK信息釋放,原因是接收端有可能先發送一個SACK塊,然后后面又不在反饋這個SACK塊(SACK reneging)。(實際上按照協議發送端接收到的SACK塊可能是接收端已經丟棄的TCP報文,雖然這個報文丟棄了但是特定情況下接收端仍然可以在SACK塊中攜帶這個報文信息,而在實現上如果linux內存不足,那么有可能會丟掉已經收到的亂序TCP報文)。SACK reneging的示例我們后面會在FACK介紹中進行簡單介紹。

另外一個需要注意的就是在快速重傳的時候dup ACK的定義,RFC6675中對於SACK下dup ACK的定義如下

  For the purposes of this specification, we define a "duplicate   acknowledgment" as a segment that arrives carrying a SACK block that   identifies previously unacknowledged and un-SACKed octets between   HighACK and HighData.  Note that an ACK which carries new SACK data   is counted as a duplicate acknowledgment under this definition even if it carries new data, changes the advertised window, or moves the   cumulative acknowledgment point, which is different from the   definition of duplicate acknowledgment in [RFC5681].

其中

     "HighACK" is the sequence number of the highest byte of data that has been cumulatively ACKed at a given point.      "HighData" is the highest sequence number transmitted at a given point.

下面我們還是重點關注一下Linux實現上的處理吧。

三、SACK下的重傳示例

1、SACK打開但是不攜帶SACK選項的場景

前面我們介紹快速重傳示例的時候,都是把tcp_sack開關設置為0。其中有一個示例如下

 其中No12-No14三個數據包是不帶有SACK選項的ACK確認包。可以看到server在接收到三個dup ack后觸發了快速重傳,我們設置tcp_sack為1后重新運行測試程序,抓包如下,可以看到server在接收到三個不帶有SACK選項的dup ack后並沒有觸發快速重傳,由此可以看到SACK下對於dup ACK理解上的差異。

2、帶有SACK選項的快速重傳

下面我們看一個帶有SACK的快速重傳,下面的測試程序與上面類似,同樣打開tcp_sack功能,不同的時候這次在No12確認包中包含17-25的SACK塊信息,在No13確認包中包含17-33的SACK塊信息,在No14確認包中包含17-41的SACK塊信息。No12-No14確認包的ack number都是9,在收到No14確認包后累計收到三個dup ACK,因此觸發了快速重傳。注意這里對dup ACK的認定並不是因為ack number相同,而是因為SACK塊中累計反饋了三個發送出去的數據包。

3、SACK下ack number不同的dup ACK

上面我們說過SACK下對於dup ACK的認定並不是因為ack number不同。我們在來看一個例子,從下圖可以看到wireshark顯示兩個dup ack后就觸發了快速重傳,實際上是因為wireshark對於dup ack的認定只關注ack number導致的。在No11中帶有17-25的SACK塊信息,No12中帶有17-33的SACK塊信息,No13中帶有17-41的SACK塊信息。按照上面SACK下對於dup ACK的定義,server實際上已經接收到了3個dup ACK,因此觸發了快速重傳。

 

 

 

 

 






免責聲明!

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



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