You are on page 1of 274

QualNet 3.

6 Developer’s Guide

For QualNet Developer Version 3.6

Scalable Network Technologies, Inc.


6071 Bristol Parkway, Suite 200
Culver City, CA 90230

Phone: 310-338-3318
Fax: 310-338-7213

http://www.scalable-networks.com
http://www.qualnet.com
Copyright Information

©2003 Scalable Network Technologies, Inc. All rights reserved.

QualNet is a registered trademark of Scalable Network Technologies, Inc.

All other trademarks and trade names used are property of their respective companies.

Scalable Network Technologies, Inc.


6071 Bristol Parkway, Suite 200
Culver City, CA 90230
Phone: 310-338-3318
Fax: 310-338-7213
http://www.scalable-networks.com
http://www.qualnet.com
Table of Contents

CHAPTER 1
Introduction to QualNet .................................................... 1
Chapter Overview ......................................................... 1

CHAPTER 2
QualNet Architecture ........................................................ 3
Chapter Overview ......................................................... 3
QualNet Components ................................................... 4
File Organization........................................................... 5
Obtaining and Installing QualNet.............................................. 5
Directory Organization.............................................................. 6
Compiling QualNet ................................................................... 6
Active optimization and Debugging....................................................... 8
Customized Development: Modifying makefiles ....................... 8
Addons ........................................................................ 11
Addon Overview ..................................................................... 11
Activating an Addon Module................................................... 11
Creating an Addon.................................................................. 12
The 'Hello' Addon ................................................................................ 12

QualNet 3.6 Developer’s Guide 1


CHAPTER 3
QualNet Simulator .......................................................... 17
Chapter Overview ....................................................... 17
Events .......................................................................... 18
Events Overview ..................................................................... 18
Events and Messages ............................................................ 20
Types of Events ...................................................................... 20
Packet Events......................................................................................21
Sending Packets From Application Layer Using Layer Specific API ...23
Sending Packets Using Message API .................................................25
Message Info Field ..............................................................................28
Timer Events........................................................................................29
Setting Timers......................................................................................30
Canceling Timers.................................................................................30
Event Handling ....................................................................... 31
Experiment Configuration.......................................... 34
Reading Input from a Configuration File ................................. 34
Adding Trace Collection.......................................................... 36
Adding Statistics ..................................................................... 40
Collecting Statistics................................................................. 42
Time-based Statistics ............................................................. 42
Layering....................................................................... 47
Layering Overview .................................................................. 47
Application Layer Overview .................................................... 48
Transport Layer Overview ...................................................... 48
Network Layer Overview......................................................... 49
Link (MAC) Layer Overview .................................................... 49
Physical Layer Overview ........................................................ 49
Communication Between Layers .............................. 50
Communication Between Adjacent Layers ............................. 50
Communication Between Non-adjacent Layers...................... 52
Communication Among Layers Across Nodes ....................... 57

CHAPTER 4
Networking Using QualNet ............................................. 61
Chapter Overview ....................................................... 61
Application Layer ....................................................... 62
Application Layer Overview .................................................... 62
Application Layer Protocols In QualNet .................................. 63
Traffic Generating Protocols ................................................................64
Service Providing (Routing) Protocols .................................................65
Application Layer Organization: Files And Folders ................. 66

2 QualNet 3.6 Developer’s Guide


Writing and Adding an Application Protocol ........................... 67
Creating Files ...................................................................................... 67
Determining the Application Configuration Format ............................. 69
Integrating With QualNet..................................................................... 70
Adding Application Type ..................................................................... 70
Specifying the Event Dispatcher ......................................................... 71
Reading Configuration Parameters and Calling Init( )......................... 73
Application Initialization: Init( )............................................................. 77
Creating An Instance & Storing The State .......................................... 77
Initializing Timers ................................................................................ 79
Implementing Event Dispatcher: The Flow Controller......................... 80
Packet Exchange: Sending/Receiving Packets .................................. 83
Collecting and Reporting Statistics ..................................................... 85
The Finalize Function.......................................................................... 86
Tips For Application Layer Routing Protocol .......................... 87
Calling INIT ......................................................................................... 87
Application Initialization: Init( )............................................................. 88
Creating An Instance & Storing The State .......................................... 88
Initializing Tables................................................................................. 89
The Finalize Function.......................................................................... 89
Using QualNet Designer For Application Layer Development 90
Transport Layer .......................................................... 92
Transport Layer Overview ...................................................... 92
Transport Protocols in QualNet .............................................. 93
User Datagram Protocol (UDP)........................................................... 94
Transmission Control Protocol (TCP) ................................................. 95
Reservation Protocol (RSVP).............................................................. 97
Transport Layer Organization: Files and Folders ................... 97
Data Structure ........................................................................ 98
UDP..................................................................................................... 99
Transport............................................................................................. 99
General Data Structure ..................................................................... 100
APIs ...................................................................................... 102
Message............................................................................................ 102
Transport to Network API.................................................................. 106
Writing and Adding a Transport Protocol.............................. 106
Creating Files .................................................................................... 107
Deciding the Transport Configuration Format ................................... 108
Integrating With QualNet................................................................... 109
Adding Transport Type...................................................................... 109
Specifying The Event Dispatcher ...................................................... 110
Reading Configuration Parameters and Calling Init( )....................... 112
Transport Initialization: Init( )............................................................. 113
Initializing Timers .............................................................................. 114
Implementing Event Dispatcher: The Flow Controller....................... 115
Integration in IP Layer ....................................................................... 117
Packet Exchange: Sending/Receiving Packets ................................ 117
Statistics Collection & Reporting ....................................................... 121

QualNet 3.6 Developer’s Guide 3


The Finalize Function ........................................................................123
Network Layer ........................................................... 125
Network Layer Overview....................................................... 125
Network Layer Protocols in QualNet..................................... 126
IP (Version 4).....................................................................................127
IPv4 Addressing.................................................................................129
Fragmentation....................................................................................130
Routing Protocols ..............................................................................130
Unicast Routing .................................................................................131
Multicast Routing ...............................................................................132
QualNet Schedulers...........................................................................133
Strict Priority ......................................................................................133
Round Robin......................................................................................133
Weighted Round Robin......................................................................134
Weighted Fair ....................................................................................134
Self Clocked Fair ...............................................................................135
QualNet Queue Management Algorithms..........................................135
Best Effort Queue Management Techniques.....................................135
QoS (Diffserv) Queue Management Techniques...............................136
Access Lists.......................................................................................139
Route Map .........................................................................................140
Differentiated Services.......................................................................141
MPLS .................................................................................................141
Network Layer Organization: Files and Folders.................... 142
Data Structures ..................................................................... 143
Header File: network..........................................................................144
Header File: ip ...................................................................................145
APIs ...................................................................................... 150
APIs for Transport Layer Interface.....................................................150
APIs for IP Background Protocol ...................................................... 154
APIs for Mac to Network Layer Interface ...........................................158
APIs for Mac to Network Layer Callback Function ............................159
APIs Related to Router Function .......................................................160
Routing a Packet .................................................................. 161
Writing and Adding a Network Layer Routing Protocol......... 165
Explanation of a Routing Protocol? ...................................................165
QualNet Queuing Protocols .................................................. 165
Data Structure....................................................................................166
Specify Queue Type ..........................................................................166
Internal Structure Definitions for Queue ............................................166
Interfacing Functionalities ..................................................................167
Enqueue ............................................................................................168
Dequeue ............................................................................................168
Check if Queue is Empty ...................................................................169
Get Number of Packets in Queue......................................................169
Drop Packet from Queue ...................................................................169
Finalize ..............................................................................................170
Initialization ........................................................................................170

4 QualNet 3.6 Developer’s Guide


MAC Layer ................................................................. 173
MAC Layer Overview............................................................ 173
Functionality in the MAC Layer ......................................................... 173
MAC Layer Protocols in QualNet.......................................... 174
MAC Layer Organization: Files and Folders......................... 175
Data Structures..................................................................... 176
Element Descriptions ........................................................................ 177
Enumerations .................................................................................... 178
API Functions ....................................................................... 179
Writing and Adding MAC Layer Protocols ............................ 181
Adding a Wired Protocol ................................................................... 181
Configuration..................................................................................... 182
Integrating with QualNet.................................................................... 182
Protocol Initialization ......................................................................... 184
Event Dispatcher............................................................................... 186
Sending / Receiving Packet .............................................................. 188
Finalize Function ............................................................................... 190
Physical Layer........................................................... 192
Physical Layer Overview ...................................................... 192
Physical Layer Organization: Files and Folders ................... 192
Writing and Adding an Antenna Model ................................. 193
Adding An Antenna Model ................................................................ 193
Initialization ....................................................................................... 194
Antenna Model Functionality............................................................. 196
Writing and Adding a Radio Model ....................................... 198
Creating Files .................................................................................... 199
Integrating with QualNet.................................................................... 201
Writing and Adding a Channel Model ................................... 216
Adding a Propagation Model............................................................. 216
Initialization ....................................................................................... 217
Calculating Propagation Model Values ............................................. 219
Finalization ........................................................................................ 222
Adding a Mobility Model ....................................................... 222
Creating Files .................................................................................... 223

CHAPTER 5
QualNet Graphical User Interface (GUI)....................... 229
Chapter Overview ..................................................... 229
Overview of GUI Components ................................. 230
Using QualNet Animator .......................................... 231
Adding New GUI Parameters and Protocols ........................ 231
Variable Token .................................................................................. 232
Option Token..................................................................................... 235
Categories, Subcategories, and Applications ................................... 236

QualNet 3.6 Developer’s Guide 5


General Rules and Examples ............................................................237
Adding a New Routing Protocol.........................................................237
Adding GUI Animation to a Protocol ..................................... 238
Customizable Animation ....................................................................239
Communicating with QualNet Simulator and Animator......... 240
Initializing QualNet...............................................................................40
Runtime Interaction............................................................................241
Finalization.........................................................................................244
Using QualNet Analyzer ........................................... 245
Using QualNet Designer .......................................... 246
Adding Capabilities to Designer............................................ 246
Adding Protocols Using Designer ......................................... 248
Example: Adding a Simple ALOHA Protocol .....................................248
Specifying Simple ALOHA Data Structures .......................................251
Specifying Additional Protocol State Fields .......................................252
Specifying Statistics Variables...........................................................253
Creating the ALOHA State Diagram ..................................................254
Using QualNet Tracer ............................................... 261
Simulator Modifications......................................................... 261
Trace File...........................................................................................264
Updating Tracer Description Files ........................................ 265

6 QualNet 3.6 Developer’s Guide


CHAPTER 1 Introduction to
QualNet

1. Chapter Overview
This chapter provides an overview of the QualNet Developer’s Guide, it’s
purpose, and what to expect in it.

The intended audience of the Developer’s Guide are developers who want to use
the interface and programming functions in QualNet for their own simulation
purposes.

QualNet 3.6 Developer’s Guide 1


Introduction to QualNet

2 QualNet 3.6 Developer’s Guide


CHAPTER 2 QualNet
Architecture

The QualNet architecture has a variety of components, each of which are


important to the overall understanding of how QualNet works.

1. Chapter Overview
This chapter on QualNet Architecture covers the following topics:
• QualNet Components
• File Organization
• Add-ons

QualNet 3.6 Developer’s Guide 3


QualNet Architecture

2. QualNet Components
QualNet Developer has several core components, as well as various add-on
components.

The core components of QualNet are as follows:


• QualNet Simulator
• QualNet Animator
• QualNet Tracer
• QualNet Importer
• QualNet Analyzer
• QualNet Designer

Descriptions, functions, and usage instructions for each of the QualNet Developer
components is available in the QualNet User Manual. Contact
support@qualnet.com for more information on this and other QualNet
documentation.

4 QualNet 3.6 Developer’s Guide


3. File Organization
This section covers the following topics:
• Obtaining and Installing QualNet
• Directory Organization
• Compiling QualNet
• Customized Development: Modifying makefiles

3.1 Obtaining and Installing QualNet


QualNet software can be downloaded from the SNT website, http://www.scalable-
networks.com. To evaluate QualNet, go to the Download QualNet page and
submit an Evaluation Request form. The QualNet 3.6 Evaluation Request email
will be sent with instructions for downloading QualNet. For organizations that have
purchased QualNet, the technical contact will receive similar instructions, as well
as instructions for installing the QualNet license server and license.

On the download page, all of the resources necessary to install QualNet are
available, including optional QualNet model libraries and the latest QualNet user
manual.

To get started, select the appropriate installation guide PDF file (requires Adobe
Acrobat) under 'Installation Packages' and follow the instructions provided. Users
should complete the Product Tour PDF file to become familiarized with QualNet's
features. Access to this file is available until the license expires.

After installation, copy the license file into QualNet's license_dir directory. QualNet
evaluators receive this file as an e-mail attachment from SNT.

For users that have purchased QualNet, copy the client.lic file to the license_dir
directory. If this file cannot be found, please inquire with the person(s) responsible
acquiring QualNet.

Users running Red Hat Linux 7.1 or higher that receive the error Invalid
(inconsistent) license key or observe an immediate segmentation fault when
attempting to run QualNet should access the solution to this problem at http://
www.scalable-networks.com/help/index.html. Click on the Search tab and type
Invalid (inconsistent) license key in the search field.

QualNet 3.6 Developer’s Guide 5


QualNet Architecture

3.2 Directory Organization


QualNet distribution files are grouped into several subdirectories. This allows
users to quickly find source code, binary object files, configuration files,
documentation, or samples.

The following table lists the default QualNet subdirectories and a brief description
of their content:

3.3 Compiling QualNet


When modifying the QualNet source code, or adding customized models, it is
necessary to recompile the main executable file. For Windows users, this requires
that the system has the Visual C++ command-line utilities directory set in the

6 QualNet 3.6 Developer’s Guide


PATH environment variable. For Unix users, the GNU gcc 2.9x compiler or the
Sun Forte compilers, cc and CC, are required.

To compile QualNet, complete the following steps:


1. Open a command prompt.
2. Go to the main/ directory using cd to change directories.
3. Make a copy of the original Makefile, by typing the following commands:
For Windows (Microsoft Visual C++):

copy Makefile-windowsnt Makefile

For Linux (GNU gcc):

cp Makefile-linux Makefile

For Solaris (GNU gcc):

cp Makefile-solaris Makefile

For Solaris (Sun cc):

cp Makefile-solaris-cc Makefile

4. Perform the compile step using the following commands:


For Windows: nmake
For UNIX: make

When run without parameters, nmake and make will use a file named
Makefile. The user can also type nmake -f Makefile-windowsnt or
make -f Makefile-linux if the copy step is not performed.

This will create the QualNet executable in the bin/ directory. In Windows, the
executable is qualnet.exe; in UNIX, the executable is qualnet.

To recompile QualNet, run nmake or make again. However, it is sometimes useful


to delete all object files.
1. Remove all .obj (Windows) or .o (UNIX) files:
For Windows: nmake clean
For UNIX: make clean

QualNet 3.6 Developer’s Guide 7


QualNet Architecture

2. Perform the compile step:


For Windows: nmake
For UNIX: make

Active optimization and Debugging


Debugging works best when optimizations are off. In the Makefile, remove the
comments from the DEBUG macro and comment out the OPT macro, then
recompile QualNet.
For Unix:

DEBUG = -g
#OPT = -O3

For Windows:

DEBUG = /Zi
#OPT = /Ox /Ob2

Standard debugging tools such as gdb and Visual C++ Debugger can be used
with QualNet.

3.4 Customized Development: Modifying makefiles


The Makefiles have been structured so that minimal changes are required to
modify the build process (add, remove files) in a platform-independent way.

8 QualNet 3.6 Developer’s Guide


The Makefile organization is demonstrated in the following table:

The Windows and Unix Makefiles only include one common file because the
Visual C++ development environment differs from Unix compilers and their
common set of commands. However, the general organization of the files is
similar. The main/Makefile-common-[platform] file is for making changes to the

QualNet 3.6 Developer’s Guide 9


QualNet Architecture

OPT and DEBUG macros, as well as including any Addon Makefiles. Other
modifications should be made to the files that it includes. For instance, the user
can add or modify compiler flags in main/Makefile-[platform]-common files.

Example:

CFLAGS = \
$(INCLUDE_DIRS) \
$(DEBUG) \
$(OPT) \
$(ADDON_OPTIONS) \
-DTEST_FLAG

To compile customized source files into QualNet, it is necessary to append the


filenames to the SIM_SRCS and SIM_HDRS definitions in main/Makefile-
common. Also note that if creating an addon module, source files should be
defined in the addon Makefile (addons/your_addon/Makefile-common). Refer
to “Creating an Addon” on page 12 for more information.

10 QualNet 3.6 Developer’s Guide


4. Addons
This section covers the following topics:
• Addon Overview
• Activating an Addon Module
• Creating Addons

4.1 Addon Overview


An addon module comes as a separate directory of files, placed in QualNet's
addons/ folder. Example addons are the sattsm addon (providing more
sophisticated satellite modeling), and the dted addon (support for reading DTED
format elevation map files). These would be located in the addons/sattsm/ and
addons/dted/ directories, respectively.

QualNet is usually distributed with only one addon, addons/seq/. This seq addon
provides sequential execution functionality to QualNet—this is in contrast to the
par addon, which provides parallel execution on multiple processors.

Addons are an important way in which the user can modularize a protocol,
propagation model, map format decoder, or other capability. The following
sections cover how to activate a received addon, and also how to create an
addon.

4.2 Activating an Addon Module

Addon modules are available for download from the same location as the main
QualNet distribution

This is described in the QualNet distribution email. To receive a copy,


inquire with the person(s) involved in acquiring QualNet.

After downloading the appropriate file, extract the contents to the QualNet
installation directory. Be sure to include the addon Makefile in the QualNet
Makefile-<platform> in the /main subdirectory. Place the include line in the
addons section of the Makefile-<platform>. If the user had the Link16 addon and

QualNet 3.6 Developer’s Guide 11


QualNet Architecture

were running Windows, they would add the following beneath the # INSERT
ADDONS HERE line:

include ../addons/dted/Makefile-windows

Save the file and then rebuild QualNet using make clean and make, or nmake
clean and nmake if running Windows. Then execute QualNet using the config file
(a sample config file may be provided).

4.3 Creating an Addon


The following is an example on how to create an application-layer addon.

4.3.1 The 'Hello' Addon


Complete the following steps to create the Hello Addon:
1. Make a directory in $QUALNET_HOME/addons called hello.
2. Create a header file for the addon. The addon should include Init,
ProcessEvent, and Finalize calls hello.h:

#ifndef HELLO_H
#define HELLO_H

void AppHelloInit(Node *node, const NodeInput


*nodeInput);
void AppHelloProcessEvent(Node *node, Message *packet);
void AppHelloFinalize(Node *node);

#endif

3. Define the addon procedures in hello.c:

#include <stdlib.h>
#include "api.h"
#include "hello.h"

void AppHelloInit(Node *node, const NodeInput *nodeInput{


printf("AppHelloInit called.\n");
}
void AppHelloProcessEvent(Node *node, Message *packet) {
printf("AppHelloProcessEvent called.\n");
}

12 QualNet 3.6 Developer’s Guide


void AppHelloFinalize(Node *node) {
printf("AppHelloFinalize called.\n");
}

The ‘hello’ addon will only contain one source file, but as many as required can
be added.
4. In the hello addon directory, create the necessary Makefiles for each platform
and a Makefile-common that defines which source files to include.
Makefile-common:

HELLO_OPTIONS = -DADDON_HELLO

HELLO_HDRS = \
../addons/hello/hello.h

HELLO_SRCS = \
../addons/hello/hello.c

HELLO_INCLUDES = \
-I../addons/hello

Makefile-windows:

include ../addons/hello/Makefile-common

ADDON_OPTIONS = $(ADDON_OPTIONS) $(HELLO_OPTIONS)


ADDON_HDRS = $(ADDON_HDRS) $(HELLO_HDRS)
ADDON_SRCS = $(ADDON_SRCS) $(HELLO_SRCS)
ADDON_INCLUDES = $(ADDON_INCLUDES) $(HELLO_INCLUDES)
ADDON_LIBRARIES = $(ADDON_LIBRARIES)

Makefile-unix:

include ../addons/hello/Makefile-common

ADDON_OPTIONS += $(HELLO_OPTIONS)
ADDON_HDRS += $(HELLO_HDRS)
ADDON_SRCS += $(HELLO_SRCS)
ADDON_INCLUDES += $(HELLO_INCLUDES)
ADDON_LIBRARIES +=

5. In application/application.c, insert calls to the addon using the #ifdef macro


(these have already been included):

QualNet 3.6 Developer’s Guide 13


QualNet Architecture

Include header file:

#ifdef ADDON_HELLO
#include "hello.h"
#endif /* ADDON_HELLO */

Within the APP_Initialize function:

#ifdef ADDON_HELLO
AppHelloInit(node, nodeInput);
#endif /* ADDON_HELLO */

Within APP_ProcessEvent:

#ifdef ADDON_HELLO
case APP_HELLO:
{
AppHelloProcessEvent(node,msg);
break;
}
#endif /* ADDON_HELLO */

Within APP_Finalize:

#ifdef ADDON_HELLO
case APP_HELLO:
{
AppHelloFinalize(node);
break;
}
#endif /* ADDON_HELLO */

And in includes/application.h, define the APP_HELLO constant:

#ifdef ADDON_HELLO
APP_HELLO,
#endif /* ADDON_HELLO */

The APP_ProcessEvent procedure will call AppHelloProcessEvent whenever


it receives an event message with the protocolType set as APP_HELLO.
6. Add the addon Makefile to the main QualNet Makefile:
In main/Makefile-windows:

14 QualNet 3.6 Developer’s Guide


# INSERT ADDONS HERE
include ../addons/hello/Makefile-windows

In main/Makefile-linux and main/Makefile-solaris-cc:

# INSERT ADDONS HERE


include ../addons/hello/Makefile-unix

7. Recompile QualNet (make clean and make).

QualNet 3.6 Developer’s Guide 15


QualNet Architecture

16 QualNet 3.6 Developer’s Guide


CHAPTER 3 QualNet
Simulator

QualNet Simulator has various elements of interest to developers. This chapter


covers the basics of QualNet Simulator.

1. Chapter Overview
• Events
• Experiment Configuration
• Layering
• Communication Between Layers

QualNet 3.6 Developer’s Guide 17


QualNet Simulator

2. Events
This section covers the following topics:
• Events Overview
• Events and Messages
• Types of Events
• Event Handling

2.1 Events Overview

QualNet is a discrete event simulator. In a discrete event simulation time is viewed


not as a constant flow, but as separate points in time when events occur. The
simulator essentially operates by single stepping through events in an event
scheduler and executing the next scheduled event. The simulation clock is
advanced in discrete steps and is set to the time of the currently executing event.
While processing an event, further events might be generated and inserted into
the event scheduler.

Protocols in QualNet essentially operate as a finite state machine that changes


state only on the occurrence of an event. Thus an event is defined as an incident
which causes the system to change its state or to perform a specific action (also
known as event handling). Examples of events are arrival of a packet, periodic
alarm informing a routing protocol to send out routing update to neighbors etc.

The QualNet Simulator is implemented using a stack model. Each protocol is


inserted at one or more adjacent layers of the stack. At each layer, each protocol
runs its own finite state machine. The interface between the layers is also event
based. To pass data to, or request a service from, an adjacent layer, the system
schedules an event at that layer. Each protocol can thus, either create events that
make it change its own state (or perform some event handling), or create events
that are processed by another protocol operating at another layer in the stack
model.

The layer code (protocols), therefore, is implemented as an event handler, that


receives an event data structure, called a message, containing the type of event,
and the associated data. The event handler then parses the data and handles it
appropriately, perhaps scheduling further events at the next layer (i.e. passing the
data further down the stack).

18 QualNet 3.6 Developer’s Guide


FIGURE 1. Protocol Overview

This figure shows an overview of a typical QualNet protocol, in state diagram


form. Every protocol begins with an Initialization function. The initialization
function reads external input to configure the state of the protocol. The protocol
will then pass control to an event dispatcher. When an event comes in to this
layer, the QualNet Simulator will determine to which protocol it should be directed,
and calls the event dispatcher for that protocol. The event dispatcher will
determine what type of event it is, and will call an appropriate event handler to
process it. Finally, at the end of the simulation, a finalization function is called for
every protocol (at each node), to print out the collected statistics. At the end of
simulation the simulator automatically generates the event that cause a transition
to the finalize state.

Thus, every protocol must implement the following three functions:

QualNet 3.6 Developer’s Guide 19


QualNet Simulator

1. Initialization
2. Event dispatcher
3. Finalization

2.2 Events and Messages


The data structure used to define an event is called a 'Message'. Message holds
information about the event such as the type of event, and the associated data.
This data structure is defined at the following location:
File: QUALNET_HOME/addons/seq/message.h
Structure: struct message_str
The file 'message.h' also contains prototypes of various API functions in QualNet
to handle messages. The implementation code for these functions can be found in
QUALNET_HOME/main/message.c
In the context of QualNet, the terms 'event' and 'message' are often used
interchangeably. The QualNet API uses the 'message' keyword to refer to event
related functions such as:
MESSAGE_Alloc: Function used to create a message (event)
MESSAGE_Free: Function used to free the message
As discussed earlier, a protocol can change state on the arrival of a particular
event. These events whose arrival causes a state transition to happen are called
triggers. Triggers are also named in QualNet with the prefix 'MSG_'.

Example:

MSG_APP_FromNetwork

MSG_Route_FromNetwork

2.3 Types of Events


In QualNet, there are two types of events:
• Packet Events
• Timer Events

20 QualNet 3.6 Developer’s Guide


Although both packet and timer events are defined using the same message data
structure (QUALNET_HOME/addons/seq/message.h), they vary in their purpose
and the manner in which they are handled by QualNet.
To create a timer or a packet event the first step is to allocate a message using
API function MESSAGE_Alloc. The following parameters to the function are used
to define the event:
• Node: Node which is allocating message
• Layer: layer type to be set for this message
• Protocol: Protocol to be set for this message
• Event Type: Event type to be set for this message

The QualNet kernel uses the above fields associated with a message to call the
appropriate function to process a message. Detailed discussion on both timer and
packet events follows.

2.3.1 Packet Events


This section includes the following topic:
• Sending Packets From Application Layer Using Layer Specific API
• Sending Packets Using Message API

Packet events are used to simulate sending of packets across the network. A
packet is defined as a unit of virtual or real data at any layer of the protocol stack.
When a node needs to send a packet to an adjacent layer in the QualNet protocol
stack, it schedules a packet event at the adjacent layer. The occurrence of the
packet event at the adjacent layer simulates the arrival of the packet.

When an application sends packets from one node to another, the packet is
passed down through the protocol stack on the sending node, across the network,
and then up through the protocol stack on the receiving node. At each level of the
protocol stack, header information is added to the packet as it is sent. Each layer
is responsible for sending the packet to its adjacent layer. On the receiving node,
this information is stripped off until the original packet is finally available to the
receiving application. In QualNet this header information is added/ stripped using
the Message API. This process looks something like the following illustration:

QualNet 3.6 Developer’s Guide 21


QualNet Simulator

FIGURE 2. The Life Cycle of a Packet

To simplify protocol development, QualNet provides layer specific API functions to


send packets. Rather than using the raw message API as shown in the illustration
above, the protocol developer can simply use the layer specific API functions to
send packets out from a particular layer. The layer API functions are responsible
for scheduling events at the adjacent layers as the packet travels through the
protocol stack. The API provided at each layer, encapsulates the message API
and hides details of scheduling events at the adjacent layer, thus providing easy-
to-use functions for sending out packets from a specific layer of the protocol stack.

The layer API functions vary for each layer. The API calls available at each layer
to send packets are discussed in the Developer's Guide section corresponding to
each layer. To understand the available APIs at each layer, look up API functions
used for sending packets in the source code of QualNet native protocols operating
at that layer. Although each layer's API details are not discussed here, however as

22 QualNet 3.6 Developer’s Guide


a sample, the following section gives a broad overview of using the packet
exchange API available at Application layer.

2.3.1.1 Sending Packets From Application Layer Using Layer Specific API
Packet exchange API at application layer falls into two categories:
• Exchanging packets with UDP
• Exchanging packets with TCP

The following table lists details of the API calls available for sending packets at
application layer using UDP at the transport layer:

QualNet 3.6 Developer’s Guide 23


QualNet Simulator

The following are the API calls available for sending packets at application layer
using TCP at transport layer:

The previously-listed functions are defined in QUALNET_HOME/application/


app_util.c The underlying code for each of these functions creates and sends
messages using the message API.

At this point, the user should be able to understand the following piece of code,
which uses the API function APP_UdpSendNewDataWithPriority mentioned
previously, to send packets from application layer. The code is taken from the
Ripv2 implementation in QualNet (QUALNET_HOME/application/ripv2.c). Notice
how initially a response variable is allocated. This variable is the packet payload. It
is then filled with information (command and version). The code then gets the
destination address and calls the API function to send the packet out. The
parameters to APP_UdpSendNewDataWithPriority are explained in the figure.

24 QualNet 3.6 Developer’s Guide


FIGURE 3. RIPv2 Code

2.3.1.2 Sending Packets Using Message API

The layer specific API uses the message API to create and send packets. The
layer API provides easy function calls for sending packets through the protocol
stack. It acts as an abstraction layer that hides detailed function calls to the raw
message API.

However sometimes it may be desirable to bypass the layer specific API. This
may be due to the protocol being developed residing in a protocol stack not
supported by the layer specific API, or due to certain specifics of protocol design.
This section describes details of how to send packets using the message API.

QualNet 3.6 Developer’s Guide 25


QualNet Simulator

void
APP_UdpSendNewDataWithPriority(
Node *node,
AppType appType,
NodeAddress sourceAddr,
short sourcePort,
NodeAddress destAddr,
int outgoingInterface,
char *payload,
int payloadSize,
NetworkQueueingPriorityType priority,
clocktype delay,
TraceProtocolType traceProtocol)
{
Message *msg;
AppToUdpSend *info;

msg = MESSAGE_Alloc(
node,
TRANSPORT_LAYER,
TransportProtocol_UDP,
MSG_TRANSPORT_FromAppSend);

MESSAGE_PacketAlloc(node, msg, payloadSize, traceProtocol);

memcpy(MESSAGE_ReturnPacket(msg), payload, payloadSize);

MESSAGE_InfoAlloc(node, msg, sizeof(AppToUdpSend));


info = (AppToUdpSend *) MESSAGE_ReturnInfo(msg);
info->sourceAddr = sourceAddr;
info->sourcePort = sourcePort;
info->destAddr = destAddr;
info->destPort = appType;
info->priority = priority;
info->outgoingInterface = outgoingInterface;

MESSAGE_Send(node, msg, delay);


}

FIGURE 4. Implementation of APP_UdpSendNewDataWithPriority

To understand the message API lets take a look at the implementation of


APP_UdpSendNewDataWithPriority, which was previously used to send packets
from application layer. This is shown in the previous figure. The function allocates
a message using MESSAGE_Alloc. This is followed by a call to
MESSAGE_PacketAlloc. MESSAGE_PacketAlloc is used to allocate the payload
field for the packet to be delivered. This function can be called from the application
layer or from any other layer (e.g. TCP, IP) that a packet may originate from. The

26 QualNet 3.6 Developer’s Guide


third parameter to MESSAGE_PacketAlloc, payloadSize, is used to set the packet
size. Once this function has been called the packet variable in the message
structure can be used to access this space. The API call
MESSAGE_ReturnPacket (msg) is used for this purpose. It is essentially a
#define stated in QUALNET_HOME/addons/seq/message.h

#define MESSAGE_ReturnPacket(msg) (msg->packet)

The payload is then copied into the allocated payload field of the packet.
Additional information can be allocated using MESSAGE_InfoAlloc (discussed in
detail in Message Info Field section). The packet is then sent to the next layer
using the MESSAGE_send function.

void
TransportUdpSendToNetwork(Node *node, Message *msg)
{
TransportDataUdp *udp = (TransportDataUdp *) node->transportData.udp;
TransportUdpHeader *udpHdr;
AppToUdpSend *info;
if (udp->udpStatsEnabled == TRUE)
{
udp->statistics->numPktFromApp++;
}

MESSAGE_AddHeader(node, msg, sizeof(TransportUdpHeader), TRACE_UDP);

udpHdr = (TransportUdpHeader *) msg->packet;


info = (AppToUdpSend *) msg->info;

udpHdr->sourcePort = info->sourcePort;
udpHdr->destPort = info->destPort;
udpHdr->length = MESSAGE_ReturnPacketSize(msg);
udpHdr->checksum = 0; /* checksum not calculated */

TRACE_PrintTrace(node, msg, TRACE_TRANSPORT_LAYER);


NetworkIpReceivePacketFromTransportLayer(
node,
msg,
info->sourceAddr,
info->destAddr,
info->outgoingInterface,
info->priority,
IPPROTO_UDP,
FALSE);
}

FIGURE 5. Code that Executes when Packet Sent

QualNet 3.6 Developer’s Guide 27


QualNet Simulator

The previous figure shows the code that executes when the packet sent using the
code in Figure 4 on page 26 arrives at the transport layer. Notice how API function
MESSAGE_AddHeader is used to add header before a packet. This function
reserves additional space in the packet, for a header. The header size is specified
by the third parameter. MESSAGE_AddHeader also appropriately increases thee
packetSize variable in the message structure. After this function is called, the
packet variable in the message structure will point the space occupied by this new
header.

Notice how after the header information is set, Transport layer specific API
function NetworkIpReceivePacketFromTransportLayer is called to send the
packet to the next layer (Network, IP Layer). In this way the packet travels down
the protocol stack with each layer adding its own header. This is graphically
illustrated in Figure 2, “The Life Cycle of a Packet,” on page 22.

2.3.1.3 Message Info Field


Message info field is used to store extra information about the message, beyond
what is stored in the payload of the message. The information stored in message
info field travels only 1 layer through the protocol stack. This information is not
stored in the packet payload and thus does not affect the transmission/
propagation delay calculations.

The Message Info field is generally used with timers, although it can be used with
packets also. It is commonly used to store additional information with a timer e.g.
for route expired timer, the message info field can be used to store the destination
address for the expired route. This can assist the timer event handler to locate the
correct entry in the routing table and remove it.

The following are the API functions provided for using this field:

MESSAGE_ReturnInfo: Return pointer to the information


field

MESSAGE_ReturnInfoSize: Return the size in byes of the


information field

MESSAGE_InfoAlloc: Allocate the information field for


the message

To use the information field, allocate a message and call MESSSAGE_InfoAlloc


providing it the following parameters:

28 QualNet 3.6 Developer’s Guide


• node: node that is allocating info
• msg: pointer to message for which data has to be allocated
• infoSize: size of the info to be allocated (bytes)

After the message info field has been allocated, it can be accessed using API
function MESSAGE_ReturnInfo. The size of the info field can be read using
MESSAGE_ReturnInfoSize. The following code snippet from QUALNET_HOME/
application/cbr.c, function AppCbrClientInit, illustrates how to set this field in an
outgoing message:

AppTimer *timer;
Message *timerMsg;

timerMsg = MESSAGE_Alloc(node,
APP_LAYER,
APP_CBR_CLIENT,
MSG_APP_TimerExpired);

MESSAGE_InfoAlloc(node, timerMsg, sizeof(AppTimer));


timer = (AppTimer *)MESSAGE_ReturnInfo(timerMsg);
timer->sourcePort = clientPtr->sourcePort;
timer->type = APP_TIMER_SEND_PKT;
MESSAGE_Send(node, timerMsg, startTime);

2.3.2 Timer Events


This section includes the following topics:
• Setting Timers
• Cancelling Timers

Timer events are used to perform the function of alarms. They essentially allow
applications to schedule events for a future time. Periodic alarms are
implemented by re-setting the timer event after it is fired. Timer events are set and
received by the same protocol and they do not travel through the protocol stack.

Example:

-Timer alarm to send route update every 5 seconds

Timer alarm to remove expired route from routing table 3 seconds after it is
installed

QualNet 3.6 Developer’s Guide 29


QualNet Simulator

2.3.2.1 Setting Timers


To set a timer event, allocate a new message using the Message_Alloc function
defined in QUALNET_HOME/main/message.c. Pass as parameters to the
function the node pointer, the layer, the protocol and event type. The event types
are defined in QUALNET_HOME/include/api.h.

Message *newMsg;
newMsg = MESSAGE_Alloc(node,
APP_LAYER,
APP_ROUTING_RIPV2,

MSG_APP_RIPV2_RegularUpdateAlarm);

Set a clocktype variable (delay) to the number of seconds from the current
simulation time after which this event should occur. When delay is set to 0, the
event occurs immediately (before the current function finishes execution).

clocktype delay;

delay = 5* SECOND;

The API function MESSAGE_Send is used to send a message within QualNet.


This function is responsible for scheduling the event. When a message is sent
using this mechanism, only the pointer to the message is actually sent through the
system. So the user has to be careful not to do anything with the pointer to the
message once MESSAGE_Send has been called.

MESSAGE_Send(node, newMsg, delay);

It may be required to store some additional information with the timer. Message
info field is used with timers for this purpose. As an example, consider a timeout
timer for missed packet reception, e.g. ACK. In this case the Info Field can store
the sequence number, and neighbor IP address of the packet for which it expects
an ACK. These are discussed in detail in the Message Info Field section.

2.3.2.2 Canceling Timers


API function MESSAGE_CancelSelfMsg (QUALNET_HOME/addons/seq/
message.h) is used to cancel a event message in the QualNet scheduler. The
Message must be a self message (timer). i.e. a message the node sent to itself.
The function accepts node pointer and msgToCancelPtr pointer as arguments.
The msgToCancelPtr pointer is a pointer to the original message that needs to be

30 QualNet 3.6 Developer’s Guide


canceled. To use this function, the pointer to the original message has to be
retained.
MESSAGE_CancelSelfMsg(node, newMsg);

Do not free the message explicitly or re-use the message after canceling it. The
function MESSAGE_CancelSelfMsg also frees the memory associated with the
message.

2.4 Event Handling


Event handling is defined as execution of code that performs appropriate action
when an event occurs. To reach the event handling function, the control flows
through a series of dispatcher functions when an event occurs.

When using the graphical development environment of QualNet Designer, the


protocol developer does not have to write any dispatcher code. Designer provides
an integrated development environment that plugs the protocol into the QualNet
source tree and generates the code for the dispatcher. The developer simply
creates a finite state machine for the protocol with transitions occurring on events.
The code in state automatically gets executed when a transition to that state
occurs. The protocol developer can thus, simply add the code to the state without
writing any dispatcher code. The dispatcher code is automatically generated by
Designer. For developing a protocol using QualNet Designer read the designer
manual and designer section of the developers manual.

However when developing a protocol manually by making direct additions to the


source code, the protocol developer has to write a dispatcher function to handle
different events that occur at that layer.

When an event occurs, the QualNet kernel gets a handle to the node for which the
event is scheduled. It then calls a dispatcher function in QUALNET_HOME/
addons/seq/node.c called NODE_ProcessEvent. This function determines the
layer for which the event has occurred and calls the LAYER_ProcessEvent
function for the appropriate layer e.g. if the packet/event is for the application
layer, the function APP_ProcessEvent in application.c gets called.

The LAYER_ProcessEvent is a layer dispatcher function which calls the protocol


handler for the appropriate protocol e.g. for an event scheduled for application
layer protocol Ripv2, the application layer dispatcher (APP_ProcessEvent) will
call Ripv2ProcessEvent. This is illustrated graphically and as well as in the code

QualNet 3.6 Developer’s Guide 31


QualNet Simulator

snippet in Figure 6. The code snippet contains sections of code from the
application layer dispatcher. The developer needs to add his protocol to the
appropriate layer dispatcher, from where the protocol's event dispatcher gets
called.

FIGURE 6. How Protocol Functions Get Called

32 QualNet 3.6 Developer’s Guide


FIGURE 7. Code Example of Protocol Functions

The protocol event dispatcher like the other dispatcher functions comprises of a
series of switch statements. It calls the required event handler function of the
protocol. The event handler is code specific to the event and performs the
required action on the occurrence of the event e.g. TransportUdpSendToApp
(QUALNET_HOME/transport/udp.c) is event handler for packet traveling up the
stack. It removes the UDP header and passes the packet to the application layer.

QualNet 3.6 Developer’s Guide 33


QualNet Simulator

3. Experiment Configuration
This section covers the following topics:
• Reading Input from a Configuration File
• Adding Trace Collection
• Adding Statistics
• Collecting Statistics
• Timed-based Statistics

3.1 Reading Input from a Configuration File


The QualNet configuration file is primarily used to specify the protocol stack for a
given simulation, but is also used to specify supplementary protocol parameters.

These parameters can be specified in the following form:

[Qualifier] VARIABLE [Instance] VALUE

The qualifier field is used to specify a specific node that the parameter's value will
be valid for. The instance field allows multiple values of the parameter to be
specified in the experiment (no correlation to specific nodes). Both fields are
optional, and the instance takes precedence over the qualifier.

The value specified for a variable in the configuration file can take several forms:
string, integer, double, float, and clocktype. The QualNet API supplies a function
for reading each variable format from the configuration file.

A synonymous usage of "instance ID" is array index. The types of variables that
require instance IDs are typically arrays of values, such as for priority queues. In
the default configuration each node has three priority queues on each interface.
To set the values of the interface queues, the user would make use of instance
IDs such as the following:

QUEUE-WEIGHT[0] 0.5

QUEUE-WEIGHT[1] 0.3

QUEUE-WEIGHT[2] 0.2

34 QualNet 3.6 Developer’s Guide


Instance IDs are also used when specifying more than one communication
channel. Refer to the file QUALNET_HOME/bin/default.config for examples.

For example, to read a string, one would use the following API:

void
IO_ReadString(
const NodeAddress nodeId,
const NodeAddress interfaceAddress,
const NodeInput *nodeInput,
const char *index,
BOOL *wasFound,
char *readVal);

The node's ID and address are passed to the function (in case a qualifier is
specified in the parameter), along with a pointer to the data representation of a file
(nodeInput), usually representing the configuration file. As expected, the variable
name (index) and destination string pointer (readVal). A pointer to a boolean
variable is also passed in (wasFound), to inform the caller if the parameter was
found in the file.

