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 ifaceobj
.link_kind
= ifaceLinkKind
.BRIDGE
224 return self
.parse_port_list(ifaceobj
.get_attr_value_first(
225 'bridge-ports'), ifacenames_all
)
227 def get_dependent_ifacenames_running(self
, ifaceobj
):
228 self
._init
_command
_handlers
()
229 if not self
.brctlcmd
.bridge_exists(ifaceobj
.name
):
231 return self
.brctlcmd
.get_bridge_ports(ifaceobj
.name
)
233 def _get_bridge_port_list(self
, ifaceobj
):
235 # port list is also available in the previously
236 # parsed dependent list. Use that if available, instead
237 # of parsing port expr again
238 port_list
= ifaceobj
.lowerifaces
241 ports
= ifaceobj
.get_attr_value_first('bridge-ports')
243 return self
.parse_port_list(ports
)
247 def _process_bridge_waitport(self
, ifaceobj
, portlist
):
248 waitport_value
= ifaceobj
.get_attr_value_first('bridge-waitport')
249 if not waitport_value
: return
251 waitportvals
= re
.split(r
'[\s\t]\s*', waitport_value
, 1)
252 if not waitportvals
: return
254 waitporttime
= int(waitportvals
[0])
256 self
.log_warn('%s: invalid waitport value \'%s\''
257 %(ifaceobj
.name
, waitporttime
))
259 if waitporttime
<= 0: return
261 waitportlist
= self
.parse_port_list(waitportvals
[1])
262 except IndexError, e
:
263 # ignore error and use all bridge ports
264 waitportlist
= portlist
266 if not waitportlist
: return
267 self
.logger
.info('%s: waiting for ports %s to exist ...'
268 %(ifaceobj
.name
, str(waitportlist
)))
269 starttime
= time
.time()
270 while ((time
.time() - starttime
) < waitporttime
):
271 if all([False for p
in waitportlist
272 if not self
.ipcmd
.link_exists(p
)]):
276 self
.log_warn('%s: unable to process waitport: %s'
277 %(ifaceobj
.name
, str(e
)))
279 def _ports_enable_disable_ipv6(self
, ports
, enable
='1'):
282 self
.write_file('/proc/sys/net/ipv6/conf/%s' %p
+
283 '/disable_ipv6', enable
)
285 self
.logger
.info(str(e
))
288 def _add_ports(self
, ifaceobj
):
289 bridgeports
= self
._get
_bridge
_port
_list
(ifaceobj
)
290 runningbridgeports
= []
291 removedbridgeports
= []
293 self
.ipcmd
.batch_start()
294 self
._process
_bridge
_waitport
(ifaceobj
, bridgeports
)
295 self
.ipcmd
.batch_start()
296 # Delete active ports not in the new port list
297 if not self
.PERFMODE
:
298 runningbridgeports
= self
.brctlcmd
.get_bridge_ports(ifaceobj
.name
)
299 if runningbridgeports
:
300 for bport
in runningbridgeports
:
301 if not bridgeports
or bport
not in bridgeports
:
302 self
.ipcmd
.link_set(bport
, 'nomaster')
303 removedbridgeports
.append(bport
)
305 runningbridgeports
= []
307 self
.ipcmd
.batch_commit()
310 for bridgeport
in Set(bridgeports
).difference(Set(runningbridgeports
)):
312 if not self
.DRYRUN
and not self
.ipcmd
.link_exists(bridgeport
):
313 self
.log_warn('%s: bridge port %s does not exist'
314 %(ifaceobj
.name
, bridgeport
))
317 hwaddress
= self
.ipcmd
.link_get_hwaddress(bridgeport
)
318 if not self
._valid
_ethaddr
(hwaddress
):
319 self
.log_warn('%s: skipping port %s, ' %(ifaceobj
.name
,
320 bridgeport
) + 'invalid ether addr %s'
323 self
.ipcmd
.link_set(bridgeport
, 'master', ifaceobj
.name
)
324 self
.ipcmd
.addr_flush(bridgeport
)
326 self
.logger
.error(str(e
))
329 self
.ipcmd
.batch_commit()
331 self
.logger
.error(str(e
))
334 # enable ipv6 for ports that were removed
335 self
._ports
_enable
_disable
_ipv
6(removedbridgeports
, '0')
337 self
.log_error('bridge configuration failed (missing ports)')
340 def _process_bridge_maxwait(self
, ifaceobj
, portlist
):
341 maxwait
= ifaceobj
.get_attr_value_first('bridge-maxwait')
342 if not maxwait
: return
344 maxwait
= int(maxwait
)
346 self
.log_warn('%s: invalid maxwait value \'%s\'' %(ifaceobj
.name
,
349 if not maxwait
: return
350 self
.logger
.info('%s: waiting for ports to go to fowarding state ..'
353 starttime
= time
.time()
354 while ((time
.time() - starttime
) < maxwait
):
355 if all([False for p
in portlist
356 if self
.read_file_oneline(
357 '/sys/class/net/%s/brif/%s/state'
358 %(ifaceobj
.name
, p
)) != '3']):
362 self
.log_warn('%s: unable to process maxwait: %s'
363 %(ifaceobj
.name
, str(e
)))
365 def _ints_to_ranges(self
, ints
):
366 for a
, b
in itertools
.groupby(enumerate(ints
), lambda (x
, y
): y
- x
):
368 yield b
[0][1], b
[-1][1]
370 def _ranges_to_ints(self
, rangelist
):
371 """ returns expanded list of integers given set of string ranges
372 example: ['1', '2-4', '6'] returns [1, 2, 3, 4, 6]
375 for part
in rangelist
:
377 a
, b
= part
.split('-')
378 a
, b
= int(a
), int(b
)
379 result
.extend(range(a
, b
+ 1))
385 def _diff_vids(self
, vids1
, vids2
):
389 vids1_ints
= self
._ranges
_to
_ints
(vids1
)
390 vids2_ints
= self
._ranges
_to
_ints
(vids2
)
391 vids1_diff
= Set(vids1_ints
).difference(vids2_ints
)
392 vids2_diff
= Set(vids2_ints
).difference(vids1_ints
)
394 vids_to_add
= ['%d' %start
if start
== end
else '%d-%d' %(start
, end
)
395 for start
, end
in self
._ints
_to
_ranges
(vids1_diff
)]
397 vids_to_del
= ['%d' %start
if start
== end
else '%d-%d' %(start
, end
)
398 for start
, end
in self
._ints
_to
_ranges
(vids2_diff
)]
399 return (vids_to_del
, vids_to_add
)
401 def _compare_vids(self
, vids1
, vids2
):
402 """ Returns true if the vids are same else return false """
404 vids1_ints
= self
._ranges
_to
_ints
(vids1
)
405 vids2_ints
= self
._ranges
_to
_ints
(vids2
)
406 if Set(vids1_ints
).symmetric_difference(vids2_ints
):
411 def _set_bridge_mcqv4src_compat(self
, ifaceobj
):
413 # Sets old style igmp querier
415 attrval
= ifaceobj
.get_attr_value_first('bridge-mcqv4src')
417 running_mcqv4src
= {}
418 if not self
.PERFMODE
:
419 running_mcqv4src
= self
.brctlcmd
.get_mcqv4src(ifaceobj
.name
)
421 srclist
= attrval
.split()
426 k_to_del
= Set(running_mcqv4src
.keys()).difference(mcqs
.keys())
428 self
.brctlcmd
.del_mcqv4src(ifaceobj
.name
, v
)
429 for v
in mcqs
.keys():
430 self
.brctlcmd
.set_mcqv4src(ifaceobj
.name
, v
, mcqs
[v
])
432 def _get_running_vidinfo(self
):
433 if self
._running
_vidinfo
_valid
:
434 return self
._running
_vidinfo
435 self
._running
_vidinfo
= {}
436 if not self
.PERFMODE
:
437 self
._running
_vidinfo
= self
.ipcmd
.bridge_port_vids_get_all()
438 self
._running
_vidinfo
_valid
= True
439 return self
._running
_vidinfo
441 def _flush_running_vidinfo(self
):
442 self
._running
_vidinfo
= {}
443 self
._running
_vidinfo
_valid
= False
445 def _set_bridge_vidinfo_compat(self
, ifaceobj
):
447 # Supports old style vlan vid info format
451 # Handle bridge vlan attrs
452 running_vidinfo
= self
._get
_running
_vidinfo
()
455 attrval
= ifaceobj
.get_attr_value_first('bridge-port-pvids')
457 portlist
= self
.parse_port_list(attrval
)
459 self
.log_warn('%s: could not parse \'%s %s\''
460 %(ifaceobj
.name
, attrname
, attrval
))
464 (port
, pvid
) = p
.split('=')
465 running_pvid
= running_vidinfo
.get(port
, {}).get('pvid')
467 if running_pvid
== pvid
:
470 self
.ipcmd
.bridge_port_pvid_del(port
, running_pvid
)
471 self
.ipcmd
.bridge_port_pvid_add(port
, pvid
)
473 self
.log_warn('%s: failed to set pvid `%s` (%s)'
474 %(ifaceobj
.name
, p
, str(e
)))
477 attrval
= ifaceobj
.get_attr_value_first('bridge-port-vids')
479 portlist
= self
.parse_port_list(attrval
)
481 self
.log_warn('%s: could not parse \'%s %s\''
482 %(ifaceobj
.name
, attrname
, attrval
))
486 (port
, val
) = p
.split('=')
487 vids
= val
.split(',')
488 if running_vidinfo
.get(port
):
489 (vids_to_del
, vids_to_add
) = \
490 self
._diff
_vids
(vids
,
491 running_vidinfo
.get(port
).get('vlan'))
493 self
.ipcmd
.bridge_port_vids_del(port
, vids_to_del
)
495 self
.ipcmd
.bridge_port_vids_add(port
, vids_to_add
)
497 self
.ipcmd
.bridge_port_vids_add(port
, vids
)
499 self
.log_warn('%s: failed to set vid `%s` (%s)'
500 %(ifaceobj
.name
, p
, str(e
)))
503 # XXX: Commenting out this code for now because it was decided
504 # that this is not needed
505 #attrval = ifaceobj.get_attr_value_first('bridge-vids')
507 # vids = re.split(r'[\s\t]\s*', attrval)
508 # if running_vidinfo.get(ifaceobj.name):
509 # (vids_to_del, vids_to_add) = \
510 # self._diff_vids(vids,
511 # running_vidinfo.get(ifaceobj.name).get('vlan'))
513 # self.ipcmd.bridge_vids_del(ifaceobj.name, vids_to_del)
515 # self.ipcmd.bridge_vids_add(ifaceobj.name, vids_to_add)
517 # self.ipcmd.bridge_vids_add(ifaceobj.name, vids)
519 # running_vids = running_vidinfo.get(ifaceobj.name)
521 # self.ipcmd.bridge_vids_del(ifaceobj.name, running_vids)
523 def _apply_bridge_settings(self
, ifaceobj
):
525 stp
= ifaceobj
.get_attr_value_first('bridge-stp')
527 self
.brctlcmd
.set_stp(ifaceobj
.name
, stp
)
529 # If stp not specified and running stp state on, set it to off
530 running_stp_state
= self
.read_file_oneline(
531 '/sys/class/net/%s/bridge/stp_state' %ifaceobj
.name
)
532 if running_stp_state
and running_stp_state
!= '0':
533 self
.brctlcmd
.set_stp(ifaceobj
.name
, 'no')
535 if ifaceobj
.get_attr_value_first('bridge-vlan-aware') == 'yes':
536 self
.write_file('/sys/class/net/%s/bridge/vlan_filtering'
538 # Use the brctlcmd bulk set method: first build a dictionary
540 bridgeattrs
= { k
:v
for k
,v
in
542 ifaceobj
.get_attr_value_first('bridge-ageing'),
544 ifaceobj
.get_attr_value_first(
545 'bridge-bridgeprio'),
547 ifaceobj
.get_attr_value_first('bridge-fd'),
549 ifaceobj
.get_attr_value_first('bridge-gcint'),
551 ifaceobj
.get_attr_value_first('bridge-hello'),
553 ifaceobj
.get_attr_value_first('bridge-maxage'),
555 ifaceobj
.get_attr_value_first('bridge-mclmc'),
557 ifaceobj
.get_attr_value_first(
560 ifaceobj
.get_attr_value_first('bridge-mcsnoop'),
562 ifaceobj
.get_attr_value_first('bridge-mcsqc'),
564 ifaceobj
.get_attr_value_first(
567 ifaceobj
.get_attr_value_first(
570 ifaceobj
.get_attr_value_first('bridge-hashel'),
572 ifaceobj
.get_attr_value_first('bridge-hashmax'),
574 ifaceobj
.get_attr_value_first('bridge-mclmi'),
576 ifaceobj
.get_attr_value_first('bridge-mcmi'),
578 ifaceobj
.get_attr_value_first('bridge-mcqpi'),
580 ifaceobj
.get_attr_value_first('bridge-mcqi'),
582 ifaceobj
.get_attr_value_first('bridge-mcqri'),
584 ifaceobj
.get_attr_value_first('bridge-mcsqi')
588 self
.brctlcmd
.set_bridge_attrs(ifaceobj
.name
, bridgeattrs
)
590 for attrname
, dstattrname
in {'bridge-pathcosts' : 'pathcost',
591 'bridge-portprios' : 'portprio',
592 'bridge-portmcrouter' : 'portmcrouter',
593 'bridge-portmcfl' : 'portmcfl'}.items():
594 attrval
= ifaceobj
.get_attr_value_first(attrname
)
597 portlist
= self
.parse_port_list(attrval
)
599 self
.log_warn('%s: could not parse \'%s %s\''
600 %(ifaceobj
.name
, attrname
, attrval
))
604 (port
, val
) = p
.split('=')
605 if not portattrs
.get(port
):
607 portattrs
[port
].update({dstattrname
: val
})
609 self
.log_warn('%s: could not parse %s (%s)'
610 %(ifaceobj
.name
, attrname
, str(e
)))
611 for port
, attrdict
in portattrs
.iteritems():
613 self
.brctlcmd
.set_bridgeport_attrs(ifaceobj
.name
, port
,
616 self
.log_warn('%s: %s', str(e
))
618 self
._set
_bridge
_vidinfo
_compat
(ifaceobj
)
619 self
._set
_bridge
_mcqv
4src
_compat
(ifaceobj
)
620 self
._process
_bridge
_maxwait
(ifaceobj
,
621 self
._get
_bridge
_port
_list
(ifaceobj
))
623 self
.log_warn(str(e
))
625 def _check_vids(self
, ifaceobj
, vids
):
629 va
, vb
= v
.split('-')
630 va
, vb
= int(va
), int(vb
)
631 if (self
._handle
_reserved
_vlan
(va
, ifaceobj
.name
) or
632 self
._handle
_reserved
_vlan
(vb
, ifaceobj
.name
)):
636 if self
._handle
_reserved
_vlan
(va
, ifaceobj
.name
):
640 def _apply_bridge_vids(self
, bportifaceobj
, vids
, running_vids
, isbridge
):
642 if not self
._check
_vids
(bportifaceobj
, vids
):
645 (vids_to_del
, vids_to_add
) = \
646 self
._diff
_vids
(vids
, running_vids
)
648 self
.ipcmd
.bridge_vids_del(bportifaceobj
.name
,
649 vids_to_del
, isbridge
)
651 self
.ipcmd
.bridge_vids_add(bportifaceobj
.name
,
652 vids_to_add
, isbridge
)
654 self
.ipcmd
.bridge_vids_add(bportifaceobj
.name
, vids
, isbridge
)
656 self
.log_warn('%s: failed to set vid `%s` (%s)'
657 %(bportifaceobj
.name
, str(vids
), str(e
)))
659 def _apply_bridge_port_pvids(self
, bportifaceobj
, pvid
, running_pvid
):
663 if running_pvid
!= pvid
:
664 self
.ipcmd
.bridge_port_pvid_del(bportifaceobj
.name
,
666 self
.ipcmd
.bridge_port_pvid_add(bportifaceobj
.name
, pvid
)
668 self
.ipcmd
.bridge_port_pvid_add(bportifaceobj
.name
, pvid
)
670 self
.log_warn('%s: failed to set pvid `%s` (%s)'
671 %(bportifaceobj
.name
, pvid
, str(e
)))
673 def _apply_bridge_vlan_aware_port_settings_all(self
, bportifaceobj
,
676 running_vidinfo
= self
._get
_running
_vidinfo
()
679 bport_access
= bportifaceobj
.get_attr_value_first('bridge-access')
681 vids
= re
.split(r
'[\s\t]\s*', bport_access
)
684 bport_vids
= bportifaceobj
.get_attr_value_first('bridge-vids')
686 vids
= re
.split(r
'[\s\t,]\s*', bport_vids
)
688 bport_pvids
= bportifaceobj
.get_attr_value_first('bridge-pvid')
690 pvids
= re
.split(r
'[\s\t]\s*', bport_pvids
)
693 self
._apply
_bridge
_port
_pvids
(bportifaceobj
, pvids
[0],
694 running_vidinfo
.get(bportifaceobj
.name
, {}).get('pvid'))
696 self
._apply
_bridge
_port
_pvids
(bportifaceobj
,
697 bridge_pvid
, running_vidinfo
.get(bportifaceobj
.name
,
699 # XXX: default pvid is already one
701 # self._apply_bridge_port_pvids(bportifaceobj,
702 # '1', running_vidinfo.get(bportifaceobj.name,
706 self
._apply
_bridge
_vids
(bportifaceobj
, vids
,
707 running_vidinfo
.get(bportifaceobj
.name
,
708 {}).get('vlan'), False)
710 self
._apply
_bridge
_vids
(bportifaceobj
,
711 bridge_vids
, running_vidinfo
.get(
712 bportifaceobj
.name
, {}).get('vlan'), False)
715 def _apply_bridge_port_settings(self
, bportifaceobj
, bridgename
=None,
716 bridgeifaceobj
=None):
717 if not bridgename
and bridgeifaceobj
:
718 bridgename
= bridgeifaceobj
.name
719 # Set other stp and igmp attributes
721 for attrname
, dstattrname
in {
722 'bridge-pathcosts' : 'pathcost',
723 'bridge-portprios' : 'portprio',
724 'bridge-portmcrouter' : 'portmcrouter',
725 'bridge-portmcfl' : 'portmcfl'}.items():
726 attrval
= bportifaceobj
.get_attr_value_first(attrname
)
728 # Check if bridge has that attribute
730 # attrval = bridgeifaceobj.get_attr_value_first(attrname)
735 portattrs
[dstattrname
] = attrval
737 self
.brctlcmd
.set_bridgeport_attrs(bridgename
,
738 bportifaceobj
.name
, portattrs
)
740 self
.log_warn(str(e
))
742 def _apply_bridge_port_settings_all(self
, ifaceobj
,
743 ifaceobj_getfunc
=None):
745 bridge_vlan_aware
= ifaceobj
.get_attr_value_first(
747 if bridge_vlan_aware
and bridge_vlan_aware
== 'yes':
748 bridge_vlan_aware
= True
750 bridge_vlan_aware
= False
752 if (ifaceobj
.get_attr_value_first('bridge-port-vids') and
753 ifaceobj
.get_attr_value_first('bridge-port-pvids')):
754 # Old style bridge port vid info
755 # skip new style setting on ports
757 self
.logger
.info('%s: applying bridge configuration '
758 %ifaceobj
.name
+ 'specific to ports')
760 bridge_vids
= ifaceobj
.get_attr_value_first('bridge-vids')
762 bridge_vids
= re
.split(r
'[\s\t,]\s*', bridge_vids
)
766 bridge_pvid
= ifaceobj
.get_attr_value_first('bridge-pvid')
768 bridge_pvid
= re
.split(r
'[\s\t]\s*', bridge_pvid
)[0]
772 bridgeports
= self
._get
_bridge
_port
_list
(ifaceobj
)
774 self
.logger
.debug('%s: cannot find bridgeports' %ifaceobj
.name
)
776 for bport
in bridgeports
:
777 # Use the brctlcmd bulk set method: first build a dictionary
779 if not self
.ipcmd
.bridge_port_exists(ifaceobj
.name
, bport
):
780 self
.logger
.info('%s: skipping bridge config' %ifaceobj
.name
+
781 ' for port %s (missing port)' %bport
)
783 self
.logger
.info('%s: processing bridge config for port %s'
784 %(ifaceobj
.name
, bport
))
785 bportifaceobjlist
= ifaceobj_getfunc(bport
)
786 if not bportifaceobjlist
:
788 for bportifaceobj
in bportifaceobjlist
:
789 # Dont process bridge port if it already has been processed
790 if bportifaceobj
.priv_flags
& self
._BRIDGE
_PORT
_PROCESSED
:
793 # Add attributes specific to the vlan aware bridge
794 if bridge_vlan_aware
:
795 self
._apply
_bridge
_vlan
_aware
_port
_settings
_all
(
796 bportifaceobj
, bridge_vids
, bridge_pvid
)
797 self
._apply
_bridge
_port
_settings
(bportifaceobj
,
798 bridgeifaceobj
=ifaceobj
)
801 self
.logger
.warn('%s: %s' %(ifaceobj
.name
, str(e
)))
804 raise Exception('%s: errors applying port settings' %ifaceobj
.name
)
806 def _up(self
, ifaceobj
, ifaceobj_getfunc
=None):
807 # Check if bridge port
808 bridgename
= self
.ipcmd
.bridge_port_get_bridge_name(ifaceobj
.name
)
810 if self
.ipcmd
.bridge_is_vlan_aware(bridgename
):
811 bridge_vids
= self
._get
_bridge
_vids
(bridgename
,
813 bridge_pvid
= self
._get
_bridge
_pvid
(bridgename
,
815 self
._apply
_bridge
_vlan
_aware
_port
_settings
_all
(ifaceobj
,
818 self
._apply
_bridge
_port
_settings
(ifaceobj
, bridgename
=bridgename
)
819 ifaceobj
.priv_flags |
= self
._BRIDGE
_PORT
_PROCESSED
821 if not self
._is
_bridge
(ifaceobj
):
827 if not self
.PERFMODE
:
828 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
829 self
.ipcmd
.link_create(ifaceobj
.name
, 'bridge')
831 self
.ipcmd
.link_create(ifaceobj
.name
, 'bridge')
833 raise Exception(str(e
))
835 self
._add
_ports
(ifaceobj
)
842 self
._apply
_bridge
_settings
(ifaceobj
)
849 running_ports
= self
.brctlcmd
.get_bridge_ports(ifaceobj
.name
)
850 if not running_ports
:
852 # disable ipv6 for ports that were added to bridge
853 self
._ports
_enable
_disable
_ipv
6(running_ports
, '1')
854 self
._apply
_bridge
_port
_settings
_all
(ifaceobj
,
855 ifaceobj_getfunc
=ifaceobj_getfunc
)
860 #self._flush_running_vidinfo()
862 if ifaceobj
.link_type
!= ifaceLinkType
.LINK_NA
:
863 for p
in running_ports
:
865 rtnetlink_api
.rtnl_api
.link_set(p
, "up")
867 self
.logger
.debug('%s: %s: link set up (%s)'
868 %(ifaceobj
.name
, p
, str(e
)))
871 if ifaceobj
.addr_method
== 'manual':
872 rtnetlink_api
.rtnl_api
.link_set(ifaceobj
.name
, "up")
874 raise Exception(errstr
)
876 def _down(self
, ifaceobj
, ifaceobj_getfunc
=None):
878 if ifaceobj
.get_attr_value_first('bridge-ports'):
879 ports
= self
.brctlcmd
.get_bridge_ports(ifaceobj
.name
)
880 self
.brctlcmd
.delete_bridge(ifaceobj
.name
)
882 self
._ports
_enable
_disable
_ipv
6(ports
, '0')
883 if ifaceobj
.link_type
!= ifaceLinkType
.LINK_NA
:
884 map(lambda p
: rtnetlink_api
.rtnl_api
.link_set(p
,
887 self
.log_error(str(e
))
889 def _query_running_vidinfo_compat(self
, ifaceobjrunning
, ports
):
891 running_vidinfo
= self
._get
_running
_vidinfo
()
893 running_bridge_port_vids
= ''
896 running_vids
= running_vidinfo
.get(p
, {}).get('vlan')
898 running_bridge_port_vids
+= ' %s=%s' %(p
,
899 ','.join(running_vids
))
902 running_attrs
['bridge-port-vids'] = running_bridge_port_vids
904 running_bridge_port_pvids
= ''
907 running_pvids
= running_vidinfo
.get(p
, {}).get('pvid')
909 running_bridge_port_pvids
+= ' %s=%s' %(p
,
913 running_attrs
['bridge-port-pvids'] = running_bridge_port_pvids
915 running_bridge_vids
= running_vidinfo
.get(ifaceobjrunning
.name
,
917 if running_bridge_vids
:
918 running_attrs
['bridge-vids'] = ','.join(running_bridge_vids
)
921 def _query_running_vidinfo(self
, ifaceobjrunning
, ifaceobj_getfunc
,
924 running_vidinfo
= self
._get
_running
_vidinfo
()
925 if not running_vidinfo
:
928 # 'bridge-vids' under the bridge is all about 'vids' on the port.
930 running_bridgeport_vids
= []
931 running_bridgeport_pvids
= []
932 for bport
in bridgeports
:
933 vids
= running_vidinfo
.get(bport
, {}).get('vlan')
935 running_bridgeport_vids
.append(' '.join(vids
))
936 pvids
= running_vidinfo
.get(bport
, {}).get('pvid')
938 running_bridgeport_pvids
.append(pvids
[0])
941 if running_bridgeport_vids
:
942 (vidval
, freq
) = Counter(running_bridgeport_vids
).most_common()[0]
943 if freq
== len(bridgeports
):
944 running_attrs
['bridge-vids'] = vidval
945 bridge_vids
= vidval
.split()
948 if running_bridgeport_pvids
:
949 (vidval
, freq
) = Counter(running_bridgeport_pvids
).most_common()[0]
950 if freq
== len(bridgeports
) and vidval
!= '1':
951 running_attrs
['bridge-pvid'] = vidval
952 bridge_pvid
= vidval
.split()
954 # Go through all bridge ports and find their vids
955 for bport
in bridgeports
:
956 bportifaceobj
= ifaceobj_getfunc(bport
)
957 if not bportifaceobj
:
961 vids
= running_vidinfo
.get(bport
, {}).get('vlan')
962 if vids
and vids
!= bridge_vids
:
964 pvids
= running_vidinfo
.get(bport
, {}).get('pvid')
965 if pvids
and pvids
[0] != bridge_pvid
:
967 if not bport_vids
and bport_pvids
and bport_pvids
[0] != '1':
968 bportifaceobj
[0].replace_config('bridge-access', bport_pvids
[0])
970 if bport_pvids
and bport_pvids
[0] != '1':
971 bportifaceobj
[0].replace_config('bridge-pvid', bport_pvids
[0])
973 # delete any stale bridge-vids under ports
974 bportifaceobj
[0].delete_config('bridge-pvid')
976 bportifaceobj
[0].replace_config('bridge-vids',
977 ' '.join(bport_vids
))
979 # delete any stale bridge-vids under ports
980 bportifaceobj
[0].delete_config('bridge-vids')
983 def _query_running_mcqv4src(self
, ifaceobjrunning
):
984 running_mcqv4src
= self
.brctlcmd
.get_mcqv4src(ifaceobjrunning
.name
)
985 mcqs
= ['%s=%s' %(v
, i
) for v
, i
in running_mcqv4src
.items()]
990 def _query_running_attrs(self
, ifaceobjrunning
, ifaceobj_getfunc
,
991 bridge_vlan_aware
=False):
995 skip_kernel_stp_attrs
= 0
997 if self
.sysctl_get('net.bridge.bridge-stp-user-space') == '1':
1000 tmpbridgeattrdict
= self
.brctlcmd
.get_bridge_attrs(ifaceobjrunning
.name
)
1001 if not tmpbridgeattrdict
:
1002 self
.logger
.warn('%s: unable to get bridge attrs'
1003 %ifaceobjrunning
.name
)
1004 return bridgeattrdict
1006 # Fill bridge_ports and bridge stp attributes first
1007 ports
= tmpbridgeattrdict
.get('ports')
1009 bridgeattrdict
['bridge-ports'] = [' '.join(ports
.keys())]
1010 stp
= tmpbridgeattrdict
.get('stp', 'no')
1011 if stp
!= self
.get_mod_subattr('bridge-stp', 'default'):
1012 bridgeattrdict
['bridge-stp'] = [stp
]
1014 if stp
== 'yes' and userspace_stp
:
1015 skip_kernel_stp_attrs
= 1
1017 # pick all other attributes
1018 for k
,v
in tmpbridgeattrdict
.items():
1021 if k
== 'ports' or k
== 'stp':
1024 if skip_kernel_stp_attrs
and k
[:2] != 'mc':
1025 # only include igmp attributes if kernel stp is off
1027 attrname
= 'bridge-' + k
1028 if v
!= self
.get_mod_subattr(attrname
, 'default'):
1029 bridgeattrdict
[attrname
] = [v
]
1031 if bridge_vlan_aware
:
1032 bridgevidinfo
= self
._query
_running
_vidinfo
(ifaceobjrunning
,
1036 bridgevidinfo
= self
._query
_running
_vidinfo
_compat
(ifaceobjrunning
,
1039 bridgeattrdict
.update({k
: [v
] for k
, v
in bridgevidinfo
.items()
1042 mcq
= self
._query
_running
_mcqv
4src
(ifaceobjrunning
)
1044 bridgeattrdict
['bridge-mcqv4src'] = [mcq
]
1046 if skip_kernel_stp_attrs
:
1047 return bridgeattrdict
1050 portconfig
= {'bridge-pathcosts' : '',
1051 'bridge-portprios' : ''}
1052 for p
, v
in ports
.items():
1053 v
= self
.brctlcmd
.get_pathcost(ifaceobjrunning
.name
, p
)
1054 if v
and v
!= self
.get_mod_subattr('bridge-pathcosts',
1056 portconfig
['bridge-pathcosts'] += ' %s=%s' %(p
, v
)
1058 v
= self
.brctlcmd
.get_portprio(ifaceobjrunning
.name
, p
)
1059 if v
and v
!= self
.get_mod_subattr('bridge-portprios',
1061 portconfig
['bridge-portprios'] += ' %s=%s' %(p
, v
)
1063 bridgeattrdict
.update({k
: [v
] for k
, v
in portconfig
.items()
1066 return bridgeattrdict
1068 def _query_check_mcqv4src(self
, ifaceobj
, ifaceobjcurr
):
1069 running_mcqs
= self
._query
_running
_mcqv
4src
(ifaceobj
)
1070 attrval
= ifaceobj
.get_attr_value_first('bridge-mcqv4src')
1072 mcqs
= attrval
.split()
1074 mcqsout
= ' '.join(mcqs
)
1075 ifaceobjcurr
.update_config_with_status('bridge-mcqv4src',
1076 running_mcqs
, 1 if running_mcqs
!= mcqsout
else 0)
1078 def _query_check_bridge_vidinfo(self
, ifaceobj
, ifaceobjcurr
):
1080 running_vidinfo
= self
._get
_running
_vidinfo
()
1081 attrval
= ifaceobj
.get_attr_value_first('bridge-port-vids')
1083 running_bridge_port_vids
= ''
1084 portlist
= self
.parse_port_list(attrval
)
1086 self
.log_warn('%s: could not parse \'%s %s\''
1087 %(ifaceobj
.name
, attrname
, attrval
))
1092 (port
, val
) = p
.split('=')
1093 vids
= val
.split(',')
1094 running_vids
= running_vidinfo
.get(port
, {}).get('vlan')
1096 if not self
._compare
_vids
(vids
, running_vids
):
1098 running_bridge_port_vids
+= ' %s=%s' %(port
,
1099 ','.join(running_vids
))
1101 running_bridge_port_vids
+= ' %s' %p
1104 except Exception, e
:
1105 self
.log_warn('%s: failure checking vid %s (%s)'
1106 %(ifaceobj
.name
, p
, str(e
)))
1108 ifaceobjcurr
.update_config_with_status('bridge-port-vids',
1109 running_bridge_port_vids
, 1)
1111 ifaceobjcurr
.update_config_with_status('bridge-port-vids',
1114 attrval
= ifaceobj
.get_attr_value_first('bridge-port-pvids')
1116 portlist
= self
.parse_port_list(attrval
)
1118 self
.log_warn('%s: could not parse \'%s %s\''
1119 %(ifaceobj
.name
, attrname
, attrval
))
1121 running_bridge_port_pvids
= ''
1125 (port
, pvid
) = p
.split('=')
1126 running_pvid
= running_vidinfo
.get(port
, {}).get('pvid')
1127 if running_pvid
and running_pvid
== pvid
:
1128 running_bridge_port_pvids
+= ' %s' %p
1131 running_bridge_port_pvids
+= ' %s=%s' %(port
,
1133 except Exception, e
:
1134 self
.log_warn('%s: failure checking pvid %s (%s)'
1135 %(ifaceobj
.name
, pvid
, str(e
)))
1137 ifaceobjcurr
.update_config_with_status('bridge-port-pvids',
1138 running_bridge_port_pvids
, 1)
1140 ifaceobjcurr
.update_config_with_status('bridge-port-pvids',
1141 running_bridge_port_pvids
, 0)
1143 # XXX: No need to check for bridge-vids on the bridge
1144 # This is used by the ports. The vids on the bridge
1145 # come from the vlan interfaces on the bridge.
1147 attrval
= ifaceobj
.get_attr_value_first('bridge-vids')
1149 # vids = re.split(r'[\s\t]\s*', attrval)
1150 # running_vids = running_vidinfo.get(ifaceobj.name, {}).get('vlan')
1152 # if self._compare_vids(vids, running_vids):
1153 # ifaceobjcurr.update_config_with_status('bridge-vids',
1156 # ifaceobjcurr.update_config_with_status('bridge-vids',
1157 # ','.join(running_vids), 1)
1159 # ifaceobjcurr.update_config_with_status('bridge-vids', attrval,
1162 ifaceobjcurr
.update_config_with_status('bridge-vids', attrval
, -1)
1164 def _query_check_bridge(self
, ifaceobj
, ifaceobjcurr
,
1165 ifaceobj_getfunc
=None):
1166 if not self
._is
_bridge
(ifaceobj
):
1168 if not self
.brctlcmd
.bridge_exists(ifaceobj
.name
):
1169 self
.logger
.info('%s: bridge: does not exist' %(ifaceobj
.name
))
1172 ifaceattrs
= self
.dict_key_subset(ifaceobj
.config
,
1173 self
.get_mod_attrs())
1177 runningattrs
= self
.brctlcmd
.get_bridge_attrs(ifaceobj
.name
)
1178 if not runningattrs
:
1179 self
.logger
.debug('%s: bridge: unable to get bridge attrs'
1182 except Exception, e
:
1183 self
.logger
.warn(str(e
))
1185 filterattrs
= ['bridge-vids', 'bridge-port-vids',
1186 'bridge-port-pvids']
1187 for k
in Set(ifaceattrs
).difference(filterattrs
):
1188 # get the corresponding ifaceobj attr
1189 v
= ifaceobj
.get_attr_value_first(k
)
1192 rv
= runningattrs
.get(k
[7:])
1193 if k
== 'bridge-mcqv4src':
1195 if k
== 'bridge-vlan-aware' and v
== 'yes':
1196 if self
.ipcmd
.bridge_is_vlan_aware(ifaceobj
.name
):
1197 ifaceobjcurr
.update_config_with_status('bridge-vlan-aware',
1200 ifaceobjcurr
.update_config_with_status('bridge-vlan-aware',
1202 elif k
== 'bridge-stp':
1203 # special case stp compare because it may
1204 # contain more than one valid values
1205 stp_on_vals
= ['on', 'yes']
1206 stp_off_vals
= ['off']
1207 if ((v
in stp_on_vals
and rv
in stp_on_vals
) or
1208 (v
in stp_off_vals
and rv
in stp_off_vals
)):
1209 ifaceobjcurr
.update_config_with_status('bridge-stp',
1212 ifaceobjcurr
.update_config_with_status('bridge-stp',
1214 elif k
== 'bridge-ports':
1215 # special case ports because it can contain regex or glob
1216 running_port_list
= rv
.keys() if rv
else []
1217 bridge_port_list
= self
._get
_bridge
_port
_list
(ifaceobj
)
1218 if not running_port_list
and not bridge_port_list
:
1221 if running_port_list
and bridge_port_list
:
1222 difference
= set(running_port_list
1223 ).symmetric_difference(bridge_port_list
)
1226 ifaceobjcurr
.update_config_with_status('bridge-ports',
1227 ' '.join(running_port_list
)
1228 if running_port_list
else '', portliststatus
)
1229 elif (k
== 'bridge-pathcosts' or
1230 k
== 'bridge-portprios' or k
== 'bridge-portmcrouter'
1231 or k
== 'bridge-portmcfl'):
1232 brctlcmdattrname
= k
[11:].rstrip('s')
1233 # for port attributes, the attributes are in a list
1234 # <portname>=<portattrvalue>
1237 vlist
= self
.parse_port_list(v
)
1240 for vlistitem
in vlist
:
1242 (p
, v
) = vlistitem
.split('=')
1243 currv
= self
.brctlcmd
.get_bridgeport_attr(
1247 currstr
+= ' %s=%s' %(p
, currv
)
1249 currstr
+= ' %s=%s' %(p
, 'None')
1252 except Exception, e
:
1253 self
.log_warn(str(e
))
1255 ifaceobjcurr
.update_config_with_status(k
, currstr
, status
)
1257 ifaceobjcurr
.update_config_with_status(k
, 'notfound', 1)
1260 ifaceobjcurr
.update_config_with_status(k
, rv
, 1)
1262 ifaceobjcurr
.update_config_with_status(k
, rv
, 0)
1264 self
._query
_check
_bridge
_vidinfo
(ifaceobj
, ifaceobjcurr
)
1266 self
._query
_check
_mcqv
4src
(ifaceobj
, ifaceobjcurr
)
1268 def _get_bridge_vids(self
, bridgename
, ifaceobj_getfunc
):
1269 ifaceobjs
= ifaceobj_getfunc(bridgename
)
1270 for ifaceobj
in ifaceobjs
:
1271 vids
= ifaceobj
.get_attr_value_first('bridge-vids')
1272 if vids
: return re
.split(r
'[\s\t,]\s*', vids
)
1275 def _get_bridge_pvid(self
, bridgename
, ifaceobj_getfunc
):
1276 ifaceobjs
= ifaceobj_getfunc(bridgename
)
1278 for ifaceobj
in ifaceobjs
:
1279 pvid
= ifaceobj
.get_attr_value_first('bridge-pvid')
1282 def _get_bridge_name(self
, ifaceobj
):
1283 return self
.ipcmd
.bridge_port_get_bridge_name(ifaceobj
.name
)
1285 def _query_check_bridge_port_vidinfo(self
, ifaceobj
, ifaceobjcurr
,
1286 ifaceobj_getfunc
, bridgename
):
1287 running_vidinfo
= self
._get
_running
_vidinfo
()
1289 attr_name
= 'bridge-access'
1290 vids
= ifaceobj
.get_attr_value_first(attr_name
)
1292 running_pvids
= running_vidinfo
.get(ifaceobj
.name
,
1294 running_vids
= running_vidinfo
.get(ifaceobj
.name
,
1296 if (not running_pvids
or running_pvids
!= vids
or
1298 ifaceobjcurr
.update_config_with_status(attr_name
,
1301 ifaceobjcurr
.update_config_with_status(attr_name
, vids
, 0)
1304 attr_name
= 'bridge-vids'
1305 vids
= ifaceobj
.get_attr_value_first(attr_name
)
1307 vids
= re
.split(r
'[\s\t]\s*', vids
)
1308 running_vids
= running_vidinfo
.get(ifaceobj
.name
,
1310 if not running_vids
or not self
._compare
_vids
(vids
, running_vids
):
1311 ifaceobjcurr
.update_config_with_status(attr_name
,
1312 ' '.join(running_vids
), 1)
1314 ifaceobjcurr
.update_config_with_status(attr_name
,
1315 ' '.join(running_vids
), 0)
1317 # check if it matches the bridge vids
1318 bridge_vids
= self
._get
_bridge
_vids
(bridgename
, ifaceobj_getfunc
)
1319 running_vids
= running_vidinfo
.get(ifaceobj
.name
,
1321 if (bridge_vids
and (not running_vids
or
1322 not self
._compare
_vids
(bridge_vids
, running_vids
))):
1323 ifaceobjcurr
.status
= ifaceStatus
.ERROR
1324 ifaceobjcurr
.status_str
= 'bridge vid error'
1326 running_pvid
= running_vidinfo
.get(ifaceobj
.name
,
1328 attr_name
= 'bridge-pvid'
1329 pvid
= ifaceobj
.get_attr_value_first(attr_name
)
1331 if running_pvid
and running_pvid
== pvid
:
1332 ifaceobjcurr
.update_config_with_status(attr_name
,
1335 ifaceobjcurr
.update_config_with_status(attr_name
,
1337 elif not running_pvid
or running_pvid
!= '1':
1338 ifaceobjcurr
.status
= ifaceStatus
.ERROR
1339 ifaceobjcurr
.status_str
= 'bridge pvid error'
1341 def _query_check_bridge_port(self
, ifaceobj
, ifaceobjcurr
,
1343 if not self
._is
_bridge
_port
(ifaceobj
):
1344 # Mark all bridge attributes as failed
1345 ifaceobjcurr
.check_n_update_config_with_status_many(ifaceobj
,
1346 ['bridge-vids', 'bridge-pvid', 'bridge-access',
1347 'bridge-pathcosts', 'bridge-portprios',
1348 'bridge-portmcrouter',
1349 'bridge-portmcfl'], 1)
1351 bridgename
= self
._get
_bridge
_name
(ifaceobj
)
1353 self
.logger
.warn('%s: unable to determine bridge name'
1357 if self
.ipcmd
.bridge_is_vlan_aware(bridgename
):
1358 self
._query
_check
_bridge
_port
_vidinfo
(ifaceobj
, ifaceobjcurr
,
1361 for attr
, dstattr
in {'bridge-pathcosts' : 'pathcost',
1362 'bridge-portprios' : 'priority',
1363 'bridge-portmcrouter' : 'mcrouter',
1364 'bridge-portmcfl' : 'mcfl' }.items():
1365 attrval
= ifaceobj
.get_attr_value_first(attr
)
1370 running_attrval
= self
.brctlcmd
.get_bridgeport_attr(
1371 bridgename
, ifaceobj
.name
, dstattr
)
1372 if running_attrval
!= attrval
:
1373 ifaceobjcurr
.update_config_with_status(attr
,
1376 ifaceobjcurr
.update_config_with_status(attr
,
1378 except Exception, e
:
1379 self
.log_warn('%s: %s' %(ifaceobj
.name
, str(e
)))
1381 def _query_check(self
, ifaceobj
, ifaceobjcurr
, ifaceobj_getfunc
=None):
1382 if self
._is
_bridge
(ifaceobj
):
1383 self
._query
_check
_bridge
(ifaceobj
, ifaceobjcurr
)
1385 self
._query
_check
_bridge
_port
(ifaceobj
, ifaceobjcurr
,
1388 def _query_running_bridge(self
, ifaceobjrunning
, ifaceobj_getfunc
):
1389 if self
.ipcmd
.bridge_is_vlan_aware(ifaceobjrunning
.name
):
1390 ifaceobjrunning
.update_config('bridge-vlan-aware', 'yes')
1391 ifaceobjrunning
.update_config_dict(self
._query
_running
_attrs
(
1394 bridge_vlan_aware
=True))
1396 ifaceobjrunning
.update_config_dict(self
._query
_running
_attrs
(
1397 ifaceobjrunning
, None))
1399 def _query_running_bridge_port_attrs(self
, ifaceobjrunning
, bridgename
):
1400 if self
.sysctl_get('net.bridge.bridge-stp-user-space') == '1':
1403 v
= self
.brctlcmd
.get_pathcost(bridgename
, ifaceobjrunning
.name
)
1404 if v
and v
!= self
.get_mod_subattr('bridge-pathcosts', 'default'):
1405 ifaceobjrunning
.update_config('bridge-pathcosts', v
)
1407 v
= self
.brctlcmd
.get_pathcost(bridgename
, ifaceobjrunning
.name
)
1408 if v
and v
!= self
.get_mod_subattr('bridge-portprios', 'default'):
1409 ifaceobjrunning
.update_config('bridge-portprios', v
)
1411 def _query_running_bridge_port(self
, ifaceobjrunning
,
1412 ifaceobj_getfunc
=None):
1413 bridgename
= self
.ipcmd
.bridge_port_get_bridge_name(
1414 ifaceobjrunning
.name
)
1418 self
.logger
.warn('%s: unable to find bridgename'
1419 %ifaceobjrunning
.name
)
1421 if not self
.ipcmd
.bridge_is_vlan_aware(bridgename
):
1424 running_vidinfo
= self
._get
_running
_vidinfo
()
1425 bridge_port_vids
= running_vidinfo
.get(ifaceobjrunning
.name
,
1427 bridge_port_pvid
= running_vidinfo
.get(ifaceobjrunning
.name
,
1430 bridgeifaceobjlist
= ifaceobj_getfunc(bridgename
)
1431 if bridgeifaceobjlist
:
1432 bridge_vids
= bridgeifaceobjlist
[0].get_attr_value('bridge-vids')
1433 bridge_pvid
= bridgeifaceobjlist
[0].get_attr_value_first('bridge-pvid')
1435 if not bridge_port_vids
and bridge_port_pvid
:
1436 # must be an access port
1437 if bridge_port_pvid
!= '1':
1438 ifaceobjrunning
.update_config('bridge-access',
1441 if bridge_port_vids
:
1442 if (not bridge_vids
or bridge_port_vids
!= bridge_vids
):
1443 ifaceobjrunning
.update_config('bridge-vids',
1444 ' '.join(bridge_port_vids
))
1445 if bridge_port_pvid
and bridge_port_pvid
!= '1':
1446 if (not bridge_pvid
or (bridge_port_pvid
!= bridge_pvid
)):
1447 ifaceobjrunning
.update_config('bridge-pvid',
1449 self
._query
_running
_bridge
_port
_attrs
(ifaceobjrunning
, bridgename
)
1451 def _query_running(self
, ifaceobjrunning
, ifaceobj_getfunc
=None):
1452 if self
.brctlcmd
.bridge_exists(ifaceobjrunning
.name
):
1453 self
._query
_running
_bridge
(ifaceobjrunning
, ifaceobj_getfunc
)
1454 elif self
.brctlcmd
.is_bridge_port(ifaceobjrunning
.name
):
1455 self
._query
_running
_bridge
_port
(ifaceobjrunning
, ifaceobj_getfunc
)
1457 _run_ops
= {'pre-up' : _up
,
1458 'post-down' : _down
,
1459 'query-checkcurr' : _query_check
,
1460 'query-running' : _query_running
}
1463 """ returns list of ops supported by this module """
1464 return self
._run
_ops
.keys()
1466 def _init_command_handlers(self
):
1467 flags
= self
.get_flags()
1469 self
.ipcmd
= iproute2(**flags
)
1470 if not self
.brctlcmd
:
1471 self
.brctlcmd
= brctl(**flags
)
1473 def run(self
, ifaceobj
, operation
, query_ifaceobj
=None,
1474 ifaceobj_getfunc
=None):
1475 """ run bridge configuration on the interface object passed as
1476 argument. Can create bridge interfaces if they dont exist already
1479 **ifaceobj** (object): iface object
1481 **operation** (str): any of 'pre-up', 'post-down', 'query-checkcurr',
1485 **query_ifaceobj** (object): query check ifaceobject. This is only
1486 valid when op is 'query-checkcurr'. It is an object same as
1487 ifaceobj, but contains running attribute values and its config
1488 status. The modules can use it to return queried running state
1489 of interfaces. status is success if the running state is same
1490 as user required state in ifaceobj. error otherwise.
1492 op_handler
= self
._run
_ops
.get(operation
)
1495 self
._init
_command
_handlers
()
1496 self
._flush
_running
_vidinfo
()
1497 if operation
== 'query-checkcurr':
1498 op_handler(self
, ifaceobj
, query_ifaceobj
,
1499 ifaceobj_getfunc
=ifaceobj_getfunc
)
1501 op_handler(self
, ifaceobj
, ifaceobj_getfunc
=ifaceobj_getfunc
)