Merge pull request #229 from mininet/devel/mobility-example
A simple mobility API and example
This commit is contained in:
@@ -65,6 +65,11 @@ that uses Linux IP forwarding.
|
|||||||
|
|
||||||
This example demonstrates creating a network via a graphical editor.
|
This example demonstrates creating a network via a graphical editor.
|
||||||
|
|
||||||
|
#### mobility.py
|
||||||
|
|
||||||
|
This example demonstrates detaching an interface from one switch and
|
||||||
|
attaching it another as a basic way to move a host around a network.
|
||||||
|
|
||||||
#### multiping.py:
|
#### multiping.py:
|
||||||
|
|
||||||
This example demonstrates one method for
|
This example demonstrates one method for
|
||||||
|
|||||||
Executable
+136
@@ -0,0 +1,136 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Simple example of Mobility with Mininet
|
||||||
|
(aka enough rope to hang yourself.)
|
||||||
|
|
||||||
|
We move a host from s1 to s2, s2 to s3, and then back to s1.
|
||||||
|
|
||||||
|
Gotchas:
|
||||||
|
|
||||||
|
The reference controller doesn't support mobility, so we need to
|
||||||
|
manually flush the switch flow tables!
|
||||||
|
|
||||||
|
Good luck!
|
||||||
|
|
||||||
|
to-do:
|
||||||
|
|
||||||
|
- think about wifi/hub behavior
|
||||||
|
- think about clearing last hop - why doesn't that work?
|
||||||
|
"""
|
||||||
|
|
||||||
|
from mininet.net import Mininet
|
||||||
|
from mininet.node import OVSSwitch
|
||||||
|
from mininet.topo import LinearTopo
|
||||||
|
from mininet.util import quietRun
|
||||||
|
from mininet.log import output, warn
|
||||||
|
|
||||||
|
from random import randint
|
||||||
|
from re import findall
|
||||||
|
|
||||||
|
|
||||||
|
class MobilitySwitch( OVSSwitch ):
|
||||||
|
"Switch that can reattach and rename interfaces"
|
||||||
|
|
||||||
|
def delIntf( self, intf ):
|
||||||
|
"Remove (and detach) an interface"
|
||||||
|
port = self.ports[ intf ]
|
||||||
|
del self.ports[ intf ]
|
||||||
|
del self.intfs[ port ]
|
||||||
|
del self.nameToIntf[ intf.name ]
|
||||||
|
|
||||||
|
def addIntf( self, intf, rename=False, **kwargs ):
|
||||||
|
"Add (and reparent) an interface"
|
||||||
|
OVSSwitch.addIntf( self, intf, **kwargs )
|
||||||
|
intf.node = self
|
||||||
|
if rename:
|
||||||
|
self.renameIntf( intf )
|
||||||
|
|
||||||
|
def attach( self, intf ):
|
||||||
|
"Attach an interface and set its port"
|
||||||
|
port = self.ports[ intf ]
|
||||||
|
if port:
|
||||||
|
if self.isOldOVS():
|
||||||
|
self.cmd( 'ovs-vsctl add-port', self, intf )
|
||||||
|
else:
|
||||||
|
self.cmd( 'ovs-vsctl add-port', self, intf,
|
||||||
|
'-- set Interface', intf,
|
||||||
|
'ofport_request=%s' % port )
|
||||||
|
self.validatePort( intf )
|
||||||
|
|
||||||
|
def validatePort( self, intf ):
|
||||||
|
"Validate intf's OF port number"
|
||||||
|
ofport = int( self.cmd( 'ovs-vsctl get Interface', intf,
|
||||||
|
'ofport' ) )
|
||||||
|
if ofport != self.ports[ intf ]:
|
||||||
|
warn( 'WARNING: ofport for', intf, 'is actually', ofport,
|
||||||
|
'\n' )
|
||||||
|
|
||||||
|
def renameIntf( self, intf, newname='' ):
|
||||||
|
"Rename an interface (to its canonical name)"
|
||||||
|
intf.ifconfig( 'down' )
|
||||||
|
if not newname:
|
||||||
|
newname = '%s-eth%d' % ( self.name, self.ports[ intf ] )
|
||||||
|
intf.cmd( 'ip link set', intf, 'name', newname )
|
||||||
|
del self.nameToIntf[ intf.name ]
|
||||||
|
intf.name = newname
|
||||||
|
self.nameToIntf[ intf.name ] = intf
|
||||||
|
intf.ifconfig( 'up' )
|
||||||
|
|
||||||
|
def moveIntf( self, intf, switch, port=None, rename=True ):
|
||||||
|
"Move one of our interfaces to another switch"
|
||||||
|
self.detach( intf )
|
||||||
|
self.delIntf( intf )
|
||||||
|
switch.addIntf( intf, port=port, rename=rename )
|
||||||
|
switch.attach( intf )
|
||||||
|
|
||||||
|
|
||||||
|
def printConnections( switches ):
|
||||||
|
"Compactly print connected nodes to each switch"
|
||||||
|
for sw in switches:
|
||||||
|
output( '%s: ' % sw )
|
||||||
|
for intf in sw.intfList():
|
||||||
|
link = intf.link
|
||||||
|
if link:
|
||||||
|
intf1, intf2 = link.intf1, link.intf2
|
||||||
|
remote = intf1 if intf1.node != sw else intf2
|
||||||
|
output( '%s(%s) ' % ( remote.node, sw.ports[ intf ] ) )
|
||||||
|
output( '\n' )
|
||||||
|
|
||||||
|
|
||||||
|
def moveHost( host, oldSwitch, newSwitch, newPort=None ):
|
||||||
|
"Move a host from old switch to new switch"
|
||||||
|
hintf, sintf = host.connectionsTo( oldSwitch )[ 0 ]
|
||||||
|
oldSwitch.moveIntf( sintf, newSwitch, port=newPort )
|
||||||
|
return hintf, sintf
|
||||||
|
|
||||||
|
|
||||||
|
def mobilityTest():
|
||||||
|
"A simple test of mobility"
|
||||||
|
print '* Simple mobility test'
|
||||||
|
net = Mininet( topo=LinearTopo( 3 ), switch=MobilitySwitch )
|
||||||
|
print '* Starting network:'
|
||||||
|
net.start()
|
||||||
|
printConnections( net.switches )
|
||||||
|
print '* Testing network'
|
||||||
|
net.pingAll()
|
||||||
|
print '* Identifying switch interface for h1'
|
||||||
|
h1, old = net.get( 'h1', 's1' )
|
||||||
|
for s in 2, 3, 1:
|
||||||
|
new = net[ 's%d' % s ]
|
||||||
|
port = randint( 10, 20 )
|
||||||
|
print '* Moving', h1, 'from', old, 'to', new, 'port', port
|
||||||
|
hintf, sintf = moveHost( h1, old, new, newPort=port )
|
||||||
|
print '*', hintf, 'is now connected to', sintf
|
||||||
|
print '* Clearing out old flows'
|
||||||
|
for sw in net.switches:
|
||||||
|
sw.dpctl( 'del-flows' )
|
||||||
|
print '* New network:'
|
||||||
|
printConnections( net.switches )
|
||||||
|
print '* Testing connectivity:'
|
||||||
|
net.pingAll()
|
||||||
|
old = new
|
||||||
|
net.stop()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
mobilityTest()
|
||||||
Executable
+20
@@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Test for mobility.py
|
||||||
|
"""
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from subprocess import check_output
|
||||||
|
|
||||||
|
class testMobility( unittest.TestCase ):
|
||||||
|
|
||||||
|
def testMobility( self ):
|
||||||
|
"Run the example and verify its 4 ping results"
|
||||||
|
cmd = 'python -m mininet.examples.mobility 2>&1'
|
||||||
|
grep = ' | grep -c " 0% dropped" '
|
||||||
|
result = check_output( cmd + grep, shell=True )
|
||||||
|
assert int( result ) == 4
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
Reference in New Issue
Block a user