共用方式為


檢查碼卸載

NetAdapterCx 支援在執行時卸載 TCP/IP 總和檢查碼工作。

在 TCP/IP 傳輸將 NET_PACKET 結構傳遞至用戶端驅動程式之前,它會在 NET_PACKET_CHECKSUM 封包擴充功能中指定與 NET_PACKET 相關的總和檢查碼資訊。

TCP/IP 傳輸會在卸載 TCP/UDP 封包的檢查碼計算之前,計算 TCP/UDP 伪标头的一补码总和,如 卸載檢查碼任務中所述。

一般分割卸載(GSO)啟用時,關閉檢查碼卸載並不會阻止用戶端驅動程式對 GSO 功能產生的封包進行檢查碼計算和插入。 若要完全停用檢查碼卸載,您也必須停用 GSO。

用於控制檢查總和卸載的 INF 關鍵詞

NetAdapterCx 會檢查登錄關鍵詞,並在啟用作用中的卸除功能時接受它們。 驅動程式不需要採取任何進一步的動作。

使用登錄值啟用和停用任務卸載 中提供的校驗和關鍵字,可用來透過登錄機碼設定啟用或停用校驗和卸載。 不支援群組關鍵詞。

關鍵字值的類型必須是 REG_SZ

設定檢查碼卸載

用戶端驅動程式會在網路適配器初始化期間,先宣告其硬體的校驗和卸載能力。 這可能會發生在其 EvtDevicePrepareHardware 回呼中,再啟動網路適配器。

若要設定 Tx 傳輸檢查碼卸載,客戶端驅動程式:

  1. 配置 NET_ADAPTER_OFFLOAD_TX_CHECKSUM_CAPABILITIES 結構。

  2. 呼叫 NET_ADAPTER_OFFLOAD_TX_CHECKSUM_CAPABILITIES_INIT 來初始化 結構。

  3. 呼叫 NetAdapterOffloadSetTxChecksumCapabilities 向 NetAdapterCx 註冊結構。

在呼叫 NET_ADAPTER_OFFLOAD_TX_CHECKSUM_CAPABILITIES_INIT 的過程中,客戶端驅動程序提供了指向 EVT_NET_ADAPTER_OFFLOAD_SET_TX_CHECKSUM 回呼的指標。 如果作用中的卸除功能變更,系統稍後會叫用此回呼。

若要設定接收 Rx 檢查碼卸載,客戶端驅動程式:

  1. 配置 NET_ADAPTER_OFFLOAD_RX_CHECKSUM_CAPABILITIES 結構。

  2. 呼叫 NET_ADAPTER_OFFLOAD_RX_CHECKSUM_CAPABILITIES_INIT 以初始化該結構。

  3. 呼叫 ,將 NetAdapterOffloadSetRxChecksumCapabilities 註冊到 NetAdapterCx 中的結構。

在呼叫 NET_ADAPTER_OFFLOAD_RX_CHECKSUM_CAPABILITIES_INIT 時,客戶端驅動程序會提供指向 EVT_NET_ADAPTER_OFFLOAD_SET_RX_CHECKSUM 回呼的指標。 如果主動卸載功能變更,系統稍後會叫用此回呼。

指出硬體傳輸總和檢查碼功能的規則

  1. Layer3Flags 必須設定在 NET_ADAPTER_OFFLOAD_TX_CHECKSUM_CAPABILITIES 結構中。 設定 Layer4Flags 是選擇性的。 設定 Layer3Flags 和 Layer4Flags 表示 NIC 能夠執行總和檢查碼卸除的封包。

  2. NET_ADAPTER_OFFLOAD_TX_CHECKSUM_CAPABILITIES 中的 Layer3HeaderOffsetLimit 和 Layer4HeaderOffsetLimit 是選擇性的。 如果OS傳送標頭位移大於指定限制的封包,則不會要求 NIC 計算該層總和檢查碼。

  3. 如果支援選項/擴充功能,則必須支援不含選項/延伸模組的IP/TCP 封包。

指出硬體接收總和檢查碼功能的規則

NetAdapterCx 不需要驅動程式公告硬體接收總和檢查碼功能。 如果已啟用總和檢查碼卸除,NIC 應該在它可以處理的所有封包上執行總和檢查碼卸除。 如果 NIC 無法對封包資料執行校驗和卸載,NetAdapterCx 會以軟體方式卸載它。

此範例示範用戶端驅動程式如何設定其硬體的校驗碼卸載功能:

VOID
MyAdapterSetOffloadCapabilities(
    NETADAPTER NetAdapter
)
{
    // Configure the hardware's Tx checksum offload capabilities
    NET_ADAPTER_OFFLOAD_TX_CHECKSUM_CAPABILITIES txChecksumOffloadCapabilities;

    auto const layer3Flags = NetAdapterOffloadLayer3FlagIPv4NoOptions |
        NetAdapterOffloadLayer3FlagIPv4WithOptions |
        NetAdapterOffloadLayer3FlagIPv6NoExtensions |
        NetAdapterOffloadLayer3FlagIPv6WithExtensions;

    auto const layer4Flags = NetAdapterOffloadLayer4FlagTcpNoOptions |
        NetAdapterOffloadLayer4FlagTcpWithOptions |
        NetAdapterOffloadLayer4FlagUdp;

    NET_ADAPTER_OFFLOAD_TX_CHECKSUM_CAPABILITIES_INIT(
        &txChecksumOffloadCapabilities,
        layer3Flags,
        EvtAdapterOffloadSetTxChecksum);

    txChecksumOffloadCapabilities.Layer4Flags = layer4Flags;

    txChecksumOffloadCapabilities.Layer4HeaderOffsetLimit = 127;

    // Set the current Tx checksum offload capabilities and register the callback for future changes in active capabilities
    NetAdapterOffloadSetTxChecksumCapabilities(NetAdapter,
        &txChecksumOffloadCapabilities);

    // Configure the hardware's Rx checksum offload capabilities
    NET_ADAPTER_OFFLOAD_RX_CHECKSUM_CAPABILITIES rxChecksumOffloadCapabilities;

    NET_ADAPTER_OFFLOAD_RX_CHECKSUM_CAPABILITIES_INIT(
        &rxChecksumOffloadCapabilities,
        EvtAdapterOffloadSetRxChecksum);

    // Set the current Rx checksum offload capabilities and register the callback for future changes in active capabilities
    NetAdapterOffloadSetRxChecksumCapabilities(NetAdapter,
        &rxChecksumOffloadCapabilities);
}

更新硬體卸除

如果 TCP/IP 堆疊或上層通訊協定驅動程式要求變更 net adapter 的有效功能,NetAdapterCx 會調用用戶端驅動程式的 EVT_NET_ADAPTER_OFFLOAD_SET_TX_CHECKSUMEVT_NET_ADAPTER_OFFLOAD_SET_RX_CHECKSUM 當網卡初始化期間已註冊的回呼。 在這些函式中,系統會在 NETOFFLOAD 物件中提供更新的功能,用戶端驅動程式會查詢以更新其卸載功能。

用戶端驅動程式可以呼叫下列函式,以判斷已啟用哪些檢查碼卸載:

下列範例示範用戶端驅動程式如何更新其 Tx/Rx 總和檢查碼卸除功能:

VOID
MyEvtAdapterOffloadSetTxChecksum(
    NETADAPTER  NetAdapter,
    NETOFFLOAD  Offload
)
{
    PMY_NET_ADAPTER_CONTEXT adapterContext = MyGetNetAdapterContext(NetAdapter);

    // Store the updated information in the context
    adapterContext->TxHardwareIpChecksum = NetOffloadIsTxChecksumIPv4Enabled(Offload);
    adapterContext->TxHardwareTcpChecksum = NetOffloadIsTxChecksumTcpEnabled(Offload);
    adapterContext->TxHardwareUdpChecksum = NetOffloadIsTxChecksumUdpEnabled(Offload);

    // Update the new hardware Tx checksum offload capabilities
    MyUpdateHardwareChecksum(adapterContext);
}

VOID
MyEvtAdapterOffloadSetRxChecksum(
    NETADAPTER  NetAdapter,
    NETOFFLOAD  Offload
)
{
    PMY_NET_ADAPTER_CONTEXT adapterContext = MyGetNetAdapterContext(NetAdapter);

    // Store the updated information in the context
    adapterContext->RxHardwareIpChecksum = NetOffloadIsRxChecksumIPv4Enabled(Offload);
    adapterContext->RxHardwareTcpChecksum = NetOffloadIsRxChecksumTcpEnabled(Offload);
    adapterContext->RxHardwareUdpChecksum = NetOffloadIsRxChecksumUdpEnabled(Offload);

    // Update the new hardware Rx checksum offload capabilities
    MyUpdateHardwareChecksum(adapterContext);
}

傳輸總和檢查碼處理

用戶端驅動程式通常會在傳輸路徑上執行下列總和檢查碼處理:

  1. 用戶端驅動程式會使用封包索引呼叫 NetExtensionGetPacketChecksum 函式,以取得 NET_PACKET_CHECKSUM 結構。

  2. 用戶端驅動程式會測試NET_PACKET_CHECKSUM結構中的圖層特定旗標。

    • 如果旗標是 NetPacketTxChecksumActionPassthrough,則 NIC 不應該在該層中執行總和檢查碼作業。

    • 如果旗標是 NetPacketTxChecksumActionRequired,則用戶端驅動程序應該使用 NET_PACKET_LAYOUT 結構,判斷該特定封包中該層所使用的通訊協定,並向 NIC 指出它應該計算封包的總和檢查碼。

  3. 用戶端驅動程式會將封包傳遞至 NIC,以計算封包的適當總和檢查碼。

接收總和檢查碼處理

在指示執行總和檢查碼工作的接收封包 NET_PACKET 結構之前,用戶端驅動程式會驗證總和檢查碼,並在 NET_PACKET_CHECKSUM 結構中設定適當的旗標。

旗標可以是下列其中一項:

描述
NetPacketRxChecksumEvaluationNotChecked NIC 無法驗證封包的總和檢查碼
NetPacketRxChecksumEvaluationValid 封包總和檢查碼有效
NetPacketRxChecksumEvaluationInvalid 封包總和檢查碼無效