The API also supplies a set of similar functions for reading parameters with the
instance field.

As an illustration, the mirrored function for the above string example is as follows:

void
IO_ReadStringInstance(
const NodeAddress nodeId,
const NodeAddress interfaceAddress,
const NodeInput *nodeInput,
const char *parameterName,
const int parameterInstanceNumber,
const BOOL fallbackIfNoInstanceMatch,
BOOL *wasFound,
char *parameterValue);

There are two extra parameters in the instance version of the readString function.
One is fairly self-explanatory, parameterInstanceNumber, which identifies which
instance of the parameter is to be read. The other, fallbackIfNoInstanceMatch, is a
boolean that dictates if a parameter without an instance number is chosen if there
is no instance match.

QualNet 3.6 Developer’s Guide 35


QualNet Simulator

Besides reading the standard types described above, the QualNet I/O API allows
to treat a parameter value as a file name, and store the file's content into a
NodeInput data structure.

The function is as follows:

void
IO_ReadCachedFile(
const NodeAddress nodeId,
const NodeAddress interfaceAddress,
const NodeInput *nodeInput,
const char *parameterName,
BOOL *wasFound,
NodeInput *parameterValue);

This is similar to the previous functions described, except that the parameter's
value will be treated as a filename where the cached contents will be stored in
parameterValue. There is also an instance version of this function.

3.2 Adding Trace Collection


To enable packet tracking for a particular protocol, make several insertions both in
the protocol files as well as several general simulator files (Several examples
noted from the UDP protocol).
1. Open the file QUALNET_HOME\include\trace.h and insert an entry into the
enumeration TraceProtocolType.
These entries are used to identify the trace type for each protocol. The
convention for each trace entry is TRACE_[PROTOCOL_NAME].

// All the possible traces...


typedef enum
{
TRACE_TCP = 0, // 0
TRACE_UDP, // 1
TRACE_IP, // 2


TRACE_MYROUTE,
TRACE_SEAMLSS,

/** INSERT YOUR ENTRY HERE! **/

36 QualNet 3.6 Developer’s Guide


// Must be last one!!!
TRACE_ANY_PROTOCOL
}
TraceProtocolType;

2. Enable/Disable tracing in the protocol's initialization function.


In the protocol's initialization function, make the decision if tracing is to be
enabled. There are three relevant QualNet APIs to consider here:
• TRACE_IsTraceAll(Node* node)
This determines if the TRACE-ALL parameter in the configuration file is set.
• TRACE_EnableTrace(Node* node,
TraceProtocolType protocol)
Enables tracing for the protocol.
• TRACE_DisableTrace(Node* node,
TraceProtocolType protocol)
Disables tracing for the protocol.
Most protocols in QualNet enable tracing if the TRACE-ALL parameter returns
true. Otherwise, a check is made for a protocol specific parameter in the
configuration file:

IO_ReadString(
node->nodeId,
ANY_ADDRESS,
nodeInput,
"TRACE-UDP",
&retVal,
buf);

