]>
git.proxmox.com Git - mirror_ifupdown2.git/blob - addons/mstpctl.py
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 ifupdownaddons
.mstpctlutil
import mstpctlutil
15 class mstpctl(moduleBase
):
16 """ ifupdown2 addon module to configure mstp attributes """
18 _modinfo
= {'mhelp' : 'mstp configuration module for bridges',
21 {'help' : 'mstp ports',
24 {'help': 'bridge stp yes/no',
28 {'help': 'tree priority',
30 'validrange' : ['0', '65535'],
32 'example' : ['mstpctl-treeprio 32768']},
34 {'help': 'ageing time',
37 'example' : ['mstpctl-ageing 300']},
39 { 'help' : 'max message age',
42 'example' : ['mstpctl-maxage 20']},
44 { 'help' : 'set forwarding delay',
47 'example' : ['mstpctl-fdelay 15']},
49 { 'help' : 'bridge max hops',
52 'example' : ['mstpctl-maxhops 15']},
53 'mstpctl-txholdcount' :
54 { 'help' : 'bridge transmit holdcount',
57 'example' : ['mstpctl-txholdcount 6']},
59 { 'help' : 'bridge force stp version',
62 'example' : ['mstpctl-forcevers rstp']},
63 'mstpctl-portpathcost' :
64 { 'help' : 'bridge port path cost',
67 'example' : ['mstpctl-portpathcost swp1=0 swp2=1']},
69 { 'help' : 'bridge port p2p detection mode',
71 'validvals' : ['yes', 'no', 'auto'],
73 'example' : ['mstpctl-portp2p swp1=no swp2=no']},
74 'mstpctl-portrestrrole' :
76 'enable/disable port ability to take root role of the port',
78 'validvals' : ['yes', 'no'],
80 'example' : ['mstpctl-portrestrrole swp1=no swp2=no']},
81 'mstpctl-portrestrtcn' :
83 'enable/disable port ability to propagate received topology change notification of the port',
85 'validvals' : ['yes', 'no'],
87 'example' : ['mstpctl-portrestrtcn swp1=no swp2=no']},
90 'enable/disable bpduguard',
92 'validvals' : ['yes', 'no'],
94 'example' : ['mstpctl-bpduguard swp1=no swp2=no']},
95 'mstpctl-treeportprio' :
97 'port priority for MSTI instance',
99 'validrange' : ['0', '240'],
101 'example' : ['mstpctl-treeportprio swp1=128 swp2=128']},
103 { 'help' : 'set hello time',
106 'example' : ['mstpctl-hello 2']},
107 'mstpctl-portnetwork' :
108 { 'help' : 'enable/disable bridge assurance capability for a port',
109 'validvals' : ['yes', 'no'],
112 'example' : ['mstpctl-portnetwork swp1=no swp2=no']},
113 'mstpctl-portadminedge' :
114 { 'help' : 'enable/disable initial edge state of the port',
115 'validvals' : ['yes', 'no'],
118 'example' : ['mstpctl-portadminedge swp1=no swp2=no']},
119 'mstpctl-portautoedge' :
120 { 'help' : 'enable/disable auto transition to/from edge state of the port',
121 'validvals' : ['yes', 'no'],
124 'example' : ['mstpctl-portautoedge swp1=yes swp2=yes']},
125 'mstpctl-treeportcost' :
126 { 'help' : 'port tree cost',
128 'mstpctl-portbpdufilter' :
129 { 'help' : 'enable/disable bpdu filter on a port. ' +
130 'syntax varies when defined under a bridge ' +
132 'validvals' : ['yes', 'no'],
135 'example' : ['under a bridge: mstpctl-portbpdufilter swp1=no swp2=no',
136 'under a port: mstpctl-portbpdufilter yes']},
139 # Maps mstp bridge attribute names to corresponding mstpctl commands
140 # XXX: This can be encoded in the modules dict above
141 _attrs_map
= OrderedDict([('mstpctl-treeprio' , 'treeprio'),
142 ('mstpctl-ageing' , 'ageing'),
143 ('mstpctl-maxage' , 'maxage'),
144 ('mstpctl-fdelay' , 'fdelay'),
145 ('mstpctl-maxhops' , 'maxhops'),
146 ('mstpctl-txholdcount' , 'txholdcount'),
147 ('mstpctl-forcevers', 'forcevers'),
148 ('mstpctl-hello' , 'hello')])
150 # Maps mstp port attribute names to corresponding mstpctl commands
151 # XXX: This can be encoded in the modules dict above
152 _port_attrs_map
= {'mstpctl-portpathcost' : 'portpathcost',
153 'mstpctl-portadminedge' : 'portadminedge',
154 'mstpctl-portautoedge' : 'portautoedge' ,
155 'mstpctl-portp2p' : 'portp2p',
156 'mstpctl-portrestrrole' : 'portrestrrole',
157 'mstpctl-portrestrtcn' : 'portrestrtcn',
158 'mstpctl-bpduguard' : 'bpduguard',
159 'mstpctl-treeportprio' : 'treeportprio',
160 'mstpctl-treeportcost' : 'treeportcost',
161 'mstpctl-portnetwork' : 'portnetwork',
162 'mstpctl-portbpdufilter' : 'portbpdufilter'}
164 # declare some ifaceobj priv_flags.
165 # XXX: This assumes that the priv_flags is owned by this module
167 _BRIDGE_PORT_PROCESSED
= 0x1
169 def __init__(self
, *args
, **kargs
):
170 moduleBase
.__init
__(self
, *args
, **kargs
)
173 self
.mstpctlcmd
= None
175 def _is_bridge(self
, ifaceobj
):
176 if (ifaceobj
.get_attr_value_first('mstpctl-ports') or
177 ifaceobj
.get_attr_value_first('bridge-ports')):
181 def _is_bridge_port(self
, ifaceobj
):
182 if self
.brctlcmd
.is_bridge_port(ifaceobj
.name
):
186 def get_dependent_ifacenames(self
, ifaceobj
, ifacenames_all
=None):
187 if not self
._is
_bridge
(ifaceobj
):
189 return self
.parse_port_list(ifaceobj
.get_attr_value_first(
190 'mstpctl-ports'), ifacenames_all
)
192 def get_dependent_ifacenames_running(self
, ifaceobj
):
193 self
._init
_command
_handlers
()
194 if (self
.brctlcmd
.bridge_exists(ifaceobj
.name
) and
195 not self
.mstpctlcmd
.mstpbridge_exists(ifaceobj
.name
)):
197 return self
.brctlcmd
.get_bridge_ports(ifaceobj
.name
)
199 def _get_bridge_port_list(self
, ifaceobj
):
201 # port list is also available in the previously
202 # parsed dependent list. Use that if available, instead
203 # of parsing port expr again
204 port_list
= ifaceobj
.lowerifaces
207 ports
= ifaceobj
.get_attr_value_first('mstpctl-ports')
209 return self
.parse_port_list(ports
)
213 def _add_ports(self
, ifaceobj
):
214 bridgeports
= self
._get
_bridge
_port
_list
(ifaceobj
)
216 runningbridgeports
= []
217 # Delete active ports not in the new port list
218 if not self
.PERFMODE
:
219 runningbridgeports
= self
.brctlcmd
.get_bridge_ports(ifaceobj
.name
)
220 if runningbridgeports
:
221 [self
.ipcmd
.link_set(bport
, 'nomaster')
222 for bport
in runningbridgeports
223 if not bridgeports
or bport
not in bridgeports
]
225 runningbridgeports
= []
229 for bridgeport
in Set(bridgeports
).difference(Set(runningbridgeports
)):
231 if not self
.DRYRUN
and not self
.ipcmd
.link_exists(bridgeport
):
232 self
.log_warn('%s: bridge port %s does not exist'
233 %(ifaceobj
.name
, bridgeport
))
236 self
.ipcmd
.link_set(bridgeport
, 'master', ifaceobj
.name
)
237 self
.write_file('/proc/sys/net/ipv6/conf/%s' %bridgeport
+
238 '/disable_ipv6', '1')
239 self
.ipcmd
.addr_flush(bridgeport
)
241 self
.log_error(str(e
))
243 self
.log_error('error configuring bridge (missing ports)')
245 def _apply_bridge_settings(self
, ifaceobj
):
246 check
= False if self
.PERFMODE
else True
248 # set bridge attributes
249 for attrname
, dstattrname
in self
._attrs
_map
.items():
251 v
= ifaceobj
.get_attr_value_first(attrname
)
254 if attrname
== 'mstpctl-treeprio':
255 self
.mstpctlcmd
.set_bridge_treeprio(ifaceobj
.name
,
258 self
.mstpctlcmd
.set_bridge_attr(ifaceobj
.name
,
259 dstattrname
, v
, check
)
261 self
.logger
.warn('%s' %str
(e
))
264 # set bridge port attributes
265 for attrname
, dstattrname
in self
._port
_attrs
_map
.items():
266 attrval
= ifaceobj
.get_attr_value_first(attrname
)
269 portlist
= self
.parse_port_list(attrval
)
271 self
.log_warn('%s: error parsing \'%s %s\''
272 %(ifaceobj
.name
, attrname
, attrval
))
276 (port
, val
) = p
.split('=')
277 self
.mstpctlcmd
.set_bridgeport_attr(ifaceobj
.name
,
278 port
, dstattrname
, val
, check
)
280 self
.log_warn('%s: error setting %s (%s)'
281 %(ifaceobj
.name
, attrname
, str(e
)))
283 self
.log_warn(str(e
))
286 def _apply_bridge_port_settings(self
, ifaceobj
, bridgename
=None,
287 bridgeifaceobj
=None, stp_on
=True,
289 check
= False if self
.PERFMODE
else True
290 if not bridgename
and bridgeifaceobj
:
291 bridgename
= bridgeifaceobj
.name
292 # set bridge port attributes
293 for attrname
, dstattrname
in self
._port
_attrs
_map
.items():
294 attrval
= ifaceobj
.get_attr_value_first(attrname
)
297 # # If bridge object available, check if the bridge
298 # # has the attribute set, in which case,
299 # # inherit it from the bridge
300 # attrval = bridgeifaceobj.get_attr_value_first(attrname)
306 self
.logger
.warn('%s: cannot set %s (stp on bridge %s not on)\n'
307 %(ifaceobj
.name
, attrname
, bridgename
))
309 if not mstpd_running
:
312 self
.mstpctlcmd
.set_bridgeport_attr(bridgename
,
313 ifaceobj
.name
, dstattrname
, attrval
, check
)
315 self
.log_warn('%s: error setting %s (%s)'
316 %(ifaceobj
.name
, attrname
, str(e
)))
318 def _apply_bridge_port_settings_all(self
, ifaceobj
,
319 ifaceobj_getfunc
=None):
320 self
.logger
.info('%s: applying mstp configuration '
321 %ifaceobj
.name
+ 'specific to ports')
323 bridgeports
= self
._get
_bridge
_port
_list
(ifaceobj
)
325 self
.logger
.debug('%s: cannot find bridgeports' %ifaceobj
.name
)
327 for bport
in bridgeports
:
328 self
.logger
.info('%s: processing mstp config for port %s'
329 %(ifaceobj
.name
, bport
))
330 if not self
.ipcmd
.link_exists(bport
):
331 self
.logger
.warn('%s: port %s does not exist' %(ifaceobj
.name
,
334 bportifaceobjlist
= ifaceobj_getfunc(bport
)
335 if not bportifaceobjlist
:
337 for bportifaceobj
in bportifaceobjlist
:
338 # Dont process bridge port if it already has been processed
339 if bportifaceobj
.priv_flags
& self
._BRIDGE
_PORT
_PROCESSED
:
342 self
._apply
_bridge
_port
_settings
(bportifaceobj
,
343 ifaceobj
.name
, ifaceobj
)
345 self
.log_warn(str(e
))
347 def _up(self
, ifaceobj
, ifaceobj_getfunc
=None):
348 # Check if bridge port
349 bridgename
= self
.ipcmd
.bridge_port_get_bridge_name(ifaceobj
.name
)
351 mstpd_running
= (True if self
.mstpctlcmd
.is_mstpd_running()
353 stp_on
= (True if self
.read_file_oneline(
354 '/sys/class/net/%s/bridge/stp_state'
355 %bridgename
) == '2' else False)
356 self
._apply
_bridge
_port
_settings
(ifaceobj
, bridgename
, None,
357 stp_on
, mstpd_running
)
358 ifaceobj
.priv_flags |
= self
._BRIDGE
_PORT
_PROCESSED
360 if not self
._is
_bridge
(ifaceobj
):
366 if ifaceobj
.get_attr_value_first('mstpctl-ports'):
367 # If bridge ports specified with mstpctl attr, create the
368 # bridge and also add its ports
369 self
.ipcmd
.batch_start()
370 if not self
.PERFMODE
:
371 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
372 self
.ipcmd
.link_create(ifaceobj
.name
, 'bridge')
374 self
.ipcmd
.link_create(ifaceobj
.name
, 'bridge')
376 self
._add
_ports
(ifaceobj
)
382 self
.ipcmd
.batch_commit()
383 stp
= ifaceobj
.get_attr_value_first('mstpctl-stp')
385 self
.set_iface_attr(ifaceobj
, 'mstpctl-stp',
386 self
.brctlcmd
.set_stp
)
388 stp
= self
.brctlcmd
.get_stp(ifaceobj
.name
)
389 if (self
.mstpctlcmd
.is_mstpd_running() and
390 (stp
== 'yes' or stp
== 'on')):
391 self
._apply
_bridge
_settings
(ifaceobj
)
392 self
._apply
_bridge
_port
_settings
_all
(ifaceobj
,
393 ifaceobj_getfunc
=ifaceobj_getfunc
)
395 self
.log_error(str(e
))
397 raise Exception(porterrstr
)
399 def _down(self
, ifaceobj
, ifaceobj_getfunc
=None):
400 if not self
._is
_bridge
(ifaceobj
):
403 if ifaceobj
.get_attr_value_first('mstpctl-ports'):
404 # If bridge ports specified with mstpctl attr, delete the
406 ports
= self
.brctlcmd
.get_bridge_ports(ifaceobj
.name
)
409 proc_file
= ('/proc/sys/net/ipv6/conf/%s' %p
+
411 self
.write_file(proc_file
, '0')
412 self
.brctlcmd
.delete_bridge(ifaceobj
.name
)
414 self
.log_error(str(e
))
416 def _query_running_attrs(self
, ifaceobjrunning
):
419 tmpbridgeattrdict
= self
.mstpctlcmd
.get_bridge_attrs(ifaceobjrunning
.name
)
420 if not tmpbridgeattrdict
:
421 return bridgeattrdict
423 for k
,v
in tmpbridgeattrdict
.items():
424 if k
== 'stp' or not v
:
429 attrname
= 'mstpctl-' + k
430 if v
and v
!= self
.get_mod_subattr(attrname
, 'default'):
431 bridgeattrdict
[attrname
] = [v
]
433 ports
= self
.brctlcmd
.get_bridge_ports(ifaceobjrunning
.name
)
435 portconfig
= {'mstpctl-portnetwork' : '',
436 'mstpctl-portpathcost' : '',
437 'mstpctl-portadminedge' : '',
438 'mstpctl-portautoedge' : '',
439 'mstpctl-portp2p' : '',
440 'mstpctl-portrestrrole' : '',
441 'mstpctl-portrestrtcn' : '',
442 'mstpctl-bpduguard' : '',
443 'mstpctl-treeportprio' : '',
444 'mstpctl-treeportcost' : ''}
447 v
= self
.mstpctlcmd
.get_bridgeport_attr(ifaceobjrunning
.name
,
450 portconfig
['mstpctl-portnetwork'] += ' %s=%s' %(p
, v
)
452 # XXX: Can we really get path cost of a port ???
453 #v = self.mstpctlcmd.get_portpathcost(ifaceobjrunning.name, p)
454 #if v and v != self.get_mod_subattr('mstpctl-portpathcost',
456 # portconfig['mstpctl-portpathcost'] += ' %s=%s' %(p, v)
458 v
= self
.mstpctlcmd
.get_bridgeport_attr(ifaceobjrunning
.name
,
461 portconfig
['mstpctl-portadminedge'] += ' %s=%s' %(p
, v
)
463 v
= self
.mstpctlcmd
.get_bridgeport_attr(ifaceobjrunning
.name
,
466 portconfig
['mstpctl-portp2p'] += ' %s=%s' %(p
, v
)
468 v
= self
.mstpctlcmd
.get_bridgeport_attr(ifaceobjrunning
.name
,
471 portconfig
['mstpctl-portrestrrole'] += ' %s=%s' %(p
, v
)
473 v
= self
.mstpctlcmd
.get_bridgeport_attr(ifaceobjrunning
.name
,
476 portconfig
['mstpctl-portrestrtcn'] += ' %s=%s' %(p
, v
)
478 v
= self
.mstpctlcmd
.get_bridgeport_attr(ifaceobjrunning
.name
,
481 portconfig
['mstpctl-bpduguard'] += ' %s=%s' %(p
, v
)
483 # XXX: Can we really get path cost of a port ???
484 #v = self.mstpctlcmd.get_bridgeport_attr(ifaceobjrunning.name,
486 #if v and v != self.get_mod_subattr('mstpctl-treeportprio',
488 # portconfig['mstpctl-treeportprio'] += ' %s=%s' %(p, v)
490 #v = self.mstpctlcmd.get_bridgeport_attr(ifaceobjrunning.name,
492 #if v and v != self.get_mod_subattr('mstpctl-treeportcost',
494 # portconfig['mstpctl-treeportcost'] += ' %s=%s' %(p, v)
496 bridgeattrdict
.update({k
: [v
] for k
, v
in portconfig
.items()
498 return bridgeattrdict
500 def _query_check_bridge(self
, ifaceobj
, ifaceobjcurr
):
501 # list of attributes that are not supported currently
502 blacklistedattrs
= ['mstpctl-portpathcost',
503 'mstpctl-treeportprio', 'mstpctl-treeportcost']
504 if not self
.brctlcmd
.bridge_exists(ifaceobj
.name
):
505 self
.logger
.debug('bridge %s does not exist' %ifaceobj
.name
)
507 ifaceattrs
= self
.dict_key_subset(ifaceobj
.config
,
508 self
.get_mod_attrs())
511 runningattrs
= self
.mstpctlcmd
.get_bridge_attrs(ifaceobj
.name
)
515 # for all mstpctl options
516 if k
in blacklistedattrs
:
518 # get the corresponding ifaceobj attr
519 v
= ifaceobj
.get_attr_value_first(k
)
523 # Get the running attribute
524 rv
= runningattrs
.get(k
[8:])
525 if k
== 'mstpctl-stp':
526 # special case stp compare because it may
527 # contain more than one valid values
528 stp_on_vals
= ['on', 'yes']
529 stp_off_vals
= ['off']
530 rv
= self
.brctlcmd
.get_stp(ifaceobj
.name
)
531 if ((v
in stp_on_vals
and rv
in stp_on_vals
) or
532 (v
in stp_off_vals
and rv
in stp_off_vals
)):
533 ifaceobjcurr
.update_config_with_status('mstpctl-stp', v
, 0)
535 ifaceobjcurr
.update_config_with_status('mstpctl-stp', v
, 1)
538 if k
== 'mstpctl-ports':
539 # special case ports because it can contain regex or glob
540 # XXX: We get all info from mstputils, which means if
541 # mstpd is down, we will not be returning any bridge bridgeports
542 running_port_list
= self
.brctlcmd
.get_bridge_ports(ifaceobj
.name
)
543 bridge_port_list
= self
._get
_bridge
_port
_list
(ifaceobj
)
544 if not running_port_list
and not bridge_port_list
:
547 if running_port_list
and bridge_port_list
:
548 difference
= Set(running_port_list
).symmetric_difference(
549 Set(bridge_port_list
))
552 ifaceobjcurr
.update_config_with_status('mstpctl-ports',
553 ' '.join(running_port_list
)
554 if running_port_list
else '', portliststatus
)
555 elif k
[:12] == 'mstpctl-port' or k
== 'mstpctl-bpduguard':
556 # Now, look at port attributes
557 # derive the mstpctlcmd attr name
558 #mstpctlcmdattrname = k[12:] if k[:12] == 'mstpctl-port' else k[8:]
559 mstpctlcmdattrname
= k
[8:]
561 # for port attributes, the attributes are in a list
562 # <portname>=<portattrvalue>
565 vlist
= self
.parse_port_list(v
)
568 for vlistitem
in vlist
:
570 (p
, v
) = vlistitem
.split('=')
571 currv
= self
.mstpctlcmd
.get_bridgeport_attr(
572 ifaceobj
.name
, p
, mstpctlcmdattrname
)
574 currstr
+= ' %s=%s' %(p
, currv
)
576 currstr
+= ' %s=%s' %(p
, 'None')
580 self
.log_warn(str(e
))
582 ifaceobjcurr
.update_config_with_status(k
, currstr
, status
)
584 ifaceobjcurr
.update_config_with_status(k
, '', 1)
586 ifaceobjcurr
.update_config_with_status(k
, rv
, 1)
588 ifaceobjcurr
.update_config_with_status(k
, rv
, 0)
590 def _query_check_bridge_port(self
, ifaceobj
, ifaceobjcurr
):
591 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
592 #self.logger.debug('bridge port %s does not exist' %ifaceobj.name)
593 ifaceobjcurr
.status
= ifaceStatus
.NOTFOUND
595 # Check if this is a bridge port
596 if not self
._is
_bridge
_port
(ifaceobj
):
597 # mark all the bridge attributes as error
598 ifaceobjcurr
.check_n_update_config_with_status_many(ifaceobj
,
599 self
._port
_attrs
_map
.keys(), 0)
601 bridgename
= self
.ipcmd
.bridge_port_get_bridge_name(ifaceobj
.name
)
602 # list of attributes that are not supported currently
603 blacklistedattrs
= ['mstpctl-portpathcost',
604 'mstpctl-treeportprio', 'mstpctl-treeportcost']
605 ifaceattrs
= self
.dict_key_subset(ifaceobj
.config
,
606 self
._port
_attrs
_map
.keys())
609 runningattrs
= self
.mstpctlcmd
.get_bridge_attrs(ifaceobj
.name
)
613 # for all mstpctl options
614 # get the corresponding ifaceobj attr
615 v
= ifaceobj
.get_attr_value_first(k
)
616 if not v
or k
in blacklistedattrs
:
617 ifaceobjcurr
.update_config_with_status(k
, v
, -1)
619 currv
= self
.mstpctlcmd
.get_bridgeport_attr(bridgename
,
620 ifaceobj
.name
, self
._port
_attrs
_map
.get(k
))
623 ifaceobjcurr
.update_config_with_status(k
, currv
, 1)
625 ifaceobjcurr
.update_config_with_status(k
, currv
, 0)
627 ifaceobjcurr
.update_config_with_status(k
, None, 1)
629 def _query_check(self
, ifaceobj
, ifaceobjcurr
, ifaceobj_getfunc
=None):
630 if self
._is
_bridge
(ifaceobj
):
631 self
._query
_check
_bridge
(ifaceobj
, ifaceobjcurr
)
633 self
._query
_check
_bridge
_port
(ifaceobj
, ifaceobjcurr
)
635 def _query_running_bridge_port(self
, ifaceobjrunning
):
636 bridgename
= self
.ipcmd
.bridge_port_get_bridge_name(
637 ifaceobjrunning
.name
)
639 self
.logger
.warn('%s: unable to determine bridgename'
640 %ifaceobjrunning
.name
)
642 if self
.brctlcmd
.get_stp(bridgename
) == 'no':
643 # This bridge does not run stp, return
645 # if userspace stp not set, return
646 if self
.sysctl_get('net.bridge.bridge-stp-user-space') != '1':
648 v
= self
.mstpctlcmd
.get_bridgeport_attr(bridgename
,
649 ifaceobjrunning
.name
,
652 ifaceobjrunning
.update_config('mstpctl-network', v
)
654 # XXX: Can we really get path cost of a port ???
655 #v = self.mstpctlcmd.get_portpathcost(ifaceobjrunning.name, p)
656 #if v and v != self.get_mod_subattr('mstpctl-pathcost',
658 # ifaceobjrunning.update_config('mstpctl-network', v)
660 v
= self
.mstpctlcmd
.get_bridgeport_attr(bridgename
,
661 ifaceobjrunning
.name
, 'portadminedge')
663 ifaceobjrunning
.update_config('mstpctl-portadminedge', v
)
665 v
= self
.mstpctlcmd
.get_bridgeport_attr(bridgename
,
666 ifaceobjrunning
.name
,'portp2p')
667 if v
and v
!= 'auto':
668 ifaceobjrunning
.update_config('mstpctl-portp2p', v
)
670 v
= self
.mstpctlcmd
.get_bridgeport_attr(bridgename
,
671 ifaceobjrunning
.name
, 'portrestrrole')
673 ifaceobjrunning
.update_config('mstpctl-portrestrrole', v
)
675 v
= self
.mstpctlcmd
.get_bridgeport_attr(bridgename
,
676 ifaceobjrunning
.name
, 'restrtcn')
678 ifaceobjrunning
.update_config('mstpctl-portrestrtcn', v
)
680 v
= self
.mstpctlcmd
.get_bridgeport_attr(bridgename
,
681 ifaceobjrunning
.name
, 'bpduguard')
683 ifaceobjrunning
.update_config('mstpctl-bpduguard', v
)
685 # XXX: Can we really get path cost of a port ???
686 #v = self.mstpctlcmd.get_bridgeport_attr(ifaceobjrunning.name,
688 #if v and v != self.get_mod_subattr('mstpctl-treeportprio',
690 # portconfig['mstpctl-treeportprio'] += ' %s=%s' %(p, v)
692 #v = self.mstpctlcmd.get_bridgeport_attr(ifaceobjrunning.name,
694 #if v and v != self.get_mod_subattr('mstpctl-treeportcost',
696 # portconfig['mstpctl-treeportcost'] += ' %s=%s' %(p, v)
698 def _query_running_bridge(self
, ifaceobjrunning
):
699 if self
.brctlcmd
.get_stp(ifaceobjrunning
.name
) == 'no':
700 # This bridge does not run stp, return
702 # if userspace stp not set, return
703 if self
.sysctl_get('net.bridge.bridge-stp-user-space') != '1':
705 # Check if mstp really knows about this bridge
706 if not self
.mstpctlcmd
.mstpbridge_exists(ifaceobjrunning
.name
):
708 ifaceobjrunning
.update_config_dict(self
._query
_running
_attrs
(
711 def _query_running(self
, ifaceobjrunning
, **extra_args
):
712 if self
.brctlcmd
.bridge_exists(ifaceobjrunning
.name
):
713 self
._query
_running
_bridge
(ifaceobjrunning
)
714 elif self
.brctlcmd
.is_bridge_port(ifaceobjrunning
.name
):
715 self
._query
_running
_bridge
_port
(ifaceobjrunning
)
717 _run_ops
= {'pre-up' : _up
,
719 'query-checkcurr' : _query_check
,
720 'query-running' : _query_running
}
723 """ returns list of ops supported by this module """
724 return self
._run
_ops
.keys()
726 def _init_command_handlers(self
):
727 flags
= self
.get_flags()
729 self
.ipcmd
= iproute2(**flags
)
730 if not self
.brctlcmd
:
731 self
.brctlcmd
= brctl(**flags
)
732 if not self
.mstpctlcmd
:
733 self
.mstpctlcmd
= mstpctlutil(**flags
)
735 def run(self
, ifaceobj
, operation
, query_ifaceobj
=None,
736 ifaceobj_getfunc
=None, **extra_args
):
737 """ run mstp configuration on the interface object passed as argument
740 **ifaceobj** (object): iface object
742 **operation** (str): any of 'pre-up', 'post-down', 'query-checkcurr',
745 **query_ifaceobj** (object): query check ifaceobject. This is only
746 valid when op is 'query-checkcurr'. It is an object same as
747 ifaceobj, but contains running attribute values and its config
748 status. The modules can use it to return queried running state
749 of interfaces. status is success if the running state is same
750 as user required state in ifaceobj. error otherwise.
752 if ifaceobj
.type == ifaceType
.BRIDGE_VLAN
:
754 op_handler
= self
._run
_ops
.get(operation
)
757 self
._init
_command
_handlers
()
758 if operation
== 'query-checkcurr':
759 op_handler(self
, ifaceobj
, query_ifaceobj
,
760 ifaceobj_getfunc
=ifaceobj_getfunc
)
762 op_handler(self
, ifaceobj
, ifaceobj_getfunc
=ifaceobj_getfunc
)