L'arma segreta di TCP: il controllo del flusso di rete e il controllo della congestione di rete.

Trasporto di affidabilità TCP
Tutti conosciamo il protocollo TCP come protocollo di trasporto affidabile, ma come garantisce l'affidabilità del trasporto?

Per ottenere una trasmissione affidabile, è necessario considerare molti fattori, come la corruzione, la perdita, la duplicazione dei dati e la presenza di frammenti non in ordine. Se questi problemi non possono essere risolti, non è possibile ottenere una trasmissione affidabile.

Pertanto, TCP impiega meccanismi quali il numero di sequenza, la risposta di conferma, il controllo di reinvio, la gestione della connessione e il controllo della finestra per garantire una trasmissione affidabile.

In questo articolo, ci concentreremo sulla finestra scorrevole, sul controllo di flusso e sul controllo della congestione del protocollo TCP. Il meccanismo di ritrasmissione verrà trattato separatamente nella sezione successiva.

Controllo del flusso di rete
Il controllo del flusso di rete, noto anche come controllo del traffico di rete, è in realtà una manifestazione della complessa relazione tra produttori e consumatori. Probabilmente vi sarete imbattuti spesso in questo scenario sul lavoro o durante i colloqui. Se la capacità di produzione di un produttore supera di gran lunga la capacità di consumo di un consumatore, la coda crescerà all'infinito. In un caso più grave, saprete che quando i messaggi di RabbitMQ si accumulano eccessivamente, si può verificare un degrado delle prestazioni dell'intero server MQ. Lo stesso vale per il protocollo TCP: se non controllato, troppi messaggi verranno immessi nella rete, i consumatori supereranno la loro capacità e i produttori continueranno a inviare messaggi duplicati, con conseguente grave impatto sulle prestazioni della rete.

Per ovviare a questo problema, il protocollo TCP fornisce un meccanismo che permette al mittente di controllare la quantità di dati inviati in base alla capacità di ricezione effettiva del destinatario, meccanismo noto come controllo di flusso. Il destinatario mantiene una finestra di ricezione, mentre il mittente mantiene una finestra di invio. È importante notare che queste finestre sono valide solo per una singola connessione TCP e non tutte le connessioni condividono la stessa finestra.

Il protocollo TCP gestisce il controllo di flusso utilizzando una variabile per la finestra di ricezione. La finestra di ricezione fornisce al mittente un'indicazione della quantità di spazio di cache ancora disponibile. Il mittente controlla la quantità di dati inviati in base alla capacità di accettazione effettiva del destinatario.

L'host ricevente comunica al mittente la dimensione dei dati che può ricevere, e il mittente invia dati fino a tale limite. Questo limite è la dimensione della finestra, ricordate l'intestazione TCP? Esiste un campo per la finestra di ricezione, utilizzato per indicare il numero di byte che il ricevitore è in grado o disposto a ricevere.

L'host mittente invierà periodicamente un pacchetto di verifica della finestra, utilizzato per rilevare se l'host ricevente è ancora in grado di accettare dati. Quando il buffer del ricevente rischia di saturarsi, la dimensione della finestra viene impostata su un valore inferiore per indicare al mittente di controllare la quantità di dati inviati.

Ecco un diagramma di controllo del flusso di rete:

Controllo del traffico

Controllo della congestione di rete
Prima di introdurre il controllo della congestione, è necessario comprendere che, oltre alla finestra di ricezione e alla finestra di invio, esiste anche una finestra di congestione, utilizzata principalmente per risolvere il problema della velocità con cui il mittente inizia a inviare dati alla finestra di ricezione. Pertanto, anche la finestra di congestione viene gestita dal mittente TCP. È necessario un algoritmo per decidere la quantità appropriata di dati da inviare, poiché inviare troppi o troppo pochi dati non è ottimale; da qui il concetto di finestra di congestione.

Nel precedente controllo di flusso di rete, ciò che abbiamo evitato era che il mittente riempisse la cache del destinatario con dati, ma non sapevamo cosa stesse succedendo nella rete. Tipicamente, le reti di computer si trovano in un ambiente condiviso. Di conseguenza, può verificarsi una congestione di rete dovuta alla comunicazione tra host diversi.

Quando la rete è congestionata, l'invio continuo di un gran numero di pacchetti può causare problemi come ritardi e perdita di pacchetti. In questo caso, il protocollo TCP ritrasmette i dati, ma la ritrasmissione aumenta il carico sulla rete, provocando ritardi maggiori e ulteriori perdite di pacchetti. Questo può innescare un circolo vizioso che si aggrava progressivamente.

Pertanto, TCP non può ignorare ciò che accade sulla rete. Quando la rete è congestionata, TCP si sacrifica riducendo la quantità di dati che invia.

Pertanto, viene proposto il controllo della congestione, che mira a evitare di saturare l'intera rete con i dati del mittente. Per regolare la quantità di dati che il mittente deve inviare, TCP definisce un concetto chiamato finestra di congestione. L'algoritmo di controllo della congestione regola la dimensione della finestra di congestione in base al grado di congestione della rete, in modo da controllare la quantità di dati inviati dal mittente.

Che cos'è una finestra di congestione? Che relazione ha con la finestra di invio?

La finestra di congestione è una variabile di stato gestita dal mittente che determina la quantità di dati che quest'ultimo può inviare. La finestra di congestione cambia dinamicamente in base al livello di congestione della rete.

La finestra di invio è una dimensione concordata tra mittente e destinatario che indica la quantità di dati che il destinatario può ricevere. La finestra di congestione e la finestra di invio sono correlate; la finestra di invio è solitamente uguale al minimo tra la finestra di congestione e la finestra di ricezione, ovvero swnd = min(cwnd, rwnd).

La finestra di congestione cwnd cambia come segue:

Se non si verifica congestione nella rete, ovvero non si verifica alcun timeout di ritrasmissione, la finestra di congestione aumenta.

In caso di congestione nella rete, la finestra di congestione si riduce.

Il mittente determina se la rete è congestionata verificando se il pacchetto di conferma ACK viene ricevuto entro il tempo specificato. Se il mittente non riceve il pacchetto di conferma ACK entro il tempo specificato, si considera che la rete sia congestionata.

Oltre alla finestra di congestione, è giunto il momento di parlare dell'algoritmo di controllo della congestione TCP. L'algoritmo di controllo della congestione TCP è composto da tre parti principali:

Partenza lenta:Inizialmente, la finestra di congestione cwnd è relativamente piccola e il mittente aumenta esponenzialmente la finestra di congestione per adattarsi rapidamente alla capacità della rete.
Prevenzione della congestione:Dopo che la finestra di congestione supera una certa soglia, il mittente aumenta la finestra di congestione in modo lineare per rallentare il tasso di crescita della finestra di congestione ed evitare di sovraccaricare la rete.
Recupero rapido:In caso di congestione, il mittente dimezza la finestra di congestione ed entra nello stato di ripristino rapido per determinare la posizione del ripristino della rete tramite gli ack duplicati ricevuti, dopodiché continua ad aumentare la finestra di congestione.

Partenza lenta
Quando viene stabilita una connessione TCP, la finestra di congestione cwnd viene inizialmente impostata su un valore minimo MSS (dimensione massima del segmento). In questo modo, la velocità di trasmissione iniziale è di circa MSS/RTT byte/secondo. La larghezza di banda effettivamente disponibile è solitamente molto maggiore di MSS/RTT, quindi TCP cerca di trovare la velocità di trasmissione ottimale, che può essere raggiunta tramite la tecnica dello slow-start.

Nella fase di avvio lento, il valore della finestra di congestione cwnd viene inizializzato a 1 MSS e, ogni volta che il segmento di pacchetto trasmesso viene confermato, il valore di cwnd viene incrementato di un MSS, ovvero diventa 2 MSS. Successivamente, il valore di cwnd raddoppia per ogni trasmissione riuscita di un segmento di pacchetto, e così via. Il processo di crescita specifico è illustrato nella figura seguente.

 controllo della congestione di rete

Tuttavia, la velocità di invio non può crescere all'infinito; la crescita deve pur finire prima o poi. Quindi, quando termina l'aumento della velocità di invio? La strategia slow-start in genere pone fine all'aumento della velocità di invio in uno dei seguenti modi:

Il primo caso riguarda la perdita di pacchetti durante la fase di slow start. Quando si verifica una perdita di pacchetti, TCP imposta la finestra di congestione del mittente cwnd a 1 e riavvia il processo di slow start. A questo punto, viene introdotto il concetto di soglia di slow start ssthresh, il cui valore iniziale è pari alla metà del valore di cwnd che ha generato la perdita di pacchetti. Ovvero, quando viene rilevata congestione, il valore di ssthresh è pari alla metà del valore della finestra.

Il secondo metodo consiste nel correlare direttamente il valore con la soglia di slow-start ssthresh. Poiché il valore di ssthresh è pari alla metà del valore della finestra quando viene rilevata la congestione, la perdita di pacchetti può verificarsi ad ogni raddoppio quando cwnd è maggiore di ssthresh. Pertanto, è consigliabile impostare cwnd su ssthresh, il che farà sì che TCP passi alla modalità di controllo della congestione e termini lo slow-start.

L'ultimo modo in cui lo slow start può terminare è se vengono rilevati tre ACK ridondanti: in tal caso, TCP esegue una ritrasmissione rapida ed entra nello stato di ripristino. (Se non è chiaro il motivo per cui vengono inviati tre pacchetti ACK, questo verrà spiegato separatamente nella sezione relativa al meccanismo di ritrasmissione.)

Evitare la congestione
Quando TCP entra nello stato di controllo della congestione, cwnd viene impostato a metà della soglia di congestione ssthresh. Ciò significa che il valore di cwnd non può essere raddoppiato ogni volta che viene ricevuto un segmento di pacchetto. Viene invece adottato un approccio relativamente conservativo in cui il valore di cwnd viene incrementato di un solo MSS (lunghezza massima del segmento di pacchetto) dopo il completamento di ogni trasmissione. Ad esempio, anche se vengono confermati 10 segmenti di pacchetto, il valore di cwnd aumenterà solo di un MSS. Questo è un modello di crescita lineare e ha anche un limite superiore alla crescita. Quando si verifica una perdita di pacchetti, il valore di cwnd viene modificato a un MSS e il valore di ssthresh viene impostato a metà di cwnd. Oppure, la crescita di MSS si arresta anche quando vengono ricevute 3 risposte ACK ridondanti. Se vengono ancora ricevute tre risposte ACK ridondanti dopo aver dimezzato il valore di cwnd, il valore di ssthresh viene registrato come metà del valore di cwnd e si entra nello stato di ripristino rapido.

Recupero rapido
Nello stato di ripristino rapido, il valore della finestra di congestione cwnd viene incrementato di un MSS per ogni ACK ridondante ricevuto, ovvero un ACK che non arriva in sequenza. Questo per sfruttare al meglio i segmenti di pacchetto che sono stati trasmessi correttamente nella rete e migliorare il più possibile l'efficienza della trasmissione.

Quando arriva un ACK del segmento di pacchetto perso, TCP decrementa il valore di cwnd e quindi entra nello stato di prevenzione della congestione. Questo serve a controllare la dimensione della finestra di congestione ed evitare un ulteriore aumento della congestione della rete.

Se si verifica un timeout dopo lo stato di controllo della congestione, le condizioni della rete peggiorano e TCP passa dallo stato di prevenzione della congestione allo stato di avvio lento. In questo caso, il valore della finestra di congestione cwnd viene impostato a 1 MSS, la lunghezza massima del segmento di pacchetto, e il valore della soglia di avvio lento ssthresh viene impostato alla metà di cwnd. Lo scopo è quello di aumentare gradualmente la dimensione della finestra di congestione dopo il ripristino della rete, in modo da bilanciare la velocità di trasmissione e il grado di congestione della rete.

Riepilogo
Come protocollo di trasporto affidabile, TCP implementa il trasporto affidabile tramite numero di sequenza, riconoscimento, controllo della ritrasmissione, gestione della connessione e controllo della finestra. Tra questi, il meccanismo di controllo del flusso regola la quantità di dati inviati dal mittente in base alla capacità di ricezione effettiva del destinatario, evitando così problemi di congestione della rete e degrado delle prestazioni. Il meccanismo di controllo della congestione evita il verificarsi di congestione della rete regolando la quantità di dati inviati dal mittente. I concetti di finestra di congestione e finestra di invio sono correlati e la quantità di dati inviati dal mittente viene controllata regolando dinamicamente la dimensione della finestra di congestione. Avvio lento, prevenzione della congestione e ripristino rapido sono le tre componenti principali dell'algoritmo di controllo della congestione TCP, che regolano la dimensione della finestra di congestione attraverso diverse strategie per adattarsi alla capacità e al grado di congestione della rete.

Nella prossima sezione esamineremo in dettaglio il meccanismo di ritrasmissione del TCP. Il meccanismo di ritrasmissione è una parte importante del TCP per garantire una trasmissione affidabile. Assicura la trasmissione affidabile dei dati ritrasmettendo i dati persi, corrotti o ritardati. Il principio di implementazione e la strategia del meccanismo di ritrasmissione saranno introdotti e analizzati in dettaglio nella prossima sezione. Continuate a seguirci!


Data di pubblicazione: 24 febbraio 2025