Compartilhar via


Descarregar a segmentação de pacotes TCP grandes

Os drivers de miniporta Especificação de Interface de Dispositivo de Rede (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. Uma NIC que dá 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 OOB LSOv1 ou LSOv2 também contém uma única estrutura de 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 apenas os pacotes TCP grandes que atendem aos seguintes critérios:

Antes de descarregar um pacote TCP grande para segmentação, o transporte TCP/IP:

  • No LSOv1, escreve o comprimento total do grande pacote TCP no campo Total Length do cabeçalho IP do pacote. O comprimento total inclui o comprimento do cabeçalho IP, o comprimento das opções de IP se estiverem presentes, o comprimento do cabeçalho TCP, o comprimento das opções TCP se estiverem presentes e o comprimento do conteúdo TCP. Para LSOv2, define o campo Total Length 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 uma soma do complemento para o pseudo-cabeçalho TCP e grava essa soma no campo Checksum do cabeçalho TCP. O transporte TCP/IP calcula a soma complementar sobre os seguintes campos no pseudo-cabeçalho: Source IP Address, Destination IP Address e Protocol. 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. Observe que a RFC 793 estipula que a soma de verificação do pseudo-cabeçalho é calculada sobre os Source IP Address, Destination IP Address, Protocol e TCP Length. (O comprimento TCP é o comprimento do cabeçalho TCP mais o comprimento da carga útil TCP. O comprimento TCP não inclui o comprimento do pseudo-cabeçalho.) No entanto, como o driver de miniporto subjacente e a placa de interface de rede (NIC) geram segmentos TCP do pacote grande que é passado para o transporte TCP/IP, o transporte não sabe o tamanho da carga útil TCP para cada segmento TCP e, portanto, não pode incluir o comprimento TCP no pseudo-cabeç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.

  • Grava o número de sequência correto no campo Sequence Number do cabeçalho TCP. O número de sequência identifica o primeiro byte do conteúdo 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 miniporto obtém o comprimento total do pacote grande do cabeçalho IP do pacote e usa o valor 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 do pacote grande segmentado deve conter menos do que o MSS de bytes de dados do usuário. Todos os outros pacotes criados a partir do pacote segmentado devem conter bytes de dados do usuário de MSS. 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 miniporto 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 RFC 793 e RFC 1122.

A figura a seguir mostra a segmentação de um pacote grande.

Diagrama mostrando a segmentação de um pacote TCP grande em pacotes menores com cabeçalhos MAC, IP e TCP.

O comprimento dos dados do usuário TCP no pacote TCP grande deve ser igual ou menor que o valor que o driver de miniporto atribui ao valor MaxOffLoadSize. Para obter mais informações sobre o valor do MaxOffLoadSize, consulte Relatando os recursos LSOv1 TCP-Packet-Segmentation da NIC e relatando recursos LSOv2 TCP-Packet-Segmentation da NIC.

Depois que um driver emite uma indicação de status para indicar uma alteração no valor MaxOffLoadSize, o driver não deverá falhar se receber uma solicitação de envio de LSO que use o valor MaxOffLoadSize anterior. Em vez disso, o driver pode não atender a solicitação de envio.

Um controlador intermediário que emite independentemente indicações de status relatando uma alteração no valor de MaxOffLoadSize deve garantir que o adaptador miniporto subjacente que não tenha emitido uma indicação de status não receba nenhum pacote maior que o valor de MaxOffLoadSize relatado pelo adaptador miniporto.

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 TCP em um pacote de segmento 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 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 com base no pacote segmentado devem conter bytes de dados de usuário do MSS. 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 segmentos derivados do pacote TCP grande deve ser igual ou maior que o valor MinSegmentCount especificado pelo driver de miniporto. Para obter mais informações sobre o valor do MinSegmentCount, consulte Relatando os recursos LSOv1 TCP-Packet-Segmentation da NIC e relatando recursos LSOv2 TCP-Packet-Segmentation da NIC.

As seguintes suposições e restrições se aplicam ao processamento de cabeçalhos IP e TCP para qualquer driver de miniporto 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 FIN bit no cabeçalho TCP do pacote grande estiver definido, o driver de miniporto deverá definir esse bit no cabeçalho TCP do último pacote que ele cria com base no pacote TCP grande.

  • Se o PSH bit no cabeçalho TCP do pacote TCP grande estiver definido, o driver de miniporto deverá definir esse bit no cabeçalho TCP do último pacote que ele cria a partir do pacote TCP grande.

  • Se o CWR bit no cabeçalho TCP do pacote TCP grande estiver definido, o driver de miniporto deverá definir esse bit no cabeçalho TCP do primeiro pacote que ele cria a partir do pacote TCP grande. O driver de miniporto pode optar por definir esse bit no cabeçalho TCP do último pacote que ele cria a partir do pacote TCP grande, embora isso seja menos desejável.

  • Se o pacote TCP grande contiver opções de IP ou opções TCP (ou ambas), o driver de miniporto copiará essas opções, sem alterações, para cada pacote derivado do pacote TCP grande. Especificamente, o NIC não incrementará a opção 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. Caso contrário, quando o LSO não estiver habilitado, os drivers de miniporto não poderão assumir que os cabeçalhos IP estão no mesmo MDL que os cabeçalhos ethernet.

O driver de miniporto deve enviar os pacotes em estruturas de NET_BUFFER_LIST na ordem em que recebe as estruturas de NET_BUFFER_LIST do protocolo de transporte TCP/IP.

Ao processar um pacote TCP grande, o adaptador de miniporto é responsável apenas por segmentar o pacote e fixar 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 anteriores de LSO, os drivers de miniporto compatíveis com LSOv2 também devem:

  • Suporte para IPv4 ou IPv6 ou IPv4 e IPv6.

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

  • Suporte à replicação de opções TCP em cada pacote de segmento TCP gerado pelo driver de miniporto.

  • Use o cabeçalho IP e TCP na estrutura NET_BUFFER_LIST como um modelo para gerar cabeçalhos TCP/IP para cada pacote de segmento.

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

    Nota

    Esse é um novo requisito para drivers de miniporto compatíveis com LSOv2. Essa regra não é explicitamente imposta para drivers miniport LSOv1, embora seja recomendada.

  • Determine 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 para LSOv1.

  • Suporte para opções TCP, opções de IP e cabeçalhos de extensão IP.

  • Quando uma operação de envio for concluída, o driver de miniporta deverá 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.