3 # Copyright 2014-2017 Cumulus Networks, Inc. All rights reserved.
4 # Author: Roopa Prabhu, roopa@cumulusnetworks.com
12 from ifupdown2
.ifupdown
.iface
import *
13 from ifupdown2
.ifupdown
.utils
import utils
14 from ifupdown2
.ifupdown
.netlink
import netlink
16 import ifupdown2
.ifupdown
.ifupdownflags
as ifupdownflags
17 import ifupdown2
.ifupdown
.policymanager
as policymanager
19 from ifupdown2
.ifupdownaddons
.LinkUtils
import LinkUtils
20 from ifupdown2
.ifupdownaddons
.modulebase
import moduleBase
21 from ifupdown2
.ifupdownaddons
.mstpctlutil
import mstpctlutil
22 from ifupdown2
.ifupdownaddons
.systemutils
import systemUtils
24 from ifupdown
.iface
import *
25 from ifupdown
.utils
import utils
26 from ifupdown
.netlink
import netlink
28 import ifupdown
.ifupdownflags
as ifupdownflags
29 import ifupdown
.policymanager
as policymanager
31 from ifupdownaddons
.LinkUtils
import LinkUtils
32 from ifupdownaddons
.modulebase
import moduleBase
33 from ifupdownaddons
.mstpctlutil
import mstpctlutil
34 from ifupdownaddons
.systemutils
import systemUtils
40 class mstpctl(moduleBase
):
41 """ ifupdown2 addon module to configure mstp attributes """
43 _modinfo
= {'mhelp' : 'mstp configuration module for bridges',
46 {'help' : 'mstp ports',
49 'new-attribute': 'bridge-ports'},
51 {'help': 'bridge stp yes/no',
52 'validvals' : ['yes', 'no', 'on', 'off'],
56 'new-attribute': 'bridge-stp'},
58 {'help': 'tree priority',
60 'validvals' : ['0', '4096', '8192', '12288', '16384',
61 '20480', '24576', '28672', '32768',
62 '36864', '40960', '45056', '49152',
63 '53248', '57344', '61440'],
65 'example' : ['mstpctl-treeprio 32768']},
67 {'help': 'ageing time',
68 'validrange' : ['0', '4096'],
71 'jsonAttr': 'ageingTime',
72 'example' : ['mstpctl-ageing 300']},
74 { 'help' : 'max message age',
75 'validrange' : ['0', '255'],
77 'jsonAttr': 'bridgeMaxAge',
79 'example' : ['mstpctl-maxage 20']},
81 { 'help' : 'set forwarding delay',
82 'validrange' : ['0', '255'],
84 'jsonAttr': 'bridgeFwdDelay',
86 'example' : ['mstpctl-fdelay 15']},
88 { 'help' : 'bridge max hops',
89 'validrange' : ['0', '255'],
91 'jsonAttr': 'maxHops',
93 'example' : ['mstpctl-maxhops 15']},
94 'mstpctl-txholdcount' :
95 { 'help' : 'bridge transmit holdcount',
96 'validrange' : ['0', '255'],
98 'jsonAttr': 'txHoldCounter',
100 'example' : ['mstpctl-txholdcount 6']},
101 'mstpctl-forcevers' :
102 { 'help' : 'bridge force stp version',
103 'validvals' : ['rstp', ],
106 'jsonAttr': 'forceProtocolVersion',
107 'example' : ['mstpctl-forcevers rstp']},
108 'mstpctl-portpathcost' :
109 { 'help' : 'bridge port path cost',
110 'validvals': ['<interface-range-list>'],
111 'validrange' : ['0', '65535'],
113 'jsonAttr' : 'adminExtPortCost',
115 'example' : ['under the bridge: mstpctl-portpathcost swp1=0 swp2=1',
116 'under the port (recommended): mstpctl-portpathcost 0']},
118 { 'help' : 'bridge port p2p detection mode',
120 'jsonAttr' : 'adminPointToPoint',
121 'validvals' : ['<interface-yes-no-auto-list>'],
123 'example' : ['under the bridge: mstpctl-portp2p swp1=yes swp2=no',
124 'under the port (recommended): mstpctl-portp2p yes']},
125 'mstpctl-portrestrrole' :
127 'enable/disable port ability to take root role of the port',
129 'jsonAttr' : 'restrictedRole',
130 'validvals' : ['<interface-yes-no-list>'],
132 'example' : ['under the bridge: mstpctl-portrestrrole swp1=yes swp2=no',
133 'under the port (recommended): mstpctl-portrestrrole yes']},
134 'mstpctl-portrestrtcn' :
136 'enable/disable port ability to propagate received topology change notification of the port',
138 'jsonAttr' : 'restrictedTcn',
139 'validvals' : ['<interface-yes-no-list>'],
141 'example' : ['under the bridge: mstpctl-portrestrtcn swp1=yes swp2=no',
142 'under the port (recommended): mstpctl-portrestrtcn yes']},
143 'mstpctl-bpduguard' :
145 'enable/disable bpduguard',
147 'jsonAttr' : 'bpduGuardPort',
148 'validvals' : ['<interface-yes-no-list>'],
150 'example' : ['under the bridge: mstpctl-bpduguard swp1=yes swp2=no',
151 'under the port (recommended): mstpctl-bpduguard yes']},
152 'mstpctl-treeportprio' :
153 { 'help': 'Sets the <port>\'s priority MSTI instance. '
154 'The priority value must be a number between 0 and 240 and a multiple of 16.',
156 'validvals': ['<interface-range-list-multiple-of-16>'],
157 'validrange' : ['0', '240'],
158 'jsonAttr': 'treeportprio',
160 'example' : ['under the bridge: mstpctl-treeportprio swp1=128 swp2=128',
161 'under the port (recommended): mstpctl-treeportprio 128']},
163 { 'help' : 'set hello time',
164 'validrange' : ['0', '255'],
167 'jsonAttr': 'helloTime',
168 'example' : ['mstpctl-hello 2']},
169 'mstpctl-portnetwork' :
170 { 'help' : 'enable/disable bridge assurance capability for a port',
171 'validvals' : ['<interface-yes-no-list>'],
173 'jsonAttr' : 'networkPort',
175 'example' : ['under the bridge: mstpctl-portnetwork swp1=yes swp2=no',
176 'under the port (recommended): mstpctl-portnetwork yes']},
177 'mstpctl-portadminedge' :
178 { 'help' : 'enable/disable initial edge state of the port',
179 'validvals' : ['<interface-yes-no-list>'],
181 'jsonAttr' : 'adminEdgePort',
183 'example' : ['under the bridge: mstpctl-portadminedge swp1=yes swp2=no',
184 'under the port (recommended): mstpctl-portadminedge yes']},
185 'mstpctl-portautoedge' :
186 { 'help' : 'enable/disable auto transition to/from edge state of the port',
187 'validvals' : ['<interface-yes-no-list>'],
189 'jsonAttr' : 'autoEdgePort',
191 'example' : ['under the bridge: mstpctl-portautoedge swp1=yes swp2=no',
192 'under the port (recommended): mstpctl-portautoedge yes']},
193 'mstpctl-treeportcost' :
194 { 'help' : 'port tree cost',
195 'validrange' : ['0', '255'],
197 'jsonAttr': 'extPortCost',
199 'mstpctl-portbpdufilter' :
200 { 'help' : 'enable/disable bpdu filter on a port. ' +
201 'syntax varies when defined under a bridge ' +
203 'validvals' : ['<interface-yes-no-list>'],
204 'jsonAttr' : 'bpduFilterPort',
207 'example' : ['under a bridge: mstpctl-portbpdufilter swp1=no swp2=no',
208 'under a port: mstpctl-portbpdufilter yes']},
211 # Maps mstp bridge attribute names to corresponding mstpctl commands
212 # XXX: This can be encoded in the modules dict above
213 _attrs_map
= OrderedDict([('mstpctl-treeprio' , 'treeprio'),
214 ('mstpctl-ageing' , 'ageing'),
215 ('mstpctl-fdelay' , 'fdelay'),
216 ('mstpctl-maxage' , 'maxage'),
217 ('mstpctl-maxhops' , 'maxhops'),
218 ('mstpctl-txholdcount' , 'txholdcount'),
219 ('mstpctl-forcevers', 'forcevers'),
220 ('mstpctl-hello' , 'hello')])
222 # Maps mstp port attribute names to corresponding mstpctl commands
223 # XXX: This can be encoded in the modules dict above
224 _port_attrs_map
= {'mstpctl-portpathcost' : 'portpathcost',
225 'mstpctl-portadminedge' : 'portadminedge',
226 'mstpctl-portautoedge' : 'portautoedge' ,
227 'mstpctl-portp2p' : 'portp2p',
228 'mstpctl-portrestrrole' : 'portrestrrole',
229 'mstpctl-portrestrtcn' : 'portrestrtcn',
230 'mstpctl-bpduguard' : 'bpduguard',
231 'mstpctl-treeportprio' : 'treeportprio',
232 'mstpctl-treeportcost' : 'treeportcost',
233 'mstpctl-portnetwork' : 'portnetwork',
234 'mstpctl-portbpdufilter' : 'portbpdufilter'}
236 def __init__(self
, *args
, **kargs
):
237 moduleBase
.__init
__(self
, *args
, **kargs
)
239 self
.name
= self
.__class
__.__name
__
241 self
.mstpctlcmd
= None
242 self
.mstpd_running
= (True if systemUtils
.is_process_running('mstpd')
246 # The ask is to make "mstpctl-portadminedge yes" part of the default ifupdown2
247 # policy for all vxlan interfaces. In the absence of this, the mstp work flow
248 # is flawed in the event of vxlan flap.
250 # As of today, for vxlan interfaces "oper edge port" is set to 'yes' and also
251 # "bpdufilter port" is also set to 'yes'. So, in a case where bridge has multiple
252 # vxlan interfaces, if one vxlan interface is flapped, this would trigger mstp
253 # re-evaluation of states on other vxlan interfaces, creating momentary traffic
254 # glitch on those vxlans. Setting "admin edge port" to yes (in addition to the
255 # defaults we already have) prevents this.
257 # We use to only support 'mstpctl-vxlan-always-set-bpdu-params' but introducing a
258 # separate policy attribute doesn't make sense, we should have one single
259 # attribute to handle the whole thing (and deprecate mstpctl-vxlan-always-set-bpdu-params)
260 # mstpctl-set-default-vxlan-bridge-attrs=yes will set
261 # mstpctl-portbpdufilter
263 # mstpctl-portadminedge
265 self
.set_default_mstp_vxlan_bridge_config
= utils
.get_boolean_from_string(
266 policymanager
.policymanager_api
.get_module_globals(
267 module_name
=self
.__class
__.__name
__,
268 attr
='mstpctl-vxlan-always-set-bpdu-params'
270 ) or utils
.get_boolean_from_string(
271 policymanager
.policymanager_api
.get_module_globals(
272 module_name
=self
.__class
__.__name
__,
273 attr
='mstpctl-set-default-vxlan-bridge-attrs'
277 def syntax_check(self
, ifaceobj
, ifaceobj_getfunc
):
278 if self
._is
_bridge
(ifaceobj
):
279 if (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_VLAN_AWARE
280 and ifaceobj
.get_attr_value_first('mstpctl-portadminedge')):
281 self
.logger
.error('%s: unsupported use of keyword '
282 '\'mstpctl-portadminedge\' when '
283 'bridge-vlan-aware is on'
288 def _is_bridge(self
, ifaceobj
):
289 if (ifaceobj
.get_attr_value_first('mstpctl-ports') or
290 ifaceobj
.get_attr_value_first('bridge-ports')):
294 def _is_bridge_port(self
, ifaceobj
):
295 if self
.brctlcmd
.is_bridge_port(ifaceobj
.name
):
299 def get_dependent_ifacenames(self
, ifaceobj
, ifacenames_all
=None):
300 if not self
._is
_bridge
(ifaceobj
):
302 return self
.parse_port_list(ifaceobj
.name
,
303 ifaceobj
.get_attr_value_first(
304 'mstpctl-ports'), ifacenames_all
)
306 def get_dependent_ifacenames_running(self
, ifaceobj
):
307 self
._init
_command
_handlers
()
308 if (self
.brctlcmd
.bridge_exists(ifaceobj
.name
) and
309 not self
.mstpctlcmd
.mstpbridge_exists(ifaceobj
.name
)):
311 return self
.brctlcmd
.get_bridge_ports(ifaceobj
.name
)
313 def _get_bridge_port_attr_value(self
, bridgename
, portname
, attr
):
314 json_attr
= self
.get_mod_subattr(attr
, 'jsonAttr')
315 return self
.mstpctlcmd
.get_bridge_port_attr(bridgename
,
319 def _get_bridge_port_list(self
, ifaceobj
):
321 # port list is also available in the previously
322 # parsed dependent list. Use that if available, instead
323 # of parsing port expr again
324 port_list
= ifaceobj
.lowerifaces
327 ports
= ifaceobj
.get_attr_value_first('mstpctl-ports')
329 return self
.parse_port_list(ifaceobj
.name
, ports
)
333 def _ports_enable_disable_ipv6(self
, ports
, enable
='1'):
336 self
.write_file('/proc/sys/net/ipv6/conf/%s' %p
+
337 '/disable_ipv6', enable
)
339 self
.logger
.info(str(e
))
342 def _add_ports(self
, ifaceobj
):
343 bridgeports
= self
._get
_bridge
_port
_list
(ifaceobj
)
345 runningbridgeports
= []
346 # Delete active ports not in the new port list
347 if not ifupdownflags
.flags
.PERFMODE
:
348 runningbridgeports
= self
.brctlcmd
.get_bridge_ports(ifaceobj
.name
)
349 if runningbridgeports
:
350 [self
.ipcmd
.link_set(bport
, 'nomaster')
351 for bport
in runningbridgeports
352 if not bridgeports
or bport
not in bridgeports
]
354 runningbridgeports
= []
358 for bridgeport
in Set(bridgeports
).difference(Set(runningbridgeports
)):
360 if (not ifupdownflags
.flags
.DRYRUN
and
361 not self
.ipcmd
.link_exists(bridgeport
)):
362 self
.log_warn('%s: bridge port %s does not exist'
363 %(ifaceobj
.name
, bridgeport
))
366 self
.ipcmd
.link_set(bridgeport
, 'master', ifaceobj
.name
)
367 self
.ipcmd
.addr_flush(bridgeport
)
369 self
.log_error(str(e
), ifaceobj
)
372 self
.log_error('error configuring bridge (missing ports)')
374 def _apply_bridge_settings(self
, ifaceobj
, ifaceobj_getfunc
):
375 check
= False if ifupdownflags
.flags
.PERFMODE
else True
377 # set bridge attributes
378 for attrname
, dstattrname
in self
._attrs
_map
.items():
379 config_val
= ifaceobj
.get_attr_value_first(attrname
)
380 default_val
= policymanager
.policymanager_api
.get_iface_default(module_name
=self
.__class
__.__name
__, ifname
=ifaceobj
.name
, attr
=attrname
)
382 default_val
= self
.get_mod_subattr(attrname
, 'default')
383 jsonAttr
= self
.get_mod_subattr(attrname
, 'jsonAttr')
385 running_val
= self
.mstpctlcmd
.get_bridge_attr(
386 ifaceobj
.name
, jsonAttr
)
388 self
.logger
.info('%s: could not get running %s value'
389 %(ifaceobj
.name
, attrname
))
391 if (not config_val
and default_val
and (running_val
!= default_val
)):
392 # this happens when users remove an attribute from a port
393 # and expect the default to be restored with ifreload.
394 config_val
= default_val
396 # there is nothing configured and no default to reset
399 if attrname
== 'mstpctl-treeprio':
400 self
.mstpctlcmd
.set_bridge_treeprio(ifaceobj
.name
,
403 self
.mstpctlcmd
.set_bridge_attr(ifaceobj
.name
,
404 dstattrname
, config_val
, check
)
406 self
.logger
.warn('%s' %str
(e
))
409 if self
.ipcmd
.bridge_is_vlan_aware(ifaceobj
.name
):
411 # set bridge port attributes
412 for attrname
, dstattrname
in self
._port
_attrs
_map
.items():
413 config_val
= ifaceobj
.get_attr_value_first(attrname
)
414 default_val
= self
.get_mod_subattr(attrname
,'default')
416 # nothing configured, we may need to reset all ports to defaults
417 # if the default exists and jsonAttribute conversion exists
419 jsonAttr
= self
.get_mod_subattr(attrname
, 'jsonAttr')
420 if default_val
and jsonAttr
:
421 bridgeports
= self
._get
_bridge
_port
_list
(ifaceobj
)
422 for port
in bridgeports
:
423 if not self
.brctlcmd
.is_bridge_port(port
):
426 bport_ifaceobj
= ifaceobj_getfunc(port
)
428 default_val
= self
._get
_default
_val
(attrname
, bport_ifaceobj
[0], ifaceobj
)
430 self
.mstpctlcmd
.set_bridge_port_attr(ifaceobj
.name
,
435 except Exception as e
:
436 self
.logger
.debug('%s' % str(e
))
437 self
.logger
.info('%s: not resetting %s config'
438 %(ifaceobj
.name
, attrname
))
439 # leave the loop for this attribute
442 portlist
= self
.parse_port_list(ifaceobj
.name
, config_val
)
444 self
.log_error('%s: error parsing \'%s %s\''
445 %(ifaceobj
.name
, attrname
, config_val
), ifaceobj
)
447 # there was a configured value so we need to parse it
448 # and set the attribute for each port configured
451 (port
, val
) = p
.split('=')
452 # if it is not bridge port, continue
453 if not os
.path
.exists('/sys/class/net/%s/brport' %port
):
455 json_attr
= self
.get_mod_subattr(attrname
, 'jsonAttr')
456 self
.mstpctlcmd
.set_bridge_port_attr(ifaceobj
.name
,
462 self
.log_error('%s: error setting %s (%s)'
463 %(ifaceobj
.name
, attrname
, str(e
)),
464 ifaceobj
, raise_error
=False)
466 self
.log_warn(str(e
))
469 def _get_default_val(self
, attr
, ifaceobj
, bridgeifaceobj
):
470 if (self
.set_default_mstp_vxlan_bridge_config
471 and ifaceobj
.link_kind
& ifaceLinkKind
.VXLAN
473 'mstpctl-portbpdufilter',
475 'mstpctl-portadminedge',
479 config_val
= bridgeifaceobj
.get_attr_value_first(attr
)
483 if ifaceobj
.name
not in [v
.split('=')[0] for v
in config_val
.split()]:
486 index
= [v
.split('=')[0] for v
in config_val
.split()].index(ifaceobj
.name
)
487 return [v
.split('=')[1] for v
in config_val
.split()][index
]
491 default_val
= policymanager
.policymanager_api
.get_iface_default(module_name
=self
.__class
__.__name
__, ifname
=ifaceobj
.name
, attr
=attr
)
493 return self
.get_mod_subattr(attr
,'default')
496 def _apply_bridge_port_settings(self
, ifaceobj
, bridgename
=None,
500 check
= False if ifupdownflags
.flags
.PERFMODE
else True
502 if not bridgename
and bridgeifaceobj
:
503 bridgename
= bridgeifaceobj
.name
505 if not stp_running_on
:
506 # stp may get turned on at a later point
507 self
.logger
.info('%s: ignoring config'
509 ' (stp on bridge %s is not on yet)' %bridgename
)
511 bvlan_aware
= self
.ipcmd
.bridge_is_vlan_aware(bridgename
)
512 if (not mstpd_running
or
513 not os
.path
.exists('/sys/class/net/%s/brport' %ifaceobj
.name
) or
515 if (not bvlan_aware
and
516 self
.set_default_mstp_vxlan_bridge_config
and
517 (ifaceobj
.link_kind
& ifaceLinkKind
.VXLAN
)):
519 'mstpctl-portbpdufilter',
521 'mstpctl-portadminedge'
523 json_attr
= self
.get_mod_subattr(attr
, 'jsonAttr')
524 config_val
= self
._get
_default
_val
(attr
, ifaceobj
,
527 self
.mstpctlcmd
.set_bridge_port_attr(bridgename
,
529 self
._port
_attrs
_map
[attr
],
533 self
.log_warn('%s: error setting %s (%s)'
534 % (ifaceobj
.name
, attr
, str(e
)))
537 # for "traditional" bridges we also want to let the user configure
538 # some attributes (possibly all of them in the future)
539 applied
= self
._apply
_bridge
_port
_settings
_attributes
_list
(
541 ('mstpctl-portrestrrole', 'portrestrrole'),
542 ('mstpctl-portautoedge', 'portautoedge')
550 # set bridge port attributes
551 return self
._apply
_bridge
_port
_settings
_attributes
_list
(
552 self
._port
_attrs
_map
.items(),
559 def _apply_bridge_port_settings_attributes_list(self
, attributes_list
, ifaceobj
, bridgeifaceobj
, bridgename
, applied
):
560 for attrname
, dstattrname
in attributes_list
:
561 config_val
= ifaceobj
.get_attr_value_first(attrname
)
562 default_val
= self
._get
_default
_val
(attrname
, ifaceobj
, bridgeifaceobj
)
563 jsonAttr
= self
.get_mod_subattr(attrname
, 'jsonAttr')
564 # to see the running value, stp would have to be on
565 # so we would have parsed mstpctl showportdetail json output
567 running_val
= self
.mstpctlcmd
.get_bridge_port_attr(bridgename
,
568 ifaceobj
.name
, jsonAttr
)
570 self
.logger
.info('%s %s: could not get running %s value'
571 %(bridgename
, ifaceobj
.name
, attrname
))
573 if (not config_val
and default_val
and (running_val
!= default_val
)):
574 # this happens when users remove an attribute from a port
575 # and expect the default to be restored with ifreload.
576 config_val
= default_val
578 # there is nothing configured and no default to reset
582 self
.mstpctlcmd
.set_bridge_port_attr(bridgename
,
583 ifaceobj
.name
, dstattrname
, config_val
, json_attr
=jsonAttr
)
586 self
.log_error('%s: error setting %s (%s)'
587 %(ifaceobj
.name
, attrname
, str(e
)), ifaceobj
,
591 def _apply_bridge_port_settings_all(self
, ifaceobj
,
592 ifaceobj_getfunc
=None):
593 self
.logger
.info('%s: applying mstp configuration '
594 %ifaceobj
.name
+ 'specific to ports')
595 # Query running bridge ports. and only apply attributes on them
596 bridgeports
= self
.brctlcmd
.get_bridge_ports(ifaceobj
.name
)
598 self
.logger
.debug('%s: cannot find bridgeports' %ifaceobj
.name
)
600 for bport
in bridgeports
:
601 self
.logger
.info('%s: processing mstp config for port %s'
602 %(ifaceobj
.name
, bport
))
603 if not self
.ipcmd
.link_exists(bport
):
605 if not os
.path
.exists('/sys/class/net/%s/brport' %bport
):
607 bportifaceobjlist
= ifaceobj_getfunc(bport
)
608 if not bportifaceobjlist
:
610 for bportifaceobj
in bportifaceobjlist
:
611 # Dont process bridge port if it already has been processed
612 if (bportifaceobj
.module_flags
.get(self
.name
,0x0) & \
613 mstpctlFlags
.PORT_PROCESSED
):
616 self
._apply
_bridge
_port
_settings
(bportifaceobj
,
617 ifaceobj
.name
, ifaceobj
)
620 self
.log_warn(str(e
))
622 def _is_running_userspace_stp_state_on(self
, bridgename
):
623 stp_state_file
= '/sys/class/net/%s/bridge/stp_state' %bridgename
624 if not stp_state_file
:
626 running_stp_state
= self
.read_file_oneline(stp_state_file
)
627 if running_stp_state
and running_stp_state
== '2':
631 def _up(self
, ifaceobj
, ifaceobj_getfunc
=None):
632 # Check if bridge port
633 bridgename
= self
.ipcmd
.bridge_port_get_bridge_name(ifaceobj
.name
)
635 mstpd_running
= self
.mstpd_running
636 stp_running_on
= self
._is
_running
_userspace
_stp
_state
_on
(bridgename
)
637 applied
= self
._apply
_bridge
_port
_settings
(ifaceobj
, bridgename
,
638 None, stp_running_on
,
641 ifaceobj
.module_flags
[self
.name
] = \
642 ifaceobj
.module_flags
.setdefault(self
.name
,0) | \
643 mstpctlFlags
.PORT_PROCESSED
645 if not self
._is
_bridge
(ifaceobj
):
647 # we are now here because the ifaceobj is a bridge
652 if ifaceobj
.get_attr_value_first('mstpctl-ports'):
653 # If bridge ports specified with mstpctl attr, create the
654 # bridge and also add its ports
655 self
.ipcmd
.batch_start()
656 if not ifupdownflags
.flags
.PERFMODE
:
657 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
658 self
.ipcmd
.link_create(ifaceobj
.name
, 'bridge')
660 self
.ipcmd
.link_create(ifaceobj
.name
, 'bridge')
662 self
._add
_ports
(ifaceobj
)
668 self
.ipcmd
.batch_commit()
669 running_ports
= self
.brctlcmd
.get_bridge_ports(ifaceobj
.name
)
671 # disable ipv6 for ports that were added to bridge
672 self
._ports
_enable
_disable
_ipv
6(running_ports
, '1')
674 stp
= ifaceobj
.get_attr_value_first('mstpctl-stp')
676 self
.set_iface_attr(ifaceobj
, 'mstpctl-stp',
677 self
.brctlcmd
.bridge_set_stp
)
679 stp
= self
.brctlcmd
.bridge_get_stp(ifaceobj
.name
)
680 if (self
.mstpd_running
and
681 (stp
== 'yes' or stp
== 'on')):
682 self
._apply
_bridge
_settings
(ifaceobj
, ifaceobj_getfunc
)
683 self
._apply
_bridge
_port
_settings
_all
(ifaceobj
,
684 ifaceobj_getfunc
=ifaceobj_getfunc
)
686 self
.log_error(str(e
), ifaceobj
)
688 raise Exception(porterrstr
)
690 def _down(self
, ifaceobj
, ifaceobj_getfunc
=None):
691 if not self
._is
_bridge
(ifaceobj
):
694 if ifaceobj
.get_attr_value_first('mstpctl-ports'):
695 # If bridge ports specified with mstpctl attr, delete the
697 ports
= self
.brctlcmd
.get_bridge_ports(ifaceobj
.name
)
699 self
._ports
_enable
_disable
_ipv
6(ports
, '0')
700 self
.brctlcmd
.delete_bridge(ifaceobj
.name
)
702 self
.log_error(str(e
), ifaceobj
)
704 def _query_running_attrs(self
, ifaceobjrunning
, bridge_vlan_aware
=False):
707 tmpbridgeattrdict
= self
.mstpctlcmd
.get_bridge_attrs(ifaceobjrunning
.name
)
708 #self.logger.info('A' + str(tmpbridgeattrdict))
709 if not tmpbridgeattrdict
:
710 return bridgeattrdict
712 for k
,v
in tmpbridgeattrdict
.items():
713 if k
== 'stp' or not v
:
718 attrname
= 'mstpctl-' + k
719 if (v
and v
!= self
.get_mod_subattr(attrname
, 'default')
720 and attrname
!= 'mstpctl-maxhops'):
721 bridgeattrdict
[attrname
] = [v
]
723 ports
= self
.brctlcmd
.get_bridge_ports(ifaceobjrunning
.name
)
724 # Do this only for vlan-UNAWARE-bridge
725 if ports
and not bridge_vlan_aware
:
726 portconfig
= {'mstpctl-portautoedge' : '',
727 'mstpctl-portbpdufilter' : '',
728 'mstpctl-portnetwork' : '',
729 'mstpctl-portpathcost' : '',
730 'mstpctl-portadminedge' : '',
731 'mstpctl-portp2p' : '',
732 'mstpctl-portrestrrole' : '',
733 'mstpctl-portrestrtcn' : '',
734 'mstpctl-bpduguard' : '',
735 'mstpctl-treeportprio' : '',
736 'mstpctl-treeportcost' : ''}
740 for attr
in ['mstpctl-portautoedge',
741 'mstpctl-portbpdufilter',
742 'mstpctl-portnetwork',
743 'mstpctl-portadminedge',
745 'mstpctl-portrestrrole',
746 'mstpctl-portrestrtcn',
749 v
= self
._get
_bridge
_port
_attr
_value
(ifaceobjrunning
.name
,
752 portconfig
[attr
] += ' %s=%s' % (p
, v
)
754 for attr
in ['mstpctl-portpathcost', 'mstpctl-treeportcost']:
755 v
= self
._get
_bridge
_port
_attr
_value
(ifaceobjrunning
.name
,
757 if v
and v
!= self
.get_mod_subattr(attr
, 'default'):
758 portconfig
[attr
] += ' %s=%s' % (p
, v
)
760 bridgeattrdict
.update({k
: [v
] for k
, v
in portconfig
.items()
762 return bridgeattrdict
764 def _get_config_stp(self
, ifaceobj
):
765 stp
= (ifaceobj
.get_attr_value_first('mstpctl-stp') or
766 ifaceobj
.get_attr_value_first('bridge-stp') or
767 policymanager
.policymanager_api
.get_iface_default(module_name
=self
.__class
__.__name
__, ifname
=ifaceobj
.name
, attr
='mstpctl-stp') or
768 # this is a temporary method to access policy default value of bridge-stp
769 policymanager
.policymanager_api
.get_iface_default(module_name
='bridge', ifname
=ifaceobj
.name
, attr
='bridge-stp'))
770 return utils
.get_boolean_from_string(stp
)
772 def _get_running_stp(self
, ifaceobj
):
773 stp
= self
.brctlcmd
.bridge_get_stp(ifaceobj
.name
)
774 return utils
.get_boolean_from_string(stp
)
776 def _query_check_bridge(self
, ifaceobj
, ifaceobjcurr
,
777 ifaceobj_getfunc
=None):
778 # list of attributes that are not supported currently
779 blacklistedattrs
= ['mstpctl-portpathcost',
780 'mstpctl-treeportprio', 'mstpctl-treeportcost']
781 if not self
.brctlcmd
.bridge_exists(ifaceobj
.name
):
782 self
.logger
.debug('bridge %s does not exist' %ifaceobj
.name
)
784 ifaceattrs
= self
.dict_key_subset(ifaceobj
.config
,
785 self
.get_mod_attrs())
786 if self
.set_default_mstp_vxlan_bridge_config
:
787 for attr
in ('mstpctl-portbpdufilter', 'mstpctl-bpduguard', 'mstpctl-portadminedge'):
788 if attr
not in ifaceattrs
:
789 ifaceattrs
.append(attr
)
792 runningattrs
= self
.mstpctlcmd
.get_bridge_attrs(ifaceobj
.name
)
793 #self.logger.info('B' + str(runningattrs))
796 config_stp
= self
._get
_config
_stp
(ifaceobj
)
797 running_stp
= self
._get
_running
_stp
(ifaceobj
)
798 running_port_list
= self
.brctlcmd
.get_bridge_ports(ifaceobj
.name
)
800 # for all mstpctl options
801 if k
in blacklistedattrs
:
803 if k
in ('mstpctl-portbpdufilter', 'mstpctl-bpduguard', 'mstpctl-portadminedge'):
804 #special case, 'ifquery --check --with-defaults' on a VLAN
806 if not running_port_list
:
808 if (not config_stp
or not running_stp
):
810 v
= ifaceobj
.get_attr_value_first(k
)
817 for bportval
in v
.split():
818 config_val
[bportval
.split('=')[0]] = bportval
.split('=')[1]
819 #for bport in bridgeports:
820 for bport
in running_port_list
:
821 bportifaceobjlist
= ifaceobj_getfunc(bport
)
822 if not bportifaceobjlist
:
824 for bportifaceobj
in bportifaceobjlist
:
825 if (bport
not in config_val
):
826 if (bportifaceobj
.link_kind
& ifaceLinkKind
.VXLAN
):
827 if (not ifupdownflags
.flags
.WITHDEFAULTS
or
828 (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_VLAN_AWARE
)):
834 if ((bportifaceobj
.link_kind
& ifaceLinkKind
.VXLAN
) and
835 (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_VLAN_AWARE
)):
837 conf
= config_val
[bport
]
838 jsonAttr
= self
.get_mod_subattr(k
, 'jsonAttr')
840 running_val
= self
.mstpctlcmd
.get_bridge_port_attr(ifaceobj
.name
, bport
, jsonAttr
)
842 self
.logger
.info('%s %s: could not get running %s value'
843 %(ifaceobj
.name
, bport
, attr
))
845 if conf
!= running_val
:
847 bridge_ports
.update({bport
: running_val
})
848 for port
, val
in bridge_ports
.items():
849 #running state format
850 #mstpctl-portbpdufilter swp2=yes swp1=yes vx-14567101=yes [pass]
851 #mstpctl-bpduguard swp2=yes swp1=yes vx-14567101=yes [pass]
852 state
+= port
+ '=' + val
+ ' '
854 ifaceobjcurr
.update_config_with_status(k
, state
, result
)
857 # get the corresponding ifaceobj attr
858 v
= ifaceobj
.get_attr_value_first(k
)
862 # Get the running attribute
863 rv
= runningattrs
.get(k
[8:])
864 if k
== 'mstpctl-stp':
865 # special case stp compare because it may
866 # contain more than one valid values
867 stp_on_vals
= ['on', 'yes']
868 stp_off_vals
= ['off']
869 rv
= self
.brctlcmd
.bridge_get_stp(ifaceobj
.name
)
870 if ((v
in stp_on_vals
and rv
in stp_on_vals
) or
871 (v
in stp_off_vals
and rv
in stp_off_vals
)):
872 ifaceobjcurr
.update_config_with_status('mstpctl-stp', v
, 0)
874 ifaceobjcurr
.update_config_with_status('mstpctl-stp', v
, 1)
877 if k
== 'mstpctl-ports':
878 # special case ports because it can contain regex or glob
879 # XXX: We get all info from mstputils, which means if
880 # mstpd is down, we will not be returning any bridge bridgeports
881 bridge_port_list
= self
._get
_bridge
_port
_list
(ifaceobj
)
882 if not running_port_list
and not bridge_port_list
:
885 if running_port_list
and bridge_port_list
:
886 difference
= Set(running_port_list
).symmetric_difference(
887 Set(bridge_port_list
))
890 ifaceobjcurr
.update_config_with_status('mstpctl-ports',
891 ' '.join(running_port_list
)
892 if running_port_list
else '', portliststatus
)
893 elif k
[:12] == 'mstpctl-port' or k
== 'mstpctl-bpduguard':
894 # Now, look at port attributes
895 # derive the mstpctlcmd attr name
896 #mstpctlcmdattrname = k[12:] if k[:12] == 'mstpctl-port' else k[8:]
897 mstpctlcmdattrname
= k
[8:]
899 # for port attributes, the attributes are in a list
900 # <portname>=<portattrvalue>
903 vlist
= self
.parse_port_list(ifaceobj
.name
, v
)
906 for vlistitem
in vlist
:
908 (p
, v
) = vlistitem
.split('=')
909 currv
= self
._get
_bridge
_port
_attr
_value
(ifaceobj
.name
, p
, k
)
911 currstr
+= ' %s=%s' %(p
, currv
)
913 currstr
+= ' %s=%s' %(p
, 'None')
917 self
.log_warn(str(e
))
919 ifaceobjcurr
.update_config_with_status(k
, currstr
, status
)
921 ifaceobjcurr
.update_config_with_status(k
, '', 1)
923 ifaceobjcurr
.update_config_with_status(k
, rv
, 1)
925 ifaceobjcurr
.update_config_with_status(k
, rv
, 0)
927 def _query_check_bridge_vxlan_port(self
, ifaceobj
, ifaceobjcurr
,
928 ifaceobj_getfunc
=None):
929 masters
= ifaceobj
.upperifaces
932 for bridge
in masters
:
933 bifaceobjlist
= ifaceobj_getfunc(bridge
)
934 for bifaceobj
in bifaceobjlist
:
935 if (self
._is
_bridge
(bifaceobj
) and
936 self
.set_default_mstp_vxlan_bridge_config
and
937 (bifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_VLAN_AWARE
)):
938 config_stp
= self
._get
_config
_stp
(bifaceobj
)
939 running_stp
= self
._get
_running
_stp
(bifaceobj
)
940 if (not config_stp
or not running_stp
):
943 'mstpctl-portbpdufilter',
945 'mstpctl-portadminedge'
947 jsonAttr
= self
.get_mod_subattr(attr
, 'jsonAttr')
948 config_val
= bifaceobj
.get_attr_value_first(attr
)
950 if ifaceobj
.name
not in [v
.split('=')[0] for v
in config_val
.split()]:
951 if not ifupdownflags
.flags
.WITHDEFAULTS
:
955 index
= [v
.split('=')[0] for v
in config_val
.split()].index(ifaceobj
.name
)
956 config_val
= [v
.split('=')[1] for v
in config_val
.split()][index
]
958 if not ifupdownflags
.flags
.WITHDEFAULTS
:
962 running_val
= self
.mstpctlcmd
.get_bridge_port_attr(bifaceobj
.name
,
963 ifaceobj
.name
, jsonAttr
)
965 self
.logger
.info('%s %s: could not get running %s value'
966 %(bifaceobj
.name
, ifaceobj
.name
, attr
))
968 ifaceobjcurr
.update_config_with_status(attr
,
970 0 if running_val
== config_val
else 1)
974 def _query_check_bridge_port(self
, ifaceobj
, ifaceobjcurr
):
975 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
976 #self.logger.debug('bridge port %s does not exist' %ifaceobj.name)
977 ifaceobjcurr
.status
= ifaceStatus
.NOTFOUND
979 # Check if this is a bridge port
980 if not self
._is
_bridge
_port
(ifaceobj
):
981 # mark all the bridge attributes as error
982 ifaceobjcurr
.check_n_update_config_with_status_many(ifaceobj
,
983 self
._port
_attrs
_map
.keys(), 0)
985 bridgename
= self
.ipcmd
.bridge_port_get_bridge_name(ifaceobj
.name
)
986 # list of attributes that are not supported currently
987 blacklistedattrs
= ['mstpctl-portpathcost',
988 'mstpctl-treeportprio', 'mstpctl-treeportcost']
989 ifaceattrs
= self
.dict_key_subset(ifaceobj
.config
,
990 self
._port
_attrs
_map
.keys())
993 runningattrs
= self
.mstpctlcmd
.get_bridge_attrs(ifaceobj
.name
)
994 #self.logger.info('C' + str(runningattrs))
998 # for all mstpctl options
999 # get the corresponding ifaceobj attr
1000 v
= ifaceobj
.get_attr_value_first(k
)
1001 if not v
or k
in blacklistedattrs
:
1002 ifaceobjcurr
.update_config_with_status(k
, v
, -1)
1004 currv
= self
._get
_bridge
_port
_attr
_value
(bridgename
, ifaceobj
.name
, k
)
1007 ifaceobjcurr
.update_config_with_status(k
, currv
, 1)
1009 ifaceobjcurr
.update_config_with_status(k
, currv
, 0)
1011 ifaceobjcurr
.update_config_with_status(k
, None, 1)
1013 def _query_check(self
, ifaceobj
, ifaceobjcurr
, ifaceobj_getfunc
=None):
1014 if self
._is
_bridge
(ifaceobj
):
1015 self
._query
_check
_bridge
(ifaceobj
, ifaceobjcurr
, ifaceobj_getfunc
)
1016 elif ifaceobj
.link_kind
& ifaceLinkKind
.VXLAN
:
1017 self
._query
_check
_bridge
_vxlan
_port
(ifaceobj
, ifaceobjcurr
,
1020 self
._query
_check
_bridge
_port
(ifaceobj
, ifaceobjcurr
)
1022 def _query_bridge_port_attr(self
, ifaceobjrunning
, bridgename
, attr
, value_cmp
):
1023 v
= self
._get
_bridge
_port
_attr
_value
(bridgename
,
1024 ifaceobjrunning
.name
,
1026 if v
and value_cmp
and v
!= value_cmp
:
1027 ifaceobjrunning
.update_config(attr
, v
)
1028 elif v
and not value_cmp
:
1029 ifaceobjrunning
.update_config(attr
, v
)
1031 def _query_running_bridge_port(self
, ifaceobjrunning
):
1032 bridgename
= self
.ipcmd
.bridge_port_get_bridge_name(
1033 ifaceobjrunning
.name
)
1035 self
.logger
.warn('%s: unable to determine bridgename'
1036 %ifaceobjrunning
.name
)
1038 if self
.brctlcmd
.bridge_get_stp(bridgename
) == 'no':
1039 # This bridge does not run stp, return
1041 # if userspace stp not set, return
1042 if self
.systcl_get_net_bridge_stp_user_space() != '1':
1045 self
._query
_bridge
_port
_attr
(ifaceobjrunning
, bridgename
,
1046 'mstpctl-portautoedge',
1047 self
.get_mod_subattr('mstpctl-portautoedge', 'default'))
1049 self
._query
_bridge
_port
_attr
(ifaceobjrunning
, bridgename
,
1050 'mstpctl-portbpdufilter',
1053 self
._query
_bridge
_port
_attr
(ifaceobjrunning
, bridgename
,
1054 'mstpctl-portnetwork',
1057 # XXX: Can we really get path cost of a port ???
1058 #v = self.mstpctlcmd.get_portpathcost(ifaceobjrunning.name, p)
1059 #if v and v != self.get_mod_subattr('mstpctl-pathcost',
1061 # ifaceobjrunning.update_config('mstpctl-network', v)
1063 self
._query
_bridge
_port
_attr
(ifaceobjrunning
, bridgename
,
1064 'mstpctl-portadminedge',
1067 self
._query
_bridge
_port
_attr
(ifaceobjrunning
, bridgename
,
1071 self
._query
_bridge
_port
_attr
(ifaceobjrunning
, bridgename
,
1072 'mstpctl-portrestrrole',
1075 self
._query
_bridge
_port
_attr
(ifaceobjrunning
, bridgename
,
1076 'mstpctl-portrestrtcn',
1079 self
._query
_bridge
_port
_attr
(ifaceobjrunning
, bridgename
,
1080 'mstpctl-bpduguard',
1083 # XXX: Can we really get path cost of a port ???
1084 #v = self.mstpctlcmd.get_bridgeport_attr(ifaceobjrunning.name,
1086 #if v and v != self.get_mod_subattr('mstpctl-treeportprio',
1088 # portconfig['mstpctl-treeportprio'] += ' %s=%s' %(p, v)
1090 #v = self.mstpctlcmd.get_bridgeport_attr(ifaceobjrunning.name,
1092 #if v and v != self.get_mod_subattr('mstpctl-treeportcost',
1094 # portconfig['mstpctl-treeportcost'] += ' %s=%s' %(p, v)
1096 def _query_running_bridge(self
, ifaceobjrunning
):
1097 if self
.brctlcmd
.bridge_get_stp(ifaceobjrunning
.name
) == 'no':
1098 # This bridge does not run stp, return
1100 # if userspace stp not set, return
1101 if self
.systcl_get_net_bridge_stp_user_space() != '1':
1103 # Check if mstp really knows about this bridge
1104 if not self
.mstpctlcmd
.mstpbridge_exists(ifaceobjrunning
.name
):
1106 bridge_vlan_aware
= False
1107 if ifaceobjrunning
.get_attr_value_first('bridge-vlan-aware') == 'yes':
1108 bridge_vlan_aware
= True
1109 ifaceobjrunning
.update_config_dict(self
._query
_running
_attrs
(
1113 def _query_running(self
, ifaceobjrunning
, **extra_args
):
1114 if self
.brctlcmd
.bridge_exists(ifaceobjrunning
.name
):
1115 self
._query
_running
_bridge
(ifaceobjrunning
)
1116 elif self
.brctlcmd
.is_bridge_port(ifaceobjrunning
.name
):
1117 self
._query
_running
_bridge
_port
(ifaceobjrunning
)
1119 def _query_bridge_port(self
, ifaceobj
, ifaceobj_getfunc
=None):
1133 bridge_ports vxlan1wd vxlan2wd
1134 bridge-vlan-aware yes
1142 $ ifquery --with-defaults vxlan1wd
1146 mstpctl-portbpdufilter yes
1147 mstpctl-bpduguard yes
1149 masters
= ifaceobj
.upperifaces
1153 for bridge
in masters
:
1154 bifaceobj
= ifaceobj_getfunc(bridge
)[0]
1155 if (self
._is
_bridge
(bifaceobj
) and
1156 self
.set_default_mstp_vxlan_bridge_config
and
1157 (bifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_VLAN_AWARE
)):
1158 for attr
in ('mstpctl-portbpdufilter',
1159 'mstpctl-bpduguard',
1160 'mstpctl-portadminedge'):
1161 jsonAttr
= self
.get_mod_subattr(attr
, 'jsonAttr')
1162 config_val
= ifaceobj
.get_attr_value_first(attr
)
1163 if config_val
or not ifupdownflags
.flags
.WITHDEFAULTS
:
1166 ifaceobj
.replace_config(attr
, config_val
)
1168 except Exception, e
:
1169 self
.logger
.info("%s: %s" %(ifaceobj
.name
, str(e
)))
1172 def _query(self
, ifaceobj
, ifaceobj_getfunc
=None, **kwargs
):
1173 """ add default policy attributes supported by the module """
1174 if not self
._is
_bridge
(ifaceobj
):
1175 if (ifaceobj
.module_flags
.get(self
.name
,0x0) &
1176 mstpctlFlags
.PORT_PROCESSED
):
1178 self
._query
_bridge
_port
(ifaceobj
, ifaceobj_getfunc
)
1179 ifaceobj
.module_flags
[self
.name
] = (
1180 ifaceobj
.module_flags
.setdefault(self
.name
,0) |
1181 mstpctlFlags
.PORT_PROCESSED
)
1183 lowerinfs
= ifaceobj
.lowerifaces
1186 if ifaceobj
.get_attr_value_first('bridge-vlan-aware') != 'yes':
1187 for attr
in ('mstpctl-portbpdufilter', 'mstpctl-bpduguard', 'mstpctl-portadminedge'):
1189 config
= ifaceobj
.get_attr_value_first(attr
)
1190 for port
in lowerinfs
:
1191 bportobjlist
= ifaceobj_getfunc(port
)
1192 for bportobj
in bportobjlist
:
1193 if bportobj
.get_attr_value_first('vxlan-id'):
1195 if port
not in [v
.split('=')[0] for v
in config
.split()]:
1196 config
+= ' %s=yes' %port
1198 state
+= '%s=yes ' %port
1199 ifaceobj
.replace_config(attr
, config
if config
else state
)
1201 for attr
in ('mstpctl-portbpdufilter', 'mstpctl-bpduguard', 'mstpctl-portadminedge'):
1203 config
= ifaceobj
.get_attr_value_first(attr
)
1204 for port
in lowerinfs
:
1205 bportobjlist
= ifaceobj_getfunc(port
)
1206 for bportobj
in bportobjlist
:
1207 if (bportobj
.module_flags
.get(self
.name
,0x0) &
1208 mstpctlFlags
.PORT_PROCESSED
):
1210 if bportobj
.get_attr_value_first('vxlan-id'):
1212 if port
not in [v
.split('=')[0] for v
in config
.split()]:
1213 bportobj
.update_config(attr
, 'yes')
1215 index
= [v
.split('=')[0] for v
in config
.split()].index(port
)
1216 state
= [v
.split('=')[1] for v
in config
.split()][index
]
1217 bportobj
.update_config(attr
, '%s' %state
)
1220 config
= ' '.join(v
)
1222 bportobj
.replace_config(attr
, 'yes')
1223 bportobj
.module_flags
[self
.name
] = (
1224 bportobj
.module_flags
.setdefault(self
.name
,0) |
1225 mstpctlFlags
.PORT_PROCESSED
)
1227 ifaceobj
.replace_config(attr
, config
)
1231 _run_ops
= {'pre-up' : _up
,
1232 'post-down' : _down
,
1233 'query-checkcurr' : _query_check
,
1234 'query-running' : _query_running
,
1238 """ returns list of ops supported by this module """
1239 return self
._run
_ops
.keys()
1241 def _init_command_handlers(self
):
1243 self
.ipcmd
= self
.brctlcmd
= LinkUtils()
1244 if not self
.mstpctlcmd
:
1245 self
.mstpctlcmd
= mstpctlutil()
1247 def run(self
, ifaceobj
, operation
, query_ifaceobj
=None,
1248 ifaceobj_getfunc
=None, **extra_args
):
1249 """ run mstp configuration on the interface object passed as argument
1252 **ifaceobj** (object): iface object
1254 **operation** (str): any of 'pre-up', 'post-down', 'query-checkcurr',
1257 **query_ifaceobj** (object): query check ifaceobject. This is only
1258 valid when op is 'query-checkcurr'. It is an object same as
1259 ifaceobj, but contains running attribute values and its config
1260 status. The modules can use it to return queried running state
1261 of interfaces. status is success if the running state is same
1262 as user required state in ifaceobj. error otherwise.
1264 if ifaceobj
.type == ifaceType
.BRIDGE_VLAN
:
1266 op_handler
= self
._run
_ops
.get(operation
)
1269 self
._init
_command
_handlers
()
1270 if operation
== 'query-checkcurr':
1271 op_handler(self
, ifaceobj
, query_ifaceobj
,
1272 ifaceobj_getfunc
=ifaceobj_getfunc
)
1274 op_handler(self
, ifaceobj
, ifaceobj_getfunc
=ifaceobj_getfunc
)