Statistics
| Branch: | Tag: | Revision:

mininet / mininet / nodelib.py @ f7601da0

History | View | Annotate | Download (5.39 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
from mininet.util import quietRun
11

    
12
import re
13

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

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

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

    
30
    def connected( self ):
31
        "Are we forwarding yet?"
32
        if self.stp:
33
            return 'forwarding' in self.cmd( 'brctl showstp', self )
34
        else:
35
            return True
36

    
37
    def start( self, _controllers ):
38
        "Start Linux bridge"
39
        self.cmd( 'ifconfig', self, 'down' )
40
        self.cmd( 'brctl delbr', self )
41
        self.cmd( 'brctl addbr', self )
42
        if self.stp:
43
            self.cmd( 'brctl setbridgeprio', self.prio )
44
            self.cmd( 'brctl stp', self, 'on' )
45
        for i in self.intfList():
46
            if self.name in i.name:
47
                self.cmd( 'brctl addif', self, i )
48
        self.cmd( 'ifconfig', self, 'up' )
49

    
50
    def stop( self, deleteIntfs=True ):
51
        """Stop Linux bridge
52
           deleteIntfs: delete interfaces? (True)"""
53
        self.cmd( 'ifconfig', self, 'down' )
54
        self.cmd( 'brctl delbr', self )
55
        super( LinuxBridge, self ).stop( deleteIntfs )
56

    
57
    def dpctl( self, *args ):
58
        "Run brctl command"
59
        return self.cmd( 'brctl', *args )
60

    
61
    @classmethod
62
    def setup( cls ):
63
        "Check dependencies and warn about firewalling"
64
        pathCheck( 'brctl', moduleName='bridge-utils' )
65
        # Disable Linux bridge firewalling so that traffic can flow!
66
        for table in 'arp', 'ip', 'ip6':
67
            cmd = 'sysctl net.bridge.bridge-nf-call-%stables' % table
68
            out = quietRun( cmd ).strip()
69
            if out.endswith( '1' ):
70
                warn( 'Warning: Linux bridge may not work with', out, '\n' )
71

    
72

    
73
class NAT( Node ):
74
    "NAT: Provides connectivity to external network"
75

    
76
    def __init__( self, name, subnet='10.0/8',
77
                  localIntf=None, flush=False, **params):
78
        """Start NAT/forwarding between Mininet and external network
79
           subnet: Mininet subnet (default 10.0/8)
80
           flush: flush iptables before installing NAT rules"""
81
        super( NAT, self ).__init__( name, **params )
82

    
83
        self.subnet = subnet
84
        self.localIntf = localIntf
85
        self.flush = flush
86
        self.forwardState = self.cmd( 'sysctl -n net.ipv4.ip_forward' ).strip()
87

    
88
    def config( self, **params ):
89
        """Configure the NAT and iptables"""
90
        super( NAT, self).config( **params )
91

    
92
        if not self.localIntf:
93
            self.localIntf = self.defaultIntf()
94

    
95
        if self.flush:
96
            self.cmd( 'sysctl net.ipv4.ip_forward=0' )
97
            
98
            self.cmd( 'iptables -F' )
99
            self.cmd( 'iptables -t nat -F' )
100
            # Create default entries for unmatched traffic
101
            self.cmd( 'iptables -P INPUT ACCEPT' )
102
            self.cmd( 'iptables -P OUTPUT ACCEPT' )
103
            self.cmd( 'iptables -P FORWARD DROP' )
104

    
105
        # Install NAT rules
106
        self.cmd( 'iptables -I FORWARD',
107
                  '-i', self.localIntf, '-d', self.subnet, '-j DROP' )
108
        self.cmd( 'iptables -A FORWARD',
109
                  '-i', self.localIntf, '-s', self.subnet, '-j ACCEPT' )
110
        self.cmd( 'iptables -A FORWARD',
111
                  '-o', self.localIntf, '-d', self.subnet,'-j ACCEPT' )
112
        self.cmd( 'iptables -t nat -A POSTROUTING',
113
                  '-s', self.subnet, "'!'", '-d', self.subnet, '-j MASQUERADE' )
114

    
115
        # Instruct the kernel to perform forwarding
116
        self.cmd( 'sysctl net.ipv4.ip_forward=1' )
117

    
118
        # Prevent network-manager from messing with our interface
119
        # by specifying manual configuration in /etc/network/interfaces
120
        intf = self.localIntf
121
        cfile = '/etc/network/interfaces'
122
        line = '\niface %s inet manual\n' % intf
123
        config = open( cfile ).read()
124
        if ( line ) not in config:
125
            info( '*** Adding "' + line.strip() + '" to ' + cfile + '\n' )
126
            with open( cfile, 'a' ) as f:
127
                f.write( line )
128
        # Probably need to restart network-manager to be safe -
129
        # hopefully this won't disconnect you
130
        self.cmd( 'service network-manager restart' )
131

    
132
    def terminate( self ):
133
        "Stop NAT/forwarding between Mininet and external network"
134
        # Remote NAT rules
135
        self.cmd( 'iptables -D FORWARD',
136
                   '-i', self.localIntf, '-d', self.subnet, '-j DROP' )
137
        self.cmd( 'iptables -D FORWARD',
138
                  '-i', self.localIntf, '-s', self.subnet, '-j ACCEPT' )
139
        self.cmd( 'iptables -D FORWARD',
140
                  '-o', self.localIntf, '-d', self.subnet,'-j ACCEPT' )
141
        self.cmd( 'iptables -t nat -D POSTROUTING',
142
                  '-s', self.subnet, '\'!\'', '-d', self.subnet, '-j MASQUERADE' )
143
        # Put the forwarding state back to what it was
144
        self.cmd( 'sysctl net.ipv4.ip_forward=%s' % self.forwardState )
145
        super( NAT, self ).terminate()