3. Méthode de compression
3. Méthode de compression
La majeure partie des informations d'en-tête reste inchangée pendant la durée de vie d'un flux de paquets. Pour les flux de paquets non-TCP, presque tous les champs d'en-tête sont constants. Pour TCP, de nombreux champs sont constants, tandis que d'autres changent avec des valeurs petites et prévisibles.
Pour commencer à compresser les en-têtes d'un flux de paquets, un en-tête complet portant l'identifiant de contexte CID est transmis sur la liaison. Le compresseur et le décompresseur stockent la plupart des champs de cet en-tête complet comme contexte. Le contexte est composé des champs de l'en-tête dont les valeurs sont constantes et n'ont donc pas besoin d'être envoyées sur la liaison du tout, ou qui changent si peu entre les en-têtes consécutifs qu'il est moins coûteux en bits d'envoyer la différence par rapport à la valeur précédente que d'envoyer la valeur absolue.
Tout changement dans les champs supposés constants dans un flux de paquets amènera le compresseur à envoyer à nouveau un en-tête complet pour mettre à jour le contexte au niveau du décompresseur. Tant que les contextes du compresseur et du décompresseur sont identiques, les en-têtes peuvent être décompressés exactement comme avant la compression. Cependant, si un en-tête complet ou compressé est perdu lors de la transmission, le contexte du décompresseur peut être obsolète car il n'a pas été correctement mis à jour. Les en-têtes compressés seront alors décompressés incorrectement.
IPv6 n'est pas destiné à être utilisé sur des liaisons pouvant délivrer un grand nombre de paquets corrompus au module IPv6. Cela signifie que la liaison doit avoir un taux d'erreur binaire très faible, ou que les trames de couche liaison doivent être protégées par une somme de contrôle forte, une correction d'erreur en aval ou une protection similaire. La compression d'en-têtes NE DEVRAIT PAS être utilisée pour IPv4 sans somme de contrôle de couche liaison forte. Les trames corrompues seront donc rejetées par la couche liaison. L'implémentation de la couche liaison peut indiquer au module de compression d'en-têtes qu'une trame est corrompue, mais elle ne peut pas indiquer à quel flux de paquets elle appartient, car c'est peut-être le CID qui est corrompu. De plus, des trames peuvent disparaître à l'insu de l'implémentation de la couche liaison, par exemple si la liaison est une liaison multi-sauts où des trames peuvent être rejetées en raison de la congestion à chaque saut. Par conséquent, le type d'erreur de liaison que le module de compression d'en-têtes doit gérer et prévenir sera la perte de paquets.
Le schéma de compression d'en-têtes nécessite donc des mécanismes pour mettre à jour le contexte au niveau du décompresseur et pour détecter ou éviter une décompression incorrecte. Ces mécanismes sont très différents pour les flux TCP et non-TCP, et sont décrits dans les sections 3.2 et 3.3.
Les mécanismes de compression dans ce document supposent que les paquets ne sont pas réordonnés entre le compresseur et le décompresseur. Si la liaison peut réordonner les paquets, la section 11 décrit des mécanismes pour ordonner les paquets avant la décompression. Il est également supposé que l'implémentation de la couche liaison peut fournir la longueur des paquets, et qu'il n'y a pas de rembourrage dans les paquets UDP ou les paquets encapsulés.
3.1 Types de paquets (Packet types)
En plus des types de paquets IPv4 et IPv6, cette méthode de compression utilise quatre types de paquets. La combinaison du type de paquet de couche liaison et de la valeur des quatre premiers bits du paquet détermine de manière unique le type de paquet. Les détails sur la façon de représenter ces types de paquets se trouvent dans la section 13.
FULL_HEADER — Représente un paquet avec un en-tête non compressé, incluant le CID, et si ce n'est pas un paquet TCP, la génération. Il établit ou rafraîchit le contexte pour le flux de paquets identifié par le CID.
COMPRESSED_NON_TCP — Représente un paquet non-TCP avec un en-tête compressé. L'en-tête compressé est composé du CID identifiant le contexte à utiliser pour la décompression, de la génération pour détecter les contextes incohérents, et des champs d'en-tête changeant de manière aléatoire.
COMPRESSED_TCP — Représente un paquet avec un en-tête TCP compressé, contenant le CID, un octet de drapeaux identifiant les champs modifiés, et les champs modifiés encodés comme différences par rapport aux valeurs précédentes.
COMPRESSED_TCP_NODELTA — Représente un paquet avec un en-tête TCP compressé dans lequel tous les champs normalement envoyés comme différences par rapport aux valeurs précédentes sont envoyés tels quels. Ce type de paquet est envoyé uniquement en réponse à une demande d'en-tête du décompresseur. Il NE PEUT PAS être envoyé à la suite d'une retransmission.
En plus des types de paquets utilisés pour la compression, les paquets IPv4 et IPv6 réguliers sont utilisés chaque fois que le compresseur décide de ne pas compresser un paquet. Des types de paquets supplémentaires peuvent être utilisés pour accélérer la réparation des flux TCP sur la liaison, où le décompresseur peut envoyer des paquets au compresseur.
CONTEXT_STATE — Représente un paquet spécial envoyé du décompresseur au compresseur pour communiquer la liste des CID (TCP) qui ont perdu la synchronisation. Ce paquet est envoyé uniquement sur une seule liaison et ne nécessite donc pas d'en-tête IP. Le format est présenté dans la section 10.2.
3.2 Paquets perdus dans les flux de paquets TCP (Lost packets in TCP packet streams)
Comme les en-têtes TCP sont compressés en utilisant des différences par rapport aux en-têtes TCP précédents, la perte d'un paquet avec un en-tête compressé ou complet entraînera une décompression incorrecte des en-têtes compressés suivants, car le contexte utilisé pour la décompression n'a pas été correctement incrémenté.
La perte d'un en-tête TCP compressé entraînera un décalage de k dans les numéros de séquence TCP des en-têtes TCP décompressés suivants, où k est la taille du segment perdu. Cet en-tête TCP décompressé incorrectement sera rejeté par le récepteur TCP, car la somme de contrôle TCP détecte de manière fiable les erreurs de « décalage de k » dans les numéros de séquence pour des valeurs raisonnables de k.
Le mécanisme de réparation de TCP finira par retransmettre les segments rejetés, et le compresseur surveille les en-têtes TCP pour détecter quand TCP retransmet. Lorsque cela se produit, le compresseur envoie un en-tête complet, en supposant que la retransmission est due à un état de compression non concordant au niveau du décompresseur. [RFC-1144] fournit une bonne explication de ce mécanisme.
Les mécanismes de la section 10 DEVRAIENT être utilisés pour accélérer la réparation du contexte. Cela est important pour les liaisons à moyen débit avec un taux de perte de paquets élevé, comme les liaisons sans fil. Perdre des paquets pendant une valeur de délai d'attente après chaque perte de paquet sur la liaison en raison d'un contexte incohérent est inacceptable, surtout lorsque la connexion TCP passe par un réseau étendu.
3.3 Paquets perdus dans les flux UDP et autres flux non-TCP (Lost packets in UDP and other non-TCP packet streams)
Les en-têtes de paquets UDP décompressés incorrectement et les autres en-têtes de paquets non-TCP ne sont pas aussi bien protégés par les sommes de contrôle que les paquets TCP. Il n'y a pas de numéro de séquence qui deviendrait « décalé de k » et provoquerait presque certainement un échec de la somme de contrôle, comme c'est le cas pour TCP. La somme de contrôle UDP ne couvre que la charge utile, l'en-tête UDP et le pseudo-en-tête. Le pseudo-en-tête comprend les adresses source et de destination, le type de protocole de transport et la longueur du paquet de transport. En dehors de ces champs, la majeure partie de l'en-tête IPv6 n'est pas couverte par la somme de contrôle UDP. De plus, d'autres en-têtes non-TCP manquent totalement de somme de contrôle, comme les en-têtes de fragmentation.
Pour éviter en toute sécurité une décompression incorrecte des en-têtes non-TCP, chaque version du contexte d'un flux de paquets non-TCP est identifiée par une génération, un petit nombre transporté par les en-têtes complets qui établissent et rafraîchissent le contexte. Les en-têtes compressés transportent la valeur de génération du contexte utilisé pour les compresser. Lorsque le décompresseur voit que la valeur de génération transportée par un en-tête compressé n'est pas la génération de son contexte pour ce flux de paquets, le contexte n'est pas à jour et le paquet doit être rejeté ou stocké jusqu'à ce qu'un en-tête complet établisse le contexte correct.
Le codage différentiel n'est pas utilisé pour les flux non-TCP, donc les en-têtes non-TCP compressés ne modifient pas le contexte. Par conséquent, la perte d'en-têtes compressés n'invalide pas les paquets suivants avec des en-têtes compressés. De plus, la génération ne change que lorsque le contexte d'un en-tête complet diffère du contexte de l'en-tête complet précédent. Cela signifie que la perte d'un en-tête complet ne rend le contexte du décompresseur obsolète que si l'en-tête complet aurait effectivement modifié le contexte.
Le champ de génération a une longueur de 6 bits, donc la valeur de génération se répète après 64 changements de contexte. Pour éviter une décompression incorrecte après une rafale d'erreurs ou une autre interruption temporaire, le compresseur NE DOIT PAS réutiliser la même valeur de génération avant MIN_WRAP secondes. Un décompresseur qui a été déconnecté pendant MIN_WRAP secondes ou plus DOIT attendre le prochain en-tête complet avant de décompresser. Le compresseur DOIT attendre au moins MIN_WRAP secondes après le démarrage avant de compresser les en-têtes non-TCP. Le compresseur PEUT passer à un autre CID ou envoyer des en-têtes réguliers jusqu'à ce que MIN_WRAP secondes se soient écoulées, plutôt que de réutiliser prématurément une valeur de génération. La valeur de MIN_WRAP se trouve dans la section 14.
3.3.1 Démarrage lent de compression (Compression Slow-Start)
Pour permettre au décompresseur de récupérer rapidement après la perte d'un en-tête complet qui modifie le contexte, des en-têtes complets sont envoyés périodiquement à des intervalles croissant de manière exponentielle après un changement de contexte. Cette technique évite l'échange de messages entre le compresseur et le décompresseur utilisé par d'autres schémas de compression, comme dans [RFC-1553]. Cet échange peut être coûteux pour les appareils mobiles sans fil, car l'émetteur consomme plus d'énergie et la commutation entre l'envoi et la réception peut introduire des délais. De plus, les techniques nécessitant un échange de messages ne peuvent pas être utilisées sur les liaisons simplex, comme les canaux de diffusion directe par satellite ou les systèmes de câblodistribution, et sont difficiles à adapter à la multidiffusion sur les liaisons multi-accès.
|.|..|....|........|................|..............................
^
Changement Paquets envoyés : | avec en-tête complet, . avec en-tête compressé
La figure montre comment les paquets sont envoyés après un changement. Le compresseur maintient une variable F_PERIOD pour chaque flux de paquets non-TCP, qui suit le nombre d'en-têtes compressés pouvant être envoyés entre les en-têtes complets. Lorsque l'en-tête d'un flux de paquets non-TCP change de telle sorte que son contexte change, un en-tête complet est envoyé et F_PERIOD est mis à 1. Après l'envoi de F_PERIOD en-têtes compressés, un en-tête complet est envoyé. F_PERIOD est doublé à chaque envoi d'un en-tête complet pendant le démarrage lent de compression.
3.3.2 Rafraîchissements périodiques d'en-têtes (Periodic Header Refreshes)
Pour éviter de perdre trop de paquets lorsque le récepteur perd son contexte, il existe une limite supérieure F_MAX_PERIOD au nombre de paquets non-TCP avec des en-têtes compressés pouvant être envoyés entre les rafraîchissements d'en-têtes. Si un paquet doit être envoyé et que F_MAX_PERIOD en-têtes compressés ont été envoyés depuis le dernier en-tête complet pour ce flux de paquets, un en-tête complet DOIT être envoyé.
Pour éviter de longues périodes de déconnexion pour les flux de paquets à faible débit, il existe également une limite supérieure F_MAX_TIME au temps entre les en-têtes complets dans un flux de paquets non-TCP. Si un paquet doit être envoyé et que plus de F_MAX_TIME secondes se sont écoulées depuis le dernier en-tête complet pour ce flux de paquets, un en-tête complet DOIT être envoyé. Les valeurs de F_MAX_PERIOD et F_MAX_TIME se trouvent dans la section 14.
3.3.3 Règles d'envoi des en-têtes complets (Rules for sending Full Headers)
Le compresseur PEUT utiliser le pseudo-code suivant pour déterminer quand envoyer un en-tête complet pour un flux de paquets non-TCP. Le code maintient deux variables :
C_NUM -- Compteur des en-têtes compressés envoyés depuis le dernier en-tête complet.
F_LAST -- Heure d'envoi du dernier en-tête complet.
et utilise les fonctions
current_time() retourne l'heure actuelle
min(a,b) retourne la plus petite valeur entre a et b
Les procédures send_full_header(), increment_generation_value() et send_compressed_header() effectuent les opérations évidentes.
if ( <cet en-tête modifie le contexte> )
C_NUM := 0;
F_LAST := current_time();
F_PERIOD := 1;
increment_generation_value();
send_full_header();
elseif ( C_NUM >= F_PERIOD )
C_NUM := 0;
F_LAST := current_time();
F_PERIOD := min(2 * F_PERIOD, F_MAX_PERIOD);
send_full_header();
elseif ( current_time() > F_LAST + F_MAX_TIME )
C_NUM := 0;
F_LAST := current_time();
send_full_header();
else
C_NUM := C_NUM + 1
send_compressed_header();
endif
3.3.4 Coût des rafraîchissements d'en-têtes (Cost of sending Header Refreshes)
Si chaque f-ième paquet porte un en-tête complet, H est la taille de l'en-tête complet et C est la taille de l'en-tête compressé, alors la taille moyenne de l'en-tête est :
(H-C)/f + C
Pour f > 1, la taille moyenne de l'en-tête est supérieure à l'en-tête compressé de (H-C)/f.
Dans un graphique de la taille moyenne de l'en-tête pour diverses valeurs de f, il y a un point d'inflexion évident dans la courbe, c'est-à-dire qu'il existe une limite au-delà de laquelle augmenter davantage f produit des rendements décroissants. F_MAX_PERIOD DEVRAIT être choisi comme une fréquence à droite du point d'inflexion de la courbe. Pour des tailles H et C typiques, par exemple 48 octets pour un en-tête complet (IPv6/UDP) et 4 octets pour un en-tête compressé, définir F_MAX_PERIOD > 44 signifie que les en-têtes complets contribueront à moins d'un octet à la taille moyenne de l'en-tête. Avec un en-tête de routage à quatre adresses, F_MAX_PERIOD > 115 aurait le même effet.
La valeur par défaut de F_MAX_PERIOD de 256 (section 14) place la fréquence des en-têtes complets à droite du point d'inflexion et signifie que les en-têtes complets contribueront généralement à bien moins d'un octet à la taille moyenne de l'en-tête. Pour H = 48 et C = 4, après avoir atteint la fréquence de rafraîchissement d'en-tête en régime permanent déterminée par le F_MAX_PERIOD par défaut, les en-têtes complets contribuent environ 1,4 bit à la taille moyenne de l'en-tête. 1,4 bit est une surcharge très faible.
Après un changement de contexte, le schéma de retrait exponentiel envoie initialement des en-têtes complets fréquemment. Le F_MAX_PERIOD par défaut sera atteint après l'envoi de 9 en-têtes complets et 255 en-têtes compressés. Pour un flux vocal typique avec 20 ms d'échantillons vocaux par paquet, cela équivaut à un peu plus de 5 secondes.
Pendant toute la période de retrait, avec H = 48 et C = 4, les en-têtes complets contribuent 1,5 octet à la taille moyenne de l'en-tête. Pour des échantillons vocaux de 20 ms, il faut moins de 1,3 seconde pour que les en-têtes complets contribuent à moins d'un octet à la taille moyenne de l'en-tête, et pendant ces 1,3 premières secondes, les en-têtes complets ajoutent moins de 4 octets à la taille moyenne de l'en-tête. Le coût du retrait exponentiel n'est pas élevé, et comme les en-têtes des flux de paquets non-TCP sont censés changer rarement, il sera amorti sur une longue période.
Le coût en bande passante des rafraîchissements d'en-têtes est plus élevé que le coût d'un schéma à état dur similaire (comme [RFC-1553]), dans lequel les en-têtes complets doivent être acquittés par le décompresseur avant que des en-têtes compressés puissent être envoyés. De tels schémas envoient généralement un en-tête complet plus quelques messages de contrôle lorsque le contexte change. Les schémas à état dur nécessitent plus de types de messages de protocole et nécessitent un échange de messages. Les schémas à état dur nécessitent également une gestion explicite de diverses conditions d'erreur que l'état logiciel gère automatiquement, comme le cas où une partie disparaît de manière inattendue, ce qui est courant sur les liaisons sans fil où un appareil mobile peut sortir de la portée d'une station de base.
Le principal avantage du schéma à état logiciel est qu'il ne nécessite pas de poignée de main entre le compresseur et le décompresseur, de sorte que le schéma peut être utilisé sur des liaisons simplex. Le coût en bande passante est plus élevé que les schémas à état dur, mais la simplicité du décompresseur, la simplicité du protocole et l'absence de poignée de main entre le compresseur et le décompresseur justifient ce petit coût supplémentaire. De plus, le schéma à état logiciel est plus facile à étendre à la multidiffusion sur les liaisons multi-accès, comme les liaisons sans fil.