Manuale di Network Simulator v.2
Capitolo 4 - La classe "Simulator"
a cura di Sandro Petrizzelli
Il simulatore,
nel suo complesso, è descritto dalla classe Tcl denominata Simulator:
tale classe fornisce un insieme di interfacce sia per configurare una
simulazione sia per scegliere il tipo di schedulatore di eventi da
usare per guidare la simulazione.
Uno script
di simulazione generalmente inizia con una istruzione di creazione di una
istanza della classe Simulator (del tipo set ns [new Simulator]), cui fanno seguito una serie di istruzioni di chiamata a vari metodi per
la creazione di nodi e di topologie più o meno complicate e per la
configurazione di tutta una serie di aspetti della simulazione.
E’ prevista
anche una sottoclasse della classe Simulator,
denominata OldSim: questa è usata solo
per supportare la compatibilità con la precedente versione di ns (ns v 1).
Le procedure e
le funzioni descritte in questo capitolo possono essere trovate nei seguenti
file:
~ns/tcl/lib/ns-lib.tcl
~ns/scheduler.cc
~ns/scheduler.h
~ns/heap.h.
Quando viene
creato, in Tcl, un nuovo oggetto di simulazione, la procedura di
inizializzazione esegue le seguenti operazioni:
1)
in primo luogo, inizializza il formato
dei pacchetti da usare per la simulazione: viene chiamata, a tal
proposito, la procedura create_packetformat(),
che serve al setup di un oggetto della classe PacketHeaderManager,
di cui parleremo più avanti;
2)
in secondo luogo, crea uno schedulatore:
è possibile scegliere diversi tipi di schedulatore, oppure accettare
direttamente quello di default (che è il cosiddetto “calendar scheduler”);
3)
infine, crea opzionalmente un cosiddetto “null
agent”, ossia una sorta di “cestino” per i pacchetti simulati.
La prima fase è dunque quella di inizializzazione del formato dei
pacchetti: essa consiste nell’approntare i campi all’interno dei
pacchetti che saranno usati nella simulazione. Questa fase sarà meglio
descritta nel capitolo 12.
Lo schedulatore,
che viene impostato nella seconda fase della procedura, esegue la simulazione
in modo “event-driven”, ossia “guidato dagli eventi”. Come detto,
esistono diversi tipi di schedulatore, ognuno dei quali basa la schedulazione
su meccanismi differenti: ne parleremo nei prossimi paragrafi.
Infine, il “null
agent” può essere creato tramite la seguente istruzione OTcl:
set nullAgent_ [new Agent/Null]
Si tratta di un agente generalmente molto utile come “cestino” per i pacchetti scartati oppure come destinazione per quei pacchetti che non si intende conteggiare o considerare.
NS è un
simulatore guidato ad eventi (event-driven).
Attualmente, sono previsti quattro diversi schedulatori nel simulatore,
ognuno dei quali è implementato usando una differente struttura dati:
linked-list scheduler;
heap scheduler;
calendar queue scheduler (lo schedulatore usato per
default);
real time scheduler.
Ognuno di questi schedulatori
verrà descritto nei prossimi paragrafi.
Lo
schedulatore, quale che sia la sua tipologia, funziona nel modo seguente:
in primo luogo, sceglie l’evento successivo da eseguire: se la simulazione non è ancora partita, si tratterà dell’evento di “start” della simulazione, mentre invece, a simulazione già in corso, si tratterà dell’evento successivo all’ultimo che è stato eseguito ed è in fase di completamento;
in secondo luogo, esegue l’evento
successivo fino al suo completamento;
ritorna ad individuare l’evento
successivo e così via, fino all’evento finale della simulazione (evento
di “stop”).
L’unità utilizzata dallo schedulatore per misurare il tempo sono i secondi.
Attualmente, il
simulatore è progettato in modo che un solo evento possa essere eseguito in
un dato istante. Ciò significa che, se fossero previsti due eventi per lo
stesso istante, il simulatore eseguirà comunque prima uno e poi l’altro: in
particolare, viene eseguito per primo l’evento che è stato schedulato per
primo. A tal proposito, si tenga conto che gli eventuali eventi simultanei
non vengono riordinati in alcun modo dagli schedulatori, proprio in modo tale
che gli schedulatori rispettino, nell’esecuzione degli eventi, lo stesso
ordine con cui tali eventi sono stati schedulati dall’utente.
Segnaliamo
inoltre che non sono supportate le esecuzioni parziali degli eventi.
Scendendo in
maggiore dettaglio, segnaliamo che un generico evento comprende generalmente
un firing time e una funzione manipolatrice (detta “handler”).
L’attuale definizione di un evento si può trovare nel file ~ns/scheduler.h
ed è la seguente:
class Event
{
public:
Event* next_;
/* event list */
Handler* handler_;
/* handler to call when event ready */
double time_;
/* time at which event is ready */
int uid_;
/* unique ID */
Event() : time_(0), uid_(0) {}
};
/*
* The base class for all event handlers. When an
event’s scheduled
* time arrives, it is passed to handle which must
consume it.
* i.e., if it needs to be freed it, it must be
freed by the handler.
*/
class Handler
{
public:
virtual void handle(Event* event);
};
La classe
denominata Event corrisponde dunque alla
definizione di evento. In tale definizione sono incluse quattro variabili
pubbliche ed un costruttore. Le quattro variabili hanno il seguente
significato (peraltro evidente nei rispettivi nomi):
·
“next_”
è un puntatore al successivo evento nella lista usata dallo schedulatore;
·
“handler_”
è un puntatore ad un oggetto di classe Handler,
ossia ad un manipolatore di eventi, da chiamare quanto l’evento in questione
deve essere eseguito;
·
“time_”
è l’istante di tempo in cui l’evento deve essere eseguito;
·
“uid_”
è un identificatore univoco dell’evento.
La classe denominata Handler contiene
semplicemente una funzione virtuale, che quindi dovrà essere
specializzata tramite le classi da essa derivate.
Tornando invece
alla classe Event,
da essa vengono derivati due tipi di oggetti fondamentali per ns:
·
i pacchetti (classe Packet),
dei quali si parlerà in dettaglio nel capitolo 12;
·
le procedure cosiddette “at-event”:
si tratta di procedure Tcl che devono essere eseguite nel momento in cui
arriva un determinato istante (specificato dall’utente). Questo “strumento”
viene usato molto spesso negli script di simulazione. Un semplice esempio di
come usare questo strumento è riportato nelle seguenti istruzioni Tcl:
...
set ns_ [new Simulator]
$ns_ use-scheduler Heap
$ns_ at 300.5 "$self complete_sim"
...
Questo
frammento di codice Tcl per prima cosa crea un oggetto di classe Simulator,
ossia appunto un simulatore; nella riga successiva, viene modificato lo
schedulatore da usare rispetto a quello previsto di default: si sceglie
infatti di usare lo schedulatore denominato “heap”, del quale
parleremo più avanti. La riga ancora successiva serve a schedulare la
chiamata della funzione “$self complete_sim”
(
[1]
) in corrispondenza dell’istante t = 300.5 secondi.
Questo
particolare schedulatore corrisponde alla classe Scheduler/List,
derivata appunto dalla classe base Scheduler. Esso
implementa la schedulazione usando una semplice struttura a lista linkata:
tale lista viene mantenuta in ordine di tempo (dall’evento da eseguirsi per
primo a quello da eseguirsi per ultimo), il che significa che l’inserimento
di un nuovo evento nella lista richiede di scorrere la lista stessa per
individuare il corretto punto di inserimento, in base appunto all’istante di
esecuzione.
L’individuazione del prossimo evento da eseguire richiede semplicemente di prelevare l’elemento in cima alla lista: in questo modo, si garantisce una esecuzione degli eventi simultanei in modo FIFO (infatti, in caso di due eventi la cui esecuzione è prevista nello stesso istante, sarà eseguito per primo quello che è stato anche schedulato per primo).
Questo schedulatore (corrispondente alla classe Scheduler/Heap), implementa la schedulazione usando una classica struttura a “heap”.
Questo schedulatore (classe Scheduler/Calendar) usa una struttura dati analoga ad un calendario annuale da tavolo, in cui gli eventi nello stesso giorno o mese di anni multipli possono essere registrati in un giorno.
Questo schedulatore (classe Scheduler/RealTime) tenta di sincronizzare l’esecuzione degli eventi in tempo reale. La capacità di real-time di ns è attualmente ancora in fase di sviluppo ed è usata per introdurre le reti simulate in ns all’interno di una topologia di rete realmente esistente.
La classe Simulator fornisce un buon numero di metodi da usare per impostare le proprie simulazioni. Questi metodi possono essere suddivisi fondamentalmente in tre categorie:
metodi per creare e gestire la topologia della rete, il che significa gestire sia i nodi ( [2] ) sia i link ( [3] );
metodi per attuare il “tracing” dei pacchetti ( [4] );
funzioni di ausilio all’utilizzatore.
Segue una lista dei principali metodi non legati alla topologia della
rete da simulare:
Simulator
instproc now
;# return scheduler’s notion of current time
Simulator
instproc at args
;# schedule execution of code at specified time
Simulator
instproc cancel args
;# cancel event
Simulator
instproc run args
;# start scheduler
Simulator
instproc halt
;# stop (pause) the scheduler
Simulator
instproc flush-trace
;# flush all trace object write buffers
Simulator
instproc create-trace type files src dst ;# create trace object
Simulator instproc create_packetformat ;# set up the simulator’s packet format
Il comando base per eseguire uno script di simulazione in
ns è il seguente:
ns <otclfile> <arg>
<arg> …
Il simulatore viene invocato attraverso l’interprete OTcl. Una particolare simulazione è invece definita da un file contenente un certo numero di script. Numerosi esempi di script OTcl possono essere trovati nella directory ~ns/tcl/ex.
Segue ora una lista dei comandi di simulazione maggiormente usati nella pratica:
set ns_ [new Simulator]
This
command creates an instance of the simulator object.
set now [$ns_ now]
The
scheduler keeps track of time in a simulation. This returns scheduler’s
notion of current time.
$ns_ halt
This
stops or pauses the scheduler.
$ns_ run
This
starts the scheduler.
$ns_ at <time> <event>
This
schedules an <event> (which is normally a piece of code) to be executed
at the specified <time>.
$ns_ cancel <event>
Cancels
the event. In effect, event is removed from scheduler’s list of ready to run
events.
$ns_ create-trace <type> <file> <src>
<dst> <optional arg: op>
This
creates a trace-object of type <type> between <src> and
<dst> objects and attaches trace-object to <file> for writing
trace-outputs. If op is defined as "nam", this creates nam
tracefiles; otherwise if op is not defined, ns tracefiles are created on
default.
$ns_ flush-trace
Flushes all trace object write buffers.
$ns_ gen-map
This dumps information like nodes, node components,
links etc created for a given
simulation. This may be broken for some scenarios (like wireless).
$ns_ at-now <args>
This is in effect like command "$ns_ at $now $args".
Note that this function may not work because of tcl’s string number
resolution.
Segue
adesso una breve lista di alcune funzioni di aiuto interne al simulatore,
normalmente usare per modificare il codice “core” di ns:
$ns_ use-scheduler <type>
Used
to specify the type of scheduler to be used for simulation. The different
types of scheduler available are List, Calendar, Heap and RealTime. Currently
Calendar is used as default.
$ns_ after <delay> <event>
Scheduling
an <event> to be executed after the lapse of time <delay>.
$ns_ clearMemTrace
Used
for memory debugging purposes.
$ns_ is-started
This
returns true if simulator has started to run and false if not.
$ns_ dumpq
Command
for dumping events queued in scheduler while scheduler is halted.
$ns_ create_packetformat
This
sets up simulator’s packet format.
[1] E’ bene notare che questo particolare frammento di codice assume implicitamente di essere incapsulato in una procedura di istanziamento di un oggetto, in modo tale che sia correttamente definito il riferimento a $self.
[2] Capitolo 5
[3] Capitolo 6
[4] Capitolo 22
Continua con: Indice Capitolo 3 Capitolo 5
Aggiornamento: 18 giugno 2001