ns-3 netwerksimulator-tutorial. Hoofdstuk 4

ns-3 netwerksimulator-tutorial. Hoofdstuk 4
Hoofdstuk 1,2
hoofdstuk 3

4 Conceptoverzicht
4.1 Belangrijkste abstracties
4.1.1 Knooppunt
4.1.2 Toepassing
4.1.3 Kanaal
4.1.4 Netapparaat
4.1.5 Topologische assistenten
4.2 Eerste ns-3-script
4.2.1 Boilerplatecode
4.2.2 Plug-ins
4.2.3 ns3-naamruimte
4.2.4 Loggen
4.2.5 Hoofdfunctie
4.2.6 Topologie-assistenten gebruiken
4.2.7 Applicatie gebruiken
4.2.8 Simulatie
4.2.9 Uw script bouwen
4.3 ns-3 Broncode

Hoofdstuk 4

Conceptoverzicht

Het eerste dat we moeten doen voordat we ns-3-code gaan leren of schrijven, is een paar basisconcepten en abstracties in het systeem uitleggen. Veel hiervan lijkt voor sommigen vanzelfsprekend, maar we raden u aan de tijd te nemen om dit gedeelte te lezen, zodat u zeker weet dat u op een solide basis begint.

4.1 Belangrijkste abstracties

In dit gedeelte bekijken we enkele termen die vaak op internet worden gebruikt, maar die in ns-3 een specifieke betekenis hebben.

4.1.1 Knooppunt

In internetjargon wordt een computerapparaat dat verbinding maakt met een netwerk een host of soms een eindsysteem genoemd. Omdat ns-3 een netwerksimulator is en geen internetsimulator, gebruiken we bewust niet de term host, omdat deze nauw verwant is aan internet en zijn protocollen. In plaats daarvan gebruiken we een meer algemene term, die ook door andere simulatoren wordt gebruikt en die zijn oorsprong vindt in de grafentheorie: node (knooppunt).

In ns-3 wordt de onderliggende abstractie van een computerapparaat een knooppunt genoemd. Deze abstractie wordt in C++ weergegeven door de klasse Node. Klas KnooppuntNode (knooppunt) biedt methoden voor het manipuleren van representaties van computerapparatuur in simulaties.

Je moet het begrijpen Knooppunt zoals een computer waaraan je functionaliteit toevoegt. U voegt zaken toe als applicaties, protocolstacks en randkaarten met stuurprogramma's waarmee de computer nuttig werk kan doen. Hetzelfde basismodel gebruiken we in ns-3.

4.1.2 Toepassing

Over het algemeen wordt computersoftware verdeeld in twee brede klassen. Systeemsoftware organiseert verschillende computerbronnen zoals geheugen, processorcycli, schijf, netwerk, enz. volgens een bepaald computermodel. Systeemsoftware gebruikt deze bronnen doorgaans niet om taken uit te voeren die de gebruiker rechtstreeks ten goede komen. Een gebruiker voert doorgaans een applicatie uit om een ​​specifiek doel te bereiken, waarbij bronnen worden verkregen en gebruikt die worden beheerd door de systeemsoftware.

Vaak wordt de scheidingslijn tussen systeem- en applicatiesoftware getrokken bij wijzigingen op het privilegeniveau die optreden in traps van besturingssystemen. ns-3 heeft geen echt concept van een besturingssysteem en daarom ook geen concept van privilegeniveaus of systeemaanroepen. Wel hebben wij een idee voor een app. Net zoals in de ‘echte wereld’ softwareapplicaties op computers draaien om taken uit te voeren, draaien ns-3-applicaties op ns-3-nodes om simulaties in de gesimuleerde wereld te besturen.

In ns-3 is de basisabstractie voor een gebruikersprogramma dat enige activiteit voor modellering genereert een applicatie. Deze abstractie wordt in C++ weergegeven door de klasse Application. De klasse Application biedt methoden voor het manipuleren van weergaven van onze gebruikersversie van applicaties in simulaties. Van ontwikkelaars wordt verwacht dat ze de klasse Application specialiseren in objectgeoriënteerd programmeren om nieuwe applicaties te creëren. In deze zelfstudie gebruiken we specialisaties van de klasse Application genaamd UdpEchoClientApplicatie и UdpEchoServerApplicatie. Zoals je zou verwachten, vormen deze applicaties een set client/server-applicaties die worden gebruikt om netwerkpakketten te genereren en te echoën.

4.1.3 Kanaal

In de echte wereld kunt u een computer op een netwerk aansluiten. Vaak worden de media waarover gegevens in deze netwerken worden verzonden, kanalen genoemd. Wanneer u een Ethernet-kabel in een stopcontact steekt, verbindt u uw computer met een Ethernet-verbinding. In de gesimuleerde ns-3-wereld is een knooppunt verbonden met een object dat een communicatiekanaal vertegenwoordigt. Hier wordt de basisabstractie van het communicatiesubnetwerk een kanaal genoemd en in C++ weergegeven door de klasse Channel.

Klasse KanaalKanaal biedt methoden voor het beheren van de interactie tussen subnetobjecten en het verbinden van hosts ermee. Kanalen kunnen ook door ontwikkelaars worden gespecialiseerd in objectgeoriënteerde programmeerzin. Kanaalspecialisatie kan zoiets eenvoudigs als een draad modelleren. Een speciaal kanaal kan ook complexe zaken modelleren, zoals een grote Ethernet-switch of een driedimensionale ruimte vol obstakels in het geval van draadloze netwerken.

We gebruiken gespecialiseerde versies van het kanaal in deze tutorial genaamd CsmaChannelCsmaChannel, PointToPointChannelPointToPointChannel и WifikanaalWifikanaal. CsmakanaalModelleert bijvoorbeeld een versie van een communicatiesubnet dat een carrier-sense communicatieomgeving met meerdere toegangen implementeert. Dit geeft ons Ethernet-achtige functionaliteit.

4.1.4 Netapparaat

Vroeger was het zo dat als je een computer op een netwerk wilde aansluiten, je een specifieke netwerkkabel en een hardwareapparaat moest kopen dat (in pc-terminologie) een randkaart werd genoemd en dat in de computer moest worden geïnstalleerd. Als een randkaart bepaalde netwerkfuncties implementeerde, werden ze netwerkinterfacekaarten of netwerkkaarten genoemd. Tegenwoordig worden de meeste computers geleverd met geïntegreerde netwerkinterfacehardware en worden ze door gebruikers niet als afzonderlijke apparaten gezien.

Een netwerkkaart werkt niet zonder een softwarestuurprogramma dat de hardware bestuurt. In Unix (of Linux) wordt een randapparaat geclassificeerd als een apparaat. Apparaten worden beheerd met behulp van apparaatstuurprogramma's, en netwerkapparaten (NIC's) worden beheerd met behulp van netwerkapparaatstuurprogramma's (stuurprogramma's voor netwerkapparaten) en worden gezamenlijk netwerkapparaten genoemd (netto apparaten). In Unix en Linux verwijs je naar netwerkapparaten met namen zoals eth0.

In ns-3 omvat de abstractie van netwerkapparaten zowel het softwarestuurprogramma als de hardware die wordt gemodelleerd. In de simulatie wordt een netwerkapparaat in een knooppunt "geïnstalleerd" zodat het via kanalen met andere knooppunten kan communiceren. Net als een echte computer kan een knooppunt via meerdere apparaten met meerdere kanalen worden verbonden NetApparaten.

De netwerkabstractie van een apparaat wordt in C++ weergegeven door de klasse Netapparaat. Klas Netapparaat biedt methoden voor het beheren van verbindingen met knooppunt- en kanaalobjecten; en kan door ontwikkelaars worden gespecialiseerd in de zin van objectgeoriënteerd programmeren. In deze tutorial zullen we verschillende gespecialiseerde versies van NetDevice gebruiken, genaamd CsmaNet-apparaat, PointToPointNetDevice и WifiNet-apparaat. Net zoals een Ethernet-netwerkadapter is ontworpen om met een netwerk te werken Ethernet, CsmaNet-apparaat ontworpen om mee te werken Csmakanaal, PointToPointNetDevice ontworpen om mee te werken PuntToPuntKanaalEn WifiNet-apparaat - ontworpen om mee te werken WifiKanaal.

4.1.5 Topologische assistenten

In een echt netwerk vindt u hostcomputers met toegevoegde (of ingebouwde) netwerkkaarten. In ns-3 zouden we zeggen dat je knooppunten zult zien waaraan NetDevices zijn gekoppeld. In een groot gesimuleerd netwerk moet u verbindingen tussen veel objecten organiseren Knooppunt, Netapparaat и Kanaal.

Sinds het verbinden van NetDevices met knooppunten, NetDevices met links, het toewijzen van IP-adressen, enz. in ns-3 zijn een veel voorkomende taak, om dit zo eenvoudig mogelijk te maken bieden wij zogenaamde topologiehelpers aan. Als u bijvoorbeeld een NetDevice wilt maken, moet u veel ns-3-kernelbewerkingen uitvoeren, een MAC-adres toevoegen, het netwerkapparaat in Node installeren, de protocolstack van het knooppunt configureren en vervolgens het NetDevice met het Channel verbinden. Er zal nog meer werk nodig zijn om meerdere apparaten op multipoint-verbindingen aan te sluiten en vervolgens de afzonderlijke netwerken tot een Internetworks-netwerk te verbinden. Wij bieden topologiehulpobjecten die deze vele bewerkingen voor uw gemak combineren in een eenvoudig te gebruiken model.

4.2 Eerste ns-3-script

Als u het systeem hebt geïnstalleerd zoals hierboven voorgesteld, beschikt u over de ns-3-release in een map met de naam repos in uw thuismap. Ga naar map los

Als u niet over een dergelijke map beschikt, betekent dit dat u de uitvoermap niet hebt opgegeven bij het bouwen van de releaseversie van ns-3, bouw deze als volgt:
$ ./waf configureren —build-profile=release —out=build/release,
$ ./waf bouwen

daar zou je een directorystructuur moeten zien die er ongeveer als volgt uitziet:

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

Ga naar map voorbeelden/tutorial. Je zou daar een bestand moeten zien genaamd eerste.cc. Dit is een script dat een eenvoudige point-to-point-verbinding tussen twee knooppunten tot stand brengt en één pakket tussen de knooppunten verzendt. Laten we dit script regel voor regel bekijken; hiervoor opent u first.cc in uw favoriete editor.

4.2.1 Boilerplatecode
De eerste regel in het bestand is de editormodusregel emacs. Het vertelt emacs over de opmaakconventies (coderingsstijl) die we in onze broncode gebruiken.

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

Dit is altijd een nogal controversiële kwestie, dus we moeten de feiten rechtzetten om deze meteen uit de weg te ruimen. Het ns-3-project heeft, zoals de meeste grote projecten, een codeerstijl aangenomen waaraan alle bijgedragen code moet voldoen. Als u uw code wilt bijdragen aan het project, zult u zich uiteindelijk moeten conformeren aan de ns-3 coderingsstandaard, zoals beschreven in het bestand doc/codingstd.txt of weergegeven op de projectwebpagina: https://www.nsnam.org/develop/contributing-code/coding-style/.

Wij raden u aan te wennen aan het uiterlijk van de ns-3-code en deze standaard toe te passen wanneer u met onze code werkt. Het hele ontwikkelingsteam en de bijdragers gingen hier na enig gemopper mee akkoord. De bovenstaande emacs-modusregel maakt het eenvoudig om correct te formatteren als u de emacs-editor gebruikt.

De ns-3-simulator heeft een licentie voor het gebruik van GNU General Public License. U zult de juiste juridische GNU-header in elk ns-3-distributiebestand zien. Vaak ziet u een copyrightvermelding voor een van de deelnemende instellingen aan het ns-3-project boven de GPL-tekst en auteur, zoals hieronder weergegeven.

/* 
* 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-ins

De code zelf begint met een reeks inclusieverklaringen (omvatten).

#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 scriptinggebruikers op hoog niveau te helpen omgaan met het grote aantal headerbestanden in het systeem, groeperen we ze op basis van hun gebruik in grote modules. We bieden een enkel headerbestand dat recursief alle headerbestanden laadt die in een bepaalde module worden gebruikt. In plaats van te moeten zoeken naar precies welke header u nodig heeft en mogelijk de juiste lijst met afhankelijkheden te krijgen, bieden wij u de mogelijkheid om een ​​groep bestanden met grote granulariteit te downloaden. Het is niet de meest efficiënte aanpak, maar het maakt het schrijven van scripts zeker een stuk eenvoudiger.

Elk van de ns-3 include-bestanden wordt in een map geplaatst met de naam ns3 (submap build) om conflicten met bestandsnamen tijdens het bouwproces te voorkomen. Bestand ns3/core-module.h komt overeen met de ns-3-module, die u in de directory vindt src/kern in de release die u hebt geïnstalleerd. In de lijst van deze map vindt u een groot aantal headerbestanden. Wanneer u de montage uitvoert, Waf plaatst openbare headerbestanden in de ns3-map in een submap bouwen/debuggen

Als u niet over een dergelijke map beschikt, betekent dit dat u de uitvoermap niet hebt opgegeven bij het bouwen van de releaseversie van ns-3, bouw deze als volgt:
$ ./waf configureren --build-profile=debug --out=build/debug
$ ./waf bouwen
of
$ ./waf configure --build-profile=geoptimaliseerd --out=build/geoptimaliseerd
$ ./waf bouwen

of bouwen/geoptimaliseerd, afhankelijk van uw configuratie. Waf zal ook automatisch een module-include-bestand genereren om alle openbare header-bestanden te laden. Omdat je deze gids natuurlijk religieus volgt, heb je dat al gedaan

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

om het project te configureren om foutopsporingsbuilds uit te voeren die voorbeelden en tests bevatten. Dat deed jij ook

$ ./waf

om het project samen te stellen. Dus als je nu in de map kijkt ../../build/debug/ns3, dan vind je daar onder andere de headerbestanden van de vier hierboven weergegeven modules. U kunt de inhoud van deze bestanden bekijken en ontdekken dat deze alle openbare bestanden bevatten die door de overeenkomstige modules worden gebruikt.

4.2.3 ns3-naamruimte

Volgende regel in script eerste.cc is een naamruimtedeclaratie.

using namespace ns3;

Het ns-3-project is geïmplementeerd in een C++-naamruimte genaamd ns3. Hierdoor worden alle ns-3-gerelateerde declaraties gegroepeerd in een bereik buiten de globale naamruimte, wat hopelijk zal helpen bij de integratie met andere code. Met behulp van de C++-operator wordt de ns-3-naamruimte geïntroduceerd in de huidige (algemene) declaratieve regio. Dit is een mooie manier om te zeggen dat je na deze declaratie niet de toestemmingsoperator ns3::scope hoeft te typen vóór al je ns-3-code om deze te gebruiken. Als u niet bekend bent met naamruimten, raadpleeg dan vrijwel elke C++-tutorial en vergelijk de ns3-naamruimte met behulp van de std-naamruimte en declaratie using namespace std; in voorbeelden van het werken met de uitvoeroperator cout en stromen.

4.2.4 Loggen

De volgende regel van het script is:

NS_LOG_COMPONENT_DEFINE ("FirstScriptExample");

We zullen deze verklaring gebruiken als een handige plek om ons documentatiesysteem te bespreken zuurstofoxy. Als u naar de ns-3 projectwebsite kijkt, vindt u een documentatielink in de navigatiebalk. Als u op deze link klikt, wordt u naar onze documentatiepagina geleid. Er is een link "Nieuwste release" die u naar de documentatie voor de nieuwste stabiele versie van ns-3 brengt. Als u de link "API-documentatie" selecteert, wordt u naar de ns-3 API-documentatiepagina geleid.

Aan de linkerkant van de pagina vindt u een grafische weergave van de documentatiestructuur. Een goed beginpunt is het Modules ns-3 "boek" in de ns-3 navigatieboom. Als je onthult Modules, ziet u een lijst met documentatie over ns-3-modules. Zoals hierboven besproken, houdt het concept van een module hier rechtstreeks verband met de bestanden in de bovenstaande module. Het ns-3-logboeksubsysteem wordt in sectie besproken Gebruik van de logmodule, dus we komen er later in deze tutorial op terug, maar je kunt meer te weten komen over de bovenstaande verklaring door naar de module te kijken Kernen dan het boek openen Tools voor foutopsporingen selecteer vervolgens de pagina Logging. Klik op Logging.

U moet nu de documentatie bekijken zuurstofoxy voor moduul 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, moet u eerst de “Gedetailleerde beschrijving” van de registratiemodule bekijken om te begrijpen hoe deze in het algemeen werkt. Om dit te doen, kunt u naar beneden scrollen of "Meer..." onder het diagram selecteren.

Zodra u een algemeen idee heeft van wat er aan de hand is, kunt u de documentatie voor de specifieke NS_LOG_COMPONENT_DEFINE bekijken. Ik zal de documentatie hier niet dupliceren, maar om samen te vatten: deze regel declareert een registratiecomponent genaamd FirstScriptVoorbeeld, waarmee u consolelogboekregistratie van berichten op basis van een naam kunt in- of uitschakelen.

4.2.5 Hoofdfunctie

In de volgende regels van het script ziet u:

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

Dit is eenvoudigweg een verklaring van de hoofdfunctie van uw programma (script). Zoals bij elk C++-programma moet u een hoofdfunctie definiëren. Deze wordt eerst uitgevoerd. Er is hier niets bijzonders. Uw ns-3-script is slechts een C++-programma. De volgende regel stelt de tijdresolutie in op 1 nanoseconde, wat de standaard is:

Time::SetResolution (Time::NS);

Tijdresolutie, of eenvoudigweg resolutie, is de kleinste tijdswaarde die kan worden gebruikt (het kleinste representatieve verschil tussen twee tijden). U kunt de resolutie precies één keer wijzigen. Het mechanisme dat deze flexibiliteit biedt, verbruikt geheugen, dus zodra de resolutie expliciet is ingesteld, maken we het geheugen vrij, waardoor verdere updates worden voorkomen. (Als u de resolutie niet expliciet instelt, wordt deze standaard ingesteld op één nanoseconde en wordt het geheugen vrijgegeven wanneer de simulatie start.)

De volgende twee scriptregels worden gebruikt om twee logboekcomponenten in te schakelen die in toepassingen zijn ingebouwd EchoClient и EchoServer:

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

Als u de documentatie voor de component Logging leest, zult u zien dat er verschillende niveaus van loggen/granulariteit zijn die u voor elke component kunt inschakelen. Deze twee coderegels maken foutopsporingsregistratie op INFO-niveau mogelijk voor echo-clients en -servers. Op dit niveau drukt de applicatie berichten af ​​terwijl deze pakketten verzendt en ontvangt tijdens de simulatie.

Nu gaan we aan de slag met het creëren van de topologie en het uitvoeren van de simulatie. We gebruiken topologie-helperobjecten om deze taak zo eenvoudig mogelijk te maken.

4.2.6 Topologie-assistenten gebruiken

De volgende twee regels code in ons script zullen feitelijk de Node ns-3-objecten creëren die de computers in de simulatie zullen vertegenwoordigen.

NodeContainer nodes;
nodes.Create (2);

Voordat we verder gaan, gaan we eerst de documentatie voor de klasse opzoeken KnooppuntContainer. Een andere manier om bij de documentatie voor een bepaalde klasse te komen is via het tabblad Klassen op de pagina's zuurstofoxy. Als je Doxygen al open hebt, scroll dan eenvoudigweg naar de bovenkant van de pagina en selecteer het tabblad Klassen. Je zou een nieuwe set tabbladen moeten zien, waarvan er één een lijst met klassen is. Onder dit tabblad ziet u een lijst met alle ns-3-klassen. Scroll naar beneden naar ns3::NodeContainer. Wanneer u een klasse vindt, selecteert u deze om naar de documentatie voor de klasse te gaan.

Zoals we ons herinneren, is een van onze belangrijkste abstracties het knooppunt. Het vertegenwoordigt de computer waaraan we zaken als protocolstacks, applicaties en randkaarten gaan toevoegen. Topologie assistent KnooppuntContainer biedt een handige manier om objecten te maken, beheren en openen Knooppunt, die we maken om de simulatie uit te voeren. De eerste regel hierboven verklaart eenvoudigweg KnooppuntContainer, die we knooppunten noemen. De tweede regel roept de Create-methode op het knooppuntenobject aan en vraagt ​​de container om twee knooppunten te maken. Zoals beschreven in zuurstofoxy, vraagt ​​de container het ns-3-systeem om twee objecten te maken Knooppunt en slaat verwijzingen naar deze objecten intern op.

De knooppunten die in het script zijn gemaakt, doen nog niets. De volgende stap bij het bouwen van de topologie is het verbinden van onze knooppunten met het netwerk. De eenvoudigste netwerkvorm die wij ondersteunen is een point-to-point-verbinding tussen twee knooppunten. We zullen nu een dergelijke verbinding tot stand brengen.

PuntToPuntHelper

We creëren een point-to-point-verbinding met behulp van een bekend patroon, waarbij we een topologie-helperobject gebruiken om het werk op laag niveau uit te voeren dat nodig is voor de verbinding. Bedenk dat onze twee belangrijkste abstracties zijn Netapparaat и Kanaal. In de echte wereld komen deze termen grofweg overeen met randapparatuurkaarten en netwerkkabels. Meestal zijn deze twee dingen nauw met elkaar verbonden en kan niemand rekenen op het delen van bijvoorbeeld apparaten Ethernet via een draadloos kanaal. Onze topologiehelpers volgen deze nauwe relatie en daarom gebruikt u in dit scenario één object PuntToPuntHelper voor het opzetten en verbinden van ns-3 objecten PointToPointNetDevice и PuntToPuntKanaal. De volgende drie regels in het script:

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

Eerste lijn,

PointToPointHelper pointToPoint;

creëert een exemplaar van een object op de stapel PuntToPuntHelper. Vanuit het oogpunt van het hoogste niveau is de volgende regel:

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

vertelt het voorwerp PuntToPuntHelper gebruik de waarde "5 Mbit/s" (vijf megabit per seconde) als "Datasnelheid.

Vanuit een specifieker gezichtspunt komt de string "DataRate" overeen met wat we een attribuut noemen PointToPointNetDevice. Als je kijkt zuurstofoxy voor de les ns3::PointToPointNetDevice en in de documentatie voor de methode GetTypeId vindt u een lijst met attributen die voor het apparaat zijn gedefinieerd. Onder hen zal het attribuut zijn “Datasnelheid" De meeste voor de gebruiker zichtbare ns-3-objecten hebben vergelijkbare lijsten met attributen. We gebruiken dit mechanisme om de simulatie eenvoudig op te zetten zonder hercompilatie, zoals u in de volgende sectie zult zien.

Gelijkwaardig aan "Datasnelheid" in PointToPointNetDevice vindt u het kenmerk "Delay" dat is gekoppeld aan PointToPointChannel. De laatste regel

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

говорит PuntToPuntHelper gebruik de waarde "2 ms" (twee milliseconden) als de voortplantingsvertragingswaarde voor de point-to-point-verbinding die vervolgens wordt gemaakt.

NetDeviceContainer

Op dit moment hebben we in het script KnooppuntContainer, die twee knooppunten bevat. We hebben PuntToPuntHelper, dat is voorbereid voor het maken van objecten PointToPointNetDevices en deze te verbinden met behulp van een PointToPointChannel-object. Net zoals we het NodeContainer-topologiehelperobject hebben gebruikt om knooppunten te maken, zullen we dit vragen PuntToPuntHelper werk voor ons uitvoeren met betrekking tot het maken, configureren en installeren van onze apparaten. We hebben een lijst nodig van alle gemaakte objecten Netapparaat, dus gebruiken wij NetDeviceContainer om ze op dezelfde manier op te slaan als wij gewend zijn KnooppuntContainer om de knooppunten op te slaan die we hebben gemaakt. De volgende twee regels code,

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

complete apparaat- en kanaalconfiguratie. De eerste regel declareert de hierboven genoemde apparaatcontainer en de tweede doet het hoofdwerk. Methode Install een object PuntToPuntHelper neemt KnooppuntContainer als parameter. Binnen NetDeviceContainer voor elk knooppunt dat zich in bevindt KnooppuntContainer is gemaakt (voor point-to-point-communicatie moeten er precies twee zijn) PointToPointNetDevice wordt gemaakt en opgeslagen in de apparaatcontainer. PuntToPuntKanaal is gemaakt en er zijn er twee aan gekoppeld PointToPointNetDevices. Na het maken van objecten worden de attributen opgeslagen in PuntToPuntHelper, worden gebruikt om de overeenkomstige attributen in de gemaakte objecten te initialiseren.

Na een oproep te hebben gedaan pointToPoint.Install (knooppunten) we zullen twee knooppunten hebben, elk met een geïnstalleerd point-to-point-netwerkapparaat en één point-to-point-verbinding ertussen. Beide apparaten zullen worden geconfigureerd om gegevens te verzenden met een snelheid van vijf megabits per seconde met een transmissievertraging van twee milliseconden over het kanaal.

InternetStackHelper

We hebben nu knooppunten en apparaten geconfigureerd, maar op onze knooppunten zijn geen protocolstacks geïnstalleerd. De volgende twee regels code zullen hiervoor zorgen.

InternetStackHelper stack;
stack.Install (nodes);

InternetStackHelper - is een topologiehelper voor internetstacks, vergelijkbaar met PointToPointHelper voor point-to-point netwerkapparaten. Methode Install neemt NodeContainer als parameter. Wanneer het wordt uitgevoerd, wordt de internetstack (TCP, UDP, IP, enz.) op elk containerknooppunt geïnstalleerd.

IPv4AddressHelper

Vervolgens moeten we onze apparaten koppelen aan IP-adressen. We bieden een topologieassistent om de toewijzing van IP-adressen te beheren. De enige API die zichtbaar is voor de gebruiker is het instellen van het basis-IP-adres en het netmasker dat moet worden gebruikt bij de daadwerkelijke adresdistributie (dit gebeurt op een lager niveau binnen de helper). De volgende twee regels code in ons voorbeeldscript eerste.cc,

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

declareer het adreshulpobject en vertel het dat het moet beginnen met het toewijzen van IP-adressen van netwerk 10.1.1.0, met behulp van het bitmasker 255.255.255.0 om te bepalen. Standaard beginnen de toegewezen adressen bij één en nemen ze monotoon toe, dus het eerste adres dat vanaf deze basis wordt toegewezen, is 10.1.1.1, daarna 10.1.1.2, enz. In werkelijkheid onthoudt het ns-3-systeem op een laag niveau alle toegewezen IP-adressen en genereert het een fatale fout als je per ongeluk een situatie creëert waarin hetzelfde adres tweemaal wordt gegenereerd (deze fout is overigens moeilijk te debuggen).

De volgende coderegel,

Ipv4InterfaceContainer interfaces = address.Assign (devices);

voert de daadwerkelijke adrestoewijzing uit. In ns-3 brengen we een verbinding tot stand tussen een IP-adres en een apparaat dat het object gebruikt IPv4Interface. Net zoals we soms een lijst met netwerkapparaten nodig hebben die door de assistent is gemaakt voor later gebruik, hebben we soms een lijst met objecten nodig IPv4Interface. IPv4InterfaceContainer biedt deze functionaliteit.

We hebben een point-to-point-netwerk gebouwd, met geïnstalleerde stacks en toegewezen IP-adressen. Nu hebben we in elk knooppunt applicaties nodig om verkeer te genereren.

4.2.7 Applicatie gebruiken

Een andere van de belangrijkste abstracties van het ns-3-systeem is Aanvraag (sollicitatie). In dit scenario gebruiken we twee basisklassespecialisaties Aanvraag ns-3 gebeld UdpEchoServerApplicatie и UdpEchoClientApplicatie. Net als in eerdere gevallen gebruiken we hulpobjecten om de basisobjecten te configureren en te beheren. Hier gebruiken wij UdpEchoServerHelper и UdpEchoClientHelper objecten om ons leven gemakkelijker te maken.

UdpEchoServerHelper

De volgende coderegels in ons first.cc-voorbeeldscript worden gebruikt om een ​​UDP-echoservertoepassing te configureren op een van de knooppunten die we eerder hebben gemaakt.

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 wordt gemaakt UdpEchoServerHelper. Zoals gewoonlijk is dit geen applicatie zelf, het is een object dat ons helpt echte applicaties te maken. Een van onze conventies is om de vereiste attributen door te geven aan de constructor van het helperobject. In dit geval kan de helper niets nuttigs doen tenzij hij het poortnummer krijgt waarop de server naar pakketten zal luisteren, dit nummer moet ook bekend zijn bij de client. In dit geval geven we het poortnummer door aan de helperconstructor. De constructeur doet dat op zijn beurt gewoon SetAttribuut met de doorgegeven waarde. Later kunt u, indien gewenst, SetAttribute gebruiken om een ​​andere waarde voor het Port-attribuut in te stellen.

Net als veel andere hulpobjecten is het object UdpEchoServerHelper heeft een methode Install. Door deze methode uit te voeren, wordt effectief een basis-echoservertoepassing gecreëerd en aan de host gekoppeld. Interessant is de methode Install neemt KnooppuntContainer als parameter, net als de andere Install methoden die we hebben gezien.

De impliciete C++-conversie die hier werkt, neemt het resultaat van de methode knooppunt.Get(1) (die een slimme aanwijzer retourneert naar het knooppuntobject - Ptr ) en gebruikt deze in de constructor voor het anonieme object KnooppuntContainerdie vervolgens wordt doorgegeven aan de methode Install. Als je in C++-code niet kunt bepalen welke methodehandtekening wordt gecompileerd en uitgevoerd, kijk dan eens naar de impliciete conversies.

Nu zien wij dat echoServer.Installeren op het punt staat de applicatie te installeren UdpEchoServerApplicatie op gevonden in KnooppuntContainerwaarmee we onze knooppunten beheren, knooppunt met index 1. Methode Install zal een container retourneren die verwijzingen naar alle applicaties bevat (in dit geval één, aangezien we een anoniem KnooppuntContainer, met één knooppunt) gemaakt door de helper.

Applicaties moeten specificeren wanneer ze verkeer moeten genereren "begin" en moet mogelijk bovendien een tijdstip opgeven waarop het moet worden gestopt "stop". Wij bieden beide opties. Deze tijden worden ingesteld met behulp van de methoden ApplicatieContainer Start и stop. Deze methoden accepteren parameters van het type Tijd. In dit geval gebruiken we een expliciete reeks C++-conversies om C++ te nemen verdubbelen 1.0 en converteer het naar een tns-3 Time-object dat het Seconds-object gebruikt om naar seconden te converteren. Houd er rekening mee dat de conversieregels kunnen worden beheerd door de modelauteur en dat C++ zijn eigen regels heeft, zodat u er niet altijd op kunt rekenen dat de parameters worden geconverteerd zoals u had verwacht. Twee lijnen

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

zorgt ervoor dat de echoservertoepassing één seconde na het starten van de simulatie start (automatisch wordt ingeschakeld) en stopt (uitschakelt) na tien seconden van de simulatie. Vanwege het feit dat we een simulatiegebeurtenis (toepassingsstopgebeurtenis) hebben gedeclareerd, die binnen tien seconden zal worden uitgevoerd, zullen ten minste tien seconden netwerkwerking worden gesimuleerd.

UdpEchoClientHelper

Klanttoepassing echo geconfigureerd op een manier die bijna vergelijkbaar is met die van de server. Er is een basisobject UdpEchoClientApplicatie, die wordt beheerd
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));;

Voor de echoclient moeten we echter vijf verschillende attributen instellen. De eerste twee attributen worden ingesteld tijdens het maken UdpEchoClientHelper. We geven parameters door die worden gebruikt (binnen de helper) om de attributen in te stellen "Extern adres" и "RemotePort" in overeenstemming met onze overeenkomst om de noodzakelijke parameters door te geven aan de helperconstructor.

Laten we niet vergeten dat we gebruikten IPv4InterfaceContainer om de IP-adressen te volgen die we aan onze apparaten hebben toegewezen. De nulinterface in de interfacescontainer komt overeen met het IP-adres van het nulknooppunt in de knooppuntencontainer. De eerste interface in de interfacescontainer komt overeen met het IP-adres van het eerste knooppunt in de knooppuntencontainer. Dus in de eerste regel code (hierboven) maken we een helper en vertellen deze dat het externe adres van de client het IP-adres is dat is toegewezen aan de host waarop de server zich bevindt. We zeggen ook dat we ervoor moeten zorgen dat pakketten naar poort negen worden verzonden.

Het attribuut "MaxPackets" vertelt de klant het maximale aantal pakketten dat we tijdens de simulatie kunnen verzenden. Het attribuut "Interval" vertelt de client hoe lang er moet worden gewacht tussen pakketten, en het attribuut "PacketSize" vertelt de client hoe groot de payload van het pakket moet zijn. Met deze attribuutcombinatie vertellen we de client dat hij een enkel pakket van 1024 bytes moet verzenden.

Net als bij de echoserver stellen we de attributen van de echoclient in Start и stop, maar hier starten we de client een seconde nadat de server is ingeschakeld (twee seconden na het starten van de simulatie).

4.2.8 Simulatie

Op dit punt moeten we de simulatie uitvoeren. Dit wordt gedaan met behulp van de globale functie Simulator::Uitvoeren.

Simulator::Run ();

Toen we de methoden eerder aanroepen,

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

we hebben feitelijk evenementen in de simulator gepland op 1,0 seconden, 2,0 seconden en twee evenementen op 10,0 seconden. Na de oproep Simulator::Uitvoeren, begint het systeem de lijst met geplande gebeurtenissen te bekijken en deze uit te voeren. Na 1,0 seconden wordt voor het eerst een gebeurtenis geactiveerd, waardoor de echoservertoepassing wordt geactiveerd (deze gebeurtenis kan op zijn beurt vele andere gebeurtenissen plannen). Vervolgens wordt een gebeurtenis geactiveerd die is gepland op t=2,0 seconden, waardoor de echo-clienttoepassing wordt gestart. Nogmaals, voor dit evenement zijn mogelijk nog veel meer evenementen gepland. De startgebeurtenisimplementatie in de echoclient begint de gegevensoverdrachtfase van de simulatie door een pakket naar de server te sturen.

De handeling van het verzenden van een pakket naar de server zal een reeks gebeurtenissen activeren die automatisch achter de schermen worden gepland en die de mechanismen van het verzenden van een echopakket implementeren volgens de timingparameters die we in het script hebben ingesteld.

Als gevolg hiervan verzenden we slechts één pakket (onthoud het attribuut MaxPakketten was ingesteld op één), zal de reeks gebeurtenissen die door deze enkele clientping wordt geïnitieerd, eindigen en zal de simulatie in de stand-bymodus gaan. Zodra dit gebeurt, zijn de resterende geplande evenementen de evenementen stop voor server en client. Wanneer deze gebeurtenissen worden uitgevoerd, zijn er geen gebeurtenissen meer voor verdere verwerking Simulator::Uitvoeren zal de controle teruggeven. De simulatie is voltooid.

Het enige dat overblijft is het opruimen van jezelf. Dit wordt gedaan door de globale functie aan te roepen Simulator::Vernietigen. Omdat de helperfuncties (of ns-3-code op laag niveau) werden aangeroepen, die zo zijn georganiseerd dat er haken in de simulator werden geplaatst om alle gemaakte objecten te vernietigen. U hoefde deze objecten niet zelf te volgen; u hoefde alleen maar te bellen Simulator::Vernietigen en ga naar buiten. Het ns-3-systeem zal dit zware werk voor u doen. 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 (DE)-simulator. In een dergelijke simulator wordt elke gebeurtenis geassocieerd met de uitvoeringstijd ervan, en gaat de simulatie verder door gebeurtenissen te verwerken in de volgorde waarin ze plaatsvinden naarmate de simulatie vordert. Gebeurtenissen kunnen ervoor zorgen dat toekomstige gebeurtenissen worden gepland (een timer kan zichzelf bijvoorbeeld opnieuw plannen om het tellen in het volgende interval te voltooien).

Initiële gebeurtenissen worden meestal geïnitieerd door de entiteit. IPv6 plant bijvoorbeeld de ontdekking van services op het netwerk, buurverzoeken, enz. De toepassing plant de eerste gebeurtenis voor het verzenden van pakketten, enzovoort. Wanneer een gebeurtenis wordt verwerkt, kan deze nul, één of meer gebeurtenissen genereren. Naarmate de simulatie vordert, vinden er gebeurtenissen plaats die eindigen of nieuwe creëren. De simulatie stopt automatisch als de gebeurteniswachtrij leeg is of als er een speciale gebeurtenis wordt gedetecteerd stop. Evenement stop gegenereerd door de functie Simulator::Houd op (stoptijd).

Er is een typisch geval waarin Simulator::Stop absoluut noodzakelijk is om de simulatie te stoppen: wanneer er zichzelf in stand houdende gebeurtenissen plaatsvinden. Zelfvoorzienende (of herhalende) evenementen zijn evenementen die altijd opnieuw worden gepland. Als gevolg hiervan houden ze de gebeurteniswachtrij altijd niet leeg. Er zijn veel protocollen en modules die herhalende gebeurtenissen bevatten, bijvoorbeeld:

• FlowMonitor - periodieke controle op verloren pakketten;

• RIPng – periodieke uitzending van routeringstabelupdates;

• enz.

In dergelijke gevallen Simulator::Houd op nodig om de simulatie correct te stoppen. Bovendien wordt, wanneer ns-3 zich in de emulatiemodus bevindt, de RealtimeSimulator gebruikt om de simulatieklok te synchroniseren met de machineklok, en Simulator::Houd op noodzakelijk om het proces te stoppen.

Veel van de simulatieprogramma's in het leerboek bellen niet Simulator::Houd op expliciet, omdat ze automatisch eindigen wanneer de gebeurtenissen in de wachtrij zijn uitgeput. Deze programma's accepteren echter ook de Simulator::Stop-oproep. De volgende aanvullende instructie in het eerste voorbeeldprogramma plant bijvoorbeeld een expliciete stop op 11 seconden:

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

Het bovenstaande zal het gedrag van dit programma feitelijk niet veranderen, aangezien deze specifieke simulatie uiteraard na 10 seconden eindigt. Maar als u de stoptijd in de bovenstaande verklaring zou veranderen van 11 seconden naar 1 seconde, zou u merken dat de simulatie stopt voordat er enige uitvoer op het scherm verschijnt (aangezien de uitvoer plaatsvindt na ongeveer 2 seconden simulatietijd).

Het is belangrijk om Simulator::Stop aan te roepen voordat u Simulator::Run aanroept; anders geeft Simulator::Run mogelijk nooit de controle terug aan het hoofdprogramma om de stop uit te voeren!

4.2.9 Uw script bouwen

We hebben het maken van uw eenvoudige scripts triviaal gemaakt. Het enige wat u hoeft te doen is uw script in de scratch-map te plaatsen en het wordt automatisch gebouwd als u het uitvoert Waf. Laten we proberen. Ga terug naar de map op het hoogste niveau en kopieer voorbeelden/tutorial/eerste.cc catalogiseren krassen

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

Bouw nu uw eerste voorbeeldscript met behulp van waf:

$ ./waf

U zou berichten moeten zien die aangeven dat uw eerste voorbeeld met succes is gemaakt.

Waf: Entering directory `/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: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
'build' finished successfully (2.357s)

Nu kunt u het voorbeeld uitvoeren (merk op dat als u uw programma in de scratch-map bouwt, u het moet uitvoeren vanuit krassen):

$ ./waf --run scratch/myfirst

Je zou vergelijkbare uitvoer moeten zien:

Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
'build' finished successfully (0.418s) Sent 1024 bytes to 10.1.1.2
Received 1024 bytes from 10.1.1.1
Received 1024 bytes from 10.1.1.2

Hier kunt u zien dat het bouwsysteem verifieert dat het bestand is gebouwd en het vervolgens uitvoert. U ziet dat de componentvermelding op de echo-client aangeeft dat deze een enkel pakket van 1024 bytes naar echoserver 10.1.1.2 heeft verzonden. Ook jij ziet de logcomponent op de echoserver die zegt dat deze 1024 bytes heeft ontvangen van 10.1.1.1. De echoserver speelt het pakket stilletjes af en u kunt in het logboek van de echoclient zien dat het pakket terug is ontvangen van de server.

4.3 ns-3 Broncode

Nu u enkele van de ns-3-helpers heeft gebruikt, kunt u een deel van de broncode bekijken die deze functionaliteit implementeert. De nieuwste code kunt u op onze webserver bekijken via de volgende link: https://gitlab.com/nsnam/ns-3-dev.git. Daar ziet u de Mercurial-samenvattingspagina voor onze ns-3-ontwikkelingsboom. Bovenaan de pagina ziet u verschillende links,

summary | shortlog | changelog | graph | tags | files

Ga je gang en selecteer de bestandslink. Dit is hoe het hoogste niveau van de meeste van onze repository's eruit zal zien:

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

Onze voorbeeldscripts bevinden zich in de directory voorbeelden. Als u op de voorbeelden klikt, ziet u een lijst met submappen. Een van de bestanden in de submap tutorial - eerste.cc. Als u op klikt eerste.cc je ziet de code die je zojuist hebt geleerd.

De broncode bevindt zich voornamelijk in de directory src. U kunt de broncode bekijken door op de mapnaam te klikken of op de bestandslink rechts van de mapnaam te klikken. Als u op de src-map klikt, krijgt u een lijst met src-submappen. Als u vervolgens op de kernsubmap klikt, vindt u een lijst met bestanden. Het eerste bestand dat u ziet (op het moment dat deze handleiding wordt geschreven) is afbreken.h. Als u op de link klikt afbreken.h, u wordt naar het bronbestand gestuurd voor afbreken.h, dat handige macro's bevat voor het afsluiten van scripts als er abnormale omstandigheden worden gedetecteerd. De broncode van de helpers die we in dit hoofdstuk hebben gebruikt, is te vinden in de directory src/Toepassingen/helper. Voel je vrij om door de directorystructuur te snuffelen om erachter te komen wat waar is en om de stijl van ns-3-programma's te begrijpen.

Bron: www.habr.com

Voeg een reactie