TCP

TCP come abbiamo più volte detto è un servizio orientato alla connessione questo vuol dire che i due host prima di cominciare a scambiarsi dati devono effettuare l'handshake (una operazione che consiste nello scambio di alcuni segmenti particolari che consente ai sistemi periferici di stabilire la connessione TCP).
Gli elementi della rete (router e switch a livello di collegamento) non salvano lo stato della connessione, la connessione risiede nei sistemi periferici, gli elementi intermedi sono ignari che i pacchetti che viaggiano nella rete siano elementi di una connessione TCP, essi vedono solo dei datagrammi.
TCP offre un servizio full-duplex: pacchetti possono viaggiare da e verso il mittente/destinatario contemporaneamente.
TCP è una connessione di tipo punto a punto: ha luogo fra un singolo mittente e un singolo destinatario, il multicast (pacchetti che viaggiano da un mittente e più destinatari) in TCP non è fattibile.

Creazione di una socket TCP in python
...
clientSocket.connect((serverName, serverPort))  
# dove serverName: nome del server  
# serverPort: porta su cui opera il processo server

Quando un client contatta un server in TCP invia un pacchetto speciale, il server risponde con un pacchetto altrettanto speciale e infine il cliente invia una ulteriore conferma di aver ricevuto tale pacchetto, questa volta il pacchetto conterrà anche i dati della richiesta che il client vuole effettuare. Questa è la procedura di handshake che viene detto a tre vie (per il numero di scambio di pacchetti). I primi due pacchetti non contengono payload (dati), ma l'ultimo si.
Stabilita la connessione i due processi possono cominciare a scambiarsi dati.

Pasted image 20230927140512.png
Quando un processo vuole inviare dati su TCP:

  • Il processo scrive i dati
  • Attraverso la socket li consegna a TCP
  • TCP li mette nel suo buffer di invio e li invia quando è meglio inviarli (in senso di prestazioni)
    C'è un limite alla quantità di dati impachettabile in un segmento: MSS (maximum segment size). Tale valore viene impostato generalmente determinando prima la lunghezza del frame più grande che può essere inviato a livello di collegamento dall'host mittente locale, la cosiddetta unità trasmissiva massima (MTU - maximum transfer unit) e poi scegliendo un MSS tale che il segmento TCP (una volta incapsulato in un datagramma IP) stia all'interno di un singolo frame a livello di collegamento, considerando anche la lunghezza dell'intestazione TCP/IP (40 byte in genere).
    Si noti che MSS è la quantità massima di dati trasportabili da un segmento TCP (escluso di intestazione). Quando arrivano a destinazione i segmenti TCP vengono salvati nel buffer del ricevente da dove poi verranno prelevati ed inviati all'applicazione.
Struttura segmenti TCP
...

Pasted image 20230927140705.png
Un pacchetto TCP è un insieme di dati (payload) e elementi di controllo del protocollo.
Se deve essere trasportato un dato con dimensione superiore a MSS, il dato viene suddiviso in più pacchetti. In altri casi possono anche essere inferiori della lunghezza di MSS.
Il campo header length indica la lunghezza dell’intestazione del pacchetto TCP: l’intestazione in TCP è variabile in termini di dimensione.
Campo flag:

  • ACK: il pacchetto contiene un ACK valido, ovvero il pacchetto è stato ricevuto con successo
  • RST, SYN, FIN: per impostare e chiudere la connessione
  • CWR, ECE: per il controllo della congestione
  • PSH: se è 1 i dati devono essere subito consegnati al livello superiore dal destinatario
  • URG: indica che il pacchetto è urgente, nella pratica PSH è URG non vengono usati.
Differenza PSH e URG

Vediamo in dettaglio cosa fa il flag URG e in cosa è diverso da PSH.
Diciamo, per esempio, che il mittente ha necessità (livello di applicazione) di inviare dei dati urgenti. Quindi crea i dati e li invia al buffer TCP (livello di trasporto):

  • Qui i dati vengono impacchettati e il bit URG viene posto a 1
  • Durante la creazione del segmento, TCP piazza i dati (urgenti) all'inizio del segmento
  • Il campo urgent data pointer indica il punto in cui terminano i dati nel segmento.
  • TCP consegna il pacchetto a livello sottostante (rete - IP)

Si noti che il segmento transita in IP normalmente, non subisce alcun trattamento speciale.
Quando il segmento giunge nel buffer TCP del mittente, inoltre TCP informa l'applicazione destinataria che è appena arrivato un segmento urgente e gli viene consegnato. Ora spetta all'applicazione ricevente agire su tali dati urgenti.
Pasted image 20230927141059.png
Il flag URG è utile quando il mittente vuole interrompere un trasferimento che è avvenuto, per esempio per errore.
Il flag PSH comunica al livello di trasporto (del destinatario) che il segmento deve essere inviato immediatamente al livello superiore (applicazione).

Campi: numero di sequenza e numero di acknowledgment
...

TCP vede i dati come un flusso di byte ordinati.
Il numero di sequenza si riferisce al primo byte nel flusso di byte del segmento.
Supponiamo che debba essere inviato un file di 500.000 byte.
Diciamo che MSS valga 1000 byte e che il primo byte nel flusso sia numerato con 0.
Per questo flusso di dati TCP creerà 500 segmenti. Il primo avrà numero di sequenza 0, il secondo 1000, il terzo 2000 e così via.
Pasted image 20230927141813.png
Per i numeri di acknowledgment, dobbiamo ricordare che TCP è full-duplex e che i dati viaggiano in entrambe le direzioni.
Il numero di ACK che l'host A, scrive nei propri segmenti è il numero di sequenza del byte successivo che l'host A attende dall'host B.
Esempio: Supponiamo che l’Host A abbia ricevuto da B tutti i byte numerati da 0 a 535 e che A stia per mandare un segmento all’Host B.
L’Host A è in attesa del byte 536 e dei successivi byte nel flusso di dati di B.
Pertanto, l’Host A scrive 536 nel campo del numero di acknowledgment del segmento che spedisce a B.
Come ulteriore esempio, supponiamo che l’Host A abbia ricevuto un segmento dall’Host B contenente i byte da 0 a 535 e un altro segmento contenente i byte da 900 a 1000.
Per qualche motivo l’Host A non ha ancora ricevuto i byte da 536 a 899.
In questo esempio, l’Host A sta ancora attendendo il byte 536 (e i successivi) per ricreare
il flusso di dati di B.
Perciò il prossimo segmento di A destinato a B conterrà 536 nel campo del numero di acknowledgment. Dato che TCP effettua l’acknowledgment solo dei byte fino al primo byte mancante nel flusso, si dice che tale protocollo offre acknowledgment cumulativi (cumulative acknowledgment).

Cosa succede se un host riceve (come in questo esempio) i pacchetti in modo disordinato

L'RFC lascia la scelta a chi implementa il protocollo:

  1. Si può decidere di far scartare i pacchetti
  2. Si può decidere di tenerli nel buffer in attesa di tutti gli altri (scelta utilizzata e più efficiente)
Timeout e stima del round trip time (RTT)
...

TCP come per rdt, usa un meccanismo di timeout e ritrasmissione per recuperare i pacchetti persi. Il timeout dovrebbe essere più grande di un RTT. Ma di quanto? E come dovrebbe essere stimato?

SampleRTT: il tempo che intercorre tra la consegna del segmento a IP e l'istante in cui arriva l'ACK relativo ad esso. Esso non viene calcolato per i pacchetti ritrasmessi e non viene calcolato per tutti i pacchetti, ma solo uno su dieci per esempio. Per ottenere una approssimazione dell'RTT, viene fatta una media di tutti gli RTT calcolati fino a quel momento.
Ad ogni nuovo SampleRTT si aggiorna la media (che TCP chiama EstimatedRTT):
Il valore raccomandato per è

Nota

EstimatedRTT è una media ponderata che attribuisce maggiore importante ai nuovi pacchetti rispetto che a quelli vecchi.
Oltre ad avere una stima di RTT, è anche importante avere una variazione: DevRTT, ovvero quanto SampleRTT si scosta da EstimatedRTT.
Il valore suggerito per è
Se i SampleRTT variano poco, DevRTT sarà piccolo, altrimenti sarà grande.
Il timeout non deve essere tanto maggiore di EstimatedRTT, altrimenti TCP non ritrasmetterebbe velocemente il segmento perduto, ma neanche troppo inferiore rispetto EstimatedRTT, altrimenti andrebbero ritrasmessi pacchetti che non dovrebbero essere ritrasmessi.
Il timeout quindi viene impostato a EstimatedRTT incrementato di un certo margine.

Viene raccomandato un valore iniziale di TimeoutInterval pari a 1 secondo. Inoltre quando si verifica un timeout, TimeoutInterval viene raddoppiato per evitare un timeout prematuro riferito ad un segmento successivo per cui si riceverà presto ACK. Tuttavia, quando viene ricevuto un segmento che permette l'aggiornamento di EstimatedRTT, TimeouInterval viene ricalcolato secondo la variabile sopra.

Trasferimento dati affidabile
...

TCP offre un trasferimento dati affidabile, sfruttando molte delle caratteristiche descritte in rdt. Avevamo accennato in rdt (che è un protocollo puramente teorico) che ogni segmento utilizza un timer, questo nella pratica sarebbe molto costoso, quindi TCP utilizza un singolo timer unico.

Descrizione del mittente TCP:

loop(forever){
	event: data received from application above
		create TCP segment with sequence number NextSeqNum
		if(time currently not working)
			start timer
		pass segment to IP protocol
		NextSeqNum = NextSeqNum + length(data)

	event: timer timeout
		retransmit not-yet-acknowledged segment with smallest
			sequence number
		start timer

	event: ACK received, with ACK field value of y
		if(y > SendBase){
			SendBase = y;
			if(there are currently not-yet-acknowledged segments)
				start timer
		}
}

Nel terzo evento (ACK received, with ACK filed value of y), avviene la ricezione di un ACK con il campo "numero di sequenza ACK" uguale a . TCP confronta con la variabile SendBase (numero di sequenza del più vecchio byte che non ha ricevuto ACK, di conseguenza SendBase - 1 è l'ultimo numero di sequenza del segmento per cui si è ricevuto ACK). TCP marca i segmenti con numero di sequenza inferiore a come ricevuti (perché TCP usa ACK cumulativi), quindi il mittente aggiorna la propria variabile SendBase. Poi se ci sono segmenti che necessitano di ACK, riavvia il timer.

Scenario: perdita di un pacchetto
...

Pasted image 20230927190616.png
L'hos A ha inviato un segmento con numero di sequenza (contenente 8 byte di dati).
L'host B lo riceve, ma l'ACK si perde.
Il timer di A scade e A ritrasmette il segmento con numero di sequenza .
B ha già ricevuto quel pacchetto, lo scarta e invia nuovamente l'ACK.

Scenario: timeout prematuro
...

Pasted image 20230927191235.png
L'host A invia i segmenti e .
L'host B invia gli ACK per quei pacchetti dopo il timeout.
Ad A scade il timer e rispedisce il segmento , poi riavvia il timer.
Il secondo pacchetto viene rispedito solo se l'ACK del secondo segmento non arriva entro il nuovo timeout.

Scenario: ACK cumulativi coprono la perdita di pacchetti avvenuta in precedenza
...

Pasted image 20230927191825.png
L'host A invia due pacchetti con numero di sequenza e .
L'host B invia gli ACK: l'ACK 100 si perde.
Prima dello scadere del timer, arriva l'ACK 120 al mittente che gli segnala che il pacchetto (con 8 byte di dati) è stato ricevuto. Quindi è come se fosse arrivato anche l'ACK 100.

Ritrasmissione rapida
...

Il periodo di timeout può rivelarsi relativamente lungo (per esempio quando un pacchetto si smarrisce ed impedisce al mittente di ritrasmettere il pacchetto subito). In molti casi il mittente può rilevare la perdita ancora prima che si verifichi il timeout grazie agli ACK duplicati relativi ad un segmento per cui è già stato ricevuto ACK dal mittente.

Tabella politica di generazione ACK.

EventoAzione del destinatario TCP
Arrivo ordinato di un segmento con un numero di sequenza atteso. Tutti i dati fino al numero di sequenza atteso sono già stati riscontrati.ACK ritardato. Attende fino a 500 millisecondi per l'arrivo ordinato di un altro segmento. Se in questo intervallo non arriva il successivo segmento, invia ACK.
Arrivo ordinato di un segmento con un numero di sequenza atteso. Un altro segmento ordinato è in attesa di trasmissione dell'ACK.Invia immediatamente un singolo ACK cumulativo, riscontrando entrambi i segmenti ordinati.
Arrivo non ordinato di segmento con numero di sequenza superiore a quello atteso. Viene rilevato un buco.Invia immediatamente un ACK duplicato, indicando il numero di sequenza del prossimo byte atteso (che è l'estremità inferiore del buco).
Arrivo di segmento che colma parzialmente o interamente il buco.Invia immediatamente un ACK, ammesso che il segmento comincia all'estremità inferiore del buco.

Se il mittente riceve tre ACKs duplicati per lo stesso dato, considera questo evento come indice che il segmento che lo segue è andato perduto. In questo caso TCP effettua una ritrasmissione rapida del pacchetto prima che scada il timer.
Pasted image 20230927192717.png
Come si vede nella figura avviene la perdita di un pacchetto.
Il pacchetto precedente e quelli successivi al pacchetto perduto arrivano a destinazione. Il destinatario invia ACK duplicati per il segmento con numero di sequenza . Il mittente capisce che il segmento è andato perso allora invia, prima dello scadere del timer, tale pacchetto.
I segmenti successivi, vengono salvati nel buffer del destinatario.

GBN o SR?
...

Ricordiamo che gli acknowledgment sono cumulativi, e che i segmenti ricevuti correttamente, ma in modo disordinato, non vengono notificati singolarmente dal destinatario, ovvero se un destinatario TCP riceve i pacchetti 1, 2, 5, salverà 5 nel buffer e solo quando riceverà 3 e 4, invierà ACK per 5. Mentre l'ACK per 2 verrà inviato subito. Quindi il mittente TCP deve memorizzare solo il numero di sequenza più basso tra i byte trasmessi che non hanno ancora ricevuto ACK (SendBase) e il numero di sequenza del successivo byte da inviare (nextseqnum). In questo contesto TCP somiglia molto a Go-Back-N. Ma ci sono delle differenze.
Esempio: supponiamo che il mittente invii una sequenza di segmenti da 1 a N che arrivano al destinatario in ordine e senza errori. Ipotizziamo che il pacchetto con numero vada perduto, ma che tutti gli altri vengono ricevuti dal mittente entro il timeout.
In questo caso GBN re-invierebbe non solo il segmento per cui è stato perso l'ACK, ma anche tutti gli altri a partire da fino a . TCP invece ritrasmetterebbe al massimo il segmento . Inoltre TCP non ritrasmetterebbe nemmeno quello se ricevesse ACK prima dello scadere del timeout.
Una modifica proposta di TCP, il cosiddetto riscontro selettivo, consente al ricevente di inviare ACK non cumulativamente, quindi pacchetti ricevuti in disordine il destinatario invia ACK non cumulativo, ma selettivo. Se combinato con la ritrasmissione selettiva (ovvero evitando la ritrasmissione dei segmenti per cui si è già ricevuto un ACK in modo selettivo da destinatario), TCP è molto simile a un generico protocollo SR. Dunque è opportuno classificare il meccanismo di ripristino degli errori di TCP come un ibrido tra SR e GBN.

Controllo del flusso
...

Gli estremi delle connessioni TCP hanno dei buffer per i segmenti in arrivo. Quando la connessione TCP riceve byte corretti e in sequenza, li posiziona nel buffer. Il processo applicativo legge i dati da questo buffer, ma non necessariamente nell'istante in cui arrivano. Il processo potrebbe ricevente potrebbe leggere i dati solo molto tempo dopo il loro arrivo. Nel caso in cui il processo ricevente è relativamente lento ad eseguire altre operazioni, il mittente potrebbe inviare più pacchetti di quanto il buffer ricevente venga svuotato dal processo ricevente. TCP offre un controllo del flusso alle applicazioni per evitare che il mittente saturi il buffer del ricevente.
Il controllo del flusso è un servizio di confronto sulla velocità, dato che paragona la frequenza di invio del mittente con quella di lettura dell'applicazione ricevente.
Il controllo della congestione riguarda invece la rete IP (livello di rete), che vedremo successivamente.

Parliamo del controllo del flusso e, per il momento, supponiamo che il ricevente TCP scarti i segmenti non in ordine. TCP mantiene una variabile chiamata finestra di ricezione (receive window) che fornisce al mittente un'indicazione sullo spazio libero nel buffer del ricevente.
Supponiamo che l'host A voglia inviare un file di grandi dimensioni all'host B tramite una connessione TCP. L'host B alloca un buffer, la cui dimensione è rcvBuffer. Definiamo le seguenti variabili:

  • lastByteRead: numero dell'ultimo byte nel flusso di dati che il processo applicativo in B ha letto dal buffer.
  • lastByteRcvd: numero dell'ultimo byte nel flusso di dati che proviene dalla rete e che è stato copiato nel buffer di ricezione di B.
    Dato che TCP non deve mandare in overflow il buffer ricevente dovremo avere per forza: La finestra di ricezione (rwnd) viene impostata alla quantità di spazio disponibile nel buffer:rwnd è dinamica, dato che lo spazio varia col tempo. B comunica ad A quanto spazio disponibile è presente nel buffer della connessione, scrivendo il valore corrente di rwnd nel campo apposito dei segmenti che manda ad A.
    B inizializza rwnd con il valore di rcvBuffer e deve tenere traccia delle variabili specifiche per ogni connessione.
    A sua volta il mittente tiene traccia di due varaibili: lastByteSent e lastByteAcked.
    A si assicura che sia rispettata la seguente disuguaglianza:
    Pasted image 20230927195448.png
    Pasted image 20231217204917.png
    La finestra di ricezione TCP viene calcolata in questo modo.
    La dimensione della finestra di ricezione viene stabilita in base a come il destinatario preleva i pacchetti dal buffer. Il mittente sa solo che non può inviare più di pacchetti senza ACK.

In questo schema esiste un problema tecnico secondario, per accorgercene supponiamo che il buffer di ricezione dell'host B sia pieno, quindi rwnd = 0 e che dopo averlo notificato all'host A, non abbia più nulla da inviare ad A e vediamo cosa succede.
Quando B svuoterà il buffer, TCP non invia nuovi segmenti con il valore aggiornato di rwnd (che si è svuotato). TCP fa pervenire segmenti ad A solo se B ha dati o ACK da mandare ad A. Di conseguenza l'host A non viene informato del fatto che sul buffer di B si è liberato dello spazio. A è bloccato e non invia dati. Per questo motivo le specifiche TCP impongono che il mittente continui ad inviare pacchetti al destinatario per dargli modo di rispondere. Prima o poi rwnd non sarà più nullo e B dovrà avere modo di farlo sapere ad A.
UDP non offre controllo del flusso, nel caso di UDP, semplicemente alcuni pacchetti andranno persi a causa di overflow nel buffer del destinatario.

Gestione della connessione (3-way-hanshake)
...

Quando un processo client chiede ad un processo server di stabilire una connessione TCP, la connessione avviene attraverso i seguenti passi:

  1. TCP lato cliente invia un pacchetto speciale al TCP lato server, questo segmento non contiene dati, ma il bit SYN è posto a 1. Per questo tale segmento viene detto segmento di SYN. Inoltre il client genera casualmente un numero di sequenza iniziale (client_isn) e lo pone nel campo numero di sequenza. Questo viene fatto al fine di evitare attacchi alla sicurezza.
  2. Quando il segmento di SYN arriva al server, alloca buffer e varaibili TCP e invia un segmento di connessione approvata al client. Anche questo non contiene dati. SYN è posto a 1. Il campo ACK assume valore client_isn + 1 e genera un numero di sequenza iniziale server_isn e lo comunica al client. Tale segmento viene detto di SYNACK.
  3. Alla ricezione del segmento di SYNACK anche il client alloca buffer e variabili. Il client invia un altro segmento ponendo il valore server_isn + 1 nel campo ACK. SYN è posto a 0. Il campo dati può contenere dati.
    Pasted image 20230927200445.png
    Se si vuole chiudere la connessione, l'host che vuole effettuare la chiusura invia un comando di terminazione che forza TCP ad inviare un pacchetto speciale.
    Il bit FIN sarà posto a 1. Quando l'host riceve questo segmento invia un ACK e risponde con un segmento con bit FIN a 1. L'altro host risponde con un ACK e tutte le risorse vengono deallocate sui sistemi periferici.
    Pasted image 20230927200556.png
    Inviato l'ultimo ACK il server temporizza per l'ultima volta il segmento inviato, così da poterlo rispedire nel caso in cui vada smarrito.
    Nel corso di una connessione TCP i protocolli TCP in esecuzione sugli host passano per vari stati.
Stati lato client
...

Pasted image 20230927200652.png

Stati lato server
...

Pasted image 20230927200729.png

Se un client invia una connessione su una porta su cui il server non è in ascolto il server restituisce un segmento speciale con bit RST.
nmap, un tool per analizzare le porte in ascolto su un host, come funziona? Invia segmenti TCP SYN, i possibili risultati sono tre:

  1. Il server risponde con TCP SYNACK: porta aperta, nmap restituisce "open"
  2. Il server risponde RST: porta non aperta, ma non difesa da nessun firewall
  3. Il server non risponde: c'è un firewall
Attacco SYN flooding

Letteralmente inondazione di SYN.
Abbiamo visto come funzione l'handshake. Se l'ultimo segmento non viene inviato dal client, dopo un certo periodo di tempo (1 minuto circa), la connessione viene chiusa dal server.
Questo pone le basi per un attacco SYN FLOOD di tipo DoS. Chi attacca manda un gran numero di segmenti di SYN senza completare il terzo passo della procedura di handshake. Se partecipano più host l'attacco diventa di tipo distribuito (DDoS).

Una contromisura efficace è il SYN cookie.

  • Quando il server riceve un segmento di SYN non sa se chi lo ha inviato ha cattive intenzioni. Quindi non crea una connessione TCP mezza aperta, ma crea un numero di sequenza TCP iniziale come come funzione hash dell'IP e della porta sorgente e destinazione del segmento di SYN e una chiave segreta nota solo al server. Il server usa la stessa chiave per un ampio numero di connessioni. Il cookie è il numero di sequenza generato. Il server invia un SYNACK con questo numero di sequenza iniziale. (Il server non memorizza il cookie o qualsiasi altra informazione di stato corrispondente al SYN).
  • Se il client è legittimo, risponde con un segmento di ACK. Il server, alla ricezione di esso, ha necessità di verificare se corrisponde allo stesso SYN inviato precedentemente. Come fa il server se non ha memoria sui segmenti di SYN? Come potete immaginare, viene fatto con il cookie. In particolare, per un ACK legittimo, il valore del campo di ACK è uguale al numero di sequenza SYNACK (il valore del cookie) più uno. Il server eseguirà poi la stessa funzione hash sopracitata usando i campi del segmento SYNACK (che erano poi gli stessi del SYN originale) e la chiave segreta. Se il risultato della funzione più uno è lo stesso del campo di ACK, il server conclude che l'ACK corrisponde al precedente segmento SYN e quindi è valido. Il server crea quindi una connessione TCP completamente aperta e una socket.
  • Viceversa, se il client non risponde con un segmento di ACK, allora il SYN originale non ha fatto danni, in quanto non era state allocate risorse.
Principi del controllo della congestione
...

Vediamo tre scenari via via più complessi. Non presenteremo subito una soluzione alla congestione, ma cercheremo di capire cosa succede quando gli host aumentano il loro tasso trasmissivo e le reti si congestionano.

Potrebbe essere necessario ripassare e avere ben chiaro cosa sono il tasso di invio del mittente, il tasso di invio del destinatario e il throughput per comprendere bene ciò che segue
  • Tasso di invio del mittente: si tratta della velocità con cui il mittente genera e invia dati nella rete. Questo tasso di invio è controllato dall'applicazione o dal livello di trasporto sul mittente e rappresenta la quantità di dati che il mittente è in grado di immettere nella rete in un certo periodo di tempo. Ad esempio un'applicazione può inviare dati ad una velocità di 1000 byte al secondo.
  • Tasso di invio del ricevente: si tratta della velocità con cui il destinatario è in grado di ricevere e processare i dati provenienti dalla rete.
  • Throughput: si tratta della misura effettiva della velocità di trasferimento dei dati tra il mittente e il destinatario attraverso la rete.
Scenario 1: due mittenti e un router con buffer limitati
...

Pasted image 20230927202428.png
è la frequenza con cui i mittenti inviano dati al livello di trasporto (con una socket), ovvero la velocità di trasmissione.
Il router condiviso ha buffer illimitato.
Il collegamento uscente (verso la i server sulla destra) sul router ha capacità .
Il buffer del router ha una capacità (illimitata) tale da consentirgli di memorizzare i segmenti con la velocità con cui arrivano nel router, anche quando la velocità sul collegamento entrante supera quella uscente.
Pasted image 20230927202721.png
Queste immagini mostrano le prestazioni della connessione per uno dei due host.
In questo primo scenario vengono illustrate le prestazioni per l'host A.
L'immagine di sinistra mostra il throughput per connessione (la velocità con cui ricevono i destinatari) in funzione del tasso di invio. Vediamo che al crescere del tasso di invio, cresce anche il tasso di ricezione.
Essendoci due mittenti, la capacità del collegamento è divisa tra di essi (per ciascun mittente).
Finché il tasso di invio non supera il valore di , il throughput del ricevente equivale alla velocità di invio del mittente: tutto ciò che viene trasmesso dal mittente viene ricevuto dal destinatario con un ritardo finito.
Ma se il tasso di invio supera , il throughput resta .
Il collegamento, semplicemente, non è in grado di consegnare pacchetti al destinatario a un tasso superiore a .
Per quanto elevata sia la velocità di invio da parte degli host, né A né B avranno mai un throughput superiore a . Poiché effettivamente i pacchetti vengono inoltrati con velocità .

Il grafico a destra, mostra le conseguenze di operare al limite della capacità del collegamento.
Quando la velocità di invio si avvicina a (da sinistra), il ritardo medio cresce sempre di più.
Quando supera , il numero medio di pacchetti in coda nel router cresce senza limiti e il ritardo medio tra origine e destinazione tende all'infinito (nell'ipotesi che le connessioni mantengano questa velocità di invio per un periodo di tempo infinito e che la capacità del buffer sia infinita).
Di conseguenza, avere un throughput aggregato vicino a potrebbe sembrare ideale dal punto di visita del throughput, ma non lo è certo dal punto di vista del ritardo. Perfino in questo scenario estremamente idealizzato abbiamo già trovato un costo dovuto alla congestione delle reti: quando il tasso di arrivo dei pacchetti si avvicina alla capacità del collegamento, si rilevano lunghi ritardi di accodamento.

Scenario 2: due mittenti con buffer limitato
...

Pasted image 20230928111457.png
è la frequenza con cui i mittenti inviano dati al livello di trasporto (con una socket), ovvero la velocità di trasmissione.
è il tasso al quale il livello di trasporto invia i segmenti originali più quelli ritrasmessi (detto offered load).
Il router condiviso ha buffer limitato: i segmenti che arrivano quando il buffer è pieno vengono scartati.
Adesso il buffer è limitato. I pacchetti che arrivano quando il buffer è pieno vengono scartati. Si suppone che il livello di trasporto sia affidabile, ovvero che i pacchetti scartati vengano prima o poi ritrasmessi. Le prestazioni dipendono da come vengono effettuate le ritrasmissioni. Distinguiamo dei casi:

  • Il mittente è in grado, per assurdo, di sapere quando il buffer del router è pieno, e quindi invia pacchetti solo quando c'è spazio nel buffer del router. In questo caso non si verificano perdite avremmo che perché essenzialmente non vengono rispediti altri dati. Visto che non viene perso nessun pacchetto e non vi sono ritrasmissioni la velocità di invio media dell'host non supera (grafico (a)).
  • Caso un po' più realistico: il mittente rispedisce un pacchetto solo quando è certo che esso sia andato perduto (grafico (b)). Consideriamo il caso in cui il carico offerto alla rete (offered load) valga . Questo vuol dire che ci sono dei dati ritrasmessi e dei dati nuovi. Il tasso con cui i dati vengono consegnati all'applicazione destinataria è : sono dati originali più dati ritrasmessi, di questi diciamo che sono ritrasmessi e gli altri sono originali. Abbiamo rilevato un costo della congestione: il mittente deve ritrasmettere i pacchetti scartati a causa di overflow nei buffer.
  • Caso ancora più realistico: il mittente può effettuare timeout prematuramente e rispedire un pacchetto che ha subito ritardo in coda, ma che non è andato perduto. In questo caso, il ricevente può ricevere entrambe le copie del segmento, ma ne avrà bisogno solo di una, una parte del lavoro del mittente quindi è sprecata. Ed ecco un ulteriore costo: ritrasmissioni non necessarie. Considerando in media che un pacchetto viene instradato mediamente due volte dal router, il throughput assumerà asintoticamente valore quando il carico offerto si avvicina a (grafico (c)).

Pasted image 20230928112239.png
Grafico (a)
Pasted image 20230928112305.png
Grafico (b)
Pasted image 20230928112444.png
Grafico (c)

Scenario 3: quattro mittenti, router con buffer limitati e percorsi composti da più collegamenti
...

Pasted image 20230928123136.png
In questo caso supponiamo che i pacchetti siano trasmessi da 4 host, ciascuno su percorsi composti da due collegamenti sovrapposti tra loro. Ciascun host, inoltre, utilizza un meccanismo di timeout e ritrasmissione per implementare il servizio di trasporto affidabile.
Tutti e quattro hanno lo stesso valore di .
La capacità dei collegamenti dei router è bps.
Consideriamo la connessione dall'host A all'host C che passa per i router e .
Il router condivide la connessione D-B (linea verde).
Il router condivide la connessione B-D (linea rossa).
Per valori estremamente piccoli di , gli overflow dei buffer sono rari (come gli scenari 1 e 2).
Per valori leggermente più grandi, il throughput è anch'esso più grande, gli overflow rimangono ancora rari. Di conseguenza per piccoli valori di , un incremento di , provoca l'aumento di .

Esaminata la situazione in cui il traffico è estremamente scarso, passiamo a considerare il caso in cui (e quindi ) sia molto grande.
Prendiamo in considerazione.
Il traffico (da A a C, linea azzurra) che giunge a , dopo essere stato inoltrato da , non può presentare un tasso di arrivo maggiore di (che è la capacità del collegamento da a e anche di tutti gli altri) a prescindere dal valore di .
Se è estremamente grande per tutte le connessioni (B-D inclusa), il tasso di arrivo del traffico B-D su può essere molto più elevato di quello del traffico A-C.
Dato che su il traffico da A a C e quello da B a D sono in competizione per il limitato spazio dei buffer, la quantità di traffico A-C che passa con successo attraverso R2 (ossia, che non viene persa a causa dell'overflow) diventa sempre più piccola al crescere del traffico trasportato da B-D. Quando questo tende all'infinito, un buffer vuoto in viene colmato da un pacchetto B-D, e il throughput della connessione A-C in si annulla. Il traffico end-to-end di A-C si annulla in caso di traffico pesante.
Praticamente ogni volta che un pacchetto nel secondo hop (salto, router) viene scartato, il lavoro fatto dal primo router per inviare quel pacchetto viene sprecato. Di fatti la rete avrebbe funzionato allo stesso modo, se il primo router non avesse spedito quel pacchetto che il secondo avrebbe rifiutato. La capacità trasmissiva sprecata potrebbe essere utilizzata in modo più proficuo. Sarebbe utile per esempio che il router desse priorità ai pacchetti che hanno già superato un certo numero di router.

Approcci al controllo della congestione
...

Identifichiamo i principali orientamenti al controllo della congestione:

  • Controllo di congestione end-to-end: il livello sottostante non ritorna nessun feedback riguardo il livello di congestione, quindi il controllo della congestione deve avvenire agli estremi della rete, nei sistemi periferici. La perdita dei pacchetti (indicata dal timeout o ACK triplicati) è una indicazione di congestione della rete. TCP agisce diminuendo l’ampiezza della propria finestra.
  • Controllo di congestione assistito dalla rete: i componenti della rete forniscono feedback riguardo la congestione della rete. Viene inviato un pacchetto chockepacket che informa, direttamente, il mittente di essere congestionato oppure il router congestionato invia un pacchetto diretto al destinatario in cui viene aggiunto un campo che indica la congestione, il ricevente poi comunicherà al mittente la congestione. Le versioni standard di TCP e IP adottano l'approccio end-to-end, ma possono implementare anche il controllo di congestione assistito.

Navigazione: