Tartalmi kivonat
Mérési útmutató a Mobil Távközlési és Informatikai Laboratórium méréseihez I. sz mérés OMNET++ bevezető mérés Mérés helye: Híradástechnikai Tanszék Mobil Távközlési és Informatikai Laboratórium (MC2L) I.B113 Összeállította: Schulcz Róbert, tudományos segédmunkatárs Csege Viktor Heim István Utolsó módosítás: 2005. október 11 1. Bevezetés Jelen mérés célja, hogy egy egyszerű példaprogram segítségével megismerkedjünk az OMNeT++ szimulációs környezet programozásával. Távközlési és számítógép hálózatok vizsgálatát sok esetben költséghatékony módon vizsgálhatjuk számítógépre megírt szimulációk segítségével. Ekkor a költséges fizikai megvalósítás helyett, egy számítógépes program segítségével vizsgáljuk az adott hálózat működését és teljesítőképességét. Számos szimulációs környezet áll rendelkezésre, mint pl: NS (Network Simulator), OPNET, OMNeT++. Az OMNeT++ rendszert
egyetemünkön fejlesztették ki, nyílt forráskódú, szabadon felhasználható (http://www.omnetpporg/) 2. Az OMNeT++ -ről általánosságban Az OMNeT++ egy objektum orientált, moduláris, diszkrét szimulációs környezet. Egy OMNeT++ hálózat hierarchikus modulokból épül fel. A modell mélysége nincs meghatározva A modulok üzenetek segítségével kommunikálnak egymással, mely üzenetek komplex adatstruktúrákat is tartalmazhatnak. Az üzeneteket a modulok között előre definiált kapukon és csatornákon keresztül, vagy akár közvetlenül is el lehet küldeni. A fejlesztőnek a hierarchia legalsó szintjén található modul viselkedését kell megírni C++ nyelven. A szimuláció futtatása során ezen modulok párhuzamosan (korutinként) futnak A környezet különböző felhasználói felületeket (hibakeresés, bemutató, batch futtatás) biztosít, mely nagyban elősegíti a fejlesztést. A modulok összeköttetését, szerkezetét egy speciális
leírónyelven, a NED (NEtwork Description) nyelven kell megírni, melyet a környezet szintén C++ nyelvre fordít le. Így a teljes szimuláció C++ nyelven áll rendelkezésre, mely jó hordozhatóságot biztosít – a szimuláció Windows NT/9x/2000/XP, Linux és Solaris operációs rendszeren is módosítások nélkül fut. A környezet a grafikus megjelenítéshez a Tcl/Tk könyvtárakat használja, mely szintén segíti a hordozhatóságot. 3. Egy OMNeT++ szimulátor megvalósítása Első lépésként a hálózatot kell megtervezni. A megtervezett hálózatot NED nyelvre kell átírnunk A részegységeket moduloknak feleltetjük meg, két féle modul van, az egyszerű (simple, tovább nem bontható) és az összetett (module, mely egyszerű modulokból áll). A hálózat (network) pedig ezen modulok összességét jelenti (Ábra 1.) A NED file elkészítése során az egyszerű modulok megadása után következnek az összetett modulok, majd végén megadjuk a hálózatot
is. A modulokat kapuk segítségével kötjük össze (Ábra 2.) hálózat (network) egyszerű modulok (simple) összetett modul (module) Ábra 1.: Modell struktúra Az egyszerű modul felépítése: simple Típusnév parameters : //paraméterek megadása paraméter név : paraméter típus; //típus lehet numeric, input, boolean, gates : // a modul be- és kimeneti kapujai out : ki kapu neve[]; //kimeneti kapu, [] esetén egynél több kimeneti kapu van in : be kapu neve[]; //bemeneti kapu, [] esetén egynél több bemeneti kapu van endsimple összett modul ki kapu egyszerű modul ki kapu egyszerű modul összetett modul egyszerű modul be kapu összett modul be kapu Ábra 2.: Kapuk összekötése Az összetett modul felépítése: module Név // modul neve gates : // a modul kapui in : be kapu neve[]; out : ki kapu neve[]; submodules : // almodulok megadása almodul neve : almodul típusa; // az előbb definiált egyszerű modulra hivatkozhatunk parameters : // az
egyszerű modul paramétereinek itt lehet értéket adni paraméter név = paraméter érték; gatesizes : // vektoros kapuk esetén itt kell megadni a vektor méretét out[5]; display : "p=130,259;b=40,24"; // modul helye a képernyőn connections : // kapuk összeköttetései egyszerű modul ki kapu --> összetett modul ki kapu; egyszerű modul be kapu <-- összetett modul be kapu; endmodule A hálózat felépítése: network hálózat neve : összetett modul endnetwork A paramétereknek a hierarchia tetszőleges szintjén adhatunk értéket. Ha a paraméterek az egyszerű modulban nem kapnak értéket, akkor az összetett modulban, vagy a hálózatban kell megadnunk az értékeket. Lehetőségünk van még paraméterek megadásásra az omnetppini állományban is. Második lépésként megírjuk az egyszerű modulok viselkedését: class egyszerű modul típusa : public cSimpleModule { Module Class Members(egyszerű modul típusa,cSimpleModule,16384) virtual
void activity(); // a viselkedést leíró függvény }; Define Module (egyszerű modul típusa); //a NED-ben lévő típus megfeleltetése a C++ kódban megírt osztálynak Az activity() függvény: Korutinokként futnak,vagyis ezek párhuzamosan futó szálak, így lehetővé válik a Multitasking feldolgozás. Állandóan futnak, ezért van bennük egy végtelen ciklus Ha egy esemény érkezett, akkor a „főprogram” futása felfüggesztődik, és annak a modulnak az activity fv.-ére adódik a vezérlés, amelyik az üzenetet kapta Ha lekezelte, visszatér a főprogramba. Az activity()-ben alkalmazott fontosabb függvények: • receive (üzenet vétele) • wait (várakozás meghatározott ideig) • send (üzenet küldése) • ScheduleAt (esemény ütemezése) • cancelEvent (ütemezett esemény törlése) Egy példa activity() függvény: void Source::activity() { char mit[30]; int gs= par("gs"); //a NED fájlban megadott paraméter beolvasása cMessage
*smsg = new cMessage; // új üzenet konstruálása scheduleAt(simTime()+exponential(5),smsg); // ütemezés, timer megvalósítása önüzenettel 5 másodperces várhatóértékű exponenciális eloszlás szerint do { cMessage *msgin = receive(); // üzenet fogadása if (msgin->isScheduled()) delete cancelEvent(smsg); // önüzenet törlése int out = intrand(gs); //véletlenszám generálás if (out%2) strcpy(mit,"message (to HOLE)"); else strcpy(mit,"message"); cMessage *msg = new cMessage(mit); if (out%2) msg->setKind(7); else msg->setKind(2); ev.printf("[SOURCE]: Sending message on gate %d ",out); send(msg,"out",out); //üzenet elküldése az out vektorkapu out sorszámú kimenetén cMessage *smsg = new cMessage; scheduleAt(simTime()+exponential(5),smsg); } while (1); } 4. A billiárd szimulátor Működés Kétféle csomópont van, lyuk és fal: A lyuk meghatározott időközönként üzentet generál és elküldi valamelyik
kimenetén, valamint a neki címzett üzenetet elnyeli. A fal routerként viselkedik, vagyis a szabályrendszert követve egy adott bemenetén érkező üzenetet, adott kimenetre küldi ki. A hálózatot 6 lyuk és 6 fal alkotja a biliárdasztalon szokásos elrendezésben. A visszaverődési (routolási) szabályok megalkotása a geometriát figyelembe véve történt. 2 féle üzenetet van, az egyik a közvetlen üzenet (lyuk->lyuk), a másik a fal által továbbított. A falak az üzeneteket 0.5 sec késleltetéssel a megfelelő irányba továbbítják A késleltetésre azért van szükség, hogy eközben más generátorok is küldhessenek üzenetet, ezáltal növelve az elosztott működés érzését. Routolási szabályok: Az egyes elemeket összekötése oly módon történt, hogy az üzenetek továbbításában szabályszerűség legyen megfigyelhető, ne legyen szükség bonyolult forgalomirányítási táblákra. Egy egyszerű feltétel vizsgálata elegendő: • A kapuk
indexelése az óramutató járásával megegyező irányítású. • Ha a fal 4 kapus, akkor a be-és kimenti kapuk indexösszege 3. • Ha a fal 6 kapus,akkor ez az érték 5. A hálózat NED nyelvű kialakítása A lyuk egy hierarchikus modul, amely két egyszerű modult tartalmaz, a forrást és a nyelőt. Kétfajta lyuk-modult különböztetünk meg, egy 5 kimenetüt (alsó-felsők) és egy 7 kimenetűt (középsők). A fal egy egyszerű modul, amiből szintén két fajta van, egy 4 kapus és egy 6 kapus A hálózat 4db 5 kimenetű, 2db 7 kimenetű lyuk-modult, 2 db 6 kapus és 4 db 4 kapus fal modult tartalmaz. Összeköttetések A hálózat egyes elemeinek összeköttetését felsorolással adtuk meg. Kétféle linket különböztettünk meg logikailag, a paramétereik azonosak: • Lyukak közötti (fekete színű nyilak) • Lyuk és fal közötti (kék színű nyilak) A modulok a következő ábrán látható módon vannak összekötve: Ábra 3.: A hálózat 5. A
szimulációs környezet használatáról A bill.exe fájl futtatásával inditható el Két ablak jelenik meg (Ábra 3), egyiken a hálózat felépítése, a másikon a szimuláció futása alatt fellépő események láthatók. A grafikus ablakon látszanak az üzenetek, valamint a kívánt modulra kattintva nézhetjük meg annak belső felépítését. A szöveges ablakon találjuk a főbb vezérlő gombokat, melyek a következők: − Step: Egy lépést hajt végre, az esemény bekövetkezése után megállítja a szimulátor futását. − Run: Ezzel a gombbal indíthatjuk el a szimulátort. − Stop: Ezzel a gombbal állíthatjuk le a szimulátort. A szimuláció egyéb esetben akkor áll le, ha vagy elfogynak az események, vagy lejár a szimuláció előre megadott futási ideje. Az események értelmezése a következő: * Event #39. T=5397338 ( 539s) Module #10 `thebillgenerator5 2hole esemény azonosítója bekövetkezés ideje modul azonosítója hierarchialeiró 6.
Ellenőrző kérdések 1. Hogyan kommunikálnak egymással az OMNeT++ környezetben megírt modulok? 2. Mit kell implementálnia a fejlesztőnek OMNeT++ környezetben? 3. Hogyan épül fel a modul hierarchia? Hogyan lehet a paramétereknek értéket adni? 4. Hogyan kell vektoros kaput megadni? Hol adjuk meg a vektor méretét? 5. Melyek az activity() függvényben alkalmazható legfontosabb függvények? Mire szolgál a scheduleAt() függvény? 7. Mérési feladatok 1. feladat: A szimuláció nem indul el, mert hiányzik egy összeköttetés a generator7 1 és a generator7 0 között. A billned fájl szerkesztésével vegye fel a hiányzó összeköttetést! (Segítség: a vektoros kapuknál a sorszámokat az óramutató járásával ellenkező irányban számozzuk.) 2. feladat: A program futása közben csak a generator5 0 küld üzeneteket. Javítsa ki a hibát! 3. feladat: Írja át úgy a kódot, hogy a wall6 típusú „falak” nyeljenek el minden hozzájuk érkező
üzenetet! 4. feladat: Írja át úgy a kódot, hogy a routerek ne késleltessenek! A források normális eloszlás szerint generáljanak csomagokat tetszőleges paraméterek alapján. (Segítség: a distrib.h fájlban találhatóak az eloszlások deklarációi) 5. feladat: A generator7 típusú modulok által küldött üzeneteket különítse el a többitől! Pl.: legyen piros színű és a felirata is különbözzön a többi üzenettől. (Segítség: az üzenetek színét a setKind(int) metódussal állíthatja be, az aktuális modul hierarchialeíróját pedig a fullPath() metódussal kérdezheti le.)