An expedient introduction to Mininet


Mininet

Mininet is a network emulator (no, not a simulator) that can aid the creation of an entire virtual network– replete with hosts, switches, controllers, and links. Mininet primarily serves to bolster research and prototyping in the realm of Software Defined Networking (SDN) as it supports Linux based OpenFlow switches, flexibile routing, custom topologies and much more. And the best part is it’s almost entirely written in Python.

Advantages of Mininet

The advantages of Mininet are many and I’ve directly copied my favourite from the Mininet homepage:

  • Provides a simple and inexpensive network testbed for developing OpenFlow applications
  • Enables complex topology testing, without the need to wire up a physical network
  • Provides a straightforward and extensible Python API for network creation and experimentation
  • Boots faster: seconds instead of minutes
  • Scales larger: hundreds of hosts and switches vs. single digits
  • Provides more bandwidth: typically 2Gbps total bandwidth on modest hardware

I touched upon way too many things (OpenFlow, SDN, emulators, etc.) without adequate explanation in the previous section, but we will get to them soon enough. Also, while we will plumb the depths of SDN and OpenFlow, we will not be discussing how Mininet works under the hood. It builds on something called Linux network namespaces, and to some extent Linux Containers (or LXCs - also what powers Docker). However, to completely discuss these will be the job of another post, some other day.

So what exactly is an Emulator?

Well, an emulator is something which exactly replicates the working of a device, and uses processes or abstractions that are inherently used by the original device. A simulator only models these processes, and tries to model the original device based on some assumptions. Both have their pros and cons and there is no reason to consider one to always be superior than the other.

OpenFlow and SDN

Software Defined Networking relates to being able to control the forwarding plane of the network by instantiating controllers as a central authority, capable of handling and relaying information to switches/routers sitting below it as well as networking applications sitting above it. The controller is able to do this through southbound APIs for the switches and northbound APIs for the business logic/applications. OpenFlow is just a (in fact, the first) standard for SDN. Moreover, OpenFlow allows for the remote handling of a Layer-3 switch’s packet forwarding tables. This allows for dynamic routing by the addition or removal of packet matching rules by the controller. Most networking companies (Corsa, Cisco, Alcatel, Huawei among others) have OpenFlow enabled switches in production. Also, there are a number of OpenFlow controllers available with support from different programming languages, such as Floodlight (Java based) and POX (Python based). A visual diagram of the SDN setup is shown below:

alt text

Our aim for today

So now that we have an idea about what Mininet is, we can write some Python code in Mininet to achieve very basic things, such as emulating an entire network topology. Thus, the goals for today are as follows:

  1. Downloading and installing the Mininet VM
  2. Writing Python code to emulate a Tree network topology
  3. Validating our code and the running of the network using the Mininet CLI

Downloading and installing Mininet

Mininet comes as a ready to use Virtual Machine which is by far the simplest way of getting it running. All one needs is a virtualization software like VMware or VirtualBox (it’s free) and you’re good to go.

  • Download the Mininet VM here
  • Download VirtualBox here

Just double click on the downloaded VM image and it should open up in VirtualBox. Next, click Settings and add a host-only network adapter you can use to log in to the image. After this, start the VM. The username as well as the password are mininet. That’s it - you’re good to go.

Emulating a Tree topology in Mininet

First off, a Tree network topology looks lie this:

alt text

So our goal is to model this network in Mininet. Once you have logged in to the Mininet VM, create a new Python file and call it (say) tree.py.

We will first import all the required modules and libraries:

from mininet.net import Mininet
from mininet.node import Controller
from mininet.cli import CLI
from mininet.log import setLogLevel, info

Next, we will create a function called treeTopo that will house all our code for creating the topology. Here we will first instantiate a Mininet object by passing in a default controller object (Maybe in a later post we can see how to use either Floodlight or POX). Once that is done we will be writing code to add hosts and switches. It is also important to note that since Mininet logs all such additions, we can use it’s inbuilt info function we imported above to print/log out information instead of the print statement. All this code can be seen below:

def treeTopo():
    net = Mininet( controller=Controller )
    
    info( '*** Adding controller\n' )
    net.addController( 'c0' )

    info( '*** Adding hosts\n' )
    h1 = net.addHost( 'h1', ip='10.0.0.1' )
    h2 = net.addHost( 'h2', ip='10.0.0.2' )
    h3 = net.addHost( 'h3', ip='10.0.0.3' )
    h4 = net.addHost( 'h4', ip='10.0.0.4' )
    h5 = net.addHost( 'h5', ip='10.0.0.5' )
    h6 = net.addHost( 'h6', ip='10.0.0.6' )
    h7 = net.addHost( 'h7', ip='10.0.0.7' )
    h8 = net.addHost( 'h8', ip='10.0.0.8' )

    info( '*** Adding switches\n' )
    s1 = net.addSwitch( 's1' )
    s2 = net.addSwitch( 's2' )
    s3 = net.addSwitch( 's3' )
    s4 = net.addSwitch( 's4' )
    s5 = net.addSwitch( 's5' )
    s6 = net.addSwitch( 's6' )
    s7 = net.addSwitch( 's7' )

