Handleiding voor de netwerksimulator ns-3. Hoofdstuk 4

Handleiding voor de netwerksimulator ns-3. Hoofdstuk 4
hoofdstukken 1,2
hoofdstuk 3

4 Overzicht van het concept
4.1 Sleutelabstracties
4.1.1 Node (Knoop)
4.1.2 Application (Toepassing)
4.1.3 Channel (Kanaal)
4.1.4 Net Device (Netwerkapparaat)
4.1.5 Topologische assistenten
4.2 Eerste ns-3 script
4.2.1 Boilerplate code
4.2.2 Inbegrepen modules
4.2.3 Namensruimte ns3
4.2.4 Logging
4.2.5 Hoofdfunctie
4.2.6 Gebruik van topologische assistenten
4.2.7 Gebruik van de Application
4.2.8 Simulator
4.2.9 Het bouwen van je scenario
4.3 ns-3 Bronnen code

Hoofdstuk 4

Overzicht van het concept

Het eerste wat we moeten doen voordat we beginnen met het bestuderen of schrijven van ns-3 code, is het uitleggen van enkele fundamentele concepten en abstracties binnen het systeem. Voor sommigen kan veel hiervan voor de hand liggend lijken, maar we raden aan om de tijd te nemen om deze sectie te lezen, om ervoor te zorgen dat je op een stevige basis begint.

4.1 Sleutelabstracties

In deze sectie behandelen we enkele termen die vaak in netwerken worden gebruikt, maar een specifieke betekenis hebben in ns-3.

4.1.1 Node (Knoop)

In internetjargon wordt een computerapparaat dat op een netwerk is aangesloten een host of soms een eindpunt genoemd. Omdat ns-3 een netwerk simulator is en geen internet simulator, vermijden we opzettelijk de term host, omdat dit nauw verbonden is met het internet en zijn protocollen. In plaats daarvan gebruiken we de meer algemene term, die ook door andere simulators wordt gebruikt en zijn oorsprong vindt in de grafentheorie - knoop (node).

In ns-3 wordt de basisabstractie van een computerapparaat een knoop genoemd. Deze abstractie wordt in C++ vertegenwoordigd door de Node klasse. De klasse NodeNode (knoop) biedt methoden voor het beheren van de representaties van computerapparaten in simulaties.

Je moet begrijpen Node hoe een computer, waaraan je functionaliteit zult toevoegen. Je voegt dingen toe zoals toepassingen, protocolstacks en uitbreidingskaarten met stuurprogramma's, die de computer in staat stellen nuttig werk te verrichten. We gebruiken hetzelfde basismodel in ns-3.

4.1.2 Application (Toepassing)

Over het algemeen wordt computerprogrammatuur verdeeld in twee brede categorieën. Systeemsoftware organiseert verschillende computerbronnen zoals geheugen, processorkernen, schijven, netwerken, enzovoort volgens een bepaald rekenmodel. Systeemsoftware gebruikt deze bronnen meestal niet om taken uit te voeren die rechtstreeks voordeel opleveren voor de gebruiker. De gebruiker start doorgaans een applicatie voor het bereiken van een bepaald doel, waarbij deze de bronnen gebruikt die worden beheerd door de systeemsoftware.

Vaak ligt de scheidslijn tussen systeem- en applicatiesoftware bij het niveau van privileges, dat plaatsvindt tijdens de traps van het besturingssysteem. In ns-3 bestaat er geen echt concept van een besturingssysteem, en derhalve zijn er geen concepten van privilege-niveaus of systeemoproepen. We hebben echter wel het idee van een applicatie. Net zoals in de “echte wereld” op computers programma-applicaties draaien om taken uit te voeren, draaien ns-3-applicaties op ns-3-nodes om simulaties in de gesimuleerde wereld te beheren.

In ns-3 is de basisabstractie voor een gebruikersprogramma dat enige activiteit genereert voor simulatie, een applicatie. Deze abstractie wordt in C++ weergegeven door de klasse Application. De klasse Application biedt methoden voor het beheren van de weergaven van onze versie van gebruikersniveau-applicaties in simulaties. Van ontwikkelaars wordt verwacht dat ze de klasse Application specialiseren in de zin van objectgeoriënteerd programmeren om nieuwe applicaties te creëren. In deze gids zullen we de specialisaties van de klasse Application gebruiken, genaamd UdpEchoClientApplication en UdpEchoServerApplication. Zoals verwacht, vormen deze applicaties een set van client/server-applicaties die worden gebruikt voor het genereren en echo-simuleren van netwerkpakketten.

4.1.3 Channel (Kanaal)

In de echte wereld kun je een computer met een netwerk verbinden. De omgevingen waar gegevens in deze netwerken worden verzonden, worden vaak kanalen genoemd. Wanneer je een Ethernet-kabel op een wandcontactdoos aansluit, verbind je de computer met een Ethernet-communicatiekanaal. In de gesimuleerde wereld van ns-3 is een knooppunt verbonden met een object dat een communicatiekanaal vertegenwoordigt. Hier wordt de belangrijkste abstractie van de communicatienetwerk aangeduid als kanaal en wordt vertegenwoordigd in C++ door de klasse Channel.

Klasse ChannelChannel biedt methoden voor het beheren van de interactie tussen netwerkobjecten en het aansluiten van knooppunten erop. Kanalen kunnen ook worden gespecialiseerd door ontwikkelaars in termen van objectgeoriënteerd programmeren. De specialisatie van een kanaal kan iets eenvoudigs zoals een draad modelleren. Een gespecialiseerd kanaal kan ook complexe zaken modelleren, zoals een grote Ethernet-switch of driedimensionale ruimtes vol obstakels in het geval van draadloze netwerken.

