패킷 설명자 및 확장

NetAdapterCx에서 패킷 설명자는 네트워크 패킷 을 설명하는 작고 압축되고 런타임 확장 가능한 구조입니다. 각 패킷에는 다음이 필요합니다.

  • 하나의 핵심 설명자
  • 하나 이상의 조각 설명자
  • 0개 이상의 패킷 확장

패킷의 핵심 설명자는NET_PACKET 구조입니다. 지정된 패킷의 프레이밍 레이아웃 및 패킷의 첫 번째 조각 설명자에 대한 인덱스와 같이 모든 패킷에 적용할 수 있는 가장 기본적인 메타데이터만 포함합니다.

또한 각 패킷에는 패킷 데이터가 있는 시스템 메모리 내의 위치를 설명하는 하나 이상의 조각 설명자 또는 NET_FRAGMENT 구조체가 있어야 합니다.

확장은 선택 사항이며 시나리오별 기능에 대한 패킷당 또는 조각별 메타데이터를 보유합니다. instance 경우 패킷 확장은 체크섬, LSO(대규모 송신 오프로드) 및 수신 RSC(세그먼트 병합)에 대한 오프로드 정보를 보유하거나 애플리케이션별 세부 정보를 보유할 수 있습니다. 조각 확장은 가상 주소 정보, 논리적 DMA 주소 정보 또는 조각에 대한 기타 정보를 보유할 수 있습니다.

이러한 설명자와 확장은 함께 네트워크 패킷에 대한 모든 메타데이터를 보유합니다. 다음은 패킷을 설명하는 방법에 대한 두 가지 예입니다. 첫 번째 그림은 전체 패킷이 단일 메모리 조각 내에 저장되고 체크섬 오프로드가 켜져 있는 시나리오를 보여줍니다.

조각 1과 확장이 1인 패킷 레이아웃을 보여 주는 다이어그램

두 번째 그림은 RSC 및 체크섬 오프로드를 모두 사용하도록 설정된 두 개의 메모리 조각에 저장된 패킷을 보여줍니다.

2개의 조각과 2개의 확장이 있는 패킷 레이아웃을 보여 주는 다이어그램

패킷 설명자 스토리지 및 액세스

패킷 설명자와 조각 설명자는 모두 NET_RING 구조에 저장됩니다. NIC 클라이언트 드라이버는 Net Ring에 액세스하고 Net Ring Iterator 인터페이스를 호출하여 작업을 수행합니다. 이를 통해 드라이버는 NetAdapterCx와 함께 작업하여 네트워크 데이터를 하드웨어에 게시하고 완료된 데이터를 OS로 다시 드레이닝할 수 있습니다.

net 링 및 Net Ring 반복기 인터페이스에 대한 자세한 내용은 net 링 소개를 참조하세요.

패킷 설명자 확장성

확장성은 NetAdapterCx 패킷 설명자의 핵심 기능으로, 설명자의 버전 및 성능을 위한 토대를 형성합니다. 런타임 시 운영 체제는 연속 블록의 각 패킷 큐에 대한 모든 패킷 설명자를 모든 확장과 함께 할당합니다. 각 확장 블록은 다음 그림과 같이 핵심 설명자 바로 뒤에 있습니다.

확장 블록이 3개인 NetAdapterCx 패킷 설명자 레이아웃을 보여 주는 다이어그램

NIC 클라이언트 드라이버는 확장 블록에 오프셋을 하드 코딩할 수 없습니다. 대신 런타임에 특정 확장에 대한 오프셋을 쿼리해야 합니다. 예를 들어 드라이버는 확장 B에 대한 오프셋을 쿼리하고 다음 그림과 같이 70바이트를 다시 가져올 수 있습니다.

코어 패킷 설명자의 확장에 대한 오프셋 쿼리를 보여 주는 다이어그램

패킷 큐와 해당 설명자가 만들어지면 시스템에서 모든 확장 오프셋이 일정하게 보장되므로 드라이버는 오프셋을 자주 다시 쿼리할 필요가 없습니다. 또한 모든 확장은 패킷 큐가 초기화될 때 시스템에서 블록에 미리 할당되므로 블록의 런타임 할당, 특정 설명자 목록을 검색하거나 모든 패킷 확장에 대한 포인터를 저장할 필요가 없습니다.

패킷 설명자 버전 관리

NetAdapterCx의 핵심 패킷 설명자는 다음 그림과 같이 끝에 새 필드를 추가하여 향후 릴리스에서 쉽게 확장할 수 있습니다.

NetAdapterCx 핵심 패킷 설명자 버전 관리를 보여 주는 다이어그램

V2 필드에 대해 알고 있는 최신 클라이언트 드라이버는 액세스할 수 있으며, 이전 V1 전용 드라이버는 확장 오프셋을 사용하여 V2 필드를 건너뛰어 자신이 이해하는 필드에 액세스할 수 있습니다. 또한 다음 그림과 같이 각 확장의 버전이 동일한 방식으로 버전이 지정될 수 있습니다.

NetAdapterCx 패킷 확장 버전 관리를 보여 주는 다이어그램

새 확장을 이해하는 클라이언트 드라이버가 사용할 수 있습니다. 다른 클라이언트 드라이버는 새 필드를 건너뛸 수 있습니다. 이렇게 하면 패킷 설명자의 여러 부분을 독립적으로 버전이 지정될 수 있습니다.

패킷 설명자 및 데이터 경로 성능

이전에 설명한 확장성 기능은 클라이언트 드라이버가 수천 개의 큐를 사용하여 초당 수백 기가비트를 제한할 수 있는 NIC의 성능 요구 사항을 충족하는 데 도움이 되는 이점을 제공합니다.

  1. 패킷 설명자는 사용되지 않는 기능 및 확장이 설명자에서 0바이트의 공간을 차지하므로 CPU 캐시 적중 횟수 향상을 위해 최대한 간결하게 유지됩니다.
  2. 확장이 인라인이기 때문에 포인터 역참조는 없으며 오프셋 산술만 있으면 공간을 절약할 수 있을 뿐만 아니라 CPU 캐시 적중에 도움이 됩니다.
  3. 확장은 큐를 만들 때 할당되므로 드라이버는 활성 데이터 경로에서 메모리를 할당 및 할당 취소하거나 컨텍스트 블록의 lookaside 목록을 처리할 필요가 없습니다.

패킷 확장 사용

중요

현재 클라이언트 드라이버는 운영 체제에서 정의한 기존 패킷 확장으로 제한됩니다.

패킷 확장 등록

NIC 클라이언트 드라이버에서 패킷 확장을 사용하는 첫 번째 단계는 지원되는 하드웨어 오프로드를 선언하는 것입니다. 체크섬 및 LSO와 같은 오프로드에 대한 지원을 보급하면 NetAdapterCx는 연결된 패킷 확장을 사용자를 대신하여 자동으로 등록합니다.

하드웨어 오프로드를 보급하는 코드 예제는 하드웨어 오프로드 소개를 참조하세요.

데이터 경로 큐에 대한 패킷 확장 오프셋 쿼리

하드웨어 오프로드 지원을 선언하여 패킷 확장을 등록한 후 패킷을 처리할 때 각 확장 오프셋에 액세스하려면 확장 오프셋이 필요합니다. 드라이버에서 호출을 줄이고 성능을 향상시키려면 EvtNetAdapterCreateTx(Rx)큐 콜백 함수 중에 확장에 대한 오프셋을 쿼리하고 큐 컨텍스트에 오프셋 정보를 저장할 수 있습니다.

확장 오프셋을 쿼리하고 큐 컨텍스트에 저장하는 예제는 큐 전송 및 받기를 참조하세요.

런타임에 패킷 확장 가져오기

큐 컨텍스트에 확장 오프셋을 저장한 후에는 확장에 정보가 필요할 때마다 사용할 수 있습니다. 예를 들어 전송 큐에 대한 하드웨어에 설명자를 프로그래밍하는 동안 NetExtensionGetPacketChecksum 메서드를 호출할 수 있습니다.

    // Get the extension offset from the device context
    PMY_TX_QUEUE_CONTEXT queueContext = GetMyTxQueueContext(txQueue);
    NET_EXTENSION checksumExtension = queueContext->ChecksumExtension;

    // Get the checksum info for this packet
    NET_PACKET_CHECKSUM* checksumInfo = NetExtensionGetPacketChecksum(checksumExtension, packetIndex);

    // Do work with the checksum info
    if (packet->Layout.Layer3Type == NET_PACKET_LAYER3_TYPE_IPV4_NO_OPTIONS ||
        packet->Layout.Layer3Type == NET_PACKET_LAYER3_TYPE_IPV4_WITH_OPTIONS ||
        packet->Layout.Layer3Type == NET_PACKET_LAYER3_TYPE_IPV4_UNSPECIFIED_OPTIONS)
    {
        if(checksumInfo->Layer4 == NET_PACKET_TX_CHECKSUM_REQUIRED)
        {
            ...
        }
    }
    ...

미리 정의된 패킷 확장 상수 및 도우미 메서드

NetAdapterCx는 알려진 패킷 확장 상수에 대한 정의를 제공합니다.

상수 정의
NET_PACKET_EXTENSION_INVALID_OFFSET 잘못된 오프셋 크기를 보호합니다.
NET_PACKET_EXTENSION_CHECKSUM_NAME NET_PACKET_EXTENSION_CHECKSUM_VERSION_1 체크섬 패킷 확장의 이름 및 버전입니다.
NET_PACKET_EXTENSION_LSO_NAME NET_PACKET_EXTENSION_LSO_VERSION_1 LSO(대규모 송신 오프로드) 패킷 확장의 이름 및 버전입니다.
NET_PACKET_EXTENSION_RSC_NAME NET_PACKET_EXTENSION_RSC_VERSION_1 수신 세그먼트 병합(RSC) 패킷 확장의 이름 및 버전입니다.

또한 NetAdapterCx는 NetExtensionGetData 메서드를 중심으로 래퍼 역할을 하는 도우미 메서드를 제공합니다. 이러한 각 메서드는 적절한 형식의 구조체에 대한 포인터를 반환합니다.

메서드 구조체
NetExtensionGetPacketChecksum NET_PACKET_CHECKSUM
NetExtensionGetGso NET_PACKET_GSO
NetExtensionGetPacketRsc NET_PACKET_RSC

조각 확장 사용

중요

현재 클라이언트 드라이버는 운영 체제에서 정의한 기존 조각 확장으로 제한됩니다.

조각 확장 등록

NetAdapterCx는 드라이버의 표현된 기능을 해석하여 대부분의 조각 확장을 자동으로 등록합니다. 예를 들어 드라이버가 DMA를 지원한다고 표현하면 프레임워크는 DMA 프로그래밍에 필요한 NET_FRAGMENT_LOGICAL_ADDRESS 확장을 자동으로 추가합니다.

데이터 경로 큐에 대한 조각 확장 오프셋 쿼리

조각 확장에 액세스하려면 데이터 경로 큐에 대한 패킷 확장 오프셋 쿼리에 설명된 패킷 확장에 액세스하는 동일한 프로세스를 따를 수 있습니다.

미리 정의된 조각 확장 상수

NetAdapterCx는 알려진 조각 확장 상수에 대한 정의를 제공합니다.

상수 정의
NET_FRAGMENT_EXTENSION_DATA_BUFFER_NAME NET_FRAGMENT_EXTENSION_DATA_BUFFER_VERSION_1 데이터 버퍼 조각 확장의 이름 및 버전입니다.
NET_FRAGMENT_EXTENSION_LOGICAL_ADDRESS_NAME NET_FRAGMENT_EXTENSION_LOGICAL_ADDRESS_VERSION_1 논리 주소 조각 확장의 이름 및 버전입니다.
NET_FRAGMENT_EXTENSION_MDL_NAME NET_FRAGMENT_EXTENSION_MDL_VERSION_1 MDL 조각 확장의 이름 및 버전입니다.
NET_FRAGMENT_EXTENSION_RETURN_CONTEXT_NAME NET_FRAGMENT_EXTENSION_RETURN_CONTEXT_VERSION_1 반환 컨텍스트 조각 확장의 이름 및 버전입니다.
NET_FRAGMENT_EXTENSION_VIRTUAL_ADDRESS_NAME NET_FRAGMENT_EXTENSION_VIRTUAL_ADDRESS_VERSION_1 가상 주소 조각 확장의 이름 및 버전입니다.