Freigeben über


Auslagerung der Segmentierung großer TCP-Pakete

Die Segmentierung großer TCP-Pakete, die größer als die maximale Übertragungseinheit (Maximum Transmission Unit, MTU) des Netzwerkmediums sind, kann von NDIS-Miniporttreibern ausgelagert werden. Eine NIC, die die Segmentierung großer TCP-Pakete unterstützt, muss auch Folgendes können:

  • IP-Prüfsummen für Sendepakete berechnen, die IP-Optionen enthalten.

  • TCP-Prüfsummen für Sendepakete berechnen, die TCP-Optionen enthalten.

NDIS-Versionen 6.0 und höher unterstützen Large Send Offload Version 1 (LSOv1), das Large Send Offload (LSO) in NDIS 5.x ähnelt. NDIS-Versionen 6.0 und höher unterstützen auch Large Send Offload Version 2 (LSOv2), die erweiterte Dienste für die Segmentierung großer Pakete bietet, einschließlich Unterstützung für IPv6.

Ein Miniporttreiber, der LSOv2 und LSOv1 unterstützt, muss den Auslagerungstyp aus den OOB-Informationen der NET_BUFFER_LIST-Struktur bestimmen. Der Treiber kann das Type-Element der NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO-Struktur verwenden, um zu bestimmen, ob der Treiberstapel LSOv2 oder LSOv1 verwendet, und die entsprechenden Auslagerungsdienste ausführen. Jede NET_BUFFER_LIST-Struktur, die die LSOv1- oder LSOv2-OOB-Daten enthält, enthält auch eine einzelne NET_BUFFER-Struktur. Weitere Informationen zu NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO finden Sie unter Zugreifen auf TCP/IP-Auslagerungsinformationen von NET_BUFFER_LIST.

Tritt jedoch der Fall ein, dass der Miniport zum Deaktivieren seiner LSO-Funktion OID_TCP_OFFLOAD_PARAMETERS empfangen hat, und wenn der Miniport die OID erfolgreich abgeschlossen hat, muss er jede NET_BUFFER_LIST löschen, die LSOv1- oder LSOv2-OOB-Daten ungleich null enthält(NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO).

Der TCP/IP-Transport lagert nur die großen TCP-Pakete aus, die die folgenden Kriterien erfüllen:

Bevor der TCP/IP-Transport ein großes TCP-Paket für die Segmentierung auslagert:

  • Bei LSOv1 wird die Gesamtlänge des großen TCP-Pakets in das Feld „Gesamtlänge“ des IP-Headers des Pakets geschrieben. Die Gesamtlänge enthält die Länge des IP-Headers, die Länge der IP-Optionen (sofern vorhanden), die Länge des TCP-Headers, die Länge der TCP-Optionen (sofern vorhanden) und die Länge der TCP-Nutzlast. Bei LSOv2 wird das Feld „Gesamtlänge“ des IP-Headers des Pakets auf 0 festgelegt. Miniporttreiber sollten anhand der Länge der ersten NET_BUFFER-Struktur in der NET_BUFFER_LIST-Struktur die Länge des Pakets bestimmen.

  • Die Einerkomplementsumme für den TCP-Pseudoheader wird berechnet und diese Summe in das Prüfsummenfeld des TCP-Headers geschrieben. Der TCP/IP-Transport berechnet die Einerkomplementsumme über die folgenden Felder im Pseudoheader: Quell-IP-Adresse, Ziel-IP-Adresse und Protokoll. Die Einerkomplementsumme für den vom TCP/IP-Transport bereitgestellten Pseudoheader ermöglicht der NIC eine frühzeitige Berechnung der tatsächlichen TCP-Prüfsumme für jedes Paket, das die NIC vom großen TCP-Paket ableitet, ohne dass der IP-Header untersucht werden muss. RFC 793 schreibt vor, dass die Pseudoheaderprüfsumme über die Quell-IP-Adresse, die Ziel-IP-Adresse, das Protokoll und die TCP-Länge berechnet wird. (Die TCP-Länge entspricht der Länge des TCP-Headers plus der Länge der TCP-Nutzlast. Die TCP-Länge schließt die Länge des Pseudoheaders nicht ein.) Da jedoch der zugrunde liegende Miniporttreiber und die NIC TCP-Segmente aus dem vom TCP/IP-Transport übergebenen großen Paket generieren, erkennt der Transport die Größe der TCP-Nutzlast für jedes TCP-Segment nicht und er kann daher die TCP-Länge nicht in den Pseudoheader aufnehmen. Wie unten beschrieben, erweitert die NIC stattdessen die Pseudoheaderprüfsumme, die vom TCP/IP-Transport bereitgestellt wurde, um die TCP-Länge jedes generierten TCP-Segments zu berücksichtigen.

  • Schreibt die richtige Sequenznummer in das Feld „Sequenznummer“ des TCP-Headers. Die Sequenznummer identifiziert das erste Byte der TCP-Nutzlast.

