Introduktion til ns-3 netværkssimulator. Kapitel 4

Introduktion til ns-3 netværkssimulator. Kapitel 4
kapitler 1,2
kapitel 3

4 Oversigt over konceptet
4.1 Nøgleabstraktioner
4.1.1 Node
4.1.2 Applikation
4.1.3 Kanal
4.1.4 Netværksenhed
4.1.5 Topologiske hjælpere
4.2 Første ns-3 script
4.2.1 Boilerplate kode
4.2.2 Plug-in moduler
4.2.3 Namespace ns3
4.2.4 Logning
4.2.5 Hovedfunktion
4.2.6 Brug af topologiske hjælpere
4.2.7 Brug af applikation
4.2.8 Simulator
4.2.9 Bygning af dit scenarie
4.3 ns-3 Kildekode

Kapitel 4

Oversigt over konceptet

Det første, vi skal gøre, før vi begynder at lære eller skrive ns-3 kode, er at forklare nogle grundlæggende begreber og abstraktioner i systemet. Meget af dette kan virke indlysende for nogle, men vi anbefaler at tage sig tid til at læse denne sektion for at sikre, at du starter på et solidt fundament.

4.1 Nøgleabstraktioner

I denne sektion vil vi se på nogle termer, der normalt bruges i nettet, men har en specifik betydning i ns-3.

4.1.1 Node

I internetslængden kaldes en computer, der tilsluttes et netværk, en vært eller nogle gange et slutpunkt. Da ns-3 er en netværkssimulator og ikke en internetsimulator, undgår vi bevidst termen vært, da det er tæt relateret til internettet og dets protokoller. I stedet bruger vi et mere generelt udtryk, der også anvendes af andre simulatorer, som har sin oprindelse i grafteori — node (node).

I ns-3 er den grundlæggende abstraktion af en computer en node. Denne abstraktion er repræsenteret i C++ ved klassen Node. Klassen NodeNode (node) giver metoder til at styre repræsentationerne af computerenheder i simulationer.

Du skal forstå Node hvordan en computer, hvortil du vil tilføje funktionalitet. Du vil tilføje ting som applikationer, protokolstakke og perifere kort med drivere, der giver computeren mulighed for at udføre nyttigt arbejde. Vi bruger den samme grundlæggende model i ns-3.

4.1.2 Applikation

Generelt opdeles computerprogrammer i to brede klasser. Systemsoftware organiserer forskellige computerressourcer som hukommelse, CPU-cyklusser, disk, netværk mv. i overensstemmelse med en bestemt beregningsmodel. Systemsoftware bruger normalt ikke disse ressourcer til at udføre opgaver, der giver direkte fordel for brugeren. For at nå et bestemt mål starter brugeren typisk et program, der får og bruger de ressourcer, der styres af systemsoftwaren.

Grænsen mellem systemsoftware og applikationssoftware trækkes ofte ved ændring af privilegieniveauet, som finder sted ved operativsystemets traps. I ns-3 findes der ikke nogen reel koncept for operativsystemet, og derfor er der heller ikke begreber som privilegieniveauer eller systemopkald. Vi har dog ideen om applikationer. Ligesom i den 'virkelige verden' udfører programapplikationer opgaver på computere, fungerer ns-3-applikationer på ns-3-noder for at styre simulationer i den simulerede verden.

I ns-3 er den grundlæggende abstraktion for brugerprogrammer, der genererer noget aktivitet til modellering, en applikation. Denne abstraktion er repræsenteret i C++ ved klassen Application. Klassed Application giver metoder til at styre præsentationerne af vores versioner af brugerniveauapplikationer i simulationerne. Det forventes, at udviklerne specialiserer klassens Application for at oprette nye applikationer i forhold til objektorienteret programmering. I denne vejledning vil vi bruge specialiseringer af klassen Application, kaldet UdpEchoClientApplication og UdpEchoServerApplication. Som forventet udgør disse applikationer et sæt client/server-applikationer, der bruges til at generere og ekko-simulere netværkspakker.

4.1.3 Kanal

I den virkelige verden kan en computer tilsluttes et netværk. Ofte kaldes de miljøer, hvor data overføres i disse netværk, for kanaler. Når du tilslutter et Ethernet-kabel til en stikkontakt i væggen, forbinder du computeren med en Ethernet-forbindelseskanal. I den simulerede verden ns‑3 tilsluttes en node til et objekt, der repræsenterer en kommunikationskanal. Her kaldes den primære abstraktion af kommunikationsunderkabet en kanal og repræsenteres i C++ af klassen Channel.

Klasse ChannelChannel giver metoder til at styre interaktionen mellem objekter i underkabet og tilslutningen af noder til dem. Kanaler kan også specialiseres af udviklere inden for objektorienteret programmering. En specialiseret kanal kan modellere noget enkelt som en ledning. En specialiseret kanal kan også modellere komplekse ting som en stor Ethernet-switch eller et tredimensionelt rum fyldt med forhindringer i tilfælde af trådløse netværk.

