Descarga de segmentación UDP (USO)
La descarga de segmentación UDP (USO), compatible con Windows 10, versión 2004 y posteriores, es una característica que permite a las tarjetas de interfaz de red (NIC) descargar la segmentación de datagramas UDP que son mayores que la unidad de transmisión máxima (MTU) del medio de red. Al hacerlo, Windows reduce el uso de CPU asociado al procesamiento TCP/IP por paquete. Los requisitos de USO son similares a la versión 2 de descarga de envío grande (LSOv2), que es para el protocolo de transporte TCP.
Requisitos para USO
En esta sección se hace referencia principalmente al protocolo NDIS y a los controladores de miniport. Los controladores de filtro ligero (LWF) NDIS deben seguir los requisitos del controlador de protocolo al modificar o enviar paquetes, y también pueden asumir que los paquetes proporcionados a su manejador FilterSendNetBufferLists cumplen los requisitos del controlador de protocolo.
Los controladores de minipuerto pueden descargar la segmentación de paquetes UDP grandes que son mayores que la MTU del medio de red. Una NIC que admita la segmentación de paquetes UDP grandes también debe ser capaz de hacer lo siguiente:
- Calcular de sumas de comprobación de IP para paquetes enviados que contienen opciones de IPv4
- Calcular las sumas de comprobación UDP para paquetes enviados
Un controlador de minipuerto que admita USO debe determinar el tipo de descarga de la información de fuera de banda (OOB) de la estructura NET_BUFFER_LIST. Si el valor de la estructura NDIS_UDP_SEGMENTATION_OFFLOAD_NET_BUFFER_LIST_INFO es distinto de cero, el controlador de minipuerto debe realizar USO. Cualquier NET_BUFFER_LIST
que contenga datos de OOB USO también contiene una única estructura NET_BUFFER. Sin embargo, en el caso de que el controlador de miniporte haya recibido OID_TCP_OFFLOAD_PARAMETERS para desactivar USO, después de que el controlador de miniporte haya completado correctamente el OID, debería rechazar y devolver cualquier NET_BUFFER_LIST
que tenga establecido el campo USO OOB.
El transporte TCP/IP solo descarga los paquetes UDP que cumplen los criterios siguientes:
- El paquete es un paquete UDP.
- La longitud del paquete debe ser mayor que el tamaño máximo del segmento
(MSS) * (MinSegmentCount - 1)
. - Si el controlador de minipuerto no establece la funcionalidad
SubMssFinalSegmentSupported
, cada paquete de UDP grande descargado por el transporte debe tenerLength % MSS == 0
. Es decir, el paquete grande es divisible en N paquetes con cada segmento de paquete que contiene exactamente MSS bytes de usuario. Si el controlador de miniporte establece la funcionalidadSubMssFinalSegmentSupported
, esta condición de divisibilidad de longitud de paquete en el transporte no se aplica. En otras palabras, el segmento final puede ser menor que MSS. - El paquete no es un paquete de bucle invertido.
- El bit MF del encabezado IP del paquete UDP grande que no se establecerá el transporte TCP/IP descargado y el desplazamiento de fragmento en el encabezado IP será cero.
- La aplicación ha especificado
UDP_SEND_MSG_SIZE
/WSASetUdpSendMessageSize.
Antes de descargar un paquete UDP grande para la segmentación, el transporte TCP/IP hace lo siguiente:
- Actualiza la información de segmentación de paquetes de gran tamaño asociada a la estructura de NET_BUFFER_LIST. Esta información es una estructura NDIS_UDP_SEGMENTATION_OFFLOAD_NET_BUFFER_LIST_INFO que forma parte de la información de OOB de la estructura
NET_BUFFER_LIST
. El transporte TCP/IP establece el valor de MSS en el MSS deseado. - Calcula la suma de un complemento para el pseudoencabezado UDP y escribe esta suma en el campo
Checksum
del encabezado UDP. El transporte TCP/IP calcula la suma de los complementos que se incluyen en los campos siguientes del pseudoencabezado: Dirección IP de origen, Dirección IP de destino y Protocolo.
La suma de complemento de la pseudoencabezado proporcionada por el transporte TCP/IP proporciona a la NIC un inicio temprano al calcular la suma de comprobación UDP real para cada paquete que la NIC deriva del paquete UDP grande, sin tener que examinar el encabezado IP.
Tenga en cuenta que RFC 768 y RFC 2460 estipulan que el pseudoheader se calcula a través de la dirección IP de origen, la dirección IP de destino, el protocolo y la longitud UDP (la longitud del encabezado UDP más la longitud de la carga UDP, no incluida la longitud del pseudoheader). Sin embargo, dado que el controlador de minipuerto subyacente y la NIC generan datagramas UDP a partir del paquete grande que pasa el transporte TCP/IP, el transporte no conoce el tamaño de la carga UDP para cada datagrama UDP y, por tanto, no puede incluir la longitud UDP en el cálculo del pseudoencabezado. En su lugar, como se describe en la sección siguiente, la NIC extiende la suma de comprobación del pseudoencabezado proporcionada por el transporte TCP/IP para cubrir la longitud UDP de cada datagrama UDP generado.
Importante
Si el campo de suma de comprobación del encabezado UDP proporcionado por el transporte TCP/IP es cero, la NIC no debe realizar el cálculo de la suma de comprobación UDP.
Envío de paquetes con USO
Una vez que el controlador de minipuerto obtiene la NET_BUFFER_LIST en su función de devolución de llamada MiniportSendNetBufferLists, puede llamar a la macro NET_BUFFER_LIST_INFO con un _Id
de UdpSegmentationOffloadInfo
para obtener el valor de MSS y el protocolo IP.
El controlador de miniporte obtiene la longitud total del paquete grande a partir de la longitud de la primera estructura NET_BUFFER y usa el valor de MSS para dividir el paquete UDP grande en paquetes UDP más pequeños. Cada uno de los paquetes más pequeños contiene MSS o menos bytes de datos de usuario. Solo el último paquete creado a partir del paquete grande segmentado debe contener menos de MSS bytes de datos de usuario. Todos los demás paquetes creados a partir del paquete segmentado deben contener MSS bytes de datos de usuario. Si un controlador de miniporte no cumple esta regla, los datagramas UDP se entregan incorrectamente. Si el controlador de minipuerto no establece la funcionalidad SubMssFinalSegmentSupported
, la longitud del paquete se divide por MSS y cada uno de los paquetes segmentados contiene MSS bytes de usuario.
El controlador de minipuerto coloca los encabezados MAC, IP y UDP en cada segmento derivado del paquete grande. El controlador de minipuerto debe calcular las sumas de comprobación IP y UDP para estos paquetes derivados. Para calcular la suma de comprobación UDP de cada paquete derivado del paquete UDP grande, la NIC calcula la parte variable de la suma de comprobación UDP (para el encabezado UDP y la carga UDP), agrega esta suma de comprobación a la suma de complemento de uno para el pseudoheader calculado por el transporte TCP/IP y, a continuación, calcula el complemento de uno de 16 bits para la suma de comprobación. Para obtener más información sobre cómo calcular estas sumas de comprobación, vea RFC 768 y RFC 2460.
La longitud de los datos de usuario UDP en el paquete UDP grande debe ser menor o igual que el valor que el controlador de miniporte asigna a MaxOffLoadSize
.
Después de que un controlador emite una indicación de estado para señalar un cambio a MaxOffLoadSize
, el controlador no debe provocar una comprobación de errores si recibe una solicitud de envío LSO que utiliza el valor anterior de MaxOffLoadSize
. En su lugar, el controlador debe producir un error en la solicitud de envío. Los controladores deben rechazar cualquier solicitud de envío que sean incapaces de realizar, por cualquier motivo (incluido el tamaño, el recuento mínimo de segmentos, las opciones IP, etc.). Los conductores deben enviar una indicación de estado tan pronto como sea posible si cambian sus capacidades.
Un controlador intermedio que emite independientemente indicaciones de estado que notifican un cambio en el valor de MaxOffLoadSize
debe asegurarse de que el adaptador de miniporte subyacente que no ha emitido una indicación de estado no obtiene ningún paquete que sea mayor que el valor de MaxOffLoadSize
que notificó el adaptador de miniport.
Un controlador intermedio de minipuerto que responde a OID_TCP_OFFLOAD_PARAMETERS para desactivar los servicios USO debe estar preparado para un pequeño período de tiempo en el que las solicitudes USO todavía podrían llegar al controlador de minipuerto.
El número de paquetes de segmentación derivados del paquete UDP grande debe ser igual o mayor que el valor de MinSegmentCount
especificado por el controlador de miniport.
Al procesar un paquete UDP grande, el controlador de miniporte solo es responsable de segmentar el paquete y colocar los encabezados MAC, IP y UDP en los paquetes derivados del paquete UDP grande. Si el minipuerto no puede enviar al menos un paquete segmentado, el NBL debe completarse finalmente con un estado de error. El miniporte puede seguir enviando paquetes posteriores, pero no es necesario hacerlo. El NBL no se puede volver a completar en NDIS hasta que todos los paquetes segmentados se hayan transmitido o producido un error.
Los controladores de miniport compatibles con USO también deben hacer lo siguiente:
- Admite IPv4 e IPv6.
- Admite la replicación de opciones IPv4 del paquete grande en cada paquete segmentado que genera la NIC.
- Use el encabezado IP y UDP en la estructura de NET_BUFFER_LIST como plantilla para generar encabezados UDP e IP para cada paquete segmentado.
- Use valores de identificación IP (ID. de IP) en el intervalo de 0x0000 a 0xFFFF. Por ejemplo, si el encabezado IP de plantilla comienza con un valor de campo Identificación de 0xFFFE, el primer paquete de datagrama UDP debe tener un valor de 0xFFFE, seguido de 0xFFFF, 0x0000, 0x0001, etc.
- Si el paquete UDP grande contiene opciones IP, el controlador de miniporta copia estas opciones, sin modificar, en cada paquete derivado del paquete UDP grande.
- Usar el desplazamiento de bytes en el miembro
UdpHeaderOffset
de NDIS_UDP_SEGMENTATION_OFFLOAD_NET_BUFFER_LIST_INFO para determinar la ubicación del encabezado UDP, comenzando desde el primer byte del paquete. - Incrementar las estadísticas de transmisión en función de los paquetes segmentados. Por ejemplo, incluir el recuento de bytes de encabezado Ethernet, IP y UDP para cada segmento de paquete, y el recuento de paquetes es el número de segmentos con tamaño MSS, no 1.
- Establezca los campos de longitud total de UDP y longitud IP en función de cada tamaño de datagrama segmentado.
Cambios en la interfaz NDIS
En esta sección se describen los cambios en NDIS 6.83 que permiten que la pila de controladores TCP/IP host aproveche las funcionalidades uso expuestas por los controladores de minipuerto.
NDIS y el controlador de miniportar realizan lo siguiente:
- Anunciar que la NIC admite la funcionalidad USO
- Habilitar o deshabilitar USO
- Obtención del estado actual de la funcionalidad USO
Avisar de la funcionalidad USO
Los controladores de minipuerto avisan de la funcionalidad USO rellenando el campo UdpSegmentation
de la estructura NDIS_OFFLOAD, que se pasa a los parámetros de NdisMSetMiniportAttributes. El campo Header.Revision
de la estructura NDIS_OFFLOAD
debe establecerse en NDIS_OFFLOAD_REVISION_6 y el campo Header.Size
debe establecerse en NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_6
.
Consulta del estado USO
El estado USO actual se puede consultar con OID_TCP_OFFLOAD_CURRENT_CONFIG. NDIS controla este OID y no lo pasa al controlador de miniport.
Cambio del estado de USO
USO se puede habilitar o deshabilitar mediante OID_TCP_OFFLOAD_PARAMETERS. Una vez que el controlador de miniporte procesa el OID, debe enviar una indicación de estado NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG indicando el estado actualizado de descarga.
Palabras clave USO
Las palabras clave de enumeración USO son las siguientes:
*UsoIPv4
*UsoIPv6
Estos valores describen si USO está habilitado o deshabilitado para ese protocolo IP concreto. La configuración de USO no depende de la configuración de NDIS_TCP_IP_CHECKSUM_OFFLOAD. Por ejemplo, deshabilitar *UDPChecksumOffloadIPv4
no deshabilita implícitamente *UsoIPv4
.
Nombre de subclave | Descripción del parámetro | Valor | Descripción de enumeración |
---|---|---|---|
*UsoIPv4 |
USO (IPv4) | 0 | Deshabilitado |
1 | habilitado | ||
*UsoIPv6 |
USO (IPV6) | 0 | Deshabilitado |
1 | habilitado |