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 :doc:`Emulation section ` in the User's Guide. | INET version: ``4.1`` | Source files location: `inet/showcases/emulation/babel `__ 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 :cpp:`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 :ned:`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. .. image:: media/network4.png :align: center :width: 80% The simulation and the real world is split at the wlan Ext interfaces in the hosts. The following figure illustrates the emulation setup: .. figure:: media/setup__.png :width: 90% :align: center Each host has an :ned:`ExtUpperIeee80211Interface`. The interface contains an :ned:`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: .. figure:: media/extinterface.png :width: 50% :align: center 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: .. literalinclude:: ../Setup.sh :language: bash 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: .. literalinclude:: ../Run.sh :language: bash The ``Teardown.sh`` script can be run to destroy the TAP interfaces and the network namespaces when they are not needed anymore: .. literalinclude:: ../Teardown.sh :language: bash Note that commands involving network namespaces (netns) require root privileges. Here is the Ext interface configuration in :download:`omnetpp.ini <../omnetpp.ini>`: .. literalinclude:: ../omnetpp.ini :start-at: ExtUpperIeee80211Interface :end-at: host2 :language: ini 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``: .. literalinclude:: ../omnetpp.ini :start-at: General :end-at: sim-time-limit :emphasize-lines: 3 :language: ini 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): .. literalinclude:: ../omnetpp.ini :start-at: fcsMode :end-at: fcsMode :language: ini Also, for the sake of simplicity, we turn off everything that's not strictly required, such as loopback interfaces and unused protocols: .. literalinclude:: ../omnetpp.ini :start-at: numLoInterfaces :end-at: hasIpv6 :language: ini Results ------- Here is a video of the simulation running: .. video:: media/babel.mp4 :align: center :width: 100% 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]`` and ``host[2]`` - ``host[0]`` can reach ``host[2]`` in one hop (via ``host[1]``) - ``host[0]`` can reach ``host[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: .. figure:: media/babelmessage3.png :align: center :width: 100% 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: :download:`omnetpp.ini <../omnetpp.ini>`, :download:`BabelShowcase.ned <../BabelShowcase.ned>` Discussion ---------- Use `this `__ page in the GitHub issue tracker for commenting on this showcase.