Developer Guide¶
This section details some essential points to contribute to the code base. Don’t hesitate to ask for advice on the mailing list, to report bugs as Github issues and to contribute through Github pull requests.
Setting up the development environment¶
To develop a new feature, you have to install IPMininet from source in development mode.
First get the source code of your fork:
$ git clone <your-fork-url>
$ cd ipmininet
Then, install your version of IPMininet in development mode. If you have pip above 18.1, execute:
$ sudo pip -e install .
If you have an older version of pip, use:
$ sudo pip -e install --process-dependency-links .
Finally, you can install all the daemons:
$ sudo python -m ipmininet.install -af
Understanding IPMininet workflow¶
The following code creates, starts and stops a network:
from ipmininet.ipnet import IPNet
from ipmininet.cli import IPCLI
from ipmininet.iptopo import IPTopo
class MyTopology(IPTopo):
# [...]
topo = MyTopology() # Step 1
net = IPNet(topo=topo) # Steps 2 to 5
try:
net.start() # Steps 6 to 8
finally:
net.stop() # Step 9
During the execution of this code, IPMininet goes through the following steps (detailed in the following sections):
- Instantiation of the topology and application of the overlays
- Instantiation of all the devices classes
- Instantiation of the daemons
- Addressing
- Call of the post_build method
- Finalization and validation of daemon configurations
- Start of daemons
- Insertion of the default routes
- Cleanup of the network
1. Instantiation of the topology and application of the overlays¶
The instantiation of the Topology triggers a call to its
build()
method. This method is where users
define the topology: switches, routers, links, hosts,… But at that time,
every node is actually a node name, not instances of Switches, Routers,
IPHosts,…
The node and link options are stored in the IPTopo
object and a instance of mininet.topo.MultiGraph
stores the
interconnections between nodes.
At the end of the build method, overlays are applied
(ipmininet.overlay.Overlay.apply()
) and checked for consistency
(ipmininet.overlay.Overlay.check_consistency()
).
2. Instantiation of all the devices classes¶
Each device class (e.g., routers or hosts) is actually instantiated based
on the graph and the parameters stored in the IPTopo
instance (in ipmininet.ipnet.IPNet.buildFromTopo()
). From this point, a
network namespace is created for each device with interfaces linking to the
other namespaces as defined in the topology.
It becomes possible to execute commands on a given device.
3. Instantiation of the daemons¶
When instantiating each router and each host, their daemons are also instantiated and options parsed. However the daemon configurations are not built yet.
3. Addressing¶
After creating all the devices and their interfaces,
build()
create one
BroadcastDomain
by IP broadcast domain. That is,
two router or host interfaces belong to the same BroadcastDomain if they are
directly connected or indirectly connected through only switches or hubs.
IPMIninet then allocates the same IP prefix on interfaces in the same IP broadcast domain. At the end of this step, every interface has its IPv4 and/or IPv6 addresses assigned (if auto-allocation was not disabled).
5. Call of the post_build method¶
Now, all the devices are created and that they have their IP addresses
assigned. Users may need this information before adding other elements to
the network like IPv6 Segment Routing rules
(see Using IPv6 Segment Routing).
Therefore the method post_build()
is called.
6. Finalization and validation of the daemon configurations¶
In each router and each host, their daemon configurations are
built (through each daemon’s
build()
method).
Then the built configuration is used to fill in the templates and create the
actual configuration files of each daemons (in the
render()
method).
When all configurations are built, the configuration is checked by running
the dry run command specified by the
dry_run()
property of each deamon.
If one of the dry runs fails, the network starting is aborted.
7. Start of the daemons¶
From this point, all the daemon configuration files are generated and they
were checked. Thus, the next step is to start each daemon in its respective
network namespace. The command line used to run the daemon is specified by the
startup_line()
property.
8. Insertion of the default routes¶
For each host, a default route is added to one of the router in the same IP broadcast domain. This behavior is disabled if a default route was harcoded in the options or if router advertisements are enabled in the IP broadcast domain.
9. Cleanup of the network¶
This cleans up all the network namespaces defined for the devices as well as
killing all the daemon processes started. By default, the configuration files
are removed (except when the ipmininet.DEBUG_FLAG
is set to True
).
Running the tests¶
The pytest framework is used for the test suite and are integrated within setuptools. Currently the suite has end-to-end tests that check if the daemons work as expected. Therefore, the tests require an operating environment, i.e. daemons have to be installed and must be in PATH.
To run the whole test suite go the top level directory and run:
sudo pytest
You can also run a single test by passing options to pytest:
sudo pytest ipmininet/tests/test_sshd.py --fulltrace
Building the documentation¶
First, you have to install the requirements to build the project. When at the root of the documentation, run:
pip install -r requirements.txt
Then you can generate the html documentation
in the folder docs/_build/html/
with:
make html
The examples in the documentation can also be tested when changing the code base with the following command:
sudo make doctest
Adding a new example¶
When adding a new example of topology to IPMininet, you have to perform the following tasks:
- Create a new
IPTopo
subclass in the folderipmininet/examples/
. - Add the new class to the dictionary
TOPOS
ofipmininet/examples/__main__.py
. - Document its layout in the
build()
method docstring. - Document the example in
ipmininet/examples/README.md
. - Add a test to check the correctness of the example.
Adding a new daemon¶
When adding a new daemon to IPMininet, you have to perform the following tasks:
- Create a new mako template
in the folder
ipmininet/router/config/templates/
oripmininet/host/config/templates/
for the daemon configuration. - Create a new
RouterDaemon
orHostDaemon
subclass in the folderipmininet/router/config/
oripmininet/host/config/
. The following things are required in this new subclass:- Set the class variable
NAME
with a unique name. - Set the class variable
KILL_PATTERNS
that lists all the process names that have to be cleaned if a user uses the cleaning command in IPMininet network cleaning. - Extend the property
startup_line
that gives the command line to launch the daemon. - Extend the property
dry_run
that gives the command line to check the generated configuration. - Extend the method
set_defaults()
to set default configuration values and document them all in the method docstring. - Extend the method
build()
to set the ConfigDict object that will be fed to the template. - Declare the daemon and its helper classes
in
ipmininet/router/config/__init__.py
oripmininet/host/config/__init__.py
.
- Set the class variable
- Add at least one example for the users (see Adding a new example).
- Implement the tests to prove the correct configuration of the daemon.
- Update the setup of IPMininet to install the new daemon by updating
ipmininet/install/__main__.py
andipmininet/install/install.py
. - Document the daemon and its configuration options
in the sphinx documentation in
docs/daemons.rst
.
Adding a new overlay¶
An overlay is a way to change options of multiple nodes or links in a single
code. For instance, defining an AS
object
will add the defined as number in each node declared in the AS.
When adding a new overlay to IPMininet, you have to perform the following tasks:
Create a new
Overlay
subclass in the most appropriate file. For instance, BGP overlays likeAS
are in the BGP daemon file. The following methods are potentially useful to override in this new subclass:-
Overlay.
apply
(topo: IPTopo) Apply the Overlay properties to the given topology
-
Overlay.
check_consistency
(topo: IPTopo) → bool Check that this overlay is consistent
-
Add the new subclass in the dictionary
OVERLAYS
of classIPTopo
. This enables users to useself.addX()
in the build method of their topology subclass withX
being the name of your new overlay.Add at least one example for the users (see Adding a new example).
Implement the tests to prove the correctness of the overlay.
Document the overlay and its configuration options in the sphinx documentation.