디버거 2PF KDNET 지원

이 항목에서는 데이터 센터에서 자주 사용되는 고속 어댑터의 성능을 향상할 수 있도록 2PF 디버거 지원에 미니포트 NDIS 드라이버를 사용하도록 설정하는 방법을 설명합니다. 이 기능은 Windows 11 이상에서 사용할 수 있습니다.

NIC에서 커널 디버깅을 사용하도록 설정하는 경우 커널 디버깅 지원은 물리적 디바이스를 인수하여 상자에 커널 디버깅 및 네트워크 연결을 모두 제공합니다. 이는 소비자 낮은 대역폭 NIC(1-10Gbps)에서 잘 작동하지만 10-40Gbps를 지원하는 높은 처리량 디바이스에서는 하드웨어와 통신하는 커널 디버깅 확장성 모듈이 일반적으로 Windows 네트워킹 스택에서 발생하는 트래픽 양을 따라갈 수 없으므로 전반적인 시스템 성능이 저하됩니다.

KDNET에 PCI PF(다중 물리적 함수) 기능을 사용하면 성능에 거의 영향을 주지 않고 디버깅을 사용할 수 있습니다.

PF(물리적 함수)는 SR-IOV(단일 루트 I/O 가상화) 인터페이스를 지원하는 네트워크 어댑터의 PCI Express(PCIe) 함수입니다. PF는 PCIe 구성 공간에 SR-IOV 확장 기능을 포함합니다. 이 기능은 가상화 사용 및 PCIe VF(가상 함수) 노출과 같은 네트워크 어댑터의 SR-IOV 기능을 구성하고 관리하는 데 사용됩니다.

PF는 PCIe 구성 공간에서 SR-IOV 확장 기능 구조를 지원합니다. 이 구조는 PCI-SIG 단일 루트 I/O 가상화 및 공유 1.1 사양에 정의 되어 있습니다.

디버거 전송은 여러 또는 2PF 지원 미니포트 드라이버를 활용합니다. 고속 서버 시스템의 디버깅을 허용하려면 NIC 공급업체가 네트워크 카드 펌웨어에서 여러 PF를 지원하는 모든 NIC에서 2PF를 사용하도록 설정하는 것이 좋습니다.

연결을 테스트하기 위해 2PF 지원을 구성하는 방법에 대한 자세한 내용은 KDNET을 사용하여 2PF 커널 모드 디버깅 설정을 참조하세요.

여러 PF KDNET 아키텍처 개요

  • 2PF(다중 PF) 기능은 원래 PCI 네트워크 포트(예: Bus.dev.fun0.0)에 새 PF를 추가/할당하는 것입니다.

  • 새로 추가된 PF(예: bus.dev.fun0.1)는 KDNET에서만 디버거 패킷을 대상으로 라우팅하는 데 사용됩니다.

  • 원래 PF는 Windows 받은 편지함 NIC 드라이버에서 Windows 네트워킹 패킷(TCP/IP)을 라우팅하는 데 사용됩니다.

  • 이 방법을 사용하면 두 드라이버가 병렬로 작동하여 서로 작업을 방해할 수 있습니다.

  • 두 드라이버 모두 분할된 PCI 구성 공간을 통해 실행됩니다.

    • Windows 받은 편지함 드라이버는 bus.dev 원래 네트워크 포트가 부족합니다.fun0.0

    • KDNET-KDNET-Ext. 모듈은 bus.dev 추가된 PF가 부족합니다.fun0.1이면 Windows 받은 편지함 NIC 드라이버가 KDNET과 NIC를 공유하여 영향을 받지 않습니다.

  • kdnet.exe 사용자 모드 도구는 특정 IOCTL 코드를 추가하여 KDNET PF를 추가/제거하여 Windows 받은 편지함 드라이버를 사용하여 2PF 기능을 구성합니다.

결합된 PCI 카드 설정을 사용하여 2PF를 지원하는 두 개의 네트워크 스택을 보여 주는 다이어그램

여러 PF 기능 디자인 요구 사항

  1. KDNET 2PF 기능은 NT 이전 OS(예: 부팅 관리자, OS 로더, WinResume, Hyper-V, SK 등), NT OS 또는 Windows 데스크톱 등 모든 현재 KD 시나리오에서 작동해야 합니다.

  2. 디바이스에 대한 새 PF를 추가하면 설정을 디버깅하기 위해 BCD 구성에 변경이 필요할 때 시스템을 다시 부팅해야 합니다. 즉, 추가 PF에 대한 구성은 부팅에서 지속적이어야 합니다.

  3. 디버거가 디버그 디바이스를 소유할 때 PCI 2PF 위치에서 액세스/실행되는 다른 Windows/UEFI 이더넷 드라이버가 없는지 확인하기 위해 디버거에서만 KDNET 2PF를 사용해야 합니다(2PF 위치는 dbgsettings::busparams를 사용하여 구성됨).

  4. 시스템에서 KDNET을 사용하도록 설정하지 않은 경우에도 Windows 또는 UEFI 이더넷 드라이버는 추가된 KDNET 2PF가 부족할 수 없습니다.

  5. 2PF 기능은 현재 NIC에서 기능을 추가/사용 및 제거/비활성화하기 위한 동적 메커니즘을 지원해야 합니다.

  6. Windows 미니포트 드라이버는 다음 NDIS OID를 통해 2PF 기능을 구현합니다.

