本部分定义规则,这些规则指定接收段合并(RSC)支持的微型端口驱动程序何时必须合并给定 TCP 连接的段。 如果违反任何规则,则会生成异常,微型端口驱动程序必须中止段的合并。
微型端口驱动程序必须更新单个合并单元(SCU)的 IP 和 TCP 标头。 微型端口驱动程序必须重新计算 SCU 上的 TCP 和 IPv4 校验和,并链接 TCP 有效负载。
以下两个流程图中的第一个描述了合并段和更新 TCP 标头的规则。 此流程图是指用于区分有效重复 ACK 和窗口更新的机制。 第二个流程图描述了这些机制。
这些流程图作为了解 RSC 规则的参考。 只要维护正确性,硬件实现就可以优化流程图。
流程图中使用以下术语:
| 术语 | DESCRIPTION | 
|---|---|
| SEG。SEQ | 传入段的序列号。 | 
| H.SEQ | 当前跟踪的 SCU 的序列号。 | 
| SEG.ACK | 传入段的确认编号。 | 
| H.ACK | 当前跟踪的 SCU 的确认编号。 | 
| SEG.WND | 传入数据段所发布的窗口。 | 
| H.WND | 当前跟踪的 SCU 所通告的窗口。 | 
| SEG。莱恩 | 传入段的 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 中的 时间戳 值。 | 
| SEG。TSecr | 当前收到的段中的 时间戳回显回复 。 | 
| H.TSecr | 当前所跟踪的 SCU 中的 时间戳回显回复。 | 
              
              
              
              
            
              
              
              
              
            
流程图显示微型端口驱动程序可能会合并具有不同 ACK 编号的段。 但是,微型端口驱动程序必须遵循以下有关 ACK 编号的规则,如上面的第一个流程图所示:
执行序列号检查后,如果传入的纯 ACK 满足以下一个或两个条件,则可能会合并到当前跟踪的 SCU 中:
H.ACK == SEG.ACK.
正在跟踪的合并段中的重复 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。
 - 正在跟踪的合并段中的重复 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(规则禁止合并多个纯 ACK)组成的 SCU 时,如果接下来到达重复的 ACK,则跟踪 SCU 的 DupAckCount 应增加。 如果收到其他重复的 ACK,则它还应递增。 在这种情况下, DupAckCount 将等于合并的重复 ACK 数。
在 DPC 中接收到的第一段是重复的 ACK 时
在这种情况下,NIC 无法确定收到的段是否为重复的 ACK,因为它不保留任何状态。 因此,应将该段视为单纯的 ACK,如下所示:
应从此段开始跟踪新的 SCU。
新 SCU 的 DupAckCount 应设置为零。
对于收到的每个额外的重复 ACK,DupAckCount 应递增 1。
在这种情况下,DupAckCount 将等于重复 ACK 的实际数量减去 1。 主机堆栈将正确处理计数。
重复 ACK 豁免
微型端口驱动程序可以将重复的 ACK 段视为等同于纯粹的 ACK,而不将其合并在一起。 在这种情况下,必须完成当前的 SCU(如果有),并将重复的 ACK 段作为单个段进行指示。 由于 Windows 客户端默认使用 SACK,因此重复的 ACK 段可能会生成异常。 有关示例,请参阅 接收段合并的示例。 此豁免不适用于窗口更新段。
使用时间戳选项合并段落
TCP 时间戳选项是唯一可以合法合并的选项。 使用此选项合并段的决定取决于具体实现。 如果微型端口驱动程序在合并段时使用时间戳选项,则它必须遵循以下流程图中概述的规则:
              
              
              
              
            
注释
检查 SEG。TSval= H.TSval> 必须使用模数-232 算术来执行,类似于用于 TCP 序列号的算术。 请参阅 RFC 793,第 3.3 节。
指示合并段时,必须通过设置描述合并段的NET_BUFFER_LIST结构中的NetBufferListInfo成员,按如下方式指示下述带外信息:
合并的段数必须存储在 NetBufferListInfo[TcpRecvSegCoalesceInfo] 中。CoalescedSegCount 成员。 此数字仅表示合并的数据段。 禁止纯 ACK 合并,窗口更新段不得计入此字段的一部分。
重复的 ACK 计数必须存储在 NetBufferListInfo[TcpRecvSegCoalesceInfo] 中的 DupAckCount 成员。 上面的第一个流程图说明了如何计算此值。
合并具有 TCP 时间戳选项的段时,NetBufferListInfo[RscTcpTimestampDelta] 必须填入最早和最新的 TCP 时间戳值——在由 SCU 组成的合并段序列中观察到的时间戳值之间的绝对差值。 SCU 本身应包含合并段序列中显示的最新 TCP 时间戳值。
仅当 CoalescedSegCount 成员大于零时才解释 DupAckCount 和 RscTcpTimestampDelta 成员。 如果 CoalescedSegCount 为零,则段被视为非合并的非 RSC 段。
有关 NetBufferListInfo 成员的内容的信息,请参阅 NDIS_NET_BUFFER_LIST_INFO 和 NDIS_RSC_NBL_INFO。
PSH 位应该对所有合并的段执行 OR 操作。 换句话说,如果 PSH 位在任何单个段中设置,则微型端口驱动程序应在 SCU 中设置 PSH 位。
要完成 SCU,涉及:
重新计算 TCP 校验和,如适用,则重新计算 IPv4 校验和。
按照更新合并段的 IP 标头中的说明更新 IP 标头。
将 TCP 和 IP 标头中的 ECN 位和 ECN 字段设置为各个段中的相应值。
处理 TCP/IP IPsec 段
网卡可以报告 RSC 和 IPsec 任务卸载功能。 (请参阅 确定网络适配器的 RSC 功能。但是,如果它支持 IPsec 任务卸载,则它不得尝试合并受 IPsec 保护的段。