Поделиться через


Поддержка отладчика 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.

диаграмма, которая показывает два сетевых стека, один поддерживающий 2PF с установленной объединенной картой PCI.

Требования к проектированию функций нескольких PFS

  1. Функция KDNET 2PF должна работать для всех текущих сценариев KD, будь то предварительная ОС NT (например, диспетчер загрузки, загрузчик ОС, WinResume, Hyper-V, SK и т. д.), NT OS или Настольный компьютер Windows.

  2. Перезагрузка системы потребуется при добавлении нового PF для устройства, что приведет к изменению конфигурации BCD для отладки параметров. Это означает, что конфигурация дополнительного PF должна сохраняться после перезагрузки.

  3. KDNET 2PF следует использовать только отладчиком, чтобы гарантировать отсутствие других драйверов Ethernet Windows/UEFI, которые обращаются к расположению PCI 2PF или работают в нем, когда отладчик использует отладочное устройство (расположение 2PF настраивается с помощью dbgsettings::busparams).

  4. Драйверы Ethernet для Windows или UEFI не могут работать вне рамок добавленной KDNET 2PF, даже если KDNET не активирована в системе.

  5. Функция 2PF должна поддерживать динамический механизм для добавления/включения и удаления/отключения функциональности на текущей сетевой карте.

  6. Драйверы мини-порта 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.

  1. 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

сетевых идентификаторов объектов

заголовка kdnetpf.h