File: controlnet.py

package info (click to toggle)
mininet 2.3.0-1.1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,588 kB
  • sloc: python: 11,181; ansic: 1,332; sh: 967; makefile: 87
file content (161 lines) | stat: -rwxr-xr-x 5,077 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#!/usr/bin/env python

"""
controlnet.py: Mininet with a custom control network

We create two Mininet() networks, a control network
and a data network, running four DataControllers on the
control network to control the data network.

Since we're using UserSwitch on the data network,
it should correctly fail over to a backup controller.

We also use a Mininet Facade to talk to both the
control and data networks from a single CLI.
"""

from functools import partial

from mininet.net import Mininet
from mininet.node import Controller, UserSwitch
from mininet.cli import CLI
from mininet.topo import Topo
from mininet.topolib import TreeTopo
from mininet.log import setLogLevel, info

# Some minor hacks

class DataController( Controller ):
    """Data Network Controller.
       patched to avoid checkListening error and to delete intfs"""

    def checkListening( self ):
        "Ignore spurious error"
        pass

    def stop( self, *args, **kwargs ):
        "Make sure intfs are deleted"
        kwargs.update( deleteIntfs=True )
        super( DataController, self ).stop( *args, **kwargs )


class MininetFacade( object ):
    """Mininet object facade that allows a single CLI to
       talk to one or more networks"""

    def __init__( self, net, *args, **kwargs ):
        """Create MininetFacade object.
           net: Primary Mininet object
           args: unnamed networks passed as arguments
           kwargs: named networks passed as arguments"""
        self.net = net
        self.nets = [ net ] + list( args ) + list( kwargs.values() )
        self.nameToNet = kwargs
        self.nameToNet['net'] = net

    def __getattr__( self, name ):
        "returns attribute from Primary Mininet object"
        return getattr( self.net, name )

    def __getitem__( self, key ):
        "returns primary/named networks or node from any net"
        # search kwargs for net named key
        if key in self.nameToNet:
            return self.nameToNet[ key ]
        # search each net for node named key
        for net in self.nets:
            if key in net:
                return net[ key ]
        return None

    def __iter__( self ):
        "Iterate through all nodes in all Mininet objects"
        for net in self.nets:
            for node in net:
                yield node

    def __len__( self ):
        "returns aggregate number of nodes in all nets"
        count = 0
        for net in self.nets:
            count += len(net)
        return count

    def __contains__( self, key ):
        "returns True if node is a member of any net"
        return key in self.keys()

    def keys( self ):
        "returns a list of all node names in all networks"
        return list( self )

    def values( self ):
        "returns a list of all nodes in all networks"
        return [ self[ key ] for key in self ]

    def items( self ):
        "returns (key,value) tuple list for every node in all networks"
        return zip( self.keys(), self.values() )

# A real control network!

class ControlNetwork( Topo ):
    "Control Network Topology"
    # pylint: disable=arguments-differ
    def build( self, n, dataController=DataController, **_kwargs ):
        """n: number of data network controller nodes
           dataController: class for data network controllers"""
        # Connect everything to a single switch
        cs0 = self.addSwitch( 'cs0' )
        # Add hosts which will serve as data network controllers
        for i in range( 0, n ):
            c = self.addHost( 'c%s' % i, cls=dataController,
                              inNamespace=True )
            self.addLink( c, cs0 )
        # Connect switch to root namespace so that data network
        # switches will be able to talk to us
        root = self.addHost( 'root', inNamespace=False )
        self.addLink( root, cs0 )


# Make it Happen!!

def run():
    "Create control and data networks, and invoke the CLI"

    info( '* Creating Control Network\n' )
    ctopo = ControlNetwork( n=4, dataController=DataController )
    cnet = Mininet( topo=ctopo, ipBase='192.168.123.0/24',
                    controller=None, waitConnected=True )
    info( '* Adding Control Network Controller\n')
    cnet.addController( 'cc0', controller=Controller )
    info( '* Starting Control Network\n')
    cnet.start()

    info( '* Creating Data Network\n' )
    topo = TreeTopo( depth=2, fanout=2 )
    # UserSwitch so we can easily test failover
    sw = partial( UserSwitch, opts='--inactivity-probe=1 --max-backoff=1' )
    net = Mininet( topo=topo, switch=sw, controller=None,
                   waitConnected=True )
    info( '* Adding Controllers to Data Network\n' )
    for host in cnet.hosts:
        if isinstance(host, Controller):
            net.addController( host )
    info( '* Starting Data Network\n')
    net.start()

    mn = MininetFacade( net, cnet=cnet )

    CLI( mn )

    info( '* Stopping Data Network\n' )
    net.stop()

    info( '* Stopping Control Network\n' )
    cnet.stop()


if __name__ == '__main__':
    setLogLevel( 'info' )
    run()