Compartir a través de


Descarga de la segmentación de paquetes TCP grandes

Los controladores de minipuerto NDIS pueden descargar la segmentación de paquetes TCP grandes con un tamaño superior a la unidad de transmisión máxima (MTU) del medio de red. Una NIC que admita la segmentación de paquetes TCP grandes también debe ser capaz de:

  • Calcular sumas de comprobación de IP para paquetes enviados que contienen opciones de IP

  • Calcular las sumas de comprobación de TCP para los paquetes de envío que contienen opciones de TCP.

Las versiones 6.0 y posteriores de NDIS admiten la versión 1 de descarga de envíos grandes (LSOv1), que es similar a la descarga de envíos grandes (LSO) en NDIS 5.x. Las versiones 6.0 y posteriores de NDIS también admiten la versión 2 de descarga de envíos grandes (LSOv2), que proporciona servicios mejorados de segmentación de paquetes de gran tamaño, incluida la compatibilidad con IPv6.

Un controlador de minipuerto que admita LSOv2 y LSOv1 debe determinar el tipo de descarga de la información de OOB de la estructura NET_BUFFER_LIST. El controlador puede usar el miembro Type de la estructura NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO para determinar si la pila de controladores usa LSOv2 o LSOv1 y realiza los servicios de descarga adecuados. Cualquier estructura NET_BUFFER_LIST que contenga los datos de OOB de LSOv1 o LSOv2 también contiene una única estructura NET_BUFFER. Para obtener más información sobre NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO, consulte Acceso a información sobre NET_BUFFER_LIST de la descarga de TCP/IP.

Sin embargo, en un caso en el que el minipuerto haya recibido OID_TCP_OFFLOAD_PARAMETERS para desactivar la característica LSO en el minipuerto y después de que el minipuerto haya completado correctamente el OID, el minipuerto quitará todos los NET_BUFFER_LIST que contengan datos OOB de LSOv1 o LSOv2 distintos de cero (NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO).

El transporte TCP/IP solo descarga los paquetes TCP grandes que cumplen los criterios siguientes:

Antes de descargar un paquete TCP grande para la segmentación, el transporte TCP/IP:

  • Para LSOv1, escribe la longitud total del paquete TCP grande en el campo Longitud total del encabezado IP del paquete. La longitud total incluye la longitud del encabezado IP, la longitud de las opciones ip si están presentes, la longitud del encabezado TCP, la longitud de las opciones TCP si están presentes y la longitud de la carga TCP. Para LSOv2, establece el campo Longitud total del encabezado IP del paquete en 0. Los controladores de minipuerto deben determinar la longitud del paquete a partir de la longitud de la primera estructura NET_BUFFER de la estructura NET_BUFFER_LIST.

  • Calcula la suma de un complemento para el pseudoencabezado TCP y escribe esta suma en el campo Suma de comprobación del encabezado TCP. 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 TCP real para cada paquete que la NIC deriva del paquete TCP grande, sin tener que examinar el encabezado IP. Tenga en cuenta que RFC 793 estipula que la suma de comprobación de pseudoencabezado se calcula a través de la dirección IP de origen, la dirección IP de destino, el protocolo y la longitud de TCP. (La longitud TCP es la longitud del encabezado TCP más la longitud de la carga TCP. La longitud TCP no incluye la longitud del pseudoencabezado). Sin embargo, dado que el controlador de minipuerto subyacente y la NIC generan segmentos TCP a partir del paquete grande que pasa el transporte TCP/IP, el transporte no conoce el tamaño de la carga TCP para cada segmento TCP y, por lo tanto, no puede incluir la longitud TCP en el pseudoencabezado. En su lugar, como se describe a continuación, la NIC extiende la suma de comprobación de pseudoencabezado proporcionada por el transporte TCP/IP para cubrir la longitud TCP de cada segmento TCP generado.

  • Escribe el número de secuencia correcto en el campo Número de secuencia del encabezado TCP. El número de secuencia identifica el primer byte de la carga TCP.

Una vez que el controlador de minipuerto obtiene la estructura NET_BUFFER_LIST en su función MiniportSendNetBufferLists o MiniportCoSendNetBufferLists, puede llamar a la macro NET_BUFFER_LIST_INFO con un _Id de TcpLargeSendNetBufferListInfo para obtener el valor de MSS escrito por el transporte TCP/IP.

