Descarregando a segmentação de pacotes TCP grandes
Os drivers de miniporta NDIS podem descarregar a segmentação de pacotes TCP grandes que são maiores do que a unidade máxima de transmissão (MTU) do meio de rede. Um NIC que oferece suporte à segmentação de pacotes TCP grandes também deve ser capaz de:
Calcular somas de verificação de IP para pacotes de envio que contêm opções de IP.
Calcular somas de verificação de TCP para pacotes de envio que contêm opções de TCP.
As versões 6.0 e posteriores do NDIS oferecem suporte ao descarregamento de envio grande versão 1 (LSOv1), que é semelhante ao LSO do NDIS 5.x. As versões 6.0 e posteriores do NDIS também são compatíveis com o LSOv2, que fornece serviços aprimorados de segmentação de pacotes grandes, incluindo suporte para IPv6.
Um driver de miniporta compatível com LSOv2 e LSOv1 deve determinar o tipo de descarregamento das informações OOB da estrutura NET_BUFFER_LIST. O driver pode usar o membro Type da estrutura NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO para determinar se a pilha de drivers está usando LSOv2 ou LSOv1 e executar os serviços de descarregamento apropriados. Qualquer estrutura NET_BUFFER_LIST que contenha os dados de LSOv1 ou LSOv2 OOB também contém uma única estrutura NET_BUFFER. Para obter mais informações sobre NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO, consulte Acessando informações de NET_BUFFER_LIST de descarregamento de TCP/IP.
No entanto, se a miniporta tiver recebido OID_TCP_OFFLOAD_PARAMETERS para desativar o recurso de LSO e depois de concluir o OID com êxito, ela deverá descartar todos os NET_BUFFER_LIST que contêm dados de OOB do LSOv1 ou do LSOv2 diferentes de zero (NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO).
O transporte TCP/IP descarrega somente os pacotes TCP grandes que atendem aos seguintes critérios:
O pacote é um pacote TCP. O transporte TCP/IP não descarrega pacotes UDP grandes para segmentação.
O pacote deve ser divisível por pelo menos o número mínimo de segmentos especificado pelo driver de miniporta. Para obter mais informações, consulte Como relatar os recursos de segmentação de pacotes TCP LSOv1 de um NIC e Como relatar os recursos de segmentação de pacotes TCP LSOv2 de um NIC.
O pacote não é um pacote de loopback.
O pacote não será enviado por meio de um túnel.
Antes de descarregar um pacote TCP grande para segmentação, o transporte TCP/IP:
- Atualiza as informações de segmentação de pacotes grandes associadas à estrutura NET_BUFFER_LIST. Essas informações são uma estrutura NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO que faz parte das informações de NET_BUFFER_LIST associadas à estrutura NET_BUFFER_LIST. Para saber mais sobre informações de NET_BUFFER_LIST, consulte Acessando informações de NET_BUFFER_LIST de descarregamento de TCP/IP. O transporte TCP/IP define o valor MSS para o tamanho máximo do segmento (MSS).
No LSOv1, registra o comprimento total do pacote TCP grande no campo de comprimento total do cabeçalho IP do pacote. O comprimento total inclui o comprimento do cabeçalho IP, o comprimento das opções de IP, se aplicável, o comprimento do cabeçalho TCP, o comprimento das opções de TCP, se aplicável, e o comprimento do conteúdo TCP. No LSOv2, define o campo de comprimento total do cabeçalho IP do pacote como 0. Os drivers de miniporta devem determinar o comprimento do pacote a partir do comprimento da primeira estrutura NET_BUFFER na estrutura NET_BUFFER_LIST.
Calcula a soma do complemento para o pseudocabeçalho TCP e grava essa soma no campo de soma de verificação do cabeçalho TCP. O transporte TCP/IP calcula a soma do complemento sobre os seguintes campos no pseudocabeçalho: endereço IP de origem, endereço IP de destino e protocolo. A soma do complemento para o pseudocabeçalho fornecido pelo transporte TCP/IP ajuda o NIC a começar a calcular a soma de verificação TCP real para cada pacote que o NIC deriva do pacote TCP grande sem precisar examinar o cabeçalho IP. Vale observar que o RFC 793 estipula que a soma de verificação do pseudocabeçalho é calculada sobre o endereço IP de origem, o endereço IP de destino, o protocolo e o comprimento de TCP. (O comprimento de TCP é o comprimento do cabeçalho TCP mais o comprimento do conteúdo de TCP. O comprimento de TCP não inclui o comprimento do pseudocabeçalho.) Porém, como o driver de miniporta subjacente e o NIC geram segmentos TCP a partir do pacote grande que é transmitido pelo transporte TCP/IP, o transporte não sabe o tamanho do conteúdo de TCP para cada segmento TCP e, portanto, não pode incluir o comprimento de TCP no pseudocabeçalho. Em vez disso, conforme descrito abaixo, o NIC estende a soma de verificação do pseudocabeçalho fornecida pelo transporte TCP/IP para cobrir o comprimento de TCP de cada segmento TCP gerado.
Registra o número de sequência correto no campo de número de sequência do cabeçalho TCP. O número de sequência identifica o primeiro byte do conteúdo de TCP.
Depois que o driver de miniporta obtém a estrutura NET_BUFFER_LIST em sua função MiniportSendNetBufferLists ou MiniportCoSendNetBufferLists, ele pode chamar a macro NET_BUFFER_LIST_INFO com um _Id de TcpLargeSendNetBufferListInfo para obter o valor de MSS registrado pelo transporte TCP/IP.
O driver de miniporta obtém o comprimento total do pacote grande do cabeçalho IP do pacote e usa o valor de MSS para dividir o pacote TCP grande em pacotes menores. Cada um dos pacotes menores contém o MSS ou menos bytes de dados do usuário. Somente o último pacote criado a partir do pacote grande segmentado deve conter menos do que o MSS de bytes de dados do usuário. Todos os outros pacotes que foram criados a partir do pacote segmentado devem conter o MSS de bytes de dados do usuário. Se você não seguir essa regra, a criação e a transmissão de pacotes extras desnecessários poderão prejudicar o desempenho.
O driver de miniporta afixa cabeçalhos MAC, IP e TCP para cada segmento derivado do pacote grande. O driver de miniporta deve calcular as somas de verificação de IP e TCP para esses pacotes derivados. Para calcular a soma de verificação de TCP para cada pacote derivado do pacote TCP grande, o NIC calcula a parte variável da soma de verificação de TCP (do cabeçalho de TCP e do conteúdo de TCP), adiciona essa soma de verificação à soma do complemento do pseudocabeçalho calculada pelo transporte TCP/IP e, em seguida, calcula o complemento de 16 bits da soma de verificação. Para obter mais informações sobre como calcular essas somas de verificação, consulte o RFC 793 e o RFC 1122.
A figura a seguir mostra a segmentação de um pacote grande.
O comprimento dos dados do usuário TCP no pacote TCP grande deve ser igual ou menor que o valor atribuído pelo driver de miniporta ao valor de MaxOffLoadSize. Para obter mais informações sobre o valor de MaxOffLoadSize, consulte Como relatar os recursos de segmentação de pacotes TCP LSOv1 de um NIC e Como relatar os recursos de segmentação de pacotes TCP LSOv2 de um NIC.
Depois que um driver emite uma indicação de status para sinalizar uma alteração no valor de MaxOffLoadSize, ele não deve falhar se receber uma solicitação de envio do LSO que use o valor anterior de MaxOffLoadSize. Em vez disso, o driver pode não atender a solicitação de envio.
Um driver intermediário que emite, de modo independente, indicações de status que informam uma alteração no valor de MaxOffLoadSize deve garantir que o adaptador de miniporta subjacente que não emitiu uma indicação de status não obtenha pacotes maiores do que o valor de MaxOffLoadSize reportado pelo adaptador de miniporta.
Um driver intermediário de miniporta que responde a OID_TCP_OFFLOAD_PARAMETERS para desativar os serviços do LSO deve estar preparado para uma pequena janela de tempo em que as solicitações de envio do LSO ainda podem chegar ao driver de miniporta.
O comprimento dos dados do usuário de TCP em um pacote de segmentos deve ser menor ou igual ao MSS. O MSS é o valor ULONG que o transporte TCP transmite usando as informações de NET_BUFFER_LIST do LSO associadas à estrutura NET_BUFFER_LIST. Somente o último pacote criado a partir do pacote grande segmentado deve conter menos do que o MSS de bytes de dados do usuário. Todos os outros pacotes que foram criados a partir do pacote segmentado devem conter o MSS de bytes de dados do usuário. Se você não seguir essa regra, a criação e a transmissão de pacotes extras desnecessários poderão prejudicar o desempenho.
O número de pacotes de segmento que foram derivados do pacote TCP grande deve ser igual ou maior do que o valor de MinSegmentCount especificado pelo driver de miniporta. Para obter mais informações sobre o valor de MinSegmentCount, consulte Como relatar os recursos de segmentação de pacotes TCP LSOv1 de um NIC e Como relatar os recursos de segmentação de pacotes TCP LSOv2 de um NIC.
As seguintes suposições e restrições se aplicam ao processamento de cabeçalhos IP e TCP de qualquer driver de miniporta compatível com LSO, independentemente da versão:
O bit MF no cabeçalho IP do pacote TCP grande descarregado pelo transporte TCP/IP não será definido, e o deslocamento de fragmento no cabeçalho IP será zero.
Os sinalizadores URG, RST e SYN no cabeçalho TCP do pacote TCP grande não serão definidos, e o deslocamento urgente (ponteiro) no cabeçalho TCP será zero.
Se o bit FIN no cabeçalho TCP do pacote grande estiver definido, o driver de miniporta deverá definir esse bit no cabeçalho TCP do último pacote que criar a partir do pacote TCP grande.
Se o bit PSH no cabeçalho TCP do pacote TCP grande estiver definido, o driver de miniporta deverá definir esse bit no cabeçalho TCP do último pacote que criar a partir do pacote TCP grande.
Se o bit CWR no cabeçalho TCP do pacote TCP grande estiver definido, o driver de miniporta deverá definir esse bit no cabeçalho TCP do primeiro pacote que criar a partir do pacote TCP grande. O driver de miniporta pode optar por definir esse bit no cabeçalho TCP do último pacote que criar a partir do pacote TCP grande, embora isso seja menos desejável.
Se o pacote TCP grande contiver opções de IP ou de TCP (ou ambas), o driver de miniporta copiará essas opções, inalteradas, para cada pacote derivado do pacote TCP grande. Especificamente, o NIC não incrementará a opção de carimbo de data/hora.
Todos os cabeçalhos de pacote (Ethernet, IP, TCP) estarão no primeiro MDL do pacote. Os cabeçalhos não serão divididos em vários MDLs.
Dica
Essa suposição é válida quando o LSO está habilitado. Do contrário, quando o LSO não está habilitado, os drivers de miniporta não podem presumir que os cabeçalhos IP estão no mesmo MDL que os cabeçalhos Ethernet.
O driver de miniporta deve enviar os pacotes em estruturas NET_BUFFER_LIST na ordem em que recebe essas estruturas do transporte TCP/IP.
Ao processar um pacote TCP grande, o adaptador de miniporta só é responsável por segmentá-lo e afixar cabeçalhos MAC, IP e TCP nos pacotes derivados do pacote TCP grande. O transporte TCP/IP executa todas as outras tarefas (como ajustar o tamanho da janela de envio com base no tamanho da janela de recebimento do host remoto).
Antes de concluir a operação de envio do pacote grande (como faz com NdisMSendNetBufferListsComplete ou NdisMCoSendNetBufferListsComplete), o driver de miniporta grava o valor de NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO (informações de NET_BUFFER_LIST referentes a descarregamentos de envios grandes) com o número total de bytes de dados do usuário de TCP enviados com êxito em todos os pacotes que foram criados a partir do pacote TCP grande.
Além dos requisitos de LSO anteriores, os drivers de miniporta compatíveis com LSOv2 também devem:
Dar suporte para IPv4, IPv6 ou para ambos.
Dar suporte à replicação das opções de IPv4, a partir do pacote grande, em cada pacote de segmentos gerado pelo adaptador de rede (NIC).
Dar suporte à replicação do cabeçalho de extensão IPv6, a partir do pacote TCP grande, em cada pacote de segmentos TCP.
Dar suporte à replicação de opções TCP em cada pacote de segmentos TCP gerado pelo driver de miniporta.
Usar o cabeçalho IP e TCP na estrutura NET_BUFFER_LIST como modelo para gerar cabeçalhos TCP/IP para cada pacote de segmentos.
Usar valores de identificação IP (IP ID) no intervalo de 0x0000 a 0x7FFF. (O intervalo de 0x8000 a 0xFFFF é reservado para dispositivos com capacidade de descarregamento de chimney TCP). Por exemplo, se o cabeçalho IP do modelo começar com um valor de campo identificação de 0x7FFE, o primeiro pacote de segmentos TCP deverá ter um valor IP ID de 0x7FFE, seguido por 0x7FFF, 0x0000, 0x0001 e assim por diante.
Usar o deslocamento de byte no membro TcpHeaderOffset de NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO para determinar a localização do cabeçalho TCP, a partir do primeiro byte do pacote.
Limitar a 1 o número de estruturas NET_BUFFER associadas a cada estrutura NET_BUFFER_LIST do LSOv2.
Observação
Esse é um requisito novo para os drivers de miniporta compatíveis com LSOv2. Essa regra não se aplica para drivers de miniporta LSOv1 explicitamente, embora seja recomendada.
Determinar o comprimento total do pacote a partir do comprimento da primeira estrutura NET_BUFFER na estrutura NET_BUFFER_LIST. Isso é diferente dos drivers de método usados para LSOv1.
Dar suporte a opções de TCP, a opções de IP e a cabeçalhos de extensão IP.
Quando uma operação de envio é concluída, o driver de miniporta deve definir o membro LsoV2TransmitComplete.Reserved da estrutura NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO como zero e o membro LsoV2TransmitComplete.Type como NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE.