Compartilhar 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, frequentemente usados em data centers. Esse recurso está disponível no Windows 11 e posterior.

Ao ativar a depuração do kernel em uma NIC, o suporte à depuração do kernel assume o dispositivo físico para fornecer uma depuração do kernel e uma conexão de rede na caixa. 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 de múltiplas funções físicas (PF) para o KDNET permite que a depuração seja habilitada com quase nenhum impacto no desempenho.

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

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 aproveitará vários ou 2PF habilitados para drivers de miniporta. Para permitir a depuração de sistemas de servidores de alta velocidade, recomenda-se que os fornecedores de NIC habilitem 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 ao 2PF para testar uma conexão, consulte Configurando a depuração do modo kernel do 2PF usando o 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 rotear pacotes do Depurador de/para o destino.

  • O PF original será usado pelo driver de 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 ficará sem a porta de rede original em bus.dev.fun0.0

    • KDNET-KDNET-Ext. módulo ficará sem o PF adicionado em bus.dev.fun0.1, Dessa forma, garante que o driver de 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 requisitos de design de recursos de PFs

  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 SO, WinResume, Hyper-V, SK, etc.), NT OS 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 de 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 do 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 oferecer suporte a um mecanismo dinâmico para adicionar/habilitar e remover/desabilitar a funcionalidade na NIC atual.

  6. Os drivers de miniporta do Windows implementarão o recurso 2PF por meio da manutenção dos seguintes OIDs NDIS.

Nome do 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 driver de miniporta está em execução.
OID_KDNET_REMOVE_PF Remove o PF adicionado, do passado em BDF.
OID_KDNET_QUERY_PF_INFORMATION Consulta dados de informações da PF a partir do repassado 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.

Consulte 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 por meio 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.

KDNET Multiple PF Interface para drivers de NIC do Windows

Para suportar o KDNET, os drivers de Miniporta de Interface PF Múltipla precisarão implementar o tratamento 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) usa um NDIS IOCTL privado para rotear os OIDs NDIS KDNET 2PF para os drivers de miniporta.

O recurso Multiple PF NDIS OIDs

O recurso Multiple PF é operado usando esses quatro OIDs NDIS.

1. Enumere PFs na porta primária BDF de miniporta usando 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 especificada de onde o driver de miniporta está sendo executado. A porta é representada pelo bus.dev.fun (BDF). A operação 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á retornada 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 PFs com cada elemento PF descrito pelo tipo NDIS_KDNET_PF_ENUM_ELEMENT.

    O campo PfNumber contém o Número da Função PF (por exemplo, bus.dev.diversã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 de miniporta.

    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 de saída da lista PF não for grande o suficiente para alocar a lista PFs real, o manipulador OID precisará retornar E_NOT_SUFFICIENT_BUFFER o valor de retorno de erro, juntamente com o tamanho do buffer necessário, para que a ferramenta cliente possa alocar o buffer de tamanho necessário e, em seguida, o cliente 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 miniporta (OID: OID_KDNET_ADD_PF, veja a definição abaixo)

  • Adicione um PF à porta primária da miniporta. A porta é representada pelo BDF.

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

  • O OID_KDNET_ADD_PF OID está associado à estrutura NDIS_KDNET_ADD_PF.

  • O manipulador de driver OID_KDNET_ADD_PF retornará um ULONG contendo o número de função PF adicionado .

  • Essa solicitação OID terá apenas um parâmetro Output: 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á esse valor e configurará dbgsettings::busparams para apontar para o PF adicionado.

Observação

O PF adicionado pode ser usado exclusivamente pelo KDNET, então os drivers de NIC do Windows são manipulados para executar expressamente *NÃO* em um PF adicionado, então isso também se aplica quando o KDNET está *NÃO* habilitado no sistema e o PF foi adicionado à porta.

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

  • Remova um PF da porta fornecida. A porta é representada pelo BDF.

  • O OID_KDNET_REMOVE_PF OID está associado à estrutura NDIS_KDNET_REMOVE_PF.

  • O OID OID_KDNET_REMOVE_PF tem uma porta BDF de entrada e retorna um ULONG contendo o número da função PF removido por meio de uma operação do Método NDIS.

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

  • Essa 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. A porta é representada pelo BDF.

  • As informações solicitadas do PF serão devolvidas ao cliente por meio 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 OID_KDNET_QUERY_PF_INFORMATION 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 houver.

    • 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 fornecido.

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

  • Esse 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

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

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

Confira também

Configurando a depuração no modo kernel 2PF usando o KDNET

OIDs de rede

kdnetpf.h cabeçalho