Partilhar via


Suporte ao Depurador 2PF KDNET

Este tópico descreve como habilitar o driver NDIS de miniporta para suporte ao depurador 2PF para permitir maior desempenho para adaptadores de alta velocidade, geralmente usados em data centers. Esta funcionalidade está disponível no Windows 11 e posterior.

Ao ativar a depuração do kernel numa NIC, o suporte de depuração do kernel assume o controle do dispositivo físico para fornecer tanto uma depuração do kernel quanto uma ligação de rede na máquina. Isso funciona bem em NICs de baixa largura de banda do consumidor (1-10 Gbps), mas em dispositivos de alta taxa de transferência que suportam 10-40+ Gbps, os módulos de extensibilidade de depuração do kernel que conversam com o hardware geralmente não conseguem acompanhar a quantidade de tráfego que vem da pilha de rede do Windows, portanto, isso degrada o desempenho geral do sistema.

O uso do recurso PCI multiple Physical Function (PF) para KDNET permite que a depuração seja ativada sem quase nenhum impacto no desempenho.

A função física (PF) é uma função PCI Express (PCIe) de um adaptador de rede que suporta a interface de virtualização de E/S de raiz única (SR-IOV). O PF inclui o SR-IOV Extended Capability no espaço de configuração PCIe. O recurso é usado para configurar e gerenciar a funcionalidade SR-IOV do adaptador de rede, como habilitar a virtualização e expor PCIe Virtual Functions (VFs).

O PF suporta a estrutura SR-IOV Extended Capability em seu espaço de configuração PCIe. Essa estrutura é definida na especificação PCI-SIG Single Root I/O Virtualization and Sharing 1.1.

O transporte do depurador tirará proveito de drivers de miniporta múltiplos ou habilitados para 2PF. Para permitir a depuração de sistemas de servidores de alta velocidade, recomenda-se que os fornecedores de NIC habilitem o 2PF em todas as NICs que suportam vários PF no firmware da placa de rede.

Para obter informações sobre como configurar o suporte a 2PF para testar uma conexão, consulte Setting Up 2PF Kernel-Mode Debugging using KDNET.

Visão geral da arquitetura KDNET de vários PF

  • A funcionalidade Multiple PF (2PF) é adicionar/atribuir um novo PF à porta de rede PCI original (por exemplo, Bus.dev.fun0.0).

  • O novo PF adicionado (por exemplo, bus.dev.fun0.1) é usado apenas pelo KDNET para encaminhar pacotes do Depurador de/para o alvo.

  • O PF original será usado pelo driver NIC da caixa de entrada do Windows para rotear os pacotes de rede do Windows (TCP/IP).

  • Usando essa abordagem, ambos os drivers podem trabalhar em paralelo sem interferir no trabalho um do outro.

  • Ambos os drivers serão executados sobre o espaço de configuração PCI particionado

    • O driver da Caixa de Entrada do Windows será executado fora da porta de rede original em bus.dev.fun0.0

    • KDNET-KDNET-Ext. módulo deixará de utilizar o PF adicionado em bus.dev.fun0.1. Desta forma, é garantido que o driver NIC da caixa de entrada do Windows não seja afetado pelo compartilhamento da NIC com o KDNET.

  • A ferramenta de modo de usuário kdnet.exe configura o recurso 2PF usando o driver da caixa de entrada do Windows adicionando códigos IOCTL específicos para adicionar/remover o KDNET PF.

Diagrama que mostra duas pilhas de rede, uma suportando 2PF usando uma configuração combinada de placa PCI.

Vários PFs apresentam requisitos de design

  1. O recurso KDNET 2PF precisa funcionar para todos os cenários atuais do KD, seja o sistema operacional pré-NT (por exemplo, Gerenciador de inicialização, carregador de sistema operacional, WinResume, Hyper-V, SK, etc.), sistema operacional NT ou Windows Desktop.

  2. A reinicialização do sistema será necessária quando a adição de um novo PF para um dispositivo resultar em uma alteração necessária na configuração do BCD para as configurações de depuração. Isso significa que a configuração para um PF adicional deve ser persistente nas inicializações.

  3. O KDNET 2PF deve ser usado apenas pelo depurador para garantir que não haja nenhum outro driver ethernet Windows/UEFI acessando/executando a partir do local PCI 2PF quando o depurador possui o dispositivo de depuração (o local 2PF é configurado usando dbgsettings::busparams).

  4. Os drivers Ethernet Windows ou UEFI não podem ficar sem o KDNET 2PF adicionado, mesmo quando o KDNET não está habilitado no sistema.

  5. O recurso 2PF deve suportar um mecanismo dinâmico para adicionar/habilitar e remover/desabilitar a funcionalidade na NIC atual.

  6. Os controladores miniport do Windows implementarão o recurso 2PF por meio do suporte aos seguintes OIDs NDIS.

