Statistics
| Branch: | Tag: | Revision:

mininet / mininet / nodelib.py @ 4219b229

History | View | Annotate | Download (4.73 KB)

1
"""
2
Node Library for Mininet
3

4
This contains additional Node types which you may find to be useful.
5
"""
6

    
7
from mininet.node import Node, Switch
8
from mininet.log import info, warn
9
from mininet.moduledeps import pathCheck
10

    
11
import re
12

    
13
class LinuxBridge( Switch ):
14
    "Linux Bridge (with optional spanning tree)"
15

    
16
    nextPrio = 100  # next bridge priority for spanning tree
17

    
18
    def __init__( self, name, stp=False, prio=None, **kwargs ):
19
        """stp: use spanning tree protocol? (default False)
20
           prio: optional explicit bridge priority for STP"""
21
        self.stp = stp
22
        if prio:
23
            self.prio = prio
24
        else:
25
            self.prio = LinuxBridge.nextPrio
26
            LinuxBridge.nextPrio += 1
27
        Switch.__init__( self, name, **kwargs )
28

    
29
    def connected( self ):
30
        "Are we forwarding yet?"
31
        if self.stp:
32
            return 'forwarding' in self.cmd( 'brctl showstp', self )
33
        else:
34
            return True
35
    
36
    def start( self, controllers ):
37
        "Start Linux bridge"
38
        self.cmd( 'ifconfig', self, 'down' )
39
        self.cmd( 'brctl delbr', self )
40
        self.cmd( 'brctl addbr', self )
41
        if self.stp:
42
            self.cmd( 'brctl setbridgeprio', self.prio )
43
            self.cmd( 'brctl stp', self, 'on' )
44
        for i in self.intfList():
45
            if self.name in i.name:
46
                self.cmd( 'brctl addif', self, i )
47
        self.cmd( 'ifconfig', self, 'up' )
48

    
49
    def stop( self ):
50
        "Stop Linux bridge"
51
        self.cmd( 'ifconfig', self, 'down' )
52
        self.cmd( 'brctl delbr', self )
53

    
54
    def dpctl( self, *args ):
55
        "Run brctl command"
56
        return self.cmd( 'brctl', *args )
57

    
58
    @classmethod
59
    def setup( cls ):
60
        "Make sure our class dependencies are available"
61
        pathCheck( 'brctl', moduleName='bridge-utils' )
62

    
63

    
64
class NAT( Node ):
65
    """NAT: Provides connectivity to external network"""
66

    
67
    def __init__( self, name, inetIntf=None, subnet='10.0/8', localIntf=None, **params):
68
        super( NAT, self ).__init__( name, **params )
69

    
70
        """Start NAT/forwarding between Mininet and external network
71
        inetIntf: interface for internet access
72
        subnet: Mininet subnet (default 10.0/8)="""
73
        self.inetIntf = inetIntf if inetIntf else self.getGatewayIntf()
74
        self.subnet = subnet
75
        self.localIntf = localIntf
76

    
77
    def config( self, **params ):
78
        super( NAT, self).config( **params )
79
        """Configure the NAT and iptables"""
80

    
81
        if not self.localIntf:
82
            self.localIntf =  self.defaultIntf()
83

    
84
        self.cmd( 'sysctl net.ipv4.ip_forward=0' )
85

    
86
        # Flush any currently active rules
87
        # TODO: is this safe?
88
        self.cmd( 'iptables -F' )
89
        self.cmd( 'iptables -t nat -F' )
90

    
91
        # Create default entries for unmatched traffic
92
        self.cmd( 'iptables -P INPUT ACCEPT' )
93
        self.cmd( 'iptables -P OUTPUT ACCEPT' )
94
        self.cmd( 'iptables -P FORWARD DROP' )
95

    
96
        # Configure NAT
97
        self.cmd( 'iptables -I FORWARD -i', self.localIntf, '-d', self.subnet, '-j DROP' )
98
        self.cmd( 'iptables -A FORWARD -i', self.localIntf, '-s', self.subnet, '-j ACCEPT' )
99
        self.cmd( 'iptables -A FORWARD -i', self.inetIntf, '-d', self.subnet, '-j ACCEPT' )
100
        self.cmd( 'iptables -t nat -A POSTROUTING -o ', self.inetIntf, '-s', self.subnet, '-j MASQUERADE' )
101

    
102
        # Instruct the kernel to perform forwarding
103
        self.cmd( 'sysctl net.ipv4.ip_forward=1' )
104

    
105
        # Prevent network-manager from messing with our interface
106
        # by specifying manual configuration in /etc/network/interfaces
107
        intf = self.localIntf
108
        cfile = '/etc/network/interfaces'
109
        line = '\niface %s inet manual\n' % intf
110
        config = open( cfile ).read()
111
        if ( line ) not in config:
112
            info( '*** Adding "' + line.strip() + '" to ' + cfile + '\n' )
113
            with open( cfile, 'a' ) as f:
114
                f.write( line )
115
        # Probably need to restart network-manager to be safe -
116
        # hopefully this won't disconnect you
117
        self.cmd( 'service network-manager restart' )
118

    
119
    def getGatewayIntf( self ):
120
        routes = self.cmd( 'ip route show' )
121
        match = re.search('default via \S+ dev (\S+)', routes )
122
        if match:
123
            return match.group( 1 )
124
        else:
125
            warn( 'There is no default route set. Using eth0 as gateway interface...\n' )
126
            return 'eth0'
127

    
128
    def terminate( self ):
129
        """Stop NAT/forwarding between Mininet and external network"""
130
        # Flush any currently active rules
131
        # TODO: is this safe?
132
        self.cmd( 'iptables -F' )
133
        self.cmd( 'iptables -t nat -F' )
134

    
135
        # Instruct the kernel to stop forwarding
136
        self.cmd( 'sysctl net.ipv4.ip_forward=0' )
137

    
138
        super( NAT, self ).terminate()
139