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_ifaceobjs
= ifaceobj_getfunc(port
)
428 default_val
= self
._get
_default
_val
(attrname
, bport_ifaceobjs
[0], ifaceobj
)
429 for brport_ifaceobj
in bport_ifaceobjs
or []:
430 attr_value
= brport_ifaceobj
.get_attr_value_first(attrname
)
432 default_val
= attr_value
435 self
.mstpctlcmd
.set_bridge_port_attr(ifaceobj
.name
,
440 except Exception as e
:
441 self
.logger
.debug('%s' % str(e
))
442 self
.logger
.info('%s: not resetting %s config'
443 %(ifaceobj
.name
, attrname
))
444 # leave the loop for this attribute
447 portlist
= self
.parse_port_list(ifaceobj
.name
, config_val
)
449 self
.log_error('%s: error parsing \'%s %s\''
450 %(ifaceobj
.name
, attrname
, config_val
), ifaceobj
)
452 # there was a configured value so we need to parse it
453 # and set the attribute for each port configured
456 (port
, val
) = p
.split('=')
457 # if it is not bridge port, continue
458 if not os
.path
.exists('/sys/class/net/%s/brport' %port
):
460 json_attr
= self
.get_mod_subattr(attrname
, 'jsonAttr')
461 self
.mstpctlcmd
.set_bridge_port_attr(ifaceobj
.name
,
467 self
.log_error('%s: error setting %s (%s)'
468 %(ifaceobj
.name
, attrname
, str(e
)),
469 ifaceobj
, raise_error
=False)
471 self
.log_warn(str(e
))
474 def _get_default_val(self
, attr
, ifaceobj
, bridgeifaceobj
):
475 if (self
.set_default_mstp_vxlan_bridge_config
476 and ifaceobj
.link_kind
& ifaceLinkKind
.VXLAN
478 'mstpctl-portbpdufilter',
480 'mstpctl-portadminedge',
484 config_val
= bridgeifaceobj
.get_attr_value_first(attr
)
488 if ifaceobj
.name
not in [v
.split('=')[0] for v
in config_val
.split()]:
491 index
= [v
.split('=')[0] for v
in config_val
.split()].index(ifaceobj
.name
)
492 return [v
.split('=')[1] for v
in config_val
.split()][index
]
496 default_val
= policymanager
.policymanager_api
.get_iface_default(module_name
=self
.__class
__.__name
__, ifname
=ifaceobj
.name
, attr
=attr
)
498 return self
.get_mod_subattr(attr
,'default')
501 def _apply_bridge_port_settings(self
, ifaceobj
, bridgename
=None,
505 check
= False if ifupdownflags
.flags
.PERFMODE
else True
507 if not bridgename
and bridgeifaceobj
:
508 bridgename
= bridgeifaceobj
.name
510 if not stp_running_on
:
511 # stp may get turned on at a later point
512 self
.logger
.info('%s: ignoring config'
514 ' (stp on bridge %s is not on yet)' %bridgename
)
516 bvlan_aware
= self
.ipcmd
.bridge_is_vlan_aware(bridgename
)
517 if (not mstpd_running
or
518 not os
.path
.exists('/sys/class/net/%s/brport' %ifaceobj
.name
) or
520 if (not bvlan_aware
and
521 self
.set_default_mstp_vxlan_bridge_config
and
522 (ifaceobj
.link_kind
& ifaceLinkKind
.VXLAN
)):
524 'mstpctl-portbpdufilter',
526 'mstpctl-portadminedge'
528 json_attr
= self
.get_mod_subattr(attr
, 'jsonAttr')
529 config_val
= self
._get
_default
_val
(attr
, ifaceobj
,
532 self
.mstpctlcmd
.set_bridge_port_attr(bridgename
,
534 self
._port
_attrs
_map
[attr
],
538 self
.log_warn('%s: error setting %s (%s)'
539 % (ifaceobj
.name
, attr
, str(e
)))
542 # for "traditional" bridges we also want to let the user configure
543 # some attributes (possibly all of them in the future)
544 applied
= self
._apply
_bridge
_port
_settings
_attributes
_list
(
546 ('mstpctl-portrestrrole', 'portrestrrole'),
547 ('mstpctl-portautoedge', 'portautoedge')
555 # set bridge port attributes
556 return self
._apply
_bridge
_port
_settings
_attributes
_list
(
557 self
._port
_attrs
_map
.items(),
564 def _apply_bridge_port_settings_attributes_list(self
, attributes_list
, ifaceobj
, bridgeifaceobj
, bridgename
, applied
):
565 for attrname
, dstattrname
in attributes_list
:
566 config_val
= ifaceobj
.get_attr_value_first(attrname
)
567 default_val
= self
._get
_default
_val
(attrname
, ifaceobj
, bridgeifaceobj
)
568 jsonAttr
= self
.get_mod_subattr(attrname
, 'jsonAttr')
569 # to see the running value, stp would have to be on
570 # so we would have parsed mstpctl showportdetail json output
572 running_val
= self
.mstpctlcmd
.get_bridge_port_attr(bridgename
,
573 ifaceobj
.name
, jsonAttr
)
575 self
.logger
.info('%s %s: could not get running %s value'
576 %(bridgename
, ifaceobj
.name
, attrname
))
578 if (not config_val
and default_val
and (running_val
!= default_val
)):
579 # this happens when users remove an attribute from a port
580 # and expect the default to be restored with ifreload.
581 config_val
= default_val
583 # there is nothing configured and no default to reset
587 self
.mstpctlcmd
.set_bridge_port_attr(bridgename
,
588 ifaceobj
.name
, dstattrname
, config_val
, json_attr
=jsonAttr
)
591 self
.log_error('%s: error setting %s (%s)'
592 %(ifaceobj
.name
, attrname
, str(e
)), ifaceobj
,
596 def _apply_bridge_port_settings_all(self
, ifaceobj
,
597 ifaceobj_getfunc
=None):
598 self
.logger
.info('%s: applying mstp configuration '
599 %ifaceobj
.name
+ 'specific to ports')
600 # Query running bridge ports. and only apply attributes on them
601 bridgeports
= self
.brctlcmd
.get_bridge_ports(ifaceobj
.name
)
603 self
.logger
.debug('%s: cannot find bridgeports' %ifaceobj
.name
)
605 for bport
in bridgeports
:
606 self
.logger
.info('%s: processing mstp config for port %s'
607 %(ifaceobj
.name
, bport
))
608 if not self
.ipcmd
.link_exists(bport
):
610 if not os
.path
.exists('/sys/class/net/%s/brport' %bport
):
612 bportifaceobjlist
= ifaceobj_getfunc(bport
)
613 if not bportifaceobjlist
:
615 for bportifaceobj
in bportifaceobjlist
:
616 # Dont process bridge port if it already has been processed
617 if (bportifaceobj
.module_flags
.get(self
.name
,0x0) & \
618 mstpctlFlags
.PORT_PROCESSED
):
621 self
._apply
_bridge
_port
_settings
(bportifaceobj
,
622 ifaceobj
.name
, ifaceobj
)
625 self
.log_warn(str(e
))
627 def _is_running_userspace_stp_state_on(self
, bridgename
):
628 stp_state_file
= '/sys/class/net/%s/bridge/stp_state' %bridgename
629 if not stp_state_file
:
631 running_stp_state
= self
.read_file_oneline(stp_state_file
)
632 if running_stp_state
and running_stp_state
== '2':
636 def _up(self
, ifaceobj
, ifaceobj_getfunc
=None):
637 # Check if bridge port
638 bridgename
= self
.ipcmd
.bridge_port_get_bridge_name(ifaceobj
.name
)
640 mstpd_running
= self
.mstpd_running
641 stp_running_on
= self
._is
_running
_userspace
_stp
_state
_on
(bridgename
)
642 applied
= self
._apply
_bridge
_port
_settings
(ifaceobj
, bridgename
,
643 None, stp_running_on
,
646 ifaceobj
.module_flags
[self
.name
] = \
647 ifaceobj
.module_flags
.setdefault(self
.name
,0) | \
648 mstpctlFlags
.PORT_PROCESSED
650 if not self
._is
_bridge
(ifaceobj
):
652 # we are now here because the ifaceobj is a bridge
657 if ifaceobj
.get_attr_value_first('mstpctl-ports'):
658 # If bridge ports specified with mstpctl attr, create the
659 # bridge and also add its ports
660 self
.ipcmd
.batch_start()
661 if not ifupdownflags
.flags
.PERFMODE
:
662 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
663 self
.ipcmd
.link_create(ifaceobj
.name
, 'bridge')
665 self
.ipcmd
.link_create(ifaceobj
.name
, 'bridge')
667 self
._add
_ports
(ifaceobj
)
673 self
.ipcmd
.batch_commit()
674 running_ports
= self
.brctlcmd
.get_bridge_ports(ifaceobj
.name
)
676 # disable ipv6 for ports that were added to bridge
677 self
._ports
_enable
_disable
_ipv
6(running_ports
, '1')
679 stp
= ifaceobj
.get_attr_value_first('mstpctl-stp')
681 self
.set_iface_attr(ifaceobj
, 'mstpctl-stp',
682 self
.brctlcmd
.bridge_set_stp
)
684 stp
= self
.brctlcmd
.bridge_get_stp(ifaceobj
.name
)
685 if (self
.mstpd_running
and
686 (stp
== 'yes' or stp
== 'on')):
687 self
._apply
_bridge
_settings
(ifaceobj
, ifaceobj_getfunc
)
688 self
._apply
_bridge
_port
_settings
_all
(ifaceobj
,
689 ifaceobj_getfunc
=ifaceobj_getfunc
)
691 self
.log_error(str(e
), ifaceobj
)
693 raise Exception(porterrstr
)
695 def _down(self
, ifaceobj
, ifaceobj_getfunc
=None):
696 if not self
._is
_bridge
(ifaceobj
):
699 if ifaceobj
.get_attr_value_first('mstpctl-ports'):
700 # If bridge ports specified with mstpctl attr, delete the
702 ports
= self
.brctlcmd
.get_bridge_ports(ifaceobj
.name
)
704 self
._ports
_enable
_disable
_ipv
6(ports
, '0')
705 self
.brctlcmd
.delete_bridge(ifaceobj
.name
)
707 self
.log_error(str(e
), ifaceobj
)
709 def _query_running_attrs(self
, ifaceobjrunning
, bridge_vlan_aware
=False):
712 tmpbridgeattrdict
= self
.mstpctlcmd
.get_bridge_attrs(ifaceobjrunning
.name
)
713 #self.logger.info('A' + str(tmpbridgeattrdict))
714 if not tmpbridgeattrdict
:
715 return bridgeattrdict
717 for k
,v
in tmpbridgeattrdict
.items():
718 if k
== 'stp' or not v
:
723 attrname
= 'mstpctl-' + k
724 if (v
and v
!= self
.get_mod_subattr(attrname
, 'default')
725 and attrname
!= 'mstpctl-maxhops'):
726 bridgeattrdict
[attrname
] = [v
]
728 ports
= self
.brctlcmd
.get_bridge_ports(ifaceobjrunning
.name
)
729 # Do this only for vlan-UNAWARE-bridge
730 if ports
and not bridge_vlan_aware
:
731 portconfig
= {'mstpctl-portautoedge' : '',
732 'mstpctl-portbpdufilter' : '',
733 'mstpctl-portnetwork' : '',
734 'mstpctl-portpathcost' : '',
735 'mstpctl-portadminedge' : '',
736 'mstpctl-portp2p' : '',
737 'mstpctl-portrestrrole' : '',
738 'mstpctl-portrestrtcn' : '',
739 'mstpctl-bpduguard' : '',
740 'mstpctl-treeportprio' : '',
741 'mstpctl-treeportcost' : ''}
745 for attr
in ['mstpctl-portautoedge',
746 'mstpctl-portbpdufilter',
747 'mstpctl-portnetwork',
748 'mstpctl-portadminedge',
750 'mstpctl-portrestrrole',
751 'mstpctl-portrestrtcn',
754 v
= self
._get
_bridge
_port
_attr
_value
(ifaceobjrunning
.name
,
757 portconfig
[attr
] += ' %s=%s' % (p
, v
)
759 for attr
in ['mstpctl-portpathcost', 'mstpctl-treeportcost']:
760 v
= self
._get
_bridge
_port
_attr
_value
(ifaceobjrunning
.name
,
762 if v
and v
!= self
.get_mod_subattr(attr
, 'default'):
763 portconfig
[attr
] += ' %s=%s' % (p
, v
)
765 bridgeattrdict
.update({k
: [v
] for k
, v
in portconfig
.items()
767 return bridgeattrdict
769 def _get_config_stp(self
, ifaceobj
):
770 stp
= (ifaceobj
.get_attr_value_first('mstpctl-stp') or
771 ifaceobj
.get_attr_value_first('bridge-stp') or
772 policymanager
.policymanager_api
.get_iface_default(module_name
=self
.__class
__.__name
__, ifname
=ifaceobj
.name
, attr
='mstpctl-stp') or
773 # this is a temporary method to access policy default value of bridge-stp
774 policymanager
.policymanager_api
.get_iface_default(module_name
='bridge', ifname
=ifaceobj
.name
, attr
='bridge-stp'))
775 return utils
.get_boolean_from_string(stp
)
777 def _get_running_stp(self
, ifaceobj
):
778 stp
= self
.brctlcmd
.bridge_get_stp(ifaceobj
.name
)
779 return utils
.get_boolean_from_string(stp
)
781 def _query_check_bridge(self
, ifaceobj
, ifaceobjcurr
,
782 ifaceobj_getfunc
=None):
783 # list of attributes that are not supported currently
784 blacklistedattrs
= ['mstpctl-portpathcost',
785 'mstpctl-treeportprio', 'mstpctl-treeportcost']
786 if not self
.brctlcmd
.bridge_exists(ifaceobj
.name
):
787 self
.logger
.debug('bridge %s does not exist' %ifaceobj
.name
)
789 ifaceattrs
= self
.dict_key_subset(ifaceobj
.config
,
790 self
.get_mod_attrs())
791 if self
.set_default_mstp_vxlan_bridge_config
:
792 for attr
in ('mstpctl-portbpdufilter', 'mstpctl-bpduguard', 'mstpctl-portadminedge'):
793 if attr
not in ifaceattrs
:
794 ifaceattrs
.append(attr
)
797 runningattrs
= self
.mstpctlcmd
.get_bridge_attrs(ifaceobj
.name
)
798 #self.logger.info('B' + str(runningattrs))
801 config_stp
= self
._get
_config
_stp
(ifaceobj
)
802 running_stp
= self
._get
_running
_stp
(ifaceobj
)
803 running_port_list
= self
.brctlcmd
.get_bridge_ports(ifaceobj
.name
)
805 # for all mstpctl options
806 if k
in blacklistedattrs
:
808 if k
in ('mstpctl-portbpdufilter', 'mstpctl-bpduguard', 'mstpctl-portadminedge'):
809 #special case, 'ifquery --check --with-defaults' on a VLAN
811 if not running_port_list
:
813 if (not config_stp
or not running_stp
):
815 v
= ifaceobj
.get_attr_value_first(k
)
822 for bportval
in v
.split():
823 config_val
[bportval
.split('=')[0]] = bportval
.split('=')[1]
824 #for bport in bridgeports:
825 for bport
in running_port_list
:
826 bportifaceobjlist
= ifaceobj_getfunc(bport
)
827 if not bportifaceobjlist
:
829 for bportifaceobj
in bportifaceobjlist
:
830 if (bport
not in config_val
):
831 if (bportifaceobj
.link_kind
& ifaceLinkKind
.VXLAN
):
832 if (not ifupdownflags
.flags
.WITHDEFAULTS
or
833 (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_VLAN_AWARE
)):
839 if ((bportifaceobj
.link_kind
& ifaceLinkKind
.VXLAN
) and
840 (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_VLAN_AWARE
)):
842 conf
= config_val
[bport
]
843 jsonAttr
= self
.get_mod_subattr(k
, 'jsonAttr')
845 running_val
= self
.mstpctlcmd
.get_bridge_port_attr(ifaceobj
.name
, bport
, jsonAttr
)
847 self
.logger
.info('%s %s: could not get running %s value'
848 %(ifaceobj
.name
, bport
, attr
))
850 if conf
!= running_val
:
852 bridge_ports
.update({bport
: running_val
})
853 for port
, val
in bridge_ports
.items():
854 #running state format
855 #mstpctl-portbpdufilter swp2=yes swp1=yes vx-14567101=yes [pass]
856 #mstpctl-bpduguard swp2=yes swp1=yes vx-14567101=yes [pass]
857 state
+= port
+ '=' + val
+ ' '
859 ifaceobjcurr
.update_config_with_status(k
, state
, result
)
862 # get the corresponding ifaceobj attr
863 v
= ifaceobj
.get_attr_value_first(k
)
867 # Get the running attribute
868 rv
= runningattrs
.get(k
[8:])
869 if k
== 'mstpctl-stp':
870 # special case stp compare because it may
871 # contain more than one valid values
872 stp_on_vals
= ['on', 'yes']
873 stp_off_vals
= ['off']
874 rv
= self
.brctlcmd
.bridge_get_stp(ifaceobj
.name
)
875 if ((v
in stp_on_vals
and rv
in stp_on_vals
) or
876 (v
in stp_off_vals
and rv
in stp_off_vals
)):
877 ifaceobjcurr
.update_config_with_status('mstpctl-stp', v
, 0)
879 ifaceobjcurr
.update_config_with_status('mstpctl-stp', v
, 1)
882 if k
== 'mstpctl-ports':
883 # special case ports because it can contain regex or glob
884 # XXX: We get all info from mstputils, which means if
885 # mstpd is down, we will not be returning any bridge bridgeports
886 bridge_port_list
= self
._get
_bridge
_port
_list
(ifaceobj
)
887 if not running_port_list
and not bridge_port_list
:
890 if running_port_list
and bridge_port_list
:
891 difference
= Set(running_port_list
).symmetric_difference(
892 Set(bridge_port_list
))
895 ifaceobjcurr
.update_config_with_status('mstpctl-ports',
896 ' '.join(running_port_list
)
897 if running_port_list
else '', portliststatus
)
898 elif k
[:12] == 'mstpctl-port' or k
== 'mstpctl-bpduguard':
899 # Now, look at port attributes
900 # derive the mstpctlcmd attr name
901 #mstpctlcmdattrname = k[12:] if k[:12] == 'mstpctl-port' else k[8:]
902 mstpctlcmdattrname
= k
[8:]
904 # for port attributes, the attributes are in a list
905 # <portname>=<portattrvalue>
908 vlist
= self
.parse_port_list(ifaceobj
.name
, v
)
911 for vlistitem
in vlist
:
913 (p
, v
) = vlistitem
.split('=')
914 currv
= self
._get
_bridge
_port
_attr
_value
(ifaceobj
.name
, p
, k
)
916 currstr
+= ' %s=%s' %(p
, currv
)
918 currstr
+= ' %s=%s' %(p
, 'None')
922 self
.log_warn(str(e
))
924 ifaceobjcurr
.update_config_with_status(k
, currstr
, status
)
926 ifaceobjcurr
.update_config_with_status(k
, '', 1)
928 ifaceobjcurr
.update_config_with_status(k
, rv
, 1)
930 ifaceobjcurr
.update_config_with_status(k
, rv
, 0)
932 def _query_check_bridge_vxlan_port(self
, ifaceobj
, ifaceobjcurr
,
933 ifaceobj_getfunc
=None):
934 masters
= ifaceobj
.upperifaces
937 for bridge
in masters
:
938 bifaceobjlist
= ifaceobj_getfunc(bridge
)
939 for bifaceobj
in bifaceobjlist
:
940 if (self
._is
_bridge
(bifaceobj
) and
941 self
.set_default_mstp_vxlan_bridge_config
and
942 (bifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_VLAN_AWARE
)):
943 config_stp
= self
._get
_config
_stp
(bifaceobj
)
944 running_stp
= self
._get
_running
_stp
(bifaceobj
)
945 if (not config_stp
or not running_stp
):
948 'mstpctl-portbpdufilter',
950 'mstpctl-portadminedge'
952 jsonAttr
= self
.get_mod_subattr(attr
, 'jsonAttr')
953 config_val
= bifaceobj
.get_attr_value_first(attr
)
955 if ifaceobj
.name
not in [v
.split('=')[0] for v
in config_val
.split()]:
956 if not ifupdownflags
.flags
.WITHDEFAULTS
:
960 index
= [v
.split('=')[0] for v
in config_val
.split()].index(ifaceobj
.name
)
961 config_val
= [v
.split('=')[1] for v
in config_val
.split()][index
]
963 if not ifupdownflags
.flags
.WITHDEFAULTS
:
967 running_val
= self
.mstpctlcmd
.get_bridge_port_attr(bifaceobj
.name
,
968 ifaceobj
.name
, jsonAttr
)
970 self
.logger
.info('%s %s: could not get running %s value'
971 %(bifaceobj
.name
, ifaceobj
.name
, attr
))
973 ifaceobjcurr
.update_config_with_status(attr
,
975 0 if running_val
== config_val
else 1)
979 def _query_check_bridge_port(self
, ifaceobj
, ifaceobjcurr
):
980 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
981 #self.logger.debug('bridge port %s does not exist' %ifaceobj.name)
982 ifaceobjcurr
.status
= ifaceStatus
.NOTFOUND
984 # Check if this is a bridge port
985 if not self
._is
_bridge
_port
(ifaceobj
):
986 # mark all the bridge attributes as error
987 ifaceobjcurr
.check_n_update_config_with_status_many(ifaceobj
,
988 self
._port
_attrs
_map
.keys(), 0)
990 bridgename
= self
.ipcmd
.bridge_port_get_bridge_name(ifaceobj
.name
)
991 # list of attributes that are not supported currently
992 blacklistedattrs
= ['mstpctl-portpathcost',
993 'mstpctl-treeportprio', 'mstpctl-treeportcost']
994 ifaceattrs
= self
.dict_key_subset(ifaceobj
.config
,
995 self
._port
_attrs
_map
.keys())
998 runningattrs
= self
.mstpctlcmd
.get_bridge_attrs(ifaceobj
.name
)
999 #self.logger.info('C' + str(runningattrs))
1000 if not runningattrs
:
1002 for k
in ifaceattrs
:
1003 # for all mstpctl options
1004 # get the corresponding ifaceobj attr
1005 v
= ifaceobj
.get_attr_value_first(k
)
1006 if not v
or k
in blacklistedattrs
:
1007 ifaceobjcurr
.update_config_with_status(k
, v
, -1)
1009 currv
= self
._get
_bridge
_port
_attr
_value
(bridgename
, ifaceobj
.name
, k
)
1012 ifaceobjcurr
.update_config_with_status(k
, currv
, 1)
1014 ifaceobjcurr
.update_config_with_status(k
, currv
, 0)
1016 ifaceobjcurr
.update_config_with_status(k
, None, 1)
1018 def _query_check(self
, ifaceobj
, ifaceobjcurr
, ifaceobj_getfunc
=None):
1019 if self
._is
_bridge
(ifaceobj
):
1020 self
._query
_check
_bridge
(ifaceobj
, ifaceobjcurr
, ifaceobj_getfunc
)
1021 elif ifaceobj
.link_kind
& ifaceLinkKind
.VXLAN
:
1022 self
._query
_check
_bridge
_vxlan
_port
(ifaceobj
, ifaceobjcurr
,
1025 self
._query
_check
_bridge
_port
(ifaceobj
, ifaceobjcurr
)
1027 def _query_bridge_port_attr(self
, ifaceobjrunning
, bridgename
, attr
, value_cmp
):
1028 v
= self
._get
_bridge
_port
_attr
_value
(bridgename
,
1029 ifaceobjrunning
.name
,
1031 if v
and value_cmp
and v
!= value_cmp
:
1032 ifaceobjrunning
.update_config(attr
, v
)
1033 elif v
and not value_cmp
:
1034 ifaceobjrunning
.update_config(attr
, v
)
1036 def _query_running_bridge_port(self
, ifaceobjrunning
):
1037 bridgename
= self
.ipcmd
.bridge_port_get_bridge_name(
1038 ifaceobjrunning
.name
)
1040 self
.logger
.warn('%s: unable to determine bridgename'
1041 %ifaceobjrunning
.name
)
1043 if self
.brctlcmd
.bridge_get_stp(bridgename
) == 'no':
1044 # This bridge does not run stp, return
1046 # if userspace stp not set, return
1047 if self
.systcl_get_net_bridge_stp_user_space() != '1':
1050 self
._query
_bridge
_port
_attr
(ifaceobjrunning
, bridgename
,
1051 'mstpctl-portautoedge',
1052 self
.get_mod_subattr('mstpctl-portautoedge', 'default'))
1054 self
._query
_bridge
_port
_attr
(ifaceobjrunning
, bridgename
,
1055 'mstpctl-portbpdufilter',
1058 self
._query
_bridge
_port
_attr
(ifaceobjrunning
, bridgename
,
1059 'mstpctl-portnetwork',
1062 # XXX: Can we really get path cost of a port ???
1063 #v = self.mstpctlcmd.get_portpathcost(ifaceobjrunning.name, p)
1064 #if v and v != self.get_mod_subattr('mstpctl-pathcost',
1066 # ifaceobjrunning.update_config('mstpctl-network', v)
1068 self
._query
_bridge
_port
_attr
(ifaceobjrunning
, bridgename
,
1069 'mstpctl-portadminedge',
1072 self
._query
_bridge
_port
_attr
(ifaceobjrunning
, bridgename
,
1076 self
._query
_bridge
_port
_attr
(ifaceobjrunning
, bridgename
,
1077 'mstpctl-portrestrrole',
1080 self
._query
_bridge
_port
_attr
(ifaceobjrunning
, bridgename
,
1081 'mstpctl-portrestrtcn',
1084 self
._query
_bridge
_port
_attr
(ifaceobjrunning
, bridgename
,
1085 'mstpctl-bpduguard',
1088 # XXX: Can we really get path cost of a port ???
1089 #v = self.mstpctlcmd.get_bridgeport_attr(ifaceobjrunning.name,
1091 #if v and v != self.get_mod_subattr('mstpctl-treeportprio',
1093 # portconfig['mstpctl-treeportprio'] += ' %s=%s' %(p, v)
1095 #v = self.mstpctlcmd.get_bridgeport_attr(ifaceobjrunning.name,
1097 #if v and v != self.get_mod_subattr('mstpctl-treeportcost',
1099 # portconfig['mstpctl-treeportcost'] += ' %s=%s' %(p, v)
1101 def _query_running_bridge(self
, ifaceobjrunning
):
1102 if self
.brctlcmd
.bridge_get_stp(ifaceobjrunning
.name
) == 'no':
1103 # This bridge does not run stp, return
1105 # if userspace stp not set, return
1106 if self
.systcl_get_net_bridge_stp_user_space() != '1':
1108 # Check if mstp really knows about this bridge
1109 if not self
.mstpctlcmd
.mstpbridge_exists(ifaceobjrunning
.name
):
1111 bridge_vlan_aware
= False
1112 if ifaceobjrunning
.get_attr_value_first('bridge-vlan-aware') == 'yes':
1113 bridge_vlan_aware
= True
1114 ifaceobjrunning
.update_config_dict(self
._query
_running
_attrs
(
1118 def _query_running(self
, ifaceobjrunning
, **extra_args
):
1119 if self
.brctlcmd
.bridge_exists(ifaceobjrunning
.name
):
1120 self
._query
_running
_bridge
(ifaceobjrunning
)
1121 elif self
.brctlcmd
.is_bridge_port(ifaceobjrunning
.name
):
1122 self
._query
_running
_bridge
_port
(ifaceobjrunning
)
1124 def _query_bridge_port(self
, ifaceobj
, ifaceobj_getfunc
=None):
1138 bridge_ports vxlan1wd vxlan2wd
1139 bridge-vlan-aware yes
1147 $ ifquery --with-defaults vxlan1wd
1151 mstpctl-portbpdufilter yes
1152 mstpctl-bpduguard yes
1154 masters
= ifaceobj
.upperifaces
1158 for bridge
in masters
:
1159 bifaceobj
= ifaceobj_getfunc(bridge
)[0]
1160 if (self
._is
_bridge
(bifaceobj
) and
1161 self
.set_default_mstp_vxlan_bridge_config
and
1162 (bifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_VLAN_AWARE
)):
1163 for attr
in ('mstpctl-portbpdufilter',
1164 'mstpctl-bpduguard',
1165 'mstpctl-portadminedge'):
1166 jsonAttr
= self
.get_mod_subattr(attr
, 'jsonAttr')
1167 config_val
= ifaceobj
.get_attr_value_first(attr
)
1168 if config_val
or not ifupdownflags
.flags
.WITHDEFAULTS
:
1171 ifaceobj
.replace_config(attr
, config_val
)
1173 except Exception, e
:
1174 self
.logger
.info("%s: %s" %(ifaceobj
.name
, str(e
)))
1177 def _query(self
, ifaceobj
, ifaceobj_getfunc
=None, **kwargs
):
1178 """ add default policy attributes supported by the module """
1179 if not self
._is
_bridge
(ifaceobj
):
1180 if (ifaceobj
.module_flags
.get(self
.name
,0x0) &
1181 mstpctlFlags
.PORT_PROCESSED
):
1183 self
._query
_bridge
_port
(ifaceobj
, ifaceobj_getfunc
)
1184 ifaceobj
.module_flags
[self
.name
] = (
1185 ifaceobj
.module_flags
.setdefault(self
.name
,0) |
1186 mstpctlFlags
.PORT_PROCESSED
)
1188 lowerinfs
= ifaceobj
.lowerifaces
1191 if ifaceobj
.get_attr_value_first('bridge-vlan-aware') != 'yes':
1192 for attr
in ('mstpctl-portbpdufilter', 'mstpctl-bpduguard', 'mstpctl-portadminedge'):
1194 config
= ifaceobj
.get_attr_value_first(attr
)
1195 for port
in lowerinfs
:
1196 bportobjlist
= ifaceobj_getfunc(port
)
1197 for bportobj
in bportobjlist
:
1198 if bportobj
.get_attr_value_first('vxlan-id'):
1200 if port
not in [v
.split('=')[0] for v
in config
.split()]:
1201 config
+= ' %s=yes' %port
1203 state
+= '%s=yes ' %port
1204 ifaceobj
.replace_config(attr
, config
if config
else state
)
1206 for attr
in ('mstpctl-portbpdufilter', 'mstpctl-bpduguard', 'mstpctl-portadminedge'):
1208 config
= ifaceobj
.get_attr_value_first(attr
)
1209 for port
in lowerinfs
:
1210 bportobjlist
= ifaceobj_getfunc(port
)
1211 for bportobj
in bportobjlist
:
1212 if (bportobj
.module_flags
.get(self
.name
,0x0) &
1213 mstpctlFlags
.PORT_PROCESSED
):
1215 if bportobj
.get_attr_value_first('vxlan-id'):
1217 if port
not in [v
.split('=')[0] for v
in config
.split()]:
1218 bportobj
.update_config(attr
, 'yes')
1220 index
= [v
.split('=')[0] for v
in config
.split()].index(port
)
1221 state
= [v
.split('=')[1] for v
in config
.split()][index
]
1222 bportobj
.update_config(attr
, '%s' %state
)
1225 config
= ' '.join(v
)
1227 bportobj
.replace_config(attr
, 'yes')
1228 bportobj
.module_flags
[self
.name
] = (
1229 bportobj
.module_flags
.setdefault(self
.name
,0) |
1230 mstpctlFlags
.PORT_PROCESSED
)
1232 ifaceobj
.replace_config(attr
, config
)
1236 _run_ops
= {'pre-up' : _up
,
1237 'post-down' : _down
,
1238 'query-checkcurr' : _query_check
,
1239 'query-running' : _query_running
,
1243 """ returns list of ops supported by this module """
1244 return self
._run
_ops
.keys()
1246 def _init_command_handlers(self
):
1248 self
.ipcmd
= self
.brctlcmd
= LinkUtils()
1249 if not self
.mstpctlcmd
:
1250 self
.mstpctlcmd
= mstpctlutil()
1252 def run(self
, ifaceobj
, operation
, query_ifaceobj
=None,
1253 ifaceobj_getfunc
=None, **extra_args
):
1254 """ run mstp configuration on the interface object passed as argument
1257 **ifaceobj** (object): iface object
1259 **operation** (str): any of 'pre-up', 'post-down', 'query-checkcurr',
1262 **query_ifaceobj** (object): query check ifaceobject. This is only
1263 valid when op is 'query-checkcurr'. It is an object same as
1264 ifaceobj, but contains running attribute values and its config
1265 status. The modules can use it to return queried running state
1266 of interfaces. status is success if the running state is same
1267 as user required state in ifaceobj. error otherwise.
1269 if ifaceobj
.type == ifaceType
.BRIDGE_VLAN
:
1271 op_handler
= self
._run
_ops
.get(operation
)
1274 self
._init
_command
_handlers
()
1275 if operation
== 'query-checkcurr':
1276 op_handler(self
, ifaceobj
, query_ifaceobj
,
1277 ifaceobj_getfunc
=ifaceobj_getfunc
)
1279 op_handler(self
, ifaceobj
, ifaceobj_getfunc
=ifaceobj_getfunc
)