You are on page 1of 11

OMNET++ Tutorial/Homework 1

Problem: Our task is to create a generator that will generate arrival rates for customers at a bank in between 1 and 8 minutes with equal probability (as in the class example).

Design steps: Step 1. Create a working directory called my_example1 in the C:\OMNET++\samples directory, and cd to this directory. Step 2. Describe your example network by creating a topology file. A topology file is a text file that describes the network's nodes and the links between them. The easiest way to do it, is to create a couple of .ned files, one for each simple module, and one for the network that includes all the simple modules. For our case, we have the network file: my_net1.ned, and two modules: the generator module (with an associated description file gen1.ned) and a sink module (sink1.cpp) which simply has the role to destroy the received messages. You can create the .ned files using your favorite text editor. The file my_net1.ned should contain:
// // This file is the network description for my first OMNET++ example // // import "gen1"; // imports all the code from gen1.ned file // alteratively, for simple examples, you can put the // code in gen.ned at the top of the net1.ned file import "sink1"; // imports all the code from sink1.ned file module Network1 //declare network object Network1 submodules: first: Generator; //one instance of the Generator module //object; // The Generator module object is declared // in gen1.ned as a simple module object parameters: number_rand = input, //the number of messages and the

// probability will be specified // at runtime (or from the config // file) prob = input; sink: Sink; connections: first.out --> sink.in; endmodule network my_net1 : Network1 endnetwork

The gen1.ned file should contain


simple Generator //declaration of simple module object parameters: number_rand, prob; //declare parameters for the module gates: out: out; endsimple

The sink1.ned file should contain


simple Sink gates: in: in; endsimple //declaration of simple module object

Important observations: 1) Pay attention to the matching names for modules: Network1 for the compound module which represents the network, Generator, and Sink for the simple modules. The network declaration in the end of the file associates the name of the file my_net1 with the name of the object module Network1. 2) In the network description, submodules are declared as first: Generator first is the name of the module as it will appear in the network; Generator is the object module which was declared in gen1.ned. sink: Sink sink is the name of the module as it will appear in the network; Sink is the object module which was declared in sink1.ned.

You could have many instances of an object Generator (or Sink for that matter), if you desire to implement simultaneously several generators. To illustrate this, consider a second example. Create a new file my_net2.ned as follows:
// // This file is the network description for my first OMNET++ example // // import "gen1"; // imports all the code from gen.ned file // alteratively, for simple examples, you can put the // code in gen.ned at the top of the net1.ned file import "sink2"; // imports all the code from sink2.ned file module Network2 //declare network object Network1 submodules: first: Generator; //one instance of the Generator module //object; // The Generator module object is declared // in gen1.ned as a simple module object parameters: number_rand = input, //the number of messages and the // probability will be specified // at runtime (or from the config // file) prob = input; second: Generator; //second instance for the Generator module //object; // The Generator module object is declared // in gen1.ned as a simple module object parameters: number_rand = input, //the number of messages and the // probability will be specified // at runtime (or from the config // file) prob = input; sink: Sink2; connections: first.out --> sink.in1; second.out --> sink.in2; endmodule

network my_net2 : Network2 endnetwork

We also need to describe Sink2 in sink2.ned


simple Sink2 //declaration of simple module object gates: in: in1, in2; endsimple

Note: the sink module should have to in gates, one for each generator. You cannot have multiple inputs in one gate. Step 3. Visualize and maybe further edit the newly created ned files, using the graphical editor. In windows explorer, double click on my_net1.ned and my_net2.ned and they will be opened with the graphical editor. Here is the visualization for my_net2.ned:

If you click with your mouse on the NED source button, you will be able to see the network description (without the end declaration). Also, by right clicking any of the modules, you can select to maybe change the appearance of the module, to see the ned code description, to see the modules parameters, or to rename and delete the module.

We will change the appearance for the second module: select appearance, than chose icon as in the next figure: check icon, and then scroll to select block/departure_l, then press OK.

Here is the result you should get:

Step 4. Add functionality. Up to know we have only the network topology description, with no functionality. Since the modules need to do something, we will implement a cpp file for each of the modules types. The name of the cpp file should be identical with its corresponding ned file, i.e., gen1.ned gen1.cpp; sink1.cpp; sink2.ned sink2.cpp. sink1.ned The Generator simple module type is represented by the C++ class Generator, which has to be subclassed from cSimpleModule, and registered in OMNeT++ with the Define_Module() macro. We need to redefine one single function from cSimpleModule: activity(). The activity() function needs to be interrupted, otherwise will continuously run; this is achieved by introducing the function wait(). While wait, the module passes the control to the simulation kernel, and other modules may be allowed to run code. The file simply gets from the input (config file) the parameters prob and number_rand, which are used to determine the type of the generated packet (with probability prob the generated packet is a data packet), and the number of packets that need to be generated. The packets are generated every int_arr seconds (which we fixed to be 120 seconds), the type of the paket (voice or data is encoded in the packet ), and then the packets are sent on the out gate towards the sink. The code is given below:
// gen1.cpp code // This file implements functionality for the generator module #include <omnetpp.h>

class Generator: public cSimpleModule { // This is a macro; it expands to constructor definition. Module_Class_Members(Generator, cSimpleModule, 8192); // 8192 estimated stack size needs // The following redefined virtual function implements the // module functionality. virtual void activity(); }; // The module class needs to be registered with OMNeT++ Define_Module(Generator); void Generator::activity() {

const ia_time = 120; double temp; int num_pkts = par("number_rand"); double p1 = par("prob"); for (int i=0; i<num_pkts; i++) { // create message cMessage *msg = new cMessage("packet"); temp = (double)rand()/RAND_MAX; if (temp < p1) { ev << "Generate data packet\n"; msg -> setKind(1); } else { ev << "Generate voice packet\n"; msg -> setKind(0); } send(msg, "out"); wait((double)ia_time); } }

We implement a very simple sink1.cpp functionality: the sink receives a message, test for the type of packet and prints a message regarding the type, then deletes the packet. The code is implemented as a process, with the receive() function providing a break in the infinite loop. The sink1.cpp file is given below:
// sink1.cpp code // This file implements functionality for the very simple sink module #include <omnetpp.h> class Sink: public cSimpleModule { // This is a macro; it expands to constructor definition. Module_Class_Members(Sink, cSimpleModule, 8192); // 8192 estimated stack size needs

// The following redefined virtual function implements the // module functionality. virtual void activity(); }; // The module class needs to be registered with OMNeT++ Define_Module(Sink); void Sink::activity() { while(1) { cMessage *msg = receive(); int pkt_type = msg -> kind(); if (pkt_type ==1) ev << Received data packet\n; else ev << Received voice packet\n; delete msg; } }

Step 5. We now create the Makefile which will help us to compile and link our program to create the executable my_example1. Note that the name of the executable is always the same as the name of the directory that holds the files. In the command window, type the following sequence of commands:
opp_nmakemake -f

This creates a Makefile.vc in the working directory my_example1.


nmake f Makefile.vc depend nmake f Makefile.vc

Notes: 1) If you get 'nmake' is not recognized as an internal or external command..., find vcvars32.bat somewhere in the MSVC directories, and run it first thing in every command window in which you want to compile. If there are compilation errors, you need to rectify those and repeat the make until you get an error-free compilation and linking.

2) If depend is not recognized, ignore and continue with next step (newer versions add dependencies automatically).

Step 6. Create the configuration file If you start the executable now, it will complain that it cannot find the file omnetpp.ini, so you have to create one. omnetpp.ini tells the simulation program which network you want to simulate (remember that we have defined two different networks, one with one single generator, and the other one with two). In the configuration/initialization file, you can pass parameters to the model, explicitly specify seeds for the random number generators etc. We will create a very simple omnetpp.ini file:
# This file is shared by all network descriptions: Network1 and # Network2 # Lines beginning with `#' are comments [General] preload-ned-files=*.ned network=Network1 # this line is for Cmdenv, Tkenv will still let you choose from a dialog [Parameters] my_net1.first.number_rand = 10; my_net1.first.prob = 0.5; #possible parameters for the network 2 implementation: my_net2.first.number_rand = 10; my_net2.first.prob = 0.5; my_net2.second.number_rand = exponential(5); my_net2.second.prob = 1;

The config. file does not specify the network (the simulation program ask it in a dialog when it starts). Step 7. Once you complete the above steps, you launch the simulation by issuing this command:
my_example1

and hopefully you should now get the OMNeT++ simulation window.

Step 8. Press the Run button on the toolbar to start the simulation. Select the network: Network1 (Network2 still needs to be finalized). What you should see is the packet going from the module first to the sink module, and several print-out messages, about the events and about the type of packets generated and received.

Homework assignment: Finalize Network2, by implementing gen2.cpp and sink2.cpp, and appropriately modify omnetpp.ini if needed. The sink should be able to distinguish if the message received is from module first or module second and should print messages such as: message from first, message from second. Further, modify gen2.cpp to generate messages with a random inter-arrival time, uniformly distributed in (0, 240) seconds. Turn in: listing for all the modified files, and screenshots for the program (using Network1 and Network2).

Note: If you cut and paste the text of the tutorials, you may have to retype in the Microsoft Visual C++ Development Environment some special characters, such as , which may not be correctly interpreted.