Descarregamento de segmentação UDP (USO)

O descarregamento de segmentação UDP (USO), suportado no Windows 10, versão 2004 e em versões posteriores, é um recurso que permite aos adaptadores de rede (NICs) descarregar a segmentação de datagramas UDP que são maiores do que a unidade máxima de transmissão (MTU) do meio de rede. Ao fazer isso, o Windows reduz a utilização da CPU associada ao processamento TCP/IP por pacote. Os requisitos do USO são semelhantes aos do LSOv2 para o protocolo de transporte TCP.

Requisitos do USO

Esta seção refere-se principalmente ao protocolo NDIS e aos drivers de miniporta. Os drivers de filtro leve (LWFs) do NDIS devem seguir os requisitos de driver de protocolo ao modificar ou enviar pacotes e também podem presumir que todos os pacotes fornecidos ao manipulador FilterSendNetBufferLists atendem aos requisitos de driver do protocolo.

Os drivers de miniporta podem descarregar a segmentação de pacotes UDP grandes que são maiores do que a MTU do meio de rede. Um NIC com suporte à segmentação de pacotes UDP grandes também deve ser capaz de fazer o seguinte:

  • Calcular somas de verificação de IP para pacotes enviados que contêm opções de IPv4
  • Calcular somas de verificação de UDP para pacotes enviados

Um driver de miniporta com suporte para USO deve determinar o tipo de descarregamento com base nas informações OOB (fora de banda) da estrutura NET_BUFFER_LIST . Se o valor da estrutura NDIS_UDP_SEGMENTATION_OFFLOAD_NET_BUFFER_LIST_INFO for diferente de zero, o driver de miniporta deverá executar o USO. Qualquer NET_BUFFER_LIST que contém dados OOB do USO também contém uma única estrutura NET_BUFFER. No entanto, se o driver de miniporta tiver recebido OID_TCP_OFFLOAD_PARAMETERS para desativar o USO, depois de concluir o OID com êxito, ele deverá rejeitar e retornar qualquer NET_BUFFER_LIST que tenha o campo de OOB do USO definido.

O transporte TCP/IP descarrega somente os pacotes UDP que atendem aos seguintes critérios:

  • O pacote é um pacote UDP.
  • O comprimento do pacote deve ser maior do que o tamanho máximo do segmento (MSS) * (MinSegmentCount - 1).
  • Se o driver de miniporta não definir o recurso SubMssFinalSegmentSupported , cada pacote UDP grande descarregado pelo transporte deverá ter Length % MSS == 0. Ou seja, o pacote grande é divisível em N pacotes, com cada segmento de pacote contendo exatamente MSS de bytes de dados do usuário. Se o driver de miniporta definir o recurso SubMssFinalSegmentSupported, essa condição de divisibilidade do comprimento do pacote no transporte não se aplicará. Ou seja, o segmento final pode ser menor do que o MSS.
  • O pacote não é um pacote de loopback.
  • O bit MF no cabeçalho IP do pacote UDP grande descarregado pelo transporte TCP/IP não será definido, e o deslocamento de fragmento no cabeçalho IP será zero.
  • O aplicativo especificou UDP_SEND_MSG_SIZE/WSASetUdpSendMessageSize.

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

  • Atualiza as informações de segmentação de pacotes grandes associadas à estrutura NET_BUFFER_LIST. Essas informações são uma estrutura NDIS_UDP_SEGMENTATION_OFFLOAD_NET_BUFFER_LIST_INFO que faz parte das informações OOB da estrutura NET_BUFFER_LIST. O transporte TCP/IP define o valor de MSS para o MSS desejado.
  • Calcula a soma do complemento para o pseudocabeçalho UDP e grava essa soma no campo Checksum do cabeçalho UDP. O transporte TCP/IP calcula a soma dos complementos 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 UDP real para cada pacote que o NIC deriva do pacote UDP grande, sem precisar examinar o cabeçalho IP.

