ns-3 nettverkssimulator opplæring. Kapittel 4

ns-3 nettverkssimulator opplæring. Kapittel 4
kapittel 1,2
kapittel 3

4 Konseptoversikt
4.1 Nøkkelabstraksjoner
4.1.1 Node
4.1.2 Søknad
4.1.3 Kanal
4.1.4 Nettenhet
4.1.5 Topologiske assistenter
4.2 Første ns-3-skript
4.2.1 Kjelekode
4.2.2 Plug-ins
4.2.3 ns3 navneområde
4.2.4 Logging
4.2.5 Hovedfunksjon
4.2.6 Bruke topologiassistenter
4.2.7 Bruke applikasjonen
4.2.8 Simulator
4.2.9 Bygge skriptet ditt
4.3 ns-3 Kildekode

Kapittel 4

Konseptoversikt

Det første vi må gjøre før vi begynner å lære eller skrive ns-3-kode er å forklare noen få grunnleggende konsepter og abstraksjoner i systemet. Mye av dette kan virke innlysende for noen, men vi anbefaler at du tar deg tid til å lese denne delen for å sikre at du starter på et solid grunnlag.

4.1 Nøkkelabstraksjoner

I denne delen skal vi se på noen begreper som vanligvis brukes på nettet, men som har en spesifikk betydning i ns-3.

4.1.1 Node

I Internett-sjargong kalles en datamaskinenhet som kobles til et nettverk en vert eller noen ganger et sluttsystem. Fordi ns-3 er en nettverkssimulator og ikke en internettsimulator, bruker vi bevisst ikke begrepet vert, da dette er nært knyttet til Internett og dets protokoller. I stedet bruker vi en mer generell term, også brukt av andre simulatorer, som har sin opprinnelse i grafteori: node (node).

I ns-3 kalles den underliggende abstraksjonen til en dataenhet en node. Denne abstraksjonen er representert i C++ av Node-klassen. Klasse NodeNode (node) gir metoder for å manipulere representasjoner av dataenheter i simuleringer.

Du må forstå Node som en datamaskin som du legger til funksjonalitet til. Du vil legge til ting som applikasjoner, protokollstabler og periferikort med drivere som lar datamaskinen gjøre nyttig arbeid. Vi bruker samme grunnmodell i ns-3.

4.1.2 Søknad

Generelt er dataprogramvare delt inn i to brede klasser. Systemprogramvare organiserer ulike dataressurser som minne, prosessorsykluser, disk, nettverk osv. i henhold til en eller annen datamodell. Systemprogramvare bruker vanligvis ikke disse ressursene til å utføre oppgaver som er direkte til fordel for brukeren. En bruker kjører vanligvis en applikasjon for å oppnå et spesifikt mål, som skaffer og bruker ressurser kontrollert av systemprogramvaren.

Ofte trekkes skillelinjen mellom system- og applikasjonsprogramvare ved endringer på rettighetsnivå som oppstår i operativsystemfeller. ns-3 har ikke noe reelt konsept for et operativsystem og derfor ikke noe konsept for rettighetsnivåer eller systemanrop. Vi har imidlertid en idé til en app. Akkurat som i den "virkelige verden" kjører applikasjoner på datamaskiner for å utføre oppgaver, kjører ns-3 applikasjoner på ns-3 noder for å kontrollere simuleringer i den simulerte verden.

I ns-3 er den grunnleggende abstraksjonen for et brukerprogram som genererer noe aktivitet for modellering en applikasjon. Denne abstraksjonen er representert i C++ av Application-klassen. Applikasjonsklassen gir metoder for å manipulere visninger av vår versjon av applikasjoner på brukernivå i simuleringer. Utviklere forventes å spesialisere applikasjonsklassen i en objektorientert programmeringsforstand for å lage nye applikasjoner. I denne opplæringen vil vi bruke spesialiseringer av applikasjonsklassen kalt UdpEchoClientApplication и UdpEchoServerApplication. Som du kanskje forventer, utgjør disse applikasjonene et sett med klient/serverapplikasjoner som brukes til å generere og ekko nettverkspakker.

4.1.3 Kanal

I den virkelige verden kan du koble en datamaskin til et nettverk. Ofte kalles mediet som data overføres over i disse nettverkene kanaler. Når du kobler en Ethernet-kabel til en stikkontakt, kobler du datamaskinen til en Ethernet-kobling. I den simulerte ns-3-verdenen er en node koblet til et objekt som representerer en kommunikasjonskanal. Her kalles den grunnleggende abstraksjonen av kommunikasjonsundernettverket en kanal og er representert i C++ av Channel-klassen.

Klasse ChannelChannel gir metoder for å administrere samspillet mellom subnettobjekter og koble noder til dem. Kanaler kan også spesialiseres av utviklere i en objektorientert programmeringsforstand. Kanalspesialisering kan modellere noe så enkelt som en ledning. En dedikert kanal kan også modellere komplekse ting som en stor Ethernet-svitsj eller et tredimensjonalt rom fullt av hindringer når det gjelder trådløse nettverk.

Vi vil bruke spesialiserte versjoner av kanalen i denne opplæringen kalt CsmaChannelCsmaChannel, PointToPointChannelPointToPointChannel и WifiChannelWifiChannel. CsmaChannel, for eksempel, modellerer en versjon av et kommunikasjonsundernett som implementerer et kommunikasjonsmiljø med flere tilgangsbærere. Dette gir oss Ethernet-lignende funksjonalitet.

4.1.4 Nettenhet

Det pleide å være slik at hvis du ville koble en datamaskin til et nettverk, måtte du kjøpe en spesifikk nettverkskabel og en maskinvareenhet kalt (i PC-terminologi) et periferkort som måtte installeres i datamaskinen. Hvis et periferkort implementerte noen nettverksfunksjoner, ble de kalt nettverkskort eller nettverkskort. I dag kommer de fleste datamaskiner med integrert nettverksgrensesnitt maskinvare og blir ikke sett av brukere som separate enheter.

Et nettverkskort vil ikke fungere uten en programvaredriver som kontrollerer maskinvaren. I Unix (eller Linux) er et stykke perifert utstyr klassifisert som en enhet. Enheter administreres ved hjelp av enhetsdrivere, og nettverksenheter (NIC) administreres ved hjelp av nettverksenhetsdrivere (nettverksenhetsdrivere) og kalles samlet nettverksenheter (nettenheter). I Unix og Linux refererer du til nettverksenheter med navn som f.eks eth0.

I ns-3 spenner abstraksjonen av nettverksenheten både driverprogramvaren og maskinvaren som modelleres. I simuleringen "installeres" en nettverksenhet i en node for å la den kommunisere med andre noder gjennom kanaler. Akkurat som en ekte datamaskin, kan en node kobles til flere kanaler gjennom flere enheter NetDevices.

Nettverksabstraksjonen til en enhet er representert i C++ av klassen NetDevice. Klasse NetDevice gir metoder for å administrere tilkoblinger til node- og kanalobjekter; og kan spesialiseres av utviklere i betydningen objektorientert programmering. I denne opplæringen vil vi bruke flere spesialiserte versjoner av NetDevice kalt CsmaNetDevice, PointToPointNetDevice и WifiNetDevice. Akkurat som en Ethernet-nettverksadapter er designet for å fungere med et nettverk Ethernet, CsmaNetDevice designet for å jobbe med CsmaChannel, PointToPointNetDevice designet for å jobbe med PointToPointChannelOg WifiNetDevice - designet for å jobbe med WifiChannel.

4.1.5 Topologiske assistenter

I et ekte nettverk vil du finne vertsdatamaskiner med nettverkskort lagt til (eller innebygd). I ns-3 vil vi si at du vil se noder med NetDevices tilkoblet. I et stort simulert nettverk må du organisere forbindelser mellom mange objekter Node, NetDevice и Kanal.

Siden tilkobling av NetDevices til noder, NetDevices til koblinger, tildeling av IP-adresser, etc. i ns-3 er en vanlig oppgave, for å gjøre dette så enkelt som mulig stiller vi med såkalte topologihjelpere. For å lage en NetDevice, må du for eksempel utføre mange ns-3-kjerneoperasjoner, legge til en MAC-adresse, installere nettverksenheten i Node, konfigurere nodens protokollstabel og deretter koble NetDevice til kanalen. Enda mer arbeid vil kreves for å koble flere enheter til flerpunktskoblinger og deretter koble de individuelle nettverkene til et Internetworks-nettverk. Vi tilbyr topologihjelpeobjekter som kombinerer disse mange operasjonene til en brukervennlig modell for din bekvemmelighet.

4.2 Første ns-3-skript

Hvis du installerte systemet som foreslått ovenfor, vil du ha ns-3-utgivelsen i en katalog kalt repos i hjemmekatalogen din. Gå til katalogen slipp

Hvis du ikke har en slik katalog, betyr det at du ikke spesifiserte utdatakatalogen da du bygde utgivelsesversjonen av ns-3, bygg slik:
$ ./waf configure —build-profile=release —out=build/release,
$ ./waf bygge

der bør du se en katalogstruktur som ligner på følgende:

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

Gå til katalogen eksempler/opplæring. Du bør se en fil som heter første.cc. Dette er et skript som vil lage en enkel punkt-til-punkt-forbindelse mellom to noder og overføre en pakke mellom nodene. La oss se på dette skriptet linje for linje; for å gjøre dette, åpne first.cc i favorittredigeringsprogrammet ditt.

4.2.1 Kjelekode
Den første linjen i filen er redigeringsmoduslinjen emacs. Den forteller emacs om formateringskonvensjonene (kodingsstilen) som vi bruker i kildekoden vår.

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

