卸载校验和任务

NDIS 支持在运行时卸载 TCP/IP 校验和任务。

注意

 校验和卸载带外 (OOB) 数据存储在 NET_BUFFER_LIST 信息数组中。 有关 OOB 数据的详细信息,请参阅 访问 TCP/IP 卸载NET_BUFFER_LIST信息

在将微型端口驱动程序NET_BUFFER_LIST结构传递给微型端口驱动程序将对其执行校验和任务的数据包之前,TCP/IP 传输会指定与NET_BUFFER_LIST结构关联的校验和信息。 此信息由 NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO 结构指定,该结构是与NET_BUFFER_LIST结构关联的带外数据) (NET_BUFFER_LIST信息的一部分。

在卸载 TCP 数据包的校验和计算之前,TCP/IP 传输会计算 TCP 伪标头的补总和。 TCP/IP 传输计算伪头程序中所有字段(包括源 IP 地址、目标 IP 地址、协议和 TCP 数据包的 TCP 长度)的补补总和。 TCP/IP 传输在 TCP 标头的校验和字段中输入伪标头的补码总和。

TCP/IP 传输提供的伪标头的补码总和使 NIC 提前开始计算发送数据包的实际 TCP 校验和。 为了计算实际的 TCP 校验和,NIC 计算 TCP 标头和有效负载) 的 TCP 校验和 (的变量部分,将此校验和添加到 TCP/IP 传输计算的伪标头的补数之和中,并计算校验和的 16 位补数。 有关计算此类校验和的详细信息,请参阅 RFC 793 和 RFC 1122。

注意

TCP/IP 传输使用与 TCP 数据包相同的步骤计算 UDP 数据包伪标头的补码总和,并将值存储在 UDP 标头的校验和字段中。

请注意,TCP/IP 传输始终确保在将数据包传递到基础微型端口驱动程序之前,数据包的 IP 标头中的校验和字段设置为零。 微型端口驱动程序应忽略 IP 标头中的校验和字段。 微型端口驱动程序不需要验证校验和字段是否设置为零,也不需要将此字段设置为零。

在其 MiniportSendNetBufferLists 或 MiniportCoSendNetBufferLists 函数中收到 NET_BUFFER_LIST 结构后,微型端口驱动程序通常会执行以下校验和处理:

  1. 微型端口驱动程序使用 tcpIpChecksumNetBufferListInfo_Id调用 NET_BUFFER_LIST_INFO 宏以获取NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO结构。

  2. 微型端口驱动程序在NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO结构中测试 IsIPv4IsIPv6 标志。 如果未同时设置 IsIPv4IsIPv6 标志,则 NIC 不应对数据包执行任何校验和操作。

  3. 如果设置了 IsIPv4IsIPv6 标志,微型端口驱动程序将测试 TcpChecksumUdpChecksumIpHeaderChecksum 标志,以确定 NIC 应为数据包计算哪些校验和。

  4. 微型端口驱动程序将数据包传递给 NIC,该 NIC 计算数据包的相应校验和。 如果数据包同时具有隧道 IP 标头和传输 IP 标头,则支持 IP 校验和卸载的 NIC 仅在隧道标头上执行 IP 校验和任务。 TCP/IP 传输对传输 IP 标头执行 IP 校验和任务。

在指示其执行校验和任务的接收数据包 的NET_BUFFER_LIST 结构之前,微型端口驱动程序会验证相应的校验和,并在NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO结构中设置相应的 XxxChecksumFailedXxxChecksumSucceeded 标志。

启用大型发送卸载 (LSO) 时关闭地址校验和卸载不会阻止微型端口驱动程序计算校验和并在 LSO 功能生成的数据包中插入校验和。 在这种情况下,若要禁用地址校验和卸载,用户还必须禁用 LSO。