Condividi tramite


Udp Receive Segment Coalescing Offload (URO)

A partire da Windows 11 versione 24H2, UDP Receive Segment Coalescing Offload (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.

L'unione di datagrammi UDP riduce il costo della CPU per elaborare i pacchetti in flussi a larghezza di banda elevata, con conseguente 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. Ciò significa che l'offload checksum di ricezione deve convalidare il pacchetto.
  • Le intestazioni di livello 2 devono essere identiche 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.
  • IPv4Header.HeaderChecksum nei 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 (nessuna intestazione 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

L'unità single coalesced (SCU) risultante deve avere una singola intestazione IP e un'intestazione UDP, seguita dal payload UDP per tutti i datagrammi uniti concatenati.

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

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 essere simile all'intestazione L2 dei datagrammi uniti.

Convalida e indicazione checksum

Le indicazioni URO devono impostare i campi IPv4Header.HeaderChecksum e UdpHeader.Checksum su zero e compilare le informazioni di offload out-of-band sull'SCU che indicano l'esito positivo del checksum IPv4 e UDP.

È necessario indicare separatamente un pacchetto che corrisponde a tutte le condizioni per l'unione, ma la convalida del checksum non riesce. 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 più flussi possono essere uniti in parallelo, perché l'hardware e la memoria consentono. I pacchetti provenienti da flussi diversi non devono essere uniti.

I pacchetti di più ricevute interleaved possono essere separati e uniti con i rispettivi flussi. Ad esempio, i flussi A, B e C, se i pacchetti arrivano nell'ordine A, A, B, C, B, A, A, I pacchetti del flusso A possono essere uniti in AAA e i pacchetti del flusso B uniti in BB, mentre il pacchetto dal flusso C può essere indicato normalmente o unito a un SCU in sospeso dal 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 ricevuto, indipendentemente dai pacchetti dei flussi B e C ricevuti tra.

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

Le parole chiave INF standardizzate dell'enumerazione hanno gli attributi 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 di enumerazione associato a ogni opzione nell'elenco. Questo valore viene archiviato in NDI\params\ SubkeyName\Value.

EnumDesc
Testo visualizzato associato a ogni valore visualizzato nel menu.

Default
Valore predefinito per il menu.

SubkeyName ParamDesc Valore EnumDesc
*UdpRsc URO 0 Disabilitata
1 (impostazione predefinita) Attivata

Per altre informazioni sull'uso delle parole chiave di enumerazione, vedere Enumeration Keywords.For more information about using enumeration keywords, see Enumeration Keywords.

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.

Funzionalità URO report

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

Funzionalità URO di query

Per verificare se un driver miniport supporta URO, i driver NDIS e altre applicazioni possono eseguire 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 eseguire query sulla 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 inviando la richiesta OID OID_TCP_OFFLOAD_PARAMETERS . Questo OID usa 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 è disabilitato.
NDIS_OFFLOAD_PARAMETERS_UDP_RSC_ENABLED
2
L'URO è abilitato.

Quando un driver elabora una richiesta OID OID_TCP_OFFLOAD_PARAMETERS con il NDIS_OFFLOAD_PARAMETERS_UDP_RSC_DISABLED flag 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 OID OID_TCP_OFFLOAD_PARAMETERS , il driver miniport deve emettere un'indicazione di stato NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG con lo stato di offload aggiornato.

Il NDIS_OFFLOAD_PARAMETERS_SKIP_REGISTRY_UPDATE flag in NDIS_OFFLOAD_PARAMETERS consente la disabilitazione di sola fase dell'URO. 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 destinati a NDIS 6.89 e versioni successive devono comprendere i pacchetti URO e gestirli normalmente. Per rifiutare esplicitamente l'URO:

Questo approccio garantisce che i componenti che non hanno familiarità con l'URO non ricevano gli NCL 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 IPPROTO_UDP opzioni socket. 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 in fase di associazione con NDIS, a meno che la configurazione non ne impedisca l'esecuzione.

I callout WFP possono usare FWP_CALLOUT_FLAG_ALLOW_URO in FWPS_CALLOUT2 per pubblicizzare il loro supporto per l'URO. Se un callout WFP incompatibile viene registrato a un livello sensibile all'URO, il sistema operativo disabiliterà 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 di unione più piccola, lo stack interromperà la ricezione coalesced nella dimensione inferiore per il socket.

Se un socket non acconsente esplicitamente all'URO, lo stack riceverà di nuovo per tale socket. In assenza di URO hardware, la funzionalità URO software esistente continuerà a essere disponibile.