Дескрипторы и расширения пакетов

В NetAdapterCx дескрипторы пакетов — это небольшие, компактные расширяемые структуры, которые описывают сетевой пакет. Для каждого пакета требуется следующее:

  • Один основной дескриптор
  • Один или несколько дескрипторов фрагментов
  • Ноль или более расширений пакетов

Основной дескриптор пакета — это структура NET_PACKET. Он содержит только самые основные метаданные, применимые ко всем пакетам, например структуру заданного пакета и индекс дескриптора первого фрагмента пакета.

Каждый пакет также должен иметь один или несколько дескрипторов фрагментов или NET_FRAGMENT структур, которые описывают расположение в системной памяти, где находятся данные пакета.

Расширения являются необязательными и содержат метаданные для каждого пакета или фрагмента для функций, зависящих от сценария. Например, расширения пакетов могут хранить сведения о разгрузке для контрольной суммы, большой разгрузки отправки (LSO) и получения объединения сегментов (RSC) или могут содержать сведения, относящиеся к приложению. Расширения фрагмента могут содержать сведения о виртуальном адресе, логический адрес DMA или другие сведения для фрагмента.

Вместе эти дескрипторы и расширения содержат все метаданные о сетевом пакете. Ниже приведены два примера описания пакета. На первом рисунке показан сценарий, в котором весь пакет хранится в одном фрагменте памяти и включена разгрузка контрольной суммы.

Схема: макет пакета с 1 фрагментом и 1 расширением.

На втором рисунке показан пакет, хранящийся в двух фрагментах памяти с включенной разгрузкой RSC и контрольной суммы.

Схема: макет пакета с 2 фрагментами и 2 расширениями.

Хранение и доступ к дескрипторов пакетов

Дескрипторы пакетов и дескрипторы фрагментов хранятся в NET_RING структурах. Драйвер клиента сетевой карты обращается к сетевым кольцам и выполняет с ними операции, вызывая интерфейс итератора сетевого кольца, который позволяет драйверу работать с NetAdapterCx для передачи сетевых данных на оборудование и стекать завершенные данные обратно в ОС.

Дополнительные сведения о сетевых кольцах и интерфейсе итератора сетевого кольца см. в статье Общие сведения о сетевых кольцах.

Расширяемость дескриптора пакетов

Расширяемость — это основная функция дескриптора пакетов NetAdapterCx, которая формирует основу для обеспечения версий и производительности дескриптора. Во время выполнения операционная система выделяет все дескрипторы пакетов для каждой очереди пакетов в непрерывном блоке вместе со всеми доступными расширениями. Каждый блок расширения находится сразу за основным дескрипторов, как показано на следующем рисунке:

Схема: макет дескриптора пакета NetAdapterCx с 3 блоками расширений.

Драйверам клиента сетевой карты не разрешено жестко закодировать смещение для любого блока расширения. Вместо этого они должны запрашивать во время выполнения смещение к любому конкретному расширению. Например, драйвер может запросить смещение до расширения B и получить обратно 70 байт, как показано на следующем рисунке:

Схема, показывающая запрос смещения к расширению основного дескриптора пакетов.

После создания очереди пакетов и ее дескрипторов все смещения расширений гарантируются системой как постоянные, поэтому драйверам не нужно часто повторно запрашивать смещения. Кроме того, так как все расширения предварительно выделяются системой в блоке во время инициализации очереди пакетов, нет необходимости в выделении блоков в среде выполнения, поиске в списке определенного дескриптора или необходимости хранения указателей на каждое расширение пакета.

Возможность версий дескриптора пакетов

Основной дескриптор пакетов NetAdapterCx можно легко расширить в будущих выпусках, добавив новые поля в конец, как показано на следующем рисунке:

Схема, показывающая управление версиями основного дескриптора пакетов NetAdapterCx.

Новые клиентские драйверы, которые знают о полях версии 2, могут получить к ним доступ, в то время как старые драйверы версии 1 будут использовать смещения расширений для пропуска полей версии 2, чтобы они могли получить доступ к полям, которые они понимают. Кроме того, каждое расширение можно управлять версиями таким же образом, как показано на следующем рисунке:

Схема, показывающая управление версиями расширений пакетов NetAdapterCx.

Драйвер клиента, который понимает новое расширение, может использовать его. Другие клиентские драйверы могут пропускать новые поля. Это позволяет независимо управлять версиями различных частей дескриптора пакетов.

Производительность дескрипторов пакетов и пути к данным

Функция расширяемости, описанная ранее, предоставляет преимущества, помогающие клиентским драйверам соответствовать требованиям к производительности сетевых адаптеров с ограничением в сотни гигабит в секунду с тысячами очередей:

  1. Дескрипторы пакетов хранятся как можно более компактными для улучшения попаданий в кэш ЦП, так как функции и расширения, которые не используются, занимают 0 байт места в дескрипторах.
  2. Нет разыменовки указателя, а только арифметика смещения, так как расширения являются встроенными, что не только экономит место, но и помогает с попаданиями в кэш ЦП.
  3. Расширения выделяются во время создания очереди, поэтому драйверам не нужно выделять и отменять выделение памяти в активном пути данных или работать со списками lookaside блоков контекста.

