共用方式為


調試程式 2PF KDNET 支援

本主題描述如何啟用迷你埠 NDIS 驅動程式,以支援 2PF 調試程式,以允許高速適配卡的效能提升,通常用於數據中心。 這項功能適用於 Windows 11 和更新版本。

在網路介面卡上啟用核心偵錯功能時,核心偵錯支援會掌控實體裝置,提供系統的核心偵錯和網路連線功能。 這適用於取用者低頻寬 NIC (1-10 Gbps),但在支援 10-40+ Gbps 的高輸送量裝置上,與硬體通訊的核心偵錯擴充性模組通常無法跟上來自 Windows 網路堆疊的流量量,因此這會降低整體系統效能。

針對 KDNET 使用 PCI 多重實體函式 (PF) 功能可讓偵錯啟用,幾乎不會影響效能。

實體函式 (PF) 是網路適配器的 PCI Express (PCIe) 函式,可支援單一根 I/O 虛擬化 (SR-IOV) 介面。 PF 在 PCIe 設定空間中包含 SR-IOV 擴展功能。 此功能可用來設定和管理網路適配器的 SR-IOV 功能,例如啟用虛擬化和公開PCIe虛擬函式 (VFs)。

PF 在其 PCIe 設定空間中支援 SR-IOV 擴充功能結構。 此結構定義於 PCI-SIG 單根 I/O 虛擬化與共用 1.1 規格中。

偵錯工具傳輸將利用啟用了多重或 2PF 的迷你端口驅動程式。 若要允許對高速伺服器系統進行偵錯,建議 NIC 廠商在所有支援多個 PF 的網路卡韌體中啟用 2PF。

如需設定 2PF 支援以測試連線的資訊,請參閱 使用 KDNET設定 2PF Kernel-Mode 偵錯。

多重 PF KDNET 架構總覽

  • 多重 PF (2PF) 功能是將新的 PF 新增/指派給原始 PCI 網路埠(例如 Bus.dev.fun0.0)。

  • 新增的 PF(如 bus.dev.fun0.1)僅被 KDNET 用於將調試器封包路由至目標或從目標返回。

  • Windows 收件匣 NIC 驅動程式將使用原始 PF 來路由傳送 Windows 網络封包 (TCP/IP) 。

  • 使用此方法,這兩個驅動程式可以平行運作,而不干擾彼此的工作。

  • 這兩個驅動程式都會在分割的PCI設定空間上執行

    • Windows Inbox 驅動程式將從 bus.dev 的原始網路埠fun0.0 運行

    • KDNET-KDNET-Ext. 模組將在 bus.dev 上耗盡新增的 PFfun0.1。確保這樣可以使 Windows 收件匣 NIC 驅動程式不會受到與 KDNET 共用 NIC 的影響。

  • kdnet.exe 使用者模式工具會藉由新增特定的 IOCTL 程式代碼來新增/移除 KDNET PF,使用 Windows 收件匣驅動程式來設定 2PF 功能。

顯示兩個網路堆疊的圖表,其中一個使用合併的 PCI 介面卡設定來支援 2PF。

多個 PFS 功能設計需求

  1. KDNET 2PF 功能必須適用於所有目前的 KD 案例,無論是預先 NT OS(例如開機管理員、OS 載入器、WinResume、Hyper-V、SK 等)、NT OS 或 Windows 桌面。

  2. 為裝置新增 PF 時,需要重新啟動系統,導致 BCD 組態需要變更以進行偵錯設定。 這表示額外的 PF 的設定必須在多次開機後持續存在。

  3. 只有在調試程式擁有偵錯裝置時,調試程式才應該使用 KDNET 2PF,以確保調試程式擁有偵錯裝置時,沒有任何其他從 PCI 2PF 位置存取/執行的 Windows/UEFI 以太網路驅動程式(使用 dbgsettings::busparams 設定 2PF 位置)。

  4. 即使系統中未啟用 KDNET,Windows 或 UEFI 乙太網路驅動程式也無法用盡新增的 KDNET 2PF。

  5. 2PF 功能應該支援動態機制,以便在目前的 NIC 上新增/啟用和移除/停用功能。

  6. Windows 迷你埠驅動程式會透過維護下列 NDIS OID 來實作 2PF 功能。

OID 名稱 描述
OID_KDNET_ENUMERATE_PFS 列舉目前 bus.dev.fun (BDF) 上的 PF,其中迷你埠驅動程式正在執行。
OID_KDNET_ADD_PF 在迷你埠驅動程式運行的環境下,將 PF 新增至目前的 BDF。
OID_KDNET_REMOVE_PF 從傳入的 BDF 中移除新增的 PF。
OID_KDNET_QUERY_PF_INFORMATION 從傳入的 BDF 查詢 PF 信息數據。

OID 及其結構定義於 ntddndis.h 和 kdnetpf.h 檔案中,這些檔案會隨著公用 WDK 發行。

請參閱下列詳細數據,以瞭解每個 OID 的輸入/輸出參數,以及 kdnetpf.h 頭檔中提供的資訊。

  1. KDNET 應該透過 NICS 上的 KDNET 2PF 功能來設定,其中有多個 PF 功能可供使用,而 NIC 會遵循上述所有需求來啟用 2PF 功能。

適用於 Windows NIC 驅動程式的 KDNET 多重 PF 介面

若要支援 KDNET 多個 PF 介面迷你埠驅動程式,必須實作下列四個 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 OIDs 路由至小端口驅動程式。

多重 PF 功能 NDIS OID

多重 PF 功能是使用這四個 NDIS OID 來運作。

1. 使用 OID 列舉迷你埠 BDF 的主埠上的 PF:OID_KDNET_ENUMERATE_PFS,請參閱下方定義。

  • OID_KDNET_ENUMERATE_PFS 會從迷你埠驅動程序執行所在的指定主要埠傳回與指定主要埠相關聯的所有 BDF 清單。 埠是由 bus.dev.fun (BDF) 表示。 作業將列出/列舉只與來自執行迷你埠驅動程式之系統上的 bus.dev.fun(BDF 埠)相關聯的 PF 列表,因為每個迷你埠驅動程式都可以確定其 BDF 位置。

  • PFS 清單會透過 NDIS 查詢作業傳回給用戶端。

  • OID_KDNET_ENUMERATE_PFS OID 與 NDIS_KDNET_ENUMERATE_PFS 結構相關聯。

  • OID_KDNET_ENUMERATE_PFS 驅動程式處理程式會傳回包含 PFS 清單的緩衝區,緩衝區中的每個 PF 元素皆由 NDIS_KDNET_PF_ENUM_ELEMENT類型描述。

    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 清單輸出緩衝區大小不足以配置實際的 PFs 清單,則 OID 處理程式必須傳回 E_NOT_SUFFICIENT_BUFFER 錯誤傳回值,以及所需的緩衝區大小,因此用戶端工具可以配置所需的大小緩衝區,然後用戶端可以使用配置正確的緩衝區大小進行另一個呼叫。 此外,OID 要求狀態欄位 (由 NDIS_IOCTL_OID_REQUEST_INFO.status 描述) 應設定為等於 NDIS_STATUS_BUFFER_TOO_SHORT

2.將 PCI PF 新增至迷你埠 BDF 主要埠(OID:OID_KDNET_ADD_PF, 請參閱以下定義)

  • 將 PF 新增至迷你埠主要埠。 埠是由 BDF 表示。

  • 新新增的 PF 將會透過 NDIS 查詢作業傳回給用戶端。

  • OID_KDNET_ADD_PF OID 與 NDIS_KDNET_ADD_PF 結構相關聯。

  • OID_KDNET_ADD_PF 驅動程式處理程式會傳回ULONG,其中包含新增 PF 函式編號

  • 此 OID 要求只會有 Output 參數:AddedFunctionNumberAddedFunctionNumber 表示在迷你埠 PCI 位置(BDF 迷你埠)新增的函數數值。 kdnet.exe 公用程式會收到此值,並設定 dbgsettings::busparams 以指向新增的 PF。

提示

新增的 PF 可以專供 KDNET 使用,因此 Windows NIC 驅動程式特別設計為*不*在新增的 PF 上運行,這也適用於未在系統上啟用 KDNET 且 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 方法操作返還一個 ULONG,其中包含已移除的 PF 函數編號

  • 此函式只會在使用 OID_KDNET_ADD_PF OID 新增的 PF 上成功。

  • 此 OID 要求將 BDF 從輸入 BDF 埠中移除。 此函式具有 FunctionNumber的 Output 參數。 輸出 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 數目上限:包含一個 ULONG,該值為可新增至指定 BDF 的 PF 最多數量。

    • 裝置標識碼:包含與指定 BDF 埠相關聯的裝置識別碼。 當 NIC FW 將新的裝置識別碼指派給新增的 KDNET PF 埠時,這是必要的。

  • 此 OID 會請求任何傳入 BDF 埠的資訊(BDF 是此項作業的輸入參數),因此它不一定與驅動程序當前正在運行的 BDF 相關,不一定是

用於 2PF 上 KDNET 的 NDIS OIDs

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 Kernel-Mode 偵錯

網路 OID

kdnetpf.h 標頭