Nome OID Descrição
OID_KDNET_ENUMERATE_PFS Enumera PFs no bus.dev.fun atual (BDF), onde o driver de miniporta está sendo executado.
OID_KDNET_ADD_PF Adiciona um PF ao BDF atual, onde o miniport driver está a funcionar.
OID_KDNET_REMOVE_PF Remove o PF adicionado, do passado no BDF.
OID_KDNET_QUERY_PF_INFORMATION Consulta dados de informações da PF fornecidos no BDF.

Os OIDs e suas estruturas são definidos em arquivos ntddndis.h e kdnetpf.h que são liberados com o WDK público.

Veja os detalhes abaixo sobre os parâmetros de entrada/saída para cada OID e as informações fornecidas no arquivo de cabeçalho kdnetpf.h.

  1. O KDNET deve ser configurado através do recurso KDNET 2PF no NICS onde vários recursos PF estão disponíveis, e o NIC habilita a funcionalidade 2PF seguindo todos os requisitos descritos acima.

Interface multicanal PF KDNET para controladores de interface de rede do Windows

Para suportar o KDNET Multiple PF Interface Miniport, os drivers precisarão implementar o processamento dos quatro OIDs NDIS a seguir.

  • OID_KDNET_ENUMERATE_PFS

  • OID_KDNET_ADD_PF

  • OID_KDNET_REMOVE_PF

  • OID_KDNET_QUERY_PF_INFORMATION

Esses OIDs e estruturas são preenchidos nos arquivos ntddndis.h e kdnetpf.h na versão pública do WDK neste caminho:

<WDK root directory>\ddk\inc\ndis

Esses arquivos também estão disponíveis no SDK do Windows e podem ser encontrados neste diretório.

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

A ferramenta cliente (kdnet.exe) utiliza um IOCTL NDIS privado para rotear os OIDs NDIS KDNET 2PF para os drivers de miniport.

O recurso de PF múltiplo nos NDIS OIDs

O recurso PF múltiplo é operado usando esses quatro OIDs NDIS.

1. Enumere PFs na porta primária BDF da miniporta usando o OID: OID_KDNET_ENUMERATE_PFS, veja a definição abaixo.

  • OID_KDNET_ENUMERATE_PFS retorna uma lista de todos os BDFs associados à porta primária onde o driver de miniporta está a ser executado. A porta é representada pelo bus.dev.fun (BDF). A operação irá listar/enumerar a lista de PFs que estão associados apenas à bus.dev.fun (porta BDF) de onde o driver de miniporta está sendo executado no sistema, uma vez que cada driver de miniporta pode determinar sua localização BDF.

  • A lista de PFs será devolvida ao cliente por meio de uma operação de consulta NDIS.

  • O OID_KDNET_ENUMERATE_PFS OID está associado à estrutura NDIS_KDNET_ENUMERATE_PFS.

  • O manipulador de driver OID_KDNET_ENUMERATE_PFS retornará um buffer contendo a lista dos PFs, com cada elemento PF descrito pelo tipo de NDIS_KDNET_PF_ENUM_ELEMENT.

    O campo PfNumber contém o número da função PF (por exemplo, bus.dev.função)

    O campo PfState contém os valores possíveis do estado PF - cada tipo de elemento descrito por NDIS_KDNET_PF_STATE enum.

    NDIS_KDNET_PF_STATE::NdisKdNetPfStatePrimary - Este é um PF primário e geralmente é usado apenas pelo driver miniport.

    NDIS_KDNET_PF_STATE::NdisKdnetPfStateEnabled - Este é um PF secundário adicionado, que é usado pelo KDNET.

    NDIS_KDNET_PF_STATE::NdisKdnetPfStateConfigured - Este é um PF adicionado, mas é apenas adicionado/configurado e não é usado.

  • Se o tamanho do buffer da lista de saída PF não for grande o suficiente para alocar a lista de PFs real, o manipulador OID precisará retornar o código de erro E_NOT_SUFFICIENT_BUFFER, juntamente com o tamanho do buffer necessário, para que o cliente possa alocar o buffer com o tamanho necessário e, em seguida, possa fazer outra chamada com o tamanho correto do buffer alocado. Além disso, o campo de status da solicitação OID (descrito por NDIS_IOCTL_OID_REQUEST_INFO.status) deve ser definido como igual a NDIS_STATUS_BUFFER_TOO_SHORT.

2. Adicione PCI PF à porta primária BDF da miniporta (OID: OID_KDNET_ADD_PF, veja a definição abaixo)

  • Adicione um PF à porta primária da miniporta. O porto é representado pelo BDF.

  • O PF recém-adicionado será devolvido ao cliente por meio de uma operação de consulta NDIS.

  • O OID OID_KDNET_ADD_PF está associado à estrutura NDIS_KDNET_ADD_PF.

  • O manipulador de driver OID_KDNET_ADD_PF irá retornar um ULONG que contém o número de função PF adicionado.

  • Esta solicitação OID terá apenas um parâmetro de saída: AddedFunctionNumber. O AddedFunctionNumber indica o valor do número de função adicionado no local PCI da miniporta (a miniporta BDF). O utilitário kdnet.exe receberá este valor e configurará dbgsettings::busparams para que aponte para o PF adicionado.

Observação

O PF adicionado pode ser usado exclusivamente pelo KDNET, de modo que os drivers NIC do Windows são configurados para **NÃO** serem executados num PF adicionado, portanto, isto também se aplica quando o KDNET não está ativado no sistema e o PF foi adicionado à interface.

3. Remover PCI PF (OID: OID_KDNET_REMOVE_PF, ver definição abaixo)

  • Remova um PF da porta especificada . O porto é representado pelo BDF.

  • O OID_KDNET_REMOVE_PF OID está associado à estrutura NDIS_KDNET_REMOVE_PF.

  • O OID_KDNET_REMOVE_PF OID, tendo uma porta BDF de entrada, retorna um ULONG contendo o número da função PF removido através de uma operação do Método NDIS.

  • Esta função terá êxito apenas nos PFs que foram adicionados usando o OID_KDNET_ADD_PF OID.

  • Esta solicitação OID terá a porta BDF de entrada de onde precisa ser removido o BDF. Esta função tem um parâmetro Output de FunctionNumber. A saída FunctionNumber conterá o valor do número da função removido.

4. Consultar informações do PCI PF (OID: OID_KDNET_QUERY_PF_INFORMATION, ver definição abaixo)

  • Este código OID permite consultar dados PF específicos em uma determinada porta. O porto é representado pelo BDF.

  • As informações de PF solicitadas serão devolvidas ao cliente através de uma operação do Método NDIS.

  • O OID_KDNET_QUERY_PF_INFORMATION OID está associado à estrutura NDIS_KDNET_QUERY_PF_INFORMATION.

  • O OID_KDNET_QUERY_PF_INFORMATION OID tem uma porta BDF de entrada e retorna um buffer contendo os seguintes dados:

    • Endereço MAC: Endereço de rede do novo KDNET PF atribuído, se existir.

    • Tag de uso: descreve a entidade proprietária da porta PF. Ele contém um valor constante descrito por NDIS_KDNET_PF_USAGE_TAG enum.

    • Número máximo de PFs: Contém um ULONG com o número máximo de PFs que podem ser adicionados ao BDF dado.

    • ID do dispositivo: contém o ID do dispositivo associado à porta BDF fornecida. Isso é necessário para casos em que a NIC FW atribui um novo ID de dispositivo à nova porta KDNET PF adicionada.

  • Este OID solicita as informações para qualquer porta BDF passada (BDF é um parâmetro de entrada para esta operação), portanto, não está necessariamente relacionado ao BDF atual de onde o driver está sendo executado.

NDIS OIDs para KDNET em 2PF

arquivo Ntddndis.h define os 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)

arquivo Kdnetpf.h descreve o tipo e as estruturas associadas aos OIDs NDIS.

#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)

Ver também

Configurando a depuração de Kernel-Mode 2PF usando o KDNET

OIDs de rede

cabeçalho do ficheiro kdnetpf.h