デバッガーの 2PF KDNET サポート

このトピックでは、2PF デバッガーのサポートのミニポート NDIS ドライバーを有効にして、データ センターでよく使用される高速アダプターのパフォーマンスを向上させる方法について説明します。 この機能は、Windows 11 以降で使用できます。

NIC でカーネル デバッグを有効にすると、カーネル デバッグ サポートが物理デバイスを引き継ぎ、カーネル デバッグとネットワーク接続の両方をボックスに提供します。 これは、コンシューマーの低帯域幅 NIC (1 から 10 Gbps) では正常に機能しますが、10 から 40+ + Gbps をサポートする高スループット デバイスでは、ハードウェアと通信するカーネル デバッグ拡張機能モジュールは、通常、Windows ネットワーク スタックからのトラフィック量に追いつくことができないため、システム全体のパフォーマンスが低下します。

KDNET の PCI 複数の物理機能 (PF) 機能を使用すると、パフォーマンスにほとんど影響を与えずにデバッグを有効にできます。

物理機能 (PF) は、単一ルート I/O 仮想化 (SR-IOV) インターフェイスをサポートするネットワーク アダプターの PCI Express (PCIe) 関数です。 PF には、PCIe 構成スペースに SR-IOV 拡張機能が含まれています。 この機能は、仮想化の有効化や PCIe Virtual Functions (VFs) の公開など、ネットワーク アダプターの SR-IOV 機能を構成および管理するために使用されます。

PF は、PCIe 構成スペースの SR-IOV 拡張機能構造をサポートしています。 この構造は、 PCI-SIG Single Root I/O Virtualization and Sharing 1.1 仕様で定義されています。

デバッガー トランスポートは、複数の 2PF 対応ミニポート ドライバーを利用します。 高速サーバーのシステムのデバッグを可能にするには、NIC ベンダーが、ネットワーク カード ファームウェアで複数の PF をサポートするすべての NIC で 2PF を有効にすることをお勧めします。

接続をテストするための 2PF サポートの構成については、KDNET を使用した 2PF カーネル・モード・デバッグのセットアップを参照してください

複数 PF KDNET アーキテクチャの概要

  • Multiple PF (2PF) 機能は、新しい PF を元の PCI ネットワーク ポート (Bus.dev.fun0.0 など) に追加/割り当てることです。

  • 新しく追加された PF (例: bus.dev.fun0.1) は、ターゲットとの間でデバッガー パケットをルーティングするために KDNET によってのみ使用されます。

  • 元の PF は、Windows ネットワーク パケット (TCP/IP) をルーティングするために Windows 受信トレイ NIC ドライバーによって使用されます。

  • このアプローチを使用すると、両方のドライバーが互いの作業に干渉することなく並行して動作できます。

  • どちらのドライバも、パーティション分割されたPCI構成空間上で実行されます

    • Windowsインボックスドライバは、bus.dev 時に元のネットワークポートを使い果たしますfun0.0

    • KDNET-KDNET-Ext. モジュールは、bus.dev.fun0.1 で追加 PF から実行されます。この技法を活用して、KDNET と NIC を共有し、Windows 受信トレイ NIC ドライバーが影響を受けないようにします。

  • kdnet.exe ユーザー モード ツールは、特定の IOCTL コードを追加して KDNET PF を追加/削除することで、Windows 受信トレイ ドライバーを使用して 2PF 機能を構成します。

Diagram that shows two network stacks, one supporting 2PF using a combined PCI card setup.

複数のPFは設計要件を備えています

  1. KDNET 2PF 機能は、NT より前の OS (ブート マネージャー、OS ローダー、WinResume、Hyper-V、SK など)、NT OS、Windows デスクトップのいずれであっても、現在のすべての KD シナリオで機能する必要があります。

  2. デバイスの新しい PF を追加すると、デバッグ設定のために BCD 構成の変更が必要になった場合は、システムの再起動が必要になります。 つまり、追加の PF の設定は、ブート後も永続的でなければなりません。

  3. KDNET 2PF は、デバッガーがデバッグ デバイスを所有している場合に、PCI 2PF の場所からアクセス/実行されている他の Windows/UEFI イーサネット ドライバーがないことを確認するために、デバッガーでのみ使用する必要があります (2PF の場所は dbgsettings::busparams を使用して構成されます)。

  4. Windows または UEFI イーサネット ドライバーは、システムで KDNET が有効になっていない場合でも、追加された KDNET 2PF を使い果たすことはできません。

  5. 2PF 機能は、現在の NIC の機能を追加/有効化および削除/無効化するための動的なメカニズムをサポートする必要があります。

  6. Windows ミニポート ドライバーは、次の NDIS OID をサービスを使用して 2PF 機能を実装します。

OID 名 説明
OID_KDNET_ENUMERATE_PFS ミニポート ドライバーが実行されている現在の bus.dev.fun (BDF) 上の GIF を列挙します。
OID_KDNET_ADD_PF ミニポート ドライバーが実行されている現在の BDF に PF を追加します。
OID_KDNET_REMOVE_PF 渡された BDF から追加された PF を削除します。
OID_KDNET_QUERY_PF_INFORMATION 渡された BDF から PF 情報データを照会します。

OID とその構造は、パブリック WDK と共にリリースされる ntddndis.h ファイルと kdnetpf.h ファイルで定義されます。

各OIDの入出力パラメータとkdnetpf.hヘッダー・ファイルで提供される情報については、以下の詳細を参照してください。

  1. KDNET は、複数の PF 機能が使用可能な NICS で KDNET 2PF 機能を使用して構成する必要があり、NIC は上記のすべての要件に従って 2PF 機能を有効にします。

Windows NIC ドライバー用の KDNET 複数 PF インターフェイス

KDNET をサポートするには、複数の PF インターフェイス ミニポート ドライバーで、次の 4 つの NDIS OID の処理を実装する必要があります。

  • OID_KDNET_ENUMERATE_PFS

  • OID_KDNET_ADD_PF

  • OID_KDNET_REMOVE_PF

  • OID_KDNET_QUERY_PF_INFORMATION

これらの OID と構造体は、次のパスのパブリック WDK リリースの ntddndis.h ファイルと kdnetpf.h ファイルに設定されます。

<WDK root directory>\ddk\inc\ndis

これらのファイルは Windows SDK でも使用でき、このディレクトリにあります。

\Program Files (x86)\Windows Kits\10\Include\<Version for example 10.0.21301.0>\shared

クライアント ツール (kdnet.exe) は、プライベート NDIS IOCTL を使用して、ミニポート ドライバーに KDNET 2PF NDIS OID をルーティングします。

複数の PF 機能 NDIS OID

複数 PF 機能は、これら 4 つの NDIS OID を使用して操作されます。

1. OID を使用してミニポート BDF プライマリ ポートの GIF を列挙する: OID_KDNET_ENUMERATE_PFS、以下の定義を参照してください。

  • OID_KDNET_ENUMERATE_PFSは、ミニポート ドライバーが実行されている特定のプライマリ ポートに関連付けられているすべての BDF の一覧を返します。 ポートは bus.dev.fun (BDF) で表されます。 この操作では、ミニポート ドライバーがシステム上で実行されている bus.dev.fun (BDF ポート) にのみ 関連付けられている UDF の一覧が一覧表示または列挙されます。これは、すべてのミニポート ドライバーがその BDF の場所を決定できるためです。

  • PF の一覧は、NDIS クエリ操作を介してクライアントに返されます。

  • OID_KDNET_ENUMERATE_PFS OID は、NDIS_KDNET_ENUMERATE_PFS構造体に関連付けられています。

  • OID_KDNET_ENUMERATE_PFS ドライバー ハンドラーは、型NDIS_KDNET_PF_ENUM_ELEMENTで記述された各 PF 要素を含む、PFs リストを含むバッファーを返します。

    PfNumber フィールドには、PF 関数番号が含まれています (例: bus.dev。楽しい)

    PfState フィールドには、PF 状態の可能な値 (列挙型によって記述される 各要素の型) NDIS_KDNET_PF_STATE 含まれます。

    NDIS_KDNET_PF_STATE::NdisKdNetPfStatePrimary - これはプライマリ PF であり、通常はミニポート ドライバーでのみ使用されます。

    NDIS_KDNET_PF_STATE::NdisKdnetPfStateEnabled - これは、KDNET によって使用される追加のセカンダリ PF です。

    NDIS_KDNET_PF_STATE::NdisKdnetPfStateConfigured - これは追加された PF ですが、追加/構成のみが行われ、使用されません。

  • PF リストの出力バッファー サイズが実際の PF リストを割り当てるのに十分な大きさでない場合、OID ハンドラーは、必要なバッファー サイズと共にエラー戻り値を返す E_NOT_SUFFICIENT_BUFFER 必要があります。そのため、クライアント ツールは必要なサイズ バッファーを割り当てることができ、クライアントは正しいバッファー サイズを割り当てて別の呼び出しを行うことができます。 さらに、OID 要求の状態フィールド (NDIS_IOCTL_OID_REQUEST_INFO.status で説明) を次のように設定する NDIS_STATUS_BUFFER_TOO_SHORT必要があります。

2. ミニポート BDF プライマリ ポートに PCI PF を追加する (OID: OID_KDNET_ADD_PF、以下の 定義を参照)

  • ミニポートのプライマリ ポートに PF を追加します。 ポートは BDF で表されます。

  • 新しく追加された PF は、NDIS クエリ操作を介してクライアントに返されます。

  • OID_KDNET_ADD_PF OID は、NDIS_KDNET_ADD_PF構造体に関連付けられています。

  • OID_KDNET_ADD_PF ドライバー ハンドラーは、追加された PF 関数番号を含む ULONG を返します。

  • この OID 要求には、出力パラメーターが 1 つだけ含まれます AddedFunctionNumber。 ミニポート AddedFunctionNumber PCI の場所に追加された関数番号の値を示します (BDF ミニポート)。 kdnet.exe ユーティリティはこの値を受け取り、追加された PF を指すように dbgsettings::busparams を設定します。

Note

追加された PF は KDNET によって排他的に使用できるため、Windows NIC ドライバーは追加された PF で明示的に *NOT* 実行されるようにトリガーされるため、システムで KDNET が *NOT* 有効になっていて、PF がポートに追加されている場合にも適用されます。

3. PCI PF を削除する (OID: OID_KDNET_REMOVE_PF、以下の定義を参照)

  • 指定されたポートから PF を 削除します。 ポートは BDF で表されます。

  • OID_KDNET_REMOVE_PF OID は、NDIS_KDNET_REMOVE_PF構造体に関連付けられています。

  • OID_KDNET_REMOVE_PF OID には入力 BDF ポートがあり、NDIS メソッド操作を介して削除された PF 関数番号を含む ULONG を返します。

  • この関数は、OID_KDNET_ADD_PF OID を使用して追加された CF でのみ成功します。

  • この OID 要求には、BDF を削除する必要がある入力 BDF ポートがあります。 この関数の Output パラメーターは次のとおりです FunctionNumber。 出力 FunctionNumber には、削除された関数番号の値が含まれます。

4. PCI PF 情報のクエリ (OID: OID_KDNET_QUERY_PF_INFORMATION、以下の定義を参照)

  • この OID コードを使用すると、特定のポートで特定の PF データに対してクエリを 実行できます。 ポートは BDF で表されます。

  • 要求された PF 情報は、NDIS メソッド操作を介してクライアントに返されます。

  • OID_KDNET_QUERY_PF_INFORMATION OID は、NDIS_KDNET_QUERY_PF_INFORMATION構造体に関連付けられています。

  • OID_KDNET_QUERY_PF_INFORMATION OID には入力 BDF ポートがあり、次のデータを含むバッファーが返されます。

    • MAC アドレス: 割り当てられた新しい KDNET PF のネットワーク アドレス (存在する場合)。

    • 使用タグ: PF ポートを所有するエンティティーを記述します。 これには、列挙型によって記述された 定数値NDIS_KDNET_PF_USAGE_TAG 含まれています。

    • PF の最大数: 指定された BDF に追加できる PF の最大数を含む ULONG が含まれます。

    • デバイス ID: 特定の BDF ポートに関連付けられているデバイス ID が含まれます。 これは、NIC FW が新しく追加された KDNET PF ポートに新しいデバイス ID を割り当てる場合に必要です。

  • この OID は、渡された BDF ポートの情報を要求します (BDF はこの操作の入力パラメーターです)。そのため、ドライバーが実行されている現在の BDF に必ずしも関連しているわけではありません

2PF 上の KDNET 用 NDIS OID

Ntddndis.h ファイルは OID を定義します。

#if (NDIS_SUPPORT_NDIS686)

 //

 // Optional OIDs to handle network multiple PF feature.

 //
#define OID_KDNET_ENUMERATE_PFS 0x00020222
#define OID_KDNET_ADD_PF 0x00020223
#define OID_KDNET_REMOVE_PF 0x00020224
#define OID_KDNET_QUERY_PF_INFORMATION 0x00020225
#endif // (NDIS_SUPPORT_NDIS686)

Kdnetpf.h ファイルは、NDIS OID に関連付けられている型と構造体を記述します。

#if (NDIS_SUPPORT_NDIS686)

 //
 // Used to query/add/remove Physical function on a network port.
 // These structures are used by these OIDs:
 // OID_KDNET_ENUMERATE_PFS
 // OID_KDNET_ADD_PF
 // OID_KDNET_REMOVE_PF
 // OID_KDNET_QUERY_PF_INFORMATION
 // These OIDs handle PFs that are primary intended to be used by  KDNET.
 //
 //
 // PCI location of the port to query
 //
 typedef struct _NDIS_KDNET_BDF
 {
 ULONG SegmentNumber;
 ULONG BusNumber;
 ULONG DeviceNumber;
 ULONG FunctionNumber;
 ULONG Reserved;
 } NDIS_KDNET_BDF, *PNDIS_KDNET_PCI_BDF;

 //
 // PF supported states.
 //
 typedef enum _NDIS_KDNET_PF_STATE
 {
 NdisKdNetPfStatePrimary = 0x0,
 NdisKdnetPfStateEnabled = 0x1,
 NdisKdnetPfStateConfigured = 0x2,
 } NDIS_KDNET_PF_STATE,*PNDIS_KDNET_PF_STATE;

 //
 // PF Usage Tag
 // Used to indicate the entity that owns the PF.
 // Used by the query NdisKdnetQueryUsageTag.
 //
 typedef enum _NDIS_KDNET_PF_USAGE_TAG
 {
 NdisKdnetPfUsageUnknown = 0x0,
 NdisKdnetPfUsageKdModule = 0x1,
 } NDIS_KDNET_PF_USAGE_TAG,*PNDIS_KDNET_PF_USAGE_TAG;

 //
 // PF element array structure
 //
 typedef struct _NDIS_KDNET_PF_ENUM_ELEMENT
 {
 NDIS_OBJECT_HEADER Header;

 //
 // PF value (e.g. if <bus.dev.fun>, then PF value = fun)
 //
 ULONG PfNumber;

 //
 // The PF state value (defined by NDIS_KDNET_PF_STATE)
 //
 NDIS_KDNET_PF_STATE PfState;

 } NDIS_KDNET_PF_ENUM_ELEMENT, *PNDIS_KDNET_PF_ENUM_ELEMENT;
#define NDIS_KDNET_PF_ENUM_ELEMENT_REVISION_1 1
#define NDIS_SIZEOF_KDNET_PF_ENUM_ELEMENT_REVISION_1 \
 RTL_SIZEOF_THROUGH_FIELD(NDIS_KDNET_PF_ENUM_ELEMENT, PfState)

 //
 // This structure describes the data required to enumerate the list of PF
 // Used by OID_KDNET_ENUMERATE_PFS.
 //
 typedef struct _NDIS_KDNET_ENUMERATE_PFS
 {
 NDIS_OBJECT_HEADER Header;

 //
 // The size of each element is the sizeof(NDIS_KDNET_PF_ENUM_ELEMENT)
 //
 ULONG ElementSize;

 //
 // The number of elements in the returned array
 //
 ULONG NumberOfElements;

 //
 // Offset value to the first element of the returned array.
 // Each array element is defined by NDIS_KDNET_PF_ENUM_ELEMENT.
 //
 ULONG OffsetToFirstElement;
 } NDIS_KDNET_ENUMERATE_PFS, *PNDIS_KDNET_ENUMERATE_PFS;

#define NDIS_KDNET_ENUMERATE_PFS_REVISION_1 1
#define NDIS_SIZEOF_KDNET_ENUMERATE_PFS_REVISION_1 \
 RTL_SIZEOF_THROUGH_FIELD(NDIS_KDNET_ENUMERATE_PFS,
 OffsetToFirstElement)

 //
 // This structure indicates the data required to add a PF to the BDF port.
 // Used by OID_KDNET_ADD_PF.
 //
 typedef struct _NDIS_KDNET_ADD_PF
 {
 NDIS_OBJECT_HEADER Header;

 //
 // One element containing the added PF port number
 //
 ULONG AddedFunctionNumber;
 } NDIS_KDNET_ADD_PF, *PNDIS_KDNET_ADD_PF;

#define NDIS_KDNET_ADD_PF_REVISION_1 1
#define NDIS_SIZEOF_KDNET_ADD_PF_REVISION_1 \
 RTL_SIZEOF_THROUGH_FIELD(NDIS_KDNET_ADD_PF, AddedFunctionNumber)

 //
 // This structure indicates the data required to remove a PF from the BDF port.
 // Used by OID_KDNET_REMOVE_PF.
 //

 typedef struct _NDIS_KDNET_REMOVE_PF
 {
 NDIS_OBJECT_HEADER Header;

 //
 // PCI location that points to the PF that needs to be removed
 //
 NDIS_KDNET_BDF Bdf;

 //
 // One element containing the removed PF port
 //
 ULONG FunctionNumber;
 } NDIS_KDNET_REMOVE_PF, *PNDIS_KDNET_REMOVE_PF;
#define NDIS_KDNET_REMOVE_PF_REVISION_1 1
#define NDIS_SIZEOF_KDNET_REMOVE_PF_REVISION_1 \
 RTL_SIZEOF_THROUGH_FIELD(NDIS_KDNET_REMOVE_PF, FunctionNumber)

 //
 // This structure describes the data required to query the PF management data
 // Used by OID_KDNET_QUERY_PF_INFORMATION
 //
 typedef struct _NDIS_KDNET_QUERY_PF_INFORMATION
 {
 NDIS_OBJECT_HEADER Header;

 //
 // PF PCI location to query for
 //
 NDIS_KDNET_BDF Bdf;

 //
 // PF assigned MAC address
 //
 UCHAR NetworkAdddress[6];

 //
 // PF Usage tag described by NDIS_KDNET_PF_USAGE_TAG
 //
 ULONG UsageTag;

 //
 // Maximum number of Pfs that can be associated to the Primary BDF.
 //
 ULONG MaximumNumberOfSupportedPfs;

 //
 // KDNET PF device ID (Used if there is a new added PF and
 // the FW assigns a new DeviceID to the added KDNET PF)
 //
 ULONG DeviceId;

 } NDIS_KDNET_QUERY_PF_INFORMATION, *PNDIS_KDNET_QUERY_PF_INFORMATION;
#define NDIS_KDNET_QUERY_PF_INFORMATION_REVISION_1 1
#define NDIS_SIZEOF_KDNET_QUERY_PF_INFORMATION_REVISION_1 \
 RTL_SIZEOF_THROUGH_FIELD(NDIS_KDNET_QUERY_PF_INFORMATION, DeviceId)

#endif // (NDIS_SUPPORT_NDIS686)

関連項目

KDNET を使用した 2PF カーネルモード デバッグの設定

ネットワーク OID

kdnetpf.h ヘッダー