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
21 class bridge(moduleBase
):
22 """ ifupdown2 addon module to configure linux bridges """
24 _modinfo
= { 'mhelp' : 'Bridge configuration module. Supports both ' +
25 'vlan aware and non vlan aware bridges. For the vlan ' +
26 'aware bridge, the port specific attributes must be ' +
27 'specified under the port. And for vlan unaware bridge ' +
28 'port specific attributes must be specified under the ' +
32 {'help' : 'vlan aware bridge. Setting this ' +
33 'attribute to yes enables vlan filtering' +
35 'example' : ['bridge-vlan-aware yes/no']},
37 {'help' : 'bridge ports',
39 'example' : ['bridge-ports swp1.100 swp2.100 swp3.100',
40 'bridge-ports glob swp1-3.100',
41 'bridge-ports regex (swp[1|2|3].100)']},
43 {'help': 'bridge-stp yes/no',
44 'example' : ['bridge-stp no'],
45 'validvals' : ['yes', 'on', 'off', 'no'],
48 {'help': 'bridge priority',
49 'example' : ['bridge-bridgeprio 32768'],
52 {'help': 'bridge ageing',
53 'example' : ['bridge-ageing 300'],
56 { 'help' : 'bridge forward delay',
57 'example' : ['bridge-fd 15'],
61 { 'help' : 'bridge garbage collection interval in secs',
62 'example' : ['bridge-gcint 4'],
65 { 'help' : 'bridge set hello time',
66 'example' : ['bridge-hello 2'],
69 { 'help' : 'bridge set maxage',
70 'example' : ['bridge-maxage 20'],
73 { 'help' : 'bridge set port path costs',
74 'example' : ['bridge-pathcosts swp1=100 swp2=100'],
77 { 'help' : 'bridge port prios',
78 'example' : ['bridge-portprios swp1=32 swp2=32'],
81 { 'help' : 'set multicast last member count',
82 'example' : ['bridge-mclmc 2'],
85 { 'help' : 'set multicast router',
87 'example' : ['bridge-mcrouter 1']},
89 { 'help' : 'set multicast snooping',
91 'example' : ['bridge-mcsnoop 1']},
93 { 'help' : 'set multicast startup query count',
95 'example' : ['bridge-mcsqc 2']},
97 { 'help' : 'set multicast query to use ifaddr',
99 'example' : ['bridge-mcqifaddr 0']},
101 { 'help' : 'set multicast querier',
103 'example' : ['bridge-mcquerier 0']},
105 { 'help' : 'set hash elasticity',
107 'example' : ['bridge-hashel 4096']},
109 { 'help' : 'set hash max',
111 'example' : ['bridge-hashmax 4096']},
113 { 'help' : 'set multicast last member interval (in secs)',
115 'example' : ['bridge-mclmi 1']},
117 { 'help' : 'set multicast membership interval (in secs)',
119 'example' : ['bridge-mcmi 260']},
121 { 'help' : 'set multicast querier interval (in secs)',
123 'example' : ['bridge-mcqpi 255']},
125 { 'help' : 'set multicast query interval (in secs)',
127 'example' : ['bridge-mcqi 125']},
129 { 'help' : 'set multicast query response interval (in secs)',
131 'example' : ['bridge-mcqri 10']},
133 { 'help' : 'set multicast startup query interval (in secs)',
135 'example' : ['bridge-mcsqi 31']},
137 { 'help' : 'set per VLAN v4 multicast querier source address',
139 'example' : ['bridge-mcqv4src 100=172.16.100.1 101=172.16.101.1']},
140 'bridge-portmcrouter' :
141 { 'help' : 'set port multicast routers',
143 'example' : ['under the bridge: bridge-portmcrouter swp1=1 swp2=1',
144 'under the port: bridge-portmcrouter 1']},
146 { 'help' : 'port multicast fast leave.',
148 'example' : ['under the bridge: bridge-portmcfl swp1=0 swp2=0',
149 'under the port: bridge-portmcfl 0']},
151 { 'help' : 'wait for a max of time secs for the' +
152 ' specified ports to become available,' +
153 'if no ports are specified then those' +
154 ' specified on bridge-ports will be' +
155 ' used here. Specifying no ports here ' +
156 'should not be used if we are using ' +
157 'regex or \"all\" on bridge_ports,' +
158 'as it wouldnt work.',
160 'example' : ['bridge-waitport 4 swp1 swp2']},
162 { 'help' : 'forces to time seconds the maximum time ' +
163 'that the Debian bridge setup scripts will ' +
164 'wait for the bridge ports to get to the ' +
165 'forwarding status, doesn\'t allow factional ' +
166 'part. If it is equal to 0 then no waiting' +
169 'example' : ['bridge-maxwait 3']},
171 { 'help' : 'bridge port vids. Can be specified ' +
172 'under the bridge or under the port. ' +
173 'If specified under the bridge the ports ' +
174 'inherit it unless overridden by a ' +
175 'bridge-vids attribuet under the port',
176 'example' : ['bridge-vids 4000',
177 'bridge-vids 2000 2200-3000']},
179 { 'help' : 'bridge port pvid. Must be specified under' +
181 'example' : ['bridge-pvid 1']},
183 { 'help' : 'bridge port access vlan. Must be ' +
184 'specified under the bridge port',
185 'example' : ['bridge-access 300']},
187 { 'help' : 'bridge vlans',
189 'example' : ['bridge-port-vids bond0=1-1000,1010-1020']},
190 'bridge-port-pvids' :
191 { 'help' : 'bridge port vlans',
193 'example' : ['bridge-port-pvids bond0=100 bond1=200']},
196 def __init__(self
, *args
, **kargs
):
197 moduleBase
.__init
__(self
, *args
, **kargs
)
199 self
.name
= self
.__class
__.__name
__
201 self
._running
_vidinfo
= {}
202 self
._running
_vidinfo
_valid
= False
203 self
._resv
_vlan
_range
= self
._get
_reserved
_vlan
_range
()
204 self
.logger
.debug('%s: using reserved vlan range %s'
205 %(self
.__class
__.__name
__, str(self
._resv
_vlan
_range
)))
207 def _is_bridge(self
, ifaceobj
):
208 if ifaceobj
.get_attr_value_first('bridge-ports'):
212 def _is_bridge_port(self
, ifaceobj
):
213 if self
.brctlcmd
.is_bridge_port(ifaceobj
.name
):
217 def get_dependent_ifacenames(self
, ifaceobj
, ifacenames_all
=None):
218 if not self
._is
_bridge
(ifaceobj
):
220 if ifaceobj
.link_type
!= ifaceLinkType
.LINK_NA
:
221 ifaceobj
.link_type
= ifaceLinkType
.LINK_MASTER
222 ifaceobj
.link_kind |
= ifaceLinkKind
.BRIDGE
223 ifaceobj
.role |
= ifaceRole
.MASTER
224 ifaceobj
.dependency_type
= ifaceDependencyType
.MASTER_SLAVE
225 return self
.parse_port_list(ifaceobj
.get_attr_value_first(
226 'bridge-ports'), ifacenames_all
)
228 def get_dependent_ifacenames_running(self
, ifaceobj
):
229 self
._init
_command
_handlers
()
230 if not self
.brctlcmd
.bridge_exists(ifaceobj
.name
):
232 return self
.brctlcmd
.get_bridge_ports(ifaceobj
.name
)
234 def _get_bridge_port_list(self
, ifaceobj
):
236 # port list is also available in the previously
237 # parsed dependent list. Use that if available, instead
238 # of parsing port expr again
239 port_list
= ifaceobj
.lowerifaces
242 ports
= ifaceobj
.get_attr_value_first('bridge-ports')
244 return self
.parse_port_list(ports
)
248 def _process_bridge_waitport(self
, ifaceobj
, portlist
):
249 waitport_value
= ifaceobj
.get_attr_value_first('bridge-waitport')
250 if not waitport_value
: return
252 waitportvals
= re
.split(r
'[\s\t]\s*', waitport_value
, 1)
253 if not waitportvals
: return
255 waitporttime
= int(waitportvals
[0])
257 self
.log_warn('%s: invalid waitport value \'%s\''
258 %(ifaceobj
.name
, waitporttime
))
260 if waitporttime
<= 0: return
262 waitportlist
= self
.parse_port_list(waitportvals
[1])
263 except IndexError, e
:
264 # ignore error and use all bridge ports
265 waitportlist
= portlist
267 if not waitportlist
: return
268 self
.logger
.info('%s: waiting for ports %s to exist ...'
269 %(ifaceobj
.name
, str(waitportlist
)))
270 starttime
= time
.time()
271 while ((time
.time() - starttime
) < waitporttime
):
272 if all([False for p
in waitportlist
273 if not self
.ipcmd
.link_exists(p
)]):
277 self
.log_warn('%s: unable to process waitport: %s'
278 %(ifaceobj
.name
, str(e
)))
280 def _ports_enable_disable_ipv6(self
, ports
, enable
='1'):
283 self
.write_file('/proc/sys/net/ipv6/conf/%s' %p
+
284 '/disable_ipv6', enable
)
286 self
.logger
.info(str(e
))
289 def _add_ports(self
, ifaceobj
):
290 bridgeports
= self
._get
_bridge
_port
_list
(ifaceobj
)
291 runningbridgeports
= []
292 removedbridgeports
= []
294 self
.ipcmd
.batch_start()
295 self
._process
_bridge
_waitport
(ifaceobj
, bridgeports
)
296 self
.ipcmd
.batch_start()
297 # Delete active ports not in the new port list
298 if not self
.PERFMODE
:
299 runningbridgeports
= self
.brctlcmd
.get_bridge_ports(ifaceobj
.name
)
300 if runningbridgeports
:
301 for bport
in runningbridgeports
:
302 if not bridgeports
or bport
not in bridgeports
:
303 self
.ipcmd
.link_set(bport
, 'nomaster')
304 removedbridgeports
.append(bport
)
306 runningbridgeports
= []
308 self
.ipcmd
.batch_commit()
311 for bridgeport
in Set(bridgeports
).difference(Set(runningbridgeports
)):
313 if not self
.DRYRUN
and not self
.ipcmd
.link_exists(bridgeport
):
314 self
.log_warn('%s: bridge port %s does not exist'
315 %(ifaceobj
.name
, bridgeport
))
318 hwaddress
= self
.ipcmd
.link_get_hwaddress(bridgeport
)
319 if not self
._valid
_ethaddr
(hwaddress
):
320 self
.log_warn('%s: skipping port %s, ' %(ifaceobj
.name
,
321 bridgeport
) + 'invalid ether addr %s'
324 self
.ipcmd
.link_set(bridgeport
, 'master', ifaceobj
.name
)
325 self
.ipcmd
.addr_flush(bridgeport
)
327 self
.logger
.error(str(e
))
330 self
.ipcmd
.batch_commit()
332 self
.logger
.error(str(e
))
335 # enable ipv6 for ports that were removed
336 self
._ports
_enable
_disable
_ipv
6(removedbridgeports
, '0')
338 self
.log_error('bridge configuration failed (missing ports)')
341 def _process_bridge_maxwait(self
, ifaceobj
, portlist
):
342 maxwait
= ifaceobj
.get_attr_value_first('bridge-maxwait')
343 if not maxwait
: return
345 maxwait
= int(maxwait
)
347 self
.log_warn('%s: invalid maxwait value \'%s\'' %(ifaceobj
.name
,
350 if not maxwait
: return
351 self
.logger
.info('%s: waiting for ports to go to fowarding state ..'
354 starttime
= time
.time()
355 while ((time
.time() - starttime
) < maxwait
):
356 if all([False for p
in portlist
357 if self
.read_file_oneline(
358 '/sys/class/net/%s/brif/%s/state'
359 %(ifaceobj
.name
, p
)) != '3']):
363 self
.log_warn('%s: unable to process maxwait: %s'
364 %(ifaceobj
.name
, str(e
)))
366 def _ints_to_ranges(self
, ints
):
367 for a
, b
in itertools
.groupby(enumerate(ints
), lambda (x
, y
): y
- x
):
369 yield b
[0][1], b
[-1][1]
371 def _ranges_to_ints(self
, rangelist
):
372 """ returns expanded list of integers given set of string ranges
373 example: ['1', '2-4', '6'] returns [1, 2, 3, 4, 6]
376 for part
in rangelist
:
378 a
, b
= part
.split('-')
379 a
, b
= int(a
), int(b
)
380 result
.extend(range(a
, b
+ 1))
386 def _diff_vids(self
, vids1
, vids2
):
390 vids1_ints
= self
._ranges
_to
_ints
(vids1
)
391 vids2_ints
= self
._ranges
_to
_ints
(vids2
)
392 vids1_diff
= Set(vids1_ints
).difference(vids2_ints
)
393 vids2_diff
= Set(vids2_ints
).difference(vids1_ints
)
395 vids_to_add
= ['%d' %start
if start
== end
else '%d-%d' %(start
, end
)
396 for start
, end
in self
._ints
_to
_ranges
(vids1_diff
)]
398 vids_to_del
= ['%d' %start
if start
== end
else '%d-%d' %(start
, end
)
399 for start
, end
in self
._ints
_to
_ranges
(vids2_diff
)]
400 return (vids_to_del
, vids_to_add
)
402 def _compare_vids(self
, vids1
, vids2
):
403 """ Returns true if the vids are same else return false """
405 vids1_ints
= self
._ranges
_to
_ints
(vids1
)
406 vids2_ints
= self
._ranges
_to
_ints
(vids2
)
407 if Set(vids1_ints
).symmetric_difference(vids2_ints
):
412 def _set_bridge_mcqv4src_compat(self
, ifaceobj
):
414 # Sets old style igmp querier
416 attrval
= ifaceobj
.get_attr_value_first('bridge-mcqv4src')
418 running_mcqv4src
= {}
419 if not self
.PERFMODE
:
420 running_mcqv4src
= self
.brctlcmd
.get_mcqv4src(ifaceobj
.name
)
422 srclist
= attrval
.split()
427 k_to_del
= Set(running_mcqv4src
.keys()).difference(mcqs
.keys())
429 self
.brctlcmd
.del_mcqv4src(ifaceobj
.name
, v
)
430 for v
in mcqs
.keys():
431 self
.brctlcmd
.set_mcqv4src(ifaceobj
.name
, v
, mcqs
[v
])
433 def _get_running_vidinfo(self
):
434 if self
._running
_vidinfo
_valid
:
435 return self
._running
_vidinfo
436 self
._running
_vidinfo
= {}
437 if not self
.PERFMODE
:
438 self
._running
_vidinfo
= self
.ipcmd
.bridge_port_vids_get_all()
439 self
._running
_vidinfo
_valid
= True
440 return self
._running
_vidinfo
442 def _flush_running_vidinfo(self
):
443 self
._running
_vidinfo
= {}
444 self
._running
_vidinfo
_valid
= False
446 def _set_bridge_vidinfo_compat(self
, ifaceobj
):
448 # Supports old style vlan vid info format
452 # Handle bridge vlan attrs
453 running_vidinfo
= self
._get
_running
_vidinfo
()
456 attrval
= ifaceobj
.get_attr_value_first('bridge-port-pvids')
458 portlist
= self
.parse_port_list(attrval
)
460 self
.log_warn('%s: could not parse \'%s %s\''
461 %(ifaceobj
.name
, attrname
, attrval
))
465 (port
, pvid
) = p
.split('=')
466 running_pvid
= running_vidinfo
.get(port
, {}).get('pvid')
468 if running_pvid
== pvid
:
471 self
.ipcmd
.bridge_port_pvid_del(port
, running_pvid
)
472 self
.ipcmd
.bridge_port_pvid_add(port
, pvid
)
474 self
.log_warn('%s: failed to set pvid `%s` (%s)'
475 %(ifaceobj
.name
, p
, str(e
)))
478 attrval
= ifaceobj
.get_attr_value_first('bridge-port-vids')
480 portlist
= self
.parse_port_list(attrval
)
482 self
.log_warn('%s: could not parse \'%s %s\''
483 %(ifaceobj
.name
, attrname
, attrval
))
487 (port
, val
) = p
.split('=')
488 vids
= val
.split(',')
489 if running_vidinfo
.get(port
):
490 (vids_to_del
, vids_to_add
) = \
491 self
._diff
_vids
(vids
,
492 running_vidinfo
.get(port
).get('vlan'))
494 self
.ipcmd
.bridge_port_vids_del(port
, vids_to_del
)
496 self
.ipcmd
.bridge_port_vids_add(port
, vids_to_add
)
498 self
.ipcmd
.bridge_port_vids_add(port
, vids
)
500 self
.log_warn('%s: failed to set vid `%s` (%s)'
501 %(ifaceobj
.name
, p
, str(e
)))
504 # XXX: Commenting out this code for now because it was decided
505 # that this is not needed
506 #attrval = ifaceobj.get_attr_value_first('bridge-vids')
508 # vids = re.split(r'[\s\t]\s*', attrval)
509 # if running_vidinfo.get(ifaceobj.name):
510 # (vids_to_del, vids_to_add) = \
511 # self._diff_vids(vids,
512 # running_vidinfo.get(ifaceobj.name).get('vlan'))
514 # self.ipcmd.bridge_vids_del(ifaceobj.name, vids_to_del)
516 # self.ipcmd.bridge_vids_add(ifaceobj.name, vids_to_add)
518 # self.ipcmd.bridge_vids_add(ifaceobj.name, vids)
520 # running_vids = running_vidinfo.get(ifaceobj.name)
522 # self.ipcmd.bridge_vids_del(ifaceobj.name, running_vids)
524 def _apply_bridge_settings(self
, ifaceobj
):
526 stp
= ifaceobj
.get_attr_value_first('bridge-stp')
528 self
.brctlcmd
.set_stp(ifaceobj
.name
, stp
)
530 # If stp not specified and running stp state on, set it to off
531 running_stp_state
= self
.read_file_oneline(
532 '/sys/class/net/%s/bridge/stp_state' %ifaceobj
.name
)
533 if running_stp_state
and running_stp_state
!= '0':
534 self
.brctlcmd
.set_stp(ifaceobj
.name
, 'no')
536 if ifaceobj
.get_attr_value_first('bridge-vlan-aware') == 'yes':
537 self
.write_file('/sys/class/net/%s/bridge/vlan_filtering'
539 # Use the brctlcmd bulk set method: first build a dictionary
541 bridgeattrs
= { k
:v
for k
,v
in
543 ifaceobj
.get_attr_value_first('bridge-ageing'),
545 ifaceobj
.get_attr_value_first(
546 'bridge-bridgeprio'),
548 ifaceobj
.get_attr_value_first('bridge-fd'),
550 ifaceobj
.get_attr_value_first('bridge-gcint'),
552 ifaceobj
.get_attr_value_first('bridge-hello'),
554 ifaceobj
.get_attr_value_first('bridge-maxage'),
556 ifaceobj
.get_attr_value_first('bridge-mclmc'),
558 ifaceobj
.get_attr_value_first(
561 ifaceobj
.get_attr_value_first('bridge-mcsnoop'),
563 ifaceobj
.get_attr_value_first('bridge-mcsqc'),
565 ifaceobj
.get_attr_value_first(
568 ifaceobj
.get_attr_value_first(
571 ifaceobj
.get_attr_value_first('bridge-hashel'),
573 ifaceobj
.get_attr_value_first('bridge-hashmax'),
575 ifaceobj
.get_attr_value_first('bridge-mclmi'),
577 ifaceobj
.get_attr_value_first('bridge-mcmi'),
579 ifaceobj
.get_attr_value_first('bridge-mcqpi'),
581 ifaceobj
.get_attr_value_first('bridge-mcqi'),
583 ifaceobj
.get_attr_value_first('bridge-mcqri'),
585 ifaceobj
.get_attr_value_first('bridge-mcsqi')
589 self
.brctlcmd
.set_bridge_attrs(ifaceobj
.name
, bridgeattrs
)
591 for attrname
, dstattrname
in {'bridge-pathcosts' : 'pathcost',
592 'bridge-portprios' : 'portprio',
593 'bridge-portmcrouter' : 'portmcrouter',
594 'bridge-portmcfl' : 'portmcfl'}.items():
595 attrval
= ifaceobj
.get_attr_value_first(attrname
)
598 portlist
= self
.parse_port_list(attrval
)
600 self
.log_warn('%s: could not parse \'%s %s\''
601 %(ifaceobj
.name
, attrname
, attrval
))
605 (port
, val
) = p
.split('=')
606 if not portattrs
.get(port
):
608 portattrs
[port
].update({dstattrname
: val
})
610 self
.log_warn('%s: could not parse %s (%s)'
611 %(ifaceobj
.name
, attrname
, str(e
)))
612 for port
, attrdict
in portattrs
.iteritems():
614 self
.brctlcmd
.set_bridgeport_attrs(ifaceobj
.name
, port
,
617 self
.log_warn('%s: %s', str(e
))
619 self
._set
_bridge
_vidinfo
_compat
(ifaceobj
)
620 self
._set
_bridge
_mcqv
4src
_compat
(ifaceobj
)
621 self
._process
_bridge
_maxwait
(ifaceobj
,
622 self
._get
_bridge
_port
_list
(ifaceobj
))
624 self
.log_warn(str(e
))
626 def _check_vids(self
, ifaceobj
, vids
):
630 va
, vb
= v
.split('-')
631 va
, vb
= int(va
), int(vb
)
632 if (self
._handle
_reserved
_vlan
(va
, ifaceobj
.name
) or
633 self
._handle
_reserved
_vlan
(vb
, ifaceobj
.name
)):
637 if self
._handle
_reserved
_vlan
(va
, ifaceobj
.name
):
641 def _apply_bridge_vids(self
, bportifaceobj
, vids
, running_vids
, isbridge
):
643 if not self
._check
_vids
(bportifaceobj
, vids
):
646 (vids_to_del
, vids_to_add
) = \
647 self
._diff
_vids
(vids
, running_vids
)
649 self
.ipcmd
.bridge_vids_del(bportifaceobj
.name
,
650 vids_to_del
, isbridge
)
652 self
.ipcmd
.bridge_vids_add(bportifaceobj
.name
,
653 vids_to_add
, isbridge
)
655 self
.ipcmd
.bridge_vids_add(bportifaceobj
.name
, vids
, isbridge
)
657 self
.log_warn('%s: failed to set vid `%s` (%s)'
658 %(bportifaceobj
.name
, str(vids
), str(e
)))
660 def _apply_bridge_port_pvids(self
, bportifaceobj
, pvid
, running_pvid
):
664 if running_pvid
!= pvid
:
665 self
.ipcmd
.bridge_port_pvid_del(bportifaceobj
.name
,
667 self
.ipcmd
.bridge_port_pvid_add(bportifaceobj
.name
, pvid
)
669 self
.ipcmd
.bridge_port_pvid_add(bportifaceobj
.name
, pvid
)
671 self
.log_warn('%s: failed to set pvid `%s` (%s)'
672 %(bportifaceobj
.name
, pvid
, str(e
)))
674 def _apply_bridge_vids_and_pvid(self
, bportifaceobj
, vids
, running_vids
,
675 pvid
, running_pvid
, isbridge
):
676 """ This method is a combination of methods _apply_bridge_vids and
677 _apply_bridge_port_pvids above. A combined function is
678 found necessary to do the deletes first and the adds later
679 because kernel does honor vid info flags during deletes.
684 if not self
._check
_vids
(bportifaceobj
, vids
):
690 pvid_to_add
= pvid
if pvid
else '1'
693 (vids_to_del
, vids_to_add
) = \
694 self
._diff
_vids
(vids
, running_vids
)
697 if running_pvid
!= pvid
:
698 pvid_to_del
= running_pvid
700 if (pvid_to_del
and (pvid_to_del
in vids
) and
701 (pvid_to_del
not in vids_to_add
)):
702 # kernel deletes dont take into account
703 # bridge vid flags and its possible that
704 # the pvid deletes we do end up deleting
705 # the vids. Be proactive and add the pvid
706 # to the vid add list if it is in the vids
707 # and not already part of vids_to_add.
708 # This helps with a small corner case:
712 # - new change is going to move the state to
715 vids_to_add
.append(pvid_to_del
)
717 self
.log_warn('%s: failed to process vids/pvids'
718 %bportifaceobj
.name
+ ' vids = %s' %str
(vids
) +
719 'pvid = %s ' %pvid
+ '(%s)' %str
(e
))
722 self
.ipcmd
.bridge_vids_del(bportifaceobj
.name
,
723 vids_to_del
, isbridge
)
725 self
.log_warn('%s: failed to del vid `%s` (%s)'
726 %(bportifaceobj
.name
, str(vids_to_del
), str(e
)))
730 self
.ipcmd
.bridge_port_pvid_del(bportifaceobj
.name
,
733 self
.log_warn('%s: failed to del pvid `%s` (%s)'
734 %(bportifaceobj
.name
, pvid_to_del
, str(e
)))
738 self
.ipcmd
.bridge_vids_add(bportifaceobj
.name
,
739 vids_to_add
, isbridge
)
741 self
.log_warn('%s: failed to set vid `%s` (%s)'
742 %(bportifaceobj
.name
, str(vids_to_add
), str(e
)))
745 self
.ipcmd
.bridge_port_pvid_add(bportifaceobj
.name
, pvid_to_add
)
747 self
.log_warn('%s: failed to set pvid `%s` (%s)'
748 %(bportifaceobj
.name
, pvid_to_add
, str(e
)))
750 def _apply_bridge_vlan_aware_port_settings_all(self
, bportifaceobj
,
753 running_vidinfo
= self
._get
_running
_vidinfo
()
758 bport_access
= bportifaceobj
.get_attr_value_first('bridge-access')
760 vids
= re
.split(r
'[\s\t]\s*', bport_access
)
763 bport_vids
= bportifaceobj
.get_attr_value_first('bridge-vids')
765 vids
= re
.split(r
'[\s\t,]\s*', bport_vids
)
767 bport_pvids
= bportifaceobj
.get_attr_value_first('bridge-pvid')
769 pvids
= re
.split(r
'[\s\t]\s*', bport_pvids
)
774 vids_final
= bridge_vids
777 pvid_final
= pvids
[0]
779 pvid_final
= bridge_pvid
781 self
._apply
_bridge
_vids
_and
_pvid
(bportifaceobj
, vids_final
,
782 running_vidinfo
.get(bportifaceobj
.name
, {}).get('vlan'),
784 running_vidinfo
.get(bportifaceobj
.name
, {}).get('pvid'),
787 def _apply_bridge_port_settings(self
, bportifaceobj
, bridgename
=None,
788 bridgeifaceobj
=None):
789 if not bridgename
and bridgeifaceobj
:
790 bridgename
= bridgeifaceobj
.name
791 # Set other stp and igmp attributes
793 for attrname
, dstattrname
in {
794 'bridge-pathcosts' : 'pathcost',
795 'bridge-portprios' : 'portprio',
796 'bridge-portmcrouter' : 'portmcrouter',
797 'bridge-portmcfl' : 'portmcfl'}.items():
798 attrval
= bportifaceobj
.get_attr_value_first(attrname
)
800 # Check if bridge has that attribute
802 # attrval = bridgeifaceobj.get_attr_value_first(attrname)
807 portattrs
[dstattrname
] = attrval
809 self
.brctlcmd
.set_bridgeport_attrs(bridgename
,
810 bportifaceobj
.name
, portattrs
)
812 self
.log_warn(str(e
))
814 def _apply_bridge_port_settings_all(self
, ifaceobj
,
815 ifaceobj_getfunc
=None):
817 bridge_vlan_aware
= ifaceobj
.get_attr_value_first(
819 if bridge_vlan_aware
and bridge_vlan_aware
== 'yes':
820 bridge_vlan_aware
= True
822 bridge_vlan_aware
= False
824 if (ifaceobj
.get_attr_value_first('bridge-port-vids') and
825 ifaceobj
.get_attr_value_first('bridge-port-pvids')):
826 # Old style bridge port vid info
827 # skip new style setting on ports
829 self
.logger
.info('%s: applying bridge configuration '
830 %ifaceobj
.name
+ 'specific to ports')
832 bridge_vids
= ifaceobj
.get_attr_value_first('bridge-vids')
834 bridge_vids
= re
.split(r
'[\s\t,]\s*', bridge_vids
)
838 bridge_pvid
= ifaceobj
.get_attr_value_first('bridge-pvid')
840 bridge_pvid
= re
.split(r
'[\s\t]\s*', bridge_pvid
)[0]
844 bridgeports
= self
._get
_bridge
_port
_list
(ifaceobj
)
846 self
.logger
.debug('%s: cannot find bridgeports' %ifaceobj
.name
)
848 for bport
in bridgeports
:
849 # Use the brctlcmd bulk set method: first build a dictionary
851 if not self
.ipcmd
.bridge_port_exists(ifaceobj
.name
, bport
):
852 self
.logger
.info('%s: skipping bridge config' %ifaceobj
.name
+
853 ' for port %s (missing port)' %bport
)
855 self
.logger
.info('%s: processing bridge config for port %s'
856 %(ifaceobj
.name
, bport
))
857 bportifaceobjlist
= ifaceobj_getfunc(bport
)
858 if not bportifaceobjlist
:
860 for bportifaceobj
in bportifaceobjlist
:
861 # Dont process bridge port if it already has been processed
862 if (bportifaceobj
.module_flags
.get(self
.name
,0x0) & \
863 bridgeFlags
.PORT_PROCESSED
):
866 # Add attributes specific to the vlan aware bridge
867 if bridge_vlan_aware
:
868 self
._apply
_bridge
_vlan
_aware
_port
_settings
_all
(
869 bportifaceobj
, bridge_vids
, bridge_pvid
)
870 self
._apply
_bridge
_port
_settings
(bportifaceobj
,
871 bridgeifaceobj
=ifaceobj
)
874 self
.logger
.warn('%s: %s' %(ifaceobj
.name
, str(e
)))
877 raise Exception('%s: errors applying port settings' %ifaceobj
.name
)
879 def _up(self
, ifaceobj
, ifaceobj_getfunc
=None):
880 # Check if bridge port
881 bridgename
= self
.ipcmd
.bridge_port_get_bridge_name(ifaceobj
.name
)
883 if self
.ipcmd
.bridge_is_vlan_aware(bridgename
):
884 bridge_vids
= self
._get
_bridge
_vids
(bridgename
,
886 bridge_pvid
= self
._get
_bridge
_pvid
(bridgename
,
888 self
._apply
_bridge
_vlan
_aware
_port
_settings
_all
(ifaceobj
,
891 self
._apply
_bridge
_port
_settings
(ifaceobj
, bridgename
=bridgename
)
892 ifaceobj
.module_flags
[self
.name
] = ifaceobj
.module_flags
.setdefault(self
.name
,0) | \
893 bridgeFlags
.PORT_PROCESSED
895 if not self
._is
_bridge
(ifaceobj
):
901 if not self
.PERFMODE
:
902 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
903 self
.ipcmd
.link_create(ifaceobj
.name
, 'bridge')
905 self
.ipcmd
.link_create(ifaceobj
.name
, 'bridge')
907 raise Exception(str(e
))
909 self
._add
_ports
(ifaceobj
)
916 self
._apply
_bridge
_settings
(ifaceobj
)
923 running_ports
= self
.brctlcmd
.get_bridge_ports(ifaceobj
.name
)
924 if not running_ports
:
926 # disable ipv6 for ports that were added to bridge
927 self
._ports
_enable
_disable
_ipv
6(running_ports
, '1')
928 self
._apply
_bridge
_port
_settings
_all
(ifaceobj
,
929 ifaceobj_getfunc
=ifaceobj_getfunc
)
934 #self._flush_running_vidinfo()
936 if ifaceobj
.link_type
!= ifaceLinkType
.LINK_NA
:
937 for p
in running_ports
:
939 rtnetlink_api
.rtnl_api
.link_set(p
, "up")
941 self
.logger
.debug('%s: %s: link set up (%s)'
942 %(ifaceobj
.name
, p
, str(e
)))
945 if ifaceobj
.addr_method
== 'manual':
946 rtnetlink_api
.rtnl_api
.link_set(ifaceobj
.name
, "up")
948 raise Exception(errstr
)
950 def _down(self
, ifaceobj
, ifaceobj_getfunc
=None):
952 if ifaceobj
.get_attr_value_first('bridge-ports'):
953 ports
= self
.brctlcmd
.get_bridge_ports(ifaceobj
.name
)
954 self
.brctlcmd
.delete_bridge(ifaceobj
.name
)
956 self
._ports
_enable
_disable
_ipv
6(ports
, '0')
957 if ifaceobj
.link_type
!= ifaceLinkType
.LINK_NA
:
958 map(lambda p
: rtnetlink_api
.rtnl_api
.link_set(p
,
961 self
.log_error(str(e
))
963 def _query_running_vidinfo_compat(self
, ifaceobjrunning
, ports
):
965 running_vidinfo
= self
._get
_running
_vidinfo
()
967 running_bridge_port_vids
= ''
970 running_vids
= running_vidinfo
.get(p
, {}).get('vlan')
972 running_bridge_port_vids
+= ' %s=%s' %(p
,
973 ','.join(running_vids
))
976 running_attrs
['bridge-port-vids'] = running_bridge_port_vids
978 running_bridge_port_pvids
= ''
981 running_pvids
= running_vidinfo
.get(p
, {}).get('pvid')
983 running_bridge_port_pvids
+= ' %s=%s' %(p
,
987 running_attrs
['bridge-port-pvids'] = running_bridge_port_pvids
989 running_bridge_vids
= running_vidinfo
.get(ifaceobjrunning
.name
,
991 if running_bridge_vids
:
992 running_attrs
['bridge-vids'] = ','.join(running_bridge_vids
)
995 def _query_running_vidinfo(self
, ifaceobjrunning
, ifaceobj_getfunc
,
998 running_vidinfo
= self
._get
_running
_vidinfo
()
999 if not running_vidinfo
:
1000 return running_attrs
1002 # 'bridge-vids' under the bridge is all about 'vids' on the port.
1003 # so query the ports
1004 running_bridgeport_vids
= []
1005 running_bridgeport_pvids
= []
1006 for bport
in bridgeports
:
1007 vids
= running_vidinfo
.get(bport
, {}).get('vlan')
1009 running_bridgeport_vids
.append(' '.join(vids
))
1010 pvids
= running_vidinfo
.get(bport
, {}).get('pvid')
1012 running_bridgeport_pvids
.append(pvids
[0])
1015 if running_bridgeport_vids
:
1016 (vidval
, freq
) = Counter(running_bridgeport_vids
).most_common()[0]
1017 if freq
== len(bridgeports
):
1018 running_attrs
['bridge-vids'] = vidval
1019 bridge_vids
= vidval
.split()
1022 if running_bridgeport_pvids
:
1023 (vidval
, freq
) = Counter(running_bridgeport_pvids
).most_common()[0]
1024 if freq
== len(bridgeports
) and vidval
!= '1':
1025 running_attrs
['bridge-pvid'] = vidval
1026 bridge_pvid
= vidval
.split()
1028 # Go through all bridge ports and find their vids
1029 for bport
in bridgeports
:
1030 bportifaceobj
= ifaceobj_getfunc(bport
)
1031 if not bportifaceobj
:
1035 vids
= running_vidinfo
.get(bport
, {}).get('vlan')
1036 if vids
and vids
!= bridge_vids
:
1038 pvids
= running_vidinfo
.get(bport
, {}).get('pvid')
1039 if pvids
and pvids
[0] != bridge_pvid
:
1041 if not bport_vids
and bport_pvids
and bport_pvids
[0] != '1':
1042 bportifaceobj
[0].replace_config('bridge-access', bport_pvids
[0])
1044 if bport_pvids
and bport_pvids
[0] != '1':
1045 bportifaceobj
[0].replace_config('bridge-pvid', bport_pvids
[0])
1047 # delete any stale bridge-vids under ports
1048 bportifaceobj
[0].delete_config('bridge-pvid')
1050 bportifaceobj
[0].replace_config('bridge-vids',
1051 ' '.join(bport_vids
))
1053 # delete any stale bridge-vids under ports
1054 bportifaceobj
[0].delete_config('bridge-vids')
1055 return running_attrs
1057 def _query_running_mcqv4src(self
, ifaceobjrunning
):
1058 running_mcqv4src
= self
.brctlcmd
.get_mcqv4src(ifaceobjrunning
.name
)
1059 mcqs
= ['%s=%s' %(v
, i
) for v
, i
in running_mcqv4src
.items()]
1061 mcq
= ' '.join(mcqs
)
1064 def _query_running_attrs(self
, ifaceobjrunning
, ifaceobj_getfunc
,
1065 bridge_vlan_aware
=False):
1069 skip_kernel_stp_attrs
= 0
1071 if self
.sysctl_get('net.bridge.bridge-stp-user-space') == '1':
1074 tmpbridgeattrdict
= self
.brctlcmd
.get_bridge_attrs(ifaceobjrunning
.name
)
1075 if not tmpbridgeattrdict
:
1076 self
.logger
.warn('%s: unable to get bridge attrs'
1077 %ifaceobjrunning
.name
)
1078 return bridgeattrdict
1080 # Fill bridge_ports and bridge stp attributes first
1081 ports
= tmpbridgeattrdict
.get('ports')
1083 bridgeattrdict
['bridge-ports'] = [' '.join(ports
.keys())]
1084 stp
= tmpbridgeattrdict
.get('stp', 'no')
1085 if stp
!= self
.get_mod_subattr('bridge-stp', 'default'):
1086 bridgeattrdict
['bridge-stp'] = [stp
]
1088 if stp
== 'yes' and userspace_stp
:
1089 skip_kernel_stp_attrs
= 1
1091 # pick all other attributes
1092 for k
,v
in tmpbridgeattrdict
.items():
1095 if k
== 'ports' or k
== 'stp':
1098 if skip_kernel_stp_attrs
and k
[:2] != 'mc':
1099 # only include igmp attributes if kernel stp is off
1101 attrname
= 'bridge-' + k
1102 if v
!= self
.get_mod_subattr(attrname
, 'default'):
1103 bridgeattrdict
[attrname
] = [v
]
1105 if bridge_vlan_aware
:
1106 bridgevidinfo
= self
._query
_running
_vidinfo
(ifaceobjrunning
,
1110 bridgevidinfo
= self
._query
_running
_vidinfo
_compat
(ifaceobjrunning
,
1113 bridgeattrdict
.update({k
: [v
] for k
, v
in bridgevidinfo
.items()
1116 mcq
= self
._query
_running
_mcqv
4src
(ifaceobjrunning
)
1118 bridgeattrdict
['bridge-mcqv4src'] = [mcq
]
1120 if skip_kernel_stp_attrs
:
1121 return bridgeattrdict
1124 portconfig
= {'bridge-pathcosts' : '',
1125 'bridge-portprios' : ''}
1126 for p
, v
in ports
.items():
1127 v
= self
.brctlcmd
.get_pathcost(ifaceobjrunning
.name
, p
)
1128 if v
and v
!= self
.get_mod_subattr('bridge-pathcosts',
1130 portconfig
['bridge-pathcosts'] += ' %s=%s' %(p
, v
)
1132 v
= self
.brctlcmd
.get_portprio(ifaceobjrunning
.name
, p
)
1133 if v
and v
!= self
.get_mod_subattr('bridge-portprios',
1135 portconfig
['bridge-portprios'] += ' %s=%s' %(p
, v
)
1137 bridgeattrdict
.update({k
: [v
] for k
, v
in portconfig
.items()
1140 return bridgeattrdict
1142 def _query_check_mcqv4src(self
, ifaceobj
, ifaceobjcurr
):
1143 running_mcqs
= self
._query
_running
_mcqv
4src
(ifaceobj
)
1144 attrval
= ifaceobj
.get_attr_value_first('bridge-mcqv4src')
1146 mcqs
= attrval
.split()
1148 mcqsout
= ' '.join(mcqs
)
1149 ifaceobjcurr
.update_config_with_status('bridge-mcqv4src',
1150 running_mcqs
, 1 if running_mcqs
!= mcqsout
else 0)
1152 def _query_check_bridge_vidinfo(self
, ifaceobj
, ifaceobjcurr
):
1154 running_vidinfo
= self
._get
_running
_vidinfo
()
1155 attrval
= ifaceobj
.get_attr_value_first('bridge-port-vids')
1157 running_bridge_port_vids
= ''
1158 portlist
= self
.parse_port_list(attrval
)
1160 self
.log_warn('%s: could not parse \'%s %s\''
1161 %(ifaceobj
.name
, attrname
, attrval
))
1166 (port
, val
) = p
.split('=')
1167 vids
= val
.split(',')
1168 running_vids
= running_vidinfo
.get(port
, {}).get('vlan')
1170 if not self
._compare
_vids
(vids
, running_vids
):
1172 running_bridge_port_vids
+= ' %s=%s' %(port
,
1173 ','.join(running_vids
))
1175 running_bridge_port_vids
+= ' %s' %p
1178 except Exception, e
:
1179 self
.log_warn('%s: failure checking vid %s (%s)'
1180 %(ifaceobj
.name
, p
, str(e
)))
1182 ifaceobjcurr
.update_config_with_status('bridge-port-vids',
1183 running_bridge_port_vids
, 1)
1185 ifaceobjcurr
.update_config_with_status('bridge-port-vids',
1188 attrval
= ifaceobj
.get_attr_value_first('bridge-port-pvids')
1190 portlist
= self
.parse_port_list(attrval
)
1192 self
.log_warn('%s: could not parse \'%s %s\''
1193 %(ifaceobj
.name
, attrname
, attrval
))
1195 running_bridge_port_pvids
= ''
1199 (port
, pvid
) = p
.split('=')
1200 running_pvid
= running_vidinfo
.get(port
, {}).get('pvid')
1201 if running_pvid
and running_pvid
== pvid
:
1202 running_bridge_port_pvids
+= ' %s' %p
1205 running_bridge_port_pvids
+= ' %s=%s' %(port
,
1207 except Exception, e
:
1208 self
.log_warn('%s: failure checking pvid %s (%s)'
1209 %(ifaceobj
.name
, pvid
, str(e
)))
1211 ifaceobjcurr
.update_config_with_status('bridge-port-pvids',
1212 running_bridge_port_pvids
, 1)
1214 ifaceobjcurr
.update_config_with_status('bridge-port-pvids',
1215 running_bridge_port_pvids
, 0)
1217 # XXX: No need to check for bridge-vids on the bridge
1218 # This is used by the ports. The vids on the bridge
1219 # come from the vlan interfaces on the bridge.
1221 attrval
= ifaceobj
.get_attr_value_first('bridge-vids')
1223 # vids = re.split(r'[\s\t]\s*', attrval)
1224 # running_vids = running_vidinfo.get(ifaceobj.name, {}).get('vlan')
1226 # if self._compare_vids(vids, running_vids):
1227 # ifaceobjcurr.update_config_with_status('bridge-vids',
1230 # ifaceobjcurr.update_config_with_status('bridge-vids',
1231 # ','.join(running_vids), 1)
1233 # ifaceobjcurr.update_config_with_status('bridge-vids', attrval,
1236 ifaceobjcurr
.update_config_with_status('bridge-vids', attrval
, -1)
1238 def _query_check_bridge(self
, ifaceobj
, ifaceobjcurr
,
1239 ifaceobj_getfunc
=None):
1240 if not self
._is
_bridge
(ifaceobj
):
1242 if not self
.brctlcmd
.bridge_exists(ifaceobj
.name
):
1243 self
.logger
.info('%s: bridge: does not exist' %(ifaceobj
.name
))
1246 ifaceattrs
= self
.dict_key_subset(ifaceobj
.config
,
1247 self
.get_mod_attrs())
1251 runningattrs
= self
.brctlcmd
.get_bridge_attrs(ifaceobj
.name
)
1252 if not runningattrs
:
1253 self
.logger
.debug('%s: bridge: unable to get bridge attrs'
1256 except Exception, e
:
1257 self
.logger
.warn(str(e
))
1259 filterattrs
= ['bridge-vids', 'bridge-port-vids',
1260 'bridge-port-pvids']
1261 for k
in Set(ifaceattrs
).difference(filterattrs
):
1262 # get the corresponding ifaceobj attr
1263 v
= ifaceobj
.get_attr_value_first(k
)
1266 rv
= runningattrs
.get(k
[7:])
1267 if k
== 'bridge-mcqv4src':
1269 if k
== 'bridge-vlan-aware' and v
== 'yes':
1270 if self
.ipcmd
.bridge_is_vlan_aware(ifaceobj
.name
):
1271 ifaceobjcurr
.update_config_with_status('bridge-vlan-aware',
1274 ifaceobjcurr
.update_config_with_status('bridge-vlan-aware',
1276 elif k
== 'bridge-stp':
1277 # special case stp compare because it may
1278 # contain more than one valid values
1279 stp_on_vals
= ['on', 'yes']
1280 stp_off_vals
= ['off']
1281 if ((v
in stp_on_vals
and rv
in stp_on_vals
) or
1282 (v
in stp_off_vals
and rv
in stp_off_vals
)):
1283 ifaceobjcurr
.update_config_with_status('bridge-stp',
1286 ifaceobjcurr
.update_config_with_status('bridge-stp',
1288 elif k
== 'bridge-ports':
1289 # special case ports because it can contain regex or glob
1290 running_port_list
= rv
.keys() if rv
else []
1291 bridge_port_list
= self
._get
_bridge
_port
_list
(ifaceobj
)
1292 if not running_port_list
and not bridge_port_list
:
1295 if running_port_list
and bridge_port_list
:
1296 difference
= set(running_port_list
1297 ).symmetric_difference(bridge_port_list
)
1300 ifaceobjcurr
.update_config_with_status('bridge-ports',
1301 ' '.join(running_port_list
)
1302 if running_port_list
else '', portliststatus
)
1303 elif (k
== 'bridge-pathcosts' or
1304 k
== 'bridge-portprios' or k
== 'bridge-portmcrouter'
1305 or k
== 'bridge-portmcfl'):
1306 brctlcmdattrname
= k
[11:].rstrip('s')
1307 # for port attributes, the attributes are in a list
1308 # <portname>=<portattrvalue>
1311 vlist
= self
.parse_port_list(v
)
1314 for vlistitem
in vlist
:
1316 (p
, v
) = vlistitem
.split('=')
1317 currv
= self
.brctlcmd
.get_bridgeport_attr(
1321 currstr
+= ' %s=%s' %(p
, currv
)
1323 currstr
+= ' %s=%s' %(p
, 'None')
1326 except Exception, e
:
1327 self
.log_warn(str(e
))
1329 ifaceobjcurr
.update_config_with_status(k
, currstr
, status
)
1331 ifaceobjcurr
.update_config_with_status(k
, 'notfound', 1)
1334 ifaceobjcurr
.update_config_with_status(k
, rv
, 1)
1336 ifaceobjcurr
.update_config_with_status(k
, rv
, 0)
1338 self
._query
_check
_bridge
_vidinfo
(ifaceobj
, ifaceobjcurr
)
1340 self
._query
_check
_mcqv
4src
(ifaceobj
, ifaceobjcurr
)
1342 def _get_bridge_vids(self
, bridgename
, ifaceobj_getfunc
):
1343 ifaceobjs
= ifaceobj_getfunc(bridgename
)
1344 for ifaceobj
in ifaceobjs
:
1345 vids
= ifaceobj
.get_attr_value_first('bridge-vids')
1346 if vids
: return re
.split(r
'[\s\t,]\s*', vids
)
1349 def _get_bridge_pvid(self
, bridgename
, ifaceobj_getfunc
):
1350 ifaceobjs
= ifaceobj_getfunc(bridgename
)
1352 for ifaceobj
in ifaceobjs
:
1353 pvid
= ifaceobj
.get_attr_value_first('bridge-pvid')
1356 def _get_bridge_name(self
, ifaceobj
):
1357 return self
.ipcmd
.bridge_port_get_bridge_name(ifaceobj
.name
)
1359 def _query_check_bridge_port_vidinfo(self
, ifaceobj
, ifaceobjcurr
,
1360 ifaceobj_getfunc
, bridgename
):
1361 running_vidinfo
= self
._get
_running
_vidinfo
()
1363 attr_name
= 'bridge-access'
1364 vids
= ifaceobj
.get_attr_value_first(attr_name
)
1366 running_pvids
= running_vidinfo
.get(ifaceobj
.name
,
1368 running_vids
= running_vidinfo
.get(ifaceobj
.name
,
1370 if (not running_pvids
or running_pvids
!= vids
or
1372 ifaceobjcurr
.update_config_with_status(attr_name
,
1375 ifaceobjcurr
.update_config_with_status(attr_name
, vids
, 0)
1378 attr_name
= 'bridge-vids'
1379 vids
= ifaceobj
.get_attr_value_first(attr_name
)
1381 vids
= re
.split(r
'[\s\t]\s*', vids
)
1382 running_vids
= running_vidinfo
.get(ifaceobj
.name
,
1384 if not running_vids
or not self
._compare
_vids
(vids
, running_vids
):
1385 ifaceobjcurr
.update_config_with_status(attr_name
,
1386 ' '.join(running_vids
), 1)
1388 ifaceobjcurr
.update_config_with_status(attr_name
,
1389 ' '.join(running_vids
), 0)
1391 # check if it matches the bridge vids
1392 bridge_vids
= self
._get
_bridge
_vids
(bridgename
, ifaceobj_getfunc
)
1393 running_vids
= running_vidinfo
.get(ifaceobj
.name
,
1395 if (bridge_vids
and (not running_vids
or
1396 not self
._compare
_vids
(bridge_vids
, running_vids
))):
1397 ifaceobjcurr
.status
= ifaceStatus
.ERROR
1398 ifaceobjcurr
.status_str
= 'bridge vid error'
1400 running_pvid
= running_vidinfo
.get(ifaceobj
.name
,
1402 attr_name
= 'bridge-pvid'
1403 pvid
= ifaceobj
.get_attr_value_first(attr_name
)
1405 if running_pvid
and running_pvid
== pvid
:
1406 ifaceobjcurr
.update_config_with_status(attr_name
,
1409 ifaceobjcurr
.update_config_with_status(attr_name
,
1411 elif not running_pvid
or running_pvid
!= '1':
1412 ifaceobjcurr
.status
= ifaceStatus
.ERROR
1413 ifaceobjcurr
.status_str
= 'bridge pvid error'
1415 def _query_check_bridge_port(self
, ifaceobj
, ifaceobjcurr
,
1417 if not self
._is
_bridge
_port
(ifaceobj
):
1418 # Mark all bridge attributes as failed
1419 ifaceobjcurr
.check_n_update_config_with_status_many(ifaceobj
,
1420 ['bridge-vids', 'bridge-pvid', 'bridge-access',
1421 'bridge-pathcosts', 'bridge-portprios',
1422 'bridge-portmcrouter',
1423 'bridge-portmcfl'], 1)
1425 bridgename
= self
._get
_bridge
_name
(ifaceobj
)
1427 self
.logger
.warn('%s: unable to determine bridge name'
1431 if self
.ipcmd
.bridge_is_vlan_aware(bridgename
):
1432 self
._query
_check
_bridge
_port
_vidinfo
(ifaceobj
, ifaceobjcurr
,
1435 for attr
, dstattr
in {'bridge-pathcosts' : 'pathcost',
1436 'bridge-portprios' : 'priority',
1437 'bridge-portmcrouter' : 'mcrouter',
1438 'bridge-portmcfl' : 'mcfl' }.items():
1439 attrval
= ifaceobj
.get_attr_value_first(attr
)
1444 running_attrval
= self
.brctlcmd
.get_bridgeport_attr(
1445 bridgename
, ifaceobj
.name
, dstattr
)
1446 if running_attrval
!= attrval
:
1447 ifaceobjcurr
.update_config_with_status(attr
,
1450 ifaceobjcurr
.update_config_with_status(attr
,
1452 except Exception, e
:
1453 self
.log_warn('%s: %s' %(ifaceobj
.name
, str(e
)))
1455 def _query_check(self
, ifaceobj
, ifaceobjcurr
, ifaceobj_getfunc
=None):
1456 if self
._is
_bridge
(ifaceobj
):
1457 self
._query
_check
_bridge
(ifaceobj
, ifaceobjcurr
)
1459 self
._query
_check
_bridge
_port
(ifaceobj
, ifaceobjcurr
,
1462 def _query_running_bridge(self
, ifaceobjrunning
, ifaceobj_getfunc
):
1463 if self
.ipcmd
.bridge_is_vlan_aware(ifaceobjrunning
.name
):
1464 ifaceobjrunning
.update_config('bridge-vlan-aware', 'yes')
1465 ifaceobjrunning
.update_config_dict(self
._query
_running
_attrs
(
1468 bridge_vlan_aware
=True))
1470 ifaceobjrunning
.update_config_dict(self
._query
_running
_attrs
(
1471 ifaceobjrunning
, None))
1473 def _query_running_bridge_port_attrs(self
, ifaceobjrunning
, bridgename
):
1474 if self
.sysctl_get('net.bridge.bridge-stp-user-space') == '1':
1477 v
= self
.brctlcmd
.get_pathcost(bridgename
, ifaceobjrunning
.name
)
1478 if v
and v
!= self
.get_mod_subattr('bridge-pathcosts', 'default'):
1479 ifaceobjrunning
.update_config('bridge-pathcosts', v
)
1481 v
= self
.brctlcmd
.get_pathcost(bridgename
, ifaceobjrunning
.name
)
1482 if v
and v
!= self
.get_mod_subattr('bridge-portprios', 'default'):
1483 ifaceobjrunning
.update_config('bridge-portprios', v
)
1485 def _query_running_bridge_port(self
, ifaceobjrunning
,
1486 ifaceobj_getfunc
=None):
1487 bridgename
= self
.ipcmd
.bridge_port_get_bridge_name(
1488 ifaceobjrunning
.name
)
1492 self
.logger
.warn('%s: unable to find bridgename'
1493 %ifaceobjrunning
.name
)
1495 if not self
.ipcmd
.bridge_is_vlan_aware(bridgename
):
1498 running_vidinfo
= self
._get
_running
_vidinfo
()
1499 bridge_port_vids
= running_vidinfo
.get(ifaceobjrunning
.name
,
1501 bridge_port_pvid
= running_vidinfo
.get(ifaceobjrunning
.name
,
1504 bridgeifaceobjlist
= ifaceobj_getfunc(bridgename
)
1505 if bridgeifaceobjlist
:
1506 bridge_vids
= bridgeifaceobjlist
[0].get_attr_value('bridge-vids')
1507 bridge_pvid
= bridgeifaceobjlist
[0].get_attr_value_first('bridge-pvid')
1509 if not bridge_port_vids
and bridge_port_pvid
:
1510 # must be an access port
1511 if bridge_port_pvid
!= '1':
1512 ifaceobjrunning
.update_config('bridge-access',
1515 if bridge_port_vids
:
1516 if (not bridge_vids
or bridge_port_vids
!= bridge_vids
):
1517 ifaceobjrunning
.update_config('bridge-vids',
1518 ' '.join(bridge_port_vids
))
1519 if bridge_port_pvid
and bridge_port_pvid
!= '1':
1520 if (not bridge_pvid
or (bridge_port_pvid
!= bridge_pvid
)):
1521 ifaceobjrunning
.update_config('bridge-pvid',
1523 self
._query
_running
_bridge
_port
_attrs
(ifaceobjrunning
, bridgename
)
1525 def _query_running(self
, ifaceobjrunning
, ifaceobj_getfunc
=None):
1526 if self
.brctlcmd
.bridge_exists(ifaceobjrunning
.name
):
1527 self
._query
_running
_bridge
(ifaceobjrunning
, ifaceobj_getfunc
)
1528 elif self
.brctlcmd
.is_bridge_port(ifaceobjrunning
.name
):
1529 self
._query
_running
_bridge
_port
(ifaceobjrunning
, ifaceobj_getfunc
)
1531 _run_ops
= {'pre-up' : _up
,
1532 'post-down' : _down
,
1533 'query-checkcurr' : _query_check
,
1534 'query-running' : _query_running
}
1537 """ returns list of ops supported by this module """
1538 return self
._run
_ops
.keys()
1540 def _init_command_handlers(self
):
1541 flags
= self
.get_flags()
1543 self
.ipcmd
= iproute2(**flags
)
1544 if not self
.brctlcmd
:
1545 self
.brctlcmd
= brctl(**flags
)
1547 def run(self
, ifaceobj
, operation
, query_ifaceobj
=None,
1548 ifaceobj_getfunc
=None):
1549 """ run bridge configuration on the interface object passed as
1550 argument. Can create bridge interfaces if they dont exist already
1553 **ifaceobj** (object): iface object
1555 **operation** (str): any of 'pre-up', 'post-down', 'query-checkcurr',
1559 **query_ifaceobj** (object): query check ifaceobject. This is only
1560 valid when op is 'query-checkcurr'. It is an object same as
1561 ifaceobj, but contains running attribute values and its config
1562 status. The modules can use it to return queried running state
1563 of interfaces. status is success if the running state is same
1564 as user required state in ifaceobj. error otherwise.
1566 op_handler
= self
._run
_ops
.get(operation
)
1569 self
._init
_command
_handlers
()
1570 self
._flush
_running
_vidinfo
()
1571 if operation
== 'query-checkcurr':
1572 op_handler(self
, ifaceobj
, query_ifaceobj
,
1573 ifaceobj_getfunc
=ifaceobj_getfunc
)
1575 op_handler(self
, ifaceobj
, ifaceobj_getfunc
=ifaceobj_getfunc
)