ネットワーク データ バッファーの管理

バッファー管理は、ネットワーク インターフェイス カード (NIC) クライアント ドライバーとオペレーティング システムが連携して、送信 (Tx) および受信 (Rx) データ パスに、システム メモリからパケット データ バッファーを割り当てるときに機能です。 これにより、NIC のパフォーマンスが向上し、NIC のクライアント ドライバーのメモリ有効期間管理が容易になり、メモリに対するシステムの制御が強化されます。

NetAdapterCx のバッファー管理の利点

パケット ペイロードのシステム メモリからデータ バッファーを割り当てる場所の選択は、データ パスのパフォーマンスにとって重要です。 NetAdapterCx では、バッファー管理モデルは、DMA 対応の NIC ハードウェア用に最適化されており、クライアント ドライバーがそれを利用する最善の方法は、システムが Tx パスと Rx パスの両方にデータ バッファーを割り当てることです。 ただし、クライアント ドライバーは、システムがデータ バッファーを割り当てる場所と方法に影響を与える可能性があるため、クライアントのハードウェアで簡単に使用できます。

たとえば、一般的な DMA 対応 NIC について考えてみます。 このアプローチには、サーバルの利点があります。

  1. データ バッファーは、システムによって割り振られ、解放されます。 したがって、クライアント ドライバーは、メモリの有効期間管理の負担から解放されます。
  2. システムは、割り当てられたデータ バッファーが、クライアント ドライバーによって宣言された機能に基づいて NIC ハードウェアに対して DMA 対応であることを確認します。 その後、クライアント ドライバーは追加の DMA マッピング操作を実行することなく、データ バッファーをそのままハードウェアにプログラムできます。
  3. システムは、データ バッファーを割り当てる際に、上位層アプリケーションのニーズを考慮できるため、システムは、ローカルの、エンド ツー エンドのパフォーマンスだけでなく、グローバルなエンド ツー エンドのパフォーマンスに最適化することを決定できます。

USB ベースのネットワーク ドングルなどの DMA 非対応 NIC の場合、またはその他の高度なソフトウェア NIC の場合、バッファー管理モデルには、データ バッファー管理を完全にクライアント ドライバーに任せるオプションも用意されています。

バッファー管理の活用方法

重要

ハードウェアが DMA 対応の場合は、Rx および Tx 機能を設定する前に WDFDMAENABLER オブジェクトを作成する必要があります。 WDF_DMA_ENABLER_CONFIG 構造体を使用して WDFDMAENABLER オブジェクトを構成する場合は、DMA バージョン 3 を指定するために、WdmDmaVersionOverride メンバーを 3 に設定してください。

バッファー管理にオプトインするには、次の手順を実行します。

  1. ネット アダプターを起動するとき、ただし、NetAdapterStart を呼び出す前に、Rx パスと Tx パスにそれぞれ NET_ADAPTER_RX_CAPABILITIESNET_ADAPTER_TX_CAPABILITIES データ構造を使用して、ハードウェアのデータ バッファー機能と制約についてシステムに通知します。
  2. 初期化関数の 1 つを呼び出して、2 つの機能構造体を初期化します。 たとえば、DMA 対応の NIC クライアント ドライバーは、NET_ADAPTER_TX_CAPABILITIES_INIT_FOR_DMANET_ADAPTER_RX_CAPABILITIES_INIT_SYSTEM_MANAGED_DMA を使用して、ハードウェア DMA 機能を宣言し、代わりに、データ バッファーを完全に管理するようにシステムに指示します。
  3. 初期化された 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);
}