Dela via


UDP-segmenteringsavlastning (USO)

UDP-segmenterings avlastning (USO), som stöds i Windows 10, version 2004 och senare, är en funktion som gör det möjligt för nätverkskort (NIC) att avlasta segmenteringen av UDP-datagram som är större än den maximala överföringsenheten (MTU) för nätverksmediet. På så sätt minskar Windows processoranvändningen som är associerad med TCP/IP-bearbetning per paket. Kraven för USO liknar stor avlastningsversion 2 (LSOv2), som gäller för TCP-transportprotokollet.

Krav för USO

Det här avsnittet refererar främst till NDIS-protokoll och miniportdrivrutiner. NDIS lättviktiga filterdrivrutiner (LWFs) måste följa krav på protokolldrivrutiner när de modifierar eller skickar paket och kan också anta att alla paket som tillhandahålls sin FilterSendNetBufferLists-handler uppfyller kraven för protokolldrivrutiner.

Miniportdrivrutiner kan avlasta segmenteringen av stora UDP-paket som är större än MTU för nätverksmediet. Ett nätverkskort som stöder segmentering av stora UDP-paket måste också kunna göra följande:

  • Beräkna IP-kontrollsummor för skickade paket som innehåller IPv4-alternativ
  • Beräkna UDP-kontrollsummor för skickade paket

En miniportdrivrutin som stöder USO måste fastställa avlastningstypen från NET_BUFFER_LIST-strukturens OOB-information (utanför bandet). Om värdet på strukturen NDIS_UDP_SEGMENTATION_OFFLOAD_NET_BUFFER_LIST_INFO inte är noll, måste miniportdrivrutinen utföra USO. Alla NET_BUFFER_LIST som innehåller USO OOB-data innehåller också en enda NET_BUFFER struktur. Men om miniportdrivrutinen har fått OID_TCP_OFFLOAD_PARAMETERS att stänga av USO, efter att miniportdrivrutinen har slutfört OID:n bör den avvisa och returnera alla NET_BUFFER_LIST som har USO OOB-fältet inställt.

TCP/IP-transporten avlastar endast de UDP-paket som uppfyller följande kriterier:

  • Paketet är ett UDP-paket.
  • Paketlängden måste vara större än den maximala segmentstorleken (MSS) * (MinSegmentCount - 1).
  • Om miniportdrivrutinen inte anger funktionen SubMssFinalSegmentSupported måste varje stort UDP-paket som avlastas av transporten ha Length % MSS == 0. Det innebär att det stora paketet kan delas upp i N paket där varje segment innehåller exakt MSS användarbytes. Om miniportdrivrutinen anger kapaciteten SubMssFinalSegmentSupported gäller inte det här villkoret för paketlängdsdelbarhet på transporten. Det slutliga segmentet kan med andra ord vara mindre än MSS-.
  • Paketet är inte ett loopback-paket.
  • Den MF- biten i IP-huvudet för det stora UDP-paket som TCP/IP-transporten avlastade kommer inte att anges, och Fragmentförskjutning i IP-huvudet blir noll.
  • Programmet har angett UDP_SEND_MSG_SIZE/WSASetUdpSendMessageSize.

Innan du avlastar ett stort UDP-paket för segmentering gör TCP/IP-transporten följande:

  • Uppdaterar den stora paketsegmenteringsinformation som är associerad med den NET_BUFFER_LIST strukturen. Den här informationen är en NDIS_UDP_SEGMENTATION_OFFLOAD_NET_BUFFER_LIST_INFO struktur som ingår i NET_BUFFER_LIST-strukturens OOB-information. TCP/IP-transporten ställer in MSS-värdet till den önskade MSS.
  • Beräknar en ens komplementsumma för UDP-pseudohuvudet och skriver den här summan till fältet Checksum i UDP-huvudet. TCP/IP-transporten beräknar summan av komplementen över följande fält i pseudohuvuden: Käll-IP-adress, mål-IP-adress och protokoll.

Ettorns komplement summa för pseudohuvudet som tillhandahålls av TCP/IP-transporten ger nätverkskortet en tidig start för att beräkna den faktiska UDP-kontrollsumman för varje paket som nätverkskortet härleder från det stora UDP-paketet, utan att undersöka IP-huvudet.

Observera att RFC 768 och RFC 2460 anger att pseudoheader beräknas över källans IP-adress, mål-IP-adress, protokoll och UDP-längd (längden på UDP-huvudet plus längden på UDP-nyttolasten, exklusive längden på pseudoheader). Men eftersom den underliggande miniportdrivrutinen och NIC genererar UDP-datagram från det stora paket som skickas av TCP/IP-transporten, vet transporten inte storleken på UDP-nyttolasten för varje UDP-datagram och kan därför inte inkludera UDP-längden i pseudoheader-beräkningen. Enligt beskrivningen i följande avsnitt utökar nätverkskortet i stället den pseudoheader-kontrollsumma som tillhandahölls av TCP/IP-transporten för att täcka UDP-längden för varje genererat UDP-datagram.

Viktig

Om UDP-huvudets kontrollsummafält, som tillhandahålls av TCP/IP-transporten, är noll bör nätverkskortet inte utföra någon UDP-kontrollsummaberäkning.

Skicka paket med USO

När miniportdrivrutinen har hämtat NET_BUFFER_LIST i sin MiniportSendNetBufferLists återanropsfunktion kan den anropa NET_BUFFER_LIST_INFO makrot med en _Id av UdpSegmentationOffloadInfo för att hämta MSS-värdet och IP-protokollet.

Miniportdrivrutinen hämtar den totala längden på det stora paketet från längden på den första NET_BUFFER strukturen och använder värdet MSS för att dela upp det stora UDP-paketet i mindre UDP-paket. Vart och ett av de mindre paketen innehåller MSS- eller färre användardatabyte. Endast det sista paket som skapades från det segmenterade stora paketet ska innehålla mindre än MSS- användardatabyte. Alla andra paket som har skapats från det segmenterade paketet måste innehålla MSS- användardatabyte. Om en miniportdrivrutin inte följer den här regeln levereras UDP-datagrammen felaktigt. Om miniportdrivrutinen inte anger funktionen SubMssFinalSegmentSupported delas paketlängden efter MSS- och vart och ett av de segmenterade paketen innehåller MSS- användarbyte.

Miniportdrivrutinen fäster MAC-, IP- och UDP-huvuden till varje segment som härleds från det stora paketet. Miniportdrivrutinen måste beräkna IP- och UDP-kontrollsummorna för dessa härledda paket. För att beräkna UDP-kontrollsumman för varje paket som härleddes från det stora UDP-paketet beräknar nätverkskortet variabeldelen av UDP-kontrollsumman (för UDP-huvudet och UDP-nyttolasten), lägger sedan till denna kontrollsumma till ettorskomplementssumman för pseudohuvudet som beräknades av TCP/IP-transporten, och därefter beräknar ettorskomplementet av 16-bitars kontrollsumman. Mer information om hur du beräknar sådana kontrollsummor finns i RFC 768 och RFC 2460.

Längden på UDP-användardata i det stora UDP-paketet måste vara mindre än eller lika med värdet som miniportdrivrutinen tilldelar till MaxOffLoadSize.

Efter att en drivrutin har angett en statusindikering för att indikera en ändring av MaxOffLoadSizefår drivrutinen inte orsaka en felkontroll om den tar emot en LSO-sändningsbegäran som använder det tidigare MaxOffLoadSize-värdet. I stället måste drivrutinen avvisa begäran. Drivrutiner måste avvisa alla sändningsbegäranden som de av någon anledning inte kan utföra (inklusive storlek, minsta antal segment, IP-inställningar osv.). Förare måste skicka en statusindikator så snart som möjligt om deras kapacitet ändras.

En mellanliggande drivrutin som oberoende utfärdar statusindikationer som rapporterar en ändring i MaxOffLoadSize-värdet måste se till att det underliggande miniportkortet som inte har utfärdat någon statusindikering inte hämtar några paket som är större än det MaxOffLoadSize värde som miniportkortet rapporterade.

En miniport-mellanliggande drivrutin som svarar på OID_TCP_OFFLOAD_PARAMETERS för att inaktivera USO-tjänster måste förberedas för en liten tidsperiod där USO-begäranden fortfarande kan nå miniportdrivrutinen.

Antalet segmenteringspaket som härletts från det stora UDP-paketet måste vara lika med eller större än det MinSegmentCount värde som anges av miniportdrivrutinen.

När du bearbetar ett stort UDP-paket ansvarar miniportdrivrutinen endast för att segmentera paketet och fästa MAC-, IP- och UDP-huvuden på paketen som härleds från det stora UDP-paketet. Om miniporten inte kan skicka minst ett segmenterat paket måste NBL så småningom slutföras med felstatus. Miniporten kan fortsätta att skicka efterföljande paket men krävs inte för att göra det. NBL kan inte slutföras tillbaka till NDIS förrän alla segmenterade paket har överförts eller misslyckats.

USO-kompatibla miniportdrivrutiner måste också göra följande:

  • Stöd för både IPv4 och IPv6.
  • Stöd för replikering av IPv4-alternativ från det stora paketet i varje segmenterat paket som nätverkskortet genererar.
  • Använd IP- och UDP-huvudet i NET_BUFFER_LIST struktur som mall för att generera UDP- och IP-huvuden för varje segmenterat paket.
  • Använd IP-identifieringsvärden (IP-ID) i intervallet från 0x0000 till 0xFFFF. Om mallens IP-huvud till exempel börjar med värdet ID-fält på 0xFFFEmåste det första UDP-datagrampaketet ha värdet 0xFFFEföljt av 0xFFFF, 0x0000, 0x0001och så vidare.
  • Om det stora UDP-paketet innehåller IP-alternativ kopierar miniportdrivrutinen dessa alternativ, oförändrade, till varje paket som härleds från det stora UDP-paketet.
  • Använd byteförskjutningen i UdpHeaderOffset-medlemmen av NDIS_UDP_SEGMENTATION_OFFLOAD_NET_BUFFER_LIST_INFO för att fastställa platsen för UDP-huvudet, som börjar vid paketets första byte.
  • Öka överföringsstatistiken baserat på de segmenterade paketen. Inkludera till exempel antalet byte i ethernet-, IP- och UDP-huvuden för varje paketsegment. Paketantalet är antalet segment i MSSstorlek, inte 1.
  • Ange fälten total längd och IP-längd för UDP baserat på varje segmenterad datagramstorlek.

Ändringar i NDIS-gränssnittet

I det här avsnittet beskrivs de ändringar i NDIS 6.83 som gör att värd-TCP/IP-drivrutinsstacken kan utnyttja USO-funktionerna som exponeras av miniportdrivrutiner.

NDIS och miniportdrivrutinen utför följande:

  • Annonsera att nätverkskortet stöder USO-funktionalitet
  • Aktivera eller inaktivera USO
  • Hämta det aktuella USO-funktionstillståndet

Marknadsföring av USO-kapacitet

Miniportdrivrutiner exponerar USO-kapacitet genom att fylla i fältet UdpSegmentation i NDIS_OFFLOAD-strukturen, som skickas i parametrarna för NdisMSetMiniportAttributes. Fältet Header.Revision i strukturen NDIS_OFFLOAD måste ställas in på NDIS_OFFLOAD_REVISION_6 och fältet Header.Size måste ställas in på NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_6.

Förfrågan om USO-status

Det aktuella USO-tillståndet kan efterfrågas med OID_TCP_OFFLOAD_CURRENT_CONFIG. NDIS hanterar denna OID och skickar den inte till miniportdrivrutinen.

Ändra USO-tillstånd

USO kan aktiveras eller inaktiveras med hjälp av OID_TCP_OFFLOAD_PARAMETERS. När miniportdrivrutinen har bearbetat OID måste den skicka en statusindikering för NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG med det uppdaterade avlastningstillståndet.

USO-nyckelord

UsO-uppräkningsnyckelorden är följande:

  • *UsoIPv4
  • *UsoIPv6

Dessa värden beskriver om USO är aktiverat eller inaktiverat för det specifika IP-protokollet. USO-inställningarna är inte beroende av NDIS_TCP_IP_CHECKSUM_OFFLOAD konfiguration. Om du till exempel inaktiverar *UDPChecksumOffloadIPv4 inaktiveras inte implicit *UsoIPv4.

Undernyckelnamn Parameterbeskrivning Värde Enum-beskrivning
*UsoIPv4 USO (IPv4) 0 Handikappad
1 Aktiverat
*UsoIPv6 USO (IPV6) 0 Handikappad
1 Aktiverat