Transcript slides.

Principi di trasferimento affidabile

Il livello rete è inaffidabile:
Presenza di errori
 Perdita e duplicazione di pacchetti
 Ordine dei pacchetti non garantito


In caso di errori è necessario:
Rilevare e/o identificare gli errori
 Correggere gli errori oppure notificare al mittente
 Chiedere la ritrasmissione


E’ necessario considerare le risorse di rete e le
risorse del destinatario
Principi di trasferimento affidabile
1
Principi di trasferimento affidabile

Le caratteristiche del canale inaffidabile determinano la
complessità del protocollo di trasferimento affidabile (rdt:
reliable data transfer)
Trasferimento affidabile
rdt_send(): chiamata dall’alto (e.g.,
app.). I dati vengono passati per la
consegna al livello alto ricevente
send
side
udt_send(): chiamata da rdt,
per trasferire pacchetti su un
canale inaffidabile
deliver_data(): consegna
di dati al livello superiore
receive
side
rdt_rcv(): i pacchetti arrivano
su lato ricevente del canale
2
Macchine a stati finiti (FSM)
Stato iniziale
Evento che causa la transizione di stato
Azione in seguito alla transizione di stato
stato
1
stato
2
evento
azione
Lo stato successivo è
determinato dal
prossimo evento
rdt1.0: trasferimento affidabile su canale
affidabile

Canale sottostante affidabile
no errori sui bit
 no perdita di pacchetti


FSM per sender e receiver:
sender invia dati al canale sottostante
 receiver legge dati dal canale sottostante

Wait for
call from
above
rdt_send(data)
packet = make_pkt(data)
udt_send(packet)
sender
Wait for
call from
below
rdt_rcv(packet)
extract (packet,data)
deliver_data(data)
receiver
3
rdt2.0: canale con errori sui bit
o

sender ritrasmette il pacchetto al ricevimento di NAK
Meccanismi:
o riconoscimento errori (checksum)
o feedback: messaggi di controllo (ACK,NAK)
dal receiver al sender
• acknowledgements (ACK): il receiver conferma la ricezione
corretta del pacchetto
• negative acknowledgements (NAK): il receiver conferma la
ricezione del pacchetto con errori
o
ritrasmissione
rdt2.0: FSM
rdt_send(data)
sndpkt = make_pkt(data, checksum)
udt_send(sndpkt)
rdt_rcv(rcvpkt) &&
isNAK(rcvpkt)
Wait for
Wait for
call from
ACK or
udt_send(sndpkt)
above
NAK
rdt_rcv(rcvpkt) && isACK(rcvpkt)

sender
receiver
rdt_rcv(rcvpkt) &&
corrupt(rcvpkt)
udt_send(NAK)
Wait for
call from
below
rdt_rcv(rcvpkt) &&
notcorrupt(rcvpkt)
extract(rcvpkt,data)
deliver_data(data)
udt_send(ACK)
4
rdt2.0: scenario senza errori
rdt_send(data)
sndpkt = make_pkt(data, checksum)
udt_send(sndpkt)
rdt_rcv(rcvpkt) &&
isNAK(rcvpkt)
Wait for
Wait for
call from
ACK or
udt_send(sndpkt)
above
NAK
rdt_rcv(rcvpkt) && isACK(rcvpkt)

rdt_rcv(rcvpkt) &&
corrupt(rcvpkt)
udt_send(NAK)
Wait for
call from
below
rdt_rcv(rcvpkt) &&
notcorrupt(rcvpkt)
extract(rcvpkt,data)
deliver_data(data)
udt_send(ACK)
rdt2.0: scenario con errori
rdt_send(data)
snkpkt = make_pkt(data, checksum)
udt_send(sndpkt)
rdt_rcv(rcvpkt) &&
isNAK(rcvpkt)
Wait for
Wait for
call from
ACK or
udt_send(sndpkt)
above
NAK
rdt_rcv(rcvpkt) && isACK(rcvpkt)

rdt_rcv(rcvpkt) &&
corrupt(rcvpkt)
udt_send(NAK)
Wait for
call from
below
rdt_rcv(rcvpkt) &&
notcorrupt(rcvpkt)
extract(rcvpkt,data)
deliver_data(data)
udt_send(ACK)
5
rdt2.0: problema
Problema: ACK/NAK
con errori