Vi vil i denne vejledning anvende specialiserede versioner af kanalen, kaldet CsmaChannelCsmaChannel, PointToPointChannelPointToPointChannel og WifiChannelWifiChannel. CsmaChannel, for eksempel, modellerer en version af kommunikationsunderkabet, der implementerer et kommunikationsmiljø for multiple adgang med bærerkontrol. Dette giver os Ethernet-lignende funktionalitet.

4.1.4 Netværksenhed

Tidligere var det sådan, at hvis du ville tilslutte en computer til et netværk, var du nødt til at købe et specifikt netværkskabel og en hardwareenhed, kaldet (i PC-terminologi) et perifert kort, som skulle installeres i computeren. Hvis der blev implementeret nogle netværksfunktioner på det perifere kort, blev de kaldt netværksinterfacekort eller netværkskort. I dag leveres de fleste computere med integreret netværksinterfacehardware, og brugerne ser dem ikke længere som separate enheder.

Et netværkskort fungerer ikke uden en softwaredriver, der styrer dets hardware. I Unix (eller Linux) klassificeres en del perifert udstyr som device. Enheder styres ved hjælp af enhedsdrivere (device drivers), og netværksenheder (NIC) styres ved hjælp af netværksenhedsdrivere (network device drivers) og har det samlede navn netværksenheder (net devices). I Unix og Linux får du adgang til netværksenheder ved hjælp af navne som for eksempel eth0.

I ns-3 dækker abstraktionen af netværksenheden både softwaredriveren og det simulerede udstyr. Når der simuleres, er netværksenheden "installeret" i noden for at muliggøre kommunikation med andre noder via kanaler. Ligesom i en rigtig computer kan en node være tilsluttet flere kanaler gennem flere enheder. NetDevices.

Netværksabstraktionen af enheden repræsenteres i C++ ved klassen NetDevice. Klassen NetDevice giver metoder til at styre forbindelser med objekterne Node og Channel; og kan specialiseres af udviklere inden for objektorienteret programmering. I denne vejledning vil vi bruge flere specialiserede versioner af NetDevice med navnene CsmaNetDevice, PointToPointNetDevice. og WifiNetDevice. Ligesom netværksadapteren Ethernet er designet til at arbejde med netværket Ethernet, CsmaNetDevice er designet til at arbejde med CsmaChannel, PointToPointNetDevice. er designet til at arbejde med PointToPointChannel, og WifiNetDevice — er designet til at arbejde med WifiChannel.

4.1.5 Topologiske hjælpere

I et rigtigt netværk vil du finde værtscomputere med tilføjede (eller indbyggede) netværkskort. I ns-3 ville vi sige, at du vil se noder med tilsluttede NetDevices. I et stort simuleret netværk skal du organisere forbindelser mellem mange objekter. Node, NetDevice og Channel.

Da tilslutning af NetDevices til noder, NetDevices til kanaler, tildeling af IP-adresser osv. i ns-3 er en almindelig opgave, tilbyder vi såkaldte topologihjælpere for at gøre denne proces så enkel som muligt. For eksempel kræver oprettelse af en NetDevice mange operationer i ns-3-kernen, tilføjelse af en MAC-adresse, installation af denne netværksenhed i Node, konfiguration af nodens protokolstack og derefter tilslutning af NetDevice til Channel. Endnu flere operationer vil være nødvendige for at forbinde flere enheder til multipointkanaler og derefter forbinde separate netværk til et samlet netværk (Internetworks). Vi tilbyder hjælpeobjekter til topologi, der for din bekvemmelighed samler disse mange operationer i en brugervenlig model.

4.2 Første ns-3 script

Hvis du har installeret systemet som foreslået ovenfor, vil du have en ns-3-udgivelse i en mappe med navnet repos i din hjemmemappe. Gå ind i mappen release

Hvis du ikke har en sådan mappe, betyder det, at du ikke har angivet output-mappen, da du byggede ns-3-udgivelsen. Byg den således:
$ .\/waf configure —build-profile=release —out=build\/release,
$ .\/waf build

her skal du se en mappestruktur, der ligner følgende:

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

Gå til mappen eksempler/tutorial. Du skal se en fil med navn first.cc. Dette er et script, der opretter en simpel punkt-til-punkt-forbindelse mellem to noder og sender et enkelt paket mellem dem. Lad os se på dette script linje for linje, ved at åbne first.cc i din yndlingseditor.

4.2.1 Boilerplate kode
Den første linje i filen er editorens tilstandslinje emacs. Den informerer emacs om formateringskonventionerne (kodestil), som vi bruger i vores kildekode.

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

Det er altid et ret omdiskuteret emne, så vi skal gøre det klart og komme det til livs med det samme. Projektet ns-3, ligesom de fleste store projekter, har vedtaget en kodestil, som al medfølgende kode skal overholde. Hvis du ønsker at bidrage med din kode til projektet, må du til sidst overholde ns-3's kodestandard, som beskrevet i filen doc\/codingstd.txt eller vist på projektets webside: https://www.nsnam.org/develop/contributing-code/coding-style/.

Vi anbefaler, at du vænner dig til udseendet af ns-3-koden og anvender denne standard hver gang du arbejder med vores kode. Hele udviklerteamet og bidragydere er blevet enige om dette efter noget brok. Emacs tilstandslinjen ovenfor gør korrekt formatering lettere, hvis du bruger emacs.

Simulatoren ns-3 licenseres under GNU General Public License. Du vil se den relevante juridiske header for GNU i hver fil i ns-3 distributionen. Ofte kan du se en ophavsretserklæring for et af de deltagende institutioner i projektet ns-3 over teksten GPL og forfatteren vist nedenfor.

/* 
* 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 Plug-in moduler

Selve koden starter med en række include-direktiver (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"

For at hjælpe vores brugere af høj-niveau scripts med at håndtere det store antal header-filer i systemet, grupperer vi dem efter deres anvendelse i større moduler. Vi tilbyder en enkelt header-fil, der rekursivt indlæser alle de header-filer, der anvendes i det pågældende modul. I stedet for at skulle finde den specifikke header, du har brug for, og muligvis få den rigtige liste af afhængigheder, giver vi dig mulighed for at indlæse en gruppe filer med stor detaljeringsgrad. Dette er ikke den mest effektive tilgang, men det gør bestemt scriptningen meget lettere.

Hver af de inkluderede filer ns-3 placeres i en mappe med navnet ns3 (build-undermappe), for at undgå navnekonflikter under byggeprocessen. Filen ns3/core-module.h svarer til ns-3 modulet, som du finder i mappen src/core i den version, du har installeret. I listen over denne mappe vil du finde et stort antal header-filer. Når du bygger, Waf placerer de offentlige header-filer i ns3 mappen i undermappen build/debug

Hvis du ikke har en sådan mappe, betyder det, at du ikke har angivet output-mappen, da du byggede ns-3-udgivelsen. Byg den således:
$ ./waf configure --build-profile=debug --out=build/debug
$ .\/waf build
eller
$ ./waf configure --build-profile=optimized --out=build/optimized
$ .\/waf build

eller build/optimized, afhængigt af din konfiguration. Waf vil også automatisk generere en inkluderingsfil for modulet til at indlæse alle de offentlige header-filer. Da du naturligvis strengt følger denne vejledning, har du allerede lavet

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

for at konfigurere projektet til at udføre debug builds, der inkluderer eksempler og tests. Du har også lavet

$ ./waf

for at bygge projektet. Så nu, når du kigger i mappen ../../build/debug/ns3, finder du der blandt andet header-filerne fra de fire nævnte moduler. Du kan kigge på indholdet af disse filer og opdage, at de inkluderer alle de offentlige filer, der anvendes af de respektive moduler.

4.2.3 Namespace ns3

Den næste linje i scriptet first.cc er erklæringen om namespaces.

using namespace ns3;

Projektet ns-3 er implementeret i et C++ navnerum kaldet ns3. Dette grupperer alle ns-3-relaterede erklæringer uden for det globale navnerum, hvilket vi håber vil hjælpe med integrationen med anden kode. Brug af C++ operatoren introducerer ns-3 navnerummet i den nuværende (globale) deklarative region. Dette er en sjov måde at sige, at efter denne erklæring, behøver du ikke at indtaste ns3:: scope operatoren før al ns-3 kode for at bruge det. Hvis du ikke er bekendt med navnerum, kan du konsultere næsten enhver C++ lærebog og sammenligne navnerummet ns3 med brugen af navnerummet std og erklæringer. using namespace std; i eksempler med udskrivningsoperatoren cout og streamene.

4.2.4 Logning

Den næste linje i scriptet er

NS_LOG_COMPONENT_DEFINE ("FirstScriptExample");

Vi vil bruge denne erklæring som et bekvemt udgangspunkt for at diskutere vores dokumentationssystem Doxygen. Hvis du ser på webstedet for ns-3 projektet, vil du finde et link til "Dokumentation" (Documentation) i navigationspanelet. Hvis du vælger dette link, vil du komme til vores dokumentationsside. Der er et link til "Seneste udgave", som vil føre dig til dokumentationen for den nyeste stabile version af ns-3. Hvis du vælger linket "API Documentation", vil du komme til siden for ns-3 API dokumentationen.

Til venstre på siden finder du en grafisk repræsentation af dokumentationsstrukturen. Et godt sted at starte er "bogen" Modules ns-3 i navigeringstræet for ns-3. Hvis du folder ud Moduler, vil du se en liste over dokumentationen for ns-3 moduler. Som nævnt ovenfor er konceptet med moduler her direkte relateret til de filer, der er inkluderet i modulet ovenfor. ns-3's logningsunder-system diskuteres i afsnittet Brug af logningsmodulet, så vi vender tilbage til det senere i denne vejledning, men du kan lære om den ovenfor nævnte erklæring ved at se på modulet Core, og derefter åbne bogen Debugging tools, og derefter vælge siden Logging. Klik på Logging.

Nu skal du gennemse dokumentationen Doxygen for modulet Logging. I listen to the macros in the top of the page, you will see an entry for NS_LOG_COMPONENT_DEFINE. Before following the link, be sure to check the 'Detailed Description' of the logging module to understand its function as a whole. To do this, you can scroll down or select 'More...' under the diagram.

Once you have a general understanding of what is happening, continue and look at the documentation for specific NS_LOG_COMPONENT_DEFINE. I will not duplicate the documentation here, but to summarize, this line declares a logging component called FirstScriptExample, which allows you to enable and disable console logging of messages by linking to its name.

4.2.5 Hovedfunktion

In the following lines of the script, you will see

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

This is simply the declaration of the main function of your program (script). As in any C++ program, you need to define the main function; it executes first. There is nothing special here. Your ns-3 script is just a C++ program. The next line sets the time resolution to 1 nanosecond, which is the default value:

Time::SetResolution (Time::NS);

Time resolution, or simply resolution, is the smallest time value that can be used (the smallest representable difference between two time values). You can change the resolution exactly once. The mechanism that provides this flexibility consumes memory; therefore, once the resolution is explicitly set, we release the memory to prevent further updates. (If you do not set the resolution explicitly, it will default to one nanosecond, and memory will be released at the start of the simulation.)

The next two lines of the script are used to enable two logging components that are built into the applications EchoClient og EchoServer:

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

Hvis du har læst dokumentationen for Logging-komponenten, vil du se, at der er flere detaljegrader for logning, som du kan aktivere for hver komponent. Disse to linjer med kode aktiverer fejllogning på INFO-niveau for echo-klienter og servere. På dette niveau vil applikationen udskrive beskeder under simuleringen, når pakker sendes og modtages.

Lad os nu gå direkte til oprettelsen af topologien og kørsel af simuleringen. Vi vil bruge topologiske hjælpeobjekter for at gøre arbejdet så nemt som muligt.

4.2.6 Brug af topologiske hjælpere

De følgende to linjer med kode i vores script vil faktisk oprette ns-3 Node-objekter, som vil repræsentere computere i simuleringen.

NodeContainer nodes;
nodes.Create (2);

Før vi fortsætter, lad os finde dokumentationen for klassen NodeContainer. En anden måde at tilgå dokumentationen for denne klasse på er via fanen Classes på siderne Doxygen. Hvis du allerede har Doxygen åbnet, skal du blot rulle op til toppen af siden og vælge fanen Classes. Du skal se et nyt sæt faner, hvoraf en indeholder en liste over klasser. Under denne fane vil du se en liste af alle ns-3 klasser. Rul ned til ns3::NodeContainer. Når du finder klassen, skal du vælge den for at gå til dokumentationen for klassen.

Som vi husker, er en af vores vigtigste abstraktioner noden. Den repræsenterer en computer, hvortil vi vil tilføje ting som protokolstakke, applikationer og perifere kort. Den topologiske hjælper NodeContainer giver en praktisk måde at oprette, styre og tilgå alle objekter Node, som vi opretter for at køre simuleringen. Den første linje ovenfor erklærer NodeContainer, som vi kalder nodes. Den anden linje kalder metoden Create for objektet nodes og beder containeren om at oprette to noder. Som beskrevet i Doxygen, beder containeren systemet ns-3 om at oprette to objekter Node og gemmer pointerne til disse objekter internt.

De noder, der er oprettet i scriptet, laver indtil videre ingenting. Næste skridt i opbygning af topologien er at forbinde vores noder til netværket. Den enkleste form for netværk, vi understøtter, er en punkt-til-punkt-forbindelse mellem to noder. Vi vil nu oprette sådan en forbindelse.

PointToPointHelper

Vi skaber en to-punkts-forbindelse ved at følge en kendt skabelon, hvor vi bruger et topologisk hjælpeobjekt til at udføre det lavniveau arbejde, der er nødvendigt for at oprette forbindelsen. Lad os minde om, at vores to nøgleabstraktioner NetDevice og Channel. I den virkelige verden svarer disse termer nogenlunde til periferikort og netværkskabler. Generelt er disse to ting tæt forbundet, og ingen kan forvente at udveksle for eksempel enheder Ethernet via et trådløst link. Vores topologiske hjælpere følger denne tætte forbindelse, og derfor vil du i dette scenarie bruge ét objekt PointToPointHelper til at konfigurere og oprette forbindelse mellem ns‑3 objekter PointToPointNetDevice. og PointToPointChannel. De følgende tre linjer i scenariet:

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

Den første linje,

PointToPointHelper pointToPoint;

opretter et instans af objektet i stakken. PointToPointHelperSet fra et overordnet perspektiv, fortæller den næste linje,

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

objektet PointToPointHelper at bruge værdien "5 Mbps" (fem megabit pr. sekund) som "DataRate».

Set fra et mere konkret perspektiv, svarer linjen "DataRate" til det, vi kalder en attribut PointToPointNetDevice.. Hvis du ser på Doxygen for klassen ns3::PointToPointNetDevice og i dokumentationen for metoden GetTypeId vil du finde en liste over de attributter, der er defineret for enheden. Blandt dem vil der være attributten "DataRate". De fleste synlige brugerobjekter i ns‑3 har lignende lister over attributter. Vi bruger denne mekanisme til let at tilpasse simuleringen uden at skulle recompilere, som du vil se i det næste afsnit.

Ligesom "DataRate" i PointToPointNetDevice, finder du attributten "Delay" relateret til PointToPointChannel. Den afsluttende linje,

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

says PointToPointHelper bruger værdien "2 ms" (to millisekunder) som spredningsforsinkelsesværdi for den point-to-point kanal, den efterfølgende opretter.

NetDeviceContainer

På nuværende tidspunkt har vi i scenariet NodeContainer, som indeholder to noder. Vi har PointToPointHelper, som er klargjort til at oprette objekter PointToPointNetDevices og forbinde dem via et PointToPointChannel objekt. Ligesom vi brugte et topologisk hjælpeobjekt NodeContainer til at oprette noder, vil vi bede PointToPointHelper om at udføre det arbejde, der er relateret til at oprette, konfigurere og installere vores enheder. Vi får brug for en liste over alle de oprettede objekter NetDevice, så vi bruger NetDeviceContainer til opbevaring ligesom vi brugte NodeContainer til opbevaring af de noder, vi har oprettet. De næste to linjer kode,

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

afslutter konfigurationen af enhederne og kanalen. Den første linje deklarerer enhedens container, som nævnt ovenfor, og den anden udfører det primære arbejde. Metoden Installer området PointToPointHelper modtager NodeContainer som parameter. Inden for NetDeviceContainer for hver node, der er i NodeContainer oprettes (for en punkt-til-punkt-forbindelse skal der være præcist to) PointToPointNetDevice. oprettes og gemmes i enhedens container. PointToPointChannel oprettes, og der tilsluttes to PointToPointNetDevices. Efter oprettelsen af objekterne anvendes de gemte attributter i PointToPointHelper, til at initialisere de relevante attributter i de oprettede objekter.

Efter kaldet pointToPoint.Install (nodes) vil vi have to noder, hver med en installeret "punkt-til-punkt" netværksenhed og en "punkt-til-punkt" forbindelse mellem dem. Begge enheder vil være konfigureret til at transmittere data med en hastighed på fem megabit per sekund med en overførselstid på to millisekunder.

InternetStackHelper

Nu har vi konfigureret noderne og enhederne, men der er ikke installeret protokolstakke på vores noder. De næste to linjer kode vil sørge for dette.

InternetStackHelper stack;
stack.Install (nodes);

InternetStackHelper — fungerer som en topologisk hjælpeklasse for internetstakke, ligesom PointToPointHelper gør det for punkt-til-punkt netværksenheder. Metoden Installer modtager NodeContainer som parameter. Ved udførelse vil den installere internetstakken (TCP, UDP, IP osv.) på hver node i containeren.

Ipv4AddressHelper

Derefter skal vi tilknytte vores enheder med IP-adresser. Vi leverer en topologisk hjælpeklasse til at styre distributionen af IP-adresser. Den eneste synlige API for brugeren er indstillingen af en grundlæggende IP-adresse og subnetmaske, som skal bruges ved udførelsen af den faktiske adressering (dette gøres på et lavere niveau inden for hjælpeklassen). De næste to linjer i vores eksempel script first.cc,

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

deklarerer et hjælpeobjekt for adressen og fortæller det, at det skal begynde at tildele IP-adresser fra netværket 10.1.1.0 ved at bruge en subnetmaske på 255.255.255.0. Som standard vil de tildelte adresser begynde med én og stige monotont, så den første adresse tildelt fra denne base vil være 10.1.1.1, derefter 10.1.1.2 osv. I virkeligheden gemmer systemet ns-3 alle tildelte IP-adresser på et lavt niveau og genererer en kritisk fejl, hvis du ved et uheld skaber en situation, hvor den samme adresse genereres to gange (forresten er denne fejl svær at debugge).

Den næste linje kode,

Ipv4InterfaceContainer interfaces = address.Assign (devices);

udfører den faktiske tildeling af adressen. I ns-3 etablerer vi forbindelsen mellem IP-adressen og enheden ved at bruge objektet Ipv4Interface. Ligesom vi nogle gange har brug for en liste over netværksenheder, der er oprettet af assistenten til fremtidig brug, har vi nogle gange brug for en liste over objekter, Ipv4Interface. Ipv4InterfaceContainer giver denne funktionalitet.

Vi har bygget et punkt-til-punkt netværk med installerede stak og tildelte IP-adresser. Nu har vi brug for applikationer i hver node til at generere trafik.

4.2.7 Brug af applikation

Endnu en af de grundlæggende abstraktioner i systemet ns-3 er Applikation (applikation). I dette scenario bruger vi to specialiseringer af basis-klassen Applikation ns-3 kaldet UdpEchoServerApplication og UdpEchoClientApplication. Ligesom tidligere tilfælde bruger vi hjælpeobjekter til at konfigurere og administrere grundlæggende objekter. Her bruger vi UdpEchoServerHelper og UdpEchoClientHelperobjekter for at gøre vores liv lettere.

UdpEchoServerHelper

De følgende linjer kode i vores eksempel script first.cc anvendes til at konfigurere UDP echo serverapplikationen i en af de noder, vi tidligere har oprettet.

UdpEchoServerHelper echoServer (9);

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

Den første linje kode i det ovenfor nævnte fragment skaber UdpEchoServerHelper. Som sædvanligt er dette ikke en applikation i sig selv, men et objekt, der hjælper os med at skabe reelle applikationer. En af vores aftaler er at videregive de nødvendige attributter til konstruktøren af hjælpeobjektet. I dette tilfælde kan hjælpemidlet ikke gøre noget nyttigt, hvis det ikke får tildelt portnummeret, som serveren vil lytte på, og dette nummer skal også være kendt af klienten. Her videregiver vi konstruktøren af hjælpeobjektet portnummeret. Konstruktøren udfører i sin tur bare SetAttribute med den overførte værdi. Senere, hvis det ønskes, kan du med SetAttribute indstille en anden værdi for attributten 'Port'.

Ligesom mange andre hjælpeobjekter har objektet UdpEchoServerHelper en metode Installer. At udføre denne metode resulterer faktisk i, at der oprettes en grundlæggende echo-server applikation, der bindes til noden. Det er interessant, at metoden Installer modtager NodeContainter som parameter, ligesom andre Installer metoder, vi har set.

Implicit konvertering i C++, der fungerer her, tager resultatet af metoden node.Get (1) (som returnerer en smart pointer til nodeobjektet - Ptr) og bruger det i konstruktøren til det anonyme objekt NodeContainer, som derefter videregives til metoden Installer. Hvis du ikke kan bestemme, hvilken signatur metoden kompileres og udføres med i C++ koden, så kig blandt de implicitte konverteringer.

Nu ser vi, at echoServer.Install vil installere applikationen UdpEchoServerApplication på den fundne i NodeContainer, som vi bruger til at administrere vores noder, noden med indeks 1. Metoden Installer vil returnere en container, der indeholder pointers til alle applikationer (i dette tilfælde én, da vi videregav det anonyme NodeContainer, der indeholder én node), som blev oprettet af hjælpemidlet.

Applikationerne skal angive tidspunktet for begyndelsen af trafikgenereringen 'start' og kan også have brug for at angive det tidspunkt, hvor den skal stoppes 'stop'.Vi leverer begge parametre. Disse tidspunkter indstilles ved hjælp af metoderne ApplicationContainer Start og Stop. Disse metoder tager parametre af typen Tid. I dette tilfælde bruger vi eksplicitte sekvenser af C++ konverteringer for at tage C++ double 1.0 og transformere det til objektet tns‑3 Time, der bruger objektet Seconds til at konvertere til sekunder. Husk, at transformationsreglerne kan styres af modelens forfatter, og C++ har sine egne regler, så du kan ikke altid regne med, at parametrene bliver konverteret, som du forventede. To linjer,

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

vil føre til, at echo-serverapplikationen starter (tændes automatisk) et sekund efter simulationsstart og stopper (slukkes) efter ti sekunder af simulationen. Da vi har erklæret en simuleringsbegivenhed (applikationsstopbegivenhed), der vil blive udført efter ti sekunder, vil der blive simuleret mindst ti sekunders netværksdrift.

UdpEchoClientHelper

Klientapplikationen echo konfigureres på en måde, der praktisk talt ligner serveren. Der findes et grundlæggende objekt UdpEchoClientApplication, som styres af
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));;

Men for echo-klienten skal vi indstille fem forskellige attributter. De første to attributter sættes under oprettelsen UdpEchoClientHelper. Vi sender de parametre, der bruges (inde i hjælpemidlet) til at indstille attributterne «RemoteAddress» og «RemotePort» i henhold til vores aftale om at overføre de nødvendige parametre til hjælpekonstruktøren.

Lad os huske, at vi brugte Ipv4InterfaceContainer til at spore IP-adresserne, som vi har tildelt vores enheder. Den nul-interface i interface-containeren vil svare til IP-adressen for nul-knuden i noden-containeren. Den første interface i interface-containeren svarer til IP-adressen for den første knude i noden-containeren. Så i den første linje af koden (øverst) opretter vi hjælpemidlet og informerer det om, at klientens fjernadresse vil være IP-adressen tildelt den knude, hvor serveren er placeret. Vi siger også, at pakkerne skal sendes til den niende port.

Attributten «MaxPackets» informerer klienten om det maksimale antal pakker, vi kan sende under simuleringen. Attributten «Interval» fortæller klienten, hvor længe der skal ventet mellem pakkerne, og attributten «PacketSize» angiver, hvor stor nyttelasten for pakken skal være. Med denne kombination af attributter beder vi klienten om at sende én 1024-byte pakke.

Som i tilfældet med ekko-serveren, konfigurerer vi ekko-klienten med attributter, Start og Stop, men her starter vi klienten et sekund efter, at serveren er blevet tændt (to sekunder efter simuleringen er startet).

4.2.8 Simulator

På dette tidspunkt skal vi starte simuleringen. Dette gøres ved hjælp af den globale funktion, Simulator::Run.

Simulator::Run ();

Da vi tidligere kaldte metoderne,

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

planlagde vi faktisk hændelser i simulatoren til 1,0 sekunder, 2,0 sekunder og to hændelser til 10,0 sekunder. Efter kaldet, Simulator::Run, vil systemet begynde at gennemgå listen over planlagte hændelser og udføre dem. Først vil det starte hændelsen efter 1,0 sekunder, hvilket aktiverer ekko-server applikationen (denne hændelse kan til gengæld planlægge mange andre hændelser). Derefter vil den starte hændelsen, der er planlagt til t = 2,0 sekunder, som vil starte ekko-klient applikationen. Igen kan denne hændelse planlægge mange flere hændelser. Implementeringen af start hændelsen i ekko-klienten vil starte dataoverførselsfasen af simuleringen ved at sende en pakke til serveren.

Aktet med at sende pakken til serveren vil tilkalde en kæde af hændelser, som automatisk vil blive planlagt i baggrunden og som vil implementere mekanikken for at sende ekkosignaler i henhold til de synkroniseringsparametre, vi har angivet i scriptet.

Som et resultat, da vi kun sender én pakke (husker at attributten MaxPackets er indstillet til én), vil kæden af hændelser, der blev initieret af denne enkeltstående klient ekko-anmodning, afsluttes, og simuleringen vil gå i ventetilstand. Så snart dette sker, vil de resterende planlagte hændelser være for serveren og klienten. Når disse hændelser udføres, vil der ikke være nogen hændelser tilbage til videre behandling og Stop vil returnere kontrol. Simuleringen er afsluttet. Simulator::Run Der er kun tilbage at rydde op efter os. Dette gøres ved at kalde den globale funktion,

Simulator::Destroy Simulator::Destroy. Da der kaldte hjælpefunktioner (eller ns-3 lavniveau kode), der er designet til at indføre hooks i simulatoren for at destruere alle oprettede objekter. Du behøver ikke at holde styr på nogen af disse objekter selv — alt hvad du skulle gøre, var at kalde Simulator::Destroy og afslutte. Ns-3-systemet vil gøre dette hårde arbejde for dig. De resterende linjer i vores første ns-3 script, first.cc, gør netop dette:

Simulator::Destroy ();
return 0;
}

Hvornår stopper simulatoren?

Ns-3 er en diskret hændelsessimulator (DE). I en sådan simulator er hver hændelse relateret til tidspunktet for dens udførelse, og simuleringen fortsætter med at behandle hændelser i den rækkefølge, de opstår undervejs i simuleringen. Hændelser kan føre til planlægning af fremtidige hændelser (for eksempel kan en timer omplanlægge sig selv for at afslutte nedtællingen i det næste interval).

Start-hændelser bliver typisk initieret af et objekt, for eksempel vil IPv6 planlægge opdagelse af tjenester i netværket, naborequests osv. Anvendelsen planlægger den første hændelse for afsendelse af pakker osv. Når hændelsen behandles, kan den generere nul, en eller flere hændelser. Efterhånden som simuleringen udføres, opstår hændelser, der enten afsluttes eller frembringer nye. Simuleringen stopper automatisk, hvis hændelseskøen er tom, eller hvis der opdages en særlig hændelse. Stop. Hændelsen Stop genereres af funktionen Simulator::Stop (stop tid).

Der er et typisk tilfælde, hvor Simulator::Stop er absolut nødvendigt for at stoppe simuleringen: når der er selvopretholdende hændelser. Selvopretholdende (eller gentagende) hændelser er hændelser, der altid omplanlægges. Som følge heraf holder de altid hændelseskøen ikke tom. Der er mange protokoller og moduler, der indeholder gentagende hændelser, såsom:

• FlowMonitor — periodisk kontrol for tabte pakker;

• RIPng — periodisk broadcasting af opdatering af rutetabeller;

• osv.

I sådanne tilfælde Simulator::Stop er nødvendig for korrekt at stoppe simuleringen. Desuden, når ns-3 er i emulator-mode, anvendes RealtimeSimulator til at synkronisere simulatorens ure med maskinens ure, og Simulator::Stop er nødvendigt for at stoppe processen.

Mange af simulationsprogrammerne i lærebogen kalder ikke Simulator::Stop klar, da de automatisk afsluttes, når der ikke er flere hændelser i køen. Men disse programmer vil også modtage kaldet Simulator::Stop. For eksempel vil følgende ekstra erklæring i det første program planlægge en eksplicit stop ved 11. sekund:

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

Det ovenstående vil faktisk ikke ændre adfærden af dette program, da denne specifikke simulering naturligvis slutter efter 10 sekunder. Men hvis du ændrede stop-tiden i den tidligere nævnte erklæring fra 11 sekunder til 1 sekund, ville du bemærke, at simuleringen stopper, før nogen output bliver vist på skærmen (da output sker cirka 2 sekunder efter simuleringens starttid).

Det er vigtigt at kalde Simulator::Stop før du kalder Simulator::Run; ellers kan Simulator::Run aldrig returnere kontrollen til hovedprogrammet for at udføre stoppet!

4.2.9 Bygning af dit scenarie

Vi har gjort det trivielt at oprette dine enkle scripts. Alt hvad du skal gøre, er at placere dit script i scratch-kataloget, og det vil automatisk blive bygget, hvis du kører Waf. Lad os prøve. Gå tilbage til rodkataloget og kopier examples/tutorial/first.cc til kataloget scratch

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

Nu skal du bygge dit første skripteksempel med waf:

$ ./waf

Du skal se beskeder, der viser, at dit første eksempel er blevet oprettet med succes.

Waf: Går ind i kataloget `/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: Forlader kataloget `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build`
'build' blev afsluttet med succes (2.357s)

Nu kan du køre eksemplet (vær opmærksom på, at hvis du bygger dit program i scratch-kataloget, så skal du også køre det fra scratch):

$ ./waf --run scratch/myfirst

Du skal se en lignende output:

Waf: Går ind i kataloget `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build`
Waf: Forlader kataloget `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build`
'build' blev afsluttet med succes (0.418s) Sendt 1024 bytes til 10.1.1.2
Modtaget 1024 bytes fra 10.1.1.1
Modtaget 1024 bytes fra 10.1.1.2

Her ser du, at bygge systemet tjekker, at filen er bygget, og derefter kører den den. Du ser, at komponentloggen på echo-klienten angiver, at den har sendt et 1024-byte pakke til echo-serveren 10.1.1.2. Du kan også se komponentloggeren på echo-serveren, der siger, at den har modtaget 1024 bytes fra 10.1.1.1. Echo-serveren gentager stille pakken, og du kan se i loggen på echo-klienten, at den har modtaget sin pakke tilbage fra serveren.

4.3 ns-3 Kildekode

Nu hvor du har brugt nogle af ns-3's hjælpere, kan du se på noget kildekode, der implementerer denne funktionalitet. Den nyeste kode kan ses på vores webserver via følgende link: https://gitlab.com/nsnam/ns-3-dev.git. Her vil du se en oversigtsside for Mercurial for vores ns-3 udviklingstræ. Øverst på siden vil du se nogle links,

summary | shortlog | changelog | graph | tags | files

Gå videre og vælg linket til filerne. Her er, hvordan toppen af de fleste af vores repositories vil se ud:

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

Vores eksempel scripts findes i mappen examples. Hvis du klikker på eksemplerne, vil du se en liste over undermapper. En af filerne i undermappen tutorial — first.cc. Hvis du klikker på first.cc vil du se koden, som du lige har lært.

Kildekoden ligger hovedsageligt i mappen src. Du kan se kildekoden ved at klikke på navnet på mappen eller ved at klikke på filerne til højre for mappenavnet. Hvis du klikker på mappen src, får du en liste over undermapperne i src. Hvis du derefter klikker på undermappen core, finder du en liste over filer. Den første fil, du vil se (på tidspunktet for skrivningen af denne vejledning) — abort.h. Hvis du klikker på linket abort.h, vil du blive sendt til kildefilen for abort.h, som indeholder nyttige makroer til at afslutte scripts, hvis unormale forhold opdages. Kildekoden til de hjælpeprogrammer, vi brugte i dette kapitel, findes i mappen src/Applications/helper. Tøv ikke med at dykke ned i mappestrukturen for at forstå, hvad der er, hvor det er, og få styr på stilen i ns-3 programmene.

Kilde: habr.com

Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere 🔥 Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster