next up previous contents index
Next: 5 Physical Layer Modules Up: A Mobility Framework for Previous: 3 Getting the Mobility   Contents   Index


4 Building Own Simulations

This section explains the basic concepts behind the Mobility Framework. The class hierarchy is explained and all relevant functions of the Basic* modules are introduced. For the detailed description of the functionality of the individual modules read Sections 5 - 7 and also refer to the Neddoc and API reference.

4.1 The Basic Module concept

All our Host submodule classes have a common base class BasicModule. The BasicModule itself is derived from cSimpleModule (OMNeT++) and BlackboardAccess which provides the functionality to subscribe for and publish information on the Blackboard module. The usage of the Blackboard is explained in Section 6. BasicModule

The BasicModule uses the multi-stage initialization of OMNeT++ so all modules in the MF have to be implemented with two-stage initialization. In case you use the Blackboard you have to do all your publish calls in stage 0 and the subscribe calls have to be done in stage 1! This is to explicitly avoid that a subscription to a parameter can happen before that parameter is published.

In the template files the initialize(int) functions already contain the call of the initialize(int) function of the Basic Module this module is derived from. Do not delete this line as the obligatory parameters of the Basic Modules have to be initialized, too!

Additionally the BasicModule provides the logName() function, which returns the ned module name and the OMNeT++ module index() of the Host module this module belongs to. logName() is used in the debug macro for identification of the host the debug output comes from. You can use the EV «``your debug output'' macro to print debug messages. Address Concept

We use the OMNeT++ module id()s for addressing in the MF. The nic module id() is used as mac address and the netwLayer module id() as network layer address. The netwLayer id() is also used as application layer address. In order to obtain the address of the module we provide a myApplAddr(), myNetwAddr() and myMacAddr() function in the BasicApplLayer, BasicNetwLayer and BasicMacLayer modules respectively.

The netw2mac() function of the ChannelControl module provides a simple ARP like translation of network addresses to MAC addresses. However by redefining the getMacAddr() function of the BasicNetwLayer you can implement your own ARP functionality. Naming Conventions

There are some naming conventions for the modules in the ned files, you have to follow. Not following these naming conventions will result in segmentation faults upon execution of your code!!!

All host modules have to include the characters host or Host somewhere in its name. Whereas most of the example networks just use host as a ned module name, you could also come up with names like baseStationHost and mobileHost in order to create a centralized base station network.

For more or less all the other ned modules the names cannot be changed. Those are: channelcontrol, blackboard, net, phy, snrEval. However, it is a good practice to also keep the default names for the other modules (namely, appl, nic, mobility). Basic* Modules

In order to have clearly defined interfaces that are easy to understand - and extend if necessary - we provide a Basic* module for each layer which in turn is derived from the global BasicModule explained above. The concept of a Basic* module is to have a base class which takes care of the necessary work that has to be done but is not of specific importance for the real functionality. The general derivation structure of a Mobility Framework module is shown in Figure 3. The Basic* modules also provide a very basic functionality in terms of ``the BasicNetwLayer is capable of forwarding messages to and from upper and lower layers but has no routing functionality at all yet''. The idea is to have the possibility to easily extend or adapt modules of different layers to the specific requirements of the simulation. To serve this purpose we defined two kinds of functions: handle*Msg() functions and convenience functions.

Figure 3: The general derivation structure
\includegraphics[width=7cm]{derivation} handle*Msg() Functions

The handle*Msg() functions contain the actual protocol functionality. They are called each time a corresponding message arrives and contain all necessary processing and forwarding information for messages where required. We provide three different functions to handle the three different kinds of message events possible:

The easiest way to implement timers in OMNeT++ are self messages. handleSelfMsg() thus is the place to handle all timer related things and to initiate actions upon timeouts.
This function is called every time a message has arrived from an upper layer. The message already has the corresponding layer n format (i.e. it is already encapsulated). After processing the message can be forwarded to the lower layers with the sendDown() function, if necessary.
For messages from lower layers it is the other way around. After being processed they have to be forwarded to upper layers if necessary. This is done by using the sendUp() function which also takes care of decapsulation. convenience Functions

The convenience functions are defined to facilitate common interfaces and to hide inevitable interface management from the user. Here we provide three different functions:

This function is called right after a message has arrived from the upper layers. It is responsible for encapsulation of the layer n+1 message into a layer n message. This implies to provide all necessary header information and if applicable also the conversion of layer n+1 header information into layer n information (in case of the network layer to convert the application or transport layer address into a network address). After this the message is passed to the handleUpperMsg() function.
sendUp() is the function to be called if a message should be forwarded to upper layers and is usually called within handleLowerMsg(). It decapsulates the message before sending it to the layer n+1 module.
Sending messages to layer n-1 is done with the sendDown() function. Sometimes it may be necessary to also provide or process additional meta information here. In the case of the network layer for example it may be necessary to provide a next hop. The network layer destination address usually contains no information about the next-hop MAC address a message has to be forwarded to on its way to the destination so it has to be translated (ARP does this for IP).
In case you want to delay the point of time the message is sent to the upper layer, you can use this function. The time the message should be delayed can be given as a parameter.
The same as sendDelayedUp, but for sending delayed messages to the lower layer.

