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