OID 이름 설명
OID_KDNET_ENUMERATE_PFS 미니포트 드라이버가 실행 중인 BDF(현재 bus.dev.fun)에서 PDF를 열거합니다.
OID_KDNET_ADD_PF 미니포트 드라이버가 실행 중인 현재 BDF에 PF를 추가합니다.
OID_KDNET_REMOVE_PF BDF에 전달된 PF에서 추가된 PF를 제거합니다.
OID_KDNET_QUERY_PF_INFORMATION BDF에 전달된 PF 정보 데이터를 쿼리합니다.

UD 및 해당 구조는 공용 WDK와 함께 릴리스되는 ntddndis.h 및 kdnetpf.h 파일에 정의됩니다.

각 OID에 대한 입력/출력 매개 변수 및 kdnetpf.h 헤더 파일에 제공된 정보에 대한 아래 세부 정보를 참조하세요.

  1. KDNET은 여러 PF 기능을 사용할 수 있는 NICS의 KDNET 2PF 기능을 통해 구성해야 하며, NIC는 위에서 설명한 모든 요구 사항에 따라 2PF 기능을 사용하도록 설정합니다.

Windows NIC 드라이버용 KDNET 다중 PF 인터페이스

KDNET 다중 PF 인터페이스 미니포트 드라이버를 지원하려면 다음 4개의 NDIS OID 처리를 구현해야 합니다.

  • OID_KDNET_ENUMERATE_PFS

  • OID_KDNET_ADD_PF

  • OID_KDNET_REMOVE_PF

  • OID_KDNET_QUERY_PF_INFORMATION

이러한 OID 및 구조체는 이 경로의 공용 WDK 릴리스에 있는 ntddndis.h 및 kdnetpf.h 파일에 채워집니다.

<WDK root directory>\ddk\inc\ndis

이러한 파일은 Windows SDK에서도 사용할 수 있으며 이 디렉터리에서 찾을 수 있습니다.

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

클라이언트 도구(kdnet.exe)는 프라이빗 NDIS IOCTL을 사용하여 KDNET 2PF NDIS OID를 미니포트 드라이버로 라우팅합니다.

다중 PF 기능 NDIS OIDS

다중 PF 기능은 이러한 4개의 NDIS OID를 사용하여 작동합니다.

1. OID: OID_KDNET_ENUMERATE_PFS 사용하여 미니포트 BDF 기본 포트에서 PDF를 열거합니다. 아래 정의를 참조하세요.

  • OID_KDNET_ENUMERATE_PFS 미니포트 드라이버가 실행 중인 위치에서 지정된 기본 포트에 연결된 모든 BDF 목록을 반환합니다. 포트는 BDF(bus.dev.fun)로 표시됩니다. 모든 미니포트 드라이버가 해당 BDF 위치를 확인할 수 있으므로 이 작업은 미니포트 드라이버가 시스템에서 실행되는 bus.dev.fun(BDF 포트)에만 연결된 PDF 목록을 나열/열거합니다.

  • PDF 목록은 NDIS 쿼리 작업을 통해 클라이언트에 반환됩니다.

  • OID_KDNET_ENUMERATE_PFS OID는 NDIS_KDNET_ENUMERATE_PFS 구조체와 연결됩니다.

  • OID_KDNET_ENUMERATE_PFS 드라이버 처리기는 NDIS_KDNET_PF_ENUM_ELEMENT 형식에서 설명하는 각 PF 요소와 함께 PDF 목록을 포함하는 버퍼를 반환합니다.

    PfNumber 필드에는 PF 함수 번호(예: bus.dev)가 포함됩니다.재미)

    PfState 필드에는 가능한 PF 상태 값(NDIS_KDNET_PF_STATE 열거형에서 설명하는 각 요소 형식)이 포함됩니다.

    NDIS_KDNET_PF_STATE::NdisKdNetPfStatePrimary - 기본 PF이며 일반적으로 미니포트 드라이버에서만 사용됩니다.

    NDIS_KDNET_PF_STATE::NdisKdnetPfStateEnabled - KDNET에서 사용되는 추가된 보조 PF입니다.

    NDIS_KDNET_PF_STATE::NdisKdnetPfState 구성 - 추가된 PF이지만 추가/구성되며 사용되지 않습니다.

  • PF 목록 출력 버퍼 크기가 실제 PDF 목록을 할당할 만큼 충분히 크지 않은 경우 OID 처리기는 필요한 버퍼 크기와 함께 오류 반환 값을 반환 E_NOT_SUFFICIENT_BUFFER 해야 하므로 클라이언트 도구는 필요한 크기 버퍼를 할당한 다음 클라이언트가 올바른 버퍼 크기를 할당하여 다른 호출을 수행할 수 있습니다. 또한 OID 요청 상태 필드(NDIS_IOCTL_OID_REQUEST_INFO.상태 설명)를 같NDIS_STATUS_BUFFER_TOO_SHORT게 설정해야 합니다.

