Module Creation for WSNet

De Ensiwiki
Aller à : navigation, rechercher
Project schedule.png
Titre du projet Simulation de routage sous WSNet
Cadre Projets de spécialité
Page principale Simulation de routage sous WSNet


Installing WSNet

See Installation and Usage of WSNet

Setting up the working directory

Once WSNet is correctly installed, you can start the implementation of a new module. An environment variable will be configured to tell the simulator where our modules can be found. Afterward, the path $HOME/wsnet-module/ is set as the home directory for writing new WSNet modules. Follow the following instructions.

First of all, create and move to the working directory by typing the following commands:

mkdir $HOME/wsnet-module/
cd $HOME/wsnet-module/

Then, download the files needed for the implementation from the SVN repository by typing the following command:

svn checkout svn://

This will download the files needed for writing new WSNet modules. Now, the $HOME/wsnet-module/user_models/ directory should contain the following files:

ls ./user_models/
> bootstrap

Finally, we have to setup the WSNET_MODDIR environment variable by adding the following lines in $HOME/.bashrc file:

export WSNET_MODDIR=$HOME/wsnet-module/lib

This variable tells the WSNet simulator where our modules can be found. In our case, the modules will be installed within the $HOME/wsnet-module/lib directory.

AttentionWSNet doesn't perform recursive search of libraries. So they can't be placed in subdirectories of the directory indicated by the WSNET_MODDIR variable.


You can directly download a tutorial about the WSNet framework.


In order to implement WSNet moduls you will have to deal with three concepts : NODE, ENTITY and CALL.


node_t is a structure that represent your network in the simulator. It contains various fields, the most useful being : nodeid_t id. Since all of the nodes are stocked in an array defined as a global variable, you will never use the structure node_t directly. It's the node id that will make you able to access to other fields such as :

  • position_t position : the geographical position of the node.
  • a field named "private" in which you can put some data you will use to implement your module.

Some functions to get or set those fields :

  • position_t *get_node_position (nodeid_t node) : return the geographical position of the node.
  • void set_node_private_data (call_t *c, void *data) : give data to the node. *data is typically a structure defined in your module and designed to contain useful information for the functioning of the module.
  • void *get_node_private_data (call_t *c) : return the field named "private" which contains the data you put in it before.

For the moment, don't focus on the "call_t *c" parameter. You just need to know that "c" contain the node id of the current node.

Nodes are created by the mobility entity specified in the mobility section of the XML configuration file. You can read their coordinates in a graph by using the library "mobility_filestatic". In that case, coordinates have to be placed in a .data file with the following format : "id x y z". You also can work on a random graph by using the library "mobility_static". In any case, the number of nodes in the simulated graph is indicated in the "simulation" tag of the XML file's "worldsens" section. WSNet read this number automatically and then create all of the nodes. If you are using an existing graph placed in a .data file, make sure that the number of nodes you have indicated in the XML file's simulation tag is less or equal to the number of nodes coordinates placed in the graph file.


An entity represents a module during a simulation. It defines the behavior of your module : the impact of your module on the nodes creation, on the nodes bootstrapping, on the packets reception, etc. You have to know that each required function for the module are contained in the structure entity_t which represent the module. Those functions are :

  • int init(call_t *c, void *params) : Function called at the beginning of the simulation to initialize the entity. In this function you have access to the value of the init tag of your entity in the XML file. You can access to the entity through the call_t* parameter which contains its id to add some entity data.
  • int setnode (call_t *c, void *params) : Initialize the node after its construction.
  • int destroy (call_t *c) : Destroy the entity called in call_t* parameter. It can free the memory for example.
  • int unsetnode (call_t *c) : Destroy the node in call_t* parameter.
  • int bootstrap (call_t *c) : Function called when the node is about to be set "alive" so you can schedule the first action of the node for example.
  • int ioctl (call_t *c, int option, void *in, void **out).

Note that a function return 0 if it ended well and -1 otherwise.

An entity also contains an other set of functions that will depend on the type of the module. Indeed, a module can be from different types, depending on what part of the network you want to simulate. All of the possible types are listed bellow :

  • environment
  • mobility
  • antenna
  • radio
  • mac
  • routing
  • application
  • energy
  • monitor
  • propagation
  • interferences
  • modulation
  • noise
  • generic

The entity_t structure also contains a structure model_t that briefly describes the module (authors, version, type ...). You have to note that the field "type" is of primitive type "int". You can find all of the possible values for this fild in the pdf "Framework.pdf" at the top of this page.

You can see the needed functions for one type of module in the pdf "Framework.pdf" you can find at the top of this page, or in the file /include/models.h directory of your installation directory.

Note that, as for the nodes, the entities are identified by their entity id. Then, there is an array of entities defined as a global variable and you obtain access to the entity by using some functions and the entity id. So you will never use directly the structure entity_t. You can find some usefull functions to access to the entity in the pdf "Framework.pdf" at the top of this page.

For example, to correctly define an application module you need to follow the following architecture for your .c file :

   #include <include/modelutils.h>
   model_t model = {
   {NULL, 0}
   int init(call_t *c, void *params);
   int destroy(call_t *c);
   int setnode(call_t *c, void *params);
   int unsetnode(call_t *c);
   int bootstrap(call_t *c);
   int rx(call_t *c, packet_t *packet);
   // Be careful !! The part bellow depends on the type of the module
   application_methods_t methods = {rx};


During a simulation, one entity can call a function on one node and one other entity (not necessarily the same entity). For example, one node, say node 1, just received a packet that is currently being treated in one layer, say layer A. Then this layer will ask the upper layer, say layer B, to treat the packet. This way the packet will be able to be treated by all of the layers in the correct order. So you want to call a reception function, which is named rx in every module, on node 1, and you want to represent the fact that this function is the one of layer B and was called by layer A. This is the meaning of the structure call_t which is a parameter of all of the functions needed by a WSNet module. The pattern of this structure is the following one :

  • entityid_t entity : the entity destination of the call.
  • nodeid_t node : the node destination of the call.
  • entityid_t from : the entity that initiated the call.

So in a function, the call_t parameter give you access to the calling entity and to the called node and entity.


The functions needed in a module are divided into two categories :

1) The functions you will implement but never use directly. Init, setnode and bootstrap, for example, will only be called by the simulator.

2) The functions you will implement and use directly. There are six functions, needed to some types of modules :

  • rx (call_t *c, packet_t *packet)
  • tx (call_t *c, packet_t *packet)
  • get_header_size (call_t *c)
  • set_header (call_t *c, packet_t *packet, destination_t dst)
  • get_header_real_size (call_t *c)
  • ioctl (call_t *c, int option, void *in, void **out)

But you can't call functions of this second category that easily. Indeed, modules are implementing according to a kind of "object oriented" programming approach : each module have the same functions placed in a structure representing the module. So to call directly a function defined in your module, you need to access to the entity_t structure describing the module. But, as we said before, the interface is designed in a way that you don't access directly to this structure type. That's why macros were implemented.

Instead of access to the entity_t structure and then call the good rx function, for example, you will just call the RX macro with the same call_t* parameter. The others macros available are : TX, SET_HEADER, GET_HEADER_SIZE, GET_HEADER_REAL_SIZE, IOCTL.


You have access to the simulator's scheduler with the following functions :

  • event_t *scheduler_add_callback (uint64_t clock, call_t *c, callback_t callback, void *arg) : schedule the callback of the function "callback" at the date "clock" with parameters "c" and "arg".

Note that arg can be equal to NULL. The event_t returned describe the scheduled function call.

  • void scheduler_delete_callback (call_t *c, event_t *event)

Global functioning of WSNet

Now you have good knowledge of some structures you will have to use, you need to understand how they will be called by the simulator.

At the beginning, the simulator create all of the entities defined in the XML file. For each entity, it will fill the entity_t structure with all the methods defined in the .c file of your module. Then it calls the "init" function of each entity.

Then, the simulator can create all of the nodes. It will create an array of nb_nodes, nb_nodes being the number of nodes indicated in the XML file. Then it will call the "setnode" function of each entity on each node.

At this point, all of the nodes and entities are created. The simulation will be launched by calling the "bootstrap" function of each entity on each node.

At the end of the simulation, the "unsetnode" function of each entity is called on each node. Then, the destroy function of each entity is called.

Note that even if all of the nodes are created at the same time at the beginning of the simulation, you can delay the action of the node by scheduling it at a later time in the bootstrap function (see the Scheduler subsection).

Layer model

The WSNet simulator is based on a layer model. One layer is represented by an entity, or a group of entities, and can have several upper layers and lower layers. In this case, the packet need to be transmitted to all the upper or lower layers, so the packet may sometimes have more than one overhead. This last point can create problems with a layer architecture with several potentials routing paths. For example an architecture 1 layer - 3 layers - 3 layers, can create problems linked to many possible overheads.

To illustrate the layer architecture, here is an example of exchanges between the different layers :


Here we give the code that make you able to to transmit a packet to each upper layer :

 struct nodedata *nodedata = get_node_private_data(c);
 array_t *up = get_entity_bindings_up(c);
 int i = up->size;
 while (i--) {
   call_t c_up = {up->elts[i], c->node, c->entity};
   packet_t *packet_up;
   if (i > 0) {
     packet_up = packet_clone(packet);         
   } else {
     packet_up = packet;
   RX(&c_up, packet_up);

Compiling and installing the new module

Let's take the example of a module named example.c

Compiling the protocol

Copy your file example.c into $HOME/wsnet-module/user_modules/, then move to this directory. Next, modify the content of This file should contain the following entries :

libapplication_example_la_CFLAGS = $(CFLAGS) $(GLIB_FLAGS) -Wall
libapplication_example_la_SOURCES = example.c
libapplication_example_la_LDFLAGS = -module

To compile example.c type the following commands:

./configure --prefix=$HOME/wsnet-module --with-wsnet-dir=/usr/local/wsnet-2.0

The --prefix option represent the directory where modules will be installed, and the --with-wsnet-dir is the WSNet install directory.

Installing the protocol

To install the compiled module, type the following command:

make install

This command will install the module within the directory defined by the configure --prefix option. In our case, the module is installed within the $HOME/wsnet-module/lib/ directory:

ls $HOME/wsnet-module/lib/
> libapplication_example.a


INRIA module creation tutorial