Update and rename MantenerFIFO to MantenerFIFO.md
[vsorcdistro/.git] / mininet / mininet / nodelib.py
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
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, deleteIntfs=True ):
50         """Stop Linux bridge
51            deleteIntfs: delete interfaces? (True)"""
52         self.cmd( 'ifconfig', self, 'down' )
53         self.cmd( 'brctl delbr', self )
54         super( LinuxBridge, self ).stop( deleteIntfs )
55
56     def dpctl( self, *args ):
57         "Run brctl command"
58         return self.cmd( 'brctl', *args )
59
60     @classmethod
61     def setup( cls ):
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' )
70
71
72 class NAT( Node ):
73     "NAT: Provides connectivity to external network"
74
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 )
81
82         self.subnet = subnet
83         self.localIntf = localIntf
84         self.flush = flush
85         self.forwardState = self.cmd( 'sysctl -n net.ipv4.ip_forward' ).strip()
86
87     def config( self, **params ):
88         """Configure the NAT and iptables"""
89         super( NAT, self).config( **params )
90
91         if not self.localIntf:
92             self.localIntf = self.defaultIntf()
93
94         if self.flush:
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' )
102
103         # Install NAT rules
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,
112                   '-j MASQUERADE' )
113
114         # Instruct the kernel to perform forwarding
115         self.cmd( 'sysctl net.ipv4.ip_forward=1' )
116
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:
126                 f.write( line )
127         # Probably need to restart network-manager to be safe -
128         # hopefully this won't disconnect you
129         self.cmd( 'service network-manager restart' )
130
131     def terminate( self ):
132         "Stop NAT/forwarding between Mininet and external network"
133         # Remote NAT rules
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,
142                   '-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()