Salta al contenuto
Note per Studenti TCP - controllo di congestione

TCP - controllo di congestione

In questa pagina 7
In questa pagina 6

Che cos'è la congestione

Si ha congestione quando il carico offerto alla rete supera la sua capacità. Nasce perché i router e i commutatori hanno code: un router ha una coda di ingresso e una di uscita per ogni interfaccia, e se non riesce a elaborare i pacchetti alla velocità con cui arrivano le code si riempiono. Esempio tipico: due sorgenti S1S_1 e S2S_2 collegate da link da 100100 Mbit/s a un router che le inoltra su un collegamento da 1010 Mbit/s: i collegamenti veloci alimentano uno lento.

Conseguenze:

Il collasso non è solo teoria: è stato osservato più volte in reti reali.

Ginocchio e precipizio; efficienza ed equità

Se si disegna il throughput in funzione del carico offerto, la curva sale linearmente, poi si appiattisce nel ginocchio (knee): da lì in poi più carico dà solo più ritardo. Più avanti c'è il precipizio (cliff): oltre, il throughput crolla (collasso).

Grafico interattivo: Throughput in funzione del carico offerto (andamento qualitativo, unità normalizzate alla capacità): retta ideale tratteggiata, curva reale con ginocchio e precipizio

  • Evitare la congestione (congestion avoidance) significa operare vicino al ginocchio: si rallenta se si sa che più avanti c'è un precipizio.
  • Controllare la congestione (congestion control) significa operare al precipizio e rallentare quando si nota un calo di capacità (la perdita di un pacchetto è un'indicazione).

Requisiti: usare le risorse in modo efficiente (massimo throughput senza ritardi eccessivi: il ginocchio), distribuirle in modo equo (fair) e prevenire o evitare il collasso. Senza conoscere i requisiti dei flussi, equo significa dividere in parti uguali.

Formula (indice di equità di Jain). Per NN flussi con rate x1,…,xNx_1,\dots,x_N: FI=(∑i=1Nxi)2N∑i=1Nxi2,1N≤FI≤1.\text{FI}=\frac{\left(\sum_{i=1}^{N}x_i\right)^2}{N\sum_{i=1}^{N}x_i^2},\qquad \frac1N\le\text{FI}\le1. Vale 11 se tutti hanno lo stesso rate, 1/N1/N se uno solo usa tutto.

Perché i limiti: indicando con μ=1N∑xi\mu=\frac1N\sum x_i la media dei rate e con σ2=1N∑xi2−μ2\sigma^2=\frac1N\sum x_i^2-\mu^2 la loro varianzaI momenti E[X^k] e i momenti centrati E[(X − μ)^k] descrivono la forma di una legge; la varianza Var(X) = E[(X − μ)²] = E[X²] − E[X]² misura quanto X si disperde attorno alla media, vale Var(aX + b) = a² Var(X) e Var(X) = 0 solo se X è costante.Varianza e momenti → (sempre ≥0\ge0), si ha ∑xi=Nμ\sum x_i=N\mu e ∑xi2=N(σ2+μ2)\sum x_i^2=N(\sigma^2+\mu^2), quindi FI=N2μ2N⋅N(σ2+μ2)=μ2σ2+μ2≤1\text{FI}=\frac{N^2\mu^2}{N\cdot N(\sigma^2+\mu^2)}=\frac{\mu^2}{\sigma^2+\mu^2}\le1, con uguale solo se σ=0\sigma=0 (rate tutti uguali). Se uno solo usa tutto, x=(R,0,…,0)x=(R,0,\dots,0): FI=R2/(NR2)=1/N\text{FI}=R^2/(N R^2)=1/N.

Esempio. Tre flussi su un link da 3030 Mbit/s. Divisione (10,10,10)(10,10,10): FI=302/(3⋅300)=1\text{FI}=30^2/(3\cdot300)=1. Divisione (18,1,1)(18,1,1): FI=202/(3⋅326)=400/978=0,409\text{FI}=20^2/(3\cdot326)=400/978=0{,}409. Divisione (8,6,4)(8,6,4): FI=182/(3⋅116)=324/348=0,931\text{FI}=18^2/(3\cdot116)=324/348=0{,}931.

L'idea di TCP

TCP sonda il canale per trovare il punto appena prima del precipizio (la "capienza del tubo") e rallenta quando lo supera. È un protocollo a finestra: in ogni RTT si possono inviare al più WW pacchetti non riscontrati. Adattare WW significa adattare il ritmo di immissione di pacchetti nella rete.

Le variabili del mittente:

Formula (finestra effettiva). W=min⁡(cwnd,rwnd)W=\min(\text{cwnd},\text{rwnd}).

Esempio. Con ssthresh=4\text{ssthresh}=4 MSS e rwnd=6\text{rwnd}=6 MSS: W=min⁡(1,6)=1W=\min(1,6)=1, poi 22, 44 (si raggiunge ssthresh), 55, 66 (si raggiunge rwnd: da lì WW resta 66 anche se cwnd continua a crescere: min⁡(6,7)=6\min(6,7)=6).

Slow start e congestion avoidance

Slow start (SS, "partenza lenta", esponenziale) e congestion avoidance (CA, "evitamento della congestione", lineare) sono algoritmi con obiettivi diversi implementati insieme:

  • SS: alla partenza della connessione e dopo un timeout controlla la fase iniziale di trasmissione: si parte piano ma si cresce in fretta, per arrivare presto a un buon throughput. Il nome inganna: la crescita è esponenziale.
  • CA: quando si è raggiunta la capacità del collegamento, controlla la trasmissione crescendo lentamente per non causare congestione.

Si parte con cwnd=1\text{cwnd}=1 MSS e ssthresh=Wmax⁡\text{ssthresh}=W_{\max} (un valore molto grande, o prefissato).

Formula (regole per ogni ACK nuovo).

  • se cwnd≤ssthresh\text{cwnd}\le\text{ssthresh} (SS): cwnd←cwnd+1\text{cwnd}\leftarrow\text{cwnd}+1;
  • se cwnd>ssthresh\text{cwnd}>\text{ssthresh} (CA): cwnd←cwnd+1cwnd\text{cwnd}\leftarrow\text{cwnd}+\dfrac1{\text{cwnd}}.

Conseguenza per RTT: in SS cwnd\text{cwnd} raddoppia a ogni RTT (un ACK per ogni segmento: +1+1 per ACK vale +W+W per round); in CA aumenta di 1 MSS per RTT (arrivano WW ACK, ciascuno vale 1/W1/W).

Il conto: in un round il mittente invia WW segmenti e riceve WW ACK. In SS ogni ACK somma 11: W+W⋅1=2WW+W\cdot1=2W. In CA ogni ACK somma 1/W1/W: W+W⋅1W=W+1W+W\cdot\frac1W=W+1. Per questo la crescita in SS è esponenziale (W=2iW=2^i dopo ii round) e in CA è lineare (W=W0+iW=W_0+i).

Esempio. Partendo da cwnd=1\text{cwnd}=1 con ssthresh=8\text{ssthresh}=8: round 00: 11; round 11: 22; round 22: 44; round 33: 88; da qui 99, 1010, 1111, …\dots. Nel round i≤3i\le3 la finestra vale Wi=2iW_i=2^i e sono stati inviati 2i+1−12^{i+1}-1 segmenti in tutto (1+2+4+8=151+2+4+8=15 dopo il round 33): è la somma di una progressione geometricaLe serie di cui si conosce il carattere e da usare come termine di paragone: geometrica (converge a 1/(1-q) se |q|<1), telescopiche (somma b_1 - lim b_n, come Mengoli), armonica generalizzata (1/n^alpha converge se e solo se alpha>1).Serie notevoli - geometrica, telescopica, armonica → di ragione 22, ∑k=0i2k=2i+1−12−1\sum_{k=0}^{i}2^k=\frac{2^{i+1}-1}{2-1}. Viceversa, per arrivare a una finestra WW in SS servono log⁡2W\log_2W round (Esponenziale e logaritmoLa funzione esponenziale a^x (base positiva diversa da 1) e la sua inversa, il logaritmo in base a, con grafici e proprietà.Esponenziale e logaritmo →): da 11 a 88 sono log⁡28=3\log_28=3 round.

Alcune precisazioni:

Convenzione per i calcoli in round. Negli esercizi del corso, a ogni RTT: se cwnd<ssthresh\text{cwnd}<\text{ssthresh} si passa a min⁡(2 cwnd,ssthresh)\min(2\,\text{cwnd},\text{ssthresh}); se cwnd≥ssthresh\text{cwnd}\ge\text{ssthresh} si aggiunge 11. La finestra di invio effettiva è sempre min⁡(cwnd,rwnd)\min(\text{cwnd},\text{rwnd}).

Esercizi: Esercizio - TCP, slow start e messaggio da 18 kB su un collegamento da 8 Mbps, Esercizio - TCP, slow start e 120 segmenti su un collegamento da 32 Mbps, Esercizio - TCP con perdita di finestra e riduzione di rwnd, Esercizio - UDP e TCP su tre collegamenti, messaggio da 225 kB, Esercizio - TCP e stop-and-wait su tre collegamenti, messaggio da 100 kB.

Come TCP scopre le perdite

Il timeout è l'indizio di congestione grave (non arriva più niente); i tre dupACK sono un indizio lieve (qualche pacchetto è comunque passato).

Formula (reazioni di base, regole del corso). Quando la congestione è indicata da KK dupACK: ssthresh=W/2\text{ssthresh}=W/2. Con timeout: ssthresh=W/2\text{ssthresh}=W/2 e cwnd=1\text{cwnd}=1 (nuovo slow start). (WW è la finestra al momento dell'evento.)

Le varianti di TCP

Old Tahoe

Implementa slow start e congestion avoidance e usa solo il timeout come recupero. Allo scadere del timeout riparte dal primo pacchetto non riscontrato, senza ritrasmettere esplicitamente (in pratica un Go-Back-N).

Tahoe

Aggiunge la ritrasmissione rapida. Alla KK-esima dupACK: ritrasmette il segmento mancante, pone ssthresh=W/2\text{ssthresh}=W/2 e cwnd=1\text{cwnd}=1 e riparte dallo slow start, come se fosse scaduto un timeout. In SS: se c'è congestione, ssthresh=cwnd/2=\text{cwnd}/2 e cwnd=1\text{cwnd}=1; se non c'è, a ssthresh si passa in CA; in CA, se c'è congestione, stesso trattamento (ssthresh dimezzata, ritorno in SS). Tahoe tratta allo stesso modo timeout e tre dupACK.

Reimpostare cwnd=1\text{cwnd}=1 dopo la ritrasmissione rapida è inefficiente: è come riavviare la connessione, con possibile calo di throughput. Ma i dupACK dicono che i pacchetti dopo quello perso sono arrivati: si può ritrasmettere meno e far avanzare cwnd con più decisione. È l'idea del fast recovery.

Reno: fast recovery

Reno aggiunge a Tahoe lo stato di fast recovery (recupero rapido), per riprendersi da una congestione lieve. Quando il ricevente continua a mandare dupACK, ogni dupACK in più vuol dire che un altro pacchetto è uscito dalla rete.

Formula (Reno).

  • Alla terza dupACK: ssthresh=cwnd/2\text{ssthresh}=\text{cwnd}/2; si ritrasmette il segmento mancante; cwnd=ssthresh+3\text{cwnd}=\text{ssthresh}+3 MSS (i tre pacchetti che hanno generato i tre dupACK hanno lasciato la rete).
  • A ogni dupACK successivo: cwnd←cwnd+1\text{cwnd}\leftarrow\text{cwnd}+1 MSS (un altro pacchetto ha raggiunto il ricevente) e si trasmette un pacchetto se cwnd lo consente.
  • Quando arriva un ACK che riscontra dati nuovi: cwnd=ssthresh\text{cwnd}=\text{ssthresh} e si esce dal fast recovery (si prosegue in CA).
  • Dopo un timeout: come Tahoe (ssthresh=cwnd/2\text{ssthresh}=\text{cwnd}/2, cwnd=1\text{cwnd}=1, slow start).

Esempio. cwnd=12\text{cwnd}=12: tre dupACK ⇒\Rightarrow ssthresh=6\text{ssthresh}=6, cwnd=9\text{cwnd}=9; due dupACK in più ⇒cwnd=11\Rightarrow\text{cwnd}=11; all'ACK nuovo cwnd=6\text{cwnd}=6 e CA (7,8,…7,8,\dots). Tahoe, nello stesso caso, ripartirebbe da 11.

Limite di Reno: se nella stessa finestra si perdono più segmenti, il primo ACK che riscontra dati nuovi (parziale, perché non copre tutta la finestra) fa uscire dal fast recovery; per recuperare il secondo segmento servono altri tre dupACK, e a volte non ne arrivano abbastanza e scatta il timeout.

NewReno

NewReno recupera più perdite nella stessa finestra, restando nel fast recovery finché non è riscontrato tutto ciò che era in volo quando è iniziata la perdita. Variabili: recover (il più alto numero di sequenza trasmesso quando inizia il recupero) e flightsize =lastseqno−ack_no+1=\text{lastseqno}-\text{ack\_no}+1 (pacchetti in volo).

Formula (NewReno).

  • Alla KK-esima dupACK: recover=lastseqno\text{recover}=\text{lastseqno}; ssthresh=max⁡(flightsize/2, 2 MSS)\text{ssthresh}=\max(\text{flightsize}/2,\ 2\,\text{MSS}); cwnd=ssthresh+3\text{cwnd}=\text{ssthresh}+3 MSS; si azzera il timer di ritrasmissione (per evitare un timeout durante il recupero); si ritrasmette il segmento mancante.
  • A ogni nuovo dupACK: cwnd←cwnd+1\text{cwnd}\leftarrow\text{cwnd}+1, e si trasmette se cwnd lo permette.
  • Quando arriva un ACK che riscontra dati nuovi: se ack_no>recover\text{ack\_no}>\text{recover} (ACK completo) allora cwnd=ssthresh\text{cwnd}=\text{ssthresh} ed esce dal fast recovery; altrimenti è un ACK parziale che riscontra nackedn_{\text{acked}} pacchetti: cwnd←cwnd−nacked+1\text{cwnd}\leftarrow\text{cwnd}-n_{\text{acked}}+1, si azzera il timer, si ritrasmette il pacchetto con seq_no=ack_no\text{seq\_no}=\text{ack\_no} e si trasmette se consentito.

Esempio (slide del corso). Finestra W=9W=9 in CA, sono in volo i pacchetti P3,…,P11P_3,\dots,P_{11}; si perdono P6P_6 e P8P_8; ACK ritardati con b=2b=2. Il ricevente manda ACK 5\text{ACK}\,5 (riscontra P3,P4P_3,P_4), ACK 6\text{ACK}\,6 (riscontra P5P_5), poi ogni pacchetto che arriva fuori ordine (P7,P9,P10,P11P_7,P_9,P_{10},P_{11}) genera un dupACK 6\,6. Alla terza dupACK il mittente ha già inviato fino a P14P_{14}: recover=P14\text{recover}=P_{14}, flightsize=14−6+1=9\text{flightsize}=14-6+1=9, ssthresh=⌊9/2⌋=4\text{ssthresh}=\lfloor9/2\rfloor=4, cwnd=4+3=7\text{cwnd}=4+3=7; ritrasmette P6P_6. Gli altri dupACK portano cwnd a 88, 99, 1010 e fanno partire P15P_{15}. L'arrivo di P6P_6 al ricevente genera ACK 8\text{ACK}\,8 (riscontra P6P_6 e P7P_7, manca P8P_8): è un ACK parziale (8≤148\le14) con nacked=2n_{\text{acked}}=2, quindi cwnd=10−2+1=9\text{cwnd}=10-2+1=9; in volo ci sono P8,…,P15P_8,\dots,P_{15}, cioè 88 pacchetti <9<9, quindi parte un nuovo pacchetto, P16P_{16}, e si ritrasmette P8P_8. Quando poi arriva ACK 16\text{ACK}\,16, 16>recover=1416>\text{recover}=14: ACK completo, cwnd=ssthresh=4\text{cwnd}=\text{ssthresh}=4 e fine del recupero. Due perdite sono state recuperate in due RTT senza timeout.

SACK: riscontro selettivo

Con l'opzione SACK (selective acknowledgment) il ricevente comunica quali blocchi ha ricevuto, così il mittente ritrasmette solo quello che manca.

  • Apertura: l'opzione si negozia nel solo segmento SYN: Kind =4=4, Length =2=2.
  • Uso: in ogni ACK, quando ci sono pacchetti fuori ordine, compare l'opzione con Kind =5=5, Length variabile e una lista di blocchi: per ognuno il bordo sinistro (primo byte del blocco) e il bordo destro (primo byte dopo il blocco), 4 byte ciascuno.

Formula (lunghezza dell'opzione SACK). Con nn blocchi: lunghezza=8n+2\text{lunghezza}=8n+2 byte. Poiché le opzioni TCP sono al massimo 4040 byte, n≤4n\le4 (8⋅4+2=348\cdot4+2=34). Se c'è anche il timestamp (1212 byte con riempimento), restano 2828 byte e n≤3n\le3 (8⋅3+2=268\cdot3+2=26).

Passaggio: ogni blocco ha due bordi da 44 byte, quindi 88 byte, e a questi si aggiungono 22 byte per Kind e Length. Imporre 8n+2≤408n+2\le40 dà n≤38/8=4,75n\le38/8=4{,}75, cioè n≤4n\le4 perché nn è intero; con 2828 byte disponibili 8n+2≤288n+2\le28 dà n≤26/8=3,25n\le26/8=3{,}25, cioè n≤3n\le3.

Esempio. Il ricevente ha i byte 11–10001000 (campo ACK =1001=1001, riscontro cumulativo), manca 10011001–20002000, ha 20012001–30003000, manca 30013001–40004000, ha 40014001–50005000. Opzione: Kind =5=5, Length =2+2⋅8=18=2+2\cdot8=18, blocchi [2001,3001)[2001,3001) e [4001,5001)[4001,5001).

NewReno con SACK. Alla KK-esima dupACK: recover=lastseqno\text{recover}=\text{lastseqno}; ssthresh=max⁡(flightsize/2,2 MSS)\text{ssthresh}=\max(\text{flightsize}/2,2\,\text{MSS}); cwnd=ssthresh\text{cwnd}=\text{ssthresh} (senza "+3+3": non serve, perché il numero di pacchetti in rete si calcola con la variabile pipe); si ritrasmette il segmento mancante; pipe=lastseqno−lastackno+1\text{pipe}=\text{lastseqno}-\text{lastackno}+1, diminuita dei pacchetti che SACK dice già arrivati. Finché pipe<cwnd\text{pipe}<\text{cwnd}: se la lista SACK mostra un buco si ritrasmette il primo pacchetto mancante, altrimenti si trasmette un pacchetto nuovo, e pipe\text{pipe} aumenta di 1. A ogni nuovo ACK (duplicato o no) pipe=pipe−nacked\text{pipe}=\text{pipe}-n_{\text{acked}} e si ripete il ciclo. Con un ACK che riscontra dati nuovi oltre recover si esce dal recupero.

variante slow start CA ritrasmissione rapida fast recovery recupera più perdite
Old Tahoe sì sì no no no
Tahoe sì sì (solo dopo timeout) sì no no
Reno sì sì sì sì no
NewReno sì sì sì sì sì

La finestra nel tempo: Tahoe e Reno a confronto

Esempio completo, a round (un round =1=1 RTT; non si conta l'attesa dell'RTO, che sul grafico tempo-reale sarebbe uno o più RTT di silenzio). ssthresh\text{ssthresh} iniziale =16=16 MSS. Nel round 99 (cwnd=20\text{cwnd}=20) scade un timeout: ssthresh =10=10, cwnd=1\text{cwnd}=1 (uguale in Tahoe e Reno). Nel round 1616 (cwnd=12\text{cwnd}=12) arrivano 3 dupACK: ssthresh =6=6; Tahoe riparte con cwnd=1\text{cwnd}=1 (slow start), Reno con cwnd=6\text{cwnd}=6 (CA, ignorando la fase di gonfiamento durante il recupero).

round Tahoe cwnd Tahoe ssthresh Reno cwnd Reno ssthresh evento a fine round
1 1 16 1 16
2 2 16 2 16
3 4 16 4 16
4 8 16 8 16
5 16 16 16 16
6 17 16 17 16
7 18 16 18 16
8 19 16 19 16
9 20 16 20 16 timeout
10 1 10 1 10
11 2 10 2 10
12 4 10 4 10
13 8 10 8 10
14 10 10 10 10
15 11 10 11 10
16 12 10 12 10 3 dupACK
17 1 6 6 6
18 2 6 7 6
19 4 6 8 6
20 6 6 9 6
21 7 6 10 6
22 8 6 11 6
23 9 6 12 6
24 10 6 13 6

Nel round 55 si raggiunge la soglia (cwnd=16=ssthresh\text{cwnd}=16=\text{ssthresh}) e da lì si cresce di 11 per round. Dopo il timeout lo slow start si ferma al valore 1010 (metà di 2020) e riprende la crescita lineare. Dopo i tre dupACK Reno perde meno finestra: nel round 2424 ha 1313 contro i 1010 di Tahoe.

Grafico interattivo

Linea continua: Tahoe; tratteggiata: Reno (coincide con Tahoe fino al round 1616).

Tahoe, Reno, NewReno e SACK con quattro perdite in una finestra

Il confronto sperimentale di Fall e Floyd (simulazione con quattro pacchetti persi nella stessa finestra) si riassume così:

  1. Tahoe ≈\approx NewReno: Tahoe riparte da 11, NewReno recupera una perdita per RTT (quattro ritrasmissioni, una per RTT), in tempi simili.
  2. Reno fatica a recuperare più perdite nella stessa finestra: ritrasmette il primo pacchetto perso, poi servono abbastanza trasmissioni per produrre nuovi dupACK e permettere la seconda ritrasmissione, e alla fine scatta il timeout.
  3. SACK dà le prestazioni migliori: con i dupACK arricchiti dalle informazioni SACK il mittente fa ritrasmissioni selettive dei soli pacchetti persi, quindi recupera tutte le perdite in circa un RTT.

Versione ripasso

Congestione

Idea di TCP e finestra

TCP sonda il canale e rallenta oltre il limite; adattare WW significa adattare il ritmo di immissione. Variabili: cwnd (decisa dal mittente in base alla rete), rwnd (annunciata dal ricevente: TCP - connessione, affidabilità e controllo di flussoTCP (Transmission Control Protocol) è il protocollo di trasporto con connessione e affidabile: trasforma il servizio senza connessione e inaffidabile di IP in un flusso di byte ordinato, senza errori né duplicati. La connessione si apre con l'handshake a tre vie (SYN, SYN+ACK, ACK) e si chiude con tre o quattro segmenti (FIN). I byte sono numerati: il numero di sequenza è quello del primo byte del segmento, il numero di ACK (cumulativo) è il prossimo byte atteso. Il mittente può inviare $\min(\text{rwnd},\text{cwnd})$ byte non ancora confermati; rwnd (finestra del ricevitore, in un campo di 16 bit) è il controllo di flusso. L'errore si gestisce con checksum, ACK, timeout di ritrasmissione (RTO) e ritrasmissione rapida dopo tre ACK duplicati. Per usare tutto il canale la finestra deve valere almeno il prodotto banda-ritardo (BDP); il throughput massimo è $\text{MSS}\cdot W_{\max}/\text{RTT}$.TCP - connessione, affidabilità e controllo di flusso →), ssthresh (stima della capacità).

W=min⁡(cwnd,rwnd)W=\min(\text{cwnd},\text{rwnd}). Esempio con ssthresh=4\text{ssthresh}=4, rwnd=6\text{rwnd}=6: W=1,2,4,5,6W=1,2,4,5,6, poi resta 66 anche se cwnd cresce (min⁡(6,7)=6\min(6,7)=6).

Slow start e congestion avoidance

Si parte con cwnd=1\text{cwnd}=1 MSS e ssthresh=Wmax⁡\text{ssthresh}=W_{\max} (grande). Per ogni ACK nuovo:

Rilevare le perdite

Varianti

  • Old Tahoe: SS e CA, recupero solo col timeout.
  • Tahoe: aggiunge il fast retransmit; al KK-esimo dupACK ritrasmette, ssthresh=W/2\text{ssthresh}=W/2, cwnd=1\text{cwnd}=1 e riparte da SS (come un timeout): inefficiente, perché i dupACK dicono che i pacchetti successivi sono arrivati.
  • Reno (fast recovery):
    • terza dupACK: ssthresh=cwnd/2\text{ssthresh}=\text{cwnd}/2, ritrasmette, cwnd=ssthresh+3\text{cwnd}=\text{ssthresh}+3 MSS;
    • ogni dupACK successivo: cwnd←cwnd+1\text{cwnd}\leftarrow\text{cwnd}+1 e si trasmette se consentito;
    • ACK con dati nuovi: cwnd=ssthresh\text{cwnd}=\text{ssthresh}, si esce e si prosegue in CA.
    • Esempio: cwnd=12→ssthresh=6\text{cwnd}=12\to\text{ssthresh}=6, cwnd=9\text{cwnd}=9; due dupACK →11\to11; ACK nuovo →6\to6, poi 7,8,…7,8,\dots (Tahoe ripartirebbe da 11).
    • Limite: con più perdite nella stessa finestra il primo ACK parziale fa uscire dal recovery; servono altri tre dupACK o scatta il timeout.
  • NewReno: resta nel recovery finché non è riscontrato tutto ciò che era in volo. Variabili recover (massimo numero trasmesso all'inizio) e flightsize=lastseqno−ack_no+1\text{flightsize}=\text{lastseqno}-\text{ack\_no}+1.
    • KK-esima dupACK: recover=lastseqno\text{recover}=\text{lastseqno}, ssthresh=max⁡(flightsize/2, 2 MSS)\text{ssthresh}=\max(\text{flightsize}/2,\,2\,\text{MSS}), cwnd=ssthresh+3\text{cwnd}=\text{ssthresh}+3, azzera il timer, ritrasmette;
    • dupACK successivi: cwnd+1\text{cwnd}+1;
    • ACK nuovo con ack_no>recover\text{ack\_no}>\text{recover} (completo): cwnd=ssthresh\text{cwnd}=\text{ssthresh}, esce; altrimenti parziale: cwnd←cwnd−nacked+1\text{cwnd}\leftarrow\text{cwnd}-n_{\text{acked}}+1, ritrasmette seq_no=ack_no\text{seq\_no}=\text{ack\_no}, azzera il timer.
    • Esempio (W=9W=9, in volo P3,…,P11P_3,\dots,P_{11}, persi P6P_6 e P8P_8, b=2b=2): alla terza dupACK 6\,6 il mittente è a P14P_{14}: recover=14\text{recover}=14, flightsize=14−6+1=9\text{flightsize}=14-6+1=9, ssthresh=4\text{ssthresh}=4, cwnd=7\text{cwnd}=7, ritrasmette P6P_6. Arriva ACK 8\text{ACK}\,8 parziale (8≤148\le14, nacked=2n_{\text{acked}}=2): cwnd=10−2+1=9\text{cwnd}=10-2+1=9, ritrasmette P8P_8. ACK 16>14\text{ACK}\,16>14: completo, cwnd=4\text{cwnd}=4. Due perdite in due RTT senza timeout.
  • SACK: negoziato nel SYN (Kind =4=4, Length =2=2); negli ACK Kind =5=5 con blocchi (bordo sinistro = primo byte, destro = primo byte dopo il blocco, 4 B ciascuno). Lunghezza 8n+28n+2 B; opzioni al massimo 4040 B, quindi n≤4n\le4 (3434 B), con timestamp (1212 B) n≤3n\le3 (2626 B). Esempio: ricevuti 11–10001000 (ACK =1001=1001), 20012001–30003000, 40014001–50005000: Length =2+2⋅8=18=2+2\cdot8=18, blocchi [2001,3001)[2001,3001) e [4001,5001)[4001,5001).
    • NewReno con SACK: cwnd=ssthresh\text{cwnd}=\text{ssthresh} (senza +3+3) e variabile pipe (pacchetti in rete, meno quelli già arrivati secondo SACK): finché pipe<cwnd\text{pipe}<\text{cwnd} si ritrasmette il primo buco, altrimenti si trasmette nuovo.
variante SS e CA fast retransmit fast recovery più perdite
Old Tahoe sì no no no
Tahoe sì sì no no
Reno sì sì sì no
NewReno sì sì sì sì

Tahoe e Reno a confronto

ssthresh=16\text{ssthresh}=16: cwnd 1,2,4,8,16,17,18,19,201,2,4,8,16,17,18,19,20; timeout a 2020 ⇒\Rightarrow ssthresh=10\text{ssthresh}=10, cwnd=1\text{cwnd}=1 (uguale in Tahoe e Reno); 1,2,4,8,10,11,121,2,4,8,10,11,12; 3 dupACK a 1212 ⇒\Rightarrow ssthresh=6\text{ssthresh}=6. Tahoe: 1,2,4,6,7,…,101,2,4,6,7,\dots,10 (round 24); Reno: 6,7,…,136,7,\dots,13 (round 24).

Con quattro perdite in una finestra (Fall e Floyd): Tahoe ≈\approx NewReno (una perdita per RTT), Reno fatica e arriva al timeout, SACK è il migliore (ritrasmissioni selettive, circa un RTT).

Errori tipici: cwnd=1\text{cwnd}=1 in Reno dopo i tre dupACK; dopo il timeout ssthresh è W/2W/2, non la vecchia soglia; usare +1+1 per ACK anche in CA; trattare come completo un ACK parziale in NewReno.

Esercizi su questo argomento

Lezioni in cui compare

Teoria collegata