Вы находитесь на странице: 1из 33

Computer and Communication Systems (Lehrstuhl fr Technische Informatik)

OMNeT++

[Car2X] Summer 2012

OMNeT++

Overview
OMNeT++
Discrete-Event Simulation (DES) kernel Multi-platform, Open Source Modular concept Pure C++ IDE (source code, configuration, , evaluation) optional GUI (simulation execution) optional

Model repositories
OverSim
Upper layers (Overlay networks)

The INET Framework


Middle layers (HTTP, TCP, IP, )

MiXiM
Lower layers (, MAC, PHY)
[Car2X] Summer 2012 OMNeT++

MiXiM
2

Modeling Approach
Hierarchical, modular, object oriented,

Compound Module
Simple Module Simple Module Simple Module

Gate

[Car2X] Summer 2012

OMNeT++

Modeling Approach
Compare to layered architecture
Application Transport Network Link Application Transport Network Link

Physical

Physical

[Car2X] Summer 2012

OMNeT++

Example

[Car2X] Summer 2012

OMNeT++

The DES Modeling Paradigm


Simulations are based on event queue
1. 2.

Select next event from queue Deliver event to destination module


Destination module reacts to event Potentially places new event(s) into queue

3.

Repeat

Scheduling events
send/sendDelayed: Send message via output gate
Event scheduled for delivery via connected modules input gate

sendDirect: Send message to other modules input gate


Disrupts hierarchical modeling pattern

scheduleAt: Send message to oneself


Common way of modeling timer expiry,
[Car2X] Summer 2012 OMNeT++ 6

The DES Modeling Paradigm


Need to map real-world processes discrete events
ex.: transmission of a packet

Alice

Bob
[Car2X] Summer 2012 OMNeT++ 7

Simulation GUI
Event queue

Parent Module Event delivery Child Module

[Car2X] Summer 2012

OMNeT++

Separation of Concerns
Simulation components
Runtime parameters
omnetpp.ini

Structure
network description (NED) (plain text file) message format (MSG) (plain text file)

Behavior
C++ code

[Car2X] Summer 2012

OMNeT++

Structure: NED files


Simple Module
simple TicModule { gates: input in; output out; }

Compound Module
import TicModule; import TocModule; module Watch { gates: input lightSwitch; output lcd; submodules: tic: TicModule; toc: TocModule; connections: tic.out --> toc.in; tic.in <-- toc.out; }
OMNeT++ 10

[Car2X] Summer 2012

Structure: NED files


Properties
@namespace(MySimulation); @display("i=block/queue"); @display("p=100,100;i= @display(t=Now Running;p= @node; @foo[1](s=apples; i=42); @foo[2](s=pears!; n=42);

Network definition
network sim extends Watch { }

[Car2X] Summer 2012

OMNeT++

11

Structure: MSG files


Messages and Gates
message MyMessage { int sourceId; int destinationId; string information; } simple MyModule { gates: input gate1; output gate2; inout gate3; }

[Car2X] Summer 2012

OMNeT++

12

Messages and Packets


Messages vs. Packets
#include MyMessage_m.h cMessage* msg = ; msg->setName(Bob); msg->setControlInfo(); #include MyPacket_m.h cPacket* pkt = ; pkt->setName(Bob); pkt->setControlInfo(); pkt->encapsulate(innerPkt); pkt->setByteLength(42);

Packet encapsulation
IP Packet TCP Segment

IP Control Info en/decapsulation


TCP Segment

[Car2X] Summer 2012

OMNeT++

13

Runtime Parameters
Defining parameters
Nodes NED file
simple Node { parameters: int foo; double bar; }

Reading parameters
C++ source code
void Node::initialize() { int i = par(foo); double bar = par(bar); }

Setting parameters
omnetpp.ini file
[General] network = sim sim.node.foo = 42
[Car2X] Summer 2012 OMNeT++ 14

Parameter Studies and Sensitivity Analyses

[General] sim.tic.tickRate = 42 sim.toc.tickRate = 42 # wildcards (first-match policy) sim.t[io]c.tickRate = 42 sim.*.tickRate = 42 *.*.tickRate = 42 **.tickRate = 42 **.tic.tickRate = intuniform(1, 12) **.tic.tickRate = ${FOO = 1, 5, 10} **.toc.tickRate = ${ 10, 5, 1 ! FOO}

[Car2X] Summer 2012

OMNeT++

15

Experiment Measurement Replication


Simulation: Use DYMO protocol to find route
Experiment 1: impact of network load?
Measurement 1.1: load of 5 packets/s?
Replication 1.1.1: random seed 7 Replication 1.1.2: random seed 42 (= run 0) (= run 1) (= run 2) (= run 3)

Measurement 1.2: load of 15 packets/s?


Replication 1.2.1: random seed 7 Replication 1.2.2: random seed 42

Experiment 2: impact of node density?


Measurement 2.1: density of 25 nodes/m2?
Replication 2.1.1: random seed 7 Replication 2.1.2: random seed 42 (= run 0) (= run 1) (= run 2) (= run 3)

Measurement 2.2: density of 50 nodes/m2?


Replication 2.2.1: random seed 7 Replication 2.2.2: random seed 42

[Car2X] Summer 2012

OMNeT++

16

Behavior: C++ Code


#include <omnetpp.h> Define_Module(TicModule); class TicModule : public cSimpleModule { void initialize() { cMessage *msg = new cMessage(sendTock"); send(msg, "out"); recordScalar(start time, simTime()); }

void handleMessage(cMessage *msg) { send(msg, "out"); cOutVector v; v.setName(ticks); v.record(1); }


};
[Car2X] Summer 2012 OMNeT++ 17

Use of initialize/finish
constructor
set pointers to 0

initialize(int stage)
initialize pointers read parameters schedule messages

finish()
record statistics

destructor
cancel and delete messages free (owned) memory
[Car2X] Summer 2012 OMNeT++ 18

Finite State Machines


Declare FSM
cFSM fsm; enum { INIT = 0, ONE = FSM_Steady(1), TWO = FSM_Steady(2), }; FSM_Switch(fsm) { case FSM_Exit(INIT): FSM_Goto(fsm, ONE); break; case FSM_Enter(ONE): break;

Enter of steady state: FSM_Switch returns Exit branch taken on next call
determines next state
[Car2X] Summer 2012

ONE

case FSM_Exit(ONE): FSM_Goto(fsm, TWO); break;


OMNeT++

TWO

19

Building the Simulation


GUI OMNeT++ kernel Model Library Own Models

Executable Simulation

static/dynamic linker .ned files .ini file sim kernel


20

Results

[Car2X] Summer 2012

OMNeT++

Running Simulations
With GUI
$ opp_run u Tkenv l /model-lib c Config1 r 0

Command line only


$ opp_run u Cmdenv l /model-lib c Config1 r 0..8,10

Parameters
-u: user interface to load -l: model library to load -c: configuration section (= experiment) to read -r: run (= measurement and replication) to execute

[Car2X] Summer 2012

OMNeT++

21

Generating Random Numbers


Properties of the stdlib pRNG
#include <cstdlib> { srand(42); while (1) { int dice = rand() % 6; std::cout << dice << std::endl; }

4 2 6 1 4 2 3 3 1

4 2 6 1 4 2 3 3 1

4 2 6 1 4 2 3 3 1

[Car2X] Summer 2012

OMNeT++

22

Generating Random Numbers


Properties of the stdlib pRNG
#include <cstdlib> { srand(42); while (1) { int dice = rand() % 6; std::cout << dice << \n;

if (doBuf && !rand() % 100) { std::cout.flush(); }


} }

4 2 6 1 4 2 3 3 1

4 2 6 1 4 2 3 3 1

4 6 4 3 1 2 1 2 3

[Car2X] Summer 2012

OMNeT++

23

Generating Random Numbers


Use OMNeT++ library functions
#include <omnetpp.h> {

uniform(1.0, 6.0) normal(3.0, 0.5) poisson(1.0)

4 4 2 2 if (doBuf && !genk_intrand(2, 100) % 100) { 6 6 std::cout.flush(); 1 1 } 4 4 } 2 2 } 3 3 3 3 1 1 Default seed derived from run #

while (1) { int dice = intrand(6); std::cout << dice << \n;

4 2 6 1 4 2 3 3 1

[Car2X] Summer 2012

OMNeT++

24

Collecting Results (1)


Either (1) do statistics in simulation
Can track mean, histogram bin population, estimate quantiles,
cStdDev stat; stat.collect(0.012); stat.collect(0.013); stat.collect(0.014); ASSERT(stat.getMean() == 0.013);

Transient phase detection


cTDExpandingWindows::setParameters( int reps=3, int minw=4, double wind=1.3, double acc=0.3)

Accuracy judging
cADByStddev::setParameters( double acc=0.1, int reps=3)
[Car2X] Summer 2012

OMNeT++

25

Collecting Results (2)


Or (2) write raw observations to a file
Can use C++ standard file I/O
Problem: when and how to open, close file? Problem: how to manage files?

Better: Use OMNeT++ data logging


Data associated with whole simulation: Scalar Value
e.g.: numPacketsReceived = 42

Data associated with event / time: Vector Value


e.g. packetDelays = {0.013s, 0.014s, 0.012s, }

Next Step: read file, derive statistics


[Car2X] Summer 2012 OMNeT++ 26

Statistics and Plotting


Convert vector output file to .csv
./opp_vec2csv.pl -F packetDelay results/run1.vec > packetDelays.csv

Read and use in GNU R


% R > d <- read.delim(packetDelays.csv") > summary(d$delay) Min. 1st Qu. Median Mean 3rd Qu. Max. 0.00400 0.01200 0.01200 0.01211 0.01400 0.01600 > boxplot(d$delay) > plot(density(d$delay)) > _

[Car2X] Summer 2012

OMNeT++

27

Logging and Debugging


Logging
EV << Variable i is now << i << std::endl;

Watches (and interaction with watched variables)


WATCH(i); WATCH_OBJ(cObject); WATCH_PTR(cObject*); WATCH_LIST(std::list<>); WATCH_RW(i);

[Car2X] Summer 2012

OMNeT++

28

Error Handling
ASSERT(7 < 42); if (7 >= 42) { this->error(this shouldnt have happened); opp_error(same); throw cRuntimeError(same); }

Kernel will catch and display errors


<!> Error in module (Txc2) Tictoc2.tic (id=2) during network initialization: Model error: ASSERT: condition 7 < 42 false in function initialize, txc2.cc line 41.

or allow debugger to trap errors


[General] debug-on-errors = true
[Car2X] Summer 2012 OMNeT++ 29

Error Handling
[General] debug-on-errors = true

Run simulation in gdb


% gdb --args opp_run u Cmdenv l /model-lib r 0 (gdb) run <!> Error in module: ASSERT: condition i > 42 false TRAPPING on the exception above, due to a debug-onerrors=true configuration option. Is your debugger ready? (gdb) up 4 tx2.cc:33 (gdb) print i $1 = 7 (gdb) _

ASSERT(i > 42);

[Car2X] Summer 2012

OMNeT++

30

Documentation
NED and MSG files
// // Documentation // simple MyModule { parameters: int foo; // The Foo int bar; // The Bar gates: // Leave unconnected input in; }

C++ code
/** * Documentation */ class TicModule { public: int foo; int bar;

/**< The Foo */ /**< The Bar */

/** Dont call before 7 */ void main(); };

[Car2X] Summer 2012

OMNeT++

31

Work Smart not Hard


Make (ample) use of scripting
Less error-prone than dozens of manual steps (and less work) Ideal documentation
% ./runall.sh Building simulation... Copying binary/data to target machines... [100%] Starting simulations... [100%] Waiting for runs to finish... Error check of log files... [93%] Collecting results... [0%] Transforming to csv... [0%] Plotting results... [0%] ERROR: Sanity check failed. Run 927 incomplete. % _
[Car2X] Summer 2012

OMNeT++

32

Pitfalls
Common and very common pitfalls
Use of pointer after send()
Pointer now owned by kernel; might have moved/destroyed data

Use of constructor for initializing members


Multiple simulation runs per binary execution

Use of finish() method for cleanup


Other modules (or kernel) might still need data or messages

Use of global variables / static members


Who initializes those? When?

Using std::map<cModule*, int>::const_iterator


Nondeterminism: order of iteration dependent on raw pointer value

[Car2X] Summer 2012

OMNeT++

33