Tuesday, February 23, 2016

Emulating Networks with Routers using Mininet

Basic setup and the simple usages of Mininet emulator is described in two previous blog posts which are given in the references section of this article. In this blog post, I'm hoping to write more examples coving the usage of Linux routers on a Mininet emulation. Since having multiple IP domains within the emulation makes it complicated to explain each interface, I decided to use some diagrams. Let's start.


Simple network with a router and two hosts

The above diagram shows our first network. We have a router and two hosts connected to it directly. IP addresses assigned to each interface is clearly defined there. Let's implement that network using a python script as follows.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#!/usr/bin/python

from mininet.topo import Topo
from mininet.net import Mininet
from mininet.node import Node
from mininet.log import setLogLevel, info
from mininet.cli import CLI

class LinuxRouter( Node ):
    "A Node with IP forwarding enabled."

    def config( self, **params ):
        super( LinuxRouter, self).config( **params )
        # Enable forwarding on the router
        self.cmd( 'sysctl net.ipv4.ip_forward=1' )

    def terminate( self ):
        self.cmd( 'sysctl net.ipv4.ip_forward=0' )
        super( LinuxRouter, self ).terminate()


class NetworkTopo( Topo ):
    "A LinuxRouter connecting three IP subnets"

    def build( self, **_opts ):

        defaultIP = '10.0.1.1/24'  # IP address for r0-eth1
        router = self.addNode( 'r0', cls=LinuxRouter, ip=defaultIP )

        h1 = self.addHost( 'h1', ip='10.0.1.2/24', defaultRoute='via 10.0.1.1' )
        h2 = self.addHost( 'h2', ip='10.0.2.2/24', defaultRoute='via 10.0.2.1' )

        self.addLink( h1, router, intfName2='r0-eth1', params2={ 'ip' : '10.0.1.1/24' } )
        self.addLink( h2, router, intfName2='r0-eth2', params2={ 'ip' : '10.0.2.1/24' } )


def run():
    "Test linux router"
    topo = NetworkTopo()
    net = Mininet( topo=topo )  # controller is used by s1-s3
    net.start()
    info( '*** Routing Table on Router:\n' )
    print net[ 'r0' ].cmd( 'route' )
    CLI( net )
    net.stop()

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

When we run the above script we get the Mininet CLI interface where we can start the xterm terminals for the hosts h1 and h2. Using the two terminals on the two hosts, we can do different things such as pinging from one to the other, using traceroute command and even wireshark to capture the packets going between the two hosts. Following figure shows  the two xterm terminals on my machine.

xterm terminals of two hosts between a router
Let's build a little bit complicated network than the above simple network. This time we are going to use three hosts and only one is directly connected to the router. The other two are connected to a switch, which connects to the router. Following figure illustrate that network.

A network with a router, switch and three hosts.

Implementation of that network is given below. I hope that when reading through the code, it is easily to understand how the above illustrated network has became a reality in our emulation code.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#!/usr/bin/python

from mininet.topo import Topo
from mininet.net import Mininet
from mininet.node import Node
from mininet.log import setLogLevel, info
from mininet.cli import CLI

class LinuxRouter( Node ):
    "A Node with IP forwarding enabled."

    def config( self, **params ):
        super( LinuxRouter, self).config( **params )
        # Enable forwarding on the router
        self.cmd( 'sysctl net.ipv4.ip_forward=1' )

    def terminate( self ):
        self.cmd( 'sysctl net.ipv4.ip_forward=0' )
        super( LinuxRouter, self ).terminate()


class NetworkTopo( Topo ):
    "A LinuxRouter connecting three IP subnets"

    def build( self, **_opts ):

        defaultIP = '10.0.1.1/24'  # IP address for r0-eth1
        router = self.addNode( 'r0', cls=LinuxRouter, ip=defaultIP )

        h1 = self.addHost( 'h1', ip='10.0.1.2/24', defaultRoute='via 10.0.1.1' )
        h2 = self.addHost( 'h2', ip='10.0.2.2/24', defaultRoute='via 10.0.2.1' )
        h3 = self.addHost( 'h3', ip='10.0.2.3/24', defaultRoute='via 10.0.2.1' )

 s1 = self.addSwitch('s1')

        self.addLink( h1, router, intfName2='r0-eth1', params2={ 'ip' : '10.0.1.1/24' } )
        self.addLink( s1, router, intfName2='r0-eth2', params2={ 'ip' : '10.0.2.1/24' } )

 self.addLink(h2, s1)
 self.addLink(h3, s1)

def run():
    "Test linux router"
    topo = NetworkTopo()
    net = Mininet( topo=topo )  # controller is used by s1-s3
    net.start()
    info( '*** Routing Table on Router:\n' )
    print net[ 'r0' ].cmd( 'route' )
    CLI( net )
    net.stop()

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

After running the python script, I open the xterm terminals of the three hosts and and then pinged from host 1 to host 3. Additionally, I ran traceroute command on host 1 to find the route to host 3. Those outputs can be seen from the following image.

xterm terminals of three hosts connected by a router and a switch.
With these examples, I think it's getting clear how to build and emulate networks using Mininet.

References:




No comments:

Post a Comment