Offload di segmentazione UDP (USO)
L'offload di segmentazione UDP (USO), disponibile in Windows 10, versione 2004 e successive, è una funzione che consente alle schede di rete di delegare la segmentazione di datagrammi UDP che superano l'unità massima di trasmissione (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 versione 2 dell'offload di invio di grandi dimensioni (LSOv2), che è 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 quando modificano o inviano pacchetti e possono anche presupporre che tutti i pacchetti forniti al relativo gestore FilterSendNetBufferLists soddisfino tali requisiti.
I driver Miniport possono delegare la segmentazione di pacchetti UDP di grandi dimensioni che superano l'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
Il driver miniport che supporta USO deve determinare il tipo di offload dalle informazioni OOB (out of band) della struttura NET_BUFFER_LIST. Se il valore della struttura NDIS_UDP_SEGMENTATION_OFFLOAD_NET_BUFFER_LIST_INFO è diverso da zero, allora 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à di
SubMssFinalSegmentSupported
, ogni pacchetto UDP di grandi dimensioni scaricato dal trasporto deve avereLength % MSS == 0
. Ovvero, il pacchetto di grandi dimensioni è divisibile in N pacchetti, ognuno dei quali contiene esattamente MSS byte utente. Se il driver miniport imposta la funzionalità diSubMssFinalSegmentSupported
, 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 di loopback.
- Il bit MF nell'intestazione IP del pacchetto UDP di grandi dimensioni che il trasporto TCP/IP ha scaricato non verrà impostato e l'offset del 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:
- Aggiorna le informazioni di 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 una somma di complemento per lo pseudoheader UDP e scrive questa somma nel campo
Checksum
dell'intestazione UDP. Il trasporto TCP/IP calcola la somma dei complementi di uno sui campi seguenti nello pseudoheader: Indirizzo IP di origine, Indirizzo IP di destinazione e Protocollo.
La somma del complemento a uno per lo pseudoheader fornito dal trasporto TCP/IP fornisce alla scheda di interfaccia di rete un vantaggio iniziale nel calcolare il checksum UDP reale per ogni pacchetto che la scheda deriva dal grande pacchetto UDP, senza dover esaminare direttamente 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 (la 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 a partire dal pacchetto di grandi dimensioni fornito dal trasporto TCP/IP, il trasporto non conosce le dimensioni del payload UDP per ogni datagramma UDP e pertanto non può includere l'UDP Length nel calcolo dello pseudoheader. Invece, come descritto nella sezione seguente, la scheda di interfaccia di rete estende il checksum del pseudoheader fornito dal trasporto TCP/IP per includere la lunghezza UDP di ciascun 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 sua funzione di callback MiniportSendNetBufferLists, può chiamare la macro NET_BUFFER_LIST_INFO con un valore di UdpSegmentationOffloadInfo
in _Id
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. Solo l'ultimo pacchetto creato dal pacchetto di grandi dimensioni segmentato deve contenere meno di MSS byte di dati utente. Tutti gli altri pacchetti creati dal pacchetto segmentato devono contenere MSS byte di dati utente. Se un driver miniport non rispetta questa regola, i datagrammi UDP vengono recapitati in modo non corretto. Se il driver miniport non imposta la capacità SubMssFinalSegmentSupported
, la lunghezza del pacchetto viene divisa per MSS e ognuno dei pacchetti segmentati contiene MSS byte utente.
Il driver miniport appone le intestazioni MAC, IP e UDP a ogni segmento derivato dal pacchetto grande. 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 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 a MaxOffLoadSize
.
, Dopo che un driver emette un'indicazione di stato per segnalare un cambiamento verso MaxOffLoadSize
, il driver non deve causare un controllo bug se riceve una richiesta di invio LSO che utilizza il precedente valore MaxOffLoadSize
. Anziché, il driver deve far fallire la richiesta di invio. I driver devono non riescono a eseguire qualsiasi richiesta di invio, 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 del valore MaxOffLoadSize
deve garantire che l'adattatore miniport sottostante che non ha emesso un'indicazione di stato non ottenga 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 pronto a gestire un breve periodo di tempo in cui le richieste USO potrebbero ancora raggiungere il driver miniport.
Il numero di pacchetti di segmentazione derivati 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, l'NBL deve essere completato con uno stato di errore. Il miniport può continuare a inviare pacchetti successivi, ma non è necessario farlo. NBL non può essere completato nuovamente in NDIS fino a quando tutti i pacchetti segmentati non siano stati trasmessi o siano falliti.
Anche i driver miniport compatibili con USO devono eseguire le operazioni seguenti:
- Supportare sia IPv4 che IPv6.
- Supportare la replica delle opzioni IPv4 del pacchetto di grandi dimensioni in ogni pacchetto segmentato generato dalla NIC.
- 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 compreso tra 0x0000 e 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 0xFFFE, seguito da 0xFFFF, 0x0000, 0x0001e così via.
- Se il pacchetto UDP di grandi dimensioni contiene opzioni IP, il driver miniport copia queste opzioni, non modificate, in ogni pacchetto derivato dal pacchetto UDP di grandi dimensioni.
- Usa l'offset del 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 conteggio dei byte delle intestazioni ethernet, IP e UDP per ogni segmento di pacchetto e il conteggio dei pacchetti è il numero di segmenti delle dimensioni di 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 usare le funzionalità USO esposte dai driver miniport.
NDIS e il driver miniport eseguono le operazioni seguenti:
- Comunicare 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
.
Consultazione dello stato USO
È possibile consultare lo stato USO corrente con OID_TCP_OFFLOAD_CURRENT_CONFIG. NDIS gestisce questo OID e non lo passa al driver miniport.
Modifica dello stato USO
È possibile abilitare o disabilitare USO tramite OID_TCP_OFFLOAD_PARAMETERS. Dopo che il driver miniport elabora l'OID, deve inviare una segnalazione 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 del parametro | Valore | Descrizione dell'enumerazione |
---|---|---|---|
*UsoIPv4 |
USO (IPv4) | 0 | Disabile |
1 | Abilitato | ||
*UsoIPv6 |
USO (IPV6) | 0 | Disabile |
1 | Abilitato |