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 傳輸檢查碼卸載,客戶端驅動程式:
呼叫 NET_ADAPTER_OFFLOAD_TX_CHECKSUM_CAPABILITIES_INIT 來初始化 結構。
呼叫 NetAdapterOffloadSetTxChecksumCapabilities 向 NetAdapterCx 註冊結構。
在呼叫 NET_ADAPTER_OFFLOAD_TX_CHECKSUM_CAPABILITIES_INIT 的過程中,客戶端驅動程序提供了指向 EVT_NET_ADAPTER_OFFLOAD_SET_TX_CHECKSUM 回呼的指標。 如果作用中的卸除功能變更,系統稍後會叫用此回呼。
若要設定接收 Rx 檢查碼卸載,客戶端驅動程式:
呼叫 NET_ADAPTER_OFFLOAD_RX_CHECKSUM_CAPABILITIES_INIT 以初始化該結構。
呼叫 ,將 NetAdapterOffloadSetRxChecksumCapabilities 註冊到 NetAdapterCx 中的結構。
在呼叫 NET_ADAPTER_OFFLOAD_RX_CHECKSUM_CAPABILITIES_INIT 時,客戶端驅動程序會提供指向 EVT_NET_ADAPTER_OFFLOAD_SET_RX_CHECKSUM 回呼的指標。 如果主動卸載功能變更,系統稍後會叫用此回呼。
指出硬體傳輸總和檢查碼功能的規則
Layer3Flags 必須設定在 NET_ADAPTER_OFFLOAD_TX_CHECKSUM_CAPABILITIES 結構中。 設定 Layer4Flags 是選擇性的。 設定 Layer3Flags 和 Layer4Flags 表示 NIC 能夠執行總和檢查碼卸除的封包。
NET_ADAPTER_OFFLOAD_TX_CHECKSUM_CAPABILITIES 中的 Layer3HeaderOffsetLimit 和 Layer4HeaderOffsetLimit 是選擇性的。 如果OS傳送標頭位移大於指定限制的封包,則不會要求 NIC 計算該層總和檢查碼。
如果支援選項/擴充功能,則必須支援不含選項/延伸模組的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_CHECKSUM 或 EVT_NET_ADAPTER_OFFLOAD_SET_RX_CHECKSUM 當網卡初始化期間已註冊的回呼。 在這些函式中,系統會在 NETOFFLOAD 物件中提供更新的功能,用戶端驅動程式會查詢以更新其卸載功能。
用戶端驅動程式可以呼叫下列函式,以判斷已啟用哪些檢查碼卸載:
- NetOffloadIsTxChecksumIPv4Enabled
- NetOffloadIsTxChecksumTcpEnabled
- NetOffloadIsTxChecksumUdpEnabled
- NetOffloadIsRxChecksumIPv4Enabled
- NetOffloadIsRxChecksumTcpEnabled
- NetOffloadIsRxChecksumUdpEnabled
下列範例示範用戶端驅動程式如何更新其 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);
}
傳輸總和檢查碼處理
用戶端驅動程式通常會在傳輸路徑上執行下列總和檢查碼處理:
用戶端驅動程式會使用封包索引呼叫 NetExtensionGetPacketChecksum 函式,以取得 NET_PACKET_CHECKSUM 結構。
用戶端驅動程式會測試NET_PACKET_CHECKSUM結構中的圖層特定旗標。
如果旗標是
NetPacketTxChecksumActionPassthrough
,則 NIC 不應該在該層中執行總和檢查碼作業。如果旗標是
NetPacketTxChecksumActionRequired
,則用戶端驅動程序應該使用 NET_PACKET_LAYOUT 結構,判斷該特定封包中該層所使用的通訊協定,並向 NIC 指出它應該計算封包的總和檢查碼。
用戶端驅動程式會將封包傳遞至 NIC,以計算封包的適當總和檢查碼。
接收總和檢查碼處理
在指示執行總和檢查碼工作的接收封包 NET_PACKET 結構之前,用戶端驅動程式會驗證總和檢查碼,並在 NET_PACKET_CHECKSUM 結構中設定適當的旗標。
旗標可以是下列其中一項:
旗 | 描述 |
---|---|
NetPacketRxChecksumEvaluationNotChecked |
NIC 無法驗證封包的總和檢查碼 |
NetPacketRxChecksumEvaluationValid |
封包總和檢查碼有效 |
NetPacketRxChecksumEvaluationInvalid |
封包總和檢查碼無效 |