Partager via


‭Segmentation des paquets UDP (USO)

UDP Segmentation Offload (USO), pris en charge dans Windows 10, version 2004 et ultérieure, est une fonctionnalité qui permet aux cartes d’interface réseau (NIC) de déléguer la segmentation des datagrammes UDP plus grands que l’unité de transmission maximale (MTU) du support réseau. Ce faisant, Windows réduit l’utilisation du CPU associée au traitement TCP/IP par paquet. Les exigences pour USO sont similaires à LSOv2, qui est pour le protocole de transport TCP.

Exigences pour USO

Cette section se réfère principalement aux pilotes de protocole NDIS et aux pilotes miniports. Les pilotes de filtre léger NDIS (LWF) doivent suivre les exigences des pilotes de protocole lors de la modification ou de l’envoi de paquets, et peuvent également supposer que tous les paquets fournis à leur gestionnaire FilterSendNetBufferLists répondent aux exigences des pilotes de protocole.

Les pilotes miniports peuvent déléguer la segmentation des grands paquets UDP plus grands que la MTU du support réseau. Une NIC qui prend en charge la segmentation des grands paquets UDP doit également être capable de :

  • Calculer les sommes de contrôle IP pour les paquets envoyés contenant des options IPv4
  • Calculer les sommes de contrôle UDP pour les paquets envoyés

Un pilote miniport qui prend en charge USO doit déterminer le type de délégation à partir des informations hors bande (OOB) de la structure NET_BUFFER_LIST. Si la valeur de la structure NDIS_UDP_SEGMENTATION_OFFLOAD_NET_BUFFER_LIST_INFO est non nulle, alors le pilote miniport doit effectuer l’USO. Tout NET_BUFFER_LIST contenant des données OOB USO contient également une seule structure NET_BUFFER. Cependant, dans le cas où le pilote miniport a reçu OID_TCP_OFFLOAD_PARAMETERS pour désactiver l’USO, après que le pilote miniport a complété l’OID avec succès, il doit rejeter et retourner toute NET_BUFFER_LIST ayant le champ OOB USO défini.

Le transport TCP/IP délègue uniquement les paquets UDP qui répondent aux critères suivants :

  • Le paquet est un paquet UDP.
  • La longueur du paquet doit être supérieure à la taille maximale du segment (MSS) * (MinSegmentCount - 1).
  • Si le pilote miniport ne définit pas la capacité SubMssFinalSegmentSupported, alors chaque grand paquet UDP délégué par le transport doit avoir Length % MSS == 0. C’est-à-dire que le grand paquet est divisible en N paquets avec chaque segment de paquet contenant exactement MSS octets utilisateur. Si le pilote miniport définit la capacité SubMssFinalSegmentSupported, alors cette condition de divisibilité de la longueur du paquet sur le transport ne s’applique pas. En d’autres termes, le segment final peut être inférieur à MSS.
  • Le paquet n’est pas un paquet de bouclage.
  • Le bit MF dans l’en-tête IP du grand paquet UDP délégué par le transport TCP/IP ne sera pas défini, et le Fragment Offset dans l’en-tête IP sera zéro.
  • L’application a spécifié UDP_SEND_MSG_SIZE/WSASetUdpSendMessageSize.

Avant de déléguer un grand paquet UDP pour la segmentation, le transport TCP/IP fait ce qui suit :

  • Met à jour les informations de segmentation des grands paquets associées à la structure NET_BUFFER_LIST. Ces informations sont une structure NDIS_UDP_SEGMENTATION_OFFLOAD_NET_BUFFER_LIST_INFO qui fait partie des informations OOB de la structure NET_BUFFER_LIST. Le transport TCP/IP définit la valeur MSS à la MSS souhaitée.
  • Calcule une somme de contrôle complément à un pour le pseudo-en-tête UDP et écrit cette somme dans le champ Checksum de l’en-tête UDP. Le transport TCP/IP calcule la somme complémentaire à un sur les champs suivants dans le pseudo-en-tête : Adresse IP source, Adresse IP de destination et Protocole.

La somme complémentaire à un pour le pseudo-en-tête fournie par le transport TCP/IP donne à la NIC un avantage pour calculer la vraie somme de contrôle UDP pour chaque paquet que la NIC dérive du grand paquet UDP, sans avoir à examiner l’en-tête IP.

Notez que RFC 768 et RFC 2460 stipulent que le pseudo-en-tête est calculé sur l’adresse IP source, l’adresse IP de destination, le protocole et la longueur UDP (la longueur de l’en-tête UDP plus la longueur de la charge utile UDP, sans inclure la longueur du pseudo-en-tête). Cependant, parce que le pilote miniport sous-jacent et la NIC génèrent des datagrammes UDP à partir du grand paquet transmis par le transport TCP/IP, le transport ne connaît pas la taille de la charge utile UDP pour chaque datagramme UDP et ne peut donc pas inclure la longueur UDP dans le calcul du pseudo-en-tête. Au lieu de cela, comme décrit dans la section suivante, la NIC étend la somme de contrôle du pseudo-en-tête fournie par le transport TCP/IP pour couvrir la longueur UDP de chaque datagramme UDP généré.

Important

Si le champ de somme de contrôle de l’en-tête UDP fourni par le transport TCP/IP est zéro, la NIC ne doit pas effectuer le calcul de la somme de contrôle UDP.

Envoi de paquets avec USO

Après que le pilote miniport a obtenu la NET_BUFFER_LIST dans sa fonction de rappel MiniportSendNetBufferLists, il peut appeler la macro NET_BUFFER_LIST_INFO avec un _Id de UdpSegmentationOffloadInfo pour obtenir la valeur MSS et le protocole IP.

Le pilote miniport obtient la longueur totale du grand paquet à partir de la longueur de la première structure NET_BUFFER et utilise la valeur MSS pour diviser le grand paquet UDP en plus petits paquets UDP. Chacun des petits paquets contient MSS ou moins d’octets de données utilisateur. Notez que seul le dernier paquet créé à partir du paquet segmenté doit contenir moins d’octets de données utilisateur MSS. Tous les autres paquets créés à partir du paquet segmenté doivent contenir des octets de données utilisateur MSS. Si un pilote miniport ne respecte pas cette règle, les datagrammes UDP seront incorrectement livrés. Si le pilote miniport ne définit pas la capacité SubMssFinalSegmentSupported, alors la longueur du paquet se divise par MSS et chacun des paquets segmentés contient MSS octets utilisateur.

Le pilote de miniport fixe les en-têtes MAC, IP et UDP à chaque segment dérivé du grand paquet. Le pilote de miniport doit calculer les sommes de contrôle IP et UDP pour ces paquets dérivés. Pour calculer la somme de contrôle UDP pour chaque paquet dérivé du grand paquet UDP, la NIC calcule la partie variable de la somme de contrôle UDP (pour l’en-tête UDP et la charge utile UDP), ajoute cette somme de contrôle à la somme complémentaire à un pour le pseudo-en-tête calculée par le transport TCP/IP, puis calcule le complément à un de 16 bits pour la somme de contrôle. Pour plus d’informations sur le calcul de ces sommes de contrôle, voir RFC 768 et RFC 2460.

La longueur des données utilisateur UDP dans le grand paquet UDP doit être inférieure ou égale à la valeur que le pilote de miniport attribue à la valeur MaxOffLoadSize.

Après qu’un pilote a émis une indication de statut pour indiquer un changement de la valeur MaxOffLoadSize, le pilote ne doit causer un bug check s’il reçoit une demande d’envoi LSO utilisant la valeur MaxOffLoadSize précédente. Au lieu de cela, le pilote doit échouer à la demande d’envoi. Les pilotes doivent échouer toute demande d’envoi qu’ils ne peuvent pas exécuter, pour quelque raison que ce soit (y compris la taille, le nombre minimum de segments, les options IP, etc.). Les pilotes doivent envoyer une indication de statut dès que possible si leurs capacités changent.

Un pilote intermédiaire qui émet indépendamment des indications de statut signalant un changement de la valeur MaxOffLoadSize doit s’assurer que l’adaptateur de miniport sous-jacent qui n’a pas émis d’indication de statut ne reçoit aucun paquet plus important que la valeur MaxOffLoadSize signalée par l’adaptateur de miniport.

Un pilote miniport-intermédiaire qui répond à OID_TCP_OFFLOAD_PARAMETERS pour désactiver les services USO doit être prêt pour une petite fenêtre de temps où des demandes USO pourraient encore atteindre le pilote miniport.

Le nombre de paquets de segmentation dérivés du grand paquet UDP doit être égal ou supérieur à la valeur MinSegmentCount spécifiée par le pilote miniport.

Lors du traitement d’un grand paquet UDP, le pilote miniport est responsable uniquement de la segmentation du paquet et de l’ajout des en-têtes MAC, IP et UDP aux paquets dérivés du grand paquet UDP. Si le miniport ne parvient pas à envoyer au moins un paquet segmenté, la NBL doit finalement être complétée avec un statut d’échec. Le miniport peut continuer à envoyer des paquets ultérieurs mais n’est pas obligé de le faire. La NBL ne peut pas être complétée de retour à NDIS tant que tous les paquets segmentés n’ont pas été transmis ou échoués.

Les pilotes miniports compatibles USO doivent également faire ce qui suit :

  • Prendre en charge à la fois IPv4 et IPv6.
  • Prendre en charge la réplication des options IPv4 à partir du grand paquet dans chaque paquet segmenté généré par la NIC.
  • Utiliser l’en-tête IP et UDP dans la structure NET_BUFFER_LIST comme modèle pour générer les en-têtes UDP et IP pour chaque paquet segmenté.
  • Utiliser des valeurs d’identification IP (ID IP) dans la plage de 0x0000 à 0xFFFF. Par exemple, si l’en-tête IP modèle commence avec une valeur de champ d’identification de 0xFFFE, le premier paquet datagramme UDP doit avoir une valeur de 0xFFFE, suivi de 0xFFFF, 0x0000, 0x0001, et ainsi de suite.
  • Si le grand paquet UDP contient des options IP, le pilote miniport copie ces options, non modifiées, dans chaque paquet dérivé du grand paquet UDP.
  • Utiliser le décalage en octets dans le membre UdpHeaderOffset de NDIS_UDP_SEGMENTATION_OFFLOAD_NET_BUFFER_LIST_INFO pour déterminer l’emplacement de l’en-tête UDP, à partir du premier octet du paquet.
  • Incrémenter les statistiques de transmission en fonction des paquets segmentés. Par exemple, inclure le nombre d’octets des en-têtes Ethernet, IP et UDP pour chaque segment de paquet, et le nombre de paquets est le nombre de segments de taille MSS, pas 1.
  • Définir les champs de longueur totale UDP et de longueur IP en fonction de la taille de chaque datagramme segmenté.

Modifications de l’interface NDIS

Cette section décrit les modifications apportées à NDIS 6.83 qui permettent à la pile de pilotes TCP/IP hôte d’exploiter les capacités USO exposées par les pilotes miniports.

NDIS et le pilote miniport effectuent les actions suivantes :

  • Annoncer que la NIC prend en charge la capacité USO
  • Activer ou désactiver USO
  • Obtenir l’état fonctionnel actuel de l’USO

Annoncer la capacité USO

Les pilotes miniports annoncent la capacité USO en remplissant le champ UdpSegmentation de la structure NDIS_OFFLOAD, qui est passée dans les paramètres de NdisMSetMiniportAttributes. Le champ Header.Revision dans la structure NDIS_OFFLOAD doit être défini sur NDIS_OFFLOAD_REVISION_6 et le champ Header.Size doit être défini sur NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_6.

Interroger l’état de l’USO

L’état actuel de l’USO peut être interrogé avec OID_TCP_OFFLOAD_CURRENT_CONFIG. NDIS gère cet OID et ne le transmet pas au pilote miniport.

Modifier l’état de l’USO

L’USO peut être activé ou désactivé à l’aide de OID_TCP_OFFLOAD_PARAMETERS. Après que le pilote miniport a traité l’OID, il doit envoyer une indication de statut NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG avec l’état de délégation mis à jour.

Mots clés USO

Les mots-clés d’énumération USO sont les suivants :

  • *UsoIPv4
  • *UsoIPv6

Ces valeurs décrivent si l’USO est activé ou désactivé pour ce protocole IP particulier. Les paramètres de l’USO ne dépendent pas de la configuration NDIS_TCP_IP_CHECKSUM_OFFLOAD. Par exemple, désactiver *UDPChecksumOffloadIPv4 ne désactive pas implicitement *UsoIPv4.

Nom de sous-clé Description des paramètres Valeur Description de l’énumération
*UsoIPv4 Déchargement de segmentation UDP (IPv4) 0 Désactivé
1 Activé(e)
*UsoIPv6 Déchargement de segmentation UDP (IPV6) 0 Désactivé
1 Activé(e)