UDP 구분 오프로드(USO)

Windows 10 버전 2004 이상에서 지원되는 UDP 구분 오프로드(USO)는 NIC(네트워크 인터페이스 카드)가 네트워크 매체의 최대 전송 단위(MTU)보다 큰 UDP 데이터그램의 분할을 오프로드할 수 있도록 하는 기능입니다. 이렇게 하면 Windows는 패킷당 TCP/IP 처리와 관련된 CPU 사용률을 줄입니다. USO에 대한 요구 사항은 TCP 전송 프로토콜에 대한 LSOv2와 유사합니다.

USO에 대한 요구 사항

이 섹션에서는 주로 NDIS 프로토콜 및 미니포트 드라이버를 참조합니다. NDIS LWF(경량 필터 드라이버)는 패킷을 수정하거나 보낼 때 프로토콜 드라이버 요구 사항을 따라야 하며 FilterSendNetBufferLists 처리기에 제공된 모든 패킷이 프로토콜 드라이버 요구 사항을 충족한다고 가정할 수도 있습니다.

미니포트 드라이버는 네트워크 매체의 MTU보다 큰 큰 UDP 패킷의 분할을 오프로드할 수 있습니다. 큰 UDP 패킷의 구분을 지원하는 NIC도 다음을 수행할 수 있어야 합니다.

  • IPv4 옵션을 포함하는 전송된 패킷에 대한 IP 체크섬 계산
  • 보낸 패킷에 대한 UDP 체크섬 계산

USO를 지원하는 미니포트 드라이버는 NET_BUFFER_LIST 구조체의 OOB(대역 외) 정보에서 오프로드 유형을 결정해야 합니다. NDIS_UDP_SEGMENTATION_OFFLOAD_NET_BUFFER_LIST_INFO 구조체의 값이 0이 아닌 경우 미니포트 드라이버는 USO를 수행해야 합니다. USO OOB 데이터를 포함하는 모든 NET_BUFFER_LIST 단일 NET_BUFFER 구조도 포함합니다. 그러나 미니포트 드라이버가 USO를 해제하는 OID_TCP_OFFLOAD_PARAMETERS 받은 경우 미니포트 드라이버가 OID를 성공적으로 완료한 후에는 USO OOB 필드가 설정된 NET_BUFFER_LIST 거부하고 반환해야 합니다.

TCP/IP 전송은 다음 조건을 충족하는 UDP 패킷만 오프로드합니다.

  • 패킷은 UDP 패킷입니다.
  • 패킷 길이는 최대 세그먼트 크기 (MSS) * (MinSegmentCount - 1)보다 커야 합니다.
  • 미니포트 드라이버가 SubMssFinalSegmentSupported 기능을 설정하지 않은 경우 전송에 의해 오프로드된 각 큰 UDP 패킷에는 Length % MSS == 0이 있어야 합니다. 즉, 큰 패킷은 정확히 MSS 사용자 바이트를 포함하는 각 패킷 세그먼트를 사용하여 N 패킷으로 나눌 수 있습니다. 미니포트 드라이버가 SubMssFinalSegmentSupported 기능을 설정하는 경우 전송에 대한 이 패킷 길이 다양성 조건이 적용되지 않습니다. 즉, 최종 세그먼트는 MSS보다 작을 수 있습니다.
  • 패킷이 루프백 패킷이 아닙니다.
  • 오프로드된 TCP/IP 전송이 설정되지 않고 IP 헤더의 조각 오프셋이 0이 되는 큰 UDP 패킷의 IP 헤더에 있는 MF 비트입니다.
  • 애플리케이션은 UDP_SEND_MSG_SIZE/WSASetUdpSendMessageSize를 지정했습니다.

분할을 위해 큰 UDP 패킷을 오프로드하기 전에 TCP/IP 전송은 다음을 수행합니다.

  • NET_BUFFER_LIST 구조와 연결된 큰 패킷 구분 정보를 업데이트. 이 정보는 NET_BUFFER_LIST 구조체의 OOB 정보의 일부인 NDIS_UDP_SEGMENTATION_OFFLOAD_NET_BUFFER_LIST_INFO 구조체입니다. TCP/IP 전송은 MSS 값을 원하는 MSS로 설정합니다.
  • UDP 의사 헤더에 대한 보수 합계를 계산하고 이 합계를 UDP 헤더의 체크섬 필드에 씁니다. TCP/IP 전송은 의사 헤더의 소스 IP 주소, 대상 IP 주소 및 프로토콜의 다음 필드에 대한 하나의 보완 합계를 계산합니다.

TCP/IP 전송에서 제공하는 의사 헤더에 대한 보완 합계는 IP 헤더를 검사하지 않고도 NIC가 큰 UDP 패킷에서 파생되는 각 패킷에 대한 실제 UDP 체크섬을 계산하는 초기 시작을 NIC에 제공합니다.

