From 08d83d136d26e0c4849b31c31f0fda8091dfa797 Mon Sep 17 00:00:00 2001
From: Bob Lantz <rlantz@cs.stanford.edu>
Date: Tue, 15 Oct 2013 17:30:42 -0700
Subject: [PATCH] Rename intfs, and add simple moveHost() function

---
 examples/mobility.py | 87 ++++++++++++++++++++++++++++----------------
 1 file changed, 55 insertions(+), 32 deletions(-)

diff --git a/examples/mobility.py b/examples/mobility.py
index dda400c0..f59b7ae9 100755
--- a/examples/mobility.py
+++ b/examples/mobility.py
@@ -4,22 +4,12 @@
 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.
+We move a host from s1 to s2, s2 to s3, and then back to s1.
 
 Gotchas:
 
-1. The interfaces are not renamed; this
-   means that s1-eth1 will show up on other
-   switches.
-
-2. The reference controller doesn't support
-   mobility, so we need to flush the switch
-   flow tables.
-
-3. The port numbers reported by the switch
-   may not match the actual OpenFlow port
-   numbers used by OVS.
+The reference controller doesn't support mobility, so we need to
+manually flush the switch flow tables!
 
 Good luck!
 """
@@ -29,33 +19,71 @@
 from mininet.topo import LinearTopo
 from mininet.cli import CLI
 from mininet.util import dumpNetConnections
+from mininet.log import output
 from time import sleep
 
+
 class MobilitySwitch( OVSSwitch ):
-    "Switch that can delete interfaces"
+    "Switch that can reattach and rename interfaces"
 
     def delIntf( self, intf ):
-        "Remove an interface"
+        "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=True, **kwargs ):
+        "Add (and reparent) an interface"
+        OVSSwitch.addIntf( self, intf, **kwargs )
+        intf.node = self
+        if rename:
+            self.renameIntf( intf )
+
+    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 validatePort( self, intf ):
+        "Validate intf's OF port number"
+        ofport = int( intf.cmd( 'ovs-vsctl get Interface', intf,
+                              'ofport' ) )
+        assert ofport == self.ports[ intf ]
+
+    def moveIntf( self, intf, switch, rename=True ):
+        "Move one of our interfaces to another switch"
         self.detach( intf )
+        self.delIntf( intf )
+        switch.addIntf( intf, rename=True )
+        switch.attach( intf )
+        switch.validatePort( intf )
 
 
 def printConnections( switches ):
     "Compactly print connected nodes to each switch"
     for sw in switches:
-        print '%s:' % sw,
+        output( '%s: ' % sw )
         for intf in sw.intfList():
             link = intf.link
             if link:
-                intfs = [ link.intf1, link.intf2 ]
-                if intfs[ 0 ].node != sw:
-                    intfs.reverse()
-                local, remote = intfs
-                print remote.node,
-        print
+                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 ):
+    "Move a host from old switch to new switch"
+    hintf, sintf = host.connectionsTo( oldSwitch )[ 0 ]
+    oldSwitch.moveIntf( sintf, newSwitch )
+    return hintf, sintf
 
 
 def mobilityTest():
@@ -67,17 +95,12 @@ def mobilityTest():
     printConnections( net.switches )
     net.pingAll()
     print '* Identifying switch interface for h1'
-    h1, s1 = net.get( 'h1', 's1' )
-    hintf, sintf = h1.connectionsTo( s1 )[ 0 ]
-    last = s1
+    h1, last = net.get( 'h1', 's1' )
     for s in 2, 3, 1:
-        next = net['s%d' % s ]
-        print '* Moving', sintf, 'from', last, 'to', next
-        last.detach( sintf )
-        last.delIntf( sintf )
-        next.attach( sintf )
-        next.addIntf( sintf )
-        sintf.node = next
+        next = net[ 's%d' % s ]
+        print '* Moving', h1, 'from', last, 'to', next
+        hintf, sintf = moveHost( h1, last, next )
+        print '*', hintf, 'is now connected to', sintf
         print '* Clearing out old flows'
         for sw in net.switches:
             sw.dpctl( 'del-flows' )
-- 
GitLab