Dette er alltid ganske kontroversielt, så vi må sette rekorden rett for å få det ut av veien med en gang. ns-3-prosjektet har, som de fleste store prosjekter, tatt i bruk en kodestil som all innsendt kode må samsvare med. Hvis du ønsker å bidra med koden din til prosjektet, må du etter hvert følge ns-3-kodestandarden, som beskrevet i filen doc/codingstd.txt eller vist på prosjektets nettside: https://www.nsnam.org/develop/contributing-code/coding-style/.

Vi anbefaler at du blir vant til utseendet og følelsen til ns-3-koden og bruker denne standarden når du jobber med koden vår. Hele utviklingsteamet og bidragsytere gikk med på dette etter litt murring. Emacs-moduslinjen ovenfor gjør det enkelt å formatere riktig hvis du bruker emacs-editoren.

ns-3-simulatoren er lisensiert med GNU General Public License. Du vil se den riktige GNU juridiske overskriften i hver ns-3 distribusjonsfil. Ofte vil du se en opphavsrettserklæring for en av de deltakende institusjonene i ns-3-prosjektet over GPL-teksten 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-ins

Selve koden begynner med en serie inkluderingsutsagn (inkludere).

#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 å hjelpe våre skriptbrukere på høyt nivå med å takle det store antallet header-filer som finnes i systemet, grupperer vi dem i henhold til deres bruk i store moduler. Vi tilbyr en enkelt overskriftsfil som rekursivt vil laste inn alle overskriftsfiler som brukes i en gitt modul. I stedet for å måtte søke etter nøyaktig hvilken overskrift du trenger og muligens få den riktige listen over avhengigheter, gir vi deg muligheten til å laste ned en gruppe filer med stor granularitet. Det er ikke den mest effektive tilnærmingen, men det gjør det absolutt mye enklere å skrive manus.

Hver av ns-3 include-filene er plassert i en katalog kalt ns3 (bygg underkatalog) for å unngå filnavnkonflikter under byggeprosessen. Fil ns3/kjernemodul.h tilsvarer ns-3-modulen, som du finner i katalogen src/kjerne i utgivelsen du installerte. I listen over denne katalogen finner du et stort antall header-filer. Når du gjør monteringen, waf plasserer offentlige header-filer i ns3-katalogen i en underkatalog bygge/feilsøke

Hvis du ikke har en slik katalog, betyr det at du ikke spesifiserte utdatakatalogen da du bygde utgivelsesversjonen av ns-3, bygg slik:
$ ./waf configure --build-profile=debug --out=build/debug
$ ./waf bygge
eller
$ ./waf configure --build-profile=optimalisert --out=bygg/optimalisert
$ ./waf bygge

eller bygge/optimalisere, avhengig av konfigurasjonen din. waf vil også automatisk generere en modulinkluderingsfil for å laste alle offentlige overskriftsfiler. Siden du selvfølgelig følger denne veiledningen religiøst, har du allerede gjort det

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

for å konfigurere prosjektet til å kjøre feilsøkingsbygg som inkluderer eksempler og tester. Det gjorde du også

$ ./waf

å sette sammen prosjektet. Så nå når du ser i katalogen ../../build/debug/ns3, så finner du blant annet headerfilene til de fire modulene vist ovenfor. Du kan se på innholdet i disse filene og finne at de inkluderer alle de offentlige filene som brukes av de tilsvarende modulene.

4.2.3 ns3 navneområde

Neste linje i manus første.cc er en navneområdeerklæring.

using namespace ns3;

ns-3-prosjektet er implementert i et C++ navneområde kalt ns3. Dette grupperer alle ns-3-relaterte erklæringer i et omfang utenfor det globale navneområdet, som forhåpentligvis vil hjelpe med integrasjon med annen kode. Ved å bruke C++-operatoren introduseres ns-3-navneområdet i den gjeldende (globale) deklarative regionen. Dette er en fancy måte å si at etter denne erklæringen, trenger du ikke å skrive inn ns3::scope-tillatelsesoperatøren før all ns-3-koden for å bruke den. Hvis du ikke er kjent med navneområder, kan du se nesten hvilken som helst C++-lærebok og sammenligne ns3-navneområdet ved å bruke std-navneområdet og deklarasjonen using namespace std; i eksempler på arbeid med utdataoperatøren domstol og bekker.

4.2.4 Logging

Den neste linjen i manuset er,

NS_LOG_COMPONENT_DEFINE ("FirstScriptExample");

Vi vil bruke denne erklæringen som et praktisk sted å diskutere vårt dokumentasjonssystem Doxygen. Hvis du ser på ns-3-prosjektets nettside, finner du en dokumentasjonslenke i navigasjonslinjen. Hvis du klikker på denne lenken, kommer du til vår dokumentasjonsside. Det er en "Siste utgivelse"-lenke som tar deg til dokumentasjonen for den siste stabile versjonen av ns-3. Hvis du velger "API Documentation"-koblingen, vil du bli ført til ns-3 API-dokumentasjonssiden.

