パケットの記述子と拡張機能

NetAdapterCx では、 パケット記述子 は、ネットワーク パケットを記述する小規模でコンパクトなランタイム拡張可能な構造体です。 各パケットには次のものが必要です。

  • 1 つのコア記述子
  • 1 つ以上のフラグメント記述子
  • 0 個以上のパケット拡張

パケットの コア記述子、NET_PACKET 構造体です。 指定されたパケットのフレーミング レイアウトや、パケットの最初のフラグメント記述子へのインデックスなど、すべてのパケットに適用できる最も基本的なメタデータのみが含まれます。

各パケットには、パケット データが存在するシステム メモリ内の場所を記述する 1 つ以上の フラグメント記述子 ( NET_FRAGMENT 構造体) も必要です。

拡張機能 はオプションであり、シナリオ固有の機能のパケット単位またはフラグメントごとのメタデータを保持します。 たとえば、パケット拡張機能はチェックサム、大規模送信オフロード (LSO)、受信セグメント結合 (RSC) のオフロード情報を保持したり、アプリケーション固有の詳細を保持したりできます。 フラグメント拡張機能は、仮想アドレス情報、論理 DMA アドレス情報、またはその他のフラグメントの情報を保持できます。

これらの記述子と拡張機能は一緒に、ネットワーク パケットに関するすべてのメタデータを保持します。 パケットを記述する方法の 2 つの例を次に示します。 最初の図は、パケット全体が 1 つのメモリ フラグメント内に格納され、チェックサム オフロードがオンになっているシナリオを示しています。

1 fragment packet layout.

2 番目の図は、RSC とチェックサム オフロードの両方が有効になっている 2 つのメモリ フラグメントに格納されているパケットを示しています。

2 fragments packet layout.

パケット記述子のストレージとアクセス

パケット記述子とフラグメント記述子は、どちらも NET_RING 構造体に格納されます。 NIC クライアント ドライバーは、ネット リングにアクセスし、Net リング反復子インターフェイスを呼び出すことによって操作を実行します。これにより、ドライバーは NetAdapterCx を使用してネットワーク データをハードウェアにポストし、完成したデータを OS にドレインできます。

ネット リングと Net リング反復子インターフェイスの詳細については、「 ネット リングの概要」を参照してください。

パケット記述子の拡張性

拡張性は、NetAdapterCx パケット記述子のコア機能であり、記述子のバージョン管理とパフォーマンスの基礎を形成します。 実行時に、オペレーティング システムは、使用できる拡張機能と共に、連続したブロック内の各パケット キューのすべてのパケット記述子を割り当てます。 次の図に示すように、各拡張ブロックはコア記述子のすぐ後ろにあります。

NetAdapterCx packet descriptor layout.

NIC クライアント ドライバーは、任意の拡張ブロックにオフセットをハードコーディングすることはできません。 代わりに、実行時に特定の拡張機能へのオフセットを照会する必要があります。 たとえば、ドライバーは拡張 B へのオフセットを照会し、次の図のように 70 バイトを返す場合があります。

Querying the offset to an extension of the core packet descriptor.

パケット キューとその記述子が作成されると、その拡張オフセットはすべてシステムによって一定であることが保証されるため、ドライバーはオフセットを頻繁に再クエリする必要はありません。 さらに、すべての拡張機能は、パケット キューの初期化時にブロック内のシステムによって事前に割り当てられるため、ブロックのランタイム割り当て、特定の記述子の一覧の検索、またはすべてのパケット拡張機能へのポインターの格納は必要ありません。

パケット記述子のバージョン管理

NetAdapterCx のコア パケット記述子は、次の図のように、新しいフィールドを末尾に追加することで、将来のリリースで簡単に拡張できます。

NetAdapterCx core packet descriptor versioning.

V2 フィールドを知っている新しいクライアント ドライバーはそれらにアクセスできますが、以前の V1 のみのドライバーは拡張オフセットを使用して V2 フィールドをスキップし、理解しているフィールドにアクセスできるようにします。 さらに、次の図に示すように、各拡張機能は同じ方法でバージョン管理できます。

NetAdapterCx packet extension versioning.

新しい拡張機能を理解しているクライアント ドライバーは、それを使用できます。 他のクライアント ドライバーでは、新しいフィールドをスキップできます。 これにより、パケット記述子のさまざまな部分を個別にバージョン管理できます。

パケット記述子とデータパスのパフォーマンス

前に説明した拡張性機能は、クライアント ドライバーが数百ギガビット/秒の数百のキューを備えた NIC のパフォーマンス要件を満たすのに役立つ利点を提供します。

  1. パケット記述子は、CPU キャッシュ ヒットを改善するためにできるだけコンパクトに保たれます。使用されていない機能と拡張機能は記述子の 0 バイトの領域を占有するためです。
  2. ポインターの逆参照はなく、オフセット算術演算のみが行われます。拡張はインラインであるため、スペースを節約するだけでなく、CPU キャッシュ ヒットにも役立ちます。
  3. 拡張機能はキュー作成時に割り当てられるため、ドライバーはアクティブなデータ パスにメモリを割り当てて割り当て解除したり、コンテキスト ブロックのルックアサイド リストを処理したりする必要はありません。

パケット拡張機能の使用

重要

現在、クライアント ドライバーは、 オペレーティング システムによって定義されている既存のパケット拡張機能に制限されています。

パケット拡張機能の登録

NIC クライアント ドライバーでパケット拡張機能を操作する最初の手順は、サポートされているハードウェア オフロードを宣言することです。 チェックサムや LSO などのオフロードのサポートをアドバタイズすると、NetAdapterCx によって、関連付けられているパケット拡張機能が自動的に登録されます。

ハードウェア オフロードのアドバタイズのコード例については、「 ハードウェア オフロードの概要」を参照してください。

データパス キューのパケット拡張オフセットのクエリ

ハードウェア オフロード サポートを宣言してパケット拡張機能を登録した後、パケットを処理するときに、それぞれにアクセスするための拡張オフセットが必要になります。 ドライバーからの呼び出しを減らし、パフォーマンスを向上させるには、 EvtNetAdapterCreateTx(Rx)Queue コールバック関数中に拡張機能のオフセットを照会し、オフセット情報をキュー コンテキストに格納します。

拡張オフセットの照会とキュー コンテキストへの格納の例については、「キューの 送受信」を参照してください。

実行時にパケット拡張機能を取得する

キュー コンテキストに拡張オフセットを格納したら、拡張機能に情報が必要なときにいつでも使用できます。 たとえば、送信キューのハードウェアに記述子をプログラムするときに 、NetExtensionGetPacketChecksum メソッドを呼び出します。

    // Get the extension offset from the device context
    PMY_TX_QUEUE_CONTEXT queueContext = GetMyTxQueueContext(txQueue);
    NET_EXTENSION checksumExtension = queueContext->ChecksumExtension;

    // Get the checksum info for this packet
    NET_PACKET_CHECKSUM* checksumInfo = NetExtensionGetPacketChecksum(checksumExtension, packetIndex);

    // Do work with the checksum info
    if (packet->Layout.Layer3Type == NET_PACKET_LAYER3_TYPE_IPV4_NO_OPTIONS ||
        packet->Layout.Layer3Type == NET_PACKET_LAYER3_TYPE_IPV4_WITH_OPTIONS ||
        packet->Layout.Layer3Type == NET_PACKET_LAYER3_TYPE_IPV4_UNSPECIFIED_OPTIONS)
    {
        if(checksumInfo->Layer4 == NET_PACKET_TX_CHECKSUM_REQUIRED)
        {
            ...
        }
    }
    ...

定義済みのパケット拡張定数とヘルパー メソッド

NetAdapterCx は、既知のパケット拡張定数の定義を提供します。

定数 定義
NET_PACKET_EXTENSION_INVALID_OFFSET 無効なオフセット サイズから保護します。
NET_PACKET_EXTENSION_CHECKSUM_NAME NET_PACKET_EXTENSION_CHECKSUM_VERSION_1 チェックサム パケット拡張機能の名前とバージョン。
NET_PACKET_EXTENSION_LSO_NAME NET_PACKET_EXTENSION_LSO_VERSION_1 LSO (LSO) パケット拡張の名前とバージョン。
NET_PACKET_EXTENSION_RSC_NAME NET_PACKET_EXTENSION_RSC_VERSION_1 受信セグメント結合 (RSC) パケット拡張の名前とバージョン。

さらに、NetAdapterCx には、 NetExtensionGetData メソッドのラッパーとして機能するヘルパー メソッドが用意されています。 これらの各メソッドは、適切な型の構造体へのポインターを返します。

メソッド 構造体
NetExtensionGetPacketChecksum NET_PACKET_CHECKSUM
NetExtensionGetGso NET_PACKET_GSO
NetExtensionGetPacketRsc NET_PACKET_RSC

フラグメント拡張の使用

重要

現在、クライアント ドライバーは、オペレーティング システムによって定義されている既存のフラグメント拡張機能に制限されています。

フラグメント拡張機能の登録

NetAdapterCx は、ドライバーの表現された機能を解釈することによって、ほとんどのフラグメント拡張機能を自動的に登録します。 たとえば、ドライバーが DMA をサポートしていることを示している場合、フレームワークは DMA プログラミングに必要なNET_FRAGMENT_LOGICAL_ADDRESS拡張機能を自動的に追加します。

データパス キューのフラグメント拡張オフセットのクエリ

フラグメント拡張にアクセスするには、「 データパス キューのパケット拡張オフセットのクエリ」で説明されているパケット拡張機能にアクセスする場合と同じプロセスに従います。

定義済みのフラグメント拡張定数

NetAdapterCx は、既知のフラグメント拡張定数の定義を提供します。

定数 定義
NET_FRAGMENT_EXTENSION_DATA_BUFFER_NAME NET_FRAGMENT_EXTENSION_DATA_BUFFER_VERSION_1 データ バッファー フラグメント拡張機能の名前とバージョン。
NET_FRAGMENT_EXTENSION_LOGICAL_ADDRESS_NAME NET_FRAGMENT_EXTENSION_LOGICAL_ADDRESS_VERSION_1 論理アドレス フラグメント拡張の名前とバージョン。
NET_FRAGMENT_EXTENSION_MDL_NAME NET_FRAGMENT_EXTENSION_MDL_VERSION_1 MDL フラグメント拡張機能の名前とバージョン。
NET_FRAGMENT_EXTENSION_RETURN_CONTEXT_NAME NET_FRAGMENT_EXTENSION_RETURN_CONTEXT_VERSION_1 戻りコンテキスト フラグメント拡張の名前とバージョン。
NET_FRAGMENT_EXTENSION_VIRTUAL_ADDRESS_NAME NET_FRAGMENT_EXTENSION_VIRTUAL_ADDRESS_VERSION_1 仮想アドレス フラグメント拡張機能の名前とバージョン。