RFC 768RFC 2460은 의사 헤더가 원본 IP 주소, 대상 IP 주소, 프로토콜 및 UDP 길이(UDP 헤더의 길이와 의사 헤더의 길이를 포함하지 않는 UDP 페이로드의 길이)를 통해 계산되도록 규정합니다. 그러나 기본 미니포트 드라이버와 NIC는 TCP/IP 전송에 의해 전달되는 큰 패킷에서 UDP 데이터그램을 생성하므로 전송은 각 UDP 데이터그램에 대한 UDP 페이로드의 크기를 알지 못하므로 의사 헤더 계산에 UDP 길이를 포함할 수 없습니다. 대신, 다음 섹션에 설명된 대로 NIC는 TCP/IP 전송에서 제공한 의사 헤더 체크섬을 확장하여 생성된 각 UDP 데이터그램의 UDP 길이를 포함합니다.

중요

TCP/IP 전송에서 제공하는 UDP 헤더 체크섬 필드가 0이면 NIC에서 UDP 체크섬 계산을 수행해서는 안 됩니다.

USO를 사용하여 패킷 보내기

미니포트 드라이버가 MiniportSendNetBufferLists 콜백 함수에서 NET_BUFFER_LIST 가져온 후 UdpSegmentationOffloadInfo_Id NET_BUFFER_LIST_INFO 매크로를 호출하여 MSS 값 및 IP 프로토콜을 가져올 수 있습니다.

미니포트 드라이버는 첫 번째 NET_BUFFER 구조체의 길이에서 큰 패킷의 총 길이를 가져오고 MSS 값을 사용하여 큰 UDP 패킷을 더 작은 UDP 패킷으로 나눕니다. 각 작은 패킷에는 MSS 이하의 사용자 데이터 바이트가 포함됩니다. 분할된 큰 패킷에서 만든 마지막 패킷만 MSS 사용자 데이터 바이트보다 작아야 합니다. 분할된 패킷에서 만든 다른 모든 패킷에는 MSS 사용자 데이터 바이트가 포함되어야 합니다. 미니포트 드라이버가 이 규칙을 준수하지 않으면 UDP 데이터그램이 잘못 전달됩니다. 미니포트 드라이버가 SubMssFinalSegmentSupported 기능을 설정하지 않으면 패킷 길이가 MSS 로 나뉘고 분할된 각 패킷에는 MSS 사용자 바이트가 포함됩니다.

미니포트 드라이버는 MAC, IP 및 UDP 헤더를 큰 패킷에서 파생된 각 세그먼트에 연결합니다. 미니포트 드라이버는 이러한 파생 패킷에 대한 IP 및 UDP 체크섬을 계산해야 합니다. 큰 UDP 패킷에서 파생된 각 패킷의 UDP 체크섬을 계산하기 위해 NIC는 UDP 체크섬의 변수 부분(UDP 헤더 및 UDP 페이로드용)을 계산하고, 이 체크섬을 TCP/IP 전송에서 계산한 의사 헤더의 보수 합계에 추가한 다음 체크섬에 대한 16비트 보수를 계산합니다. 이러한 체크섬 계산에 대한 자세한 내용은 RFC 768RFC 2460을 참조하세요.

큰 UDP 패킷에 있는 UDP 사용자 데이터의 길이는 미니포트 드라이버가 MaxOffLoadSize 값에 할당하는 값보다 작거나 같아야 합니다.

드라이버가 MaxOffLoadSize 값의 변경을 나타내는 상태 표시를 발급한 후 드라이버는 이전 MaxOffLoadSize 값을 사용하는 LSO 보내기 요청을 수신하는 경우 버그 검사 발생해서는 안 됩니다. 대신 드라이버가 보내기 요청에 실패해야 합니다. 드라이버는 어떤 이유로든(크기, 최소 세그먼트 수, IP 옵션 등) 수행할 수 없는 송신 요청에 실패 해야 합니다 . 드라이버는 기능이 변경되면 가능한 한 빨리 상태 표시를 보내야 합니다.

MaxOffLoadSize 값의 변경을 보고하는 상태 표시를 독립적으로 발급하는 중간 드라이버는 상태 표시를 발급하지 않은 기본 미니포트 어댑터가 미니포트 어댑터가 보고한 MaxOffLoadSize 값보다 큰 패킷을 가져오지 않도록 해야 합니다.

USO 서비스를 끄기 위해 OID_TCP_OFFLOAD_PARAMETERS 응답하는 미니포트 중간 드라이버는 USO 요청이 여전히 미니포트 드라이버에 도달할 수 있는 짧은 기간 동안 준비해야 합니다.

큰 UDP 패킷에서 벗어난 구분 패킷 수는 미니포트 드라이버에서 지정한 MinSegmentCount 값보다 크거나 같아야 합니다.

