4. PROTOCOLES DE TRANSPORT (TRANSPORT PROTOCOLS)
4.1 PROTOCOLE DE DATAGRAMME UTILISATEUR -- UDP (USER DATAGRAM PROTOCOL)
4.1.1 INTRODUCTION
Le protocole de datagramme utilisateur (User Datagram Protocol, UDP) [UDP:1] offre uniquement un service de transport minimal -- la livraison de datagrammes non garantie -- et donne aux applications un accès direct au service de datagramme de la couche IP. UDP est utilisé par les applications qui n'ont pas besoin du niveau de service de TCP ou qui souhaitent utiliser des services de communication (par exemple, la livraison multicast ou broadcast) non disponibles avec TCP.
UDP est presque un protocole nul; les seuls services qu'il fournit au-dessus d'IP sont la somme de contrôle des données et le multiplexage par numéro de port. Par conséquent, un programme d'application fonctionnant sur UDP doit traiter directement les problèmes de communication de bout en bout qu'un protocole orienté connexion aurait gérés -- par exemple, la retransmission pour une livraison fiable, la packetisation et le réassemblage, le contrôle de flux, l'évitement de congestion, etc., lorsque ceux-ci sont nécessaires. Le couplage assez complexe entre IP et TCP se reflétera dans le couplage entre UDP et de nombreuses applications utilisant UDP.
4.1.2 PARCOURS DU PROTOCOLE (PROTOCOL WALK-THROUGH)
Il n'y a pas d'erreurs connues dans la spécification d'UDP.
4.1.3 QUESTIONS SPÉCIFIQUES (SPECIFIC ISSUES)
4.1.3.1 Ports
Les ports bien connus UDP suivent les mêmes règles que les ports bien connus TCP; voir la section 4.2.2.1 ci-dessous.
Si un datagramme arrive adressé à un port UDP pour lequel il n'y a pas d'appel LISTEN en attente, UDP DEVRAIT envoyer un message ICMP Port Unreachable.
4.1.3.2 Options IP (IP Options)
UDP DOIT transmettre de manière transparente à la couche application toute option IP qu'il reçoit de la couche IP.
Une application DOIT pouvoir spécifier les options IP à envoyer dans ses datagrammes UDP, et UDP DOIT transmettre ces options à la couche IP.
DISCUSSION:
Actuellement, les seules options qui doivent passer par UDP sont Source Route, Record Route et Time Stamp. Cependant, de nouvelles options peuvent être définies à l'avenir, et UDP n'a pas besoin et ne devrait pas faire d'hypothèses sur le format ou le contenu des options qu'il transmet vers ou depuis l'application; une exception à cela pourrait être une option de sécurité de la couche IP.
Une application basée sur UDP devra obtenir un itinéraire source à partir d'un datagramme de requête et fournir un itinéraire inversé pour envoyer la réponse correspondante.
4.1.3.3 Messages ICMP (ICMP Messages)
UDP DOIT transmettre à la couche application tous les messages d'erreur ICMP qu'il reçoit de la couche IP. Conceptuellement au moins, cela peut être accompli avec un appel ascendant vers la routine ERROR_REPORT (voir la section 4.2.4.1).
DISCUSSION:
Notez que les messages d'erreur ICMP résultant de l'envoi d'un datagramme UDP sont reçus de manière asynchrone. Une application basée sur UDP qui souhaite recevoir des messages d'erreur ICMP est responsable du maintien de l'état nécessaire pour démultiplexer ces messages lorsqu'ils arrivent; par exemple, l'application peut conserver une opération de réception en attente à cette fin. L'application est également responsable d'éviter la confusion due à un message d'erreur ICMP retardé résultant d'une utilisation antérieure du ou des mêmes ports.
4.1.3.4 Sommes de contrôle UDP (UDP Checksums)
Un hôte DOIT implémenter la capacité de générer et de valider les sommes de contrôle UDP. Une application PEUT optionnellement pouvoir contrôler si une somme de contrôle UDP sera générée, mais elle DOIT être activée par défaut.
Si un datagramme UDP est reçu avec une somme de contrôle non nulle et invalide, UDP DOIT rejeter silencieusement le datagramme. Une application PEUT optionnellement pouvoir contrôler si les datagrammes UDP sans sommes de contrôle doivent être rejetés ou transmis à l'application.
DISCUSSION:
Certaines applications qui s'exécutent généralement uniquement sur des réseaux locaux choisissent de désactiver les sommes de contrôle UDP pour des raisons d'efficacité. En conséquence, de nombreux cas d'erreurs non détectées ont été signalés. Les recommandations sur la question de savoir si les sommes de contrôle UDP doivent être désactivées sont très controversées.
IMPLÉMENTATION:
Il existe une erreur d'implémentation courante dans la somme de contrôle UDP. Contrairement à la somme de contrôle TCP, la somme de contrôle UDP est optionnelle; un zéro transmis dans le champ de somme de contrôle de l'en-tête UDP indique l'absence de somme de contrôle. Si la somme de contrôle UDP réellement calculée par l'expéditeur est zéro, elle doit être transmise comme tous les uns (65535). Le récepteur n'a pas besoin de prendre de mesure spéciale, car en arithmétique en complément à un, zéro et 65535 sont équivalents.
4.1.3.5 Multihébergement UDP (UDP Multihoming)
Lorsqu'un datagramme UDP est reçu, son adresse de destination spécifique DOIT être transmise à la couche application.
Une application DOIT pouvoir spécifier l'adresse IP source à utiliser pour envoyer un datagramme UDP, ou la laisser vide (auquel cas le logiciel réseau choisira une adresse source appropriée). Il DEVRAIT y avoir un moyen d'informer la couche application de l'adresse source sélectionnée (par exemple, pour que l'application ne puisse recevoir ultérieurement que les datagrammes de réponse de l'interface correspondante).
DISCUSSION:
Les applications de requête/réponse utilisant UDP devraient utiliser la même adresse source pour la réponse que l'adresse de destination spécifique de la requête. Voir la section "Problèmes généraux" de [INTRO:1].
4.1.3.6 Adresses invalides (Invalid Addresses)
Les datagrammes UDP reçus avec une adresse IP source invalide (par exemple, une adresse de diffusion ou de multicast) DOIVENT être rejetés par UDP ou la couche IP (voir la section 3.2.1.3).
Lorsqu'un hôte envoie un datagramme UDP, l'adresse source DOIT être l'une (ou plusieurs) des adresses IP de l'hôte.
4.1.4 INTERFACE UDP/COUCHE APPLICATION (UDP/APPLICATION LAYER INTERFACE)
L'interface d'application d'UDP DOIT fournir l'ensemble complet des services de l'interface IP/transport décrite dans la section 3.4 de ce document. Par conséquent, les applications utilisant UDP ont besoin des fonctions GET_SRCADDR(), GET_MAXSIZES(), ADVISE_DELIVPROB() et RECV_ICMP() décrites dans la section 3.4. Par exemple, GET_MAXSIZES() peut être utilisé pour connaître la taille maximale effective du datagramme UDP pour un triplet {interface, hôte distant, TOS} particulier.
Les programmes de la couche application DOIVENT pouvoir définir les valeurs TTL et TOS pour l'envoi d'un datagramme UDP et les options IP, et ces valeurs doivent être transmises de manière transparente à la couche IP. UDP PEUT transmettre le TOS reçu à la couche application.
4.1.5 RÉSUMÉ DES EXIGENCES UDP (UDP REQUIREMENTS SUMMARY)
| Fonctionnalité | Section | DOIT | DEVRAIT | PEUT | NE DOIT PAS |
|---|---|---|---|---|---|
| UDP | |||||
| --- | --- | --- | --- | --- | --- |
| UDP envoie Port Unreachable | 4.1.3.1 | x | |||
| Options IP dans UDP | |||||
| - Transmettre les options IP reçues à l'application | 4.1.3.2 | x | |||
| - L'application peut spécifier les options IP lors de l'envoi | 4.1.3.2 | x | |||
| - UDP transmet les options IP à la couche IP | 4.1.3.2 | x | |||
| Transmettre les messages ICMP à l'application | 4.1.3.3 | x | |||
| Somme de contrôle UDP: | |||||
| - Capacité de générer/vérifier la somme de contrôle | 4.1.3.4 | x | |||
| - Rejeter silencieusement la somme de contrôle invalide | 4.1.3.4 | x | |||
| - Option d'envoi sans générer de somme de contrôle | 4.1.3.4 | x | |||
| - Somme de contrôle activée par défaut | 4.1.3.4 | x | |||
| - Option de réception nécessitant une somme de contrôle | 4.1.3.4 | x | |||
| Multihébergement UDP | |||||
| - Transmettre l'adresse de destination spécifique à l'application | 4.1.3.5 | x | |||
| - L'application peut spécifier l'adresse IP locale | 4.1.3.5 | x | |||
| - L'application peut spécifier l'adresse IP locale joker | 4.1.3.5 | x | |||
| - L'application est informée de l'adresse IP locale utilisée | 4.1.3.5 | x | |||
| Adresse IP source invalide rejetée par UDP/IP | 4.1.3.6 | x | |||
| Envoyer uniquement une adresse IP source valide | 4.1.3.6 | x | |||
| Services d'interface d'application UDP | |||||
| Fournir l'interface IP complète de 3.4 à l'application | 4.1.4 | x | |||
| - Spécifier TTL, TOS, options IP lors de l'envoi | 4.1.4 | x | |||
| - Transmettre le TOS reçu à l'application | 4.1.4 | x |
4.2 PROTOCOLE DE CONTRÔLE DE TRANSMISSION -- TCP (TRANSMISSION CONTROL PROTOCOL)
4.2.1 INTRODUCTION
Le protocole de contrôle de transmission (Transmission Control Protocol, TCP) [TCP:1] est le principal protocole de transport de circuit virtuel fiable orienté connexion de la suite Internet. TCP fournit une livraison fiable et ordonnée d'un flux d'octets bidirectionnel. TCP est utilisé par les applications nécessitant un service de transport fiable orienté connexion, telles que le courrier (SMTP), le transfert de fichiers (FTP) et le service de terminal virtuel (Telnet); les exigences de ces protocoles de couche application sont décrites dans [INTRO:1].
4.2.2 PARCOURS DU PROTOCOLE (PROTOCOL WALK-THROUGH)
4.2.2.1 Ports bien connus (Well-Known Ports): RFC-793 Section 2.7
DISCUSSION:
TCP réserve les numéros de port dans la plage 0-255 pour les ports "bien connus", pour accéder aux services standardisés sur Internet. Le reste de l'espace de port peut être librement alloué aux processus d'application. Les définitions actuelles des ports bien connus sont répertoriées dans le RFC intitulé "Assigned Numbers" [INTRO:6]. Le prérequis pour définir un nouveau port bien connu est un RFC qui documente le service proposé de manière suffisamment détaillée pour permettre de nouvelles implémentations.
Certains systèmes étendent ce concept en ajoutant une troisième subdivision de l'espace de port TCP: les ports réservés (reserved ports), qui sont généralement utilisés pour les services spécifiques au système d'exploitation. Par exemple, les ports réservés peuvent se situer entre 256 et une limite supérieure dépendante du système. Certains systèmes choisissent en outre de protéger les ports bien connus et les ports réservés en n'autorisant que les utilisateurs privilégiés à ouvrir des connexions TCP avec ces valeurs de port. Ceci est parfaitement raisonnable tant que l'hôte ne suppose pas que tous les hôtes protègent leurs ports de faible numéro de cette manière.
4.2.2.2 Utilisation de Push (Use of Push): RFC-793 Section 2.8
Lorsque l'application émet une série d'appels SEND sans définir le flag PUSH, TCP PEUT agréger les données en interne sans les envoyer. De même, lors de la réception d'une série de segments sans le bit PSH, TCP PEUT mettre les données en file d'attente en interne sans les livrer à l'application réceptrice.
Le bit PSH n'est pas un marqueur d'enregistrement et est indépendant des limites de segment. L'expéditeur DEVRAIT regrouper les bits PSH consécutifs lors de la packetisation des données pour envoyer le plus grand segment possible.
TCP PEUT implémenter le flag PUSH sur l'appel SEND. Si le flag PUSH n'est pas implémenté, alors le TCP d'envoi: (1) ne doit pas mettre les données en mémoire tampon indéfiniment, et (2) DOIT définir le bit PSH dans le dernier segment mis en mémoire tampon (c'est-à-dire lorsqu'il n'y a plus de données en file d'attente à envoyer).
La discussion dans RFC-793 aux pages 48, 50 et 74 suggère incorrectement que le flag PSH reçu doit être transmis à la couche application. La transmission du flag PSH reçu à la couche application est maintenant OPTIONNELLE.
L'application a logiquement besoin de définir le flag PUSH dans un appel SEND chaque fois qu'elle a besoin de forcer la livraison des données pour éviter un blocage de communication. Cependant, TCP DEVRAIT envoyer des segments de taille maximale dans la mesure du possible pour améliorer les performances (voir la section 4.2.3.4).
DISCUSSION:
Lorsque le flag PUSH n'est pas implémenté sur les appels SEND, c'est-à-dire lorsque l'interface application/TCP utilise un modèle de flux pur, la responsabilité d'agréger les petits fragments de données pour former des segments de taille raisonnable incombe en partie à la couche application.
Normalement, les protocoles d'application interactifs doivent définir le flag PUSH au moins sur le dernier appel SEND de chaque séquence de commande ou de réponse. Les protocoles de transfert en masse comme FTP devraient définir le flag PUSH sur le dernier segment d'un fichier, ou quand nécessaire pour empêcher un blocage de mémoire tampon.
Du côté du récepteur, le bit PSH force la livraison des données mises en mémoire tampon à l'application (même si moins qu'un tampon complet de données a été reçu). Inversement, l'absence de bit PSH peut être utilisée pour éviter des appels de réveil inutiles du processus d'application; cela peut être une optimisation importante des performances pour les grands hôtes à temps partagé. La transmission du bit PSH à l'application réceptrice permet des optimisations similaires au sein de l'application.
4.2.2.3 Taille de fenêtre (Window Size): RFC-793 Section 3.1
La taille de fenêtre DOIT être traitée comme un nombre non signé, sinon les grandes tailles de fenêtre apparaîtront comme des fenêtres négatives et TCP ne fonctionnera pas. Il est RECOMMANDÉ que les implémentations réservent des champs de 32 bits pour les tailles de fenêtre d'envoi et de réception dans l'enregistrement de connexion et utilisent 32 bits pour tous les calculs de fenêtre.
DISCUSSION:
Le champ de fenêtre dans l'en-tête TCP est connu pour être trop petit pour les chemins à haute vitesse et à long délai. Des options TCP expérimentales ont été définies pour étendre la taille de la fenêtre; voir par exemple [TCP:11]. Pour anticiper l'adoption de telles extensions, les implémenteurs TCP devraient traiter la fenêtre comme étant de 32 bits.
4.2.2.4 Pointeur urgent (Urgent Pointer): RFC-793 Section 3.1
Il y a une erreur dans la deuxième phrase: le pointeur urgent pointe vers le numéro de séquence du dernier octet (pas LAST+1) de la séquence de données urgentes. La description à la page 56 (dernière phrase) est correcte.
TCP DOIT supporter des séquences de données urgentes de longueur arbitraire.
TCP DOIT notifier de manière asynchrone la couche application lors de la réception d'un pointeur urgent et qu'il n'y a pas de données urgentes en attente auparavant, ou chaque fois que le pointeur urgent avance dans le flux de données. Il DOIT y avoir un moyen pour l'application de savoir combien de données urgentes restent à lire de la connexion, ou au moins de déterminer s'il y a encore plus de données urgentes à lire.
DISCUSSION:
Bien que le mécanisme urgent puisse être utilisé par n'importe quelle application, il est normalement utilisé pour envoyer des commandes de type "interrupt" aux programmes Telnet (voir la section "Utilisation de la séquence de synchronisation Telnet" dans [INTRO:1]).
La notification asynchrone ou "hors bande" permettra à l'application d'entrer en "mode urgent", en lisant les données de la connexion TCP. Cela permet d'envoyer des commandes de contrôle à une application dont la mémoire tampon d'entrée normale est pleine de données non traitées.
IMPLÉMENTATION:
L'appel ascendant générique ERROR-REPORT() décrit dans la section 4.2.4.1 est un mécanisme possible pour notifier l'application de l'arrivée de données urgentes.
4.2.2.5 Options TCP (TCP Options): RFC-793 Section 3.1
TCP DOIT pouvoir recevoir des options TCP dans n'importe quel segment. TCP DOIT ignorer toute option TCP qu'il n'implémente pas sans erreur, en supposant que l'option a un champ de longueur (toutes les options TCP définies à l'avenir auront un champ de longueur). TCP DOIT être prêt à gérer une longueur d'option illégale (par exemple, zéro) sans planter; la procédure suggérée est de réinitialiser la connexion et d'enregistrer la raison.
4.2.2.6 Option de taille maximale de segment (Maximum Segment Size Option): RFC-793 Section 3.1
TCP DOIT implémenter l'envoi et la réception de l'option de taille maximale de segment (Maximum Segment Size, MSS) [TCP:4].
TCP DEVRAIT envoyer une option MSS (taille maximale de segment) dans chaque segment SYN lorsque son MSS de réception diffère de la valeur par défaut 536, et PEUT toujours l'envoyer.
Si aucune option MSS n'est reçue lors de l'établissement de la connexion, TCP DOIT supposer un MSS d'envoi par défaut de 536 (576-40) [TCP:4].
La taille maximale des segments que TCP envoie réellement, le "MSS d'envoi effectif", DOIT être le plus petit entre le MSS d'envoi (reflétant la taille de mémoire tampon de réassemblage disponible de l'hôte distant) et la taille maximale autorisée par la couche IP:
Eff.snd.MSS = min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize
où:
- SendMSS est la valeur MSS reçue de l'hôte distant, ou la valeur par défaut 536 si aucune option MSS n'a été reçue.
- MMS_S est la taille maximale d'un message de couche transport que TCP peut envoyer.
- TCPhdrsize est la taille de l'en-tête TCP; c'est normalement 20, mais peut être plus grand si des options TCP doivent être envoyées.
- IPoptionsize est la taille de toutes les options IP que TCP transmettra à la couche IP avec le message actuel.
La valeur MSS à envoyer dans une option MSS doit être inférieure ou égale à:
MMS_R - 20
où MMS_R est la taille maximale d'un message de couche transport qui peut être reçu (et réassemblé). TCP obtient MMS_R et MMS_S de la couche IP; voir l'appel générique GET_MAXSIZES dans la section 3.4.
DISCUSSION:
Le choix de la taille de segment TCP a un fort effet sur les performances. Les segments plus grands améliorent le débit en amortissant la taille d'en-tête et les frais généraux de traitement par datagramme sur plus d'octets de données; cependant, si le paquet est si grand qu'il provoque une fragmentation IP, l'efficacité chute fortement si un fragment est perdu [IP:9].
Certaines implémentations TCP n'envoient l'option MSS que si l'hôte de destination se trouve sur un réseau non connecté. Cependant, en général, la couche TCP peut ne pas avoir les informations appropriées pour prendre cette décision, il est donc préférable de laisser à la couche IP la tâche de déterminer le MTU approprié pour le chemin Internet. Par conséquent, nous recommandons que TCP envoie toujours l'option (si elle n'est pas 536) et que la couche IP détermine MMS_R comme spécifié dans les sections 3.3.3 et 3.4. Le mécanisme de couche IP proposé pour mesurer le MTU modifierait alors la couche IP sans changer TCP.
4.2.2.7 Somme de contrôle TCP (TCP Checksum): RFC-793 Section 3.1
Contrairement à la somme de contrôle UDP (voir la section 4.1.3.4), la somme de contrôle TCP n'est jamais optionnelle. L'expéditeur DOIT la générer et le récepteur DOIT la vérifier.
4.2.2.8 Diagramme d'état de connexion TCP (TCP Connection State Diagram): RFC-793 Section 3.2, page 23
Il y a plusieurs problèmes avec ce diagramme:
(a) La flèche de SYN-SENT vers SYN-RCVD devrait être étiquetée "snd SYN,ACK", pour être en accord avec le texte à la page 68 et la figure 8.
(b) Il pourrait y avoir une flèche de l'état SYN-RCVD vers l'état LISTEN, conditionnée à la réception d'un RST après une ouverture passive (voir le texte page 70).
(c) Il est possible d'aller directement de l'état FIN-WAIT-1 à l'état TIME-WAIT (voir la page 75 de la spécification).
4.2.2.9 Sélection du numéro de séquence initial (Initial Sequence Number Selection): RFC-793 Section 3.3, page 27
TCP DOIT utiliser la sélection du numéro de séquence initial pilotée par horloge spécifiée.
4.2.2.10 Tentatives d'ouverture simultanée (Simultaneous Open Attempts): RFC-793 Section 3.4
Il y a une erreur dans la figure 8: le paquet à la ligne 7 devrait être identique au paquet à la ligne 5.
TCP DOIT supporter les tentatives d'ouverture simultanée.
DISCUSSION:
Il surprend parfois les implémenteurs que si deux applications tentent de se connecter simultanément l'une à l'autre, une seule connexion est générée au lieu de deux. C'était une décision de conception intentionnelle; n'essayez pas de la "corriger".
4.2.2.11 Récupération d'un SYN dupliqué ancien (Recovery from Old Duplicate SYN): RFC-793 Section 3.4, page 33
Notez qu'une implémentation TCP DOIT suivre si la connexion a atteint l'état SYN_RCVD en résultat d'un OPEN passif ou d'un OPEN actif.
4.2.2.12 Segment RST (RST Segment): RFC-793 Section 3.4
TCP DEVRAIT permettre à un segment RST reçu de contenir des données.
DISCUSSION:
Il a été suggéré qu'un segment RST pourrait contenir du texte ASCII encodant et expliquant la cause du RST. Aucune norme n'a encore été établie pour de telles données.
4.2.2.13 Fermeture d'une connexion (Closing a Connection): RFC-793 Section 3.5
Une connexion TCP peut se terminer de deux manières: (1) la séquence de fermeture TCP normale utilisant une poignée de main FIN, et (2) un "abandon" dans lequel un ou plusieurs segments RST sont envoyés et l'état de connexion est immédiatement supprimé. Si une connexion TCP est fermée par le site distant, l'application locale DOIT être informée si elle a été fermée normalement ou a été abandonnée.
La séquence de fermeture TCP normale livre de manière fiable les données mises en mémoire tampon dans les deux directions. Comme les deux directions d'une connexion TCP sont fermées indépendamment, il est possible qu'une connexion soit "semi-fermée", c'est-à-dire fermée dans une seule direction, et un hôte est autorisé à continuer à envoyer des données dans la direction ouverte sur une connexion semi-fermée.
Un hôte PEUT implémenter une séquence de fermeture TCP "semi-duplex", de sorte qu'une application qui a appelé CLOSE ne peut pas continuer à lire les données de la connexion. Si un tel hôte émet un appel CLOSE alors que des données reçues sont encore en attente dans TCP, ou si de nouvelles données sont reçues après l'appel de CLOSE, son TCP DEVRAIT envoyer un RST pour montrer que des données ont été perdues.
Lorsqu'une connexion est fermée activement, elle DOIT rester dans l'état TIME-WAIT pendant un temps de 2×MSL (Maximum Segment Lifetime). Cependant, elle PEUT accepter un nouveau SYN du TCP distant pour rouvrir la connexion directement depuis l'état TIME-WAIT, si elle:
(1) attribue son numéro de séquence initial pour la nouvelle connexion pour qu'il soit plus grand que le plus grand numéro de séquence qu'elle a utilisé sur l'incarnation de connexion précédente, et
(2) retourne à l'état TIME-WAIT si le SYN s'avère être un ancien duplicata.
DISCUSSION:
La fermeture complète en duplex intégral avec préservation des données de TCP est une fonctionnalité qui n'est pas incluse dans le protocole de transport ISO analogue TP4.
Certains systèmes n'ont pas implémenté de connexions semi-fermées, probablement parce qu'elles ne s'intègrent pas dans le modèle d'E/S de leur système d'exploitation particulier. Sur ces systèmes, une fois qu'une application a appelé CLOSE, elle ne peut plus lire les données d'entrée de la connexion; cela est appelé une séquence de fermeture TCP "semi-duplex".
L'algorithme de fermeture gracieuse de TCP exige que l'état de connexion reste défini sur (au moins) une extrémité de la connexion, pendant une période de délai de 2×MSL, c'est-à-dire 4 minutes. Pendant cette période, la paire (socket distant, socket local) qui définit la connexion est occupée et ne peut pas être réutilisée. Pour raccourcir le temps pendant lequel une paire de ports donnée est occupée, certains TCP permettent à un nouveau SYN d'être accepté dans l'état TIME-WAIT.
4.2.2.14 Communication de données (Data Communication): RFC-793 Section 3.7, page 40
Depuis l'écriture de RFC-793, il y a eu des travaux approfondis sur les algorithmes TCP pour réaliser une communication de données efficace. Les sections ultérieures du présent document décrivent les algorithmes TCP requis et recommandés pour déterminer quand envoyer des données (section 4.2.3.4), quand envoyer un accusé de réception (section 4.2.3.2) et quand mettre à jour la fenêtre (section 4.2.3.3).
DISCUSSION:
Un problème de performance important est le "syndrome de fenêtre stupide" ou "SWS" [TCP:5], un modèle stable de petits mouvements de fenêtre incrémentiels entraînant des performances TCP extrêmement médiocres. Les algorithmes pour éviter SWS sont décrits ci-dessous pour le côté émission (section 4.2.3.4) et le côté réception (section 4.2.3.3).
En bref, SWS est causé par le récepteur qui avance le bord droit de la fenêtre chaque fois qu'il a un nouvel espace de mémoire tampon disponible pour recevoir des données et par l'expéditeur qui utilise n'importe quelle fenêtre incrémentielle, aussi petite soit-elle, pour envoyer plus de données [TCP:5]. Le résultat peut être un modèle stable d'envoi de segments de données minuscules, même si l'expéditeur et le récepteur ont tous deux un grand espace de mémoire tampon total pour la connexion. SWS ne peut se produire que pendant la transmission d'une grande quantité de données; si la connexion devient quiescente, le problème disparaîtra. Il est causé par une implémentation typique simple de la gestion de fenêtre, mais les algorithmes d'expéditeur et de récepteur donnés ci-dessous l'éviteront.
Un autre problème important de performance TCP est que certaines applications, en particulier la connexion à distance vers des hôtes caractère par caractère, ont tendance à envoyer des flux de segments de données d'un octet. Pour éviter les blocages, chaque appel TCP SEND de telles applications doit être "poussé", soit explicitement par l'application, soit implicitement par TCP. Le résultat peut être un flux de segments TCP contenant chacun un octet de données, ce qui rend l'utilisation de l'Internet très inefficace et contribue à la congestion de l'Internet. L'algorithme de Nagle décrit dans la section 4.2.3.4 fournit une solution simple et efficace à ce problème. Il a pour effet de regrouper les caractères sur les connexions Telnet; cela peut initialement surprendre les utilisateurs habitués à l'écho d'un seul caractère, mais ce regroupement est bénéfique à la fois pour le réseau et le temps de réponse de l'utilisateur.
L'acceptation par les utilisateurs n'a pas été un problème.
Notez que l'algorithme de Nagle et l'algorithme d'évitement SWS d'envoi jouent des rôles complémentaires dans l'amélioration des performances. L'algorithme de Nagle décourage l'envoi de segments minuscules lorsque les données à envoyer augmentent par petits incréments, tandis que l'algorithme d'évitement SWS décourage les petits segments résultant de l'avancement du bord droit de la fenêtre par petits incréments.
Une implémentation négligente peut envoyer deux segments d'accusé de réception ou plus par segment de données reçu. Par exemple, supposons que le récepteur accuse réception de chaque segment de données immédiatement. Lorsque le programme d'application consomme ensuite les données et augmente à nouveau l'espace de mémoire tampon de réception disponible, le récepteur peut envoyer un deuxième segment d'accusé de réception pour mettre à jour la fenêtre de l'expéditeur. Le cas extrême se produit avec des segments à un seul caractère sur des connexions TCP utilisant le protocole Telnet pour le service de connexion à distance. Certaines implémentations ont été observées dans lesquelles chaque segment entrant d'un caractère génère trois segments de retour: (1) l'accusé de réception, (2) une augmentation d'un octet de la fenêtre, et (3) le caractère en écho, respectivement.
4.2.2.15 Délai de retransmission (Retransmission Timeout): RFC-793 Section 3.7, page 41
L'algorithme suggéré dans RFC-793 pour calculer le délai de retransmission est maintenant connu pour être inadéquat; voir la section 4.2.3.1 ci-dessous.
Les travaux récents de Jacobson [TCP:7] sur la congestion Internet et la stabilité de retransmission TCP ont produit un algorithme de transmission combinant "démarrage lent" avec "évitement de congestion". Un TCP DOIT implémenter cet algorithme.
Si un paquet retransmis est identique au paquet original (ce qui implique non seulement que les limites de données n'ont pas changé, mais aussi que les champs de fenêtre et d'accusé de réception de l'en-tête n'ont pas changé), alors le même champ d'identification IP PEUT être utilisé (voir la section 3.2.1.5).
IMPLÉMENTATION:
Certains implémenteurs TCP ont choisi de "packetiser" le flux de données, c'est-à-dire de choisir les limites de segment lorsque les segments sont initialement envoyés et de mettre ces segments en file d'attente dans une "file d'attente de retransmission" jusqu'à ce qu'ils soient accusés de réception. Une autre conception (qui peut être plus simple) est de différer la packetisation jusqu'à chaque fois que les données sont transmises ou retransmises, de sorte qu'il n'y aura pas de file d'attente de retransmission de segment.
Dans une implémentation avec une file d'attente de retransmission de segment, les performances TCP peuvent être améliorées en repacketisant les segments en attente d'accusé de réception lorsque le premier délai de retransmission se produit. C'est-à-dire que les segments en attente qui s'adapteraient seraient combinés en un segment de taille maximale, avec une nouvelle valeur d'identification IP. Le TCP conserverait alors ce segment combiné dans la file d'attente de retransmission jusqu'à ce qu'il soit accusé de réception. Cependant, si les deux premiers segments dans la file d'attente de retransmission totalisaient plus qu'un segment de taille maximale, le TCP ne retransmettrait que le premier segment en utilisant le champ d'identification IP original.
4.2.2.16 Gestion de la fenêtre (Managing the Window): RFC-793 Section 3.7, page 41
Un récepteur TCP NE DEVRAIT PAS réduire la fenêtre, c'est-à-dire déplacer le bord droit de la fenêtre vers la gauche. Cependant, un TCP d'envoi DOIT être robuste contre la réduction de fenêtre, ce qui peut faire devenir négative la "fenêtre utilisable" (voir la section 4.2.3.4).
Si cela se produit, l'expéditeur NE DEVRAIT PAS envoyer de nouvelles données, mais DEVRAIT retransmettre normalement les anciennes données non accusées de réception entre SND.UNA et SND.UNA+SND.WND. L'expéditeur PEUT également retransmettre d'anciennes données au-delà de SND.UNA+SND.WND, mais NE DEVRAIT PAS expirer la connexion si les données au-delà du bord droit de la fenêtre ne sont pas accusées de réception. Si la fenêtre se réduit à zéro, le TCP DOIT la sonder de manière standard (voir la section suivante).
DISCUSSION:
De nombreuses implémentations TCP deviennent confuses si la fenêtre se réduit depuis la droite après que les données aient été envoyées dans une fenêtre plus grande. Notez que TCP a une heuristique pour sélectionner la dernière mise à jour de fenêtre malgré la possible réorganisation des datagrammes; en conséquence, il peut ignorer une mise à jour de fenêtre avec une fenêtre plus petite que celle précédemment offerte si ni le numéro de séquence ni le numéro d'accusé de réception n'est augmenté.
4.2.2.17 Sondage des fenêtres zéro (Probing Zero Windows): RFC-793 Section 3.7, page 42
Le sondage des fenêtres zéro (offertes) DOIT être pris en charge.
Un TCP PEUT garder sa fenêtre de réception offerte fermée indéfiniment. Tant que le TCP de réception continue d'envoyer des accusés de réception en réponse aux segments de sonde, le TCP d'envoi DOIT permettre à la connexion de rester ouverte.
DISCUSSION:
Il est extrêmement important de se rappeler que les segments ACK (accusé de réception) qui ne contiennent pas de données ne sont pas transmis de manière fiable par TCP. Si le sondage de fenêtre zéro n'est pas pris en charge, une connexion peut se bloquer indéfiniment lorsqu'un segment ACK qui rouvre la fenêtre est perdu.
Le retard dans l'ouverture d'une fenêtre zéro se produit généralement lorsque l'application réceptrice cesse de prendre des données de son TCP. Par exemple, considérez une application daemon d'imprimante, arrêtée parce que l'imprimante est à court de papier.
L'hôte transmetteur DEVRAIT envoyer la première sonde de fenêtre zéro lorsqu'une fenêtre zéro a existé pendant la période de délai de retransmission (voir la section 4.2.2.15), et DEVRAIT augmenter exponentiellement l'intervalle entre les sondes successives.
DISCUSSION:
Cette procédure minimise le retard si la condition de fenêtre zéro est due à un segment ACK perdu contenant une mise à jour d'ouverture de fenêtre. Le backoff exponentiel est recommandé, éventuellement avec un intervalle maximum non spécifié ici. Cette procédure est similaire à celle de l'algorithme de retransmission, et il peut être possible de combiner les deux procédures dans l'implémentation.
4.2.2.18 Appels OPEN passifs (Passive OPEN Calls): RFC-793 Section 3.8
Chaque appel OPEN passif crée soit un nouvel enregistrement de connexion dans l'état LISTEN, soit retourne une erreur; il NE DOIT PAS affecter un enregistrement de connexion précédemment créé.
Un TCP qui prend en charge plusieurs utilisateurs simultanés DOIT fournir un appel OPEN qui permettra fonctionnellement à une application de LISTEN sur un port alors qu'un bloc de connexion avec le même port local est dans l'état SYN-SENT ou SYN-RECEIVED.
DISCUSSION:
Certaines applications (par exemple, les serveurs SMTP) peuvent avoir besoin de gérer plusieurs tentatives de connexion à peu près en même temps. La probabilité qu'une tentative de connexion échoue est réduite en donnant à l'application un moyen d'écouter une nouvelle connexion en même temps qu'une tentative de connexion antérieure passe par la poignée de main à trois voies.
IMPLÉMENTATION:
Les implémentations acceptables d'ouvertures simultanées peuvent permettre plusieurs appels OPEN passifs, ou elles peuvent permettre le "clonage" de connexions d'état LISTEN à partir d'un seul appel OPEN passif.
4.2.2.19 Durée de vie (Time to Live): RFC-793 Section 3.9, page 52
RFC-793 spécifiait que TCP devait demander à la couche IP d'envoyer des segments TCP avec TTL = 60. Ceci est obsolète; la valeur TTL utilisée pour envoyer des segments TCP DOIT être configurable. Voir la section 3.2.1.7 pour la discussion.
4.2.2.20 Traitement des événements (Event Processing): RFC-793 Section 3.9
Bien que cela ne soit pas strictement requis, un TCP DEVRAIT être capable de mettre en file d'attente les segments TCP hors séquence. Changez le "may" dans la dernière phrase du premier paragraphe à la page 70 en "should".
DISCUSSION:
Certaines implémentations de petit hôte ont omis la mise en file d'attente de segments en raison d'un espace de mémoire tampon limité. Cette omission peut être attendue pour affecter négativement le débit TCP, car la perte d'un seul segment fait apparaître tous les segments ultérieurs comme étant "hors séquence".
En général, le traitement des segments reçus DOIT être implémenté pour agréger les segments ACK chaque fois que possible. Par exemple, si le TCP traite une série de segments en file d'attente, il DOIT tous les traiter avant d'envoyer des segments ACK.
Voici quelques corrections d'erreurs détaillées et notes sur la section Traitement des événements de RFC-793.
(a) Appel CLOSE, état CLOSE-WAIT, p. 61: entrez l'état LAST-ACK, pas CLOSING.
(b) État LISTEN, vérifier SYN (pp. 65, 66): Avec un bit SYN, si la sécurité/compartiment ou la précédence est incorrecte pour le segment, une réinitialisation est envoyée. La mauvaise forme de réinitialisation est montrée dans le texte; elle devrait être:
<SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK>
(c) État SYN-SENT, Vérifier SYN, p. 68: Lorsque la connexion entre dans l'état ESTABLISHED, les variables suivantes doivent être définies:
SND.WND <- SEG.WND
SND.WL1 <- SEG.SEQ
SND.WL2 <- SEG.ACK
(d) Vérifier la sécurité et la précédence, p. 71: Le premier en-tête "ESTABLISHED STATE" devrait vraiment être une liste de tous les états autres que SYN-RECEIVED: ESTABLISHED, FIN-WAIT-1, FIN-WAIT-2, CLOSE-WAIT, CLOSING, LAST-ACK et TIME-WAIT.
(e) Vérifier le bit SYN, p. 71: "Dans l'état SYN-RECEIVED et si la connexion a été initiée avec un OPEN passif, alors retournez cette connexion à l'état LISTEN et retournez. Sinon...".
(f) Vérifier le champ ACK, état SYN-RECEIVED, p. 72: Lorsque la connexion entre dans l'état ESTABLISHED, les variables listées dans (c) doivent être définies.
(g) Vérifier le champ ACK, état ESTABLISHED, p. 72: L'ACK est un duplicata si SEG.ACK =< SND.UNA (le = a été omis). De même, la fenêtre doit être mise à jour si: SND.UNA =< SEG.ACK =< SND.NXT.
(h) USER TIMEOUT, p. 77:
Il serait préférable de notifier l'application du délai d'attente plutôt que de laisser TCP forcer la fermeture de la connexion. Cependant, voir également la section 4.2.3.5.
4.2.2.21 Accusé de réception des segments en file d'attente (Acknowledging Queued Segments): RFC-793 Section 3.9
Un TCP PEUT envoyer un segment ACK accusant réception de RCV.NXT lorsqu'un segment valide arrive qui est dans la fenêtre mais pas au bord gauche de la fenêtre.
DISCUSSION:
RFC-793 (voir page 74) était ambigu quant à savoir si un segment ACK devait ou non être envoyé lorsqu'un segment hors séquence était reçu, c'est-à-dire lorsque SEG.SEQ n'était pas égal à RCV.NXT.
Une raison pour accuser réception de segments hors séquence pourrait être de prendre en charge un algorithme expérimental connu sous le nom de "retransmission rapide". Avec cet algorithme, l'expéditeur utilise les ACK "redondants" pour déduire qu'un segment a été perdu avant l'expiration du minuteur de retransmission. Il compte le nombre de fois qu'un ACK a été reçu avec la même valeur de SEG.ACK et avec le même bord droit de fenêtre. Si plus qu'un nombre seuil de tels ACK est reçu, alors le segment contenant les octets commençant à SEG.ACK est supposé avoir été perdu et est retransmis, sans attendre un délai d'attente. Le seuil est choisi pour compenser la réorganisation maximale probable de segments dans Internet. Il n'y a pas encore assez d'expérience avec l'algorithme de retransmission rapide pour déterminer son utilité.
4.2.3 QUESTIONS SPÉCIFIQUES (SPECIFIC ISSUES)
4.2.3.1 Calcul du délai de retransmission (Retransmission Timeout Calculation)
Un TCP hôte DOIT implémenter l'algorithme de Karn et l'algorithme de Jacobson pour calculer le délai de retransmission ("RTO").
-
L'algorithme de Jacobson pour calculer le temps aller-retour ("RTT") lissé incorpore une mesure simple de la variance [TCP:7].
-
L'algorithme de Karn pour sélectionner les mesures RTT garantit que des temps aller-retour ambigus ne corrompront pas le calcul du temps aller-retour lissé [TCP:6].
Cette implémentation DOIT également inclure un "backoff exponentiel" pour les valeurs RTO successives pour le même segment. La retransmission des segments SYN DEVRAIT utiliser le même algorithme que les segments de données.
DISCUSSION:
Il y avait deux problèmes connus avec les calculs RTO spécifiés dans RFC-793. Premièrement, la mesure précise des RTT est difficile lorsqu'il y a des retransmissions. Deuxièmement, l'algorithme pour calculer le temps aller-retour lissé est inadéquat [TCP:7], car il supposait incorrectement que la variance dans les valeurs RTT serait petite et constante. Ces problèmes ont été résolus par les algorithmes de Karn et de Jacobson, respectivement.
L'augmentation de performance résultant de l'utilisation de ces améliorations varie de notable à dramatique. L'algorithme de Jacobson pour incorporer la variance RTT mesurée est particulièrement important sur une liaison à faible vitesse, où la variation naturelle des tailles de paquets provoque une grande variation de RTT. Un fournisseur a constaté que l'utilisation de la liaison sur une ligne 9.6kb est passée de 10% à 90% suite à l'implémentation de l'algorithme de variance de Jacobson dans TCP.
Les valeurs suivantes DEVRAIENT être utilisées pour initialiser les paramètres d'estimation pour une nouvelle connexion:
(a) RTT = 0 secondes.
(b) RTO = 3 secondes. (La variance lissée doit être initialisée à la valeur qui entraînera ce RTO).
Les limites supérieures et inférieures recommandées sur le RTO sont connues pour être inadéquates sur les grands internets. La limite inférieure DEVRAIT être mesurée en fractions de seconde (pour accommoder les LAN à haute vitesse) et la limite supérieure devrait être 2×MSL, c'est-à-dire 240 secondes.
DISCUSSION:
L'expérience a montré que ces valeurs d'initialisation sont raisonnables, et qu'en tout cas les algorithmes de Karn et Jacobson rendent le comportement TCP raisonnablement insensible aux choix de paramètres initiaux.
4.2.3.2 Quand envoyer un segment ACK (When to Send an ACK Segment)
Un hôte qui reçoit un flux de segments de données TCP peut augmenter l'efficacité à la fois dans Internet et les hôtes en envoyant moins d'un segment ACK (accusé de réception) par segment de données reçu; ceci est connu sous le nom d'"ACK retardé" [TCP:5].
Un TCP DEVRAIT implémenter un ACK retardé, mais un ACK ne devrait pas être excessivement retardé; en particulier, le retard DOIT être inférieur à 0,5 secondes, et dans un flux de segments de taille complète, il DEVRAIT y avoir un ACK pour au moins chaque deuxième segment.
DISCUSSION:
Un ACK retardé donne à l'application l'opportunité de mettre à jour la fenêtre et peut-être d'envoyer une réponse immédiate. En particulier, dans le cas de la connexion à distance en mode caractère, un ACK retardé peut réduire le nombre de segments envoyés par le serveur d'un facteur 3 (ACK, mise à jour de fenêtre et caractère en écho tous combinés en un segment).
De plus, sur certains grands hôtes multi-utilisateurs, un ACK retardé peut réduire considérablement les frais généraux de traitement du protocole en réduisant le nombre total de paquets à traiter [TCP:5]. Cependant, des retards excessifs sur les ACK peuvent perturber le chronométrage aller-retour et les algorithmes de "clocking" des paquets [TCP:7].
4.2.3.3 Quand envoyer une mise à jour de fenêtre (When to Send a Window Update)
Un TCP DOIT inclure un algorithme d'évitement SWS dans le récepteur [TCP:5].
IMPLÉMENTATION:
L'algorithme d'évitement SWS du récepteur détermine quand le bord droit de la fenêtre peut être avancé; ceci est habituellement connu sous le nom de "mise à jour de la fenêtre". Cet algorithme se combine avec l'algorithme d'ACK retardé (voir la section 4.2.3.2) pour déterminer quand un segment ACK contenant la fenêtre actuelle sera réellement envoyé au récepteur. Nous utilisons la notation de RFC-793; voir les figures 4 et 5 dans ce document.
La solution pour le SWS du récepteur est d'éviter d'avancer le bord droit de la fenêtre RCV.NXT+RCV.WND par petits incréments, même si les données sont reçues du réseau en petits segments.
Supposons que l'espace de mémoire tampon de réception total soit RCV.BUFF. À un moment donné, RCV.USER octets de ce total peuvent être liés à des données qui ont été reçues et accusées de réception mais que le processus utilisateur n'a pas encore consommées. Lorsque la connexion est quiescente, RCV.WND = RCV.BUFF et RCV.USER = 0.
Garder le bord droit de la fenêtre fixe alors que les données arrivent et sont accusées de réception nécessite que le récepteur offre moins que son espace de mémoire tampon complet, c'est-à-dire que le récepteur doit spécifier un RCV.WND qui maintient RCV.NXT+RCV.WND constant à mesure que RCV.NXT augmente. Ainsi, l'espace de mémoire tampon total RCV.BUFF est généralement divisé en trois parties:
|<------- RCV.BUFF ---------------->|
1 2 3
----|---------|------------------|------|----
RCV.NXT ^
(Fixed)
1 - RCV.USER = données reçues mais pas encore consommées;
2 - RCV.WND = espace annoncé à l'expéditeur;
3 - Reduction = espace disponible mais pas encore annoncé.
L'algorithme d'évitement SWS suggéré pour le récepteur est de maintenir RCV.NXT+RCV.WND fixe jusqu'à ce que la réduction satisfasse:
RCV.BUFF - RCV.USER - RCV.WND >= min(Fr * RCV.BUFF, Eff.snd.MSS)
où Fr est une fraction dont la valeur recommandée est 1/2, et Eff.snd.MSS est le MSS d'envoi effectif pour la connexion (voir la section 4.2.2.6). Lorsque l'inégalité est satisfaite, RCV.WND est défini sur RCV.BUFF-RCV.USER.
Notez que l'effet général de cet algorithme est d'avancer RCV.WND par incréments de Eff.snd.MSS (pour des tampons de réception réalistes: Eff.snd.MSS < RCV.BUFF/2). Notez également que le récepteur doit utiliser son propre Eff.snd.MSS, en supposant qu'il soit le même que celui de l'expéditeur.
4.2.3.4 Quand envoyer des données (When to Send Data)
Un TCP DOIT inclure un algorithme d'évitement SWS dans l'expéditeur.
Un TCP DEVRAIT implémenter l'algorithme de Nagle [TCP:9] pour regrouper les segments courts. Cependant, il DOIT y avoir un moyen pour une application de désactiver l'algorithme de Nagle sur une connexion individuelle. Dans tous les cas, l'envoi de données est également soumis à la limitation imposée par l'algorithme de démarrage lent (section 4.2.2.15).
DISCUSSION:
L'algorithme de Nagle est généralement le suivant:
S'il y a des données non accusées de réception (c'est-à-dire, SND.NXT > SND.UNA), alors le TCP d'envoi met toutes les données utilisateur en mémoire tampon (quel que soit le bit PSH), jusqu'à ce que les données en attente aient été accusées de réception ou jusqu'à ce que le TCP puisse envoyer un segment de taille complète (Eff.snd.MSS octets; voir la section 4.2.2.6).
Certaines applications (par exemple, les mises à jour de fenêtre d'affichage en temps réel) exigent que l'algorithme de Nagle soit désactivé, afin que de petits segments de données puissent être diffusés au débit maximum.
IMPLÉMENTATION:
L'algorithme d'évitement SWS de l'expéditeur est plus difficile que celui du récepteur, car l'expéditeur ne connaît pas (directement) l'espace de mémoire tampon total du récepteur RCV.BUFF. Une approche qui s'est avérée bien fonctionner est que l'expéditeur calcule Max(SND.WND), la fenêtre d'envoi maximale qu'il a vue jusqu'à présent sur la connexion, et utilise cette valeur comme estimation de RCV.BUFF. Malheureusement, cela ne peut être qu'une estimation; le récepteur peut à tout moment réduire la taille de RCV.BUFF. Pour éviter un blocage résultant, il est nécessaire d'avoir un délai d'attente pour forcer la transmission de données, outrepassant l'algorithme d'évitement SWS. En pratique, ce délai d'attente devrait rarement se produire.
La "fenêtre utilisable" [TCP:5] est:
U = SND.UNA + SND.WND - SND.NXT
c'est-à-dire, la fenêtre offerte moins la quantité de données envoyées mais non accusées de réception. Si D est la quantité de données en file d'attente dans le TCP d'envoi mais pas encore envoyées, alors l'ensemble de règles suivant est recommandé.
Envoyer des données:
(1) si un segment de taille maximale peut être envoyé, c'est-à-dire si:
min(D,U) >= Eff.snd.MSS;
(2) ou si les données sont poussées et toutes les données en file d'attente peuvent être envoyées maintenant, c'est-à-dire si:
[SND.NXT = SND.UNA and] PUSHED and D <= U
(la condition entre crochets est imposée par l'algorithme de Nagle);
(3) ou si au moins une fraction Fs de la fenêtre maximale peut être envoyée, c'est-à-dire si:
[SND.NXT = SND.UNA and]
min(D,U) >= Fs * Max(SND.WND);
(4) ou si les données sont PUSHées et le délai d'attente de substitution se produit.
Ici Fs est une fraction dont la valeur recommandée est 1/2. Le délai d'attente de substitution devrait être dans la plage 0,1 - 1,0 secondes. Il peut être pratique de combiner ce temporisateur avec le temporisateur utilisé pour sonder les fenêtres zéro (section 4.2.2.17).
Enfin, notez que l'algorithme d'évitement SWS qui vient d'être spécifié doit être utilisé au lieu de l'algorithme côté expéditeur contenu dans [TCP:5].
4.2.3.5 Échecs de connexion TCP (TCP Connection Failures)
Une retransmission excessive du même segment par TCP indique une défaillance de l'hôte distant ou du chemin Internet. Cette défaillance peut être de courte ou longue durée. La procédure suivante DOIT être utilisée pour gérer les retransmissions excessives de segments de données [IP:11]:
(a) Il y a deux seuils R1 et R2 mesurant la quantité de retransmission qui s'est produite pour le même segment. R1 et R2 peuvent être mesurés en unités de temps ou comme un compte de retransmissions.
(b) Lorsque le nombre de transmissions du même segment atteint ou dépasse le seuil R1, transmettre un avis négatif (voir la section 3.3.1.4) à la couche IP, pour déclencher le diagnostic de passerelle morte.
(c) Lorsque le nombre de transmissions du même segment atteint un seuil R2 supérieur à R1, fermer la connexion.
(d) Une application DOIT pouvoir définir la valeur de R2 pour une connexion particulière. Par exemple, une application interactive pourrait définir R2 sur "infini", donnant à l'utilisateur le contrôle sur le moment de se déconnecter.
(e) TCP DEVRAIT informer l'application du problème de livraison (sauf si de telles informations ont été désactivées par l'application; voir la section 4.2.4.1), lorsque R1 est atteint et avant R2. Cela permettra à une application de connexion à distance (User Telnet) d'informer l'utilisateur, par exemple.
La valeur de R1 DEVRAIT correspondre à au moins 3 retransmissions, au RTO actuel. La valeur de R2 DEVRAIT correspondre à au moins 100 secondes.
Une tentative d'ouverture d'une connexion TCP pourrait échouer avec des retransmissions excessives du segment SYN ou par réception d'un segment RST ou d'un Port Unreachable ICMP. Les retransmissions SYN DOIVENT être gérées de la manière générale qui vient d'être décrite pour les retransmissions de données, y compris la notification de la couche application.
Cependant, les valeurs de R1 et R2 peuvent être différentes pour les segments SYN et de données. En particulier, R2 pour un segment SYN DOIT être défini suffisamment grand pour fournir une retransmission du segment pendant au moins 3 minutes. L'application peut fermer la connexion (c'est-à-dire, abandonner la tentative d'ouverture) plus tôt, bien sûr.
DISCUSSION:
Certains chemins Internet ont des temps de configuration importants, et le nombre de tels chemins est susceptible d'augmenter à l'avenir.
4.2.3.6 Keep-Alives TCP (TCP Keep-Alives)
Les implémenteurs PEUVENT inclure des "keep-alives" dans leurs implémentations TCP, bien que cette pratique ne soit pas universellement acceptée. Si les keep-alives sont inclus, l'application DOIT pouvoir les activer ou désactiver pour chaque connexion TCP, et ils DOIVENT être désactivés par défaut.
Les paquets keep-alive NE DOIVENT être envoyés que lorsqu'aucun paquet de données ou d'accusé de réception n'a été reçu pour la connexion dans un intervalle. Cet intervalle DOIT être configurable et DOIT par défaut être d'au moins deux heures.
Il est extrêmement important de se rappeler que les segments ACK qui ne contiennent pas de données ne sont pas transmis de manière fiable par TCP. Par conséquent, si un mécanisme de keep-alive est implémenté, il NE DOIT PAS interpréter l'échec de réponse à une sonde spécifique comme une connexion morte.
Une implémentation DEVRAIT envoyer un segment keep-alive sans données; cependant, elle PEUT être configurable pour envoyer un segment keep-alive contenant un octet de déchet, pour la compatibilité avec les implémentations TCP erronées.
DISCUSSION:
Un mécanisme de "keep-alive" sonde périodiquement l'autre extrémité d'une connexion lorsque la connexion est autrement inactive, même lorsqu'il n'y a pas de données à envoyer. La spécification TCP n'inclut pas de mécanisme de keep-alive car il pourrait: (1) casser des connexions parfaitement bonnes pendant des défaillances Internet transitoires; (2) consommer de la bande passante inutile ("si personne n'utilise la connexion, qui se soucie si elle est encore bonne?"); et (3) coûter de l'argent pour un chemin Internet qui facture les paquets.
Cependant, certaines implémentations TCP ont inclus un mécanisme de keep-alive. Pour confirmer qu'une connexion inactive est toujours active, ces implémentations envoient un segment de sonde conçu pour provoquer une réponse du TCP pair. Un tel segment contient généralement SEG.SEQ = SND.NXT-1 et peut ou non contenir un octet de données déchet. Notez que sur une connexion silencieuse SND.NXT = RCV.NXT, de sorte que ce SEG.SEQ sera en dehors de la fenêtre. Par conséquent, la sonde amène le récepteur à retourner un segment d'accusé de réception, confirmant que la connexion est toujours vivante. Si le pair a abandonné la connexion en raison d'une partition réseau ou d'un crash, il répondra avec un RST au lieu d'un segment d'accusé de réception.
Malheureusement, certaines implémentations TCP mal comportées échouent à répondre à un segment avec SEG.SEQ = SND.NXT-1 à moins que le segment ne contienne des données. Alternativement, une implémentation pourrait déterminer si un pair a correctement répondu aux paquets keep-alive sans octet de données déchet.
Un mécanisme de keep-alive TCP ne devrait être invoqué que dans les applications serveur qui pourraient autrement se bloquer indéfiniment et consommer des ressources inutilement si un client crashe ou abandonne une connexion pendant une défaillance réseau.
4.2.3.7 Multihébergement TCP (TCP Multihoming)
Si une application sur un hôte multihébergé ne spécifie pas l'adresse IP locale lors de l'ouverture active d'une connexion TCP, alors le TCP DOIT demander à la couche IP de sélectionner une adresse IP locale avant d'envoyer le (premier) SYN. Voir la fonction GET_SRCADDR() dans la section 3.4.
À tous les autres moments, un segment précédent a soit été envoyé soit reçu sur cette connexion, et TCP DOIT utiliser la même adresse locale qui a été utilisée dans ces segments précédents.
4.2.3.8 Options IP (IP Options)
Lorsque des options reçues sont transmises de la couche IP à TCP, TCP DOIT ignorer les options qu'il ne comprend pas.
Un TCP PEUT supporter les options Horodatage et Route d'enregistrement.
Une application DOIT pouvoir spécifier une route source lorsqu'elle ouvre activement une connexion TCP, et cela DOIT avoir priorité sur une route source reçue dans un datagramme.
Lorsqu'une connexion TCP est OPENée passivement et qu'un paquet arrive avec une option de route source IP complète (contenant une route de retour), TCP DOIT sauvegarder la route de retour et l'utiliser pour tous les segments envoyés sur cette connexion. Si une route source différente arrive dans un segment ultérieur, la définition ultérieure DEVRAIT remplacer la précédente.
4.2.3.9 Messages ICMP (ICMP Messages)
TCP DOIT agir sur un message d'erreur ICMP transmis de la couche IP, en le dirigeant vers la connexion qui a créé l'erreur. Les informations de démultiplexage nécessaires peuvent être trouvées dans l'en-tête IP contenu dans le message ICMP.
-
Source Quench
TCP DOIT réagir à un Source Quench en ralentissant la transmission sur la connexion. La procédure RECOMMANDÉE est qu'un Source Quench déclenche un "démarrage lent", comme si un délai de retransmission s'était produit.
-
Destination Unreachable -- codes 0, 1, 5
Puisque ces messages Unreachable indiquent des conditions d'erreur souple, TCP NE DOIT PAS abandonner la connexion, et il DEVRAIT rendre les informations disponibles à l'application.
DISCUSSION:
TCP pourrait signaler la condition d'erreur souple directement à la couche application avec un appel ascendant vers la routine ERROR_REPORT, ou il pourrait simplement noter le message et ne le signaler à l'application que si et quand la connexion TCP expire.
-
Destination Unreachable -- codes 2-4
Ce sont des conditions d'erreur dure, donc TCP DEVRAIT abandonner la connexion.
-
Time Exceeded -- codes 0, 1
Cela devrait être géré de la même manière que les codes Destination Unreachable 0, 1, 5 (voir ci-dessus).
-
Parameter Problem
Cela devrait être géré de la même manière que les codes Destination Unreachable 0, 1, 5 (voir ci-dessus).
4.2.3.10 Validation d'adresse distante (Remote Address Validation)
Une implémentation TCP DOIT rejeter comme erreur un appel OPEN local pour une adresse IP distante invalide (par exemple, une adresse de diffusion ou de multicast).
Un SYN entrant avec une adresse source invalide doit être ignoré soit par TCP soit par la couche IP (voir la section 3.2.1.3).
Une implémentation TCP DOIT rejeter silencieusement un segment SYN entrant qui est adressé à une adresse de diffusion ou de multicast.
4.2.3.11 Modèles de trafic TCP (TCP Traffic Patterns)
IMPLÉMENTATION:
La spécification du protocole TCP [TCP:1] donne à l'implémenteur beaucoup de liberté dans la conception des algorithmes qui contrôlent le flux de messages sur la connexion -- packetisation, gestion de la fenêtre, envoi d'accusés de réception, etc. Ces décisions de conception sont difficiles car un TCP doit s'adapter à une large gamme de modèles de trafic. L'expérience a montré qu'un implémenteur TCP doit vérifier la conception sur deux modèles de trafic extrêmes:
-
Segments à caractère unique (Single-character Segments)
Même si l'expéditeur utilise l'algorithme de Nagle, lorsqu'une connexion TCP transporte du trafic de connexion à distance à travers un LAN à faible délai, le récepteur obtiendra généralement un flux de segments à caractère unique. Si le mode d'écho de terminal distant est en vigueur, le système du récepteur fera généralement écho à chaque caractère au fur et à mesure de sa réception.
-
Transfert en masse (Bulk Transfer)
Lorsque TCP est utilisé pour un transfert en masse, le flux de données devrait être composé (presque) entièrement de segments de la taille du MSS effectif. Bien que TCP utilise un espace de numéros de séquence avec une granularité d'octet (byte), en mode transfert en masse son fonctionnement devrait être comme si TCP utilisait un espace de séquence qui ne comptait que les segments.
L'expérience a en outre montré qu'un seul TCP peut gérer efficacement et effectivement ces deux extrêmes.
L'outil le plus important pour vérifier une nouvelle implémentation TCP est un programme de traçage de paquets. Il existe un grand volume d'expérience montrant l'importance de tracer une variété de modèles de trafic avec d'autres implémentations TCP et d'étudier attentivement les résultats.
4.2.3.12 Efficacité (Efficiency)
IMPLÉMENTATION:
Une expérience approfondie a conduit aux suggestions suivantes pour une implémentation efficace de TCP:
(a) Ne pas copier les données (Don't Copy Data)
Dans le transfert de données en masse, les tâches principales intensives en CPU sont la copie de données d'un endroit à un autre et la somme de contrôle des données. Il est vital de minimiser le nombre de copies de données TCP. Comme la limitation de vitesse ultime peut être l'extraction de données à travers le bus mémoire, il peut être utile de combiner la copie avec la somme de contrôle, en faisant les deux avec une seule extraction de mémoire.
(b) Créer manuellement la routine de somme de contrôle (Hand-Craft the Checksum Routine)
Une bonne routine de somme de contrôle TCP est généralement deux à cinq fois plus rapide qu'une implémentation simple et directe de la définition. Un grand soin et un codage astucieux sont souvent requis et conseillés pour rendre le code de somme de contrôle "ultra-rapide". Voir [TCP:10].
(c) Coder pour le cas commun (Code for the Common Case)
Le traitement du protocole TCP peut être compliqué, mais pour la plupart des segments, il n'y a que quelques décisions simples à prendre. Le traitement par segment sera grandement accéléré en codant la ligne principale pour minimiser le nombre de décisions dans le cas le plus courant.
4.2.4 INTERFACE TCP/COUCHE APPLICATION (TCP/APPLICATION LAYER INTERFACE)
4.2.4.1 Rapports asynchrones (Asynchronous Reports)
Il DOIT y avoir un mécanisme pour signaler les conditions d'erreur TCP souples à l'application. Génériquement, nous supposons que cela prend la forme d'une routine ERROR_REPORT fournie par l'application qui peut être appelée de manière ascendante [INTRO:7] de manière asynchrone depuis la couche transport:
ERROR_REPORT(local connection name, reason, subreason)
L'encodage précis des paramètres reason et subreason n'est pas spécifié ici. Cependant, les conditions qui sont signalées de manière asynchrone à l'application DOIVENT inclure:
- Message d'erreur ICMP arrivé (voir 4.2.3.9)
- Retransmissions excessives (voir 4.2.3.5)
- Avancement du pointeur urgent (voir 4.2.2.4).
Cependant, un programme d'application qui ne souhaite pas recevoir de tels appels ERROR_REPORT DEVRAIT pouvoir désactiver efficacement ces appels.
DISCUSSION:
Ces rapports d'erreur reflètent généralement des erreurs souples qui peuvent être ignorées sans dommage par de nombreuses applications. Il a été suggéré que ces appels de rapport d'erreur devraient par défaut être "désactivés", mais cela n'est pas requis.
4.2.4.2 Type de service (Type-of-Service)
La couche application DOIT pouvoir spécifier le type de service (TOS) pour les segments envoyés sur une connexion. Ce n'est pas requis, mais l'application DEVRAIT pouvoir changer le TOS pendant la durée de vie de la connexion. TCP DEVRAIT transmettre la valeur TOS actuelle sans changement à la couche IP, lorsqu'il envoie des segments sur la connexion.
Le TOS sera spécifié indépendamment dans chaque direction sur la connexion, de sorte que l'application réceptrice spécifiera le TOS utilisé pour les segments ACK.
TCP PEUT transmettre le TOS le plus récemment reçu à l'application.
DISCUSSION:
Certaines applications (par exemple, SMTP) changent la nature de leur communication pendant la durée de vie d'une connexion, et souhaiteraient donc changer la spécification TOS.
Notez également que l'appel OPEN spécifié dans RFC-793 inclut un paramètre ("options") dans lequel l'appelant peut spécifier des options IP telles que route source, route d'enregistrement ou horodatage.
4.2.4.3 Appel Flush (Flush Call)
Certaines implémentations TCP ont inclus un appel FLUSH, qui videra la file d'attente d'envoi TCP de toutes les données pour lesquelles l'utilisateur a émis des appels SEND mais qui sont encore à droite de la fenêtre d'envoi. C'est-à-dire, il vide autant de données d'envoi en file d'attente que possible sans perdre la synchronisation du numéro de séquence. Ceci est utile pour implémenter la fonction "abort output" de Telnet.
4.2.4.4 Multihébergement (Multihoming)
L'interface utilisateur décrite dans les sections 2.7 et 3.8 de RFC-793 doit être étendue pour le multihébergement. L'appel OPEN DOIT avoir un paramètre optionnel:
OPEN( ... [local IP address,] ... )
pour permettre la spécification de l'adresse IP locale.
DISCUSSION:
Certaines applications basées sur TCP doivent spécifier l'adresse IP locale à utiliser pour ouvrir une connexion particulière; FTP en est un exemple.
IMPLÉMENTATION:
Un appel OPEN passif avec un paramètre "adresse IP locale" spécifié attendra une demande de connexion entrante vers cette adresse. Si le paramètre n'est pas spécifié, un OPEN passif attendra une demande de connexion entrante vers n'importe quelle adresse IP locale, puis liera l'adresse IP locale de la connexion à l'adresse particulière utilisée.
Pour un appel OPEN actif, un paramètre "adresse IP locale" spécifié sera utilisé pour ouvrir la connexion. Si le paramètre n'est pas spécifié, le logiciel réseau choisira une adresse IP locale appropriée (voir la section 3.3.4.2) pour la connexion.
4.2.5 RÉSUMÉ DES EXIGENCES TCP (TCP REQUIREMENTS SUMMARY)
| Fonctionnalité | Section | DOIT | DEVRAIT | PEUT | NE DOIT PAS |
|---|---|---|---|---|---|
| Flag Push | |||||
| Agréger ou mettre en file d'attente données non poussées | 4.2.2.2 | x | |||
| Expéditeur regroupe flags PSH consécutifs | 4.2.2.2 | x | |||
| Appel SEND peut spécifier PUSH | 4.2.2.2 | x | |||
| Si non: expéditeur tampon indéfiniment | 4.2.2.2 | x | |||
| Si non: PSH dernier segment | 4.2.2.2 | x | |||
| Notifier ALP récepteur de PSH | 4.2.2.2 | x | |||
| Envoyer segment taille max quand possible | 4.2.2.2 | x | |||
| Fenêtre | |||||
| Traiter comme nombre non signé | 4.2.2.3 | x | |||
| Gérer comme nombre 32 bits | 4.2.2.3 | x | |||
| Réduire fenêtre depuis droite | 4.2.2.16 | x | |||
| Robuste contre réduction fenêtre | 4.2.2.16 | x | |||
| Fenêtre récepteur fermée indéfiniment | 4.2.2.17 | x | |||
| Expéditeur sonde fenêtre zéro | 4.2.2.17 | x | |||
| Première sonde après RTO | 4.2.2.17 | x | |||
| Backoff exponentiel | 4.2.2.17 | x | |||
| Permettre fenêtre rester zéro indéfiniment | 4.2.2.17 | x | |||
| Expéditeur timeout connexion fenêtre zéro | 4.2.2.17 | x | |||
| Données urgentes | |||||
| Pointeur pointe dernier octet | 4.2.2.4 | x | |||
| Séquence données urgentes longueur arbitraire | 4.2.2.4 | x | |||
| Informer ALP de manière asynchrone données urgentes | 4.2.2.4 | x | |||
| ALP peut savoir combien données urgentes en file | 4.2.2.4 | x | |||
| Options TCP | |||||
| Recevoir options TCP dans tout segment | 4.2.2.5 | x | |||
| Ignorer options non supportées | 4.2.2.5 | x | |||
| Gérer longueur option illégale | 4.2.2.5 | x | |||
| Implémenter envoi et réception option MSS | 4.2.2.6 | x | |||
| Envoyer option MSS sauf si 536 | 4.2.2.6 | x | |||
| Toujours envoyer option MSS | 4.2.2.6 | x | |||
| MSS envoi par défaut est 536 | 4.2.2.6 | x | |||
| Calculer taille segment envoi effectif | 4.2.2.6 | x | |||
| Somme de contrôle TCP | |||||
| Expéditeur génère somme de contrôle | 4.2.2.7 | x | |||
| Récepteur vérifie somme de contrôle | 4.2.2.7 | x | |||
| Utiliser sélection ISN pilotée horloge | 4.2.2.9 | x | |||
| Ouverture connexions | |||||
| Supporter tentatives ouverture simultanée | 4.2.2.10 | x | |||
| SYN-RCVD se souvient dernier état | 4.2.2.11 | x | |||
| Appel Open passif interfère autres | 4.2.2.18 | x | |||
| Fonction: LISTEN simultanés même port | 4.2.2.18 | x | |||
| Demander IP adresse source SYN si nécessaire | 4.2.3.7 | x | |||
| Sinon utiliser adresse locale connexion | 4.2.3.7 | x | |||
| OPEN vers adresse IP broadcast/multicast | 4.2.3.10 | x | |||
| Rejeter silencieusement segment vers broadcast/multicast | 4.2.3.10 | x | |||
| Fermeture connexions | |||||
| RST peut contenir données | 4.2.2.12 | x | |||
| Informer application connexion abandonnée | 4.2.2.13 | x | |||
| Fermeture connexions semi-duplex | 4.2.2.13 | x | |||
| Envoyer RST pour indiquer données perdues | 4.2.2.13 | x | |||
| Dans état TIME-WAIT pour 2×MSL secondes | 4.2.2.13 | x | |||
| Accepter SYN depuis état TIME-WAIT | 4.2.2.13 | x | |||
| Retransmissions | |||||
| Algorithme démarrage lent Jacobson | 4.2.2.15 | x | |||
| Algorithme évitement congestion Jacobson | 4.2.2.15 | x | |||
| Retransmettre avec même ident IP | 4.2.2.15 | x | |||
| Algorithme Karn | 4.2.3.1 | x | |||
| Algorithme estimation RTO Jacobson | 4.2.3.1 | x | |||
| Backoff exponentiel | 4.2.3.1 | x | |||
| Calcul RTO SYN même que données | 4.2.3.1 | x | |||
| Valeurs initiales et limites recommandées | 4.2.3.1 | x | |||
| Génération ACK | |||||
| Mettre en file segments hors séquence | 4.2.2.20 | x | |||
| Traiter toute file avant envoyer ACK | 4.2.2.20 | x | |||
| Envoyer ACK pour segment hors séquence | 4.2.2.21 | x | |||
| ACK retardés | 4.2.3.2 | x | |||
| Retard < 0,5 secondes | 4.2.3.2 | x | |||
| ACK chaque 2ème segment taille complète | 4.2.3.2 | x | |||
| Algorithme évitement SWS récepteur | 4.2.3.3 | x | |||
| Envoi données | |||||
| TTL configurable | 4.2.2.19 | x | |||
| Algorithme évitement SWS expéditeur | 4.2.3.4 | x | |||
| Algorithme Nagle | 4.2.3.4 | x | |||
| Application peut désactiver algorithme Nagle | 4.2.3.4 | x | |||
| Échecs connexion | |||||
| Avis négatif IP lors retrans R1 | 4.2.3.5 | x | |||
| Fermer connexion lors retrans R2 | 4.2.3.5 | x | |||
| ALP peut définir R2 | 4.2.3.5 | x | |||
Informer ALP R1≤retrans<R2 | 4.2.3.5 | x | |||
| Valeurs recommandées R1, R2 | 4.2.3.5 | x | |||
| Même mécanisme pour SYN | 4.2.3.5 | x | |||
| R2 au moins 3 minutes pour SYN | 4.2.3.5 | x | |||
| Envoi paquets keep-alive | 4.2.3.6 | x | |||
| Application peut demander | 4.2.3.6 | x | |||
| Par défaut "désactivé" | 4.2.3.6 | x | |||
| Envoyer seulement si inactif intervalle | 4.2.3.6 | x | |||
| Intervalle configurable | 4.2.3.6 | x | |||
| Par défaut au moins 2 heures | 4.2.3.6 | x | |||
| Tolérant ACK perdus | 4.2.3.6 | x | |||
| Options IP | |||||
| Ignorer options TCP ne comprend pas | 4.2.3.8 | x | |||
| Support horodatage | 4.2.3.8 | x | |||
| Support route enregistrement | 4.2.3.8 | x | |||
| Route source | |||||
| ALP peut spécifier | 4.2.3.8 | x | |||
| Remplacer route source dans datagramme | 4.2.3.8 | x | |||
| Construire route retour depuis route source | 4.2.3.8 | x | |||
| Route source ultérieure remplace | 4.2.3.8 | x | |||
| Réception messages ICMP depuis IP | 4.2.3.9 | x | |||
| Dest Unreachable(0,1,5)→informer ALP | 4.2.3.9 | x | |||
| Dest Unreachable(0,1,5)→abandonner connexion | 4.2.3.9 | x | |||
| Dest Unreachable(2-4)→abandonner connexion | 4.2.3.9 | x | |||
| Source Quench→démarrage lent | 4.2.3.9 | x | |||
| Time Exceeded→dire ALP, ne pas abandonner | 4.2.3.9 | x | |||
| Param Problem→dire ALP, ne pas abandonner | 4.2.3.9 | x | |||
| Validation adresse | |||||
| Rejeter appel OPEN adresse IP invalide | 4.2.3.10 | x | |||
| Rejeter SYN adresse IP invalide | 4.2.3.10 | x | |||
| Rejeter silencieusement SYN broadcast/multicast | 4.2.3.10 | x | |||
| Services interface TCP/ALP | |||||
| Mécanisme rapport erreur | 4.2.4.1 | x | |||
| ALP peut désactiver routine rapport erreur | 4.2.4.1 | x | |||
| ALP peut spécifier TOS envoi | 4.2.4.2 | x | |||
| Transmis sans changement à IP | 4.2.4.2 | x | |||
| ALP peut changer TOS pendant connexion | 4.2.4.2 | x | |||
| Transmettre TOS reçu à ALP | 4.2.4.2 | x | |||
| Appel FLUSH | 4.2.4.3 | x | |||
| Param adresse IP locale optionnel dans OPEN | 4.2.4.4 | x |
NOTES:
(1) "ALP" signifie Programme de couche application (Application-Layer Program).