Now we will create the links, first between the hosts and the switches and then between the switches themselves. I am going to show you that it’s fine to write down each and every link manually or if you’re clever enough, leverage programming tactics to decrease your work. I’ll show the manual approach for creating the links between hosts and switches and the programmatic approach for linking the switches with each other. Here goes:

    info( '*** Creating links\n' )
    net.addLink( h1, s3 )
    net.addLink( h2, s3 )
    net.addLink( h3, s4 )
    net.addLink( h4, s4 )
    net.addLink( h5, s6 )
    net.addLink( h6, s6 )
    net.addLink( h7, s7 )
    net.addLink( h8, s7 )
    
    root = s1
    layer1 = [s2,s5]
    layer2 = [s3,s4,s6,s7]

    for idx,l1 in enumerate(layer1):
        net.addLink( root,l1 )
        net.addLink( l1, layer2[2*idx] )
        net.addLink( l1, layer2[2*idx + 1] )
    

It can be clearly seen that using the power of Python, we were quickly able to create links between the switches, which would have been a painful manual process.

Lastly, we will just start the network and the Mininet CLI and when the process is complete, we will stop the network. We then call the treeTopo() function in main:

    info( '*** Starting network\n')
    net.start()

    info( '*** Running CLI\n' )
    CLI( net )

    info( '*** Stopping network' )
    net.stop()

if __name__ == '__main__':
    setLogLevel( 'info' )
    treeTopo()
    

Moreover, the entire tree.py script looks something like this now:

from mininet.net import Mininet
from mininet.node import Controller
from mininet.cli import CLI
from mininet.log import setLogLevel, info

def treeTopo():
    net = Mininet( controller=Controller )
    
    info( '*** Adding controller\n' )
    net.addController( 'c0' )

    info( '*** Adding hosts\n' )
    h1 = net.addHost( 'h1', ip='10.0.0.1' )
    h2 = net.addHost( 'h2', ip='10.0.0.2' )
    h3 = net.addHost( 'h3', ip='10.0.0.3' )
    h4 = net.addHost( 'h4', ip='10.0.0.4' )
    h5 = net.addHost( 'h5', ip='10.0.0.5' )
    h6 = net.addHost( 'h6', ip='10.0.0.6' )
    h7 = net.addHost( 'h7', ip='10.0.0.7' )
    h8 = net.addHost( 'h8', ip='10.0.0.8' )

    info( '*** Adding switches\n' )
    s1 = net.addSwitch( 's1' )
    s2 = net.addSwitch( 's2' )
    s3 = net.addSwitch( 's3' )
    s4 = net.addSwitch( 's4' )
    s5 = net.addSwitch( 's5' )
    s6 = net.addSwitch( 's6' )
    s7 = net.addSwitch( 's7' )

    info( '*** Creating links\n' )
    net.addLink( h1, s3 )
    net.addLink( h2, s3 )
    net.addLink( h3, s4 )
    net.addLink( h4, s4 )
    net.addLink( h5, s6 )
    net.addLink( h6, s6 )
    net.addLink( h7, s7 )
    net.addLink( h8, s7 )
    
    root = s1
    layer1 = [s2,s5]
    layer2 = [s3,s4,s6,s7]

    for idx,l1 in enumerate(layer1):
        net.addLink( root,l1 )
        net.addLink( l1, layer2[2*idx] )
        net.addLink( l1, layer2[2*idx + 1] )
        
    info( '*** Starting network\n')
    net.start()

    info( '*** Running CLI\n' )
    CLI( net )

    info( '*** Stopping network' )
    net.stop()

if __name__ == '__main__':
    setLogLevel( 'info' )
    treeTopo()
    

Validating our code

Now that our code is complete, we run the topology by typing sudo python tree.py (it is required that you run as root) in the VM terminal. If everything is correct, the code will compile and start up the Mininet CLI. This can be seen in the screenshot below.

alt text

Now we will try the pingall command which will ping all the hosts to see if we have connectivity and if our topology is indeed correctly configured. We do this by typing pingall in the Mininet CLI:

alt text

Success! As a last check we use the net command to see if all the connections are as we inteded. A quick but careful observation of the output shows us that it indeed, is correct.

alt text

We have successfully configured the tree topology in Mininet and met all the objectives. Hopefully this has given you enough of an idea into how useful and powerful Mininet is!

Recapitulating

Mininet is a great tool for research and development for SDN and OpenFlow and with this post we saw how to emulate a network topology and observe its behaviour. In future posts, we will be looking at more involved aspects of Mininet and Software Defined Networking with OpenFlow. Stay tuned and keep being awesome!