Testing a Linux Routing Daemon in a Simulated Environment¶
Goals¶
Testing routing protocols with simulation is often easier than building a test setup in the real world. INET’s emulation features make it possible to use a real-world routing protocol implementation in a simulated environment, where the simulated environment and multiple instances of the real-world routing protocol implementation can run on the same computer.
This showcase demonstrates such a test scenario with the Linux implementation of the Babel routing protocol (Babel daemon). We’ll run a simulation of a mobile ad hoc network, where mobility and wireless connectivity will be simulated using INET, and the routes will be managed by multiple instances of the Babel daemon.
Note that the emulation example only runs on Linux. For a comprehensive understanding of emulation in INET, read the Emulation section in the User’s Guide.
4.1
The Model¶
Babel is a reactive distance-vector routing protocol, similar to AODV or DSDV.
It is a robust and efficient routing protocol, suitable for both wired networks
and wireless mesh networks.
It works over IPv4/IPv6 and UDP.
The protocol’s reference implementation is available for Linux as the Babel daemon
(babeld
).
Note
The Babel daemon can be installed in Ubuntu and derivates with the following command:
sudo apt install babeld
We’ll use INET’s emulation support, namely Ext interfaces and RealTimeScheduler
,
to interface the simulation with services running on the host OS.
We test the Babel routing protocol in a simulated scenario. We build a wireless ad hoc network, where one of the hosts pings another. The position and movement of the nodes, and the physical medium carrying the wireless signals between them are simulated. The Ping requests are generated by a real Ping application, the Ping replies by the real ICMP protocol, and the routing protocol messages come from isolated instances of the real Babel daemon, all running on the host OS. The protocol instances are separated by running them in network namespaces on the host OS (network namespaces contain a complete virtualized network protocol stack, independent from the real protocol stack in the host OS). Each namespace has its IPv4 routing table that is managed by a Babel daemon instance.
Configuration¶
The network contains one stationary and two mobile AdhocHost’s. The mobile hosts
are host[0]
and host[2]
; they are configured to move around in circles, going in
and out of communication range with each other and the stationary host, host[1]
.
The Babel daemons will update the routes as connectivity changes between the three hosts.
The network is shown on the following image; the communication ranges are indicated with
blue circles, and the green movement trail circles show the path of the nodes.
The simulation and the real world is split at the wlan Ext interfaces in the hosts. The following figure illustrates the emulation setup:
Each host has an ExtUpperIeee80211Interface. The interface contains an ExtEthernetTapDevice module that has a corresponding TAP device created in the host OS. The 802.11 radio, MAC and LLC are simulated; packets enter and exit the TAP device above the LLC:
In the host OS, we set up three network namespaces for the three hosts so that the
babeld
instances can run isolated from each other. Each network namespace has a
TAP device, and an IPv4 routing table. We use a real Ping application in host0
to ping host2
. The Ping response is generated by the ICMP protocol in the
host2
network namespace.
Three shell scripts in showcase’s folder configure and control the
emulation in the host OS: Setup.sh
, Run.sh
and Teardown.sh
.
Setup.sh
needs to be run first to create the network namespaces and the TAP
devices for the three hosts. It also brings up the TAP interfaces, and assigns
IP addresses to them:
# create network namespaces
sudo ip netns add host0
sudo ip netns add host1
sudo ip netns add host2
# create TAP interfaces
sudo ip netns exec host0 ip tuntap add mode tap dev tap0
sudo ip netns exec host1 ip tuntap add mode tap dev tap1
sudo ip netns exec host2 ip tuntap add mode tap dev tap2
# bring up TAP interfaces
sudo ip netns exec host0 ip link set dev tap0 up
sudo ip netns exec host1 ip link set dev tap1 up
sudo ip netns exec host2 ip link set dev tap2 up
# assign IP addresses to interface
sudo ip netns exec host0 ip addr add 192.168.2.1/32 dev tap0
sudo ip netns exec host1 ip addr add 192.168.3.1/32 dev tap1
sudo ip netns exec host2 ip addr add 192.168.4.1/32 dev tap2
The script assigns the following IP addresses:
host0 |
192.168.2.1 |
host1 |
192.168.3.1 |
host2 |
192.168.4.1 |
The TAP devices are assigned random MAC addresses by the host OS when they are created.
Run.sh
runs the emulation example; it starts the babeld
instances, runs a
ping
command in host0
’s network namespace each second, and opens the simulation in
qtenv. The user is expected to run the simulation in express mode. After qtenv is
closed, the script stops the Ping loop and the babeld
instances:
# start babel routing daemons
sudo ip netns exec host0 babeld -I babel0.pid -S babel-state0 -r -w -h 2 -M 0 -C 'reflect-kernel-metric true' -C 'interface tap0 channel 1 link-quality false' &
sudo ip netns exec host1 babeld -I babel1.pid -S babel-state1 -r -w -h 2 -M 0 -C 'reflect-kernel-metric true' -C 'interface tap1 channel 1 link-quality false' &
sudo ip netns exec host2 babeld -I babel2.pid -S babel-state2 -r -w -h 2 -M 0 -C 'reflect-kernel-metric true' -C 'interface tap2 channel 1 link-quality false' &
# start ping loop to avoid exiting early and to wait for the simulation to start
sudo ip netns exec host0 bash -c 'while ! ping 192.168.4.1; do sleep 1; done' &
# start simulation and wait for the user to exit
inet
# stop ping loop
ps -fe | grep -v awk | awk '/ping 192.168.4.1/ {print $2}' | xargs sudo kill
# stop babel routing deamons
sudo killall babeld
The Teardown.sh
script can be run to destroy
the TAP interfaces and the network namespaces when they are not needed anymore:
# destroy TAP interfaces
sudo ip netns exec host0 ip tuntap del mode tap dev tap0
sudo ip netns exec host1 ip tuntap del mode tap dev tap1
sudo ip netns exec host2 ip tuntap del mode tap dev tap2
# destroy network namespaces
sudo ip netns del host0
sudo ip netns del host1
sudo ip netns del host2
Note that commands involving network namespaces (netns) require root privileges.
Here is the Ext interface configuration in omnetpp.ini
:
*.host[*].wlan[0].typename = "ExtUpperIeee80211Interface"
*.host[*].wlan[0].copyConfiguration = "copyFromExt"
*.host[0].wlan[0].device = "tap0"
*.host[0].wlan[0].namespace = "host0"
*.host[1].wlan[0].device = "tap1"
*.host[1].wlan[0].namespace = "host1"
*.host[2].wlan[0].device = "tap2"
*.host[2].wlan[0].namespace = "host2"
For each host, the configuration selects the corresponding TAP interface from the network namespaces of the host OS, and copies its configuration, such as assigned IP address and MAC address. Having matching addresses of the corresponding simulated and real network interface parts is important because packets will contain and be handled according to these addresses (the MAC might silently drop packets if the addresses don’t match).
It is also important to ensure synchronization between the host OS and the simulation
with RealTimeScheduler
:
[General]
network = BabelShowcase
scheduler-class = "inet::RealTimeScheduler"
sim-time-limit = 3600s
For compatibility with the host OS’s babeld
and ping
applications, the FCS mode
in the hosts’ MAC module is configured to compute the FCS (as opposed to assuming
it to be correct):
*.*.wlan[*].mac.fcsMode = "computed"
Also, for the sake of simplicity, we turn off everything that’s not strictly required, such as loopback interfaces and unused protocols:
*.*.numLoInterfaces = 0
*.*.hasTcp = false
*.*.hasUdp = false
*.*.hasIpv4 = false
*.*.hasIpv6 = false
Results¶
Here is a video of the simulation running:
The simulation is shown running in qtenv on the left. The first three terminals on the right display the routing tables of the three hosts in the three network namespaces; the fourth terminal displays the Ping output.
Successful link-layer transmissions are visualized with arrows; green for Babel messages, and red for Ping.
At first, the routing tables are empty. When the nodes move into communication range
with each other, the babel messages can be exchanged, and each babeld
instance
adds routes to its routing table. The following route topologies occur between
host[0]
and host[2]
during the simulation:
There is no connectivity between
host[0]
andhost[2]
host[0]
can reachhost[2]
in one hop (viahost[1]
)host[0]
can reachhost[2]
directly
As the connectivity changes, the babel protocols adapts the routes. Note that the route metric is 256/hop (256 when the address is reachable in one hop; 512 when two hops). The metric is a very large number when unreachable.
The routes take a few seconds (and several babel message exchanges) to form. They also expire after some time when there is no connectivity.
A Babel message opened in Wireshark is shown on the following image.
It is sent by host[0]
at the beginning of the simulation when the route
between host[0]
and host[2]
forms for the first time:
This Babel message broadcasts a route; it contains several type-length-value
elements (TLVs). The nh
and update
messages indicate that 192.168.4.1
(host2
) can be reached via 192.168.3.1 (host1
), in one hop (metric=256).
Sources: omnetpp.ini
, BabelShowcase.ned
Try It Yourself¶
First, install INET and OMNeT++. Then, start the IDE by typing
omnetpp
, import the INET project into the IDE, then navigate to the
inet/showcases/emulation/babel
folder in the Project Explorer. There, you can view
and edit the showcase files, run simulations, and analyze results.
Currently, opp_env-based installation is not available for the emulation showcases.