På venstre side av siden finner du en grafisk fremstilling av dokumentasjonsstrukturen. Et godt sted å starte er Modules ns-3 "boken" i ns-3 navigasjonstreet. Hvis du avslører Moduler, vil du se en liste over ns-3 moduler dokumentasjon. Som diskutert ovenfor, er konseptet med en modul her direkte relatert til filene som er inkludert i modulen ovenfor. ns-3 logging-delsystemet er omtalt i avsnitt Bruke loggingsmodulen, så vi kommer tilbake til det senere i denne opplæringen, men du kan lære om utsagnet ovenfor ved å se på modulen Kjerneog deretter åpne boken Feilsøkingsverktøyog deretter velge siden Logging. Klikk på Logging.

Du bør nå se gjennom dokumentasjonen Doxygen for modul Logging. I listen over makroer øverst på siden vil du se en oppføring for NS_LOG_COMPONENT_DEFINE. Før du klikker på lenken, sørg for å se på "Detaljert beskrivelse" av registreringsmodulen for å forstå hvordan den fungerer generelt. For å gjøre dette kan du bla ned eller velge "Mer..." under diagrammet.

Når du har en generell ide om hva som skjer, gå videre og se på dokumentasjonen for den spesifikke NS_LOG_COMPONENT_DEFINE. Jeg vil ikke duplisere dokumentasjonen her, men for å oppsummere, erklærer denne linjen en registreringskomponent kalt FirstScriptEksempel, som lar deg aktivere eller deaktivere konsolllogging av meldinger ved å referere til et navn.

4.2.5 Hovedfunksjon

I de følgende linjene i skriptet vil du se,

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

Dette er ganske enkelt en erklæring om hovedfunksjonen til programmet (skriptet). Som med ethvert C++-program, må du definere en hovedfunksjon, denne utføres først. Det er ikke noe spesielt her. Ditt ns-3-skript er bare et C++-program. Følgende linje setter tidsoppløsningen til 1 nanosekund, som er standard:

Time::SetResolution (Time::NS);

Tidsoppløsning, eller ganske enkelt oppløsning, er den minste tidsverdien som kan brukes (den minste representable forskjellen mellom to tider). Du kan endre oppløsningen nøyaktig én gang. Mekanismen som gir denne fleksibiliteten bruker minne, så når oppløsningen er eksplisitt angitt, frigjør vi minnet, og forhindrer ytterligere oppdateringer. (Hvis du ikke angir oppløsningen eksplisitt, vil den som standard være ett nanosekund og minnet frigjøres når simuleringen starter.)

De følgende to linjene med skript brukes til å aktivere to loggingskomponenter som er innebygd i applikasjoner EchoClient и EchoServer:

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

Hvis du leser dokumentasjonen for Logging-komponenten, vil du se at det er flere nivåer av logging/granularitet som du kan aktivere på hver komponent. Disse to kodelinjene muliggjør feilsøkingslogging til INFO-nivået for ekkoklienter og servere. På dette nivået vil applikasjonen skrive ut meldinger mens den sender og mottar pakker under simulering.

Nå skal vi gå over til virksomheten med å lage topologien og kjøre simuleringen. Vi bruker topologihjelpeobjekter for å gjøre denne jobben så enkel som mulig.

4.2.6 Bruke topologiassistenter

De neste to linjene med kode i skriptet vårt vil faktisk lage Node ns-3-objektene som vil representere datamaskinene i simuleringen.

NodeContainer nodes;
nodes.Create (2);

Før vi fortsetter, la oss finne dokumentasjonen for klassen NodeContainer. En annen måte å komme til dokumentasjonen for en gitt klasse på er gjennom fanen Klasser på sidene Doxygen. Hvis du allerede har Doxygen åpen, bla opp til toppen av siden og velg kategorien Klasser. Du bør se et nytt sett med faner, hvorav en er en liste over klasser. Under denne fanen vil du se en liste over alle ns-3 klasser. Rull ned til ns3::NodeContainer. Når du finner en klasse, velg den for å gå til dokumentasjonen for klassen.

Som vi husker, er en av våre viktigste abstraksjoner noden. Den representerer datamaskinen som vi skal legge til ting som protokollstabler, applikasjoner og periferikort. Topologiassistent NodeContainer gir en praktisk måte å opprette, administrere og få tilgang til alle objekter Node, som vi lager for å kjøre simuleringen. Den første linjen ovenfor erklærer ganske enkelt NodeContainer, som vi kaller noder. Den andre linjen kaller Create-metoden på nodeobjektet og ber beholderen om å opprette to noder. Som beskrevet i Doxygen, ber containeren ns-3-systemet om å lage to objekter Node og lagrer pekere til disse objektene internt.

Nodene som er opprettet i skriptet, gjør ingenting ennå. Det neste trinnet i å bygge topologien er å koble nodene våre til nettverket. Den enkleste formen for nettverk som vi støtter er en punkt-til-punkt-forbindelse mellom to noder. Vi skal nå opprette en slik forbindelse.

PointToPointHelper

Vi oppretter en punkt-til-punkt-forbindelse ved å bruke et kjent mønster, ved å bruke et topologi-hjelpeobjekt for å gjøre det lavnivåarbeidet som kreves for forbindelsen. Husk at våre to viktigste abstraksjoner NetDevice и Kanal. I den virkelige verden tilsvarer disse begrepene omtrent periferikort og nettverkskabler. Vanligvis er disse to tingene nært knyttet til hverandre, og ingen kan regne med å dele for eksempel enheter Ethernet over en trådløs kanal. Våre topologihjelpere følger dette nære forholdet, og derfor vil du bruke et enkelt objekt i dette scenariet PointToPointHelper for oppsett og tilkobling av ns-3 objekter PointToPointNetDevice и PointToPointChannel. De neste tre linjene i manuset:

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

Første linje,

PointToPointHelper pointToPoint;

oppretter en forekomst av et objekt på stabelen PointToPointHelper. Fra et toppnivå synspunkt følgende linje,

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

forteller objektet PointToPointHelper bruk verdien "5 Mbit/s" (fem megabit per sekund) som "Datahastighet'.

Fra et mer spesifikt synspunkt tilsvarer strengen "DataRate" det vi kaller et attributt PointToPointNetDevice. Hvis du ser på Doxygen for klassen ns3::PointToPointNetDevice og i dokumentasjonen for metoden GetTypeId vil du finne en liste over attributter definert for enheten. Blant dem vil være attributtet "Datahastighet" De fleste brukersynlige ns-3-objekter har lignende lister over attributter. Vi bruker denne mekanismen for enkelt å sette opp simuleringen uten rekompilering, som du vil se i neste avsnitt.

Lik "Datahastighet" i PointToPointNetDevice, vil du finne "Delay"-attributtet knyttet til PointToPointChannel. Den siste linjen

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

говорит PointToPointHelper bruk verdien "2 ms" (to millisekunder) som forplantningsforsinkelsesverdien for punkt-til-punkt-koblingen den deretter oppretter.

NetDeviceContainer

For øyeblikket har vi i manuset NodeContainer, som inneholder to noder. Vi har PointToPointHelper, som er forberedt for å lage objekter PointToPointNetDevices og koble dem ved hjelp av et PointToPointChannel-objekt. Akkurat som vi brukte NodeContainer-topologihjelpeobjektet for å lage noder, vil vi spørre PointToPointHelper utføre arbeid for oss knyttet til opprettelse, konfigurering og installasjon av enhetene våre. Vi trenger en liste over alle opprettede objekter NetDevice, så vi bruker NetDeviceContainer å lagre dem på samme måte som vi brukte NodeContainer for å lagre nodene vi opprettet. De neste to linjene med kode,

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

komplett enhet og kanaloppsett. Den første linjen erklærer enhetsbeholderen nevnt ovenfor, og den andre gjør hovedarbeidet. Metode Install et objekt PointToPointHelper tar NodeContainer som en parameter. Innsiden NetDeviceContainer for hver node som ligger i NodeContainer er opprettet (for punkt-til-punkt-kommunikasjon må det være nøyaktig to av dem) PointToPointNetDevice opprettes og lagres i enhetsbeholderen. PointToPointChannel er opprettet og to er knyttet til den PointToPointNetDevices. Etter å ha opprettet objekter, lagres attributtene i PointToPointHelper, brukes til å initialisere de tilsvarende attributtene i de opprettede objektene.

Etter å ha ringt pointToPoint.Install (noder) vi vil ha to noder, hver med en punkt-til-punkt nettverksenhet installert og en punkt-til-punkt-kobling mellom dem. Begge enhetene vil bli konfigurert til å overføre data med en hastighet på fem megabit per sekund med en overføringsforsinkelse på to millisekunder over kanalen.

InternetStackHelper

Vi har nå noder og enheter konfigurert, men nodene våre har ikke installert protokollstabler. De neste to linjene med kode vil ta seg av dette.

InternetStackHelper stack;
stack.Install (nodes);

InternetStackHelper - er en topologihjelper for Internett-stabler, lik PointToPointHelper for punkt-til-punkt nettverksenheter. Metode Install tar NodeContainer som en parameter. Når den kjøres, vil den installere Internett-stakken (TCP, UDP, IP, etc.) på hver containernode.

IPv4-adressehjelper

Da må vi knytte enhetene våre til IP-adresser. Vi tilbyr en topologiassistent for å administrere IP-adressetildeling. Den eneste API-en som er synlig for brukeren, er å angi base-IP-adressen og nettmasken som skal brukes når du utfører selve adressedistribusjonen (dette gjøres på et lavere nivå i hjelperen). De neste to linjene med kode i eksempelskriptet vårt første.cc,

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

erklær adressehjelpeobjektet og fortell det at det skal begynne å tildele IP-adresser fra nettverk 10.1.1.0 ved å bruke bitmasken 255.255.255.0 for å bestemme. Som standard vil tildelte adresser starte med én og øke monotont, så den første adressen som tildeles fra denne basen vil være 10.1.1.1, deretter 10.1.1.2, osv. I virkeligheten, på et lavt nivå, husker ns-3-systemet alle tildelte IP-adresser og genererer en fatal feil hvis du ved et uhell oppretter en situasjon der den samme adressen genereres to ganger (forresten, denne feilen er vanskelig å feilsøke).

Følgende kodelinje,

Ipv4InterfaceContainer interfaces = address.Assign (devices);

utfører selve adressetildelingen. I ns-3 etablerer vi en forbindelse mellom en IP-adresse og en enhet som bruker objektet IPv4-grensesnitt. Akkurat som vi noen ganger trenger en liste over nettverksenheter opprettet av assistenten for senere bruk, trenger vi noen ganger en liste over objekter IPv4-grensesnitt. IPv4 InterfaceContainer gir denne funksjonaliteten.

Vi bygde et punkt-til-punkt-nettverk, med stabler installert og IP-adresser tildelt. Nå trenger vi applikasjoner i hver node for å generere trafikk.

4.2.7 Bruke applikasjonen

En annen av hovedabstraksjonene til ns-3-systemet er Søknad (applikasjon). I dette scenariet bruker vi to basisklassespesialiseringer Søknad ns-3 kalt UdpEchoServerApplication и UdpEchoClientApplication. Som i tidligere tilfeller bruker vi hjelpeobjekter for å konfigurere og administrere basisobjektene. Her bruker vi UdpEchoServerHelper и UdpEchoClientHelper objekter for å gjøre livene våre enklere.

UdpEchoServerHelper

Følgende kodelinjer i vårt first.cc-eksempelskript brukes til å konfigurere en UDP-ekkoserverapplikasjon på en av nodene vi opprettet tidligere.

UdpEchoServerHelper echoServer (9);

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

Den første linjen med kode i kodebiten ovenfor oppretter UdpEchoServerHelper. Som vanlig er ikke dette en applikasjon i seg selv, det er et objekt som hjelper oss å lage ekte applikasjoner. En av våre konvensjoner er å sende de nødvendige attributtene til konstruktøren av hjelpeobjektet. I dette tilfellet kan ikke hjelperen gjøre noe nyttig med mindre den får portnummeret som serveren vil lytte etter pakker på, dette nummeret må også være kjent for klienten. I dette tilfellet sender vi portnummeret til hjelpekonstruktøren. Konstruktøren gjør det på sin side ganske enkelt SetAttribute med den beståtte verdien. Senere, hvis ønskelig, kan du bruke SetAttribute til å angi en annen verdi for Port-attributtet.

Som mange andre hjelpeobjekter, objektet UdpEchoServerHelper har en metode Install. Utførelse av denne metoden skaper effektivt en grunnleggende ekkoserverapplikasjon og binder den til verten. Interessant nok metoden Install tar NodeContainer som en parameter akkurat som de andre Install metoder vi har sett.

Den implisitte C++-konverteringen som fungerer her tar resultatet av metoden node.Get(1) (som returnerer en smart peker til nodeobjektet - Ptr ) og bruker den i konstruktøren for det anonyme objektet NodeContainersom deretter overføres til metoden Install. Hvis du ikke kan bestemme i C++-kode hvilken metodesignatur som er kompilert og utført, så se blant de implisitte konverteringene.

Nå ser vi det echoServer.Install i ferd med å installere programmet UdpEchoServerApplication på funnet i NodeContainersom vi bruker til å administrere nodene våre, node med indeks 1. Metode Install vil returnere en beholder som inneholder pekere til alle applikasjoner (i dette tilfellet en, siden vi passerte en anonym NodeContainer, som inneholder én node) opprettet av hjelperen.

Apper må spesifisere når de skal begynne å generere trafikk "start" og må kanskje i tillegg spesifisere et tidspunkt når den skal stoppes "Stoppe". Vi tilbyr begge alternativene. Disse tidene settes ved hjelp av metodene ApplicationContainer Start и Stopp. Disse metodene aksepterer parametere av typen Tid. I dette tilfellet bruker vi en eksplisitt sekvens av C++-konverteringer for å ta C++ dobbelt 1.0 og konverter det til et tns-3 Time-objekt som bruker Seconds-objektet til å konvertere til sekunder. Husk at konverteringsreglene kan kontrolleres av modellforfatteren, og C++ har sine egne regler, så du kan ikke alltid regne med at parameterne konverteres slik du forventet. To linjer

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

vil få ekkoserverapplikasjonen til å starte (slå på automatisk) ett sekund etter at simuleringen starter og stoppe (slå av) etter ti sekunder av simuleringen. På grunn av det faktum at vi erklærte en simuleringshendelse (applikasjonsstopphendelse), som vil bli utført om ti sekunder, vil minst ti sekunders nettverksdrift simuleres.

UdpEchoClientHelper

