Manuale di Network Simulator v.2
Capitolo 29 - Agenti TCP
a cura di Sandro Petrizzelli
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.
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).
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 ).
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.
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:
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 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
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.
Descriviamo rapidamente altri cinque tipi di mittenti TCP unidirezionali.
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.
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).
Questo agente implementa il TCP nella versione Vega.
Questo agente implementa la tecnica del selective repeat, basata sugli ACK selettivi (relativi cioè a specifici pacchetti) forniti dal ricevitore.
Questo agente implementa una modifica del Sack TCP, denominata “forward ACK TCP”.
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.
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.
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
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
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.
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.
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.
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".
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).
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 */
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.
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.
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.
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.
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.
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”.
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.
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