2 Node Library for Mininet
4 This contains additional Node types which you may find to be useful.
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
13 class LinuxBridge( Switch ):
14 "Linux Bridge (with optional spanning tree)"
16 nextPrio = 100 # next bridge priority for spanning tree
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"""
25 self.prio = LinuxBridge.nextPrio
26 LinuxBridge.nextPrio += 1
27 Switch.__init__( self, name, **kwargs )
29 def connected( self ):
30 "Are we forwarding yet?"
32 return 'forwarding' in self.cmd( 'brctl showstp', self )
36 def start( self, _controllers ):
38 self.cmd( 'ifconfig', self, 'down' )
39 self.cmd( 'brctl delbr', self )
40 self.cmd( 'brctl addbr', self )
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' )
49 def stop( self, deleteIntfs=True ):
51 deleteIntfs: delete interfaces? (True)"""
52 self.cmd( 'ifconfig', self, 'down' )
53 self.cmd( 'brctl delbr', self )
54 super( LinuxBridge, self ).stop( deleteIntfs )
56 def dpctl( self, *args ):
58 return self.cmd( 'brctl', *args )
62 "Check dependencies and warn about firewalling"
63 pathCheck( 'brctl', moduleName='bridge-utils' )
64 # Disable Linux bridge firewalling so that traffic can flow!
65 for table in 'arp', 'ip', 'ip6':
66 cmd = 'sysctl net.bridge.bridge-nf-call-%stables' % table
67 out = quietRun( cmd ).strip()
68 if out.endswith( '1' ):
69 warn( 'Warning: Linux bridge may not work with', out, '\n' )
73 "NAT: Provides connectivity to external network"
75 def __init__( self, name, subnet='10.0/8',
76 localIntf=None, flush=False, **params):
77 """Start NAT/forwarding between Mininet and external network
78 subnet: Mininet subnet (default 10.0/8)
79 flush: flush iptables before installing NAT rules"""
80 super( NAT, self ).__init__( name, **params )
83 self.localIntf = localIntf
85 self.forwardState = self.cmd( 'sysctl -n net.ipv4.ip_forward' ).strip()
87 def config( self, **params ):
88 """Configure the NAT and iptables"""
89 super( NAT, self).config( **params )
91 if not self.localIntf:
92 self.localIntf = self.defaultIntf()
95 self.cmd( 'sysctl net.ipv4.ip_forward=0' )
96 self.cmd( 'iptables -F' )
97 self.cmd( 'iptables -t nat -F' )
98 # Create default entries for unmatched traffic
99 self.cmd( 'iptables -P INPUT ACCEPT' )
100 self.cmd( 'iptables -P OUTPUT ACCEPT' )
101 self.cmd( 'iptables -P FORWARD DROP' )
104 self.cmd( 'iptables -I FORWARD',
105 '-i', self.localIntf, '-d', self.subnet, '-j DROP' )
106 self.cmd( 'iptables -A FORWARD',
107 '-i', self.localIntf, '-s', self.subnet, '-j ACCEPT' )
108 self.cmd( 'iptables -A FORWARD',
109 '-o', self.localIntf, '-d', self.subnet, '-j ACCEPT' )
110 self.cmd( 'iptables -t nat -A POSTROUTING',
111 '-s', self.subnet, "'!'", '-d', self.subnet,
114 # Instruct the kernel to perform forwarding
115 self.cmd( 'sysctl net.ipv4.ip_forward=1' )
117 # Prevent network-manager from messing with our interface
118 # by specifying manual configuration in /etc/network/interfaces
119 intf = self.localIntf
120 cfile = '/etc/network/interfaces'
121 line = '\niface %s inet manual\n' % intf
122 config = open( cfile ).read()
123 if ( line ) not in config:
124 info( '*** Adding "' + line.strip() + '" to ' + cfile + '\n' )
125 with open( cfile, 'a' ) as f:
127 # Probably need to restart network-manager to be safe -
128 # hopefully this won't disconnect you
129 self.cmd( 'service network-manager restart' )
131 def terminate( self ):
132 "Stop NAT/forwarding between Mininet and external network"
134 self.cmd( 'iptables -D FORWARD',
135 '-i', self.localIntf, '-d', self.subnet, '-j DROP' )
136 self.cmd( 'iptables -D FORWARD',
137 '-i', self.localIntf, '-s', self.subnet, '-j ACCEPT' )
138 self.cmd( 'iptables -D FORWARD',
139 '-o', self.localIntf, '-d', self.subnet, '-j ACCEPT' )
140 self.cmd( 'iptables -t nat -D POSTROUTING',
141 '-s', self.subnet, '\'!\'', '-d', self.subnet,
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()