調試程式 2PF KDNET 支援
本主題描述如何啟用迷你埠 NDIS 驅動程式,以支援 2PF 調試程式,以允許高速適配卡的效能提升,通常用於數據中心。 這項功能適用於 Windows 11 和更新版本。
在 NIC 上啟用核心偵錯時,核心偵錯支援會接管實體裝置,以提供方塊上的核心偵錯和網路連線。 這適用於取用者低頻寬 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 的 PF 中啟用 2PF。
如需設定 2PF 支援以測試連線的資訊,請參閱 使用 KDNET 設定 2PF 內核模式偵錯。
多個 PF KDNET 架構概觀
多重 PF (2PF) 功能是將新的 PF 新增/指派給原始 PCI 網路埠(例如 Bus.dev.fun0.0)。
新增的 PF (例如 bus.dev.fun0.1) 僅由 KDNET 用來將調試程式封包路由傳送至目標或從目標傳送。
Windows 收件匣 NIC 驅動程式將使用原始 PF 來路由傳送 Windows 網络封包 (TCP/IP) 。
使用此方法,這兩個驅動程式可以平行運作,而 w/o 干擾彼此的工作。
這兩個驅動程式都會在分割的PCI設定空間上執行
Windows 收件匣驅動程式會在 bus.dev 用完原始網路埠。fun0.0
KDNET-KDNET-Ext。模組會在 bus.dev 用完新增的 PF。fun0.1,這種方式可確保 Windows 收件匣 NIC 驅動程式不會受到與 KDNET 共用 NIC 的影響。
kdnet.exe使用者模式工具會藉由新增特定的 IOCTL 程式代碼來新增/移除 KDNET PF,使用 Windows 收件匣驅動程式來設定 2PF 功能。
多個 PFS 功能設計需求
KDNET 2PF 功能必須適用於所有目前的 KD 案例,無論是預先 NT OS(例如開機管理員、OS 載入器、WinResume、Hyper-V、SK 等)、NT OS 或 Windows 桌面。
為裝置新增 PF 時,需要重新啟動系統,導致 BCD 組態需要變更以進行偵錯設定。 這表示其他 PF 的設定必須在開機時持續。
只有在調試程式擁有偵錯裝置時,調試程式才應該使用 KDNET 2PF,以確保調試程式擁有偵錯裝置時,沒有任何其他從 PCI 2PF 位置存取/執行的 Windows/UEFI 以太網路驅動程式(使用 dbgsettings::busparams 設定 2PF 位置)。
即使系統中未啟用 KDNET,Windows 或 UEFI 乙太網路驅動程式也無法用盡新增的 KDNET 2PF。
2PF 功能應該支援動態機制,以便在目前的 NIC 上新增/啟用和移除/停用功能。
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 頭檔中提供的資訊。
- 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 清單的緩衝區,其中包含類型NDIS_KDNET_PF_ENUM_ELEMENT所描述的每個 PF 元素。
PfNumber 字段包含 PF 函數編號(例如 bus.dev。fun)
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驅動程式處理程式會傳回包含新增 PF 函數編號的 ULONG。
此 OID 要求只會有一個 Output 參數:
AddedFunctionNumber
。AddedFunctionNumber
表示在迷你埠 PCI 位置 (BDF 迷你埠) 新增的函式編號值。 kdnet.exe公用程式會收到此值,並設定 dbgsettings::busparams 以指向新增的 PF。
注意
新增的 PF 可以完全由 KDNET 使用,因此 Windows NIC 驅動程式會操縱以在新增的 PF 上快速執行 *NOT* ,因此當系統上啟用 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 連接埠,並傳回 ULONG,其中包含透過 NDIS 方法作業移除的 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 列舉所 描述的 常數值。
PFs 數目上限:包含ULONG,其中包含可新增至指定BDF的 PF 數目上限。
裝置標識碼:包含與指定 BDF 埠相關聯的裝置識別碼。 當 NIC FW 將新的裝置識別碼指派給新增的 KDNET PF 埠時,這是必要的。
此 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)