Descarregamento de segmentação UDP (USO)
O USO (descarregamento de segmentação UDP), com suporte no Windows 10, versão 2004 e posterior, é um recurso que permite que as NICs (placas de interface de rede) descarregam a segmentação de datagramas UDP maiores que a MTU (unidade de transmissão máxima) do meio de rede. Ao fazer isso, o Windows reduz a utilização da CPU associada ao processamento de TCP/IP por pacote. Os requisitos para USO são semelhantes a descarga de envio grande versão 2 (LSOv2), que é para o protocolo de transporte TCP.
Requisitos para 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. Uma NIC que dá 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 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 contenha dados USO OOB também contém uma única estrutura de 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 apenas os pacotes UDP que atendem aos seguintes critérios:
- O pacote é um pacote UDP.
- O comprimento do pacote deve ser maior que o tamanho máximo do segmento
(MSS) * (MinSegmentCount - 1)
. - Se o controlador de miniporta não definir a funcionalidade
SubMssFinalSegmentSupported
, cada pacote UDP grande transferido pelo transporte deverá terLength % 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 miniporto definir a funcionalidadeSubMssFinalSegmentSupported
, essa condição de divisibilidade de comprimento do pacote no transporte não se aplicará. Em outras palavras, o segmento final pode ser menor que 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 a informação de segmentação de grandes pacotes que está associada à 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 uma 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 RFC 768 e RFC 2460 estipulam que o pseudoheader é calculado sobre o endereço IP de origem, o endereço IP de destino, o protocolo e o comprimento UDP (o comprimento do cabeçalho UDP mais o comprimento do payload UDP, não incluindo o comprimento do pseudoheader). No entanto, como o driver de miniporta subjacente e o NIC geram datagramas UDP do pacote grande que é 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.
Enviar pacotes com USO
Após o driver de miniporta obter o NET_BUFFER_LIST em sua função de retorno de chamada MiniportSendNetBufferLists, ele pode chamar o macro NET_BUFFER_LIST_INFO com um _Id
de UdpSegmentationOffloadInfo
para obter o valor MSS e protocolo de IP.
O driver de miniporto obtém o comprimento total do pacote grande a partir do comprimento da primeira estrutura NET_BUFFER e usa o valor MSS para dividir o pacote UDP grande em pacotes UDP menores. Cada um dos pacotes menores contém MSS ou menos bytes de dados do usuário. Somente o último pacote criado com base no pacote grande segmentado deve conter menos de MSS bytes de dados do usuário. Todos os outros pacotes criados com base no pacote segmentado devem conter MSS bytes de dados do usuário. Se um driver de miniporto não aderir a essa regra, os datagramas UDP serão entregues incorretamente. Se o driver de miniporta não definir a função SubMssFinalSegmentSupported
, o comprimento do pacote é dividido por MSS e cada um dos pacotes segmentados contém bytes de usuário MSS.
O driver de miniporto 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 RFC 768 e 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 MaxOffLoadSize
.
Depois que um driver emite uma indicação de status para indicar uma alteração para MaxOffLoadSize
, o driver não deve causar uma checagem de erro se receber uma solicitação de envio de LSO que usa o valor MaxOffLoadSize
anterior. Em vez disso, o driver deve não atender a solicitação de envio. Os drivers devem rejeitar qualquer solicitação de envio que não possam executar, por qualquer motivo (incluindo tamanho, número mínimo 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 independentemente indicações de status relatando uma alteração no valor de MaxOffLoadSize
deve garantir que o adaptador de miniporto subjacente, que não emitiu uma indicação de status, não receba nenhum pacote maior que o valor de MaxOffLoadSize
relatado pelo adaptador de miniporto.
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 derivados do pacote UDP grande deve ser igual ou maior que o valor de MinSegmentCount
especificado pelo driver de miniporto.
Ao processar um pacote UDP grande, o driver de miniport é responsável apenas por segmentar o pacote e fixar 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. O miniporto pode continuar enviando pacotes subsequentes, mas não é necessário fazê-lo. 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:
- Dê suporte ao IPv4 e ao IPv6.
- Permitir a replicação das opções IPv4 do pacote grande em cada pacote segmentado gerado pela NIC.
- Use o cabeçalho IP e UDP na estrutura NET_BUFFER_LIST como um modelo para gerar cabeçalhos UDP e IP para cada pacote segmentado.
- Use valores de identificação de IP (ID de IP) no intervalo de 0x0000 a 0xFFFF. Por exemplo, se o cabeçalho IP do modelo começar com um valor de campo de identificação de 0xFFFE, o primeiro pacote de datagrama UDP deverá ter um valor de 0xFFFE, seguido por 0xFFFF, 0x0000, 0x0001e assim por diante.
- Se o pacote UDP grande contiver opções de IP, o driver de miniporto copiará essas opções, sem alterações, 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 o comprimento total do UDP e os campos de comprimento ip com base em cada tamanho de datagrama segmentado.
Alterações na interface do 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:
- Anuncie que a NIC dá suporte à funcionalidade USO
- Habilitar ou desabilitar USO
- Obter 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 USO são as seguintes:
*UsoIPv4
*UsoIPv6
Esses valores descrevem se o USO está habilitado ou desabilitado para esse protocolo IP específico. As configurações do USO não dependem da configuração de NDIS_TCP_IP_CHECKSUM_OFFLOAD. Por exemplo, desabilitar *UDPChecksumOffloadIPv4
não desabilita implicitamente *UsoIPv4
.
Nome da subchave | Descrição do parâmetro | Valor | Descrição de Enum |
---|---|---|---|
*UsoIPv4 |
USO (IPv4) | 0 | Desabilitadas |
1 | Enabled | ||
*UsoIPv6 |
USO (IPV6) | 0 | Desabilitado |
1 | Enabled |