Freigeben über


Paketdeskriptoren und -erweiterungen

In NetAdapterCx sind Paketdeskriptoren kleine, kompakte, laufzeiterweiterbare Strukturen, die ein Netzwerkpaket beschreiben. Für jedes Paket ist Folgendes erforderlich:

  • Ein Kerndeskriptor
  • Mindestens ein Fragmentdeskriptor
  • Keine oder mehr Paketerweiterungen

Der Kerndeskriptor des Pakets ist die NET_PACKET-Struktur . Es enthält nur die grundlegendsten Metadaten, die für alle Pakete gelten, z. B. das Rahmenlayout eines bestimmten Pakets und den Index zum ersten Fragmentdeskriptor des Pakets.

Jedes Paket muss außerdem über einen oder mehrere Fragmentdeskriptoren oder NET_FRAGMENT Strukturen verfügen, die den Speicherort im Systemspeicher beschreiben, an dem sich die Paketdaten befinden.

Erweiterungen sind optional und enthalten Paket- oder Fragmentmetadaten für szenariospezifische Features. Für instance können Paketerweiterungen Auslagerungsinformationen für Prüfsummen, große Sendeauslagerung (Large Send Offload, LSO) und Empfangssegment-Koaleszenz (RSC) enthalten oder anwendungsspezifische Details enthalten. Fragmenterweiterungen können virtuelle Adressinformationen, logische DMA-Adressinformationen oder andere Informationen für das Fragment enthalten.

Zusammen enthalten diese Deskriptoren und Erweiterungen alle Metadaten zu einem Netzwerkpaket. Im Folgenden finden Sie zwei Beispiele für die Beschreibung eines Pakets. Die erste Abbildung zeigt ein Szenario, in dem das gesamte Paket in einem einzelnen Speicherfragment gespeichert wird und die Prüfsummenauslagerung aktiviert wurde.

Diagramm, das ein Paketlayout mit 1 Fragment und 1 Erweiterung zeigt.

Die zweite Abbildung zeigt ein Paket, das über zwei Speicherfragmente gespeichert ist, wobei sowohl RSC als auch Prüfsummenauslagerung aktiviert sind.

Diagramm, das ein Paketlayout mit 2 Fragmenten und 2 Erweiterungen zeigt.

Speicher und Zugriff auf paketdeskriptor

Paketdeskriptoren und Fragmentdeskriptoren werden beide in NET_RING Strukturen gespeichert. Ein NIC-Clienttreiber greift auf die Netzringe zu und führt Vorgänge für diese aus, indem er die Net Ring Iterator-Schnittstelle aufruft, wodurch der Treiber mit NetAdapterCx arbeiten kann, um Netzwerkdaten auf der Hardware zu posten und abgeschlossene Daten wieder an das Betriebssystem zu übertragen.

Weitere Informationen zu Netzringen und der Net Ring Iterator-Schnittstelle finden Sie unter Einführung in Netzringe.

Erweiterbarkeit des Paketdeskriptors

Erweiterbarkeit ist ein Kernfeature des NetAdapterCx-Paketdeskriptors und bildet die Grundlage für die Versions- und Leistungsfähigkeit des Deskriptors. Zur Laufzeit ordnet das Betriebssystem alle Paketdeskriptoren für jede Paketwarteschlange in einem zusammenhängenden Block zusammen mit allen verfügbaren Erweiterungen zu. Jeder Erweiterungsblock befindet sich unmittelbar hinter dem Kerndeskriptor, wie in der folgenden Abbildung dargestellt:

Diagramm, das das NetAdapterCx-Paketdeskriptorlayout mit drei Erweiterungsblöcken zeigt.

NIC-Clienttreiber dürfen den Offset nicht mit einem Erweiterungsblock hartcodieren. Stattdessen müssen sie zur Laufzeit den Offset für eine bestimmte Erweiterung abfragen. Beispielsweise könnte ein Treiber den Offset auf Erweiterung B abfragen und wie in der folgenden Abbildung 70 Bytes zurückerhalten:

Diagramm, das das Abfragen des Offsets für eine Erweiterung des Kernpaketdeskriptors zeigt.

Sobald eine Paketwarteschlange und ihre Deskriptoren erstellt wurden, werden alle ihre Erweiterungsoffsets vom System als konstant garantiert, sodass Treiber Offsets nicht häufig erneut abfragen müssen. Da außerdem alle Erweiterungen zum Zeitpunkt der Paketwarteschlange initialisiert vom System in einem Block vorab zugeordnet sind, ist keine Laufzeitzuordnung von Blöcken, das Durchsuchen einer Liste nach einem bestimmten Deskriptor oder das Speichern von Zeigern auf jede Paketerweiterung erforderlich.

