Offload segmentazione UDP (USO)

UDP Segmentation Offload (USO), supportato in Windows 10, versione 2004 e successive, è una funzionalità che consente alle schede di interfaccia di rete di eseguire l'offload della segmentazione di datagrammi UDP maggiori dell'unità di trasmissione massima (MTU) del supporto di rete. In questo modo, Windows riduce l'utilizzo della CPU associato all'elaborazione TCP/IP per pacchetto. I requisiti per USO sono simili a LSOv2, ovvero per il protocollo di trasporto TCP.

Requisiti per USO

Questa sezione si riferisce principalmente al protocollo NDIS e ai driver miniport. I driver di filtro leggeri NDIS (LWFs) devono rispettare i requisiti del driver del protocollo durante la modifica o l'invio di pacchetti e possono anche presupporre che tutti i pacchetti forniti al gestore FilterSendNetBufferLists soddisfino i requisiti del driver del protocollo.

I driver Miniport possono eseguire l'offload della segmentazione di pacchetti UDP di grandi dimensioni superiori all'MTU del supporto di rete. Una scheda di interfaccia di rete che supporta la segmentazione di pacchetti UDP di grandi dimensioni deve anche essere in grado di eseguire le operazioni seguenti:

  • Calcolare i checksum IP per i pacchetti inviati che contengono opzioni IPv4
  • Calcolare i checksum UDP per i pacchetti inviati

Un driver miniport che supporta USO deve determinare il tipo di offload dalle informazioni fuori banda (OOB) della struttura di NET_BUFFER_LIST . Se il valore della struttura NDIS_UDP_SEGMENTATION_OFFLOAD_NET_BUFFER_LIST_INFO è diverso da zero, il driver miniport deve eseguire USO. Qualsiasi NET_BUFFER_LIST che contiene dati OOB USO contiene anche una singola struttura NET_BUFFER . Tuttavia, nel caso in cui il driver miniport abbia ricevuto OID_TCP_OFFLOAD_PARAMETERS per disattivare USO, dopo che il driver miniport ha completato correttamente l'OID, deve rifiutare e restituire qualsiasi NET_BUFFER_LIST con il campo USO OOB impostato.

Il trasporto TCP/IP esegue l'offload solo dei pacchetti UDP che soddisfano i criteri seguenti:

  • Il pacchetto è un pacchetto UDP.
  • La lunghezza del pacchetto deve essere maggiore della dimensione massima del segmento (MSS) * (MinSegmentCount - 1).
  • Se il driver miniport non imposta la funzionalità SubMssFinalSegmentSupported , ogni pacchetto UDP di grandi dimensioni scaricato dal trasporto deve avere Lunghezza % MSS == 0. Ovvero, il pacchetto di grandi dimensioni è divisibile in pacchetti N con ogni segmento di pacchetto contenente esattamente byte utente MSS . Se il driver miniport imposta la funzionalità SubMssFinalSegmentSupported , questa condizione di divisione della lunghezza del pacchetto nel trasporto non si applica. In altre parole, il segmento finale può essere minore di MSS.
  • Il pacchetto non è un pacchetto loopback.
  • Il bit MF nell'intestazione IP del pacchetto UDP di grandi dimensioni che il trasporto TCP/IP offloaded non verrà impostato e l'offset frammento nell'intestazione IP sarà zero.
  • L'applicazione ha specificato UDP_SEND_MSG_SIZE/WSASetUdpSendMessageSize.

Prima di eseguire l'offload di un pacchetto UDP di grandi dimensioni per la segmentazione, il trasporto TCP/IP esegue le operazioni seguenti:

  • Aggiornamenti le informazioni sulla segmentazione di pacchetti di grandi dimensioni associate alla struttura NET_BUFFER_LIST. Queste informazioni sono una struttura NDIS_UDP_SEGMENTATION_OFFLOAD_NET_BUFFER_LIST_INFO che fa parte delle informazioni OOB della struttura NET_BUFFER_LIST . Il trasporto TCP/IP imposta il valore MSS sul mss desiderato.
  • Calcola la somma di un complemento per lo pseudoheader UDP e scrive questa somma nel campo Checksum dell'intestazione UDP. Il trasporto TCP/IP calcola la somma dei complementi dei campi seguenti nello pseudoheader: Indirizzo IP di origine, Indirizzo IP di destinazione e Protocollo.

La somma del complemento per lo pseudoheader fornito dal trasporto TCP/IP fornisce alla scheda di interfaccia di rete un inizio iniziale nel calcolo del checksum UDP reale per ogni pacchetto derivato dalla scheda di interfaccia di rete dal pacchetto UDP di grandi dimensioni, senza dover esaminare l'intestazione IP.

Si noti che RFC 768 e RFC 2460 stabiliscono che lo pseudoheader viene calcolato sull'indirizzo IP di origine, l'indirizzo IP di destinazione, il protocollo e la lunghezza UDP (lunghezza dell'intestazione UDP più la lunghezza del payload UDP, non inclusa la lunghezza dello pseudoheader). Tuttavia, poiché il driver miniport sottostante e la scheda di interfaccia di rete generano datagrammi UDP dal pacchetto di grandi dimensioni passato dal trasporto TCP/IP, il trasporto non conosce le dimensioni del payload UDP per ogni datagramma UDP e pertanto non può includere la lunghezza UDP nel calcolo dello pseudoheader. Come descritto nella sezione seguente, la scheda di interfaccia di rete estende invece il checksum pseudoheader fornito dal trasporto TCP/IP per coprire la lunghezza UDP di ogni datagramma UDP generato.

Importante

Se il campo checksum dell'intestazione UDP fornito dal trasporto TCP/IP è zero, la scheda di interfaccia di rete non deve eseguire il calcolo del checksum UDP.

Invio di pacchetti con USO

Dopo che il driver miniport ottiene il NET_BUFFER_LIST nella relativa funzione di callback MiniportSendNetBufferLists , può chiamare la macro NET_BUFFER_LIST_INFO con un _Id di UdpSegmentationOffloadInfo per ottenere il valore MSS e il protocollo IP.

Il driver miniport ottiene la lunghezza totale del pacchetto di grandi dimensioni dalla lunghezza della prima struttura NET_BUFFER e usa il valore MSS per dividere il pacchetto UDP di grandi dimensioni in pacchetti UDP più piccoli. Ognuno dei pacchetti più piccoli contiene mss o meno byte di dati utente. Si noti che solo l'ultimo pacchetto creato dal pacchetto di grandi dimensioni segmentato deve contenere meno di byte di dati utente MSS . Tutti gli altri pacchetti creati dal pacchetto segmentato devono contenere byte di dati utente MSS . Se un driver miniport non rispetta questa regola, i datagrammi UDP verranno recapitati in modo non corretto. Se il driver miniport non imposta la funzionalità SubMssFinalSegmentSupported , la lunghezza del pacchetto viene diviso per MSS e ognuno dei pacchetti segmentati contiene byte utente MSS .

Il driver miniport affise le intestazioni MAC, IP e UDP a ogni segmento derivato dal pacchetto di grandi dimensioni. Il driver miniport deve calcolare i checksum IP e UDP per questi pacchetti derivati. Per calcolare il checksum UDP per ogni pacchetto derivato dal pacchetto UDP di grandi dimensioni, la scheda di interfaccia di rete calcola la parte variabile del checksum UDP (per l'intestazione UDP e il payload UDP), aggiunge questo checksum alla somma di complemento per lo pseudoheader calcolato dal trasporto TCP/IP, quindi calcola il complemento di uno a 16 bit per il checksum. Per altre informazioni sul calcolo di tali checksum, vedere RFC 768 e RFC 2460.

La lunghezza dei dati utente UDP nel pacchetto UDP di grandi dimensioni deve essere minore o uguale al valore assegnato dal driver miniport al valore MaxOffLoadSize .

Dopo che un driver emette un'indicazione di stato per indicare una modifica al valore MaxOffLoadSize , il driver non deve causare un controllo di bug se riceve una richiesta di invio LSO che usa il valore MaxOffLoadSize precedente. Al contrario, il driver deve non riuscire la richiesta di invio. I driver devono non riuscire a qualsiasi richiesta di invio che non possono eseguire, per qualsiasi motivo (incluse dimensioni, numero minimo di segmenti, opzioni IP e così via). I driver devono inviare un'indicazione di stato il prima possibile se le funzionalità cambiano.

Un driver intermedio che emette in modo indipendente indicazioni sullo stato che segnalano una modifica nel valore MaxOffLoadSize deve garantire che l'adattatore miniport sottostante che non ha emesso un'indicazione di stato non ottiene pacchetti maggiori del valore MaxOffLoadSize segnalato dall'adattatore miniport.

Un driver miniport-intermedio che risponde a OID_TCP_OFFLOAD_PARAMETERS per disattivare i servizi USO deve essere preparato per un piccolo intervallo di tempo in cui le richieste USO potrebbero comunque raggiungere il driver miniport.

Il numero di pacchetti di segmentazione che sono stati derviati dal pacchetto UDP di grandi dimensioni deve essere uguale o maggiore del valore MinSegmentCount specificato dal driver miniport.

Quando si elabora un pacchetto UDP di grandi dimensioni, il driver miniport è responsabile solo della segmentazione del pacchetto e dell'affisso di intestazioni MAC, IP e UDP ai pacchetti derivati dal pacchetto UDP di grandi dimensioni. Se il miniport non riesce a inviare almeno un pacchetto segmentato, il NBL deve essere completato con uno stato di errore. Il miniport può continuare a inviare pacchetti successivi, ma non è necessario farlo. Il NBL non può essere completato nuovamente a NDIS fino a quando tutti i pacchetti segmentati non sono stati trasmessi o non sono riusciti.

Anche i driver miniport compatibili con USO devono eseguire le operazioni seguenti:

  • Supporta sia IPv4 che IPv6.
  • Supportare la replica delle opzioni IPv4 dal pacchetto di grandi dimensioni in ogni pacchetto segmentato generato dalla scheda di interfaccia di rete.
  • Usare l'intestazione IP e UDP nella struttura NET_BUFFER_LIST come modello per generare intestazioni UDP e IP per ogni pacchetto segmentato.
  • Usare i valori di identificazione IP (ID IP) nell'intervallo tra 0x0000e 0xFFFF. Ad esempio, se l'intestazione IP del modello inizia con un valore di campo Identificazione di 0xFFFE, il primo pacchetto di datagram UDP deve avere un valore di 0xFFFE, seguito da 0xFFFF, 0x0000, 0x0001 e così via.
  • Se il pacchetto UDP di grandi dimensioni contiene opzioni IP, il driver miniport copia queste opzioni, senza modifiche, in ogni pacchetto derivato dal pacchetto UDP di grandi dimensioni.
  • Usare l'offset di byte nel membro UdpHeaderOffset di NDIS_UDP_SEGMENTATION_OFFLOAD_NET_BUFFER_LIST_INFO per determinare la posizione dell'intestazione UDP, a partire dal primo byte del pacchetto.
  • Incrementare le statistiche di trasmissione in base ai pacchetti segmentati. Ad esempio, includere il numero di byte di intestazione Ethernet, IP e UDP per ogni segmento di pacchetto e il numero di pacchetti è il numero di segmenti di dimensioni MSS, non 1.
  • Impostare i campi lunghezza totale UDP e lunghezza IP in base a ogni dimensione del datagramma segmentato.

Modifiche all'interfaccia NDIS

Questa sezione descrive le modifiche apportate a NDIS 6.83 che consentono allo stack di driver TCP/IP host di sfruttare le funzionalità USO esposte dai driver miniport.

NDIS e il driver miniport eseguono le operazioni seguenti:

  • Annunciare che la scheda di interfaccia di rete supporta la funzionalità USO
  • Abilitare o disabilitare USO
  • Ottenere lo stato corrente della funzionalità USO

Funzionalità USO pubblicitario

I driver Miniport annunciano la funzionalità USO compilando il campo UdpSegmentation della struttura NDIS_OFFLOAD , che viene passato nei parametri di NdisMSetMiniportAttributes. Il campo Header.Revision nella struttura NDIS_OFFLOAD deve essere impostato su NDIS_OFFLOAD_REVISION_6 e il campo Header.Size deve essere impostato su NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_6.

Esecuzione di query sullo stato USO

È possibile eseguire query sullo stato USO corrente con OID_TCP_OFFLOAD_CURRENT_CONFIG. NDIS gestisce questo OID e non lo passa al driver miniport.

Modifica dello stato USO

L'uso può essere abilitato o disabilitato tramite OID_TCP_OFFLOAD_PARAMETERS. Dopo che il driver miniport elabora l'OID, deve inviare un'indicazione di stato NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG con lo stato di offload aggiornato.

Parole chiave USO

Le parole chiave di enumerazione USO sono le seguenti:

  • *UsoIPv4
  • *UsoIPv6

Questi valori descrivono se USO è abilitato o disabilitato per quel particolare protocollo IP. Le impostazioni USO non dipendono dalla configurazione NDIS_TCP_IP_CHECKSUM_OFFLOAD . Ad esempio, la disabilitazione di *UDPChecksumOffloadIPv4 non disabilita in modo implicito *UsoIPv4.

Nome della sottochiave Descrizione dei parametri Valore Descrizione dell'enumerazione
*UsoIPv4 Offload segmentazione UDP (IPv4) 0 Disabled
1 Attivato
*UsoIPv6 Offload segmentazione UDP (IPV6) 0 Disabled
1 Attivato