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

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

Требования для USO

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

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

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

Драйвер мини-порта, поддерживающий USO, должен определять тип разгрузки на основе сведений о NET_BUFFER_LIST структуре вне диапазона (OOB). Если значение структуры 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-пакет, отгруженный транспортом, должен иметь длину % 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 и записывает эту сумму в поле Контрольная сумма заголовка 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.
  • Используйте смещение байтов в элементе UdpHeaderOffsetNDIS_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 Разгрузка сегментации UDP (IPv4) 0 Выключено
1 Активировано
*UsoIPv6 Разгрузка сегментации UDP (IPV6) 0 Выключено
1 Активировано