Дескрипторы пакетов и расширения
В NetAdapterCx дескрипторы пакетов - небольшие, компактные, расширяемые во время выполнения структуры, описывающие сетевой пакет. Для каждого пакета требуется следующее:
- Один основной дескриптор
- Один или несколько дескрипторов фрагментов
- Ноль или больше расширений пакетов
основной дескриптор пакета — это структура NET_PACKET. Он содержит только самые основные метаданные, применимые ко всем пакетам, например макет обрамления заданного пакета и индекс первого дескриптора фрагмента пакета.
Каждый пакет также должен содержать один или несколько дескрипторов фрагментов или NET_FRAGMENT структуры, описывающие расположение в системной памяти, в которой находятся данные пакета.
расширения являются необязательными и содержат метаданные для каждого пакета или отдельных фрагментов, предназначенные для специфических функций сценария. Например, расширения пакетов могут хранить сведения о разгрузке для контрольной суммы, крупной отправки (LSO) и объединения сегментов получения (RSC), или содержать данные, специфичные для приложений. Расширения фрагментов могут содержать сведения о виртуальном адресе, сведения об логическом адресе DMA или другие сведения для фрагмента.
Вместе эти дескрипторы и расширения содержат все метаданные о сетевом пакете. Ниже приведены два примера того, как они описывают пакет. На первом рисунке показан сценарий, в котором весь пакет хранится внутри одного фрагмента памяти и выгрузка контрольной суммы включена.
На втором рисунке показан пакет, хранящийся в двух фрагментах памяти, с включенной разгрузкой RSC и контрольной суммы.
Хранилище дескриптора пакетов и доступ
Дескрипторы пакетов и дескрипторы фрагментов хранятся в NET_RING структурах. Драйвер клиента сетевого адаптера обращается к сетевым кольцам и выполняет операции с ними, вызывая интерфейс Net Ring Iterator, который позволяет драйверу работать с NetAdapterCx для отправки сетевых данных в оборудование и возврата завершенных данных в ОС.
Дополнительные сведения о сетевых кольцах и интерфейсе итератора Net Ring см. в разделе Введение в сетевые кольца.
Расширяемость дескриптора пакетов
Расширяемость является основной функцией дескриптора пакета NetAdapterCx, формируя основу для управления версиями дескриптора и производительности дескриптора. Во время выполнения операционная система выделяет все дескрипторы пакетов для каждой очереди пакетов в непрерывном блоке вместе с любыми доступными расширениями. Каждый блок расширения непосредственно находится за основным дескриптором, как показано на следующем рисунке:
Драйверы клиента сетевого адаптера не могут жестко закодировать смещение к любому блоку расширения. Вместо этого они должны задавать запрос во время выполнения на смещение для любого определённого расширения. Например, как показано на следующем рисунке, драйвер может запросить смещение для расширения B и получить 70 байт.
После создания очереди пакетов и её дескрипторов все их смещения областей расширения гарантируются системой как константные, поэтому драйверам часто не нужно повторно запрашивать смещения. Кроме того, так как все расширения предварительно выделяются системой в блоке во время инициализации очереди пакетов, не требуется выделение блоков среды выполнения, поиск списка для определенного дескриптора или хранение указателей на каждое расширение пакета.
Доступность версий дескриптора пакетов
Дескриптор основного пакета NetAdapterCx можно легко расширить в будущих выпусках, добавив новые поля в конец, например на следующем рисунке:
Более новые клиентские драйверы, знающие о полях версии 2, могут получить к ним доступ, в то время как старые драйверы версии 1 будут использовать смещения расширения, чтобы пропустить поля версии 2 и получить доступ к полям, которые им понятны. Кроме того, каждое расширение можно использовать так же, как показано на следующем рисунке:
Драйвер клиента, который поддерживает новое расширение, может его использовать. Другие клиентские драйверы могут пропускать новые поля. Это позволяет независимо использовать разные части дескриптора пакетов.
Дескрипторы пакетов и производительность канала данных
Функция расширяемости, описанная ранее, предоставляет преимущества, которые помогают клиентским драйверам соответствовать требованиям к производительности сетевых адаптеров, способных на передачу сотен гигабит в секунду и тысячами очередей.
- Дескрипторы пакетов хранятся как можно более компактно для улучшения эффективности кэширования ЦП, поскольку функции и расширения, которые не используются, занимают 0 байт в дескрипторах.
- Нет разыменования указателей, только арифметика смещений, так как расширения встроены, что не только экономит место, но и помогает при попадании в кэш процессора.
- Расширения выделяются во время создания очереди, поэтому драйверам не нужно выделять и освобождать память в активном пути к данным или работать с 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.
Запрос смещений расширения фрагментов для очередей маршрута данных
Чтобы получить доступ к расширениям фрагментов, можно выполнить тот же процесс для доступа к расширениям пакетов, описанным в смещения расширения пакета для очередей datapath.
Предопределенные константы расширения фрагмента
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 | Имя и версия расширения фрагмента виртуального адреса. |