Manuel de simulation de réseau ns-3. Chapitre 4

Manuel de simulation de réseau ns-3. Chapitre 4
chapitres 1,2
chapitre 3

4 Aperçu du concept
4.1 Abstractions clés
4.1.1 Node (NƓud)
4.1.2 Application (Application)
4.1.3 Channel (Canal)
4.1.4 Net Device (Dispositif réseau)
4.1.5 Assistants topologiques
4.2 Premier script ns-3
4.2.1 Code boilerplate
4.2.2 Modules connectés
4.2.3 Espace de noms ns3
4.2.4 Journalisation
4.2.5 Fonction principale
4.2.6 Utilisation des assistants topologiques
4.2.7 Utilisation de l'Application
4.2.8 Simulateur
4.2.9 Assemblage de votre scénario
4.3 Code source de ns-3

Chapitre 4

Aperçu du concept

La premiÚre chose que nous devons faire avant de commencer à étudier ou à écrire du code ns-3 est d'expliquer quelques concepts fondamentaux et abstractions dans le systÚme. Beaucoup d'entre eux peuvent sembler évidents pour certains, mais nous vous recommandons de prendre le temps de lire cette section pour vous assurer que vous commencez sur une base solide.

4.1 Abstractions clés

Dans cette section, nous examinerons certains termes qui sont généralement utilisés dans le réseau, mais qui ont une signification particuliÚre dans ns-3.

4.1.1 Node (NƓud)

Dans le jargon Internet, un dispositif informatique qui se connecte au rĂ©seau est appelĂ© un hĂŽte ou parfois un systĂšme terminal. Pour cette raison, Ă©tant donnĂ© que ns-3 est un simulateur de rĂ©seau et non un simulateur Internet, nous Ă©vitons dĂ©libĂ©rĂ©ment d'utiliser le terme hĂŽte, car il est Ă©troitement liĂ© Ă  Internet et Ă  ses protocoles. À la place, nous utilisons un terme plus gĂ©nĂ©ral, Ă©galement utilisĂ© par d'autres simulateurs, qui trouve son origine dans la thĂ©orie des graphes : nƓud (node).

Dans ns-3, l'abstraction de base d'un dispositif informatique est appelĂ©e nƓud. Cette abstraction est reprĂ©sentĂ©e en C++ par la classe Node. La classe NodeNode (nƓud) fournit des mĂ©thodes pour gĂ©rer les reprĂ©sentations des dispositifs informatiques dans les simulations.

Vous devez comprendre NƓud comme un ordinateur auquel vous ajouterez des fonctionnalitĂ©s. Vous ajoutez des choses telles que des applications, des piles de protocoles et des cartes d'extension avec des pilotes, permettant Ă  l'ordinateur d'effectuer un travail utile. Nous utilisons le mĂȘme modĂšle de base dans ns-3.

4.1.2 Application (Application)

En général, les logiciels informatiques se divisent en deux grandes catégories. Les logiciels systÚme organisent diverses ressources informatiques telles que la mémoire, les cycles du processeur, le disque, le réseau, etc., selon un certain modÚle de calcul. Les logiciels systÚme n'utilisent généralement pas ces ressources pour effectuer des tùches qui apportent un bénéfice direct à l'utilisateur. Pour atteindre un objectif spécifique, l'utilisateur lance généralement une application qui obtient et utilise les ressources contrÎlées par le logiciel systÚme.

Souvent, la ligne de sĂ©paration entre le logiciel systĂšme et le logiciel applicatif se trace au niveau du changement de privilĂšges qui se produit dans les appels systĂšmes. Dans ns‑3, il n'y a pas de vĂ©ritable concept de systĂšme d'exploitation et donc pas de notions de niveaux de privilĂšges ou d'appels systĂšme. Cependant, nous avons l'idĂ©e d'application. Tout comme dans le "monde rĂ©el", pour accomplir des tĂąches, les applications fonctionnent sur des ordinateurs, les applications ns‑3 fonctionnent sur les nƓuds ns‑3 pour gĂ©rer les simulations dans un monde simulĂ©.

Dans ns‑3, l'abstraction de base pour un programme utilisateur qui gĂ©nĂšre une certaine activitĂ© pour la modĂ©lisation est l'application. Cette abstraction est reprĂ©sentĂ©e en C++ par la classe Application. La classe Application fournit des mĂ©thodes pour gĂ©rer dans les simulations les reprĂ©sentations de notre version des applications de niveau utilisateur. Il est attendu des dĂ©veloppeurs qu'ils spĂ©cialisent la classe Application pour crĂ©er de nouvelles applications dans un sens orientĂ© objet. Dans ce guide, nous utiliserons les spĂ©cialisations de la classe Application, appelĂ©es UdpEchoClientApplication et UdpEchoServerApplication. Comme il fallait s'y attendre, ces applications constituent un ensemble d'applications client/serveur utilisĂ©es pour gĂ©nĂ©rer et simuler des paquets rĂ©seau en Ă©cho.

4.1.3 Channel (Canal)

Dans le monde rĂ©el, un ordinateur peut ĂȘtre connectĂ© Ă  un rĂ©seau. Souvent, les milieux par lesquels les donnĂ©es sont transmises dans ces rĂ©seaux sont appelĂ©s des canaux. Lorsque vous connectez un cĂąble Ethernet Ă  une prise murale, vous connectez l'ordinateur Ă  un canal de communication Ethernet. Dans le monde simulĂ© de ns‑3, un nƓud est connectĂ© Ă  un objet reprĂ©sentant un canal de communication. Ici, la principale abstraction de la sous-rĂ©seau de communication est appelĂ©e canal et est reprĂ©sentĂ©e dans C++ par la classe Channel.

Classe ChannelChannel fournit des mĂ©thodes pour gĂ©rer l'interaction des objets de sous-rĂ©seau et leur connexion Ă  des nƓuds. Les canaux peuvent Ă©galement ĂȘtre spĂ©cialisĂ©s par les dĂ©veloppeurs en termes de programmation orientĂ©e objet. La spĂ©cialisation d'un canal peut modĂ©liser quelque chose d'aussi simple qu'un fil. Un canal spĂ©cialisĂ© peut Ă©galement modĂ©liser des choses complexes comme un grand commutateur Ethernet ou un espace tridimensionnel rempli d'obstacles dans le cas des rĂ©seaux sans fil.

Nous allons utiliser dans ce guide des versions spécialisées de canal appelées CsmaChannelCsmaChannel, PointToPointChannelPointToPointChannel et WifiChannelWifiChannel. CsmaChannel, par exemple, modélise une version de la sous-réseau de communication qui implémente un environnement de communication à accÚs multiple avec contrÎle de porteuse. Cela nous donne une fonctionnalité similaire à celle de l'Ethernet.