El controlador de minipuerto obtiene la longitud total del paquete grande del encabezado IP del paquete y usa el valor de MSS para dividir el paquete TCP grande en paquetes más pequeños. Cada uno de los paquetes más pequeños contiene MSS o menos bytes de datos de usuario. Tenga en cuenta que 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 no sigue esta regla, la creación y transmisión de paquetes adicionales innecesarios podría degradar el rendimiento.

El controlador de minipuerto coloca los encabezados MAC, IP y TCP en cada segmento derivado del paquete grande. El controlador de minipuerto debe calcular las sumas de comprobación IP y TCP para estos paquetes derivados. Para calcular la suma de comprobación TCP de cada paquete derivado del paquete TCP grande, la NIC calcula la parte variable de la suma de comprobación TCP (para el encabezado TCP y la carga TCP), agrega esta suma de comprobación a la suma de complemento de uno para el pseudoencabezado 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, consulte RFC 793 y RFC 1122.

En la ilustración siguiente se muestra la segmentación de un paquete grande.

Diagrama que muestra la segmentación de un paquete TCP grande en paquetes más pequeños con encabezados MAC, IP y TCP.

La longitud de los datos de usuario TCP en el paquete TCP grande debe ser menor o igual que el valor que el controlador de minipuerto asigna al valor MaxOffLoadSize. Para obtener más información sobre el valor MaxOffLoadSize, consulte Notificación de las capacidades de segmentación de paquetes TCP LSOv1 de una NIC y vNotificación de las capacidades de segmentación de paquetes TCP LSOv2 de una NIC.

Después de que un controlador emite una indicación de estado para indicar un cambio en el valor MaxOffLoadSize, el controlador no debe fallar si recibe una solicitud de envío de LSO que usa el valor MaxOffLoadSize anterior. En su lugar, el controlador puede fallar en la solicitud de envío.

Un controlador intermedio que emite independientemente indicaciones de estado que notifican un cambio en el valor MaxOffLoadSize debe asegurarse de que el adaptador de minipuerto subyacente que no ha emitido una indicación de estado no obtiene ningún paquete que sea mayor que el valor MaxOffLoadSize notificado por el adaptador de minipuerto.

Un controlador intermedio de minipuerto que responde a OID_TCP_OFFLOAD_PARAMETERS para desactivar los servicios LSO debe estar preparado para un pequeño período de tiempo en el que las solicitudes LSO todavía podrían llegar al controlador de minipuerto.

La longitud de los datos de usuario TCP en un paquete de segmento debe ser menor o igual que MSS. MSS es el valor de ULONG que el transporte TCP pasa a través de la información de LSO NET_BUFFER_LIST asociada a la estructura NET_BUFFER_LIST. Tenga en cuenta que 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 no sigue esta regla, la creación y transmisión de paquetes adicionales innecesarios podría degradar el rendimiento.

El número de paquetes de segmentos derivados del paquete TCP grande debe ser igual o mayor que el valor de MinSegmentCount especificado por el controlador de minipuerto. Para obtener más información sobre el valor MinSegmentCount, consulte Notificación de las capacidades de segmentación de paquetes TCP LSOv1 de una NIC y vNotificación de las capacidades de segmentación de paquetes TCP LSOv2 de una NIC.