2. 미니포트 BDF 기본 포트에 PCI PF 추가(OID: OID_KDNET_ADD_PF, 아래 정의 참조)

  • PF를 미니포트 기본 포트에 추가합니다. 포트는 BDF로 표시됩니다.

  • 새로 추가된 PF는 NDIS 쿼리 작업을 통해 클라이언트에 반환됩니다.

  • OID_KDNET_ADD_PF OID는 NDIS_KDNET_ADD_PF 구조체와 연결됩니다.

  • OID_KDNET_ADD_PF 드라이버 처리기는 추가된 PF 함수 번호를 포함하는 ULONG을 반환합니다.

  • 이 OID 요청에는 출력 매개 변수 AddedFunctionNumber가 하나만 있습니다. 미니 AddedFunctionNumber 포트 PCI 위치(BDF 미니포트)에 추가된 함수 번호 값을 나타냅니다. kdnet.exe 유틸리티는 이 값을 수신하고 추가된 PF를 가리키도록 dbgsettings::busparams를 설정합니다.

참고 항목

추가된 PF는 KDNET에서만 사용할 수 있으므로 Windows NIC 드라이버는 추가된 PF에서 명시적으로 *NOT*으로 실행되도록 조작되므로 KDNET이 시스템에서 *NOT*을 사용하도록 설정되고 PF가 포트에 추가된 경우에도 적용됩니다.

3. PCI PF 제거(OID: OID_KDNET_REMOVE_PF, 아래 정의 참조)

  • 지정된 포트에서 PF를 제거합니다. 포트는 BDF로 표시됩니다.

  • OID_KDNET_REMOVE_PF OID는 NDIS_KDNET_REMOVE_PF 구조체와 연결됩니다.

  • OID_KDNET_REMOVE_PF OID에는 입력 BDF 포트가 있으며 NDIS 메서드 작업을 통해 제거된 PF 함수 번호가 포함된 ULONG을 반환합니다.

  • 이 함수는 OID_KDNET_ADD_PF OID를 사용하여 추가된 PDF에서만 성공합니다.

  • 이 OID 요청에는 BDF를 제거해야 하는 위치에서 입력 BDF 포트가 있습니다. 이 함수에는 .의 출력 매개 변수가 있습니다 FunctionNumber. 출력 FunctionNumber 에는 제거된 함수 번호 값이 포함됩니다.

4. PCI PF 정보 쿼리(OID: OID_KDNET_QUERY_PF_INFORMATION, 아래 정의 참조)

  • 이 OID 코드를 사용하면 지정된 포트에서 특정 PF 데이터를 쿼리할 수 있습니다. 포트는 BDF로 표시됩니다.

  • 요청된 PF 정보는 NDIS 메서드 작업을 통해 클라이언트에 반환됩니다.

  • OID_KDNET_QUERY_PF_INFORMATION OID는 NDIS_KDNET_QUERY_PF_INFORMATION 구조체와 연결됩니다.

  • OID_KDNET_QUERY_PF_INFORMATION OID에는 입력 BDF 포트가 있으며 다음 데이터가 포함된 버퍼를 반환합니다.

    • MAC 주소: 할당된 새 KDNET PF의 네트워크 주소(있는 경우)입니다.

    • 사용 태그: PF 포트를 소유하는 엔터티를 설명합니다. NDIS_KDNET_PF_USAGE_TAG 열거형에서 설명하는 상수 값을 포함합니다.

    • 최대 PDF 수: 지정된 BDF에 추가할 수 있는 최대 PDF 수를 포함하는 ULONG을 포함합니다.

    • 디바이스 ID: 지정된 BDF 포트에 연결된 디바이스 ID를 포함합니다. 이는 NIC FW가 추가된 새 KDNET PF 포트에 새 디바이스 ID를 할당하는 경우에 필요합니다.

  • 이 OID는 BDF 포트에 전달된 모든 정보(BDF는 이 작업의 입력 매개 변수)에 대한 정보를 요청하므로 드라이버가 실행 중인 현재 BDF와 반드시 관련이 있는 것은 아닙니다 .

2PF의 KDNET용 NDIS OID

Ntddndis.h 파일은 OID를 정의합니다.

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

참고 항목

KDNET을 사용하여 2PF 커널 모드 디버깅 설정

네트워크 OID

kdnetpf.h 헤더