Vous êtes sur la page 1sur 8

Simulation de réseaux IP avec ns

Introduction à l’utilisation des logiciels

4 février 2014

1 Le simulateur ns
1.1 Principe et Architecture
Le simulateur ns permet la description et la simulation de réseaux IP. Le réseau est représenté
(modélisé) par ses sources de trafic (applications), ses protocoles (UDP, TCP), ses routeurs (avec leurs
files d’attente) et les liens qui les relient. Le réseau est ensuite simulé, ce qui produit des traces et
des statistiques. Des outils périphériques permettent l’animation du réseau (nam) ou la conversion vers
d’autres outils (comme par exemple xgraph pour dessiner des courbes).
L’utilisateur décrit le modèle de son réseau, c’est-à-dire les éléments qui le constituent, dans le langage
OTcl (une extension objet du langage tcl). Ce fichier est ensuite passé au simulateur proprement dit.
Celui-ci se nomme ns. Le modèle étant décrit dans le fichier modele.tcl, on exécute :

b52> ns modele.tcl
Il est possible de rajouter des objets réseau au simulateur, en les programmant en C++. Cette
possibilité ne sera pas exploitée dans ce TP.

Configuration, utilisation et informations


Le système ns est installé dans /usr/local/ns. Normalement, vous n’avez aucune variable d’environ-
nement à positionner. Néanmoins, si le besoin s’en fait sentir, vous devrez rajouter /usr/local/ns/bin
dans votre PATH pour utiliser les exécutables (ns, nam et éventuellement xgraph).
Sont utiles pour démarrer :
— l’exemple fourni dans ˜ns/ns-2.1b9a/tcl/ex/simple.tcl (et les autres du même répertoire)
— le fichier de configuration ˜ns/ns-2.1b9a/tcl/lib/ns-default.tcl qui contient les valeurs ini-
tiales des attributs de tous les objets du système.

Liens, sources et documents


Pour en savoir plus, suivre des exemples pas à pas ou obtenir de la documentation détaillée, voici
quelques sources :
— Le site de ns, au LBL (Lawrence Berkeley National Laboratory) :
http://www-mash.cs.berkeley.edu/ns ;
— Support de cours de C. Barakat, INRIA Sophia-Antipolis ;
— Transparents de N. Christin, Dept of Computer Science, University of Virginia (ask Google) ;
— Transparents de A.A. Abouzeid, Dept of Electrical Engineering, University of Washington (ask
Google too).

1.2 Composition d’un modèle


Un modèle de réseau en ns est constitué :
— de nœuds de réseau : endroits où est généré le trafic, ou nœuds de routage.
— de liens de communication entre les réseaux.

1
— d’agents de communication, représentant les protocoles de niveau transport (TCP, UDP) ; ces
agents sont attachés aux nœuds et connectés l’un à l’autre, ce qui représente un échange de
données (connexion TCP, flux UDP).
— d’applications qui génèrent le trafic de données selon certaines lois, et se servent des agents de
transport.
De plus, la description d’une expérience de simulation contient les instructions de trace des objets
que l’on veut observer, et les mesures que l’on veut collecter.

Le langage (O)Tcl
Le langage tcl est un langage de scripts. La fin de ligne est le délimiteur d’instructions. Les com-
mentaires commencent par un # et finissent à la fin de ligne.
Les variables ont toujours le type chaîne de caractères (ou liste de chaînes). La valeur de la variable
de nom a est $a. Les variables sont toujours instanciées avant l’exécution d’une instruction, même à
l’intérieur d’une chaîne de caractères.
Le tableau suivant décrit les principales instructions.

set a 10 affecter la chaîne de caractères 10 à la variable a


set a "une chaîne de car" autre affectation
set b $a affecter le contenu de la variable a à la variable b
puts $b imprimer le contenu de la variable b
puts "B vaut $b" idem, mais à l’intérieur d’une chaîne de caractères. b est évaluée
set a(couleur) "red" les tableaux ont des indices qui sont des chaînes de caractères
[fonc par1 par2] appeler la fonction fonc avec des paramètres
set obj [new Class1/Class2] créer une instance d’un objet
[$obj meth par1 par2] invoquer la méthode meth de l’objet obj
$obj set field val instancier une variable de l’objet obj
set a [$obj set field] récupérer la valeur d’une variable de l’objet obj
[expr $a + 6 * $b] évaluer l’expression arithmétique
set f [open "File" w] ouvrir le fichier de nom File en écriture, et mettre le descripteur dans f
puts $f "truc" écrire une chaîne dans le fichier de descripteur f
exec xemacs & exécuter un processus système (en arrière plan avec &)

Les structures de contrôle sont : pour les tests,


if { $a = $b } {
# code if
} else {
# code else
}
et pour les boucles

for { set i 0 } { $i < 10 } { incr i } {


# code de la boucle
}
Enfin, il est possible de définir des fonctions :
proc fonc { par1 par2 } {
global var1 var2
# code
return $quelquechose
}
où l’instruction global permet de faire référence à des variables globales du script tcl.

2
Instructions de création d’un modèle, et contrôle de la simulation
La simulation se prépare en écrivant un fichier OTcl, disons TP-ns.tcl. On commence par créer le
simulateur
set ns [new Simulator]
Si on veut tracer les événements du simulateur, et si on veut obtenir les données pour l’animation
post mortem, on fait :
$ns trace-all $f
$ns namtrace-all $nf
où f et nf sont des descripteurs de fichier, ouverts auparavant. Attention : ces instructions doivent venir
avant celles de création des objets de la simulation !

Topologie. Ensuite, on crée les nœuds du réseau, puis les liens qui les relient avec leur débit (1Mb par
seconde dans l’exemple ci-dessous) et leur latence (ici, 250ms), et la politique de rejet des paquets en
trop (ici DropTail mais il y en a d’autres comme par exemple Red, etc. . .). On peut aussi préciser le
nombre limite de paquets dans la file d’attente (100 dans l’exemple ci-dessous).
set n1 [$ns node]
set n2 [$ns node]
$ns duplex-link $n1 $n2 1Mb 250ms DropTail
$ns queue-limit $n1 $n2 100

Unités. ns accepte les arguments 5, 5s, 5ms, 5ns pour des durées de temps. Il est conseillé de toujours
mettre l’unité souhaitée pour ne pas se laisser piéger par la valeur par défaut. De même pour les débits
d’information, en b, Mb etc. Attention : pour les débits, B signifie «octet» (Bytes) alors que le défaut est
en bits/s. Pour les tailles de paquets, le défaut est en octets.

Transport. Il faut créer les agents de transport, les attacher aux nœuds et les connecter entre eux.
Parmi les agents disponibles, on trouve Agent/Null, Agent/LossMonitor, Agent/UDP, Agent/TCP et
Agent/TCPSink. Le code est par exemple :

set udp [new Agent/UDP] # crée une source non contrôlée UDP
set trappe [new Agent/Null] # crée un puits d’information
$ns attach-agent $n1 $udp # attache la source à un noeud
$ns attach-agent $n2 $trappe # attache la destination à un autre
$ns connect $udp $trappe # associe la paire origine/destination

Noter qu’il n’est pas nécessaire de spécifier quelle est la route suivie par les paquets d’une paire d’agents :
c’est le simulateur qui calcule les routes les plus courtes. L’agent LossMonitor peut s’utiliser à la place de
Null mais permet en plus de garder trace des pertes (attribut nloss_), paquets et octets reçus (attributs
npkts_ et nbytes_). Utile pour surveiller des flux UDP.
Important : on ne peut pas relier n’importe quel type d’agent à n’importe quel autre. Par exemple,
un agent TCP doit être relié à un TCPSink. Sinon, la connexion TCP ne fonctionnera pas. On ne peut pas
non plus relier plusieurs agents au même «sink». ns le laisse faire mais ça ne fonctionne pas correctement.

Application. Enfin, on crée les sources de trafic, héritant de la classe Application. Le tableau suivant
résume quelques objets et leurs paramètres spécifiques. Tous ont comme attributs packetSize_ (taille
des paquets, qui sera constante) et rate_ (débit en octets/s pendant les périodes on).

3
Classe (<A>=Application) description paramètres
<A>/Traffic/CBR source à débit constant interval_ intervalle entre paquets
(alternative à rate_), maxpkts_ nombre
max de paquets à envoyer
<A>/Traffic/Exponential source «on/off» à durées burst_time_ durée moyenne des périodes «on»
de distribution exponentielle idle_time_ durée moyenne des périodes «off»
<A>/Traffic/Pareto source «on/off» à durées comme Exponential, plus rate_,
de distribution de Pareto paramètre de forme
<A>/Telnet émule une application telnet
<A>/FTP émule une application FTP maxpkts_ nombre max de paquets

Il faut attacher l’application à l’agent de transport :


set app [new Application/Traffic/CBR]
$app attach-agent $udp
Pour démarrer et arrêter une source src, on a : $src start et $src stop.
Il ne faut surtout pas oublier d’ordonner à la simulation de s’exécuter. Cela se fait par la ligne suivante
insérer à la fin de votre script :
$ns run

Les processus «on/off». Les applications Traffic/Exponential et Traffic/Pareto fabriquent des


processus de paquets «on/off». Voici leur fonctionnement. Pendant les périodes d’activité, qui sont de
durée moyenne idle_time_, les paquets sont générés consécutivement au débit de rate_ bits par
seconde. Les paquets sortent donc à des intervalles constants, la durée de cet intervalle étant fonction de
la taille des paquets et de rate_. Après la fin de la période «on», il y a une période «off» sans paquets
de durée moyenne idle_time_, puis on recommence.

Pour générer un processus de Poisson. On obtient (approximativement) un processus de Poisson


pour l’arrivée des paquets quand on utilise un Application/Trafic/Exponential avec un burst_time_
égal à 0 et un rate_ grand. L’effet que cela a est d’émettre un unique paquet dans l’intervalle «on» puis
d’attendre une durée aléatoire «off», de distribution exponentielle avec moyenne idle_time_. Normale-
ment, le débit en paquets par seconde devrait être environ 1/idle_time_.

Temporisateurs. Il est possible de programmer des événements qui seront exécutés à des dates précises
de la simulation. Par exemple :
$ns at 1.0 "$truc start" # démarre l’application $truc à t=1.0
$ns at 5.0 "$truc stop" # l’arrête à t=5.0
$ns at 10.0 "finish" # invoque la procédure finish à t=10.0
Typiquement, la fin de la simulation se fera par l’invocation d’une procédure chargée du traitement final
des statistiques. Exemple :
proc finish { } {
global ns f nf stat
puts "C’est fini"
close $f # fermeture du fichier de trace (s’il y a)
close $nf # fermeture du fichier de trace animation
puts "Débit = $stat(debit)" # impression d’une statistique
}
On utilisera aussi souvent des procédures qui se re-programment, telle :
proc perpetuelle { } {
global ns
# ici un traitement utile...

4
set now [$ns now] # récupération de la date courante
set delai 0.1 # incrément de temps
$ns after $delai "perpetuelle" # c’est reparti
}

1.3 Comment faire des statistiques


Afin de faire des statistiques sur le réseau, il faut pouvoir récupérer les valeurs de différentes quantités,
comme le nombre de paquets passant par un lien. On utilise pour cela des «monitors» (surveillants). Il
y en a de plusieurs types.

Surveillants de files d’attente. Le contenu de files d’attente peut être surveillé de plusieurs façons.
On a déjà vu les instructions de trace globale. On peut également tracer une file d’attente particulière.
Ici, celle du lien allant de $n1 a $n2 dans le fichier $f :

$ns trace-queue $n1 $n2 $f


Le format de trace est le suivant :
<type evt> <tps> <orig> <dest> <type pkt> <taille> --- <flow id> <id src> <id dest> <seq> <attr>

Où le <type evt> est + pour une arrivée, - pour un départ, d pour une perte de paquet (drop), r pour
une réception de paquet.
Il existe aussi des objets «monitors». On en attache un à une file par
set spy [$ns monitor-queue $n1 $n2 $f]
$spy set pkts_ # nombre de paquets dans la file