Versionsierbarkeit des Paketdeskriptors

Der Kernpaketdeskriptor von NetAdapterCx kann in zukünftigen Versionen problemlos erweitert werden, indem neue Felder am Ende hinzugefügt werden, z. B. in der folgenden Abbildung:

Diagramm: NetAdapterCx-Kernpaketdeskriptorversionsverwaltung

Neuere Clienttreiber, die mit den V2-Feldern vertraut sind, können auf sie zugreifen, während ältere V1-Treiber Erweiterungsoffsets verwenden, um die V2-Felder zu überspringen, damit sie auf die Felder zugreifen können, die sie verstehen. Darüber hinaus kann jede Erweiterung auf die gleiche Weise versioniert werden, wie in der folgenden Abbildung gezeigt:

Diagramm, das die Versionsverwaltung der NetAdapterCx-Paketerweiterung zeigt.

Ein Clienttreiber, der die neue Erweiterung versteht, kann sie verwenden. Andere Clienttreiber können die neuen Felder überspringen. Dadurch können verschiedene Teile des Paketdeskriptors unabhängig voneinander versioniert werden.

Paketdeskriptoren und Datenpfadleistung

Das zuvor beschriebene Erweiterbarkeitsfeature bietet Vorteile, um Clienttreibern dabei zu helfen, die Leistungsanforderungen von NICs zu erfüllen, die auf Hunderte von Gigabit pro Sekunde mit Tausenden von Warteschlangen begrenzt sind:

  1. Die Paketdeskriptoren werden so kompakt wie möglich gehalten, um CPU-Cachetreffer zu verbessern, da features und Erweiterungen, die nicht verwendet werden, 0 Byte Speicherplatz in den Deskriptoren belegen.
  2. Es gibt keine Zeigerdereferenzierung, nur Offsetarithmetik, da Erweiterungen inline sind, was nicht nur Speicherplatz spart, sondern auch bei CPU-Cachetreffern hilft.
  3. Erweiterungen werden zum Zeitpunkt der Warteschlangenerstellung zugeordnet, sodass Treiber keinen Arbeitsspeicher im aktiven Datenpfad zuweisen und die Zuordnung aufheben müssen oder sich mit Lookaside-Listen von Kontextblöcken befassen müssen.

Verwenden von Paketerweiterungen

Registrieren von Paketerweiterungen

Der erste Schritt bei der Arbeit mit Paketerweiterungen in Ihrem NIC-Clienttreiber besteht darin, Ihre unterstützten Hardwareauslagerungen zu deklarieren. Wenn Sie die Unterstützung für Auslagerungen wie Prüfsummen und LSO ankündigen, registriert NetAdapterCx automatisch die zugehörigen Paketerweiterungen in Ihrem Namen.

Ein Codebeispiel zum Anzeigen von Hardwareauslagerungen finden Sie unter Einführung in Hardwareauslagerungen.

Abfragen von Paketerweiterungsoffsets für Datapath-Warteschlangen

Nachdem Sie Paketerweiterungen registriert haben, indem Sie Die Hardwareauslagerungsunterstützung deklariert haben, benötigen Sie die Erweiterungsoffsets, um während der Verarbeitung Ihrer Pakete auf die einzelnen Erweiterungen zuzugreifen. Um Aufrufe aus Dem Treiber zu reduzieren und die Leistung zu verbessern, können Sie die Offsets für Ihre Erweiterungen während der Rückruffunktion EvtNetAdapterCreateTx(Rx)Queue abfragen und die Offsetinformationen in Ihrem Warteschlangenkontext speichern.

Ein Beispiel für das Abfragen von Erweiterungsoffsets und deren Speicherung im Warteschlangenkontext finden Sie unter Übertragen und Empfangen von Warteschlangen.

Abrufen von Paketerweiterungen zur Laufzeit

Nachdem Sie Erweiterungsoffsets in Ihrem Warteschlangenkontext gespeichert haben, können Sie sie jederzeit verwenden, wenn Sie Informationen in einer Erweiterung benötigen. Sie können beispielsweise die NetExtensionGetPacketChecksum-Methode aufrufen, während Sie Deskriptoren für eine Übertragungswarteschlange auf Hardware programmieren:

    // Get the extension offset from the device context
    PMY_TX_QUEUE_CONTEXT queueContext = GetMyTxQueueContext(txQueue);
    NET_EXTENSION checksumExtension = queueContext->ChecksumExtension;

    // Get the checksum info for this packet
    NET_PACKET_CHECKSUM* checksumInfo = NetExtensionGetPacketChecksum(checksumExtension, packetIndex);

    // Do work with the checksum info
    if (packet->Layout.Layer3Type == NET_PACKET_LAYER3_TYPE_IPV4_NO_OPTIONS ||
        packet->Layout.Layer3Type == NET_PACKET_LAYER3_TYPE_IPV4_WITH_OPTIONS ||
        packet->Layout.Layer3Type == NET_PACKET_LAYER3_TYPE_IPV4_UNSPECIFIED_OPTIONS)
    {
        if(checksumInfo->Layer4 == NET_PACKET_TX_CHECKSUM_REQUIRED)
        {
            ...
        }
    }
    ...

Vordefinierte Paketerweiterungskonstanten und Hilfsmethoden

NetAdapterCx stellt Definitionen für bekannte Paketerweiterungskonstanten bereit.

Dauerhaft Definition
NET_PACKET_EXTENSION_INVALID_OFFSET Schützt vor ungültigen Offsetgrößen.
NET_PACKET_EXTENSION_CHECKSUM_NAME NET_PACKET_EXTENSION_CHECKSUM_VERSION_1 Der Name und die Version der Prüfsummenpaketerweiterung.
NET_PACKET_EXTENSION_LSO_NAME NET_PACKET_EXTENSION_LSO_VERSION_1 Der Name und die Version der Paketerweiterung für große Sendeauslagerungen (Large Send Offload, LSO).
NET_PACKET_EXTENSION_RSC_NAME NET_PACKET_EXTENSION_RSC_VERSION_1 Der Name und die Version der RSC-Paketerweiterung (Receive Segment Coalescence).

Darüber hinaus stellt NetAdapterCx Hilfsmethoden bereit, die als Wrapper um die NetExtensionGetData-Methode fungieren. Jede dieser Methoden gibt einen Zeiger auf den entsprechenden Strukturtyp zurück.

Methode Struktur
NetExtensionGetPacketChecksum NET_PACKET_CHECKSUM
NetExtensionGetGso NET_PACKET_GSO
NetExtensionGetPacketRsc NET_PACKET_RSC

Verwenden von Fragmenterweiterungen

Wichtig

Derzeit sind Clienttreiber auf bereits vorhandene Fragmenterweiterungen beschränkt, die vom Betriebssystem definiert werden.

Registrieren von Fragmenterweiterungen

NetAdapterCx registriert die meisten Fragmenterweiterungen automatisch, indem die ausgedrückten Funktionen eines Treibers interpretiert werden. Wenn der Treiber z. B. DMA unterstützt, fügt das Framework automatisch die für die DMA-Programmierung erforderliche NET_FRAGMENT_LOGICAL_ADDRESS-Erweiterung hinzu.

Abfragen von Fragmenterweiterungsoffsets für Datapath-Warteschlangen

Um auf Fragmenterweiterungen zuzugreifen, können Sie denselben Prozess für den Zugriff auf Paketerweiterungen ausführen, der unter Abfragen von Paketerweiterungsoffsets für Datapath-Warteschlangen beschrieben ist.

Vordefinierte Fragmenterweiterungskonstanten

NetAdapterCx stellt Definitionen für bekannte Fragmenterweiterungskonstanten bereit.

Dauerhaft Definition
NET_FRAGMENT_EXTENSION_DATA_BUFFER_NAME NET_FRAGMENT_EXTENSION_DATA_BUFFER_VERSION_1 Der Name und die Version der Datenpufferfragmenterweiterung.
NET_FRAGMENT_EXTENSION_LOGICAL_ADDRESS_NAME NET_FRAGMENT_EXTENSION_LOGICAL_ADDRESS_VERSION_1 Der Name und die Version der Erweiterung für logische Adressfragmente.
NET_FRAGMENT_EXTENSION_MDL_NAME NET_FRAGMENT_EXTENSION_MDL_VERSION_1 Der Name und die Version der MDL-Fragmenterweiterung.
NET_FRAGMENT_EXTENSION_RETURN_CONTEXT_NAME NET_FRAGMENT_EXTENSION_RETURN_CONTEXT_VERSION_1 Der Name und die Version der Rückgabekontextfragmenterweiterung.
NET_FRAGMENT_EXTENSION_VIRTUAL_ADDRESS_NAME NET_FRAGMENT_EXTENSION_VIRTUAL_ADDRESS_VERSION_1 Der Name und die Version der Erweiterung für virtuelle Adressfragmente.