]>
git.proxmox.com Git - mirror_ifupdown2.git/blob - ifupdown2/ifupdownaddons/bridgeutils.py
73f28b1a60728f32c2ea30f95a84c4da5ff66f35
3 # Copyright 2014 Cumulus Networks, Inc. All rights reserved.
4 # Author: Roopa Prabhu, roopa@cumulusnetworks.com
7 from ifupdown
.iface
import *
8 from utilsbase
import *
14 class brctl(utilsBase
):
15 """ This class contains helper functions to interact with the bridgeutils
18 _cache_fill_done
= False
20 def __init__(self
, *args
, **kargs
):
21 utilsBase
.__init
__(self
, *args
, **kargs
)
22 if self
.CACHE
and not brctl
._cache
_fill
_done
:
24 brctl
._cache
_fill
_done
= True
27 def _bridge_get_mcattrs_from_sysfs(self
, bridgename
):
29 mcattrmap
= {'mclmc': 'multicast_last_member_count',
30 'mcrouter': 'multicast_router',
31 'mcsnoop' : 'multicast_snooping',
32 'mcsqc' : 'multicast_startup_query_count',
33 'mcqifaddr' : 'multicast_query_use_ifaddr',
34 'mcquerier' : 'multicast_querier',
35 'hashel' : 'hash_elasticity',
36 'hashmax' : 'hash_max',
37 'mclmi' : 'multicast_last_member_interval',
38 'mcmi' : 'multicast_membership_interval',
39 'mcqpi' : 'multicast_querier_interval',
40 'mcqi' : 'multicast_query_interval',
41 'mcqri' : 'multicast_query_response_interval',
42 'mcsqi' : 'multicast_startup_query_interval'}
44 mcattrsdivby100
= ['mclmi', 'mcmi', 'mcqpi', 'mcqi', 'mcqri', 'mcsqi']
46 for m
, s
in mcattrmap
.items():
47 n
= self
.read_file_oneline('/sys/class/net/%s/bridge/%s'
49 if m
in mcattrsdivby100
:
54 self
.logger
.warn('error getting mc attr %s (%s)'
61 def _bridge_attrs_fill(self
, bridgename
):
65 brout
= self
.exec_command('/sbin/brctl showstp %s' %bridgename
)
66 chunks
= re
.split(r
'\n\n', brout
, maxsplit
=0, flags
=re
.MULTILINE
)
69 # Get all bridge attributes
70 broutlines
= chunks
[0].splitlines()
71 #battrs['pathcost'] = broutlines[3].split('path cost')[1].strip()
72 battrs
['maxage'] = broutlines
[4].split(
73 'bridge max age')[1].strip().replace('.00', '')
74 battrs
['hello'] = broutlines
[5].split(
75 'bridge hello time')[1].strip().replace('.00',
77 battrs
['fd'] = broutlines
[6].split(
78 'bridge forward delay')[1].strip(
80 battrs
.update(self
._bridge
_get
_mcattrs
_from
_sysfs
(bridgename
))
82 # XXX: comment this out until mc attributes become available
84 #battrs['hashel'] = broutlines[10].split('hash elasticity')[1].split()[0].strip()
85 #battrs['hashmax'] = broutlines[10].split('hash max')[1].strip()
86 #battrs['mclmc'] = broutlines[11].split('mc last member count')[1].split()[0].strip()
87 #battrs['mciqc'] = broutlines[11].split('mc init query count')[1].strip()
88 #battrs['mcrouter'] = broutlines[12].split('mc router')[1].split()[0].strip()
89 ##battrs['mcsnoop'] = broutlines[12].split('mc snooping')[1].strip()
90 #battrs['mclmt'] = broutlines[13].split('mc last member timer')[1].split()[0].strip()
92 self
.logger
.warn(str(e
))
95 linkCache
.update_attrdict([bridgename
, 'linkinfo'], battrs
)
97 for cidx
in range(1, len(chunks
)):
98 bpout
= chunks
[cidx
].lstrip('\n')
99 if not bpout
or bpout
[0] == ' ':
101 bplines
= bpout
.splitlines()
102 pname
= bplines
[0].split()[0]
105 bportattrs
['pathcost'] = bplines
[2].split(
106 'path cost')[1].strip()
107 bportattrs
['fdelay'] = bplines
[4].split(
108 'forward delay timer')[1].strip()
109 bportattrs
['mcrouter'] = self
.read_file_oneline(
110 '/sys/class/net/%s/brport/multicast_router' %pname
)
111 bportattrs
['mcfl'] = self
.read_file_oneline(
112 '/sys/class/net/%s/brport/multicast_fast_leave' %pname
)
114 #bportattrs['mcrouters'] = bplines[6].split('mc router')[1].split()[0].strip()
115 #bportattrs['mc fast leave'] = bplines[6].split('mc fast leave')[1].strip()
117 self
.logger
.warn(str(e
))
119 bports
[pname
] = bportattrs
120 linkCache
.update_attrdict([bridgename
, 'linkinfo', 'ports'], bports
)
122 def _bridge_fill(self
, bridgename
=None, refresh
=False):
124 # if cache is already filled, return
125 linkCache
.get_attr([bridgename
, 'linkinfo', 'fd'])
130 brctlout
= self
.exec_command('/sbin/brctl show')
132 brctlout
= self
.exec_command('/sbin/brctl show ' + bridgename
)
136 for bline
in brctlout
.splitlines()[1:]:
137 bitems
= bline
.split()
141 linkCache
.update_attrdict([bitems
[0], 'linkinfo'],
144 linkCache
.update_attrdict([bitems
[0]],
145 {'linkinfo' : {'stp' : bitems
[2]}})
146 self
._bridge
_attrs
_fill
(bitems
[0])
148 def _cache_get(self
, attrlist
, refresh
=False):
153 if not self
._cache
_fill
_done
:
155 self
._cache
_fill
_done
= True
156 return linkCache
.get_attr(attrlist
)
158 return linkCache
.get_attr(attrlist
)
159 self
._bridge
_fill
(attrlist
[0], refresh
)
160 return linkCache
.get_attr(attrlist
)
162 self
.logger
.debug('_cache_get(%s) : [%s]'
163 %(str(attrlist
), str(e
)))
167 def _cache_check(self
, attrlist
, value
, refresh
=False):
169 attrvalue
= self
._cache
_get
(attrlist
, refresh
)
170 if attrvalue
and attrvalue
== value
:
173 self
.logger
.debug('_cache_check(%s) : [%s]'
174 %(str(attrlist
), str(e
)))
178 def _cache_update(self
, attrlist
, value
):
179 if self
.DRYRUN
: return
181 linkCache
.add_attr(attrlist
, value
)
185 def _cache_delete(self
, attrlist
):
186 if self
.DRYRUN
: return
188 linkCache
.del_attr(attrlist
)
192 def _cache_invalidate(self
):
193 if self
.DRYRUN
: return
194 linkCache
.invalidate()
196 def create_bridge(self
, bridgename
):
197 if self
.bridge_exists(bridgename
):
199 self
.exec_command('/sbin/brctl addbr %s' %bridgename
)
200 self
._cache
_update
([bridgename
], {})
202 def delete_bridge(self
, bridgename
):
203 if not self
.bridge_exists(bridgename
):
205 self
.exec_command('/sbin/brctl delbr %s' %bridgename
)
206 self
._cache
_invalidate
()
208 def add_bridge_port(self
, bridgename
, bridgeportname
):
209 """ Add port to bridge """
210 ports
= self
._cache
_get
([bridgename
, 'linkinfo', 'ports'])
211 if ports
and ports
.get(bridgeportname
):
213 self
.exec_command('/sbin/brctl addif ' + bridgename
+ ' ' +
215 self
._cache
_update
([bridgename
, 'linkinfo', 'ports',
218 def delete_bridge_port(self
, bridgename
, bridgeportname
):
219 """ Delete port from bridge """
220 ports
= self
._cache
_get
([bridgename
, 'linkinfo', 'ports'])
221 if not ports
or not ports
.get(bridgeportname
):
223 self
.exec_command('/sbin/brctl delif ' + bridgename
+ ' ' +
225 self
._cache
_delete
([bridgename
, 'linkinfo', 'ports',
228 def set_bridgeport_attrs(self
, bridgename
, bridgeportname
, attrdict
):
229 portattrs
= self
._cache
_get
([bridgename
, 'linkinfo',
230 'ports', bridgeportname
])
231 if portattrs
== None: portattrs
= {}
232 for k
, v
in attrdict
.iteritems():
234 curval
= portattrs
.get(k
)
235 if curval
and curval
== v
:
237 self
.exec_command('/sbin/brctl set%s %s %s %s'
238 %(k
, bridgename
, bridgeportname
, v
))
240 def set_bridgeport_attr(self
, bridgename
, bridgeportname
,
242 if self
._cache
_check
([bridgename
, 'linkinfo', 'ports',
243 bridgeportname
, attrname
], attrval
):
245 self
.exec_command('/sbin/brctl set%s %s %s %s' %(attrname
, bridgename
,
246 bridgeportname
, attrval
))
248 def set_bridge_attrs(self
, bridgename
, attrdict
):
249 for k
, v
in attrdict
.iteritems():
252 if self
._cache
_check
([bridgename
, 'linkinfo', k
], v
):
255 self
.exec_command('/sbin/brctl set%s %s %s'
258 self
.logger
.warn('%s: %s' %(bridgename
, str(e
)))
261 def set_bridge_attr(self
, bridgename
, attrname
, attrval
):
262 if self
._cache
_check
([bridgename
, 'linkinfo', attrname
], attrval
):
264 self
.exec_command('/sbin/brctl set%s %s %s'
265 %(attrname
, bridgename
, attrval
))
267 def get_bridge_attrs(self
, bridgename
):
268 return self
._cache
_get
([bridgename
, 'linkinfo'])
270 def get_bridgeport_attrs(self
, bridgename
, bridgeportname
):
271 return self
._cache
_get
([bridgename
, 'linkinfo', 'ports',
274 def get_bridgeport_attr(self
, bridgename
, bridgeportname
, attrname
):
275 return self
._cache
_get
([bridgename
, 'linkinfo', 'ports',
276 bridgeportname
, attrname
])
278 def set_stp(self
, bridge
, stp_state
):
279 self
.exec_command('/sbin/brctl stp ' + bridge
+ ' ' + stp_state
)
281 def get_stp(self
, bridge
):
282 sysfs_stpstate
= '/sys/class/net/%s/bridge/stp_state' %bridge
283 if not os
.path
.exists(sysfs_stpstate
):
285 stpstate
= self
.read_file_oneline(sysfs_stpstate
)
289 if int(stpstate
) > 0:
291 elif int(stpstate
) == 0:
296 def conv_value_to_user(self
, str):
304 def read_value_from_sysfs(self
, filename
, preprocess_func
):
305 value
= self
.read_file_oneline(filename
)
308 return preprocess_func(value
)
310 def set_ageing(self
, bridge
, ageing
):
311 self
.exec_command('/sbin/brctl setageing ' + bridge
+ ' ' + ageing
)
313 def get_ageing(self
, bridge
):
314 return self
.read_value_from_sysfs('/sys/class/net/%s/bridge/ageing_time'
315 %bridge
, self
.conv_value_to_user
)
317 def set_bridgeprio(self
, bridge
, bridgeprio
):
318 self
.exec_command('/sbin/brctl setbridgeprio ' + bridge
+ ' ' +
321 def get_bridgeprio(self
, bridge
):
322 return self
.read_file_oneline(
323 '/sys/class/net/%s/bridge/priority' %bridge
)
325 def set_fd(self
, bridge
, fd
):
326 self
.exec_command('/sbin/brctl setfd ' + bridge
+ ' ' + fd
)
328 def get_fd(self
, bridge
):
329 return self
.read_value_from_sysfs(
330 '/sys/class/net/%s/bridge/forward_delay'
331 %bridge
, self
.conv_value_to_user
)
333 def set_gcint(self
, bridge
, gcint
):
334 #cmd = '/sbin/brctl setgcint ' + bridge + ' ' + gcint
335 raise Exception('set_gcint not implemented')
337 def set_hello(self
, bridge
, hello
):
338 self
.exec_command('/sbin/brctl sethello ' + bridge
+ ' ' + hello
)
340 def get_hello(self
, bridge
):
341 return self
.read_value_from_sysfs('/sys/class/net/%s/bridge/hello_time'
342 %bridge
, self
.conv_value_to_user
)
344 def set_maxage(self
, bridge
, maxage
):
345 self
.exec_command('/sbin/brctl setmaxage ' + bridge
+ ' ' + maxage
)
347 def get_maxage(self
, bridge
):
348 return self
.read_value_from_sysfs('/sys/class/net/%s/bridge/max_age'
349 %bridge
, self
.conv_value_to_user
)
351 def set_pathcost(self
, bridge
, port
, pathcost
):
352 self
.exec_command('/sbin/brctl setpathcost %s' %bridge
+ ' %s' %port
+
355 def get_pathcost(self
, bridge
, port
):
356 return self
.read_file_oneline('/sys/class/net/%s/brport/path_cost'
359 def set_portprio(self
, bridge
, port
, prio
):
360 self
.exec_command('/sbin/brctl setportprio %s' %bridge
+ ' %s' %port
+
363 def get_portprio(self
, bridge
, port
):
364 return self
.read_file_oneline('/sys/class/net/%s/brport/priority'
367 def set_hashmax(self
, bridge
, hashmax
):
368 self
.exec_command('/sbin/brctl sethashmax %s' %bridge
+ ' %s' %hashmax
)
370 def get_hashmax(self
, bridge
):
371 return self
.read_file_oneline('/sys/class/net/%s/bridge/hash_max'
374 def set_hashel(self
, bridge
, hashel
):
375 self
.exec_command('/sbin/brctl sethashel %s' %bridge
+ ' %s' %hashel
)
377 def get_hashel(self
, bridge
):
378 return self
.read_file_oneline('/sys/class/net/%s/bridge/hash_elasticity'
381 def set_mclmc(self
, bridge
, mclmc
):
382 self
.exec_command('/sbin/brctl setmclmc %s' %bridge
+ ' %s' %mclmc
)
384 def get_mclmc(self
, bridge
):
385 return self
.read_file_oneline(
386 '/sys/class/net/%s/bridge/multicast_last_member_count'
389 def set_mcrouter(self
, bridge
, mcrouter
):
390 self
.exec_command('/sbin/brctl setmcrouter %s' %bridge
+
393 def get_mcrouter(self
, bridge
):
394 return self
.read_file_oneline(
395 '/sys/class/net/%s/bridge/multicast_router' %bridge
)
397 def set_mcsnoop(self
, bridge
, mcsnoop
):
398 self
.exec_command('/sbin/brctl setmcsnoop %s' %bridge
+
401 def get_mcsnoop(self
, bridge
):
402 return self
.read_file_oneline(
403 '/sys/class/net/%s/bridge/multicast_snooping' %bridge
)
405 def set_mcsqc(self
, bridge
, mcsqc
):
406 self
.exec_command('/sbin/brctl setmcsqc %s' %bridge
+
409 def get_mcsqc(self
, bridge
):
410 return self
.read_file_oneline(
411 '/sys/class/net/%s/bridge/multicast_startup_query_count'
414 def set_mcqifaddr(self
, bridge
, mcqifaddr
):
415 self
.exec_command('/sbin/brctl setmcqifaddr %s' %bridge
+
418 def get_mcqifaddr(self
, bridge
):
419 return self
.read_file_oneline(
420 '/sys/class/net/%s/bridge/multicast_startup_query_use_ifaddr'
423 def set_mcquerier(self
, bridge
, mcquerier
):
424 self
.exec_command('/sbin/brctl setmcquerier %s' %bridge
+
427 def get_mcquerier(self
, bridge
):
428 return self
.read_file_oneline(
429 '/sys/class/net/%s/bridge/multicast_querier' %bridge
)
431 def set_mcqv4src(self
, bridge
, vlan
, mcquerier
):
432 if vlan
== 0 or vlan
> 4095:
433 self
.logger
.warn('mcqv4src vlan \'%d\' invalid range' %vlan
)
436 ip
= mcquerier
.split('.')
438 self
.logger
.warn('mcqv4src \'%s\' invalid IPv4 address' %mcquerier
)
441 if not k
.isdigit() or int(k
, 10) < 0 or int(k
, 10) > 255:
442 self
.logger
.warn('mcqv4src \'%s\' invalid IPv4 address' %mcquerier
)
445 self
.exec_command('/sbin/brctl setmcqv4src %s' %bridge
+
446 ' %d %s' %(vlan
, mcquerier
))
448 def del_mcqv4src(self
, bridge
, vlan
):
449 self
.exec_command('/sbin/brctl delmcqv4src %s %d' %(bridge
, vlan
))
451 def get_mcqv4src(self
, bridge
, vlan
=None):
453 mcqout
= self
.exec_command('/sbin/brctl showmcqv4src %s' %bridge
)
454 if not mcqout
: return None
455 mcqlines
= mcqout
.splitlines()
456 for l
in mcqlines
[1:]:
458 k
, d
, v
= l
.split('\t')
463 return mcqv4src
.get(vlan
)
466 def set_mclmi(self
, bridge
, mclmi
):
467 self
.exec_command('/sbin/brctl setmclmi %s' %bridge
+
470 def get_mclmi(self
, bridge
):
471 return self
.read_file_oneline(
472 '/sys/class/net/%s/bridge/multicast_last_member_interval'
475 def set_mcmi(self
, bridge
, mcmi
):
476 self
.exec_command('/sbin/brctl setmcmi %s' %bridge
+
479 def get_mcmi(self
, bridge
):
480 return self
.read_file_oneline(
481 '/sys/class/net/%s/bridge/multicast_membership_interval'
484 def bridge_exists(self
, bridge
):
485 return os
.path
.exists('/sys/class/net/%s/bridge' %bridge
)
487 def is_bridge_port(self
, ifacename
):
488 return os
.path
.exists('/sys/class/net/%s/brport' %ifacename
)
490 def bridge_port_exists(self
, bridge
, bridgeportname
):
492 return os
.path
.exists('/sys/class/net/%s/brif/%s'
493 %(bridge
, bridgeportname
))
497 def get_bridge_ports(self
, bridgename
):
499 return os
.listdir('/sys/class/net/%s/brif/' %bridgename
)