mininet / mininet / nodelib.py @ master
History | View | Annotate | Download (5.38 KB)
1 | 3878c000 | Bob Lantz | """
|
---|---|---|---|
2 | Node Library for Mininet
|
||
3 |
|
||
4 | 4015e066 | Brian O'Connor | This contains additional Node types which you may find to be useful.
|
5 | 3878c000 | Bob Lantz | """
|
6 | |||
7 | 4015e066 | Brian O'Connor | from mininet.node import Node, Switch |
8 | af1ccf93 | Brian O'Connor | from mininet.log import info, warn |
9 | f0f9907b | Bob Lantz | from mininet.moduledeps import pathCheck |
10 | ba05fd36 | Bob Lantz | from mininet.util import quietRun |
11 | f0f9907b | Bob Lantz | |
12 | af1ccf93 | Brian O'Connor | import re |
13 | 3878c000 | Bob Lantz | |
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 | ece509d5 | Bob Lantz | 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 | 5a530af1 | Bob Lantz | |
37 | b1ec912d | Bob Lantz | def start( self, _controllers ): |
38 | f0f9907b | Bob Lantz | "Start Linux bridge"
|
39 | 3878c000 | Bob Lantz | 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 | d754a7ce | Bob Lantz | def stop( self, deleteIntfs=True ): |
51 | """Stop Linux bridge
|
||
52 | deleteIntfs: delete interfaces? (True)"""
|
||
53 | 3878c000 | Bob Lantz | self.cmd( 'ifconfig', self, 'down' ) |
54 | self.cmd( 'brctl delbr', self ) |
||
55 | d754a7ce | Bob Lantz | super( LinuxBridge, self ).stop( deleteIntfs ) |
56 | 3878c000 | Bob Lantz | |
57 | f0f9907b | Bob Lantz | def dpctl( self, *args ): |
58 | "Run brctl command"
|
||
59 | return self.cmd( 'brctl', *args ) |
||
60 | |||
61 | @classmethod
|
||
62 | def setup( cls ): |
||
63 | ba05fd36 | Bob Lantz | "Check dependencies and warn about firewalling"
|
64 | f0f9907b | Bob Lantz | pathCheck( 'brctl', moduleName='bridge-utils' ) |
65 | ba05fd36 | Bob Lantz | # 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 | f0f9907b | Bob Lantz | |
72 | |||
73 | 4015e066 | Brian O'Connor | class NAT( Node ): |
74 | b1ec912d | Bob Lantz | "NAT: Provides connectivity to external network"
|
75 | 4015e066 | Brian O'Connor | |
76 | 90d50dcb | Jonathan Hart | def __init__( self, name, subnet='10.0/8', |
77 | c4a85ab1 | Bob Lantz | localIntf=None, flush=False, **params): |
78 | b1ec912d | Bob Lantz | """Start NAT/forwarding between Mininet and external network
|
79 | c4a85ab1 | Bob Lantz | subnet: Mininet subnet (default 10.0/8)
|
80 | flush: flush iptables before installing NAT rules"""
|
||
81 | 4015e066 | Brian O'Connor | super( NAT, self ).__init__( name, **params ) |
82 | |||
83 | self.subnet = subnet
|
||
84 | self.localIntf = localIntf
|
||
85 | c4a85ab1 | Bob Lantz | self.flush = flush
|
86 | 90d50dcb | Jonathan Hart | self.forwardState = self.cmd( 'sysctl -n net.ipv4.ip_forward' ).strip() |
87 | 4015e066 | Brian O'Connor | |
88 | def config( self, **params ): |
||
89 | """Configure the NAT and iptables"""
|
||
90 | b1ec912d | Bob Lantz | super( NAT, self).config( **params ) |
91 | 4015e066 | Brian O'Connor | |
92 | if not self.localIntf: |
||
93 | 7a3159c9 | Bob Lantz | self.localIntf = self.defaultIntf() |
94 | 4015e066 | Brian O'Connor | |
95 | c4a85ab1 | Bob Lantz | if self.flush: |
96 | 90d50dcb | Jonathan Hart | self.cmd( 'sysctl net.ipv4.ip_forward=0' ) |
97 | c4a85ab1 | Bob Lantz | self.cmd( 'iptables -F' ) |
98 | self.cmd( 'iptables -t nat -F' ) |
||
99 | # Create default entries for unmatched traffic
|
||
100 | self.cmd( 'iptables -P INPUT ACCEPT' ) |
||
101 | self.cmd( 'iptables -P OUTPUT ACCEPT' ) |
||
102 | self.cmd( 'iptables -P FORWARD DROP' ) |
||
103 | 4015e066 | Brian O'Connor | |
104 | c4a85ab1 | Bob Lantz | # Install NAT rules
|
105 | b1ec912d | Bob Lantz | self.cmd( 'iptables -I FORWARD', |
106 | '-i', self.localIntf, '-d', self.subnet, '-j DROP' ) |
||
107 | self.cmd( 'iptables -A FORWARD', |
||
108 | '-i', self.localIntf, '-s', self.subnet, '-j ACCEPT' ) |
||
109 | self.cmd( 'iptables -A FORWARD', |
||
110 | 90d50dcb | Jonathan Hart | '-o', self.localIntf, '-d', self.subnet,'-j ACCEPT' ) |
111 | b1ec912d | Bob Lantz | self.cmd( 'iptables -t nat -A POSTROUTING', |
112 | f7601da0 | Bob Lantz | '-s', self.subnet, "'!'", '-d', self.subnet, '-j MASQUERADE' ) |
113 | 4015e066 | Brian O'Connor | |
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 | af1ccf93 | Brian O'Connor | info( '*** Adding "' + line.strip() + '" to ' + cfile + '\n' ) |
125 | 4015e066 | Brian O'Connor | 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 | c4a85ab1 | Bob Lantz | "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 | 90d50dcb | Jonathan Hart | '-o', self.localIntf, '-d', self.subnet,'-j ACCEPT' ) |
140 | c4a85ab1 | Bob Lantz | self.cmd( 'iptables -t nat -D POSTROUTING', |
141 | 90d50dcb | Jonathan Hart | '-s', self.subnet, '\'!\'', '-d', self.subnet, '-j MASQUERADE' ) |
142 | # Put the forwarding state back to what it was
|
||
143 | self.cmd( 'sysctl net.ipv4.ip_forward=%s' % self.forwardState ) |
||
144 | 4015e066 | Brian O'Connor | super( NAT, self ).terminate() |