Manuale di Network Simulator v.2

Capitolo 29 - Agenti TCP

a cura di Sandro Petrizzelli


Introduzione

In questa sezione descriviamo le caratteristiche ed il possibile utilizzo in NS degli agenti TCP. Diciamo allora subito che esistono due principali tipi di agenti TCP:  

·         agenti monodirezionali (one-way agents): questo tipo di agenti sono a loro volta suddivisi in mittenti TCP (i quali ubbidiscono a varie tecniche di controllo della congestione e degli errori) e riceventi TCP (i cosiddetti sink);

·         agenti bidirezionali (two-way agents): questi agenti, al contrario dei precedenti, sono simmetrici, nel senso che rappresentano sia dei mittenti sia dei riceventi. Si tratta di una tipologia di agenti ancora in fase di perfezionamento.

 I file cui si fa riferimento in questa sezione sono troppi per poter essere elencati tutti. Fondamentalmente, si tratta di tutti i file il cui nome è nella forma ~ns/tcp*.cc oppure ~ns/tcp*.h.

Elenchiamo i mittenti TCP (monodirezionali) attualmente supportati dal simulatore:  

·          Agent/TCP                                               mittente TCP Tahoe

·          Agent/TCP/Reno                                    mittente TCP Reno

·          Agent/TCP/NewReno                            mittente Reno con qualche modifica

·          Agent/TCP/Sack1                                   mittente TCP sono selective repeat (in base alla RFC2018)

·          Agent/TCP/Vegas                                  mittente TCP Vegas

·          Agent/TCP/Fack                                     mittente TCP Reno con “forward acknowledgment”

 

Elenchiamo ora i riceventi TCP correntemente supportati dal simulatore:  

·          Agent/TCPSink                                       ricevente TCP con singolo ACK per ogni pacchetto ricevuto

·          Agent/TCPSink/DelAck                          ricevente TCPSink con ritardo configurabile per gli ACK

·          Agent/TCPSink/Sack1                           TCP Sink con selective ACK (RFC2018)

·          Agent/TCPSink/Sack1/DelAck             ricevente TcpSack1 con DelAck

 

L’unico agente TCP bidirezionale correntemente supportato è quello corrispondente ad mittente/ricevente di tipo Reno:  

·         Agent/TCP/FullTcp

 

Questa sezione comprende tre parti:  

1.        la prima parte è una semplice panoramica sugli agenti TCP e su come le loro versioni base possono essere configurate (in particolare, sono i mittenti che devono essere configurati, mentre i riceventi no);

2.        la seconda parte descrive la struttura interna del mittente TCP di base;

3.        l’ultima parte è una descrizione delle estensioni per gli altri tipi di agenti che sono stati inclusi nel simulatore.

 

29.1 Mittenti TCP (monodirezionali)

Come anticipato nel paragrafo precedente, il simulatore supporta diverse versioni di mittenti TCP monodirezionali. Questi oggetti tentano di “catturare” l’essenza dei comportamenti dei reali mittenti TCP con riferimento al controllo di congestione ed al controllo d’errore, ma non sono stati pensati come riproduzioni fedeli delle reali implementazioni. Ad esempio:  

·         non contengono segnalazioni per quanto riguarda la finestra dinamica;

·         eseguono i calcoli del segment number e dell’ ACK number in termini di numero di pacchetti (e non in byte) ( [1] );

·         non è previsto alcun meccanismo SYN/FIN per stabilire o far cadere una connessione;

·         nessun dato (payload) viene mai trasferito (per cui non sono previsti la checksum e i dati urgenti).

 

29.1.1 Versione base del mittente TCP (TCP Tahoe)

Questo agente, il cui nome OTcl è Agent/TCP, attua un controllo di congestione ed un calcolo del round-trip-time in modo molto simile a quello della versione di TCP rilasciata dall’università di Berkeley nella 4.3 BSD Tahoe UNIX system release. La finestra di congestione viene incrementata di un pacchetto per ogni ACK ricevuto durante la slow-start (quando ), mentre invece viene incrementata di una quantità pari a 

per ogni nuovo ACK ricevuto durante un intervallo di risoluzione di uno stato di congestione (quando ).

Risposte alla congestione

