DESERT 3.5.1
|
The DESERT underwater framework is an extension of ns-miracle, thus it inherits its modular structure and can directly use all the modules of such framework. Each DESERT module extends from the ns-miracle class Module, which in turn extends from the class PlugIn. They provide basic APIs to (i) send packets to upper/lower layers, (ii) communicate via crosslayer messages with other layers of the stack and (iii) configure the layer via tcl script (command and bind).
The folder structure is composed by two main folders: DESERT_Framework and DESERT_Addons. Inside the former, you find all the modules organized according to the ISO/OSI stack and the installer folder. While the latter contains external modules which doesn't necessarily fit inside the ISO/OSI stack and/or the DESERT core.
In this section we describe how to write a basic DESERT tcl script, following the structure of the tcl found in DESERT/samples/desert_samples/test_uwcbr.tcl
. An empty tcl script skeleton can be found inside DESERT/samples/desert_samples/ExampleSekelton.tcl
It is a good practice to start your script with a brief description and a simple draw of the simulated network topology:
The first thing to do in order to have a working script, is to import the libraries. Note that the order matters and is often a cause of errors. You first need to import the ns-miracle libraries in the following order:
Afterwards you can import DESERT libraries you need (in order).
In order to configure your simulation, some options and variables may be needed. A common approach is to use an associative array called. These options may be hardcoded or given to the simulation as bash parameters.
Common simulation options are listed below
Once you have all the needed libraries and options, you need to initialize the ns-miracle simulator and set the random number generator.
Next there are the binding of the modules. Here you can set globally the initialization values of the binded variables.
Now you are ready to define a tcl procedure (function) that allows you to create as many different kind of nodes in the network. Inside this procedure, you need to create a ns-miracle node and add the modules you need (the whole protocol stack) and configure them. Optionally you can initialize and set the node position.
You can have as many procedures you want. Typically there is a specific procedure for the sink node (a node which only receives packets). Finally, to actually create the nodes you need to call the procedure. Suppose to have $opt(nn)
nodes in the network, you can do:
Once you created the nodes you need to connect them, setup the routes and fill the arp tables.
Finally you need to start and stop the modules and the simulation.
Optionally, it is good practice to add a finish procedure where display the simulation settings and compute some statistics.
In this section we describe how to add a new module in the DESERT core (i.e., into the DESERT_Framework/DESERT directory.) As an example we present the creation of a new module (i.e., a library containing a new DESERT module) named uwcool_phy
. The procedure to create a new module is described in the following.
The folder structure aims to follow ISO/OSI structure. First of all, identify where your module can be logically placed and give it a name, in this case, our new uwcool_phy
physical layer module should stay inside DESERT_Framework/DESERT/physical
folder, therefore you need to cd to that directory and create a folder named uwcool_phy
. This folder will contain your new library.
Create two files called uwcoolphy.h
and uwcoolphy.cpp
files containing your class definition UwCoolPhy
. For this class to work, some types of binding are necessary. Moreover you will need to create the following files:
initlib.cpp
,Makefile.am
,uwcoolphy-default.tcl
.In order to use your class with tcl, in the cpp file you always need to create a static class that derives from TclClass
and gives the name that will be used from tcl to create and bind an object of that module. In our example it would be done via the following code:
Then we need to link class parameters to tcl variables, this is usually done in the cpp constructor, using the bind()
function. This function take as input a string representing a tcl variable which is bound to the second input, which represents a cpp class parameter.
The initlib.cpp
file make the connection between the cpp library of your module and the tcl representing your scenario under simulation/emulation. You need to define an extern variable representing an EmbeddedTcl object, which has a specific name structure: <ModuleNameInCamelCase><TclCode>
. You need also to define a function with fixed naming, which is the name of your module with the first capital letter and _Init
suffix. Following our example, your initlib.cc
will look like this:
All bound variables need to be initialized to a default value in the uwcoolphy-defaults.tcl
file. An example of it would be
Finally, to compile your module, you need to fill the Makefile.am
file:
libuwcoolphy
.libuwcool_phy_la_SOURCES
), which should contain only the cpp files located in the uwcool_phy
folder.CPPFLAGS
, LDFLAGS
and LIBADD
where needed.uwcool-phy-default.tcl
.Your Makefile.am
should look like this:
DESERT compilation and linking is based on autotools, hence to add a new library you need to modify the top-level DESERT_Framework/DESERT/Makefile.am
and DESERT_Framework/DESERT/configure.ac
files as follows:
Makefile.am
: we need to add our folder to the subdirectories list (SUBDIRS) using \ as a separatorconfigure.ac
: we need to add our new folder to the CPPFLAGS and tell autoconf (AC_CONFIG_FILES) where the new internal Makefile isOnce everything is ready, we need to reinstall DESERT to properly add the new module.
Note: After the module is installed, we can recompile it without reinstalling everything. In our case, we would need to do the following:
Finally, inside a tcl script we can use our module by:
To set the parameters and instantiate the object we can write
To enable the communciation between the cpp class and the tcl script we need to overwrite the command method, for example to get and set parameters of a module object. It must be declared in this way, in your module class (uwcoolphy.h
)
And then it should be defined in this way (inside uwcoolphy.cpp
)
NOTE: This is a new feature (version >= 3.6). By now only the following modules implement it:
All the other modules use the ns-way of logging: You need to define a
debug_
parameter on your module and bind it to tcl inside the constructor (see the previous section). Every time you want to print a log message, then you need to check if debug parameter is set and print to console your message.
Each DESERT module inherits a static logger parameter, shared among all the modules in a simulation istance. It lets you specify the level of logging messages you want. There are three possible values:
ERROR: only error messages will be generated. INFO : general info about the algorithms running and also ERROR messages. DEBUG: details that allow to understand the execution flow plus both ERROR and INFO messages are shown.
In particular, it gives you the method printOnLog
, defined as follows:
This method takes three parameter: (i) the log level of the message, (ii) the name of the module printing the message and (iii) a string representing the log message.
As an example, suppose you have a method to handle packets reception that you would like to track, you can do it as follows:
To enable and configure the log messages in your simulation, you can use the following commands:
Remember that all the modules in a given simulation, share the same instance of the logger, meaning, that the log_level
and log_file
can be set just once. For instance, suppose, you have a tcl file, with one transmitting node and one sink node, you can set the logger for the sink physical layer only as follows:
It will print all the coolphy
log messages inside a file called log_output.txt
. Each message has an id
associated with it, which is the ns id of the node and is incremental set, e.g., the first node created will have id
0, the second id
1 and so on.
Note: You can find a complete example on how to use the logging system inside DESERT/samples/desert_samples/logger/
folder.
In the case your module needs its own packet header, a few things need to be performed:
Define a header struct, for example hdr_uwmyprotocol
inside a file myproto-hdr.h
with your parameters plus the offset field required by the packet header manager:
To simplify the access of your header from the packet class, at the beginning of the source file where your header is defined you can define the following macro
Just after the macro, at the beginning of the file, you need to define a new packet type with
extern packet_t PT_MYPACKET;
Inside initlib.cpp you need to
init
function (before the load
function call), using the same name of the externFinally, inside the *-default.tcl you need to add the packet to the packet manager, with
This last step is really important to have the right memory allocation done. Missing it could lead to unpredictable behavior, usually really hard to troubleshoot.
In this section we describe how to add a new module as a DESERT addon. An addon, is an external autotools project that depends on DESERT, ns-miracle and, in some cases, WOSS or even other addons, so we don’t need to modify the DESERT toplevel Makefile.am
and configure.ac
. We need to create just the addon internal Makefile.am
and a dedicated configure.ac
with m4
folder to resolve the dependencies. The complete procedure is described in the following.
Inside the DESERT_Addons
folder, create your addon folder, say cool-addon
. Inside that folder, create the basic files for a properly cpp module, i.e., cool-addon.h
and cool-addon.cpp
and the initlib.cpp
as well.
Similarly to what you did for the adding a module, your initlib.cpp
will look like
To make the addon compilable and complete, we also need:
Makefile.am
,configure.ac
config file,cool-addon-init.tcl
,autogen.sh
script,m4
folderThe Makefile.am
can be taken from another addon or module and modified according to your addond needs, similarly to what what we did for a module. Just note that in case of a WOSS dependent addon, it is better to take the Makefile.am
from another WOSS-based addon, such as wossgmmob3D
or wossgroupmob3D
. Similarly, in case your addon is based on another existing addon, take it from uwswarm_control
or ms2c_evologics_lowlev
addons.
Also for the configure.ac
you take one from another addon and copy into your folder. You just need to modify the AC_INIT
with the name of your addon. Also in this case if you need WOSS functionalities take it from a WOSS-based addon.
The autogen.sh
file is needed to compile your addon and can be copied from any other addon and doesn't need any modification.
Add all the variables that you have binded in your addon class inside the cool-addon-init.tcl
files as youd did for the module.
The m4
folder contains the desert.m4
file and the desertAddon.m4
and woss.m4
files if the addon depend from another addon or woss. Also in this case, it is easier to copy from another addon and modify the dependencies wee ned for our addon. Those are directories listed in dir
and lib
portion of the given m4
file.
Finally, to have your addon visible during installation, modify the installation file DESERT_Framework/.addon.list
adding the name of your addon folder.
NOTE: When you see a pathname preceded by three dots, this refers to a well-known but unspecified top-level directory. The top-level directory is context-dependent, but almost always refers to top-level DESERT source directory. For example,
.../DESERT_Underwater/DESERT_Framework/Installer/installDESERT_LOCAL.sh
refers to theinstallDESERT_LOCAL.sh
file located in the architecture branch of a DESERT framework source tree. The actual path might be something like/home/foo/DESERT_Underwater/DESERT_Framework/Installer/installDESERT_LOCAL.sh
.
First of all, enter the installation folder:
Now, create a new script. We suggest to copy an existing installation script (e.g. installDESERT_LOCAL.sh
):
Please note the <your-custom-installation-target>
label: this will be the same parameter you will pas later as an option to the installation script when indicating which installation-target to choose. We remark that these steps are very easy but also very important, since the only way to call the correct installation script for <your-custom-installation-target>
is that the script installDESERT_<your-custom-installation-target>.sh
exists in the folder .../DESERT_Underwater/DESERT_Framework/Installation/
Let us now have a deeper look at the script. We focus first on the main block:
Notice the host directive. This tells the installation script to compile the libraries for the current host. If you need to modify this script to cross-compile for a different target, substitute all lines with the following ones:
With these changes we instructed the installer to compile some modules only for the host, some for both the host and the target and the remaining ones only for the target (target directive). This step is crucial, because some libraries must be compiled for the host, in order to correctly cross-compile DESERT and its addons for <your-custom-installation-target>
.
WARNING: be careful NOT TO CONFUSE the directive "target" with "<tt><your-custom-installation-target></tt>". The former is just a directive to the <tt>handle_package</tt> function of the installation script.
We remark that you need the TOOLCHAIN of <your-custom-installation-target>
in order to correctly complete the installation.