Поддержка отладчика 2PF KDNET
В этом разделе описывается, как включить поддержку отладчика 2PF для минипорта NDIS, чтобы обеспечить повышенную производительность для высокоскоростных адаптеров, часто используемых в центрах обработки данных. Эта функция доступна в Windows 11 и более поздних версиях.
При включении отладки ядра в сетевом адаптере поддержка отладки ядра перехватывает управление физическим устройством, чтобы предоставить возможность как отладки ядра, так и сетевого подключения на устройстве. Это хорошо работает на сетевых адаптерах с низкой пропускной способностью потребителей (1–10 Гбит/с), но на устройствах с высокой пропускной способностью, поддерживающих 10–40 Гбит/с, модули расширяемости ядра, которые разговаривают с оборудованием, как правило, не могут поддерживать объем трафика, поступающий из сетевого стека Windows, поэтому это снижает общую производительность системы.
Использование функции PCI с несколькими физическими функциями (PF) для KDNET позволяет включить отладку практически без влияния на производительность.
Физическая функция (PF) — это функция PCI Express (PCIe) сетевого адаптера, поддерживающего единый корневой интерфейс виртуализации ввода-вывода (SR-IOV) . PF включает расширенную возможность SR-IOV в пространстве конфигурации PCIe. Эта возможность используется для настройки SR-IOV функциональных возможностей сетевого адаптера и управления ими, таких как включение виртуализации и предоставление виртуальных функций PCIe.
PF поддерживает структуру расширенных возможностей SR-IOV в пространстве конфигурации PCIe. Эта структура определена в спецификации PCI-SIG виртуализации ввода-вывода с одним корнем и совместного использования ресурсов 1.1.
Транспорт отладчика будет использовать несколько драйверов или минипорт-драйверов с поддержкой 2PF. Чтобы разрешить отладку систем высокоскоростных серверов, рекомендуется, чтобы поставщики сетевых карт включили функцию 2PF во всех сетевых адаптерах, поддерживающих несколько PF, в прошивке сетевой карты.
Сведения о настройке поддержки 2PF для проверки подключения см. в статье Настройка отладки 2PF Kernel-Mode с помощью KDNET.
Обзор архитектуры PF KDNET для нескольких устройств
Функция нескольких PF (2PF) — добавить или назначить новый PF для исходного сетевого порта PCI (например, Bus.dev.fun0.0).
Новый добавленный PF (например, bus.dev.fun0.1) используется только KDNET для маршрутизации пакетов отладчика к/от целевого объекта.
Исходный PF будет использоваться встроенным драйвером сетевого интерфейса Windows для маршрутизации сетевых пакетов Windows (TCP/IP).
С помощью этого подхода оба драйвера могут работать параллельно, не мешая друг другу.
Оба драйвера будут работать над секционированным пространством конфигурации PCI
Драйвер Windows Inbox будет работать через исходный сетевой порт на bus.dev.fun0.0
KDNET-KDNET-Ext. модуль исчерпает добавленный PF в bus.dev.fun0.1. Таким образом, встроенный драйвер сетевого адаптера Windows не страдает от совместного использования сетевого адаптера с KDNET.
Средство kdnet.exe пользовательского режима настраивает функцию 2PF с помощью драйвера папки "Входящие", добавив определенные коды IOCTL для добавления и удаления KDNET PF.
Требования к проектированию функций нескольких PFS
Функция KDNET 2PF должна работать для всех текущих сценариев KD, будь то предварительная ОС NT (например, диспетчер загрузки, загрузчик ОС, WinResume, Hyper-V, SK и т. д.), NT OS или Настольный компьютер Windows.
Перезагрузка системы потребуется при добавлении нового PF для устройства, что приведет к изменению конфигурации BCD для отладки параметров. Это означает, что конфигурация дополнительного PF должна сохраняться после перезагрузки.
KDNET 2PF следует использовать только отладчиком, чтобы гарантировать отсутствие других драйверов Ethernet Windows/UEFI, которые обращаются к расположению PCI 2PF или работают в нем, когда отладчик использует отладочное устройство (расположение 2PF настраивается с помощью dbgsettings::busparams).
Драйверы Ethernet для Windows или UEFI не могут работать вне рамок добавленной KDNET 2PF, даже если KDNET не активирована в системе.
Функция 2PF должна поддерживать динамический механизм для добавления/включения и удаления/отключения функциональности на текущей сетевой карте.
Драйверы мини-порта Windows реализуют функцию 2PF с помощью обслуживания следующих NDIS OID.
Имя OID | Описание |
---|---|
OID_KDNET_ENUMERATE_PFS | Перечисляет PFs в текущем bus.dev.fun (BDF), где выполняется драйвер мини-порта. |
OID_KDNET_ADD_PF | Добавляет PF в текущий BDF, где выполняется минипортовый драйвер. |
OID_KDNET_REMOVE_PF | Удаляет добавленный PF из переданного в BDF. |
OID_KDNET_QUERY_PF_INFORMATION | Запрашивает данные сведений PF из переданного в BDF. |
OIDs и их структуры определяются в файлах ntddndis.h и kdnetpf.h, выпущенных с общедоступным WDK.
См. ниже сведения о параметрах ввода/вывода для каждого OID и информацию, предоставленную в файле заголовка kdnetpf.h.
- KDNET следует настроить с помощью функции KDNET 2PF в сетевых адаптерах, где доступна функция множественных PF, а этот сетевой адаптер обеспечивает функциональность 2PF, следуя всем описанным выше требованиям.
KDNET с несколькими интерфейсами PF для драйверов сетевого адаптера Windows
Для поддержки минипорт-драйверов интерфейса KDNET Multiple PF будет необходимо реализовать обработку следующих четырех OID NDIS.
OID_KDNET_ENUMERATE_PFS
OID_KDNET_ADD_PF
OID_KDNET_REMOVE_PF
OID_KDNET_QUERY_PF_INFORMATION
Эти OID и структуры заполняются в файлах ntddndis.h и kdnetpf.h в общедоступной версии WDK по следующему пути:
<WDK root directory>\ddk\inc\ndis
Эти файлы также доступны в пакете SDK для Windows и находятся в этом каталоге.
\Program Files (x86)\Windows Kits\10\Include\<Version for example 10.0.21301.0>\shared
Клиентский инструмент (kdnet.exe) использует частный NDIS IOCTL для маршрутизации NDIS OID KDNET 2PF к минипорт-драйверам.
Функция NDIS с несколькими PF OIDs
Функция нескольких PF управляется с помощью этих четырех NDIS OID.
1. Перечислить PFs на основном порту минипорта BDF с помощью OID: OID_KDNET_ENUMERATE_PFS, см. определение ниже.
OID_KDNET_ENUMERATE_PFS возвращает список всех BDFs, связанных с заданным основным портом, из которого работает мини-драйвер. Порт представлен bus.dev.fun (BDF). Операция будет перечислять список PFS, которые связаны только с bus.dev.fun (порт BDF), из которого драйвер минипорта работает в системе, так как каждый драйвер минипорта может определить его расположение BDF.
Список PFS будет возвращен клиенту с помощью операции запроса NDIS.
OID_KDNET_ENUMERATE_PFS OID связан с структурой NDIS_KDNET_ENUMERATE_PFS.
Обработчик драйвера OID_KDNET_ENUMERATE_PFS будет возвращать буфер, содержащий список PF, где каждый элемент 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 — это добавленная вторичная PF, используемая KDNET.
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. Добавьте PF PCI в основной порт 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 будет иметь только один выходной параметр:
AddedFunctionNumber
.AddedFunctionNumber
указывает добавленное значение номера функции в расположении минипорта 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 OID_KDNET_REMOVE_PF связан со структурой NDIS_KDNET_REMOVE_PF.
OID_KDNET_REMOVE_PF OID имеет входной порт BDF и возвращает ULONG, содержащий удаленный удаленный номер функции PF через операцию метода NDIS.
Эта функция будет успешна только для PF, добавленных с помощью OID_KDNET_ADD_PF OID.
Этот запрос OID содержит входной порт BDF, откуда нужно удалить BDF. Эта функция имеет параметр вывода
FunctionNumber
. ВыходнойFunctionNumber
будет содержать удаленное значение номера функции.
4. Запрос сведений о PCI PF (OID: OID_KDNET_QUERY_PF_INFORMATION, см. определение ниже)
Этот код OID позволяет запрашивать определенные данные PF на заданном порту . Порт представлен BDF.
Запрошенные сведения о PF будут возвращены клиенту с помощью операции метода NDIS.
OID OID_KDNET_QUERY_PF_INFORMATION связан со структурой NDIS_KDNET_QUERY_PF_INFORMATION .
OID_KDNET_QUERY_PF_INFORMATION OID имеет входной порт BDF и возвращает буфер, содержащий следующие данные:
MAC-адрес: сетевой адрес назначенного нового KDNET PF при наличии.
Тег использования: описывает сущность, которая владеет портом PF. Он содержит константное значение, описываемое перечислением NDIS_KDNET_PF_USAGE_TAG.
Максимальное число PFS: содержит ULONG с максимальным числом PFS, которые можно добавить в заданный BDF.
Идентификатор устройства: содержит идентификатор устройства, связанный с заданным портом BDF. Это необходимо для случаев, когда NIC FW назначает новый идентификатор устройства ново добавленному порту KDNET PF.
Этот OID запрашивает информацию для любого переданного порта BDF (BDF является входным параметром для этой операции), поэтому он не связан обязательно с текущим BDF, из которого работает драйвер.
NDIS OIDs для KDNET на 2PF
файл Ntddndis.h определяет OIDs.
#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)
См. также
Настройка 2PF Kernel-Mode Отладка с помощью KDNET