From 8a987b9c55e056b8066c8837d8c48de8e2eef6c8 Mon Sep 17 00:00:00 2001 From: Brian O'Connor Date: Wed, 27 Aug 2014 03:57:38 -0700 Subject: [PATCH 1/3] adding linuxrouter.py --- examples/linuxrouter.py | 49 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100755 examples/linuxrouter.py diff --git a/examples/linuxrouter.py b/examples/linuxrouter.py new file mode 100755 index 0000000..1d625ba --- /dev/null +++ b/examples/linuxrouter.py @@ -0,0 +1,49 @@ +#!/usr/bin/python + +""" +linuxrouter.py: Example network with Linux IP router + + +""" + +from mininet.topo import Topo +from mininet.net import Mininet +from mininet.node import Node +from mininet.log import setLogLevel +from mininet.cli import CLI +from mininet.util import irange + +class Router( Node ): + + def config( self, **params ): + super( Router, 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( Router, self ).terminate() + + +class NetworkTopo(Topo): + def __init__(self, n=2, h=1, **opts): + Topo.__init__(self, **opts) + + router = self.addNode('r0', cls=Router, ip='192.168.1.1/24') + h1 = self.addHost('h1', ip='192.168.1.100/8', defaultRoute='via 192.168.1.1') + h2 = self.addHost('h2', ip='172.16.0.100/8', defaultRoute='via 172.16.0.1') + h3 = self.addHost('h3', ip='10.0.0.100/24', defaultRoute='via 10.0.0.1') + self.addLink(h1, router, intfName2='r0-eth1', params2={ 'ip' : '192.168.1.1/24' }) + self.addLink(h2, router, intfName2='r0-eth2', params2={ 'ip' : '172.16.0.1/24' }) + self.addLink(h3, router, intfName2='r0-eth3', params2={ 'ip' : '10.0.0.1/24' }) + +def run(): + topo = NetworkTopo() + net = Mininet(topo=topo) + net.start() + CLI(net) + net.stop() + +if __name__ == '__main__': + setLogLevel('info') + run() From aa4dfda44cdd916a996a51d6148e548360e867ee Mon Sep 17 00:00:00 2001 From: Brian O'Connor Date: Wed, 27 Aug 2014 22:01:18 -0700 Subject: [PATCH 2/3] adding documentation and test for linuxrouter.py --- examples/README.md | 5 +++ examples/linuxrouter.py | 39 +++++++++++++++-------- examples/test/test_linuxrouter.py | 52 +++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 13 deletions(-) create mode 100644 examples/test/test_linuxrouter.py diff --git a/examples/README.md b/examples/README.md index 96e30d7..45eabb4 100644 --- a/examples/README.md +++ b/examples/README.md @@ -56,6 +56,11 @@ This example shows how to use link and CPU limits. This example shows how to create a custom topology programatically by subclassing Topo, and how to run a series of tests on it. +### linuxrouter.py: + +This example shows how to create and configure a router in Mininet +that uses Linux IP forwarding. + #### miniedit.py: This example demonstrates creating a network via a graphical editor. diff --git a/examples/linuxrouter.py b/examples/linuxrouter.py index 1d625ba..11444ea 100755 --- a/examples/linuxrouter.py +++ b/examples/linuxrouter.py @@ -3,6 +3,18 @@ """ linuxrouter.py: Example network with Linux IP router +This example converts a Node into a router using IP forwarding +already built into Linux. + +The topology contains a router with three IP subnets: + - 192.168.1.0/24 (interface IP: 192.168.1.1) + - 172.16.0.0/12 (interface IP: 172.16.0.1) + - 10.0.0.0/8 (interface IP: 10.0.0.1) + + It also contains three hosts, one in each subnet: + - h1 (IP: 192.168.1.100) + - h2 (IP: 172.16.0.100) + - h3 (IP: 10.0.0.100) """ @@ -14,6 +26,7 @@ from mininet.cli import CLI from mininet.util import irange class Router( Node ): + "A Node with IP forwarding enabled." def config( self, **params ): super( Router, self).config( **params ) @@ -25,25 +38,25 @@ class Router( Node ): super( Router, self ).terminate() -class NetworkTopo(Topo): - def __init__(self, n=2, h=1, **opts): - Topo.__init__(self, **opts) +class NetworkTopo( Topo ): + "A simple topology of a router with three subnets (one host in each)." - router = self.addNode('r0', cls=Router, ip='192.168.1.1/24') - h1 = self.addHost('h1', ip='192.168.1.100/8', defaultRoute='via 192.168.1.1') - h2 = self.addHost('h2', ip='172.16.0.100/8', defaultRoute='via 172.16.0.1') - h3 = self.addHost('h3', ip='10.0.0.100/24', defaultRoute='via 10.0.0.1') - self.addLink(h1, router, intfName2='r0-eth1', params2={ 'ip' : '192.168.1.1/24' }) - self.addLink(h2, router, intfName2='r0-eth2', params2={ 'ip' : '172.16.0.1/24' }) - self.addLink(h3, router, intfName2='r0-eth3', params2={ 'ip' : '10.0.0.1/24' }) + def build( self, n=2, h=1, **opts ): + router = self.addNode( 'r0', cls=Router, ip='192.168.1.1/24' ) + h1 = self.addHost( 'h1', ip='192.168.1.100/24', defaultRoute='via 192.168.1.1' ) + h2 = self.addHost( 'h2', ip='172.16.0.100/12', defaultRoute='via 172.16.0.1' ) + h3 = self.addHost( 'h3', ip='10.0.0.100/8', defaultRoute='via 10.0.0.1' ) + self.addLink( h1, router, intfName2='r0-eth1', params2={ 'ip' : '192.168.1.1/24' } ) + self.addLink( h2, router, intfName2='r0-eth2', params2={ 'ip' : '172.16.0.1/12' } ) + self.addLink( h3, router, intfName2='r0-eth3', params2={ 'ip' : '10.0.0.1/8' } ) def run(): topo = NetworkTopo() - net = Mininet(topo=topo) + net = Mininet( topo=topo, controller=None ) # no controller needed net.start() - CLI(net) + CLI( net ) net.stop() if __name__ == '__main__': - setLogLevel('info') + setLogLevel( 'info' ) run() diff --git a/examples/test/test_linuxrouter.py b/examples/test/test_linuxrouter.py new file mode 100644 index 0000000..60af201 --- /dev/null +++ b/examples/test/test_linuxrouter.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python + +""" +Test for linuxrouter.py +""" + +import unittest +import pexpect +from mininet.util import quietRun + +class testLinuxRouter( unittest.TestCase ): + + prompt = 'mininet>' + + def testPingall( self ): + "Test connectivity between hosts" + p = pexpect.spawn( 'python -m mininet.examples.linuxrouter' ) + p.expect( self.prompt ) + p.sendline( 'pingall' ) + p.expect ( '(\d+)% dropped' ) + percent = int( p.match.group( 1 ) ) if p.match else -1 + p.expect( self.prompt ) + p.sendline( 'exit' ) + p.wait() + self.assertEqual( percent, 0 ) + + def testRouterPing( self ): + "Test connectivity from h1 to router" + p = pexpect.spawn( 'python -m mininet.examples.linuxrouter' ) + p.expect( self.prompt ) + p.sendline( 'h1 ping -c 1 r0' ) + p.expect ( '(\d+)% packet loss' ) + percent = int( p.match.group( 1 ) ) if p.match else -1 + p.expect( self.prompt ) + p.sendline( 'exit' ) + p.wait() + self.assertEqual( percent, 0 ) + + def testTTL( self ): + "Verify that the TTL is decremented" + p = pexpect.spawn( 'python -m mininet.examples.linuxrouter' ) + p.expect( self.prompt ) + p.sendline( 'h1 ping -c 1 h2' ) + p.expect ( 'ttl=(\d+)' ) + ttl = int( p.match.group( 1 ) ) if p.match else -1 + p.expect( self.prompt ) + p.sendline( 'exit' ) + p.wait() + self.assertEqual( ttl, 63 ) # 64 - 1 + +if __name__ == '__main__': + unittest.main() From 2c76ab718b493f27f973bff4c140012052045818 Mon Sep 17 00:00:00 2001 From: Brian O'Connor Date: Wed, 27 Aug 2014 22:43:04 -0700 Subject: [PATCH 3/3] linuxrouter.py: changing name, printing routing table, and some more documentation --- examples/linuxrouter.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/examples/linuxrouter.py b/examples/linuxrouter.py index 11444ea..488ec3c 100755 --- a/examples/linuxrouter.py +++ b/examples/linuxrouter.py @@ -16,33 +16,37 @@ The topology contains a router with three IP subnets: - h2 (IP: 172.16.0.100) - h3 (IP: 10.0.0.100) + Routing entries can be added to the routing tables of the + hosts or router using the "ip route add" or "route add" command. + See the man pages for more details. + """ from mininet.topo import Topo from mininet.net import Mininet from mininet.node import Node -from mininet.log import setLogLevel +from mininet.log import setLogLevel, info from mininet.cli import CLI from mininet.util import irange -class Router( Node ): +class LinuxRouter( Node ): "A Node with IP forwarding enabled." def config( self, **params ): - super( Router, self).config( **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( Router, self ).terminate() + super( LinuxRouter, self ).terminate() class NetworkTopo( Topo ): "A simple topology of a router with three subnets (one host in each)." def build( self, n=2, h=1, **opts ): - router = self.addNode( 'r0', cls=Router, ip='192.168.1.1/24' ) + router = self.addNode( 'r0', cls=LinuxRouter, ip='192.168.1.1/24' ) h1 = self.addHost( 'h1', ip='192.168.1.100/24', defaultRoute='via 192.168.1.1' ) h2 = self.addHost( 'h2', ip='172.16.0.100/12', defaultRoute='via 172.16.0.1' ) h3 = self.addHost( 'h3', ip='10.0.0.100/8', defaultRoute='via 10.0.0.1' ) @@ -54,6 +58,8 @@ def run(): topo = NetworkTopo() net = Mininet( topo=topo, controller=None ) # no controller needed net.start() + info( '*** Routing Table on Router\n' ) + print net[ 'r0' ].cmd( 'route' ) CLI( net ) net.stop()