UDP Receive Segment Coalescing Offload (URO)

Ab Windows 11, Version 24H2, ermöglicht UDP Receive Segment Coalescing Offload (URO) Netzwerkschnittstellenkarten (NICs), UDP-Empfangssegmente zusammenzuführen. NICs können UDP-Datagramme aus demselben Fluss kombinieren, der mit einer Reihe von Regeln in einem logisch zusammenhängenden Puffer übereinstimmt. Diese kombinierten Datagramme werden dann als einzelnes großes Paket für den Windows-Netzwerkstapel angegeben.

Durch das Zusammenführen von UDP-Datagrammen wird der CPU-Aufwand für die Verarbeitung von Paketen in Datenströmen mit hoher Bandbreite verringert, was zu einem höheren Durchsatz und weniger Zyklen pro Byte führt.

In den folgenden Abschnitten werden die Regeln zum Zusammenfügen von UDP-Paketen und zum Schreiben eines URO-Miniport-Treibers beschrieben.

Regeln für das Zusammenfügen von UDP-Paketen

Die URO-Zusammenführung kann nur bei Paketen versucht werden, die alle folgenden Kriterien erfüllen:

  • IpHeader.Version ist für alle Pakete identisch.
  • IpHeader.SourceAddress und IpHeader.DestinationAddress sind für alle Pakete identisch.
  • UdpHeader.SourcePort und UdpHeader.DestinationPort sind für alle Pakete identisch.
  • UdpHeader.Length ist für alle Pakete identisch, mit Ausnahme des letzten Pakets, das kleiner sein kann.
  • UdpHeader.Length muss ungleich Null sein.
  • UdpHeader.Checksum, wenn ungleich Null, muss es bei allen Paketen korrekt sein. Dies bedeutet, dass der Empfang der Prüfsummenauslagerung das Paket überprüfen muss.
  • Ebene 2-Header müssen für alle Pakete identisch sein.

Wenn die Pakete IPv4 sind, müssen sie auch die folgenden Kriterien erfüllen:

  • IPv4Header.Protocol == 17 (UDP) für alle Pakete.
  • EthernetHeader.EtherType == 0x0800 für alle Pakete.
  • Die IPv4Header.HeaderChecksum für empfangene Pakete muss korrekt sein. Dies bedeutet, dass der Empfang der Prüfsummenauslagerung den Header überprüfen muss.
  • IPv4Header.HeaderLength == 5 (no IPv4 Option Headers) für alle Pakete.
  • IPv4Header.ToS ist für alle Pakete identisch.
  • IPv4Header.ECN ist für alle Pakete identisch.
  • IPv4Header.DontFragment ist für alle Pakete identisch.
  • IPv4Header.TTL ist für alle Pakete identisch.
  • IPv4Header.TotalLength == UdpHeader.Length + length(IPv4Header) für alle Pakete.

Wenn die Pakete IPv6 sind, müssen sie auch die folgenden Kriterien erfüllen:

  • IPv6Header.NextHeader == 17 (UDP) für alle Pakete (keine Erweiterungs-Header).
  • EthernetHeader.EtherType == 0x86dd (IPv6) für alle Pakete.
  • IPv6Header.TrafficClass und IPv6Header.ECN sind für alle Pakete identisch.
  • IPv6Header.FlowLabel ist für alle Pakete identisch.
  • IPv6Header.HopLimit ist für alle Pakete identisch.
  • IPv6Header.PayloadLength == UdpHeader.Length für alle Pakete.

URO-Paketstruktur

Die resultierende Single Coalesced Unit (SCU) muss einen einzelnen IP-Header und UDP-Header haben, gefolgt von der UDP-Nutzlast für alle zusammengefügten Datagramme.

URO-Angaben müssen das IPv4Header.TotalLength-Feld auf die Gesamtlänge der SCU oder das IPv6Header.PayloadLength-Feld auf die Länge der UDP-Nutzlast und das UdpHeader.Length-Feld auf die Länge der zusammengeführten Nutzlasten festlegen.

Wenn in zusammengefügten Datagrammen Ebene-2-Header (L2) vorhanden sind, muss die SCU einen gültigen L2-Header enthalten. Die L2-Kopfzeile in der SCU muss der L2-Kopfzeile der zusammengefügten Datagramme ähneln.

Prüfsummenüberprüfung und -angabe

URO-Angaben müssen die Felder IPv4Header.HeaderChecksum und UdpHeader.Checksum auf Null festlegen und die Out-of-Band-Informationen der Prüfsummenauslagerung auf der SCU ausfüllen, um eine erfolgreiche IPv4- und UDP-Prüfsumme anzuzeigen.

Ein Paket, das alle Bedingungen zum Zusammenführen erfüllt, aber die Prüfsummenüberprüfung nicht besteht, muss separat angegeben werden. Danach empfangene Pakete dürfen nicht mit davor empfangenen Paketen zusammengeführt werden.

Angenommen, die Pakete 1, 2, 3, 4 und 5 werden aus demselben Datenfluss empfangen, aber Paket 3 besteht die Prüfsummenüberprüfung nicht. Die Pakete 1 und 2 können zusammengeführt werden, und die Pakete 4 und 5 können zusammengeführt werden, aber Paket 3 darf mit keiner der SCUs zusammengeführt werden. Die Pakete 1 und 2 dürfen nicht mit den Paketen 4 und 5 zusammengeführt werden. Paket 2 ist das letzte Paket in einer SCU und Paket 4 startet eine neue SCU. Darüber hinaus muss die SCU mit den Paketen 1 und 2 vor der Anzeige von Paket 3 und Paket 3 vor der SCU mit den Paketen 4 und 5 angezeigt werden.

Paketzusammenführung und Flusstrennung

Pakete aus mehreren Flüssen können parallel zusammengeführt werden, sofern Hardware und Speicher dies zulassen. Pakete aus unterschiedlichen Flüssen dürfen nicht zusammengeführt werden.

Pakete aus mehreren verschachtelten Empfängern können getrennt und mit ihren jeweiligen Datenströmen zusammengeführt werden. Wenn beispielsweise bei den Flüssen A, B und C Pakete in der Reihenfolge A, A, B, C, B, A ankommen, können die Pakete aus dem Fluss A zu AAA und die Pakete aus dem Fluss B zu BB zusammengeführt werden, während das Paket aus dem Fluss C normal angezeigt oder mit einer ausstehenden SCU aus Fluss C zusammengeführt werden kann.

Die Pakete innerhalb eines bestimmten Flusses dürfen nicht in Bezug zueinander neu angeordnet werden. Beispielsweise müssen die Pakete aus dem A-Fluss in der empfangenen Reihenfolge zusammengeführt werden, unabhängig von den dazwischen empfangenen Paketen aus den B- und C-Flüssen.

INF-Schlüsselwort für die Steuerung von URO

Das folgende Schlüsselwort kann verwendet werden, um URO mit einer Registrierungsschlüsseleinstellung zu aktivieren/deaktivieren.

*UdpRsc

Aufzählungsstandardisierte INF-Schlüsselwörter haben die folgenden Attribute:

Name des Unterschlüssels
Der Name der Schlüsselworts, die Sie in der INF-Datei angeben müssen und die in der Registrierung angezeigt wird.

ParamDesc
Der Anzeigetext, der mit "SubkeyName" verknüpft ist.

Wert
Der ganzzahlige Enumerationswert, der jeder Option in der Liste zugeordnet ist. Dieser Wert wird in NDI\params\ SubkeyName\Value gespeichert.

EnumDesc
Der Anzeigetext, der jedem Wert zugeordnet ist, der im Menü angezeigt wird.

Standard
Der Standardwert für das Menü.

Name des Unterschlüssels ParamDesc Wert EnumDesc
*UdpRsc URO 0 Disabled
1 (Standard) Aktiviert

Weitere Informationen zur Verwendung von Enumerationsschlüsselwörtern finden Sie unter Enumerationsschlüsselwörter.

Schreiben eines URO-Miniport-Treibers

Ab NDIS 6.89 erleichtert die NDIS-Schnittstelle für URO die Kommunikation zwischen TCP/IP und dem NDIS-Miniport-Treiber.

Melden der URO-Funktion

Ein Miniport-Treiber kündigt Unterstützung für URO im UdpRsc-Mitglied der NDIS_OFFLOAD-Struktur an, die es an die NdisMSetMiniportAttributes-Funktion übergibt.

Abfragen der URO-Funktion

Um zu überprüfen, ob ein Miniport-Treiber URO unterstützt, können NDIS-Treiber und andere Anwendungen den OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES-OID abfragen, der die NDIS_OFFLOAD-Struktur wiedergibt.

Abfragen des URO-Status