These six functions are provided (with slide differences) in the Basic* module for each layer of the MF. Usually the three handle*Msg() and the initialize(int) and finish() functions are the only functions a programmer has to re-implement to create his/her own module and the functionality of it. The convenience functions should be used to serve the above described tasks so that newly implemented modules remain compatible with (almost) any other module implemented for the MF. The convenience functions cannot be changed in derived modules.

The tasks of the different modules and a more detailed description of the Basic* modules can be found in the following sections.

4.2 The Message Concept

In order to provide basic functionality like encapsulating and decapsulating messages in the Basic* modules we need to have fixed message formats for every layer. The provided message types have the most important fields needed for the corresponding layer. These message types with these fields are obligatory and can only be extended but not exchanged. Here is a list of all base message classes and their parameters: Creating your own message

If you need additional parameters you can derive your own message class from one of the basic message classes in the OMNeT++ style, in case of the network layer message:

cplusplus {{
#include "NetwPkt_m.h"

class NetwPkt;

message YourPkt extends NetwPkt
        int     extraField1;
        double  extraField2;
Please note that the name of the included .h file has to be extended with _m as this is the file OMNeT++ creates out of a .msg file. Using an own message

Now you have defined your own message, the next step is to teach the framework how to create it. To do so, you have to overwrite the createCapsulePkt function in YourNetwModule.h:

virtual NetwPkt* createCapsulePkt() {
   return new YourPkt;
When creating a new YourPkt message within your simulation it has to be done like this:
YourPkt* pkt = static_cast<YourPkt *>(createCapsulePkt());
The framework does the same and is hence able to create YourPkt without even knowing that such a thing would spring into existence.

These steps are necessary to be able to do the following unavoidable cast operation. A message is usually given to you as a parameter in the handleUpperMsg() and handleLowerMsg() function in the basic message format. So, if you want to have access to the extra fields you have to cast the message into your format. For YourNetwModule you could use the following code:

void YourNetwModule::handleUpperMsg(NetwPkt *packet)
  YourPkt *pkt = check_and_cast<YourPkt *>(packet);
  // do something with the message...
} Control Information Classes

OMNeT++ (version 3.0a4 or higher) allows you to define Control Information classes. They can be used to add meta information to a message that is only relevant for the next processing layer. When that layer receives this message it then can remove and process this information. As you can see in the tables, AirFrame and the NetwPkt have such a control information class.

The SnrControlInfo is used to pass s(i)nr information to the decider so that it can calculate bit errors based on the s(i)nr information of that message. The MacControlInfo contains the next hop MAC address the message should be forwarded to. Currently the MF provides no means to extend the control information attached to a message. If you need to exchange additional meta information you would have to add it as a ``normal'' parameter to your derived message as only one control information is allowed per message. However please tell us in case you need additional control information as we might extend the SnrControlInfo or MacControlInfo respectively if appropriate. Currently we only provide the absolutely necessary information. But especially the MacControlInfo serves as interface between MAC and network layer that we want to provide as powerful as possible.

4.3 The Nic Concept

A nic is a network interface card that includes physical layer functions like transmitting, receiving, modulation as well as medium access mechanisms. The nic module in the MF therefore is divided into a physical layer like part (snrEval and decider) and a MAC layer (macLayer). The snrEval module can be used to compute some sn(i)r information for a received message whereas the decider module can process this information to decide whether a message got lost, has bit errors or is correctly received. Therefore the decider only handles received messages and not messages that should be sent. The corresponding compound module with its simple modules is shown in Figure 4.

Figure 4: The structure of a nic module

The reason for putting the physical and the MAC components into one compound module is easily explained. For most lower layer protocols the MAC and the physical layer have to be coordinated, so for one protocol (e.g. IEEE 802.11) there will be a corresponding snrEval module as well as a corresponding decider module as well as a corresponding mac module. So, if you decide to run a certain routing protocol over a certain PHY/MAC protocol you simply need to choose the corresponding nic module when building the host (see Section 3.2).1

In the following the physical layer modules are explained in more detail.

4.3.1 snrEval

The structure of the snrEval modules is a little different from those of the other modules. The handleLowerMsg() function is split into two functions in order to simulate the transmission delay. Detailed examples for using these functions are given in the YourSnrEval template files.

This function is called in the moment the reception begins, i.e. in the moment the first bit arrives. Everything that is necessary to be done at the start of a reception can be done here, e.g. create and initialize an SNR-list to store SNR values, put the frame into a receive-buffer etc.

This function is called when the transmission of a message is over. Here you can do whatever is necessary before to message is handed on to the decider, e.g. take the message out of the receive-buffer, call the sendUp funtion...

next up previous contents index
Next: 5 Physical Layer Modules Up: A Mobility Framework for Previous: 3 Getting the Mobility   Contents   Index
Daniel Willkomm 2007-01-12