Statistics
| Branch: | Tag: | Revision:

mininet / examples / mobility.py @ 212399fe

History | View | Annotate | Download (4.57 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

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

    
34
    @classmethod
35
    def setup( cls ):
36
        "Call our parent method and determine OVS version"
37
        OVSSwitch.setup()
38
        info = quietRun( 'ovs-vsctl --version' )
39
        cls.OVSVersion =  float( findall( '\d+\.\d+', info )[ 0 ] )
40

    
41
    def delIntf( self, intf ):
42
        "Remove (and detach) an interface"
43
        port = self.ports[ intf ]
44
        del self.ports[ intf ]
45
        del self.intfs[ port ]
46
        del self.nameToIntf[ intf.name ]
47

    
48
    def addIntf( self, intf, rename=False, **kwargs ):
49
        "Add (and reparent) an interface"
50
        OVSSwitch.addIntf( self, intf, **kwargs )
51
        intf.node = self
52
        if rename:
53
            self.renameIntf( intf )
54

    
55
    def attach( self, intf ):
56
        "Attach an interface and set its port"
57
        port = self.ports[ intf ]
58
        if port:
59
            if MobilitySwitch.OVSVersion >= 1.10:
60
                self.cmd( 'ovs-vsctl add-port', self, intf,
61
                          '-- set Interface', intf,
62
                          'ofport_request=%s' % port )
63
            else:
64
                self.cmd( 'ovs-vsctl add-port', self, intf )
65
            self.validatePort( intf )
66

    
67
    def validatePort( self, intf ):
68
        "Validate intf's OF port number"
69
        ofport = int( self.cmd( 'ovs-vsctl get Interface', intf,
70
                              'ofport' ) )
71
        if ofport != self.ports[ intf ]:
72
            warn( 'WARNING: ofport for', intf, 'is', ofport,
73
                   'but we wanted', self.ports[ intf ], '\n' )
74

    
75
    def renameIntf( self, intf, newname='' ):
76
        "Rename an interface (to its canonical name)"
77
        intf.ifconfig( 'down' )
78
        if not newname:
79
            newname = '%s-eth%d' % ( self.name, self.ports[ intf ] )
80
        intf.cmd( 'ip link set', intf, 'name', newname )
81
        del self.nameToIntf[ intf.name ]
82
        intf.name = newname
83
        self.nameToIntf[ intf.name ] = intf
84
        intf.ifconfig( 'up' )
85

    
86
    def moveIntf( self, intf, switch, port=None, rename=True ):
87
        "Move one of our interfaces to another switch"
88
        self.detach( intf )
89
        self.delIntf( intf )
90
        switch.addIntf( intf, port=port, rename=True )
91
        switch.attach( intf )
92

    
93

    
94
def printConnections( switches ):
95
    "Compactly print connected nodes to each switch"
96
    for sw in switches:
97
        output( '%s: ' % sw )
98
        for intf in sw.intfList():
99
            link = intf.link
100
            if link:
101
                intf1, intf2 = link.intf1, link.intf2
102
                remote = intf1 if intf1.node != sw else intf2
103
                output( '%s(%s) ' % ( remote.node, sw.ports[ intf ] ) )
104
        output( '\n' )
105

    
106

    
107
def moveHost( host, oldSwitch, newSwitch, newPort=None ):
108
    "Move a host from old switch to new switch"
109
    hintf, sintf = host.connectionsTo( oldSwitch )[ 0 ]
110
    oldSwitch.moveIntf( sintf, newSwitch, port=newPort )
111
    return hintf, sintf
112

    
113

    
114
def mobilityTest():
115
    "A simple test of mobility"
116
    print '* Simple mobility test'
117
    net = Mininet( topo=LinearTopo( 3 ), switch=MobilitySwitch )
118
    print '* Starting network:'
119
    net.start()
120
    printConnections( net.switches )
121
    if MobilitySwitch.OVSVersion < 1.10:
122
        print '* WARNING: port selection may not work in OVS',
123
        print MobilitySwitch.OVSVersion
124
    print '* Testing network'
125
    net.pingAll()
126
    print '* Identifying switch interface for h1'
127
    h1, old = net.get( 'h1', 's1' )
128
    for s in 2, 3, 1:
129
        new = net[ 's%d' % s ]
130
        port = randint( 10, 20 )
131
        print '* Moving', h1, 'from', old, 'to', new, 'port', port
132
        hintf, sintf = moveHost( h1, old, new, newPort=port )
133
        print '*', hintf, 'is now connected to', sintf
134
        print '* Clearing out old flows'
135
        for sw in net.switches:
136
            sw.dpctl( 'del-flows' )
137
        print '* New network:'
138
        printConnections( net.switches )
139
        print '* Testing connectivity:'
140
        net.pingAll()
141
        old = new
142
    net.stop()
143

    
144
if __name__ == '__main__':
145
    mobilityTest()