다음을 통해 공유


UDP 세그먼트 오프로드(USO)

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

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 미만일 수 있습니다.
  • 패킷은 루프백 패킷이 아닙니다.
  • 큰 UDP 패킷의 IP 헤더에서 TCP/IP 전송이 오프로드한 MF 비트는 설정되지 않으며, IP 헤더의 조각 오프셋은 0으로 설정됩니다.
  • 애플리케이션에서 WSASetUdpSendMessageSize를 지정 UDP_SEND_MSG_SIZE/ 했습니다.

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

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

TCP/IP 전송에서 제공하는 의사 헤더에 대한 1의 보수 합은 NIC가 IP 헤더를 검사하지 않고도 큰 UDP 패킷에서 파생된 각 패킷의 실제 UDP 체크섬을 쉽게 계산할 수 있도록 합니다.

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

중요합니다

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

USO를 사용하여 패킷 보내기

미니포트 드라이버가 MiniportSendNetBufferLists 콜백 함수에서 NET_BUFFER_LIST를 가져온 후, _IdUdpSegmentationOffloadInfoNET_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비트 1의 보수를 계산합니다. 이러한 체크섬 계산에 대한 자세한 내용은 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 헤더가 0xFFFE ID 필드 값으로 시작하는 경우 첫 번째 UDP 데이터그램 패킷에는 0xFFFE 값과 0xFFFF, 0x0000, 0x0001 등이 있어야 합니다.
  • 큰 UDP 패킷에 IP 옵션이 포함된 경우 미니포트 드라이버는 이러한 옵션을 큰 UDP 패킷에서 파생된 각 패킷에 변경할 수 없는 상태로 복사합니다.
  • NDIS_UDP_SEGMENTATION_OFFLOAD_NET_BUFFER_LIST_INFO 멤버의 바이트 오프셋 UdpHeaderOffset 을 사용하여 패킷의 첫 번째 바이트부터 시작하여 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 기능을 표시합니다. Header.Revision 구조체의 NDIS_OFFLOAD 필드는 NDIS_OFFLOAD_REVISION_6로 설정해야 하며, Header.Size 필드는 NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_6로 설정해야 합니다.

USO 상태 쿼리

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

USO 상태 변경

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

USO 키워드

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

  • *UsoIPv4
  • *UsoIPv6

이러한 값은 특정 IP 프로토콜에 대해 USO를 사용하도록 설정하거나 사용하지 않도록 설정할지 여부를 설명합니다. USO 설정은 NDIS_TCP_IP_CHECKSUM_OFFLOAD 구성에 종속되지 않습니다. 예를 들어, *UDPChecksumOffloadIPv4을(를) 사용하지 않도록 설정한다고 해서 *UsoIPv4도 자동으로 사용하지 않도록 설정되는 것은 아닙니다.

하위 키 이름 매개 변수 설명 가치 열거형 설명
*UsoIPv4 USO(IPv4) 0 비활성화
1 활성화됨
*UsoIPv6 USO(IPV6) 0 비활성화
1 활성화됨