Tags:
create new tag
, view all tags

Introduction to Discrete Event Simulation with OMNeT++

Objectives

We will learn the basics of discrete-event simulation by setting up and running a simple OMNeT++ simulation project through its IDE (Integrated Development Environment).

Procedure

We will create an OMNeT++ simulation that consists of two modules connected via two unidirectional communication links. One of the modules will generate a packet and send to the other, and in response the other module will send a packet to the first one. This activity will continue until we stop the program. The network we create will look like this:
omnetpp-tictoc1.png
We will need to create three files to achieve this:
  1. a topology description file "NED file"
  2. a C++ class file that actual activity, such as packet generation and processing, happens
  3. a simulation configuration file, omnetpp.ini
The details of the procedure are as follows
  1. Start the OMNeT++ IDE via a console screen through this command: omnetpp
  2. Select a workspace to store your OMNeT++ projects. Note that you must select a directory with no spaces in the path. You can use the same workspace for multiple projects.
  3. Start a new OMNeT++ project in your workspace from the File menu by selecting File --> New --> OMNeT++ project. Choose a name for your project and click Next (Let's choose tictoc1 as the project name, we will do the basic OMNeT++ tutorial). On the next screen choose Empty Project. You may then choose Finish or click Next to examine the additional options (we don't need to modify them).
  4. Double click on your project in the Project Explorer to expand the project files. Note: here, you may need to delete the automatically created file package.ned in your project and create a new file (I will check why this is needed).
  5. We first create a topology file to describe our first example network. A topology file is a text file that identifies the network's nodes and the links between them. Here is the code of the topology description file of your first experiment:
    //
    // This file is part of an OMNeT++/OMNEST simulation example.
    //
    // Copyright (C) 2003 Ahmet Sekercioglu
    // Copyright (C) 2003-2008 Andras Varga
    //
    // This file is distributed WITHOUT ANY WARRANTY. See the file
    // `license' for details on this and other legal matters.
    
    simple Txc1
    {
            gates:
            input in;
            output out;
    }
    
    // Two instances (tic and toc) of Txc1 connected both ways.
    // Tic and toc will pass messages to one another.
    network Tictoc1
    {
            submodules:
            tic: Txc1;
            toc: Txc1;
            connections:
            tic.out --> {  delay = 100ms; } --> toc.in;
            tic.in <-- {  delay = 100ms; } <-- toc.out;
    }
    The file tells us that there is a network called Tictoc1, and has two components: tic and toc. They are both instances of a simple module Txc1. It also tells us how the modules are connected, including the propagation delay of the connections. The term simple is important. This means that there has to be a C++ source code block provided to implement the functionality of the simple module Txc1. The topology file also tells us that simple module Txc1 has one input and one output gate. All logical I think. Let's add this new NED file to our first simulation.

    Choose File --> New --> Network Description File (NED) then select your project folder tictoc1, and give the file a name tictoc1.ned. On the next screen, select Empty NED file and choose finish. By default, this will bring up an empty screen with the NED file in Design mode. Instead, we will switch to Source mode (see the bottom left of the pane), and copy and paste the above NED code into this file.

  6. We now need to implement the functionality of the simple module Txc1. This is where all the fun is!
    //
    // This file is part of an OMNeT++/OMNEST simulation example.
    //
    // Copyright (C) 2003 Ahmet Sekercioglu
    // Copyright (C) 2003-2008 Andras Varga
    //
    // This file is distributed WITHOUT ANY WARRANTY. See the file
    // `license' for details on this and other legal matters.
    
    #include <string.h>
    #include <omnetpp.h>
    
    class Txc1 : public cSimpleModule
    {
            protected:
            // The following redefined virtual function holds the algorithm.
            virtual void initialize();
            virtual void handleMessage(cMessage *msg);
    };
    
    // The module class needs to be registered with OMNeT++
    Define_Module(Txc1);
    
    void Txc1::initialize()
    {
            // Initialize is called at the beginning of the simulation.
            // To bootstrap the tic-toc-tic-toc process, one of the modules needs
            // to send the first message. Let this be `tic'.
            
            // Am I Tic or Toc?
            if (strcmp("tic", getName()) == 0)
            {
                    // create and send first message on gate "out". "tictocMsg" is an
                    // arbitrary string which will be the name of the message object.
                    cMessage *msg = new cMessage("tictocMsg");
                    send(msg, "out");
            }
    }
    
    void Txc1::handleMessage(cMessage *msg)
    {
            // The handleMessage() method is called whenever a message arrives
            // at the module. Here, we just send it to the other module, through
            // gate `out'. Because both `tic' and `toc' does the same, the message
            // will bounce between the two.
            send(msg, "out");
    }
    The Txc1 simple module type is represented by the C++ class Txc1, which has to be subclassed from OMNeT++'s own cSimpleModule, and registered in the OMNeT++ system with the Define_Module() macro. We have to provide the code for two methods: initialize() and handleMessage(). They are called by the simulation kernel. initialize() is called only once, and handleMessage() is called whenever a message arrives at the module.

    In initialize() we create a message object cMessage, and send it out on gate out. Since this gate is connected to the other module's input gate, the simulation kernel will deliver this message to the other module in the argument to handleMessage() -- after a 100ms propagation delay assigned to the link in the NED file. The other module just sends it back (another 100ms delay), so it will result in messages to continuously ping-pong.

    Messages (packets, frames, jobs, etc) and events (timers, timeouts) are all represented by cMessage objects (or its subclasses) in OMNeT++. After you send or schedule them, they will be held by the simulation kernel in the "scheduled events" or "future events" list until their time comes and they are delivered to the modules via handleMessage().

    Note that there is no stopping condition built into this simulation: it would continue forever. You will be able to stop it from the GUI. Or, we can provide a simulation time limit or CPU time limit in the configuration file omnetpp.ini (more later).

    Let's now get this C++ code into our simulation. Choose File --> New --> File and again as in previous step, select your project folder (tictoc1), give the file name txc1.cc. Be sure to use the .cc extension, otherwise OMNeT++ will not recognize it as a C++ class file. Copy and paste the above C++ code into this file.

  7. We are nearly there! Finally, we need to create an omnetpp.ini file for the project. Choose File --> New --> Initialization File (ini). Make sure that the file is named omnetpp.ini, and use the Empty Ini File template. Switch to Source mode, and edit the omnetpp.ini file to content to look like this:
    [General]
    network = Tictoc1
  8. Your project is now ready to be compiled. Choose Project --> Build All from the top toolbar. Observe that the compilation finishes without any errors. If there are any errors in your project you need to fix them before proceeding.
  9. Start running the project by choosing Run --> Run As, double click on OMNeT++ Simulation then press Run on the simulation window just popped up.

Questions

  1. In which file do we define our network topology?
  2. How many nodes and links does our network have?
  3. What does initialize() function do?
  4. What does handleMessage() function do?
  5. What does send() simulation kernel call do in the used in the initialize() function?
  6. What does the Define_module() macro do? Can this macro be used in a header file (.h file) and why?
  7. In handleMessage() function, can we use another send() function right after the first send() to send out the same message?
  8. Following activities and questions are related to dynamic memory allocation and de-allocation in C++:
    1. Locate the following two statements in the initialize() function
      cMessage *msg = new cMessage("tictocMsg");
      send(msg, "out");
      and comment them out. Rebuild the simulation model and run again. What does happen?
    2. Now, put these lines back in. But insert delete msg; between the cMessage ... and send ... statements. Does the code compile without errors? If yes, run it. Does it run without any errors? If no, what is the error reported?
    3. Modify the line containing delete ... as follows delete msg; msg = NULL, rebuild and run the code. What does happen?
    → Most of the run-time errors you will encounter in your experiments will be related to dealing with invalid pointer references. If you keep to the habit of assigning NULL value to a pointer variable referencing to a de-allocated memory block, you will be spending almost no time on finding the errors. Otherwise frustrating hours may pass without any results!

Topic revision: r3 - 2013-07-22 - AhmetSekercioglu
 
This site is powered by the TWiki collaboration platformCopyright © 2008-2017 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback