Compartilhar via


Suporte ao KDNET do depurador 2PF

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

Ao habilitar a depuração de kernel em uma NIC, o suporte à depuração de kernel assume o dispositivo físico para fornecer uma depuração de kernel e uma conexão de rede na caixa. Isso funciona bem em NICs de baixa largura de banda do consumidor (1 a 10 Gbps), mas em dispositivos de alta taxa de transferência que dão suporte a mais de 10 a 40 Gbps, os módulos de extensibilidade de depuração de kernel que conversam com o hardware geralmente não podem acompanhar a quantidade de tráfego proveniente da pilha de rede do Windows, de modo que isso degrada o desempenho geral do sistema.

O uso do recurso PF (função física múltipla) PCI para 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 dá suporte à interface de virtualização de E/S raiz única (SR-IOV). O PF inclui o SR-IOV Capacidade Estendida no espaço de Configuração do PCIe. A funcionalidade é usada para configurar e gerenciar a funcionalidade SR-IOV do adaptador de rede, como habilitar a virtualização e expor VFs (PCIe Virtual Functions).

O PF dá suporte à estrutura SR-IOV Capacidade Estendida em seu espaço de configuração pcie. Essa estrutura é definida no PCI-SIGde especificação de E/S de E/S de Raiz Única e Compartilhamento 1.1.

O transporte do depurador aproveitará vários drivers de miniportos habilitados para 2PF ou 2PF. Para permitir a depuração de sistemas de servidores de alta velocidade, é recomendável que os fornecedores de NIC habilitem o 2PF em todas as NICs que dão suporte a vários PF no firmware de cartão de rede.

Para obter informações sobre como configurar o suporte 2PF para testar uma conexão, consulte Configurando a depuração de Kernel-Mode 2PF usandoKDNET.

Visão geral da arquitetura KDNET do PF

  • A funcionalidade PF Múltipla (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 pela KDNET para rotear pacotes de depurador de/para o destino.

  • 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, interferindo uns com os outros no trabalho.

  • 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. o módulo ficará sem o PF adicionado em bus.dev.fun0.1, dessa forma, garante que o driver NIC da caixa de entrada do Windows não seja afetado compartilhando a NIC com KDNET.

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

Diagrama que mostra duas pilhas de rede, uma com suporte para 2PF usando uma configuração de cartão PCI combinada.

Requisitos de design de recursos de vários PFs

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

  2. A reinicialização do sistema será necessária ao adicionar um novo PF para um dispositivo resulta em uma alteração necessária à configuração do BCD para configurações de depuração. Isso significa que a configuração de um PF adicional deve ser persistente entre as 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 do local PCI 2PF quando o depurador possui o dispositivo de depuração (o local 2PF está configurado usando dbgsettings::busparams).

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

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

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

Nome do OID Descrição
OID_KDNET_ENUMERATE_PFS Enumera PFs no BDF (bus.dev.fun atual), em que o driver de miniporto está em execução.
OID_KDNET_ADD_PF Adiciona um PF ao BDF atual, em que o driver de miniporto está em execução.
OID_KDNET_REMOVE_PF Remove o PF adicionado do BDF passado.
OID_KDNET_QUERY_PF_INFORMATION Consulta dados de informações do PF do BDF passado.

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. A KDNET deve ser configurada por meio do recurso KDNET 2PF na NICS, em que vários recursos PF estão disponíveis e a NIC habilita a funcionalidade 2PF seguindo todos os requisitos descritos acima.

Interface PF múltipla do KDNET para drivers NIC do Windows

Para dar suporte aos drivers de miniporto de interface PF múltiplos KDNET, será necessário implementar a manipulação dos quatro OIDs do 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 de cliente (kdnet.exe) usa um IOCTL NDIS privado para rotear os OIDs NDIS do KDNET 2PF para os drivers de miniporto.

Os vários OIDs do NDIS do recurso PF

O recurso Vários PF é operado usando esses quatro OIDs do NDIS.

1. Enumerar PFs na porta primária do BDF de miniport usando OID: OID_KDNET_ENUMERATE_PFS, consulte 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 miniporto está sendo executado. A porta é representada pelo BDF (bus.dev.fun). A operação listará/enumerará a lista de PFs que estão associados apenas à bus.dev.fun (porta BDF) de onde o driver de miniporto está em execução no sistema, pois cada driver de miniporto 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 OID_KDNET_ENUMERATE_PFS está associado à estrutura de NDIS_KDNET_ENUMERATE_PFS.

  • O manipulador de driver OID_KDNET_ENUMERATE_PFS retornará um buffer que contém a lista de 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.divertido)

    O campo PfState contém os valores possíveis do estado PF, cada tipo de elemento descrito por NDIS_KDNET_PF_STATE enumeração.

    NDIS_KDNET_PF_STATE::NdisKdNetPfStatePrimary – esse é um PF primário e geralmente é usado apenas pelo driver de miniporto.

    NDIS_KDNET_PF_STATE::NdisKdnetPfStateEnabled – este é um PF secundário adicionado, que é usado pela KDNET.

    NDIS_KDNET_PF_STATE::NdisKdnetPfStateConfigured – este é um PF adicionado, mas ele só é 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 de PFs reais, o manipulador de OID precisará retornar E_NOT_SUFFICIENT_BUFFER 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 pode fazer outra chamada com o tamanho do buffer correto 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. Adicionar PCI PF à porta primária do BDF do miniport (OID: OID_KDNET_ADD_PF, consulte a definição abaixo)

  • Adicione um PF à porta primária do miniporto. A porta é representada pelo BDF.

  • O PF recém-adicionado será retornado 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 retornará um ULONG contendo o adicionado número da função PF.

  • Essa 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 da PCI do miniporto (o miniporto 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 pela KDNET, portanto, os drivers NIC do Windows são manipulados para executar expressamente *NOT* em um PF adicionado, portanto, isso também se aplica quando KDNET é *NOT* habilitado no sistema e o PF foi adicionado à porta.

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

  • Remova um PF do determinadode porta . A porta é representada pelo BDF.

  • O OID OID_KDNET_REMOVE_PF está associado à estrutura NDIS_KDNET_REMOVE_PF.

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

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

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

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

  • Esse código OID permite consultar dados específicos do PF em um determinada porta. A porta é representada pelo BDF.

  • As informações do PF solicitadas serão retornadas ao cliente por meio de uma operação do Método NDIS.

  • O OID OID_KDNET_QUERY_PF_INFORMATION está associado à estrutura NDIS_KDNET_QUERY_PF_INFORMATION.

  • O OID do OID_KDNET_QUERY_PF_INFORMATION tem uma porta BDF de entrada e retorna um buffer que contém os seguintes dados:

    • Endereço MAC: endereço de rede do novo PF KDNET atribuído se houver algum.

    • Marca de uso: descreve a entidade que possui a porta PF. Ele contém um valor constante descrito por NDIS_KDNET_PF_USAGE_TAG enumeração.

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

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

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

OIDs do NDIS para KDNET no 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 do 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)

Consulte também

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

OIDs de Rede

cabeçalho kdnetpf.h