Učebnice simulátoru sítě ns-3. Kapitola 4

Učebnice simulátoru sítě ns-3. Kapitola 4
kapitoly 1,2
kapitola 3

4 Přehled konceptu
4.1 Klíčové abstrakce
4.1.1 Uzlu (Node)
4.1.2 Aplikace (Application)
4.1.3 Kanál (Channel)
4.1.4 Síťové zařízení (Net Device)
4.1.5 Topologické pomocníky
4.2 První skript ns-3
4.2.1 Základní kód (Boilerplate)
4.2.2 Připojitelné moduly
4.2.3 Prostor názvů ns3
4.2.4 Žurnálování
4.2.5 Hlavní funkce
4.2.6 Použití topologických pomocníků
4.2.7 Použití aplikace
4.2.8 Simulátor
4.2.9 Sestavení vašeho scénáře
4.3 Zdrojový kód ns-3

Kapitola 4

Přehled konceptu

První věc, kterou musíme udělat před tím, než začneme studovat nebo psát kód ns-3, je vysvětlit několik základních pojmů a abstrakcí v systému. Mnoho z toho se může některým zdát zřejmé, ale doporučujeme věnovat čas čtení této části, abyste se ujistili, že začínáte na pevných základech.

4.1 Klíčové abstrakce

V této části se podíváme na některé termíny, které se běžně používají v síti, ale mají specifický význam v ns-3.

4.1.1 Uzlu (Node)

V internetovém žargonu se počítačové zařízení připojené k síti nazývá hostem nebo někdy koncovým systémem. Vzhledem k tomu, že ns-3 je simulátor sítě, nikoli simulátor Internetu, záměrně se vyhýbáme termínu host, protože je úzce spojen s Internetem a jeho protokoly. Místo toho používáme obecnější termín, který se také používá v jiných simulátorech, a který má svůj původ v teorii grafů — uzel (node).

V ns-3 je základní abstrakce výpočetního zařízení nazývána uzlem. Tato abstrakce je v C++ představena třídou Node. Třída NodeNode (uzel) poskytuje metody pro správu reprezentací výpočetních zařízení v simulacích.

Musíte rozumět Node jako počítači, ke kterému přidáte funkčnost. Přidáte mu takové věci, jako jsou aplikace, zásobníky protokolů a periferní karty s ovladači, které umožní počítači vykonávat užitečnou práci. Používáme stejný základní model v ns-3.

4.1.2 Aplikace (Application)

Obecně se počítačový software dělí do dvou širokých tříd. Systémový software organizuje různé počítačové zdroje, jako jsou paměť, procesorový cyklus, disk, síť atd., podle určité výpočetní modelu. Systémový software obvykle nepoužívá tyto zdroje k vykonávání úloh, které přinášejí přímý užitek uživateli. Uživatel obvykle spouští aplikaci, aby dosáhl určitého cíle, která získává a využívá zdroje řízené systémovým softwarem.

Často se hranice mezi systémovým a aplikačním softwarem určuje změnou úrovně oprávnění, která nastává při přerušení operačního systému. V ns-3 neexistuje skutečná koncepce operačního systému a tudíž nejsou pojmy úrovně oprávnění nebo systémové volání. Máme však pojem aplikace. Tak jako v "skutečném světě" pro plnění úloh pracují softwarové aplikace na počítačích, aplikace ns-3 pracují na uzlech ns-3 pro řízení simulací v simulovaném světě.

V ns-3 je základní abstrakcí pro uživatelský program, který generuje nějakou aktivitu pro modelování, aplikace. Tato abstrakce je v C++ představena třídou Application (aplikace). Třída Application poskytuje metody pro správu v simulacích zobrazením naší verze aplikací na úrovni uživatele. Od vývojářů se očekává, že pro vytváření nových aplikací budou specializovat třídu Application z pohledu objektově orientovaného programování. V této příručce budeme používat specializace třídy Application, které se nazývají UdpEchoClientApplication a UdpEchoServerApplication. Jak se dalo očekávat, tyto aplikace tvoří soubor klientských/serverových aplikací používaných pro generování a echo simulaci síťových paketů.

4.1.3 Kanál (Channel)

V reálném světě můžete připojit počítač k síti. Často se prostředí, přes která se v těchto sítích přenášejí data, nazývá kanály. Když připojíte Ethernetový kabel do zásuvky na stěně, připojujete počítač k komunikačnímu kanálu Ethernet. Ve zsimulovaném světě ns-3 je uzel připojen k objektu, který představuje komunikační kanál. Hlavní abstrakce komunikační podsítě se zde nazývá kanál a je představena třídou Channel (kanál) v C++.

Třída ChannelChannel poskytuje metody pro řízení interakce objektů podsítě a připojení uzlů k nim. Kanály mohou být také specializovány vývojáři z hlediska objektově orientovaného programování. Specializace kanálu může modelovat něco jednoduchého jako drát. Specializovaný kanál může také modelovat složité objekty, jako je velký Ethernetový switch nebo trojrozměrný prostor plný překážek v případě bezdrátových sítí.

V této příručce budeme používat specializované verze kanálu nazývané CsmaChannelCsmaChannel, PointToPointChannelPointToPointChannel a WifiChannelWifiChannel. CsmaChannel, například, modeluje verzi komunikační podsítě, která implementuje komunikační prostředí s vícestupňovým přístupem s kontrolou nosné. To nám poskytuje funkčnost podobnou Ethernetu.

4.1.4 Síťové zařízení (Net Device)

Dříve, pokud jste chtěli připojit počítač k síti, museli jste zakoupit určitou síťovou kabeláž a hardwarové zařízení, nazývané (v terminologii PC) periferie, kterou bylo nutné nainstalovat do počítače. Pokud na periferii byly implementovány některé síťové funkce, nazývaly se síťovými rozhraními nebo síťovými kartami. Dnes většina počítačů dodává s integrovaným hardwarem síťového rozhraní, a uživatelé je nevidí jako samostatná zařízení.

Síťová karta nebude fungovat bez programového ovladače, který řídí její hardware. V Unixu (nebo Linuxu) je část periferního hardwaru klasifikována jako zařízení. Zařízení jsou řízena pomocí ovladačů zařízení (device drivers) a síťová zařízení (NIC) jsou řízena pomocí ovladačů síťových zařízení (network device drivers) a mají souhrnné označení síťová zařízení (net devices). V Unix a Linux se k síťovým zařízením přistupuje podle názvů, například eth0.

V ns-3 abstrakce síťového zařízení zahrnuje jak programový ovladač, tak simulované vybavení. Při simulaci je síťové zařízení "nainstalováno" v uzlu, aby umožnilo spojení s dalšími uzly přes kanály. Stejně jako v reálném počítači může být uzel připojen k několika kanálům prostřednictvím několika zařízení. NetDevices.

Síťová abstrakce zařízení je reprezentována v C++ třídou NetDevice. Třída NetDevice poskytuje metody pro správu spojení s objekty Node a Channel; a mohou být specializovány vývojáři z hlediska objektově orientovaného programování. V této příručce budeme používat několik specializovaných verzí NetDevice nazvaných CsmaNetDevice, PointToPointNetDevice a WifiNetDevice. Stejně jako ethernetový síťový adaptér určený k práci se síťí Ethernet, CsmaNetDevice je určen k práci s CsmaChannel, PointToPointNetDevice je určen k práci s PointToPointChannel, a WifiNetDevice — určen k práci s WifiChannel.

4.1.5 Topologické pomocníky

V reálné síti najdete hostitelské počítače s přidanými (nebo integrovanými) síťovými kartami. V ns-3 bychom řekli, že uvidíte uzly s připojenými NetDevices. Ve velké simulované síti bude třeba uspořádat spojení mezi mnoha objekty. Node, NetDevice a Channel.

Jelikož připojení NetDevices k uzlům, NetDevices k kanálům, přiřazení IP adres a další v ns-3 představuje běžný úkol, abychom to udělali co nejjednodušeji, poskytujeme takzvané topologické pomocníky. Například k vytvoření NetDevice je třeba provést řadu operací jádra ns-3, přidat MAC adresu, nastavit toto síťové zařízení do Node, nakonfigurovat protokolový zásobník uzlu a poté připojit NetDevice k Channel. Ještě více operací bude zapotřebí pro připojení několika zařízení k vícestopým kanálům a následně spojení jednotlivých sítí do sjednocené sítě (Internetworks). Poskytujeme pomocné objekty topologie, které pro vaše pohodlí kombinují tyto četné operace do snadno použitelného modelu.

4.2 První skript ns-3

Pokud jste nainstalovali systém, jak bylo navrženo výše, budete mít verzi ns-3 v adresáři s názvem repos ve vaší domácí adresáři. Přejděte do adresáře release

Pokud nemáte takový adresář, znamená to, že jste při sestavení vydání ns‑3 neuvedli výstupní adresář, sestavte to takto:
$ ./waf configure --build-profile=release --out=build/release,
$ ./waf build

tam byste měli vidět strukturu adresáře podobnou následující:

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

Přejděte do adresáře examples/tutorial. Měli byste tam vidět soubor s názvem first.cc. To je skript, který vytvoří jednoduché bod-nejednoduché spojení mezi dvěma uzly a přenese jeden paket mezi uzly. Podívejme se na tento skript řádek po řádku, otevřeme first.cc ve vašem oblíbeném editoru.

4.2.1 Základní kód (Boilerplate)
První řádek v souboru je řádek režimu editoru emacs. Říká emacsu o konvencích formátování (styl kódování), které budeme používat v našem zdrojovém kódu.

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

To je vždy poměrně sporná otázka, takže bychom měli uvést na pravou míru a hned ji ze stolu odstranit. Projekt ns‑3, stejně jako většina velkých projektů, přijal styl kódování, kterému musí odpovídat veškerý poskytnutý kód. Pokud chcete přidat svůj kód do projektu, budete se nakonec muset řídit standardem kódování ns‑3, jak je popsáno v souboru doc/codingstd.txt nebo uvedeném na webové stránce projektu: https://www.nsnam.org/develop/contributing-code/coding-style/.

Doporučujeme vám zvyknout si na vzhled kódu ns‑3 a aplikovat tento standard vždy, když pracujete s naším kódem. Celý tým vývojářů a přispěvatelů s tím souhlasil po trochu brblání. Řádek režimu emacs, uvedený výše, usnadňuje správné formátování, pokud používáte editor emacs.

Simulátor ns‑3 je licencován podle GNU General Public License. Uvidíte odpovídající právní hlavičku GNU v každém souboru distribuce ns‑3. Často můžete vidět oznámení o autorských právech pro jednu z zapojených institucí v projektu ns‑3 nad textem GPL a autora, jak je uvedeno níže.

/* 
* 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 Připojitelné moduly

Samotný kód začíná sérií příkazů pro zahrnutí (include).

#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"

Aby pomóc naszym użytkownikom zaawansowanych skryptów poradzić sobie z dużą liczbą plików nagłówkowych w systemie, grupujemy je zgodnie z ich zastosowaniem w większe moduły. Oferujemy jeden plik nagłówkowy, który rekurencyjnie załadowuje wszystkie pliki nagłówkowe używane w danym module. Zamiast szukać, który dokładnie nagłówek jest potrzebny i być może otrzymać poprawną listę zależności, dajemy Ci możliwość ładowania grupy plików z dużą precyzją. To nie jest najefektywniejsze podejście, ale z pewnością ułatwia pisanie skryptów.

Każdy z dołączanych plików ns-3 umieszczany jest w katalogu o nazwie ns3 (podkatalog kompilacji), aby podczas procesu kompilacji uniknąć konfliktów nazw plików. Plik ns3/core-module.h odpowiada modułowi ns-3, który znajdziesz w katalogu src/core w zainstalowanej przez Ciebie wersji. W wylistowaniu tego katalogu znajdziesz dużą liczbę plików nagłówkowych. Gdy przeprowadzasz kompilację, Waf umieszcza publiczne pliki nagłówkowe w katalogu ns3 w podkatalogu build/debug

Pokud nemáte takový adresář, znamená to, že jste při sestavení vydání ns‑3 neuvedli výstupní adresář, sestavte to takto:
$ ./waf configure --build-profile=debug --out=build/debug
$ ./waf build
nebo
$ ./waf configure --build-profile=optimized --out=build/optimized
$ ./waf build

nebo build/optimized, w zależności od Twojej konfiguracji. Waf będzie także automatycznie generować plik nagłówkowy modułu do ładowania wszystkich publicznych plików nagłówkowych. Ponieważ oczywiście ściśle przestrzegasz tego przewodnika, już zrobiłeś

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

aby skonfigurować projekt do realizacji kompilacji debug, które obejmują przykłady i testy. Zrobiłeś także

$ ./waf

aby skompilować projekt. Więc teraz, kiedy spojrzysz do katalogu ../..//build/debug/ns3, znajdziesz tam, między innymi, pliki nagłówkowe czterech modułów pokazanych powyżej. Możesz spojrzeć na zawartość tych plików i odkryć, że zawierają wszystkie publiczne pliki używane przez odpowiednie moduły.

4.2.3 Prostor názvů ns3

Następna linia w skrypcie first.cc to deklaracja przestrzeni nazw.

using namespace ns3;

Projekt ns‑3 je implementován v prostoru jmen C++, který se nazývá ns3. Tento prostor shromažďuje všechna prohlášení související s ns‑3 v oblasti viditelnosti mimo globální prostor jmen, což, jak doufáme, pomůže při integraci s jiným kódem. Použití operátoru C++ uvádí prostor jmen ns‑3 do aktuální (globální) deklarativní oblasti. To je zvláštní způsob, jak říci, že po tomto prohlášení už nebude nutné uvádět operátor rozlišení ns3 :: scope před celým kódem ns‑3, abyste jej mohli použít. Pokud nejste obeznámeni s prostory jmen, podívejte se na prakticky jakoukoli učebnici C++ a porovnejte prostor jmen ns3 s použitím prostoru jmen std a prohlášeními. using namespace std; v příkladech práce s výstupním operátorem cout a proudy.

4.2.4 Žurnálování

Další řádek skriptu je následující,

NS_LOG_COMPONENT_DEFINE ("FirstScriptExample");

Toto prohlášení použijeme jako pohodlné místo pro diskusi o našem dokumentačním systému Doxygen. Pokud navštívíte webovou stránku projektu ns‑3, najdete odkaz "Dokumentace" (Documentation) v navigačním panelu. Pokud tento odkaz vyberete, dostanete se na naši stránku dokumentace. Existuje odkaz na "Poslední vydání", který vás přivede k dokumentaci k poslední stabilní verzi ns‑3. Pokud vyberete odkaz "API Documentation", dostanete se na stránku dokumentace API ns‑3.

Na levé straně stránky najdete grafické zobrazení struktury dokumentace. Dobré místo pro začátek je "kniha" Modules ns‑3 v navigačním stromu ns‑3. Pokud rozbalíte Modules, uvidíte seznam dokumentace modulů ns‑3. Jak bylo uvedeno výše, koncept modulu zde přímo souvisí se soubory zahrnutými v modulu výše. Podsystem logování ns‑3 se probírá v části Použití modulu logování, takže se k němu vrátíme později v této příručce, ale můžete se o výše uvedeném prohlášení dozvědět tím, že se podíváte na modul Core, a poté otevřete knihu Nástroje pro ladění, a poté vyberete stránku Logging. Klikněte na Logging.

Nyní byste měli prohlédnout dokumentaci Doxygen pro modul Logging. V seznamu maker v horní části stránky uvidíte záznam pro NS_LOG_COMPONENT_DEFINE. Před tím, než přejdete na odkaz, určitě se podívejte na „Podrobné informace“ o modulu registrace, abyste pochopili, jak funguje v celkovém pohledu. Abychom to udělali, můžete se posunout dolů nebo vybrat „Více…“ pod diagramem.

Jakmile budete mít obecnou představu o tom, co se děje, pokračujte a podívejte se na dokumentaci ke konkrétním NS_LOG_COMPONENT_DEFINE. Nebudu zde duplicovat dokumentaci, ale shrnu, že tento řádek vyhlašuje registrační komponentu s názvem FirstScriptExample, která umožňuje zapínat a vypínat registraci konzolových zpráv podle odkazu na jméno.

4.2.5 Hlavní funkce

V následujících řádcích skriptu uvidíte,

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

To je pouze vyhlášení hlavní funkce vašeho programu (skriptu). Stejně jako v jakémkoli programu v C++ musíte definovat hlavní funkci, ta se vykonává jako první. Zde není nic zvláštního. Váš skript ns‑3 je prostě C++ program. Následující řádek nastavuje časové rozlišení na 1 nanosekundu, což je výchozí hodnota:

Time::SetResolution (Time::NS);

Časové rozlišení nebo jednoduše rozlišení je nejmenší hodnota času, která může být použita (nejmenší představitelný rozdíl mezi dvěma hodnotami času). Můžete změnit rozlišení přesně jednou. Mechanismus, který zajišťuje tuto flexibilitu, spotřebovává paměť, proto, jakmile je rozlišení explicitně nastaveno, uvolňujeme paměť, čímž bráníme dalším aktualizacím. (Pokud explicitně nenastavíte rozlišení, výchozí hodnota bude jedna nanosekunda a paměť bude uvolněna na začátku simulace.)

Následující dva řádky scénáře se používají k aktivaci dvou komponentů protokolování, které jsou zabudované v aplikacích EchoClient a EchoServer:

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

Pokud jste si přečetli dokumentaci k komponentě Logging, uvidíte, že existuje několik úrovní podrobnosti registrace, které můžete zapnout na každé komponentě. Tyto dvě řádky kódu zahrnují logování ladění na úrovni INFO pro echo klienty a servery. Na této úrovni aplikace během simulace vytiskne zprávy při odesílání a přijímání paketů.

Nyní se přímo dostaneme k vytvoření topologie a spuštění simulace. Zapojíme objekty topologických pomocníků, abychom tuto práci co nejvíce usnadnili.

4.2.6 Použití topologických pomocníků

Následující dvě řádky kódu v našem skriptu vlastně vytvoří objekty Node ns-3, které budou představovat počítače v simulaci.

NodeContainer nodes;
nodes.Create (2);

Než budeme pokračovat, najděme dokumentaci pro třídu NodeContainer. Další způsob, jak se dostat k dokumentaci pro tuto třídu, je přes záložku Classes na stránkách Doxygen. Pokud již máte otevřený Doxygen, jednoduše posuňte nahoru na vrchol stránky a vyberte záložku Classes. Měli byste vidět novou sadu záložek, z nichž jedna je seznam tříd. Pod touto záložkou uvidíte seznam všech tříd ns-3. Posuňte se dolů k ns3 :: NodeContainer. Až najdete třídu, vyberte ji, abyste se dostali k dokumentaci pro třídu.

Jak si pamatujeme, jednou z našich klíčových abstrakcí je uzel. Představuje počítač, ke kterému plánujeme přidat takové věci, jako jsou zásobníky protokolů, aplikace a periferní karty. Topologický pomocník NodeContainer poskytuje pohodlný způsob vytváření, správy a přístupu k všem objektům Node, které vytváříme pro spuštění simulace. První řádek výše pouze deklaruje NodeContainer, kterému říkáme nodes. Druhý řádek volá metodu Create pro objekt nodes a žádá kontejner, aby vytvořil dva uzly. Jak je popsáno v Doxygen, kontejner žádá v systému ns-3 o vytvoření dvou objektů Node a uchovává ukazatele na tyto objekty uvnitř.

Uzly vytvořené ve skriptu v tuto chvíli nic nedělají. Dalším krokem ve výstavbě topologie je připojení našich uzlů k síti. Nejjednodušší forma sítě, kterou podporujeme, je dvoubodová vazba mezi dvěma uzly. Nyní vytvoříme takové spojení.

PointToPointHelper

Vytváříme dvoubodové spojení, postupujeme podle známého vzoru a používáme topologický pomocný objekt k provedení nízkoúrovňové práce potřebné pro spojení. Připomeňme, že naše dvě klíčové abstrakce NetDevice a Channel. V reálném světě tyto termíny přibližně odpovídají periferním kartám a síťovým kabelům. Obecně jsou tyto dvě věci úzce propojené a nikdo se nemůže spolehnout na výměnu, například zařízení Ethernet bezdrátovým kanálem. Naši topologičtí pomocníci následují toto těsné spojení, a proto v tomto scénáři budete používat jeden objekt PointToPointHelper k nastavení a připojení objektů ns‑3 PointToPointNetDevice a PointToPointChannel. Následující tři řádky ve scénáři:

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

První řádek,

PointToPointHelper pointToPoint;

vytváří v zásobníku instanci objektu PointToPointHelper. Z pohledu vyšší úrovně následující řádek,

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

říká objektu PointToPointHelper použít hodnotu „5 Mb/s“ (pět megabitů za sekundu) jako „DataRate».

Z konkrétnějšího pohledu, řádek „DataRate“ odpovídá tomu, co nazýváme atributem PointToPointNetDevice. Pokud se podíváte na Doxygen pro třídu ns3::PointToPointNetDevice a v dokumentaci k metodě GetTypeId najdete seznam atributů definovaných pro zařízení. Mezi nimi bude atribut „DataRate“. Většina objekty ns‑3 viditelné pro uživatele mají podobné seznamy atributů. Tento mechanismus používáme pro snadné nastavení simulace bez nutnosti rekompilace, jak uvidíte v následující části.

Podobně jako „DataRate“ v PointToPointNetDevice, najdete atribut „Delay“ spojený s PointToPointChannel. Konečný řádek,

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

říká PointToPointHelper použít hodnotu „2 ms“ (dvě milisekundy) jako hodnotu zpoždění šíření kanálem point-to-point, který později vytváří.

NetDeviceContainer

V tuto chvíli máme ve scénáři NodeContainer, který obsahuje dva uzly. Máme PointToPointHelper, který je připraven k vytvoření objektů PointToPointNetDevices a spojení je pomocí objektu PointToPointChannel. Stejně jako jsme použili topologický pomocný objekt NodeContainer k vytvoření uzlů, požádáme PointToPointHelper o provedení práce související s vytvořením, nastavením a instalací našich zařízení. Budeme potřebovat seznam všech vytvořených objektů. NetDevice, proto používáme NetDeviceContainer pro jejich ukládání stejně jako jsme použili NodeContainer pro ukládání námi vytvořených uzlů. Následující dvě řádky kódu,

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

dokončí konfiguraci zařízení a kanálu. První řádek deklaruje kontejner zařízení, zmíněný výše, a druhý vykonává hlavní práci. Metoda Nainstalovat objektu PointToPointHelper přijímá NodeContainer jako parametr. Uvnitř NetDeviceContainer pro každý uzel nacházející se v NodeContainer se vytváří (pro bodový spojení jich musí být přesně dva) PointToPointNetDevice vytváří se a ukládá do kontejneru zařízení. PointToPointChannel vytváří se a připojují se k němu dva PointToPointNetDevices. Po vytvoření objektů se atributy uložené v PointToPointHelper, použijí pro inicializaci odpovídajících atributů ve vytvořených objektech.

Po provedení volání pointToPoint.Install (nodes) budeme mít dva uzly, každý s nainstalovaným síťovým zařízením „bodový spoj“ a jedním „bodovým spojem“ mezi nimi. Obě zařízení budou nastavena na přenos dat rychlostí pět megabitů za sekundu s prodlevou přenosu po kanálu dvě milisekundy.

InternetStackHelper

Nyní máme nakonfigurovány uzly a zařízení, ale na našich uzlech není nainstalována zásobníková protokol. Následující dvě řádky kódu se o to postará.

InternetStackHelper stack;
stack.Install (nodes);

InternetStackHelper — představuje topologického pomocníka pro internetové zásobníky, podobně jako PointToPointHelper pro dvoubodová síťová zařízení. Metoda Nainstalovat přijímá NodeContainer jako parametr. Při provádění nainstaluje internetový zásobník (TCP, UDP, IP atd.) na každém uzlu kontejneru.

Ipv4AddressHelper

Nyní musíme k našim zařízením přiřadit IP adresy. Poskytujeme topologického pomocníka pro správu distribuce IP adres. Jediným uživatelsky viditelným API je nastavení základní IP adresy a masky sítě pro použití při skutečné distribuci adres (to se provádí na nižší úrovni uvnitř pomocníka). Následující dvě řádky kódu v našem příkladu skriptu first.cc,

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

deklarují pomocný objekt adresy a říkají mu, že by měl začít přidělovat IP adresy z sítě 10.1.1.0, přičemž pro určení se používá maska 255.255.255.0. Ve výchozím nastavení se přidělované adresy začnou od jedničky a budou monotónně přibývat, takže první adresa přidělená z této základny bude 10.1.1.1, pak 10.1.1.2 a tak dále. Ve skutečnosti na nízké úrovni systém ns-3 uchovává všechny přidělené IP adresy a generuje fatální chybu, pokud náhodou vytvoříte situaci, kdy bude stejná adresa vygenerována dvakrát (mimochodem, tuto chybu je těžké ladit).

Následující řádek kódu,

Ipv4InterfaceContainer interfaces = address.Assign (devices);

vykonává skutečné přidělení adresy. V ns-3 vytváříme spojení mezi IP adresou a zařízením prostřednictvím objektu Ipv4Interface. Tak jako občas potřebujeme seznam síťových zařízení, která vytvořil pomocník pro další použití, občas potřebujeme seznam objektů Ipv4Interface. Ipv4InterfaceContainer nabízí tuto funkcionalitu.

Vytvořili jsme síť bod-bod, se stanovenými stacky a přidělenými IP adresami. Teď potřebujeme na každém uzlu aplikaci pro generování provozu.

4.2.7 Použití aplikace

Další z hlavních abstrakcí systému ns-3 je Aplikace (aplikace). V tomto scénáři používáme dvě specializace základní třídy Aplikace ns-3 s názvem UdpEchoServerApplication a UdpEchoClientApplication. Stejně jako v předchozích případech používáme pomocné objekty k nastavení a řízení základních objektů. Zde používáme UdpEchoServerHelper a UdpEchoClientHelperobjekty, abychom si ulehčili práci.

UdpEchoServerHelper

Následující řádky kódu v našem příkladu skriptu first.cc se používají k nastavení aplikace UDP echo serveru na jednom z uzlů, které jsme vytvořili dříve.

UdpEchoServerHelper echoServer (9);

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

První řádek kódu v uvedeném výřezu vytváří UdpEchoServerHelper. Jak je obvyklé, toto není aplikace samo o sobě, je to objekt, který nám pomáhá vytvářet skutečné aplikace. Jedním z našich ujednání je předávat potřebné atributy do konstruktoru pomocného objektu. V tomto případě nemůže pomocník udělat nic užitečného, pokud mu není poskytnuto číslo portu, na kterém server bude očekávat pakety; toto číslo by mělo být známo také klientovi. V tomto případě předáváme konstruktoru pomocníka číslo portu. Konstruktor na oplátku jen provádí SetAttribute s předanou hodnotou. Později, pokud si přejete, pomocí SetAttribute budete moci nastavit jinou hodnotu atributu „Port“.

Podobně jako mnoho jiných pomocných objektů, objekt UdpEchoServerHelper má metodu Nainstalovat. Provádění této metody v podstatě vede k tomu, že se vytvoří základní aplikace echo serveru a připojí se k uzlu. Zajímavé je, že metoda Nainstalovat přijímá NodeContainter jako parametr, stejně jako jiné Nainstalovat metody, které jsme viděli.

Implicitní převod C++, který zde pracuje, bere výsledek metody node.Get (1) (který vrací chytrý ukazatel na objekt uzlu — Ptr) a používá jej v konstruktoru pro anonymní objekt NodeContainer, který je následně předán metodě Nainstalovat. Pokud nemůžete určit v kódu C++, která metoda s jakým podpisem se kompiluje a provádí, hledejte mezi implicitními převody.

Nyní vidíme, že echoServer.Install se chystá nainstalovat aplikaci UdpEchoServerApplication na nalezený v NodeContainer, který používáme k řízení našich uzlů, uzel s indexem 1. Metoda Nainstalovat vrátí kontejner, který obsahuje ukazatele na všechny aplikace (v tomto případě jednu, protože jsme předali anonymní NodeContainer, obsahující jeden uzel) vytvořenou pomocníkem.

Aplikacím je třeba uvést okamžik spuštění generování provozu "start" a může být také nutné uvést čas, kdy má být zastavena "stop". Poskytujeme oba parametry. Tyto časy jsou nastavovány pomocí metod ApplicationContainer Spustit a Stop. Tyto metody přijímají parametry typu Čas. V tomto případě používáme explicitní sekvenci převodů C++, abychom vzali C++ double 1.0 a převést ho na objekt tns‑3 Time, používající objekt Seconds pro převod na sekundy. Pamatujte, že pravidla převodu mohou být kontrolována autorem modelu a C++ má svá vlastní pravidla, takže se nemůžete vždy spoléhat na to, že parametry se převedou tak, jak očekáváte. Dvě řádky,

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

způsobí, že aplikace echo serveru se spustí (automaticky se zapne) jednu sekundu po začátku simulace a zastaví se (vypne) po deseti sekundách simulace. Vzhledem k tomu, že jsme vyhlásili událost simulace (událost zastavení aplikace), která se vykoná po deseti sekundách, bude simulováno alespoň deset sekund provozu sítě.

UdpEchoClientHelper

Klientská aplikace echo se nastavuje způsobem, který je prakticky shodný se serverem. Existuje základní objekt UdpEchoClientApplication, o který se stará
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));

Nicméně pro echo klienta musíme nastavit pět různých atributů. První dva atributy se nastavují při vytváření UdpEchoClientHelper. Přenášíme parametry, které se používají (uvnitř asistenta) pro nastavení atributů "RemoteAddress" a "RemotePort" v souladu s naším smluvním ujednáním o předávání potřebných parametrů do konstruktoru asistenta.

Připomínáme, že jsme používali Ipv4InterfaceContainer k sledování IP adres, které jsme přiřadili našim zařízením. Nulové rozhraní v kontejneru rozhraní odpovídá IP adrese nulového uzlu v kontejneru uzlů. První rozhraní v kontejneru rozhraní odpovídá IP adrese prvního uzlu v kontejneru uzlů. Takže v prvním řádku kódu (shora) vytváříme asistenta a říkáme mu, že vzdálenou adresou klienta bude IP adresa přiřazená uzlu, na kterém se nachází server. Také říkáme, že je třeba zorganizovat odesílání paketů na devátý port.

Atribut "MaxPackets" informuje klienta o maximálním počtu paketů, které můžeme odeslat během simulace. Atribut "Interval" klientovi sděluje, jak dlouho čekat mezi pakety, a atribut "PacketSize" říká klientovi, jak velká by měla být payload paketu. Tohoto kombinací atributů říkáme klientovi, aby odeslal jeden paket o velikosti 1024 bajtů.

Stejně jako v případě echo serveru nastavujeme echo klientovi atributy Spustit a Stop, ale zde spouštíme klienta sekundu po zapnutí serveru (dva sekundy po zahájení simulace).

4.2.8 Simulátor

V tomto kroku je třeba spustit simulaci. To se provádí pomocí globální funkce Simulator::Run.

Simulator::Run ();

Když jsme dříve volali metody,

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

skutečně jsme naplánovali události v simulátoru na 1,0 sekundy, 2,0 sekundy a dvě události na 10,0 sekund. Po volání Simulator::Run, systém začne procházet seznam naplánovaných událostí a vykonávat je. Nejprve spustí událost po 1,0 sekundě, která aktivuje echo server aplikaci (tato událost může naopak naplánovat mnoho dalších událostí). Pak spustí událost naplánovanou na t = 2,0 sekundy, která spustí echo klienta. Opět může tato událost naplánovat ještě mnoho dalších událostí. Realizace spouštěcí události v echo klientovi zahájí fázi přenosu dat simulace odesláním paketu na server.

Akt odeslání paketu na server vyvolá řetězec událostí, které budou automaticky naplánovány na pozadí a které realizují mechaniku odesílání paketů echo signálů podle parametrů synchronizace, které jsme nastavili ve skriptu.

Nakonec, protože odesíláme pouze jeden paket (připomeňme, že atribut MaxPackets byl nastaven na 1), řetězec událostí iniciovaný tímto jediným klientským echo požadavkem skončí a simulace přejde do čekacího režimu. Jakmile se to stane, zbývající naplánované události budou události Stop pro server a klienta. Jakmile budou tyto události vykonány, nebudou události k dalšímu zpracování a Simulator::Run vrátí kontrolu. Modelování je dokončeno.

Zbývá jen uklidit za sebou. To se provádí voláním globální funkce Simulator::Destroy. Protože byly volány funkce pomocníků (nebo kód na nízké úrovni ns‑3), které jsou uspořádány tak, aby do simulátoru byly vloženy háčky pro zničení všech objektů, které byly vytvořeny. Není třeba sledovat žádné z těchto objektů samostatně — stačilo jen zavolat Simulator::Destroy a odejít. Systém ns‑3 udělá tuto náročnou práci za vás. Zbylé řádky našeho prvního skriptu ns‑3, first.cc, dělají právě toto:

Simulator::Destroy ();
return 0;
}

Kdy se simulátor zastaví?

ns‑3 je simulátor diskrétních událostí (DE). V takovém simulátoru je každá událost spojena s časem jejího provedení a simulace pokračuje zpracováním událostí v pořadí jejich výskytu během simulace. Události mohou způsobit naplánování budoucích událostí (například časovač se může znovu naplánovat, aby dokončil počítání v následujícím intervalu).

Počáteční události obvykle iniciuje objekt, například IPv6 naplánuje rozpoznávání služeb v síti, žádosti sousedů atd. Aplikace naplánuje první událost odeslání paketu atd. Když je událost zpracována, může generovat nula, jednu nebo více událostí. Během provádění simulace se události buď prostě ukončí, nebo generují nové. Simulace se zastaví automaticky, pokud je fronta událostí prázdná nebo se objeví speciální událost Stop. Událost Stop je generována funkcí Simulator::Stop (zastavit čas).

Existuje typický případ, kdy je Simulator::Stop naprosto nezbytný k zastavení simulace: když existují samopodporující se události. Samopodporující (nebo opakující se) události jsou události, které se vždy znovu naplánují. V důsledku toho vždy udržují frontu událostí neprázdnou. Existuje mnoho protokolů a modulů, které obsahují opakující se události, například:

• FlowMonitor — periodická kontrola ztracených paketů;

• RIPng — periodické vysílání aktualizací tabulek směrování;

• atd.

V takových případech Simulator::Stop je nezbytný pro správné zastavení simulace. Kromě toho, kdy je ns‑3 v režimu emulace, je RealtimeSimulator používán k synchronizaci hodin simulace s hodinami stroje, a Simulator::Stop je nezbytný k zastavení procesu.

Mnoho programů simulace v učebnici nevyvolává Simulator::Stop to je jasné, protože se automaticky ukončují vypršením událostí v frontě. Tyto programy však také zpracují výzvu Simulator::Stop. Například následující další příkaz v prvním příkladu programu naplánuje explicitní zastavení v 11. sekundě:

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

Výše uvedené vlastně nezmění chování tohoto programu, protože toto konkrétní modelování se přirozeně končí po 10 sekundách. Ale pokud byste změnili čas zastavení v uvedeném příkazu z 11 sekund na 1 sekundu, všimli byste si, že modelování se zastaví, ještě předtím než se jakýkoliv výstup dostane na obrazovku (protože výstup se obvykle zobrazuje přibližně po 2 sekundách během simulace).

Je důležité zavolat Simulator::Stop před zavoláním Simulator::Run; jinak může Simulator::Run nikdy nevrátit kontrolu zpět do hlavního programu pro provedení zastavení!

4.2.9 Sestavení vašeho scénáře

Učinili jsme nutnost vytváření vašich jednoduchých skriptů triviální. Všechno, co musíte udělat, je umístit svůj skript do adresáře scratch, a ten bude automaticky sestaven, když spustíte Waf. Pojďme to vyzkoušet. Vraťte se do hlavního adresáře a zkopírujte examples/tutorial/first.cc do adresáře scratch

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

Nyní sestavte svůj první příklad skriptu pomocí waf:

$ ./waf

Měli byste vidět zprávy, že váš první příklad byl úspěšně vytvořen.

Waf: Vstup do adresáře `/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: Opouští adresář `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
'build' byl úspěšně dokončen (2,357 s)

Nyní můžete spustit příklad (vezměte na vědomí, že pokud sestavujete svůj program v adresáři scratch, měli byste ho také spouštět z scratch):

$ ./waf --run scratch/myfirst

Měli byste vidět podobný výstup:

Waf: Vstup do adresáře `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
Waf: Opouští adresář `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
'build' byl úspěšně dokončen (0,418 s) Odesláno 1024 bajtů na 10.1.1.2
Přijato 1024 bajtů z 10.1.1.1
Přijato 1024 bajtů z 10.1.1.2

Zde vidíte, že systém sestavení kontroluje, zda byl soubor sestaven, a poté jej spouští. Vidíte, že záznam komponenty na echo klientovi ukazuje, že odeslal jeden 1024-bajtový paket na echo server 10.1.1.2. Také vidíte záznam komponenty na echo serveru, že přijal 1024 bajty od 10.1.1.1. Echo server tiše opakuje paket a vidíte v protokolu echo klienta, že obdržel svůj paket zpět ze serveru.

4.3 Zdrojový kód ns-3

Nyní, když jste využili některé z ns‑3 asistentů, můžete se podívat na některé zdrojové kódy, které tuto funkcionalitu implementují. Nejnovější kód si můžete prohlédnout na našem webovém serveru na následujícím odkazu: https://gitlab.com/nsnam/ns-3-dev.git. Zde uvidíte shrnující stránku Mercurial pro naše vývojové strom ns‑3. V horní části stránky uvidíte několik odkazů,

shrnutí | krátký záznam | změnový záznam | graf | štítky | soubory

Pokračujte dál a vyberte odkaz na soubory. Takto bude vypadat horní úroveň většiny našich repozitářů:

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        soubor | revize | anotace
-rw-r--r-- 2009-07-01 12:47 +0200 1886   .hgtags          soubor | revize | anotace
-rw-r--r-- 2009-07-01 12:47 +0200 1276   AUTOŘI          soubor | revize | anotace
-rw-r--r-- 2009-07-01 12:47 +0200 30961  ZMĚNY.html      soubor | revize | anotace
-rw-r--r-- 2009-07-01 12:47 +0200 17987  LICENCE         soubor | revize | anotace
-rw-r--r-- 2009-07-01 12:47 +0200 3742   README          soubor | revize | anotace
-rw-r--r-- 2009-07-01 12:47 +0200 16171  VYDÁVACÍ_POZNÁMKY soubor | revize | anotace
-rw-r--r-- 2009-07-01 12:47 +0200 6      VERZE           soubor | revize | anotace
-rwxr-xr-x 2009-07-01 12:47 +0200 88110  waf             soubor | revize | anotace
-rwxr-xr-x 2009-07-01 12:47 +0200 28     waf.bat        soubor | revize | anotace
-rw-r--r-- 2009-07-01 12:47 +0200 35395  wscript         soubor | revize | anotace
-rw-r--r-- 2009-07-01 12:47 +0200 7673   wutils.py       soubor | revize | anotace

Naše příklady scénářů se nachází v adresáři examples. Pokud kliknete na příklady, uvidíte seznam podadresářů. Jeden ze souborů v podadresáři tutorial — first.cc. Pokud kliknete na first.cc , uvidíte kód, který jste právě studovali.

Zdrojový kód se nachází převážně v adresáři src. Můžete si prohlédnout zdrojový kód kliknutím na název adresáře nebo na odkaz souborů vpravo od názvu adresáře. Pokud kliknete na adresář src, zobrazí se vám seznam podadresářů src. Pokud poté kliknete na podadresář core, najdete seznam souborů. První soubor, který uvidíte (v okamžiku psaní tohoto průvodce) — abort.h. Pokud kliknete na odkaz abort.h, budete přesměrováni na zdrojový soubor pro abort.h, který obsahuje užitečné makra pro ukončení skriptů, pokud se objeví abnormální podmínky. Zdrojový kód pro pomocníky, které jsme použili v této kapitole, najdete v adresáři src/Applications/helper. Neváhejte prozkoumat strom adresářů, abyste pochopili, co a kde je, a naučili se styl programování ns-3.

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster