mardi 29 mars 2016

Acquittements sélectifs (SACK)

Contexte


Dans la présentation du protocole TCP, nous avons vu que les acquittements sont cumulatifs.
Par conséquent, la pile TCP ne peut acquitter qu'une suite continue d'octets. Le problème se pose si un segment est perdu et que les suivants arrivent à destination.

De plus, la pile TCP ne peut pas transmettre à l'application les données reçues avec des « trous », de par le modèle de flux d'octet.

Perte du premier segment dans un burst TCP


Que faire des segments 20 à 23 pour le récepteur ? De même, quelle stratégie de retransmission à appliquer pour l'émetteur des données ?
Car d'après la RFC 793, aucun des segments n'aura été reçu du point de vue de l'émetteur. En effet, le récepteur des données devra acquitter en premier le segment 19 (ci­-dessus) qui a été perdu.
Le risque est que l'émetteur retransmette les segments 19 à 23.

Le mécanisme d'acquittement sélectif (« Selective Acknowledgement » ou SACK) permet de répondre à cette problématique.
Le destinataire des données peut indiquer à l'émetteur quels sont les segments reçus, et ainsi permettre à ce dernier de ne retransmettre que les segments manquants.

Fonctionnement


La RFC 2018 définit 2 options.

La première permet d'indiquer au destinataire que l'émetteur implémente cette fonctionnalité. Le type est 0x04 et de longueur 2 (octets).

Elle ne peut être envoyée que lors de l'établissement de la connexion (Lorsque le drapeau SYN est activé).



La deuxième option informe l'émetteur de l'existence de blocs de données non contigus dans les segments reçus.

L'option liste tous les blocs reçus valides (contenus dans la fenêtre de réception) et isolés dans le flux d'octets. Pour N éléments dans la liste, la longueur de cette option est N*8+2.



Chaque bloc est constitué de 2 entiers non signés de 32 bits :

• celui de gauche indique le premier numéro de séquence de ce bloc.

• celui de droite indique le prochain numéro de séquence après ce bloc.

Chaque bloc constitue un ensemble d'octets reçus, contigus et isolés dans la fenêtre de réception. Les octets juste autour de ce bloc n'ont pas été reçus.

Dans la mesure où l'en­-tête TCP ne peut pas avoir une longueur supérieure à 60 octets, il ne peut y avoir que 4 éléments dans la liste, au maximum. Dans la pratique, avec l'utilisation des timestamps, ce nombre est plutôt de 3 au maximum.

Il est à noter que le champ d'acquittement dans l'en­tête ne change pas de signification, il pointe toujours vers le premier octet attendu dans la fenêtre de réception. Dans l'exemple ci-­dessus, le champ ACK pointe toujours vers le segment 19.

N.B. : cette option est uniquement informative, elle n'engage pas le récepteur à garder ces blocs de données.
Ce dernier peut notifier l'émetteur au moyen de l'option SACK et quand même supprimer ces blocs de ses files d'attente (par manque de mémoire), même si cela n'est pas recommandé.
Toutefois, à part le dernier segment reçu isolé, le récepteur des données ne doit pas signaler de blocs de données supprimés.

Règles d'envoi de l'option SACK


• Le destinataire de cette option doit avoir indiqué son acceptation lors de l'établissement de la connexion.

• Chaque segment d'acquittement (avec le drapeau ACK activé) peut contenir l'option SACK. Par contre, le premier bloc de la liste doit contenir les numéros de séquence du dernier segment reçu.

• Le destinataire des données devrait lister autant de blocs de données qu'il est nécessaire. Néanmoins, cette liste peut être tronquée par les limites de la taille maximale de l'en­tête.

• La liste des blocs devrait être remplie dans l'ordre inverse d'ancienneté (le plus récent d'abord). Ce qui assure à chaque bloc d'être transmis au moins 3 fois (4 sans timestamps) si nécessaire.


L'idée principale est d'indiquer à l'émetteur des données l'état le plus récent de la fenêtre de réception du destinataire.
De plus, ces segments d'acquittement SACK peuvent être perdus eux aussi. Le fait de transmettre chaque bloc au moins 3 fois diminue le risque qu'un bloc ne soit pas signalé à l'émetteur des données.


Exemple d'envoi de plusieurs blocs SACK
Exemple d'envoi de plusieurs blocs SACK
Dans l'exemple ci-dessus, le récepteur des données (10.8.0.22) indique à l'émetteur qu'il se retrouve avec un bloc isolé de données (paquet n° 131) puis avec un deuxième (paquet n° 132).
A noter que le premier bloc (n° 132) fait référence au dernier segment reçu (paquet n° 130).


Stratégie de retransmission


L'émetteur des données est supposé tenir à jour une liste des segments à retransmettre (les segments qui n'ont toujours pas été acquittés).

En cas de réception de l'option SACK, les segments concernés sont mis à part. Par exemple, avec l'utilisation d'un drapeau SACK qui indique la bonne réception par le destinataire.

Ce mécanisme permet de déterminer les segments à retransmettre, sans attendre l'expiration du temps d'attente (« retransmit timeout »).

Toutefois, en cas d'expiration de ce temps d'attente, tous les segments de cette liste, marqués ou non, sont considérés comme perdus et doivent être retransmis.

N'oublions pas que cette option SACK est informative. Le récepteur des données peut, pour des raisons diverses, ne pas avoir gardé en mémoire les segments déclarés dans l'option SACK.

Avec ou sans cette fonctionnalité SACK, LA seule façon d'enlever un segment de cette liste de retransmission, est que le récepteur des données ait acquitté ce segment grâce au champ d'acquittement dans l'en­tête TCP.


Toutes les copies écrans sont issues du logiciel d'analyse réseau de Comoe Networks.

mardi 15 mars 2016

Les options TCP


Les options ont plusieurs objectifs :

• Lors de l'établissement de la connexion, elles permettent de définir les capacités de la pile TCP implémentée (Selective Acknowledgement, Window Scale, ...) ainsi que les conditions de transmission (Maximum Segment Size, ...).

• Elles permettent aussi de fournir des moyens supplémentaires de correction d'erreurs (Selective Acknowledgement par exemple).

• Enfin, elles peuvent fournir des moyens supplémentaires pour améliorer la sécurité ou estimer la latence (Timestamps par exemple).

Les options sont de longueur variable et sont intégrées dans le checksum TCP. Elles se trouvent entre l'en-tête fixe et les éventuelles données.

La RFC 793 définit 3 options qui doivent être obligatoirement implémentées par toute pile TCP. Toutes les options sont répertoriées par l'IANA.

L'URL actuelle est ici. Elle peut changer, donc le mieux est d'utiliser l'outil de recherche de l'IANA avec les mots clés 'tcp parameter' (ou dans votre moteur de recherche favori).

Format des options


Il existe 2 formats pour les options :

• 1 seul octet pour l'option, qui correspond au code associé.

• un format TLV (Type/Longueur/Valeur) de longueur variable :

Type (1 octet) -Longueur (1 octet) -Données (variable)

La longueur inclut également les 2 octets pour le champ Type et le champ Longueur.

Les options standards à un seul octet


L'option « Fin d'option (End of Option List) » dont le code est 0x00. Elle n'est nécessaire que si la fin des options ne coïncide pas avec la longueur de l'en-tête. Elle se trouve uniquement à la fin de toutes les options.

L'option « Pas d'opération (No­ Operation) »  dont le code 0x01. Cette option est principalement utilisée pour aligner la longueur de l'en­tête sur des mots de 32 bits.
En effet, la longueur de l'en-­tête est donnée en mots de 32 bits.

L'option Maximum Segment Size (MSS)


Pour rappel, la taille maximale d'un datagramme (MTU) IPv4 DEVANT être accepté est de 576 octets (RFC 791).

Par conséquent, un hôte ne doit pas envoyer un segment avec une taille supérieure à 576 octets, à moins d'avoir la certitude que le destinataire acceptera de tels segments.

Dans le cas d'une fragmentation, la taille totale du datagramme réassemblé peut dépasser cette limite, mais chaque fragment doit respecter cette limite.

D'où l'intérêt de l'option MSS :

L'option « Taille maximale du segment » (Maximum Segment Size ou MSS) définit la longueur maximale des données dans un segment TCP acceptée par l'émetteur de cette option (RFC 793, 879 et 6691).

Cette option ne peut être envoyée qu'avec le drapeau SYN activé, par conséquent, uniquement lors de l'établissement de la connexion.

Son code est 0x02 et sa longueur fixe est de 4 octets (la valeur est codée sur 16 bits).

Il y a eu beaucoup de débat sur cette valeur (RFC 879, 6691, 1122) et, en particulier, sur comment la définir. Faut il prendre en compte les options qui peuvent ne pas être présentes ou non ?

Au départ, rien n'est spécifié (RFC 793). Puis, devant les incertitudes soulevées, la RFC 879 nous dit ceci :

THE TCP MAXIMUM SEGMENT SIZE IS THE IP MAXIMUM DATAGRAM SIZE MINUS FORTY

Donc, on enlève 40 octets à la MTU, sans être réellement sûr de savoir à quoi correspond ce chiffre.
Dans un souci de clarifier une bonne fois pour toute, la RFC 6691 nous donne la formule pour le calcul de cette valeur :

MSS = MTU – taille en­tête IP (sans options) – taille en­tête TCP (sans option).

Par contre, l'émetteur doit prendre en compte la taille des options pour calculer la taille du segment à envoyer.


Options TCP présentes lors de l'ouverture d'une connexion
Exemple d'options présentes lors de l'ouverture d'une connexion


Voilà pour les options définies par la RFC 793, nous verrons les autres options dans des articles dédiés.