Gestione dei duplicati:
Il sender non sa se il
receiver ha inviato ACK o
NACK
ritrasmette: possibili
duplicati



Il sender ritrasmette il
pacchetto se ACK/NAK
corrotti
Il sender aggiunge un
numero di sequenza ad ogni
pacchetto
Il receiver scarta i pacchetti
duplicati
rdt2.1
Protocolli di tipo ARQ (Automatic Repeat
reQuest) basati su riscontri positivi (ACK),
riscontri negativi (NAK) e ritrasmissione.
 Protocollo stop-and wait: dopo l’invio del
pacchetto il sender non può inviare altri dati
fino a quando riceve ACK sul pacchetto
inviato
 In protocolli stop-and-wait è sufficiente un
numero di sequenza di 1 bit

6
rdt2.1: sender
rdt_send(data)
sndpkt = make_pkt(0, data, checksum)
udt_send(sndpkt)
rdt_rcv(rcvpkt) &&
( corrupt(rcvpkt) ||
Wait for
Wait for
isNAK(rcvpkt) )
ACK or
call 0 from
udt_send(sndpkt)
NAK 0
above
rdt_rcv(rcvpkt)
&& notcorrupt(rcvpkt)
&& isACK(rcvpkt)
rdt_rcv(rcvpkt)
&& notcorrupt(rcvpkt)
&& isACK(rcvpkt)

rdt_rcv(rcvpkt) &&
( corrupt(rcvpkt) ||
isNAK(rcvpkt) )

Wait for
ACK or
NAK 1
udt_send(sndpkt)
Wait for
call 1 from
above
rdt_send(data)
sndpkt = make_pkt(1, data, checksum)
udt_send(sndpkt)
rdt2.1: receiver
rdt_rcv(rcvpkt) && notcorrupt(rcvpkt)
&& has_seq0(rcvpkt)
rdt_rcv(rcvpkt) && (corrupt(rcvpkt)
extract(rcvpkt,data)
deliver_data(data)
sndpkt = make_pkt(ACK, chksum)
udt_send(sndpkt)
rdt_rcv(rcvpkt) && (corrupt(rcvpkt)
sndpkt = make_pkt(NAK, chksum)
udt_send(sndpkt)
rdt_rcv(rcvpkt) &&
not corrupt(rcvpkt) &&
has_seq1(rcvpkt)
sndpkt = make_pkt(ACK, chksum)
udt_send(sndpkt)
sndpkt = make_pkt(NAK, chksum)
udt_send(sndpkt)
Wait for
0 from
below
Wait for
1 from
below
rdt_rcv(rcvpkt) && notcorrupt(rcvpkt)
&& has_seq1(rcvpkt)
rdt_rcv(rcvpkt) &&
not corrupt(rcvpkt) &&
has_seq0(rcvpkt)
sndpkt = make_pkt(ACK, chksum)
udt_send(sndpkt)
extract(rcvpkt,data)
deliver_data(data)
sndpkt = make_pkt(ACK, chksum)
udt_send(sndpkt)
7
Riscontri positivi e negativi
Aggiungendo un campo di riscontro agli ACK,
contenente il numero di sequenza del segmento cui
l’ACK si riferisce, il NAK può essere sostituito da
un ACK duplicato, relativo all’ultimo segmento
ricevuto correttamente
rdt2.2: sender
rdt_rcv(rcvpkt)
&& notcorrupt(rcvpkt)
&& isACK(rcvpkt,1)
rdt_send(data)
sndpkt = make_pkt(0, data, checksum)
udt_send(sndpkt)
rdt_rcv(rcvpkt) &&
( corrupt(rcvpkt) ||
Wait for
Wait for
isACK(rcvpkt,1) )
call 0 from
ACK0
udt_send(sndpkt)
above

rdt_rcv(rcvpkt) &&
( corrupt(rcvpkt) ||
isACK(rcvpkt,0) )
udt_send(sndpkt)
Wait for
ACK1
Wait for
call 1 from
above
rdt_rcv(rcvpkt)
&& notcorrupt(rcvpkt)
&& isACK(rcvpkt,0)

rdt_send(data)
sndpkt = make_pkt(1, data, checksum)
udt_send(sndpkt)
8
rdt2.2: receiver
rdt_rcv(rcvpkt) && notcorrupt(rcvpkt)
&& has_seq0(rcvpkt)
rdt_rcv(rcvpkt) &&
(corrupt(rcvpkt) ||
has_seq1(rcvpkt))
udt_send(sndpkt)
extract(rcvpkt,data)
deliver_data(data)
sndpkt = make_pkt(ACK0, chksum)
udt_send(sndpkt)
Wait for
0 from
below
Wait for
1 from
below
rdt_rcv(rcvpkt) &&
(corrupt(rcvpkt) ||
has_seq0(rcvpkt))
udt_send(sndpkt)
rdt_rcv(rcvpkt) && notcorrupt(rcvpkt)
&& has_seq1(rcvpkt)
extract(rcvpkt,data)
deliver_data(data)
sndpkt = make_pkt(ACK1, chksum)
udt_send(sndpkt)
rdt3.0: canale con errori e perdita di pacchetti
Il canale sottostante può anche perdere pacchetti.
È necessario meccanismo per rilevare la perdita di
pacchetti (dati o ACK)
 Se il sender non riceve alcuna notifica dal receiver
entro un tempo scelto opportunamente, il
pacchetto (o l’ACK) è andato perso e il sender
ritrasmette
 Come scegliere tale tempo?
 Il pacchetto potrebbe arrivare con forte ritardo:
problema dei duplicati, risolvibile con numeri di
sequenza

9
Ritrasmissione basata sul tempo
Meccanismo di conto alla rovescia.
 Il sender deve:

avviare il timer dopo la trasmissione di un pacchetto
(nuovo o ritrasmesso)
 interrompere il timer al ricevimento di un ACK
 rispondere alle interruzioni del timer

rdt3.0 sender
rdt_send(data)
rdt_rcv(rcvpkt)

Wait for
call 0 from
above
rdt_rcv(rcvpkt)
&& notcorrupt(rcvpkt)
&& isACK(rcvpkt,1)
timeout
udt_send(sndpkt)
start_timer
rdt_rcv(rcvpkt) &&
( corrupt(rcvpkt) ||
isACK(rcvpkt,0) )

Wait
for
ACK0
timeout
udt_send(sndpkt)
start_timer
rdt_rcv(rcvpkt)
&& notcorrupt(rcvpkt)
&& isACK(rcvpkt,0)
stop_timer
stop_timer

rdt_rcv(rcvpkt) &&
( corrupt(rcvpkt) ||
isACK(rcvpkt,1) )
sndpkt = make_pkt(0, data, checksum)
udt_send(sndpkt)
start_timer
Wait
for
ACK1
Wait for
call 1 from
above
rdt_send(data)
rdt_rcv(rcvpkt)

sndpkt = make_pkt(1, data, checksum)
udt_send(sndpkt)
start_timer
10
Prestazioni stop-and-wait
sender
receiver
first packet bit transmitted, t = 0
last packet bit transmitted, t = L / R
RTT
first packet bit arrives
last packet bit arrives, send ACK
ACK arrives, send next
packet, t = RTT + L / R
Prestazioni
Protocolli stop-and-wait poco efficienti
 Soluzione: il sender può inviare più pacchetti
senza dover aspettare i riscontri (pipelining)
 Occorre:

aumentare l’intervallo dei numeri di sequenza
 dotare sender e receiver di buffer per memorizzare i
pacchetti non riscontrati


Due alternative: Go-Back-N (GBN) e Selective
Repeat (SR)
11
Pipelining: aumento dell’utilizzo
e del throughput
sender
receiver
first packet bit transmitted, t = 0
last bit transmitted, t = L / R
RTT
first packet bit arrives
last packet bit arrives, send ACK
last bit of 2nd packet arrives, send ACK
last bit of 3rd packet arrives, send ACK
ACK arrives, send next
packet, t = RTT + L / R
12