3 # Copyright 2014 Cumulus Networks, Inc. All rights reserved.
4 # Author: Roopa Prabhu, roopa@cumulusnetworks.com
8 from ifupdown
.iface
import *
9 from ifupdownaddons
.modulebase
import moduleBase
10 from ifupdownaddons
.bridgeutils
import brctl
11 from ifupdownaddons
.iproute2
import iproute2
12 from collections
import Counter
13 import ifupdown
.rtnetlink_api
as rtnetlink_api
18 class bridge(moduleBase
):
19 """ ifupdown2 addon module to configure linux bridges """
21 _modinfo
= { 'mhelp' : 'Bridge configuration module. Supports both ' +
22 'vlan aware and non vlan aware bridges. For the vlan ' +
23 'aware bridge, the port specific attributes must be ' +
24 'specified under the port. And for vlan unaware bridge ' +
25 'port specific attributes must be specified under the ' +
29 {'help' : 'vlan aware bridge. Setting this ' +
30 'attribute to yes enables vlan filtering' +
32 'example' : ['bridge-vlan-aware yes/no']},
34 {'help' : 'bridge ports',
36 'example' : ['bridge-ports swp1.100 swp2.100 swp3.100',
37 'bridge-ports glob swp1-3.100',
38 'bridge-ports regex (swp[1|2|3].100)']},
40 {'help': 'bridge-stp yes/no',
41 'example' : ['bridge-stp no'],
42 'validvals' : ['yes', 'on', 'off', 'no'],
45 {'help': 'bridge priority',
46 'example' : ['bridge-bridgeprio 32768'],
49 {'help': 'bridge ageing',
50 'example' : ['bridge-ageing 300'],
53 { 'help' : 'bridge forward delay',
54 'example' : ['bridge-fd 15'],
58 { 'help' : 'bridge garbage collection interval in secs',
59 'example' : ['bridge-gcint 4'],
62 { 'help' : 'bridge set hello time',
63 'example' : ['bridge-hello 2'],
66 { 'help' : 'bridge set maxage',
67 'example' : ['bridge-maxage 20'],
70 { 'help' : 'bridge set port path costs',
71 'example' : ['bridge-pathcosts swp1=100 swp2=100'],
74 { 'help' : 'bridge port prios',
75 'example' : ['bridge-portprios swp1=32 swp2=32'],
78 { 'help' : 'set multicast last member count',
79 'example' : ['bridge-mclmc 2'],
82 { 'help' : 'set multicast router',
84 'example' : ['bridge-mcrouter 1']},
86 { 'help' : 'set multicast snooping',
88 'example' : ['bridge-mcsnoop 1']},
90 { 'help' : 'set multicast startup query count',
92 'example' : ['bridge-mcsqc 2']},
94 { 'help' : 'set multicast query to use ifaddr',
96 'example' : ['bridge-mcqifaddr 0']},
98 { 'help' : 'set multicast querier',
100 'example' : ['bridge-mcquerier 0']},
102 { 'help' : 'set hash elasticity',
104 'example' : ['bridge-hashel 4096']},
106 { 'help' : 'set hash max',
108 'example' : ['bridge-hashmax 4096']},
110 { 'help' : 'set multicast last member interval (in secs)',
112 'example' : ['bridge-mclmi 1']},
114 { 'help' : 'set multicast membership interval (in secs)',
116 'example' : ['bridge-mcmi 260']},
118 { 'help' : 'set multicast querier interval (in secs)',
120 'example' : ['bridge-mcqpi 255']},
122 { 'help' : 'set multicast query interval (in secs)',
124 'example' : ['bridge-mcqi 125']},
126 { 'help' : 'set multicast query response interval (in secs)',
128 'example' : ['bridge-mcqri 10']},
130 { 'help' : 'set multicast startup query interval (in secs)',
132 'example' : ['bridge-mcsqi 31']},
134 { 'help' : 'set per VLAN v4 multicast querier source address',
136 'example' : ['bridge-mcqv4src 100=172.16.100.1 101=172.16.101.1']},
137 'bridge-portmcrouter' :
138 { 'help' : 'set port multicast routers',
140 'example' : ['under the bridge: bridge-portmcrouter swp1=1 swp2=1',
141 'under the port: bridge-portmcrouter 1']},
143 { 'help' : 'port multicast fast leave.',
145 'example' : ['under the bridge: bridge-portmcfl swp1=0 swp2=0',
146 'under the port: bridge-portmcfl 0']},
148 { 'help' : 'wait for a max of time secs for the' +
149 ' specified ports to become available,' +
150 'if no ports are specified then those' +
151 ' specified on bridge-ports will be' +
152 ' used here. Specifying no ports here ' +
153 'should not be used if we are using ' +
154 'regex or \"all\" on bridge_ports,' +
155 'as it wouldnt work.',
157 'example' : ['bridge-waitport 4 swp1 swp2']},
159 { 'help' : 'forces to time seconds the maximum time ' +
160 'that the Debian bridge setup scripts will ' +
161 'wait for the bridge ports to get to the ' +
162 'forwarding status, doesn\'t allow factional ' +
163 'part. If it is equal to 0 then no waiting' +
166 'example' : ['bridge-maxwait 3']},
168 { 'help' : 'bridge port vids. Can be specified ' +
169 'under the bridge or under the port. ' +
170 'If specified under the bridge the ports ' +
171 'inherit it unless overridden by a ' +
172 'bridge-vids attribuet under the port',
173 'example' : ['bridge-vids 4000',
174 'bridge-vids 2000 2200-3000']},
176 { 'help' : 'bridge port pvid. Must be specified under' +
178 'example' : ['bridge-pvid 1']},
180 { 'help' : 'bridge port access vlan. Must be ' +
181 'specified under the bridge port',
182 'example' : ['bridge-access 300']},
184 { 'help' : 'bridge vlans',
186 'example' : ['bridge-port-vids bond0=1-1000,1010-1020']},
187 'bridge-port-pvids' :
188 { 'help' : 'bridge port vlans',
190 'example' : ['bridge-port-pvids bond0=100 bond1=200']},
193 # declare some ifaceobj priv_flags.
194 # XXX: This assumes that the priv_flags is owned by this module
196 _BRIDGE_PORT_PROCESSED
= 0x1
198 def __init__(self
, *args
, **kargs
):
199 moduleBase
.__init
__(self
, *args
, **kargs
)
202 self
._running
_vidinfo
= {}
203 self
._running
_vidinfo
_valid
= False
204 self
._resv
_vlan
_range
= self
._get
_reserved
_vlan
_range
()
205 self
.logger
.debug('%s: using reserved vlan range %s'
206 %(self
.__class
__.__name
__, str(self
._resv
_vlan
_range
)))
208 def _is_bridge(self
, ifaceobj
):
209 if ifaceobj
.get_attr_value_first('bridge-ports'):
213 def _is_bridge_port(self
, ifaceobj
):
214 if self
.brctlcmd
.is_bridge_port(ifaceobj
.name
):
218 def get_dependent_ifacenames(self
, ifaceobj
, ifacenames_all
=None):
219 if not self
._is
_bridge
(ifaceobj
):
221 if ifaceobj
.link_type
!= ifaceLinkType
.LINK_NA
:
222 ifaceobj
.link_type
= ifaceLinkType
.LINK_MASTER
223 return self
.parse_port_list(ifaceobj
.get_attr_value_first(
224 'bridge-ports'), ifacenames_all
)
226 def get_dependent_ifacenames_running(self
, ifaceobj
):
227 self
._init
_command
_handlers
()
228 if not self
.brctlcmd
.bridge_exists(ifaceobj
.name
):
230 return self
.brctlcmd
.get_bridge_ports(ifaceobj
.name
)
232 def _get_bridge_port_list(self
, ifaceobj
):
234 # port list is also available in the previously
235 # parsed dependent list. Use that if available, instead
236 # of parsing port expr again
237 port_list
= ifaceobj
.lowerifaces
240 ports
= ifaceobj
.get_attr_value_first('bridge-ports')
242 return self
.parse_port_list(ports
)
246 def _process_bridge_waitport(self
, ifaceobj
, portlist
):
247 waitport_value
= ifaceobj
.get_attr_value_first('bridge-waitport')
248 if not waitport_value
: return
250 waitportvals
= re
.split(r
'[\s\t]\s*', waitport_value
, 1)
251 if not waitportvals
: return
253 waitporttime
= int(waitportvals
[0])
255 self
.log_warn('%s: invalid waitport value \'%s\''
256 %(ifaceobj
.name
, waitporttime
))
258 if waitporttime
<= 0: return
260 waitportlist
= self
.parse_port_list(waitportvals
[1])
261 except IndexError, e
:
262 # ignore error and use all bridge ports
263 waitportlist
= portlist
265 if not waitportlist
: return
266 self
.logger
.info('%s: waiting for ports %s to exist ...'
267 %(ifaceobj
.name
, str(waitportlist
)))
268 starttime
= time
.time()
269 while ((time
.time() - starttime
) < waitporttime
):
270 if all([False for p
in waitportlist
271 if not self
.ipcmd
.link_exists(p
)]):
275 self
.log_warn('%s: unable to process waitport: %s'
276 %(ifaceobj
.name
, str(e
)))
278 def _add_ports(self
, ifaceobj
):
279 bridgeports
= self
._get
_bridge
_port
_list
(ifaceobj
)
280 runningbridgeports
= []
282 self
.ipcmd
.batch_start()
283 self
._process
_bridge
_waitport
(ifaceobj
, bridgeports
)
284 self
.ipcmd
.batch_start()
285 # Delete active ports not in the new port list
286 if not self
.PERFMODE
:
287 runningbridgeports
= self
.brctlcmd
.get_bridge_ports(ifaceobj
.name
)
288 if runningbridgeports
:
289 for bport
in runningbridgeports
:
290 if not bridgeports
or bport
not in bridgeports
:
291 self
.ipcmd
.link_set(bport
, 'nomaster')
292 self
.ipcmd
.link_set(bport
, 'down')
294 runningbridgeports
= []
296 self
.ipcmd
.batch_commit()
299 for bridgeport
in Set(bridgeports
).difference(Set(runningbridgeports
)):
301 if not self
.DRYRUN
and not self
.ipcmd
.link_exists(bridgeport
):
302 self
.log_warn('%s: bridge port %s does not exist'
303 %(ifaceobj
.name
, bridgeport
))
306 self
.ipcmd
.link_set(bridgeport
, 'master', ifaceobj
.name
)
307 self
.write_file('/proc/sys/net/ipv6/conf/%s' %bridgeport
+
308 '/disable_ipv6', '1')
309 self
.ipcmd
.addr_flush(bridgeport
)
311 self
.logger
.error(str(e
))
313 self
.ipcmd
.batch_commit()
315 self
.log_error('bridge configuration failed (missing ports)')
317 def _process_bridge_maxwait(self
, ifaceobj
, portlist
):
318 maxwait
= ifaceobj
.get_attr_value_first('bridge-maxwait')
319 if not maxwait
: return
321 maxwait
= int(maxwait
)
323 self
.log_warn('%s: invalid maxwait value \'%s\'' %(ifaceobj
.name
,
326 if not maxwait
: return
327 self
.logger
.info('%s: waiting for ports to go to fowarding state ..'
330 starttime
= time
.time()
331 while ((time
.time() - starttime
) < maxwait
):
332 if all([False for p
in portlist
333 if self
.read_file_oneline(
334 '/sys/class/net/%s/brif/%s/state'
335 %(ifaceobj
.name
, p
)) != '3']):
339 self
.log_warn('%s: unable to process maxwait: %s'
340 %(ifaceobj
.name
, str(e
)))
342 def _ints_to_ranges(self
, ints
):
343 for a
, b
in itertools
.groupby(enumerate(ints
), lambda (x
, y
): y
- x
):
345 yield b
[0][1], b
[-1][1]
347 def _ranges_to_ints(self
, rangelist
):
348 """ returns expanded list of integers given set of string ranges
349 example: ['1', '2-4', '6'] returns [1, 2, 3, 4, 6]
352 for part
in rangelist
:
354 a
, b
= part
.split('-')
355 a
, b
= int(a
), int(b
)
356 result
.extend(range(a
, b
+ 1))
362 def _diff_vids(self
, vids1
, vids2
):
366 vids1_ints
= self
._ranges
_to
_ints
(vids1
)
367 vids2_ints
= self
._ranges
_to
_ints
(vids2
)
368 vids1_diff
= Set(vids1_ints
).difference(vids2_ints
)
369 vids2_diff
= Set(vids2_ints
).difference(vids1_ints
)
371 vids_to_add
= ['%d' %start
if start
== end
else '%d-%d' %(start
, end
)
372 for start
, end
in self
._ints
_to
_ranges
(vids1_diff
)]
374 vids_to_del
= ['%d' %start
if start
== end
else '%d-%d' %(start
, end
)
375 for start
, end
in self
._ints
_to
_ranges
(vids2_diff
)]
376 return (vids_to_del
, vids_to_add
)
378 def _compare_vids(self
, vids1
, vids2
):
379 """ Returns true if the vids are same else return false """
381 vids1_ints
= self
._ranges
_to
_ints
(vids1
)
382 vids2_ints
= self
._ranges
_to
_ints
(vids2
)
383 if Set(vids1_ints
).symmetric_difference(vids2_ints
):
388 def _set_bridge_mcqv4src_compat(self
, ifaceobj
):
390 # Sets old style igmp querier
392 attrval
= ifaceobj
.get_attr_value_first('bridge-mcqv4src')
394 running_mcqv4src
= {}
395 if not self
.PERFMODE
:
396 running_mcqv4src
= self
.brctlcmd
.get_mcqv4src(ifaceobj
.name
)
398 srclist
= attrval
.split()
403 k_to_del
= Set(running_mcqv4src
.keys()).difference(mcqs
.keys())
405 self
.brctlcmd
.del_mcqv4src(ifaceobj
.name
, v
)
406 for v
in mcqs
.keys():
407 self
.brctlcmd
.set_mcqv4src(ifaceobj
.name
, v
, mcqs
[v
])
409 def _get_running_vidinfo(self
):
410 if self
._running
_vidinfo
_valid
:
411 return self
._running
_vidinfo
412 self
._running
_vidinfo
= {}
413 if not self
.PERFMODE
:
414 self
._running
_vidinfo
= self
.ipcmd
.bridge_port_vids_get_all()
415 self
._running
_vidinfo
_valid
= True
416 return self
._running
_vidinfo
418 def _flush_running_vidinfo(self
):
419 self
._running
_vidinfo
= {}
420 self
._running
_vidinfo
_valid
= False
422 def _set_bridge_vidinfo_compat(self
, ifaceobj
):
424 # Supports old style vlan vid info format
428 # Handle bridge vlan attrs
429 running_vidinfo
= self
._get
_running
_vidinfo
()
432 attrval
= ifaceobj
.get_attr_value_first('bridge-port-pvids')
434 portlist
= self
.parse_port_list(attrval
)
436 self
.log_warn('%s: could not parse \'%s %s\''
437 %(ifaceobj
.name
, attrname
, attrval
))
441 (port
, pvid
) = p
.split('=')
442 running_pvid
= running_vidinfo
.get(port
, {}).get('pvid')
444 if running_pvid
== pvid
:
447 self
.ipcmd
.bridge_port_pvid_del(port
, running_pvid
)
448 self
.ipcmd
.bridge_port_pvid_add(port
, pvid
)
450 self
.log_warn('%s: failed to set pvid `%s` (%s)'
451 %(ifaceobj
.name
, p
, str(e
)))
454 attrval
= ifaceobj
.get_attr_value_first('bridge-port-vids')
456 portlist
= self
.parse_port_list(attrval
)
458 self
.log_warn('%s: could not parse \'%s %s\''
459 %(ifaceobj
.name
, attrname
, attrval
))
463 (port
, val
) = p
.split('=')
464 vids
= val
.split(',')
465 if running_vidinfo
.get(port
):
466 (vids_to_del
, vids_to_add
) = \
467 self
._diff
_vids
(vids
,
468 running_vidinfo
.get(port
).get('vlan'))
470 self
.ipcmd
.bridge_port_vids_del(port
, vids_to_del
)
472 self
.ipcmd
.bridge_port_vids_add(port
, vids_to_add
)
474 self
.ipcmd
.bridge_port_vids_add(port
, vids
)
476 self
.log_warn('%s: failed to set vid `%s` (%s)'
477 %(ifaceobj
.name
, p
, str(e
)))
480 # XXX: Commenting out this code for now because it was decided
481 # that this is not needed
482 #attrval = ifaceobj.get_attr_value_first('bridge-vids')
484 # vids = re.split(r'[\s\t]\s*', attrval)
485 # if running_vidinfo.get(ifaceobj.name):
486 # (vids_to_del, vids_to_add) = \
487 # self._diff_vids(vids,
488 # running_vidinfo.get(ifaceobj.name).get('vlan'))
490 # self.ipcmd.bridge_vids_del(ifaceobj.name, vids_to_del)
492 # self.ipcmd.bridge_vids_add(ifaceobj.name, vids_to_add)
494 # self.ipcmd.bridge_vids_add(ifaceobj.name, vids)
496 # running_vids = running_vidinfo.get(ifaceobj.name)
498 # self.ipcmd.bridge_vids_del(ifaceobj.name, running_vids)
500 def _apply_bridge_settings(self
, ifaceobj
):
502 stp
= ifaceobj
.get_attr_value_first('bridge-stp')
504 self
.brctlcmd
.set_stp(ifaceobj
.name
, stp
)
506 # If stp not specified and running stp state on, set it to off
507 running_stp_state
= self
.read_file_oneline(
508 '/sys/class/net/%s/bridge/stp_state' %ifaceobj
.name
)
509 if running_stp_state
and running_stp_state
!= '0':
510 self
.brctlcmd
.set_stp(ifaceobj
.name
, 'no')
512 if ifaceobj
.get_attr_value_first('bridge-vlan-aware') == 'yes':
513 self
.write_file('/sys/class/net/%s/bridge/vlan_filtering'
515 # Use the brctlcmd bulk set method: first build a dictionary
517 bridgeattrs
= { k
:v
for k
,v
in
519 ifaceobj
.get_attr_value_first('bridge-ageing'),
521 ifaceobj
.get_attr_value_first(
522 'bridge-bridgeprio'),
524 ifaceobj
.get_attr_value_first('bridge-fd'),
526 ifaceobj
.get_attr_value_first('bridge-gcint'),
528 ifaceobj
.get_attr_value_first('bridge-hello'),
530 ifaceobj
.get_attr_value_first('bridge-maxage'),
532 ifaceobj
.get_attr_value_first('bridge-mclmc'),
534 ifaceobj
.get_attr_value_first(
537 ifaceobj
.get_attr_value_first('bridge-mcsnoop'),
539 ifaceobj
.get_attr_value_first('bridge-mcsqc'),
541 ifaceobj
.get_attr_value_first(
544 ifaceobj
.get_attr_value_first(
547 ifaceobj
.get_attr_value_first('bridge-hashel'),
549 ifaceobj
.get_attr_value_first('bridge-hashmax'),
551 ifaceobj
.get_attr_value_first('bridge-mclmi'),
553 ifaceobj
.get_attr_value_first('bridge-mcmi'),
555 ifaceobj
.get_attr_value_first('bridge-mcqpi'),
557 ifaceobj
.get_attr_value_first('bridge-mcqi'),
559 ifaceobj
.get_attr_value_first('bridge-mcqri'),
561 ifaceobj
.get_attr_value_first('bridge-mcsqi')
565 self
.brctlcmd
.set_bridge_attrs(ifaceobj
.name
, bridgeattrs
)
567 for attrname
, dstattrname
in {'bridge-pathcosts' : 'pathcost',
568 'bridge-portprios' : 'portprio',
569 'bridge-portmcrouter' : 'portmcrouter',
570 'bridge-portmcfl' : 'portmcfl'}.items():
571 attrval
= ifaceobj
.get_attr_value_first(attrname
)
574 portlist
= self
.parse_port_list(attrval
)
576 self
.log_warn('%s: could not parse \'%s %s\''
577 %(ifaceobj
.name
, attrname
, attrval
))
581 (port
, val
) = p
.split('=')
582 if not portattrs
.get(port
):
584 portattrs
[port
].update({dstattrname
: val
})
586 self
.log_warn('%s: could not parse %s (%s)'
587 %(ifaceobj
.name
, attrname
, str(e
)))
588 for port
, attrdict
in portattrs
.iteritems():
589 self
.brctlcmd
.set_bridgeport_attrs(ifaceobj
.name
, port
,
591 self
._set
_bridge
_vidinfo
_compat
(ifaceobj
)
593 self
._set
_bridge
_mcqv
4src
_compat
(ifaceobj
)
595 self
._process
_bridge
_maxwait
(ifaceobj
,
596 self
._get
_bridge
_port
_list
(ifaceobj
))
598 self
.log_warn(str(e
))
600 def _check_vids(self
, ifaceobj
, vids
):
604 va
, vb
= v
.split('-')
605 va
, vb
= int(va
), int(vb
)
606 if (self
._handle
_reserved
_vlan
(va
, ifaceobj
.name
) or
607 self
._handle
_reserved
_vlan
(vb
, ifaceobj
.name
)):
611 if self
._handle
_reserved
_vlan
(va
, ifaceobj
.name
):
615 def _apply_bridge_vids(self
, bportifaceobj
, vids
, running_vids
, isbridge
):
617 if not self
._check
_vids
(bportifaceobj
, vids
):
620 (vids_to_del
, vids_to_add
) = \
621 self
._diff
_vids
(vids
, running_vids
)
623 self
.ipcmd
.bridge_vids_del(bportifaceobj
.name
,
624 vids_to_del
, isbridge
)
626 self
.ipcmd
.bridge_vids_add(bportifaceobj
.name
,
627 vids_to_add
, isbridge
)
629 self
.ipcmd
.bridge_vids_add(bportifaceobj
.name
, vids
, isbridge
)
631 self
.log_warn('%s: failed to set vid `%s` (%s)'
632 %(bportifaceobj
.name
, str(vids
), str(e
)))
634 def _apply_bridge_port_pvids(self
, bportifaceobj
, pvid
, running_pvid
):
638 if running_pvid
!= pvid
:
639 self
.ipcmd
.bridge_port_pvid_del(bportifaceobj
.name
,
641 self
.ipcmd
.bridge_port_pvid_add(bportifaceobj
.name
, pvid
)
643 self
.ipcmd
.bridge_port_pvid_add(bportifaceobj
.name
, pvid
)
645 self
.log_warn('%s: failed to set pvid `%s` (%s)'
646 %(bportifaceobj
.name
, pvid
, str(e
)))
648 def _apply_bridge_vlan_aware_port_settings_all(self
, bportifaceobj
,
651 running_vidinfo
= self
._get
_running
_vidinfo
()
654 bport_access
= bportifaceobj
.get_attr_value_first('bridge-access')
656 vids
= re
.split(r
'[\s\t]\s*', bport_access
)
659 bport_vids
= bportifaceobj
.get_attr_value_first('bridge-vids')
661 vids
= re
.split(r
'[\s\t,]\s*', bport_vids
)
663 bport_pvids
= bportifaceobj
.get_attr_value_first('bridge-pvid')
665 pvids
= re
.split(r
'[\s\t]\s*', bport_pvids
)
668 self
._apply
_bridge
_port
_pvids
(bportifaceobj
, pvids
[0],
669 running_vidinfo
.get(bportifaceobj
.name
, {}).get('pvid'))
671 self
._apply
_bridge
_port
_pvids
(bportifaceobj
,
672 bridge_pvid
, running_vidinfo
.get(bportifaceobj
.name
,
674 # XXX: default pvid is already one
676 # self._apply_bridge_port_pvids(bportifaceobj,
677 # '1', running_vidinfo.get(bportifaceobj.name,
681 self
._apply
_bridge
_vids
(bportifaceobj
, vids
,
682 running_vidinfo
.get(bportifaceobj
.name
,
683 {}).get('vlan'), False)
685 self
._apply
_bridge
_vids
(bportifaceobj
,
686 bridge_vids
, running_vidinfo
.get(
687 bportifaceobj
.name
, {}).get('vlan'), False)
690 def _apply_bridge_port_settings(self
, bportifaceobj
, bridgename
=None,
691 bridgeifaceobj
=None):
692 if not bridgename
and bridgeifaceobj
:
693 bridgename
= bridgeifaceobj
.name
694 # Set other stp and igmp attributes
696 for attrname
, dstattrname
in {
697 'bridge-pathcosts' : 'pathcost',
698 'bridge-portprios' : 'portprio',
699 'bridge-portmcrouter' : 'portmcrouter',
700 'bridge-portmcfl' : 'portmcfl'}.items():
701 attrval
= bportifaceobj
.get_attr_value_first(attrname
)
703 # Check if bridge has that attribute
705 # attrval = bridgeifaceobj.get_attr_value_first(attrname)
710 portattrs
[dstattrname
] = attrval
712 self
.brctlcmd
.set_bridgeport_attrs(bridgename
,
713 bportifaceobj
.name
, portattrs
)
715 self
.log_warn(str(e
))
717 def _apply_bridge_port_settings_all(self
, ifaceobj
,
718 ifaceobj_getfunc
=None):
719 bridge_vlan_aware
= ifaceobj
.get_attr_value_first(
721 if bridge_vlan_aware
and bridge_vlan_aware
== 'yes':
722 bridge_vlan_aware
= True
724 bridge_vlan_aware
= False
726 if (ifaceobj
.get_attr_value_first('bridge-port-vids') and
727 ifaceobj
.get_attr_value_first('bridge-port-pvids')):
728 # Old style bridge port vid info
729 # skip new style setting on ports
731 self
.logger
.info('%s: applying bridge configuration '
732 %ifaceobj
.name
+ 'specific to ports')
734 bridge_vids
= ifaceobj
.get_attr_value_first('bridge-vids')
736 bridge_vids
= re
.split(r
'[\s\t,]\s*', bridge_vids
)
740 bridge_pvid
= ifaceobj
.get_attr_value_first('bridge-pvid')
742 bridge_pvid
= re
.split(r
'[\s\t]\s*', bridge_pvid
)[0]
746 bridgeports
= self
._get
_bridge
_port
_list
(ifaceobj
)
748 self
.logger
.debug('%s: cannot find bridgeports' %ifaceobj
.name
)
750 for bport
in bridgeports
:
751 # Use the brctlcmd bulk set method: first build a dictionary
753 if not self
.ipcmd
.bridge_port_exists(ifaceobj
.name
, bport
):
754 self
.logger
.info('%s: skipping bridge config' %ifaceobj
.name
+
755 ' for port %s (missing port)' %bport
)
757 self
.logger
.info('%s: processing bridge config for port %s'
758 %(ifaceobj
.name
, bport
))
759 bportifaceobjlist
= ifaceobj_getfunc(bport
)
760 if not bportifaceobjlist
:
762 for bportifaceobj
in bportifaceobjlist
:
763 # Dont process bridge port if it already has been processed
764 if bportifaceobj
.priv_flags
& self
._BRIDGE
_PORT
_PROCESSED
:
767 # Add attributes specific to the vlan aware bridge
768 if bridge_vlan_aware
:
769 self
._apply
_bridge
_vlan
_aware
_port
_settings
_all
(
770 bportifaceobj
, bridge_vids
, bridge_pvid
)
771 self
._apply
_bridge
_port
_settings
(bportifaceobj
,
772 bridgeifaceobj
=ifaceobj
)
774 def _up(self
, ifaceobj
, ifaceobj_getfunc
=None):
775 # Check if bridge port
776 bridgename
= self
.ipcmd
.bridge_port_get_bridge_name(ifaceobj
.name
)
778 if self
.ipcmd
.bridge_is_vlan_aware(bridgename
):
779 bridge_vids
= self
._get
_bridge
_vids
(bridgename
,
781 bridge_pvid
= self
._get
_bridge
_pvid
(bridgename
,
783 self
._apply
_bridge
_vlan
_aware
_port
_settings
_all
(ifaceobj
,
786 self
._apply
_bridge
_port
_settings
(ifaceobj
, bridgename
=bridgename
)
787 ifaceobj
.priv_flags |
= self
._BRIDGE
_PORT
_PROCESSED
789 if not self
._is
_bridge
(ifaceobj
):
795 if not self
.PERFMODE
:
796 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
797 self
.ipcmd
.link_create(ifaceobj
.name
, 'bridge')
799 self
.ipcmd
.link_create(ifaceobj
.name
, 'bridge')
802 self
._add
_ports
(ifaceobj
)
807 self
._apply
_bridge
_settings
(ifaceobj
)
808 self
._apply
_bridge
_port
_settings
_all
(ifaceobj
,
809 ifaceobj_getfunc
=ifaceobj_getfunc
)
810 #self._flush_running_vidinfo()
812 self
.log_error(str(e
))
814 if ifaceobj
.link_type
!= ifaceLinkType
.LINK_NA
:
815 running_ports
= self
.brctlcmd
.get_bridge_ports(ifaceobj
.name
)
816 [rtnetlink_api
.rtnl_api
.link_set(p
, "up")
817 for p
in running_ports
]
818 if link_exists
and ifaceobj
.addr_method
== 'manual':
819 rtnetlink_api
.rtnl_api
.link_set(ifaceobj
.name
, "up")
821 raise Exception(porterrstr
)
823 def _down(self
, ifaceobj
, ifaceobj_getfunc
=None):
825 if ifaceobj
.get_attr_value_first('bridge-ports'):
826 ports
= self
.brctlcmd
.get_bridge_ports(ifaceobj
.name
)
827 self
.brctlcmd
.delete_bridge(ifaceobj
.name
)
830 proc_file
= ('/proc/sys/net/ipv6/conf/%s' %p
+
832 self
.write_file(proc_file
, '0')
833 if ifaceobj
.link_type
== ifaceLinkType
.LINK_MASTER
:
834 rtnetlink_api
.rtnl_api
.link_set(p
, "down")
836 self
.log_error(str(e
))
838 def _query_running_vidinfo_compat(self
, ifaceobjrunning
, ports
):
840 running_vidinfo
= self
._get
_running
_vidinfo
()
842 running_bridge_port_vids
= ''
845 running_vids
= running_vidinfo
.get(p
, {}).get('vlan')
847 running_bridge_port_vids
+= ' %s=%s' %(p
,
848 ','.join(running_vids
))
851 running_attrs
['bridge-port-vids'] = running_bridge_port_vids
853 running_bridge_port_pvids
= ''
856 running_pvids
= running_vidinfo
.get(p
, {}).get('pvid')
858 running_bridge_port_pvids
+= ' %s=%s' %(p
,
862 running_attrs
['bridge-port-pvids'] = running_bridge_port_pvids
864 running_bridge_vids
= running_vidinfo
.get(ifaceobjrunning
.name
,
866 if running_bridge_vids
:
867 running_attrs
['bridge-vids'] = ','.join(running_bridge_vids
)
870 def _query_running_vidinfo(self
, ifaceobjrunning
, ifaceobj_getfunc
,
873 running_vidinfo
= self
._get
_running
_vidinfo
()
874 if not running_vidinfo
:
877 # 'bridge-vids' under the bridge is all about 'vids' on the port.
879 running_bridgeport_vids
= []
880 running_bridgeport_pvids
= []
881 for bport
in bridgeports
:
882 vids
= running_vidinfo
.get(bport
, {}).get('vlan')
884 running_bridgeport_vids
.append(' '.join(vids
))
885 pvids
= running_vidinfo
.get(bport
, {}).get('pvid')
887 running_bridgeport_pvids
.append(pvids
[0])
890 if running_bridgeport_vids
:
891 (vidval
, freq
) = Counter(running_bridgeport_vids
).most_common()[0]
892 if freq
== len(bridgeports
):
893 running_attrs
['bridge-vids'] = vidval
894 bridge_vids
= vidval
.split()
897 if running_bridgeport_pvids
:
898 (vidval
, freq
) = Counter(running_bridgeport_pvids
).most_common()[0]
899 if freq
== len(bridgeports
) and vidval
!= '1':
900 running_attrs
['bridge-pvid'] = vidval
901 bridge_pvid
= vidval
.split()
903 # Go through all bridge ports and find their vids
904 for bport
in bridgeports
:
905 bportifaceobj
= ifaceobj_getfunc(bport
)
906 if not bportifaceobj
:
910 vids
= running_vidinfo
.get(bport
, {}).get('vlan')
911 if vids
and vids
!= bridge_vids
:
913 pvids
= running_vidinfo
.get(bport
, {}).get('pvid')
914 if pvids
and pvids
[0] != bridge_pvid
:
916 if not bport_vids
and bport_pvids
and bport_pvids
[0] != '1':
917 bportifaceobj
[0].replace_config('bridge-access', bport_pvids
[0])
919 if bport_pvids
and bport_pvids
[0] != '1':
920 bportifaceobj
[0].replace_config('bridge-pvid', bport_pvids
[0])
922 # delete any stale bridge-vids under ports
923 bportifaceobj
[0].delete_config('bridge-pvid')
925 bportifaceobj
[0].replace_config('bridge-vids',
926 ' '.join(bport_vids
))
928 # delete any stale bridge-vids under ports
929 bportifaceobj
[0].delete_config('bridge-vids')
932 def _query_running_mcqv4src(self
, ifaceobjrunning
):
933 running_mcqv4src
= self
.brctlcmd
.get_mcqv4src(ifaceobjrunning
.name
)
934 mcqs
= ['%s=%s' %(v
, i
) for v
, i
in running_mcqv4src
.items()]
939 def _query_running_attrs(self
, ifaceobjrunning
, ifaceobj_getfunc
,
940 bridge_vlan_aware
=False):
944 skip_kernel_stp_attrs
= 0
946 if self
.sysctl_get('net.bridge.bridge-stp-user-space') == '1':
949 tmpbridgeattrdict
= self
.brctlcmd
.get_bridge_attrs(ifaceobjrunning
.name
)
950 if not tmpbridgeattrdict
:
951 self
.logger
.warn('%s: unable to get bridge attrs'
952 %ifaceobjrunning
.name
)
953 return bridgeattrdict
955 # Fill bridge_ports and bridge stp attributes first
956 ports
= tmpbridgeattrdict
.get('ports')
958 bridgeattrdict
['bridge-ports'] = [' '.join(ports
.keys())]
959 stp
= tmpbridgeattrdict
.get('stp', 'no')
960 if stp
!= self
.get_mod_subattr('bridge-stp', 'default'):
961 bridgeattrdict
['bridge-stp'] = [stp
]
963 if stp
== 'yes' and userspace_stp
:
964 skip_kernel_stp_attrs
= 1
966 # pick all other attributes
967 for k
,v
in tmpbridgeattrdict
.items():
970 if k
== 'ports' or k
== 'stp':
973 if skip_kernel_stp_attrs
and k
[:2] != 'mc':
974 # only include igmp attributes if kernel stp is off
976 attrname
= 'bridge-' + k
977 if v
!= self
.get_mod_subattr(attrname
, 'default'):
978 bridgeattrdict
[attrname
] = [v
]
980 if bridge_vlan_aware
:
981 bridgevidinfo
= self
._query
_running
_vidinfo
(ifaceobjrunning
,
985 bridgevidinfo
= self
._query
_running
_vidinfo
_compat
(ifaceobjrunning
,
988 bridgeattrdict
.update({k
: [v
] for k
, v
in bridgevidinfo
.items()
991 mcq
= self
._query
_running
_mcqv
4src
(ifaceobjrunning
)
993 bridgeattrdict
['bridge-mcqv4src'] = [mcq
]
995 if skip_kernel_stp_attrs
:
996 return bridgeattrdict
999 portconfig
= {'bridge-pathcosts' : '',
1000 'bridge-portprios' : ''}
1001 for p
, v
in ports
.items():
1002 v
= self
.brctlcmd
.get_pathcost(ifaceobjrunning
.name
, p
)
1003 if v
and v
!= self
.get_mod_subattr('bridge-pathcosts',
1005 portconfig
['bridge-pathcosts'] += ' %s=%s' %(p
, v
)
1007 v
= self
.brctlcmd
.get_portprio(ifaceobjrunning
.name
, p
)
1008 if v
and v
!= self
.get_mod_subattr('bridge-portprios',
1010 portconfig
['bridge-portprios'] += ' %s=%s' %(p
, v
)
1012 bridgeattrdict
.update({k
: [v
] for k
, v
in portconfig
.items()
1015 return bridgeattrdict
1017 def _query_check_mcqv4src(self
, ifaceobj
, ifaceobjcurr
):
1018 running_mcqs
= self
._query
_running
_mcqv
4src
(ifaceobj
)
1019 attrval
= ifaceobj
.get_attr_value_first('bridge-mcqv4src')
1021 mcqs
= attrval
.split()
1023 mcqsout
= ' '.join(mcqs
)
1024 ifaceobjcurr
.update_config_with_status('bridge-mcqv4src',
1025 running_mcqs
, 1 if running_mcqs
!= mcqsout
else 0)
1027 def _query_check_bridge_vidinfo(self
, ifaceobj
, ifaceobjcurr
):
1029 running_vidinfo
= self
._get
_running
_vidinfo
()
1030 attrval
= ifaceobj
.get_attr_value_first('bridge-port-vids')
1032 running_bridge_port_vids
= ''
1033 portlist
= self
.parse_port_list(attrval
)
1035 self
.log_warn('%s: could not parse \'%s %s\''
1036 %(ifaceobj
.name
, attrname
, attrval
))
1041 (port
, val
) = p
.split('=')
1042 vids
= val
.split(',')
1043 running_vids
= running_vidinfo
.get(port
, {}).get('vlan')
1045 if not self
._compare
_vids
(vids
, running_vids
):
1047 running_bridge_port_vids
+= ' %s=%s' %(port
,
1048 ','.join(running_vids
))
1050 running_bridge_port_vids
+= ' %s' %p
1053 except Exception, e
:
1054 self
.log_warn('%s: failure checking vid %s (%s)'
1055 %(ifaceobj
.name
, p
, str(e
)))
1057 ifaceobjcurr
.update_config_with_status('bridge-port-vids',
1058 running_bridge_port_vids
, 1)
1060 ifaceobjcurr
.update_config_with_status('bridge-port-vids',
1063 attrval
= ifaceobj
.get_attr_value_first('bridge-port-pvids')
1065 portlist
= self
.parse_port_list(attrval
)
1067 self
.log_warn('%s: could not parse \'%s %s\''
1068 %(ifaceobj
.name
, attrname
, attrval
))
1070 running_bridge_port_pvids
= ''
1074 (port
, pvid
) = p
.split('=')
1075 running_pvid
= running_vidinfo
.get(port
, {}).get('pvid')
1076 if running_pvid
and running_pvid
== pvid
:
1077 running_bridge_port_pvids
+= ' %s' %p
1080 running_bridge_port_pvids
+= ' %s=%s' %(port
,
1082 except Exception, e
:
1083 self
.log_warn('%s: failure checking pvid %s (%s)'
1084 %(ifaceobj
.name
, pvid
, str(e
)))
1086 ifaceobjcurr
.update_config_with_status('bridge-port-pvids',
1087 running_bridge_port_pvids
, 1)
1089 ifaceobjcurr
.update_config_with_status('bridge-port-pvids',
1090 running_bridge_port_pvids
, 0)
1092 # XXX: No need to check for bridge-vids on the bridge
1093 # This is used by the ports. The vids on the bridge
1094 # come from the vlan interfaces on the bridge.
1096 attrval
= ifaceobj
.get_attr_value_first('bridge-vids')
1098 # vids = re.split(r'[\s\t]\s*', attrval)
1099 # running_vids = running_vidinfo.get(ifaceobj.name, {}).get('vlan')
1101 # if self._compare_vids(vids, running_vids):
1102 # ifaceobjcurr.update_config_with_status('bridge-vids',
1105 # ifaceobjcurr.update_config_with_status('bridge-vids',
1106 # ','.join(running_vids), 1)
1108 # ifaceobjcurr.update_config_with_status('bridge-vids', attrval,
1111 ifaceobjcurr
.update_config_with_status('bridge-vids', attrval
, -1)
1113 def _query_check_bridge(self
, ifaceobj
, ifaceobjcurr
,
1114 ifaceobj_getfunc
=None):
1115 if not self
._is
_bridge
(ifaceobj
):
1117 if not self
.brctlcmd
.bridge_exists(ifaceobj
.name
):
1118 self
.logger
.info('%s: bridge: does not exist' %(ifaceobj
.name
))
1121 ifaceattrs
= self
.dict_key_subset(ifaceobj
.config
,
1122 self
.get_mod_attrs())
1126 runningattrs
= self
.brctlcmd
.get_bridge_attrs(ifaceobj
.name
)
1127 if not runningattrs
:
1128 self
.logger
.debug('%s: bridge: unable to get bridge attrs'
1131 except Exception, e
:
1132 self
.logger
.warn(str(e
))
1134 filterattrs
= ['bridge-vids', 'bridge-port-vids',
1135 'bridge-port-pvids']
1136 for k
in Set(ifaceattrs
).difference(filterattrs
):
1137 # get the corresponding ifaceobj attr
1138 v
= ifaceobj
.get_attr_value_first(k
)
1141 rv
= runningattrs
.get(k
[7:])
1142 if k
== 'bridge-mcqv4src':
1144 if k
== 'bridge-vlan-aware' and v
== 'yes':
1145 if self
.ipcmd
.bridge_is_vlan_aware(ifaceobj
.name
):
1146 ifaceobjcurr
.update_config_with_status('bridge-vlan-aware',
1149 ifaceobjcurr
.update_config_with_status('bridge-vlan-aware',
1151 elif k
== 'bridge-stp':
1152 # special case stp compare because it may
1153 # contain more than one valid values
1154 stp_on_vals
= ['on', 'yes']
1155 stp_off_vals
= ['off']
1156 if ((v
in stp_on_vals
and rv
in stp_on_vals
) or
1157 (v
in stp_off_vals
and rv
in stp_off_vals
)):
1158 ifaceobjcurr
.update_config_with_status('bridge-stp',
1161 ifaceobjcurr
.update_config_with_status('bridge-stp',
1163 elif k
== 'bridge-ports':
1164 # special case ports because it can contain regex or glob
1165 running_port_list
= rv
.keys() if rv
else []
1166 bridge_port_list
= self
._get
_bridge
_port
_list
(ifaceobj
)
1167 if not running_port_list
and not bridge_port_list
:
1170 if running_port_list
and bridge_port_list
:
1171 difference
= set(running_port_list
1172 ).symmetric_difference(bridge_port_list
)
1175 ifaceobjcurr
.update_config_with_status('bridge-ports',
1176 ' '.join(running_port_list
)
1177 if running_port_list
else '', portliststatus
)
1178 elif (k
== 'bridge-pathcosts' or
1179 k
== 'bridge-portprios' or k
== 'bridge-portmcrouter'
1180 or k
== 'bridge-portmcfl'):
1181 brctlcmdattrname
= k
[11:].rstrip('s')
1182 # for port attributes, the attributes are in a list
1183 # <portname>=<portattrvalue>
1186 vlist
= self
.parse_port_list(v
)
1189 for vlistitem
in vlist
:
1191 (p
, v
) = vlistitem
.split('=')
1192 currv
= self
.brctlcmd
.get_bridgeport_attr(
1196 currstr
+= ' %s=%s' %(p
, currv
)
1198 currstr
+= ' %s=%s' %(p
, 'None')
1201 except Exception, e
:
1202 self
.log_warn(str(e
))
1204 ifaceobjcurr
.update_config_with_status(k
, currstr
, status
)
1206 ifaceobjcurr
.update_config_with_status(k
, 'notfound', 1)
1209 ifaceobjcurr
.update_config_with_status(k
, rv
, 1)
1211 ifaceobjcurr
.update_config_with_status(k
, rv
, 0)
1213 self
._query
_check
_bridge
_vidinfo
(ifaceobj
, ifaceobjcurr
)
1215 self
._query
_check
_mcqv
4src
(ifaceobj
, ifaceobjcurr
)
1217 def _get_bridge_vids(self
, bridgename
, ifaceobj_getfunc
):
1218 ifaceobjs
= ifaceobj_getfunc(bridgename
)
1219 for ifaceobj
in ifaceobjs
:
1220 vids
= ifaceobj
.get_attr_value_first('bridge-vids')
1221 if vids
: return re
.split(r
'[\s\t,]\s*', vids
)
1224 def _get_bridge_pvid(self
, bridgename
, ifaceobj_getfunc
):
1225 ifaceobjs
= ifaceobj_getfunc(bridgename
)
1227 for ifaceobj
in ifaceobjs
:
1228 pvid
= ifaceobj
.get_attr_value_first('bridge-pvid')
1231 def _get_bridge_name(self
, ifaceobj
):
1232 return self
.ipcmd
.bridge_port_get_bridge_name(ifaceobj
.name
)
1234 def _query_check_bridge_port_vidinfo(self
, ifaceobj
, ifaceobjcurr
,
1235 ifaceobj_getfunc
, bridgename
):
1236 running_vidinfo
= self
._get
_running
_vidinfo
()
1238 attr_name
= 'bridge-access'
1239 vids
= ifaceobj
.get_attr_value_first(attr_name
)
1241 running_pvids
= running_vidinfo
.get(ifaceobj
.name
,
1243 running_vids
= running_vidinfo
.get(ifaceobj
.name
,
1245 if (not running_pvids
or running_pvids
!= vids
or
1247 ifaceobjcurr
.update_config_with_status(attr_name
,
1250 ifaceobjcurr
.update_config_with_status(attr_name
, vids
, 0)
1253 attr_name
= 'bridge-vids'
1254 vids
= ifaceobj
.get_attr_value_first(attr_name
)
1256 vids
= re
.split(r
'[\s\t]\s*', vids
)
1257 running_vids
= running_vidinfo
.get(ifaceobj
.name
,
1259 if not running_vids
or not self
._compare
_vids
(vids
, running_vids
):
1260 ifaceobjcurr
.update_config_with_status(attr_name
,
1261 ' '.join(running_vids
), 1)
1263 ifaceobjcurr
.update_config_with_status(attr_name
,
1264 ' '.join(running_vids
), 0)
1266 # check if it matches the bridge vids
1267 bridge_vids
= self
._get
_bridge
_vids
(bridgename
, ifaceobj_getfunc
)
1268 running_vids
= running_vidinfo
.get(ifaceobj
.name
,
1270 if (bridge_vids
and (not running_vids
or
1271 not self
._compare
_vids
(bridge_vids
, running_vids
))):
1272 ifaceobjcurr
.status
= ifaceStatus
.ERROR
1273 ifaceobjcurr
.status_str
= 'bridge vid error'
1275 running_pvid
= running_vidinfo
.get(ifaceobj
.name
,
1277 attr_name
= 'bridge-pvid'
1278 pvid
= ifaceobj
.get_attr_value_first(attr_name
)
1280 if running_pvid
and running_pvid
== pvid
:
1281 ifaceobjcurr
.update_config_with_status(attr_name
,
1284 ifaceobjcurr
.update_config_with_status(attr_name
,
1286 elif not running_pvid
or running_pvid
!= '1':
1287 ifaceobjcurr
.status
= ifaceStatus
.ERROR
1288 ifaceobjcurr
.status_str
= 'bridge pvid error'
1290 def _query_check_bridge_port(self
, ifaceobj
, ifaceobjcurr
,
1292 if not self
._is
_bridge
_port
(ifaceobj
):
1293 # Mark all bridge attributes as failed
1294 ifaceobjcurr
.check_n_update_config_with_status_many(ifaceobj
,
1295 ['bridge-vids', 'bridge-pvid', 'bridge-access',
1296 'bridge-pathcosts', 'bridge-portprios',
1297 'bridge-portmcrouter',
1298 'bridge-portmcfl'], 1)
1300 bridgename
= self
._get
_bridge
_name
(ifaceobj
)
1302 self
.logger
.warn('%s: unable to determine bridge name'
1306 if self
.ipcmd
.bridge_is_vlan_aware(bridgename
):
1307 self
._query
_check
_bridge
_port
_vidinfo
(ifaceobj
, ifaceobjcurr
,
1310 for attr
, dstattr
in {'bridge-pathcosts' : 'pathcost',
1311 'bridge-portprios' : 'priority',
1312 'bridge-portmcrouter' : 'mcrouter',
1313 'bridge-portmcfl' : 'mcfl' }.items():
1314 attrval
= ifaceobj
.get_attr_value_first(attr
)
1319 running_attrval
= self
.brctlcmd
.get_bridgeport_attr(
1320 bridgename
, ifaceobj
.name
, dstattr
)
1321 if running_attrval
!= attrval
:
1322 ifaceobjcurr
.update_config_with_status(attr
,
1325 ifaceobjcurr
.update_config_with_status(attr
,
1327 except Exception, e
:
1328 self
.log_warn('%s: %s' %(ifaceobj
.name
, str(e
)))
1330 def _query_check(self
, ifaceobj
, ifaceobjcurr
, ifaceobj_getfunc
=None):
1331 if self
._is
_bridge
(ifaceobj
):
1332 self
._query
_check
_bridge
(ifaceobj
, ifaceobjcurr
)
1334 self
._query
_check
_bridge
_port
(ifaceobj
, ifaceobjcurr
,
1337 def _query_running_bridge(self
, ifaceobjrunning
, ifaceobj_getfunc
):
1338 if self
.ipcmd
.bridge_is_vlan_aware(ifaceobjrunning
.name
):
1339 ifaceobjrunning
.update_config('bridge-vlan-aware', 'yes')
1340 ifaceobjrunning
.update_config_dict(self
._query
_running
_attrs
(
1343 bridge_vlan_aware
=True))
1345 ifaceobjrunning
.update_config_dict(self
._query
_running
_attrs
(
1346 ifaceobjrunning
, None))
1348 def _query_running_bridge_port_attrs(self
, ifaceobjrunning
, bridgename
):
1349 if self
.sysctl_get('net.bridge.bridge-stp-user-space') == '1':
1352 v
= self
.brctlcmd
.get_pathcost(bridgename
, ifaceobjrunning
.name
)
1353 if v
and v
!= self
.get_mod_subattr('bridge-pathcosts', 'default'):
1354 ifaceobjrunning
.update_config('bridge-pathcosts', v
)
1356 v
= self
.brctlcmd
.get_pathcost(bridgename
, ifaceobjrunning
.name
)
1357 if v
and v
!= self
.get_mod_subattr('bridge-portprios', 'default'):
1358 ifaceobjrunning
.update_config('bridge-portprios', v
)
1360 def _query_running_bridge_port(self
, ifaceobjrunning
,
1361 ifaceobj_getfunc
=None):
1362 bridgename
= self
.ipcmd
.bridge_port_get_bridge_name(
1363 ifaceobjrunning
.name
)
1367 self
.logger
.warn('%s: unable to find bridgename'
1368 %ifaceobjrunning
.name
)
1370 if not self
.ipcmd
.bridge_is_vlan_aware(bridgename
):
1373 running_vidinfo
= self
._get
_running
_vidinfo
()
1374 bridge_port_vids
= running_vidinfo
.get(ifaceobjrunning
.name
,
1376 bridge_port_pvid
= running_vidinfo
.get(ifaceobjrunning
.name
,
1379 bridgeifaceobjlist
= ifaceobj_getfunc(bridgename
)
1380 if bridgeifaceobjlist
:
1381 bridge_vids
= bridgeifaceobjlist
[0].get_attr_value('bridge-vids')
1382 bridge_pvid
= bridgeifaceobjlist
[0].get_attr_value_first('bridge-pvid')
1384 if not bridge_port_vids
and bridge_port_pvid
:
1385 # must be an access port
1386 if bridge_port_pvid
!= '1':
1387 ifaceobjrunning
.update_config('bridge-access',
1390 if bridge_port_vids
:
1391 if (not bridge_vids
or bridge_port_vids
!= bridge_vids
):
1392 ifaceobjrunning
.update_config('bridge-vids',
1393 ' '.join(bridge_port_vids
))
1394 if bridge_port_pvid
and bridge_port_pvid
!= '1':
1395 if (not bridge_pvid
or (bridge_port_pvid
!= bridge_pvid
)):
1396 ifaceobjrunning
.update_config('bridge-pvid',
1398 self
._query
_running
_bridge
_port
_attrs
(ifaceobjrunning
, bridgename
)
1400 def _query_running(self
, ifaceobjrunning
, ifaceobj_getfunc
=None):
1401 if self
.brctlcmd
.bridge_exists(ifaceobjrunning
.name
):
1402 self
._query
_running
_bridge
(ifaceobjrunning
, ifaceobj_getfunc
)
1403 elif self
.brctlcmd
.is_bridge_port(ifaceobjrunning
.name
):
1404 self
._query
_running
_bridge
_port
(ifaceobjrunning
, ifaceobj_getfunc
)
1406 _run_ops
= {'pre-up' : _up
,
1407 'post-down' : _down
,
1408 'query-checkcurr' : _query_check
,
1409 'query-running' : _query_running
}
1412 """ returns list of ops supported by this module """
1413 return self
._run
_ops
.keys()
1415 def _init_command_handlers(self
):
1416 flags
= self
.get_flags()
1418 self
.ipcmd
= iproute2(**flags
)
1419 if not self
.brctlcmd
:
1420 self
.brctlcmd
= brctl(**flags
)
1422 def run(self
, ifaceobj
, operation
, query_ifaceobj
=None,
1423 ifaceobj_getfunc
=None):
1424 """ run bridge configuration on the interface object passed as
1425 argument. Can create bridge interfaces if they dont exist already
1428 **ifaceobj** (object): iface object
1430 **operation** (str): any of 'pre-up', 'post-down', 'query-checkcurr',
1434 **query_ifaceobj** (object): query check ifaceobject. This is only
1435 valid when op is 'query-checkcurr'. It is an object same as
1436 ifaceobj, but contains running attribute values and its config
1437 status. The modules can use it to return queried running state
1438 of interfaces. status is success if the running state is same
1439 as user required state in ifaceobj. error otherwise.
1441 op_handler
= self
._run
_ops
.get(operation
)
1444 self
._init
_command
_handlers
()
1445 self
._flush
_running
_vidinfo
()
1446 if operation
== 'query-checkcurr':
1447 op_handler(self
, ifaceobj
, query_ifaceobj
,
1448 ifaceobj_getfunc
=ifaceobj_getfunc
)
1450 op_handler(self
, ifaceobj
, ifaceobj_getfunc
=ifaceobj_getfunc
)