Segmento TCP, Trasporto
Appunti della lezione in presenza del 22/11/22;
Sequence number: identificativo del segmento all'interno del flusso che si sta inviando/ricevendo;
Ack number: serve per comunicare quali segmenti sono stati ricevuti correttamente. E' strettamente legato al sequence number, è leggermente diverso; Viene inserito anche questo campo perchè i messaggi di conferma possono anch'essi inviare dati normalmente. E' un modo per diminuire il numero di pacchetti inviati.
Hlen: indica la dimensione dell'header TCP, che può essere variabile. Infatti alla fine dell'header possono essere aggiunti dei campi aggiuntivi. Hlen ragiona in multipli di 4 byte: infatti dopo TCP options si applica un padding per rendere il tutto un multiplo di 32 bit.
Code bit: Bitmask di 6 bit, ognuno ha un ruolo diverso.
URG: campo poco utilizzato, servirebbe a comunicare la presenza di dati urgenti. (Ci sono dati più importanti di altri tra quelli che si stanno inviando). Ora è utilizzato poco.
ACK: se == 1, indica che questo è il pacchetto di acknowledgment.
PSH: bit che viene usato per inviare i dati senza passare per il buffer. Usato dall'applicazione mittente quando si vuole svuotare il buffer immediatamente. Esempio: invio di un file pacchettizzato a livello TCP. L'ultimo pacchetto avrà il bit push attivato, richiedendo lo svuotamento del buffer e l'invio dei dati, dato che non ne arriveranno altri. Può essere utile (ad esempio) quando si vuole usare TCP per implementare delle applicazioni real-time, anche se di base non è consigliato perchè TCP è un protocollo asincrono.
SYN, FIN, RST: bit che sono a 1 solo in fasi di apertura/ chiusura della connessione. Syn è il bit di sincronizzazione, è settato a 1 nei pacchetti mandati durante la fase di apertura della connessione, mentre FIN e RST sono a 1 in fase di chiusura. Essi rappresentano due diversi modi (polite e non polite) di chiudere una connessione. Si vedranno approfondimenti successivamente.
Window size:destinatario e mittente si informano su quanti dati possono ancora essere immagazzinati all'interno del buffer. Magari il mittente rallenta il flusso dati sapendo che il destinatario ha poco spazio nel buffer.
Urgent Pointer: in teoria serve per specificare quali sono i dati urgenti ma è una funzionalità usata molto raramente.
TCP Options: comunica qual'è la dimensione massima in cui segmentare il flusso, ossia l'MSS (ci si torna successivamente);
L'MSS è l'informazione specificata dal TCP Pointer. Se non è specificata, allora si usa 536 byte. Ovviamente si punta ad avere l'MSS massima possibile (inviare pacchetti più grandi significa inviare meno pacchetti, quindi migliorare le performance) ma si cerca anche di rimanere in un "range" tale per cui non si debba applicare la frammentazione a livello H2N. (Infatti bisogna "rientrare" nell'MTU).
I sequence number idealmente sono da 0 a \(2^{32}-1\), in realtà viene aggiunto un offset iniziale, per una ragione di sicurezza. Ovviamente se si finiscono i sequence number per una determinata connessione, si riparte da 0, ovviamente con l'offset aggiunto.
👉 si supponga di dover trasferire un file di 500kByte, con MSS = 1000byte. I sequence number saranno \(X\), \(X+1000\), \(X+2000\),... dove \(X\) indica l'ISN, ossia l'offset iniziale.
Sequence number che identifica il prossimo byte che l'host A (sender) si aspetta di ricevere da B(receiver). Serve ad indicare la corretta ricezione del pacchetto precedente.
Solo in questa fase vengono distinti i ruoli client/server.
I pacchetti in questione hanno ovviamente il campo SYN == 1, ossia i pacchetti riservati all'apertura della connessione.
Ovviamente ci interessa soltanto la porta destinataria, su cui il server dev'essere in ascolto. Le informazioni relative all'indirizzo IP verranno gestite dal livello 3. Il client comunica l'offset di partenza della sequenza, definendo l'ISN (Initial Sequence Number). Questo valore viene scelto "casualmente", per ragioni appunto di sicurezza. Serve per contare i dati che dal client vanno verso il server, quando il server deve rispondere comunicherà un'altro ISN.
Il segmento SYN del client contiene anche:
la MRW (maximum receive window): il client comunica al server quanto è grande il suo buffer. E' utile perchè TCP è pensato per funzionare su architetture eterogenee.
MSS, ossia la massima dimensione del segmento. E' una proposta da parte del client, che può essere ritrattata in futuro. Infatti i due host potrebbero essere dispositivi molto diversi tra loro, aventi caratteristiche hardware e necessità diverse.
ASSENZA del payload: questi pacchetti non trasportano altri dati.
Il server risponde con un pacchetto SYN, a sua volta. Questo pacchetto ha anche il bit di ack == 1, dato che si conferma l'apertura della connessione. Il pacchetto prende quindi comunemente il nome di SYN/ACK \(\Downarrow\)
risposta \(\Downarrow\)
Verrà trattato in futuro. In generale è utile ricordarsi del meccanismo di PiggyBacking, cioè l'inserimento dell'informazione di ack all'interno di pacchetti che trasportano anche dati utili. E' un'ottimizzazione usata per inviare meno pacchetti, quindi per migliorare la connessione.
Modalità di chiusura con affidabilità, usata quando non si ha urgenza di chiudere la connessione.
Chi decide di chiudere la connessione invia un pacchetto con FIN settato a 1.
Chi riceve questo pacchetto, risponde confermando semplicemente la ricezione del FIN. Quando l'applicazione è pronta per essere chiusa, invia a sua volta un pacchetto con FIN settato a 1.
Il sender iniziale riceve un FIN, e invia a sua volta un ACK, confermando il FIN precedente. Vengono effetuati degli "sleep" per assicurare la chiusura corretta dei servizi.
Il client considera "chiusa" la connessione soltanto dopo un timeout finale. Questa "attesa" è dovuta al fatto che potrebbero essere in circolazione ancora dei pacchetti legati ad altre comunicazioni. Si riescono quindi a gestire anche situazioni "anomale".
Protocollo di chiusura best-effort per chiudere la connessione velocemente, che si basa sull'invio di pacchetti/segnali RST. Potrebbe essere usato (ad esempio) da un web-server se nota che un client inizia a mandare dei pacchetti che non seguono il protocollo TCP, ossia dei pacchetti "anomali".
Se il mittente di un pacchetto non riceve l'acknowledgment da parte del destinatario dopo un certo timeout, li prova a ri-inviare.
Come si fa a "stimare" il timeout?
👉 ovviamente dipende dalla rete: in una rete locale potrebbe essere più basso rispetto alla rete globale. Ovviamente essendo TCP un protocollo adattativo e general purpose, il timeout deve essere calcolato e stimato.
RTT (round trip time): tempo osservabile tra l'invio di un pacchetto e la ricezione dell'ack. E' un calcolo basato soltanto sulla vista del mittente. In generale l'idea è che il timeout finale deve essere maggiore dell'RTT minimo osservato nella comunicazione.
Si usa il doppio della media rispetto agli ultimi \(n\) round trip time. E' il metodo più semplice, non richede la stima del round trip time.
In alternativa, si può stimare il prossimo round trip time, per poi calcolare il timeout. I due passi sono i seguenti:
EstimatedRTT: è un calcolo "on the fly" in cui si da molto peso all'ultimo RTT osservato, quelli precedenti vengono man-mano assorbiti. Infatti quelli più "vecchi" hanno meno valenza: il loro peso cala esponenzialmente. E' essenzialmente una media calcolata "in movimento", dove:
\(E_{rtt}(t)\) \(\rightarrow\) Round Trip Time stimato al tempo t;
\(S_{rtt}(t)\) \(\rightarrow\) Round Trip Time osservato al tempo t;
Calcolo del timeout. Le formule dei passaggi sono le seguenti: \(\Downarrow\)
Dove \(x\) è un valore compreso tra 0 e 1. Tipicamente inizialmente si sceglie \(\frac{1}{n+1}\) dove \(n\) è il numero di campioni di RTT usati per il calcolo.
Esperimenti mostrano che la formula è molto resistente agli outlier.