]>
git.proxmox.com Git - mirror_ifupdown2.git/blob - ifupdownaddons/bridgeutils.py
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 *
12 from ifupdown
.utils
import utils
13 import ifupdown
.ifupdownflags
as ifupdownflags
16 class brctl(utilsBase
):
17 """ This class contains helper functions to interact with the bridgeutils
20 _cache_fill_done
= False
22 def __init__(self
, *args
, **kargs
):
23 utilsBase
.__init
__(self
, *args
, **kargs
)
24 if ifupdownflags
.flags
.CACHE
and not brctl
._cache
_fill
_done
:
25 if os
.path
.exists('/sbin/brctl'):
27 brctl
._cache
_fill
_done
= True
28 self
.supported_command
= {'showmcqv4src': True}
31 def _bridge_get_mcattrs_from_sysfs(self
, bridgename
):
33 mcattrmap
= {'mclmc': 'multicast_last_member_count',
34 'mcrouter': 'multicast_router',
35 'mcsnoop' : 'multicast_snooping',
36 'mcsqc' : 'multicast_startup_query_count',
37 'mcqifaddr' : 'multicast_query_use_ifaddr',
38 'mcquerier' : 'multicast_querier',
39 'hashel' : 'hash_elasticity',
40 'hashmax' : 'hash_max',
41 'mclmi' : 'multicast_last_member_interval',
42 'mcmi' : 'multicast_membership_interval',
43 'mcqpi' : 'multicast_querier_interval',
44 'mcqi' : 'multicast_query_interval',
45 'mcqri' : 'multicast_query_response_interval',
46 'mcsqi' : 'multicast_startup_query_interval'}
48 mcattrsdivby100
= ['mclmi', 'mcmi', 'mcqpi', 'mcqi', 'mcqri', 'mcsqi']
50 for m
, s
in mcattrmap
.items():
51 n
= self
.read_file_oneline('/sys/class/net/%s/bridge/%s'
53 if m
in mcattrsdivby100
:
58 self
.logger
.warn('error getting mc attr %s (%s)'
65 def _bridge_attrs_fill(self
, bridgename
):
69 brout
= utils
.exec_command('/sbin/brctl showstp %s' % bridgename
)
70 chunks
= re
.split(r
'\n\n', brout
, maxsplit
=0, flags
=re
.MULTILINE
)
73 # Get all bridge attributes
74 broutlines
= chunks
[0].splitlines()
75 #battrs['pathcost'] = broutlines[3].split('path cost')[1].strip()
78 battrs
['maxage'] = broutlines
[4].split('bridge max age')[
79 1].strip().replace('.00', '')
84 battrs
['hello'] = broutlines
[5].split('bridge hello time')[
85 1].strip().replace('.00', '')
90 battrs
['fd'] = broutlines
[6].split('bridge forward delay')[
91 1].strip().replace('.00', '')
96 battrs
['ageing'] = broutlines
[7].split('ageing time')[
97 1].strip().replace('.00', '')
102 battrs
['mcrouter'] = broutlines
[12].split('mc router')[
103 1].strip().split('\t\t\t')[0]
108 battrs
['bridgeprio'] = self
.read_file_oneline(
109 '/sys/class/net/%s/bridge/priority' % bridgename
)
114 battrs
.update(self
._bridge
_get
_mcattrs
_from
_sysfs
(bridgename
))
118 # XXX: comment this out until mc attributes become available
120 #battrs['hashel'] = broutlines[10].split('hash elasticity')[1].split()[0].strip()
121 #battrs['hashmax'] = broutlines[10].split('hash max')[1].strip()
122 #battrs['mclmc'] = broutlines[11].split('mc last member count')[1].split()[0].strip()
123 #battrs['mciqc'] = broutlines[11].split('mc init query count')[1].strip()
124 #battrs['mcrouter'] = broutlines[12].split('mc router')[1].split()[0].strip()
125 ##battrs['mcsnoop'] = broutlines[12].split('mc snooping')[1].strip()
126 #battrs['mclmt'] = broutlines[13].split('mc last member timer')[1].split()[0].strip()
128 self
.logger
.warn('%s: error while processing bridge attributes: %s' % (bridgename
, str(e
)))
131 linkCache
.update_attrdict([bridgename
, 'linkinfo'], battrs
)
132 for cidx
in range(1, len(chunks
)):
133 bpout
= chunks
[cidx
].lstrip('\n')
134 if not bpout
or bpout
[0] == ' ':
136 bplines
= bpout
.splitlines()
137 pname
= bplines
[0].split()[0]
140 bportattrs
['pathcost'] = bplines
[2].split(
141 'path cost')[1].strip()
142 bportattrs
['fdelay'] = bplines
[4].split(
143 'forward delay timer')[1].strip()
144 bportattrs
['portmcrouter'] = self
.read_file_oneline(
145 '/sys/class/net/%s/brport/multicast_router' %pname
)
146 bportattrs
['portmcfl'] = self
.read_file_oneline(
147 '/sys/class/net/%s/brport/multicast_fast_leave' %pname
)
148 bportattrs
['portprio'] = self
.read_file_oneline(
149 '/sys/class/net/%s/brport/priority' %pname
)
150 #bportattrs['mcrouters'] = bplines[6].split('mc router')[1].split()[0].strip()
151 #bportattrs['mc fast leave'] = bplines[6].split('mc fast leave')[1].strip()
153 self
.logger
.warn('%s: error while processing bridge attributes: %s' % (bridgename
, str(e
)))
154 bports
[pname
] = bportattrs
155 linkCache
.update_attrdict([bridgename
, 'linkinfo', 'ports'], bports
)
157 def _bridge_fill(self
, bridgename
=None, refresh
=False):
159 # if cache is already filled, return
160 linkCache
.get_attr([bridgename
, 'linkinfo', 'fd'])
165 brctlout
= utils
.exec_command('/sbin/brctl show')
167 brctlout
= utils
.exec_command('/sbin/brctl show %s' % bridgename
)
171 for bline
in brctlout
.splitlines()[1:]:
172 bitems
= bline
.split()
176 linkCache
.update_attrdict([bitems
[0], 'linkinfo'],
179 linkCache
.update_attrdict([bitems
[0]],
180 {'linkinfo' : {'stp' : bitems
[2]}})
181 self
._bridge
_attrs
_fill
(bitems
[0])
183 def _cache_get(self
, attrlist
, refresh
=False):
185 if ifupdownflags
.flags
.DRYRUN
:
187 if ifupdownflags
.flags
.CACHE
:
188 if not self
._cache
_fill
_done
:
190 self
._cache
_fill
_done
= True
191 return linkCache
.get_attr(attrlist
)
193 return linkCache
.get_attr(attrlist
)
194 self
._bridge
_fill
(attrlist
[0], refresh
)
195 return linkCache
.get_attr(attrlist
)
197 self
.logger
.debug('_cache_get(%s) : [%s]'
198 %(str(attrlist
), str(e
)))
202 def _cache_check(self
, attrlist
, value
, refresh
=False):
204 attrvalue
= self
._cache
_get
(attrlist
, refresh
)
205 if attrvalue
and attrvalue
== value
:
208 self
.logger
.debug('_cache_check(%s) : [%s]'
209 %(str(attrlist
), str(e
)))
213 def _cache_update(self
, attrlist
, value
):
214 if ifupdownflags
.flags
.DRYRUN
: return
216 linkCache
.add_attr(attrlist
, value
)
220 def _cache_delete(self
, attrlist
):
221 if ifupdownflags
.flags
.DRYRUN
: return
223 linkCache
.del_attr(attrlist
)
227 def _cache_invalidate(self
):
228 if ifupdownflags
.flags
.DRYRUN
: return
229 linkCache
.invalidate()
231 def create_bridge(self
, bridgename
):
232 if self
.bridge_exists(bridgename
):
234 utils
.exec_command('/sbin/brctl addbr %s' % bridgename
)
235 self
._cache
_update
([bridgename
], {})
237 def delete_bridge(self
, bridgename
):
238 if not self
.bridge_exists(bridgename
):
240 utils
.exec_command('/sbin/brctl delbr %s' % bridgename
)
241 self
._cache
_invalidate
()
243 def add_bridge_port(self
, bridgename
, bridgeportname
):
244 """ Add port to bridge """
245 ports
= self
._cache
_get
([bridgename
, 'linkinfo', 'ports'])
246 if ports
and ports
.get(bridgeportname
):
248 utils
.exec_command('/sbin/brctl addif %s %s' %
249 (bridgename
, bridgeportname
))
250 self
._cache
_update
([bridgename
, 'linkinfo', 'ports',
253 def delete_bridge_port(self
, bridgename
, bridgeportname
):
254 """ Delete port from bridge """
255 ports
= self
._cache
_get
([bridgename
, 'linkinfo', 'ports'])
256 if not ports
or not ports
.get(bridgeportname
):
258 utils
.exec_command('/sbin/brctl delif %s %s' %
259 (bridgename
, bridgeportname
))
260 self
._cache
_delete
([bridgename
, 'linkinfo', 'ports',
263 def set_bridgeport_attrs(self
, bridgename
, bridgeportname
, attrdict
):
264 portattrs
= self
._cache
_get
([bridgename
, 'linkinfo',
265 'ports', bridgeportname
])
266 if portattrs
== None: portattrs
= {}
267 for k
, v
in attrdict
.iteritems():
268 if ifupdownflags
.flags
.CACHE
:
269 curval
= portattrs
.get(k
)
270 if curval
and curval
== v
:
272 utils
.exec_command('/sbin/brctl set%s %s %s %s' %
273 (k
, bridgename
, bridgeportname
, v
))
275 def set_bridgeport_attr(self
, bridgename
, bridgeportname
,
277 if self
._cache
_check
([bridgename
, 'linkinfo', 'ports',
278 bridgeportname
, attrname
], attrval
):
280 utils
.exec_command('/sbin/brctl set%s %s %s %s' %
286 def set_bridge_attrs(self
, bridgename
, attrdict
):
287 for k
, v
in attrdict
.iteritems():
290 if self
._cache
_check
([bridgename
, 'linkinfo', k
], v
):
293 cmd
= '/sbin/brctl set%s %s %s' % (k
, bridgename
, v
)
294 utils
.exec_command(cmd
)
296 self
.logger
.warn('%s: %s' %(bridgename
, str(e
)))
299 def set_bridge_attr(self
, bridgename
, attrname
, attrval
):
300 if self
._cache
_check
([bridgename
, 'linkinfo', attrname
], attrval
):
302 utils
.exec_command('/sbin/brctl set%s %s %s' %
303 (attrname
, bridgename
, attrval
))
305 def get_bridge_attrs(self
, bridgename
):
306 return self
._cache
_get
([bridgename
, 'linkinfo'])
308 def get_bridgeport_attrs(self
, bridgename
, bridgeportname
):
309 return self
._cache
_get
([bridgename
, 'linkinfo', 'ports',
312 def get_bridgeport_attr(self
, bridgename
, bridgeportname
, attrname
):
313 return self
._cache
_get
([bridgename
, 'linkinfo', 'ports',
314 bridgeportname
, attrname
])
316 def set_stp(self
, bridge
, stp_state
):
317 utils
.exec_command('/sbin/brctl stp %s %s' % (bridge
, stp_state
))
319 def get_stp(self
, bridge
):
320 sysfs_stpstate
= '/sys/class/net/%s/bridge/stp_state' %bridge
321 if not os
.path
.exists(sysfs_stpstate
):
323 stpstate
= self
.read_file_oneline(sysfs_stpstate
)
327 if int(stpstate
) > 0:
329 elif int(stpstate
) == 0:
334 def conv_value_to_user(self
, str):
342 def read_value_from_sysfs(self
, filename
, preprocess_func
):
343 value
= self
.read_file_oneline(filename
)
346 return preprocess_func(value
)
348 def set_ageing(self
, bridge
, ageing
):
349 utils
.exec_command('/sbin/brctl setageing %s %s' % (bridge
, ageing
))
351 def get_ageing(self
, bridge
):
352 return self
.read_value_from_sysfs('/sys/class/net/%s/bridge/ageing_time'
353 %bridge
, self
.conv_value_to_user
)
355 def set_bridgeprio(self
, bridge
, prio
):
356 utils
.exec_command('/sbin/brctl setbridgeprio %s %s' % (bridge
, prio
))
358 def get_bridgeprio(self
, bridge
):
359 return self
.read_file_oneline(
360 '/sys/class/net/%s/bridge/priority' %bridge
)
362 def set_fd(self
, bridge
, fd
):
363 utils
.exec_command('/sbin/brctl setfd %s %s' % (bridge
, fd
))
365 def get_fd(self
, bridge
):
366 return self
.read_value_from_sysfs(
367 '/sys/class/net/%s/bridge/forward_delay'
368 %bridge
, self
.conv_value_to_user
)
370 def set_gcint(self
, bridge
, gcint
):
371 #cmd = '/sbin/brctl setgcint ' + bridge + ' ' + gcint
372 raise Exception('set_gcint not implemented')
374 def set_hello(self
, bridge
, hello
):
375 utils
.exec_command('/sbin/brctl sethello %s %s' % (bridge
, hello
))
377 def get_hello(self
, bridge
):
378 return self
.read_value_from_sysfs('/sys/class/net/%s/bridge/hello_time'
379 %bridge
, self
.conv_value_to_user
)
381 def set_maxage(self
, bridge
, maxage
):
382 utils
.exec_command('/sbin/brctl setmaxage %s %s' % (bridge
, maxage
))
384 def get_maxage(self
, bridge
):
385 return self
.read_value_from_sysfs('/sys/class/net/%s/bridge/max_age'
386 %bridge
, self
.conv_value_to_user
)
388 def set_pathcost(self
, bridge
, port
, pathcost
):
389 utils
.exec_command('/sbin/brctl setpathcost %s %s %s' %
390 (bridge
, port
, pathcost
))
392 def get_pathcost(self
, bridge
, port
):
393 return self
.read_file_oneline('/sys/class/net/%s/brport/path_cost'
396 def set_portprio(self
, bridge
, port
, prio
):
397 utils
.exec_command('/sbin/brctl setportprio %s %s %s' %
398 (bridge
, port
, prio
))
400 def get_portprio(self
, bridge
, port
):
401 return self
.read_file_oneline('/sys/class/net/%s/brport/priority'
404 def set_hashmax(self
, bridge
, hashmax
):
405 utils
.exec_command('/sbin/brctl sethashmax %s %s' % (bridge
, hashmax
))
407 def get_hashmax(self
, bridge
):
408 return self
.read_file_oneline('/sys/class/net/%s/bridge/hash_max'
411 def set_hashel(self
, bridge
, hashel
):
412 utils
.exec_command('/sbin/brctl sethashel %s %s' % (bridge
, hashel
))
414 def get_hashel(self
, bridge
):
415 return self
.read_file_oneline('/sys/class/net/%s/bridge/hash_elasticity'
418 def set_mclmc(self
, bridge
, mclmc
):
419 utils
.exec_command('/sbin/brctl setmclmc %s %s' % (bridge
, mclmc
))
421 def get_mclmc(self
, bridge
):
422 return self
.read_file_oneline(
423 '/sys/class/net/%s/bridge/multicast_last_member_count'
426 def set_mcrouter(self
, bridge
, mcrouter
):
427 utils
.exec_command('/sbin/brctl setmcrouter %s %s' % (bridge
, mcrouter
))
429 def get_mcrouter(self
, bridge
):
430 return self
.read_file_oneline(
431 '/sys/class/net/%s/bridge/multicast_router' %bridge
)
433 def set_mcsnoop(self
, bridge
, mcsnoop
):
434 utils
.exec_command('/sbin/brctl setmcsnoop %s %s' % (bridge
, mcsnoop
))
436 def get_mcsnoop(self
, bridge
):
437 return self
.read_file_oneline(
438 '/sys/class/net/%s/bridge/multicast_snooping' %bridge
)
440 def set_mcsqc(self
, bridge
, mcsqc
):
441 utils
.exec_command('/sbin/brctl setmcsqc %s %s' % (bridge
, mcsqc
))
443 def get_mcsqc(self
, bridge
):
444 return self
.read_file_oneline(
445 '/sys/class/net/%s/bridge/multicast_startup_query_count'
448 def set_mcqifaddr(self
, bridge
, mcqifaddr
):
449 utils
.exec_command('/sbin/brctl setmcqifaddr %s %s' %
452 def get_mcqifaddr(self
, bridge
):
453 return self
.read_file_oneline(
454 '/sys/class/net/%s/bridge/multicast_startup_query_use_ifaddr'
457 def set_mcquerier(self
, bridge
, mcquerier
):
458 utils
.exec_command('/sbin/brctl setmcquerier %s %s' %
461 def get_mcquerier(self
, bridge
):
462 return self
.read_file_oneline(
463 '/sys/class/net/%s/bridge/multicast_querier' %bridge
)
465 def set_mcqv4src(self
, bridge
, vlan
, mcquerier
):
466 if vlan
== 0 or vlan
> 4095:
467 self
.logger
.warn('mcqv4src vlan \'%d\' invalid range' %vlan
)
470 ip
= mcquerier
.split('.')
472 self
.logger
.warn('mcqv4src \'%s\' invalid IPv4 address' %mcquerier
)
475 if not k
.isdigit() or int(k
, 10) < 0 or int(k
, 10) > 255:
476 self
.logger
.warn('mcqv4src \'%s\' invalid IPv4 address' %mcquerier
)
479 utils
.exec_command('/sbin/brctl setmcqv4src %s %d %s' %
480 (bridge
, vlan
, mcquerier
))
482 def del_mcqv4src(self
, bridge
, vlan
):
483 utils
.exec_command('/sbin/brctl delmcqv4src %s %d' % (bridge
, vlan
))
485 def get_mcqv4src(self
, bridge
, vlan
=None):
486 if not self
.supported_command
['showmcqv4src']:
490 mcqout
= utils
.exec_command('/sbin/brctl showmcqv4src %s' % bridge
)
491 except Exception as e
:
493 if 'never heard' in s
:
494 self
.logger
.info('/sbin/brctl showmcqv4src: '
495 'skipping unsupported command')
496 self
.supported_command
['showmcqv4src'] = False
499 if not mcqout
: return {}
500 mcqlines
= mcqout
.splitlines()
501 for l
in mcqlines
[1:]:
503 k
, d
, v
= l
.split('\t')
508 return mcqv4src
.get(vlan
)
511 def set_mclmi(self
, bridge
, mclmi
):
512 utils
.exec_command('/sbin/brctl setmclmi %s %s' % (bridge
, mclmi
))
514 def get_mclmi(self
, bridge
):
515 return self
.read_file_oneline(
516 '/sys/class/net/%s/bridge/multicast_last_member_interval'
519 def set_mcmi(self
, bridge
, mcmi
):
520 utils
.exec_command('/sbin/brctl setmcmi %s %s' % (bridge
, mcmi
))
522 def get_mcmi(self
, bridge
):
523 return self
.read_file_oneline(
524 '/sys/class/net/%s/bridge/multicast_membership_interval'
527 def bridge_exists(self
, bridge
):
528 return os
.path
.exists('/sys/class/net/%s/bridge' %bridge
)
530 def is_bridge_port(self
, ifacename
):
531 return os
.path
.exists('/sys/class/net/%s/brport' %ifacename
)
533 def bridge_port_exists(self
, bridge
, bridgeportname
):
535 return os
.path
.exists('/sys/class/net/%s/brif/%s'
536 %(bridge
, bridgeportname
))
540 def get_bridge_ports(self
, bridgename
):
542 return os
.listdir('/sys/class/net/%s/brif/' %bridgename
)