Statistics
| Branch: | Tag: | Revision:

mininet / examples / mobility.py @ 13bdd914

History | View | Annotate | Download (4.68 KB)

1
#!/usr/bin/python
2

    
3
"""
4
Simple example of Mobility with Mininet
5
(aka enough rope to hang yourself.)
6

7
We move a host from s1 to s2, s2 to s3, and then back to s1.
8

9
Gotchas:
10

11
The reference controller doesn't support mobility, so we need to
12
manually flush the switch flow tables!
13

14
Good luck!
15

16
to-do:
17

18
- think about wifi/hub behavior
19
- think about clearing last hop - why doesn't that work?
20
"""
21

    
22
from mininet.net import Mininet
23
from mininet.node import OVSSwitch
24
from mininet.topo import LinearTopo
25
from mininet.util import quietRun
26
from mininet.log import output, warn
27

    
28
from random import randint
29
from re import findall
30
from distutils.version import StrictVersion
31

    
32
class MobilitySwitch( OVSSwitch ):
33
    "Switch that can reattach and rename interfaces"
34

    
35
    @classmethod
36
    def setup( cls ):
37
        "Call our parent method and determine OVS version"
38
        OVSSwitch.setup()
39
        info = quietRun( 'ovs-vsctl --version' )
40
        cls.OVSVersion =  findall( '\d+\.\d+', info )[ 0 ]
41
        if cls.isOldOVS():
42
            warn( 'WARNING: port selection may not work '
43
                  ' with OVS ', cls.OVSVersion )
44

    
45
    @classmethod
46
    def isOldOVS( cls ):
47
        return ( StrictVersion( cls.OVSVersion ) <
48
             StrictVersion( '1.10' ) )
49

    
50
    def delIntf( self, intf ):
51
        "Remove (and detach) an interface"
52
        port = self.ports[ intf ]
53
        del self.ports[ intf ]
54
        del self.intfs[ port ]
55
        del self.nameToIntf[ intf.name ]
56

    
57
    def addIntf( self, intf, rename=False, **kwargs ):
58
        "Add (and reparent) an interface"
59
        OVSSwitch.addIntf( self, intf, **kwargs )
60
        intf.node = self
61
        if rename:
62
            self.renameIntf( intf )
63

    
64
    def attach( self, intf ):
65
        "Attach an interface and set its port"
66
        port = self.ports[ intf ]
67
        if port:
68
            if self.isOldOVS():
69
                self.cmd( 'ovs-vsctl add-port', self, intf )
70
            else:
71
                self.cmd( 'ovs-vsctl add-port', self, intf,
72
                          '-- set Interface', intf,
73
                          'ofport_request=%s' % port )
74
            self.validatePort( intf )
75

    
76
    def validatePort( self, intf ):
77
        "Validate intf's OF port number"
78
        ofport = int( self.cmd( 'ovs-vsctl get Interface', intf,
79
                              'ofport' ) )
80
        if ofport != self.ports[ intf ]:
81
            warn( 'WARNING: ofport for', intf, 'is actually', ofport,
82
                  '\n' )
83

    
84
    def renameIntf( self, intf, newname='' ):
85
        "Rename an interface (to its canonical name)"
86
        intf.ifconfig( 'down' )
87
        if not newname:
88
            newname = '%s-eth%d' % ( self.name, self.ports[ intf ] )
89
        intf.cmd( 'ip link set', intf, 'name', newname )
90
        del self.nameToIntf[ intf.name ]
91
        intf.name = newname
92
        self.nameToIntf[ intf.name ] = intf
93
        intf.ifconfig( 'up' )
94

    
95
    def moveIntf( self, intf, switch, port=None, rename=True ):
96
        "Move one of our interfaces to another switch"
97
        self.detach( intf )
98
        self.delIntf( intf )
99
        switch.addIntf( intf, port=port, rename=rename )
100
        switch.attach( intf )
101

    
102

    
103
def printConnections( switches ):
104
    "Compactly print connected nodes to each switch"
105
    for sw in switches:
106
        output( '%s: ' % sw )
107
        for intf in sw.intfList():
108
            link = intf.link
109
            if link:
110
                intf1, intf2 = link.intf1, link.intf2
111
                remote = intf1 if intf1.node != sw else intf2
112
                output( '%s(%s) ' % ( remote.node, sw.ports[ intf ] ) )
113
        output( '\n' )
114

    
115

    
116
def moveHost( host, oldSwitch, newSwitch, newPort=None ):
117
    "Move a host from old switch to new switch"
118
    hintf, sintf = host.connectionsTo( oldSwitch )[ 0 ]
119
    oldSwitch.moveIntf( sintf, newSwitch, port=newPort )
120
    return hintf, sintf
121

    
122

    
123
def mobilityTest():
124
    "A simple test of mobility"
125
    print '* Simple mobility test'
126
    net = Mininet( topo=LinearTopo( 3 ), switch=MobilitySwitch )
127
    print '* Starting network:'
128
    net.start()
129
    printConnections( net.switches )
130
    print '* Testing network'
131
    net.pingAll()
132
    print '* Identifying switch interface for h1'
133
    h1, old = net.get( 'h1', 's1' )
134
    for s in 2, 3, 1:
135
        new = net[ 's%d' % s ]
136
        port = randint( 10, 20 )
137
        print '* Moving', h1, 'from', old, 'to', new, 'port', port
138
        hintf, sintf = moveHost( h1, old, new, newPort=port )
139
        print '*', hintf, 'is now connected to', sintf
140
        print '* Clearing out old flows'
141
        for sw in net.switches:
142
            sw.dpctl( 'del-flows' )
143
        print '* New network:'
144
        printConnections( net.switches )
145
        print '* Testing connectivity:'
146
        net.pingAll()
147
        old = new
148
    net.stop()
149

    
150
if __name__ == '__main__':
151
    mobilityTest()