Il mittente TCP Tahoe assume che un pacchetto sia stato perso (a causa della congestione) quando osserva un numero di ACK duplicati pari al valore della variabile NUMDUPACKS (valore di default: 3) oppure quando un timer di ritrasmissione risulta scaduto. In entrambi i casi, il mittente TCP Tahoe reagisce settando la variabile ssthresh_ a metà dell’attuale dimensione della finestra di congestione (pari al minimo tra i parametri cwnd_ e window_) oppure direttamente al valore 2, a seconda di quale dei due valori sia maggiore. Successivamente, esso inizializza la variabile cwnd_ nuovamente al valore windowInit_. Questo meccanismo tipicamente fa sì che il mittente entri nuovamente nella fase della slow start.

Stima del round-trip time e selezione del timeout RTO

Cinque diverse variabili vengono usate per stimare il round-trip time e per settare il timer di ritrasmissione: i loro nomi sono rtt_, srtt_, rttvar_ , tcpTick_ e backoff_. Il mittente TCP Tahoe inizializza la variabile rttvar_ al valore 

 e la variabile backoff_ al valore 1. Quando un qualsiasi successivo timer di ritrasmissione viene impostato, il suo timeout viene settato all’istante corrente sommato ad un numero di secondi pari a 

dove b è il corrente valore di backoff_, t il corrente valore di tcpTick_, a il valore di srtt_ e v il valore di rttvar_.

I campioni di round-trip time arrivano con i nuovi ACK. Il campione RTT viene calcolato come differenza tra l’istante attuale ed il campo “time echo” nel pacchetto di ACK. Quando il primo campione viene calcolato, il suo valore viene usato come valore iniziale per srtt_. Metà di questo primo campione viene invece usata come valore di rttvar_. Per i campioni successivi, i valori vengono aggiornati nel modo seguente:

 

29.1.2 Configurazione

L’esecuzione di una simulazione TCP richiede la creazione e la configurazione di un agente, l’aggancio di tale agente ad una sorgente di dati di livello application (oppure ad un generatore di traffico) e l’avvio dell’agente e della sua sorgente.

 

29.1.3 Configurazione semplice

Possiamo considerare il seguente esempio:  

set ns [new Simulator]           ;# preamble initialization

set node1 [$ns node]             ;# agent to reside on this node

set node2 [$ns node]             ;# agent to reside on this node  

set tcp1 [$ns create-connection TCP $node1 TCPSink $node2 42]

$tcp set window_ 50              ;# configure the TCP agent

 

set ftp1 [new Application/FTP]

$ftp1 attach-agent $tcp1

 

$ns at 0.0 "$ftp start"

Questo esempio illustra l’uso della funzione predefinita del simulatore denominata create-connection; questa funzione richiede in ingresso degli argomenti, che sono: l’agente sorgente da creare, il nodo sorgente, l’agente destinazione da creare, il nodo destinazione, l’identificatore del flusso (flow ID) da usare per la connessione tra sorgente e destinazione. La funzione opera creando i due agenti, settando i campi flow ID in tali agenti, attaccando tali due agenti ai rispettivi nodi e, infine, collegando i due agenti (il che significa, sostanzialmente, che vengono impostati opportunamente gli indirizzi sorgente e destinazione ed i numeri di porta per i pacchetti da simulare). Il valore restituito dalla funzione è semplicemente il nome dell’agente sorgente appena creato.

A questo punto, dobbiamo considerare che l’agente TCP non genera, per conto proprio, alcun dato di livello application. Al contrario, per poter generare dei dati, l’utilizzatore deve connettere, all’agente TCP sorgente, una qualsiasi modulo di generazione di traffico. Ci sono allora due applicazioni frequentemente usate per il TCP: l’FTP ed il Telnet. Nell’esempio prima riportato, l’applicazione usata è proprio l’FTP. Ulteriori dettagli per la configurazione di questo tipo di applicazioni si trovano nel paragrafo 32.4

 

29.1.4 Altri parametri di configurazione

In aggiunta al parametro window_ precedentemente citato, l’agente TCP supporta ulteriori variabili di configurazione. Ognuna delle variabili descritte in questo paragrafo è sia una variabile C++ (class variable) sia una variabile OTcl (instance variable). Modificare una variabile C++ equivale a modificare il valore di default per tutti gli agenti che saranno successivamente creati. Al contrario, modificare una variabile OTcl di un particolare agente ha effetto solo sul valore usato da quell’agente. Facciamo un semplice esempio:  

Agent/TCP set window_ 100        ;# Changes the class variable

$tcp set window_ 2.0             ;# Changes window_ for the $tcp object only  

Entrambe queste istruzioni sono per l’interprete OTcl. La prima modifica la variabile C++ window_ degli agenti TCP, impostandola sul valore 100: questo significa che tutti gli agenti TCP successivamente creati avranno per default tale valore. Tuttavia, dopo aver creato uno specifico agente TCP, denominato tcp, la seconda istruzione dell’esempio ha l’effetto di modificare il parametro window_ solo per tale agente.

Riportiamo ora una lista dei valori di default dei parametri per tutti gli agenti TCP:

 

Agent/TCP set window_ 20                    ;# max bound on window size

Agent/TCP set windowInit_ 1                 ;# initial/reset value of cwnd

Agent/TCP set windowOption_ 1               ;# cong avoid algorithm (1: standard)

Agent/TCP set windowConstant_ 4             ;# used only when windowOption != 1

Agent/TCP set windowThresh_ 0.002           ;# used in computing averaged window

Agent/TCP set overhead_ 0                   ;# !=0 adds random time between sends

Agent/TCP set ecn_ 0                        ;# TCP should react to ecn bit

Agent/TCP set packetSize_ 1000              ;# packet size used by sender (bytes)

Agent/TCP set bugFix_ true                  ;# see explanation

Agent/TCP set slow_start_restart_ true      ;# see explanation

Agent/TCP set tcpTick_ 0.1                  ;# timer granulatiry in sec (.1 is NONSTANDARD)

Agent/TCP set maxrto_ 64                    ;# bound on RTO (seconds)

Agent/TCP set dupacks_ 0                    ;# duplicate ACK counter

Agent/TCP set ack_ 0                        ;# highest ACK received

Agent/TCP set cwnd_ 0                       ;# congestion window (packets)

Agent/TCP set awnd_ 0                       ;# averaged cwnd (experimental)

Agent/TCP set ssthresh_ 0                   ;# slow-stat threshold (packets)

Agent/TCP set rtt_ 0                        ;# rtt sample

Agent/TCP set srtt_ 0                       ;# smoothed (averaged) rtt

Agent/TCP set rttvar_ 0                     ;# mean deviation of rtt samples

Agent/TCP set backoff_ 0                    ;# current RTO backoff factor

Agent/TCP set maxseq_ 0                     ;# max (packet) seq number sent  

In molte situazioni, è richiesta una modifica di un numero molto ridotto di questi parametri. In particolare, i parametri modificati più di frequente sono window_ e packetSize_. Il primo determina la finestra TCP da usare ed in pratica fa le veci dei messaggi di avvertimento usati dai riceventi TCP nelle reti reali. Il secondo parametro, invece, rappresenta la dimensione dei pacchetti inviati dal mittente. Eventuali variazioni di questi parametri possono avere un effetto profondo sul comportamento del TCP. Generalmente, gli agenti TCP che usano pacchetti molto grandi, finestre molto estese e piccoli round-trip time (che comunque dipendono dalla topologia e dalla congestione della rete) sono quelli più avidi di banda sui collegamenti.

 

 

29.1.5 Altri mittenti TCP monodirezionali

Descriviamo rapidamente altri cinque tipi di mittenti TCP unidirezionali.

 

Reno TCP

Questo agente è molto simile all’agente TCP Tahoe, eccetto per il fatto di includere il fast recovery (recupero veloce), in cui la corrente finestra di congestione viene allargata dal numero di ACK duplicati che il mittente TCP ha ricevuto prima di ricevere un “nuovo ACK”. Un “nuovo ACK” si riferisce ad un qualsiasi ACK recante un valore più alto tra tutti quelli precedentemente ricevuti (in particolare, dato che il maggiore valore di ACK, tra quelli ricevuti, viene sempre conservato in memoria, basta fare un confronto tra questo valore e quello dell’ACK appena giunto). In aggiunta, l’agente TCP Reno non ritorna in slow-start durante una fase di ritrasmissione; piuttosto, esso riduce la finestra di congestione a metà del valore attuale e imposta anche la soglia ssthresh_ a tale valore.

