Introduktion til ns-3 netværkssimulator. Kapitel 5

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

5 Konfiguration
5.1 Brug af logningsmodulet
5.1.1 Oversigt over logning
5.1.2 Aktivering af logning
5.1.3 Tilføjelse af logning til din kode
5.2 Brug af kommandolinje-argumenter
5.2.1 Omskrivning af standardattributværdier
5.2.2 Fang dine egne kommandoer
5.3 Brug af sporingssystemet
5.3.1 ASCII Sporings
Parsing af ASCII sporing
5.3.2 PCAP Sporing

Kapitel 5

Indstillinger

5.1 Brug af logningsmodulet

Vi har allerede kort gennemgået ns‑3 logningsmodulet, mens vi kiggede på scriptet first.cc. I dette kapitel vil vi se nærmere på mulige anvendelser af logningsunderenheden.

5.1.1 Oversigt over logning

Mange store systemer understøtter en eller anden form for beskedregistrering, og ns‑3 er ingen undtagelse. I nogle tilfælde registreres kun fejlmeddelelser i "operatørens konsol" (som normalt er stderr i Unix-baserede systemer). I andre systemer kan advarselsmeddelelser såvel som mere detaljeret information blive vist. I nogle tilfælde anvendes logningsmidler til at udskrive fejlfindingmeddelelser, som hurtigt kan "sløre" output.

Den tilgang, der anvendes i ns‑3, antager, at alle disse niveauer af informativitet er nyttige, og vi tilbyder en selektiv, flerniveau-tilgang til registrering af meddelelser. Logning kan være helt deaktiveret, aktiveret for enkelte komponenter eller globalt. Dette gøres gennem justerbare informativitetsniveauer. ns‑3 logningsmodulet giver en relativt enkel måde at få nyttige oplysninger fra din simulation.

Du skal forstå, at vi tilbyder et generelt mekanisme — sporing — til at udtrække data fra dine modeller, som bør foretrækkes til output ved modellering (for mere detaljerede oplysninger om vores sporingssystem, se afsnit 5.3). Logning bør være den foretrukne metode til at få fejlfindinginformation, advarsler, fejlmeddelelser eller til hurtigt at udskrive meddelelser fra dine scenarier eller modeller på ethvert tidspunkt.

I øjeblikket er der defineret syv niveauer (typer) af logmeddelelser i systemet, rangeret efter stigende informativitet.

  • LOG_ERROR — registrering af fejlmeddelelser (relateret makro: NS_LOG_ERROR);
  • LOG_WARN — registrering af advarselsmeddelelser (relateret makro: NS_LOG_WARN);
  • LOG_DEBUG — registrering af sjældne specielle debugmeddelelser (relateret makro: NS_LOG_DEBUG);
  • LOG_INFO — registrering af informationsmeddelelser om programmets kørsel (relateret makro: NS_LOG_INFO);
  • LOG_FUNCTION — registrering af meddelelser, der beskriver hver kaldte funktion (to relaterede makroer: NS_LOG_FUNCTION, der anvendes til medlemsfunktioner, og NS_LOG_FUNCTION_NOARGS, der anvendes til statiske funktioner);
  • LOG_LOGIC — registrering af meddelelser, der beskriver den logiske strøm inden for funktionen (relateret makro: NS_LOG_LOGIC);
  • LOG_ALL — registrering af alt ovenstående (ingen relateret makro).
    For hver type (LOG_TYPE) er der også en type LOG_LEVEL_TYPE, som, hvis den bruges, tillader registrering af alle niveauer over dens eget niveau. (Som følge heraf er LOG_ERROR og LOG_LEVEL_ERROR samt LOG_ALL og LOG_LEVEL_ALL funktionelt ækvivalente.) For eksempel vil aktivering af LOG_INFO kun tillade meddelelser givet af makroen NS_LOG_INFO, mens aktivering af LOG_LEVEL_INFO også vil inkludere meddelelser givet af makroerne NS_LOG_DEBUG, NS_LOG_WARN og NS_LOG_ERROR.

Vi tilbyder også en makro til ubetinget logning, som altid vises, uanset logningsniveau eller komponentvalg.

  • NS_LOG_UNCOND — ubetinget registrering af relateret meddelelse (uden relateret logningsniveau).

Hvert niveau kan anmodes om separat eller kumulativt. Logning kan konfigureres ved hjælp af miljøvariablen NS_LOG eller gennem registrering af et systemfunktion kald. Som tidligere vist, har logningssystemet Doxygen-dokumentation, og det er nu tid til at gennemgå det, hvis du ikke allerede har gjort det.

Nu, hvor du har læst dokumentationen grundigt, lad os bruge denne viden til at få nogle interessante oplysninger fra eksempelscriptet scratch/myfirst.cc, som du allerede har kompileret.

5.1.2 Aktivering af logning

Lad os bruge miljøvariablen NS_LOG til at køre nogle flere logs, men først, bare for at få styr på det, kør det seneste script, som du gjorde tidligere,

$ ./waf --run scratch/myfirst

Du skal se den velkendte output fra det første eksempelprogram ns-3

$ Waf: Går ind i biblioteket `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
Waf: Forlader biblioteket `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' 'build'
Afsluttet med succes (0.413s)
Sendte 1024 bytes til 10.1.1.2
Modtog 1024 bytes fra 10.1.1.1
Modtog 1024 bytes fra 10.1.1.2

Det viser sig, at de 'sendte' og 'modtagne' beskeder, du ser ovenfor, faktisk er registrerede beskeder fra UdpEchoClientApplication og UdpEchoServerApplication. For eksempel kan vi bede klientapplikationen om at udskrive yderligere information ved at indstille dens logningsniveau via miljøvariablen NS_LOG.

Fra dette øjeblik vil jeg antage, at du bruger en sh-lignende skald, som bruger syntaksen 'VARIABLE = value'. Hvis du bruger en csh-lignende skald, skal du konvertere mine eksempler til syntaksen 'setenv variable value', som kræves af disse skaller.

I øjeblikket reagerer UDP-echo-klientapplikationen på følgende kode i scratch/myfirst.cc,

LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);

Det aktiverer logningsniveauet LOG_LEVEL_INFO. Når vi sender en logningsniveau-flag, aktiverer vi faktisk dette niveau og alle lavere niveauer. I dette tilfælde har vi aktiveret NS_LOG_INFO, NS_LOG_DEBUG, NS_LOG_WARN og NS_LOG_ERROR. Vi kan hæve logningsniveauet og få flere oplysninger uden at ændre scriptet og genkompilere ved at sætte miljøvariablen NS_LOG som følger:

$ export NS_LOG=UdpEchoClientApplication=level_all

Så vi sætter følgende værdi af miljøvariablen NS_LOG i sh-skallen,

UdpEchoClientApplication=level_all

Den venstre side af tildelingen er navnet på den loggede komponent, som vi ønsker at konfigurere, mens den højre side er flaget, som vi vil anvende for dette. I dette tilfælde planlægger vi at inkludere alle fejlniveauer i applikationen. Hvis du kører scriptet med NS_LOG sat på denne måde, vil logningssystemet ns-3 acceptere ændringerne, og du skulle se følgende output:

Waf: Går ind i biblioteket `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
Waf: Forlader biblioteket `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
'build' afsluttet med succes (0.404s)
UdpEchoClientApplication:UdpEchoClient()
UdpEchoClientApplication:SetDataSize(1024)
UdpEchoClientApplication:StartApplication()
UdpEchoClientApplication:ScheduleTransmit()
UdpEchoClientApplication:Send()
Sendte 1024 bytes til 10.1.1.2
Modtog 1024 bytes fra 10.1.1.1
UdpEchoClientApplication:HandleRead(0x6241e0, 0x624a20)
Modtog 1024 bytes fra 10.1.1.2
UdpEchoClientApplication:StopApplication()
UdpEchoClientApplication:DoDispose()
UdpEchoClientApplication:~UdpEchoClient()

Den ekstra fejlinformation leveret af applikationen svarer nu til niveauet NS_LOG_FUNCTION. Det viser hvert tilfælde af funktionsopkald under udførelsen af scriptet. Som regel er det at foretrække at bruge (mindst)NS_LOG_FUNCTION (this). Brug NS_LOG_FUNCTION_NOARGS ()
kun i statiske funktioner. Det skal dog bemærkes, at der ikke er krav i ns-3-systemet om at opretholde nogen form for logningsfunktionalitet. Beslutningen om, hvor meget information der registreres, ligger helt i hænderne på modeludvikleren. For echo-applikationer er der mange outputmuligheder til logning.

Nu kan du se loggen over de funktionsopkald, der er blevet lavet af applikationen. Hvis du ser nøje efter, vil du bemærke et kolonet mellem linjen UdpEchoClientApplication og metodeNavnet, hvor du måske forventede at se C++'s områdeoperatør (: :). Dette er gjort med vilje.

Det er faktisk ikke navnet på klassen, men navnet på logningskomponenten. Når der er et match mellem kildefilen og klassen, er det normalt klassenavnet, men du skal forstå, at det rent faktisk ikke er klasseNavnet, og der er et enkelt kolon i stedet for dobbelt kolon. Det er en måde at hjælpe dig med at konceptere logningskomponentens navn fra klasseNavnet på en relativt subtil måde.

Nogle gange kan det dog være svært at bestemme, hvilken metode der faktisk genererer logbeskeden. Hvis du ser på teksten ovenfor, vil du undre dig over, hvor linjen "Received 1024 bytes from 10.1.1.2" kom fra. Du kan løse dette problem ved at sætte niveauet prefix_func i miljøvariablen NS_LOG. Prøv at gøre følgende,

$ export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func'

Bemærk, at citationstegnene er nødvendige, da det lodrette streg, som vi bruger til at angive en OGS-operation, også er en Unix-pipeline separator. Nu, hvis du kører scriptet, vil du se, at logningssystemet sikrer, at hver besked fra den givne log har et præfiks med navnet på komponenten.

Waf: Indtager bibliotek `\/home\/craigdo\/repos\/ns-3-allinone\/ns-3-dev\/build'\nWaf: Forlader bibliotek `\/home\/craigdo\/repos\/ns-3-allinone\/ns-3-dev\/build'\n'build' afsluttet med succes (0.417s)\nUdpEchoClientApplication:UdpEchoClient()\nUdpEchoClientApplication:SetDataSize(1024)\nUdpEchoClientApplication:StartApplication()\nUdpEchoClientApplication:ScheduleTransmit()\nUdpEchoClientApplication:Send()\nUdpEchoClientApplication:Send(): Sendt 1024 bytes til 10.1.1.2\nModtaget 1024 bytes fra 10.1.1.1\nUdpEchoClientApplication:HandleRead(0x6241e0, 0x624a20)\nUdpEchoClientApplication:HandleRead(): Modtaget 1024 bytes fra 10.1.1.2\nUdpEchoClientApplication:StopApplication()\nUdpEchoClientApplication:DoDispose()\nUdpEchoClientApplication:~UdpEchoClient()

Nu kan du se, at alle beskeder, der kommer fra UDP echo-klientapplikationen, identificeres som sådanne. Beskeden «Received 1024 bytes from 10.1.1.2» er nu tydeligt defineret som coming fra echo-klientapplikationen. Den resterende besked skal komme fra UDP echo-serverapplikationen. Vi kan tænde denne komponent ved at indtaste en liste over komponenter adskilt ved kolon i miljøvariablen NS_LOG.

$ export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func:\n               UdpEchoServerApplication=level_all|prefix_func'

Advarsel: I eksemplet ovenfor skal du fjerne linjeskiftet efter kolon (:), som er brugt til at formatere dokumentet. Nu, hvis du kører scriptet, vil du se alle logbeskeder fra klient- og serverecho-applikationerne. Dette kan være meget nyttigt ved fejlfinding.

Waf: Indtager bibliotek `\/home\/craigdo\/repos\/ns-3-allinone\/ns-3-dev\/build'\nWaf: Forlader bibliotek `\/home\/craigdo\/repos\/ns-3-allinone\/ns-3-dev\/build'\n'build' afsluttet med succes (0.406s)\nUdpEchoServerApplication:UdpEchoServer()\nUdpEchoClientApplication:UdpEchoClient()\nUdpEchoClientApplication:SetDataSize(1024)\nUdpEchoServerApplication:StartApplication()\nUdpEchoClientApplication:StartApplication()\nUdpEchoClientApplication:ScheduleTransmit()\nUdpEchoClientApplication:Send()\nUdpEchoClientApplication:Send(): Sendt 1024 bytes til 10.1.1.2\nUdpEchoServerApplication:HandleRead(): Modtaget 1024 bytes fra 10.1.1.1\nUdpEchoServerApplication:HandleRead(): Echoing packet\nUdpEchoClientApplication:HandleRead(0x624920, 0x625160)\nUdpEchoClientApplication:HandleRead(): Modtaget 1024 bytes fra 10.1.1.2\nUdpEchoServerApplication:StopApplication()\nUdpEchoClientApplication:StopApplication()\nUdpEchoClientApplication:DoDispose()\nUdpEchoServerApplication:DoDispose()\nUdpEchoClientApplication:~UdpEchoClient()\nUdpEchoServerApplication:~UdpEchoServer()

Det kan også være nyttigt at se simuleringsklokken, hvori logbeskeden blev oprettet. Du kan gøre dette ved at tilføje en bit prefix_time:

$ export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func|prefix_time: UdpEchoServerApplication=level_all|prefix_func|prefix_time'

Igen skal du fjerne det ovenstående linjeskift. Hvis du nu kører scriptet, bør du se følgende output:

Waf: Indtager bibliotek `\/home\/craigdo\/repos\/ns-3-allinone\/ns-3-dev\/build'  
Waf: Forlader bibliotek `\/home\/craigdo\/repos\/ns-3-allinone\/ns-3-dev\/build'  
'build' afsluttet med succes (0.418s)  
0s UdpEchoServerApplication:UdpEchoServer()  
0s UdpEchoClientApplication:UdpEchoClient()  
0s UdpEchoClientApplication:SetDataSize(1024)  
1s UdpEchoServerApplication:StartApplication()  
2s UdpEchoClientApplication:StartApplication()  
2s UdpEchoClientApplication:ScheduleTransmit()  
2s UdpEchoClientApplication:Send()  
2s UdpEchoClientApplication:Send(): Sendte 1024 bytes til 10.1.1.2  
2.00369s UdpEchoServerApplication:HandleRead(): Modtog 1024 bytes fra 10.1.1.1  
2.00369s UdpEchoServerApplication:HandleRead(): Ekko pakke  
2.00737s UdpEchoClientApplication:HandleRead(0x624290, 0x624ad0)  
2.00737s UdpEchoClientApplication:HandleRead(): Modtog 1024 bytes fra 10.1.1.2  
10s UdpEchoServerApplication:StopApplication()  
10s UdpEchoClientApplication:StopApplication()  
UdpEchoClientApplication:DoDispose()  
UdpEchoServerApplication:DoDispose()  
UdpEchoClientApplication:~UdpEchoClient()  
UdpEchoServerApplication:~UdpEchoServer()

Bemærk venligst, at konstruktøren for UdpEchoServer blev kaldt under simulationen 0 sekunder. Dette sker faktisk før simulationen starter, men denne tid vises som nul sekunder. Det samme gælder for beskeden fra konstruktøren UdpEchoClient.

Waf: Indtager bibliotek `\/home\/craigdo\/repos\/ns-3-allinone\/ns-3-dev\/build'  
Waf: Forlader bibliotek `\/home\/craigdo\/repos\/ns-3-allinone\/ns-3-dev\/build'  
'build' afsluttet med succes (0.418s)  
0s UdpEchoServerApplication:UdpEchoServer()  
0s UdpEchoClientApplication:UdpEchoClient()  
0s UdpEchoClientApplication:SetDataSize(1024)  
1s UdpEchoServerApplication:StartApplication()  
2s UdpEchoClientApplication:StartApplication()  
2s UdpEchoClientApplication:ScheduleTransmit()  
2s UdpEchoClientApplication:Send()  
2s UdpEchoClientApplication:Send(): Sendte 1024 bytes til 10.1.1.2  
2.00369s UdpEchoServerApplication:HandleRead(): Modtog 1024 bytes fra 10.1.1.1  
2.00369s UdpEchoServerApplication:HandleRead(): Ekko pakke  
2.00737s UdpEchoClientApplication:HandleRead(0x624290, 0x624ad0)  
2.00737s UdpEchoClientApplication:HandleRead(): Modtog 1024 bytes fra 10.1.1.2  
10s UdpEchoServerApplication:StopApplication()  
10s UdpEchoClientApplication:StopApplication()  
UdpEchoClientApplication:DoDispose()  
UdpEchoServerApplication:DoDispose()  
UdpEchoClientApplication:~UdpEchoClient()  
UdpEchoServerApplication:~UdpEchoServer()

Lad os huske, at scriptet scratch\/first.cc startede ekserverapplikationen et sekund før simulationen begyndte. Nu kan du se, at metoden StartApplication for serveren faktisk kaldes i det første sekund. Du kan også bemærke, at ekklienten starter i det andet sekund af simulationen, som vi bad om i scriptet.

Nu kan du følge simulationens forløb ved at kalde ScheduleTransmit i klienten, som kalder Send til tilbagekaldet HandleRead i ekserverapplikationen. Bemærk, at den brugte tid til at sende en pakke gennem den to-punkts forbindelse er 3,69 millisekunder. Det er tydeligt, at ekserveren registrerer besked om, at den har svaret på pakken, og derefter, efter en forsinkelse i kanalen, ser du, at ekklienten modtager ekkopakken i sin metode HandleRead.

I denne simulation sker der meget, der er usynligt for dig. Men du kan let spore hele processen ved at aktivere alle komponenter til logning i systemet. Prøv at sætte følgende værdi i variablen NS_LOG,

$ export 'NS_LOG=*=level_all|prefix_func|prefix_time'

Stjernen ovenfor er en wildcard for logningskomponenten. Dette vil aktivere alle poster i alle komponenter, der bruges i simulationen. Jeg vil ikke gentage output her (på tidspunktet for at skrive dette producerer det 1265 linjer output for én ekkopakke), men du kan omdirigere denne information til en fil og se den i din yndlingseditor,

$ ./waf --run scratch/myfirst > log.out 2>&1

Jeg bruger personligt denne ekstremt detaljerede logversion, når jeg har et problem, og jeg ikke har en idé om, hvor det gik galt. Jeg kan ret nemt følge med i koden uden at sætte breakpoints og køre koden trin for trin i debuggeren. Jeg kan bare redigere output i min yndlingseditor og lede efter det, jeg forventer, og se hvad der sker, som jeg ikke forventede. Når jeg har en generel idé om, hvad der går galt, går jeg over til debuggeren for at undersøge problemet nærmere. Denne type output kan være særligt nyttig, når dit script gør noget fuldstændig uventet. Hvis du kun bruger debuggeren, kan du helt overse en uventet drejning. Logningen gør sådanne drejninger synlige.

5.1.3 Tilføjelse af logning til din kode

Du kan tilføje nye poster til dine simulationer ved at foretage log-opkald fra flere makroer. Lad os gøre det i scriptet myfirst.cc, som vi har i den "rene" mappe. Lad os minde os selv om, at vi i dette script har defineret logningskomponenten:

NS_LOG_COMPONENT_DEFINE ("FirstScriptExample");

Du er klar over, at du kan aktivere logning af alle beskeder fra denne komponent ved at sætte miljøvariablen NS_LOG til forskellige niveauer. Lad os fortsætte og tilføje nogle poster til scriptet. Makroerne, der bruges til at tilføje logbeskeder på informationsniveau, er NS_LOG_INFO. Lad os tilføje en besked (lige før vi begynder at oprette noder), der fortæller dig, at scriptet er i gang med at oprette topologi ("Creating Topology"). Dette gøres i det følgende kodefragment,
Åbn scratch/myfirst.cc i din yndlingseditor og tilføj linjen,
NS_LOG_INFO ("Creating Topology");
lige før linjerne,

NodeContainer nodes;
nodes.Create (2);

Nu skal du kompilere scriptet med waf, og nulstil NS_LOG-variablen for at deaktivere logningsstrømmen, vi aktiverede tidligere:

$ ./waf
$ export NS_LOG=
Nu, hvis du kører scriptet,
$ ./waf --run scratch/myfirst

vil du ikke se den nye besked, da den tilknyttede logningskomponent (FirstScriptExample) ikke blev aktiveret. For at se din besked skal du aktivere logningskomponenten FirstScriptExample med et niveau, der ikke er lavere end NS_LOG_INFO. Hvis du bare vil se dette specifikke logningsniveau, kan du aktivere det sådan,

$ export NS_LOG=FirstScriptExample=info

Hvis du kører scriptet nu, vil du se den nye besked «Creating Topology»

Waf: Går ind i mappen `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build`
Waf: Forlader mappen `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build`
'build' afsluttet med succes (0.404s)
Oprettelse af topologi
Sendt 1024 byte til 10.1.1.2
Modtaget 1024 byte fra 10.1.1.1
Modtaget 1024 byte fra 10.1.1.2

5.2 Brug af kommandolinje-argumenter

5.2.1 Omskrivning af standardattributværdier

En anden måde at ændre adfærden af ns-3 scripts uden at redigere og bygge er ved at bruge kommandolinjeargumenter. Vi giver et mekanisme til at parsetekster kommandolinjeargumenter og automatisk oprette lokale og globale variabler baseret på resultaterne.

Det første skridt i at bruge systemet med kommandolinjeargumenter er at erklære en kommandolinjeparsesystem. Det er ret enkelt at gøre (i dit hovedprogram), som i følgende kode:

int
main (int argc, char *argv[])
{
...
CommandLine cmd;
cmd.Parse (argc, argv);
...
}

Dette enkle to-linjers kodefragment er faktisk meget nyttigt i sig selv. Det åbner døren til den globale ns-3 variabel og attributsystemet. Lad os tilføje to linjer kode i starten af skriptets hovedfunktion. scratch/myfirst.cc. Når vi går videre, kompilerer vi scriptet og kører det, når vi starter, gør vi en forespørgsel om hjælp på følgende måde:

$ ./waf --run "scratch/myfirst --PrintHelp"

Denne kommando beder Waf om at køre scriptet scratch/myfirst og give det et kommandolinjeargument --PrintHelp. Anførselstegnene er nødvendige for at vise, hvilken applikation argumentet er tiltænkt. Kommando-lineparsesystemet vil opdage argumentet --PrintHelp og give et svar,

Waf: Går ind i mappen `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build`
Waf: Forlader mappen `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build`
'build' afsluttet med succes (0.413s)
TcpL4Protocol:TcpStateMachine()
CommandLine:HandleArgument(): Håndter arg navn=PrintHelp værdi=
--PrintHelp: Vis denne hjælpebesked.
--PrintGroups: Vis listen over grupper.
--PrintTypeIds: Vis alle TypeIds.
--PrintGroup=[gruppe]: Vis alle TypeIds i gruppen.
--PrintAttributes=[typeid]: Vis alle attributter fra typeid.
--PrintGlobals: Vis listen over globale.

Lad os nu se på muligheden --PrintAttributes. Vi har allerede nævnt ns-3- attributsystemet, da vi studerede scriptet first.cc. Vi så følgende kode:

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

og nævnte, at DataRate faktisk er en attribut af PointToPointNetDevice.Lad os anvende kommandolinjeparsesystemet for at se attributterne. PointToPointNetDevice.Hjælpelisten siger, at vi skal give TypeId. Dette er navnet på klassen, til hvilken de relevante attributter hører. I vores tilfælde bliver det ns3::PointToPointNetDevice. Lad os fortsætte, indtast

$ ./waf --run "scratch/myfirst --PrintAttributes=ns3::PointToPointNetDevice"

Systemet vil udskrive alle attributter for denne type netværksenhed. Du vil se, at der blandt attributterne er

--ns3::PointToPointNetDevice::DataRate=[32768bps]:
Den standard datahastighed for punkt-til-punkt-forbindelser

Dette er den standardværdi, der vil blive brugt i systemet ved oprettelse af et objekt PointToPointNetDevice.. Vi vil overskrive denne standardværdi med parameteren Attribut i PointToPointHelper ovenfor. Lad os bruge standardværdierne for punkt-til-punkt-enheder og kanaler. For at gøre dette vil vi fjerne kald til SetDeviceAttribute og SetChannelAttribute af myfirst.cc, som vi har i den rene mappe.

Dit script skal nu blot erklære PointToPointHelper og ikke udføre nogen installationsoperationer, som vist i eksemplet nedenfor,

...
NodeContainer nodes;
nodes.Create (2);
PointToPointHelper pointToPoint;
NetDeviceContainer devices;
devices = pointToPoint.Install (nodes);
...

Fortsæt og opret et nyt script med Waf (./waf) og lad os gå tilbage og inkludere nogle logning fra UDP echo serverapplikationen samt inkludere tidspræfiks.

$ export 'NS_LOG=UdpEchoServerApplication=level_all|prefix_time'

Hvis du kører scriptet, bør du se følgende output:

Waf: Indtager mappe `\/home\/craigdo\/repos\/ns-3-allinone\/ns-3-dev\/build'\nWaf: Forlader mappe `\/home\/craigdo\/repos\/ns-3-allinone\/ns-3-dev\/build'\n'build' afsluttet succesfuldt (0.405s)\n0s UdpEchoServerApplication:UdpEchoServer()\n1s UdpEchoServerApplication:StartApplication()\nSendte 1024 byte til 10.1.1.2\n2.25732s Modtaget 1024 byte fra 10.1.1.1\n2.25732s Echoing packet\nModtaget 1024 byte fra 10.1.1.2\n10s UdpEchoServerApplication:StopApplication()\nUdpEchoServerApplication:DoDispose()\nUdpEchoServerApplication:~UdpEchoServer()

Lad os huske, at sidste gang vi kiggede på simuleringstiden, var tidspunktet for modtagelsen af pakken af echo-serveren 2.00369 sekunder.

2.00369s UdpEchoServerApplication:HandleRead(): Modtaget 1024 byte fra 10.1.1.1

Nu modtager den pakken på 2.25732 sekunder. Dette er fordi vi blot har nulstillet datahastigheden for PointToPointNetDevice fra fem megabit pr. sekund til standardværdien på 32768 bit pr. sekund. Hvis vi havde angivet den nye DataRate via kommandolinjen, kunne vi igen have fremskyndet vores simulering. Vi gør dette som følger, ifølge den formel, som det relevante hjælpeelement antyder:

$ ./waf --run "scratch/myfirst --ns3::PointToPointNetDevice::DataRate=5Mbps"

Som standard vil værdien af DataRate-attributten vende tilbage til fem megabit per sekund. Er du overrasket over resultatet? Det viser sig, at for at genskabe den oprindelige adfærd i scriptet skal vi også indstille kanalforsinkelsen til lys hastighed. Vi kan bede kommandolinjesystemet om at udskrive kanalens attributter, ligesom vi gjorde for netværksenheden:

$ .\/waf --run "scratch\/myfirst --PrintAttributes=ns3::PointToPointChannel"

Vi vil opdage, at attribute forsinkelsen for kanalen er indstillet som følger:

--ns3::PointToPointChannel::Delay=[0ns]:
Transmission forsinkelse gennem kanalen

Derefter kan vi gennem kommandolinjesystemet indstille begge disse standardværdier:

$ .\/waf --run "scratch\/myfirst
--ns3::PointToPointNetDevice::DataRate=5Mbps
--ns3::PointToPointChannel::Delay=2ms"

I dette tilfælde genskaber vi den tid, vi havde, da vi eksplicit indstillede DataRate og Delay i scriptet:

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.417s)
0s UdpEchoServerApplication:UdpEchoServer()
1s UdpEchoServerApplication:StartApplication()
Sent 1024 bytes to 10.1.1.2
2.00369s Received 1024 bytes from 10.1.1.1
2.00369s Echoing packet
Received 1024 bytes from 10.1.1.2
10s UdpEchoServerApplication:StopApplication()
UdpEchoServerApplication:DoDispose()
UdpEchoServerApplication:~UdpEchoServer()

Bemærk, at pakken igen blev modtaget af serveren efter 2,00369 sekunder. Vi kunne faktisk indstille hvilken som helst af de brugte attributter i scenariet på denne måde. Især kunne vi indstille værdier forskellig fra en for attributten MaxPackets. UdpEchoClient.

Hvordan ville du bruge dette? Prøv det. Husk, at du skal kommentere det sted, hvor vi overskriver standardattributværdien og eksplicit sætter MaxPackets i scriptet. Derefter skal du genkompilere scriptet. Du kan også bruge kommandolinjen til at få hjælp til syntaksen for at indstille en ny standardattributværdi. Når du har forstået dette, kan du styre mængden af pakker, der vises på kommandolinjen. Da vi er studious, skal vores kommandolinje se nogenlunde sådan ud:

$ .\/waf --run "scratch\/myfirst
--ns3::PointToPointNetDevice::DataRate=5Mbps
--ns3::PointToPointChannel::Delay=2ms
--ns3::UdpEchoClient::MaxPackets=2"

Det naturlige spørgsmål, der opstår her, er, hvordan man kan finde ud af, at alle disse attributter eksisterer. Igen har kommandolinjesystemet en hjælpefunktion til dette. Hvis vi anmoder om hjælp fra kommandolinjen, bør vi se:

$ ./waf --run "scratch/myfirst --PrintHelp"
myfirst [Program Arguments] [General Arguments]
General Arguments:
--PrintGlobals: Print the list of globals.
--PrintGroups: Print the list of groups.
--PrintGroup=[group]: Print all TypeIds of group.
--PrintTypeIds: Print all TypeIds.
--PrintAttributes=[typeid]: Print all attributes of typeid.
--PrintHelp: Print this help message.

Hvis du vælger argumentet "PrintGroups", bør du se en liste over alle registrerede grupper TypeId. Gruppenavne svarer til modulnavne i den oprindelige mappe (dog med stort forbogstav). Udskrift af alle oplysninger på én gang vil være for omfattende, så der findes et ekstra filter til at udskrive oplysninger efter grupper. Så, når vi igen fokuserer på modulet "point-to-point":

./waf --run "scratch/myfirst --PrintGroup=PointToPoint"
TypeIds i gruppe PointToPoint:
ns3::PointToPointChannel
ns3::PointToPointNetDevice
ns3::PointToPointRemoteChannel
ns3::PppHeader

Her kan du finde de tilgængelige TypeId-navne for at søge efter attributter, for eksempel i
--PrintAttributes = ns3::PointToPointChannel, som vist ovenfor.

En anden måde at lære om attributter på er gennem Doxygen ns-3. Der er en side, der opregner alle registrerede attributter i simulatoren.

5.2.2 Fang dine egne kommandoer

Du kan også tilføje dine egne hooks gennem kommandolinjesystemet. Dette gøres ret nemt med command-line parser metoden AddValue.
Lad os bruge denne mulighed for at angive antallet af pakker, der skal vises, på en helt anden måde. Lad os tilføje en lokal variabel ved navn nPackets til funktionen main. Vi sætter den til en, så den matcher vores tidligere standardadfærd. For at lade kommandolinjeparseren ændre denne værdi, skal vi fange den værdi i parseren. Det gør vi ved at tilføje et kald AddValue. Gå til og ændr scriptet scratch/myfirst.cc så det starter med følgende kode,

int
main (int argc, char *argv[])
{
uint32_t nPackets = 1;
CommandLine cmd;
cmd.AddValue("nPackets", "Antal pakker til at echo", nPackets);
cmd.Parse (argc, argv);
...

Rul ned til det punkt i scriptet, hvor vi sætter attributten MaxPackets og ændre den, så den er indstillet til variablen nPackets i stedet for konstanten 1, som vist nedenfor.

echoClient.SetAttribute ("MaxPackets", UintegerValue (nPackets));

Nu, hvis du kører scriptet og indsætter argumentet --PrintHelp, bør du se den nye brugerargument, der er angivet på hjælpeskærmen. Skriv,

$ ./waf --run "scratch/myfirst --PrintHelp"
Waf: Indtræder 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' færdiggjort med succes (0.403s)
--PrintHelp: Udskriv denne hjælp meddelelse.
--PrintGroups: Udskriv listen over grupper.
--PrintTypeIds: Udskriv alle TypeIds.
--PrintGroup=[group]: Udskriv alle TypeIds for gruppen.
--PrintAttributes=[typeid]: Udskriv alle attributter for typeid.
--PrintGlobals: Udskriv listen over globale.
Brugerargumenter:
--nPackets: Antal pakker der skal ekkoes

Hvis du ønsker at ændre antallet af sendte pakker, kan du gøre det ved at angive argumentet -nPackets i kommandolinjen,

$ ./waf --run "scratch/myfirst --nPackets=2"

Nu skal du kunne se

Waf: Indtræder 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' færdiggjort med succes (0.404s)
0s UdpEchoServerApplication:UdpEchoServer()
1s UdpEchoServerApplication:StartApplication()
Sendt 1024 bytes til 10.1.1.2
2.25732s Modtaget 1024 bytes fra 10.1.1.1
2.25732s Ekko pakke
Modtaget 1024 bytes fra 10.1.1.2
Sendt 1024 bytes til 10.1.1.2
3.25732s Modtaget 1024 bytes fra 10.1.1.1
3.25732s Ekko pakke
Modtaget 1024 bytes fra 10.1.1.2
10s UdpEchoServerApplication:StopApplication()
UdpEchoServerApplication:DoDispose()
UdpEchoServerApplication:~UdpEchoServer()

Du har nu sendt to pakker. Ret enkelt, ikke?
Du kan se, at som bruger af ns-3 kan du bruge kommandolinjeargument systemet til at kontrollere globale værdier og attributter. Hvis du er model forfatter, kan du tilføje nye attributter til dine objekter, og de vil automatisk være tilgængelige for konfiguration af dine brugere via kommandolinjesystemet. Hvis du er scriptforfatter, kan du tilføje nye variabler til dine scripts og problemfrit tilslutte dem til kommandolinjesystemet.

5.3 Brug af sporingssystemet

Formålet med modellering er at skabe output til videre undersøgelse, og ns-3's sporingssystem er den primære mekanisme til dette. Da ns-3 er et C++ program, kan der bruges standardmetoder til at generere output i C++ programmer:

#include <iostream>
...
int main ()
{
...
std::cout << "The value of x is " << x << std::endl;
...
}

Du kan endda bruge logningsmodulet til at tilføje lidt struktur til din løsning. Der er kendt mange problemer forårsaget af en sådan tilgang, og derfor har vi givet et fælles subsystem til at spore begivenheder for at løse disse problemer.

De primære mål for ns-3's sporingssystem:

  • For grundlæggende opgaver skal sporingssystemet tillade brugeren at generere standardsporingsoplysninger for populære kilder og vælge de objekter, der genererer sporingen;

  • Intermediære brugere skal have mulighed for at udvide sporingssystemet for at ændre det genererede outputformat eller for at indsætte nye sporingskilder uden at modificere simulatorens kerne;

  • Erfarne brugere kan modificere simulatorens kerne for at tilføje nye sporingskilder og modtagere. Sporingssystemet ns-3 er bygget på principperne om uafhængige sporingskilder og modtagere samt et samlet mekanisme til at forbinde kilderne til forbrugerne.

Sporingssystemet ns-3 er bygget på principperne om uafhængige sporingskilder og modtagere samt en samlet mekanisme til at forbinde kilderne til modtagere. Sporingskilder er objekter, der kan signalere om begivenheder, der sker i simuleringen og give adgang til interessante grundlæggende data. For eksempel kan en sporingskilde indikere, hvornår en netværksenhed har modtaget en pakke og give adgang til indholdet af pakken for interesserede sporingsmodtagere.

Sporingskilder er i sig selv ubrugelige, hvis de ikke er 'forbundet' med andre dele af koden, som faktisk gør noget nyttigt med informationen leveret af modtageren. Sporere er forbrugere af de begivenheder og data, der leveres af sporingskilderne. For eksempel kan man oprette en sporingsmodtager, der (ved tilslutning til sporingskilden fra det tidligere eksempel) udskriver interessante dele af den modtagne pakke.

En rimelig grund til en sådan klar opdeling er at give brugerne mulighed for at tilslutte nye typer modtagere til eksisterende sporingskilder uden behov for at redigere og recompilere simulatorens kerne. På denne måde kan brugeren i det ovenstående eksempel definere en ny sporingsenhed i sit script og tilslutte den til en eksisterende sporingskilde defineret i simuleringskernen, blot ved at redigere det brugerdefinerede script.

I denne vejledning vil vi gennemgå nogle foruddefinerede kilder og modtagere og vise, hvordan de kan konfigureres med minimal brugerindsats. Se ns-3-dokumentationen eller instruktionerne for avanceret konfiguration af sporing, inklusive udvidelse af sporingsnavnerum og oprettelse af nye sporingskilder.

5.3.1 ASCII Sporings

ns-3 tilbyder hjælpefunktionalitet, der giver et lavniveau sporing system, så du kan få hjælp til detaljerne, når du konfigurerer enkle pakkesporinger. Hvis du aktiverer denne funktion, vil du se output i ASCII-filer. For dem, der er bekendt med ns-2-udgangen, er denne type sporing tilsvarende out.tr, som er genereret af mange scripts.

Lad os komme til sagen og tilføje nogle ASCII sporingsresultater til vores script scratch/myfirst.cc. Lige før kaldet til Simulator::Run(), tilføj følgende kodelinjer:
AsciiTraceHelper ascii;

pointToPoint.EnableAsciiAll(ascii.CreateFileStream("myfirst.tr"));

Som i mange andre idiomer i ns-3 bruger denne kode et hjælpeobjekt til at oprette ASCII-sporinger. Den anden linje indeholder to indlejrede metodeopkald. Metoden "indeni" CreateFileStream() bruger idiomet for en anonymt objekt til at oprette et filstrømobjekt på stakken (uden navn) og videregiver det til det kaldende metode. I fremtiden vil vi dykke dybere ned i dette emne, men alt hvad du behøver at vide på dette stadium, er at du opretter et objekt, der repræsenterer en fil med navnet myfirst.tr og videregiver det til ns-3. Vi overlader ns-3 ansvaret for det oprettede objekt i hele dets livscyklus, hvor problemer relateret til de mindre kendte (intentionelle) begrænsninger, der er forbundet med kopi-constructors for stream objekter i C++, bliver løst.

Det eksterne opkald EnableAsciiAll() informerer hjælperen om, at du ønsker at inkludere ASCII-sporing i din simulation for alle point-to-point enhedstilknytninger, og at du ønsker, at (de angivne) sporingsmodtagere skal registrere information om pakkeoverførsler i ASCII-format.

For dem, der er bekendt med ns-2, er de overvågede begivenheder lig med de kendte sporingspunkter, der logger begivenhederne "+", "-", "d" og "r".
Nu kan du samle scriptet og køre det fra kommandolinjen:

$ ./waf --run scratch/myfirst

Hvor mange gange før har du set adskillige meddelelser fra Waf og derefter "‘build’ finished successfully" med nogle meddelelser fra det kørende program.

Når programmet kører, opretter det en fil med navnet myfirst.tr. På grund af programmets særlige funktioner Waf, oprettes filen som standard ikke i den lokale mappe, men i roden af lageret. Hvis du ønsker at ændre stien, hvor sporene gemmes, kan du angive det til Waf ved hjælp af parameteren --cwd. Da vi ikke gjorde det, skal vi navigere til rodmappen af vores lager for at se ASCII-sporfilen myfirst.tr i din foretrukne editor.

Parsing af ASCII sporing

Der er meget information i en ret kompakt form, men det første, du skal bemærke, er, at filen består af separate linjer. Dette vil være tydeligt, hvis du udvider visningsvinduet.

Hver linje i filen svarer til en sporingsbegivenhed. I dette tilfælde sporer vi begivenheder i transmissionskøen, som findes i hver point-to-point netværksenhed i simuleringen. Transmissionskøen er den kø, som hver pakke skal passere for point-to-point-kanalen. Vær opmærksom på, at hver linje i sporingsfilen begynder med et enkelt tegn (og har et mellemrum efter sig). Dette tegn vil have følgende betydning:

+: der skete en enqueue-operation i enhedens kø;
-: der skete en dequeue-operation i enhedens kø;
d: pakken blev droppet, normalt fordi køen var fuld;
r: pakken blev modtaget af netværksenheden.

Lad os se nærmere på den første linje i sporingsfilen. Jeg vil opdele den i sektioner (med indrykning for klarhed) og nummerere linjerne til venstre:

0 +
1 2
2 /NodeList/0/DeviceList/0/$ns3::PointToPointNetDevice/TxQueue/Enqueue
3 ns3::PppHeader (
4   Point-to-Point Protocol: IP (0x0021))
6   ns3::Ipv4Header (
7     tos 0x0 ttl 64 id 0 protocol 17 offset 0 flags [none]
8     length: 1052 10.1.1.1 > 10.1.1.2)
9     ns3::UdpHeader (
10      length: 1032 49153 > 9)
11      Payload (size=1024)

Den første del af denne udvidede sporingsbegivenhed (linje 0) er operationen. Vi har her symbolet +, som svarer til enqueue-operationen for transmission. Den anden del (linje 1) er simulations tiden, udtrykt i sekunder. Du kan huske, at vi bad om UdpEchoClientApplication Starter transmission of packets in two seconds. Here we can see confirmation that this is indeed happening.

In the next section of the trace example (from line 2), it shows which trace source generated this event (the trace namespace is indicated). You can think of the trace namespace much like a file system namespace. The root of the namespace is NodeList. This corresponds to the container primarily managed in the ns-3 code. It contains all the nodes created in the script. Just like a file system can have directories at the root, we NodeList can have many nodes. Thus, the line /NodeList/0 refers to the zero node in NodeList, which we often understand as "node 0". Each node has a list of devices that have been installed. This list is located next in the namespace. You can see that this trace event originates from DeviceList/0, which is the zero device installed in the node.

The next substring, $ns3::PointToPointNetDevice, indicates which device is in the zero position: from the list of devices of the zero node. Recall that the operation +, located on line 0, meant that an element was added to the device's transmission queue. This is reflected in the last segments of the "trace path": TxQueue/Enqueue.

The remaining sections of the trace should be quite intuitive. Lines 3-4 indicate that the packet is encapsulated in the point-to-point protocol. Lines 5-7 show that the packet has an IP4 version header and originated from the IP address 10.1.1.1 and is destined for 10.1.1.2. Lines 8-9 show that this packet has a UDP header and finally, line 10 shows that the payload is the expected 1024 bytes.

The next line in the trace file shows that the same packet was extracted from the transmission queue on the same node.

The third line in the trace file shows that the packet was received by the network device on the node with the echo server. I reproduced this event below.

0 r
1 2.25732
2 /NodeList/1/DeviceList/0/$ns3::PointToPointNetDevice/MacRx
3   ns3::Ipv4Header (
4     tos 0x0 ttl 64 id 0 protocol 17 offset 0 flags [none]
5     length: 1052 10.1.1.1 > 10.1.1.2)
6     ns3::UdpHeader (
7       length: 1032 49153 > 9)
8       Payload (size=1024)

Bemærk, at sporingsoperationen nu er r, og simuleringstiden er øget til 2,25732 sekunder. Hvis du har fulgt instruktionerne i vejledningen nøje, betyder det, at du har efterladt DataRate for netværksenhederne og kanalens forsinkelse på deres standardværdier. Denne tid burde være velkendt, da du allerede har set den i det forrige afsnit.

NAMESPACE OPKALDETS KILDE SPORING (linje 2) er blevet ændret for at angive, at denne begivenhed stammer fra knude 1 (/NodeList/1) и пакет принят источником трассировки (/MacRx). Det skal være ret nemt for dig at spore pakkens bevægelse gennem topologien ved at se på de resterende spor i filen.

5.3.2 PCAP Sporing

ns-3 enhedsassistenterne kan også bruges til at oprette sporingsfiler i .pcap format. Akronymet pcap (normalt skrevet med små bogstaver) står for pakkeopsamling og er faktisk et API, der inkluderer definitionen af filformatet .pcap. Det mest populære program, der kan læse og vise dette format, er Wireshark (tidligere kendt som Ethereal). Der er dog mange analyseværktøjer til trafikspor, der bruger dette pakkeforum. Vi anbefaler brugerne at anvende en række værktøjer, der er tilgængelige til analyse af pcap spor. I denne vejledning vil vi fokusere på at se pcap spor ved hjælp af tcpdump.

Aktivering af pcap-sporing udføres med én kode linje.

pointToPoint.EnablePcapAll("myfirst");

Indsæt denne kode linje efter ASCII sporingskoden, som vi lige har tilføjet i scratch/myfirst.cc. Bemærk, at vi kun har givet strengen 'myfirst' og ikke 'myfirst.pcap' eller lignende. Dette er fordi parameteren er et præfiks og ikke et komplet filnavn. Under simuleringen vil assistenten faktisk oprette en sporingsfil for hver point-to-point enhed. Filnavnene vil blive bygget ved hjælp af præfiks, knude nummer, enhed nummer og suffikset 'pcap».

I vores eksempel vil vi i sidste ende se filer med navne 'myfirst-0-0.pcap" og "myfirst-1-0.pcap', som er pcap spor for knude 0-enhed 0 og knude 1-enhed 0 henholdsvis. Når du har tilføjet kode linjen for at aktivere pcap-sporing, kan du køre scriptet på normal måde:

$ ./waf --run scratch/myfirst

Hvis du ser i roden af dit distributionsbibliotek, bør du se tre filer: ASCII sporingsfilen, myfirst.trsom vi tidligere har gennemgået, og filerne myfirst-0-0.pcap og myfirst-1-0.pcap — nye pcap-filer, som vi lige har genereret.

Læsning af output med tcpdump

I øjeblikket er det nemmest at bruge tcpdump til at se pcap-filer.

$ tcpdump -nn -tt -r myfirst-0-0.pcap
læser fra fil myfirst-0-0.pcap, linktype PPP (PPP)
2.000000 IP 10.1.1.1.49153 > 10.1.1.2.9: UDP, længde 1024
2.514648 IP 10.1.1.2.9 > 10.1.1.1.49153: UDP, længde 1024
tcpdump -nn -tt -r myfirst-1-0.pcap
læser fra fil myfirst-1-0.pcap, linktype PPP (PPP)
2.257324 IP 10.1.1.1.49153 > 10.1.1.2.9: UDP, længde 1024
2.257324 IP 10.1.1.2.9 > 10.1.1.1.49153: UDP, længde 1024

I dumpen myfirst-0-0.pcap (klientudstyr) kan du se, at echo-pakken sendes efter 2 sekunders simulering. Hvis du ser på den anden dump (myfirst-1-0.pcap), vil du se, at pakken modtages på tidspunktet 2,257324 sekunder. Du vil se i den anden dump, at pakken returneres på tidspunktet 2.257324 sekunder, og endelig at pakken blev modtaget af klienten tilbage i den første dump på tidspunktet 2.514648 sekunder.

Læsning af output med Wireshark

Hvis du ikke er bekendt med Wireshark, er der et websted, hvor du kan downloade programmer og dokumentation: http://www.wireshark.org/. Wireshark — det er en grafisk brugergrænseflade, som kan bruges til at vise disse sporingsfiler. Hvis du har Wireshark, kan du åbne en hvilken som helst af sporingsfilerne og vise indholdet, som om du havde indfanget pakker ved at bruge en pakkeanalysator.

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