Um den aktuellen URO-Zustand zu ermitteln, können NDIS-Treiber und andere Anwendungen die OID_TCP_OFFLOAD_CURRENT_CONFIG-OID-Anforderung abfragen. NDIS verarbeitet diese OID und gibt sie nicht an den Miniport weiter.

Ändern des URO-Status

URO kann durch Ausgabe der OID_TCP_OFFLOAD_PARAMETERS-OID-Anforderung aktiviert oder deaktiviert werden. Diese OID verwendet eine NDIS_OFFLOAD_PARAMETERS-Struktur. In dieser Struktur kann das UdpRsc.Enabled-Mitglied die folgenden Werte aufweisen:

Wert Bedeutung
NDIS_OFFLOAD_PARAMETERS_UDP_RSC_NO_CHANGE
0
Der Miniport-Treiber sollte die aktuelle Einstellung nicht ändern.
NDIS_OFFLOAD_PARAMETERS_UDP_RSC_DISABLED
1
Gültigkeitsdauer (URO) ist deaktiviert.
NDIS_OFFLOAD_PARAMETERS_UDP_RSC_ENABLED
2
Gültigkeitsdauer (URO) ist aktiviert.

Wenn ein Treiber eine OID_TCP_OFFLOAD_PARAMETERS-OID-Anforderung mit gesetztem NDIS_OFFLOAD_PARAMETERS_UDP_RSC_DISABLED-Flag verarbeitet, muss die Netzwerkschnittstellenkarte mit der Ausführung der Anforderung warten, bis alle vorhandenen zusammengeführten Segmente und ausstehenden URO-Anzeigen angezeigt sind. Dadurch wird die Synchronisierung von URO-Aktivierungs-/Deaktivierungsereignissen über alle NDIS-Komponenten hinweg sichergestellt.

Nachdem der Miniport-Treiber die OID_TCP_OFFLOAD_PARAMETERS-OID-Anforderung verarbeitet, muss der Miniport-Treiber eine NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG-Statusanzeige mit aktualisiertem Auslagerungsstatus ausgeben.

Das NDIS_OFFLOAD_PARAMETERS_SKIP_REGISTRY_UPDATE-Flag in NDIS_OFFLOAD_PARAMETERS ermöglicht die ausschließlich zur Laufzeit erfolgende Deaktivierung von URO. Änderungen, die mit diesem Flag vorgenommen wurden, werden nicht in der Registrierung gespeichert.

Deaktivieren von URO in NDIS 6.89 und höher

Treiber für NDIS 6.89 und höher sollten URO-Pakete verstehen und ordnungsgemäß verarbeiten. So deaktivieren Sie URO:

Dieser Ansatz stellt sicher, dass Komponenten, die mit URO nicht vertraut sind, keine URO-NBLs erhalten. NDIS deaktiviert URO auf dem Miniport während der Bindung, wenn ein LWF- oder Protokolltreiber vorhanden ist, der URO nicht unterstützt.

Überlegungen zur Programmierung für URO-Treiber

Berücksichtigen Sie bei der Implementierung eines URO-fähigen Miniport-Treibers die folgenden Probleme.

Winsock URO-API

Informationen zur Winsock URO-API finden Sie unter IPPROTO_UDP-Socketoptionen. Sehen Sie sich die Informationen zu UDP_RECV_MAX_COALESCED_SIZE und UDP_COALESCED_INFO an.

Windows TCP/IP-Stapelupdates

Der Microsoft TCP/IP-Transport aktiviert URO zum Zeitpunkt der Bindung mit NDIS, sofern die Konfiguration dies nicht verhindert.

WFP-Callouts können FWP_CALLOUT_FLAG_ALLOW_URO in FWPS_CALLOUT2 verwenden, um ihre Unterstützung für URO anzukündigen. Wenn ein inkompatibler WFP-Callout auf einer URO-sensitiven Ebene registriert ist, deaktiviert das Betriebssystem URO, während der Callout registriert ist.

Wenn sich ein Socket für URO mit einer maximalen zusammengefügten Größe entscheidet, die größer oder gleich der Hardware-Auslagerungsgröße ist, stellt der Stapel die NBLs unverändert von der Hardware an das Socket bereit. Wenn sich ein Socket für eine kleinere maximale zusammengefügte Größe entscheidet, teilt der Stapel den zusammengefügten Empfang auf die kleinere Größe für den Socket auf.

Wenn sich ein Socket nicht für URO entscheidet, wird der Stapel für dieses Socket erneut segmentiert. Ohne Hardware-URO ist die vorhandene Software-URO-Funktion weiterhin verfügbar.