NewReno TCP

Questo agente è basato sull’agente Reno TCP, con la differenza che modifica le azioni intraprese all’arrivo di un nuovo ACK. Al fine di uscire dal fast recovery, il mittente deve ricevere un ACK per il pacchetto con il massimo numero di sequenza precedentemente inviato. Thus, new "partial ACKs" (those which represent new ACKs but do not represent an ACK for all outstanding data) do not deflate the window (and possibly lead to a stall, characteristic of Reno).

Vegas TCP

Questo agente implementa il TCP nella versione Vega.

Sack TCP

Questo agente implementa la tecnica del selective repeat, basata sugli ACK selettivi (relativi cioè a specifici pacchetti) forniti dal ricevitore.

Fack TCP

Questo agente implementa una modifica del Sack TCP, denominata “forward ACK TCP”.

 

29.2 Ricevitori TCP (sinks)

I mittenti TCP descritti nei precedenti paragrafi rappresentano mittenti unidirezionali di dati. Essi devono essere “accoppiati”, nelle simulazioni, ad oggetti TCP sink, ossia appunto a ricevitori TCP.

 

29.2.1 Il ricevitore TCP di base

L’ agente TCP sink di base (classe Agent/TCPSink) è responsabile di restituire ACK ad un corrispondente oggetto TCP mittente. Il TCP sink genera un ACK per ciascun pacchetto ricevuto. La dimensione di tale ACK può essere configurata. La creazione e la configurazione degli oggetti TCP Sink è generalmente ottenuta automaticamente da una chiamata di libreria (la già citata create-connection).

L’istruzione  

Agent/TCPSink set packetSize_ 40  

serve a configurare al valore 40 la dimensione dei pacchetti ACK.

 

29.2.2 Ricevitore TCP con Delayed-ACK

Questo ricevitore TCP (corrispondente alla classe Agent/TCPSink/DelAck) è disponibile per la simulazione di un ricevitore TCP che invia ACK in numero minore rispetto al numero di pacchetti ricevuti (come invece accade per i ricevitori TCP Sink). Questo oggetto contiene infatti una variabile, interval_, che fornisce il numero di secondi che il ricevitore deve attendere tra l’invio di un ACK e l’invio del successivo. Da notare che questo meccanismo vale solo per i pacchetti che arrivano in ordine, mentre invece per i pacchetti che arrivano fuori ordine è prevista la generazione immediata dei corrispondenti ACK.

Con la seguente istruzione è possibile impostare il desiderato intervallo tra un invio e l’altro:  

Agent/TCPSink/DelAck set interval_ 100ms

 

29.2.3 Ricevitore TCP Sack

Questo ricevitore (corrispondente alla classe Agent/TCPSink/Sack1) implementa un meccanismo di generazione degli ACK basato sul selective-acknowledgment, così come specificato nella RFC 2018. This object includes a bound variable maxSackBlocks_ which gives the maximum number of blocks of information in an ACK available for holding SACK information. The default value for this variable is 3, in accordance with the expected use of SACK with RTTM (see RFC 2018, section 3).

Mettendo insieme le caratteristiche di questo tipo di ricevitore e di quello descritto nel paragrafo precedente, si è ottenuta la classe di oggetti denominata Agent/TCPSink/Sack1/DelAck.

Con la seguente istruzione è possibile configurare la variabile maxSackBlocks_:  

Agent/TCPink/Sack1 set maxSackBlocks_ 3

 

29.3 Agenti TCP bidirezionali (FullTcp)

Questo tipo di agenti permette una simulazione più realistica del traffico TCP. La classe Agent/TCP/FullTcp è ancora in via di sviluppo da parte di coloro che lavorano all’espansione delle caratteristiche di NS. Gli agenti di tale classe sono diversi (oltre che incompatibili) con gli altri tipi di agenti, anche se fanno uso sostanzialmente della stessa architettura.

Le principali caratteristiche sono:  

·         viene usato un meccanismo, basato su pacchetti SYN/FIN (three-way-handshake), per stabilire e per chiudere le connessioni;

·         viene supportato il trasferimento bidirezionale di dati, per cui è possibile instaurare una connessione bilanciata;

·         non è previsto il piggybacking;

·         i numeri di sequenza dei pacchetti e degli ACK sono espressi in termini di byte (così come nella realtà) e non più in termini di singoli pacchetti (così come invece accade per simulazioni TCP più elementari).

·         la ritrasmissione è di tipo TCP Reno.

Instaurazione e rilascio di una connessione

Questa versione di TCP adotta un meccanismo di attivazione di una connessione fatto nel modo seguente: si apre con l’invio, da parte della sorgente, di un pacchetto SYN; a questo segue una risposta della destinazione, rappresentata da un pacchetto SYN+ACK; a quest’ultimo fa riscontro un ulteriore pacchetto ACK da parte del mittente, il quale accoda immediatamente dopo il primo segmento contenenti dati (provenienti da una applicazione).

 

Sequenza temporale dei pacchetti scambiati tra due agenti FullTcp per l’instaurazione di una connessione (tramite il meccanismo del “3-way handshake”): la sorgente invia un pacchetto SYN per instaurare la connessione e si pone in attesa; la destinazione conferma il pacchetto SYN con un pacchetto SYN+ACK,ricevuto il quale il mittente risponde con un ACK al quale accoda immediatamente il primo pacchetto dati

La richiesta di connessione (tramite pacchetto SYN) viene inoltrata quando l'applicazione che si appoggia sull'agente mittente (che differisce dal ricevente per il fatto di non essere stato messo in condizioni di "listen", cioè di attesa) inizia a trasmettere. L'altra applicazione deve invece aspettare che la connessione sia avvenuta per trasmettere dati.

Quando uno dei due agenti invia un pacchetto di FIN, l'altro continua ad inviare dati ed a ricevere ACK. Una volta chiusa la connessione con il FIN inviato dal secondo agente, potrebbero esserci ancora pacchetti nella rete. Ciò comporta la segnalazione di errori da parte di NS.

Segnaliamo che, comunque, questa versione di TCP può anche essere configurata per inviare dati fin dall’iniziale segmento SYN. Eventuali futuri perfezionamenti del codice potranno includere le necessarie funzionalità per inviare il primo segmento di dati più tardi.

 

29.3.1 Configurazione semplice

Come già osservato in precedenza, l’esecuzione di una simulazione TCP richiede la creazione e la configurazione di un agente, l’aggancio di tale agente ad una sorgente di dati di livello application (oppure ad un generatore di traffico) e l’avvio dell’agente e della sua sorgente.

Possiamo allora considerare il seguente semplice esempio:  

# set up connection (do not use "create-connection" method because

# we need a handle on the sink object)

set src [new Agent/TCP/FullTcp]              ;# create agent

set sink [new Agent/TCP/FullTcp]             ;# create agent

$ns_ attach-agent $node_(s1) $src            ;# bind src to node

$ns_ attach-agent $node_(k1) $sink           ;# bind sink to node

$src set fid_ 0                              ;# set flow ID field

$sink set fid_ 0                             ;# set flow ID field

$ns_ connect $src $sink                      ;# active connection src to sink

 

# set up TCP-level connections

$sink listen                                 ;# will figure out who its peer is

$src set window_ 100;

 

La creazione di un agente FullTcp è dunque simile alla creazione degli altri tipi di agenti, con la differenza che il ricevitore (sink) è posto in stato di attesa tramite l’apposito metodo listen ($sink listen). Dato che un riferimento al lato ricevente è richiesto per effettuare questa chiamata, non si può più usare, così come visto in precedenza, la chiamata della funzione create-connection, che restituirebbe solo un riferimento all’agente mittente.

 

Parametri di configurazione

I seguenti parametri di configurazione sono disponibili, attraverso OTcl, per l’agente di tipo FullTcp:  

Agent/TCP/FullTcp set segsperack_ 1         ;# segs received before generating ACK

Agent/TCP/FullTcp set segsize_ 536          ;# segment size (MSS size for bulk xfers)

Agent/TCP/FullTcp set tcprexmtthresh_ 3     ;# dupACKs thresh to trigger fast rexmt

Agent/TCP/FullTcp set iss_ 0                ;# initial send sequence number