큰 UDP 패킷을 처리할 때 미니포트 드라이버는 패킷을 분할하고 MAC, IP 및 UDP 헤더를 큰 UDP 패킷에서 파생된 패킷에만 연결합니다. 미니포트가 하나 이상의 분할된 패킷을 보내지 못하면 결국 실패 상태 NBL이 완료되어야 합니다. 미니포트는 후속 패킷을 계속 보낼 수 있지만 그렇게 할 필요는 없습니다. 분할된 모든 패킷이 전송되거나 실패할 때까지 NBL을 NDIS로 다시 완료할 수 없습니다.

USO 지원 미니포트 드라이버도 다음을 수행해야 합니다.

  • IPv4 및 IPv6을 모두 지원합니다.
  • NIC에서 생성하는 각 분할된 패킷의 큰 패킷에서 IPv4 옵션 복제를 지원합니다.
  • NET_BUFFER_LIST 구조의 IP 및 UDP 헤더를 템플릿으로 사용하여 분할된 각 패킷에 대한 UDP 및 IP 헤더를 생성합니다.
  • 0x0000 범위에서 0xFFFF 범위의 IP ID(IP ID) 값을 사용합니다. 예를 들어 템플릿 IP 헤더가 0xFFFE ID 필드 값으로 시작하는 경우 첫 번째 UDP 데이터그램 패킷의 값은 0xFFFE, 그 뒤에 0xFFFF, 0x0000, 0x0001 등이 있어야 합니다.
  • 큰 UDP 패킷에 IP 옵션이 포함된 경우 미니포트 드라이버는 이러한 옵션을 큰 UDP 패킷에서 파생된 각 패킷에 변환되지 않은 상태로 복사합니다.
  • NDIS_UDP_SEGMENTATION_OFFLOAD_NET_BUFFER_LIST_INFOUdpHeaderOffset 멤버의 바이트 오프셋을 사용하여 패킷의 첫 번째 바이트부터 UDP 헤더의 위치를 확인합니다.
  • 증분은 분할된 패킷을 기반으로 통계를 전송합니다. 예를 들어 각 패킷 세그먼트에 대한 이더넷, IP 및 UDP 헤더 바이트 수를 포함하고 패킷 수는 1이 아닌 MSS 크기의 세그먼트 수입니다.
  • 분할된 각 데이터그램 크기에 따라 UDP 총 길이 및 IP 길이 필드를 설정합니다.

NDIS 인터페이스 변경 내용

이 섹션에서는 호스트 TCP/IP 드라이버 스택이 미니포트 드라이버에서 노출하는 USO 기능을 활용할 수 있도록 하는 NDIS 6.83의 변경 내용을 설명합니다.

NDIS 및 미니포트 드라이버는 다음을 수행합니다.

  • NIC가 USO 기능을 지원한다고 보급
  • USO 사용 또는 사용 안 함
  • 현재 USO 기능 상태 가져오기

USO 기능 보급

미니포트 드라이버는 NdisMSetMiniportAttributes의 매개 변수에 전달되는 NDIS_OFFLOAD 구조체의 UdpSegmentation 필드를 입력하여 USO 기능을 보급합니다. NDIS_OFFLOAD 구조체의 Header.Revision 필드는 NDIS_OFFLOAD_REVISION_6 설정해야 하며 Header.Size 필드는 NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_6 설정해야 합니다.

USO 상태 쿼리

현재 USO 상태는 OID_TCP_OFFLOAD_CURRENT_CONFIG 사용하여 쿼리할 수 있습니다. NDIS는 이 OID를 처리하고 미니포트 드라이버에 전달하지 않습니다.

USO 상태 변경

USO는 OID_TCP_OFFLOAD_PARAMETERS 사용하여 사용하거나 사용하지 않도록 설정할 수 있습니다. 미니포트 드라이버는 OID를 처리한 후 업데이트된 오프로드 상태의 NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG 상태 표시를 보내야 합니다.

USO 키워드

USO 열거형 키워드는 다음과 같습니다.

  • *UsoIPv4
  • *UsoIPv6

이러한 값은 특정 IP 프로토콜에 대해 USO를 사용하도록 설정하거나 사용하지 않도록 설정할지 여부를 설명합니다. USO 설정은 NDIS_TCP_IP_CHECKSUM_OFFLOAD 구성에 종속되지 않습니다. 예를 들어 *UDPChecksumOffloadIPv4를 사용하지 않도록 설정해도 *UsoIPv4는 암시적으로 사용하지 않도록 설정되지 않습니다.

하위 키 이름 매개 변수 설명 열거형 설명
*UsoIPv4 UDP 구분 오프로드(IPv4) 0 사용 안 함
1 사용
*UsoIPv6 UDP 구분 오프로드(IPV6) 0 사용 안 함
1 사용