Compartir a través de


Descarga de la segmentación de paquetes TCP grandes

Los controladores de minipuerto de la especificación de interfaz de controlador de red (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ío grande (LSOv2), que proporciona servicios mejorados de segmentación de paquetes de gran tamaño, incluida la compatibilidad con IPv6.

Un controlador de miniporte que admita LSOv2 y LSOv1 debe determinar el tipo de descarga a partir de la información de estructura fuera de banda (OOB) de 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 OOB LSOv1 o LSOv2 también contiene una única estructura de 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 miniporte haya recibido OID_TCP_OFFLOAD_PARAMETERS para desactivar la característica LSO en el miniporte y después de que el miniporte haya completado correctamente el OID, el miniporte descartará todos los NET_BUFFER_LIST que contengan cualquier dato OOB de LSOv1 o LSOv2 que no sea cero (NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO).

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

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 Total Length 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 Total Length 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 del complemento a uno para el pseudoencabezado TCP y escribe esta suma en el campo Checksum del encabezado TCP. El transporte TCP/IP calcula la suma del complemento a uno sobre los siguientes campos del pseudoencabezado: Source IP Address, Destination IP Address y Protocol. 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 del pseudoencabezado se calcula sobre Source IP Address, Destination IP Address, Protocol y TCP Length. (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 pseudo encabezado). Sin embargo, dado que el controlador de miniport subyacente y la NIC generan segmentos TCP desde el paquete grande que se pasa por 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 pseudo encabezado. 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 Sequence Number 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 miniporte 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. 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 bytes de datos de usuario de MSS. Si no sigue esta regla, la creación y transmisión de paquetes adicionales innecesarios podría reducir el rendimiento.

El controlador de miniporta 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 igual o menor que el valor que el controlador de miniporte asigna al valor de 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 Notificación de las capacidades de segmentación de paquetes TCP LSOv2 de una NIC.

Una vez que un controlador emite una indicación de estado para indicar un cambio en el valor de MaxOffLoadSize, el controlador no debe bloquearse si recibe una solicitud de envío de LSO que usa el valor de 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 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 de tamaño que el valor de MaxOffLoadSize que notificó el adaptador de miniporte.

Un controlador intermedio de miniporte que responde a OID_TCP_OFFLOAD_PARAMETERS para desactivar los servicios LSO debe estar preparado para un breve período de tiempo en el que las solicitudes de envío de LSO podrían seguir llegando al controlador de miniporte.

La longitud de los datos de usuario TCP en un paquete de segmento debe ser menor o igual que el 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. 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 bytes de datos de usuario de MSS. Si no sigue esta regla, la creación y transmisión de paquetes adicionales innecesarios podría reducir el rendimiento.

El número de paquetes de segmento derivados del paquete TCP grande debe ser igual o mayor que el valor de MinSegmentCount especificado por el controlador de miniport. Para obtener más información sobre el valor de MinSegmentCount, consulte Informar las capacidades TCP-LSOv1 de una NICPacket-Segmentation y Informar las capacidades TCP-LSOv2 de una NICPacket-Segmentation.

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

  • El bit MF del encabezado IP del paquete TCP grande que no 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 ni SYN en el encabezado TCP del paquete TCP grande y el desplazamiento urgente (puntero) en el encabezado TCP será cero.

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

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

  • Si se establece el CWR bit en el encabezado TCP del paquete TCP grande, el controlador de miniport debe establecer este bit en el encabezado TCP del primer paquete que crea a partir del paquete TCP grande. Es posible que el controlador de miniporte elija 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 ip o opciones TCP (o ambas), el controlador de miniporta 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 miniport no pueden suponer que los encabezados IP están en la misma MDL que los encabezados ethernet.

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

Al procesar un paquete TCP grande, el adaptador de miniporte 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 miniport compatibles con LSOv2 también deben:

  • Admite IPv4 o IPv6, o tanto IPv4 como IPv6.

  • Admite 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.

  • Admite la replicación de opciones tcp en cada paquete de segmento TCP que genera el controlador de miniporte.

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

  • Use 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 que soportan la descarga de TCP chimney). Por ejemplo, si el encabezado IP de plantilla comienza con un valor de campo de 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 a una.

    Nota

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

  • Determine 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 de los controladores de método para LSOv1.

  • Admite 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.