if (retVal) {
if (strcmp(buf, "YES") == 0) {
TRACE_EnableTrace(node, TRACE_UDP);
} else if (strcmp(buf, "NO") == 0) {
TRACE_DisableTrace(node, TRACE_UDP);
}

3. Create a function that prints out the protocols header. This function will be
called when the header needs to be traced.

void TransportUdpPrintTrace(Node *node, Message *msg) {


char buf[MAX_STRING_LENGTH];
TransportUdpHeader* udpHdr = (TransportUdpHeader *)

QualNet 3.6 Developer’s Guide 37


QualNet Simulator

MESSAGE_ReturnPacket(msg);
sprintf(buf, "%d", udpHdr->sourcePort);
IO_PrintTrace(node, buf);
sprintf(buf, "%d", udpHdr->destPort);
IO_PrintTrace(node, buf);
sprintf(buf, "%d", udpHdr->length);
IO_PrintTrace(node, buf);
sprintf(buf, "%d", udpHdr->checksum);
IO_PrintTrace(node, buf);
}

4. Call the QualNet printTrace function in appropriate places of the protocol. The
printTrace API is usually called when the protocol is sending a packet to an
adjacent layer (the time a header is added or removed).

void
TRACE_PrintTrace(Node *node, Message* message,
TraceLayerType layerType);

5. Make sure to pass the protocol's trace enumeration value in calls for adding
and removing message headers and allocating packet payload. The following
are the APIs for adding/removing headers, and allocating packet payload.

void MESSAGE_AddHeader(Node *node,


Message *msg,
int hdrSize,
TraceProtocolType traceProtocol)

void MESSAGE_RemoveHeader(Node *node,


Message *msg,
int hdrSize,
TraceProtocolType traceProtocol)

void MESSAGE_PacketAlloc(Node *node,


Message *msg,
int packetSize,
TraceProtocolType originatingProtocol)

6. Modify the TRACE_PrintTrace() function to include a case statement for the


protocol.

38 QualNet 3.6 Developer’s Guide


7. Open QUALNET_HOME\main\trace.c and modify the TRACE_PrintTrace()
function:

void TRACE_PrintTrace(Node *node, Message* message,


TraceLayerType layerType)
...
...
switch (message->headerProtocols[i]) {
case TRACE_TCP: {
TransportTcpPrintTrace(node, message);
break;
}
case TRACE_UDP: {
TransportUdpPrintTrace(node, message);
break;
}
/** ADD YOUR CASE HERE, CALLING YOUR printTrace
FUNCTION FROM STEP 3 **/
}

8. Enable the QualNet Tracer GUI to recognize the new traced headers. There
are two file formats to be concerned with for Tracer to read the produced trace
file.
• The Header Description File
The header description file is located in
QUALNET_HOME\gui\settings\tracerheaderdescription.txt.
This file tells Tracer how to interpret the headers in the trace file.
The format of this file is as follows:

<header trace-protocol-enum-value header-size protocol-


name>
field1-name,size-in-bytes,data-type
field2-name,size-in-bytes,data-type
...
</header>

For example UDP has been designated protocol 1 in the trace protocol
enumeration, and its header is 8 bytes (consisting of four 2-byte fields).

<header 1 8 UDP>
Source Port,2,int
Destination Port,2,int

QualNet 3.6 Developer’s Guide 39


QualNet Simulator

Length,2,int
Checksum,2,int
</header>

Add a <header> entry for the new protocol in this file as shown above.
• The Trace File
The trace file format is involved. The important thing to learn is
that each header is printed as a comma-separated list of integers
corresponding to the fields described in the Header Description File. It is not
necessary to make any changes to the trace file.
Each of the following sections of each line are separated by semicolons.

packet ID (source node ID, sequence number)


simulation time
ID of node processing packet
originating protocol ID
comma separated list of protocol Ids (same order as
headers)
comma separated list of header 1 fields
comma separated list of header 2 fields

3.3 Adding Statistics


Adding statistics to QualNet protocol is a very similar to process to adding trace
support. However, all changes will be local to the protocol files. The following
procedure is only valid for adding static statistics, which will output cumulative
statistic values (code samples from VBR).
1. Add a data structure to store statistics in the protocol header file. This structure
should have a field for every statistic to track. Acceptable statistics types are
int, double, and unsigned.

typedef struct {
int BytesSent;
int BytesReceived;
} VbrStatsType;

Be sure to add an instance of this structure into the protocol data structure field
as well.

struct struct_vbr_str
{

40 QualNet 3.6 Developer’s Guide


int state;
int connectionId;

...
...

VbrStatsType stats; /** Instance of stats structure **/


...
...
};

2. Create a function to initialize statistics in the protocol source file. All of the
statistics variables must be initialized. Create a function that sets all the
variables to zero.

static void VbrInitStats(Node* node, VbrStatsType *stats)


{
stats->BytesSent = 0;
stats->BytesReceived = 0;
}

In the initialization function, check if statistics are enabled for the current
protocol, and call the initStats routine above accordingly.

if (node->appData.appStats == TRUE) {
VbrInitStats(node, dataPtr);
}

Use the following list to determine if statistics are enabled for the current layer
the model resides on.
• Application Layer—node->appData.appestats
• Application Routing—node->appData.routingStats
• Transport Layer—Protocol specific parameter in configuration file (See
UDP)
• Network Layer—ROUTING-STATISTICS parameter in configuration file
• MAC Layer—node->macData[interfaceIndex]->macStats
3. Create a function that outputs statistics. Every protocol needs a function that
will output statistics once the protocol has finished running it's course in the
simulation. This function will use the IO_PrintStat QualNet API to write out
statistics to the simulation statistics file.

QualNet 3.6 Developer’s Guide 41


QualNet Simulator

void VbrPrintStats(Node* node, VbrData* dataPtr) {


VbrStatsType *stats = &(dataPtr->stats);
char buf[MAX_STRING_LENGTH];

sprintf(buf, "BytesSent = %d", stats->BytesSent);


IO_PrintStat(node, "Application", "APPVBR", ANY_DEST,
dataPtr->sourcePort, buf);

sprintf(buf, "BytesReceived = %d", stats-


>BytesReceived);
IO_PrintStat(node, "Application", "APPVBR", ANY_DEST,
dataPtr->sourcePort, buf);
}

This function is to be called from the protocol's finalize procedure. This function
call is contingent on statistics being enabled, so we must do a similar check as
the one done in the initialization function.

if (node->appData.appStats == TRUE) {
VbrPrintStats(node, dataPtr);
}

3.4 Collecting Statistics


Collecting statistics in QualNet is a matter of manipulating the fields in the statistic
structure that was instantiated in the protocol data structure (Step 1). These fields
can be manipulated as the protocol designer sees fit throughout the function code
of the protocol.

If the format above was used to add statistics to a protocol, statistic variables
should be accessible by the following convention in the protocol code:

dataPtr->stats.<statsVariableName>

3.5 Time-based Statistics


The QualNet GUI also has support for dynamic statistics. This feature enables the
protocol designer to report intermediate values of statistics throughout the
simulation time.

42 QualNet 3.6 Developer’s Guide


The following steps outline how to add dynamic statistics ability to a protocol. This
assumes that the model already support static statistics. (The examples are from
VBR.)
1. Add an extra field in the statistics structure for every existing field in the form:

int <statisticName>ID;

To send an intermediate statistic value to the GUI, it is important to keep track


of the statistic with integer handle. This ID field in the statistics structure will
serve as that handle.

typedef struct {
int BytesSent;
int BytesSentId;
int BytesReceived;
int BytesReceivedId;
} VbrStatsType;

2. Initialize the statistic handles in the InitStats function. The QualNet API that
creates unique handles for statistics is GUI_DefineMetric (can be found in
main/gui.c).

int GUI_DefineMetric(char* name,


NodeAddress nodeID,
GuiLayers layer,
int linkID,
GuiDataTypes datatype,
GuiMetrics metrictype) {

The name variable specifies the description label of the statistic in the GUI.
The linkID refers to the application session ID (zero if not applicable). The
GuiLayers, GuiDataTypes, and GuiMetrics enumeration definitions can be
found in include/gui.h.
GuiLayers specifies the protocol layer the model resides at. GuiDataTypes
specifies the statistic's data type (GUI_INTEGER_TYPE,
GUI_DOUBLE_TYPE, GUI_UNSIGNED_TYPE). GuiMetrics specifies if the
statistic is cumulative or averaged (GUI_CUMULATIVE_METRIC,
GUI_AVERAGE_METRIC).
In the InitStats procedure that was created in the Adding Stats section would
contain all the calls to the DefineMetric routine:

QualNet 3.6 Developer’s Guide 43


QualNet Simulator

static void VbrInitStats(Node* node, VbrStatsType *stats)


{
if (node->guiOption) {
stats->BytesSentId = GUI_DefineMetric("Total Bytes
Sent",
node->nodeId,
GUI_APP_LAYER, 0,
GUI_INTEGER_TYPE,GUI_CUMUL
ATIVE_METRIC);

stats->BytesReceivedId = GUI_DefineMetric("Total
Bytes Received",

node->nodeId,
GUI_APP_LAYER, 0,
GUI_INTEGER_TYPE,
GUI_CUMULATIVE_METRIC);
}
...

The node->guiOption clause is to ensure that the simulation is running in GUI


mode. This is because dynamic statistics aren't supported in command line
simulations at this time.
3. Create the RunTimeStat function for the model. When the GUI requires
intermediate statistic values, a function in the file partition.c called
PARTITION_PrintRunTimeStats is executed. This function calls the
RunTimeStat functions of all QualNet layers (APP_RunTimeStat,
MAC_RunTimeStat, etc.), which in turn call all specific RunTimeStat functions
at each respective layer. To enable runtime statistics in a model, furnish the
code with a RunTimeStat function. The RunTimeStat function should send the
GUI the intermediate values of all the statistics. There is a separate API for
each statistic type (integer, double, unsigned):

void GUI_SendIntegerData(NodeAddress node,


int metricID,
int value,
clocktype time);

void GUI_SendRealData(NodeAddress node,


int metricID,
double value,
clocktype time);

44 QualNet 3.6 Developer’s Guide


void GUI_SendUnsignedData(NodeAddress node,
int metricID,
unsigned value,
clocktype time);

The example of a RunTimeStat function for an application layer protocol:

void VbrRunTimeStat(Node* node, VbrData* dataPtr) {


clocktype now = getSimTime(node);

if (node->guiOption) {
GUI_SendIntegerData(node->nodeId, dataPtr-
>stats.BytesSentId,
dataPtr->stats.BytesSent, now);

GUI_SendIntegerData(node->nodeId, dataPtr-
>stats.BytesReceivedId,
dataPtr->stats.BytesReceived, now);
}
}

Notice the node->guiOption clause, previously seen in the initStats function.


This ensures that the protocol sends data to the GUI only if in fact there is a
GUI! This RunTimeStat function needs to be called by the layer's general
RunTimeStat function. This will require users to first to add the protocol's
RunTimeStat function signature to the protocol header file. This will allow the
function to be accessible to the rest of the simulator. Second, modify the layer's
RunTimeStat function to call the protocol's RunTimeStat function. A call to the
protocol's RunTimeStat function should be added in the switch that appears in
the layer's RunTimeStat function.

void
APP_RunTimeStat(Node *node) {


for (appList = node->appData.appPtr;


appList != NULL;
appList = appList->appNext) {

switch (appList->appType) {

QualNet 3.6 Developer’s Guide 45


QualNet Simulator

case APP_VBR_CLIENT:
case APP_VBR_SERVER:
{
VbrRunTimeStat(node, (VbrData *)
appList->appDetail);
}
break;

/*** ADD YOUR CASE HERE ***/



The RunTimeStat facility is now complete. The entire stats/runtime stats tutorial is
based on creating protocols by hand. If a protocol is created via Designer, all
statistic code is generated and inserted automatically into the protocol files.

46 QualNet 3.6 Developer’s Guide


4. Layering
This section covers the following topics:
• Layering Overview
• Application Layer Overview
• Transport Layer Overview
• Network Layer Overview
• Link (MAC) Layer Overview
• Physical Layer Overview

4.1 Layering Overview

QualNet employs a layered architecture similar to that of the TCP/IP network


protocol stack. As such, data traverses between adjacent layers. QualNet's
protocol stack consists of, from top to bottom, the application, transport, network,
link (MAC) and physical layer.

Well-defined APIs are used to communicate between adjacent layers in the


protocol stack. As a general rule, layer communication can only occur between
adjacent layers. For example, transport layer protocols can get and pass data to
and from the application and network layer protocols, but cannot do so with the
link (MAC) protocols or the physical layer models. However, this rule is not strictly
enforced and may be broken by the developer, as explained later. The following
figure depicts the protocol stack and the general responsibility of each layer.

QualNet 3.6 Developer’s Guide 47


QualNet Simulator

Application Provides traffic generation and


application-level routing

Transport Provides end-to-end transmission of data

Network Provides packet forwarding, queuing/scheduling


and network-level routing

Link (MAC) Provides link-by-link transmission of data

Physical Provides raw bit transmission over


communication channel

FIGURE 8. QualNet Protocol Stack

4.2 Application Layer Overview


The application layer is in charge of traffic generation and application-level
routing. Protocols written at the application layer rely on the transport layer to
deliver application-level data from and to the source and destination. Thus,
application layer protocols pass data down to the transport layer at the source
node and receive the data from the transport layer at the destination node.
Examples of application layer protocols include Constant Bit Rate (CBR), FTP,
and Telnet. Examples of application-level routing protocol include RIPv2, Bellman-
Ford, and BGP.

4.3 Transport Layer Overview


The transport layer provides end-to-end data transmission services to the
application layer. Protocols written at the transport layer receive data from the
application layer and rely on the network layer for data forwarding at the source
node, and receive data from the network layer and pass data to the application
layer at the destination node. Examples of transport layer protocols include UDP,
TCP and RSVP.

48 QualNet 3.6 Developer’s Guide


4.4 Network Layer Overview
The network layer is responsible for data forwarding and queuing/scheduling. The
Internet Protocol (IP) resides at this layer and is responsible for packet forwarding.
Routing protocols can also be implemented at the network layer if the routing
protocol does not rely on any transport protocol for its route maintenance packet
delivery. At one end, the network layer receives data from the transport layer and
relies on the link (MAC) layer for link-by-link data delivery. At another end, the
network layer receives data from the link (MAC) layer and passes the data up to
the transport layer. Examples of routing protocols at the network layer include
AODV, DSR, OSPF and DVMRP. Examples of queuing/scheduling protocols
include FIFO, RED, RIO, WFQ and WRR.

4.5 Link (MAC) Layer Overview


The link (MAC) layer provides link-by-link transmission. Protocols written at the
link (MAC) layer receive data from the network layer and rely on the physical layer
to transmit data over the wired/wireless channel at the sending side. At the
receiving side, the link (MAC) layer receives data from the physical layer and
forwards the data up to the network layer. Examples of protocols at the link (MAC)
layer includes point-to-point, IEEE 802.3, IEEE 802.11 and CSMA.

4.6 Physical Layer Overview


The physical layer is in charge of transmitting and receiving raw bits from the
wired and wireless channel. The physical layer receives data from the link (MAC)
layer and sends data from the physical layer of one node to the physical layer of
another node, where the data is then passed to the link (MAC) layer for further
processing. Note that for wired networks, the physical layer code is incorporated
into the link (MAC) layer. Example of physical layer models include wired point-to-
point links, IEEE 802.3, IEEE 802.11, pathloss and fading.

QualNet 3.6 Developer’s Guide 49


QualNet Simulator

5. Communication Between Layers


Although QualNet protocols follow a strict, adjacent layering approach, protocols
can be written to deviate from this and communicate across layers and even
across nodes.

5.1 Communication Between Adjacent Layers


This section covers the general approach used to communicate between adjacent
layers. It is also important to know how headers are added and stripped as it goes
down and back up in the protocol stack.

Communication between adjacent layers is accomplished by either using


MESSAGE_Send() or direct function calls. Below is an example of using
MESSAGE_Send() to pass data from the application to the transport layer (UDP
in this case).

50 QualNet 3.6 Developer’s Guide


void
APP_UdpSendNewData(
Node *node,
AppType appType,
NodeAddress sourceAddr,
short sourcePort,
NodeAddress destAddr,
char *payload,
int payloadSize,
clocktype delay,
TraceProtocolType traceProtocol)
{
Message *msg;
AppToUdpSend *info;

// Create message event with the transport layer as the destination


// layer and UDP as the protocol destination within the transport
// layer. The message type is MSG_TRANSPORT_FromAppSend.
msg = MESSAGE_Alloc(
node,
TRANSPORT_LAYER,
TransportProtocol_UDP,
MSG_TRANSPORT_FromAppSend);

// Now allocate memory to store data


MESSAGE_PacketAlloc(node, msg, payloadSize, traceProtocol);

// Copy application data into just allocated memory.


memcpy(MESSAGE_ReturnPacket(msg), payload, payloadSize);

// Create and assign info field values for UDP.


MESSAGE_InfoAlloc(node, msg, sizeof(AppToUdpSend));
info = (AppToUdpSend *) MESSAGE_ReturnInfo(msg);
info->sourceAddr = sourceAddr;
info->sourcePort = sourcePort;
info->destAddr = destAddr;
info->destPort = appType;
info->priority = NON_REAL_TIME;
info->outgoingInterface = ANY_INTERFACE;

// Now send the message to UDP at the transport layer.


MESSAGE_Send(node, msg, delay);
}

Applications that rely on UDP may call APP_UdpSendNewData() to pass data to


UDP. APP_UdpSendNewData() will then send a message to UDP using
MESSAGE_Send().

QualNet 3.6 Developer’s Guide 51


QualNet Simulator

The other alternative to pass data between adjacent layers is to use function calls.
Below is an example of how data is passed from the transport to the network
layer, called within QUALNET_HOME/transport/udp.c using
NetworkIpReceivePacketFromTransportLayer().

NetworkIpReceivePacketFromTransportLayer(
node,
msg,
info->sourceAddr,
info->destAddr,
info->outgoingInterface,
info->priority,
IPPROTO_UDP,
FALSE);

In this case, UDP is calling NetworkIpReceivePacketFromTransportLayer() when


there is a packet to send to IP. IP will then process the packet accordingly. Note
here that MESSAGE_Send() is never called for IP to receive UDP messages.

The method of layer communication (whether to use direct function calls or


message send's) is dependent on the layer and how it is implemented. As an
aside, performance is improved using function calls compared to that of message
send's. This is because function calls bypass the message scheduling system of
QualNet, and thus some overhead is reduced. However, if delays are required to
be modeled between layers, function calls cannot be used.

5.2 Communication Between Non-adjacent Layers

Although the design philosophy of QualNet is to utilize the network stack for
communication between layers and then across layers, it is possible to also have
protocols communicate between non-adjacent layers. For instance, protocols
written at the application layer, if desired, may bypass the transport layer and
communicate directly with the network layer. This procedure would entail the
application protocol to use the network layer API calls instead of the transport
layer APIs.

As an example, suppose we want the current CBR application to bypass the


transport layer (UDP in this case) and communicate directly with the network
layer. Also, suppose that we want to maintain the current network layer APIs. In
order to achieve this, we must close the gap between the application and network

52 QualNet 3.6 Developer’s Guide


layer, by squeezing out UDP (the transport layer), as shown in Figure 9,
“Bypassing the transport layer.”

The following is an example of communication between the non-adjacent


Application and MAC layers.

FIGURE 9. Bypassing the transport layer.

This is accomplished by first determining what APIs are used by UDP to


communicate with the network layer, and then copying the same interface
between the application and network layer. In this case, UDP uses
NetworkIpReceivePacketFromTransportLayer() to pass data to the network layer.
The modified CBR application must then also use
NetworkIpReceivePacketFromTransportLayer() to pass data to the network layer
(with the appropriate parameters) instead of calling
APP_UdpSendNewHeaderVirtualDataWithPriority(), which CBR normally does.
This will allow for the application to pass data directly to the network layer and not
use UDP. For communication from the network layer to UDP, a similar approach is
used. First determine what APIs are used between the transport and application
layer and then have the network layer use this same interface to pass data to the
application layer (and thus again bypassing the transport layer). Here, observe
that the communication from the transport to the application layer is via message
send calls (i.e., using MESSAGE_Send()). To see this, look in QUALNET_HOME/

QualNet 3.6 Developer’s Guide 53


QualNet Simulator

transport/udp.c under the function TransportUdpSendToApp()). Thus, the network


layer must take the same approach to communicate with CBR.

Now go over code snippets of what modifications are required for data passing
from CBR to the network layer, and omitting UDP.

Start by looking at how to modify CBR to bypass UDP and communicate directly
with IP (network layer). To do so, declare the following in QUALNET_HOME/
application/cbr.c.

#include "ip.h"

The include statement allows the user to call


NetworkIpReceivePacketFromTransportLayer() in cbr.c. Then remove the call to
APP_UdpSendNewHeaderVirtualDataWithPriority() in cbr.c and replace it the
code snippet shown in Figure 10, “Code to bypass UDP transport layer”

54 QualNet 3.6 Developer’s Guide


// This must be declared at the beginning of the case statement.
Message *msg;

// Create a message to hold the data. Use 0’s as we are not using
// MESSAGE_Send() to pass data to IP. We use a function call instead.
// Therefore, we do not care what values are being initialized.
msg = MESSAGE_Alloc(node, 0, 0, 0);

// Allocate enough payload within the message to store the CBR data.
MESSAGE_PacketAlloc(
node,
msg,
sizeof(CbrData),
TRACE_CBR);

// Copy the CBR data into the message payload.


memcpy(MESSAGE_ReturnPacket(msg),
&data,
sizeof(CbrData));

// Pass the data (message) down to IP for IP to process.


NetworkIpReceivePacketFromTransportLayer(
node,
msg,
clientPtr->localAddr,
clientPtr->remoteAddr,
ANY_INTERFACE,
clientPtr->tos,
IPPROTO_CBR,
FALSE);

FIGURE 10. Code to bypass UDP transport layer

The comments in the code shown in the previous figure explain the function of
each statement. Now that communication from CBR to IP has been covered,
communication from IP to CBR comes next. In QUALNET_HOME/network/ip.h,
first add the following line:

#define IPPROTO_CBR 22

This allows IP to put in its header which protocol IP should pass the packet to
once it is received at the destination node. The value of 22 is picked arbitrarily
(making sure that 22 is not already in use by another protocol). Then, the user
should define the function SendToCbr() in QUALNET_HOME/network/ip.c. This is
shown in Figure 10, “Code to bypass UDP transport layer”

QualNet 3.6 Developer’s Guide 55


QualNet Simulator

void SendToCbr(
Node *node,
Message *msg,
NetworkQueueingPriorityType priority,
NodeAddress sourceAddress,
NodeAddress destinationAddress,
int incomingInterfaceIndex)
{
CbrData data;
UdpToAppRecv *info;

// Get the CBR data so as to get the source port information


memcpy(&data, MESSAGE_ReturnPacket(msg), sizeof(data));

// Set layer and protocol to application layer and


// CBR Server, respectively.
MESSAGE_SetLayer(msg, APP_LAYER, APP_CBR_SERVER);

// Set the event to the type that is recognized by CBR.


MESSAGE_SetEvent(msg, MSG_APP_FromTransport);

// Update info field (used by the CBR Server).


MESSAGE_InfoAlloc(node, msg, sizeof(UdpToAppRecv));
info = (UdpToAppRecv *) msg->info;

info->sourceAddr = sourceAddress;
info->sourcePort = data.sourcePort;
info->destAddr = destinationAddress;
info->destPort = APP_CBR_SERVER;
info->incomingInterfaceIndex = incomingInterfaceIndex;

// Send message/packet to application layer.


MESSAGE_Send(node, msg, PROCESS_IMMEDIATELY);
}

SendToCbr() prepares the message to be in a form that is recognized by CBR. Of


course, the type UdpToAppRecv is misleading here since this message is not
from UDP, but is instead from IP. Alternately, it could be renamed to IpToAppRecv
in order to better reflect the message meaning (UdpToAppRecv is defined in
QUALNET_HOME/include/api.h). If this approach is taken, make sure that cbr.c
also is updated to reflect this change. However, for this example, leave it as
UdpToAppRecv.

56 QualNet 3.6 Developer’s Guide


Finally, in DeliverPacket() (QUALNET_HOME/network/ip.c), add the following
case statement to the second switch statement:

case IPPROTO_CBR:
{
SendToCbr(node, msg, priority, sourceAddress,
destinationAddress, interfaceIndex);
break;
}

The previous case statement tells IP to send the packet up to CBR for further
processing (once IP receives data from the link (MAC) layer) if the protocol
number in the IP header is IPPROTO_CBR.

Of course, the user could also disregard the existing APIs (such as
NetworkIpReceivePacketFromTransportLayer()) and create a new set of APIs
between the desired layers, either with new functions or message send's. In
general, communication among layers may be non-adjacent as long as the APIs
in the layers of interest are met or new APIs are created for them.

5.3 Communication Among Layers Across Nodes

Besides supporting the ability to communicate between non-adjacent layers,


QualNet also allows the capability to bypass the protocol stack and communicate
directly across nodes. For instance, an application protocol at one node can
directly communicate with an application protocol at another node. Of course, this
is not restricted to just between the same applications. The cross-node
communication can also occur between different protocols in the same layer or of
different layers. To continue with our CBR example, suppose that we only wanted
to model a fixed delay when sending CBR traffic between the source node and the
destination node. One approach to achieve this is to directly send a message from
the CBR source node to the CBR destination node without having to rely on any of
the lower layers. The code example below illustrates this.

First include partition.h to access the partition data structure, which are required to
map the destination node ID to a Node pointer.

#include "partition.h"

QualNet 3.6 Developer’s Guide 57


QualNet Simulator

Next, replace the code snippet in Figure 10, “Code to bypass UDP transport layer”
with the following code snippet depicted in Figure 11, “Code sample to bypass
layers and directly communicate between nodes” .

58 QualNet 3.6 Developer’s Guide


Message *msg;
UdpToAppRecv *info;
Node *destNode;
NodeAddress destId;

// Get the destination nodeId associated with the destination IP address.


destId = MAPPING_GetNodeIdFromInterfaceAddress(node,
clientPtr->remoteAddr);

// Get the destination Node pointer associated with the destination nodeId.
destNode = MAPPING_GetNodePtrFromHash(node->partitionData->nodeIdHash,
destId);

// Make sure that the destination Node pointer exists.


assert(destNode != NULL);

// Create the message to pass directly to the CBR Server at the


// destination node.
msg = MESSAGE_Alloc(node, APP_LAYER, APP_CBR_SERVER, MSG_APP_FromTransport)

// Allocate enough payload in the message to carry the CBR data.


MESSAGE_PacketAlloc(node,
msg,
sizeof(CbrData),
TRACE_CBR);

// Put the CBR data into the message payload.


memcpy(MESSAGE_ReturnPacket(msg),
&data,
sizeof(CbrData));

// Create the necessary info structure that the


// destination CBR node expects.
MESSAGE_InfoAlloc(node, msg, sizeof(UdpToAppRecv));
info = (UdpToAppRecv *) msg->info;

info->sourceAddr = clientPtr->localAddr;
info->sourcePort = clientPtr->sourcePort;
info->destAddr = clientPtr->remoteAddr;
info->destPort = APP_CBR_SERVER;
info->incomingInterfaceIndex = 0;

// Send the message to the destination node with a fixed 1ms delay.
MESSAGE_Send(destNode, msg, 1 * MILLI_SECOND);

Code sample to bypass layers and directly communicate


FIGURE 11.
between nodes

QualNet 3.6 Developer’s Guide 59


QualNet Simulator

The comments in the code from the previous figure explain what each line of code
does. Note the first parameter in the MESSAGE_Send() call. The variable
destNode is used instead of node. By using destNode, QualNet knows to send the
message to the destination node directly. While the name UdpToAppRecv could
be changed to be more descriptive. However, for simplicity in this example,
UdpToAppRecv is used.

In general, direct communication across nodes may occur as long as the APIs in
the layers of interest are met or new APIs are created for them.

60 QualNet 3.6 Developer’s Guide


CHAPTER 4 Networking
Using QualNet

Developers familiar with the seven layers of networking may want to know how
those layers work with QualNet. QualNet follows the protocol stack approach,
similar to that of TCP/IP protocol stack, but can also deviate from such as stack.

1. Chapter Overview
• Application Layer
• Transport Layer
• Network Layer
• MAC Layer
• Physical Layer

QualNet 3.6 Developer’s Guide 61


Networking Using QualNet

2. Application Layer
This section covers the following topics:
• Application Layer Overview
• Application Layer Protocols In QualNet
• Application Layer Organization: Files And Folders
• Writing and Adding an Application Protocol
• Tips For Application Layer Routing Protocol
• Writing and Adding an Application Layer Routing Protocol
• Using QualNet Designer For Application Layer Development

2.1 Application Layer Overview


The Application layer is the topmost layer in the protocol stack. This layer is
responsible for providing services to the end user. Being the topmost layer, it
interacts with the layers below and uses their services. In general, an application
layer protocol defines:
• The type and number of messages exchanged
• The syntax of the message and the meaning of the information in the fields
• The response or processing for received messages

Figure 1, “The Application Layer,” on page 63, illustrates application layer residing
at the top in the QualNet protocol stack. Since the application layer resides on top
of transport layer it is responsible for interfacing with the transport layer and
passing messages to and from the transport layer. It uses this interaction to
implement functionality, such as ensuring available resources for communication
and synchronizing data transmission.

62 QualNet 3.6 Developer’s Guide


FIGURE 1. The Application Layer

This layer includes protocols like Telnet, CBR, and File Transfer Protocol (FTP).
An understanding of this layer is important for modeling today's networks.

2.2 Application Layer Protocols In QualNet


QualNet provides an implementation of a large number of application layer
protocols. QualNet permits multiples applications to be running at a node
simultaneously, much like a real network, where users may have multiples
applications or multiple instances of the same application being executed
simultaneously.

QualNet 3.6 Developer’s Guide 63


Networking Using QualNet

This section covers the following topics:


• Traffic Generating Protocols
• Service Providing (Routing) Protocols

The following section describes the different kinds of application layer protocols in
QualNet.

2.2.1 Traffic Generating Protocols


Traffic generating protocols are used to simulate the traffic generated by a real
network application. Large number of traffic generating protocols are provided in
QualNet. Figure 2, “The QualNet User Manual provides the syntax, parameters
and configuration information needed for using each of these applications” , lists
the application layer protocols in QualNet.
While some of protocols are used directly by users as applications, such as FTP
and Telnet, others can be used to simulate a real network applications.
Applications such as CBR (constant bit rate) can be configured to simulate a large
number of real network applications by mimicking their traffic pattern. For an
example, audio traffic and old video codecs, infuse traffic at a constant rate into
the network and can be accurately simulated by appropriately configuring the
CBR application in QualNet.

CBR Constant Bit Rate


FTP File Transfer Protocol
HTTP HyperText Transfer Protocol
ModSAF/OTB* Modular Semi-Automated Forces / OneSAF Testbed Baseline*
NETWARS* NETwork WARfare Simulation*
SEAM-LSS Simulation and Evaluation of Adaptive Mobile Large Scale
Networks Systems
Traffic-TRACE Self-similar traffic
Traffic-GEN Synthetic traffic
TCPLIB TCP/IP Traffic Characteristics Library
Telnet
VBR Variable Bit Rate
VoIP Voice over Internet Protocol

64 QualNet 3.6 Developer’s Guide


FIGURE 2.The QualNet User Manual provides the syntax, parameters and
configuration information needed for using each of these applications

2.2.2 Service Providing (Routing) Protocols


Besides traffic generators, certain service providing protocols may also reside at
the application layer. In general, a protocol residing at the top layer and using the
services of layers below (transport layer), is said to be an application layer
protocol. Routing protocols is a common category of service providing protocols
that may reside at the application layer.
Routing Information Protocol version 2 (RIPv2) and Optimized Link State Routing
(OLSR) are examples of routing protocols that reside at the application layer. Both
these protocols exchange routing information using UDP packets and are thus
regarded as an application layer routing protocol.
Other routing protocols may send messages straight from the network layer by
residing directly above IP. These do no use UDP or TCP services and thus will not
fall into the category of application layer routing. Examples of such network layer
routing protocols include Ad-hoc Distance Vector (AODV) and Dynamic Source
Routing(DSR). The following table lists some differences that exist between
application layer and network layer routing protocols.

Application Routing Network Routing


Use UDP or TCP to transmit their Uses IP directly to transmit their
route discovery and control route discovery and control
packets. packets.
Use an IP kernel function to Uses IP kernel functions to
update the IP forwarding table. register itself as the packet routing
function.
Does not receive data packets to Receives data packets and decides
forward, IP handles those itself. outgoing interface to forward
packets.

FIGURE 3. Application versus Network Routing

QualNet 3.6 Developer’s Guide 65


Networking Using QualNet

2.3 Application Layer Organization: Files And Folders


Let's briefly examine what information is stored in which directory or file. The
application layer API is composed of several macros, functions, and structures.
These are defined in the following header files:
• QUALNET_HOME/include/api.h
This file defines the events and data structures needed to communicate
between different layers of the protocol stack.

• QUALNET_HOME/include/application.h
This file contains definitions common to application layer protocols and
application data structure in node structure.

• QUALNET_HOME/application /app_util.h
This file contains prototypes of the functions defined in app_util.c.

Additionally, the following header files are also relevant to the application layer:
• QUALNET_HOME/include/fileio.h
• QUALNET_HOME/include/mapping.h

These files are described in greater detail in the application layer section of the
API reference document. Alternatively the source code also contains detailed
comments on functions and other code components.

The following are the source files (*.c) associated with the application layer:
• QUALNET_HOME/application
This folder contains the source and header files for the various QualNet native
applications. The file names are indicative of the application for which they
provide an implementation e.g. to see the implementation for CBR (Constant
Bit Rate), look at cbr.c and cbr.h files.
• QUALNET_HOME/application/application.c
This file contains initialization function, message processing function, and
finalize function used by application layer.

66 QualNet 3.6 Developer’s Guide


• QUALNET_HOME/application /app_util.c
This file contains utilities used by application. This includes functions to set
timers, register an application and send packets and manage connection to
transport layer (UDP, SRM and TCP).

2.4 Writing and Adding an Application Protocol


In QualNet, an application layer protocol serves the following three purposes:
• To exchange packets with the transport layer and other applications.
• To instantiate and tear down application instances.
• To update multicast tables.

Although the working of each application layer protocol is different, there are
certain functions that are performed by most application layer protocols. This
section provides an architectural overview of the flow of an application layer
protocol and gives an insight into developing and adding an application layer
protocol to QualNet. It describes in detail how to develop code components
common to most application protocols such as sending packet, receiving packets
etc. As these steps are followed, users will see the implementation code for CBR
(Constant Bit Rate), which is one of most frequently used protocols.

2.4.1 Creating Files


The first step towards adding an application layer protocol is to create files. Most
application protocols comprise of two files, the header file and the source file.
Create the files for the application and place them in the
QUALNET_HOME/application folder. Name these in a way that clearly indicates
the protocol that they implement.

ftp.c, ftp.h: Implement FTP (File Transfer Protocol)

cbr.c, cbr.h: Implement CBR

It is strongly recommended to have separate header and source files. Not having
a header file, sometimes leads to unexpected problems even if the compilation
process does not indicate any error.

QualNet 3.6 Developer’s Guide 67


Networking Using QualNet

Next, add these files to the QualNet source tree. Modify the file
QUALNET_HOME/main/Makefile-common to include the created files. Add the
header file (*.h) to the simulator header files section and the source file(*.c) to the
simulator source file section of Makefile-common. This addition ensures that the
files will be compiled. The files are sorted alphabetically for simplicity, but it
doesn't matter where it is inserts into the list.

Test that the files are successfully added to the QualNet source tree by compiling
QualNet. This is done by performing the following steps:
• cd main
• Copy Makefile-windowsnt to Makefile

If this step is performed, users can run nmake without arguments.


• Run nmake

While adding code to the files, it’s important to organize code well between the
files. The header file should generally contain the following:
• Prototypes for functions in source file
• Constant definitions: All # defines
• Data structure definitions and data types: struct, enums

The application layer source file should contain the following:


• Include declarations for appropriate header files

Add the following files to the source file. A typical application layer file includes
these files:

#include <stdio.h>

#include "api.h" // include/api.h

#include "app_util.h" // application/app_util.h

#include "ip.h" // network/ip.h. This allows for


use of the IP protocol

• Dispatcher code
• Protocol implementation functions

68 QualNet 3.6 Developer’s Guide


When adding the protocol, it is recommended that users compile frequently to test
the code.

2.4.2 Determining the Application Configuration Format


Each application has a input format for specifying the user configuration
parameters. The application is called from the QualNet configuration file using this
input format. The syntax for specifying an application configuration format is as
follows:

Keyword param1 param2 .. paramN

Where:
• Keyword: Uniquely identifies the protocol.
• Param1 Param2 .. ParamN: User specified configuration parameter values. An
application protocol may have any number of required /optional parameters.

For example, in order to specify CBR traffic in the default.app configuration file,
make entries according to the following format:

CBR <src> <dest> <items_to_send> <item_size> <interval>


<start time> <end time>

Where:
• <src> refers to the client node's nodeId or IP Address.
• <dest> indicates the server node's nodeId or IP Address.
• <items_to_send> specifies the number of items to send.
• <item_size> specifies the size of each item.
• <interval> indicates the pause time between transmission of each item.
• <start_time> indicates when the transmissions should begin.
• <end_time> indicates when the transmissions should cease

The time is always specified in QualNet Time Format which explained in greater
detail in the simulator manual.
The following example specifies that the node with nodeId 1 (node 1) will send
500 2-kilobyte items to node 2, sending one per minute, starting from 50
simulation seconds into the total simulation time, and ending 100 seconds later:

QualNet 3.6 Developer’s Guide 69


Networking Using QualNet

CBR 1 2 500 2048 1M 50S 100S

Similarly decide on the configuration input format for the application. The next
section explains how to read this user input to initialize the application.

2.4.3 Integrating With QualNet


Each node in QualNet hosts an operating protocol stack. This stack includes a list
of protocols at each layer that the node may be running. New application
protocols need to be added to the list of application layer protocols of the stack.
The list of application layer protocols is specified by an enumerated data type
called AppType, which is defined in QUALNET_HOME/application/
application.h.

It is useful to understand how a node accesses the list of application layer


protocols. Each node has a node structure which holds all the information for the
node. This node structure contains a pointer to a structure called AppData.
AppData contains a pointer to a list of applications running at this node. Each
element of this list contains a pointer to a structure that contains information about
the application instance. This information includes the application protocol name
(application type) which is stored using the AppType enum. A graphical
representation of this organization is provided in Figure 4, “Application Layer
Protocol Organization,” on page 71.

2.4.3.1 Adding Application Type

To integrate an application into QualNet, it needs to be defined as member of the


list of application protocols that a node may run. To do this, add the protocol name
to the enumeration AppType defined in QUALNET_HOME/application/
application.h. Traffic generating applications have two parts: A client which
generates the traffic and a server that receives the traffic. Both client and server of
an application protocol should be added to AppType. The QualNet coding
guidelines suggest the following format for this:

APP_yourAppName_CLIENT: For Client

And

APP_yourAppName_SERVER: For Server

Or

70 QualNet 3.6 Developer’s Guide


APP_ROUTING_ yourAppName: For Application Layer Routing
Protocol

Always add to the end of lists in header files. QualNet's pre-built object files use
the values which existed when the object files were created. By inserting the
constant at the top of the list, the values below will be offset in any new object files
and may lead to the simulator crashing.

FIGURE 4. Application Layer Protocol Organization

2.4.3.2 Specifying the Event Dispatcher


The file QUALNET_HOME/application/application.c contains a variety of functions
useful to all applications such as the application layer event dispatcher and
initialization functions. Since all application layer protocols use these functions,
include the header file of the protocol under development in this file.

Specify the event dispatcher function of the protocol. This function is called when
event / messages are received for the protocol. Event dispatchers are explained
in detail in Chapter 3, “Events and Messages” on page 20.

The application.c function APP_ProcessEvent implements an application layer


event dispatcher which informs the appropriate application protocol of received
events. The application layer event dispatcher calls a protocol specific event
dispatcher. It checks the destination protocol of an event and passes the event to

QualNet 3.6 Developer’s Guide 71


Networking Using QualNet

the dispatcher function of the destination protocol. To call the protocol's event
dispatcher function, add code to this function.

Messages/Events contain the name of the protocol that they are destined for.
APP_ProcessEvent implements a switch statement on the protocol name read
from the message. This is the application protocol name specified in the
enumerated data type called AppType. To enable the protocol to receive events,
add code to APP_ProcessEvent to call the protocol's event dispatcher function
when messages for the protocol are received. For a traffic generating application
protocol, do this separately for both the server and the client.

Figure 5, “Application event dispatcher in application/application.c” shows code


fragment from APP_ProcessEvent with sample code for calling event dispatcher
function of an application layer traffic generation protocol.

72 QualNet 3.6 Developer’s Guide


void APP_ProcessEvent(Node *node, Message *msg)
{
switch(MESSAGE_GetProtocol(msg))
{
....
case APP_CBR_CLIENT:
{
AppLayerCbrClient(node, msg);
break;
}
case APP_CBR_SERVER:
{
AppLayerCbrServer(node, msg);
break;
}
.....
case APP_ROUTING_RIPV2:
{
Ripv2ProcessEvent(node,msg);
break;
}
....
// Your Protocol Client
case APP_YourAppName_CLIENT:
{
AppLayerYourAppNameClient(node, msg);
break;
}
// Your Protocol Server
case APP_YourAppName_CLIENT:
{
AppLayerYourAppNameClient(node, msg);
break;
}
.....
}
}

FIGURE 5. Application event dispatcher in application/application.c

In subsequent sections, how to implement the protocol's event dispatcher function


being specified here is covered.

2.4.3.3 Reading Configuration Parameters and Calling Init( )


QualNet can configure protocols to a user's specified parameters provided in the
QualNet configuration file which sets up the experiment. Application configuration
parameters are also provided by users in this configuration file. This section

QualNet 3.6 Developer’s Guide 73


Networking Using QualNet

explains how to read these user specified configuration parameters for the
application protocol and providing them to the protocol's initialization function.

The protocol stack of each node is initialized in a bottom up manner. The


initialization of the application layer thus occurs after other layers have been
initialized. This process is performed in the node initialization function
PARTITION_InitializeNodes, implemented in addons/seq/partition.c.

The node initialization function, PARTITION_InitializeNodes, calls the application


initialization functions APP_InitializeApplications and APP_Initialize, which are
implemented in the file application/application.c. APP_Initialize initializes
application layer routing protocols while APP_InitializeApplications is used for
initializing traffic generation protocols.

These application initialization functions read the user's configuration parameters


and pass them to the init function of the application protocol. To initialize the
application protocol in QualNet, add code to these functions for reading the
protocol's configuration parameters and calling its init function.

Calling a protocol's init function is best understood by examining how


APP_InitializeApplications initializes CBR. Figure 6, “Reading configuration
parameters and calling init; File: application/application.c,” on page 77, has the
appropriate code samples that illustrate this process. Examine them while reading
the following paragraphs.

The APP_InitializeApplications function has access to the configuration input for


application layer, as specified by the user in the experiment configuration file. This
is stored in a variable called appInput. The first word of the currently examined
input line is stored in a variable called appStr. The appStr variable is compared
with the keyword used to uniquely identify an application such as CBR, FTP, etc. If
it matches then corresponding parameters to the application are read from the
input string. The C library function sscanf is used to split the input string into
multiple words that constitute the parameters to the protocol.

The parameters containing time related information are converted from string to
QualNet's clocktype variables by calling QualNet library function
TIME_ConvertToClock.

The source and destination Id are parameters commonly specified by users to


most traffic generating applications. The strings containing the source and
destination Id (obtained by splitting input string) are passed to the QualNet library

74 QualNet 3.6 Developer’s Guide


function IO_AppParseSourceAndDestStrings. This function performs the following
tasks:
• Gets the source and destination nodeID and node address from the string
• Displays error message if source and destination are same
• Displays error message if source/destination does not exist

After obtaining the nodeId, the QualNet library function


MAPPING_GetNodePtrFromHash is called to get a handle to the node pointer
which stores the state of the node. This is finally followed by a call to the
application initialization function, which is passed the node pointer and user
configuration values that were read from input string appInput.

To develop a deeper understanding, it is advisable to read through a section of the


actual source code of function APP_InitializeApplications, which reads
parameters for a protocol having similar parameters to the protocol under
development.

QualNet 3.6 Developer’s Guide 75


Networking Using QualNet

Void APP_InitializeApplications(Node *firstNode, const NodeInput *nodeInput)


{
………………
else
if (strcmp(appStr, "CBR") == 0)
{
char sourceString[MAX_STRING_LENGTH];
char destString[MAX_STRING_LENGTH];
……………
NodeAddress destAddr;
…………..
retVal = sscanf(appInput.inputStrings[i],
"%*s %s %s %d %d %s %s %s %s %s",
sourceString, destString,
&itemsToSend, &itemSize,
intervalStr, startTimeStr,
endTimeStr, optionToken1,
optionToken2);
……………………..
IO_AppParseSourceAndDestStrings(
firstNode, appInput.inputStrings[i],
sourceString, &sourceNodeId,
&sourceAddr, destString,
&destNodeId, &destAddr);

node = MAPPING_GetNodePtrFromHash(nodeHash, sourceNodeId);


if (node != NULL)
{
clocktype startTime = TIME_ConvertToClock(startTimeStr);
…………..
clocktype interval = TIME_ConvertToClock(intervalStr);

AppCbrClientInit(
node,
sourceAddr,
destAddr,
itemsToSend,
itemSize,
interval,
startTime,
endTime,
tos,
isRsvpTeEnabled);
}
node = MAPPING_GetNodePtrFromHash(nodeHash, destNodeId);
if (node != NULL)
{
AppCbrServerInit(node);
}

76 QualNet 3.6 Developer’s Guide


FIGURE 6.Reading configuration parameters and calling init; File:
application/application.c

2.4.4 Application Initialization: Init( )


The initialization of an application happens in the init function of the protocol that
is called by the application layer. The init function of an application commonly
performs the following tasks:
• Initialize the state and store the user specified configuration parameters
• Create an instance of the application
• Schedule a timer to itself for starting the application
• Initialize data structures and variables as required e.g. allocate memory to
tables, set default values, etc.

Like all other functions belonging to the application, the prototype for init should
be included in the application's header file.

Although each protocol's init function is customized according to the requirements


of the protocol, however there are functions that are generally performed as a part
of the initialization of most application protocols. We discuss these using code
snippets from QualNet native protocol CBR.

After understanding the discussed snippets, look at the complete init code of a
protocol. CBR is a starting point because many of its code fragments are covered
in other sections.

2.4.4.1 Creating An Instance & Storing The State


The init function initializes the protocol state. Each protocol has a structure that it
uses to store state information. This may include information such as timer state
(next periodic update etc.), flags, connection information, sequence number,
pointers to tables used by the protocol, etc. Each instance of the application
maintains its own state variable.

To store the state, declare the structure to hold the protocol state in the header
file. Then, create an instance of the application by allocating memory to the state
structure.

QualNet 3.6 Developer’s Guide 77


Networking Using QualNet

CBR performs this task by calling AppCbrClientNewCbrClient in its init function


AppCbrClientInit:

AppDataCbrClient *clientPtr; //pointer to the state


structure
clientPtr = AppCbrClientNewCbrClient(node,
clientAddr, serverAddr,
itemsToSend, itemSize,
interval, startTime,
endTime, tos);

In the implementation of AppCbrClientNewCbrClient, MEM_malloc is used to


allocate memory to the state structure. It is then used to store some user specified
configuration parameters that were passed to the init function.

The following code from AppCbrClientNewCbrClient, illustrates this.

AppDataCbrClient *cbrClient;
cbrClient =
(AppDataCbrClient*)MEM_malloc(sizeof(AppDataCbrClient));
cbrClient->interval = interval;
cbrClient->sessionStart = getSimTime(node) + startTime;
APP_RegisterNewApp(node, APP_CBR_CLIENT, cbrClient);
return cbrClient;

The next step after creating the application instance is to register the instance as
one of the protocols running at the node. This is done by making a call to
APP_RegisterNewApp, which is a QualNet library function to add an application
to the list of applications running at the node. When the application needs to
access it's state variable, it retrieves it from this list. This list is maintained using
the AppInfo data structure defined in QUALNET_HOME/include/application.h.

APP_RegisterNewApp accepts the following three parameters:


• the node pointer
• the application type
• the pointer to the state structure

At later stages in the protocol the list can be traversed. This is useful when a
handle needs to get to an application instance; at this point, find the state of the

78 QualNet 3.6 Developer’s Guide


correct protocol instance. The protocol instance can be identified by a connection
Id or port number. This is demonstrated in the following code.

static AppDataCbrClient * AppCbrClientGetCbrClient(Node *node, short sourcePort


{
AppInfo *appList = node->appData.appPtr;
AppDataCbrClient *cbrClient;

for (; appList != NULL; appList = appList->appNext)


{
if (appList->appType == APP_CBR_CLIENT)
{
cbrClient = (AppDataCbrClient *) appList->appDetail;

if (cbrClient->sourcePort == sourcePort)
{
return cbrClient;
}
}
}

return NULL;
}

2.4.4.2 Initializing Timers


Besides initializing data structures, the init function also initializes timers for the
application. Timers serve a variety of purposes at the application layer e.g. to
notify when the application is supposed to begin sending data, to simulate traffic
sending rate etc.

This section discusses in detail how to use timers. Since each node can have
multiple applications of the same type, application layer timers frequently use
message info field, to distinguish which application instance the timer is for.

QualNet provides a general structure used to hold information on application


timers called AppTimer (QUALNET_HOME/application.h). AppTimer can be used
to store the following information:
• Timer Type: Category or purpose of timer.
• Connection Id: Connection this timer is meant for.
• SourcePort: The session that this timer belongs to.

QualNet 3.6 Developer’s Guide 79


Networking Using QualNet

The Timer Type can be one of the following three pre-defined types:
• Name: APP_TIMER_SEND_PKT
Purpose: Timer to send a packet. Used to simulate data sending rate
• Name: APP_TIMER_UPDATE_TABLE
Purpose: Timer to close a session. Used to notify of application end time.
• Name: APP_TIMER_CLOSE_SESS
Purpose: Timer to update local table e.g., update entries, remove timed-out
entries from a table etc.

The following code from AppCbrClientInit, is used by CBR to set a timer to inform
itself of when to start sending data. It demonstrates how a timer can store the
source port of the application instance in the message info field. This source port
is used to identify the instance of the CBR application, incase there are multiple
CBR applications running at the node. The timer type used is
APP_TIMER_SEND_PKT because it notifies an application to start sending
packets.

timerMsg = MESSAGE_Alloc(node,
APP_LAYER,
APP_CBR_CLIENT,
MSG_APP_TimerExpired);
MESSAGE_InfoAlloc(node, timerMsg, sizeof(AppTimer));
timer = (AppTimer *)MESSAGE_ReturnInfo(timerMsg);
timer->sourcePort = clientPtr->sourcePort;
timer->type = APP_TIMER_SEND_PKT;
MESSAGE_Send(node, timerMsg, startTime);

The message type used here is MSG_APP_TimerExpired. Commonly needed


message type for the application layer are defined in QUALNET_HOME/include/
api.h.

The API function APP_SetTimer can also be used instead of the above code to
set a new App Layer Timer and send to self after specified delay. The function is
implemented in QUALNET_HOME/application/app_util.c.

2.4.5 Implementing Event Dispatcher: The Flow Controller


The event dispatcher implements event handling for the protocol. It is discussed in
detail in the Chapter 3, “Event Handling” on page 31.

80 QualNet 3.6 Developer’s Guide


The event dispatcher performs a series of switch statements to appropriately calls
the function that handles the particular event. Register the event dispatcher with
the application.c function APP_ProcessEvent.

A protocol's event dispatcher should include a switch on all message types that
the protocol may receive. It can then process each message type either inside the
switch or by calling a function to handle the message type received. However
before processing a message it must be determined which instance of the
application protocol this message is for. This can be done by looking up additional
information stored in the message info field such as source/destination port.

The following snippet from CBR handles the timer event that is set in the init
function. CBR operates by setting periodic timers to itself. Each time the timer
goes off, it sends virtual data packets to destination. It then sets a new timer to
occur after the periodic interval. In this way the data sending rate is achieved and
maintained.

In the following code, a call to the function


APP_UdpSendNewHeaderVirtualDataWithPriority is made to send packets to the
neighbors. This generates MSG_APP_FromTransport event at the receiver since
the packets arrive from the transport layer at the receiver. Thus this event is
handled by the function AppLayerCbrServer which is the protocol event
dispatcher function at the server. The event dispatcher at the client does not
handle this event but only generates it.

After the message is handled by the event dispatcher, it frees the memory
associated with the message by calling MESSAGE_Free(node, msg). It is
important to free the memory after the message has been handled as otherwise
the protocol will leak memory.

The event dispatcher should also include a default case in the switch statement to
handle error packets which contain an undefined msg->eventType.

QualNet 3.6 Developer’s Guide 81


Networking Using QualNet

AppLayerCbrClient(Node *node, Message *msg)


{
...
AppDataCbrClient *clientPtr;
...
switch(msg->eventType)
{
case MSG_APP_TimerExpired:
{
AppTimer *timer;
timer = (AppTimer *) MESSAGE_ReturnInfo(msg);
clientPtr = AppCbrClientGetCbrClient(node, timer->sourcePort);
...
switch (timer->type)
{
case APP_TIMER_SEND_PKT:
{
CbrData data;
...
data.sourcePort = clientPtr->sourcePort;
data.txTime = getSimTime(node);
...
APP_UdpSendNewHeaderVirtualDataWithPriority(....);
clientPtr->numBytesSent += clientPtr->itemSize;
clientPtr->numPktsSent++;
...
AppCbrClientScheduleNextPkt(node, clientPtr);
...
break;
}
...
}
default:
{
….
ERROR_ReportError(error);

}
…..
}
MESSAGE_Free(node, msg);
}

FIGURE 7. Event dispatcher for CBR Client

82 QualNet 3.6 Developer’s Guide


2.4.6 Packet Exchange: Sending/Receiving Packets
The application layer is good place to start protocol development. Being the
topmost layer it only sends and receives packets from the layer below, the
transport layer. This reduces and simplifies the API for packet exchange.

Packet exchange at any layer can be performed either by using the raw the
message API or by using the Layer specific API.

The complete and detailed API at the application layer is also available in the
application layer section of the QualNet API reference document. This also
includes API for using the SRM transport protocol. The implementation of these
API functions can be found in QUALNET_HOME/application/app_util.c.

While sending a packet to the transport layer the API generates the message
MSG_TRANSPORT_FromAppSend. This message is passed down the protocol
stack at the sender and up the protocol stack at the receiver. This process
happens transparently to the application layer. The application layer developer
only needs to be concerned with receiving the message from the transport layer at
the receiver. The transport layer sends the message MSG_APP_FromTransport
to the application layer when it has a packet for the application layer.

For broadcasting packets the destination address can be set to ANY_DEST or


library function NetworkIpGetInterfaceBroadcastAddress can be used to get the
interface broadcast address. The follow code sets the destination address to
interface broadcast address for wired interface and to ANY_DEST for wireless.

NodeAddress destAddress;
if (MAC_IsWiredNetwork(node, interfaceIndex))
{
destAddress =
NetworkIpGetInterfaceBroadcastAddress(node,
interfaceIndex);
}
else
{
destAddress = ANY_DEST;
}

To receive packets at the application layer, add a switch on


MSG_APP_FromTransport in the protocol's event dispatcher to receive packets
from the application layer. An example of this can be found in the function
AppLayerCbrServer in cbr.c. After the message has been received the packet

QualNet 3.6 Developer’s Guide 83


Networking Using QualNet

variable in the message structure can be used to access the payload. The API call
MESSAGE_ReturnPacket (msg) is used for this purpose. It is essentially a
#define stated in QUALNET_HOME/addons/seq/message.h.

#define MESSAGE_ReturnPacket(msg) (msg->packet)

The following code snippet from AppLayerCbrServer demonstrates how


MESSAGE_ReturnPacket is used and the payload is copied into another variable
called data. The code then gets the state pointer to the correct instance of the
server based on the source port of the application. It then updates the state to
reflect the received packet.

void AppLayerCbrServer(Node *node, Message *msg)


{
AppDataCbrServer *serverPtr;

switch(msg->eventType)
{
case MSG_APP_FromTransport:
{

UdpToAppRecv *info;
CbrData data;

info = (UdpToAppRecv *) MESSAGE_ReturnInfo(msg);


memcpy(&data, MESSAGE_ReturnPacket(msg), sizeof(data));

serverPtr = AppCbrServerGetCbrServer(node,
info->sourceAddr,
data.sourcePort);
...
serverPtr->numPktsRecvd++;
default:
{
...
ERROR_ReportError(error);
}
}
MESSAGE_Free(node, msg);
}

FIGURE 8. Event dispatcher for CBR Server

84 QualNet 3.6 Developer’s Guide


2.4.7 Collecting and Reporting Statistics
Each application protocol can be configured to record developer specified
statistics such as the following:
• Number of bytes sent
• Number of bytes received
• Number of packets sent

To enable statistics collection for the protocol, include the statistic collection
variables in the structure used to hold the protocol state e.g. the
AppDataCbrServer structure in cbr.h includes stat variables such as the following:
• long numBytesRecvd; // variable to record number of received bytes
• long numPktsRecvd; // variable to record number of received packets
• clocktype totalEndToEndDelay; // variable used to calculate throughput

The statistics related variables can also be defined in a structure and then that
structure be included in the state variable. QualNet designer follows this
approach.

Initialize stat variables in the init function of the protocol.


AppCbrServerNewCbrServer contains the following code for initializing the
statistics variables:

cbrServer->numBytesRecvd = 0;

cbrServer->numPktsRecvd = 0;

cbrServer->totalEndToEndDelay = 0;

After the declaration and initialization of the stat variables, increment or


decrement their value during the protocol life cycle, as required e.g. increment the
value of numPktsRecvd every time the receiver gets a packet. CBR's
AppLayerCbrServer function performs this task by executing the following code
when CBR receives a packet:

serverPtr->numBytesRecvd +=
MESSAGE_ReturnPacketSize(msg);

serverPtr->numPktsRecvd++;

QualNet 3.6 Developer’s Guide 85


Networking Using QualNet

As a final step towards statistics collection create a function to print statistics. This
function will be called in the finalize function of the protocol, which is discussed in
the next section.

In the print function, create a string containing the information to be printed along
with the statistic and statistic value into a combined single string e.g. the print
function of CBR, AppCbrServerPrintStats performs this as follows:

char buf[MAX_STRING_LENGTH];

sprintf(buf, "Total Bytes Received = %ld", serverPtr-


>numBytesRecvd);

The statistics are finally sent to the stat file by making a call to the IO_PrintStat
function (QUALNET_HOME/main/fileio.c). This function requires the following
parameters:
• Node pointer: Pointer to the node reporting the stat
• Layer: Set this to Application for application layer
• Protocol: String indicating protocol name
• Interface Address: Set to ANY_DEST if not needed.
• Instance Id: Instance identifier / port number
• Buf: String containing the stat

The following is a sample call to IO_PrintStat by from AppCbrServerPrintStats:

IO_PrintStat( node,
"Application",
"CBR Server",
ANY_DEST,
serverPtr->sourcePort,
buf);

2.4.8 The Finalize Function


The finalize function of the protocol is called by the simulator at the end of
simulation. It is the last code that executes during the lifestyle of a protocol. This
function is responsible for printing statistics to the stat file.

86 QualNet 3.6 Developer’s Guide


The finalize function of a protocol needs to be specified to the generic application
layer. This is done in APP_Finalize function in QUALNET_HOME/application.c.
To add the protocol's finalize function, add a case statement on the protocol name
and make a call to the finalize function within the case, as done for other protocols
in the function. In APP_Finalize, the finalize functions of Application layer routing
models are specified in the first switch statement and whereas the second switch
statement is used to specify finalize functions of application layer traffic
generators.

Like all other functions specify the prototype of the finalize function in the
protocol's header file. In the finalize function, make a call to the function
responsible for printing the statistics if application statistics collection was set to
true in the configuration file. Sample code follows:

Void AppCbrServerFinalize(Node *node, AppInfo* appInfo)


{
AppDataCbrServer *serverPtr =
(AppDataCbrServer*)appInfo->appDetail;
if (node->appData.appStats == TRUE)
{
AppCbrServerPrintStats(node, serverPtr);
}
}

2.5 Tips For Application Layer Routing Protocol

Application layer routing protocols function mostly as other application layer


protocols. They operate at the application layer and send/receive packets using
application layer API. However, there are certain differences in their
implementation. This section requires knowledge of the content in Chapter 4,
“Writing and Adding an Application Protocol” on page 67 and provides addition
implementation details necessary while implementing a routing protocol at the
application layer.

2.5.1 Calling INIT


The call to the init of a routing protocol is slightly different from that of a traffic
generating protocol. Call the init function of a routing protocol in APP_Initialize of
application.c and not in APP_InitializeApplications. Also call
NetworkIpAddUnicastRoutingProtocolType to add the unicast routing protocol to
interface.

QualNet 3.6 Developer’s Guide 87


Networking Using QualNet

Sample code follows:

if (strcmp(buf, "RIPv2") == 0)
{
NetworkIpAddUnicastRoutingProtocolType(
node,
ROUTING_PROTOCOL_RIPV2,
i);
RoutingRipv2Init(node, i, nodeInput);
}

2.5.2 Application Initialization: Init( )

2.5.2.1 Creating An Instance & Storing The State


While typically there may be multiple instances of the same traffic generating
protocol running on a node, there is only one instance of a routing protocol. This
one instance can be running on all interfaces of the node. To write a custom
routing protocol that runs multiple instances of itself at the same node, either
modify AppData or store it in a manner similar to application traffic generating
protocols.

The routing protocol state is stored in AppData. While AppData stores a list
containing all instances of the application layer traffic protocols, this is not the
case for routing protocols. It is recommended to store the single instance of any
custom routing protocol in AppData member routingVar. AppData contains the
following declarations for routing protocols:

void *routingVar; /* deprecated */


void *ripv2;
void *bellmanford;
void *olsr;

Another pointer can even be added in AppData for storing state if routingVar is
used by another custom routing protocol. The following code from
RoutingRipv2Init demonstrates how the routing protocol state is stored in
AppData.

// Allocate and init state.


ripv2 = (Ripv2 *) MEM_malloc(sizeof(Ripv2));
memset(ripv2, 0, sizeof(Ripv2));
// Set pointer in node data structure to RIPv2 state.
node->appData.ripv2 = (void *) ripv2;

88 QualNet 3.6 Developer’s Guide


2.5.2.2 Initializing Tables
Most routing protocols initialize their route tables in the init function. This may
include allocating memory to the data structure and setting initial values as
required. There is not one standard way of implementing a route table and
protocol designers are free to use any data structure well suited to their protocol.

Another commonly performed task in the init function is to add directly connected
networks as permanent routes to the route table. This can be performed by
looping through all the interfaces of the node and writing its network address,
interface address, and subnet mask to the route table.

The following code from function RoutingRipv2Init, demonstrates how to add


directly connected networks to the route table.

for (i = 0; i < node->numberInterfaces; i++)


{
Route *routePtr;

if (MAC_IsWiredNetwork(node, i))
{
if (!GetRoute(node,NetworkIpGetInterfaceNetworkAddress(node, i)))
{
routePtr = AddRoute(
node,
NetworkIpGetInterfaceNetworkAddress(node, i),
NetworkIpGetInterfaceSubnetMask(node, i),
NetworkIpGetInterfaceAddress(node, i),
0,
i,
i);
}
….
}

2.5.2.3 The Finalize Function


In APP_Finalize, the finalize functions of Application layer routing models are
specified in the first switch statement and whereas the second switch statement is
used to specify finalize functions of application layer traffic generators.

QualNet 3.6 Developer’s Guide 89


Networking Using QualNet

Before printing the statistics the routing protocol should check if


appData.routingStats is TRUE instead of appData.appStat.

If (node->appData.routingStats == TRUE)
{
printStat(….);
}

2.6 Using QualNet Designer For Application Layer


Development
QualNet Designer provides a comprehensive visual environment for designing
protocols. It acts as a integrated development environment, with compiler support.

Designer is also covered in detail in Chapter 5, “Using QualNet Designer” on


page 246. This section provides a quick insight into the potential benefits of
developing application layer protocols using Designer.

Designer offers a number of benefits to a protocol developer. It generates the


skeleton code for any protocol and plugs the protocol into the QualNet source
tree, thus providing a simplified mechanism for incorporating protocols into the
QualNet Simulator.

Protocols in designer are developed using a state diagram. This diagram is


achieved in code using the event dispatcher. To develop a protocol in Designer,
create the state diagram and add the code to the states. Designer can
automatically make additions to the QualNet source tree and saves an application
layer protocol developer the following effort:
• Creating files
• Adding application type to QualNet
• Specifying the event dispatcher in application.c
• Specifying the finalize function in application.c
• Coding the event dispatcher

By using Designer for developing an application layer protocol, modifications do


not need to be made to application.c. These are done by Designer automatically.

The remainder of the development process remains the similar except that code
can be directly added to the states.

90 QualNet 3.6 Developer’s Guide


Figure 9, “RipV2 state diagram in Designer” provides a sample snapshot of
designer state diagram of an application layer protocol (RIPv2).

FIGURE 9. RipV2 state diagram in Designer

QualNet 3.6 Developer’s Guide 91


Networking Using QualNet

3. Transport Layer
This section covers the following topics:
• Transport Layer Overview
• Transport Protocols in QualNet
• Transport Layer Organization: Files and Folders
• Data Structure
• API
• Writing and Adding a Transport Protocol

3.1 Transport Layer Overview


The transport layer provides the service of transporting application layer
messages between the client and server sides of an application. The transport
layer ensures the reliable arrival of messages. It provides error checking
mechanisms and data flow controls. The transport layer provides services for both
connection-mode transmissions and for connectionless-mode transmissions.
Figure 10, “QualNet Protocol Stack” illustrates transport layer residing just below
the application layer in the QualNet protocol stack. Because the application layer
resides on top of the transport layer and the network layer resides just below it,
the transport layer is responsible for interfacing with the application layer and the
network layer, as well as passing messages to and from these layers.

92 QualNet 3.6 Developer’s Guide


FIGURE 10. QualNet Protocol Stack

When the application layer sends a data packet to the transport layer, the data
packet is encapsulated into the transport layer protocol header and passed down
to the next layer Network (IP).

Similarly, when the transport layer receives a packet from Network layer, it
removes the transport layer header residing above the data packet and sends it
up to the application layer.

3.2 Transport Protocols in QualNet


The transport layer of the TCP/IP protocol suite consists of two protocols, UDP
and TCP. UDP provides an unreliable connectionless delivery service to send and
receive messages. TCP adds reliable byte stream-delivery services on top of the

QualNet 3.6 Developer’s Guide 93


Networking Using QualNet

IP datagram delivery service. QualNet also provides extension of RSVP that is


used to Label Switch Path (LSP) determination for MPLS.
This section covers the following topics:
• User Datagram Protocol (UDP)
• Transmission Control Protocol (TCP)
• Reservation Protocol (RSVP)

3.2.1 User Datagram Protocol (UDP)


The User Datagram Protocol (UDP) offers only a minimal transport service, non-
guaranteed datagram delivery. On the surface, an unreliable network protocol
may not seem very worthwhile or desirable. However, UDP can be very useful in
certain situations, and it has one key advantage over TCP—speed. The reliability
features built into TCP can be expensive in terms of overhead at execution time.
Many applications are better suited for UDP for the following reasons:
• No Connection Establishment
UDP does not introduce any delay for connection establishment before it starts
to transfer data. UDP simply starts transferring data without any formal
preliminaries.

94 QualNet 3.6 Developer’s Guide


• Small Packet Header Overhead
The UDP datagram has only 8 bytes of header overhead in every datagram.

• Unregulated Data Transmission Rate


There are some real time applications, which may tolerate some packet loss,
but require a minimum transmission rate. UDP has no congestion control
mechanism and its data transmission is contained by the application's data
generation rate and the access bandwidth.

In QualNet, the CBR (constant bit rate) application uses UDP in the transport
layer.

3.2.2 Transmission Control Protocol (TCP)


TCP, Transmission Control Protocol, is a Transport layer connection-oriented byte
stream protocol. This protocol is typically used by applications that require
guaranteed delivery.

QualNet 3.6 Developer’s Guide 95


Networking Using QualNet

• Connection Establishment
TCP is connection-oriented and it uses a three-way handshake before it starts
transmitting data. A TCP connection is always point-to-point, i.e., between a
single sender and a single receiver.

• Connection State
TCP maintains connection state in the end systems. This connection state
includes receive and send buffers, congestion control parameters, and
sequence and acknowledgment number parameters. This state information is
needed to implement TCP's reliable data transfer service and to provide
congestion control.

96 QualNet 3.6 Developer’s Guide


• Regulated Send Rate
TCP has a congestion control mechanism that throttles the sender when one
or more links between sender and receiver becomes excessively congested.
This throttling can have a severe impact on real-time applications, which can
tolerate some packet loss but require a minimum send rate.
QualNet TCP implementation supports following Five TCP variants.
• TAHOE: Consists of three TCP congestion control algorithms Slow Start,
Congestion Avoidance, and Fast Retransmit.
• RENO: Consists of TAHOE plus forth congestion control algorithm called
Fast Recovery.
• LITE: Consists of RENO plus Big Window and Protection Against Wrapped
Sequence Numbers options.
• NEWRENO: Consists of RENO with modification to Fast Recovery, (i.e.,
must receive an ACK for highest sequence number sent to exit Fast
Recovery).
• SACK: Consists of Selective Acknowledgement combined with RENO
congestion algorithm.

TCP applications implemented in QualNet, are FTP, FTP/GEN, HTTP, etc.

3.2.3 Reservation Protocol (RSVP)


RSVP is a control protocol in the transport layer. This protocol is not used to send
data packet from transport layer to IP layer. This is only used as control protocol in
transport layer and determines the resource in a path for the quality of service.
RSVP protocol is extended to determine label switch path (LSP), with or without
resource reservations in MPLS domain. When a LSP is established between two
MPLS nodes, then packets can be delivered through this LSP tunnel without
considering IP layer routing technique. Right now QualNet does not support basic
RSVP service to reserve any bandwidth. But with its functionality RSVP-TE has
been implemented.

3.3 Transport Layer Organization: Files and Folders


The following is a brief examination of what information is stored in which
directory and file. The transport layer API is composed of several macros,
functions, and structures.

QualNet 3.6 Developer’s Guide 97


Networking Using QualNet

These are defined in the following header files:


• QUALNET_HOME/include/api.h
This file defines the events and data structures needed to communicate
between different layers of the protocol stack.
• QUALNET_HOME/include/transport.h
This file contains definitions common to transport layer protocols and transport
data structure in node structure.

Additionally, the following header files are also relevant to the transport layer:
• QUALNET_HOME/include/fileio.h

The source code contains detailed comments on functions and other code
components. The following are the source files (*.c) associated with the transport
layer:
• QUALNET_HOME/transport
This folder contains the source and header files for the various QualNet
transport layer protocol implementations. The file names are indicative of the
protocols for which they provide an implementation e.g. to see the
implementation for UDP (User Datagram Protocol), look at udp.c and udp.h
files. For TCP implementation, see tcp.c and tcp.h and other associated files
kept at QUALNET_HOME/transport/tcp. RSVP-TE implementation is made at
rsvp.c and rsvp.h file.
• QUALNET_HOME/transport/transport.c
This file contains initialization function, message-processing function, and
finalize function used by transport layer.

3.4 Data Structure


This section covers the following topics:
• UDP
• Transport
• General Data Structure

98 QualNet 3.6 Developer’s Guide


3.4.1 UDP
• TransportUdpHeader—The UDP header structure is defined below. This UDP
header is added with the packet received from the application layer and
forwarded to the network layer.

typedef struct
{
unsigned short sourcePort; /* source port */
unsigned short destPort; /* destination port */
unsigned short length; /* length of the packet */
unsigned short checksum; /* checksum */
} TransportUdpHeader;

• TransportUdpStat—This is statistics structure of UDP. One instance of this


structure is kept in main UDP structure.

typedef struct
{
int numPktFromApp;
int numPktToApp;
} TransportUdpStat;

• TransportDataUdpStruct—The main UDP structure.

struct TransportDataUdpStruct
{
BOOL udpStatsEnabled; /* whether to collect stats */
TransportUdpStat *statistics; /* statistics */
BOOL traceEnabled;
};

3.4.2 Transport
• TransportProtocol—This is the structure to keep different transport layer
protocol. Add the new transport protocol at the end of this structure with a
proper name.

QualNet 3.6 Developer’s Guide 99


Networking Using QualNet

typedef enum {
TransportProtocol_UDP,
TransportProtocol_TCP,
TransportProtocol_SRM,
//InsertPatch TRANSPORT_ENUMERATION
TransportProtocol_RSVP
} TransportProtocol;

• TransportData—Main data structure of transport layer. Pointer of new


transport layer should be added here. Also if that protocol is not a mandatory
one, another Boolean variable should be maintained to indicate whether it is
enabled or disabled from the configuration.

struct struct_transport_str
{
TransportDataUdp* udp;
TransportDataTcp* tcp;
BOOL rsvpProtocol;
void *rsvpVariable;
BOOL srmProtocol;
void *srmVariable;
};

3.4.3 General Data Structure


• NetworkToTransportInfo—Structure that is used in the info field when
packets are sent from Network To Transport layer. Transport protocol should
receive the info field as this structure and gets proper information from the
Network layer.

Typedef struct
{
NodeAddress sourceAddr;
NodeAddress destinationAddr;
NetworkQueueingPriorityType priority;
int incomingInterfaceIndex;
unsigned receivingTtl;
BOOL isCongestionExperienced; /* ECN related variables */
} NetworkToTransportInfo;

• PacketTransportNetwork—Structure that is used in the info field when


packets are sent from the transport to the network layer. The transport layer

100 QualNet 3.6 Developer’s Guide


should create this structure and set all the information when forwarding any
received packet to network layer.

Typedef struct pkt_nstcp_to_network


{
NodeAddress sourceId;
NodeAddress destId;
long packetSize;
long agenttype;
short sourcePort;
short destPort;
NetworkQueueingPriorityType priority;
void *pkt;
} PacketTransportNetwork;

• TcpTimerPacket—TCP timer packet structure, where different timer types can


be set at timerType and event can be triggered. It is based on the timer type in
the receiving end.

Typedef struct tcp_timer__


{
int timerId;
int timerType;
int connectionId;
} TcpTimerPacket;

• AppToUdpSend—Additional information given to UDP from applications. This


information is saved in the info field of a message. UDP receives this message
and collects session and other information from this info field.

Typedef struct app_to_udp_send


{
NodeAddress sourceAddr;
short sourcePort;
NodeAddress destAddr;
short destPort;
NetworkQueueingPriorityType priority;
int outgoingInterface;
} AppToUdpSend;

QualNet 3.6 Developer’s Guide 101


Networking Using QualNet

• UdpToAppRecv—Additional information given to applications from UDP. This


information is saved in the info field of a message.

Typedef struct udp_to_app_send


{
NodeAddress sourceAddr;
short sourcePort;
NodeAddress destAddr;
short destPort;
int incomingInterfaceIndex;
} UdpToAppRecv;

The same types of structures are available for all other transport layer protocol.
For a new protocol written in the transport layer, users may need to add this kind
of structure in api.h to interact between application-transport and transport-
network.

3.5 APIs
This section covers the following topics:
• Message APIs
• Transport to Network APIs

3.5.1 Message
These APIs are called when transport layer forwards packets to the application
layer, and receives packets from application and network layer.
• MESSAGE_Send—This API is used to send a message within QualNet. When
a message is sent using this mechanism, only the pointer to the message is
actually sent through the system. So the user has to be careful not to do
anything with the content of the pointer once MESSAGE_Send has been
called.
Syntax: void MESSAGE_Send(Node *node, Message *msg, clocktype delay);
Parameters:
node: node which is sending message
msg: message to be delivered
delay: delay suffered by this message

102 QualNet 3.6 Developer’s Guide


• MESSAGE_CancelSelfMsg—This API is used to cancel a event message in
the QualNet scheduler. The msgToCancelPtr must a pointer to the original
message that needs to be canceled.
Syntax: void MESSAGE_CancelSelfMsg(Node *node, Message
*msgToCancelPtr);
Parameters:
node: node which is sending message
msgToCancelPtr: message to be canceled
• MESSAGE_Alloc—Allocates a new Message structure. This is called when a
new message has to be sent through the system.
Syntax: Message* MESSAGE_Alloc(Node *node, int layerType, int protocol,
int eventType);
Parameters:
node: node which is allocating message
layerType: layer type to be set for this message
protocol: destination protocol to be set for this message
eventType: event type to be set for this message
• MESSAGE_InfoAlloc—Allocates the info field for the message. This function
is used for the delivery of data for messages which are not packets as well as
the delivery of extra information for messages which are packets. If the info
field has previously been allocated for the message, it will be replaced by a
new info field with the specified size.
Syntax: void MESSAGE_InfoAlloc(Node *node, Message *msg, int infoSize);
Parameters:
node: node which is allocating payLoad
msg: message for which info field has to be allocated
infoSize: size of the info field to be allocated
• MESSAGE_PacketAlloc—Allocates the payLoad field for the packet to be
delivered. Adds additional free space in front of the packet for headers that

QualNet 3.6 Developer’s Guide 103


Networking Using QualNet

might be added to the packet. The packetSize variable is set to the packetSize
parameter specified in the function call.
Syntax: void MESSAGE_PacketAlloc(Node *node, Message *msg,
int packetSize, TraceProtocolType originalProtocol);
Parameters:
node: node which is allocating message
msg: message for which data has to be allocated
payLoadSize: size of the payLoad to be allocated
originalProtocol: protocol allocating this packet
• MESSAGE_AddHeader—This API is called to reserve additional space for a
header of size hdrSize for the packet enclosed in the message. The
packetSize variable in the message structure will be increased by hdrSize.
After this function is called, the packet variable in the message structure points
to the space occupied by this new header.
Syntax: void MESSAGE_AddHeader(Node *node, Message *msg,
int hdrSize, TraceProtocolType traceProtocol);
Parameters:
node: node which is adding header
msg: message for which header has to be added
hdrSize: size of the header to be added
traceProtocol: protocol name, from trace.h
• MESSAGE_RemoveHeader—This function is called to remove a header from
the packet enclosed in the message. The packetSize variable in the message
will be decreased by hdrSize.
Syntax: void MESSAGE_RemoveHeader(Node *node, Message *msg,
int hdrSize, TraceProtocolType traceProtocol);
Parameters:
node: node which is removing the header
msg: message for which header is being removed
hdrSize: size of the header being removed
traceProtocol: protocol removing this header.
• MESSAGE_Free—When the message is no longer needed it can be freed.
Firstly the payLoad and info fields of the message are freed. Then the

104 QualNet 3.6 Developer’s Guide


message itself is freed. It is important to remember to free the message.
Otherwise there will nasty memory leaks in the program.
Syntax: void MESSAGE_Free (Node *node, Message *msg);
Parameters:
node: node which is freeing the message
msg: message which has to be freed
• MESSAGE_Duplicate—Create a new message which is an exact duplicate of
the message supplied as the parameter to the function and return the new
message.
Syntax: Message *MESSAGE_Duplicate (Node *node, const Message *msg);
Parameters:
node: node which is calling message copy
msg: message for which duplicate has to be made
• MESSAGE_ReturnPacket & MESSAGE_ReturnPacketSize—Returns the
payload pointer and size of the current msg respectively. They take Message
pointer as the argument.
• MESSAGE_ReturnInfo & MESSAGE_ReturnInfoSize—Returns info pointer
and size of the info field respectively. It takes Message pointer as the
argument.
• MESSAGE_SetLayer—This API sets layer type when protocol fields and
message is given. The input syntax is MESSAGE_SetLayer(msg, layer,
protocol)
• MESSAGE_GetLayer & MESSAGE_GetProtocol—These two APIs retrieves
the actual layer and protocol type fields, when called with a message pointer.
• MESSAGE_SetEvent & MESSAGE_GetEvent—These two APIs sets or gets
the event, when called with a message pointer.

QualNet 3.6 Developer’s Guide 105


Networking Using QualNet

3.5.2 Transport to Network API


• NetworkIpReceivePacketFromTransportLayer—Called by transport layer
protocols (UDP, TCP etc.) to send UDP datagrams and TCP segments using
IP.
Parameters:
Node: pointer to node
Msg: pointer to message from transport layer containing payload data
sourceAddress: source IP address
destinationAddress: destination IP address
OutgoingInterface: outgoing interface to use to transmit packet
Priority: priority of packet
Protocol: IP protocol number
IsEcnCapable: asks is this node ECN capable?

3.6 Writing and Adding a Transport Protocol


In QualNet, a transport layer protocol provides the service of transporting
application layer messages to the network layer and vice versa. There are mainly
two transport protocols: TCP and UDP in QualNet. Either one of these two
transport protocols can transport application layer messages.

This section provides an architectural overview of the flow of a transport layer


protocol and gives an insight into developing and adding a new transport layer
protocol to QualNet. It describes in detail how to develop code components
common to most transport protocols, such as sending packets, receiving packets,
etc. As these steps are followed, look at the implementation code for UDP.
This section covers the following topics:
• Creating Files
• Deciding the Transport Configuration Format
• Integrating With QualNet
• Transport Initialization: Init( )
• Implementing Event Dispatcher: The Flow Controller
• Integration in IP Layer
• Packet Exchange: Sending/Receiving Packets
• Statistics Collection & Reporting

106 QualNet 3.6 Developer’s Guide


• The Finalize Function

3.6.1 Creating Files


The first step towards adding a transport layer protocol is to create the files. Most
protocols comprise of two files, the header file and the source file. Create the files
for the transport protocol and place them in the folder
QUALNET_HOME/transport. Name these files in a way that clearly indicates the
protocol that they implement.

Example:

udp.c, udp.h: Implement UDP

rsvp.c, rsvp.h: Implement RSVP

It is strongly recommended to have separate header and source files. Not having
a header file sometimes leads to unexpected problems, even if the compilation
process does not indicate any error.

Next, add these files to the QualNet source tree. Modify the file
QUALNET_HOME/main/Makefile-common to include the newly created files.
Add the header file (*.h) to the simulator header files section and the source file
(*.c) to the simulator source file section of Makefile-common. This addition
ensures that the files will be compiled. The files are sorted alphabetically for
easier organization, but it doesn't matter where it is inserted into the list.

Test that the files have been successfully added to the QualNet source tree by
compiling QualNet. This is done by performing the following steps:
1. Type the following command:

cd main

2. For Windows NT:

Run nmake -f Makefile-windowsnt

For linux:

Run make -f Makefile-linux

QualNet 3.6 Developer’s Guide 107


Networking Using QualNet

As code is added to the files, it is important to organize the code well between the
files. The header file should generally contain the following:
• Prototypes for functions in source file
• Constant definitions: All # defines
• Data structure definitions and data types: struct, enums

The transport layer source file should contain the following:


• Include declarations for appropriate header files
Add the following files to the source file. A typical transport layer file includes
these files:

#include <stdio.h>

#include "api.h"

#include "ip.h"

#include "udp.h"

• Dispatcher code
Here all the events specific to the protocols are dispatched.
• Protocol implementation functions
When adding the protocol, it is recommended to compile frequently to test the
code.

3.6.2 Deciding the Transport Configuration Format


A transport protocol might have an input format for specifying the user
configuration parameters. The QualNet configuration file contains these
configurations and the transport layer protocol should read them during the
initialization of the protocol. This is described in detail in Init section.

The syntax of the configuration format is as follows:

<Keyword> <value>

Where:
Keyword: Uniquely identifies the protocol.
Value: Identifies the value of that keyword.

108 QualNet 3.6 Developer’s Guide


As an example, the following configuration shows variant used by TCP.

TCP RENO

A configuration variable is not always mandatory. If an optional configuration is not


given, the program should consider the default value. For example, if a user does
not give the above configuration, the default variant LITE will be set by the TCP
program.

The time is always specified in QualNet Time Format.

The new transport layer protocol may not be a mandatory service in the transport
layer. In that case, keep an option in the configuration to make the protocol
enabled or disabled. The syntax of this configuration is as follows:

TRANSPORT-PROTOCOL-<Protocol_name> <status>

Where:
<Protocol_name>: the new transport layer protocol
<Status>: value is YES (protocol enabled) or NO (protocol disabled)

3.6.3 Integrating With QualNet


This section covers the following topics:
• Adding Transport Type
• Specifying The Event Dispatcher
• Reading Configuration Parameters and Calling Init( )

3.6.3.1 Adding Transport Type


Each node in QualNet hosts an operating protocol stack. This stack includes a list
of protocols at each layer that the node may be running. New transport protocols
need to be added to the list of transport layer protocols of the stack. The list of
transport layer protocols is specified by an enumerated data type called
TransportProtocol, which is defined in QUALNET_HOME/include/transport.h.

It is useful to understand how a node accesses the list of transport layer protocols.
Each node has a node structure, which holds all the information for the node. This
node structure contains a pointer to a structure called struct_transport_str
declared in file QUALNET_HOME/include/transport.h. A pointer to the newly

QualNet 3.6 Developer’s Guide 109


Networking Using QualNet

created protocol data structure should be kept in this structure. A graphical


representation is provided in Figure 11, “Transport Protocol Node Structures” to
understand the structures previously discussed.

Always add to the end of lists in header files. QualNet's pre-built object files use
the values, which existed when the object files were created. If a constant is
inserted at the top of the list, the values below will be offset in any new object files
and may lead to the simulator crashing.

If the transport protocol is not a mandatory one, such as TCP or UDP, a Boolean
flag should be added in TransportData structure along with the protocol structure
pointer. This Boolean is only true during runtime if the newly created protocol is
enabled.

FIGURE 11. Transport Protocol Node Structures

3.6.3.2 Specifying The Event Dispatcher


Specify the event dispatcher function of the protocol. This function is called when
events/messages are received for the protocol. Event dispatchers are explained
in detail in Chapter 3, “Events and Messages” on page 20.

The transport.c function TRANSPORT_ProcessEvent implements an transport


layer event dispatcher which informs the appropriate transport protocol of
received events. The transport layer event dispatcher calls a protocol-specific

110 QualNet 3.6 Developer’s Guide


event dispatcher. It checks the destination protocol of an event and passes the
event to the dispatcher function of the destination protocol. Add code to this
function to call the protocol's event dispatcher function.

Messages/Events contain the name of the protocol that they are destined for.
TRANSPORT_ProcessEvent implements a switch statement on the protocol
name read from the message. This is the transport protocol name specified in the
enumerated data type called TransportData. To enable the protocol to receive
events, add code to TRANSPORT_ProcessEvent, which calls the protocol's event
dispatcher function when messages for the protocol are received.

Figure 12, “Transport event dispatcher in transport/transport.c” shows code


fragment from TRANSPORT_ProcessEvent with sample code for calling event
dispatcher function of a transport layer traffic generation protocol.

void TRANSPORT_ProcessEvent(Node *node, Message *msg)


{
switch(MESSAGE_GetProtocol(msg))
{
….
case TransportProtocol_UDP:
{
TransportUdpLayer(node, msg);
break;
}
case TransportProtocol_RSVP:
{
if (node->transportData.rsvpProtocol == FALSE)
{
fprintf(stderr,
"RSVP must be enabled through"
" TRANSPORT-PROTOCOL-RSVP\n");
abort();
}
RsvpLayer(node, msg);
break;
}
// Your Transport Protocol
case TransportProtocol_YourProtocol:
{
YourProtocolLayer(node, msg);
break;
}
}
}

FIGURE 12. Transport event dispatcher in transport/transport.c

QualNet 3.6 Developer’s Guide 111


Networking Using QualNet

3.6.3.3 Reading Configuration Parameters and Calling Init( )


QualNet can configure protocols to user's specified parameters provided in the
QualNet configuration file, which sets up the experiment. This section explains
how to read these user-specified configuration parameters for the protocol and
providing them to the protocol's initialization function.

The function TRANSPORT_Initialize in transport/transport.c is the place from


where configuration parameters are read and stored in appropriate data structure.
The newly created transport protocol's initialization routine is also called from this
function. Following example shows how to call transport layer mandatory service
like TCP and UDP initialization routine.

If the transport protocol is not a mandatory one, then the function


TRANSPORT_Initialize first finds whether the protocol is enabled by searching
the keyword TRANSPORT-PROTOCOL-<protocol_name>. IO_ReadString is a
utility function that gives the value for the above configuration. The initialization
routine for the protocol will only be called when the protocol is kept enabled.

TRANSPORT_Initialize(Node * node, const NodeInput * nodeInput)


{
….
TransportTcpInit(node, nodeInput);
TransportUdpInit(node, nodeInput);

IO_ReadString(node->nodeId, ANY_ADDRESS,
nodeInput, "TRANSPORT-PROTOCOL-SRM", &wasFound, buf);

if (wasFound && strcmp(buf, "YES") == 0)


{
node->transportData.srmProtocol = TRUE;
TransportSrmInit(node, nodeInput);
}
else if (!wasFound || strcmp(buf, "NO") == 0)
{
node->transportData.srmProtocol = FALSE;
}
else
{
abort();
}
}

FIGURE 13. Calling TRANSPORT_Initialize

112 QualNet 3.6 Developer’s Guide


The parameters containing time related information are converted from string to
QualNet's clocktype variables by calling QualNet library function
TIME_ConvertToClock.

3.6.4 Transport Initialization: Init( )


This section covers the following topics:
• Initializing Timers

The initialization of a transport protocol happens in the init function of the protocol
that is called by the transport layer. The init function of a transport protocol
commonly performs the following tasks:
• Create an instance of the transport data structure. The transport protocol
should have a data structure that stores configuration variables and any other
information required. For example, TransportDataUdp is such a data structure
for UDP. The transport protocol's header file contains this data structure.
• Initialize data structures and variables as required, e.g. allocate memory to
tables, set default values etc.
• Initialize the state and store the user specified configuration parameters. The
Init routine should read QualNet configuration and store the different
configurable information in the protocol data structure. Functions such as
IO_ReadString are helpful to read them from the configuration.
• Schedule a timer to itself if required. This timer is protocol specific and if
required they are scheduled from Init routine. How to schedule a timer is
described below.

Like all other functions belonging to the transport, the prototype for init should be
included in the header file.

QualNet 3.6 Developer’s Guide 113


Networking Using QualNet

The example Init routine for UDP is shown here.

TransportUdpInit(Node *node, const NodeInput *nodeInput)


{
TransportDataUdp* udp = (TransportDataUdp*)MEM_malloc(sizeof(TransportDataUdp));
node->transportData.udp = udp;

IO_ReadString(node->nodeId, ANY_ADDRESS, nodeInput, "UDP-STATISTICS", &retVal, buf);

if (strcmp(buf, "YES") == 0)
{
udp->udpStatsEnabled = TRUE;
}
else if (strcmp(buf, "NO") == 0)
{
udp->udpStatsEnabled = FALSE;
}
else
{
abort();
}

if (udp->udpStatsEnabled == TRUE)
{
udp->statistics = (TransportUdpStat *)
MEM_malloc(sizeof(TransportUdpStat));
if (udp->statistics == NULL)
{
printf("TRANSPORT UDP: cannot allocate memory\n");
abort();
}
memset(udp->statistics, 0, sizeof(TransportUdpStat));
}
}

FIGURE 14. Transport protocol init

3.6.4.1 Initializing Timers


In addition to initializing data structures, the init function may also initialize timers
for the transport protocol.

Chapter 3, “Timer Events” on page 29 discusses in detail how to use timers. The
transport layer timers frequently use the message info field to distinguish the
message from which transport protocol appears. The info field is also used to
send any protocol specific information.

114 QualNet 3.6 Developer’s Guide


Create a data structure for the timer. The steps to create and send a timer are as
follows.
1. Create timer data structure in the protocol header file.
If the protocol requires more than type of a specific timer, then the timer data
structure should contain a field like timerType to identify type of the timer at
the receiving end. Different timer types also can be enumerated.
2. Allocate memory for that structure.
3. Get the memory pointer of that structure to Info field of the message.
MESSAGE_InfoAlloc function provides this functionality.
4. Assign proper value in the structure element
5. Send the message.

An example of creating a timer in RSVP is given below. It is not necessary to use


Info field always and in that case Info field is kept as null.

refreshPathMsg = MESSAGE_Alloc(node,
TRANSPORT_LAYER,
TransportProtocol_RSVP,
MSG_TRANSPORT_RSVP_PathRefresh);

MESSAGE_InfoAlloc(node, refreshPathMsg, sizeof(RsvpTimerStore));


timerStore = (RsvpTimerStore *)MESSAGE_ReturnInfo(refreshPathMsg);
timerStore = (RsvpTimerStore*) MEM_malloc(sizeof(RsvpTimerStore));
timerStore->messagePtr = refreshPathMsg;
timerStore->psb = cPSB;
MESSAGE_Send(node, refreshPathMsg, delayTime);

All the events used in the protocol should be included in the event enum structure,
with unique enumerated value.

3.6.5 Implementing Event Dispatcher: The Flow Controller


The event dispatcher implements event handling for the protocol. It is discussed in
detail in Chapter 3, “Event Handling” on page 31.

The event dispatcher performs a series of switch statements to appropriately call


the function that handles the particular event. Register the event dispatcher with
the transport.c function TRANSPORT_ProcessEvent.

A protocol's event dispatcher should include a switch on all message types that
the protocol may receive. It can then process each message type either inside the

QualNet 3.6 Developer’s Guide 115


Networking Using QualNet

switch or by calling a function to handle the message type received. However,


before processing a message, which instance of the transport protocol this
message is for must be determined. This can be done by looking up additional
information stored in the message info field.

The following example from UDP handles the event that is set from the application
and network layer. Against each such event, the program should have specific
activity, which can be written in a separate function. In the following example, the
name of such function is TransportUdpSendToApp. After the message is handled
by the event dispatcher, it frees the memory associated with the message by
calling MESSAGE_Free(node, msg) unless the called function frees the memory
itself. It is important to free the memory after the message has been handled.
Otherwise the protocol will leak memory.

The event dispatcher should also include a default case in the switch statement to
handle error packets which contain an undefined msg->eventType.

If the event is a timer, there may be a need to reschedule it after the processing is
finished. A rescheduled event triggers after the rescheduled time and will be
processed similarly.

116 QualNet 3.6 Developer’s Guide


FIGURE 15. Event dispatcher for UDP

3.6.6 Integration in IP Layer


The transport layer protocol should write a function in the ip.c file. Purpose of this
function is to collect the protocol-specific packet from IP network. DeliverPacket is
the function in ip.c where protocol type of the message is identified and proper
switching is made based on that protocol type. The following code shows how this
is done for UDP in DeliverPacket.

Now it is determined that this packet is for UDP protocol and the function
SendToUdp sends this packet up the hierarchy to the transport layer. The
following function shows how that can be done.

SendToUdp(….)
{
MESSAGE_SetEvent(msg, MSG_TRANSPORT_FromNetwork);
MESSAGE_SetLayer(msg, TRANSPORT_LAYER, TransportProtocol_UDP);
MESSAGE_InfoAlloc(node, msg, sizeof(NetworkToTransportInfo));
((NetworkToTransportInfo *) msg->info)->sourceAddr = sourceAddress;
((NetworkToTransportInfo *) msg->info)->destinationAddr =
destinationAddress;
((NetworkToTransportInfo *) msg->info)->priority = priority;
((NetworkToTransportInfo *) msg->info)->incomingInterfaceIndex =
incomingInterfaceIndex;
MESSAGE_Send(node, msg, PROCESS_IMMEDIATELY);
}

3.6.7 Packet Exchange: Sending/Receiving Packets


The transport layer resides between the application and network layers. It sends
and receives packet from the application layer, as well as the network layer.

QualNet 3.6 Developer’s Guide 117


Networking Using QualNet

QualNet provides set of APIs that are helpful to send and receive packets to
different layers. Packet exchanges at any layer can be performed either by using
the raw the message API or by using the layer-specific API.

The complete and detailed API at the transport layer is also available in the
QualNet API reference document. Transport protocols send packets to the
application layer by using different API sets from
QUALNET_HOME/main/message.c. The transport layer sends packets to the
network layer by using a set of APIs available at QUALNET_HOME/network/ip.c.

While sending packets to the application layer, the transport layer generates the
message MSG_APP_FromTransport. This message is passed up the protocol
stack to the application layer. The new protocol should handle this after receiving
it from the network layer. The following example is provided to demonstrate how
the packet is forwarded to the application layer properly. In this example, Info field
is used to carry the session information from the transport layer to the application
layer. The application layer developer should only be concerned with receiving the
message from the transport layer at the receiver.

FIGURE 16. Sending process to Application layer

118 QualNet 3.6 Developer’s Guide


For broadcasting packets, the destination address can be set to ANY_DEST or
the library function NetworkIpGetInterfaceBroadcastAddress can be used to get
the interface broadcast address. The following code sets the destination address
to interface broadcast address for wired interface and to ANY_DEST for wireless.

NodeAddress destAddress;
if (MAC_IsWiredNetwork(node, interfaceIndex))
{
destAddress = NetworkIpGetInterfaceBroadcastAddress(node, interfaceIndex);
}
else
{
destAddress = ANY_DEST;
}

The application layer sends packets to the transport layer by using the event
MSG_TRANSPORT_FromAppSend. To receive packets at transport layer, add a
switch on MSG_TRANSPORT_FromAppSend in the protocol's event dispatcher.
An example of this event trapping is shown at the function TransportUdpLayer in
“Specifying the Event Dispatcher” on page 71.

After receiving packets from the application layer, the transport layer forwards
them to the network layer by using APIs available in
QUALNET_HOME/network/ip.c. The transport protocol calls the network layer
APIs with the source and destination session information (IP address and port of
the source and destination address). The transport protocol must add the
transport layer header before sending packets to network layer. The following
example function shows how this has been done in the case of UDP. The
TransportUdpSendToNetwork function is called when
MSG_TRANSPORT_FromAppSend event is received. The message received
from the application layer has got the session information in the info field. The new
protocol should extract them from info field and creates transport header with the
help of them.

QualNet 3.6 Developer’s Guide 119


Networking Using QualNet

FIGURE 17. Sending process to the network layer

The API calls MESSAGE_ReturnPacket and MESSAGE_ReturnPacketSize are


normally used to get the packet pointer and size of the packet. They are
essentially #define stated in QUALNET_HOME/addons/seq/message.h. This
file also have additional APIs that can be used to collect different information of
the packet.

When the transport protocol receives packets from the network layer, it should
check whether this packet is for this layer only. If so, the protocol should trap the
message MSG_TRANSPORT_FromNetwork and the process it, as it requires.
The following code sample shows how RSVP handles
MSG_TRANSPORT_FromNetwork, this function, and process according to the
protocol.

120 QualNet 3.6 Developer’s Guide


FIGURE 18. Event dispatcher in RSVP

If the packet is for the application layer, then the transport layer should forward
this packet to the application layer. This is shown in the function
TransportUdpSendToApp above.

3.6.8 Statistics Collection & Reporting


Each transport protocol can be configured to record developer specified statistics.
This is totally dependent on the protocol. Statistics is shown at the end of the
simulation. So the protocol should allocate some space in its data structure so that
all the statistical related information can be stored during simulation. For example,
the UDP transport protocol uses following statistics structure to keep its statistics.

typedef struct
{
int numPktFromApp;
int numPktToApp;
} TransportUdpStat;

This statistics structure is kept inside the main UDP data structure as follows.
Here, udpStatsEnabled is the Boolean flag that stores whether statistics to be
shown is enabled or not in the configuration. As described earlier, the init routine
reads the statistics configuration variable from the configuration file and stores it in
a variables.

QualNet 3.6 Developer’s Guide 121


Networking Using QualNet

struct TransportDataUdpStruct
{
BOOL udpStatsEnabled;
TransportUdpStat *statistics;
….
};

Next, initialize stat variables in the init function of the protocol. The following code
shows how statistics is handled for UDP in the init routine.

During simulation, these statistics variables are updated as required. For


example, the following piece of code can be added when the transport layer
receives a packet from the application layer.

udp->statistics->numPktFromApp++;

TransportUdpInit(Node *node, const NodeInput *nodeInput)


{
….
IO_ReadString(node->nodeId, ANY_ADDRESS, nodeInput,
"UDP-STATISTICS", &retVal, buf);

if (strcmp(buf, "YES") == 0)
{
udp->udpStatsEnabled = TRUE;
}
else
{
if (strcmp(buf, "NO") == 0)
{
udp->udpStatsEnabled = FALSE;
}
}
else
{
printf("TransportUdp unknown setting (%s) for UDP-STATISTICS.\n", buf);
abort();
}

if (udp->udpStatsEnabled == TRUE)
{
udp->statistics = (TransportUdpStat *) MEM_malloc(sizeof(TransportUdpStat));
memset(udp->statistics, 0, sizeof(TransportUdpStat));
}
}

122 QualNet 3.6 Developer’s Guide


FIGURE 19. Statistics collection procedure

As a final step towards statistics collection, create a function to print statistics.


This function will be called in the finalize function of the protocol, which is
discussed in the next section.

In the print function, create a string containing the information to be printed along
with the statistic and statistic value into a combined single string e.g. the print
function of UDP for the above statistics should perform as follows:

char buf[MAX_STRING_LEN];
TransportDataUdp* udp = node->transportData.udp;
TransportUdpStat* st = udp->statistics;

sprintf (buf, "Packets from Application Layer = %d", st->numPktFromApp);


IO_PrintStat(node,
"Transport",
"UDP",
ANY_DEST,
-1,
buf);

The statistics are finally sent to the stat file by making a call to the IO_PrintStat
function (QUALNET_HOME/main/fileio.c). This function requires the following
parameters:
Node pointer: pointer to the node reporting the stat
Layer: set this to Transport for transport layer
Protocol: string indicating protocol name
Interface Address: set to ANY_DEST if not needed.
Instance Id: instance identifier / port number
Buf: string containing the stat

3.6.9 The Finalize Function


The finalize function of the protocol is called by the Simulator at the end of
simulation. It is the last code that executes during the life cycle of a protocol. This
function is responsible for printing statistics to the stat file.

QualNet 3.6 Developer’s Guide 123


Networking Using QualNet

The finalize function of a protocol needs to be specified to the generic transport


layer. This finalize function is added in TRANSPORT_Finalize function in
QUALNET_HOME/transport/transport.c.

Sample code of this transport finalize follows.

Like all other functions, specify the prototype of the finalize function in the
protocol's header file. In the finalize function, make a call to the function
responsible for printing the stats if the transport statistics collection was set to true
in the configuration file.

Sample code follows:

TransportUdpFinalize(Node *node)
{
char buf[200];
TransportDataUdp* udp = node->transportData.udp;
TransportUdpStat* st = udp->statistics;

if (udp->udpStatsEnabled == TRUE)
{
// call print statistics function
}

124 QualNet 3.6 Developer’s Guide


4. Network Layer
This section covers the following topics:
• Network Layer Overview
• Network Layer Protocols in QualNet
• Network Layer Organization: Files and Folders
• Data Structures
• APIs
• Routing a Packet
• Writing and Adding a Network Layer Routing Protocol
• QualNet Queuing Protocols

4.1 Network Layer Overview

The network layer provides a communication service between hosts to support


the transport layer for a communication service between two processes in two
different hosts. In particular, the network layer moves the transport layer segment
from the source host to the destination host. It's the lowest layer to deal with the
end-to-end issue. The main issues related to this layer are as follows:
• Routing: Path determination
• Switching: Datagrams or Virtual circuits
• Traffic Control: Congestion and Rate control
• Addressing: Finding a network node
• Internetworking: Interconnect heterogeneous network

QualNet 3.6 Developer’s Guide 125


Networking Using QualNet

Figure 20, “Network layer” illustrates the network layer residing in between the
transport and link layer in the QualNet protocol stack.

FIGURE 20. Network layer

4.2 Network Layer Protocols in QualNet


QualNet provides an implementation of a large number of network layer protocols,
which can be grouped into a number of categories. Each of these is briefly
discussed in subsequent sections.

This section covers the following topics:


• IP (Version 4)
• Routing Protocols
• QualNet Schedulers

126 QualNet 3.6 Developer’s Guide


• QualNet Queue Management Algorithms
• Access Lists
• Route Map
• Differentiated Services
• MPLS

4.2.1 IP (Version 4)
This section covers the following topics:
• IPv4 Addressing
• Fragmentation

The Internet Protocol (IP, documented in RFC 791) is the primary network layer
protocol in the TCP/IP protocol suite. It has two primary responsibilities:
• Providing connectionless, best-effort delivery of datagrams through an
internetwork.
• Providing fragmentation and reassembly of datagrams to support data links
with different MTU size.

When the network layer at the sending host receives a segment from the transport
layer, it encapsulates the segment into an IP datagram, writes the destination and
source IP address along with any other fields in the datagram, and sends it to the
first router on the path toward the destination host. The protocol treats each
datagram as an independent entity unrelated to any other datagram. There are no
connections or logical circuits. The protocol uses four key mechanisms in
providing its service:
• Type of Service (TOS)
• Time to Live (TTL)
• Options
• Header Checksum

QualNet 3.6 Developer’s Guide 127


Networking Using QualNet

An IP datagram contains several types of information as illustrated in figure 2.

FIGURE 21. IP Datagram

• Version—Indicates the version of IP currently used.


• IP Header Length (IHL)—Indicates the datagram header length in 32-bit
words.
• Type-of-Service—Specifies how an upper-layer protocol would like a current
datagram to be handled, and assigns datagrams various levels of importance.
• Total Length—Specifies the length, in bytes, of the entire IP packet, including
the data and header.

128 QualNet 3.6 Developer’s Guide


• Identification—Contains an integer that identifies the current datagram. This
field is used to help piece together datagram fragments.
• Flags—Consists of a 3-bit field of which the two low-order (least-significant)
bits control fragmentation. The low-order bit specifies whether the packet can
be fragmented. The middle bit specifies whether the packet is the last fragment
in a series of fragmented packets. The third or high-order bit is not used.
• Fragment Offset—Indicates the position of the fragment's data relative to the
beginning of the data in the original datagram, which allows the destination IP
process to properly reconstruct the original datagram.
• Time-to-Live—Maintains a counter that gradually decrements down to zero, at
which point the datagram is discarded. This keeps packets from looping
endlessly.
• Protocol—Indicates which upper-layer protocol receives incoming packets
after IP processing is complete.
• Header Checksum—Helps ensure IP header integrity.
• Source Address—Specifies the sending node.
• Destination Address—Specifies the receiving node.
• Options—Allows IP to support various options, such as security.
• Data—Contains upper-layer information.

As mentioned earlier, the function or purpose of Internet protocol is to move


datagrams through an interconnected network by passing the datagram from one
Internet module to another until the destination is reached. The datagrams are
routed through individual networks based on the interpretation of an Internet
address while the fragmentation meets the need to traverse a network whose
maximum packet size is smaller than the actual datagram.

4.2.1.1 IPv4 Addressing


The Internet modules use the addresses carried in the IP header to transmit the
datagram toward their destination. Each IP address is 32 bits long and this is
normally written in dotted decimal notation. An address begins with a network
number, followed by local address. Each interface on every host and router in the
global Internet must have an IP address that is globally unique.

IP addressing supports five different address classes: A, B, C, D, and E. Only


classes A, B, and C are available for commercial use. Class D addresses are

QualNet 3.6 Developer’s Guide 129


Networking Using QualNet

reserved for multicast addresses and class E are reserved for future use. The
table below describes a range of possible values exists for each address class.

It should be noted that these address classes are no longer formally part of the IP
addressing architecture. For a better utilization of the address space in 1993 IETF
standardize Classless Interdomain Routing (commonly known as CIDR).

4.2.1.2 Fragmentation
Fragmentation of an Internet datagram is necessary when it originates in a local
net that allows a large packet size and must traverse a local net that limits packets
to a smaller size to reach its destination.

The fragmentation and reassembly procedure needs to be able to break a


datagram into an almost arbitrary number of pieces that can be later reassembled.
The receiver of the fragments uses the identification field to ensure that fragments
of different datagrams are not mixed. The fragment offset field tells the receiver
the position of a fragment in the original datagram. The fragment offset and length
determine the portion of the original datagram covered by this fragment. The
more-fragments flag indicates (by being reset) the last fragment. These fields
provide sufficient information to reassemble datagrams.

4.2.2 Routing Protocols


This section covers the following topics:
• Unicast Routing
• Multicast Routing

130 QualNet 3.6 Developer’s Guide


In general, routing is moving information across an internetwork that involves the
following two activities:
• Optimal path determination
• Transporting packets through an internetwork (also referred to as switching)

Routing algorithms determine optimal path and store the information in routing
table. Routers communicate with one another and maintain their routing tables
through the transmission of a variety of messages. Based on the information of a
router, the packets are forwarded to the desired destination.

QualNet develops a variety of routing protocols, which can be grouped into the
following sections:
• Unicast routing: wireless ad hoc
• Unicast routing: wired
• Multicast Routing: wireless
• Multicast Routing: wired

The following table describes which protocols support which type of network.

Some other routing protocols are implemented at application layer and they
are not included here.

4.2.2.1 Unicast Routing


Routing can be done in a variety of ways and depending on underlying network
technologies and topology choices can be made. In general, this set of protocols
can be viewed as proactive or reactive. While proactive routing strategy is suitable
for wired network, they may not be a good choice for MANET (though OLSR and
STAR makes an exception of this general theory for some specific topology
configuration). Alternatively, reactive routing strategy works well for ad hoc
network in general but can cause extra overhead for wired network.

QualNet 3.6 Developer’s Guide 131


Networking Using QualNet

• Wireless ad hoc
One of the primary characteristics of ad hoc network is that network topology
constantly changing. It is recommended to evaluate routes only on an as-
needed basis. AODV and DSR are two typical example of this type of routing
protocol. Reactive routing protocols normally have two types of routing
packets, request/discovery and reply packet. Request packets are normally
flooded while reply packets are unicasted backed. These types of routing
protocols are efficient if routes are used infrequently and routes can become
sub optimal over time. These types of protocols (AODV, DSR, LAR1) uses their
own router function to forward a data packet, they don't populate IP forwarding
table.
Proactive routing is also popular for ad hoc networks. An example of this type
of routing protocol is STAR. Proactive routing protocols mainly used two types
of broadcast, periodic and triggered. They are efficient if routes are popular
and routes are always optimal. These types of protocols populate IP
forwarding table each time they calculated routes and data packets are
forwarded through IP module.
• Wired
Wired networks are comparatively stable and topology changes occur less
frequently than with wireless ad hoc networks. QualNet currently has four
routing protocols that support wired networks. These protocols normally
populate IP forwarding table with calculated routes and packets are forwarded
from IP module (i.e. routing protocols don't need to handle data packet
directly).

IGRP is an exception to this normal rule. Though it populates IP


forwarding table it handle data packets directly in order to use
multipath.

• Mixed Network
For mixed networks (i.e., switch ethernet, point-to-point, and wireless ad hoc
networks connected together,) OSPF is the only network layer routing protocol
that can be used for the entire mixed network.

4.2.2.2 Multicast Routing


QualNet implements a variety of multicast routing protocol in order to support
wired and wireless network.

132 QualNet 3.6 Developer’s Guide


• Wireless
ODMRP is the only wireless option. It's a mesh-based multicast scheme and
uses a forwarding group concept. The On Demand routing technique used by
ODMRP helps to avoid channel overhead and to improve scalability.
• Wired
All the wired multicast routing protocols implemented in QualNet are dense
mode protocols and build a source-based multicast delivery tree. The tree is
built when a router receives a multicast data packet first time for a particular
group. All of these protocols have their own forwarding function that is called
when a node needs to forward a multicast data packet.

4.2.3 QualNet Schedulers


This section covers the following topics:
• Strict Priority
• Round Robin
• Weighted Round Robin
• Weighted Fair
• Self Clocked Fair

4.2.3.1 Strict Priority


Strict Priority Scheduling is one of the first approaches used to provide different
services. Traffic is inserted into different queues that are served according to their
priority. Highest priority queue (queue with priority 0) are served as soon as they
have packets in there.

With strict priority scheduling, the queue with highest priority served first, and
continues to be served until it is empty which lead to starvation of queues with
lower priority.

4.2.3.2 Round Robin


Round Robin Scheduling is proposed to avoid starvation of queues with lower
priority. A Round Robin Scheduler alternates the service among the classes. For
example, if there are three types of priority packets 0, 1, 2 respectively, a class 0
packet (highest priority packet) is transmitted first, followed by a class 1 packet,
followed by a class 2 packet and then again a class 0 packet and so on.

QualNet 3.6 Developer’s Guide 133


Networking Using QualNet

Round Robin Scheduling avoids starvation of some queues and ensures that
traffic gets fair share of bandwidth. With this type of scheduling, services cannot
be prioritized.

4.2.3.3 Weighted Round Robin


Weighted Round Robin Scheduler can prioritize service so that different traffic
may be serviced differently. Each queue has a weight that reflects their allocated
bandwidth and allows the sending of specific quantities of data before giving
service to the next queue. The weight is usually given as a percentage of total
available bandwidth.

Weighted Round Robin improves the performance of Round Robin and ensures
traffic to get fair share of total bandwidth. However it does not solve the problem of
delay, because a packet arriving into a queue that has just been served has to
wait for the complete round robin before getting served, regardless of the
importance of the queue. This algorithm can't identify and punish ill-behaved
sessions, because it does not have congestion control and is sending large
amounts of traffic.

4.2.3.4 Weighted Fair


Weighted Fair Queue (WFQ) Scheduling was born to share bandwidth. Weights
are assigned to each queue, to reflect their allocated bandwidth. A virtual clock
V(t) is maintained. The progression of virtual time is defined as follows:

dV(t) / dt = 1 / (Sum of active sessions)

This means that when there are inactive sessions, the virtual time progresses
faster. The virtual finish time (F) of the first packet in each queue is stored in the
queue header. Whenever a new packet is enqueued, the corresponding F is
updated accordingly. The algorithm selects the queue with the smallest virtual
finish time (SF) for dequeue. Thus, an ill-behaved session, which is sending huge
traffic, will not affect the performance of other sessions, but will reduce its own
performance.

A strong limitation to the deployment of WFQ derives from its high computational
cost that arises from updating the virtual time on the arrival and departure of each
packet (keeping track of active flows).

134 QualNet 3.6 Developer’s Guide


4.2.3.5 Self Clocked Fair
Self Clocked Fair Scheduling solves the problem of higher complexity of Weighted
Fair Queuing to calculate finish time of a packet. SCFQ speeds up virtual time
computation with reduced complexity by using the finish number of the packet
currently in service (CF) as the virtual time function. Similar to WFQ, the queue
with smallest virtual finish time is selected for dequeue. Thus, with SCFQ, an ill-
behaved session that is sending a large amount of traffic and doesn’t have
congestion control will not affect the performance of other sessions, but will
reduce its own performance by punishing itself.
SCFQ inherits the features of Weighted fair with lesser computational complexity
and looser delay bound.

4.2.4 QualNet Queue Management Algorithms


This section covers the following topics:
• Best Effort Queue Management Techniques
• QoS (Diffserv) Queue Management Techniques

4.2.4.1 Best Effort Queue Management Techniques


Traditional Internet service model, Best Effort, is the simplest one and consists of
a generic assurance that the network would have done its best to transport data to
the destination. In this model, all packets compete equally for network resources.
This is the best choice if both the user requirements and the application
requirements are similar. The most popular best effort queuing mechanisms are
FIFO and RED.
• FIFO—First In First Out
It dequeues a packet first that entered first in that queue. It uses the simplest
queue management algorithm, i.e., the Drop Tail, where packets are dropped
when there is no more space in that queue buffer.
FIFO has several limitations. Since packets are discarded at burst (when the
queue is full all the incoming packets are discarded) the utilization of the
network varies quite a lot. When a certain number of applications are sending
packets from different source with same priority value, they will be queued in
the same queue at some intermediate node, to reach destination. Some of
those applications may have congestion control (such as TCP) that react at the
same time decreasing their sending rate. In this case the network oscillates
between high traffic and low traffic and it is not able to create equilibrium.

QualNet 3.6 Developer’s Guide 135


Networking Using QualNet

There can be malicious effects due to the source synchronization, where one
source does not experience any drop and another does.
• RED—Random Early Detection
It is an Active Queue Management (AQM) technique that detects incipient
congestion and provides feedback to end hosts by dropping the packets. The
motivation behind RED is to keep the queue size small, reduce burstiness and
solve the problem of global synchronization. RED drops packets before the
actual physical queue is full. It operates based on an average queue length
that is calculated using an exponential weighted average of the instantaneous
queue length. RED drops packets with certain probability depending on the
average length of the queue. The drop probability increases from 0 to
maximum drop probability (maxp) as average queue size increases from
minimum threshold (minth) to maximum threshold (maxth). If average queue
size goes above maxth, all packets are dropped.

However, RED suffers from some fairness problem—it cannot identify any
preferentially nor can it differentiate and penalize misbehaving users.

4.2.4.2 QoS (Diffserv) Queue Management Techniques


The applications that use the network to transfer data from a location to a remote
one are the following:
• The remote terminal (telnet)
• Data transfer (ftp)
• Mail exchange (SMTP)

136 QualNet 3.6 Developer’s Guide


These applications have different requirements. Remote terminal requires small
bandwidth but, being an interactive application, it needs small delay. Data transfer
requires high bandwidth but it can tolerate delays. Mail exchange can be seen as
a batch form of data transfer and its requirements are basically the same ones as
FTP transfers.

A mechanism that helped to differentiate traffic is needed. The rise in usage and
popularity of the Internet, coupled with new applications such as voice, video, and
the web has fueled research to improve the Quality of Service delivered by the
best effort networks today. The underlying concept in IP Quality of Service (IP-
QoS) is the ability of network operators to offer differing levels of treatment to user
traffic based on their requirements.

The Differentiated Services (DS) architecture has recently become the preferred
method to address QoS issues in IP networks. This packet marking based
approach to IP-QoS is attractive due to its simplicity and ability to scale. DS
domain, a Diffserv Architecture term, refers to a contiguous set of nodes which
operate with a common set of service provisioning policies and Per Hop Behavior
(PHB) definitions. Per domain services are realized by traffic conditioning at the
edge and simple differentiated forwarding mechanisms (such as Expedited
Forwarding (EF), Assured Forwarding (AF), etc.) at the core of the network.
Assured forwarding is a group of 12 PHBs (4 classes X 3 levels of drop
precedence). The levels of drop precedence are as follows:
• Level Low Drop, DP0
• Level Medium Drop, DP1
• Level High Drop, DP2

To build service with AF, subscribed traffic profiles for customers are maintained at
the network edge traffic conditioning nodes. The aggregated traffic is monitored
and packets are marked at the traffic conditioner on the basis of Service Level
Agreement (SLA) between the customer and service-provider. The marking can
be two colors marking:
• In profile (Packets with lower drop precedence, DP0)
• Out Profile (Packets with higher drop precedence)

OR it can be three colors marking:


• Green profile (Packets with lower drop precedence, DP0)
• Yellow profile (Packets with medium drop precedence, DP1)

QualNet 3.6 Developer’s Guide 137


Networking Using QualNet

• Red (Packets with lower drop precedence, DP2)

RFC 2597 recommends that an Active Queue Management (AQM) technique


should be used to realize the multiple levels of drop precedence required in the
AF PHB. Most implementations of AF use RED like Active Queue Management
technique where different sets of RED parameters are maintained for different
colored packets. This configuration is referred as MRED (Multi-level RED). There
are several ways to extend RED to a Multilevel RED (MRED) algorithm, suitable
for the AF PHB that can identify any preferences and can punish misbehaving
applications. SAMT (Single Average Multiple Threshold) and MAMT (Multiple
Average Multiple Threshold) are different ways of implementing MRED. SAMT is
better known in the Internet community by the name WRED (Weighted RED).
With two colors marking, RIO is the most popular MAMT variant of MRED. Two
simple approaches to the MAMT variant of MRED are GRIO-C (Generalized RED
with In/Out and Coupled average Queues) and GRIO -DC (Generalized RED with
In/Out and Decoupled average Queues) with three-color drop precedence.
• WRED—Weighted RED
It uses three RED algorithms—one destined for packets marked green
(minth_g, maxth_g, Pmax_g), the other for the packets marked yellow
(minth_y, maxth_y, Pmax_y), and the last one for the packets marked red
(minth_r, maxth_r, Pmax_r). It drops red packets more aggressively than
dropping the yellow packets. Likewise, it drops yellow packets more
aggressively than dropping the green packets. When congestion occurs, it first
drops red packets, and if the congestion persists it drops all yellow packets.
When the gateway is flooded with green packets, as a last resort it drops green
packets in the hope of controlling congestion. How it drops the red, yellow, or
green packets depends on the RED parameter specification for each color.

• RIO (Coupled and Decoupled)


RIO-C | DC implemented in TWO | THREE color mode. In three-color mode it
uses three different sets of RED parameters—one for green packets (minth_g,
maxth_g, Pmax_g), one for yellow packets (minth_y, maxth_y, Pmax_y), and
the other for the red packets (minth_r, maxth_r, Pmax_r). In two-color mode

138 QualNet 3.6 Developer’s Guide


there is only two sets of threshold parameters—one for green [In profile]
packets (minth_g, maxth_g, Pmax_g) and the other for out profile yellow and
red packets (minth_y, maxth_y, Pmax_y).
In RIO-C, the average queue size different colors can be calculated by adding
its average queue size to that of the average queue size of lower drop
precedence colors. For example, for yellow colored packets, the average
queue will be calculated using green and yellow packets. RIO-C derives its
name from the coupled relationship of the average queue calculation. The
implication of this scheme is that the drop probability for packets with higher
drop precedence is dependent on the buffer occupancy of packets having
lower drop precedence. Thus, there is an inherent assumption that it is better
to drop DP1 and DP2 packets for DP0 packets. Similarly, for DP1 packets, it is
assumed better to drop DP2 packets. Services based on AF implementations
utilizing RIO-C will be subject to this restriction.

In RIO-DC (RIO with Decoupled Queues), the average queue size for packets
of each color is calculated independently. In this scheme, the average queue
length for a color is calculated using number of packets of that color in the
queue only. The average queue length for green, yellow and red packets are
calculated using the number of green, yellow and red packets in the queue
respectively. The RED parameter settings can be chosen depending on the
treatment to be given to different colors. RIO-DC appears to be the most
suitable MRED-variant if the operator desires to assign weights to different
colored packets within the same queue i.e. there is no relationship between the
packets marked green and yellow. Thus, the RIO-DC scheme could start to
emulate the WRR scheduling scheme except that a single queue is used.

4.2.5 Access Lists


Access Lists (AL) is used in routers and gateways to identify and control traffic.
Access lists define a set of criteria's that give added control for filtering packets
that enter inbound interfaces and packets that exit the router's or gateway's
outbound interfaces. It can filter based on source and destination address,

QualNet 3.6 Developer’s Guide 139


Networking Using QualNet

specific IP protocol, port number, TOS, precedence and other protocol specific
parameters.

Access lists are a group of statements, also called criteria's. Each statement
defines a pattern that would be found in an IP packet. As each packet enters or
leaves an interface with an associated access list, the list is scanned from top to
bottom--in the exact order that it was entered for a pattern that matches the
incoming packet. A permit or deny rule associated with the pattern determines
that packet's fate. A mask, which is like a wild card, to determine how much of an
IP source or destination address to apply to the pattern match.

Once the access list is entered, it must associate with the interface on the router
to apply the filtering. Access lists do not act on packets that originate from the
router itself, such as routing updates or outgoing telnet sessions.

4.2.6 Route Map


Route maps have criteria for matching the details of certain packets and an action
of permitting or denying those packets. Along with the match commands a set
criteria is added that can change the packet or the route information in a specified
manner. Route maps are used when we want detailed control over how routes are
redistributed between routing processes. When passing routes through a route
map, a route map can have several parts of match and set clause. Any route that
does not match at least one match clause relating to a route-map command will
be ignored, that is, the route will not be advertised for outbound route maps and
will not be accepted for inbound route maps.

140 QualNet 3.6 Developer’s Guide


Some of the uses of Route maps are as follows:
• To control redistribution
• To control and modify routing information
• To define policies in policy routing

4.2.7 Differentiated Services


Differentiated Services (DiffServ) is architecture for deploying IP QoS (Quality of
Service), where QoS is a set of service requirements (e.g., bandwidth, link delay)
to be met by the network during transmission of traffic. This architecture is flexible
and allows for either end-to-end QoS or intra-domain QoS by implementing
complex classification and mapping functions at the network boundary or access
points. Within the DiffServ network, packet behavior is regulated by classification
and mapping.

When it enters the network, flow of traffic is classified and assigned a PHB (Per-
Hop Behavior) based on that classification. PHB is the externally observable
forwarding treatment that packets with the same DiffServ Code Point (DSCP)
receive from a network node. The contents of the DSCP are the six most
significant bits in the IP header Type of Service (TOS) field. Within the IP packet,
the DSCP tells how the packet should be treated at each network node.
Additionally, the mapping of DSCP to PHB is configurable, and DSCP may be re-
marked as it passes into a DiffServ network. Re-marking of DSCP allows for the
variable treatment of packets based on network specifications or desired levels of
service.

Within PHB, there are two standard groups: Assured Forwarding (AF) and
Expedited Forwarding (EF). Within AF, the group is further divided into four
independent classes with three drop precedence levels. AF offers different levels
of forwarding resources in each DiffServ node. In the case of network congestion,
the relative importance of the packet determines its drop precedence among other
packets in its AF class. EF, on the other hand, known as premium service, gives
the best service a network can offer. EF is defined as a forwarding treatment
where the rate of packet flow from any DiffServ node is whatever rate ensures
highest priority and no packet loss for in-profile traffic.

4.2.8 MPLS
Multi Protocol Label Switching (MPLS) is a Network layer protocol that enables
levels of Quality of Service (QoS) by forwarding packets towards their destination

QualNet 3.6 Developer’s Guide 141


Networking Using QualNet

without using conventional IP routing. MPLS creates Forwarding Equivalence


Classes (FEC), or classes of IP packets that are forwarded over the same path.
MPLS partitions all the packets into FEC's and then gives the same label to all
packets of the same FEC.

Multi Protocol Label Switching-Label Distribution Protocol (MPLS-LDP) is a set of


procedures by which one Label Switching Router (LSR) informs another LSR
about labels. These labels are used in MPLS to determine the path by which
packets of the same class are sent. LDP distributes labels among LSRs and
prepares the Label Switched Path (LSP).

Each FEC has an LSP associated with it. An LSR builds up LSPs by exchanging
Label Request Messages and Label Reply Messages, with the ultimate goal of
having a path for each FEC of packets. If an LSR does not have a label for a
particular FEC, it requests a label from its most promising downstream neighbor. If
that downstream node has a label for that FEC, it immediately replies back with a
label; otherwise the original request is forwarded to the next downstream neighbor
for a label.

When a new data packet arrives at the network, it is mapped to a particular FEC.
LDP associates a label to that FEC. At each hop, unlike IP, there is no need to
analyze the packet's network layer header and make a forwarding decision.
Rather, the label is used as an index into a table that specifies the next hop and a
new label. The old label is replaced with the new label, and the packet is
forwarded to its next hop, and so on until the packet reaches its final destination.

In addition to MPLS-LDP, Reservation Protocol with Traffic Engineering (RSVP-


TE) is also capable of creating LSPs among LSRs.

4.3 Network Layer Organization: Files and Folders


This section briefly examines what files are needed for network protocols in and in
which folders they are located.
• QUALNET_HOME/include/api.h
This file defines the events and data structures needed to communicate
between different layers of the protocol stack.
• QUALNET_HOME/include/network.h
This file contains definitions common to network layer protocols and network
data structure in node structure.

142 QualNet 3.6 Developer’s Guide


• QUALNET_HOME/network/ip.h
This file contains definitions of data structure and parameters used in IP and
also prototypes of the functions defined in ip.c.

The following header files are also relevant to the network layer:
• QUALNET_HOME/include/fileio.h
This file contains various prototypes defined in fileio.c that might be needed for
parsing of input configuration file.
• QUALNET_HOME/include/buffer.h
This file contains data structures and prototypes to allocate, manipulate and
delete packet memory and generic data buffer.
• QUALNET_HOME/network/list.h
This file defines a generic doubly link list structure and prototypes related to
insertion, deletion etc.
• QUALNET_HOME/network/ipqueue.h
This file defines IP Queue/Scheduler Structures, function pointers, prototypes
of various utility functions related to QualNet queue and scheduler.
• QUALNET_HOME/network
This folder contains various network layer protocols implemented in QualNet.
The file names are indicative of the protocol for which they provide an
implementation. To implement a network layer protocol, place the source files
here.

4.4 Data Structures


Data structures do the following:
• Describe the enums used, such as NetworkRoutingAdminDistanceType and
NetworkRoutingProtocolType
• Describe the structs used, such as NetworkData (i.e., struct_network_str)
• Describe in detail about the interface data structure
• Describe in detail about the unicast forwarding table data structure

This section describes various enums, structure that are commonly used and
accessed in writing a network layer protocol. Commonly used structures and
enums are defined in mainly two files. QUALNET_HOME/include/network.h and
QUALNET_HOME/network/ip.h.

QualNet 3.6 Developer’s Guide 143


Networking Using QualNet

This section covers the following topics:


• Header File: network
• Header File: ip

4.4.1 Header File: network


This section provides details about the network header file.

The default priority values for queues and packets are as follows:
• CONTROL 0
• REAL_TIME 1
• NON_REAL_TIME 2

Because there are three types, 3 is a good minimum value for the input
configuration parameter IP-QUEUE-NUM-PRIORITIES. If it's specified as less
than 3, the lower priority packets will be placed in the lowest-priority queue.

The default values for queues are as follows:


• DEFAULT_IP_QUEUE_COUNT 3
• DEFAULT_CPU_QUEUE_SIZE 640000 (in byte)
• DEFAULT_NETWORK_INPUT_QUEUE_SIZE 150000 (in byte)
• DEFAULT_NETWORK_OUTPUT_QUEUE_SIZE 150000 (in byte)

Default input/output Queue size is taken when they are not specified in the input
configuration file through IP-QUEUE-PRIORITY-QUEUE-SIZE.

The ENUMS are as follows:


• NetworkRoutingAdminDistanceType
Administrative distances for various routing protocols implemented are defined
here. These values don't match the specified Cisco values. A route with lower
administrative distance is preferred over higher one.
• NetworkRoutingProtocolType
Various network layer protocols type are defined here. The value is used to set
the protocol type field when initiating a self-timer so that appropriate protocol
event handler function could get the trigger. The value is also used in some

144 QualNet 3.6 Developer’s Guide


other places, such as in IP forwarding table to identify which routing protocol
have contributed the route etc.

The STRUCTURE is as follows:


• struct_network_str
This is the main data structure of network layer typedefed to NetworkData in
QUALNEY_HOME/include/main.h.

4.4.2 Header File: ip


This section provides details about the ip header file.

Most of the variables have a self-descriptive name and one can understand its
purpose by looking its name. Some of the important member variables are
described in each following subsection.
• NetworkDataIp
This is the main structure of IP module that is liked to the universal node
structure through the networkVar pointer variable of NetworkData. All other
background network protocol (e.g. routing protocol, icmp, etc.) should have a
link with this structure.
Member: forwardTable
Data Type: NetworkForwardingTable
Description: IP forwarding table. Wired routing protocols populate this
table as they calculate new routes. Wireless routing
protocols normally don't use this table (STAR is an exception
of this).

Member: interfaceInfo[MAX_NUM_INTERFACES]
Data Type: IpInterfaceInfoType*
Description: Array of pointer, of which each element points to an interface
structure indexed by array index. MAX_NUM_INTERFACES
is the maximum number of interface QualNet support. The
value is defined in QUALNET_HOME/include/main.h.

QualNet 3.6 Developer’s Guide 145


Networking Using QualNet

Member: phbInfo
Data Type: IpPerHopBehaviorInfoType*
Description: Contains TOS field to Queue mapping information that was
given in input configuration file specified by
PER-HOP-BEHAVIOR-FILE in default.config. Based on this
information a node decides which queue will be used to store
a data packet.

Member: mftcInfo
Data Type: IpMultiFieldTrafficConditionerInfo*
Description: Main data structure for Diffserv.

Member: ipMftcParameter
Data Type: IpMftcParameter*
Description: Contains multifield traffic conditioner parameters used in
Diffserv.

Member: ipForwardingEnabled
Data Type: BOOL
Description: Specify whether this node will act as a router (i.e. whether
they'll forward data packet or not). Setting
IP-FORWARDING to YES in default.config file can set the
value.

Member: multicastGroupList
Data Type: List*
Description: List of multicast group this node has joined.

Member: routeUpdateFunction
Data Type: NetworkRouteUpdateEventType
Description: Pointer to a function used by IP to trigger a protocol (e.g.
PIM-DM) when a unicast route add/delete or change.

146 QualNet 3.6 Developer’s Guide


• IpInterfaceInfoType
Structure to hold IP interface related information.
Member: scheduler
Data Type: SchedulerType
Description: Holds generic structure for scheduler applied to output
queue.

Member: inputScheduler
Data Type: SchedulerType
Description: Holds generic structure for scheduler applied to input and
cpu queue.

Member: inputScheduler
Data Type: SchedulerType
Description: Holds generic structure for scheduler applied to input and
cpu queue.

Member: routerFunction
Data Type: RouterFunctionType
Description: A pointer to the function provided by routing protocol running
over this interface. The function will be responsible to route a
packet to its final destination. This function generally used by
wireless ad hoc routing protocols. Wired routing protocols
normally don't use this function. The function can be set by
calling NetworkIpSetRouterFunction() from the protocol
module.

Member: routingProtocol
Data Type: void*
Description: Data pointer pointing to the main data structure of the routing
protocol running over this interface. The address of this
pointer normally passed to the routing protocol module at
initialization time.

QualNet 3.6 Developer’s Guide 147


Networking Using QualNet

Member: multicastRouterFunction
Data Type: MulticastRouterFunctionType
Description: The purpose of this function pointer is same as
routerFunction described above except this if used by
multicast routing protocols. The pointer can be set by calling
NetworkIpSetMulticastRouterFunction().

Member: multicastRoutingProtocol
Data Type: void*
Description: Data pointer pointing to the main data structure of multicast
routing protocol.

Member: macLayerStatusEventHandlerFunction
Data Type: MacLayerStatusEventHandlerFunctionType
Description: Function pointer that allows the MAC layer to send status
messages (e.g., packet drop, link failure) to a network-layer
routing protocol for routing optimization. It’s used by wireless
routing protocols. The pointer is set by calling
NetworkIpSetMacLayerStatusEventHandlerFunction().

Member: promiscuousMessagePeekFunction
Data Type: PromiscuousMessagePeekFunctionType
Description: Sometimes it might be a necessity for a network layer
protocol to overhear packets destined to neighboring nodes.
This function pointer will be set by the protocol wants to
check every packets passing through its own interface. The
setting can be done by calling
NetworkIpSetPromiscuousMessagePeekFunction(). To
check packet promiscuously one need to set
PROMISCUOUS-MODE to YES in default.config file. When
this is enable mac call NetworkIpSneakPeekAtMacPacket()
directly from mac layer which in turn call the appropriate
function through this function pointer. Currently dsr is using
this feature so one can check the related file for a good
example.

148 QualNet 3.6 Developer’s Guide


Member: macAckHandler
Data Type: MacLayerAckHandlerType
Description: It's also a function pointer that holds a callback function
handling mac layer acknowledgement that it has successfully transmitted a
packet. The pointer can be set by calling NetworkIpSetMacLayerAckHandler().

• NetworkForwardingTableRow
Structure that describe a single row in IP forwarding table.

Member: destAddress
Data Type: NodeAddress
Description: Destination address for which this row has been inserted in
routing table.

Member: destAddressMask
Data Type: NodeAddress
Description: Mask of the destination. This in combination with
destAddress gives the destination network/host.

Member: interfaceIndex
Data Type: int
Description: Outgoing interface index to reach this destination.

Member: nextHopAddress
Data Type: NodeAddress
Description: Address of next hop router (or the final node/network if it's
directly reachable).

Member: cost
Data Type: int
Description: Cost of sending a packet out this interface.

QualNet 3.6 Developer’s Guide 149


Networking Using QualNet

Member: protocolType
Data Type: NetworkRoutingProtocolType
Description: Routing protocol that has contributed this route to IP
forwarding table.

Member: adminDistance
Data Type: NetworkRoutingAdminDistanceType
Description: Administrative distance of the protocol. If there are two routes
(contributed by two different protocol) to the same destination
with same cost then this will be the determining factor of
choosing the preferred route.

Member: interfaceIsEnabled
Data Type: BOOL
Description: It's a flag indicating whether the outgoing interface is enabled
or not.

4.5 APIs
This section discusses what the different APIs QualNet provide at the network
layer. This section contains the following topics:
• APIs for Transport Layer Interface
• APIs for IP Background Protocols
• APIs for Mac to Network Layer Interface
• APIs for Mac to Network Layer Callback Function
• APIs Related to Router Function

4.5.1 APIs for Transport Layer Interface


• NetworkIpReceivePacketFromTransportLayer—Called by transport layer
protocols (UDP, TCP) to send UDP datagrams and TCP segments using IP.
Simply calls NetworkIpSendRawMessage().
SYNTAX:
void NetworkIpReceivePacketFromTransportLayer(
Node *node,

150 QualNet 3.6 Developer’s Guide


Message *msg,
NodeAddress sourceAddress,
NodeAddress destinationAddress,
int outgoingInterface,
NetworkQueueingPriorityType priority,
unsigned char protocol,
BOOL isEcnCapable);
PARAMETERS:
node: Pointer to node.
msg: Pointer to message from transport layer containing
payload data (UDP datagram, TCP segment) for an
IP packet. (IP header needs to be added)
sourceAddress: Source IP address. See
NetworkIpSendRawMessage() for special values.
destinationAddress: Destination IP address.
outgoingInterface: outgoing interface to use to transmit packet.
priority: Priority of packet.
protocol: IP protocol number.
isEcnCapable: Is this node ECN capable?
RETURN: void

• SendToUdp—Sends a UDP packet to UDP in the transport layer. The source


IP address, destination IP address, and priority of the packet are also sent.
SYNTAX:
void SendToUdp(
Node *node,
Message *msg,
NetworkQueueingPriorityType priority,
NodeAddress sourceAddress,
NodeAddress destinationAddress,
int incomingInterfaceIndex);

QualNet 3.6 Developer’s Guide 151


Networking Using QualNet

PARAMETERS:
node: Pointer to node.
msg: Pointer to message with UDP packet.
Priority: Priority of packet.
sourceAddress: Source IP address.
destinationAddress: Destination IP address.
incomingInterfaceIndex: interface that received the packet.
RETURN: void

• SendToTcp—Sends a TCP packet to TCP in the transport layer. The source IP


address, destination IP address, and priority of the packet are also sent.

SYNTAX:
void SendToTcp(
Node *node,
Message *msg,
NetworkQueueingPriorityType priority,
NodeAddress sourceAddress,
NodeAddress destinationAddress,
BOOL aCongestionExperienced);

PARAMETERS:
node: Pointer to node.
msg: Pointer to message with TCP packet.
Priority: Priority of packet.
sourceAddress: Source IP address.
destinationAddress: Destination IP address.
aCongestionExperienced:Determine if congestion is experienced (via ECN).
RETURN: void

• SendToRsvp—Sends a RSVP packet to RSVP in the transport layer. The


source IP address, destination IP address, and priority of the packet are also
sent.

SYNTAX:

152 QualNet 3.6 Developer’s Guide


void SendToRsvp(
Node *node,
Message *msg,
NetworkQueueingPriorityType priority,
NodeAddress sourceAddress,
NodeAddress destinationAddress,
int interfaceIndex,
unsigned ttl);

PARAMETERS:
node: Pointer to node.
msg: Pointer to message with RSVP packet.
Priority: Priority of packet.
sourceAddress: Source IP address.
destinationAddress:Destination IP address.
interfaceIndex: incoming interface index.
ttl: Receiving TTL.
RETURN: void

• SendToSrm—Sends a SRM packet to SRM in the transport layer. The source


IP address, destination IP address, and priority of the packet are also sent.

SYNTAX:
void SendToSrm(
Node *node,
Message *msg,
NetworkQueueingPriorityType priority,
NodeAddress sourceAddress,
NodeAddress destinationAddress);

PARAMETERS:
node: Pointer to node.
msg: Pointer to message with SRM packet.
Priority: Priority of packet.
sourceAddress: Source IP address.
destinationAddress:Destination IP address.

QualNet 3.6 Developer’s Guide 153


Networking Using QualNet

RETURN: void

4.5.2 APIs for IP Background Protocols


• NetworkIpSendRawMessage—Called by
NetworkIpReceivePacketFromTransportLayer() to send UDP datagrams, TCP
segments using IP. Also called by network-layer routing protocols (AODV,
OSPF, etc.) to send IP packets. This function adds an IP header and calls
RoutePacketAndSendToMac().

SYNTAX:
void NetworkIpSendRawMessage(
Node *node,
Message *msg,
NodeAddress sourceAddress,
NodeAddress destinationAddress,
int outgoingInterface,
NetworkQueueingPriorityType priority,
unsigned char protocol,
unsigned ttl);

PARAMETERS:
node: Pointer to node.
msg: Pointer to message with payload data for IP packet.
(IP header needs to be added).
sourceAddress: Source IP address. If sourceAddress is ANY_IP, lets IP
assign the source address (depends on the route).
destinationAddress:Destination IP address.
outgoingInterface: outgoing interface to use to transmit packet.
priority: Priority of packet.
protocol: IP protocol number.
ttl: Time to live. See AddIpHeader() for special values.
RETURN: void

• NetworkIpSendRawMessageWithDelay—Same as
NetworkIpSendRawMessage(), but schedules event after a simulation delay.

154 QualNet 3.6 Developer’s Guide


SYNTAX:
void NetworkIpSendRawMessageWithDelay(
Node *node,
Message *msg,
NodeAddress sourceAddress,
NodeAddress destinationAddress,
int outgoingInterface,
NetworkQueueingPriorityType priority,
unsigned char protocol,
unsigned ttl,
clocktype delay);

PARAMETERS:
node: Pointer to node.
msg: Pointer to message with payload data for IP packet. (IP
header needs to be added).
sourceAddress: Source IP address. If sourceAddress is ANY_IP, lets IP
assign the source address (depends on the route).
destinationAddress:Destination IP address.
outgoingInterface: outgoing interface to use to transmit packet.
priority: Priority of packet.
protocol: IP protocol number.
ttl: Time to live.
delay: Scheduled delay.
RETURN: void

• NetworkIpSendRawMessageToMacLayer—Called by network-layer routing


protocols (AODV, OSPF, etc.) to add an IP header to payload data, and with
the resulting IP packet, calls NetworkIpSendPacketOnInterface().

SYNTAX:
void NetworkIpSendRawMessageToMacLayer(
Node *node,
Message *msg,
NodeAddress sourceAddress,

QualNet 3.6 Developer’s Guide 155


Networking Using QualNet

NodeAddress destinationAddress,
NetworkQueueingPriorityType priority,
unsigned char protocol,
unsigned ttl,
int interfaceIndex,
NodeAddress nextHop);

PARAMETERS:
node: Pointer to node.
msg: Pointer to message with payload data for IP packet. (IP
header needs to be added).
sourceAddress: Source IP address.
destinationAddress:Destination IP address.
priority: Priority of packet.
protocol: IP protocol number.
ttl: Time to live. See AddIpHeader() for special values.
interfaceIndex: outgoing interface to use to transmit packet.
nextHop: Next hop IP address.
RETURN: void

• NetworkIpSendRawMessageToMacLayerWithDelay—Same as
NetworkIpSendRawMessageToMacLayer(), but schedules the event after a
simulation delay by calling NetworkIpSendPacketOnInterfaceWithDelay().

SYNTAX:
void NetworkIpSendRawMessageToMacLayerWithDelay (
Node *node,
Message *msg,
NodeAddress sourceAddress,
NodeAddress destinationAddress,
NetworkQueueingPriorityType priority,
unsigned char protocol,
unsigned ttl,
int interfaceIndex,
NodeAddress nextHop,
clocktype delay);

156 QualNet 3.6 Developer’s Guide


PARAMETERS:
node: Pointer to node.
msg: Pointer to message with payload data for IP packet. (IP
header needs to be added).
sourceAddress: Source IP address.
destinationAddress:Destination IP address.
priority: Priority of packet.
protocol: IP protocol number.
ttl: Time to live. See AddIpHeader() for special values.
interfaceIndex: outgoing interface to use to transmit packet.
nextHop: Next hop IP address.
delay: Scheduled delay.
RETURN: void

• NetworkIpSendPacketToMacLayer—This function is called once the


outgoing interface index and next hop address to which to route an IP packet
are known.

SYNTAX:
void NetworkIpSendPacketToMacLayer(
Node *node,
Message *msg,
int interfaceIndex,
NodeAddress nextHop);

PARAMETERS:
node: Pointer to node.
msg: Pointer to message with ip packet.
interfaceIndex: outgoing interface to use to transmit packet.
nextHop: Next hop IP address.
RETURN: void

• NetworkIpSendPacketToMacLayerWithNewStrictSourceRoute—Tacks on
a new source route to an existing IP packet and then sends the packet to the
MAC layer.

QualNet 3.6 Developer’s Guide 157


Networking Using QualNet

SYNTAX:
void NetworkIpSendPacketToMacLayerWithNewStrictSourceRoute(
Node *node,
Message *msg,
NodeAddress newRouteAddresses[],
int numNewRouteAddresses,
BOOL removeExistingRecordedRoute);

PARAMETERS:
node: Pointer to node.
msg: Pointer to message with ip packet.
newRouteAddresses: Source route (address array).
numNewRouteAddresses: Number of array elements.
removeExistingRecordedRoute: Flag to indicate previous record route should
be removed or not.
RETURN: void

4.5.3 APIs for Mac to Network Layer Interface


• NetworkIpReceivePacketFromMacLayer—IP received IP packet from MAC
layer. Determine whether the packet is to be delivered to this node, or needs to
be forwarded. The ipHeader->ip_ttl is decremented here, instead of the way
BSD TCP/IP does it, which is to decrement TTL right before forwarding the
packet. QualNet's alternative method suits its network-layer ad hoc routing
protocols, which may do their own forwarding.

SYNTAX:
void NetworkIpReceivePacketFromMacLayer(
Node *node,
Message *msg,
NodeAddress previousHopNodeId,
int interfaceIndex);

PARAMETERS:

158 QualNet 3.6 Developer’s Guide


node: Pointer to node.
msg: Pointer to message with ip packet.
previousHopNodeId: nodeId of the previous hop.
interfaceIndex: Index of interface on which packet arrived.
RETURN: void

4.5.4 APIs for Mac to Network Layer Callback Function


• NetworkIpSneakPeekAtMacPacket—Called directly by the MAC layer, this
allows a routing protocol to view messages it would not normally see from the
MAC layer. This function will possibly defragment such packets and call the
function registered by the routing protocol to do the viewing.

SYNTAX:
void NetworkIpSneakPeekAtMacPacket(
Node *node,
const Message *msg,
int interfaceIndex,
NodeAddress prevHop);

PARAMETERS:
node: Pointer to node.
msg: The message being peeked at from the MAC layer. It must
not be freed or modified.
interfaceIndex: The interface of which the viewed message belongs to
packet drop.
prevHop: Previous hop address of the packet.
RETURN: void

• NetworkIpReceiveMacAck—Inform IP layer that packet has been delivered


successfully. Called Directly by the MAC layer after it receives an ack of
previously sending packet.

SYNTAX:

QualNet 3.6 Developer’s Guide 159


Networking Using QualNet

void NetworkIpReceiveMacAck(
Node* node,
int interfaceIndex,
const Message* msg,
NodeAddress nextHop);

PARAMETERS:
node: Pointer to node.
interfaceIndex: Interface associated with the ACK handler function.
msg: Message that was ACKed.
nextHop: Next hop that sent the MAC layer ACK.
RETURN: void

4.5.5 APIs Related to Router Function


• NetworkIpSetRouterFunction—Allows a routing protocol to set the routing
function (one of its functions) which is called when a packet needs to be
routed. NetworkIpSetRouterFunction() allows a routing protocol to define the
routing function. The routing function is called by the network layer to ask the
routing protocol to route the packet. The routing function is given the packet
and its destination. The routing protocol can route the packet and set
PacketWasRouted to TRUE; or not route the packet and set to FALSE. If the
packet, was not routed, then the network layer will try to use the forwarding
table or the source route the source route in the IP header. This function will
also be given packets for the local node the routing protocols can look at
packets for protocol reasons. In this case, the message should not be modified
and PacketWasRouted must be set to FALSE.

SYNTAX:
void NetworkIpSetRouterFunction(
Node *node,
RouterFunctionType RouterFunctionPtr,
int interfaceIndex);

PARAMETERS:
node: Pointer to node.
routerFunctionPtr: Pointer to the router function to be set.

160 QualNet 3.6 Developer’s Guide


interfaceIndex: Interface that will be associated with router function.
RETURN: void

• NetworkIpGetRouterFunction—Get the router function pointer.

SYNTAX:
RouterFunctionType NetworkIpGetRouterFunction(
Node *node,
int interfaceIndex);

PARAMETERS:
node: Pointer to node.
interfaceIndex: Interface for which we want the router function.
RETURN: Router function pointer associated with this interface.

4.6 Routing a Packet


One of the major responsibilities of network layer is to route a packet. This section
describes how an IP packet is routed and queued at the appropriate interface
output queue.

RoutePacketAndSendToMac—The main routing module of IP layer.

View RoutePacketAndSendToMac() function as the starting point. After normal IP


layer processing (e.g. adding IP header to payload at sending node or
decrementing TTL in a intermediate node) processing node call this function with
message containing IP packet as an argument to it. The following are its other
arguments.
• node: Pointer to node.
• IncomingInterface: Index of interface on which packet arrived. This is different
if the packet originated from the network or transport layers. This value is only
for multicast packets, currently.
• outgoingInterface: Used only when the application specifies a specific interface
to use to transmit packet.

QualNet 3.6 Developer’s Guide 161


Networking Using QualNet

The logical path followed by the packet is illustrated with following figure.

162 QualNet 3.6 Developer’s Guide


FIGURE 22. Packet Path

RoutePacketAndSendToMac

Determine what routing protocol to use. If current node is


originator of packet routing protocol should be associated with
outgoing interface, otherwise use incoming interface.

YES
Destination is a
broadcast address?

Outgoing interface should have


NO already been determined before
this. So sent it over that interface.

Destination is a YES
multicast address?

Let multicast router function handle


NO this packet. If it fails try to forward
with IP Multicast forwarding table.
If it’s fails also then drop the
packet.
Packet requires QoS
service and Q-OSPF YES End
running?
Let Q-OSPF handle the routing of
this packet. It gives full path for
NO source routing, if packets come from
predetermined connection.

Is MPLS enable? YES

NO Transfer the packet to MPLS.

YES
Packet already
routed?
Packet already
routed?
End NO
Get router function associated with YES NO
the interface determined at first
step. If router function is available
let it handle the packet. If it has a source route try to
forward with it. Otherwise try to
forward with IP forwarding table.

End

QualNet 3.6 Developer’s Guide 163


Networking Using QualNet

Once the routing decision has been made (i.e. once the outgoing interface and
next hop address is known), the NetworkIpSendPacketOnInterface() function is
called to send the packet on desired interface. This function queues an IP packet
for delivery to the MAC layer. It takes the following arguments.
• node: Pointer to the node.
• msg: Pointer to the message containing IP packet.
• IncomingInterface: Index of incoming interface
• outgoingInterface: Index of outgoing interface
• nextHop: IP address of next hop.

If an access list is specified over this interface this function checks whether
access list permits the packet. If not, then it simply drops the packet silently.
Otherwise it calls NetworkIpSendOnBackplane().
• NetworkIpSendOnBackplane()—This is an internal static function of IP
module. It simulates the backplane delay before they are further processed. Its
arguments are same as previous function. If backplane throughput capacity is
specified as NETWORK_IP_UNLIMITED_BACKPLANE_THROUGHPUT it
simply call QueueUpIpFragmentForMacLayer() with appropriate interface
index, otherwise it tries to insert the packet in CPU Queue (if queue is not full
already, if so then just drop the packet) by calling the function
NetworkIpCpuQueueInsert() and call the function
NetworkIpUseBackplaneIfPossible().
• NetworkIpUseBackplaneIfPossible()—This function basically determines
whether backplane is busy. If so it just returns. Otherwise if there is any packet
that needs to go through the backplane then it just calculates the required
delay and sends a self-timer with event MSG_NETWORK_Backplane.
• NetworkIpLayer()—Catches the event when this timer expire and calls
NetworkIpReceiveFromBackplane().
• NetworkIpReceiveFromBackplane()—This function de-queued the packet
from the queue, set the backplane status to idle so that other packets waiting at
queue can use it and then calls QueueUpIpFragmentForMacLayer() with
appropriate interface index.
• QueueUpIpFragmentForMacLayer()—If the Diffserv Multi-Field Traffic
Conditioner is enabled it first checks whether or not the Diffserv Multi-Field
Traffic Conditioner will drop this packet. If Diffserv allows the packet it checks if
the output queue for the specified interface is empty or full, and calls
NetworkIpOutputQueueInsert() to queue the IP packet. If queue is already full

164 QualNet 3.6 Developer’s Guide


just drops the packet. If the queue was empty before this packet it informs
MAC layer that network layer has packet to send. From now on MAC takes the
responsibility to transmit the packet.

4.7 Writing and Adding a Network Layer Routing Protocol


This section provides an architectural overview of the flow of a Network Layer
Routing Protocol and gives an insight into developing and adding a new routing
protocol manually to QualNet. It describes in detail how to develop code
components common to most routing protocols such as sending packets,
receiving and processing packets, etc. As we follow these steps we will look at the
sample code for my_route, an example on-demand routing protocol.

This section covers the following topics:


• Explanation of a Routing Protocol
• Overview of Protocol Integration

4.7.1 Explanation of a Routing Protocol?


A routing protocol in QualNet is responsible for determining the next hop or full
path of a data packet between source and destination
• The Routing Protocol discovers the network topology by sending and receiving
its own control packets.
• These packets are transmitted via API calls to IP.
• IP at the receiving end passes the control packets it successfully receives to
the routing protocol.
• IP also gives the routing protocol the data packets that need "next hop" or full
path information.

4.8 QualNet Queuing Protocols

QualNet queuing protocols currently implemented in network layer and all source
and header files for queues are found in the QualNet/network folder.
The following section describes how to add a new queuing protocol e.g. 'GREEN'
in QualNet. Assume the source filename is greenqueue.c and the corresponding
header is greenqueue.h.

QualNet 3.6 Developer’s Guide 165


Networking Using QualNet

This section covers the following topics:


• Data Structure
• Interfacing Functionalities
• Initialization

4.8.1 Data Structure


This section covers the following topics:
• Specify Queue Type
• Internal Structure Definitions for Queue

Queue specific general data structures are maintained in file


QualNet/network/ipqueue.h.

4.8.1.1 Specify Queue Type


Queue Types available at Network Layer is given in structure
NetworkIpQueueType.

typedef enum {
FIFO_QUEUE,
RED_QUEUE,
RIO_QUEUE,
WRED_QUEUE,
// Add any new Queue Type before this entry
DEFAULT_QUEUE
} NetworkIpQueueType;

To insert a new Queue Type, a symbolic constant for the queuing type (e.g.,
GREEN_QUEUE), should be inserted just before the DEFAULT_QUEUE entry.

4.8.1.2 Internal Structure Definitions for Queue


IpQueue structure contains the internal structure definitions for Queue. If the new
queue requires some more variables they need to be assigned in the void pointer
available in this structure.

Example

queue->queueVar = greenQueue;

166 QualNet 3.6 Developer’s Guide


Where greenQueue is the internal structure for the
"Green Queue".

typedef struct ip_queue_type


{………
// Access excess queue specific data structure via this
pointer
void *queueVar;
……….
} IpQueue;

4.8.2 Interfacing Functionalities


This section covers the following topics:
• Enqueue
• Dequeue
• Check if Queue is Empty
• Get Number of Packets in Queue
• Drop Packet from Queue
• Finalize

There are six interface functions for QualNet queues as depicted in the IpQueue
structure.

// Standard Function Pointers for queue

IpQueueInsertFunctionType insertFunction;

IpQueueRetrieveMsgAndMaybeDequeueFunctionType retrieveFunction;

IpQueueIsEmptyFunctionType isEmptyFunction;
IpQueueNumberInQueueFunctionType numberInQueueFunction
IpQueueFinalizationFunctionType finalizationFunction;
IpQueueDropPacketFromQueueFunctionType packetDropFunction;

These interface functions are accessed via function pointers and kept separately
in the source file specified for that queue, e.g., greenqueue.c. These functions
are briefly described in the following sections.

QualNet 3.6 Developer’s Guide 167


Networking Using QualNet

NB: User written functions should match the function prototype of these interface
functions.

4.8.2.1 Enqueue
The Enqueue function inserts an incoming packet in the Queue. This is
associated with the function pointer IpQueueInsertFunctionType.
Example

For GREEN queue, the insert function will look like the follwoing:

GreenInsert()
{
// Do GREEN queue specific operations
……….
// NB. Insert a packet in the queue using this generic
function kept in ipqueue.h.
GenericQueueInsert();

// Update variables and statistic changes during this


operation.

………
}

4.8.2.2 Dequeue
The Dequeue function Dequeue a packet from the Queue. This is associated with
the function pointer IpQueueRetrieveMsgAndMaybeDequeueFunctionType.
Example

For GREEN queue, the Dequeue function will look like the following:

GreenDequeue()

{
// Do GREEN queue specific operations
……….
// NB. Dequeue a packet from queue using this generic
function kept in ipqueue.h.
GenericQueueDequeue();
// Update variables and statistic changes during this

168 QualNet 3.6 Developer’s Guide


operation.
………
}

4.8.2.3 Check if Queue is Empty


The isEmptyFunction checks if the queue is empty or not. This functionality is
associated with the function pointer "IpQueueIsEmptyFunctionType".
Example

For GREEN queue, the isEmptyFunction will look like the following:

GreenIsEmpty()
{
// NB. Checks for a packet in the queue using this
generic function kept in ipqueue.h.
return(GenericQueueIsEmpty());
}

4.8.2.4 Get Number of Packets in Queue


The numberInQueueFunction checks total number of packets in the Queue and
returns its value. This functionality is associated with the function pointer
IpQueueNumberInQueueFunctionType.
Example

For GREEN queue, the numberInQueueFunction will look like the following:

GreenNumberInQueue ()
{
// NB. Get number of packet in the queue using this
generic function kept in ipqueue.h.
return(GenericNumberInQueue());
}

4.8.2.5 Drop Packet from Queue


The packetDropFunction drops a packet from the queue in case of link/interface
failure. This functionality is associated with the function pointer
IpQueueDropPacketFromQueueFunctionType.
Example

For GREEN queue, the packetDropFunction will look like the following:

QualNet 3.6 Developer’s Guide 169


Networking Using QualNet

GreenDropPacketFromQueue()

{
// NB. Drop a packet from the queue using this
generic function kept in ipqueue.h.
GenericDropPacketFromQueue();
}

4.8.2.6 Finalize
The finalizationFunction is required to print final statistics collected for this queue
at the end of the simulation. This functionality is optional.

If one doesn't want to print final statistics for this protocol, the associated function
pointer for this functionality, IpQueueFinalizationFunctionType, should be
initialized to NULL. Otherwise this function would look like the following:

GreenFinalize()

{
// Print Extra statistics associated with this
queue
……………..
// NB. Get generic statistics for queue using this
generic function kept in ipqueue.h.
GenericQueueFinalize();
}

4.8.3 Initialization
QualNet queue type is specified in configuration file using the key IP-QUEUE-
TYPE. This is read by the network layer from the file QualNet/network/ip.c.

IP-QUEUE-TYPE GREEN

The inserted string 'GREEN' is verified by NetworkIpReturnQueueType() and


'NetworkIpQueueType' is returned. Insert the following code block in this function
body just before the default return statement.

NetworkIpReturnQueueType()
{
else if (strcmp(qTypeString, "GREEN") == 0)
{
return GREEN_QUEUE;

170 QualNet 3.6 Developer’s Guide


}
return UserInterfaceReturnQueueType(qTypeString);
}

After getting 'NetworkIpQueueType', the function NetworkIpSetupQueue() is


called to setup configured queue type at the interfaces. Add initialization function
for new queue types here.

NetworkIpSetupQueue()

{
// Add initialization functions for new queueing
types here.

// The enum NetworkIpQueueType is defined in


network/ipqueue.h.

switch (queueType)
{
case FIFO_QUEUE:
{
FifoInitialize();
break;
}
…………….
case GREEN_QUEUE:
{
GreenQueueInitialize();
break;
}
default:
{
UserInterfaceInitializeQueue();
}
}//switch//
……….
}

The Queue specific initialization function namely GreenQueueInitialize() definition


should be kept in the source file for that queue. A declaration of this function
should be kept in the associated header (e.g., greenqueue.h).

The following steps will lead to the integration of a new queue, e.g., GREEN, in
QualNet.

QualNet 3.6 Developer’s Guide 171


Networking Using QualNet

This function body should contain following initialization blocks.

GreenQueueInitialize(…,IpQueue *queuePtr,…)
{
//NB. Initializing the common variables and structures
for queue using this generic function kept in
ipqueue.h.

GenericQueueInit();

// Memory allocation and Initialization for 'Green


Queue' structure (if any)

// Read and assign configuration parameters GREEN QUEUE


(if any)

// Initializing function pointers for GREEN

queuePtr->insertFunction = &GreenInsert;
queuePtr->retrieveFunction = &GreenDequeue;
queuePtr->isEmptyFunction = &GreenIsEmpty;
queuePtr->numberInQueueFunction = &GreenNumberInQueue;
queuePtr->packetDropFunction =
&GreenDropPacketFromQueue;
if (Want to Collect Statistics)
{
queuePtr->finalizationFunction = &GreenFinalize;
}
else
{
queuePtr->finalizationFunction = NULL;
}
}

172 QualNet 3.6 Developer’s Guide


5. MAC Layer
This section covers the following topics:
• MAC Layer Overview
• MAC Layer Protocols in QualNet
• MAC Layer Organization: Files and Folders
• Data Structures
• API Functions
• Writing and Adding MAC Layer Protocols

5.1 MAC Layer Overview


The MAC layer is the second layer in TCP/IP protocol stack. This is a part of Data
Link Layer whose other part is Logical Link Control. Logical Link Control is yet to
be implemented in QualNet. The MAC layer is between network layer and
physical layer. It interacts with network layer and physical layer. In QualNet some
of the MAC protocols do not use the physical layer. Instead they take the
responsibility to send and receive data to and from the network. That is the
physical layer is integrated with those MAC layer protocols.

The following section is covered:


• Functionality in the MAC Layer

5.1.1 Functionality in the MAC Layer


Queues are implemented in the Network layer in QualNet. When a packet goes to
queue i.e. there is a packet ready to be sent in the network, the Network Layer
triggers MAC. MAC layer then triggers the appropriate MAC protocol running in
the interface. The MAC protocol, depending on its logic, retrieves the packet from
Network Queue, buffers it, does the necessary processing like checking the
channel status, checking whether it can reach destination, etc. Then it sends out
the packet. Upon receiving a packet it checks whether it is its own packet or if it is
operating in promiscuous mode. In either case, it send the packet up in the stack.
MAC layer protocols also takes the responsibility to let upper protocols know
about any packet drop or malfunctioning interface.

To summarize, the functionality of MAC layer takes place as follows:

QualNet 3.6 Developer’s Guide 173


Networking Using QualNet

1. Transfers data between Network Layer and Physical Layer


2. Error free transfer of data through physical layer
3. Defines methods to transfer and receive data to and from the network
4. Error detection in transferring data

FIGURE 23. MAC Layer Position in the Protocol Stack

5.2 MAC Layer Protocols in QualNet


QualNet provides an implementation of a large number of MAC layer protocols
both wired and wireless. If a node has multiple interfaces then, it may run different
MAC protocols at different interfaces. Even the MAC protocol at different
interfaces can be a mix of wired and wireless protocols. As described previously,
some of the MAC protocols interact with physical to transmit or receive data to
and from network, while other MAC Beside different MAC protocol

174 QualNet 3.6 Developer’s Guide


implementation, QualNet also implements, fault simulation and Switch at MAC
layer.
The following table lists existing MAC protocols in QualNet protocol stack.

FIGURE 24. MAC Protocols in QualNet

5.3 MAC Layer Organization: Files and Folders


This section briefly covers the information stored in the directories and files. The
MAC layer API is composed of several macros, functions, and structures.

They are defined in the following header files:


• QUALNET_HOME/include/api.h
This file defines the events and data structures needed to communicate
between different layers of the protocol stack.
• QUALNET_HOME/include/mac.h
This file contains API functions to communicate with other layers and some
API function to communicate between general MAC layer information needed
for a specific protocol.
• QUALNET_HOME/network/ip.h
This file contains general some general API function for interface address
information.
• QUALNET_HOME/phy/phy.h
This file contains the API functions needed to communicate with the Physical
layer.

QualNet 3.6 Developer’s Guide 175


Networking Using QualNet

Additionally, the following header files are also relevant to the MAC layer which
contains general API functions relevant to all layers:
• QUALNET_HOME/include/fileio.h
• QUALNET_HOME/include/mapping.h

These files are described in greater detail in “Application Layer” on page 62.
Alternatively the source code also contains detailed comments on functions and
other code components.

The following are the source files and folders (*.c) associated with the MAC layer:
• QUALNET_HOME/mac/
This folder contains the source and header files for the various QualNet MAC
protocols. The file names are indicative of the MAC protocol for which they
provide an implementation e.g. to see the implementation for IEEE 802.3, look
at mac_802_3.c and mac_802_3.h files. There is one exception. IEEE 802.11
(mac_802_11.c and mac_802_11.h) has been placed in QUALNET_HOME/
addons/seq.
• QUALNET_HOME/mac/mac.h and QUALNET_HOME/mac/mac.c
These files contain initialization function, message-processing function, and
finalize function used by MAC layer which in tern calls protocol specific
initialization, message processing, event handling, and finalize functions. It
also contains some function to trigger upper layer on event of errors in
physical.

5.4 Data Structures


The main data structure for the MAC layer is described in this section.
Additionally, the following topic is covered:
• Element Descriptions
• Enumerations

Each of the MAC interfaces has this structure.

176 QualNet 3.6 Developer’s Guide


struct struct_mac_str
{
MAC_PROTOCOL macProtocol;
int interfaceIndex;
BOOL macStats;
BOOL promiscuousMode;
int bandwidth; // In bytes.
clocktype propDelay;
BOOL interfaceIsEnabled;
int phyNumber;
void *macVar;
void *mplsVar;

MacHasFrameToSendFn sendFrameFn;
MacReceiveFrameFn receiveFrameFn;

List *interfaceStatusHandlerList;
NodeAddress virtualMacAddress;
MacVlan *vlan;
};

FIGURE 25. MAC Interface Structure

5.4.1 Element Descriptions


• macProtocol: This is the MAC protocol running in the particular interface
• interfaceIndex: This is an unique integer for a node for each interface to
distinguish between interfaces
• macStats: This Boolean variable used to identify whether MAC statistics
should be printed at end of simulation
• promiscuousMode: This Boolean variable is used to identify whether this
interface will operate in promiscuous mode.
• bandwidth: This variable collects the bandwidth of the attached network.
• propDelay: This variable collects the propagation delay suffered by a frame.
• interfaceIsEnabled: This Boolean variable is used to identify whether this
interface is working correctly or not.
• phyNumber: This variable gives the number of physicals associated with the
interface.
• macVar: This variable points to a specific MAC protocol data running at this
interface.

QualNet 3.6 Developer’s Guide 177


Networking Using QualNet

• mplsVar: This variable points to MPLS data if MPLS is selected to run at this
interface.
• sendFrameFn: Used to send frames to the network.
• receiveFrameFn: Used to receive frames from the network
• interfaceStatusHandlerList: List of functions to let the upper layer protocols
know about packet drop.
• virtualMacAddress: Virtual MAC address needed for HSRP
• vlan: This variable points to the interface VLAN data when it is an interface of a
switch node and VLAN information is provided for this interface.

5.4.2 Enumerations
The main ENUMERATION for the MAC layer is provided in this section. All
protocols must be enlisted in the enumeration. Depending on this enumeration
value MAC kernel determines which protocol functions to call.

typedef enum
{
MAC_PROTOCOL_MPLS = 1,
MAC_PROTOCOL_CSMA,
MAC_PROTOCOL_FCSC_CSMA,
MAC_PROTOCOL_MACA,
MAC_PROTOCOL_FAMA,
MAC_PROTOCOL_802_11,
MAC_PROTOCOL_802_3,
MAC_PROTOCOL_DAWN,
MAC_PROTOCOL_LINK,
MAC_PROTOCOL_ALOHA,
MAC_PROTOCOL_SWITCHED_ETHERNET,
MAC_PROTOCOL_TDMA,
MAC_PROTOCOL_GSM,
MAC_PROTOCOL_LINK16,
MAC_PROTOCOL_SATTSM,
MAC_PROTOCOL_SATCOM,
MAC_SWITCH
} MAC_PROTOCOL;

One more enumeration will be needed for writing a MAC protocol. This
enumeration is in QUALNET_HOME/include/trace.h

178 QualNet 3.6 Developer’s Guide


The new protocol must have an entry in the enumeration TraceProtocolType. This
entry is necessary for packet tracing.

5.5 API Functions


The following are the API functions related with Queue operation:
• NetworkIpCreateQueues
Creates a network queue for a newly created interface. This API is not
necessary to develop a new MAC protocol. MAC kernel uses this API.
• MAC_OutputQueueIsEmpty
This is used to check if a queue is empty or not. After sending a frame
successfully, MAC protocols use this function to check for additional packets to
send.
• MAC_OutputQueueDequeuePacket
If channel is idle MAC protocols use this API to dequeue a packet from network
queue. Before sending a frame MAC uses this function to dequeue the frame
to transmit.
• MAC_OutputQueueTopPacket
This API is used to view the top packet of a queue without dequeuing it from
the queue.
• MAC_OutputQueueDequeuePacketForAPriority
This API is used to dequeue a specific priority packet from network queue
• MAC_OutputQueueTopPacketForAPriority
This API is used to view to top packet of a specific priority queue.

The following are API functions related to Routing Table manipulation:


• NetworkUpdateForwardingTable
This API is used to add or update an entry to network forwarding table. Every
MAC protocol calls this to automatically add a routing entry for directly
connected network. It is generally used to add default routes for attached
network.

QualNet 3.6 Developer’s Guide 179


Networking Using QualNet

The following are API functions necessary to interface with the network layer:
• MAC_NetworkLayerHasPacketToSend
The network layer to trigger MAC when a packet arrives at empty queue uses
this API function. Receiving this trigger a MAC protocol runs protocol specific
access technique to retrieve the packet from the queue.
• MAC_HandOffSuccessfullyReceivedPacket
After receiving a frame from channel, MAC uses this API to pass the received
frame to upper layer. In addition to data, this API also provides incoming
interface of the node and previous hop address of the frame.
• MAC_SneakPeekAtMacPacket
To allow a peek on a packet by network layer when it is not the intended
receiver of that packet. This is needed if a node is operating in promiscuous
mode.
• MAC_MacLayerAcknowledgement
This API function allows the network layer to know that a packet has been
successfully delivered.
• MAC_NotificationOfPacketDrop
This API function is used to let upper layer protocols to know about a unicast
packet drop in MAC or Physical layer.

The following are API functions to interact with the physical:


• MAC_ReceivePacketFromPhy
The physical layer, to deliver a frame to MAC uses this API function.
• MAC_ReceivePhyStatusChangeNotification
The physical layer uses this API function to let MAC know about status
changes of the Physical.
• PHY_GetStatus
MAC layer uses this API function to know the current status of the physical
• PHY_StartTransmittingSignal
MAC layer protocols uses this API function transmit a frame to the network.

Additional API functions include the following:

180 QualNet 3.6 Developer’s Guide


• MAC_IsMyMacAddress
This API function is used to check whether a particular address belongs to this
node. The function will return TRUE if the address is a broadcast address, or if
this is a multicast address for which the node is a member or if the address is
unicast address of this interface.
• MAC_IsMyUnicastFrame
This API function is used to identify whether a particular address is this
interface unicast address.
• MAC_IsWiredNetwork
API function to check if the attached network is wired or wireless network
• MAC_IsPointToPointNetwork
API function used to check if the attached network is point-to-point network
• MAC_IsWiredBroadcastNetwork
API function used to check if the attached network is a wired broadcast
network
• MAC_IsWirelessNetwork
API function to check if the attached network is a wireless network
• MAC_IsOneHopBroadcastNetwork
API function to check if the attached network is one hop broadcast network

5.6 Writing and Adding MAC Layer Protocols


This section covers the following topics:
• Adding a Wired Protocol

5.6.1 Adding a Wired Protocol


This section covers how to add a new wired protocol in QualNet. New Wired Mac
Protocol (NWMP) is the protocol used.

This section covers the following topics:


• Configuration
• Integrating with QualNet
• Protocol Initialization
• Event Dispatcher

QualNet 3.6 Developer’s Guide 181


Networking Using QualNet

• Sending/ Receiving Packet


• Finalize Function

Before adding, write this new protocol in two files, nwmp.c and nwmp.h. Like other
protocols, provide data structure definitions and interface functions in the header
file. Place these two files in the 'mac' folder, i.e., QUALNET_HOME/mac. To
compile these files along with other QualNet files, add them to the
QUALNET_HOME/main/Makefile-common file. Add the header file (*.h) to the
simulator header files section and the source file (*.c) to the simulator source file
section of Makefile-common. This addition ensures that the files are compiled.

5.6.1.1 Configuration
QualNet supports the following two types of networks:
• point-to-point network
• broadcast type network

Specify the new protocol to support broadcast network. To create a broadcast


network, choose SUBNET in the configuration file. To run the protocol to that
subnet, specify the following configuration in the configuration file.

SUBNET N16-0 { Station list }

[N16-0] MAC-PROTOCOL NWMP

This will specify to run NWMP in the [N16-0] network. In addition, each protocol
requires some configuration parameters for its own operations. Generally existing
wired MAC protocols require data rate and propagation delay to specify.

5.6.1.2 Integrating with QualNet


As specified above, QualNet has a list of MAC protocols. These existing protocols
are defined at QUALNET_HOME/include/mac.h. The new protocol should be
included to that list.

182 QualNet 3.6 Developer’s Guide


// /**
// ENUM :: MAC_PROTOCOL
// DESCRIPTION :: Specifies different MAC_PROTOCOLs used
// **/
typedef enum
{
MAC_PROTOCOL_MPLS = 1,
MAC_PROTOCOL_CSMA,
.
.
MAC_PROTOCOL_NWMP,
.
.
}
MAC_PROTOCOL;

Now QualNet knows the new protocol type. It is time to add this new protocol's
data to a node. The MAC protocol is interface-specific and the node structure has
the provision to add different MAC protocols at each interface. This is elaborated
in the following figure.

FIGURE 26. MAC Protocol Node Structure

As the previous figure shows, a generic MAC data is created for each interface.
This MAC data provides a pointer to hold protocol data for particular protocol that

QualNet 3.6 Developer’s Guide 183


Networking Using QualNet

is configured for that interface. The tie up between MAC data and protocol data is
done during initialization.

5.6.1.3 Protocol Initialization


According to convention, each protocol is initialized during the respective layer
initialization. To initialize this new protocol, an initialization API should be provided
and MAC layer will use that function to initialize it. The function AddNodeToSubnet
in QUALNET_HOME/mac/mac.c invokes each protocol initialization routines for
broadcast networks. So, for the new protocol, this function should be updated to
provide the required initialization call. The code provided lists the necessary
changes to the function.

184 QualNet 3.6 Developer’s Guide


static void //inline//
AddNodeToSubnet(
Node *node,
const NodeInput *nodeInput,
NodeAddress subnetAddress, //base address
NodeAddress interfaceAddress, //my IP# on this interface
int numHostBits,
char *macProtocolName,
MacSubnetMemberData* subnetList,
int nodesInSubnet,
int subnetListIndex)
{
...
...

/* Select the MAC protocol and initialize. */

if (strcmp(macProtocolName, "SWITCHED-ETHERNET") == 0) {
...
...
return;
}
else if (strcmp(macProtocolName, "MAC802.3") == 0) {
...
...
return;
}
else if (strcmp(macProtocolName, "NWMP") == 0) {

NwmpGetSubnetParameters(interfaceAddress, nodeInput,
&subnetBandwidth, &subnetPropDelay);

NetworkIpCreateQueues(node, nodeInput, interfaceIndex);

node->macData[interfaceIndex]->macProtocol = MAC_PROTOCOL_NWMP;

node->macData[interfaceIndex]->bandwidth = subnetBandwidth;
node->macData[interfaceIndex]->propDelay = subnetPropDelay;
node->macData[interfaceIndex]->mplsVar = NULL;

NwmpInit(node, nodeInput, interfaceIndex,


subnetAddress, interfaceAddress,
numHostBits, subnetList,
nodesInSubnet);
return;
}

//
// MAC protocol models below require a PHY model
//
...
...
...

QualNet 3.6 Developer’s Guide 185


Networking Using QualNet

As seen from the above code segment, NwmpInit is responsible to initialize this
new protocol. It assigns the initial values for NwmpData members. As said earlier,
wired MAC protocol takes the additional responsibility to provide physical layer
functionality. So it keeps a list of its members that are connected to same network,
to broadcast frames. In general, a wired initialization routine routing do the
following activity.
• Creates the protocol data and links it to macVar present in MacData for a
interface.
• Initialize the members belongs to protocol data.
• Reads additional user configurable parameters if required for the protocol.
• Adds an entry for the attached network to forwarding table for this newly
created interface.
• Schedules periodic times if require by the protocol.
• Collects neighbor information to create neighbor list necessary for physical
functionality.

Generally a MAC protocol waits for any packets to come from either upper layer or
below the mac layer. It then processes the packet and passes it to proper layer.
When it gets packets from upper layer in idle state, it broadcasts it and schedules
a self-timer to make it busy. Besides, some MAC protocols sends protocol specific
control packets that are received by this protocol at receiving nodes. This requires
an event dispatcher to handle all the timers and protocol events.

5.6.1.4 Event Dispatcher


MAC_ProcessEvent is the MAC layer event dispatcher that calls protocol event
dispatcher running at a particular interface. This is used for self-timers. Let our
event dispatcher is NwmpLayer. The layer dispatcher, MAC_ProcessEvent,
should be updated to hook up our event dispatcher. Code block given below
provides the necessary changes.

186 QualNet 3.6 Developer’s Guide


void
MAC_ProcessEvent(Node *node, Message *msg)
{
int interfaceIndex = MESSAGE_GetInstanceId(msg);
int protocol = MESSAGE_GetProtocol(msg);

...
...
/* Select the MAC protocol model, and direct it to handle the
message. */

switch (node->macData[interfaceIndex]->macProtocol)
{
case MAC_PROTOCOL_802_11:
{
Mac802_11Layer(node, interfaceIndex, msg);
break;
}
...
...
case MAC_PROTOCOL_NWMP:
{
NwmpLayer(node, interfaceIndex, msg);
break;
}
}
}

This update provides all the new protocol related self-timers and protocol events
to reach up to the protocol. But proper flow requires correct scheduling of these
timers and events. According to convention, message can handle all the self-
timers and protocol events. The following steps should be executed during a
scheduling message.
1. Set the layer as MAC_LAYER.
2. Set the protocol as MAC_PROTOCOL_NWMP.
3. Set the event to proper event for which the message is going to schedule.
4. Set the instance ID with interfaceIndex where the message is going to fire.

At the protocol level all timers and events are separated using event field of
message. So each protocol should provide well-defined events to execute its
protocol activity. Unknown events should handled properly to eliminate any
malfunctioning. A generic construction of NwmpLayer is provided with an example
of message scheduling.

QualNet 3.6 Developer’s Guide 187


Networking Using QualNet

void NwmpLayer(Node *node, int interfaceIndex, Message *msg)


{
int eventType = msg->event;

switch (eventType)
{
case MSG_MAC_Event_A:

NwmpEventARelatedProcessing(node, interfaceIndex, msg);


MESSAGE_Free(node, msg);
break;

case MSG_MAC_Event_B:

NwmpEventBRelatedProcessing(node, interfaceIndex, msg);


MESSAGE_Free(node, msg);
break;

case MSG_MAC_Event_C:

NwmpEventCRelatedProcessing(node, interfaceIndex, msg);


MESSAGE_Free(node, msg);
break;

default:
ERROR_Assert(FALSE,
"Received a message of unknown event");
MESSAGE_Free(node, msg);
break;
}
}

The scheduling of a message for NWMP is as follows.

Message *newMsg = MESSAGE_Alloc(node,


MAC_LAYER,
MAC_PROTOCOL_NWMP,
MSG_MAC_Event_A);
MESSAGE_SetInstanceId(newMsg, interfaceIndex);

MESSAGE_Send(node, newMsg, delay);

5.6.1.5 Sending / Receiving Packet


In QualNet every wired MAC protocol receives datagram from network layer and
sends them to proper destination. So in absence of physical layer, it interacts with
network layer only. When network has a datagram to send using MAC it uses an
API to trigger its service provider. MAC_NetworkLayerHasPacketToSend is the

188 QualNet 3.6 Developer’s Guide


API that calls proper protocol running at that interface. So every new protocol
modifies this function to get its upper layer packets. Actually this is a trigger to
MAC to inform some packet is waiting in a queue for transmission. MAC is
responsible to dequeue them one by one and transmit to other end. Each protocol
uses a well-defined API, MAC_OutputQueueDequeuePacket, to dequeue a
packet from network queue. When to dequeue a packet, is totally a protocol
specific decision. The code provided gives an idea of this activity.

void
MAC_NetworkLayerHasPacketToSend(Node *node, int interfaceIndex)
{
...
...
...
switch (node->macData[interfaceIndex]->macProtocol)
{
case MAC_PROTOCOL_802_11:
{
Mac802_11NetworkLayerHasPacketToSend(
node,
(MacData802_11 *) node->macData[interfaceIndex]->macVar);
break;
}
...
...
case MAC_PROTOCOL_NWMP:
{
NwmpNetworkLayerHasPacketToSend(
node,
(MacData802_11 *) node->macData[interfaceIndex]->macVar);
break;
}
}

This modification in existing API provides the necessary changes to get proper
trigger. Now the protocol specific function NwmpNetworkLayerHasPacketToSend
is responsible for retrieving datagram. A generic example is provided.

QualNet 3.6 Developer’s Guide 189


Networking Using QualNet

static
void NwmpNetworkLayerHasPacketToSend(
Node *node, int interfaceIndex)
{
if (channel is busy)
{
return;
}

MAC_OutputQueueDequeuePacket(node,
interfaceIndex,
&newMsg,
&nextHopAddress,
&networkType,
&priority);

// Add protocol specific header.

// Send the packet to its neighbor.


}

All neighbors will get this frame and decides if the frame is sent for this station. If
frame is intended for this station, it will retrieve the datagram from the received
frame and send it to upper layer. MAC_HandOffSuccessfullyReceivedPacket is
the API that is used by a MAC protocol to send datagram to upper layer.

5.6.1.6 Finalize Function


At the end of simulation every protocol finalize routine is called. It is responsible
for providing the statistics it collected during the simulation. Like other protocol,
the new protocol should also provide a finalize function. This function should be
inserted to MAC layer finalize function.

190 QualNet 3.6 Developer’s Guide


void
MAC_Finalize(Node *node)
{
int interfaceIndex;

for (interfaceIndex = 0;
interfaceIndex < node->numberInterfaces;
interfaceIndex++)
{
/* Select the MAC protocol model and finalize it. */

if (node->macData[interfaceIndex])
{
switch (node->macData[interfaceIndex]->macProtocol)
{
case MAC_PROTOCOL_802_11:
{
Mac802_11Finalize(node, interfaceIndex);
break;
}
...
...
case MAC_PROTOCOL_NWMP:
{
NwmpFinalize(node, interfaceIndex);
break;
}
}
}
}
...
...

The previously displayed code provides the necessary changes to layer finalize
API. NwmpFinalize is responsible for printing statistics.

QualNet 3.6 Developer’s Guide 191


Networking Using QualNet

6. Physical Layer
This section covers the following topics
• Physical Layer Overview
• Physical Layer Organization: Files and Folders
• Writing and Adding an Antenna Model
• Writing and Adding a Radio Model
• Writing and Adding a Channel Model
• Adding a Mobility Model

6.1 Physical Layer Overview


The physical layer is layer 1, the lowest one, in the OSI Reference Model. It
transmits and receives data over physical media. The physical layer interfaces
with peer physical layer entities in other communicating nodes to provide services
to the data link / MAC layer.

To model the physical layer in a simulation we need to incorporate characteristics


of the transmitter, the receiver and the physical medium through which
communication occurs. Modeling the physical layer requires modeling all aspects
of a wireless system: propagation effects, modulation, coding, noise, interference
and antennas. The following sections provide guidance in building antenna
models, radio models, channel models and mobility models in QualNet. An
extensive set of physical layer features and models is available in QualNet; these
can be used to model a variety of wireless scenarios. While developing the
physical layer models, look at the existing physical layer models to understand
how they work within QualNet. As with other layers in QualNet, the Node structure
in addons/seq/node.h provides the starting point for the organization of physical
layer data.

6.2 Physical Layer Organization: Files and Folders


The following is a listing of source code files relevant to the physical layer. The
paths shown are relative to the environment variable QUALNET_HOME, which is
the path to the QualNet installation directory. Each of the files listed below include
relevant header files for their supporting data structures and externally declared
functions. The function names in these header files give a good idea of what
functionality is expected of each model. Any new source and header files added

192 QualNet 3.6 Developer’s Guide


to QualNet should be included in the correct Makefile's. Please refer to Chapter 2,
“QualNet Architecture” on page 3 for instructions.

The following are the relevant files:


• phy/phy.c
Contains the general physical layer initialization, event and message
processing functions and finalize functions. It serves as the interface point
between the Mac layer and specific physical layer models.
• phy/propagation.c
Contains code for calculating propagation characteristics: path loss,
shadowing and fading.
• phy/antenna.c
Contains code for creating and using specific antenna models.
• phy/prop_range.c
Creates the radio_range program, which calculates the propagation range of a
configuration file, under no interference conditions.

In addition, the physical layer models also utilize functions from the following:
• main/fileio.c—parsing input files for parameters
• main/gui.c—GUI animation of physical layer events
• main/random.c—random number generation

6.3 Writing and Adding an Antenna Model


This section includes the following topics:
• Adding An Antenna Model
• Initialization
• Antenna Model Functionality

6.3.1 Adding An Antenna Model


QualNet allows each physical device to have an antenna model, as seen in the
data structure PhyData shown in the following figure. This structure also holds
some more antenna specific properties. To integrate an antenna model into
QualNet add its name to the enumerated data type AntennaModel in phy/phy.h.

QualNet 3.6 Developer’s Guide 193


Networking Using QualNet

FIGURE 27. Antenna Related Data Structures In phy/phy.h

6.3.2 Initialization
Initialization of an antenna model starts with reading the antenna properties such
as ANTENNA-GAIN, ANTENNA-HEIGHT, and ANTENNA-MODEL. Add the
initialization code or function call of the antenna model to the AntennaInit function
in phy/antenna.c. The AntennaInit function is called during the physical layer
model initialization of each node. If needed, the model may use the antennaVar
pointer in PhyData to store model specific data in addition to the antenna
properties stored in PhyData. This model-specific data structure may be created
in a separate header file supporting the antenna's main source file. The header
file should be included in the necessary places, such as any source files of
physical layer models that intend to use the antenna model. Figure 28, “Antenna
Model Initialization” presents some sample code displaying the initialization of
antenna models.

194 QualNet 3.6 Developer’s Guide


FIGURE 28. Antenna Model Initialization
void AntennaInit(Node *node, int phyIndex, const NodeInput *nodeInput)
{
PhyData *phyData = node->phyData[phyIndex];

// Read-in and set ANTENNA-GAIN
IO_ReadString(
node->nodeId,
phyData->macInterfaceAddress,
nodeInput,
"ANTENNA-GAIN",
&wasFound,
buf);

if (wasFound) {
phyData->antennaGain_dBi = (float)antennaGain_dBi;
}
else {
phyData->antennaGain_dBi = ANTENNA_DEFAULT_GAIN_dBi;
}

// Read-in and set ANTENNA-HEIGHT

// Read-in and set ANTENNA-MODEL


IO_ReadString(
node->nodeId,
phyData->macInterfaceAddress,
nodeInput,
"ANTENNA-MODEL",
&wasFound,
buf);

if (!wasFound || strcmp(buf, "OMNIDIRECTIONAL") == 0) {


phyData->antennaModel = ANTENNA_OMNIDIRECTIONAL;
AntennaOmniDirectionalInit(node, phyIndex, nodeInput);
}
else if (strcmp(buf, "SWITCHED-BEAM") == 0) {
phyData->antennaModel = ANTENNA_SWITCHED_BEAM;
AntennaSwitchedBeamInit(node, phyIndex, nodeInput);
}

else if (strcmp(buf, “YOUR-ANTENNA-MODEL”) == 0) {
phyData->antennaModel = ANTENNA_YOUR_MODEL;
AntennaYourModelNameInit(node, phyIndex, nodeInput);
}
else {
fprintf(stderr, "Error: unknown ANTENNA-MODEL %s for phy %d.\n",
buf, phyIndex);
abort( );
}
return;
}

QualNet 3.6 Developer’s Guide 195


Networking Using QualNet

During the antenna model's initialization, it may need to read in an antenna


pattern file which is specified in the main configuration file of the simulations. For
example the switched beam antenna model (phy/antenna_switched.c) in
QualNet requires an azimuth pattern file, while the elevation pattern file is
optional. The antenna pattern file allows developers to specify a gain value for an
angle of arrival for each antenna radiation pattern.

#ifndef ANTENNA_YOUR_MODEL_H
#define ANTENNA_YOUR_MODEL_H

typedef struct {
int numPatterns;
int patternSetRepeatAngle;
int patternIndex;

float **patternAzimuth_dBi;
float **patternElevation_dB;
BOOL antennaIsLocked;
} YourAntennaModelData;

// Function declarations
void AntennaYourModelNameInit (
Node *node,
int phyIndex,
const NodeInput *nodeInput);

#endif

FIGURE 29. Antenna Model Files: antenna_yourmodel.h

6.3.3 Antenna Model Functionality


After initialization the antenna model is ready to be used for processing signal
transmissions and receptions by the various radio models. The radio models call
generic antenna functions to execute the necessary functionality. The generic
antenna functions in turn call the node's specific antenna model functions.
Depending on the antenna's characteristics not all of the functionality may be
required.

196 QualNet 3.6 Developer’s Guide


Following is a listing of the generic antenna functions in phy/antenna.c, into
which developers must insert code to call their antenna model's functions to
execute the desired functionality:

TABLE 1. Generic Antenna Functions

Function Explanation
float AntennaGainForThisDirection( Provide the antenna
gain value for the
Node *node, signal's given
int phyIndex, direction of arrival.
Orientation DOA);
void AntennaLockAntennaDirection(Node *node, For non-omni-
int phyIndex); directional antennas,
lock the direction from
which maximum gain
was observed until the
entire signal is
received.
void AntennaUnlockAntennaDirection(Node *node, Unlock the antenna's
int phyIndex); reception direction.
BOOL AntennaIsLocked(Node *node, int Checks to see whether
phyIndex); the antenna's reception
direction is locked.
void AntennaSetToOmnidirectionalMode(Node Set the antenna to use
*node, int phyIndex); an omnidirectional
pattern
void AntennaSetToBestGainConfiguration If the antenna's
ForThisSignal( direction is not locked,
then identify the
Node *node, radiation pattern which
int phyIndex, provides the best gain
PropRxInfo *propRxInfo); for a given signal and
use it for further
reception.
void AntennaSetBestConfigurationForAzimuth(

Node *node,
int phyIndex,
double azimuth);

QualNet 3.6 Developer’s Guide 197


Networking Using QualNet

// Include standard libraries


#include "api.h"
#include "antenna.h"
#include “antenna_yourmodel.h”

void AntennaYourModelNameInit (
Node *node,
int phyIndex,
const NodeInput *nodeInput)
{
PhyData *phyData = node->phyData[phyIndex];

Struct YourAntennaModelData *yourAntennaData;

// Allocate memory for yourAntennaData



phyData->antennaVar = yourAntennaData;

IO_ReadCachedFile(
node->nodeId,
phyData->macInterfaceAddress,
nodeInput,
"ANTENNA-AZIMUTH-PATTERN-FILE",
&wasFound,
&antennaInput);

AntennaReadPatterns( node,
phyIndex,
&antennaInput,
&numPatterns,
&(steerable->patternSetRepeatAngle),
&(steerable->patternAzimuth_dBi),
TRUE);

yourAntennaData->numPatterns = numPatterns;

// Read in elevation data if specified in simulation configuration file
}

FIGURE 30. Antenna Model Files: antenna_yourmodel.c

6.4 Writing and Adding a Radio Model


In QualNet, a radio model combines channel and antenna models together to
simulate the physical behavior of a wireless network. The basic function of radio
model in QualNet includes the following:

198 QualNet 3.6 Developer’s Guide


• To get data or control packets from MAC layer under the control of MAC
protocol.
• To deliver the packets at transmitter at given radio device parameters.
• To simulate the distortion from channel and the interference effects from
surrounding neighbor nodes.
• To detect the received data and control packets for desired node.
• To inform the current status and notice the packets reception quality to MAC
layer.
• To send the data packets back to MAC layer.

Although each radio model works differently, there are certain functions that are
performed by most radio models. To write a new radio model, it is recommended
that the user copy most of the functions from a radio model already existing in
QualNet and create or modify only the parts that do not meet the requirements.

This section includes the following topics:


• Creating Files
• Integrating with QualNet

6.4.1 Creating Files


Before starting, the user should read and understand the existing code. In general
the header file for new radio model should contain the following:
• Prototypes for functions in source file
• Constant definitions: All # defines
• Data structure definitions and data types: struct, enums

The new radio model source file should contain the following:
• Include directives for appropriate header files, a typical radio model file
includes these files:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

QualNet 3.6 Developer’s Guide 199


Networking Using QualNet

#include <math.h>

#include "api.h"

#include "antenna.h"

#include "antenna_switched.h"

#include "antenna_steerable.h"

#include "newradiomodel.h" // the new radio model


header file

• Dispatcher code
• Radio model implementation functions

The following functions are generally required in the new radio model (assuming
NewRadioModel is the name of the newly created protocol):
• PhyNewRadioModelInit
• PhyNewRadioModelTransmissionEnd
• PhyNewRadioModelGetStatus
• PhyNewRadioModelStartTransmittingSignal
• PhyNewRadioModelSignalArrivalFromChannel
• PhyNewRadioModelSignalEndFromChannel
• PhyNewRadioModelGetDataRate
• PhyNewRadioModelGetDataRate
• PhyNewRadioModelGetFrameDuration
• PhyNewRadioModelSetTransmitPower
• PhyNewRadioModelGetTransmitPower
• PhyNewRadioModelFinalize

Additional functions may be required depending on the new radio model


algorithm.

200 QualNet 3.6 Developer’s Guide


6.4.2 Integrating with QualNet
To integrate a new radio model into QualNet, the new radio model needs to be
added to the list of physical models. To do this, add the new radio model to the
enumeration PhyModel defined in QUALNET_HOME/include/phy.h. The
following figure shows the data structures related to physical radio models.

FIGURE 31. Data structure of physical model

In addition the new radio model needs to be called in the basic physical functions
such as the following:
• PHY_CreateAPhyForMac
• PHY_ProcessEvent
• PHY_GetStatus
• PHY_StartTransmittingSignal
• PHY_SignalArrivalFromChannel
• PHY_SignalEndFromChannel
• PHY_GetTxDataRate
• PHY_GetRxDataRate
• PHY_GetFrameDuration

QualNet 3.6 Developer’s Guide 201


Networking Using QualNet

• PHY_SetTransmitPower
• PHY_GetTransmitPower
• PHY_Finalize

The next twelve figures provide the practical function calls that need to be
implemented in the QualNet physical layer.

PHY_CreateAPhyForMac is the node based initialization function for the physical


layer, which reads the user defined parameters from configuration file and
initializes the physical model using these globe parameters. To initialize the new
radio model function, create the initialization function necessary for the new radio
model and add initial function call as showing in the figure 2. In general the
initialization function needs to read and set the following parameters:
• phy_newradiomodel-DATA-RATE
• phy_newradiomodel-TX-POWER
• phy_newradiomodel-RX-SENSITIVITY
• phy_newradiomodel-RX-THRESHOLD

The following initializations must also be done:


• Antenna model initialization
• Physical statistics variables initialization
• Physical status initialization
• Tx, Rx Channel setting up

202 QualNet 3.6 Developer’s Guide


FIGURE 32. Initialization function of the physical layer; File: phy/phy.c
void PHY_CreateAPhyForMac (Node *node,
const NodeInput *nodeInput,
int interfaceIndex,
NodeAddress interfaceAddress,
PhyModel phyModel,
int* phyNumber)
{
….
assert(phyModel == PHY802_11a ||
phyModel == PHY802_11b ||
phyModel == PHY_GSM ||
phyModel == PHY_ABSTRACT ||
phyModel == PHY_FCSC_PROTOTYPE ||
phyModel == PHY_LINK16||
phyModel == PHY_NEW_RADIO_MODEL);
….
IO_ReadString(node->nodeId,
interfaceAddress,
nodeInput,
" PHY-TEMPERATURE",
&wasFound,
buf);
….
IO_ReadString(
node->nodeId,
interfaceAddress,
nodeInput,
"PHY-RX-MODEL",
&wasFound,
buf);
….
switch(thisPhy->phyModel) {
case PHY802_11b:
case PHY802_11a: {
Phy802_11Init(node, phyIndex, nodeInput);
break;
}
….
case PHY_GSM: {
PhyGsmInit(node, phyIndex, nodeInput);
break;
}
….
case PHY_NEW_RADIO_MODEL{
Phy_New_RadioModelInit( node, phyIndex,nodeInput);
break;
}
….
}
….
}

QualNet 3.6 Developer’s Guide 203


Networking Using QualNet

FIGURE 33. Finalization function of the physical layer; file phy/phy.c

void PHY_Finalize(Node *node)


{

….
switch(node->phyData[phyNum]->phyModel) {
case PHY802_11b:
case PHY802_11a: {
Phy802_11Finalize(node, phyNum);

break;
}

….

case PHY_ABSTRACT: {
PhyAbstractFinalize(node, phyNum);

break;
}

….

case PHY_NEW_RADIO_MODEL: {
PhyNewRadioModelFinalize(node, phyNum);

break;
}
….
}
}
}
} ….

Function PHY_Finalize is called at the end of simulation to collect the results of


the simulation of the physical layer, create the finalization function for the new
radio model and call it in function PHY_Finalize.

In general following results are collected in physical finalization:


• Signals transmitted.
• Signals received and forwarded to MAC.
• Signals locked on by PHY.
• Signals received but with errors.

204 QualNet 3.6 Developer’s Guide


• Energy consumption (in mWhr).

void PHY_ProcessEvent(Node *node, Message *msg) {


….
switch(node->phyData[phyIndex]->phyModel) {
case PHY802_11b:
case PHY802_11a: {
switch (msg->eventType) {
case MSG_PHY_TransmissionEnd: {
Phy802_11TransmissionEnd(node, phyIndex);
MESSAGE_Free(node, msg);

break;
}
….
case PHY_ABSTRACT: {
switch (msg->eventType) {
case MSG_PHY_TransmissionEnd: {
PhyAbstractTransmissionEnd(node, phyIndex);
MESSAGE_Free(node, msg);

break;
}
….

case PHY_New_Radio_model: {
switch (msg->eventType) {
case MSG_PHY_TransmissionEnd: {
PhyNewRadioModelTransmissionEnd(node, phyIndex);
MESSAGE_Free(node, msg);

break;
}
….
}
….
}
}

FIGURE 34. Physical processing events; file phy/phy.c

PHY_ProcessEvent models the behaviors of the physical layer on receiving the


data or control packets. Make the new radio model call as showed in figure 4 to
implement the new radio structure or model. In general, the function
PhyNewRadioModelTransmissionEnd should implement the following functions.

QualNet 3.6 Developer’s Guide 205


Networking Using QualNet

• PHY_GetTransmissionChannel
• PHY_StartListeningToChannel
• PHY_SignalInterference
• Physical model check and setting
• PhyNewRadioModelReportStatusToMac

void PHY_StartTransmittingSignal( )
{
….
switch(node->phyData[phyNum]->phyModel) {
case PHY802_11b:
case PHY802_11a: {
Phy802_11StartTransmittingSignal(
node, phyNum, msg,
useMacLayerSpecifiedDelay, delayUntilAirborne);

break;
}
….

case PHY_ABSTRACT: {
PhyAbstractStartTransmittingSignal(
node, phyNum, msg,
useMacLayerSpecifiedDelay, delayUntilAirborne);

break;
}

….
case PHY_NEW_RADIO_MODEL: {
PhyNewRadioModelStartTransmittingSignal(
node, phyNum, msg,
useMacLayerSpecifiedDelay, delayUntilAirborne);

break;
}
….

FIGURE 35. Physical start transmitting signal; file phy/phy.c

206 QualNet 3.6 Developer’s Guide


PHY_StartTransmittingSignal is used by the MAC layer to start transmitting a
packet, in general, the function PhyNewRadioModelStartTransmittingSignal
should include the following functions.
• PHY_GetTransmissionChannel
• Physical model check and set
• PHY_StopListeningToChannel
• PROP_ReleaseSignal
• MESSAGE_SetInstanceId
• MESSAGE_Send
• Keep track of physical statistics and battery computations

QualNet 3.6 Developer’s Guide 207


Networking Using QualNet

void PHY_SignalArrivalFromChannel( )
{

….
switch(node->phyData[phyIndex]->phyModel) {
case PHY802_11b:
case PHY802_11a: {
Phy802_11SignalArrivalFromChannel(
node, phyIndex, channelIndex, propRxInfo);

break;
}

case PHY_ABSTRACT: {
PhyAbstractSignalArrivalFromChannel(
node, phyIndex, channelIndex, propRxInfo);

break;
}

case PHY_NEW_RADIO_MODEL: {
PhyNewRadioModelSignalArrivalFromChannel(
node, phyIndex, channelIndex, propRxInfo);

break;
}

….

FIGURE 36. Physical signal arrival from channel; file phy/phy.c

PHY_SignalArrivalFromChannel models the behaviors of physical model when


signal arrival from channel, it is called when PROP schedules a signal arrival to
this node. The function PhyNewRadioModelSignalArrivalFromChannel should be
called as denoted in the previous figure, and the following functions should be
generally implemented in it:
• rxPower_mW calculation
• Physical model check and set
• PhyNewRadioModelReportStatusToMac

208 QualNet 3.6 Developer’s Guide


void PHY_SignalEndFromChannel(
Node* node,
int phyIndex,
int channelIndex,
PropRxInfo *propRxInfo)
{
….
switch(node->phyData[phyIndex]->phyModel) {
case PHY802_11b:
case PHY802_11a: {
Phy802_11SignalEndFromChannel(
node, phyIndex, channelIndex, propRxInfo);

break;
}

….

case PHY_ABSTRACT: {
PhyAbstractSignalEndFromChannel(
node, phyIndex, channelIndex, propRxInfo);

break;
}

case PHY_NEW_RADIO_MODEL: {
PhyNewRadioModelSignalEndFromChannel(
node, phyIndex, channelIndex, propRxInfo);

break;
}
….
}

FIGURE 37. Physical signal end from channel; file phy/phy.c

PHY_SignalEndFromChannel is called when PROP schedules an end of signal to


this node. The function PhyNewRadioModelSignalEndFromChannel should be
called in function PHY_SignalEndFromChannel as shown in Figure 37, “Physical
signal end from channel; file phy/phy.c” , it should include but not limited to the
following functions in general:
• Check received data frame quality.
• Receive the signal and forward the frame to the MAC layer.

QualNet 3.6 Developer’s Guide 209


Networking Using QualNet

• Physical model check and set.


• Report current physical status to MAC.

int PHY_GetTxDataRate(Node *node,


int phyIndex)
{
….
switch(node->phyData[phyIndex]->phyModel) {
case PHY802_11b:
case PHY802_11a: {
return Phy802_11GetTxDataRate(node->phyData[phyIndex]);
}

….

case PHY_ABSTRACT: {
return PhyAbstractGetDataRate(node->phyData[phyIndex]);
}

….
case PHY_NEW_RADIO_MODEL: {

return PhyNewRadioModelGetDataRate(node->phyData[phyIndex]);

}
….

FIGURE 38. Physical gets data rate; file phy/phy.c

PHY_GetTxDataRate returns the current data rate in physical model, the function
PhyNewRadioModelGetDataRate should be called in this function as shown in the
previous figure.

210 QualNet 3.6 Developer’s Guide


int PHY_GetRxDataRate(Node *node,
int phyIndex)
{
….
switch(node->phyData[phyIndex]->phyModel) {
case PHY802_11b:
case PHY802_11a: {
return Phy802_11GetRxDataRate(node->phyData[phyIndex]);
}

….

case PHY_ABSTRACT: {
return PhyAbstractGetDataRate(node->phyData[phyIndex]);
}
….
case PHY_NEW_RADIO_MODEL: {
return PhyNewRadioModelGetDataRate(node->phyData[phyIndex]);
}
….
}
….
}

FIGURE 39. Physical gets Rx data rate; file phy/phy.c

PHY_GetRxDataRate returns the current data rate in receiving. Data rate, in


general, depend on the radio model, and there is some general restriction to it.
PhyNewRadioModelGetDataRate should be called in function
PHY_GetRxDataRate as in the previous figure.

QualNet 3.6 Developer’s Guide 211


Networking Using QualNet

clocktype PHY_GetFrameDuration(
Node *node,
int phyIndex,
int dataRateIndex,
int size)
{
….

switch(thisPhy->phyModel) {
case PHY802_11b:
case PHY802_11a: {
return Phy802_11GetFrameDuration(thisPhy, dataRateIndex, size);
}
….

case PHY_ABSTRACT: {
int dataRate = PHY_GetTxDataRate(node, phyIndex);
return PhyAbstractGetFrameDuration(thisPhy, size, dataRate);
}
….

case PHY_NEW_RADIO_MODEL: {
int dataRate = PHY_GetTxDataRate(node, phyIndex);
return PhyNewRadioModelGetFrameDuration
(thisPhy, size, dataRate);
}

….
}
….

FIGURE 40. Physical gets frame duration; file phy/phy.c

PHY_GetFrameDuration returns the frame duration, and is used by MAC to


implement MAC control functions. The function
PhyNewRadioModelGetFrameDuration could be called as in the previous
example, but it is not the only limited one.

212 QualNet 3.6 Developer’s Guide


void PHY_SetTransmitPower(
Node *node,
int phyIndex,
double newTxPower_mW)
{
….
switch(node->phyData[phyIndex]->phyModel) {
case PHY802_11b:
case PHY802_11a: {
Phy802_11SetTransmitPower(node->phyData[phyIndex],
newTxPower_mW);

return;
}
….
case PHY_ABSTRACT: {
PhyAbstractSetTransmitPower(node->phyData[phyIndex],
newTxPower_mW);

return;
}
….
case PHY_NEW_RADIO_MODEL: {
PhyNewRadioModelSetTransmitPower
(node->phyData[phyIndex], newTxPower_mW);

return;
}
….
}

….

FIGURE 41. Physical sets transmit power; file phy/phy.c

Function PHY_SetTransmitPower sets the radio's transmit power in mW. It is


important to note that it is in mW instead of in dBm. In general, for same radio
model with same parameters, under same propagation condition, high transmit
power will give high radio range. But there is some limitation for transmit power
setting in practical. It should be in the reasonable value. As the previous example
PhyNewRadioModelSetTransmitPower was called and return the transmit power
setting.

QualNet 3.6 Developer’s Guide 213


Networking Using QualNet

void PHY_GetTransmitPower(
Node *node,
int phyIndex,
double *txPower_mW)
{
….
switch(node->phyData[phyIndex]->phyModel) {
case PHY802_11b:
case PHY802_11a: {
Phy802_11GetTransmitPower(node->phyData[phyIndex],
txPower_mW);

return;
}
….
case PHY_ABSTRACT: {
PhyAbstractGetTransmitPower(node->phyData[phyIndex],
txPower_mW);

return;
}
….
case PHY_NEW_RADIO_MODEL: {
PhyNewRadioGetTransmitPower(node->phyData[phyIndex],
txPower_mW);

return;
}
….
}
….
}

FIGURE 42. Physical gets transmit power; file phy/phy.c

PHY_GetTransmitPower returns the radio's transmit power in mW, it is a function


pair with PHY_SetTransmitPower.

214 QualNet 3.6 Developer’s Guide


PhyStatusType
PHY_GetStatus(Node *node, int phyNum) {
….
switch(node->phyData[phyNum]->phyModel) {
case PHY802_11b:
case PHY802_11a: {
return Phy802_11GetStatus(node, phyNum);

break;
}

….

case PHY_ABSTRACT: {
return PhyAbstractGetStatus(node, phyNum);

break;
}
….
case PHY_NEW_RADIO_MODEL: {
return PhyNewRadioModelGetStatus(node, phyNum);

break;
}
….
}

….
}

FIGURE 43. Physical gets status; file phy/phy.c

Function PHY_GetStatus Retrieves the Phy's current status, and report it to MAC
layer, the function PhyNewRadioModelGetStatus should be called as in the
previous figure.

After coding work, one should add the new radio models to QualNet. To do so,
add these files to the QualNet source tree by modifying the file Makefile-common
in QUALNET_HOME/main/ to include the created files. Add the header file (*.h)
to the simulator header files section and the source file (*.c) to the simulator
source file section of Makefile-common. This ensures the files will be compiled.

Test that the files are successfully added to the QualNet source tree by compiling
QualNet. Refer to the parts in this file to see how to compile QualNet.

QualNet 3.6 Developer’s Guide 215


Networking Using QualNet

6.5 Writing and Adding a Channel Model


Creating a channel model involves modeling the channel's propagation
properties. These properties are as follows:
• Pathloss models
• Fading
• Shadowing

This section includes the following topics:


• Adding a Propagation Model
• Initialization
• Calculating Propagation Model Values
• Finalization

6.5.1 Adding a Propagation Model


To add a pathloss, fading or shadowing model to QualNet start by adding the
model name to the relevant enumerated data type in phy/propagation.h and
create the data structures in phy/propagation.h or create the own header file. The
following figure shows the data structures related to physical layer models.

216 QualNet 3.6 Developer’s Guide


FIGURE 44. Physical Layer Data Structures

6.5.2 Initialization
During initialization, propagation model parameters for each channel defined in
the simulation's configuration file are read-in and set. These parameters include
PROPAGATION-PATHLOSS-MODEL, PROPAGATION-SHADOWING-SIGMA,
and PROPAGATION-FADING-MODEL. QualNet calls the global propagation
model initialization function PROP_GlobalInit in phy/propagation.c for this. Add
code necessary for the model's global initialization to this function. Node-based
initialization of channel model properties is performed by the PROP_Init function
in phy/propagation.h.

QualNet 3.6 Developer’s Guide 217


Networking Using QualNet

void PROP_GlobalInit (PartitionData *partitionData, NodeInput *nodeInput)


{ …
// Scan configuration file to see how many channels are defined
for (i = 0; i < numChannels; i++)
{ ....
IO_ReadStringInstance(
ANY_NODEID,
ANY_ADDRESS,
nodeInput,
"PROPAGATION-PATHLOSS-MODEL",
channelIndex,
TRUE,
&wasFound,
buf);

if (wasFound) {
if (strcmp(buf, "FREE-SPACE") == 0) {
propProfile->pathlossModel = FREE_SPACE;
}
else if (strcmp(buf, "TWO-RAY") == 0) {
propProfile->pathlossModel = TWO_RAY;
}
else if (strcmp(buf, "YOUR_PATHLOSS_MODEL") == 0) {
propProfile->pathlossModel = YOUR_PATHLOSS_MODEL;
}
}
// Read-in and set Shadowing sigma for log-normal-shadowing

// Read fading model name from configuration file


if (wasFound) {
if (strcmp(buf, "NONE") == 0) {
propProfile->fadingModel = NONE;
}
else if (strcmp(buf, "RAYLEIGH") == 0) {
// When Rayleigh fading is specified, Ricean with K = 0 is used
propProfile->fadingModel = RICEAN;
propProfile->kFactor = 0.0;
}
else if (strcmp(buf, "RICEAN") == 0) {
propProfile->fadingModel = RICEAN;
}
else if (strcmp(buf, “YOUR_FADING_MODEL”) {
propProfile->fadingModel = YOUR_FADING_MODEL;
// Your fading model’s initialization code
}
}
}

FIGURE 45. Global Initialization Function PROP_GlobalInit In

218 QualNet 3.6 Developer’s Guide


6.5.3 Calculating Propagation Model Values
On a radio channel, the average received signal power decreases logarithmically
with distance. Various propagation effects, including pathloss, fading and
shadowing, contribute to this decrease. In QualNet, the propagation values
between two nodes are computed every time a node moves. During this
computation, the functions PROP_CalculateFading and
PROP_CalculatePathloss in phy/propagation.c are called by QualNet to provide
the fading, pathloss and shadowing values. The shadowing value is added
directly to the pathloss value. The model's calculations should be inserted within
these functions to provide QualNet with the fading or pathloss value via a pointer
argument, which is the last parameter in the function calls shown here. The
following figures show the fading and pathloss functions respectively from phy/
propagation.c.

QualNet 3.6 Developer’s Guide 219


Networking Using QualNet

void PROP_CalculateFading(Node* node1, Node* node2, int channelIndex,


clocktype currentTime, float* fading_dB)
{
PropChannel *propChannel = node1->partitionData->propChannel;
PropProfile* propProfile = propChannel[channelIndex].profile;
PropProfile* propProfile0 = propChannel[0].profile;

if (propProfile->fadingModel == RICEAN) {

const float kFactor = propProfile->kFactor;
const int numGaussianComponents =
propProfile0->numGaussianComponents;
const int startingPoint =
RandomizeGaussianComponentStartingPoint(
node1->nodeId, node2->nodeId, channelIndex,
numGaussianComponents);

arrayIndexInDouble =
node1->propData[channelIndex].fadingStretchingFactor *
(double)currentTime;

arrayIndex =
((int)arrayIndexInDouble + startingPoint) %
numGaussianComponents;

value1 = propProfile0->gaussianComponent1[arrayIndex] +
sqrt(2.0 * kFactor);
value2 = propProfile0->gaussianComponent2[arrayIndex];

*fading_dB =
IN_DB((value1 * value1 + value2 * value2) / (2.0 * (kFactor + 1))
}
else if (propProfile->fadingModel == YOUR_FADING_MODEL) {
*fading_dB = CalculateFadingForYourModel (…);
// Perform your fading model’s calculations
}
else {
*fading_dB = 0.0;
}
}

FIGURE 46. Fading Functions

220 QualNet 3.6 Developer’s Guide


void PROP_CalculatePathloss(
Node* node,
int channelIndex,
float wavelength,
float txAntennaHeight,
float rxAntennaHeight,
PropPathProfile *pathProfile,
double* pathloss_dB)
{
PropProfile *propProfile = node->propChannel[channelIndex].profile;
...
switch (propProfile->pathlossModel) {
case FREE_SPACE:
case TWO_RAY:
{
if (propProfile->shadowingSigma != 0.0) {
shadowing_dB =
RANDOM_GaussianDistribution(
node->propData[channelIndex].seed,
propProfile->shadowingSigma);
}
if (propProfile->pathlossModel == FREE_SPACE) {
*pathloss_dB = PathlossFreeSpace(pathProfile->distance,
wavelength);
}
else {
assert(propProfile->pathlossModel == TWO_RAY);

*pathloss_dB = PathlossTwoRay(pathProfile->distance,
wavelength,
txAntennaHeight,
rxAntennaHeight);
}
*pathloss_dB += shadowing_dB;

return;
}
case YOUR_PATHLOSS_MODEL:
{
*pathloss_dB = PathlossYourModel(…)
// Perform model specific calculations
*pathloss_dB += shadowing_dB;
}
break;

}

FIGURE 47. Pathloss And Shadowing Calculations

QualNet 3.6 Developer’s Guide 221


Networking Using QualNet

6.5.4 Finalization

As in other layers, finalization section is used to release all acquired resources


and print statistics, if required. Add the model's node specific finalization code to
the PROP_Finalize function in phy/propagation.c.

6.6 Adding a Mobility Model


In QualNet, Mobility models work together with node distribution models and
terrain models to model the nodes mobility behavior. This section describes
creating a new mobility model called NewMobilityModel that takes a single
parameter (speed). Additionally, it covers all of the functions to write, as well as
the integration points where the model is added to QualNet.

The following lists summarize the models distributed with QualNet 3.6 and its
optional integration modules. Explanations of the models and their usage can be
found in the QualNet User's Manual, and source code for most is available in the
QUALNET_HOME/mobility directory of the QualNet installation. The existing
source files can be used as reference when creating a new model.

Mobility:
• Random waypoint
• Trace files

Node Distribution:
• Uniform
• Random
• Grid
• File

Terrain:
• DTED (Digital Terrain Elevation Data)
• DEM (Digital Elevation Model)

In the QualNet mobility model, Cartesian coordinate system is used for small
terrain where the curvature of the Earth can be abstracted out, and Spherical
(Latitude-Longitude-Altitude) coordinate system is used for large terrain where the

222 QualNet 3.6 Developer’s Guide


curvature of the Earth cannot be ignored. The mobility behavior is defined by the
following rules:
• The mobility model specifies an array of destinations and arrival times for each
node.
• Each node moves straight towards the next destination. QualNet determines
the intermediate positions at user specified distances.
• Elevation of each node with ground mobility models is determined by the
terrain data if available and requested by the user.
• Mobility includes node orientation (both horizontally and vertically).

In summary, a mobility model needs to specify the positions and times where the
node changes speed or direction, and QualNet will calculate all the intermediate
positions where the node is moving at a constant velocity.

Adding a new mobility model is a two step process:


1. Creating the protocol files.
2. Integrating those models into QualNet.

6.6.1 Creating Files


In QualNet each node has a node structure that holds all the information for the
node. This node structure contains a pointer to a structure called MobilityData.
This structure keeps the data related to mobility models, including a buffer of
future position updates as well. The node also includes a pointer to a
PartitionData structure that includes global information such as coordinate
system, node positions, terrain data, etc. Generally users should not modify the
PartitionData structure. The following figure provides a graphical representation of
the data structures relevant to mobility.

QualNet 3.6 Developer’s Guide 223


Networking Using QualNet

FIGURE 48. Mobility related Data structures and file locations

QualNet provides a simple API for add new mobility model that significantly
reduces the effort required to create new mobility models. One simple technique
for creating a new model is to copy one of the existing QualNet mobility models in
the QUALNET_HOME/mobility directory and modify or create only the parts
necessary.

224 QualNet 3.6 Developer’s Guide


Each model requires two files, a C file and a C header file. For this model, create
two files named newmobilitymodel.h and newmobilitymodel.c in the mobility
subdirectory.

Newmobilitymodel.h includes the following single declaration.

#ifndef MOBILITY_NEWMOBILITYMODEL_H
#define MOBILITY_NEWMOBILITYMODEL_H

void MOBILITY_NewMobilityModelInit(Node *node,


NodeInput *nodeInput,
clocktype maxSimClock);

#endif /* MOBILITY_NEWMOBILITYMODEL_H */

The initialization function shown here is required for all mobility models as it will be
called from the QualNet kernel during initialization. The function prototype should
include the three parameters (as shown above):
• node: a pointer to the node's data structures.
• nodeInput: a pointer to the input configuration file.
• maxSimClock: the length of the simulation in nanoseconds.

In addition to the required initialization function, the C file usually includes


additional functions to implement the mobility model's algorithm. The following
figure shows a skeleton implementation of our new protocol initialization function,
which would typically perform two functions—read initialization parameters, and
call the algorithm functions to generate future mobility positions.

The speed parameter is read on line 15 using the call FILEIO_ReadDouble.


Reading parameters is done using the file I/O API declared in include/fileio.h.
Note that the QualNet coding style suggests naming the configuration parameter
using the package name (Mobility), the model name (New Mobility Model) and the
parameter name (Speed).

After the configuration parameter is read, the function determines the initial
position of the node (node->mobilityData->current.position) on line 24. The
remainder of the function repeatedly calls an algorithm function (not shown) on
line 28 to determine each future position of the node until the end of the simulation
period. Each position is added to the node's future position buffer with the function
call MOBILITY_AddDest on line 31.

QualNet 3.6 Developer’s Guide 225


Networking Using QualNet

1 void MOBILITY_NewMobilityModelInit (Node *node,


2 NodeInput *nodeInput,
3 clocktype maxSimClock)
4 {
5 double speed;
6 BOOL wasFound;
7 Orientation orientation;
8 Coordinates dest1, dest2;
9 ….
10 orientation.azimuth = 0;
11 orientation.elevation = 0;
12 ….
13
14 // Read configuration parameters
15 IO_ReadDouble(
16 node->nodeId,
17 ANY_ADDRESS,
18 nodeInput,
19 "MOBILITY-NEW-MOBILITY-MODEL-SPEED",
20 &wasFound,
21 &speed);
22 ….
23 simClock = 0;
24 dest1 = mobilityData->current.position;
25 ….
26 // Determine all future positions for this node.
27 while (simClock < maxSimClock) {
28 NewMobilityModelCalculateNextPosition
29 (speed, dest1, &dest2, &orientation, &simClock);
30
31 MOBILITY_AddDest(mobilityData,
32 simClock, dest2, orientation);
33
34 dest1 = dest2;
35 }

FIGURE 49. General implementation of Mobility model

To add the new mobility model into QualNet, it needs to be called in the function of
MOBILITY_Initialize, in the file QUALNET_HOME/mobility/mobility.c, and the new
source files need to be added to the master Makefile so that they can be
compiled. The following figure shows the MOBILITY_Initialize, which first reads
the user defined parameter in configuration file for the new mobility model, as
shown on lines 4-10, and then calls the created function for the new mobility
model on lines 26-30.

226 QualNet 3.6 Developer’s Guide


1 MOBILITY_Initialize(Node *node, NodeInput *nodeInput)
2 {
3 ……
4 IO_ReadString(
5 node->nodeId,
6 ANY_ADDRESS,
7 nodeInput,
8 "MOBILITY",
9 &wasFound,
10 buf);
11
12 if (wasFound) {
13 clocktype maxSimClock = TIME_ReturnMaxSimClock(node);
14
15 if (strcmp(buf, "NONE") == 0) {
16 }
17 else if (strcmp(buf, "RANDOM-WAYPOINT") == 0) {
18 MOBILITY_WaypointInit(node, nodeInput, maxSimClock);
19 }
20 else if (strcmp(buf, "TRACE") == 0) {
21 MOBILITY_TraceInit(node, nodeInput, maxSimClock);
22 }
23 else if (strcmp(buf, "GROUP-MOBILITY") == 0) {
24 MOBILITY_GroupMobilityInit(node,nodeInput, maxSimClock);
25 }
26 else if (strcmp(buf, "NEW-MOBILITY-MODEL") == 0)
27 {
28 MOBILITY_NewMobilityModelInit
29 (node, nodeInput, maxSimClock);
30 }
31 }
32 else {
33 fprintf(stderr,
34 "Error: Invalid value for MOBILITY: %s.\n", buf);
35 abort();
36 }
37 }
38 }

FIGURE 50. Example of calling the new mobility model

Modifying the Makefile is a simple process. Edit the file


QUALNET_HOME/main/Makefile-common and add ../mobility/
newmobilitymodel.h to the list of header files, and ../mobility/
newmobilitymodel.c to the list of C files. Then rebuild QualNet by issuing the
build command appropriate to the system. On Windows, nmake -f Makefile-
windowsnt, on linux make -f Makefile-linux, etc.

QualNet 3.6 Developer’s Guide 227


Networking Using QualNet

228 QualNet 3.6 Developer’s Guide


CHAPTER 5 QualNet
Graphical User
Interface (GUI)

The QualNet Graphical User Interface, or GUI, has several components that are
useful for developers.

1. Chapter Overview
They are covered in the following sections:
• Overview of GUI Components
• Using QualNet Animator
• Adding GUI Animation to a Protocol
• Adding New GUI Parameters
• Using QualNet Designer
• Updating Tracer to Support New Protocol Traces

QualNet 3.6 Developer’s Guide 229


QualNet Graphical User Interface (GUI)

2. Overview of GUI Components


The GUI components in QualNet include the following:
• QualNet Animator—Animator is used for experiment design and animation.
• QualNet Analyzer—Analyzer is used for displaying simple graphs of collected
statistics and thread metrics files.
• QualNet Designer—Designer is used to create new protocols to add to the
Simulator.
• QualNet Tracer—Tracer is used to examine the contents of packets as they
traverse the network.

These tools in QualNet allow for a limited amount of customization. While the
source code for these tools is not provided, configuration files in the gui/settings
directory allow the tools to be re-configured.

230 QualNet 3.6 Developer’s Guide


3. Using QualNet Animator
This section will describe how to use of QualNet Animator's customization
features—the ability to add new protocols and the animation API. Additional
details on using QualNet Animator are provided in the QualNet User Manual.

3.1 Adding New GUI Parameters and Protocols


QualNet Animator displays several dialogs for accepting protocol parameters from
the user. It then uses these parameters to create the QualNet input files (.config,
.nodes, .app etc.).
Animator itself uses some tag-based text files to build the input widgets. The
following is the list of files used by Animator. These files are stored in the
QUALNET_HOME/gui/settings directory, where QUALNET_HOME is the root of
the QualNet distribution.
• choices.txt—This file generates the Settings, Node Properties, and Interface
properties windows.
• applications.txt—This file generates application-specific windows such as
FTP, TELNET, HTTP, CBR, etc.
• differentdialogproperties.txt—This file generates the following displayed
windows: Subnet Properties, Wireless Subnet Properties, Satellite Properties,
Switch Properties, Point-to-Point Link Properties, BGP Properties, as well as
other additional windows.
• fault.txt—This file generates the Fault Properties window.

Each of these files uses an HTML-style syntax which contains nested tokens
composed of several named keys. Token syntax appears as follows:

<token key1="value1" key2="value2" key3="value3">

The values must appear in quotation marks.

This section explains the general structure and usage of these files, but is not a
complete reference.

The choices.txt file can have the following tokens:


• category
• subcategory

QualNet 3.6 Developer’s Guide 231


QualNet Graphical User Interface (GUI)

• variable
• option

The applications.txt file can have the following tokens:


• application
• variable
• option

The differentdialogproperties.txt file can have the following tokens:


• differentdialogproperties
• variable
• option

The category, subcategory, and different dialogproperties tokens place the


variables on the correct dialogs and menus.

They should not be modified.

The variable & option tokens define the variables and their values.

3.1.1 Variable Token


The variable token has the following keys:

TABLE 1. Keys for the Variable Token

Token Name Description


Name A variable is identified by its name in QualNet
Animator. This name must be unique in the file. No
two variables appearing in the same file can bear
the same name.

This is a mandatory key.


Key The key is the identifier printed to the qualnet.config
configuration file, e.g. SEED or SIMULATION-
TIME.

This is a mandatory key.

232 QualNet 3.6 Developer’s Guide


TABLE 1. Keys for the Variable Token

Token Name Description


Type The type key determines what specialized
component is used to accept the value of the
variable, and is case sensitive. For example, if it is
Selection a combo-box with items to be selected
from is displayed.

This is a mandatory key.

The type can be one of the following:


• Integer (Integer inputs)
• Fixed (floating point inputs)
• Checkbox (for YES/NO inputs)
• File (for selecting a file from the file
system)
• Time (for time inputs)
• Mask (for sequence of '0' and '1' inputs)
• Coordinates (for accepting a set of two
double values)
• Fixed multiplier (for accepting unit based
input, such as MHz, GHz, etc.)
• ServerList (for accepting space separated
integer values, e.g. a list of node IDs.)
• Text (for accepting strings)
• TextSelection (displays an editable combo-
box which can store the strings typed.)
• Selection (displays a combo-box with a list
of items to be selected from. What items
will be displayed in the combo-box is
determined from the option tokens that are
children of the variable)
Displayname This serves as the label of the variable. Within a
window, a variable can be identified by its
displayname. If no displayname key is found, it is
defaulted to the name of the variable.

QualNet 3.6 Developer’s Guide 233


QualNet Graphical User Interface (GUI)

TABLE 1. Keys for the Variable Token

Token Name Description


Default A variable always comes with a default value.

This is a mandatory key.


Help The help text is used to explain the purpose of a
variable and is typically displayed as a tool-tip.
Min, max Minimum and maximum values for the variable.

A typical variable token would appear as follows:

<variable name="Simulation Time" key="SIMULATION-TIME"


type="Time" default="30S">

TABLE 2. Terms for the Variable Token

Type Valid Default Values


Integer Any valid integer value, e.g. "1", 199" etc.
Fixed Any valid float value, e.g. "1000.50"
Checkbox NO or YES
File "Please specify" (indicates that the file parameter is
required),"optional" (the file parameter is not
required),a valid file path, e.g. "./somefile.txt"
Time The value & the unit as it would appear in the
.config file. See the QualNet User's Manual for an
explanation. E.g. "2S", "500MS" or "5H".
Mask A sequence of 0s or 1s or combination of the same.
Ex - "01"
Coordinates Space separated integer or float values. Ex - "1000
1000"
Fixed multiplier Space separated value and the unit, e.g. "10 mps".
If this type is used, the variable token needs few
other keys also. They are - unit, minunit, maxunit.
ServerList This is not recommended for user, as it requires
special handling.
Text Any string.
TextSelection This is not recommended for user.
Selection The name of the option, not the value. See below.

234 QualNet 3.6 Developer’s Guide


3.1.2 Option Token
If the type key of a variable is set to Selection, it requires one or more option
tokens as child tokens. For example, for the user to choose a routing protocol
from a list of such protocols as AODV, LAR, DSR, etc., each of these would be an
option of a Selection variable. The option can further contain variable tokens as
children. For example, AODV needs to know the Net Diameter. Tokens nested in
this way can continue to arbitrary depth.

The option has the following three keys:


TABLE 3. Keys for the Option Token

Token Name Description


name This is the string that is displayed in the
combo-box. No two options whose parent
variable is same can have the same name.
This is a mandatory key.
value This is the string that is actually written in the
QualNet configuration file.
addon This key indicates that the option should only
be displayed if the associated optional "Add-
on" feature of QualNet is enabled.

QualNet 3.6 Developer’s Guide 235


QualNet Graphical User Interface (GUI)

For example:

<variable name="Routing Protocol" key="ROUTING-


PROTOCOL" type="Selection" default="Fisheye">

<option value="AODV" name="AODV">

<variable name="Net Diameter (max hops)" key="AODV-NET-


DIAMETER" type="Integer" default="35">

</option>

<option value="FISHEYE" name="Fisheye">

<option value="LAR1" name="LAR1">

<option value="DSR" name="DSR">

</variable>

The "default" key in the variable token refers to the name of the option
rather than the value.

3.1.3 Categories, Subcategories, and Applications


Category is the top-level token in the choices.txt. This houses one or more
subcategory tokens. It has the following keys:
• title—This is the title of the category. Each category is represented by a tab in
the Settings window. The tab name is same as the title of the category. This is
a mandatory parameter.
• help—This is used for pop-up info bubbles.

A subcategory has one or more variable tokens. The following are the keys of the
subcategory token:
• title—This is the title of the subcategory
• help—This is used for pop-up info bubbles.
• class—This can have any one of the following values:
• device (means that the subcategory will appear in the "Node properties"
window

236 QualNet 3.6 Developer’s Guide


• interface—Indicates that the subcategory will appear in the Interface
properties window.
• device,interface—Indicates that the subcategory will appear in both the
Node properties and Interface properties windows.

The application token represents an application (traffic generator) supported by


QualNet. The following are the permissible keys for this token.
• name—This is the name of the application. The name of an application is
displayed in the "Application palette" window. This is a mandatory key.
• key—Its key identifies the application in the QualNet application file. This is a
mandatory key.
• singlehost—This key can be either true or false. A value of false tells the
Animator that this type of application has a client and a server (or source and
destination), and may be set up by dragging the mouse from client node to
source node. A singlehost="true" application is set up by double clicking on the
source node. This is also a mandatory key.

The differentdialogproperties token is a utility token that is used to create different


input windows. The permissible keys for are as follow:
• name—This is the title of the window. This is a mandatory key. No two
differentdialogproperties token can bear the same name.
• help—This is used for pop-up info bubbles.

3.1.3.1 General Rules and Examples

Any token that has one or more child tokens must have an ending tag. For
example the category token always contains one or more subcategory tokens, so
it always starts with <category… and ends with </category>. Similarly, whenever
a variable contains option token, it always ends with </variable> token.

New applications are added to the applications.txt file. This application will be
made available for selection in the Application palette window.

3.1.3.2 Adding a New Routing Protocol

To do this, complete the following steps:

QualNet 3.6 Developer’s Guide 237


QualNet Graphical User Interface (GUI)

1. Search the choices.txt for the variable token whose key is ROUTING-
PROTOCOL.
2. Add the new protocol as an option. The user needs to find out the right file and
right place in the file to add something new. To achieve this, one has to
typically search the choices.txt for the variable with appropriate key.

The differentdialogproperties.txt can be modified in situations where one needs to


add something new to the existing differentdialogproperties token. For example,
the user may want to add a new MAC-PROTOCOL to the Wireless subnet
properties.

3.2 Adding GUI Animation to a Protocol


QualNet provides a rich API for adding animation to a protocol. In fact, the
protocols provided with QualNet don't use all of what's available.

Animation output is enabled in the QualNet Simulator by specifying the -animate


flag on the command line, in which case the animation commands are dumped to
standard output, or by running experiments in the Animator. If animation is
enabled, each node's gui Option variable will be set to TRUE. Thereafter, all
animation commands should be wrapped in

if (node->guiOption) {

// GUI commands.

Most of the animation commands available represent "semantic" events, such as


"packet was sent" that can be displayed in different ways depending on the
situation. For example, "sending packet wirelessly" will look different than
"sending packet over a wire" even though both call the same function.

The following general types of animation are available in QualNet:


• Packet animation (sends and receives)
• Queue animation (insertions, deletions, drops)
• Wireless animation (transmissions, directional transmissions, antenna
patterns)
• Node animation (icons, labels, motion, orientation)

238 QualNet 3.6 Developer’s Guide


• Statistics (definition, data updates)
• Logical link (applications and abstract linkages)

The commands available in each class of animation will be described in more


detail in the following subsections.

Many of the functions listed require a GuiLayers parameter. This parameter is


used to enable animation filtering in the Animator, but a savvy programmer can
take advantage of this to display only the user's own defined animation. As of
QualNet 3.6, there is no animation defined at the GUI_CHANNEL_LAYER, so the
user could specify this layer for all their own animation, then disable all other
layers in the Animator.
• Packet Animation—Packet animation includes such calls as GUI_Drop,
GUI_Broadcast, GUI_EndBroadcast, GUI_Multicast, GUI_Unicast,
GUI_Receive.
• Queue Animation—GUI_AddInterfaceQueue, GUI_QueueInsertPacket,
GUI_QueueDropPacket, GUI_QueueDequeuePacket
• Wireless Animation—GUI_Collision, GUI_SetPatternIndex,
GUI_SetPatternAndAngle, GUI_Broadcast, GUI_EndBroadcast, GUI_Collision
• Node Animation—GUI_MoveNode, GUI_SetNodeOrientation,
GUI_SetNodeIcon, GUI_SetNodeLabel, GUI_SetNodeRange,
GUI_SetNodeType (not currently enabled)
• Statistics Animation—GUI_DefineMetric, GUI_SendIntegerData,
GUI_SendUnsignedData, GUI_SendRealData
• Logical Link Animation—GUI_AddLink, GUI_DeleteLink,
GUI_AddApplication, GUI_DeleteApplication

3.2.1 Customizable Animation

The programmer can customize the appearance of some of the animation using
the GUI_SetEffect function.

As of version 3.6, only the following events can handle the following set of effects.
• GUI_Receive (GUI_FLASH_X, GUI_CIRCLE_NODE,
GUI_DEFAULT_EFFECT)
• GUI_Unicast(GUI_FLASH_X, GUI_CIRCLE_NODE,
GUI_DEFAULT_EFFECT)

QualNet 3.6 Developer’s Guide 239


QualNet Graphical User Interface (GUI)

• GUI_Drop(GUI_FLASH_X, GUI_CIRCLE_NODE, GUI_DEFAULT_EFFECT)

3.3 Communicating with QualNet Simulator and QualNet


Animator
QualNet Simulator was originally designed to run from the command line. The
experiment is configured using a set of plain text files that specify the protocols
running on each node and each network. In this mode, there is no opportunity for
user interaction with the running simulation.
QualNet Animator provides a graphical interface for designing and animating
experiments, and provides limited opportunity to interact with the running
simulation. This section describes how the runtime interaction between the
Animator and Simulator is set up.
The subsequent subsections will often refer to GUI related API functions. For
descriptions of these functions, please refer to the Simulator source file include/
gui.h, or the API reference document for the correct software version.

Both the C code in the Simulator and the Java code in the Animator that
implements this interface is currently hidden from customers. Some
portions of the C code may be provided to customers upon request.

3.3.1 Initializing QualNet


When the user presses the Run QualNet (Action!) button in Animator, the
following steps occur to initialize QualNet for a simulation:
1. Its internal representation of the experiment is written into the plain text format
recognized by the Simulator.
2. These files (always more than one) are placed in the user's designated
temporary directory.
3. A socket is opened on the first available port >= 4000.
4. An external process is started with the command line:

qualnet <temp-dir>/qualnet.config -interactive hostname


<port#>

5. A connection on the socket is waited on.

Upon seeing the -interactive command line flag, QualNet Simulator does the
following:

240 QualNet 3.6 Developer’s Guide


1. Opens a socket connection to the specified host and port.
2. Checks out a license.
3. Reads the input file.
4. Send scenario initialization information to Animator (GUI_Initialize).
5. Creates and initializes nodes and networks.
• Calls GUI_InitNode for each node
• Calls GUI_CreateSubnet for each subnet
• Calls GUI_CreateHierarchy for Animator-designed hierarchical networks.
• Calls GUI_InitialInterfaces to configure IP addressing for all the nodes.

This in turn may result in calls to other GUI functions.

6. Processes instructions sent from Animator.


7. Upon receiving a STEP command from the Animator, starts processing events.

Steps 2-3 are essentially identical to running the Simulator from the command
line. Steps 1 and 4 establish the communication channel between QualNet
Simulator and Animator. Step 5 is basically identical to the non-animated mode of
execution, with occasional information sent to Animator to configure the network
for viewing. Steps 6 and 7 will be described more fully in the following section.

3.3.2 Runtime Interaction


The interaction between Animator and Simulator is very simple. The Animator
sends commands to the Simulator over the socket, and the Simulator, at user
defined intervals, reads the commands and adjusts its behavior accordingly. The
Simulator also sends animation and statistics event related information to the
Animator as the events occur. Most of the information sent to the Animator can be
enabled or disabled through the Animator's controls.

QualNet 3.6 Developer’s Guide 241


QualNet Graphical User Interface (GUI)

TABLE 4. Commands sent from Animator to Simulator

Command Parameters Description


GUI_STEP This command tells the
Simulator that it is time to begin
processing events for the
previously specified period of
simulation time (not real time.)
At the end of this period, the
Simulator will once again begin
accept commands from the
Animator.
GUI_SET_COMM_INTERVAL Time (the interval) Tells the Simulator how far to
advance in Simulation time
before checking for more
commands from the Animator.
GUI_ENABLE_LAYER Integer (layer #) All animation commands from
the specified protocol layer will
be sent over the socket to the
Animator.
GUI_DISABLE_LAYER Integer (layer #) All animation commands from
the specified layer are dropped
without being sent to the
Animator. Provides an easy
way to limit the amount of
information being passed over
the socket. However, the
Animation functions are still
called from the protocol code.
The filtering is done in the GUI
interface code.
GUI_ENABLE_NODE Integer (node ID) Enables animation for a
particular node.
GUI_DISABLE_NODE Integer (node ID) Disables animation for a
particular node.
GUI_SET_STAT_INTERVAL Time (interval) Sets the interval (in simulation
time) at which to query the
Simulator for the latest
statistics.

242 QualNet 3.6 Developer’s Guide


Command Parameters Description
GUI_ENABLE_METRIC Integer (metric ID) Enables transmission of a
specific metric across the
socket.
GUI_DISABLE_METRIC Integer (metric ID) Disables reporting of this metric.
GUI_STOP Terminates the simulation
experiment.

The commands are sent across the socket as character strings, the command
number (as defined in gui.h) followed by the parameters, if any. For example, the
command to set the communication interval to 100 milliseconds would be 1
100000000 where 1 is the command number for GUI_SET_COMM_INTERVAL
and 100000000 is the time representation of 100 milliseconds. 100MS is also an
acceptable representation.

QualNet 3.6 Developer’s Guide 243


QualNet Graphical User Interface (GUI)

TABLE 5. Replies sent from the Simulator to the Animator

Reply Parameters Description


GUI_STEPPED Time (the time just Reports to the Animator that the
reached) Simulator has reached the end
of the period specified by the
last STEP command.
GUI_DATA Unused
GUI_ANIMATION_COMMAND Varies Prefaces various animation
events
GUI_ASSERTION String (the error message) Indicates an assertion failure in
the Simulator code.
GUI_ERROR String (the error message) Indicates an error was detected
in the Simulator code.
GUI_WARNING String (the error message) Indicates a warning from the
Simulator.
GUI_SET_EFFECT 5 integers (event, layer, Assigns a visual effect to a
type, effect, color) particular animation event.
GUI_STATISTICS_COMMAND Varies Prefaces either the definition of
a metric, or the delivery of the
latest statistical data.
GUI_FINISHED Indicates the end of the
simulation.

3.3.3 Finalization

With the Animator involved, simulation execution can end in one of three ways:
• The simulation runs to completion and terminates normally. A GUI_FINISHED
reply is sent from Simulator to Animator.
• The simulation terminates with an error. A GUI_ERROR or GUI_ASSERTION
reply is sent to Animator, the Animator cleans up a little and sends a
GUI_STOP command to the Simulator, and the Simulator shuts down by
sending a GUI_FINISHED reply back to the Animator.
• The User terminates the execution by pressing the Animator's stop button. The
Animator cleans up a little and sends a GUI_STOP command to the Simulator,
and the Simulator shuts down by sending a GUI_FINISHED reply back to the
Animator.

244 QualNet 3.6 Developer’s Guide


4. Using QualNet Analyzer
Very little customization is available for Analyzer. From a programming
standpoint, the only thing that can be done to customize Analyzer is to add or
remove metrics from the output statistics file.

For reference, the statistics file is a text file, with one statistic reported per line.
The line is formatted as a comma separated list of fields:
• Node ID
• IP address (optional)
• Index (used by some protocols for queue number or interface number)
• Protocol Layer
• Protocol Name
• Metric Name = value

QualNet 3.6 Developer’s Guide 245


QualNet Graphical User Interface (GUI)

5. Using QualNet Designer


QualNet Designer allows users to graphically specify a protocol model in the
QualNet simulator. A state diagram model captures the event handling
functionality of the protocol, while user inputted code defines the semantics of
each such event handled. There are also facets available for creating local data
structures, auxiliary functions, and other various utilities that can graphically mimic
in an organized fashion any entity in a hand-written protocol.

5.1 Adding Capabilities to Designer


Using Designer to add protocols to QualNet is covered in the User's Manual. In
this section we cover how to add capabilities to Designer. In the gui/settings
directory, there are three files that Designer uses to define its runtime behavior:
• layers.txt
• ACD.rules
• patch.rules

The layers.txt file defines the standard APIs between layers that the Designer
uses as event triggers, and also defines some special requirements at each layer.
It is a text file and recognizes both # lines and <comment> tags as comments.
The file is divided into three sections—Layers, API, Special. The Layer section
numbers and names the layers.

<LAYERS>
0 Channel
1 Radio

</LAYERS>

The API section lists the standard events between layers, using the layer IDs to
mark the source and destination layers for each event, e.g.

#<SourceLayerId> <DestLayerId> <API>


<API>
0 0 MSG_CHANNEL_FromChannel
1 0 MSG_CHANNEL_FromRadio
</API>

246 QualNet 3.6 Developer’s Guide


The final section identifies special requirements for some layers, such as the
application layer needing application parameters (which are treated differently
from other configuration parameters).

#LAYERID NAME CODE HELP


<SPECIAL>
5 APPLICATIONPARAMETER PARAMETERLIST
3 IP_PROTOCOL_NUMBER PROTOCOLNUMBER
</SPECIAL>

The ACD.rules file defines the functions used in assisted code development. It is
a text file and uses C++ style commenting. Some functions, such as that defined
here, are general purpose "semantic" functions, which aren't necessary a single
function call, but some useful chunk of code that the user might want to use. The
function definition consists of three sections: PARAMETERS, COMMENTS, and
CODE, which are almost self-explanatory. The CODE section uses placeholders
for where the Designer asks the user for input.

<FUNCTION:Initialize Seed:GENERAL:GENERIC>
<PARAMETERS>
</PARAMETERS>
<COMMENTS>
</COMMENTS>
<CODE>
<dataPtr->seed[0] = (unsigned short) (node->seed[0] +
1);>
<dataPtr->seed[1] = (unsigned short) (node->seed[1] +
1);>
<dataPtr->seed[2] = (unsigned short) (node->seed[2] +
1);>
</CODE>
</FUNCTION>

Finally, the patch.rules file tells the Designer how and where to "patch" the
Simulator source code to add the newly designed protocol. The file is divided by
layer. For each layer, there is a set of rules for modifying the files. The format for
a rule is as follows:

Rule <RuleName> <file to change> <type of file>


Action list
endRule

QualNet 3.6 Developer’s Guide 247


QualNet Graphical User Interface (GUI)

The file to change is listed as a relative path from QUALNET_HOME. The type of
file can be C_FILE, GUI_FILE, or MAKE_FILE. A subset of the possible actions is
given in the following table:

5.2 Adding Protocols Using Designer


Other than having the ability to specify and modify a QualNet model in a
graphically organized representation, QualNet Designer acts as an integrated
development environment as well. The user has the ability to generate QualNet
code from their graphical model, plug in the model into the source tree, and
compile the entire simulator enabling the newly created model. With handwritten
models, the flexibility of modifying in an organized fashion, along with plugging the
protocol in and out of the simulator is not available.
Designer also has a simple debugging environment. Small changes in the
generated code format can be made by the user via designer, and ported back to
model form. This together with compiler support allows the designer act as a
formidable tool when debugging models.

5.2.1 Example: Adding a Simple ALOHA Protocol


1. Enter RunDesigner at the command prompt.
2. Choose New Protocol and name it Aloha.
3. Select the MAC layer.

248 QualNet 3.6 Developer’s Guide


4. Click OK.

QualNet 3.6 Developer’s Guide 249


QualNet Graphical User Interface (GUI)

The Designer window will be displayed as follows:

To create the Aloha protocol, users must do the following:


• Specify data structures
• Specify additional protocol state fields
• Specify statistics variables
• Create state diagram
• Specify state function code
• Specify utility functions

250 QualNet 3.6 Developer’s Guide


5.2.1.1 Specifying Simple ALOHA Data Structures
The Simple ALOHA protocol will require only one data structure, which is a struct.
The struct will be used as the message header for ALOHA packets.
The following are the attributes for the data structure:
Tag: aloha_header_str
Identifier: AlohaHeader
Members:
• NodeAddress sourceAddr
• NodeAddress destAddr

To specify the Simple ALOHA data structures, complete the following steps:
1. Choose the Add Data Definitions button from left-hand menu on the Designer
screen.

2. Enter the tag and identifier.

QualNet 3.6 Developer’s Guide 251


QualNet Graphical User Interface (GUI)

3. Click the Structure Members button to pop up a dialog to enter the fields.

4. Click the Add button after filling in the type and name for each field.
5. Once all field have been entered, click OK.
6. To add the final structure, click Add.

5.2.1.2 Specifying Additional Protocol State Fields


1. Choose the Variable Declaration button from left-hand menu on the Designer
screen.

2. In the Variable Declaration Table, enter the Variable Name myMacData.

252 QualNet 3.6 Developer’s Guide


3. In the Variable Declaration Table, set the Variable Type to MacData*.

5.2.1.3 Specifying Statistics Variables


1. Select the Statistics Variables button.

2. Add the following statistics variables:


• Packets Sent

QualNet 3.6 Developer’s Guide 253


QualNet Graphical User Interface (GUI)

• Packets Received

3. The information is accessible in State Entry Code with the following:

dataPtr->stats.<statsVariableName>

5.2.1.4 Creating the ALOHA State Diagram


ALOHA is not based on internal timer events. Rather, all behavior stems from
calls from the physical and network layers.
There are two steps in creating the state diagram.
1. Create the three special MAC functions that surrounding layers call.

NetworkLayerHasPacketToSend

ReceivePacketFromPhy

ReceivePhyStatusChangeNotification

254 QualNet 3.6 Developer’s Guide


2. Create a state to represent when ALOHA is idle.

3. Draw an automatic transition from the Initial State to the idle state.
4. Use triggers to link the idle state to the three special MAC states.

These are not event-based triggers.

This is a mechanism to let Designer know these are the special MAC
functions.
5. Draw transitions from idle to each of three states.

QualNet 3.6 Developer’s Guide 255


QualNet Graphical User Interface (GUI)

6. Use the following triggers for the corresponding state:

256 QualNet 3.6 Developer’s Guide


The diagram should be displayed like the following:

7. Add a state named Transmit and one named Receive for sending and
receiving data.
8. Before adding transition to the Receive and Transmit states, first specify the
special MAC State Entry Code function code for the three MAC functions.
• ReceivePacketFromPhy—Called when the physical layer has a packet to
send up to the MAC.
The entry code is as follows:

AlohaHeader *hdr = (AlohaHeader *)


MESSAGE_ReturnPacket(msg);

BOOL isUnicastFrame = MAC_IsMyUnicastFrame(node, hdr-


>destAddr);

BOOL isBroadcastFrame = hdr->destAddr == ANY_DEST;

This grabs AlohaHeader from the packet. It creates boolean variables that
determine if the packet is a unicast or broadcast.

QualNet 3.6 Developer’s Guide 257


QualNet Graphical User Interface (GUI)

• ReceivePhyStatusChangeNotification—Called when physical layer is


notifying MAC that it has changed status (transmit, idle, etc).
The entry code is as follows:

BOOL isQueueEmpty = MAC_OutputQueueIsEmpty(node,


dataPtr->myMacData->interfaceIndex);

if (oldPhyStatus == PHY_TRANSMITTING) {

assert(newPhyStatus != PHY_TRANSMITTING);

This creates a boolean that represents if there are any packets on the
queue. It also asserts that if the physical layer was transmitting previously,
then currently it is not.

Note: oldPhyStatus and newPhyStatus are always passed into the


ReceivePhyStatusChangeNotification function by definition.

• NetworkLayerHasPacketToSend—Called when the network layer has


packet to send down to MAC. There is no entry code in this case. This
function will automatically call the Transmit routine.
9. Create an automatic transition from NetworkLayerHasPacketToSend to
Transmit. As previously discussed, NetworkLayerHasPacketToSend
automatically calls the ALOHA transmit code.
10. Create an automatic transition from Transmit to idle.
11. Once ALOHA has transmitted, then reenter the idle state.
12. Create a transition from ReceivePhyStatusChangeNotification to Transmit.
13. This time use a guarded transition.

(oldPhyStatus == PHY_TRANSMITTING) && !isQueueEmpty

14. Create a transition from RPSCN to idle.


15. Set a guarded transition to ELSE.
These transitions state that if the physical layer is not currently transmitting and
the queue is not empty, then proceed to the transmit routine, otherwise return
to idle.

258 QualNet 3.6 Developer’s Guide


Note: isQueueEmpty was previously created in the entry code of
RPSCN.

16. Create a transition from ReceivePacketFromPhy to Receive.


17. Use a guarded transition:

isUnicastFrame || isBroadcastFrame

18. Create a transition from ReceivePacketFromPhy to idle.


19. Set a guarded transition to ELSE.
These transitions state that if the frame is a unicast or broadcast frame, then
enter the ALOHA Receive routine. Otherwise return to idle.

Note: For simplicity, ignore any notion of promiscuous mode.


Reminder: isUnicastFrame and isBroadcastFrame were previously
created in the entry code of ReceivePacketFromPhy

Much like the Transmit state, Receive will reenter the idle state after its code
has been executed.
20. Create an automatic transition from the Receive state to the Idle state.
21. Enter the entry code for Transmit and Receive:

dataPtr = (AlohaData *) MEM_malloc(sizeof(AlohaData));

assert(dataPtr != NULL);

memset(dataPtr, 0, sizeof(AlohaData));

dataPtr->myMacData = node->macData[interfaceIndex];

dataPtr->myMacData->macVar = (void *)dataPtr;

dataPtr->initStats = TRUE;

Lines 1-3 allocate the protocol data structure (dataPtr). Lines 4-5 set general
MAC data structure pointer that resides in dataPtr. Line 6 turns on statistic
initialization.

Note: dataPtr is declared automatically at the beginning of this


function. Reminder: myMacData was entered as a variable declaration
earlier.

QualNet 3.6 Developer’s Guide 259


QualNet Graphical User Interface (GUI)

22. The final state usually serves as printing out statistics and freeing structures.
Designer automatically generates all necessary statistic printing code, so all
that is necessary is to turn on the feature.
The entry code is as follows:

dataPtr->printStats = dataPtr->myMacData->macStats;

The generic MAC data structure decides if statistic printing has been enabled.

The designer model for Simple ALOHA is now complete.


1. Go to the build menu, and select Generate Code.
2. Now return to the build menu, and select View Code and pick a file to view.

260 QualNet 3.6 Developer’s Guide


6. Using QualNet Tracer
This section contains the following topics:
• Simulator Modifications
• Updating Tracer Description Files

Tracer customization consists of adding support for new protocols. This is a two
part process. First, the Simulator code must be updated to produce trace output
for a new protocol. Second, a description of that trace output must be made
available to the Tracer.

6.1 Simulator Modifications


The Simulator needs to be able to take a packet anywhere in its lifecycle and
show all of its current headers. Since lower layer protocols are unaware of what
protocols are being used higher in the stack, much less the format of their
headers, information about the protocols that have put headers on the packet
already is stored in the Message data structure that contains the packet.

The following steps must be followed to add packet tracing support to a new
protocol. For the purpose of this listing, we will use UDP as an example. (UDP
already has tracing enabled.)
1. In the file include/trace.h, add a new line to the TraceProtocolType
enumeration, e.g..

enum {
TRACE_TCP,
TRACE_IP,
TRACE_AODV,
TRACE_DSR,

TRACE_UDP,
// Must be last one!!!
TRACE_ANY_PROTOCOL
};

2. Add a parameter to default.config to enable tracing. The following code


segment from transport/udp.c checks reads the TRACE-UDP variable from the
input file, and decides, based on the global TRACE-ALL variable whether to

QualNet 3.6 Developer’s Guide 261


QualNet Graphical User Interface (GUI)

enable or disable tracing for UDP. Note the calls to TRACE_IsTraceAll,


TRACE_EnableTrace, and TRACE_DisableTrace.

static void TransportUdpInitTrace(Node *node, const NodeInput *nodeInput)


{
char buf[MAX_STRING_LENGTH];
BOOL retVal;
BOOL traceAll;

traceAll = TRACE_IsTraceAll(node);

IO_ReadString(
node->nodeId,
ANY_ADDRESS,
nodeInput,
"TRACE-UDP",
&retVal,
buf);

if (retVal)
{
if (strcmp(buf, "YES") == 0)
{
if (!traceAll)
{
TRACE_EnableTrace(node, TRACE_UDP);
}
}
else if (strcmp(buf, "NO") == 0)
{
if (traceAll)
{
TRACE_DisableTrace(node, TRACE_UDP);
}
}
else
{
ERROR_ReportError("TRACE-UDP should be either \"YES\" or \""
"NO\".\n");
}
}
else
{
if (!traceAll)
{
TRACE_DisableTrace(node, TRACE_UDP);
}
}
}

262 QualNet 3.6 Developer’s Guide


3. Add a function to print the trace data. The following function from transport/
udp.c shows how the header data for UDP is printed to the trace file. In the
code, buf is used to format the output, and IO_PrintTrace is called to copy the
formatted output to the trace file.

/*
* FUNCTION TransportUdpPrintTrace
* PURPOSE Print out packet trace information.
*
* Parameters:
* node: node printing out the trace information.
* msg: packet to be printed.
*/
void TransportUdpPrintTrace(Node *node, Message *msg)
{
char buf[MAX_STRING_LENGTH];
TransportUdpHeader* udpHdr = (TransportUdpHeader *)
MESSAGE_ReturnPacket(msg);

sprintf(buf, "%d", udpHdr->sourcePort);


IO_PrintTrace(node, buf);
sprintf(buf, "%d", udpHdr->destPort);
IO_PrintTrace(node, buf);
sprintf(buf, "%d", udpHdr->length);
IO_PrintTrace(node, buf);
sprintf(buf, "%d", udpHdr->checksum);
IO_PrintTrace(node, buf);
}

4. Update TRACE_PrintTrace in main/trace.c to call the function. The following


code segment in TRACE_PrintTrace calls the UDP function for UDP headers.

case TRACE_UDP:
{
TransportUdpPrintTrace(node, message);
break;
}

5. Place calls to TRACE_PrintTrace in the protocol code wherever packets are


manipulated. When a packet is moving up the stack, print the trace before
removing the header, e.g.

QualNet 3.6 Developer’s Guide 263


QualNet Graphical User Interface (GUI)

TRACE_PrintTrace(node, msg, TRACE_TRANSPORT_LAYER);

/* Remove UDP header. */


MESSAGE_RemoveHeader(node, msg, sizeof(TransportUdpHeader), TRACE_UDP);

When the packet is moving down the stack, add the header before printing. (In
the current implementation, the MESSAGE_AddHeader function allocates
space for the header, and then the user adds the data.)

MESSAGE_AddHeader(node, msg, sizeof(TransportUdpHeader), TRACE_UDP);

udpHdr = (TransportUdpHeader *) msg->packet;


info = (AppToUdpSend *) msg->info;

udpHdr->sourcePort = info->sourcePort;
udpHdr->destPort = info->destPort;
udpHdr->length = MESSAGE_ReturnPacketSize(msg);
udpHdr->checksum = 0; /* checksum not calculated */

TRACE_PrintTrace(node, msg, TRACE_TRANSPORT_LAYER);

6.1.1 Trace File


This section describes the format of the collected trace data. Each line consists of
the following items, in order, separated by semicolons:
1. packet ID, a tuple of source node ID, and sequence number
2. simulation time
3. ID of node processing packet
4. originating protocol ID
5. comma separated list of protocol Ids (same order as headers)
6. comma separated values for the header fields of the protocol
7. payload

Example:
9,0;70.000000000;19;3;1,2;1024,59,520,0;4,5,1,540,0,000,0,64,17,0,19,17
If the previous line is parsed, it would be like the following:

packet id (source node id, sequence number) = 9,0


simulation time =
70.000000000

264 QualNet 3.6 Developer’s Guide


id of the node that processes the packet = 19
id of the originating protocol = 3
protocols' ids with header description = 1,2
header field values for protocol id 1 =
1024,59,520,0
header field values for protocol id 2 =
4,5,1,540,0,000,0,64,17,0,19,17
payload = no value

The important part for a protocol author is that the header fields for a protocol are
printed as a comma separated list.

6.2 Updating Tracer Description Files


Tracer requires an additional input file that specifies the format of the headers for
each protocol. This file is gui/settings/tracerheaderdescription.txt. The following is
the format in which the headers are specified in this file:

<header "id of the protocol" "header length in bytes"


"name of the protocol">
"field name" "field length" "field data type"
.
.
.
</header>

Field length of less than 1 byte are written as 1 byte (purely an assumption used
by the Tracer tool).

Field data type has no special use now (exception IPADDR) and may not match
the fib6ebld length". Still, it is a mandatory field, which might be used for future
enhancements.

In the example cited, the list of protocols' ids has value "1,2". So bthe UDP and
the IP header fields appear thereafter.

The entry for UDP is as follows:

<header 1 8 UDP>

Source Port,2,int

Destination Port,2,int

QualNet 3.6 Developer’s Guide 265


QualNet Graphical User Interface (GUI)

Length,2,int

Checksum,2,int

</header>

This corresponds to the header data structure defined in transport/udp.h.

266 QualNet 3.6 Developer’s Guide

You might also like