1. Getting started

UP: Contents

Since the most common application area of OMNeT++ is the simulation of telecommunications networks, we'll borrow our topic from there. For a start, let us begin with a "network" that consists of two nodes. The nodes will do something simple: one of the nodes will create a packet, and the two nodes will keep passing the same packet back and forth. We'll call the nodes "tic" and "toc".

Here are the steps you take to implement your first simulation from scratch:

1. Create a working directory called tictoc, and cd to this directory.

2. Describe your example network by creating a topology file. Topology files are written in the NED language (Network Definition). A NED topology file is a text file that identifies the network's nodes and the links between them. You can create it with your favourite text editor.

You can find a detailed description of the NED language in Section 3 of the OMNeT++ manual (it's also in the doc directory of your OMNeT++ installation).

Let's call it tictoc1.ned:

simple Txc1
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
tic: Txc1;
toc: Txc1;
tic.out --> { delay = 100ms; } --> toc.in;
tic.in <-- { delay = 100ms; } <-- toc.out;

The file is best read from the bottom up. Here's what it says:

You can find more information on Simple modules in Section 4 of the OMNeT++ manual.

3. We now need to implement the functionality of the simple module Txc1. This is achieved by writing a C++ file txc1.cc :

#include <string.h>
#include <omnetpp.h>
using namespace omnetpp;
class Txc1 : public cSimpleModule
// The following redefined virtual function holds the algorithm.
virtual void initialize() override;
virtual void handleMessage(cMessage *msg) override;
// The module class needs to be registered with OMNeT++
// 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");
// 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"); // send out the message

The Txc1 simple module type is represented by the C++ class Txc1, which has to be subclassed from cSimpleModule, and registered in OMNeT++ with the Define_Module() macro.

We redefine two methods from cSimpleModule: initialize() and handleMessage(). They are invoked from the simulation kernel: the first one only once, and the second one 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 a continuous 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. (You could also specify a simulation time limit or CPU time limit in the configuration file, but we don't do that in the tutorial.)

4. We now create the Makefile which will help us to compile and link our program to create the executable tictoc:

$ opp_makemake

This command should have now created a Makefile in the working directory tictoc.

Windows+MSVC users: the command is opp_nmakemake, and it will create Makefile.vc. Note: MSVC is only supported in the commercial version OMNEST.

5. Let's now compile and link our very first simulation by issuing the make command:

$ make
Windows+MSVC: type nmake -f Makefile.vc. 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 in every command window in which you want to compile. Note: MSVC is only supported in the commercial version OMNEST.

If there are compilation errors, you need to rectify those and repeat the make until you get an error-free compilation and linking.

It might be more convenient to use the OMNeT++ IDE for the tutorial. Creating a new project, adding files and building your project is fully automated in the IDE. There is no need to manually create the Makefile either.

6. 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 (yes, several networks can live in the same simulation program), you can pass parameters to the model, explicitly specify seeds for the random number generators etc.

Create the following very simple omnetpp.ini:

network = Tictoc1

tictoc2 and further steps will all share the following omnetpp.ini:

# This file is shared by all tictoc simulations.
# Lines beginning with `#' are comments
# nothing here
[Config Tictoc1]
network = Tictoc1
[Config Tictoc2]
network = Tictoc2
[Config Tictoc3]
network = Tictoc3
[Config Tictoc4]
network = Tictoc4
Tictoc4.toc.limit = 5
[Config Tictoc5]
network = Tictoc5
**.limit = 5
[Config Tictoc6]
network = Tictoc6
[Config Tictoc7]
network = Tictoc7
# argument to exponential() is the mean; truncnormal() returns values from
# the normal distribution truncated to nonnegative values
Tictoc7.tic.delayTime = exponential(3s)
Tictoc7.toc.delayTime = truncnormal(3s,1s)
[Config Tictoc8]
network = Tictoc8
[Config Tictoc9]
network = Tictoc9
[Config Tictoc10]
network = Tictoc10
[Config Tictoc11]
network = Tictoc11
[Config Tictoc12]
network = Tictoc12
[Config Tictoc13]
network = Tictoc13
[Config Tictoc14]
network = Tictoc14
[Config Tictoc15]
network = Tictoc15
record-eventlog = true
[Config Tictoc16]
network = Tictoc16
**.tic[1].hopCount.result-recording-modes = +histogram
**.tic[0..2].hopCount.result-recording-modes = -vector

7. Once you complete the above steps, you launch the simulation by issuing this command:

$ ./tictoc

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

To run the simulation from the IDE, just right click on omnetpp.ini and select Run as, then OMNeT++ Simulation.

8. Press the Run button on the toolbar to start the simulation. What you should see is that tic and toc are exchanging messages with each other.

The main window toolbar displays the simulated time. This is virtual time, it has nothing to do with the actual (or wall-clock) time that the program takes to execute. Actually, how many seconds you can simulate in one real-world second depends highly on the speed of your hardware and even more on the nature and complexity of the simulation model itself.

Note that it takes zero simulation time for a node to process the message. The only thing that makes the simulation time pass in this model is the propagation delay on the connections.

9. You can play with slowing down the animation or making it faster with the slider at the top of the graphics window. You can stop the simulation by hitting F8 (equivalent to the STOP button on the toolbar), single-step through it (F4), run it with (F5) or without (F6) animation. F7 (express mode) completely turns off tracing features for maximum speed. Note the event/sec and simsec/sec gauges on the status bar of the main window (only visible when the simulation is running in fast or express mode).

10. You can exit the simulation program by clicking its Close icon or choosing File|Exit.

There are some typical mistakes that people who are new to OMNeT++ make:
- By default, the module type name must be the same in both the .ned and the .cc files. It is a common mistake to either forget the Define_Module() macro, or mistype the module name so it is not the same in the .ned and .cc files. These mistakes yield the following errors, respectively:
Error in module (omnetpp::cModule) Tictoc1 (id=1) during network setup: Class "Txc1" not found – perhaps its code was not linked in, or the class wasn't registered with Register_Class(), or in the case of modules and channels, with Define_Module()/Define_Channel().
Error in module (omnetpp::cModule) TicToc1 (id=1) during network setup: Submodule tic: cannot resolve module type 'Txc1' (not in the loaded NED files?), at /omnetpp-5.0/samples/tictoc/tictoc1.ned:26.
- Also, you must run opp_makemake and make after adding a .cc file to the project. Failing to do so will be indicated by the first error message above. If you use the OMNeT++ IDE, this is done automatically.

Sources: tictoc1.ned, txc1.cc, omnetpp.ini

NEXT: 2. Enhancing the 2-node TicToc