Klientapplikasjon savner konfigurert på en måte som nesten ligner på serveren. Det er et basisobjekt UdpEchoClientApplication, som er kontrollert
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));;

For ekkoklienten må vi imidlertid angi fem forskjellige attributter. De to første attributtene angis ved opprettelsestidspunktet UdpEchoClientHelper. Vi sender parametere som brukes (inne i hjelperen) for å sette attributtene "Ekstern adresse" и "RemotePort" i samsvar med vår avtale om å sende de nødvendige parameterne til hjelpekonstruktøren.

La oss huske at vi brukte IPv4 InterfaceContainer for å spore IP-adressene vi har tildelt enhetene våre. Nullgrensesnittet i grensesnittbeholderen vil tilsvare IP-adressen til nullnoden i nodebeholderen. Det første grensesnittet i grensesnittbeholderen tilsvarer IP-adressen til den første noden i nodebeholderen. Så i den første linjen med kode (over) lager vi en hjelper og forteller den at klientens eksterne adresse vil være IP-adressen som er tildelt verten der serveren er plassert. Vi sier også at vi må sørge for at pakker sendes til port ni.

"MaxPackets"-attributtet forteller klienten det maksimale antallet pakker vi kan sende under simuleringen. "Interval"-attributtet forteller klienten hvor lenge den skal vente mellom pakker, og "PacketSize"-attributtet forteller klienten hvor stor pakkens nyttelast skal være. Med denne attributtkombinasjonen ber vi klienten sende en enkelt 1024-byte pakke.

Som med ekkoserveren, setter vi attributtene til ekkoklienten Start и Stopp, men her starter vi klienten et sekund etter at serveren er slått på (to sekunder etter starten av simuleringen).

4.2.8 Simulator

På dette tidspunktet må vi kjøre simuleringen. Dette gjøres ved hjelp av den globale funksjonen Simulator::Kjør.

Simulator::Run ();

Da vi kalte metodene tidligere,

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

vi planla faktisk hendelser i simulatoren på 1,0 sekunder, 2,0 sekunder og to hendelser på 10,0 sekunder. Etter samtalen Simulator::Kjør, vil systemet begynne å vise listen over planlagte hendelser og utføre dem. Den vil først utløse en hendelse om 1,0 sekunder, som vil utløse ekkoserverapplikasjonen (denne hendelsen kan i sin tur planlegge mange andre hendelser). Den vil da utløse en hendelse planlagt til t=2,0 sekunder som vil starte ekkoklientapplikasjonen. Igjen, dette arrangementet kan ha mange flere arrangementer planlagt. Ekkoklientimplementeringen av starthendelsen vil begynne dataoverføringsfasen av simuleringen ved å sende en pakke til serveren.

Handlingen med å sende en pakke til serveren vil utløse en kjede av hendelser som automatisk planlegges bak kulissene og som vil implementere mekanikken for å sende en ekkopakke i henhold til tidsparameterne vi har satt i skriptet.

Som et resultat, siden vi bare sender én pakke (husk attributtet MaxPackets ble satt til én), vil hendelseskjeden initiert av denne enkeltklient-pingen avsluttes og simuleringen går i standby-modus. Når dette skjer, vil de gjenværende planlagte hendelsene være hendelsene Stopp for server og klient. Når disse hendelsene er utført, vil det ikke være noen hendelser igjen for videre behandling og Simulator::Kjør vil returnere kontrollen. Simuleringen er fullført.

Det gjenstår bare å rydde opp etter deg. Dette gjøres ved å kalle den globale funksjonen Simulator::Destroy. Fordi hjelpefunksjonene (eller lavnivå ns-3-koden) ble kalt, som er organisert slik at kroker ble satt inn i simulatoren for å ødelegge alle objekter som ble opprettet. Du trengte ikke spore noen av disse objektene selv - alt du måtte gjøre var å ringe Simulator::Destroy og gå ut. ns-3-systemet vil gjøre dette harde arbeidet for deg. De resterende linjene i vårt første ns-3-skript, first.cc, gjør nettopp det:

Simulator::Destroy ();
return 0;
}

Når stopper simulatoren?

ns-3 er en diskret hendelse (DE) simulator. I en slik simulator er hver hendelse knyttet til dens utførelsestid, og simuleringen fortsetter ved å behandle hendelser i den rekkefølgen de oppstår ettersom simuleringen skrider frem. Hendelser kan føre til at fremtidige hendelser planlegges (for eksempel kan en tidtaker omplanlegge seg selv til å fullføre tellingen i neste intervall).

Innledende hendelser initieres vanligvis av enheten, for eksempel vil IPv6 planlegge oppdagelsen av tjenester på nettverket, naboforespørsler osv. Applikasjonen planlegger den første pakkesendingshendelsen, og så videre. Når en hendelse behandles, kan den generere null, én eller flere hendelser. Etter hvert som simuleringen skrider frem, oppstår hendelser som enten avsluttes eller skaper nye. Simuleringen stopper automatisk hvis hendelseskøen er tom eller en spesiell hendelse oppdages Stopp. Begivenhet Stopp generert av funksjonen Simulator::Stopp (stopp tiden).

Det er et typisk tilfelle der Simulator::Stop er helt nødvendig for å stoppe simuleringen: når det er selvopprettholdende hendelser. Selvopprettholdende (eller gjentakende) hendelser er hendelser som alltid blir omlagt. Som en konsekvens holder de alltid arrangementskøen ikke tom. Det er mange protokoller og moduler som inneholder gjentatte hendelser, for eksempel:

• FlowMonitor - periodisk kontroll for tapte pakker;

• RIPng – periodisk kringkasting av rutetabelloppdateringer;

• etc.

I slike tilfeller Simulator::Stopp nødvendig for å stoppe simuleringen riktig. I tillegg, når ns-3 er i emuleringsmodus, brukes RealtimeSimulator til å synkronisere simuleringsklokken med maskinklokken, og Simulator::Stopp nødvendig for å stoppe prosessen.

Mange av simuleringsprogrammene i læreboka ringer ikke Simulator::Stopp eksplisitt, siden de avsluttes automatisk når hendelsene i kø er oppbrukt. Disse programmene vil imidlertid også godta Simulator::Stop-anropet. For eksempel vil følgende tilleggssetning i det første eksempelprogrammet planlegge et eksplisitt stopp ved 11 sekunder:

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

Ovennevnte vil faktisk ikke endre virkemåten til dette programmet, siden denne spesielle simuleringen avsluttes naturlig etter 10 sekunder. Men hvis du skulle endre stopptiden i setningen ovenfor fra 11 sekunder til 1 sekund, vil du legge merke til at simuleringen stopper før noen utgang treffer skjermen (siden utgangen skjer etter ca. 2 sekunders simuleringstid).

Det er viktig å ringe Simulator::Stopp før du ringer Simulator::Run; ellers kan Simulator::Run aldri returnere kontrollen til hovedprogrammet for å utføre stoppet!

4.2.9 Bygge skriptet ditt

Vi har gjort det trivielt å lage de enkle skriptene dine. Alt du trenger å gjøre er å legge skriptet ditt i scratch-katalogen, og det vil bli bygget automatisk hvis du kjører waf. La oss prøve. Gå tilbake til toppnivåkatalogen og kopier examples/tutorial/first.cc til katalogen skraper

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

Bygg nå ditt første eksempelskript med WAF:

$ ./waf

Du skal se meldinger som indikerer at ditt første eksempel ble opprettet.

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)

Nå kan du kjøre eksemplet (merk at hvis du bygger programmet i scratch-katalogen, må du kjøre det fra skraper):

$ ./waf --run scratch/myfirst

Du bør se lignende utgang:

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

Her kan du se at byggesystemet bekrefter at filen er bygget og deretter kjører den. Du ser at komponentoppføringen på ekkoklienten indikerer at den sendte en enkelt 1024-byte pakke til ekkoserver 10.1.1.2. Du ser også loggingskomponenten på ekkoserveren for å si at den mottok 1024 byte fra 10.1.1.1. Ekkoserveren spiller stille av pakken, og du kan se i ekkoklientens logg at den mottok pakken tilbake fra serveren.

4.3 ns-3 Kildekode

Nå som du har brukt noen av ns-3-hjelperne, kan du ta en titt på noe av kildekoden som implementerer denne funksjonaliteten. Den siste koden kan sees på vår webserver på følgende lenke: https://gitlab.com/nsnam/ns-3-dev.git. Der vil du se Mercurial-sammendragssiden for vårt ns-3-utviklingstre. Øverst på siden vil du se flere lenker,

summary | shortlog | changelog | graph | tags | files

Gå videre og velg filkoblingen. Slik vil toppnivået i de fleste av våre depoter se ut:

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

Våre eksempelskript er i katalogen eksempler. Hvis du klikker på eksemplene vil du se en liste over underkataloger. En av filene i underkatalogen opplæring - first.cc... Hvis du klikker på første.cc du vil se koden du nettopp har lært.

Kildekoden er hovedsakelig plassert i katalogen src. Du kan se kildekoden ved å klikke på katalognavnet eller klikke på filkoblingen til høyre for katalognavnet. Hvis du klikker på src-katalogen, får du en liste over src-underkataloger. Hvis du deretter klikker på kjerneunderkatalogen, finner du en liste over filer. Den første filen du vil se (når du skriver denne veiledningen) er abort.h. Hvis du klikker på lenken abort.h, vil du bli sendt til kildefilen for abort.h, som inneholder nyttige makroer for å avslutte skript hvis unormale forhold oppdages. Kildekoden for hjelperne vi brukte i dette kapittelet finner du i katalogen src/Applikasjoner/hjelper. Se gjerne rundt i katalogtreet for å finne ut hva som er hvor og forstå stilen til ns-3-programmer.

Kilde: www.habr.com

Legg til en kommentar