Agent/TCP/FullTcp set nodelay_ false        ;# disable sender-side Nagle algorithm

Agent/TCP/FullTcp set data_on_syn_ false    ;# send data on initial SYN?

Agent/TCP/FullTcp set dupseg_fix_ true      ;# avoid fast rxt due to dup segs+acks

Agent/TCP/FullTcp set dupack_reset_ false   ;# reset dupACK ctr on !0 len data segs

   containing dup ACKs

Agent/TCP/FullTcp set interval_ 0.1         ;# as in TCP above, (100ms is non-std)

 

Due osservazioni risultano importanti relativamente ai primi due parametri riportati nella precedente lista:  

·         segsperack_  : è il numero di pacchetti che devono essere riscontrati con un ACK. Il valore di default è 1, ma è possibile aumentarlo qualora si voglia ridurre il traffico di ACK; 

·         segsize_  : è la MTU (Unità Massima Trasferibile), avente valore di default 536. A differenza degli agenti TCP-oneway, questo valore è riferito solo al payload del pacchetto TCP: infatti, negli output del NAM e nei trace file, la dimensione di questi pacchetti è sempre segsize_+40, ossia gli vengono sommati i 40 byte dell'header IPv4+TCP.

 Osserviamo inoltre un’altra cosa: nei suddetti file di output, tutti i pacchetti provenienti dall'agente che ha richiesto la connessione sono chiamati "tcp" (anche se si tratta di ack), mentre quelli in senso contrario "ack".

 

29.4 Architettura e costituzione interna

L’agente TCP di base (classe Agent/TCP) è costruito come un insieme di routine per l’invio dei pacchetti, per l’elaborazione degli ACK, per la gestione della finestra di invio e per la gestione dei timeout. Generalmente, ciascuna di queste routine può essere sovrascritta da una omonima routine scritta in una classe derivata (questo è, ad esempio, il criterio seguito per implementare le diverse varianti di mittenti TCP).

 

29.4.1 L’header TCP

L’header TCP è definito tramite la struttura denominata hdr_tcp, definita nel file ~ns/tcp.h. L’agente TCP base fa uso solo del seguente sottoinsieme di campi:  

ts_      /* current time packet was sent from source */

ts_echo_ /* for ACKs: timestamp field from packet associated with this ACK */

seqno_   /* sequence number for this data segment or ACK (Note: overloading!) */

reason_    /* set by sender when (re)transmitting to trace reason for send */

 

29.4.2 Funzioni per l’invio dei dati

Notiamo subito che, generalmente, il mittente TCP non ha dati da inviare, per cui si limita a settare la dimensione dei propri pacchetti.

La prima funzione che esaminiamo è la seguente:  

send_much(force,reason,maxburst)

Questa funzione tenta di inviare tanti pacchetti quanti ne permette la finestra d invio. Essa tiene inoltre traccia di quanti pacchetti ha inviato e limita il totale al valore maxburst.

L’altra funzione di interesse è  

Output(seqno,reason)  

Questa funzione invia un pacchetto con il dato numero di sequenza ed inoltre aggiorna la variabile contenente il numero di sequenza appena inviato (maxseq_), in modo da conservare tale numero di sequenza se esso è il più grande che è stato inviato. Inoltre, questa funzione assegna i vari campi dell’header TCP (sequence number, timestamp, reason for transmission). Infine, essa setta un timer di ritrasmissione qualora non ce ne sia uno ancora pendente.

 

29.4.3 Funzioni per la gestione delle finestra di invio

La finestra di invio utilizzabile in un dato momento è quella fornita dalla funzione window(): quest’ultima, infatti, restituisce il minimo della finestra di congestione e la variabile wnd_, che rappresenta the la finestra di avvertimento del ricevitore.

Consideriamo inoltre la funzione  

opencwnd()  

Questa funzione apre la finestra di congestione e viene invocata quando arriva un ACK. Quando il mittente è in slow-start, la funzione incrementa semplicemente la variabile cwnd_ per ogni ACK ricevuto. Se invece si sta fronteggiando una congestione, la configurazione standard prevede di incrementare cwnd_ del suo reciproco. Altre opzioni di crescita della finestra di invio sono supportata in presenza di congestione, ma sono solo sperimentali e non ancora documentate.

L’ultima funzione di interesse, in quest’ambito, è  

Closecwnd(int how)  

Questa funzione riduce la finestra di congestione. Essa può essere invocata in vari modi. Il suo argomento, how, indica in quale modo la finestra di congestione deve essere ridotta: il valore 0 è usato per i timeout di ritrasmissione e per la ritrasmissione veloce nel TCP Tahoe. Esso tipicamente fa sì che il mittente TCP entri in slow-start e riduce la variabile ssthresh_ (soglia) a metà della finestra corrente. Il valore 1 è invece usato dal TCP Reno per implementare il recupero veloce (che evita di tornare in slow-start). Il valore 2 è usato per ridurre la finestra a causa dell’indicazione del bit ECN (che notifica una congestione): in questo caso, la finestra di congestione viene riportata al valore iniziale (il che causa generalmente la slow-start), ma il valore di ssthresh_ non viene alterato.

 

29.4.4 Funzioni per l’elaborazione degli ACK

Ci sono due fondamentali funzioni per assolvere ai compiti di elaborazione degli ACK:  

·      la funzione recv() è il metodo principale di ricezione degli ACK. Bisogna notare che, dato che solo una direzione del flusso dati viene usata, questa funzione deve essere invocata solo quando viene ricevuto un ACK puro (privo cioè di dati). La funzione si occupa di memorizzare il timestamp dell’ACK nella variabile ts_peer_ e di controllare la presenza del bit ECN (riducendo la finestra di invio se necessario). Se l’ACK è un nuovo ACK, essa invoca la procedura newACK(), di cui parleremo tra poco; in caso contrario, essa controlla che non si tratti di un duplicato dell’ultimo ACK ricevuto; se è così, essa in ritrasmissione veloce chiudendo la finestra di invio, resettando il timer di ritrasmissione e inviando un pacchetto tramite la chiamata alla procedura send_much precedentemente citata;

·      la funzione newACK() si occupa di elaborare un nuovo ACK (ossia un ACK che contenga un ACK number più alto di qualunque altro precedentemente incontrato). La funzione setta un nuovo tempo di ritrasmissione usando la procedura newtimer() (di cui parleremo nel prossimo paragrafo), aggiorna il calcolo del RTT chiamando la procedura rtt_update()(di cui parleremo nel prossimo paragrafo) ed infine aggiorna le variabili contenenti il più alto valore e l’ultimo valore dell’ACK number.

 

29.4.5 Funzioni per la gestione del timer di ritrasmissione

Queste funzioni servono a due scopi fondamentali: stimare il round-trip time e impostare l’attuale timer di ritrasmissione. Le funzioni sono le seguenti:  

·      rtt_init(): questa funzione inizializza a zero le variabili srtt_ e rtt_, inizializza la variabile rttvar_ al valore 3/tcp_tick_ e, infine, imposta il moltiplicatore di backoff (backoff multiplier) al valore 1;

·      rtt_timeout(): questa funzione fornisce il valore del timeout, in secondi, che dovrebbe essere usato per schedulare la prossima ritrasmissione. Esso computa tale valore sulla base dell’attuale stima della media e della deviazione standard del round-trip time. In addition, it implements Karn’s exponential timer backoff for multiple consecutive retransmission timeouts;

·      rtt_update():this function takes as argument the measured RTT and averages it in to the running mean and deviation estimators according to the description above. Note that t_srtt_ and t_rttvar are both stored in fixed-point (integers). They have 3 and 2 bits, respectively, to the right of the binary point;

·      resrt_rtx_timer(): questa funzione viene invocata durante la ritrasmissione veloce (fast retransmit) o durante un timeout; essa imposta un timer di ritrasmissione chiamando la funzione set_rtx_timer() e, se invocata da un timeout, chiama anche la funzione rtt_backoff();

·      rtt_backoff(): questa funzione raddoppia il timer di ritrasmissione;

·      newtimer(): questa funzione viene chiamata solo quando arriva un ACK. Se l’estremo sinistro della finestra del mittente è più in là dell’ACK, allora invoca la funzione set_rtx_timer(), altrimenti, se il timer di ritrasmissione è pendente, esso viene cancellato.

 

29.5 Tracing delle dinamiche TCP

Il comportamento del TCP è spesso osservato costruendo una sequenza di diagrammi numero-tempo. Tipicamente, una traccia è ottenuta abilitando il tracing di un collegamento sul quale fluiscono pacchetti TCP. Sono allora supportati due metodi di tracing: quello di default, usando per tracciare gli agenti TCP generici, ed una sua estensione usata solo per gli agenti FullTCP.

 

29.6 Tracing degli agenti TCP monodirezionali

I pacchetti TCP generati da un generico agente TCP monodirezionale e destinati ad un agente TCP sink attraverso un “traced link” ( [2] ) generato un trace file costituito da una successione di linee del tipo seguente:

 

+ 0.94176 2 3 tcp 1000 ------ 0 0.0 3.0 25 40

+ 0.94276 2 3 tcp 1000 ------ 0 0.0 3.0 26 41

d 0.94276 2 3 tcp 1000 ------ 0 0.0 3.0 26 41

+ 0.95072 2 0 ack 40 ------ 0 3.0 0.0 14 29

- 0.95072 2 0 ack 40 ------ 0 3.0 0.0 14 29

- 0.95176 2 3 tcp 1000 ------ 0 0.0 3.0 21 36

+ 0.95176 2 3 tcp 1000 ------ 0 0.0 3.0 27 42  

L’esatto formato di questo trace file è fornito nel paragrafo 22.4.

Quando viene effettuato il tracing TCP, sono considerati solo i pacchetti di tipo tcp o ack. Il loro tipo, dimensione, numero di sequenza (o numero di ack per i pacchetti ack), tempo di arrivo, tempo di partenza e tempo di cancellazione (drop time) sono forniti, rispettivamente, nelle posizioni 5,6,11 e 2 delle linee del trace file. In particolare, il simbolo + indica l’arrivo di un pacchetto, il simbolo d indica un drop, il simbolo indica una partenza.

E’ previsto un certo numero di script per processare file di questo tipo al fine di produrre output grafici e statistiche riassuntive di vario tipo. Si può ad esempio osservare il listato, nel file ~ns/test-suite.tcl, della procedura “finish”.

 

29.7 Tracing degli agenti FullTCP

I pacchetti TCP generati dagli agenti FullTcp e passati attraverso un traced link contengono informazioni addizionali non visualizzate, per default, dagli oggetti regular trace. Allora, basta abilitare il flag show_tcphdr_ degli oggetti trace per ottenere la visualizzazione, nel trace file, di tre ulteriori campi dell’header: numero di ack, flag specifici del TCP, lunghezza dell’header.

 

29.8 Comandi principali

Segue una lista dei principali comandi usati per impostare e manipolare i flussi TCP nelle simulazioni.

 

set tcp0 [new Agent/TCP]

Questo comando crea una istanza di agente TCP. Come visto nei precedenti paragrafi, ci sono diverse versioni di mittenti TCP e riceventi TCP attualmente implementati nel simulatore, ai quali si aggiunge, per il momento, un’unica versione di agente TCP bidirezionale.

 

$tcp set window_ <wnd-size>

Questo è un esempio di comando per configurare i parametri di un flusso TCP. I valori di default dei parametri TCP si trova nel file ~ns/tcl/lib/ns-default.tcl.

 

Segue ora un esempio di semplice configurazione di una connessione TCP:

 

set tcp [new Agent/TCP]                ;# create tcp agent

$ns_ attach-agent $node_(s1) $tcp      ;# bind src to node

$tcp set fid_ 0                        ;# set flow ID field

set ftp [new Application/FTP]          ;# create ftp traffic

$ftp attach-agent $tcp                 ;# bind ftp traffic to tcp agent

set sink [new Agent/TCPSink]           ;# create tcpsink agent

$ns_ attach-agent $node_(k1) $sink     ;# bind sink to node

$sink set fid_ 0                       ;# set flow ID field

$ns_ connect $tcp $sink                ;# active connection src (tcp) to sink

$ns_ at $start-time "$ftp start"        ;# start ftp flow



[1] Qualcosa di diverso accade invece, come vedremo, per gli agenti TCP bidirezionali

[2] Si veda in proposito il capitolo 22

 

 

 


Continua con:        Indice       Capitolo 28      Capitolo 4


Aggiornamento: 18 giugno 2001

home