Las siguientes suposiciones y restricciones se aplican al procesamiento de encabezados IP y TCP para cualquier controlador de minipuerto compatible con LSO, independientemente de la versión:

  • El bit MF del encabezado IP del paquete TCP grande que no se establecerá el transporte TCP/IP descargado y el desplazamiento de fragmento en el encabezado IP será cero.

  • No se establecerán las marcas URG, RST y SYN en el encabezado TCP del paquete TCP grande y el desplazamiento urgente (puntero) en el encabezado TCP será cero.

  • Si se establece el bit FIN en el encabezado TCP del paquete grande, el controlador de minipuerto debe establecer este bit en el encabezado TCP del último paquete que crea a partir del paquete TCP grande.

  • Si se establece el bit PSH en el encabezado TCP del paquete TCP grande, el controlador de minipuerto debe establecer este bit en el encabezado TCP del último paquete que crea a partir del paquete TCP grande.

  • Si se establece el bit CWR en el encabezado TCP del paquete TCP grande, el controlador de minipuerto debe establecer este bit en el encabezado TCP del primer paquete que crea a partir del paquete TCP grande. El controlador de minipuerto puede elegir establecer este bit en el encabezado TCP del último paquete que crea a partir del paquete TCP grande, aunque esto es menos deseable.

  • Si el paquete TCP grande contiene opciones de IP o TCP (o ambas), el controlador de minipuerto copia estas opciones, sin modificar, en cada paquete derivado del paquete TCP grande. En concreto, la NIC no incrementará la opción Marca de tiempo.

  • Todos los encabezados de paquete (Ethernet, IP, TCP) estarán en la primera MDL del paquete. Los encabezados no se dividirán entre varios MDL.

    Sugerencia

    Esta suposición es válida cuando LSO está habilitado. De lo contrario, cuando LSO no está habilitado, los controladores de minipuerto no pueden suponer que los encabezados IP están en la misma MDL que los encabezados Ethernet.

El controlador de minipuerto debe enviar los paquetes de estructuras NET_BUFFER_LIST en el orden en que recibe las estructuras NET_BUFFER_LIST del transporte TCP/IP.

Al procesar un paquete TCP grande, el adaptador de minipuerto solo es responsable de segmentar el paquete y colocar los encabezados MAC, IP y TCP en los paquetes derivados del paquete TCP grande. El transporte TCP/IP realiza todas las demás tareas (como ajustar el tamaño de la ventana de envío en función del tamaño de la ventana de recepción del host remoto).

Antes de completar la operación de envío para el paquete grande (por ejemplo, con NdisMSendNetBufferListsComplete o NdisMCoSendNetBufferListsComplete), el controlador de minipuerto escribe el valor de NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO (información de NET_BUFFER_LIST para las descargas de envío grandes) con el número total de bytes de datos de usuario TCP que se envían correctamente en todos los paquetes creados a partir del paquete TCP grande.

Además de los requisitos anteriores de LSO, los controladores de minipuerto compatibles con LSOv2 también deben:

  • Admitir IPv4 o IPv6 o IPv4 e IPv6.

  • Admitir la replicación de las opciones IPv4, desde el paquete grande, en cada paquete de segmento que genera la tarjeta de interfaz de red (NIC).

  • Admitir la replicación del encabezado de extensión IPv6, desde el paquete TCP grande, en cada paquete de segmento TCP.

  • Admitir la replicación de opciones TCP en cada paquete de segmento TCP que genera el controlador de minipuerto.

  • Usar el encabezado IP y TCP en la estructura NET_BUFFER_LIST como plantilla para generar encabezados TCP/IP para cada paquete de segmentos.

  • Usar valores de identificación IP (ID de IP) en el intervalo de 0x0000 a 0x7FFF. (El intervalo de 0x8000 a 0xFFFF está reservado para dispositivos compatibles con la descarga de chimenea TCP). Por ejemplo, si el encabezado IP de plantilla comienza con un valor de campo Identificación de 0x7FFE, el primer paquete de segmento TCP debe tener un valor de identificador IP de 0x7FFE, seguido de 0x7FFF, 0x0000, 0x0001, etc.

  • Usar el desplazamiento de bytes en el miembro TcpHeaderOffset de NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO para determinar la ubicación del encabezado TCP, comenzando desde el primer byte del paquete.

  • Limitar el número de estructuras NET_BUFFER asociadas a cada estructura NET_BUFFER_LIST de LSOv2 de una en una.

    Nota:

    Este es un nuevo requisito para los controladores de minipuerto compatibles con LSOv2. Esta regla no se aplica explícitamente a los controladores de minipuerto LSOv1, aunque se recomienda.

  • Determinar la longitud total del paquete a partir de la longitud de la primera estructura NET_BUFFER de la estructura NET_BUFFER_LIST. Esto es diferente del uso de los controladores de método para LSOv1.

  • Admitir opciones TCP, opciones IP y encabezados de extensión IP.

  • Cuando se completa una operación de envío, el controlador de minipuerto debe establecer el miembro LsoV2TransmitComplete.Reserved de la estructura NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO en cero y el miembro LsoV2TransmitComplete.Type en NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE.