windows网络适配器驱动开发-网络数据缓冲区管理

windows网络适配器驱动开发-网络数据缓冲区管理
缓冲区管理是一项功能它使网络接口卡 (NIC) 客户端驱动程序和操作系统在从系统内存为发送 (Tx) 和接收 (Rx) 数据路径分配数据包缓冲区时能够协同工作。 这可以提高 NIC 的性能简化 NIC 客户端驱动程序的内存生命周期管理同时增强系统对内存的控制。NetAdapterCx 中缓冲区管理的优点选择从系统内存中为数据包有效负载分配数据缓冲区的位置对数据路径的性能至关重要。 在 NetAdapterCx 中缓冲区管理模型针对支持 DMA 的 NIC 硬件进行了优化客户端驱动程序利用该模型的最佳方式是让系统代表它们为 Tx 和 Rx 路径分配数据缓冲区。 但是客户端驱动程序仍可影响系统分配数据缓冲区的位置和方式以便客户端硬件能轻松使用这些缓冲区。以具有 DMA 功能的典型网卡为例。 这种方法有几个好处数据缓冲区由系统分配和释放。 因此客户端驱动程序可以摆脱内存生命周期管理的负担。系统会根据客户端驱动程序声明的功能确保分配的数据缓冲区已为 NIC 硬件准备好 DMA。 然后客户端驱动程序只需将数据缓冲区按原样编程到硬件中而无需执行任何额外的 DMA 映射操作。在分配数据缓冲区时系统可以考虑上层应用程序的需求从而决定优化全局端到端性能而不是只优化本地端到端性能。对于不支持 DMA 的 NIC如基于 USB 的网络硬件保护装置或其他高级/软件 NIC缓冲区管理模式还提供了一个选项即完全由客户端驱动程序来管理数据缓冲区。如何利用缓冲区管理如果硬件支持 DMA则需要在设置 Rx 和 Tx 功能之前创建一个 WDFDMAENABLER 对象。 使用 WDF_DMA_ENABLER_CONFIG 结构来配置 WDFDMAENABLER 对象时请确保将 WdmDmaVersionOverride 成员设置为 3以指定 DMA 版本 3。要选择缓冲区管理请按照以下步骤操作启动网络适配器时要在调用 NetAdapterStart 之前使用 NET_ADAPTER_RX_CAPABILITIES 和 NET_ADAPTER_TX_CAPABILITIES 数据结构分别告诉系统有关 Rx 和 Tx 路径的硬件数据缓冲区功能和限制。调用其中一个初始化函数以便初始化两个功能结构。 例如支持 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 adapters datapath capabilities NetAdapterSetDatapathCapabilities(Adapter, txCapabilities, rxCapabilities); }