Télécommunications et réseaux 1 (TER1)
Chapitre 3 : Étude de la couche « transport »
Service de transport
Protocoles de transport Internet
Couche « transport »
Livraison fiable, séquencée et point à point (TCP) - Contrôle de congestion
- Contrôle de flux - Mode connecté
Livraison non fiable (“besteffort”), non séquencée, point a point ou multicast (UDP)
Services non disponibles : - Temps réel
- Garantie de bande passante
Port de connexion
Notion de port
Couche « transport »
Ce ne sont pas des ports physiques comme les ports séries ou parallèles, ce sont des ports logiques.
Un port de connexion est un nombre sur 16 bits - 65536 possibilités
- ports réservés en standard : de 0 à 1023
- http://www.iana.org/assignments/port-numbers
Permet d'avoir sur une même machine, plusieurs services accessibles simultanément (web, email, ftp, ...)
Port de connexion
3 catégories de port
Couche « transport »
Ports well-known : de 0 a 1023
- Alloués par l'IANA
- Sur la plupart des systèmes, ne peuvent etre utilises que par des processus système (ou root) ou des programmes exécutés par des utilisateurs privilégiés
Ports registered : de 1024 a 49 151
- Listés par l'IANA
- Sur la plupart des systèmes, peuvent être utilisés par des
processus utilisateur ordinaires ou des programmes exécutes par des utilisateurs ordinaires
Ports dynamic/private : de 49 152 a 65 535
- Alloués dynamiquement
Transport sans connexion UDP
UDP : User Datagram Protocol
Couche « transport »
Service “best effort” : les segments UDP peuvent être perdus ou déséquencés
Service en mode non connecté
Pas d’établissement de connexion entre émetteur et récepteur => simplicité
Chaque segment UDP est acheminé indépendamment des
autres (pour la même communication) => déséquencement
Transport sans connexion UDP
Services à inclure dans UDP
Couche « transport »
1) Identification des applications qui communiquent
●
Plusieurs applications doivent pouvoir fonctionner en même temps sur une machine
●
Solution
–
Port source permet d'identifier l'émetteur
–
Port destination permet d'identifier le receveur
–
Chaque segment UDP contient l'identification de l'émetteur et du receveur
2) Détection des erreurs de transmission
Transport sans connexion UDP
Format segment UDP
Couche « transport »
Port Source Port Destination Longueur UDP UDP Checksum 8 bytes
Contenu 32 bits
Contrainte
Un segment UDP complet (entête et contenu) doit tenir à l'intérieur d'un paquet IP
Permet d'identifier l'application
"source" du contenu du segment UDP
Permet d'identifier l'application
"destination" du contenu du segment UDP
Somme de contrôle couvrant le segment UDP complet et une partie de l'entête IP pour détecter les erreurs de transmission
0 indique que l'émetteur n'a pas calculé de checksum sur le segment
Transport sans connexion UDP
Checksum ( somme de contrôle)
Couche « transport »
But : détecter des “erreurs” (bits erronés) dans le segment émis Émetteur :
La suite à protéger est considérée comme une suite de mots de 16 bits
Calcul du Checksum
- Addition des mots de 16 bits puis
- Complément à 1 (inverse bit à bit) du résultat de
l’addition
Insertion du checksum dans
Récepteur :
Calcule le checksum du
segment reçu
Vérifie si le checksum calculé est 11 11...
- NON - erreur détectée.
Le segment est abandonne - OUI - pas d’erreur détectée
Transport sans connexion UDP
Exemple de checksum
Couche « transport »
Émetteur : trois mots
de 16 bits Récepteur : trois mots
de 16 bits + checksum
0110011001100110 0101010101010101 0000111100001111 1011101110111011 0000111100001111 1100101011001010
+
+
0011010100110101 Complément à 1
0110011001100110 0101010101010101 0000111100001111 0011010100110101
+
1111111111111111
Checksum
Construction d'un protocole de transport fiable
Principe (1/2)
Couche « transport »
Processus
émetteur Processus
récepteur Couche
application
Couche transport
Couche
Canal fiable
Processus
émetteur Processus
récepteur
Canal non
: data : paquet
Protocole de transfert
fiable (rdt)
Protocole de transfert
fiable (rdt)
udt_send() rdt_rcv()
rdt_send()
deliver_data()
Construction d'un protocole de transport fiable
Principe (2/2)
Couche « transport »
Application
Transport
Réseau
rdt_send()
udt_send()
deliver_data()
rdt_rcv()
Construction d'un protocole de transport fiable
Machine à états finis (FSM : Finite State Machines)
Couche « transport »
Commentaire Commentaire
État initial État n
Événement Actions
FSM sert à modéliser le comportement séquentiel d'un système.
Événement : produit le passage à l'état suivant
Action : actions exécutées en réponse à l'événement
Construction d'un protocole de transport fiable
Principe
Couche « transport »
Quels mécanismes placer dans la couche transport pour permettre un transfert fiable des données ?
Hypothèses de construction du protocole
1.
L'utilisateur transmet des données de petite taille
2.
La couche réseau est parfaite
1.
Aucune erreur de transmission sur le contenu des segments
2.
Aucune perte de segments
3.
La transmission des données se fait dans un sens
uniquement
Construction d'un protocole de transport fiable – couche réseau parfaite
Couche « transport »
●
Emetteur
●
Receveur
Attendre appel du dessus
Attendre appel du dessous
rdt_send(a)
segment=make_seg(a) udt_send(segment)
rdt_rcv(segment)
extract(segment,a)
Construction d'un protocole de transport fiable
Couche « transport »
Problème
Si le receveur ne parvient pas à traiter les segments reçus aussi
rapidement qu'ils sont envoyés par l'émetteur, on risque de perdre des segments (et donc des données)
Principe
● Introduire un segment de contrôle (ACK) envoyé par le receveur lorsqu'il a traité le segment reçu
● permet au receveur de dire à l'émetteur qu'il peut transmettre un autre segment de données
=> L'émetteur est asservi au receveur
Construction d'un protocole de transport fiable – Émetteur est asservi au receveur
Couche « transport »
●
Emetteur
●
Receveur
Attendre appel du dessus
Attendre ACK
Attendre appel du dessous
rdt_send(a)
segment=make_seg(a) udt_send(segment)
rdt_rcv(segment)
extract(segment,a) deliver_data(a) udt_send(ACK) rdt_rcv(ACK)
-
Protocole « stop and wait » => Envoyer et attendre : l'émetteur attend
Construction d'un protocole de transport fiable
Couche « transport »
Hypothèses de construction du protocole
1.
L'utilisateur transmet des données de petite taille
2.
La couche réseau n'est pas tout à fait parfaite
1.
Erreurs de transmission possibles sur le contenu des segments
2.
Aucune perte de segments
3.
La transmission des données se fait dans un sens uniquement
Comment faire face à ces erreurs ?
Construction d'un protocole de transport fiable – Segment erroné
Couche « transport »
Principe
●
Emetteur ajoute une somme de contrôle dans le segment
–
Somme calculée sur l'entièreté du segment et placée dans l'entête
●
Calcul de la somme de contrôle
–
Somme arithmétique modulo 16 ou 32 bits
–
Cyclical Redundancy Check (CRC)
–
...
●
Receveur vérifie que la somme de contrôle du segment
reçu est bien valide
Construction d'un protocole de transport fiable- Segment erroné
Couche « transport »
Que fait le receveur lorsqu'il reçoit un segment ?
●
Si la somme de contrôle est correcte
–
Envoyer un segment de contrôle ACK à l'émetteur pour lui confirmer la bonne réception du segment de donnée et lui permettre d'envoyer un autre segment
●
Si la somme de contrôle est incorrecte
–
Le segment ne peut être utilisé par le receveur
–
Avertir l'émetteur via un segment de contrôle spécial
(NAK) afin qu'il retransmette le segment en erreur
Construction d'un protocole de transport fiable - Segment erroné
Couche « transport »
Attendre appel du dessus
Attendre ACK ou
NAK rdt_send(a)
segment=make_seg(a,checksum) udt_send(segment)
rdt_rcv(ACK)
-
Émetteur
rdt_rcv(NAK)
udt_send(segment)
ARQ (Automatic Repeat reQuest) => requête automatique de
répétition: protocole visant à éviter les erreurs par retransmission.
Construction d'un protocole de transport fiable – Segment erroné
Couche « transport »
rdt_rcv(segment) && corrupt(segment)
udt_send(NAK)
Attendre appel du dessous
rdt_rcv(segment) && notcorrupt(segment)
extract(segment,a) deliver_data(a) udt_send(ACK) Receveur
Construction d'un protocole de transport fiable – Segment perdu
Couche « transport »
Hypothèses de construction du protocole
1.
L'utilisateur transmet des données de petite taille
2.
La couche réseau n'est pas tout à fait parfaite
1.
Erreurs de transmission possibles sur le contenu des segments
2.
Des segments peuvent être perdus
3.
La transmission des données se fait dans un sens uniquement
Comment faire face aux pertes ?
Construction d'un protocole de transport fiable – Segment perdu
Couche « transport »
Modification à l'émetteur
●
ajouter temporisateur pour retransmettre le segment en attente d'acquit après x secondes
−
inutile de modifier le receveur
Attendre appel du dessus
rdt_send(a)
segment=make_seg(a,checksum) udt_send(segment)
start_timer()
rdt_rcv(ACK)
cancel_timer()
rdt_rcv(NAK) || Timer expiré
udt_send(segment) restart_timer() Attendre
ACK ou NAK
Construction d'un protocole de transport fiable – Segment perdu
Couche « transport »
A B
rdt_send(b)
ACKdeliver_data(a)
seg(a)
rdt_send(a)
seg(b)
deliver_data(b)
Expiration du timer
Segment perdu
seg(b) ACK
Construction d'un protocole de transport fiable – Segment dupliqué
Couche « transport »
A B
rdt_send(b)
ACKdeliver_data(a)
seg(a)
rdt_send(a)
seg(b)
deliver_data(b) !!!
Expiration du timer
seg(b) ACK
deliver_data(b)
Segment perdu
ACK
Comment résoudre ce problème ?
Construction d'un protocole de transport fiable – Segment dupliqué
Couche « transport »
Principe de la solution
●
Numéroter chaque segment envoyé par l'émetteur
●
Le receveur peut détecter si un segment a été transmis plusieurs fois
●
une numérotation sur un seul bit suffit Problème
=> ACK perdu => segment dupliqué
27
Construction d'un protocole de transport fiable – Segment dupliqué
Couche « transport »
Attendre l'appel 0 de la couche
supérieure
Attendre l'appel 1 de la couche
supérieure
rdt_send(a)
segment=make_seg(0, a,checksum) udt_send(segment)
start_timer()
Emetteur
rdt_rcv(NAK) || Timer expiré
udt_send(segment) restart_timer()
Attendre ACK ou
NAK 0
rdt_rcv(ACK)
cancel_timer()
rdt_send(b)
segment=make_seg(1, a,checksum) udt_send(segment)
start_timer()
rdt_rcv(NAK) || Timer expiré
udt_send(segment) restart_timer()
Attendre ACK ou
NAK 1
rdt_rcv(ACK)
cancel_timer()
Construction d'un protocole de transport fiable – Segment dupliqué
Couche « transport »
Receveur
rdt_rcv(segment0)
&&
notcorrupt(segment0)
extract(segment0,a) deliver_data(a) udt_send(ACK)
rdt_rcv(segment1)
&&
notcorrupt(segment1)
extract(segment1,b) deliver_data(b)
rdt_rcv(segment0)
&&
notcorrupt(segment0)
udt_send(ACK)
rdt_rcv(segment1)
&&
corrupt(segment1)
udt_send(NAK)
Attendre L'envoi de 1 de la couche
inférieure rdt_rcv(segment1)
&&
notcorrupt(segment1)
udt_send(ACK)
rdt_rcv(segment0)
&&
corrupt(segment0)
udt_send(NAK)
Attendre l'envoi de 0 de la couche
inférieure
Construction d'un protocole de transport fiable – ACK retardé
Couche « transport »
A B
rdt_send(b)
ACKdeliver_data(a)
seg(0,a)
rdt_send(a)
Doublon détecté par le receveur
Expiration du timer
deliver_data(b) rdt_send(c)
rdt_send(d)
seg(1,d)Segment perdu seg(1,b) reçu OK
seg(0,c) reçu OK
Considéré comme
doublon par le receveur
seg(1,b) seg(1,b)
ACK
ACK seg(0,c)
Construction d'un protocole de transport fiable – ACK retardé
Couche « transport »
Attendre l'appel 0 de la couche
supérieure
Attendre l'appel 1 de la couche
supérieure
rdt_send(a)
segment=make_seg(0, a,checksum) udt_send(segment)
start_timer()
Emetteur
rdt_rcv(NAK?) || Timer expiré
|| rdt_rcv(ACK1)
udt_send(segment) restart_timer()
Attendre ACK0 ou
NAK
rdt_rcv(ACK0)
cancel_timer()
rdt_send(b)
rdt_rcv(NAK?) || Timer expiré
|| rdt_rcv(ACK0)
udt_send(segment) restart_timer()
Attendre ACK ou
NAK 1
rdt_rcv(ACK1)
cancel_timer()
Construction d'un protocole de transport fiable –ACK retardé
Couche « transport »
Receveur
rdt_rcv(segment0)
&&
notcorrupt(segment0)
extract(segment0,a) deliver_data(a) udt_send(ACK0)
rdt_rcv(segment1)
&&
notcorrupt(segment1)
extract(segment1,b) deliver_data(b) udt_send(ACK1)
rdt_rcv(segment0)
&&
notcorrupt(segment0)
udt_send(ACK1)
rdt_rcv(segment1)
&&
corrupt(segment1)
udt_send(NAK1)
Attendre L'envoi de 1 de la couche
inférieure rdt_rcv(segment1)
&&
notcorrupt(segment1)
udt_send(ACK0)
rdt_rcv(segment0)
&&
corrupt(segment0)
udt_send(NAK0)
Attendre l'envoi de 0 de la couche
inférieure
Construction d'un protocole de transport fiable –ACK retardé
Couche « transport »
A B
rdt_send(b)
ACK0deliver_date(a)
seg(0,a)
rdt_send(a)
seg(1,b)
Doublon détecté par le receveur
Expiration du timer
seg(1,b)
deliver_data(b)
ACK1
rdt_send(c)
ACK1Segment perdu
seg(0,c)
seg(1,b) reçu OK seg(1,b) reçu OK
Construction d'un protocole de transport fiable – Performance du protocole un bit
Couche « transport »
Protocole un bit => protocole stop-and-wait
15 ms
1 ko 1 Gbps
t t
RTT : temps de propagation aller-retour t_trans : temps de transmission
RTT 1 3
2 4
1 : Premier bit du premier paquet transmis, t=0
2 : Arrivée du premier bit du premier paquet
3 : dernier bit du premier paquet transmis, t=L/R
4 : Arrivée du dernier bit du premier paquet, envoyer ACK
RTT = 30ms ; t_trans = 8 µs Débit effectif = 267 kbps !!!
Construction d'un protocole de transport fiable –Amélioration des performances du protocole un bit
Couche « transport »
Technique du pipeline Principe
● permettre à l'émetteur d'envoyer plus d'un segment en attendant l'acquit du receveur
A B
deliver_data(a) rdt_send(a)
...
seg(0,a)
...
seg(4,e)
rdt_send(b) rdt_send(e)
deliver_data(e)
Construction d'un protocole de transport fiable –Amélioration des performances du protocole un bit
Couche « transport »
Modifications du protocole un bit
● Numérotation des segments
– Chaque segment de données à un numéro de séquence
– Chaque segment de contrôle indique le numéro du segment de données qu'il acquitte (ACK/NAK)
● Emetteur
– buffers pour stocker les segments en attente d'acquit afin de pouvoir les retransmettre en cas de problème
● Receveur
– buffers pour stocker les segments qui arrivent Comment éviter que les buffers du receveur ne débordent ?
Construction d'un protocole de transport fiable –Fenêtre glissante
Couche « transport »
Principe de la fenêtre glissante (coulissante)
● A tout moment, l'émetteur maintient une liste de numéros de séquence consécutifs qu'il peut envoyer
– fenêtre d'émission
● A tout moment le receveur maintient une liste de numéros de séquence consécutifs qu'il peut recevoir
– fenêtre de réception
● L'émetteur et le receveur doivent choisir leurs fenêtres respectives de façon cohérente
... 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ....
Segments acquittés
Segments non-acquittés
Numéros utilisables Numéros interdits
Construction d'un protocole de transport fiable –Fenêtre glissante
Couche « transport »
A B
0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8
0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8
rdt_send(a) rdt_send(b) rdt_send(c)
rdt_send(d) rdt_send(e)
deliver_data(a) deliver_data(b) deliver_data(c)
deliver_data(d)
seg(0,a) seg(1,b)
seg(2,c) OK(0)
ACK0
ACK1
ACK2 seg(3,d)
seg(4,e)
Fenêtre
Exemple : Fenêtre d'émission et de réception (3 segments)
Construction d'un protocole de transport fiable –Fenêtre glissante
Couche « transport »
Problème
● Pour placer le numéro de séquence dans un segment, il faut l'encoder sur N bits
– 2N numéros de séquence distincts Solution
● placer dans chaque segment (données et contrôle) le numéro de séquence modulo 2N
● on réutilisera donc le même numéro de séquence pour des segments distincts
Construction d'un protocole de transport fiable – Numéro séquence modulo 2N
Couche « transport »
Fenêtre d'émission et de réception : 3 segments => 2 bits pour le numéro de séquence
A B
0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3
0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3
rdt_send(a) rdt_send(b) rdt_send(c)
rdt_send(d) rdt_send(e)
deliver_data(a) deliver_data(b) deliver_data(c)
deliver_data(d)
seg(0,a) seg(1,b)
seg(2,c) OK(0)
ACK0
ACK1
ACK2 seg(3,d)
seg(0,e)
Fenêtre
Construction d'un protocole de transport fiable –Fenêtre glissante et transfert fiable
Couche « transport »
Problème
● Comment fournir un transfert fiable tout en utilisant une fenêtre glissante ?
Solutions
● Go-Back-N (retour au n-ième)
– simple à implémenter (surtout au receveur)
– les performances chutent si les erreurs sont fréquentes
● Selective Repeat
– plus complexe à implémenter (pour émetteur et receveur)
– meilleures performances que Go-Back-N lorsque le taux d'erreurs/pertes est élevé
Construction d'un protocole de transport fiable –Go-Back-N (GBN)
Couche « transport »
Principe Go-Back-N (GBN) (1/2)
● Simplifier le plus possible le receveur
● Receveur
– accepte uniquement les segments dans l'ordre exact des numéros de séquence
– sémantique des segments de contrôle
● ACKX signifie que toutes les segments jusque et y
compris le segment dont le numéro de séquence est X ont été reçus correctement =>ACK cumulatif !
● NAKX signifie que le segment X était en erreur
● Variable d'état
- expectedseqnum : numéro du prochain segment attendu
Construction d'un protocole de transport fiable –Fenêtre glissante et transfert fiable
Couche « transport »
Principe Go-Back-N (2/2)
● Emetteur
– utilisation d'un temporisateur de retransmission
– expiration du temporisateur ou réception d'un segment NAK : retransmettre tous les segments non-acquittés
● l'émetteur retransmet le segment perdu/erroné ainsi que tous les segments qu'il avait transmis
antérieurement sans recevoir d'acquit
● Variables d'état
- base : numéro du segment non-acquitté le plus ancien - nextseqnum : premier numéro de séquence libre
- W : taille de la fenêtre d'émission
Construction d'un protocole de transport fiable –Go-Back-N
Couche « transport »
rdt_rcv(segment) && notcorrupt(segment)
&& hasseqnum(segment,expectedseqnum)
extract(segment,a) deliver_data(a)
segment=make_pkt(expectedseqnum,ACK) udt_send(segment)
expectedseqnum++
Attendre appel du dessous
default
udt_send(segment)
rdt_rcv(segment) && corrupt(segment)&&hasseqnum(segment,expectedseqnum)
udt_send(NAK(expectedseqnum)) default
udt_send(segment) default
udt_send(segment)
Receveur
Construction d'un protocole de transport fiable –Go-Back-N
Couche « transport »
rdt_send(a) if (nextseqnum<base+w){
segment(nextseqnum)=make_pkt(nextseqnum,a,checksum)}
udt_send(segment(nextseqnum)) If (base==nextseqnum)
{ start_timer;}
nextseqnum++;
else
refuse_data(a);
Attendre appel du dessus
rdt_rcv(ACK) &¬corrupt(segment)
base=getacknum(segment)+1 if (base==nextseqnum)
rdt_rcv(NAK?) || Timer expiré
for (i=base;i<nextseqnum; i++) { udt_send(segment(i)); }
restart_timer();
rdt_rcv(segment)
&&corrupt(segment)
-
Émetteur
Construction d'un protocole de transport fiable –Go-Back-N
Couche « transport »
A B
0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3
0 1 2 3
rdt_send(a) rdt_send(b) rdt_send(c)
rdt_send(d) rdt_send(e)
deliver_data(a) seg(0,a)
seg(1,b) seg(2,c) OK(0)ACK0
NAK1
ACK0
seg(3,d)
Fenêtre
Erreur de transmission
Segment ignoré Segment ignoré
seg(1,b) seg(2,c) Retransmission
Fenêtre pleine, e
sera transmis plus tard
0 1 2 3 0 1 2 3 0 1 2 3
deliver_data(b)
deliver_data(d) deliver_data(c)
0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3
0 1 2 3 0 1 2 3 0 1 2 3
Construction d'un protocole de transport fiable –Go-Back-N- Expiration du timer
Couche « transport »
A B
0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3
0 1 2 3
rdt_send(a) rdt_send(b) rdt_send(c)
rdt_send(d) rdt_send(e)
deliver_data(a)
deliver_data(b) seg(0,a)
seg(1,b) seg(2,c) OK(0)
ACK0
ACK0
Fenêtre
Segment perdu
Segment ignoré
seg(1,b) seg(2,c) Expiration timer
Retransmission
0 1 2 3 0 1 2 3 0 1 2 3
Fenêtre pleine, e
0 1 2 3
0 1 2 3 0 1 2 3
0 1 2 3
Construction d'un protocole de transport fiable –Selective Repeat
Couche « transport »
● Receveur
– sauve dans un buffer les segments reçus hors séquence
● le receveur devra pouvoir réordonner les segments reçus
– Fenêtre de réception
– sémantique des messages de contrôle
● OKX
– le receveur émet un ACK pour tous les segments qu'il reçoit => ACK sélectif !
● NAKX
– Le segment numéroté X a été reçu en erreur
... 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ....
Segments acquittés
Segments reçus Segments acceptables Segments inacceptables
Construction d'un protocole de transport fiable –Selective Repeat
Couche « transport »
● Emetteur
– Lorsqu'un segment est perdu/erroné, on retransmet uniquement le segment perdu/erroné
– un temporisateur pour chaque segment
49
Construction d'un protocole de transport fiable –Selective Repeat
Couche « transport »
A B
0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3
0 1 2 3
rdt_send(a) rdt_send(b) rdt_send(c)
rdt_send(d) rdt_send(e)
deliver_data(a)
deliver_data(b) seg(0,a)
seg(1,b) seg(2,c) OK(0)
ACK0
NAK1
ACK2
seg(3,d)
Fenêtre
Erreur de transmission
Segment ignoré Segment -> buffer
seg(1,b) Retransmission
Fenêtre pleine, e
sera transmis plus tard
0 1 2 3 0 1 2 3 0 1 2 3
0 1 2 3 0 1 2 3
0 1 2 3
deliver_data(c) deliver_data(d)
0 1 2 3 0 1 2 3 0 1 2 3
ACK1 ACK3
Construction d'un protocole de transport fiable –Selective Repeat
Couche « transport »
0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3
0 1 2 3
rdt_send(a) rdt_send(b) rdt_send(c)
rdt_send(d) rdt_send(e)
deliver_data(a)
deliver_data(b) seg(0,a)
seg(1,b) seg(2,c) OK(0)
ACK0
ACK2
seg(3,d)
Fenêtre
Segment perdu
Dans buffer
seg(1,b) Expiration timer
Retransmission
0 1 2 3 0 1 2 3 0 1 2 3
Fenêtre pleine, e
0 1 2 3 0 1 2 3 0 1 2 3
0 1 2 3
Construction d'un protocole de transport fiable –Communication bidirectionnelle
Couche « transport »
Hypothèses de construction du protocole
1.
L'utilisateur transmet des SDUs de petite taille
2.
La couche réseau n'est pas tout à fait parfaite
1.
Erreurs de transmission possibles sur le contenu des paquets
2.
Des paquets peuvent être perdus
3.
La transmission des données se fait dans les deux
sens
Construction d'un protocole de transport fiable –Communication bidirectionnelle
Couche « transport »
Problème
● Que faire lorsque A et B veulent tous les deux envoyer des segments de données ?
Solution
● permettre à chacun d'envoyer des segments de données et de contrôle
● Piggyback
● Placer également une partie contrôle (champ "ack"
notamment) dans les segments de données
Construction d'un protocole de transport fiable –Communication bidirectionnelle
Couche « transport »
A B
rdt_send(a) rdt_send(b) rdt_send(c)
rdt_send(d)
deliver_data(a)
deliver_data(b) seg(0,0,a)
seg(1,0,b) seg(2,0,c) OK(0)
seg(5,0,w) NAK1
seg(6,2,x)
seg(3,6,d)
Erreur de transmission
Segment ignoré
Segment -> buffer seg(1,5,b)
Retransmission
deliver_data(c) deliver_data(d) ACK1
ACK2
rdt_send(w)
rdt_send(x) deliver_data(w)
deliver_data(x)
Segment seg(5,0,w) acquitte seg(0,0,a)
Construction d'un protocole de transport fiable
Couche « transport »
Hypothèses de construction du protocole
1.
L'utilisateur transmet des segment de grande taille
2.
La couche réseau n'est pas tout à fait parfaite
1.
Erreurs de transmission possibles sur le contenu des paquets
2.
Des paquets peuvent être perdus
3.
La transmission des données se fait dans les deux
sens
Construction d'un protocole de transport fiable
Couche « transport »
Comment transmettre de longs messages ? Principe
● Permettre à l'entité de transport de l'émetteur de découper un message en petites parties placées chacune dans un segment
● Demander à l'entité transport du receveur de réassembler les segments reçus pour reconstruire le message
Construction d'un protocole de transport fiable –
Couche « transport »
Comment fournir un service en mode byte stream ? Principe
● L'émetteur découpe le flux d'octets en segments
● Le receveur fournit le contenu des segments à son utilisateur
● Généralement, numéroter les octets dans le byte stream et placer dans chaque segment le numéro de séquence du premier octet de données présent dans le segment
– Dans ce cas, les fenêtres sont également exprimées sur base de la numérotation des octets du byte stream
Construction d'un protocole de transport fiable –
Couche « transport »
A B
rdt_send(abcdef)
rdt_send(ijkl) rdt_send(mnop)
deliver_data(ab)
deliver_data(cdef) seg(0,ab)
seg(2,cd) seg(4,ef) OK(0)ACK1
ACK4
seg(6,ijklmnop)
Segment perdu
Dans buffer
seg(2,cd) Expiration timer
Retransmission
deliver_data(ijklmnop)
ACK2 ACK6
Protocole de transport fiable TCP – Structure d'un segment TCP
Couche « transport »
Source port Destination port
Payload 32 bits
Checksum Urgent pointer THL Reserved Flags
20 bytes Sequence number
Optional header extension Window Flags :
Drapeaux binaires servant à spécifier la "fonction" d'un segment TCP
SYN : utilisé lors de l'ouverture FIN : utilisé lors de la fermeture RST : utilisé en cas de problème
ACK : si vrai, indique que l'Acknowledgement number contenu dans le segment est valide
Couvre l'entête du segment, le contenu du segment
et une partie de l'entête IP (adresses notamment)
Acknowledgement number
Longueur de l'entête du segment
Protocole de transport fiable TCP – Ouverture d'une connexion
Couche « transport »
SYN+ACK(ack=x+1,seq=y)
ACK(seq=x+1, ack=y+1) Demande de connexion
Demande de connexion + autorisation de connexion Numéro de séquence initial (x)
Numéro de séquence initial (y) SYN(seq=x)
Connexion établie A->B
Connexion établie B -> A
Numéro de séquence des segments de données -> commencera à x+1
Numéro de séquence des segments de données -> commencera à y+1
A B
●Three-way handshake
Protocole de transport fiable TCP – Ouverture d'une connexion
Couche « transport »
Négociation d'options
● possibilité de négocier certaines options durant l'ouverture de la connexion TCP
=> option encodée dans extension entête du segment TCP Par exemple :
Maximum segment size (MSS), longueur maximum de segment
Protocole de transport fiable TCP – Ouverture d'une connexion
Couche « transport »
RST+ACK(ack=x+1,seq=0) SYN(seq=x)
Connexion refusée
Refus d'ouverture
Demande de connexion
Déconnexion
Protocole de transport fiable TCP – Fermeture d'une connexion
Couche « transport »
FIN(seq=x)
ACK(ack=x+1)
ACK(ack=y+1) Demande de fermeture (A-B)
Autoriser la fermeture (A-B) Déconnexion (A-B)
FIN(seq=y)
Time WAIT
Attendre pendant deux fois la durée de vie maximale d'un paquet dans le réseau pour
Demande de fermeture (B-A) Autoriser la fermeture (B-A)
Déconnexion (A-B)
Fermeture ordonnée d'une connexion TCP
Protocole de transport fiable TCP – Fermeture d'une connexion
Couche « transport »
RST(seq=x) Déconnexion (abrupte)
Connexion fermée Connexion fermée
Fermeture abrupte d'une connexion TCP
Protocole de transport fiable TCP – États d'une connexion TCP
Couche « transport »
Émetteur
Protocole de transport fiable TCP – États d'une connexion TCP
Couche « transport »
Receveur
Protocole de transport fiable TCP – Fiabilité de transfert
Couche « transport »
ACK perdu ACK cumulatif
Protocole de transport fiable TCP –Contrôle de flux
Couche « transport »
Récepteur d'une connexion TCP a un tampon (buffer) de réception Le processus du récepteur peut prendre un certain temps pour récupérer les segments du tampon
Service de contrôle de flux :
Ajuster le rythme d'envoi de l'expéditeur à la vitesse de lecture de l'application destinataire
RcvBuffer : taille du buffer de réception
RcvWindow : espace libre dans le buffer
Protocole de transport fiable TCP –Contrôle de flux
Couche « transport »
Récepteur: informe explicitement l’émetteur de l’espace
disponible dans le buffer (=> nb d’octets qu’il est prêt à recevoir)
champ rcvWindow (fenêtre de réception) dans le segment TCP
0 1 0 2
3 4
5 0
6 7 8 9
RcvBuffer = 10 octets LastByteRcvd = 6
LastByteRead = 1
LastByteRcvd : n° du dernier octet dans le flux de données reçu par le destinataire et placé dans sa mémoire tampon
LastByteRead : n° du dernier octet dans le flux de données retiré du tampon par le processus d'application du destinataire
RcvWindow = RcvBuffer – (LastByteRcvd – LastByteRead)
Protocole de transport fiable TCP –Contrôle de flux
Couche « transport »
Protocole de transport fiable TCP –Contrôle de flux
Couche « transport »
RcvWindow=0 => plus de place disponible chez le récepteur L’émetteur est bloqué en attente d’ouverture de fenêtre
Et si le récepteur n’a rien à émettre ?
Dans TCP, un ACK ne peut être envoyé que sur réception de données
Solution
Lorsque l'émetteur reçoit une RcvWindow à 0, il envoie
périodiquement un segment d’1 octet de données pour provoquer l'envoi d'un ACK
Protocole de transport fiable TCP –Contrôle de congestion
Couche « transport »
Le contrôle de flux évite qu'une machine émet plus de segments (par seconde) que le récepteur ne peut consommer.
Le contrôle de congestion évite qu'une machine émet plus de segments (par seconde) dans un réseau que celui-ci peut
transporter.
=> Contrôle de congestion = Contrôle de flux du réseau (noeud de transfert)
Protocole de transport fiable TCP –Contrôle de congestion
Couche « transport »
R1 R2
2 Mbps
10 Mbps 10 Mbps
A C
10 Mbps
A C
2 Mbps Buffers de taille infinie R1
Modèle simplifié
Protocole de transport fiable TCP –Contrôle de congestion
Couche « transport »
10 Mbps
A C
2 Mbps Buffers de R1
TCP self-clocking
ACK
ACK
ACK
ACK
ACK
Protocole de transport fiable TCP –Contrôle de congestion
Couche « transport »
TCP self-clocking
=> peut suffire lorsqu'une seule connexion TCP utilise une ligne à bas débit pour autant que le routeur intermédiaire puisse stocker un fenêtre complète de segments
Que se passe-t-il si plusieurs connexions TCP doivent se partager la ligne ?
Protocole de transport fiable TCP –Contrôle de congestion
Couche « transport »
10 Mbps 2 Mbps
Buffers infinis Nombreux
émetteurs
Nombreux receveurs L'occupation des buffers du
routeur augmente... Même si les buffers sont infinis, le délai augmente et les émetteurs ne reçoivent pas d'acquit. Cela provoque l'expiration des temporisateurs de retransmission et la retransmission des segments non-acquités avec go-back-n....
Informellement : « trop de sources envoient trop de données, trop rapidement, plus que ce que le réseau peut absorber »
Protocole de transport fiable TCP –Contrôle de congestion
Couche « transport »
Comment réguler une connexion TCP en fonction de l'état de congestion du réseau ?
●
Mesurer l'état de congestion du réseau
–
TCP utilise les pertes de segments dans les routeurs comme une indication implicite de congestion
●
Adapter le débit de la connexion TCP
–
Profiter du contrôle de flux par fenêtre glissante et introduire une fenêtre de congestion (cwnd) dans la taille est fixée par l'émetteur en fonction de la
congestion du réseau
Protocole de transport fiable TCP –Contrôle de congestion
Couche « transport »
Fenêtre de réception :
• Limite imposée par le récepteur Fenêtre de congestion :
• Limite imposée par le réseau
Protocole de transport fiable TCP –Contrôle de congestion
Couche « transport »
Dans le cas où la capacité du récepteur est supérieure à celle du réseau, des risques de congestion existent
TCP applique la fenêtre d’émission suivante :
fenêtre_autorisée = min (fenêtre_récepteur, fenêtre_congestion)
Protocole de transport fiable TCP –Contrôle de congestion
Couche « transport »
Détection de perte :
Expiration du temporisateur
3 ACKs dupliqués
(seq=123,"abcd") (seq=127,"ef")
(seq=120,"xyz") (ack=123)
(seq=129,"gh")
(seq=131,"ij") (ack=123)
(ack=123)
(ack=123)
Segment perdu First duplicate ack
Second duplicate ack
Third duplicate ack
Segment hors séquence
Segment hors séquence Segment hors séquence
segment considéré perdu après 3 acquits dupliqués
Protocole de transport fiable TCP –Contrôle de congestion
Couche « transport »
Accroissement additif, décroissance multiplicative (algorithme AIMD : Additive Increase, Multiplicative Decrease)
Accroissement additif
En absence de perte, le cwnd est augmentée d'un segment par RTT
Croissance linéaire est connue sous le
Décroissance multiplicative
cwnd est diminuée de moitié après chaque perte
Protocole de transport fiable TCP –Contrôle de congestion
Couche « transport »
Départ lent (Slow start)
Principe:
A chaque transmission, la taille de la fenêtre de congestion est doublée.
=> accélération exponentielle
Protocole de transport fiable TCP –Contrôle de congestion
Couche « transport »
Réaction aux temporisations
Le contrôle de congestion TCP ne réagit pas de la même manière à un phénomène de perte détecté par l'expiration du temps imparti et à un phénomène de perte signalé par l'arrivée de trois accusés de réception identiques
Après expiration du temporisateur
La fenêtre de congestion est portée à 1 segment
La fenêtre s'agrandit exponentiellement (slow start)
Une fois la valeur de seuil(threshold=cwnd/2) dépassée, la fenêtre augmente linéairement
Après trois ACKs dupliqués
cwnd = cwnd/2
La fenêtre s'agrandit linéairement
Protocole de transport fiable TCP –Contrôle de congestion
Couche « transport »
Fenêtre de congestion (segments)
RTT (Round Trip Time)
Threshold (seuil) Par défaut : Threshold = 65 535
Protocole de transport fiable TCP –Contrôle de congestion
Couche « transport »
Fenêtre de congestion (segments)
Threshold (seuil)