Nachdem der Miniporttreiber die NET_BUFFER_LIST-Struktur in seiner MiniportSendNetBufferLists- oder MiniportCoSendNetBufferLists-Funktion abgerufen hat, kann er das NET_BUFFER_LIST_INFO-Makro mit einer _Id von TcpLargeSendNetBufferListInfo aufrufen, um den MSS-Wert abzurufen, der vom TCP/IP-Transport geschrieben wurde.

Der Miniporttreiber ruft die Gesamtlänge des großen Pakets aus dem IP-Header des Pakets ab und verwendet den MSS-Wert, um das große TCP-Paket in kleinere Pakete aufzuteilen. Jedes der kleineren Pakete enthält Benutzerdatenbytes der MSS oder weniger. Nur das letzte Paket, das aus dem segmentierten großen Paket erstellt wurde, sollte weniger Benutzerdatenbytes enthalten als die MSS. In allen anderen Pakete, die aus dem segmentierten Paket erstellt wurden, sollten die Benutzerdatenbytes der MSS entsprechen. Wenn Sie dieser Regel nicht folgen, kann die Erstellung und Übertragung unnötiger zusätzlicher Pakete die Leistung beeinträchtigen.

Der Miniporttreiber bringt MAC-, IP- und TCP-Header für jedes Segment an, das vom großen Paket abgeleitet wird. Der Miniporttreiber muss die IP- und TCP-Prüfsummen für diese abgeleiteten Pakete berechnen. Um die TCP-Prüfsumme für jedes Paket zu berechnen, das vom großen TCP-Paket abgeleitet wurde, berechnet die NIC den variablen Teil der TCP-Prüfsumme (für den TCP-Header und die TCP-Nutzlast), fügt diese Prüfsumme der Einerkomplementsumme für den vom TCP/IP-Transport berechneten Pseudoheader hinzu und berechnet dann das 16-Bit-Einerkomplement für die Prüfsumme. Weitere Informationen zum Berechnen solcher Prüfsummen finden Sie unter RFC 793 und RFC 1122.

Die folgende Abbildung zeigt die Segmentierung eines großen Pakets.

Diagramm, das die Segmentierung eines großen TCP-Pakets in kleinere Pakete mit MAC-, IP- und TCP-Headern zeigt.

Die Länge der TCP-Benutzerdaten im großen TCP-Paket sollte dem Wert entsprechen, den der Miniporttreiber dem MaxOffLoadSize-Wert zuweist. Weitere Informationen zum MaxOffLoadSize-Wert finden Sie unter Melden der TCP-Paketsegmentierungsfunktionen einer NIC LSOV1 und Melden der TCP-Paketsegmentierungsfunktionen einer NIC LSOV2.

Nachdem ein Treiber eine Statusanzeige ausgegeben hat, um eine Änderung des MaxOffLoadSize-Werts anzuzeigen, darf der Treiber nicht abstürzen, wenn er eine LSO-Sendeanforderung empfängt, die den vorherigen MaxOffLoadSize-Wert verwendet. Der Treiber kann stattdessen die Sendeanforderung unterlassen.

Ein Zwischentreiber, der unabhängig Statusanzeigen zu Änderungen am MaxOffLoadSize-Wert ausgibt, muss sicherstellen, dass der zugrunde liegende Miniportadapter, der keine Statusanzeige ausgegeben hat, keine Pakete erhält, die größer sind als der MaxOffLoadSize-Wert, den der Miniportadapter gemeldet hat.

Ein Miniport-Zwischentreiber, der auf OID_TCP_OFFLOAD_PARAMETERS reagiert, um LSO-Dienste zu deaktivieren, muss für ein kleines Zeitfenster vorbereitet sein, in dem LSO-Sendeanforderungen weiterhin den Miniporttreiber erreichen können.

Die Länge der TCP-Benutzerdaten in einem Segmentpaket muss kleiner oder gleich der MSS sein. Die MSS ist der ULONG-Wert, den der TCP-Transport mithilfe der LSO-NET_BUFFER_LIST-Informationen übergibt, die der NET_BUFFER_LIST-Struktur zugeordnet sind. Nur das letzte Paket, das aus dem segmentierten großen Paket erstellt wurde, sollte weniger Benutzerdatenbytes enthalten als die MSS. In allen anderen Pakete, die aus dem segmentierten Paket erstellt wurden, sollten die Benutzerdatenbytes der MSS entsprechen. Wenn Sie dieser Regel nicht folgen, kann die Erstellung und Übertragung unnötiger zusätzlicher Pakete die Leistung beeinträchtigen.

Die Anzahl der Segmentpakete, die vom großen TCP-Paket abgeleitet wurden, muss gleich oder größer als der MinSegmentCount-Wert sein, der vom Miniporttreiber angegeben wird. Weitere Informationen zum MinSegmentCount-Wert finden Sie unter Melden der TCP-Paketsegmentierungsfunktionen einer NIC LSOV1 und Melden der TCP-Paketsegmentierungsfunktionen einer NIC LSOV2.

Die folgenden Annahmen und Einschränkungen gelten für die Verarbeitung von IP- und TCP-Headern für jeden LSO-fähigen Miniporttreiber unabhängig von der Version:

  • Das MF-Bit im IP-Header des großen TCP-Pakets, das vom TCP/IP-Transport ausgelagert wurde, wird nicht festgelegt, und der Fragmentoffset im IP-Header ist null.

  • Die URG-, RST- und SYN-Flags im TCP-Header des großen TCP-Pakets werden nicht festgelegt, und der dringende Offset (Zeiger) im TCP-Header ist null.

  • Wenn das FIN-Bit im TCP-Header des großen Pakets festgelegt ist, muss der Miniporttreiber dieses Bit im TCP-Header des letzten Pakets festlegen, das er aus dem großen TCP-Paket erstellt.

  • Wenn das PSH-Bit im TCP-Header des großen TCP-Pakets festgelegt ist, muss der Miniporttreiber dieses Bit im TCP-Header des letzten Pakets festlegen, das er aus dem großen TCP-Paket erstellt.

  • Wenn das CWR-Bit im TCP-Header des großen TCP-Pakets festgelegt ist, muss der Miniporttreiber dieses Bit im TCP-Header des ersten Pakets festlegen, das er aus dem großen TCP-Paket erstellt. Der Miniporttreiber kann dieses Bit im TCP-Header des letzten Pakets festlegen, das er aus dem großen TCP-Paket erstellt, obwohl dies weniger wünschenswert ist.

  • Wenn das große TCP-Paket IP-Optionen oder TCP-Optionen (oder beides) enthält, kopiert der Miniporttreiber diese Optionen unverändert in jedes Paket, das er vom großen TCP-Paket abgeleitet hat. Insbesondere erhöht die NIC die Zeitstempeloption nicht.

  • Alle Paketheader (Ethernet, IP, TCP) befinden sich in der ersten MDL des Pakets. Die Header werden nicht auf mehrere MDLs aufgeteilt.

    Tipp

    Diese Annahme gilt, wenn LSO aktiviert ist. Andernfalls können Miniporttreiber bei deaktiviertem LSO nicht davon ausgehen, dass sich IP-Header in derselben MDL wie Ethernet-Header befinden.

Der Miniporttreiber muss die Pakete in NET_BUFFER_LIST-Strukturen in der Reihenfolge senden, in der er die NET_BUFFER_LIST-Strukturen vom TCP/IP-Transport empfängt.

Bei der Verarbeitung eines großen TCP-Pakets ist der Miniportadapter nur für das Segmentieren des Pakets und das Anbringen von MAC-, IP- und TCP-Headern an die Pakete verantwortlich, die vom großen TCP-Paket abgeleitet werden. Der TCP/IP-Transport führt alle anderen Aufgaben aus (z. B. Größe des Sendefensters der Empfangsfenstergröße des Remotehosts entsprechend anpassen).

Vor Abschluss des Sendevorgangs für das große Paket (z. B. mit NdisMSendNetBufferListsComplete oder NdisMCoSendNetBufferListsComplete) schreibt der Miniporttreiber den NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO-Wert (NET_BUFFER_LIST-Informationen für große Auslagerungen) mit der Gesamtanzahl der TCP-Benutzerdatenbytes, die erfolgreich in allen Paketen gesendet und aus dem großen TCP-Paket erstellt wurden.

Zusätzlich zu den genannten LSO-Anforderungen gilt für LSOv2-fähige Miniporttreiber:

  • IPv4 oder IPv6 oder beide Protokolle werden unterstützt.

  • Die Replikation der IPv4-Optionen aus dem großen Paket in jedem Segmentpaket, das die Netzwerkschnittstelle Karte (NIC) generiert, wird unterstützt.

  • Die Replikation des IPv6-Erweiterungsheaders aus dem großen TCP-Paket in jedem TCP-Segmentpaket wird unterstützt.

  • Die Replikation von TCP-Optionen in jedem TCP-Segmentpaket, das der Miniporttreiber generiert, wird unterstützt.

  • Der IP- und TCP-Header in der NET_BUFFER_LIST-Struktur wird als Vorlage verwendet, um TCP/IP-Header für jedes Segmentpaket zu generieren.

  • IP-Identifikationswerte (IP-ID) im Bereich von 0x0000 bis 0x7FFF werden verwendet. (Der Bereich von 0x8000 bis 0xFFFF ist für Geräte reserviert, die sich für die TCP-Chimney-Auslagerung eignen.) Wenn der IP-Header der Vorlage z. B. mit einem Identifikationsfeldwert 0x7FFE beginnt, muss das erste TCP-Segmentpaket über einen IP-ID-Wert 0x7FFE verfügen, gefolgt von 0x7FFF, 0x0000, 0x0001 usw.

  • Der Byteoffset im TcpHeaderOffset-Element von NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO wird verwendet, um den Speicherort des TCP-Headers zu bestimmen, beginnend mit dem ersten Byte des Pakets.

  • Die Anzahl der NET_BUFFER-Strukturen, die jeder LSOv2-NET_BUFFER_LIST-Struktur zugeordnet sind, ist auf eins beschränkt.

    Hinweis

    Dies ist eine neue Anforderung für LSOv2-fähige Miniporttreiber. Diese Regel wird für LSOv1-Miniporttreiber nicht explizit erzwungen, obwohl sie empfohlen wird.

  • Die Gesamtlänge des Pakets wird anhand der Länge der ersten NET_BUFFER-Struktur in der NET_BUFFER_LIST-Struktur bestimmt. Das ist eine andere Verwendung als bei Methodentreibern für LSOv1.

  • TCP-Optionen, IP-Optionen und IP-Erweiterungsheader werden unterstützt.

  • Wenn ein Sendevorgang abgeschlossen ist, muss der Miniporttreiber das LsoV2TransmitComplete.Reserved-Element der NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO-Struktur auf null und das LsoV2TransmitComplete.Type-Element auf NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE festlegen.