Creating a new module in ns-3

At times people create new functionality for ns-3 that takes the shape of module, that is, multiple files that implement various classes. If you’re looking for information on how to put together a new ns-3 module, you’ve come to the right place. I’ll walk you through a sequence of steps toward setting up your installation to build and recognize your module.

Step 1 – Create a directory for your new module

I’ll start the assumption that you are working with a tarball distribution – if you’re working with a mercurial repo, you’ll will know how to change the path names in this discussion. Say you want to create a new module for ns-3 and that you will want it to live in the contrib directory. This means your code will be in a path such as:

~/tarballs/ns-allinone-3.9/ns-3.9/src/contrib

For the sake of discussion, say your module is called “awesome”. Let’s further assume that it will live in a directory called:

~/tarballs/ns-allinone-3.9/ns-3.9/src/contrib/awesome

This is not just an assumption for the sake of discussion: it’s a requirement. The directory must have the same name as the module.

Step 2 – Tweak the build system

Before you write any actual code, let’s tweak the waf build scripts to take care of your new module. In a text editor, open file:

~tarballs/ns-allinone-3.9/ns-3.9/src/wscript

In this file, you will see a list of all the modules that the build system is already aware of. It’s appropriately called “all_modules”, and it will look like this:

all_modules = (
    'core',
    'common',
    'simulator',
    'contrib',
    'node',
    'internet-stack',
    'devices/point-to-point',
    ...
    'mpi',
    'contrib/topology-read',
    'contrib/energy',
    )

Add your new module to the list (perhaps at the end), so that it reads:

all_modules = (
    'core',
    'common',
    'simulator',
    'contrib',
    'node',
    'internet-stack',
    'devices/point-to-point',
    ...
    'mpi',
    'contrib/topology-read',
    'contrib/energy',
    'contrib/awesome',
    )

Next, change to the directory where your module lives. Following the pattern in this example, that would be:

~/tarballs/ns-allinone-3.9/ns-3.9/src/contrib/awesome

Now, create a new file called wscript in this directory. This file will state for the build system a complete list of your implementation (.cc) and header files (.h).

## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-

def build(bld):
    obj = bld.create_ns3_module('dcf', ['node'])
    obj.source = [
          'one_of_your.cc',
          'another_of_your.cc',
          ...
          ]
    headers = bld.new_task_gen('ns3header')
    headers.module = 'dcf'
    headers.source = [
         'one_of_your.h',
         'another_of_your.h',
         ...
    ]

Step 3 – Implement your module

By now, you have set everything up for the build system to create code for your new module. You might already have started on the development of the .cc and .h files for your module, but otherwise, you ready to start working on them. There’s more about creating a new module that I’ll address in a different post (I’ll come back to drop a hyperlink here when that is ready). For now, suffice to say that you’ll fall into the classic iterative pattern of software development: design, code, compile, run, and debug, repeating each of these steps as needed.

Remember that to compile, you will change to the directory at the root of your ns-3 distribution, which in our example has been:

~/tarballs/ns-allinone-3.9/ns-3.9/

To build in your new module, you do:

./waf build

If all goes well and your code compiled flawlessly, you can check out the fruits of your labor. Take a look at:

~tarballs/ns-allinone-3.9/ns-3.9/build/debug/ns3

You will discover that this directory contains a file called awesome-module.h, which corresponds directly to your new module. This is an aggregator header file, that is, a single header file which end-user C++ programs must include to use all the features implemented in your module. (The aggregator stands in for possibly multiple header files in your module.) These end-user scripts will be able to use your module after one single #include, such as:

#include “ns3/awesome-module.h”

Note that the ns3/ part in the path to your include refers to the directory under:

~tarballs/ns-allinone-3.9/ns-3.9/build/

which contains all the headers for all the modules in your installation. Depending on your particular configuration, this directory may be

~tarballs/ns-allinone-3.9/ns-3.9/build/debug/ns3
or
~tarballs/ns-allinone-3.9/ns-3.9/build/optimized/ns3

Step 4 – Create examples using your module

Finally, once you’ve tested and debugged your module, remember to be kind to the community and to leave some working code that demonstrates how one can use your work. Consider creating a directory such as:

~tarballs/ns-allinone-3.9/ns-3.9/examples/awesome/

which should contain one or more examples of how to use your module.

One thought on “Creating a new module in ns-3”

Comments are closed.