パケットの記述子と拡張機能
NetAdapterCx では、パケット記述子 は、ネットワーク パケットを記述する、小型で、コンパクトな、実行時に拡張可能な構造体です。 各パケットには次のものが必要です。
- 1 つのコア記述子
- 1 つ以上のフラグメント記述
- 0 個以上のパケット拡張
パケットのコア記述子は、NET_PACKET構造体です。 これには、特定のパケットのフレーミング レイアウトやパケットの最初のフラグメント記述子へのインデックスなど、すべてのパケットに適用できる、最も基本的なメタデータのみが含まれます。
また、各パケットには、パケット データが存在するシステム メモリ内の場所を記述する 1 つ以上の フラグメント記述子 (NET_FRAGMENT) 構造体が必要です。
拡張機能 は、オプションであり、シナリオ固有の機能のパケット単位またはフラグメント単位のメタデータを保持します。 たとえば、パケット拡張機能は、チェックサム、大量送信オフロード (LSO)、受信セグメント合体 (RSC) のオフロード情報を保持したり、アプリケーション固有の詳細を保持したりできます。 フラグメント拡張機能は、仮想アドレス情報、論理 DMA アドレス情報、フラグメントのその他の情報を保持できます。
これらの記述子と拡張機能は、ネットワーク パケットに関するすべてのメタデータを保持します。 次に、パケットの記述方法の例を 2 つ示します。 最初の図は、パケット全体が 1 つのメモリ フラグメント内に格納されており、チェックサム オフロードがオンになっているシナリオを示しています。
2 番目の図は、RSC とチェックサム オフロードの両方が有効になっている 2 つのメモリ フラグメントに格納されたパケットを示しています。
パケット記述子の保存とアクセス
パケット記述子とフラグメント記述子は、どちらも NET_RING 構造体に格納されます。 NIC クライアント ドライバーは、ネット リングにアクセスし、ドライバーが NetAdapterCx と連携してネットワーク データをハードウェアに投稿し、完了したデータを OS にドレインできるようにするネット リング反復子インターフェイスを呼び出すことによって、ネット リングに対して操作を実行します。
ネット リングとネット リング イテレータ インターフェイスの詳細については、ネット リングの概要 を参照してください。
パケット記述子の拡張性
拡張性は、NetAdapterCx パケット記述子のコア機能であり、記述子のバージョン管理とパフォーマンスの基盤を形成します。 実行時に、オペレーティング システムは、連続したブロック内の各パケット キューのすべてのパケット記述子を、使用可能な拡張機能と共に割り当てます。 各拡張ブロックは、次の図に示すように、コア記述子のすぐ後ろにあります。
NIC クライアント ドライバーは、オフセットを拡張ブロックにハードコーディングすることはできません。 代わりに、実行時に特定の拡張機能へのオフセットを照会する必要があります。 たとえば、ドライバーは拡張機能 B へのオフセットを照会し、次の図のように 70 バイトを返す場合があります。
パケット キューとその記述子が作成されると、すべての拡張オフセットがシステムによって一定であることが保証されるため、ドライバーが、オフセットを頻繁に再クエリする必要がありません。 さらに、すべての拡張は、パケット キューの初期化時にシステムによってブロックに事前に割り当てられるため、ブロックの実行時の割り当て、特定の記述子のリストの検索、すべてのパケット拡張へのポインターを含める必要ありません。
パケット記述子のバージョン管理可能性
NetAdapterCx のコア パケット記述子は、次の図のように末尾に新しいフィールドを追加することで、将来のリリースで簡単に拡張できます。
V2 フィールドを認識している新しいクライアント ドライバーはそれらにアクセスできますが、古い V1 専用ドライバーは、拡張オフセットを使用して、V2 フィールドをスキップし、理解しているフィールドにアクセスできます。 さらに、次の図に示すように、各拡張機能は、同じ方法でバージョン管理できます。
新しい拡張機能を理解しているクライアント ドライバーが、それを使用することができます。 他のクライアント ドライバーは、新しいフィールドをスキップできます。 これにより、パケット記述子のさまざまな部分を、個別にバージョン管理することができます。
パケット記述子とデータパスのパフォーマンス
前に概説した拡張機能には、クライアント ドライバーが、数千のキューを持つ数百ギガビット/秒の容量を持つ NIC のパフォーマンス要件を満たすのに役立つという利点があります。
- パケット記述子は、使用されていない機能と拡張機能が記述子の 0 バイトの領域を占有するため、CPU キャッシュ ヒットを改善するために可能な限りコンパクトに保たれます。
- 拡張機能はインラインであるため、ポインターの逆参照はなく、オフセット演算のみが行われ、スペースを節約するだけでなく、CPU キャッシュのヒットにも役立ちます。
- 拡張機能はキューの作成時に割り当てられるため、ドライバーはアクティブ データ パスでメモリの割り当て・割り当て解除、コンテキスト ブロックのルックア サイド リストの処理を行う必要はありません。
パケット拡張の使用
重要
現在、クライアント ドライバーは、オペレーティング システムによって定義されている 既存のパケット拡張に制限されています。
パケット拡張の登録
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 は、既知のパケット拡張定数の定義を提供します。
定数 | Definition |
---|---|
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 | Large Send Offload (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 は、既知のフラグメント拡張定数の定義を提供します。
定数 | Definition |
---|---|
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 | 仮想アドレス フラグメント拡張機能の名前とバージョン。 |