Observe que o RFC 768 e o RFC 2460 estipulam que o pseudocabeçalho é calculado com base no endereço IP de origem, no endereço IP de destino, no protocolo e no comprimento UDP (o comprimento do cabeçalho UDP mais o comprimento do conteúdo UDP, não incluindo o comprimento do pseudocabeçalho). No entanto, como o driver de miniporta subjacente e o NIC geram datagramas UDP do pacote grande transmitido pelo transporte TCP/IP, o transporte não sabe o tamanho do conteúdo UDP de cada datagrama UDP e, por isso, não pode incluir o comprimento de UDP no cálculo do pseudocabeçalho. Em vez disso, conforme descrito na próxima seção, o NIC estende a soma de verificação do pseudocabeçalho fornecida pelo transporte TCP/IP para cobrir o comprimento de UDP de cada datagrama UDP gerado.

Importante

Se o campo de soma de verificação do cabeçalho UDP fornecido pelo transporte TCP/IP for zero, o NIC não deverá executar o cálculo da soma de verificação de UDP.

Enviando pacotes com USO

Depois que o driver de miniporta obtém NET_BUFFER_LIST em sua função de retorno de chamada MiniportSendNetBufferLists , ele pode chamar a macro NET_BUFFER_LIST_INFO com _Id de UdpSegmentationOffloadInfo para obter o valor de MSS e o protocolo IP.

O driver de miniporta obtém o comprimento total do pacote grande a partir do comprimento da primeira estrutura NET_BUFFER e usa o valor de MSS para dividir o pacote UDP grande em pacotes UDP 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 um driver de miniporta não obedecer a essa regra, os datagramas UDP serão entregues incorretamente. Se o driver de miniporta não definir o recurso SubMssFinalSegmentSupported , o comprimento do pacote será dividido pelo MSS e cada um dos pacotes segmentados conterá o MSS de bytes de dados do usuário.

O driver de miniporta afixa cabeçalhos MAC, IP e UDP para cada segmento derivado do pacote grande. O driver de miniporta deve calcular as somas de verificação de IP e UDP para esses pacotes derivados. Para calcular a soma de verificação de UDP para cada pacote derivado do pacote UDP grande, o NIC calcula a parte variável da soma de verificação de UDP (do cabeçalho de UDP e do conteúdo de TCP), adiciona essa soma de verificação à soma do complemento do pseudocabeçalho que foi 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 768 e o RFC 2460.

O comprimento dos dados do usuário UDP no pacote UDP grande deve ser menor ou igual ao valor atribuído pelo driver de miniporta ao valor de MaxOffLoadSize.

Depois que um driver emite uma indicação de status para sinalizar uma alteração no valor de MaxOffLoadSize, ele não deve causar uma verificação de bugs se receber uma solicitação de envio do LSO que use o valor anterior de MaxOffLoadSize. Em vez disso, o driver deve não atender a solicitação de envio. Os drivers devem não atender a nenhuma solicitação de envio que não possam executar, por qualquer motivo (incluindo tamanho, contagem mínima de segmentos, opções de IP etc.). Os drivers devem enviar uma indicação de status o mais rápido possível se suas capacidades forem alteradas.

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 USO deve estar preparado para uma pequena janela de tempo em que as solicitações do USO ainda podem chegar ao driver de miniporta.

O número de pacotes de segmentação que foram derivados do pacote UDP grande deve ser igual ou maior do que o valor de MinSegmentCount especificado pelo driver de miniporta.

Ao processar um pacote UDP grande, o driver de miniporta só é responsável por segmentá-lo e afixar cabeçalhos MAC, IP e UDP nos pacotes derivados do pacote UDP grande. Se a miniporta não conseguir enviar pelo menos um pacote segmentado, a NBL acabará sendo concluída com um status de falha. A miniporta pode continuar enviando os pacotes subsequentes, mas não precisa fazer isso. A NBL não pode ser concluída de volta para o NDIS até que todos os pacotes segmentados tenham sido transmitidos ou tenham falhado.

Os drivers de miniporta compatíveis com USO também devem fazer o seguinte:

  • Dar suporte para IPv4 e IPv6.
  • Dar suporte à replicação de opções de IPv4 a partir do pacote grande em cada pacote segmentado gerado pelo NIC.
  • Usar o cabeçalho IP e UDP na estrutura NET_BUFFER_LIST como modelo para gerar cabeçalhos UDP e IP para cada pacote segmentado.
  • Usar valores de identificação IP (IP ID) no intervalo de 0x0000 a 0xFFFF. Por exemplo, se o cabeçalho IP do modelo começar com um valor do campo de identificação de 0xFFFE, o primeiro pacote de datagrama UDP deverá ter um valor de 0xFFFE, seguido por 0xFFFF, 0x0000, 0x0001 e assim por diante.
  • Se o pacote UDP grande contém opções de IP, o driver de miniporta copia essas opções, inalteradas, para cada pacote derivado do pacote UDP grande.
  • Usar o deslocamento de byte no membro UdpHeaderOffset de NDIS_UDP_SEGMENTATION_OFFLOAD_NET_BUFFER_LIST_INFO para determinar a localização do cabeçalho UDP, a partir do primeiro byte do pacote.
  • Incrementar as estatísticas de transmissão com base nos pacotes segmentados. Por exemplo, inclua a contagem de bytes de cabeçalho Ethernet, IP e UDP para cada segmento de pacote, e a contagem de pacotes será o número de segmentos do tamanho do MSS, não 1.
  • Defina os campos de comprimento total de UDP e comprimento de IP com base no tamanho de cada datagrama segmentado.

Alterações na interface NDIS

Esta seção descreve as alterações no NDIS 6.83 que permitem que a pilha de drivers TCP/IP do host aproveite os recursos do USO expostos pelos drivers de miniporta.

O NDIS e o driver de miniporta fazem o seguinte:

  • Anunciam que o NIC dá suporte para o recurso USO
  • Habilitar ou desabilitar o USO
  • Obtêm o estado atual da funcionalidade USO

Anunciando o recurso USO

Os drivers de miniporta anunciam o recurso USO preenchendo o campo UdpSegmentation da estrutura NDIS_OFFLOAD, que é passada nos parâmetros de NdisMSetMiniportAttributes. O campo Header.Revision na estrutura NDIS_OFFLOAD deve ser definido como NDIS_OFFLOAD_REVISION_6 e o campo Header.Size deve ser definido como NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_6.

Consultando o estado do USO

O estado atual do USO pode ser consultado com OID_TCP_OFFLOAD_CURRENT_CONFIG. O NDIS processa esse OID e não o transmite para o driver de miniporta.

Alterando o estado do USO

O USO pode ser habilitado ou desabilitado usando OID_TCP_OFFLOAD_PARAMETERS. Depois que o driver de miniporta processa o OID, ele deve enviar uma indicação de status NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG com o estado de descarregamento atualizado.

Palavras-chave do USO

As palavras-chave de enumeração do USO são as seguintes:

  • *UsoIPv4
  • *UsoIPv6

Esses valores descrevem se o USO está habilitado ou desabilitado para o protocolo IP específico. As configurações de USO não dependem da configuração de NDIS_TCP_IP_CHECKSUM_OFFLOAD. Por exemplo, desabilitar *UDPChecksumOffloadIPv4 não desabilita *UsoIPv4 implicitamente.

Nome da subchave Descrição do parâmetro Valor Descrição de Enum
*UsoIPv4 Descarregamento de segmentação UDP (IPv4) 0 Desabilitado
1 habilitado
*UsoIPv6 Descarregamento de segmentação UDP (IPV6) 0 Desabilitado
1 habilitado