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 (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 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 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 ait complété l'OID avec succès, le miniport doit abandonner toutes 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 gros paquet TCP dans le champ Total Length de l'en-tête IP du paquet. La longueur totale comprend 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, met le champ Total Length 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 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 plus 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 de miniport et la carte d'interface réseau sous-jacents génèrent des segments TCP à partir du gros 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 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 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 des octets de données utilisateur, de la taille MSS ou moins. Seul le dernier paquet créé à partir du grand paquet segmenté doit contenir moins de MSS octets de données utilisateur. Tous les autres paquets créés à partir du paquet segmenté doivent contenir des octets de données utilisateur MSS. Si vous ne respectez pas cette règle, la création et la transmission de paquets supplémentaires inutiles peuvent 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 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, 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 égale ou inférieure à la valeur que le pilote du 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.

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 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. Seul le dernier paquet créé à partir du grand paquet segmenté doit contenir moins de MSS octets de données utilisateur. Tous les autres paquets créés à partir du paquet segmenté doivent contenir des octets de données utilisateur MSS. Si vous ne respectez 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 grand paquet TCP doit être égal ou supérieur à la valeur MinSegmentCount spécifiée par le pilote du 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 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 gros paquet TCP ne seront pas activés et le décalage urgent (pointeur) dans l'en-tête TCP sera égal à zéro.

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

  • Si le bit PSH de l'en-tête TCP du paquet TCP volumineux est défini, le pilote du 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 bit CWR de l'en-tête TCP du gros paquet TCP est défini, le pilote du miniport doit définir ce bit dans l'en-tête TCP du premier paquet qu'il crée à partir du gros paquet TCP. Le pilote du miniport peut choisir de mettre ce bit dans l'en-tête TCP du dernier paquet qu'il crée à partir du gros 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 la première 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 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 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 du gros paquet (par exemple avec NdisMSendNetBufferListsComplete ou NdisMCoSendNetBufferListsComplete), le pilote du miniport écrit la valeur NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO (informations NET_BUFFER_LIST pour les décharges de gros envois) avec le nombre total d'octets de données utilisateur TCP qui sont envoyés avec succès dans tous les paquets qui ont été créés à partir du gros paquet TCP.

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.

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

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

  • Utilisez des valeurs d'identification IP (ID IP) comprises entre 0x0000 et 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 à une le nombre de structures NET_BUFFER associées à chaque structure LSOv2 NET_BUFFER_LIST.

    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éterminez 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 du mini-port 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.