Поделиться через


Разгрузка сегментации UDP (USO)

Разгрузка сегментации UDP (USO), поддерживаемая в Windows 10 версии 2004 и поздних версиях, — это функция, которая позволяет сетевым картам выгрузить сегментацию датаграмм UDP, размер которых превышает максимальное значение единицы передачи (MTU) сетевого носителя. Благодаря этому Windows сокращает использование ЦП, связанное с обработкой TCP/IP-адресов для каждого пакета. Требования к USO похожи на второй версии крупного разгрузочного отправления (LSOv2), которая предназначена для транспортного протокола TCP.

Требования к USO

Этот раздел относится в основном к протоколам NDIS и минипорт-драйверам. Драйверы упрощенных фильтров NDIS (LWFs) должны соответствовать требованиям драйвера протокола при изменении или отправке пакетов, и они также могут предполагать, что все пакеты, предоставленные обработчику FilterSendNetBufferLists соответствуют требованиям драйвера протокола.

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

  • Вычисление контрольных сумм IP-адресов для отправленных пакетов, содержащих параметры IPv4
  • Вычисление контрольных сумм UDP для отправленных пакетов

Минипорт-драйвер, поддерживающий разделение UDP, должен определить тип разгрузки на основе внеполосной информации в структуре NET_BUFFER_LIST. Если значение структуры NDIS_UDP_SEGMENTATION_OFFLOAD_NET_BUFFER_LIST_INFO ненулевое, драйвер минипорта должен выполнить USO. Любая NET_BUFFER_LIST, содержащая данные OOB USO, также содержит структуру NET_BUFFER. Однако в случае, когда драйвер минипорта получил OID_TCP_OFFLOAD_PARAMETERS для отключения USO, после успешного завершения OID он должен отклонить и вернуть любой NET_BUFFER_LIST, у которого установлено поле USO OOB.

Транспорт TCP/IP выгружает только те пакеты UDP, которые соответствуют следующим критериям:

  • Пакет является пакетом UDP.
  • Длина пакета должна превышать максимальный размер сегмента (MSS) * (MinSegmentCount - 1).
  • Если драйвер минипорта не задает возможность SubMssFinalSegmentSupported, то каждый большой пакет UDP, загруженный транспортом, должен иметь Length % MSS == 0. То есть большой пакет делится на N пакетов, каждый сегмент пакета содержит точно MSS пользовательских байтов. Если драйвер минипорта задает способность SubMssFinalSegmentSupported, то условие делимости длины пакетов на транспорте не применяется. Другими словами, конечный сегмент может быть меньше MSS.
  • Пакет не является пакетом обратного цикла.
  • MF бит в заголовке IP большого пакета UDP, который транспорт TCP/IP разгрузил, не будет установлен, и смещение фрагмента в заголовке IP будет равно нулю.
  • Приложение указало UDP_SEND_MSG_SIZE/WSASetUdpSendMessageSize.

Перед разгрузкой большого пакета UDP для сегментации транспорт TCP/IP выполняет следующие действия:

  • Обновляет сведения о сегментации больших пакетов, связанные со структурой NET_BUFFER_LIST. Эта информация представляет собой структуру NDIS_UDP_SEGMENTATION_OFFLOAD_NET_BUFFER_LIST_INFO, которая входит в состав OOB-информации структуры NET_BUFFER_LIST. Транспорт TCP/IP задает значение MSS на требуемое MSS.
  • Вычисляет суммы дополнения, для псевдохедчика UDP и записывает эту сумму в поле Checksum заголовка UDP. Транспорт TCP/IP вычисляет сумму единичного дополнения по следующим полям в псевдозаголовке: исходный IP-адрес, конечный IP-адрес и протокол.

Сумма дополнения до единицы для псевдозаголовка, предоставленного транспортом TCP/IP, дает сетевому адаптеру возможность начать вычисление реальной контрольной суммы UDP для каждого пакета, получаемого сетевым адаптером из большого пакета UDP, без необходимости проверять заголовок IP.

Обратите внимание, что RFC 768 и RFC 2460 предусматривает, что псевдозаголовок вычисляется по исходному IP-адресу, IP-адресу назначения, протоколу и длине UDP (длина заголовка UDP плюс длина полезных данных UDP, не включая длину псевдозаголовок). Однако, поскольку базовый мини-драйвер и сетевой адаптер создают UDP-датаграммы из большого пакета, предоставленного транспортом TCP/IP, транспорт не знает размер полезных данных UDP для каждой UDP-датаграммы, поэтому не может включать длину UDP при вычислении псевдозаголовка. Вместо этого, как описано в следующем разделе, сетевой адаптер расширяет псевдозаголовочную контрольную сумму, предоставляемую протоколом TCP/IP, чтобы учитывать длину UDP каждой созданной UDP датаграммы.

Важный

Если поле контрольной суммы заголовка UDP, предоставленное транспортом TCP/IP, равно нулю, сетевой адаптер не должен выполнять вычисление контрольной суммы UDP.

Отправка пакетов с помощью USO

После получения NET_BUFFER_LIST в своем MiniportSendNetBufferLists функции обратного вызова драйвер минипорта может вызвать макрос NET_BUFFER_LIST_INFO с _IdUdpSegmentationOffloadInfo, чтобы получить значение MSS и IP-протокол.

Минипорт-драйвер получает общую длину большого пакета из длины первой структуры NET_BUFFER и использует значение MSS для разделения большого UDP пакета на более мелкие UDP пакеты. Каждый из небольших пакетов содержит MSS или меньше байтов пользовательских данных. Только последний пакет, созданный из сегментированного большого пакета, должен содержать менее MSS байт данных пользователя. Все остальные пакеты, созданные из сегментированного пакета, должны содержать MSS байты пользовательских данных. Если минипорт-драйвер не соответствует этому правилу, UDP дейтаграммы доставляются неправильно. Если драйвер минипорта не устанавливает возможность SubMssFinalSegmentSupported, длина пакета делится на MSS, а каждый из сегментированных пакетов содержит MSS пользовательских байт.

Минипорт-драйвер прикрепляет заголовки MAC, IP и UDP к каждому сегменту, которые получены из большого пакета. Минипорт-драйвер должен вычислить контрольные суммы IP и UDP для этих производных пакетов. Чтобы вычислить контрольную сумму UDP для каждого пакета, полученного из большого пакета UDP, сетевой адаптер вычисляет переменную часть контрольной суммы UDP (для заголовка UDP и полезных данных UDP), добавляет эту контрольную сумму в сумму дополнения для псевдоголовика, вычисляемого транспортом TCP/IP, а затем вычисляет 16-разрядную сумму для контрольной суммы. Дополнительные сведения о вычислении таких контрольных сумм см. в RFC 768 и RFC 2460.

Длина пользовательских данных UDP в большом пакете UDP должна быть меньше или равна значению, которое драйвер мини-порта назначает MaxOffLoadSize.

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

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

Минипорт-промежуточный драйвер, реагирующий на OID_TCP_OFFLOAD_PARAMETERS для отключения служб USO, должен быть подготовлен к небольшому окну времени, когда запросы USO по-прежнему могут достичь мини-порта драйвера.

Число пакетов сегментации, производных от большого пакета UDP, должно быть равно или больше, чем значение MinSegmentCount, указанное драйвером мини-порта.

При обработке большого пакета UDP драйвер минипорта отвечает только за сегментирование пакета и аффиксирование заголовков MAC, IP и UDP к пакетам, производным от большого пакета UDP. Если минипорт не может отправить по крайней мере один сегментированный пакет, в конечном итоге NBL должен быть завершён со статусом ошибки. Минипорт может продолжать отправлять последующие пакеты, но это не обязательно. NBL не может быть возвращен в NDIS, пока все сегментированные пакеты не будут переданы или не завершатся неудачей.

Драйверы минипортов с поддержкой USO также должны выполнять следующие действия:

  • Поддержка IPv4 и IPv6.
  • Поддержка репликации параметров IPv4 из большого пакета в каждом сегментованном пакете, который создает сетевой адаптер.
  • Используйте заголовок IP и UDP в структуре NET_BUFFER_LIST в качестве шаблона для создания заголовков UDP и IP-адресов для каждого сегментированного пакета.
  • Используйте значения идентификатора IP в диапазоне от 0x0000 до 0xFFFF. Например, если заголовок IP-адреса шаблона начинается со значения поля идентификации 0xFFFE, первый пакет диаграммы UDP должен иметь значение 0xFFFE, а затем 0xFFFF, 0x0000, 0x0001и т. д.
  • Если большой пакет UDP содержит параметры IP, драйвер минипорта копирует эти параметры без изменений в каждый пакет, полученный из большого пакета UDP.
  • Используйте смещение байтов UdpHeaderOffset в элементе NDIS_UDP_SEGMENTATION_OFFLOAD_NET_BUFFER_LIST_INFO, чтобы определить местоположение заголовка UDP, начиная с первого байта пакета.
  • Увеличение статистики передачи на основе сегментированных пакетов. Например, включите количество байтов заголовков ethernet, IP и UDP для каждого сегмента пакетов, а количество пакетов определяется числом сегментов размером MSS, а не 1.
  • Задайте для полей UDP общую длину и длину IP-адресов на основе каждого сегментированного размера диаграммы данных.

Изменения интерфейса NDIS

В этом разделе описываются изменения в NDIS 6.83, которые позволяют стеку драйверов TCP/IP узла использовать возможности USO, предоставляемые драйверами мини-порта.

NDIS и драйвер минипорта выполняют следующие действия:

  • Рекламируйте то, что сетевой адаптер поддерживает функцию USO.
  • Включение или отключение USO
  • Получение текущего состояния функциональных возможностей USO

Рекламирование возможностей USO

Драйверы минипорта заявляют о поддержке возможностей USO, заполняя поле UdpSegmentation структуры NDIS_OFFLOAD, которая передается в параметрах NdisMSetMiniportAttributes. Поле Header.Revision в структуре NDIS_OFFLOAD должно иметь значение NDIS_OFFLOAD_REVISION_6, а поле Header.Size должно иметь значение NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_6.

Запрос состояния USO

Текущее состояние USO можно запросить с помощью OID_TCP_OFFLOAD_CURRENT_CONFIG. NDIS обрабатывает этот OID и не передает его минипорт-драйверу.

Изменение состояния USO

Можно включить или отключить USO с помощью OID_TCP_OFFLOAD_PARAMETERS. После обработки OID драйвер минипорта должен отправить индикатор состояния NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG с обновленным состоянием разгрузки.

Ключевые слова USO

Ключевые слова перечисления USO приведены следующим образом:

  • *UsoIPv4
  • *UsoIPv6

Эти значения описывают, включен или отключен USO для этого конкретного IP-протокола. Параметры USO не зависят от конфигурации NDIS_TCP_IP_CHECKSUM_OFFLOAD. Например, отключение *UDPChecksumOffloadIPv4 не приводит к автоматическому отключению *UsoIPv4.

Имя подкатегории Описание параметра Ценность Описание перечисления
*UsoIPv4 USO (IPv4) 0 Нетрудоспособный
1 Включен
*UsoIPv6 USO (IPV6) 0 Нетрудоспособный
1 Включен