網路數據緩衝區管理
緩衝區管理是一項功能,可讓網路適配器 (NIC) 用戶端驅動程式和作業系統在從系統記憶體配置封包數據緩衝區以用於傳輸 (Tx) 和接收 (Rx) 資料路徑時一起運作。 這可能會導致 NIC 的效能更快、NIC 用戶端驅動程式的記憶體留期管理更簡單,以及系統對記憶體的更多控制。
NetAdapterCx中的緩衝區管理優點
將數據緩衝區從系統記憶體配置給封包承載的位置,對於數據路徑的效能至關重要。 在 NetAdapterCx 中,緩衝區管理模型已針對支援 DMA 的 NIC 硬體進行優化,而用戶端驅動程式利用它的最佳方式是讓系統代表 Tx 和 Rx 路徑配置數據緩衝區。 不過,客戶端驅動程式仍然可以影響系統配置數據緩衝區的位置和方式,以便用戶端的硬體輕鬆取用它們。
例如,請考慮一般支援 DMA 的 NIC。 此方法有一個保留的優點:
- 系統會配置和釋放數據緩衝區。 因此,客戶端驅動程式會從記憶體留期管理的負擔中解脫。
- 系統會根據用戶端驅動程式所宣告的功能,確定已配置的數據緩衝區已針對 NIC 硬體備妥 DMA。 然後,客戶端驅動程式可以直接將數據緩衝區程序設計成其硬體,而不需要執行任何其他的 DMA 對應作業。
- 系統可以在配置數據緩衝區時考慮上層應用程式的需求,因此可以決定將全域端對端效能優化,而不只是本機端對端效能。
若為支援非 DMA 的 NIC,例如 USB 型網路加密機或其他進階/軟體 NIC,緩衝區管理模型也會提供讓數據緩衝區管理完全留給用戶端驅動程式的選項。
如何使用緩衝區管理
重要
如果您的硬體具備 DMA 功能,您必須先建立 WDFDMAENABLER 物件,才能設定 Rx 和 Tx 功能。 當您使用 WDF_DMA_ENABLER_CONFIG 結構設定 WDFDMAENABLER 物件時,請務必將 WdmDmaVersionOverride 成員設定為 3,以指定 DMA 第 3 版。
若要加入宣告緩衝區管理,請遵循下列步驟:
- 啟動您的網路適配器,但在呼叫 NetAdapterStart 之前,請分別使用 Rx 和 Tx 路徑的 NET_ADAPTER_RX_CAPABILITIES 和 NET_ADAPTER_TX_CAPABILITIES 數據結構,告訴系統硬體的數據緩衝區功能和條件約束。
- 呼叫其中一個初始化函式,以初始化兩個功能結構。 例如,支援 DMA 的 NIC 用戶端驅動程式會使用 NET_ADAPTER_TX_CAPABILITIES_INIT_FOR_DMA 和 NET_ADAPTER_RX_CAPABILITIES_INIT_SYSTEM_MANAGED_DMA 來宣告其硬體 DMA 上限,並指示系統代表其完全管理數據緩衝區。
- 將初始化的 Tx 和 Rx 功能結構傳遞至 NetAdapterSetDatapathCapabilities 方法。
範例
下列範例說明上一節概述的基本步驟,說明如何在 NIC 用戶端驅動程式中使用緩衝區管理員。 此範例會針對 Tx 和 Rx 使用 DMA,因此先前已建立儲存在其裝置內容空間中的 WDFDMAENABLER 物件。
請注意,此範例也會在初始化 Tx 和 Rx 功能結構之後,設定其片段緩衝區的一些提示。 NetAdapterCx 和通訊協定驅動程式可以使用這些提示來改善效能。
為了清楚起見,錯誤處理已排除在外。
VOID
MyAdapterSetDatapathCapabilities(
_In_ NETADAPTER Adapter
)
{
// Get the device context
PMY_DEVICE_CONTEXT deviceContext = GetMyContextFromDevice(Adapter);
// Set various capabilities such as link layer MTU size, link layer capabilities, and power capabilities
...
// Initialize the Tx DMA capabilities structure
NET_ADAPTER_DMA_CAPABILITIES txDmaCapabilities;
NET_ADAPTER_DMA_CAPABILITIES_INIT(&txDmaCapabilities,
deviceContext->dmaEnabler);
// Set Tx capabilities
NET_ADAPTER_TX_CAPABILITIES txCapabilities;
NET_ADAPTER_TX_CAPABILITIES_INIT_FOR_DMA(&txCapabilities,
&txDmaCapabilities,
1);
txCapabilities.FragmentRingNumberOfElementsHint = deviceContext->NumTransmitControlBlocks * MAX_PHYS_BUF_COUNT;
txCapabilities.MaximumNumberOfFragments = MAX_PHYS_BUF_COUNT;
// Initialize the Rx DMA capabilities structure
NET_ADAPTER_DMA_CAPABILITIES rxDmaCapabilities;
NET_ADAPTER_DMA_CAPABILITIES_INIT(&rxDmaCapabilities,
deviceContext->dmaEnabler);
// Set Rx capabilities
NET_ADAPTER_RX_CAPABILITIES rxCapabilities;
NET_ADAPTER_RX_CAPABILITIES_INIT_SYSTEM_MANAGED_DMA(&rxCapabilities,
&rxDmaCapabilities,
MAX_PACKET_SIZE + FRAME_CRC_SIZE + RSVD_BUF_SIZE,
1);
rxCapabilities.FragmentBufferAlignment = 64;
rxCapabilities.FragmentRingNumberOfElementsHint = deviceContext->NumReceiveBuffers;
// Set the adapter's datapath capabilities
NetAdapterSetDatapathCapabilities(Adapter,
&txCapabilities,
&rxCapabilities);
}