Partager via


Déchargement de la segmentation des grands paquets TCP

Les pilotes de miniport NDIS peuvent décharger la segmentation de grands paquets TCP qui sont plus grands que l’unité de transmission maximale (MTU) du support réseau. Une carte réseau (NIC) qui prend en charge la segmentation de grands paquets TCP doit également être capable de :

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

  • Calculer les sommes de contrôle TCP pour les paquets envoyés contenant des options TCP.

Les versions NDIS 6.0 et ultérieures prennent en charge la décharge d’envoi de grande taille version 1 (LSOv1), qui est similaire à la décharge d’envoi de grande taille (LSO) dans NDIS 5.x. Les versions NDIS 6.0 et ultérieures prennent également en charge la décharge d’envoi de grande taille version 2 (LSOv2), qui fournit des services améliorés de segmentation de grands paquets, y compris la prise en charge de l’IPv6.

Un pilote de miniport qui prend en charge LSOv2 et LSOv1 doit déterminer le type de décharge à partir des informations OOB de la structure NET_BUFFER_LIST. Le pilote peut utiliser le membre Type de la structure NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO pour déterminer si la pile de pilotes utilise LSOv2 ou LSOv1 et effectuer les services de décharge appropriés. Toute structure NET_BUFFER_LIST contenant les données OOB LSOv1 ou LSOv2 contient également une seule structure NET_BUFFER. Pour plus d’informations sur NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO, veuillez consulter la section Accéder aux informations NET_BUFFER_LIST de déchargement TCP/IP.

Cependant, dans le cas où le miniport a reçu OID_TCP_OFFLOAD_PARAMETERS pour désactiver la fonctionnalité LSO sur le miniport et après que le miniport a terminé avec succès l’OID, le miniport doit supprimer tous les NET_BUFFER_LIST qui contiennent des données OOB LSOv1 ou LSOv2 non nulles (NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO).

Le transport TCP/IP décharge uniquement les grands paquets TCP qui répondent aux critères suivants :

Avant de décharger un grand paquet TCP pour la segmentation, le transport TCP/IP :

  • Pour LSOv1, écrit la longueur totale du grand paquet TCP dans le champ Longueur totale de l’en-tête IP du paquet. La longueur totale inclut la longueur de l’en-tête IP, la longueur des options IP si elles sont présentes, la longueur de l’en-tête TCP, la longueur des options TCP si elles sont présentes, et la longueur de la charge utile TCP. Pour LSOv2, définit le champ Longueur totale de l’en-tête IP du paquet à 0. Les pilotes de miniport doivent déterminer la longueur du paquet à partir de la longueur de la première structure NET_BUFFER dans la structure NET_BUFFER_LIST.

  • Calcule la somme complémentaire de l’en-tête pseudo TCP et écrit cette somme dans le champ Checksum de l’en-tête TCP. Le transport TCP/IP calcule la somme complémentaire sur les champs suivants de l’en-tête pseudo : Adresse IP source, Adresse IP de destination et Protocole. La somme complémentaire de l’en-tête pseudo fournie par le transport TCP/IP donne à la NIC un avantage pour calculer la somme de contrôle TCP réelle pour chaque paquet que la NIC dérive du grand paquet TCP sans avoir à examiner l’en-tête IP. Notez que la RFC 793 stipule que la somme de contrôle de l’en-tête pseudo est calculée sur l’adresse IP source, l’adresse IP de destination, le protocole et la longueur TCP. (La longueur TCP est la longueur de l’en-tête TCP plus la longueur de la charge utile TCP. La longueur TCP n’inclut pas la longueur de l’en-tête pseudo.) Cependant, comme le pilote de miniport sous-jacent et la NIC génèrent des segments TCP à partir du grand paquet transmis par le transport TCP/IP, le transport ne connaît pas la taille de la charge utile TCP pour chaque segment TCP et ne peut donc pas inclure la longueur TCP dans l’en-tête pseudo. Au lieu de cela, comme décrit ci-dessous, la NIC étend la somme de contrôle de l’en-tête pseudo fournie par le transport TCP/IP pour couvrir la longueur TCP de chaque segment TCP généré.

  • Écrit le numéro de séquence correct dans le champ Numéro de séquence de l’en-tête TCP. Le numéro de séquence identifie le premier octet de la charge utile TCP.

Après que le pilote de miniport a obtenu la structure NET_BUFFER_LIST dans sa fonction MiniportSendNetBufferLists ou MiniportCoSendNetBufferLists, il peut appeler la macro NET_BUFFER_LIST_INFO avec un _Id de TcpLargeSendNetBufferListInfo pour obtenir la valeur MSS écrite par le transport TCP/IP.

Le pilote de miniport obtient la longueur totale du grand paquet à partir de l’en-tête IP du paquet et utilise la valeur MSS pour diviser le grand paquet TCP en paquets plus petits. Chacun des paquets plus petits 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 vous ne suivez pas cette règle, la création et la transmission de paquets supplémentaires inutiles pourraient dégrader les performances.

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

La figure suivante montre la segmentation d’un grand paquet.

Diagramme montrant la segmentation d’un grand paquet TCP en paquets plus petits avec des en-têtes MAC, IP et TCP.

La longueur des données utilisateur TCP dans le grand paquet TCP doit être inférieure ou égale à la valeur que le pilote de miniport attribue à la valeur MaxOffLoadSize. Pour plus d’informations sur la valeur MaxOffLoadSize, consultez Rapport des capacités de segmentation des paquets TCP LSOv1 d’une NIC et Rapport des capacités de segmentation des paquets TCP LSOv2 d’une NIC.

Après qu’un pilote a émis une indication de statut pour indiquer un changement de la valeur MaxOffLoadSize, le pilote ne doit pas planter s’il reçoit une demande d’envoi LSO utilisant la valeur MaxOffLoadSize précédente. Au lieu de cela, le pilote peut échouer à la demande d’envoi.

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 dont la taille est supérieure à 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 LSO doit être préparé pour une petite fenêtre de temps où les demandes d’envoi LSO pourraient encore atteindre le pilote de miniport.

La longueur des données utilisateur TCP dans un paquet segmenté doit être inférieure ou égale à MSS. MSS est la valeur ULONG que le transport TCP passe en utilisant les informations LSO NET_BUFFER_LIST associées à la structure NET_BUFFER_LIST. 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 vous ne suivez pas cette règle, la création et la transmission de paquets supplémentaires inutiles pourraient dégrader les performances.

Le nombre de paquets segmentés dérivés du grand paquet TCP doit être égal ou supérieur à la valeur MinSegmentCount spécifiée par le pilote de miniport. Pour plus d’informations sur la valeur MinSegmentCount, veuillez consulter la section Rapport des capacités de segmentation des paquets TCP LSOv1 d’une NIC et Rapport des capacités de segmentation des paquets TCP LSOv2 d’une NIC.

Les hypothèses et restrictions suivantes s’appliquent au traitement des en-têtes IP et TCP pour tout pilote de miniport compatible LSO, quelle que soit la version :

  • Le bit MF dans l’en-tête IP du grand paquet TCP que le transport TCP/IP a déchargé ne sera pas activé, et le décalage de fragmentation dans l’en-tête IP sera nul.

  • Les indicateurs URG, RST et SYN dans l’en-tête TCP du grand paquet TCP ne seront pas activés, et le décalage urgent (pointeur) dans l’en-tête TCP sera nul.

  • Si le bit FIN dans l’en-tête TCP du grand paquet est activé, le pilote de miniport doit activer ce bit dans l’en-tête TCP du dernier paquet qu’il crée à partir du grand paquet TCP.

  • Si le bit PSH dans l’en-tête TCP du grand paquet TCP est activé, le pilote de miniport doit activer ce bit dans l’en-tête TCP du dernier paquet qu’il crée à partir du grand paquet TCP.

  • Si le bit CWR dans l’en-tête TCP du grand paquet TCP est activé, le pilote de miniport doit activer ce bit dans l’en-tête TCP du premier paquet qu’il crée à partir du grand paquet TCP. Le pilote de miniport peut choisir d’activer ce bit dans l’en-tête TCP du dernier paquet qu’il crée à partir du grand paquet TCP, bien que cela soit moins souhaitable.

  • Si le grand paquet TCP contient des options IP ou des options TCP (ou les deux), le pilote de miniport copie ces options, inchangées, dans chaque paquet qu’il dérive du grand paquet TCP. En particulier, la NIC n’incrémentera pas l’option Time Stamp.

  • Tous les en-têtes de paquets (Ethernet, IP, TCP) seront dans le premier MDL du paquet. Les en-têtes ne seront pas divisés entre plusieurs MDL.

    Conseil

    Cette hypothèse est valide lorsque LSO est activé. Sinon, lorsque LSO n’est pas activé, les pilotes de miniport ne peuvent pas supposer que les en-têtes IP sont dans le même MDL que les en-têtes Ethernet.

Le pilote de miniport doit envoyer les paquets dans les structures NET_BUFFER_LIST dans l’ordre où il reçoit les structures NET_BUFFER_LIST du transport TCP/IP.

Lors du traitement d’un grand paquet TCP, l’adaptateur de miniport est responsable uniquement de la segmentation du paquet et de l’apposition des en-têtes MAC, IP et TCP aux paquets dérivés du grand paquet TCP. Le transport TCP/IP effectue toutes les autres tâches (telles que l’ajustement de la taille de la fenêtre d’envoi en fonction de la taille de la fenêtre de réception de l’hôte distant).

Avant de terminer l’opération d’envoi pour le grand paquet (comme avec NdisMSendNetBufferListsComplete ou NdisMCoSendNetBufferListsComplete), le pilote de miniport écrit la valeur NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO (informations NET_BUFFER_LIST pour les déchargements d’envoi de grands paquets) avec le nombre total d’octets de données utilisateur TCP envoyés avec succès dans tous les paquets créés à partir du grand paquet TCP.

En plus des exigences LSO précédentes, les pilotes de miniport compatibles LSOv2 doivent également :

  • Prendre en charge IPv4 ou IPv6 ou à la fois IPv4 et IPv6.

  • Prendre en charge la réplication des options IPv4, du grand paquet, dans chaque paquet segmenté que la carte réseau (NIC) génère.

  • Prendre en charge la réplication de l’en-tête d’extension IPv6, du grand paquet TCP, dans chaque paquet segmenté TCP.

  • Prendre en charge la réplication des options TCP dans chaque paquet segmenté TCP que le pilote de miniport génère.

  • Utiliser l’en-tête IP et TCP dans la structure NET_BUFFER_LIST comme modèle pour générer des en-têtes TCP/IP pour chaque paquet segmenté.

  • Utiliser des valeurs d’identification IP (ID IP) dans la plage de 0x0000 à 0x7FFF. (La plage de 0x8000 à 0xFFFF est réservée aux dispositifs compatibles avec le déchargement de cheminée TCP.) Par exemple, si l’en-tête IP modèle commence avec une valeur de champ Identification de 0x7FFE, le premier paquet segmenté TCP doit avoir une valeur d’ID IP de 0x7FFE, suivi de 0x7FFF, 0x0000, 0x0001, et ainsi de suite.

  • Utiliser le décalage d’octet dans le membre TcpHeaderOffset de NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO pour déterminer l’emplacement de l’en-tête TCP, en commençant à partir du premier octet du paquet.

  • Limiter le nombre de structures NET_BUFFER associées à chaque structure NET_BUFFER_LIST LSOv2 à une.

    Remarque

    C’est une nouvelle exigence pour les pilotes de miniport compatibles LSOv2. Cette règle n’est pas appliquée explicitement pour les pilotes de miniport LSOv1, bien qu’elle soit recommandée.

  • Déterminer la longueur totale du paquet à partir de la longueur de la première structure NET_BUFFER dans la structure NET_BUFFER_LIST. C’est différent de la méthode que les pilotes utilisent pour LSOv1.

  • Prendre en charge les options TCP, les options IP et les en-têtes d’extension IP.

  • Lorsqu’une opération d’envoi est terminée, le pilote de miniport doit définir le membre LsoV2TransmitComplete.Reserved de la structure NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO à zéro et le membre LsoV2TransmitComplete.Type à NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE.