Partager via


Déléguer la segmentation des paquets TCP volumineux

Les pilotes de miniport NDIS (Network Driver Interface Specification) peuvent décharger la segmentation des gros paquets TCP dont la taille est supérieure à l'unité de transmission maximale (MTU) du support réseau. Une carte réseau qui prend en charge la segmentation de paquets TCP volumineux doit également être en mesure 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 mini-port qui prend en charge LSOv2 et LSOv1 doit déterminer le type de déchargement à partir des informations hors bande (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 qui contient les données OOB LSOv1 ou LSOv2 contient également une structure NET_BUFFER unique. 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.

Toutefois, dans un cas où le miniport a reçu OID_TCP_OFFLOAD_PARAMETERS pour désactiver la fonctionnalité LSO sur le miniport et une fois que le miniport a correctement terminé l’OID, le miniport doit supprimer toutes les NET_BUFFER_LIST qui contiennent des données OOB non nulles LSOv1 ou LSOv2 (NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO).

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

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

  • Pour LSOv1, écrit la longueur totale du paquet TCP volumineux dans le champ Total Length 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 Total Length de l’en-tête IP du paquet sur 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 du complément à un sur les champs suivants du pseudo-en-tête : Source IP Address, Destination IP Address, et Protocol. 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 du pseudo-en-tête est calculée sur les Source IP Address, Destination IP Address, Protocol et TCP Length. (La longueur TCP est la longueur de l’en-tête TCP ainsi que la longueur de la charge utile TCP. La longueur TCP n’inclut pas la longueur du pseudo-en-tête.) Toutefois, étant donné que le pilote miniport sous-jacent et la carte réseau génèrent des segments TCP à partir du paquet volumineux 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 le pseudo-en-tête. 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 Sequence Number 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 miniport obtient la longueur totale du paquet volumineux à partir de l’en-tête IP du paquet et utilise la valeur MSS pour diviser le paquet TCP volumineux en paquets plus petits. Chacun des paquets plus petits contient des octets de données utilisateur, de la taille MSS ou moins. Seul le dernier paquet créé à partir du paquet volumineux 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 peuvent dégrader les performances.

Le pilote miniport fixe les en-têtes MAC, IP et TCP sur chaque segment dérivé du paquet volumineux. Le pilote miniport doit calculer les checksums 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, consultez RFC 793 et RFC 1122.

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

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

La longueur des données utilisateur TCP dans le paquet TCP volumineux doit être égale ou inférieure à la valeur affectée par le pilote miniport à 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.

Une fois qu’un pilote émet une indication d’état pour signaler un changement de la valeur MaxOffLoadSize, il ne doit pas se bloquer 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 des indications d’état de manière autonome, signalant une modification de la valeur MaxOffLoadSize, doit s'assurer que l'adaptateur miniport sous-jacent, qui n'a pas émis d'indication d'état, ne reçoive pas de paquets dont la taille dépasse la valeur MaxOffLoadSize rapportée par l’adaptateur 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 de segments doit être inférieure ou égale au 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. Seul le dernier paquet créé à partir du paquet volumineux 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 peuvent dégrader les performances.

Le nombre de paquets de segments dérivés du paquet TCP volumineux doit être égal ou supérieur à la valeur MinSegmentCount spécifiée par le pilote miniport. Pour plus d’informations sur la valeur MinSegmentCount, 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.

Les hypothèses et restrictions suivantes s’appliquent au traitement des en-têtes IP et TCP pour n’importe quel pilote 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 indicateursURG , RSTet SYN dans l’en-tête TCP du paquet TCP volumineux ne seront pas définis, et le décalage urgent (pointeur) dans l’en-tête TCP sera égal à zéro.

  • Si le FIN bit dans l’en-tête TCP du paquet volumineux est défini, le pilote miniport doit définir ce bit dans l’en-tête TCP du dernier paquet qu’il crée à partir du paquet TCP volumineux.

  • Si le PSH bit dans l’en-tête TCP du paquet TCP volumineux est défini, le pilote miniport doit définir ce bit dans l’en-tête TCP du dernier paquet qu’il crée à partir du paquet TCP volumineux.

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

  • Si le paquet TCP volumineux contient des options IP ou des options TCP (ou les deux), le pilote miniport copie ces options, non altérées, à chaque paquet qu’il a dérivé du paquet TCP volumineux. En particulier, la NIC n’incrémentera pas l’option Time Stamp.

  • Tous les en-têtes de paquets (ethernet, IP, TCP) se trouveront 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 l’authentification unique est activée. 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 miniport doit envoyer les paquets dans des 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 paquet TCP volumineux, l’adaptateur miniport est chargé uniquement de segmenter le paquet et d’attacher les en-têtes MAC, IP et TCP aux paquets dérivés du paquet TCP volumineux. 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 d’effectuer l’opération d’envoi pour le paquet volumineux (par exemple, avec NdisMSendNetBufferListsComplete ou NdisMCoSendNetBufferListsComplete), le pilote miniport écrit la valeur NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO (NET_BUFFER_LIST informations pour les déchargements d’envoi volumineux) avec le nombre total d’octets de données utilisateur TCP envoyés avec succès dans tous les paquets créés à partir du paquet TCP volumineux.

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

  • Prendre en charge IPv4, IPv6, ou les deux.

  • Permet la réplication des options IPv4, à partir du paquet large, dans chaque paquet segment que génère la carte d’interface réseau (NIC).

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

  • Prise en charge de la réplication des options TCP dans chaque paquet de segment TCP généré par le pilote miniport.

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

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

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

    Remarque

    Il s’agit d’une nouvelle exigence pour les pilotes 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éterminez la longueur totale du paquet à partir de la longueur de la première structure de 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 miniport doit définir le membre LsoV2TransmitComplete.Reserved de la structure NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO sur zéro et le membre LsoV2TransmitComplete.Type sur NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE.