合併 TCP/IP 區段的規則
本節會定義規則,指定接收區段聯合 (RSC)功能迷你埠驅動程式何時必須聯合指定 TCP 連線的區段。 如果違反任何規則,就會產生例外狀況,而迷你埠驅動程序必須中止區段的聯合。
迷你埠驅動程序必須更新單一聯合單位 (SCU) 的IP和 TCP 標頭。 迷你埠驅動程序必須透過 SCU 重新計算 TCP 和 IPv4 總和檢查碼,並鏈結 TCP 承載。
下列兩個流程圖中的第一個描述聯合區段和更新 TCP 標頭的規則。 此流程圖涉及區分有效重複 ACK 和窗口更新的機制。 第二個流程圖描述這些機制。
這些流程圖是以瞭解 RSC 規則的參考方式提供。 只要維護正確性,硬體實作就可以優化流程圖。
流程圖中會使用下列詞彙:
術語 | 描述 |
---|---|
SEG。SEQ | 傳入區段的序號。 |
H.SEQ | 目前正追蹤的 SCU 的序列號。 |
SEG。ACK | 接收區段的確認號碼。 |
H.ACK | 目前追蹤 SCU 的確認號碼。 |
SEG。WND | 傳入區段所宣告的視窗。 |
H.WND | 目前追蹤的 SCU 所顯示的視窗。 |
SEG。LEN | 傳入區段的 TCP 承載長度。 |
H.LEN | 目前追蹤 SCU 的 TCP 有效負載長度。 |
SEG。NXT | SEG.SEQ 和 SEG.LEN的總和。 |
H.NXT | H.SEQ 和 H.LEN的總和。 |
H.DupAckCount | 已整合到 SCU 的重複 ACK 數量。 這個數位應該是零。 |
SEG。Tsval | 目前接收到的區段中的 時間戳記 的值。 此值的格式定義於 RFC 1323中。 |
H.Tsval | 目前正在追蹤的 SCU 中的 Timestamp 值。 |
SEG.TSecr | 當前接收區段中的時間戳回應。 |
H.TSecr | 目前追蹤 SCU 中的 時間戳回應。 |
流程圖顯示迷你埠驅動程式可能會將不同 ACK 數位的區段聯合在一起。 不過,迷你埠驅動程序必須遵守下列有關 ACK 號碼的規則,如上述第一個流程圖所示:
執行序號檢查之後,如果傳入的純 ACK 符合下列其中一個或兩個條件,可能會合併到目前追蹤的 SCU:
H.ACK == SEG.ACK。
所追蹤之聯合區段中的 duplicate-ACK 計數為零。 換句話說,H.DupAckCount == 0。
換句話說,任何不是重複 ACK 或視窗更新的純 ACK 都會觸發例外狀況,而且不得合併。 所有這類純 ACK 都必須以個別區段表示。 此規則可確保 RSC 不會影響 Windows TCP 壅塞控制演算法的行為或效能。
傳入的數據區段(SEG.ACK == H.ACK)或傳入附帶的 ACK(SEG.ACK>H.ACK)如果符合下列兩個條件,可能會合併到目前追蹤的 SCU:
- 區段在序列空間中與SCU相鄰。 換句話說,SEG。SEQ == H.NXT。
- 所追蹤之聯合區段中的 duplicate-ACK 計數為零。 換句話說,H.DupAckCount == 0。
重複 ACK 合併的其他注意事項
重複的 ACK 行為
迷你埠驅動程式應將重複的 ACK 區段視為等同於純 ACK,並不應將其合併。 在此情況下,它必須完成目前的SCU(如果有的話)以用於信號指示,並將重複的ACK區段標記為單獨的區段。 因為 Windows 用戶端預設會使用選擇性通知 (SACK),因此重複的 ACK 區段可能會產生例外狀況。 如需範例,請參閱接收區段聯合 的 範例。 如果指出具有 DupAckCount> 0 的區段,NDIS 會在介面上停用 RSC。
在追蹤由數據段組成的 SCU 時,處理重複的 ACK
使用 H.LEN> 0 追蹤 SCU 時(換句話說,包含數據的合併區段),如果後續出現重複的 ACK,則追蹤 SCU 應該如下所示完成:
新的 SCU 追蹤應該從重複的 ACK 開始。
新 SCU 的 DupAckCount 應設定為零。
如果收到額外的重複 ACK,則 DupAckCount 應增加。
在此情況下,DupAckCount 會比重複 ACK 的數目少 1 個。 主機堆疊會正確處理計數。
追蹤由純累積 ACK 組成的 SCU 時處理重複的 ACK
追蹤由單一純累計 ACK 組成的 SCU 時(禁止合併多個純 ACK 的規則),如果後續出現重複的 ACK,則追蹤 SCU 的 DupAckCount 應該遞增。 如果收到其他重複的 ACK,該值也應該遞增。 在此情況下,DupAckCount 會等於合併的重複 ACK 數目。
當 DPC 中收到的第一個區段是重複的 ACK 時
在此情況下,NIC 無法判斷收到的區段是否為重複的 ACK,因為它不會維護任何狀態。 因此,區段應該視為純 ACK,如下所示:
從此區段開始,應當追蹤新的 SCU。
新 SCU 的 DupAckCount 應設定為零。
每當收到額外的重複 ACK 時,DupAckCount 應該遞增 1。
在此情況下,DupAckCount 將等於 1 小於實際重複 ACK 數目。 主系統堆疊程式會正確處理計數。
重複的 ACK 豁免
迷你埠驅動程式可能會將重複的 ACK 區段視為與純 ACK 等效,並且不會將其合併。 在此情況下,必須完成目前的 SCU(如果有的話)以進行指示,並將重複的 ACK 區段作為獨立區段指出。 因為 Windows 用戶端預設會使用 SACK,因此重複的 ACK 區段可能會產生例外狀況。 如需範例,請參閱 接收區段合併範例。 此豁免不適用於視窗更新區段。
使用時間戳記選項合併區段
TCP 時間戳選項是唯一可合法合併的選項。 將區段合併這一選項的決策交由具體實作來決定。 如果迷你埠驅動程式在使用時間戳記選項合併區段,則必須遵循下列流程圖中所述的規則:
注意
檢查 SEG。TSval>= H.TSval 必須使用模 232 算術進行,類似於 TCP 序號中使用的算法。 請參閱 RFC 793節 3.3。
當指出聯合區段時,必須如下所示地指出下列頻外資訊,方法是設定 NetBufferListInfo 描述聯合區段之 NET_BUFFER_LIST 結構的成員:
合併的區段數目必須儲存到 NetBufferListInfo[TcpRecvSegCoalesceInfo] 的CoalescedSegCount 成員。 這個數位只代表已聯合的數據區段。 禁止純 ACK 聯合,且視窗更新區段不得計入此欄位的一部分。
重複的 ACK 計數必須儲存至 NetBufferListInfo[TcpRecvSegCoalesceInfo] 中的DupAckCount 成員。 上述第一個流程圖說明如何計算此值。
當具有 TCP 時間戳選項的區段合併時,NetBufferListInfo[RscTcpTimestampDelta] 必須填入組成 SCU 之聯合區段序列中最早與最新 TCP 時間戳值之間的絕對差異。 SCU 本身應該包含聯合區段序列中所見的最新 TCP 時間戳值。
DupAckCount 和 RscTcpTimestampDelta 的值只有在 CoalescedSegCount 大於零時才會被解釋。 如果 CoalescedSegCount 為零,則會將區段視為非聯合的非 RSC 區段。
如需有關 NetBufferListInfo 成員內容的信息,請參閱 NDIS_NET_BUFFER_LIST_INFO 和 NDIS_RSC_NBL_INFO。
所有聯合區段的 PSH 位應該是 ORed。 換句話說,如果在任何個別區段中設定 PSH 位,迷你埠驅動程序應該在 SCU 中設定 PSH 位。
完成 SCU 的過程涉及:
重新計算 TCP 檢查碼,以及(如果適用)IPv4 檢查碼。
更新IP標頭,如 更新聯合區段的IP標頭中所述。
將 TCP 和 IP 標頭中的 ECN 位和 ECN 欄位設定為個別區段中設定的相同值。
處理 TCP/IP IPsec 區段
網路卡可能會顯示具備 RSC 和 IPsec 工作卸載功能的能力。 (請參閱 判斷網路適配器的 RSC 功能。)不過,如果支援 IPsec 工作卸除,它不可嘗試合併受 IPsec 保護的區段。