Note : l’argument $f semble ne pas être utilisé.


Les attributs associés à un monitor sont :
Attribut signification
pkts_ nombre de paquets courant
size_ nombre d’octets courant
parrivals_ nombre de paquets entrés
pdepartures_ nombre de paquets sortis
pdrops_ nombre de paquets refusés
barrivals_ nombre d’octets entrés
bdepartures_ nombre d’octets sortis
bdrops_ nombre d’octets refusés

Surveillants pour un flux particulier


Afin d’obtenir des statistiques pour un flot particulier, on utilise des objets flow monitor. On peut
alors connaître le nombre de paquets perdus pour un flot particulier. Pour cela, la syntaxe est la suivante :

$udp set fid_ 1 # donne un identifiant à un flux udp


$tcp set fid_ 2 # donne un identifiant à un flux tcp
set flowmon [$ns makeflomon Fid] # definition d’un flow monitor à partir de
# l’identifiant de flux défini précédemment
set lien [$ns link $S $D] # récupération du lien entre les noeuds S et D
$ns attach-fmon $lien $flowmon # le flowmon est greffé sur le lien
set fcl [$flowmon classifier] # fonction permettant de classer les flux selon
# leur identité

À la fin d’une simulation, on voudra par exemple connaître le nombre de paquets perdus pour les
flots tcp et udp. On écrira alors dans la procédure finish :

5
set stats_tcp [$fcl lookup auto 0 0 2] # 2 correspond à l’identifiant du flot tcp (fid_)
set stats_udp [$fcl lookup auto 0 0 1]

puts stdout "[$stats_tcp set pdrops_]"


puts stdout "[$stats_udp set pdrops_]"

Il existe bien évidemment d’autres attributs associés à un flow monitor comme par exemple pdepartures_
ou barrivals_.
Attention : l’appel aux procédures classifier et lookup doit être fait que lorsqu’on est sûr qu’au
moins un paquet de chaque flot a déjà été traité par un flow monitor. Par conséquent, si vous désirez
obtenir des statistiques pour un flux au cours du temps (probabilité de perte, débit), il est nécessaire de
faire appel à la fonction suivante quelques secondes après le début de la génération des paquets par cette
source :

proc init_udp {} {
global flowmon fcl flowstats_udp

set fcl [$flowmon classifier]


set flowstats_udp [$fcl lookup auto 0 0 1]
}

$ns at xx "init_udp"

On utilise ensuite l’objet flowstats_udp dans une fonction que vous définissez pour obtenir les
valeurs des attributs désirées.
Lors des expériences, vous serez amener à faire des statistiques (taux de perte, débit, etc. . .). Sous
(O)TCl, le traitement des nombres est assez particulier. Si vous voulez par exemple mesurer le taux de
perte de paquets et que vous connaissez le nombre de paquets perdus et le nombre de paquets générés,
vous calculez le taux de perte à l’aide de syntaxe suivante :
set taux_perte [expr [format %f $nb_paquets_perdus] / [format %f $nb_paquets_générés]]

La commande format vous permet de convertir un nombre et la syntaxe est similaire à celle du C.

2 Visualisation des paquets sous nam


Le logiciel nam permet de visualiser le réseau et les paquets qui circulent. Cela permet de se rendre
compte des flots qui parcourent le réseau, et également de localiser des problèmes dans une simulation.
Le fonctionnement de nam est “post mortem” : pour l’utiliser, il faut d’abord effectuer une simulation
par ns en demandant à ce que soit créée une trace. Ceci se fait (voir plus haut) en insérant, avant la
création des objets de la simulation, quelque chose comme :

set namFile [open "model.nam" w] # ouverture du flot/fichier de sortie


$ns namtrace-all $namFile # instruction de trace pour nam

Attention : il faut exécuter l’instruction namtrace-all avant de créér la topologie du réseau, sinon cela
ne marchera pas.
Une fois la simulation finie, on appelle nam en passant le nom du fichier trace en argument, ou bien
en le chargeant à partir de l’interface graphique.
Il est possible d’utiliser des couleurs pour visualiser les paquets provenant de la source TCP et de la
source UDP. Pour cela, il suffit de donner un numéro de classe aux agents TCP et UDP de la manière
suivante :
$udp set class_ 1
$tcp set class_ 2

Vous associez ensuite à chacune des deux classes une couleur :

6
$ns color 1 Blue
$ns color 2 Red
et vous regardez ensuite le résultat sous nam.
D’autres instructions utiles pour contrôler l’apparence du réseau dans nam sont :

$node color green


$node label "Origine"
duplex-link-op orient right
duplex-link-op orient left-up
duplex-link-op $orig $dest queuePos 0.5

Elles ont pour effet, respectivement, de colorier et mettre une étiquette à un nœud, de fixer l’orientation
des liens, et de faire apparaître la file d’attente pour le lien en question, avec un angle de 90o (c’est-à-dire :
0.5 × 180o ) par rapport à l’horizontale.

3 Micro-manuel de gnuplot
gnuplot est un outil permettant de dessiner des courbes, soit à partir de fonction définies par l’uti-
lisateur, soit à partir d’un fichier contenant des couples de points.
gnuplot fonctionne habituellement en mode interactif. On entre “gnuplot” (on obtient le “prompt”
gnuplot>), et on entre des commandes. On peut également mettre ces commandes dans un fichier et le
passer en argument à gnuplot. Le programme exécute alors les commandes et termine. Ceci est surtout
utile quand les graphes sont produits dans un fichier (PS, PDF ou autre).
Ces commandes peuvent être par exemple :
>? demande d’aide générale
> help idem
> ?plot demande d’aide sur la fonction “plot”
> lambda=0.5 définition d’un paramètre (une variable) lambda
> f(x) = sin(x)+lambda*x définition d’une fonction de la variable x
> plot [0:10] f(x) dessin de la fonction f sur l’intervalle 0 ≤ x ≤ 10
> plot [0:10] [0:5] f(x) idem mais en restreignant les y à l’intervalle [0, 5]
> set xrange [0:5] fixe l’intervalle des valeurs pour l’axe des abscisses
> plot "toto.dat" dessin du fichier de données toto.dat
> plot "toto.dat" with lines dessin du fichier de données toto.dat en reliant les points
par des droites
> plot "toto.dat" with steps idem mais avec des marches
> plot "toto.dat" with dots idem mais avec des points plus petits
> plot "toto.dat" using ($2):($1) idem, mais en intervertissant x et y (voir le manuel de using).
> plot "toto.dat", f(x) dessin simultané de données et d’une fonction.
> set term postscript configure le format de sortie des graphiques : ici à PostScript.
> set term donne la liste des formats disponibles.
Les fichiers de données acceptés par gnuplot sont formés de nombres, un ou deux par ligne. On peut
utiliser le symbole # pour commenter des lignes. Exemple :
# Fichier de données pour gnuplot crée le 5 mars 2003 en TP
# Première colonne: numéro de client n
# Seconde colonne : date d’arrivée a(n)
#
1 0.234
2 1.456
3 2.789
...
Si on omet la première colonne, gnuplot la remplacera par les abscisses 1,2, etc. Cette colonne
supplémentaire est numérotée “0” quand on utilise plot ... using. Ainsi :
> plot "toto.dat" using 1:0 renverse x et y dans le cas d’une seule colonne.
> plot "toto.dat" using 2:1 renverse x et y dans le cas de deux colonnes.

7
Enfin, il est possible de spécifier des opérations à faire sur les données avant de les placer sur le
graphique. Par exemple :
> plot "toto.dat" using 0:(log($1)/4.0) pour la coordonnée y, remplace la valeur v
de la première colonne par log(v)/4.
D’autres commandes utiles pour décorer les graphiques sont :
> plot "toto.dat" with linespoints variation sur la forme des lignes
> set xlabel "abracadabra" met un titre sur l’axe des abscisses
> set ylabel "hocuspocus" idem pour les ordonnees
> set title "titre de la courbe" met un titre à la courbe

Vous aimerez peut-être aussi