Использование расширений пакетов

Важно!

В настоящее время клиентские драйверы ограничены уже существующими расширениями пакетов, определенными операционной системой.

Регистрация расширений пакетов

Первым шагом в работе с расширениями пакетов в драйвере клиента сетевой карты является объявление поддерживаемых аппаратных разгрузк. При объявлении поддержки разгрузки, например контрольной суммы и LSO, NetAdapterCx автоматически регистрирует связанные расширения пакетов от вашего имени.

Пример кода рекламы разгрузки оборудования см. в статье Общие сведения о разгрузках оборудования.

Запрос смещения расширений пакетов для очередей пути к данным

После регистрации расширений пакетов, объявив поддержку аппаратной разгрузки, вам потребуются смещения расширений для доступа к каждому из них при обработке пакетов. Чтобы уменьшить количество вызовов драйвера и повысить производительность, можно запросить смещения для расширений во время функции обратного вызова EvtNetAdapterCreateTx(Rx)Queue и сохранить сведения смещения в контексте очереди.

Пример запроса смещения расширений и их хранения в контексте очереди см. в разделе Очереди передачи и получения.

Получение расширений пакетов во время выполнения

Сохранив смещения расширений в контексте очереди, вы можете использовать их в любое время, когда вам потребуется информация в расширении. Например, можно вызвать метод NetExtensionGetPacketChecksum при программировании дескрипторов на оборудование для очереди передачи:

    // 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)
        {
            ...
        }
    }
    ...

Предопределенные константы расширения пакетов и вспомогательные методы

NetAdapterCx предоставляет определения для известных констант расширения пакетов.

Константа Определение
NET_PACKET_EXTENSION_INVALID_OFFSET Защищает от недопустимых размеров смещения.
NET_PACKET_EXTENSION_CHECKSUM_NAME NET_PACKET_EXTENSION_CHECKSUM_VERSION_1 Имя и версия расширения пакета контрольной суммы.
NET_PACKET_EXTENSION_LSO_NAME NET_PACKET_EXTENSION_LSO_VERSION_1 Имя и версия расширения большого пакета разгрузки отправки (LSO).
NET_PACKET_EXTENSION_RSC_NAME NET_PACKET_EXTENSION_RSC_VERSION_1 Имя и версия расширения пакетов для сегмента получения (RSC).

Кроме того, NetAdapterCx предоставляет вспомогательные методы, которые действуют как оболочки для метода NetExtensionGetData . Каждый из этих методов возвращает указатель на соответствующий тип структуры.

Метод Структура
NetExtensionGetPacketChecksum NET_PACKET_CHECKSUM
NetExtensionGetGso NET_PACKET_GSO
NetExtensionGetPacketRsc NET_PACKET_RSC

Использование расширений фрагментов

Важно!

В настоящее время клиентские драйверы ограничены существующими расширениями фрагментов, определенными операционной системой.

Регистрация расширений фрагментов

NetAdapterCx автоматически регистрирует большинство расширений фрагментов, интерпретируя выраженные возможности драйвера. Например, если драйвер выражает, что поддерживает DMA, платформа автоматически добавит расширение NET_FRAGMENT_LOGICAL_ADDRESS, необходимое для программирования DMA.

Запрос смещения расширений фрагментов для очередей пути к данным

Чтобы получить доступ к расширениям фрагментов, можно выполнить тот же процесс доступа к расширениям пакетов, который описан в разделе Запрос смещения расширений пакетов для очередей пути к данным.

Предопределенные константы расширения фрагмента

NetAdapterCx предоставляет определения для известных констант расширения фрагментов.

Константа Определение
NET_FRAGMENT_EXTENSION_DATA_BUFFER_NAME NET_FRAGMENT_EXTENSION_DATA_BUFFER_VERSION_1 Имя и версия расширения буфера данных.
NET_FRAGMENT_EXTENSION_LOGICAL_ADDRESS_NAME NET_FRAGMENT_EXTENSION_LOGICAL_ADDRESS_VERSION_1 Имя и версия расширения фрагмента логического адреса.
NET_FRAGMENT_EXTENSION_MDL_NAME NET_FRAGMENT_EXTENSION_MDL_VERSION_1 Имя и версия расширения фрагмента MDL.
NET_FRAGMENT_EXTENSION_RETURN_CONTEXT_NAME NET_FRAGMENT_EXTENSION_RETURN_CONTEXT_VERSION_1 Имя и версия расширения фрагмента возвращаемого контекста.
NET_FRAGMENT_EXTENSION_VIRTUAL_ADDRESS_NAME NET_FRAGMENT_EXTENSION_VIRTUAL_ADDRESS_VERSION_1 Имя и версия расширения фрагмента виртуального адреса.