In deze handleiding zullen we gespecialiseerd versies van het kanaal gebruiken, genaamd CsmaChannelCsmaChannel, PointToPointChannelPointToPointChannel en WifiChannelWifiChannel. CsmaChannel, bijvoorbeeld, modelleert een versie van het communicatienetwerk dat een communicatieve omgeving voor meerdere toegang met draaggolfovervanging implementeert. Dit geeft ons Ethernet-achtige functionaliteit.

4.1.4 Net Device (Netwerkapparaat)

Vroeger was het zo dat als je een computer met een netwerk wilde verbinden, je een bepaald netwerk Kabel en een hardware-apparaat moest kopen, genaamd (in PC-terminologie) een uitbreidingskaart, die in de computer moest worden geïnstalleerd. Als er bepaalde netwerkfuncties op de uitbreidingskaart werden geïmplementeerd, werden ze netwerkaansluitkaart of netwerkkarten genoemd. Tegenwoordig worden de meeste computers geleverd met ingebouwde netwerkinterface-apparatuur en zien gebruikers deze niet als afzonderlijke apparaten.

Een netwerkaansluitkaart werkt niet zonder een stuurprogramma dat de hardware ervan beheert. In Unix (of Linux) wordt een deel van de randapparatuur geclassificeerd als een apparaat. Apparaten worden beheerd met behulp van stuurprogramma's (drivers), terwijl netwerkapparaten (NIC) worden beheerd met behulp van netwerkapparaatstuurprogramma's (network device drivers) en hebben de verzamelnaam netwerkapparaten (net devices). In Unix en Linux verwijst u naar netwerkt apparaten met namen zoals bijvoorbeeld eth0.

In ns-3 omvat de abstractie van een netwerkapparaat zowel de softwaredriver als de gemodelleerde hardware. Tijdens de simulatie wordt het netwerkapparaat 'geïnstalleerd' in een knoop, zodat het kan communiceren met andere knopen via kanalen. Net als in een echte computer kan een knoop op meerdere kanalen worden aangesloten via verschillende apparaten. NetDevices.

De netwerkabstractie van een apparaat wordt in C++ weergegeven door de klasse NetDevice. De klasse NetDevice biedt methoden voor het beheren van verbindingen met Node- en Channel-objecten; en kan door ontwikkelaars worden gespecialiseerd in termen van objectgeoriënteerd programmeren. In deze handleiding zullen we verschillende gespecialiseerde versies van NetDevice gebruiken met de namen CsmaNetDevice, PointToPointNetDevice en WifiNetDevice. Evenals een Ethernet-netwerkadapter bedoeld is om met het netwerk te werken, Ethernet, CsmaNetDevice is bedoeld om te werken met CsmaChannel, PointToPointNetDevice is bedoeld om te werken met PointToPointChannel, met behulp van 1 bit, gelijk aan 0, WifiNetDevice — is bedoeld om te werken met WifiChannel..

4.1.5 Topologische assistenten

In een echt netwerk vindt u hostcomputers met toegevoegde (of ingebouwde) netwerkkaarten. In ns-3 zouden we zeggen dat u knopen zult zien met aangesloten NetDevices. In een groot gemodelleerd netwerk moet u verbindingen tussen vele objecten organiseren. Node, NetDevice en Channel.

Omdat het aansluiten van NetDevices op knopen, NetDevices op kanalen, het toewijzen van IP-adressen, enz. in ns-3 een algemene taak is, bieden we zogenaamde topologische helpers aan om dit zo eenvoudig mogelijk te maken. Bijvoorbeeld, voor het creëren van een NetDevice moeten een aantal kernoperaties van ns-3 worden uitgevoerd, zoals het toevoegen van een MAC-adres, het instellen van dit netwerkapparaat in Node, het configureren van de protocolstack van de knoop en vervolgens het aansluiten van het NetDevice op Channel. Nog meer operaties zijn nodig om meerdere apparaten op multi-point kanalen aan te sluiten en vervolgens individuele netwerken te verbinden in een gezamenlijke netwerk (Internetworks). We bieden topologische hulpopjecten aan die deze talrijke operaties voor uw gemak combineren in een gebruiksvriendelijk model.

4.2 Eerste ns-3 script

Als u het systeem hebt ingesteld zoals hierboven voorgesteld, heeft u een ns-3-release in de directory met de naam repos in uw homedirectory. Ga naar de directory release

Als u zo'n directory niet heeft, hebt u tijdens het bouwen van de releaseversie van ns-3 de uitvoermap niet opgegeven, voer de bouw dan als volgt uit:
$ . /waf configure —build-profile=release —out=build/release,
$ . /waf build

Daar zou je een directorystructuur moeten zien die lijkt op de volgende:

AUTHORS       voorbeelden      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

Ga naar de directory voorbeelden/tutorial. Je zou daar een bestand met de naam moeten zien first.cc. Dit is een script dat een eenvoudige point-to-point verbinding tussen twee knooppunten opzet en één pakket tussen de knooppunten verzendt. Laten we dit script regel voor regel bekijken door first.cc in je favoriete editor te openen.

4.2.1 Boilerplate code
De eerste regel in het bestand is de editor-mode regel emacs. Het vertelt emacs over de opmaakvoorwaarden (codeerstijl) die we in onze broncode gebruiken.

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

Dit is altijd een vrij controversieel onderwerp, dus we moeten verduidelijking aanbrengen om het meteen uit de weg te ruimen. Het ns-3 project heeft, net als de meeste grote projecten, een codeerstijl aangenomen waar alle aangeleverde code aan moet voldoen. Als je jouw code aan het project wilt bijdragen, moet je uiteindelijk voldoen aan de ns-3 codeerstandaard zoals beschreven in het bestand doc/codingstd.txt of weergegeven op de website van het project: https://www.nsnam.org/develop/contributing-code/coding-style/.

We raden je aan om vertrouwd te raken met het uiterlijk van ns-3 code en deze standaard toe te passen telkens wanneer je met onze code werkt. Het hele ontwikkelteam en de bijdragers hebben hier na enige aarzeling mee ingestemd. De emacs-mode regel hierboven maakt correcte opmaak eenvoudiger als je de emacs editor gebruikt.

De ns-3 simulator wordt gelicentieerd onder de GNU General Public License. Je zult de bijbehorende juridische koptekst van de GNU in elk bestand van de ns-3 distributie zien. Vaak kun je een auteursrechtverklaring van een van de betrokken instellingen in het ns-3 project boven de GPL-tekst en de auteur die hieronder wordt weergegeven, zien.

/* 
* 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 Inbegrepen modules

De eigenlijke code begint met een reeks include-instructies (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"

Om onze gebruikers van high-level scripts te helpen met het grote aantal headerbestanden dat in het systeem aanwezig is, groeperen we deze volgens hun gebruik in grote modules. We bieden één headerbestand aan dat alle headerbestanden die in deze module worden gebruikt, recursief zal laden. In plaats van te zoeken welk specifiek headerbestand je nodig hebt en mogelijk de juiste lijst met afhankelijkheden te krijgen, geven we je de mogelijkheid om een groep bestanden met een hoge mate van detail te laden. Dit is misschien niet de meest efficiënte benadering, maar het maakt het schrijven van scripts zeker veel gemakkelijker.

Elk van de inbegrepen ns-3 bestanden wordt geplaatst in een directory met de naam ns3 (onderdirectory van de build), om naamconflicten tijdens het buildproces te vermijden. Het bestand ns3/core-module.h komt overeen met de ns-3 module die je zult vinden in de directory src/core in de release die je hebt geïnstalleerd. In de lijst van deze directory vind je een groot aantal headerbestanden. Wanneer je build, Waf plaats openbare headerbestanden in de ns3 directory in de onderdirectory build/debug

Als u zo'n directory niet heeft, hebt u tijdens het bouwen van de releaseversie van ns-3 de uitvoermap niet opgegeven, voer de bouw dan als volgt uit:
$ ./waf configure --build-profile=debug --out=build/debug
$ . /waf build
of
$ ./waf configure --build-profile=optimized --out=build/optimized
$ . /waf build

of build/optimized, afhankelijk van jouw configuratie. Waf zal ook automatisch een inclusiebestand voor de module genereren om alle openbare headerbestanden te laden. Aangezien je natuurlijk deze handleiding strikt volgt, heb je al

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

gedaan om het project te configureren voor debug builds, inclusief voorbeelden en tests. Je hebt ook gedaan

$ ./waf

om het project te bouwen. Dus nu, als je in de directory kijkt ../../build/debug/ns3, dan vind je daar, onder andere, de headerbestanden van de vier modules die hierboven zijn weergegeven. Je kunt de inhoud van deze bestanden bekijken en ontdekken dat ze alle openbare bestanden bevatten die door de betreffende modules worden gebruikt.

4.2.3 Namensruimte ns3

De volgende regel in het script first.cc is de namespace verklaring.

using namespace ns3;

Het ns‑3-project is geïmplementeerd in de C++ naamruimte die ns3 wordt genoemd. Dit groepeert alle ns‑3-gerelateerde verklaringen binnen zichtbaarheid buiten de globale naamruimte, wat, zoals we hopen, zal helpen bij de integratie met andere code. Het gebruik van de C++ operator brengt de ns‑3 naamruimte in het huidige (globale) declaratieve gebied. Dit is een bijzondere manier om te zeggen dat je na deze verklaring de resolutieoperator ns3::scope niet meer hoeft in te voeren voorafgaand aan alle ns‑3 code om het te gebruiken. Als je niet bekend bent met naamruimten, raadpleeg dan praktisch elk C++ handboek en vergelijk de ns3 naamruimte met het gebruik van de std naamruimte en verklaringen. using namespace std; in voorbeelden met de uitvoeroperator cout en streams.

4.2.4 Logging

De volgende regel van het script is als volgt:

NS_LOG_COMPONENT_DEFINE ("FirstScriptExample");

We zullen deze verklaring gebruiken als een handige plek om ons documentatiesysteem te bespreken. DoxygenAls je naar de webpagina van het ns‑3-project kijkt, vind je een link naar 'Documentatie' (Documentation) in de navigatiebalk. Als je op deze link klikt, kom je op onze documentatiepagina. Er is een link naar 'Laatste release' die je leidt naar de documentatie voor de laatste stabiele versie van ns‑3. Als je de link 'API Documentatie' kiest, kom je op de API documentatiepagina van ns‑3.

Aan de linkerkant van de pagina vind je een grafische weergave van de documentatiestructuur. Een goed beginpunt is het 'boek' Modules ns‑3 in de navigatieboom van ns‑3. Als je deze uitklapt Modules, zie je een lijst met documentatie over ns‑3 modules. Zoals hierboven besproken, is het concept van een module hier direct gerelateerd aan de bestanden die in de module hierboven zijn opgenomen. De logging subsystem van ns‑3 wordt besproken in de sectie Gebruik van de loggingmodule, dus we komen hier later in deze handleiding op terug, maar je kunt meer leren over de bovenstaande verklaring door de module Corete bekijken en het boek Debugging tools, en vervolgens de pagina te selecteren Logging. Klik op Logging.

Nu moet je de documentatie bekijken Doxygen voor de module Logging. In de lijst met macro's bovenaan de pagina ziet u een vermelding voor NS_LOG_COMPONENT_DEFINE. Voordat u op de link klikt, bekijk alstublieft de 'Gedetailleerde beschrijving' van de logmodule om een algemeen begrip van de werking te krijgen. U kunt dit doen door naar beneden te scrollen of 'Meer...' onder de diagram te selecteren.

Zodra u een algemeen idee heeft van wat er gebeurt, gaat u verder met het bekijken van de documentatie van de specifieke NS_LOG_COMPONENT_DEFINE. Ik zal de documentatie hier niet dupliceren, maar om het samen te vatten, deze regel declareert een logcomponent genaamd FirstScriptExample, die het mogelijk maakt om de console loggen van berichten in of uit te schakelen via de link naar de naam.

4.2.5 Hoofdfunctie

In de volgende regels van het script ziet u,

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

Dit is simpelweg de declaratie van de hoofdfunctie van uw programma (script). Net als bij elke C++-toepassing moet u de hoofdfunctie definiëren; deze wordt als eerste uitgevoerd. Hier is niets bijzonders aan. Uw ns-3 script is gewoon een C++ programma. De volgende regel stelt de tijdsresolutie in op 1 nanoseconde, wat de standaardwaarde is:

Time::SetResolution (Time::NS);

Tijdsresolutie of gewoon resolutie is de kleinste tijdswaarde die kan worden gebruikt (de kleinste tastbare verschil tussen twee tijdswaarden). U kunt de resolutie precies één keer wijzigen. Het mechanisme dat deze flexibiliteit biedt, verbruikt geheugen, dus zodra de resolutie expliciet is ingesteld, geven we het geheugen vrij om verdere updates te voorkomen. (Als u de resolutie niet expliciet instelt, is deze standaard ingesteld op één nanoseconde en wordt het geheugen vrijgegeven bij het begin van de simulatie.)

De volgende twee regels van het script worden gebruikt om twee logcomponenten in te schakelen die zijn ingebouwd in de applicaties EchoClient en EchoServer:

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

Als je de documentatie over de Logging-component hebt gelezen, zie je dat er verschillende detailniveaus zijn die je kunt inschakelen voor elk component. Deze twee regels code schakelen debug logging in op INFO-niveau voor echo-clients en servers. Op dit niveau drukt de applicatie tijdens de simulatie berichten af bij het verzenden en ontvangen van pakketten.

Laten we nu rechtstreeks overgaan tot het creëren van de topologie en het starten van de simulatie. We zullen topologische helperobjecten gebruiken om dit werk zo eenvoudig mogelijk te maken.

4.2.6 Gebruik van topologische assistenten

De volgende twee regels code in ons script maken daadwerkelijk ns-3 Node-objecten aan die de computers in de simulatie zullen vertegenwoordigen.

NodeContainer nodes;
nodes.Create (2);

Voordat we verder gaan, laten we de documentatie voor de klasse NodeContainer. Een andere manier om de documentatie voor deze klasse te bereiken, is via het tabblad Classes op de pagina's Doxygen. Als je Doxygen al open hebt, scrol dan gewoon naar boven naar de bovenkant van de pagina en selecteer het tabblad Classes. Je zou een nieuwe set tabbladen moeten zien, waarvan één de lijst met klassen is. Onder dit tabblad zie je een lijst van alle ns-3 klassen. Scroll naar beneden tot ns3::NodeContainer. Wanneer je de klasse hebt gevonden, selecteer deze om naar de documentatie voor de klasse te gaan.

Zoals we ons herinneren, is een van onze belangrijkste abstracties de node. Het vertegenwoordigt de computer waaraan we dingen zoals protocolstacks, applicaties en interfacekaarten willen toevoegen. De topologische helper NodeContainer biedt een handige manier om alle objecten te creëren, beheren en toegang te krijgen tot die we aanmaken voor het draaien van de simulatie. De eerste regel hierboven verklaart gewoon Node, die we nodes noemen. De tweede regel roept de Create-methode aan voor het object nodes en vraagt de container om twee nodes aan te maken. Zoals beschreven in NodeContainer, vraagt de container het systeem ns-3 om twee objecten te creëren Doxygenen slaat de verwijzingen naar deze objecten intern op. Node De nodes die in het script zijn aangemaakt, doen voorlopig niets. De volgende stap in het bouwen van de topologie is het verbinden van onze nodes met het netwerk. De eenvoudigste vorm van een netwerk die we ondersteunen, is een punt-tot-puntverbinding tussen twee nodes. We gaan nu zo'n verbinding maken.

De in het script gemaakte knooppunten doen nu nog niets. De volgende stap in het bouwen van de topologie is het aansluiten van onze knooppunten op het netwerk. De eenvoudigste netwerkvorm die we ondersteunen, is een punt-tot-puntverbinding tussen twee knooppunten. We gaan nu zo'n verbinding maken.

PointToPointHelper

We create a point-to-point connection by acting according to a familiar template, using a topological helper object to perform the low-level work necessary for the connection. Let’s remember that our two key abstractions NetDevice en Channel. In the real world, these terms roughly correspond to peripheral cards and network cables. Generally, these two things are closely related to each other, and no one can expect to exchange, for example, devices Ethernet over a wireless channel. Our topological helpers follow this close relationship, and therefore you will use one object in this scenario PointToPointHelper to configure and connect ns-3 objects PointToPointNetDevice en PointToPointChannel. The next three lines in the scenario:

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

The first line,

PointToPointHelper pointToPoint;

creates an instance of the object in the stack. PointToPointHelperFrom a high-level perspective, the next line,

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

tells the object PointToPointHelper to use the value '5 Mbps' (five megabits per second) as 'DataRate».

From a more specific viewpoint, the line 'DataRate' corresponds to what we call an attribute PointToPointNetDevice. If you look at Doxygen for the class ns3::PointToPointNetDevice and in the documentation for the method GetTypeId you will find a list of attributes defined for the device. Among them will be the attribute 'DataRate'. Most user-visible ns-3 objects have similar lists of attributes. We use this mechanism for easy simulation configuration without recompilation, as you will see in the next section.

Similar to 'DataRate' in PointToPointNetDevice, you will find the attribute 'Delay' associated with PointToPointChannel. The final line,

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

zegt PointToPointHelper uses the value '2 ms' (two milliseconds) as the propagation delay value for the point-to-point channel that it subsequently creates.

NetDeviceContainer

At this point in the scenario, we have NodeContainer, which contains two nodes. We have PointToPointHelper, which is prepared to create objects PointToPointNetDevices and connect them using the PointToPointChannel object. Just as we used the NodeContainer topology helper object to create nodes, we will ask PointToPointHelper to do the work for us related to creating, configuring, and installing our devices. We will need a list of all created objects NetDevice, so we use NetDeviceContainer voor het opslaan zoals we het gebruikten NodeContainer voor het opslaan van de door ons gemaakte knooppunten. De volgende twee regels code,

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

voltooien de configuratie van de apparaten en de verbinding. De eerste regel declareert de apparaatcontainer die eerder werd genoemd, en de tweede voert het belangrijkste werk uit. De methode Installeren object PointToPointHelper hetzelfde aanneemt NodeContainer als parameter. Binnen NetDeviceContainer voor elk knooppunt dat zich bevindt in NodeContainer wordt aangemaakt (voor punt-tot-punt communicatie moeten er precies twee zijn) PointToPointNetDevice wordt aangemaakt en opgeslagen in de apparaatcontainer. PointToPointChannel wordt aangemaakt, en er worden twee aan toegevoegd PointToPointNetDevices. Na het creëren van de objecten, worden de attributen die zijn opgeslagen in PointToPointHelper, gebruikt om de bijbehorende attributen in de gemaakte objecten te initialiseren.

Na het aanroepen van pointToPoint.Install (nodes) hebben we twee knooppunten, elk met een geïnstalleerd netwerkt apparaat 'punt-tot-punt' en één 'punt-tot-punt' verbinding tussen hen. Beide apparaten zijn ingesteld om gegevens met een snelheid van vijf megabit per seconde te verzenden met een doorvoertijd van twee milliseconden.

InternetStackHelper

Nu zijn onze knooppunten en apparaten geconfigureerd, maar er zijn geen protocolstapels op onze knooppunten geïnstalleerd. De volgende twee regels code zorgen daarvoor.

InternetStackHelper stack;
stack.Install (nodes);

InternetStackHelper is een topologische helper voor internetstapels, vergelijkbaar met PointToPointHelper voor punt-tot-punt netwerkt apparaten. De methode Installeren neem een NodeContainer als parameter. Bij uitvoering installeert het de internetstack (TCP, UDP, IP, enz.) op elk knooppunt in de container.

Ipv4AddressHelper

Vervolgens moeten we onze apparaten koppelen aan IP-adressen. We bieden een topologische helper voor het beheer van de distributie van IP-adressen. De enige zichtbare API voor de gebruiker is het instellen van een basis-IP-adres en subnetmasker voor gebruik tijdens de feitelijke adresdistributie (dit gebeurt op een lager niveau binnen de helper). De volgende twee regels code in ons voorbeeldscript first.cc,

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

declareren een hulpadresobject en vertellen het dat het IP-adressen uit het netwerk 10.1.1.0 moet beginnen te toewijzen, waarbij het gebruik maakt van het subnetmasker 255.255.255.0. Standaard beginnen de toegewezen adressen met één en nemen ze monoton toe, dus het eerste adres dat uit deze pool wordt toegewezen, is 10.1.1.1, daarna 10.1.1.2, enzovoorts. In werkelijkheid slaat het systeem ns‑3 op laag niveau alle toegewezen IP-adressen op en genereert het een fatale fout als je per ongeluk een situatie creëert waarin hetzelfde adres twee keer wordt gegenereerd (overigens is het moeilijk om deze fout te debuggen).

De volgende regel code,

Ipv4InterfaceContainer interfaces = address.Assign (devices);

voert de daadwerkelijke toewijzing van het adres uit. In ns‑3 stellen we de verbinding tussen het IP-adres en het apparaat in door gebruik te maken van het object Ipv4Interface. Net als dat we soms een lijst van netwerkapparaten nodig hebben die door de assistant zijn gemaakt voor verder gebruik, hebben we soms een lijst van objecten nodig. Ipv4Interface. Ipv4InterfaceContainer biedt deze functionaliteit aan.

We hebben een point-to-point netwerk gebouwd, met geïnstalleerde stacks en toegewezen IP-adressen. Nu hebben we voor elke knoop toepassingen nodig om verkeer te genereren.

4.2.7 Gebruik van de Application

Een andere van de belangrijkste abstracties van het systeem ns‑3 is de ) — dit is de enige plek waar je de backend hoeft op te geven. Alles andere past transparant in het concept “specificatie->wrapper”, waar we het verder over zullen hebben. (applicatie). In dit scenario gebruiken we twee specialisaties van de basisklasse ) — dit is de enige plek waar je de backend hoeft op te geven. Alles andere past transparant in het concept “specificatie->wrapper”, waar we het verder over zullen hebben. ns‑3 genaamd UdpEchoServerApplication en UdpEchoClientApplication. Zoals in de eerdere gevallen gebruiken we hulpprogramma-objecten om de basiselementen in te stellen en te beheren. Hier gebruiken we UdpEchoServerHelper en UdpEchoClientHelperobjecten om ons leven gemakkelijker te maken.

UdpEchoServerHelper

De volgende regels code in ons voorbeeldscript first.cc worden gebruikt om de UDP echo-serverapplicatie op één van de knopen die we eerder hebben gemaakt, te configureren.

UdpEchoServerHelper echoServer (9);

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

De eerste regel code in het bovenstaande fragment creëert UdpEchoServerHelper. Zoals gewoonlijk is dit niet de toepassing op zichzelf, dit is een object dat ons helpt om echte toepassingen te maken. Een van onze afspraken is om de noodzakelijke attributen door te geven aan de constructeur van het hulpopject (helper). In dit geval kan de helper niets nuttigs doen als hem niet het poortnummer wordt gegeven waarop de server zal wachten op pakketten, dit nummer moet ook bekend zijn bij de client. In dit geval geven we het poortnummer door aan de constructeur van de helper. De constructeur voert op zijn beurt eenvoudig uit SetAttribute met de doorgegeven waarde. Later, indien gewenst, kun je met SetAttribute een andere waarde voor het attribuut 'Port' instellen.

Net als veel andere hulpopjecten heeft het object UdpEchoServerHelper een methode Installeren. Het uitvoeren van deze methode leidt er feitelijk toe dat er een basis echo-servertoepassing wordt gemaakt en aan een knoop wordt gekoppeld. Het is interessant dat de methode Installeren hetzelfde aanneemt NodeContainter ook een parameter heeft, net als andere Installeren methoden die we hebben gezien.

De impliciete conversie C++, die hier werkt, neemt het resultaat van de methode node.Get (1) (die een slimme pointer naar het knoopobject — Ptr) retourneert en deze gebruikt in de constructeur voor een anoniem object NodeContainer, dat vervolgens aan de methode wordt doorgegeven. Installeren. Als je in de C++-code niet kunt bepalen welke methode met welke handtekening wordt gecompileerd en uitgevoerd, zoek dan onder de impliciete conversies.

Nu zien we dat echoServer.Install zich voorbereidt om de toepassing UdpEchoServerApplication te installeren op de gevonden in NodeContainer, dat we gebruiken om onze knooppunten te beheren, de knoop met index 1. De methode Installeren zal de container retourneren die pointers bevat naar alle toepassingen (in dit geval één, aangezien we een anoniem NodeContainer, dat één knoop bevat) die door de helper is gemaakt.

Toepassingen moeten het moment van start van de verkeersgeneratie specificeren 'start' en kunnen ook de tijd specificeren wanneer deze moet worden gestopt 'stop'.We geven beide parameters op. Deze tijden worden ingesteld met behulp van de methoden ApplicationContainer Start en Stop. Deze methoden nemen parameters van het type Tijd. In dit geval gebruiken we een expliciete reeks C++-conversies om C++ double Wij zetten 1.0 om in een object tns‑3 Time, dat het Seconds-object gebruikt om naar seconden te converteren. Houd er rekening mee dat de conversieregels door de modelauteur kunnen worden beheerd, en C++ zijn eigen regels heeft, zodat je niet altijd kunt rekenen op de parameters om omgezet te worden zoals je had verwacht. Twee regels,

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

zal ervoor zorgen dat de echo-serverapplicatie automatisch wordt gestart (ingeschakeld) een seconde na het begin van de simulatie en wordt gestopt (uitgeschakeld) na tien seconden simulatie. Aangezien we een simulatie-evenement hebben verklaard (het stop-evenement van de applicatie), dat na tien seconden zal worden uitgevoerd, zal er minimaal tien seconden netwerkactiviteit worden gesimuleerd.

UdpEchoClientHelper

De clientapplicatie echo wordt op een vergelijkbare manier geconfigureerd als de server. Er is een basisobject UdpEchoClientApplication, dat wordt beheerd door
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));

Echter, voor de echo-client moeten we vijf verschillende attributen instellen. De eerste twee attributen worden ingesteld tijdens de creatie UdpEchoClientHelper. We geven de parameters door die (binnen de helper) worden gebruikt om de attributen in te stellen "RemoteAddress" en "RemotePort" in overeenstemming met onze afspraak om de vereiste parameters in de constructor van de helper door te geven.

Laten we niet vergeten dat we Ipv4InterfaceContainer gebruikten om de IP-adressen bij te houden die we aan onze apparaten hebben toegewezen. Het nulinterface in de interfacecontainer komt overeen met het IP-adres van de nulknop in de knooppuntencontainer. De eerste interface in de interfacecontainer komt overeen met het IP-adres van de eerste knoop in de knooppuntencontainer. Dus in de eerste regel code (bovenaan) maken we de helper aan en zeggen we dat het externe adres van de cliënt het IP-adres zal zijn dat aan de knoop die de server huisvest is toegewezen. We geven ook aan dat de verzending van pakketten naar poort negen moet worden georganiseerd.

Het attribuut «MaxPackets» geeft de klant het maximale aantal pakketten aan dat we kunnen verzenden tijdens de simulatie. Het attribuut «Interval» geeft de klant aan hoe lang er gewacht moet worden tussen de pakketten, en het attribuut «PacketSize» geeft aan hoe groot de nuttige belasting van het pakket moet zijn. Met deze combinatie van attributen vragen we de klant om één pakket van 1024 bytes te verzenden.

Net zoals bij de echo-server stellen we de echo-client attributen in. Start en Stop, maar hier starten we de client een seconde na het inschakelen van de server (twee seconden na het begin van de simulatie).

4.2.8 Simulator

Op dit punt moeten we de simulatie starten. Dit gebeurt met behulp van de globale functie Simulator::Run.

Simulator::Run ();

Toen we eerder de methoden aanroepen,

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

hebben we feitelijk evenementen in de simulator gepland op 1,0 seconde, 2,0 seconden en twee evenementen op 10,0 seconden. Na de aanroep Simulator::Run, zal het systeem beginnen met het doorlopen van de lijst met geplande evenementen en deze uitvoeren. Eerst zal het evenement dat na 1,0 seconde is gepland, worden uitgevoerd, wat de echo-server-applicatie activeert (dit evenement kan op zijn beurt veel andere evenementen plannen). Vervolgens zal het het evenement dat is gepland op t = 2,0 seconden uitvoeren, wat de echo-client-applicatie zal starten. Opnieuw kan dit evenement nog veel andere evenementen plannen. De implementatie van het startevenement in de echo-client zal de fase van het verzenden van gegevens simulatie beginnen door een pakket naar de server te verzenden.

De handeling van het verzenden van een pakket naar de server zal een keten van evenementen oproepen die automatisch achter de schermen worden gepland en die de mechanica van het verzenden van echo-signalen zullen implementeren volgens de synchronisatieparameters die we in het script hebben ingesteld.

Uiteindelijk, aangezien we slechts één pakket verzenden (laten we niet vergeten dat het attribuut MaxPackets op eenheid was ingesteld), zal de keten van evenementen die door dit enkele client-echo-verzoek is geïnitieerd, eindigen en zal de simulatie in de wachtstand gaan. Zodra dit gebeurt, zijn de resterende geplande evenementen die uitgevoerd zullen worden Stop voor de server en de client. Wanneer deze evenementen worden uitgevoerd, zijn er geen evenementen meer voor verdere verwerking en Simulator::Run geeft het de controle terug. De simulatie is voltooid.

Er resteert alleen nog opruimen. Dit gebeurt door de globale functie aan te roepen Simulator::Destroy. Omdat de helperfuncties (of de laag-niveau code van ns-3) zodanig zijn georganiseerd dat ze hooks in de simulator invoegen om alle gecreëerde objecten te vernietigen. Je hoeft geen van deze objecten zelf te volgen — alles wat je hoefde te doen was aanroepen Simulator::Destroy en afmelden. Het ns-3 systeem zal deze moeilijke taak voor je uitvoeren. De resterende regels van ons eerste ns-3 script, first.cc, doen precies dat:

Simulator::Destroy ();
return 0;
}

Wanneer stopt de simulator?

ns-3 is een discrete-event simulator (DE). In zo'n simulator is elk event gekoppeld aan de tijd van uitvoering, en de simulatie gaat verder door events in de volgorde van hun optreden tijdens de simulatie te verwerken. Events kunnen nieuwe toekomstige events plannen (bijvoorbeeld, een timer kan zichzelf herplannen om de telling in het volgende interval te beëindigen).

Initiële events worden meestal geïnitieerd door een object, bijvoorbeeld, IPv6 zal de service discovery in het netwerk, neighbor requests, enz. plannen. De applicatie plant het eerste event van het verzenden van een pakket, enz. Wanneer een event wordt verwerkt, kan het nul, één of meerdere events genereren. Terwijl de simulatie voortduurt, eindigen events simpelweg of genereren nieuwe. De simulatie stopt automatisch als de event queue leeg is, of als er een speciaal event wordt gedetecteerd. Stop. Een event Stop wordt gegenereerd door de functie Simulator::Stop (stopt de tijd).

Er is een typische situatie waarin Simulator::Stop absoluut noodzakelijk is om de simulatie te stoppen: wanneer er zelf-ondersteunende events zijn. Zelf-ondersteunende (of herhalende) events zijn events die zich altijd herplannen. Hierdoor houden ze de event queue altijd niet leeg. Er zijn veel protocollen en modules die herhalende events bevatten, zoals:

• FlowMonitor — periodieke controle op verloren pakketten;

• RIPng — periodieke uitzending van updates voor routetabellen;

• enz.

In dergelijke gevallen Simulator::Stop is nodig voor een correcte stop van de simulatie. Bovendien, wanneer ns-3 in emulatiemodus is, wordt RealtimeSimulator gebruikt om de simulatieklokken te synchroniseren met de machineklokken, en Simulator::Stop is nodig om het proces te stoppen.

Veel van de simulatieprogramma's in de handleiding roepen niet op Simulator::Stop Dit is duidelijk, omdat ze automatisch eindigen met het opraken van gebeurtenissen in de wachtrij. Echter, deze programma's zullen ook Simulator::Stop aanroepen. Bijvoorbeeld, de volgende extra opdracht in het eerste programma voorbeeld plant een expliciete stop op seconde 11:

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

Het bovenstaande verandert feitelijk het gedrag van dit programma niet, aangezien deze specifieke simulatie natuurlijk eindigt na 10 seconden. Maar als je de stoptijd in de bovenstaande opdracht zou veranderen van 11 seconden naar 1 seconde, zou je merken dat de simulatie stopt voordat enige output op het scherm verschijnt (aangezien de output ongeveer 2 seconden simulatie tijd vereist).

Het is belangrijk om Simulator::Stop aan te roepen vóór de aanroep van Simulator::Run; anders kan Simulator::Run nooit de controle teruggeven aan het hoofdprogramma om de stop uit te voeren!

4.2.9 Het bouwen van je scenario

We hebben het maken van jouw eenvoudige scripts triviaal gemaakt. Alles wat je hoeft te doen, is jouw script in de scratch-directory te plaatsen, en het wordt automatisch gecompileerd wanneer je draait Waf. Laten we het proberen. Ga terug naar de bovenliggende directory en kopieer examples/tutorial/first.cc in de map scratch

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

Nu kun je je eerste script voorbeeld compileren met waf:

$ ./waf

Je zou berichten moeten zien dat je eerste voorbeeld succesvol is aangemaakt.

Waf: De directory `home/craigdo/repos/ns-3-allinone/ns-3-dev/build' binnen
[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: Verlaat directory `home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
'build' succesvol afgerond (2.357s)

Nu kun je het voorbeeld uitvoeren (let op dat als je je programma in de scratch-directory compileert, je het ook vanuit daar moet uitvoeren scratch):

$ ./waf --run scratch/myfirst

Je zou een soortgelijke output moeten zien:

Waf: De directory `home/craigdo/repos/ns-3-allinone/ns-3-dev/build' binnen
Waf: Verlaat directory `home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
'build' succesvol afgerond (0.418s) Verzend 1024 bytes naar 10.1.1.2
Ontvangen 1024 bytes van 10.1.1.1
Ontvangen 1024 bytes van 10.1.1.2

Hier ziet u dat het build-systeem controleert of het bestand is samengesteld en het vervolgens uitvoert. U ziet een registratiecomponent op de echo-client die aangeeft dat het een pakket van 1024 bytes heeft verzonden naar de echo-server 10.1.1.2. U ziet ook de registratielogboeken op de echo-server om te zeggen dat het 1024 bytes heeft ontvangen van 10.1.1.1. De echo-server herhaalt stilletjes het pakket en u ziet in het logboek van de echo-client dat het zijn pakket terug van de server heeft ontvangen.

4.3 ns-3 Bronnen code

Nu u enkele van de ns-3 helpers heeft gebruikt, kunt u kijken naar enkele broncodes die deze functionaliteit implementeren. De meest recente code kan op onze webserver worden bekeken via de volgende link: https://gitlab.com/nsnam/ns-3-dev.git. Daar vindt u een samenvattingspagina van Mercurial voor onze ns-3 ontwikkelboom. Bovenaan de pagina ziet u enkele links,

summary | shortlog | changelog | graph | tags | files

Ga verder en selecteer de link naar bestanden. Zo ziet de bovenkant van de meeste van onze repositories eruit:

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        bestand | revisies | annoteren
-rw-r--r-- 2009-07-01 12:47 +0200 1886   .hgtags          bestand | revisies | annoteren
-rw-r--r-- 2009-07-01 12:47 +0200 1276   AUTHORS          bestand | revisies | annoteren
-rw-r--r-- 2009-07-01 12:47 +0200 30961  CHANGES.html     bestand | revisies | annoteren
-rw-r--r-- 2009-07-01 12:47 +0200 17987  LICENSE          bestand | revisies | annoteren
-rw-r--r-- 2009-07-01 12:47 +0200 3742   README           bestand | revisies | annoteren
-rw-r--r-- 2009-07-01 12:47 +0200 16171  RELEASE_NOTES    bestand | revisies | annoteren
-rw-r--r-- 2009-07-01 12:47 +0200 6      VERSION          bestand | revisies | annoteren
-rwxr-xr-x 2009-07-01 12:47 +0200 88110  waf              bestand | revisies | annoteren
-rwxr-xr-x 2009-07-01 12:47 +0200 28     waf.bat          bestand | revisies | annoteren
-rw-r--r-- 2009-07-01 12:47 +0200 35395  wscript          bestand | revisies | annoteren
-rw-r--r-- 2009-07-01 12:47 +0200 7673   wutils.py        bestand | revisies | annoteren

Onze voorbeeldscriptbestanden bevinden zich in de directory examples. Als u op de voorbeelden klikt, ziet u een lijst met subdirectories. Een van de bestanden in de subdirectory tutorial — first.cc. Als u op de link klikt, first.cc ziet u de code die u zojuist hebt bestudeerd.

De broncode bevindt zich voornamelijk in de directory srcU kunt de broncode bekijken door op de mapnaam te klikken of op de bestandslink rechts van de mapnaam. Als u op de src-map klikt, krijgt u een lijst van submappen in src. Wanneer u vervolgens op de submap core klikt, vindt u een lijst met bestanden. Het eerste bestand dat u zult zien (ten tijde van het schrijven van deze handleiding) is abort.h. Als u op de link klikt abort.h, wordt u doorgestuurd naar het bronbestand voor abort.h, dat nuttige macro's bevat voor het beëindigen van scripts bij abnormaliteiten. De broncode voor de hulpprogramma's die we in dit hoofdstuk hebben gebruikt, is te vinden in de map src/Applications/helper. Aarzel niet om in de boomstructuur van mappen te graven om te begrijpen wat waar is en om vertrouwd te raken met de programmeerstijl van ns-3.

Bron: habr.com

Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers 🔥 Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers | ProHoster