Condividi tramite


Offload di coalescenza dei segmenti di ricezione UDP (URO)

A partire da Windows 11, versione 24H2, il coalescing offload dei segmenti di ricezione UDP (URO) consente alle schede di interfaccia di rete (NIC) di unire i segmenti di ricezione UDP. Le schede di interfaccia di rete possono combinare datagrammi UDP dello stesso flusso che corrispondono a un set di regole in un buffer logicamente contiguo. Questi datagrammi combinati vengono quindi indicati allo stack di rete di Windows come singolo pacchetto di grandi dimensioni.

La coalescenza di datagrammi UDP riduce il costo della CPU per elaborare i pacchetti in flussi ad alto consumo di banda, risultando in una maggiore velocità effettiva e un minor numero di cicli per byte.

Le sezioni seguenti descrivono le regole per unire pacchetti UDP e come scrivere un driver miniport URO.

Regole per l'unione di pacchetti UDP

L'unione dell'URO può essere tentata solo sui pacchetti che soddisfano tutti i criteri seguenti:

  • IpHeader.Version è identico per tutti i pacchetti.
  • IpHeader.SourceAddress e IpHeader.DestinationAddress sono identici per tutti i pacchetti.
  • UdpHeader.SourcePort e UdpHeader.DestinationPort sono identici per tutti i pacchetti.
  • UdpHeader.Length è identico per tutti i pacchetti, ad eccezione dell'ultimo pacchetto, che può essere minore.
  • UdpHeader.Length deve essere diverso da zero.
  • UdpHeader.Checksum, se diverso da zero, deve essere corretto in tutti i pacchetti. Questo significa che il checksum offload di ricezione deve convalidare il pacchetto.
  • Layer 2 headers deve essere identico per tutti i pacchetti.

Se i pacchetti sono IPv4, devono soddisfare anche i criteri seguenti:

  • IPv4Header.Protocol == 17 (UDP) per tutti i pacchetti.
  • EthernetHeader.EtherType == 0x0800 per tutti i pacchetti.
  • Il IPv4Header.HeaderChecksum sui pacchetti ricevuti deve essere corretto. Ciò significa che l'offload checksum di ricezione deve convalidare l'intestazione.
  • IPv4Header.HeaderLength == 5 (nessuna intestazione di opzione IPv4) per tutti i pacchetti.
  • IPv4Header.ToS è identico per tutti i pacchetti.
  • IPv4Header.ECN è identico per tutti i pacchetti.
  • IPv4Header.DontFragment è identico per tutti i pacchetti.
  • IPv4Header.TTL è identico per tutti i pacchetti.
  • IPv4Header.TotalLength == UdpHeader.Length* + length(IPv4Header) per tutti i pacchetti.

Se i pacchetti sono IPv6, devono soddisfare anche i criteri seguenti:

  • IPv6Header.NextHeader == 17 (UDP) per tutti i pacchetti (senza header di estensione).
  • EthernetHeader.EtherType == 0x86dd (IPv6) per tutti i pacchetti.
  • IPv6Header.TrafficClass e IPv6Header.ECN sono identici per tutti i pacchetti.
  • IPv6Header.FlowLabel è identico per tutti i pacchetti.
  • IPv6Header.HopLimit è identico per tutti i pacchetti.
  • IPv6Header.PayloadLength == UdpHeader.Length per tutti i pacchetti.

Struttura di pacchetti URO

La singola unità unificata (SCU) risultante deve avere una singola intestazione IP e un'intestazione UDP, seguita dal payload UDP di tutti i datagrammi uniti concatenati.

Le indicazioni URO devono impostare il campo IPv4Header.TotalLength sulla lunghezza totale dell'SCU, il campo IPv6Header.PayloadLength sulla lunghezza del payload UDP e il campo UdpHeader.Length sulla lunghezza dei payload coalescenti.

Se le intestazioni di livello 2 (L2) sono presenti in datagrammi uniti, l'SCU deve contenere un'intestazione L2 valida. L'intestazione L2 nell'SCU deve assomigliare all'intestazione L2 dei datagrammi combinati.

Verifica e segnalazione checksum

Le indicazioni URO devono impostare i campi IPv4Header.HeaderChecksum e UdpHeader.Checksum su zero e compilare le informazioni di offload del checksum fuori banda nell'SCU che indica l'esito positivo dei checksum IPv4 e UDP.

È necessario indicare separatamente un pacchetto che corrisponde a tutte le condizioni per essere coalescato, ma che non supera la convalida del checksum. I pacchetti ricevuti dopo non devono essere uniti con pacchetti ricevuti prima.

Si supponga, ad esempio, che i pacchetti 1, 2, 3, 4 e 5 vengano ricevuti dallo stesso flusso, ma il pacchetto 3 non riesce a convalidare il checksum. I pacchetti 1 e 2 possono essere uniti e i pacchetti 4 e 5 possono essere uniti insieme, ma i pacchetti 3 non devono essere uniti con SCU. I pacchetti 1 e 2 non devono essere uniti insieme a pacchetti 4 e 5. Il pacchetto 2 è l'ultimo pacchetto in un pacchetto SCU e il pacchetto 4 avvia una nuova SCU. Inoltre, l'SCU contenente pacchetti 1 e 2 deve essere indicato prima che il pacchetto 3 sia indicato e il pacchetto 3 deve essere indicato prima della SCU contenente pacchetti 4 e 5.

Unione dei pacchetti e separazione dei flussi

I pacchetti di flussi multipli possono essere uniti in parallelo, nella misura in cui lo consentono l'hardware e la memoria. I pacchetti provenienti da flussi diversi non devono essere uniti.

I pacchetti provenienti da più ricezioni intercalate possono essere separati e uniti ai rispettivi flussi. Ad esempio, dati i flussi A, B e C, se i pacchetti arrivano nell'ordine A, A, B, C, B, A, i pacchetti del flusso A possono essere uniti in AAA e i pacchetti del flusso B uniti in BB, mentre il pacchetto del flusso C può essere indicato normalmente oppure unito con uno SCU in sospeso del flusso C.

I pacchetti all'interno di un determinato flusso non devono essere riordinati rispetto agli altri. Ad esempio, i pacchetti del flusso A devono essere uniti nell'ordine in cui sono stati ricevuti, indipendentemente dai pacchetti dei flussi B e C ricevuti nel frattempo.

Parola chiave INF per il controllo dell'URO

La parola chiave seguente può essere usata per abilitare/disabilitare l'URO con un'impostazione della chiave del Registro di sistema:

  • *UdpRsc

Gli attributi delle parole chiave INF standardizzate dall'enumerazione sono i seguenti:

  • SubkeyName: nome della parola chiave che è necessario specificare nel file INF e visualizzato nel Registro di sistema.

  • ParamDesc: testo visualizzato associato a SubkeyName.

  • Valore: valore intero dell'enumerazione associato a ogni opzione nell'elenco. Questo valore viene archiviato in NDI\params\SubkeyName\Value.

  • EnumDesc: Il testo visualizzato associato a ciascun valore che appare nel menu.

  • Valore predefinito: Il valore predefinito per il menu.

SubkeyName ParamDesc Valore EnumDesc
*UdpRsc URO 0 Disabile
1 (impostazione predefinita) Abilitato

Per altre informazioni sull'uso delle parole chiave di enumerazione, vedere parole chiave di enumerazione.

Scrivere un driver miniport URO

A partire da NDIS 6.89, l'interfaccia NDIS per URO facilita la comunicazione tra TCP/IP e il driver miniport NDIS.

Report capacità URO

Un driver miniport annuncia il supporto per URO nel membro UdpRsc della struttura NDIS_OFFLOAD, che passa alla funzione NdisMSetMiniportAttributes.

Query della funzionalità URO

Per verificare se un driver miniport supporta URO, i driver NDIS e altre applicazioni possono fare una query sull'OID OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES, che restituisce la struttura NDIS_OFFLOAD.

Eseguire query sullo stato dell'URO

Per determinare lo stato URO corrente, i driver NDIS e altre applicazioni possono interrogare la richiesta OID OID_TCP_OFFLOAD_CURRENT_CONFIG. NDIS gestisce questo OID e non lo passa al miniport.

Modificare lo stato dell'URO

L'URO può essere abilitato o disabilitato emettendo la richiesta OID OID_TCP_OFFLOAD_PARAMETERS. Questo OID utilizza una struttura NDIS_OFFLOAD_PARAMETERS. In questa struttura il membro UdpRsc.Enabled può avere i valori seguenti:

Valore Significato
NDIS_OFFLOAD_PARAMETERS_UDP_RSC_NO_CHANGE
0
Il driver miniport non deve modificare l'impostazione corrente.
NDIS_OFFLOAD_PARAMETERS_UDP_RSC_DISABLED
1
L'URO è disattivato.
NDIS_OFFLOAD_PARAMETERS_UDP_RSC_ENABLED
2
L'URO è abilitato.

Quando un driver elabora una richiesta OID OID_TCP_OFFLOAD_PARAMETERS con il flag NDIS_OFFLOAD_PARAMETERS_UDP_RSC_DISABLED impostato, la scheda di interfaccia di rete deve attendere il completamento della richiesta fino a quando non vengono indicati tutti i segmenti uniti esistenti e le indicazioni URO in sospeso. In questo modo si garantisce la sincronizzazione degli eventi di abilitazione/disabilitazione dell'URO nei componenti NDIS.

Dopo che il driver miniport elabora la richiesta dell'OID OID_TCP_OFFLOAD_PARAMETERS, il driver miniport deve fornire un'indicazione di stato NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG con lo stato di offload aggiornato.

Il flag NDIS_OFFLOAD_PARAMETERS_SKIP_REGISTRY_UPDATE in NDIS_OFFLOAD_PARAMETERS consente la disabilitazione di URO solo in fase di esecuzione. Le modifiche apportate con questo flag non vengono salvate nel Registro di sistema.

Rifiutare esplicitamente l'URO in NDIS 6.89 e versioni successive

I driver che puntano a NDIS 6.89 e versioni successive devono comprendere i pacchetti URO e gestirli in modo efficace. Per rinunciare all'iscrizione all'URO:

Questo approccio garantisce che i componenti che non sono familiari con URO non ricevano gli NBL URO. NDIS disabilita l'URO nel miniport durante l'associazione se è presente un driver di protocollo o LWF che non supporta URO.

Considerazioni sulla programmazione per i driver URO

Quando si implementa un driver miniport con supporto per l'URO, tenere presente quanto segue.

Winsock URO API

Per informazioni sull'API Winsock URO, vedere opzioni socket IPPROTO_UDP. Vedere le informazioni su UDP_RECV_MAX_COALESCED_SIZE e UDP_COALESCED_INFO.

Aggiornamenti dello stack TCP/IP di Windows

Il trasporto TCP/IP Microsoft abilita l'URO al momento della connessione con NDIS, a meno che la configurazione ne impedisca l'abilitazione.

I callout WFP possono usare FWP_CALLOUT_FLAG_ALLOW_URO in FWPS_CALLOUT2 per annunciare il loro supporto per l'URO. Se un callout WFP incompatibile viene registrato a un livello sensibile all'URO, il sistema operativo disabilita l'URO mentre il callout è registrato.

Se un socket acconsente esplicitamente all'URO con una dimensione massima di unione maggiore o uguale alla dimensione di offload hardware, lo stack distribuirà gli NCL dall'hardware non modificato al socket. Se un socket opta per una dimensione massima aggregata più piccola, lo stack suddivide la ricezione aggregata nella dimensione più ridotta per il socket.

Se un socket non acconsente esplicitamente all'URO, lo stack reinvia le ricevute per tale socket. In assenza di URO hardware, la funzionalità URO software esistente continua a essere disponibile.