4.1.4 Net Device (Dispositif réseau)

Auparavant, si vous vouliez connecter un ordinateur Ă  un rĂ©seau, vous deviez acheter un cĂąble rĂ©seau spĂ©cifique et un dispositif matĂ©riel appelĂ© (dans le jargon PC) carte d'extension, qui devait ĂȘtre installĂ©e dans l'ordinateur. Si certaines fonctions rĂ©seau Ă©taient implĂ©mentĂ©es sur la carte d'extension, elles Ă©taient appelĂ©es cartes d'interface rĂ©seau ou cartes rĂ©seau. Aujourd'hui, la plupart des ordinateurs sont Ă©quipĂ©s de matĂ©riel d'interface rĂ©seau intĂ©grĂ©, et les utilisateurs ne les considĂšrent pas comme des dispositifs sĂ©parĂ©s.

Une carte réseau ne fonctionnera pas sans un pilote logiciel qui gÚre son matériel. Dans Unix (ou Linux), une partie du matériel est classée comme un périphérique. Les périphériques sont gérés à l'aide de pilotes de périphérique, et les dispositifs réseau (NIC) sont gérés à l'aide de pilotes de dispositifs réseau (network device drivers) et ont un terme collectif appelé dispositifs réseau (net devices). Dans Unix et Linux, vous accédez aux périphériques réseau par des noms tels que eth0.

Dans ns-3, l'abstraction du pĂ©riphĂ©rique rĂ©seau englobe Ă  la fois le pilote logiciel et le matĂ©riel simulĂ©. Lors de la simulation, le pĂ©riphĂ©rique rĂ©seau est « installĂ© » dans un nƓud pour lui permettre de communiquer avec d'autres nƓuds via des canaux. Comme sur un ordinateur rĂ©el, un nƓud peut ĂȘtre connectĂ© Ă  plusieurs canaux via plusieurs pĂ©riphĂ©riques. NetDevices.

L'abstraction rĂ©seau du pĂ©riphĂ©rique est reprĂ©sentĂ©e dans la classe C++ NetDevice. La classe NetDevice fournit des mĂ©thodes pour gĂ©rer les connexions avec les objets Node et Channel ; et peut ĂȘtre spĂ©cialisĂ©e par les dĂ©veloppeurs en termes de programmation orientĂ©e objet. Dans ce guide, nous utiliserons plusieurs versions spĂ©cialisĂ©es de NetDevice appelĂ©es CsmaNetDevice, PointToPointNetDevice et WifiNetDevice. Tout comme l'adaptateur rĂ©seau Ethernet est conçu pour fonctionner avec le Ethernet, CsmaNetDevice est conçu pour fonctionner avec le CsmaChannel, PointToPointNetDevice est conçu pour fonctionner avec le PointToPointChannel, et WifiNetDevice — est conçu pour fonctionner avec le WifiChannel.

4.1.5 Assistants topologiques

Dans un rĂ©seau rĂ©el, vous trouverez des ordinateurs hĂŽtes avec des cartes rĂ©seau ajoutĂ©es (ou intĂ©grĂ©es). Dans ns-3, nous dirions que vous verrez des nƓuds avec des NetDevices connectĂ©s. Dans un grand rĂ©seau simulĂ©, vous devrez organiser des connexions entre plusieurs objets. NƓud, NetDevice et Channel.

Étant donnĂ© que la connexion des NetDevices aux nƓuds, des NetDevices aux canaux, l'attribution d'adresses IP, etc. dans ns-3 sont des tĂąches courantes, afin de rendre cela aussi simple que possible, nous fournissons ce qu'on appelle des helpers topologiques. Par exemple, pour crĂ©er un NetDevice, vous devez effectuer de nombreuses opĂ©rations dans le cƓur de ns-3, ajouter une adresse MAC, installer ce pĂ©riphĂ©rique rĂ©seau dans un Node, configurer la pile de protocoles du nƓud, puis connecter le NetDevice au Channel. Encore plus d'opĂ©rations seront nĂ©cessaires pour connecter plusieurs pĂ©riphĂ©riques Ă  des canaux multipoints, puis relier des rĂ©seaux distincts Ă  un rĂ©seau unifiĂ© (Internetworks). Nous fournissons des objets d'assistance topologique qui, pour votre commoditĂ©, regroupent ces nombreuses opĂ©rations dans un modĂšle facile Ă  utiliser.

4.2 Premier script ns-3

Si vous avez installé le systÚme comme suggéré ci-dessus, vous aurez un release ns-3 dans un répertoire nommé repos dans votre répertoire personnel. Accédez au répertoire release

Si vous n'avez pas ce rĂ©pertoire, cela signifie que vous n'avez pas spĂ©cifiĂ© le rĂ©pertoire de sortie lors de la compilation de la version de ns‑3, exĂ©cutez la compilation comme suit :
$ ./waf configure --build-profile=release --out=build/release,
$ ./waf build

là, vous devriez voir une structure de répertoire ressemblant à ceci :

AUTHORS       examples      scratch       utils       waf.bat*
bindings      LICENSE       src           utils.py    waf-tools
build         ns3           test.py*      utils.pyc   wscript
CHANGES.html  README        testpy-output VERSION     wutils.py
doc           RELEASE_NOTES testpy.supp   waf*        wutils.pyc

Allez dans le rĂ©pertoire examples/tutorial. Vous devriez voir un fichier nommĂ© first.cc. C'est un script qui crĂ©era une connexion point Ă  point simple entre deux nƓuds et transmettra un paquet entre eux. Regardons ce script ligne par ligne, alors ouvrons first.cc dans votre Ă©diteur prĂ©fĂ©rĂ©.

4.2.1 Code boilerplate
La premiÚre ligne du fichier est la ligne de mode de l'éditeur emacs. Elle indique à emacs les conventions de formatage (style de codage) que nous utiliserons dans notre code source.

/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */

C'est toujours une question assez polĂ©mique, donc nous devons clarifier pour l’évacuer immĂ©diatement. Le projet ns‑3, comme la plupart des grands projets, a adoptĂ© un style de codage auquel tout le code fourni doit se conformer. Si vous souhaitez contribuer votre code au projet, vous devrez finalement vous conformer au standard de codage de ns‑3, tel que dĂ©crit dans le fichier doc/codingstd.txt ou prĂ©sentĂ© sur la page web du projet : https://www.nsnam.org/develop/contributing-code/coding-style/.

Nous vous recommandons de vous habituer Ă  l’apparence du code ns‑3 et d'appliquer ce standard chaque fois que vous travaillez avec notre code. Toute l'Ă©quipe de dĂ©veloppement et les contributeurs sont d'accord avec cela aprĂšs un peu de grognement. La ligne de mode emacs ci-dessus facilite le bon formatage si vous utilisez l'Ă©diteur emacs.

Le simulateur ns‑3 est sous licence avec la GNU General Public License. Vous verrez l'en-tĂȘte lĂ©gal correspondant de la GNU dans chaque fichier de distribution de ns‑3. Vous pouvez souvent voir un avis de droit d'auteur pour l'une des institutions participant au projet ns‑3 au-dessus du texte de la GPL et de l'auteur, affichĂ© ci-dessous.

/* 
* This program is free software; you can redistribute it and/or modify 
* it under the terms of the GNU General Public License version 2 as 
* published by the Free Software Foundation; 
*
* This program is distributed in the hope that it will be useful, 
* but WITHOUT ANY WARRANTY; without even the implied warranty of 
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
* GNU General Public License for more details. 
* 
* You should have received a copy of the GNU General Public License 
* along with this program; if not, write to the Free Software 
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
*/

4.2.2 Modules connectés

Le code proprement dit commence par une série d'instructions d'inclusion (include).

#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"

Pour aider nos utilisateurs de scripts de haut niveau Ă  gĂ©rer le grand nombre de fichiers d'en-tĂȘte prĂ©sents dans le systĂšme, nous les regroupons selon leur utilisation en grands modules. Nous fournissons un fichier d'en-tĂȘte qui chargera rĂ©cursivement tous les fichiers d'en-tĂȘte utilisĂ©s dans ce module. Au lieu de chercher quel en-tĂȘte vous avez besoin et de peut-ĂȘtre obtenir la bonne liste de dĂ©pendances, nous vous offrons la possibilitĂ© de charger un groupe de fichiers avec un grand niveau de dĂ©tails. Ce n'est pas la mĂ©thode la plus efficace, mais elle rend certainement l'Ă©criture de scripts beaucoup plus simple.

Chacun des fichiers inclus dans ns‑3 est placĂ© dans un rĂ©pertoire nommĂ© ns3 (sous-rĂ©pertoire de construction), afin d'Ă©viter les conflits de noms de fichiers pendant le processus de construction. Le fichier ns3/core-module.h correspond au module ns‑3 que vous trouverez dans le rĂ©pertoire src/core dans la version que vous avez installĂ©e. Dans la liste de ce rĂ©pertoire, vous trouverez un grand nombre de fichiers d'en-tĂȘte. Lorsque vous faites une construction, Waf place les fichiers d'en-tĂȘte publics dans le rĂ©pertoire ns3 dans le sous-rĂ©pertoire build/debug

Si vous n'avez pas ce rĂ©pertoire, cela signifie que vous n'avez pas spĂ©cifiĂ© le rĂ©pertoire de sortie lors de la compilation de la version de ns‑3, exĂ©cutez la compilation comme suit :
$ ./waf configure --build-profile=debug --out=build/debug
$ ./waf build
ou
$ ./waf configure --build-profile=optimized --out=build/optimized
$ ./waf build

ou build/optimized, selon votre configuration. Waf gĂ©nĂšre Ă©galement automatiquement un fichier d'inclusion de module pour charger tous les fichiers d'en-tĂȘte publics. Puisque vous suivez bien sĂ»r ce guide Ă  la lettre, vous avez dĂ©jĂ  effectuĂ©

$ ./waf -d debug --enable-examples --enable-tests configure

pour configurer le projet pour effectuer des constructions de débogage, y compris des exemples et des tests. Vous avez également exécuté

$ ./waf

pour construire le projet. Donc maintenant, lorsque vous regardez dans le rĂ©pertoire ../..../build/debug/ns3, vous trouverez parmi d'autres les fichiers d'en-tĂȘte des quatre modules mentionnĂ©s ci-dessus. Vous pouvez jeter un coup d'Ɠil au contenu de ces fichiers et constater qu'ils incluent tous les fichiers publics utilisĂ©s par les modules correspondants.

4.2.3 Espace de noms ns3

La ligne suivante dans le script first.cc est la déclaration de l'espace de noms.

using namespace ns3;

Le projet ns‑3 est rĂ©alisĂ© dans l'espace de noms C++ appelĂ© ns3. Cela regroupe toutes les dĂ©clarations liĂ©es Ă  ns‑3 en dehors de l'espace de noms global, ce qui, nous l'espĂ©rons, facilitera l'intĂ©gration avec d'autres codes. L'utilisation de l'opĂ©rateur C++ introduit l'espace de noms ns‑3 dans la rĂ©gion dĂ©clarative actuelle (globale). C'est une maniĂšre Ă©laborĂ©e de dire qu'aprĂšs cette dĂ©claration, vous n'aurez plus besoin d'utiliser l'opĂ©rateur de rĂ©solution ns3::scope devant tout le code ns‑3 pour l'utiliser. Si vous n'ĂȘtes pas familier avec les espaces de noms, consultez pratiquement n'importe quel manuel de C++ et comparez l'espace de noms ns3 avec l'utilisation de l'espace de noms std et des dĂ©clarations. using namespace std; dans les exemples travaillant avec l'opĂ©rateur de sortie cout et les flux.

4.2.4 Journalisation

La ligne suivante du script est la suivante :

NS_LOG_COMPONENT_DEFINE ("FirstScriptExample");

Nous utiliserons cette dĂ©claration comme un point pratique pour discuter de notre systĂšme de documentation. DoxygenSi vous regardez le site web du projet ns‑3, vous trouverez un lien vers « Documentation » dans la barre de navigation. Si vous cliquez sur ce lien, vous serez dirigĂ© vers notre page de documentation. Il y a un lien vers le « Dernier release », qui vous mĂšnera Ă  la documentation de la derniĂšre version stable de ns‑3. Si vous choisissez le lien « API Documentation », vous accĂ©derez Ă  la page de la documentation API de ns‑3.

Sur le cĂŽtĂ© gauche de la page, vous trouverez une reprĂ©sentation graphique de la structure de la documentation. Un bon point de dĂ©part est le « livre » Modules ns‑3 dans l'arborescence de navigation ns‑3. Si vous dĂ©veloppez Modules, vous verrez une liste de la documentation des modules ns‑3. Comme discutĂ© ci-dessus, le concept de module ici est directement liĂ© aux fichiers inclus dans le module ci-dessus. Le sous-systĂšme de journalisation (logging) de ns‑3 est discutĂ© dans la section Utilisation du module de journalisation, donc nous y reviendrons plus tard dans ce guide, mais vous pouvez en apprendre davantage sur la dĂ©claration ci-dessus en consultant le module Noyau, puis en ouvrant le livre Outils de dĂ©bogage, puis en sĂ©lectionnant la page Journalisation. Cliquez sur Journalisation.

Vous devez maintenant consulter la documentation Doxygen pour le module. Journalisation. Dans la liste des macros en haut de la page, vous verrez une entrĂ©e pour NS_LOG_COMPONENT_DEFINE. Avant de cliquer sur le lien, assurez-vous de consulter la « Description dĂ©taillĂ©e » du module de journalisation afin de comprendre son fonctionnement global. Pour cela, vous pouvez faire dĂ©filer vers le bas ou sĂ©lectionner « Plus
 » sous le diagramme.

Une fois que vous avez une vue d'ensemble de ce qui se passe, allez-y et consultez la documentation sur le NS_LOG_COMPONENT_DEFINE spécifique. Je ne vais pas dupliquer la documentation ici, mais en résumé, cette ligne déclare un composant de journalisation nommé FirstScriptExample, qui permet d'activer et de désactiver l'enregistrement des messages dans la console par un lien sur le nom.

4.2.5 Fonction principale

Dans les lignes suivantes du script, vous verrez

int 
main (int argc, char *argv[])
{ 

C'est simplement la déclaration de la fonction principale de votre programme (script). Comme dans tout programme en C++, vous devez définir la fonction principale, qui s'exécute en premier. Il n'y a rien de spécial ici. Votre script ns-3 est simplement un programme C++. La ligne suivante définit la résolution temporelle à 1 nanoseconde, ce qui est la valeur par défaut :

Time::SetResolution (Time::NS);

La rĂ©solution temporelle ou simplement la rĂ©solution est la plus petite valeur temporelle pouvant ĂȘtre utilisĂ©e (la plus petite diffĂ©rence reprĂ©sentable entre deux valeurs temporelles). Vous ne pouvez changer la rĂ©solution qu'une seule fois. Le mĂ©canisme qui permet cette flexibilitĂ© consomme de la mĂ©moire, donc une fois que la rĂ©solution est explicitement dĂ©finie, nous libĂ©rons la mĂ©moire, empĂȘchant ainsi de futures mises Ă  jour. (Si vous ne dĂ©finissez pas explicitement la rĂ©solution, elle sera par dĂ©faut d'une nanoseconde, et la mĂ©moire sera libĂ©rĂ©e au dĂ©but de la simulation.)

Les deux lignes suivantes du script sont utilisées pour activer deux composants de journalisation intégrés aux applications EchoClient et EchoServer:

LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO); LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);

Si vous avez lu la documentation du composant Logging, vous remarquerez qu'il existe plusieurs niveaux de dĂ©tail d'enregistrement que vous pouvez activer sur chaque composant. Ces deux lignes de code activent la journalisation de dĂ©bogage au niveau INFO pour les clients et serveurs Ă©cho. À ce niveau, l'application imprimera des messages lors de l'envoi et de la rĂ©ception de paquets pendant la simulation.

Nous allons maintenant passer directement à la création de la topologie et au démarrage de la simulation. Nous utiliserons des objets d'assistance topologique pour faciliter cette tùche.

4.2.6 Utilisation des assistants topologiques

Les deux lignes suivantes de code dans notre script vont en fait créer des objets Node ns-3 qui représenteront des ordinateurs dans la simulation.

NodeContainer nodes;
nodes.Create(2);

Avant de continuer, trouvons la documentation pour la classe NodeContainer. Une autre façon d'accéder à la documentation pour cette classe est à travers l'onglet Classes sur les pages Doxygen. Si vous avez déjà ouvert Doxygen, faites simplement défiler vers le haut de la page et sélectionnez l'onglet Classes. Vous devriez voir un nouvel ensemble d'onglets, dont l'un liste les classes. Sous cet onglet, vous verrez la liste de toutes les classes ns-3. Faites défiler vers le bas jusqu'à ns3::NodeContainer. Lorsque vous trouvez la classe, sélectionnez-la pour accéder à la documentation de cette classe.

Comme nous le savons, l'une de nos abstractions clĂ©s est le nƓud. Il reprĂ©sente un ordinateur auquel nous allons ajouter des Ă©lĂ©ments tels que des piles de protocoles, des applications et des cartes pĂ©riphĂ©riques. L'assistant topologique NodeContainer offre un moyen pratique de crĂ©er, gĂ©rer et accĂ©der Ă  tous les objets NƓud, que nous crĂ©ons pour lancer la simulation. La premiĂšre ligne ci-dessus dĂ©clare simplement NodeContainer, que nous appelons nodes. La deuxiĂšme ligne appelle la mĂ©thode Create pour l'objet nodes et demande au conteneur de crĂ©er deux nƓuds. Comme dĂ©crit dans Doxygen, le conteneur demande Ă  la systĂšme ns-3 de crĂ©er deux objets NƓud et conserve les pointeurs vers ces objets Ă  l'intĂ©rieur.

Les nƓuds créés dans le script ne font rien pour le moment. La prochaine Ă©tape dans la construction de la topologie est de connecter nos nƓuds au rĂ©seau. La forme de rĂ©seau la plus simple que nous soutenons est une connexion point Ă  point entre deux nƓuds. Nous allons maintenant Ă©tablir cette connexion.

PointToPointHelper

Nous établissons une connexion bidirectionnelle en suivant un modÚle familier, utilisant un objet auxiliaire topologique pour effectuer le travail de bas niveau nécessaire à la connexion. Rappelons que nos deux principales abstractions NetDevice et Channel. Dans le monde réel, ces termes correspondent grosso modo à des cartes de périphériques et à des cùbles réseau. En général, ces deux éléments sont étroitement liés, et personne ne peut compter sur l'échange, par exemple, d'appareils Ethernet via un canal sans fil. Nos aides topologiques suivent cette connexion étroite, et donc, dans ce scénario, vous utiliserez un seul objet PointToPointHelper pour configurer et connecter des objets ns-3 PointToPointNetDevice et PointToPointChannel. Les trois lignes suivantes dans le script :

PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps")); 
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));

La premiĂšre ligne,

PointToPointHelper pointToPoint;

crée une instance de l'objet dans la pile PointToPointHelper. Du point de vue de haut niveau, la ligne suivante,

pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));

indique à l'objet PointToPointHelper d'utiliser la valeur « 5 Mbps » (cinq mégabits par seconde) comme «DataRate».

D'un point de vue plus spécifique, la ligne « DataRate » correspond à ce que nous appelons un attribut PointToPointNetDevice. Si vous regardez Doxygen pour la classe ns3::PointToPointNetDevice et dans la documentation de la méthode GetTypeId vous trouverez une liste des attributs définis pour le dispositif. Parmi eux, il y aura l'attribut «DataRate». La plupart des objets visibles par l'utilisateur de ns-3 ont des listes d'attributs similaires. Nous utilisons ce mécanisme pour configurer simplement la simulation sans recompilation, comme vous le verrez dans la section suivante.

De mĂȘme que «DataRate» dans PointToPointNetDevice, vous trouverez l'attribut « Delay », associĂ© Ă  PointToPointChannel. La ligne finale,

pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));

dit PointToPointHelper utilise la valeur « 2 ms » (deux millisecondes) comme valeur de délai de propagation sur le canal point à point qu'il crée ensuite.

NetDeviceContainer

À ce stade, notre script contient NodeContainer, qui contient deux nƓuds. Nous avons PointToPointHelper, qui est prĂ©parĂ© pour crĂ©er des objets PointToPointNetDevices et les connecter Ă  l'aide d'un objet PointToPointChannel. Tout comme nous avons utilisĂ© un objet auxiliaire de topologie NodeContainer pour crĂ©er des nƓuds, nous demanderons Ă  PointToPointHelper de s'occuper pour nous de la crĂ©ation, de la configuration et de la mise en place de nos dispositifs. Nous aurons besoin d'une liste de tous les objets créés NetDevice, c'est pourquoi nous utilisons NetDeviceContainer pour leur stockage de la mĂȘme maniĂšre que nous avons utilisĂ© NodeContainer pour le stockage des nƓuds que nous avons créés. Les deux lignes de code suivantes,

NetDeviceContainer devices;
devices = pointToPoint.Install (nodes);

terminent la configuration des appareils et du canal. La premiĂšre ligne dĂ©clare le conteneur d'appareils mentionnĂ© ci-dessus, et la seconde exĂ©cute le travail principal. La mĂ©thode Installer de l'installation PointToPointHelper prend NodeContainer comme paramĂštre. À l'intĂ©rieur NetDeviceContainer pour chaque nƓud prĂ©sent dans NodeContainer est créé (pour la communication point Ă  point, il doit y en avoir exactement deux) PointToPointNetDevice est créé et stockĂ© dans le conteneur d'appareils. PointToPointChannel est créé, et deux y sont joints PointToPointNetDevices. Une fois les objets créés, les attributs stockĂ©s dans PointToPointHelper, sont utilisĂ©s pour initialiser les attributs correspondants dans les objets créés.

AprĂšs l'appel de pointToPoint.Install (nodes) , nous aurons deux nƓuds, chacun avec un dispositif rĂ©seau "point Ă  point" installĂ© et un canal "point Ă  point" entre eux. Les deux appareils seront configurĂ©s pour transmettre des donnĂ©es Ă  une vitesse de cinq mĂ©gabits par seconde avec un dĂ©lai de transmission sur le canal de deux millisecondes.

InternetStackHelper

Nous avons maintenant configurĂ© les nƓuds et les dispositifs, mais nos nƓuds n'ont pas de piles de protocoles installĂ©es. Les deux lignes de code suivantes s'occuperont de cela.

InternetStackHelper stack;
stack.Install (nodes);

InternetStackHelper reprĂ©sente un assistant topologique pour les piles Internet, semblable Ă  PointToPointHelper pour les dispositifs rĂ©seau Ă  deux points. La mĂ©thode Installer prend NodeContainer comme paramĂštre. Lors de l'exĂ©cution, elle installera la pile Internet (TCP, UDP, IP, etc.) sur chaque nƓud du conteneur.

Ipv4AddressHelper

Ensuite, nous devons associer nos dispositifs aux adresses IP. Nous fournissons un assistant topologique pour gérer la distribution des adresses IP. La seule API visible pour l'utilisateur est la configuration de l'adresse IP de base et du masque de réseau à utiliser lors de la distribution effective des adresses (cela se fait à un niveau inférieur au sein de l'assistant). Les deux lignes de code suivantes dans notre exemple de script first.cc,

Ipv4AddressHelper address;
address.SetBase ("10.1.1.0", "255.255.255.0");

dĂ©clare un objet auxiliaire d'adresse et lui indique qu'il doit commencer Ă  attribuer des adresses IP Ă  partir du rĂ©seau 10.1.1.0, en utilisant le masque de sous-rĂ©seau 255.255.255.0 pour la dĂ©termination. Par dĂ©faut, les adresses attribuĂ©es commenceront par un et augmenteront de maniĂšre monotone, ainsi la premiĂšre adresse attribuĂ©e de cette plage sera 10.1.1.1, puis 10.1.1.2, etc. En rĂ©alitĂ©, au niveau le plus bas, le systĂšme ns-3 mĂ©morise toutes les adresses IP attribuĂ©es et gĂ©nĂšre une erreur fatale si vous avez accidentellement créé une situation oĂč la mĂȘme adresse est gĂ©nĂ©rĂ©e deux fois (d'ailleurs, cette erreur est difficile Ă  dĂ©boguer).

La ligne de code suivante,

Ipv4InterfaceContainer interfaces = address.Assign (devices);

effectue l'attribution effective de l'adresse. Dans ns-3, nous établissons une liaison entre l'adresse IP et le dispositif en utilisant l'objet Ipv4Interface. Tout comme nous avons parfois besoin d'une liste des dispositifs réseau créés par l'assistant pour une utilisation ultérieure, nous avons parfois besoin d'une liste d'objets Ipv4Interface. Ipv4InterfaceContainer fournit cette fonctionnalité.

Nous avons construit un rĂ©seau point Ă  point, avec des piles installĂ©es et des adresses IP attribuĂ©es. Maintenant, nous avons besoin d'applications sur chaque nƓud pour gĂ©nĂ©rer du trafic.

4.2.7 Utilisation de l'Application

Une autre des abstractions clés du systÚme ns-3 est Application (application). Dans ce scénario, nous utilisons deux spécialisations de la classe de base Application ns-3 appelée UdpEchoServerApplication et UdpEchoClientApplication. Comme dans les cas précédents, nous utilisons des objets auxiliaires pour configurer et gérer les objets de base. Ici, nous utilisons UdpEchoServerHelper et UdpEchoClientHelperdes objets pour nous simplifier la vie.

UdpEchoServerHelper

Les lignes de code suivantes dans notre exemple de script first.cc sont utilisĂ©es pour configurer l'application de serveur UDP Ă©cho sur l'un des nƓuds que nous avons créés prĂ©cĂ©demment.

UdpEchoServerHelper echoServer (9);

ApplicationContainer serverApps = echoServer.Install (nodes.Get (1));
serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));

La premiĂšre ligne de code dans le fragment ci-dessus crĂ©e UdpEchoServerHelper. Comme d'habitude, ce n'est pas une application en soi, c'est un objet qui nous aide Ă  crĂ©er de vĂ©ritables applications. Un de nos accords consiste Ă  transmettre les attributs nĂ©cessaires au constructeur de l'objet auxiliaire (assistant). Dans ce cas, l'assistant ne peut rien faire d'utile s'il n'a pas reçu le numĂ©ro de port sur lequel le serveur attendra les paquets, ce numĂ©ro doit Ă©galement ĂȘtre connu du client. Dans ce cas, nous passons le numĂ©ro de port au constructeur de l'assistant. Le constructeur, pour sa part, exĂ©cute simplement SetAttribute avec la valeur fournie. Plus tard, si vous le souhaitez, vous pourrez dĂ©finir une autre valeur pour l'attribut « Port » Ă  l'aide de SetAttribute.

Comme beaucoup d'autres objets auxiliaires, l'objet UdpEchoServerHelper a une mĂ©thode Installer. L'exĂ©cution de cette mĂ©thode conduit en fait Ă  la crĂ©ation d'une application de serveur Ă©cho de base, qui est liĂ©e Ă  un nƓud. Il est intĂ©ressant de noter que la mĂ©thode Installer prend NodeContainer aussi comme paramĂštre, tout comme les autres Installer mĂ©thodes que nous avons vues.

La conversion implicite en C++ qui fonctionne ici prend le rĂ©sultat de la mĂ©thode node.Get(1) (qui retourne un pointeur intelligent vers l'objet nƓud — Ptr) et l'utilise dans le constructeur pour un objet anonyme NodeContainer, qui est ensuite passĂ© Ă  la mĂ©thode Installer. Si vous ne pouvez pas dĂ©terminer dans le code C++ quelle mĂ©thode avec quelle signature se compile et s'exĂ©cute, alors cherchez parmi les conversions implicites.

Maintenant, nous voyons que echoServer.Install s'apprĂȘte Ă  installer l'application UdpEchoServerApplication sur le nƓud trouvĂ© dans NodeContainer, que nous utilisons pour gĂ©rer nos nƓuds, le nƓud avec l'index 1. La mĂ©thode Installer retournera le conteneur qui contient des pointeurs vers toutes les applications (dans ce cas une seule, car nous avons passĂ© un anonyme NodeContainer, contenant un nƓud) créé par l'assistant.

Les applications doivent indiquer le moment de dĂ©but de la gĂ©nĂ©ration de trafic « start » et peuvent Ă©galement avoir besoin d'indiquer le moment oĂč elle doit s'arrĂȘter « stop ». Nous fournissons les deux paramĂštres. Ces temps sont dĂ©finis Ă  l'aide des mĂ©thodes ApplicationContainer Commencer et ArrĂȘter. Ces mĂ©thodes prennent des paramĂštres de type Temps. Dans ce cas, nous utilisons une sĂ©quence explicite de conversions C++ pour prendre un C++ double 1.0 et le convertir en un objet tns-3 Time, utilisant l'objet Seconds pour la conversion en secondes. N'oubliez pas que les rĂšgles de conversion peuvent ĂȘtre contrĂŽlĂ©es par l'auteur du modĂšle, et le C++ a ses propres rĂšgles, donc vous ne pouvez pas toujours vous attendre Ă  ce que les paramĂštres soient convertis comme vous l'aviez prĂ©vu. Deux lignes,

serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));

mĂšneront Ă  l'exĂ©cution de l'application d'Ă©cho serveur (s'active automatiquement) aprĂšs une seconde du dĂ©but de la simulation et s'arrĂȘte (se dĂ©sactive) aprĂšs dix secondes de simulation. Étant donnĂ© que nous avons dĂ©clarĂ© l'Ă©vĂ©nement de simulation (l'Ă©vĂ©nement d'arrĂȘt de l'application), qui sera exĂ©cutĂ© aprĂšs dix secondes, il y aura au moins dix secondes de fonctionnement du rĂ©seau simulĂ©.

UdpEchoClientHelper

L'application cliente echo est configurée de façon pratiquement identique au serveur. Il existe un objet de base UdpEchoClientApplication, géré par
UdpEchoClientHelper.

UdpEchoClientHelper echoClient (interfaces.GetAddress (1), 9);
echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.0)));
echoClient.SetAttribute ("PacketSize", UintegerValue (1024));

ApplicationContainer clientApps = echoClient.Install (nodes.Get (0));
clientApps.Start (Seconds (2.0));
clientApps.Stop (Seconds (10.0));

Cependant, pour le client d'écho, nous devons définir cinq attributs différents. Les deux premiers attributs sont définis lors de la création UdpEchoClientHelper. Nous passons les paramÚtres qui sont utilisés (à l'intérieur de l'assistant) pour définir les attributs "RemoteAddress" et "RemotePort" conformément à notre accord sur la transmission des paramÚtres nécessaires au constructeur de l'assistant.

Rappelons que nous avons utilisĂ© Ipv4InterfaceContainer pour suivre les adresses IP que nous avons attribuĂ©es Ă  nos appareils. L'interface zĂ©ro dans le conteneur d'interfaces correspondra Ă  l'adresse IP du nƓud zĂ©ro dans le conteneur des nƓuds. La premiĂšre interface dans le conteneur d'interfaces correspond Ă  l'adresse IP du premier nƓud dans le conteneur des nƓuds. Donc, dans la premiĂšre ligne de code (en haut), nous crĂ©ons l'assistant et lui disons que l'adresse distante du client sera l'adresse IP attribuĂ©e au nƓud oĂč se trouve le serveur. Nous indiquons Ă©galement qu'il faut organiser l'envoi des paquets au neuviĂšme port.

L'attribut «MaxPackets» informe le client du nombre maximum de paquets que nous pouvons envoyer pendant la simulation. L'attribut «Interval» indique au client combien de temps attendre entre les paquets, et l'attribut «PacketSize» indique au client la taille que doit avoir la charge utile du paquet. Grùce à cette combinaison d'attributs, nous disons au client d'envoyer un paquet de 1024 octets.

Comme dans le cas du serveur d'Ă©cho, nous dĂ©finissons les attributs pour le client d'Ă©cho Commencer et ArrĂȘter, mais ici nous lançons le client une seconde aprĂšs avoir allumĂ© le serveur (deux secondes aprĂšs le dĂ©but de la simulation).

4.2.8 Simulateur

À ce stade, nous devons lancer la simulation. Cela se fait à l'aide de la fonction globale Simulator::Run.

Simulator::Run ();

Lorsque nous avons précédemment appelé les méthodes,

serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));
... 
clientApps.Start (Seconds (2.0));
clientApps.Stop (Seconds (10.0));

nous avons effectivement planifié des événements dans le simulateur pour 1,0 seconde, 2,0 secondes et deux événements à 10,0 secondes. AprÚs avoir appelé Simulator::Run, le systÚme commencera à parcourir la liste des événements planifiés et à les exécuter. Il commencera d'abord par l'événement prévu pour 1,0 seconde, ce qui activera l'application du serveur d'écho (cet événement peut, à son tour, planifier de nombreux autres événements). Ensuite, il lancera l'événement prévu pour t = 2,0 secondes, qui démarrera l'application du client d'écho. Encore une fois, cet événement peut planifier encore beaucoup d'autres événements. L'implémentation de l'événement de lancement dans le client d'écho commencera la phase de transfert de données de la simulation en envoyant un paquet au serveur.

L'acte d'envoyer un paquet au serveur dĂ©clenchera une chaĂźne d'Ă©vĂ©nements qui seront automatiquement planifiĂ©s en coulisses et qui mettront en Ɠuvre la mĂ©canique de l'envoi de paquets d'Ă©chos en fonction des paramĂštres de synchronisation que nous avons Ă©tablis dans le scĂ©nario.

En fin de compte, comme nous n'envoyons qu'un seul paquet (rappelons que l'attribut MaxPackets Ă©tait fixĂ© Ă  un), la chaĂźne d'Ă©vĂ©nements initiĂ©e par cette unique requĂȘte d'Ă©cho client se terminera, et la simulation passera en mode attente. Une fois cela fait, les Ă©vĂ©nements restants Ă  traiter seront des Ă©vĂ©nements ArrĂȘter pour le serveur et le client. Lorsque ces Ă©vĂ©nements seront exĂ©cutĂ©s, il n'y aura plus d'Ă©vĂ©nements Ă  traiter et Simulator::Run retournera le contrĂŽle. La simulation est terminĂ©e.

Il ne reste plus qu'Ă  nettoyer. Cela se fait en appelant la fonction globale Simulator::Destroy. Étant donnĂ© que des fonctions d'assistants (ou du code de bas niveau ns-3) ont Ă©tĂ© invoquĂ©es, qui sont organisĂ©es pour insĂ©rer des crochets dans le simulateur afin de dĂ©truire tous les objets qui ont Ă©tĂ© créés. Vous n'avez pas besoin de suivre ces objets vous-mĂȘme — tout ce que vous devez faire, c'est appeler Simulator::Destroy et sortir. Le systĂšme ns-3 fera ce travail difficile pour vous. Les lignes restantes de notre premier script ns-3, first.cc, font exactement cela :

Simulator::Destroy ();
return 0;
}

Quand le simulateur s'arrĂȘtera-t-il ?

ns-3 est un simulateur d'événements discrets (DE). Dans un tel simulateur, chaque événement est lié au temps de son exécution, et la simulation se poursuit en traitant les événements dans l'ordre de leur apparition au cours de la simulation. Les événements peuvent entraßner la planification d'événements futurs (par exemple, un minuteur peut se reprogrammer pour terminer un compte à rebours dans l'intervalle suivant).

Les Ă©vĂ©nements initiaux sont gĂ©nĂ©ralement initiĂ©s par un objet, par exemple, IPv6 planifiera des services dans le rĂ©seau, des requĂȘtes de voisins, etc. L'application planifie le premier Ă©vĂ©nement d'envoi de paquet, etc. Lorsqu'un Ă©vĂ©nement est traitĂ©, il peut gĂ©nĂ©rer zĂ©ro, un ou plusieurs Ă©vĂ©nements. À mesure que la simulation progresse, les Ă©vĂ©nements se terminent simplement ou en gĂ©nĂšrent de nouveaux. La simulation s'arrĂȘtera automatiquement si la file d'attente des Ă©vĂ©nements est vide ou si un Ă©vĂ©nement spĂ©cial est dĂ©tectĂ© ArrĂȘter. L'Ă©vĂ©nement ArrĂȘter est gĂ©nĂ©rĂ© par la fonction Simulator::Stop (arrĂȘter le temps).

Il existe un cas typique oĂč Simulator::Stop est absolument nĂ©cessaire pour arrĂȘter la simulation : lorsque des Ă©vĂ©nements auto-sustainants sont prĂ©sents. Les Ă©vĂ©nements auto-sustainants (ou rĂ©pĂ©titifs) sont des Ă©vĂ©nements qui se reprogramment toujours. Par consĂ©quent, ils gardent toujours la file d'attente des Ă©vĂ©nements non vide. Il existe de nombreux protocoles et modules contenant des Ă©vĂ©nements rĂ©pĂ©titifs, par exemple :

‱ FlowMonitor — vĂ©rification pĂ©riodique des paquets perdus ;

‱ RIPng — diffusion pĂ©riodique de mises Ă  jour de tables de routage ;

‱ etc.

Dans de tels cas, Simulator::Stop est nĂ©cessaire pour arrĂȘter la simulation correctement. De plus, lorsque ns-3 est en mode Ă©mulation, RealTimeSimulator est utilisĂ© pour synchroniser les horloges de simulation avec les horloges de la machine, et Simulator::Stop est nĂ©cessaire pour arrĂȘter le processus.

De nombreux programmes de simulation dans le manuel ne sont pas appelĂ©s Simulator::Stop de maniĂšre explicite, car elles se terminent automatiquement lors de l'Ă©puisement des Ă©vĂ©nements dans la file d'attente. Cependant, ces programmes accepteront Ă©galement l'appel Ă  Simulator::Stop. Par exemple, l'instruction supplĂ©mentaire suivante dans le premier exemple de programme planifiera un arrĂȘt explicite Ă  la 11Ăšme seconde :

+ Simulator::Stop (Seconds (11.0));
  Simulator::Run ();
  Simulator::Destroy ();
  return 0;
}

Ce qui prĂ©cĂšde ne modifiera en fait pas le comportement de ce programme, car cette simulation spĂ©cifique se termine naturellement aprĂšs 10 secondes. Mais si vous deviez modifier le temps d'arrĂȘt dans l'instruction ci-dessus de 11 secondes Ă  1 seconde, vous remarqueriez que la simulation s'arrĂȘte avant que n'importe quelle sortie n'apparaisse Ă  l'Ă©cran (la sortie se produisant environ 2 secondes aprĂšs le temps de simulation).

Il est important d'appeler Simulator::Stop avant d'appeler Simulator::Run ; sinon, Simulator::Run peut ne jamais rendre le contrĂŽle au programme principal pour effectuer l'arrĂȘt !

4.2.9 Assemblage de votre scénario

Nous avons rendu la création de vos scripts simples triviale. Tout ce que vous avez à faire est de placer votre script dans le répertoire scratch, et il sera automatiquement compilé lorsque vous exécuterez Waf. Essayons. Revenez au répertoire supérieur et copiez examples/tutorial/first.cc dans le répertoire scratch

$ cd ../..
$ cp examples/tutorial/first.cc scratch/myfirst.cc

Maintenant, compilez votre premier exemple de script en utilisant waf:

$ ./waf

Vous devez voir des messages indiquant que votre premier exemple a été créé avec succÚs.

Waf : Entrée dans le répertoire `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
[614/708] cxx: scratch/myfirst.cc -> build/debug/scratch/myfirst_3.o
[706/708] cxx_link: build/debug/scratch/myfirst_3.o -> build/debug/scratch/myfirst
Waf : Sortie du répertoire `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
'build' terminé avec succÚs (2.357s)

Vous pouvez maintenant exécuter l'exemple (notez que si vous compilez votre programme dans le répertoire scratch, vous devez également l'exécuter à partir de scratch):

$ ./waf --run scratch/myfirst

Vous devriez voir une sortie similaire :

Waf : Entrée dans le répertoire `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
Waf : Sortie du répertoire `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
'build' terminé avec succÚs (0.418s) Envoyé 1024 octets à 10.1.1.2
Reçu 1024 octets de 10.1.1.1
Reçu 1024 octets de 10.1.1.2

Ici, vous voyez que le systÚme de construction vérifie que le fichier a été assemblé, puis le lance. Vous constatez que l'enregistrement du client d'écho indique qu'il a envoyé un paquet de 1024 octets au serveur d'écho 10.1.1.2. Vous voyez également l'enregistrement du serveur d'écho qui indique qu'il a reçu 1024 octets de 10.1.1.1. Le serveur d'écho renvoie silencieusement le paquet, et vous voyez dans le journal du client d'écho qu'il a reçu son paquet de retour du serveur.

4.3 Code source de ns-3

Maintenant que vous avez utilisĂ© certains des assistants ns-3, vous pouvez jeter un Ɠil Ă  quelques codes sources qui implĂ©mentent cette fonctionnalitĂ©. Le code le plus rĂ©cent peut ĂȘtre consultĂ© sur notre serveur web Ă  l'adresse suivante : https://gitlab.com/nsnam/ns-3-dev.git. LĂ , vous verrez une page de synthĂšse Mercurial pour notre arbre de dĂ©veloppement ns-3. En haut de la page, vous verrez plusieurs liens,

summary | shortlog | changelog | graph | tags | files

Allez-y et choisissez le lien vers les fichiers. Voici à quoi ressemblera le niveau supérieur de la plupart de nos dépÎts :

drwxr-xr-x                               [up]
drwxr-xr-x                               bindings python  files
drwxr-xr-x                               doc              files
drwxr-xr-x                               examples         files
drwxr-xr-x                               ns3              files
drwxr-xr-x                               scratch          files
drwxr-xr-x                               src              files
drwxr-xr-x                               utils            files
-rw-r--r-- 2009-07-01 12:47 +0200 560    .hgignore        file | revisions | annotate
-rw-r--r-- 2009-07-01 12:47 +0200 1886   .hgtags          file | revisions | annotate
-rw-r--r-- 2009-07-01 12:47 +0200 1276   AUTHORS          file | revisions | annotate
-rw-r--r-- 2009-07-01 12:47 +0200 30961  CHANGES.html     file | revisions | annotate
-rw-r--r-- 2009-07-01 12:47 +0200 17987  LICENSE          file | revisions | annotate
-rw-r--r-- 2009-07-01 12:47 +0200 3742   README           file | revisions | annotate
-rw-r--r-- 2009-07-01 12:47 +0200 16171  RELEASE_NOTES    file | revisions | annotate
-rw-r--r-- 2009-07-01 12:47 +0200 6      VERSION          file | revisions | annotate
-rwxr-xr-x 2009-07-01 12:47 +0200 88110  waf              file | revisions | annotate
-rwxr-xr-x 2009-07-01 12:47 +0200 28     waf.bat          file | revisions | annotate
-rw-r--r-- 2009-07-01 12:47 +0200 35395  wscript          file | revisions | annotate
-rw-r--r-- 2009-07-01 12:47 +0200 7673   wutils.py        file | revisions | annotate

Nos exemples de scripts se trouvent dans le rĂ©pertoire examples. Si vous cliquez sur les exemples, vous verrez une liste de sous-rĂ©pertoires. L'un des fichiers dans le sous-rĂ©pertoire tutorial — first.cc. Si vous cliquez sur first.cc , vous verrez le code que vous venez d'Ă©tudier.

Le code source se trouve principalement dans le rĂ©pertoire src. Vous pouvez voir le code source en cliquant sur le nom du rĂ©pertoire ou en cliquant sur le lien des fichiers Ă  droite du nom du rĂ©pertoire. Si vous cliquez sur le rĂ©pertoire src, vous obtiendrez une liste des sous-rĂ©pertoires src. Si vous cliquez ensuite sur le sous-rĂ©pertoire core, vous trouverez une liste de fichiers. Le premier fichier que vous verrez (au moment de la rĂ©daction de ce guide) est abort.h. Si vous cliquez sur le lien abort.h, vous serez redirigĂ© vers le fichier source pour abort.h, qui contient des macros utiles pour quitter les scripts en cas de conditions anormales. Le code source pour les helpers que nous avons utilisĂ©s dans ce chapitre peut ĂȘtre trouvĂ© dans le rĂ©pertoire src/Applications/helper. N'hĂ©sitez pas Ă  explorer l'arborescence des rĂ©pertoires pour comprendre ce qui se trouve oĂč et vous familiariser avec le style de programmation de ns‑3.

Source : habr.com

Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS đŸ”„ Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster