다음을 통해 공유


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 패킷의 길이 % 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 검사sum을 계산하는 초기 시작을 제공합니다.

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

Important

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

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 검사sum을 계산하려면 NIC는 UDP 검사sum의 변수 부분을 계산하고(UDP 헤더 및 UDP 페이로드의 경우) 이 검사Sum을 TCP/IP 전송에서 계산한 의사 헤더의 보수 합계에 추가한 다음 검사sum에 대한 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 옵션의 복제본(replica)tion을 지원합니다.
  • 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_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 기능을 보급합니다. 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 키워드(keyword)

USO 열거형 키워드(keyword) 다음과 같습니다.

  • *UsoIPv4
  • *UsoIPv6

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

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