The discrete-event network simulator ns-3 is widely used by both the research and the industry communities to prototype and experiment on networking protocols and systems e.g. Deadline-Aware Datacenter TCP (D2TCP) (Sigcomm'12) and DeTail: Reducing the Flow Completion Time Tail in Datacenter Networks (Sigcomm'12).
ns-3
has been initially designed and built to be used primarily in c++. Although c++ allows ns-3
developers to hook at the bare metal of the simulator system as well as the linux operating-system host π€, it makes the prototyping process relatively slow βπ’ and tedious ππͺ². Recently, ns-3
maintainers proposed to leverage the versatility of python and enable python development on ns-3 to speed up the prototyping cycle π‘.
Developing with python in ns-3
relies on scanning the ns-3 c++ modules and generate their respective python bindings. The generation of python bindings in ns-3
is still a work-in-progress, and it requires some extra effort at the developer side to manually build and successfully mix, match and integrate the required libraries for the scanning process. I never say no to build, and I burned some of my saved energy ββ½ and my late-night candles β³π« getting the ns-3
python-bindings pipeline-generation built. I am shipping a ready-to-use docker image π³ for ns-3 (version 3.26) for python development on my docker hub. Feel free to give it a try! For any modification of the ns-3
c++ API, please issue the command ./waf --apiscan=all
from the ns-3
home project, to generate the corresponding python bindings.
I will be also providing docker images to automate the python bindings generation for the upcoming ns-3 releases (version >= 3.26). I hope you find this useful
Going ahead, we will be setting up our ns-3 docker box on a Linux environment. The attached build-script.sh
to the repository has been tested on a Ubuntu-18.04
machine with the zsh
interpreter, but it should also work fine for the rest of Debian and Ubuntu-based Linux distributions that are supported by Docker Inc.: for more details, please check the list of Linux platforms supported by Docker Inc. Clone the git
repository, and start running the build-script.sh
by issuing the make
command. The build-script
will update the system packages, install docker and pull my ns-3 docker image from the Docker Hub:
$ git clone https://github.com/hameliknaoh/dev-on-ns-3-inside-a-container-using-python.git
$ cd dev-on-ns-3-inside-a-container-using-python/
$ make
To verify that the setup process was successfull, we should be able to have the hamelik/ns3.26libdependencies
docker image listed when the command docker images
is issued:
$ docker imgaes
REPOSITORY TAG IMAGE ID CREATED SIZE
hamelik/ns3.26libdependencies first c53ffa37a8e1 9 months ago 4.1GB
We should be also able to have the ns-allinone-3.26.tar.bz2
tarball archive downloaded from the official ns-3 source, and decompressed to the ns-allinone-3.26
folder.
$ cd dev-on-ns-3-inside-a-container-using-python/
$ ls -a
. build-script.sh ns-allinone-3.26 README.md
.. .git ns-allinone-3.26.tar.bz2 set-up-ns-3-docker-env.sh
To start an ns-3 docker container
for development and API scanning with python, we will be using the hamelik/ns3.26libdependencies
docker image pulled from my personal hub space. We will be issuing the command docker run
and we will be mounting the ns-allinone-3.26
folder as a volume in the container using the -v
flag, under/usr/local/
. Let's call our ns-3 docker container Hello-NS-3.26
:
$ cd dev-on-ns-3-inside-a-container-using-python/
$ docker run -it \
-v `pwd`/ns-allinone-3.26/:/usr/local/ns-allinone-3.26/ \
--name Hello-NS-3.26 hamelik/ns3.26libdependencies:first
The ns-3.26 home directory
is located under:
./dev-on-ns-3-inside-a-container-using-python/ns-allinone-3.26/ns-3.26/
at the host side./usr/local/ns-allinone-3.26/ns-3.26/
at theHello-NS-3.26
docker container side.
Rather than typing the complete full docker run
command, we make use of the Makefile
attached to the project and simply type:
$ make ns-3-container-run
At the container side, navigate under /usr/local/ns-allinone-3.26/ns-3.26/
using the cd
command, and you will be able to list the following items, in particular, the waf
build automation tool:
# cd /usr/local/ns-allinone-3.26/ns-3.26/
# ls -a
. LICENSE build testpy-output waf-tools
.. Makefile doc testpy.supp waf.bat
.lock-waf_linux2_build README examples utils wscript
.waf-1.8.19-b1fc8f7baef51bd2db4c2971909a568d RELEASE_NOTES scratch utils.py wutils.py
AUTHORS VERSION src utils.pyc wutils.pyc
CHANGES.html bindings test.py waf
Fast forward, it is all setted-up now to be able to edit/develop python code on ns-3
at the host side (left side of the following figure) using your favourite code editor (I recommend vscode), and run/debug it interactively at the container side (right side of the following figure) from the terminal.
ns-3
could be configured to be built with a debug
, release
or optimized
profile. In this guide, we will be developing with the debug
profile. From the ns-3.26 home directory
, we get the network simulator ready for developping following these four steps:
# cd /usr/local/ns-allinone-3.26/ns-3.26/
# ./waf clean
'clean' finished successfully (0.191s)
# ./waf configure --build-profile=debug --enable-examples --enable-tests
'configure' finished successfully (2.262s)
Setting top to : /usr/local/ns-allinone-3.26/ns-3.26
Setting out to : /usr/local/ns-allinone-3.26/ns-3.26/build
Checking for 'gcc' (C compiler) : /usr/bin/gcc
Checking for cc version : 4.9.4
Checking for 'g++' (C++ compiler) : /usr/bin/g++
Checking for compilation flag -Wl,--soname=foo support : ok
Checking for program 'python' : /usr/bin/python
Checking for python version : (2, 7, 6, 'final', 0)
python-config : /usr/bin/python-config
Asking python-config for pyembed '--cflags --libs --ldflags' flags : yes
Testing pyembed configuration : yes
Asking python-config for pyext '--cflags --libs --ldflags' flags : yes
Testing pyext configuration : yes
Checking for compilation flag -fvisibility=hidden support : ok
Checking for compilation flag -Wno-array-bounds support : ok
Checking for pybindgen location : ../pybindgen-0.17.0.post57+nga6376f2 (guessed)
Checking for python module 'pybindgen' : 0.17.0.post57+nga6376f2
Checking for pybindgen version : 0.17.0.post57+nga6376f2
Checking for code snippet : yes
Checking for types uint64_t and unsigned long equivalence : no
Checking for code snippet : no
Checking for types uint64_t and unsigned long long equivalence : yes
Checking for the apidefs that can be used for Python bindings : gcc-LP64
Checking for internal GCC cxxabi : complete
Checking for python module 'pygccxml' : 1.0.0
Checking for pygccxml version : 1.0.0
Checking for program 'gccxml' : /usr/bin/gccxml
Checking for gccxml version : 0.9.0
Checking boost includes : headers not found, please provide a --boost-includes argument (see help)
Checking boost includes : headers not found, please provide a --boost-includes argument (see help)
Checking for click location : not found
Checking for program 'pkg-config' : /usr/bin/pkg-config
Checking for 'gtk+-2.0' >= 2.12 : yes
Checking for 'libxml-2.0' >= 2.7 : yes
Checking for type uint128_t : not found
Checking for type __uint128_t : yes
Checking high precision implementation : 128-bit integer (default)
Checking for header stdint.h : yes
Checking for header inttypes.h : yes
Checking for header sys/inttypes.h : not found
Checking for header sys/types.h : yes
Checking for header sys/stat.h : yes
Checking for header dirent.h : yes
Checking for header stdlib.h : yes
Checking for header signal.h : yes
Checking for header pthread.h : yes
Checking for header stdint.h : yes
Checking for header inttypes.h : yes
Checking for header sys/inttypes.h : not found
Checking for library rt : yes
Checking for header sys/ioctl.h : yes
Checking for header net/if.h : yes
Checking for header net/ethernet.h : yes
Checking for header linux/if_tun.h : yes
Checking for header netpacket/packet.h : yes
Checking for NSC location : not found
Checking for 'sqlite3' : yes
Checking for header linux/if_tun.h : yes
Checking for python module 'gtk' : ok
Checking for python module 'goocanvas' : 0.14.1
Checking for python module 'pygraphviz' : 1.2
Checking for program 'sudo' : /usr/bin/sudo
Checking for program 'valgrind' : /usr/bin/valgrind
Checking for 'gsl' : yes
python-config : not found
Checking for compilation flag -Wno-error=deprecated-d... support : ok
Checking for compilation flag -Wno-error=deprecated-d... support : ok
Checking for compilation flag -fstrict-aliasing support : ok
Checking for compilation flag -fstrict-aliasing support : ok
Checking for compilation flag -Wstrict-aliasing support : ok
Checking for compilation flag -Wstrict-aliasing support : ok
Checking for program 'doxygen' : /usr/bin/doxygen
---- Summary of optional NS-3 features:
Build profile : debug
Build directory :
BRITE Integration : not enabled (BRITE not enabled (see option --with-brite))
DES Metrics event collection : not enabled (defaults to disabled)
Emulation FdNetDevice : enabled
Examples : enabled
File descriptor NetDevice : enabled
GNU Scientific Library (GSL) : enabled
Gcrypt library : not enabled (libgcrypt not found: you can use libgcrypt-config to find its location.)
GtkConfigStore : enabled
MPI Support : not enabled (option --enable-mpi not selected)
NS-3 Click Integration : not enabled (nsclick not enabled (see option --with-nsclick))
NS-3 OpenFlow Integration : not enabled (Required boost libraries not found)
Network Simulation Cradle : not enabled (NSC not found (see option --with-nsc))
PlanetLab FdNetDevice : not enabled (PlanetLab operating system not detected (see option --force-planetlab))
PyViz visualizer : enabled
Python API Scanning Support : enabled
Python Bindings : enabled
Real Time Simulator : enabled
SQlite stats data output : enabled
Tap Bridge : enabled
Tap FdNetDevice : enabled
Tests : enabled
Threading Primitives : enabled
Use sudo to set suid bit : not enabled (option --enable-sudo not selected)
XmlIo : enabled
'configure' finished successfully (2.262s)
# ./waf build
'build' finished successfully (7m25.441s)
Waf: Entering directory `/usr/local/ns-allino ne-3.26/ns-3.26/build'
[ 1/2631] Compiling install-ns3-header: ns3/antenna-model.h
[ 2/2631] Compiling install-ns3-header: ns3/isotropic-antenna-model.h
[ 4/2631] Compiling install-ns3-header: ns3/angles.h
[ 5/2631] Compiling install-ns3-header: ns3/parabolic-antenna-model.h
[ 5/2631] Compiling install-ns3-header: ns3/cosine-antenna-model.h
[ 6/2631] Processing command (${PYTHON}): ../bindings/python/ns3modulegen-modular.py ../src/antenna/bindings/modulegen__gcc_LP64.py -> src/antenna/bindings/ns3module.cc src/antenna/bindings/ns3module.h src/antenna/bindings/ns3modulegen.log
[ 7/2631] Compiling install-ns3-header: ns3/aodv-packet.h
[ 8/2631] Compiling install-ns3-header: ns3/aodv-neighbor.h
[ 9/2631] Compiling install-ns3-header: ns3/aodv-rqueue.h
[ 10/2631] Compiling install-ns3-header: ns3/aodv-routing-protocol.h
[ 11/2631] Compiling install-ns3-header: ns3/aodv-rtable.h
[ 12/2631] Compiling install-ns3-header: ns3/aodv-id-cache.h
[ 14/2631] Compiling install-ns3-header: ns3/aodv-dpd.h
[ 14/2631] Compiling install-ns3-header: ns3/aodv-helper.h
[ 15/2631] Processing command (${PYTHON}): ../bindings/python/ns3modulegen-modular.py ../src/aodv/bindings/modulegen__gcc_LP64.py -> src/aodv/bindings/ns3module.cc src/aodv/bindings/ns3module.h src/aodv/bindings/ns3modulegen.log
...
...
[2619/2631] Linking build/bindings/python/ns/point_to_point.so
[2620/2631] Linking build/utils/ns3.26-test-runner-debug
[2622/2631] Compiling src/fd-net-device/helper/encode-decode.cc
[2622/2631] Compiling src/fd-net-device/helper/tap-device-creator.cc
[2623/2631] Compiling src/fd-net-device/helper/creator-utils.cc
[2624/2631] Linking build/src/fd-net-device/ns3.26-tap-device-creator-debug
[2625/2631] Compiling src/fd-net-device/helper/raw-sock-creator.cc
[2626/2631] Compiling src/fd-net-device/helper/encode-decode.cc
[2627/2631] Compiling src/fd-net-device/helper/creator-utils.cc
[2628/2631] Linking build/src/fd-net-device/ns3.26-raw-sock-creator-debug
[2629/2631] Compiling src/tap-bridge/model/tap-creator.cc
[2630/2631] Compiling src/tap-bridge/model/tap-encode-decode.cc
[2631/2631] Linking build/src/tap-bridge/ns3.26-tap-creator-debug
Waf: Leaving directory `/home/ns-allinone-3.26/ns-3.26/build'
Build commands will be stored in build/compile_commands.json
'build' finished successfully (7m25.441s)
Modules built:
antenna aodv applications
bridge buildings config-store
core csma csma-layout
dsdv dsr energy
fd-net-device flow-monitor internet
internet-apps lr-wpan lte
mesh mobility mpi
netanim (no Python) network nix-vector-routing
olsr point-to-point point-to-point-layout
propagation sixlowpan spectrum
stats tap-bridge test (no Python)
topology-read traffic-control uan
virtual-net-device visualizer wave
wifi wimax
Modules not built (see ns-3 tutorial for explanation):
brite click openflow
The ns-3
distribution is initially shipped with three python simulation scripts first.py
, second.py
, and third.py
, that are located under examples/tutorial/
. Let's run the first script that is simulating an echo message exchange between a client and a server.
# cd /usr/local/ns-allinone-3.26/ns-3.26/
# ./waf --pyrun examples/tutorial/first.py
Waf: Entering directory `/usr/local/ns-allinone-3.26/ns-3.26/build'
Waf: Leaving directory `/usr/local/ns-allinone-3.26/ns-3.26/build'
Build commands will be stored in build/compile_commands.json
'build' finished successfully (2.054s)
Modules built:
antenna aodv applications
bridge buildings config-store
core csma csma-layout
dsdv dsr energy
fd-net-device flow-monitor internet
internet-apps lr-wpan lte
mesh mobility mpi
netanim (no Python) network nix-vector-routing
olsr point-to-point point-to-point-layout
propagation sixlowpan spectrum
stats tap-bridge test (no Python)
topology-read traffic-control uan
virtual-net-device visualizer wave
wifi wimax
Modules not built (see ns-3 tutorial for explanation):
brite click openflow
At time 2s client sent 1024 bytes to 10.1.1.2 port 9
At time 2.00369s server received 1024 bytes from 10.1.1.1 port 49153
At time 2.00369s server sent 1024 bytes to 10.1.1.1 port 49153
At time 2.00737s client received 1024 bytes from 10.1.1.2 port 9
To test that the ns-3 c++ api scanning is properly working, issue the command
# ./waf --apiscan=all
The ./waf --apiscan=all
automation tool will be scanning all
the ns-3 modules
Waf: Entering directory `/usr/local/ns-allinone-3.26/ns-3.26/build'
Modules to scan: ['antenna', 'aodv', 'applications', 'bridge', 'buildings', 'config-store',
'core', 'csma', 'csma-layout', 'dsdv', 'dsr', 'energy', 'fd-net-device',
'flow-monitor', 'internet', 'internet-apps', 'lr-wpan', 'lte', 'mesh',
'mobility', 'mpi', 'network', 'nix-vector-routing', 'olsr', 'point-to-point',
'point-to-point-layout', 'propagation', 'sixlowpan', 'spectrum', 'stats',
'tap-bridge', 'topology-read', 'traffic-control', 'uan', 'virtual-net-device',
'visualizer', 'wave', 'wifi', 'wimax']
When waf
is done scanning, a green message will be outputted in the terminal specifying the operation duration as well as the successfully built modules.
Waf: Leaving directory `/usr/local/ns-allinone-3.26/ns-3.26/build'
Build commands will be stored in build/compile_commands.json
'build' finished successfully (19m42.182s)
Modules built:
antenna aodv applications
bridge buildings config-store
core csma csma-layout
dsdv dsr energy
fd-net-device flow-monitor internet
internet-apps lr-wpan lte
mesh mobility mpi
netanim (no Python) network nix-vector-routing
olsr point-to-point point-to-point-layout
propagation sixlowpan spectrum
stats tap-bridge test (no Python)
topology-read traffic-control uan
virtual-net-device visualizer wave
wifi wimax
Modules not built (see ns-3 tutorial for explanation):
brite click openflow
If a specific module with the name my_module
has only been changed, it can be scanned as follows: this will obviously help to cut down the scanning process execution time.
# ./waf --apiscan=my_module
It is completely possible to detach and re-attach to the Hello-NS-3.26
docker container at any time:
- To detach from the
Hello-NS-3.26
docker container, you can use the shortcutctrl+p ctrl+q
- To re-attach, you can issue the command
docker attach Hello-NS-3.26
ormake ns-3-container-attach
- To kill the docker container, detach first and then issue the command
docker kill Hello-NS-3.26
ormake ns-3-container-kill
- To remove the container, you can issue the command
docker rm Hello-NS-3.26
ormake ns-3-container-rm
- To clean the
ns-3-allinone
project, runmake clean