]> git.proxmox.com Git - mirror_ifupdown2.git/blame - addons/mstpctl.py
bondutils: caching min_links value
[mirror_ifupdown2.git] / addons / mstpctl.py
CommitLineData
15ef32ea
RP
1#!/usr/bin/python
2#
3# Copyright 2014 Cumulus Networks, Inc. All rights reserved.
4# Author: Roopa Prabhu, roopa@cumulusnetworks.com
5#
6
42a9d193 7import os
15ef32ea
RP
8from sets import Set
9from ifupdown.iface import *
8252491e 10from ifupdown.utils import utils
15ef32ea
RP
11from ifupdownaddons.modulebase import moduleBase
12from ifupdownaddons.bridgeutils import brctl
13from ifupdownaddons.iproute2 import iproute2
3e960ac2 14from ifupdown.netlink import netlink
15ef32ea 15from ifupdownaddons.mstpctlutil import mstpctlutil
5f8c03e7 16from ifupdownaddons.systemutils import systemUtils
fc5e1735 17import ifupdown.ifupdownflags as ifupdownflags
2e4dc724 18import ifupdown.policymanager as policymanager
15ef32ea 19
4c773918
ST
20class mstpctlFlags:
21 PORT_PROCESSED = 0x1
22
15ef32ea
RP
23class mstpctl(moduleBase):
24 """ ifupdown2 addon module to configure mstp attributes """
25
26 _modinfo = {'mhelp' : 'mstp configuration module for bridges',
27 'attrs' : {
28 'mstpctl-ports' :
29 {'help' : 'mstp ports',
48689b55
RP
30 'compat' : True,
31 'deprecated': True,
32 'new-attribute': 'bridge-ports'},
15ef32ea
RP
33 'mstpctl-stp' :
34 {'help': 'bridge stp yes/no',
482b2fab 35 'validvals' : ['yes', 'no', 'on', 'off'],
15ef32ea 36 'compat' : True,
4bdf2d1c
JF
37 'default' : 'no',
38 'deprecated': True,
39 'new-attribute': 'bridge-stp'},
15ef32ea
RP
40 'mstpctl-treeprio' :
41 {'help': 'tree priority',
42 'default' : '32768',
43 'validrange' : ['0', '65535'],
44 'required' : False,
45 'example' : ['mstpctl-treeprio 32768']},
46 'mstpctl-ageing' :
47 {'help': 'ageing time',
c6370b56 48 'validrange' : ['0', '4096'],
15ef32ea
RP
49 'default' : '300',
50 'required' : False,
9d3f53c6 51 'jsonAttr': 'ageingTime',
15ef32ea
RP
52 'example' : ['mstpctl-ageing 300']},
53 'mstpctl-maxage' :
54 { 'help' : 'max message age',
c6370b56 55 'validrange' : ['0', '255'],
15ef32ea 56 'default' : '20',
9d3f53c6 57 'jsonAttr': 'maxAge',
15ef32ea
RP
58 'required' : False,
59 'example' : ['mstpctl-maxage 20']},
60 'mstpctl-fdelay' :
61 { 'help' : 'set forwarding delay',
c6370b56 62 'validrange' : ['0', '255'],
15ef32ea 63 'default' : '15',
9d3f53c6 64 'jsonAttr': 'fwdDelay',
15ef32ea
RP
65 'required' : False,
66 'example' : ['mstpctl-fdelay 15']},
67 'mstpctl-maxhops' :
68 { 'help' : 'bridge max hops',
c6370b56 69 'validrange' : ['0', '255'],
15ef32ea 70 'default' : '15',
9d3f53c6 71 'jsonAttr': 'maxHops',
15ef32ea
RP
72 'required' : False,
73 'example' : ['mstpctl-maxhops 15']},
74 'mstpctl-txholdcount' :
75 { 'help' : 'bridge transmit holdcount',
c6370b56 76 'validrange' : ['0', '255'],
15ef32ea 77 'default' : '6',
9d3f53c6 78 'jsonAttr': 'txHoldCounter',
15ef32ea
RP
79 'required' : False,
80 'example' : ['mstpctl-txholdcount 6']},
81 'mstpctl-forcevers' :
82 { 'help' : 'bridge force stp version',
c6370b56 83 'validvals' : ['rstp', ],
15ef32ea
RP
84 'default' : 'rstp',
85 'required' : False,
9d3f53c6 86 'jsonAttr': 'forceProtocolVersion',
15ef32ea
RP
87 'example' : ['mstpctl-forcevers rstp']},
88 'mstpctl-portpathcost' :
89 { 'help' : 'bridge port path cost',
482b2fab 90 'validvals': ['<interface-range-list>'],
c6370b56 91 'validrange' : ['0', '65535'],
15ef32ea 92 'default' : '0',
b97687bc 93 'jsonAttr' : 'adminExtPortCost',
15ef32ea 94 'required' : False,
c6370b56
DW
95 'example' : ['under the bridge: mstpctl-portpathcost swp1=0 swp2=1',
96 'under the port (recommended): mstpctl-portpathcost 0']},
15ef32ea
RP
97 'mstpctl-portp2p' :
98 { 'help' : 'bridge port p2p detection mode',
e759a20a 99 'default' : 'auto',
b97687bc 100 'jsonAttr' : 'adminPointToPoint',
482b2fab 101 'validvals' : ['<interface-yes-no-auto-list>'],
15ef32ea 102 'required' : False,
c6370b56
DW
103 'example' : ['under the bridge: mstpctl-portp2p swp1=yes swp2=no',
104 'under the port (recommended): mstpctl-portp2p yes']},
15ef32ea
RP
105 'mstpctl-portrestrrole' :
106 { 'help' :
107 'enable/disable port ability to take root role of the port',
108 'default' : 'no',
b97687bc 109 'jsonAttr' : 'restrictedRole',
482b2fab 110 'validvals' : ['<interface-yes-no-list>'],
15ef32ea 111 'required' : False,
c6370b56
DW
112 'example' : ['under the bridge: mstpctl-portrestrrole swp1=yes swp2=no',
113 'under the port (recommended): mstpctl-portrestrrole yes']},
15ef32ea
RP
114 'mstpctl-portrestrtcn' :
115 { 'help' :
116 'enable/disable port ability to propagate received topology change notification of the port',
117 'default' : 'no',
b97687bc 118 'jsonAttr' : 'restrictedTcn',
482b2fab 119 'validvals' : ['<interface-yes-no-list>'],
15ef32ea 120 'required' : False,
c6370b56
DW
121 'example' : ['under the bridge: mstpctl-portrestrtcn swp1=yes swp2=no',
122 'under the port (recommended): mstpctl-portrestrtcn yes']},
15ef32ea
RP
123 'mstpctl-bpduguard' :
124 { 'help' :
125 'enable/disable bpduguard',
126 'default' : 'no',
b97687bc 127 'jsonAttr' : 'bpduGuardPort',
482b2fab 128 'validvals' : ['<interface-yes-no-list>'],
15ef32ea 129 'required' : False,
c6370b56
DW
130 'example' : ['under the bridge: mstpctl-bpduguard swp1=yes swp2=no',
131 'under the port (recommended): mstpctl-bpduguard yes']},
15ef32ea
RP
132 'mstpctl-treeportprio' :
133 { 'help' :
134 'port priority for MSTI instance',
135 'default' : '128',
482b2fab 136 'validvals': ['<interface-range-list>'],
15ef32ea 137 'validrange' : ['0', '240'],
9d3f53c6 138 'jsonAttr': 'treeportprio',
15ef32ea 139 'required' : False,
c6370b56
DW
140 'example' : ['under the bridge: mstpctl-treeportprio swp1=128 swp2=128',
141 'under the port (recommended): mstpctl-treeportprio 128']},
15ef32ea
RP
142 'mstpctl-hello' :
143 { 'help' : 'set hello time',
c6370b56 144 'validrange' : ['0', '255'],
15ef32ea
RP
145 'default' : '2',
146 'required' : False,
9d3f53c6 147 'jsonAttr': 'portHelloTime',
15ef32ea
RP
148 'example' : ['mstpctl-hello 2']},
149 'mstpctl-portnetwork' :
150 { 'help' : 'enable/disable bridge assurance capability for a port',
482b2fab 151 'validvals' : ['<interface-yes-no-list>'],
15ef32ea 152 'default' : 'no',
b97687bc 153 'jsonAttr' : 'networkPort',
15ef32ea 154 'required' : False,
c6370b56
DW
155 'example' : ['under the bridge: mstpctl-portnetwork swp1=yes swp2=no',
156 'under the port (recommended): mstpctl-portnetwork yes']},
15ef32ea
RP
157 'mstpctl-portadminedge' :
158 { 'help' : 'enable/disable initial edge state of the port',
482b2fab 159 'validvals' : ['<interface-yes-no-list>'],
15ef32ea 160 'default' : 'no',
b97687bc 161 'jsonAttr' : 'adminEdgePort',
15ef32ea 162 'required' : False,
c6370b56
DW
163 'example' : ['under the bridge: mstpctl-portadminedge swp1=yes swp2=no',
164 'under the port (recommended): mstpctl-portadminedge yes']},
15ef32ea
RP
165 'mstpctl-portautoedge' :
166 { 'help' : 'enable/disable auto transition to/from edge state of the port',
482b2fab 167 'validvals' : ['<interface-yes-no-list>'],
be1faada 168 'default' : 'yes',
b97687bc 169 'jsonAttr' : 'autoEdgePort',
15ef32ea 170 'required' : False,
c6370b56
DW
171 'example' : ['under the bridge: mstpctl-portautoedge swp1=yes swp2=no',
172 'under the port (recommended): mstpctl-portautoedge yes']},
15ef32ea
RP
173 'mstpctl-treeportcost' :
174 { 'help' : 'port tree cost',
c6370b56 175 'validrange' : ['0', '255'],
9d3f53c6
JF
176 'required' : False,
177 'jsonAttr': 'extPortCost',
178 },
15ef32ea 179 'mstpctl-portbpdufilter' :
9e012f9e
RP
180 { 'help' : 'enable/disable bpdu filter on a port. ' +
181 'syntax varies when defined under a bridge ' +
182 'vs under a port',
482b2fab 183 'validvals' : ['<interface-yes-no-list>'],
b97687bc 184 'jsonAttr' : 'bpduFilterPort',
15ef32ea
RP
185 'default' : 'no',
186 'required' : False,
9e012f9e
RP
187 'example' : ['under a bridge: mstpctl-portbpdufilter swp1=no swp2=no',
188 'under a port: mstpctl-portbpdufilter yes']},
15ef32ea
RP
189 }}
190
4c39c7b8
RP
191 # Maps mstp bridge attribute names to corresponding mstpctl commands
192 # XXX: This can be encoded in the modules dict above
193 _attrs_map = OrderedDict([('mstpctl-treeprio' , 'treeprio'),
194 ('mstpctl-ageing' , 'ageing'),
4c39c7b8 195 ('mstpctl-fdelay' , 'fdelay'),
caa23e5f 196 ('mstpctl-maxage' , 'maxage'),
4c39c7b8
RP
197 ('mstpctl-maxhops' , 'maxhops'),
198 ('mstpctl-txholdcount' , 'txholdcount'),
199 ('mstpctl-forcevers', 'forcevers'),
200 ('mstpctl-hello' , 'hello')])
201
202 # Maps mstp port attribute names to corresponding mstpctl commands
203 # XXX: This can be encoded in the modules dict above
e1601369
RP
204 _port_attrs_map = {'mstpctl-portpathcost' : 'portpathcost',
205 'mstpctl-portadminedge' : 'portadminedge',
d8e3554d 206 'mstpctl-portautoedge' : 'portautoedge' ,
e1601369
RP
207 'mstpctl-portp2p' : 'portp2p',
208 'mstpctl-portrestrrole' : 'portrestrrole',
209 'mstpctl-portrestrtcn' : 'portrestrtcn',
15ef32ea 210 'mstpctl-bpduguard' : 'bpduguard',
e1601369
RP
211 'mstpctl-treeportprio' : 'treeportprio',
212 'mstpctl-treeportcost' : 'treeportcost',
213 'mstpctl-portnetwork' : 'portnetwork',
214 'mstpctl-portbpdufilter' : 'portbpdufilter'}
15ef32ea
RP
215
216 def __init__(self, *args, **kargs):
217 moduleBase.__init__(self, *args, **kargs)
218 self.ipcmd = None
4c773918 219 self.name = self.__class__.__name__
15ef32ea
RP
220 self.brctlcmd = None
221 self.mstpctlcmd = None
5f8c03e7
RP
222 self.mstpd_running = (True if systemUtils.is_process_running('mstpd')
223 else False)
2e4dc724
N
224 self.default_vxlan_ports_set_bpduparams = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='mstpctl-vxlan-always-set-bpdu-params')
225 if self.default_vxlan_ports_set_bpduparams == 'yes':
226 self.default_vxlan_ports_set_bpduparams = True
227 else:
228 self.default_vxlan_ports_set_bpduparams = False
15ef32ea 229
8e9fc178 230 def syntax_check(self, ifaceobj, ifaceobj_getfunc):
8252491e
JF
231 if self._is_bridge(ifaceobj):
232 if (ifaceobj.link_privflags & ifaceLinkPrivFlags.BRIDGE_VLAN_AWARE
233 and ifaceobj.get_attr_value_first('mstpctl-portadminedge')):
234 self.logger.error('%s: unsupported use of keyword '
235 '\'mstpctl-portadminedge\' when '
236 'bridge-vlan-aware is on'
237 % ifaceobj.name)
238 return False
239 return True
240
15ef32ea
RP
241 def _is_bridge(self, ifaceobj):
242 if (ifaceobj.get_attr_value_first('mstpctl-ports') or
84ca006f
RP
243 ifaceobj.get_attr_value_first('bridge-ports')):
244 return True
245 return False
246
247 def _is_bridge_port(self, ifaceobj):
248 if self.brctlcmd.is_bridge_port(ifaceobj.name):
15ef32ea
RP
249 return True
250 return False
251
252 def get_dependent_ifacenames(self, ifaceobj, ifacenames_all=None):
253 if not self._is_bridge(ifaceobj):
254 return None
0c8332bc
RP
255 return self.parse_port_list(ifaceobj.name,
256 ifaceobj.get_attr_value_first(
15ef32ea
RP
257 'mstpctl-ports'), ifacenames_all)
258
259 def get_dependent_ifacenames_running(self, ifaceobj):
260 self._init_command_handlers()
261 if (self.brctlcmd.bridge_exists(ifaceobj.name) and
262 not self.mstpctlcmd.mstpbridge_exists(ifaceobj.name)):
263 return None
264 return self.brctlcmd.get_bridge_ports(ifaceobj.name)
265
9d3f53c6
JF
266 def _get_bridge_port_attr_value(self, bridgename, portname, attr):
267 json_attr = self.get_mod_subattr(attr, 'jsonAttr')
268 return self.mstpctlcmd.get_bridge_port_attr(bridgename,
269 portname,
270 json_attr)
271
15ef32ea
RP
272 def _get_bridge_port_list(self, ifaceobj):
273
274 # port list is also available in the previously
275 # parsed dependent list. Use that if available, instead
276 # of parsing port expr again
277 port_list = ifaceobj.lowerifaces
278 if port_list:
279 return port_list
280 ports = ifaceobj.get_attr_value_first('mstpctl-ports')
281 if ports:
0c8332bc 282 return self.parse_port_list(ifaceobj.name, ports)
15ef32ea
RP
283 else:
284 return None
285
404cc695
RP
286 def _ports_enable_disable_ipv6(self, ports, enable='1'):
287 for p in ports:
288 try:
289 self.write_file('/proc/sys/net/ipv6/conf/%s' %p +
290 '/disable_ipv6', enable)
291 except Exception, e:
292 self.logger.info(str(e))
293 pass
294
15ef32ea
RP
295 def _add_ports(self, ifaceobj):
296 bridgeports = self._get_bridge_port_list(ifaceobj)
297
298 runningbridgeports = []
299 # Delete active ports not in the new port list
fc5e1735 300 if not ifupdownflags.flags.PERFMODE:
15ef32ea
RP
301 runningbridgeports = self.brctlcmd.get_bridge_ports(ifaceobj.name)
302 if runningbridgeports:
3e960ac2 303 [netlink.link_set_nomaster(bport)
15ef32ea
RP
304 for bport in runningbridgeports
305 if not bridgeports or bport not in bridgeports]
306 else:
307 runningbridgeports = []
308 if not bridgeports:
309 return
310 err = 0
311 for bridgeport in Set(bridgeports).difference(Set(runningbridgeports)):
312 try:
fc5e1735
RP
313 if (not ifupdownflags.flags.DRYRUN and
314 not self.ipcmd.link_exists(bridgeport)):
15ef32ea
RP
315 self.log_warn('%s: bridge port %s does not exist'
316 %(ifaceobj.name, bridgeport))
317 err += 1
318 continue
3e960ac2 319 netlink.link_set_master(bridgeport, ifaceobj.name)
15ef32ea
RP
320 self.ipcmd.addr_flush(bridgeport)
321 except Exception, e:
bf3eda91 322 self.log_error(str(e), ifaceobj)
404cc695 323
15ef32ea
RP
324 if err:
325 self.log_error('error configuring bridge (missing ports)')
326
327 def _apply_bridge_settings(self, ifaceobj):
fc5e1735 328 check = False if ifupdownflags.flags.PERFMODE else True
15ef32ea 329 try:
4c39c7b8
RP
330 # set bridge attributes
331 for attrname, dstattrname in self._attrs_map.items():
332 try:
333 v = ifaceobj.get_attr_value_first(attrname)
2722bb19
ST
334 if not v:
335 continue
4c39c7b8
RP
336 if attrname == 'mstpctl-treeprio':
337 self.mstpctlcmd.set_bridge_treeprio(ifaceobj.name,
338 v, check)
339 else:
340 self.mstpctlcmd.set_bridge_attr(ifaceobj.name,
341 dstattrname, v, check)
342 except Exception, e:
343 self.logger.warn('%s' %str(e))
344 pass
15ef32ea 345
bb70f923
N
346 if self.ipcmd.bridge_is_vlan_aware(ifaceobj.name):
347 return
15ef32ea 348 # set bridge port attributes
4c39c7b8 349 for attrname, dstattrname in self._port_attrs_map.items():
b97687bc
ST
350 config_val = ifaceobj.get_attr_value_first(attrname)
351 default_val = self.get_mod_subattr(attrname,'default')
352 if not config_val:
353 # nothing configured, we may need to reset all ports to defaults
354 # if the default exists and jsonAttribute conversion exists
355 try:
356 jsonAttr = self.get_mod_subattr(attrname, 'jsonAttr')
357 if default_val and jsonAttr:
358 bridgeports = self._get_bridge_port_list(ifaceobj)
359 for port in bridgeports:
bf3eda91
RP
360 if not self.brctlcmd.is_bridge_port(port):
361 continue
9d3f53c6
JF
362 self.mstpctlcmd.set_bridge_port_attr(ifaceobj.name,
363 port,
364 dstattrname,
365 default_val,
366 json_attr=jsonAttr)
b97687bc
ST
367 except:
368 self.logger.info('%s: not resetting %s config'
369 %(ifaceobj.name, attrname))
370 # leave the loop for this attribute
15ef32ea 371 continue
b97687bc
ST
372
373 portlist = self.parse_port_list(ifaceobj.name, config_val)
15ef32ea 374 if not portlist:
bf3eda91
RP
375 self.log_error('%s: error parsing \'%s %s\''
376 %(ifaceobj.name, attrname, config_val), ifaceobj)
15ef32ea 377 continue
b97687bc
ST
378 # there was a configured value so we need to parse it
379 # and set the attribute for each port configured
15ef32ea
RP
380 for p in portlist:
381 try:
382 (port, val) = p.split('=')
42a9d193
RP
383 # if it is not bridge port, continue
384 if not os.path.exists('/sys/class/net/%s/brport' %port):
385 continue
9d3f53c6
JF
386 json_attr = self.get_mod_subattr(attrname, 'jsonAttr')
387 self.mstpctlcmd.set_bridge_port_attr(ifaceobj.name,
388 port,
389 dstattrname,
390 val,
391 json_attr=json_attr)
15ef32ea 392 except Exception, e:
bf3eda91
RP
393 self.log_error('%s: error setting %s (%s)'
394 %(ifaceobj.name, attrname, str(e)),
395 ifaceobj, raise_error=False)
15ef32ea
RP
396 except Exception, e:
397 self.log_warn(str(e))
398 pass
399
2e4dc724
N
400 def _get_default_val(self, attr, ifaceobj, bridgeifaceobj):
401 if ((attr == 'mstpctl-portbpdufilter' or
402 attr == 'mstpctl-bpduguard') and
403 self.default_vxlan_ports_set_bpduparams and
404 (ifaceobj.link_kind & ifaceLinkKind.VXLAN)):
405 try:
406 config_val = bridgeifaceobj.get_attr_value_first(attr)
407 except Exception, e:
408 config_val = None
409 if config_val:
410 if ifaceobj.name not in [v.split('=')[0] for v in config_val.split()]:
411 return 'yes'
412 else:
413 index = [v.split('=')[0] for v in config_val.split()].index(ifaceobj.name)
414 return [v.split('=')[1] for v in config_val.split()][index]
415 else:
416 return 'yes'
417 else:
418 return self.get_mod_subattr(attr,'default')
419
84ca006f 420 def _apply_bridge_port_settings(self, ifaceobj, bridgename=None,
641cbd1e
RP
421 bridgeifaceobj=None,
422 stp_running_on=True,
d8e3554d 423 mstpd_running=True):
fc5e1735 424 check = False if ifupdownflags.flags.PERFMODE else True
641cbd1e 425 applied = False
84ca006f
RP
426 if not bridgename and bridgeifaceobj:
427 bridgename = bridgeifaceobj.name
b97687bc
ST
428
429 if not stp_running_on:
430 # stp may get turned on at a later point
431 self.logger.info('%s: ignoring config'
432 %(ifaceobj.name) +
433 ' (stp on bridge %s is not on yet)' %bridgename)
434 return applied
2e4dc724 435 bvlan_aware = self.ipcmd.bridge_is_vlan_aware(bridgename)
b97687bc
ST
436 if (not mstpd_running or
437 not os.path.exists('/sys/class/net/%s/brport' %ifaceobj.name) or
2e4dc724
N
438 not bvlan_aware):
439 if (not bvlan_aware and
440 self.default_vxlan_ports_set_bpduparams and
441 (ifaceobj.link_kind & ifaceLinkKind.VXLAN)):
442 for attr in ['mstpctl-portbpdufilter',
443 'mstpctl-bpduguard']:
9d3f53c6
JF
444 json_attr = self.get_mod_subattr(attr, 'jsonAttr')
445 config_val = self._get_default_val(attr, ifaceobj,
446 bridgeifaceobj)
2e4dc724 447 try:
9d3f53c6
JF
448 self.mstpctlcmd.set_bridge_port_attr(bridgename,
449 ifaceobj.name,
450 self._port_attrs_map[attr],
451 config_val,
452 json_attr=json_attr)
2e4dc724
N
453 except Exception, e:
454 self.log_warn('%s: error setting %s (%s)'
9d3f53c6 455 % (ifaceobj.name, attr, str(e)))
2e4dc724 456 return applied
84ca006f
RP
457 # set bridge port attributes
458 for attrname, dstattrname in self._port_attrs_map.items():
459 attrval = ifaceobj.get_attr_value_first(attrname)
b97687bc 460 config_val = ifaceobj.get_attr_value_first(attrname)
2e4dc724 461 default_val = self._get_default_val(attrname, ifaceobj, bridgeifaceobj)
b97687bc
ST
462 jsonAttr = self.get_mod_subattr(attrname, 'jsonAttr')
463 # to see the running value, stp would have to be on
464 # so we would have parsed mstpctl showportdetail json output
465 try:
9d3f53c6 466 running_val = self.mstpctlcmd.get_bridge_port_attr(bridgename,
b97687bc
ST
467 ifaceobj.name, jsonAttr)
468 except:
469 self.logger.info('%s %s: could not get running %s value'
470 %(bridgename, ifaceobj.name, attrname))
471 running_val = None
472 if (not config_val and default_val and (running_val != default_val)):
473 # this happens when users remove an attribute from a port
474 # and expect the default to be restored with ifreload.
475 config_val = default_val
476 elif not config_val:
477 # there is nothing configured and no default to reset
42a9d193 478 continue
b97687bc 479
84ca006f 480 try:
9d3f53c6
JF
481 self.mstpctlcmd.set_bridge_port_attr(bridgename,
482 ifaceobj.name, dstattrname, config_val, json_attr=jsonAttr)
641cbd1e 483 applied = True
84ca006f 484 except Exception, e:
bf3eda91
RP
485 self.log_error('%s: error setting %s (%s)'
486 %(ifaceobj.name, attrname, str(e)), ifaceobj,
487 raise_error=False)
641cbd1e 488 return applied
84ca006f
RP
489
490 def _apply_bridge_port_settings_all(self, ifaceobj,
491 ifaceobj_getfunc=None):
98b5ee73 492 self.logger.info('%s: applying mstp configuration '
84ca006f 493 %ifaceobj.name + 'specific to ports')
f6a0fa15
RP
494 # Query running bridge ports. and only apply attributes on them
495 bridgeports = self.brctlcmd.get_bridge_ports(ifaceobj.name)
4c39c7b8
RP
496 if not bridgeports:
497 self.logger.debug('%s: cannot find bridgeports' %ifaceobj.name)
498 return
84ca006f 499 for bport in bridgeports:
98b5ee73 500 self.logger.info('%s: processing mstp config for port %s'
84ca006f 501 %(ifaceobj.name, bport))
3e6ea735 502 if not self.ipcmd.link_exists(bport):
3e6ea735 503 continue
42a9d193
RP
504 if not os.path.exists('/sys/class/net/%s/brport' %bport):
505 continue
84ca006f
RP
506 bportifaceobjlist = ifaceobj_getfunc(bport)
507 if not bportifaceobjlist:
508 continue
509 for bportifaceobj in bportifaceobjlist:
98b5ee73 510 # Dont process bridge port if it already has been processed
4c773918
ST
511 if (bportifaceobj.module_flags.get(self.name,0x0) & \
512 mstpctlFlags.PORT_PROCESSED):
98b5ee73 513 continue
15ef32ea 514 try:
2e4dc724 515 self._apply_bridge_port_settings(bportifaceobj,
84ca006f 516 ifaceobj.name, ifaceobj)
15ef32ea 517 except Exception, e:
2e4dc724 518 pass
84ca006f 519 self.log_warn(str(e))
15ef32ea 520
641cbd1e
RP
521 def _is_running_userspace_stp_state_on(self, bridgename):
522 stp_state_file = '/sys/class/net/%s/bridge/stp_state' %bridgename
523 if not stp_state_file:
524 return False
525 running_stp_state = self.read_file_oneline(stp_state_file)
526 if running_stp_state and running_stp_state == '2':
527 return True
528 return False
529
84ca006f 530 def _up(self, ifaceobj, ifaceobj_getfunc=None):
15ef32ea 531 # Check if bridge port
98b5ee73
RP
532 bridgename = self.ipcmd.bridge_port_get_bridge_name(ifaceobj.name)
533 if bridgename:
5f8c03e7 534 mstpd_running = self.mstpd_running
641cbd1e
RP
535 stp_running_on = self._is_running_userspace_stp_state_on(bridgename)
536 applied = self._apply_bridge_port_settings(ifaceobj, bridgename,
537 None, stp_running_on,
538 mstpd_running)
539 if applied:
540 ifaceobj.module_flags[self.name] = \
541 ifaceobj.module_flags.setdefault(self.name,0) | \
542 mstpctlFlags.PORT_PROCESSED
15ef32ea 543 return
39804250
RP
544 if not self._is_bridge(ifaceobj):
545 return
b97687bc 546 # we are now here because the ifaceobj is a bridge
15ef32ea
RP
547 stp = None
548 try:
549 porterr = False
550 porterrstr = ''
551 if ifaceobj.get_attr_value_first('mstpctl-ports'):
552 # If bridge ports specified with mstpctl attr, create the
553 # bridge and also add its ports
554 self.ipcmd.batch_start()
fc5e1735 555 if not ifupdownflags.flags.PERFMODE:
15ef32ea
RP
556 if not self.ipcmd.link_exists(ifaceobj.name):
557 self.ipcmd.link_create(ifaceobj.name, 'bridge')
558 else:
559 self.ipcmd.link_create(ifaceobj.name, 'bridge')
560 try:
561 self._add_ports(ifaceobj)
562 except Exception, e:
563 porterr = True
564 porterrstr = str(e)
565 pass
566 finally:
567 self.ipcmd.batch_commit()
d5c0f703
RP
568 running_ports = self.brctlcmd.get_bridge_ports(ifaceobj.name)
569 if running_ports:
570 # disable ipv6 for ports that were added to bridge
571 self._ports_enable_disable_ipv6(running_ports, '1')
404cc695 572
15ef32ea
RP
573 stp = ifaceobj.get_attr_value_first('mstpctl-stp')
574 if stp:
575 self.set_iface_attr(ifaceobj, 'mstpctl-stp',
576 self.brctlcmd.set_stp)
577 else:
578 stp = self.brctlcmd.get_stp(ifaceobj.name)
5f8c03e7 579 if (self.mstpd_running and
15ef32ea
RP
580 (stp == 'yes' or stp == 'on')):
581 self._apply_bridge_settings(ifaceobj)
84ca006f
RP
582 self._apply_bridge_port_settings_all(ifaceobj,
583 ifaceobj_getfunc=ifaceobj_getfunc)
15ef32ea 584 except Exception, e:
bf3eda91 585 self.log_error(str(e), ifaceobj)
15ef32ea
RP
586 if porterr:
587 raise Exception(porterrstr)
588
84ca006f
RP
589 def _down(self, ifaceobj, ifaceobj_getfunc=None):
590 if not self._is_bridge(ifaceobj):
591 return
15ef32ea
RP
592 try:
593 if ifaceobj.get_attr_value_first('mstpctl-ports'):
594 # If bridge ports specified with mstpctl attr, delete the
595 # bridge
596 ports = self.brctlcmd.get_bridge_ports(ifaceobj.name)
597 if ports:
404cc695 598 self._ports_enable_disable_ipv6(ports, '0')
15ef32ea
RP
599 self.brctlcmd.delete_bridge(ifaceobj.name)
600 except Exception, e:
bf3eda91 601 self.log_error(str(e), ifaceobj)
15ef32ea 602
0dd2f0d1 603 def _query_running_attrs(self, ifaceobjrunning, bridge_vlan_aware=False):
15ef32ea
RP
604 bridgeattrdict = {}
605
606 tmpbridgeattrdict = self.mstpctlcmd.get_bridge_attrs(ifaceobjrunning.name)
9d3f53c6 607 #self.logger.info('A' + str(tmpbridgeattrdict))
15ef32ea
RP
608 if not tmpbridgeattrdict:
609 return bridgeattrdict
610
611 for k,v in tmpbridgeattrdict.items():
612 if k == 'stp' or not v:
613 continue
614 if k == 'ports':
615 ports = v.keys()
616 continue
617 attrname = 'mstpctl-' + k
0dd2f0d1
N
618 if (v and v != self.get_mod_subattr(attrname, 'default')
619 and attrname != 'mstpctl-maxhops'):
15ef32ea
RP
620 bridgeattrdict[attrname] = [v]
621
622 ports = self.brctlcmd.get_bridge_ports(ifaceobjrunning.name)
0dd2f0d1
N
623 # Do this only for vlan-UNAWARE-bridge
624 if ports and not bridge_vlan_aware:
22945dd6
N
625 portconfig = {'mstpctl-portautoedge' : '',
626 'mstpctl-portbpdufilter' : '',
627 'mstpctl-portnetwork' : '',
15ef32ea
RP
628 'mstpctl-portpathcost' : '',
629 'mstpctl-portadminedge' : '',
15ef32ea
RP
630 'mstpctl-portp2p' : '',
631 'mstpctl-portrestrrole' : '',
632 'mstpctl-portrestrtcn' : '',
633 'mstpctl-bpduguard' : '',
634 'mstpctl-treeportprio' : '',
635 'mstpctl-treeportcost' : ''}
636
637 for p in ports:
9d3f53c6
JF
638
639 for attr in ['mstpctl-portautoedge',
640 'mstpctl-portbpdufilter',
641 'mstpctl-portnetwork',
642 'mstpctl-portadminedge',
643 'mstpctl-portp2p',
644 'mstpctl-portrestrrole',
645 'mstpctl-portrestrtcn',
646 'mstpctl-bpduguard',
647 '']:
648 v = self._get_bridge_port_attr_value(ifaceobjrunning.name,
649 p, attr)
650 if v and v != 'no':
651 portconfig[attr] += ' %s=%s' % (p, v)
652
653 for attr in ['mstpctl-portpathcost', 'mstpctl-treeportcost']:
654 v = self._get_bridge_port_attr_value(ifaceobjrunning.name,
655 p, attr)
656 if v and v != self.get_mod_subattr(attr, 'default'):
657 portconfig[attr] += ' %s=%s' % (p, v)
15ef32ea
RP
658
659 bridgeattrdict.update({k : [v] for k, v in portconfig.items()
660 if v})
15ef32ea
RP
661 return bridgeattrdict
662
2e4dc724
N
663 def _query_check_bridge(self, ifaceobj, ifaceobjcurr,
664 ifaceobj_getfunc=None):
15ef32ea
RP
665 # list of attributes that are not supported currently
666 blacklistedattrs = ['mstpctl-portpathcost',
667 'mstpctl-treeportprio', 'mstpctl-treeportcost']
668 if not self.brctlcmd.bridge_exists(ifaceobj.name):
669 self.logger.debug('bridge %s does not exist' %ifaceobj.name)
15ef32ea
RP
670 return
671 ifaceattrs = self.dict_key_subset(ifaceobj.config,
672 self.get_mod_attrs())
2e4dc724
N
673 if self.default_vxlan_ports_set_bpduparams:
674 for attr in ['mstpctl-portbpdufilter', 'mstpctl-bpduguard']:
675 if attr not in ifaceattrs:
676 ifaceattrs.append(attr)
15ef32ea
RP
677 if not ifaceattrs:
678 return
679 runningattrs = self.mstpctlcmd.get_bridge_attrs(ifaceobj.name)
9d3f53c6 680 #self.logger.info('B' + str(runningattrs))
15ef32ea
RP
681 if not runningattrs:
682 runningattrs = {}
2e4dc724 683 running_port_list = self.brctlcmd.get_bridge_ports(ifaceobj.name)
15ef32ea
RP
684 for k in ifaceattrs:
685 # for all mstpctl options
686 if k in blacklistedattrs:
687 continue
2e4dc724
N
688 if ((k == 'mstpctl-portbpdufilter' or
689 k == 'mstpctl-bpduguard')):
690 #special case, 'ifquery --check --with-defaults' on a VLAN
691 #unaware bridge
692 if not running_port_list:
693 continue
694 v = ifaceobj.get_attr_value_first(k)
695 config_val = {}
696 running_val = {}
697 result = 0
698 bridge_ports = {}
699 state = ''
700 if v:
701 for bportval in v.split():
702 config_val[bportval.split('=')[0]] = bportval.split('=')[1]
703 #for bport in bridgeports:
704 for bport in running_port_list:
705 bportifaceobjlist = ifaceobj_getfunc(bport)
706 if not bportifaceobjlist:
707 continue
708 for bportifaceobj in bportifaceobjlist:
709 if (bport not in config_val):
710 if (bportifaceobj.link_kind & ifaceLinkKind.VXLAN):
711 if (not ifupdownflags.flags.WITHDEFAULTS or
712 (ifaceobj.link_privflags & ifaceLinkPrivFlags.BRIDGE_VLAN_AWARE)):
713 continue
714 conf = 'yes'
715 else:
716 continue
717 else:
718 if ((bportifaceobj.link_kind & ifaceLinkKind.VXLAN) and
719 (ifaceobj.link_privflags & ifaceLinkPrivFlags.BRIDGE_VLAN_AWARE)):
720 continue
721 conf = config_val[bport]
722 jsonAttr = self.get_mod_subattr(k, 'jsonAttr')
723 try:
9d3f53c6 724 running_val = self.mstpctlcmd.get_bridge_port_attr(ifaceobj.name, bport, jsonAttr)
2e4dc724
N
725 except:
726 self.logger.info('%s %s: could not get running %s value'
727 %(ifaceobj.name, bport, attr))
728 running_val = None
729 if conf != running_val:
730 result = 1
731 bridge_ports.update({bport : running_val})
732 for port, val in bridge_ports.items():
733 #running state format
734 #mstpctl-portbpdufilter swp2=yes swp1=yes vx-14567101=yes [pass]
735 #mstpctl-bpduguard swp2=yes swp1=yes vx-14567101=yes [pass]
736 state += port + '=' + val + ' '
737 if state:
738 ifaceobjcurr.update_config_with_status(k, state, result)
739 continue
740
15ef32ea
RP
741 # get the corresponding ifaceobj attr
742 v = ifaceobj.get_attr_value_first(k)
743 if not v:
744 continue
745
746 # Get the running attribute
747 rv = runningattrs.get(k[8:])
748 if k == 'mstpctl-stp':
749 # special case stp compare because it may
750 # contain more than one valid values
751 stp_on_vals = ['on', 'yes']
752 stp_off_vals = ['off']
753 rv = self.brctlcmd.get_stp(ifaceobj.name)
754 if ((v in stp_on_vals and rv in stp_on_vals) or
755 (v in stp_off_vals and rv in stp_off_vals)):
756 ifaceobjcurr.update_config_with_status('mstpctl-stp', v, 0)
757 else:
758 ifaceobjcurr.update_config_with_status('mstpctl-stp', v, 1)
759 continue
760
761 if k == 'mstpctl-ports':
762 # special case ports because it can contain regex or glob
763 # XXX: We get all info from mstputils, which means if
764 # mstpd is down, we will not be returning any bridge bridgeports
15ef32ea
RP
765 bridge_port_list = self._get_bridge_port_list(ifaceobj)
766 if not running_port_list and not bridge_port_list:
767 continue
768 portliststatus = 1
769 if running_port_list and bridge_port_list:
770 difference = Set(running_port_list).symmetric_difference(
771 Set(bridge_port_list))
772 if not difference:
773 portliststatus = 0
774 ifaceobjcurr.update_config_with_status('mstpctl-ports',
775 ' '.join(running_port_list)
776 if running_port_list else '', portliststatus)
777 elif k[:12] == 'mstpctl-port' or k == 'mstpctl-bpduguard':
778 # Now, look at port attributes
779 # derive the mstpctlcmd attr name
780 #mstpctlcmdattrname = k[12:] if k[:12] == 'mstpctl-port' else k[8:]
781 mstpctlcmdattrname = k[8:]
782
783 # for port attributes, the attributes are in a list
784 # <portname>=<portattrvalue>
785 status = 0
786 currstr = ''
0c8332bc 787 vlist = self.parse_port_list(ifaceobj.name, v)
15ef32ea
RP
788 if not vlist:
789 continue
790 for vlistitem in vlist:
791 try:
792 (p, v) = vlistitem.split('=')
9d3f53c6 793 currv = self._get_bridge_port_attr_value(ifaceobj.name, p, k)
15ef32ea
RP
794 if currv:
795 currstr += ' %s=%s' %(p, currv)
796 else:
797 currstr += ' %s=%s' %(p, 'None')
798 if currv != v:
799 status = 1
800 except Exception, e:
801 self.log_warn(str(e))
802 pass
803 ifaceobjcurr.update_config_with_status(k, currstr, status)
804 elif not rv:
805 ifaceobjcurr.update_config_with_status(k, '', 1)
806 elif v != rv:
807 ifaceobjcurr.update_config_with_status(k, rv, 1)
808 else:
809 ifaceobjcurr.update_config_with_status(k, rv, 0)
810
2e4dc724
N
811 def _query_check_bridge_vxlan_port(self, ifaceobj, ifaceobjcurr,
812 ifaceobj_getfunc=None):
813 masters = ifaceobj.upperifaces
814 if not masters:
815 return
816 for bridge in masters:
817 bifaceobjlist = ifaceobj_getfunc(bridge)
818 for bifaceobj in bifaceobjlist:
819 if (self._is_bridge(bifaceobj) and
820 self.default_vxlan_ports_set_bpduparams and
821 (bifaceobj.link_privflags & ifaceLinkPrivFlags.BRIDGE_VLAN_AWARE)):
822 for attr in ['mstpctl-portbpdufilter',
823 'mstpctl-bpduguard']:
824 jsonAttr = self.get_mod_subattr(attr, 'jsonAttr')
825 config_val = bifaceobj.get_attr_value_first(attr)
826 if config_val:
827 if ifaceobj.name not in [v.split('=')[0] for v in config_val.split()]:
828 if not ifupdownflags.flags.WITHDEFAULTS:
829 continue
830 config_val = 'yes'
831 else:
832 index = [v.split('=')[0] for v in config_val.split()].index(ifaceobj.name)
833 config_val = [v.split('=')[1] for v in config_val.split()][index]
834 else:
835 if not ifupdownflags.flags.WITHDEFAULTS:
836 continue
837 config_val = 'yes'
838 try:
9d3f53c6 839 running_val = self.mstpctlcmd.get_bridge_port_attr(bifaceobj.name,
2e4dc724
N
840 ifaceobj.name, jsonAttr)
841 except:
842 self.logger.info('%s %s: could not get running %s value'
843 %(bifaceobj.name, ifaceobj.name, attr))
844 running_val = None
845 ifaceobjcurr.update_config_with_status(attr,
846 running_val,
847 0 if running_val == config_val else 1)
848 return
849
850
84ca006f 851 def _query_check_bridge_port(self, ifaceobj, ifaceobjcurr):
19f90a91 852 if not self.ipcmd.link_exists(ifaceobj.name):
3e6ea735 853 #self.logger.debug('bridge port %s does not exist' %ifaceobj.name)
15ef32ea
RP
854 ifaceobjcurr.status = ifaceStatus.NOTFOUND
855 return
e1601369 856 # Check if this is a bridge port
19f90a91 857 if not self._is_bridge_port(ifaceobj):
e1601369 858 # mark all the bridge attributes as error
a070c90e 859 ifaceobjcurr.check_n_update_config_with_status_many(ifaceobj,
e1601369
RP
860 self._port_attrs_map.keys(), 0)
861 return
98b5ee73 862 bridgename = self.ipcmd.bridge_port_get_bridge_name(ifaceobj.name)
e1601369 863 # list of attributes that are not supported currently
16d854b4
RP
864 blacklistedattrs = ['mstpctl-portpathcost',
865 'mstpctl-treeportprio', 'mstpctl-treeportcost']
15ef32ea
RP
866 ifaceattrs = self.dict_key_subset(ifaceobj.config,
867 self._port_attrs_map.keys())
868 if not ifaceattrs:
869 return
870 runningattrs = self.mstpctlcmd.get_bridge_attrs(ifaceobj.name)
9d3f53c6 871 #self.logger.info('C' + str(runningattrs))
15ef32ea
RP
872 if not runningattrs:
873 runningattrs = {}
874 for k in ifaceattrs:
875 # for all mstpctl options
15ef32ea
RP
876 # get the corresponding ifaceobj attr
877 v = ifaceobj.get_attr_value_first(k)
16d854b4 878 if not v or k in blacklistedattrs:
e1601369 879 ifaceobjcurr.update_config_with_status(k, v, -1)
15ef32ea 880 continue
9d3f53c6 881 currv = self._get_bridge_port_attr_value(bridgename, ifaceobj.name, k)
15ef32ea
RP
882 if currv:
883 if currv != v:
884 ifaceobjcurr.update_config_with_status(k, currv, 1)
885 else:
886 ifaceobjcurr.update_config_with_status(k, currv, 0)
887 else:
888 ifaceobjcurr.update_config_with_status(k, None, 1)
889
84ca006f 890 def _query_check(self, ifaceobj, ifaceobjcurr, ifaceobj_getfunc=None):
e1601369 891 if self._is_bridge(ifaceobj):
2e4dc724
N
892 self._query_check_bridge(ifaceobj, ifaceobjcurr, ifaceobj_getfunc)
893 elif ifaceobj.link_kind & ifaceLinkKind.VXLAN:
894 self._query_check_bridge_vxlan_port(ifaceobj, ifaceobjcurr,
895 ifaceobj_getfunc)
e1601369
RP
896 else:
897 self._query_check_bridge_port(ifaceobj, ifaceobjcurr)
15ef32ea 898
9d3f53c6
JF
899 def _query_bridge_port_attr(self, ifaceobjrunning, bridgename, attr, value_cmp):
900 v = self._get_bridge_port_attr_value(bridgename,
901 ifaceobjrunning.name,
902 attr)
903 if v and value_cmp and v != value_cmp:
904 ifaceobjrunning.update_config(attr, v)
905 elif v and not value_cmp:
906 ifaceobjrunning.update_config(attr, v)
907
e1601369
RP
908 def _query_running_bridge_port(self, ifaceobjrunning):
909 bridgename = self.ipcmd.bridge_port_get_bridge_name(
910 ifaceobjrunning.name)
911 if not bridgename:
912 self.logger.warn('%s: unable to determine bridgename'
913 %ifaceobjrunning.name)
15ef32ea 914 return
e1601369
RP
915 if self.brctlcmd.get_stp(bridgename) == 'no':
916 # This bridge does not run stp, return
917 return
15ef32ea 918 # if userspace stp not set, return
9d3f53c6
JF
919 if self.systcl_get_net_bridge_stp_user_space() != '1':
920 return
921
922 self._query_bridge_port_attr(ifaceobjrunning, bridgename,
923 'mstpctl-portautoedge',
924 self.get_mod_subattr('mstpctl-portautoedge', 'default'))
925
926 self._query_bridge_port_attr(ifaceobjrunning, bridgename,
927 'mstpctl-portbpdufilter',
928 'no')
22945dd6 929
9d3f53c6
JF
930 self._query_bridge_port_attr(ifaceobjrunning, bridgename,
931 'mstpctl-portnetwork',
932 'no')
e1601369
RP
933
934 # XXX: Can we really get path cost of a port ???
935 #v = self.mstpctlcmd.get_portpathcost(ifaceobjrunning.name, p)
936 #if v and v != self.get_mod_subattr('mstpctl-pathcost',
937 # 'default'):
938 # ifaceobjrunning.update_config('mstpctl-network', v)
939
9d3f53c6
JF
940 self._query_bridge_port_attr(ifaceobjrunning, bridgename,
941 'mstpctl-portadminedge',
942 'no')
e1601369 943
9d3f53c6
JF
944 self._query_bridge_port_attr(ifaceobjrunning, bridgename,
945 'mstpctl-portp2p',
946 'auto')
e1601369 947
9d3f53c6
JF
948 self._query_bridge_port_attr(ifaceobjrunning, bridgename,
949 'mstpctl-portrestrrole',
950 'no')
e1601369 951
9d3f53c6
JF
952 self._query_bridge_port_attr(ifaceobjrunning, bridgename,
953 'mstpctl-portrestrtcn',
954 'no')
e1601369 955
9d3f53c6
JF
956 self._query_bridge_port_attr(ifaceobjrunning, bridgename,
957 'mstpctl-bpduguard',
958 'no')
e1601369
RP
959
960 # XXX: Can we really get path cost of a port ???
961 #v = self.mstpctlcmd.get_bridgeport_attr(ifaceobjrunning.name,
962 # p, 'treeprio')
963 #if v and v != self.get_mod_subattr('mstpctl-treeportprio',
964 # 'default'):
965 # portconfig['mstpctl-treeportprio'] += ' %s=%s' %(p, v)
966
967 #v = self.mstpctlcmd.get_bridgeport_attr(ifaceobjrunning.name,
968 # p, 'treecost')
969 #if v and v != self.get_mod_subattr('mstpctl-treeportcost',
970 # 'default'):
971 # portconfig['mstpctl-treeportcost'] += ' %s=%s' %(p, v)
972
973 def _query_running_bridge(self, ifaceobjrunning):
974 if self.brctlcmd.get_stp(ifaceobjrunning.name) == 'no':
975 # This bridge does not run stp, return
976 return
977 # if userspace stp not set, return
9d3f53c6
JF
978 if self.systcl_get_net_bridge_stp_user_space() != '1':
979 return
15ef32ea
RP
980 # Check if mstp really knows about this bridge
981 if not self.mstpctlcmd.mstpbridge_exists(ifaceobjrunning.name):
982 return
0dd2f0d1
N
983 bridge_vlan_aware = False
984 if ifaceobjrunning.get_attr_value_first('bridge-vlan-aware') == 'yes':
985 bridge_vlan_aware = True
15ef32ea 986 ifaceobjrunning.update_config_dict(self._query_running_attrs(
0dd2f0d1
N
987 ifaceobjrunning,
988 bridge_vlan_aware))
15ef32ea 989
e1601369
RP
990 def _query_running(self, ifaceobjrunning, **extra_args):
991 if self.brctlcmd.bridge_exists(ifaceobjrunning.name):
992 self._query_running_bridge(ifaceobjrunning)
993 elif self.brctlcmd.is_bridge_port(ifaceobjrunning.name):
994 self._query_running_bridge_port(ifaceobjrunning)
995
286a6b99
N
996 def _query_bridge_port(self, ifaceobj, ifaceobj_getfunc=None):
997 """
998 Example:
999 Configuration:
1000 auto vxlan1wd
1001 iface vxlan1wd
1002 vxlan-id 1001
1003
1004 auto vxlan2wd
1005 iface vxlan2wd
1006 vxlan-id 1002
1007
1008 auto brwithdef2
1009 iface brwithdef2
1010 bridge_ports vxlan1wd vxlan2wd
1011 bridge-vlan-aware yes
1012
1013 Output:
1014 $ ifquery vxlan1wd
1015 auto vxlan1wd
1016 iface vxlan1wd
1017 vxlan-id 1001
1018
1019 $ ifquery --with-defaults vxlan1wd
1020 auto vxlan1wd
1021 iface vxlan1wd
1022 vxlan-id 1001
1023 mstpctl-portbpdufilter yes
1024 mstpctl-bpduguard yes
1025 """
1026 masters = ifaceobj.upperifaces
1027 if not masters:
1028 return
1029 try:
1030 for bridge in masters:
1031 bifaceobj = ifaceobj_getfunc(bridge)[0]
1032 if (self._is_bridge(bifaceobj) and
1033 self.default_vxlan_ports_set_bpduparams and
1034 (bifaceobj.link_privflags & ifaceLinkPrivFlags.BRIDGE_VLAN_AWARE)):
1035 for attr in ['mstpctl-portbpdufilter',
1036 'mstpctl-bpduguard']:
1037 jsonAttr = self.get_mod_subattr(attr, 'jsonAttr')
1038 config_val = ifaceobj.get_attr_value_first(attr)
1039 if config_val or not ifupdownflags.flags.WITHDEFAULTS:
1040 continue
1041 config_val = 'yes'
1042 ifaceobj.replace_config(attr, config_val)
1043 return
1044 except Exception, e:
1045 self.logger.info("%s: %s" %(ifaceobj.name, str(e)))
1046 pass
1047
2e4dc724
N
1048 def _query(self, ifaceobj, ifaceobj_getfunc=None, **kwargs):
1049 """ add default policy attributes supported by the module """
1050 if not self._is_bridge(ifaceobj):
286a6b99
N
1051 if (ifaceobj.module_flags.get(self.name,0x0) &
1052 mstpctlFlags.PORT_PROCESSED):
1053 return
1054 self._query_bridge_port(ifaceobj, ifaceobj_getfunc)
1055 ifaceobj.module_flags[self.name] = (
1056 ifaceobj.module_flags.setdefault(self.name,0) |
1057 mstpctlFlags.PORT_PROCESSED)
2e4dc724
N
1058 return
1059 lowerinfs = ifaceobj.lowerifaces
1060 if not lowerinfs:
1061 return
1062 if ifaceobj.get_attr_value_first('bridge-vlan-aware') != 'yes':
1063 for attr in ['mstpctl-portbpdufilter', 'mstpctl-bpduguard']:
1064 state = ''
1065 config = ifaceobj.get_attr_value_first(attr)
1066 for port in lowerinfs:
1067 bportobjlist = ifaceobj_getfunc(port)
1068 for bportobj in bportobjlist:
1069 if bportobj.get_attr_value_first('vxlan-id'):
1070 if config:
1071 if port not in [v.split('=')[0] for v in config.split()]:
1072 config += ' %s=yes' %port
1073 else:
1074 state += '%s=yes ' %port
1075 ifaceobj.replace_config(attr, config if config else state)
1076 else:
1077 for attr in ['mstpctl-portbpdufilter', 'mstpctl-bpduguard']:
1078 state = ''
1079 config = ifaceobj.get_attr_value_first(attr)
1080 for port in lowerinfs:
1081 bportobjlist = ifaceobj_getfunc(port)
1082 for bportobj in bportobjlist:
286a6b99
N
1083 if (bportobj.module_flags.get(self.name,0x0) &
1084 mstpctlFlags.PORT_PROCESSED):
1085 continue
2e4dc724
N
1086 if bportobj.get_attr_value_first('vxlan-id'):
1087 if config:
1088 if port not in [v.split('=')[0] for v in config.split()]:
1089 bportobj.update_config(attr, 'yes')
1090 else:
1091 index = [v.split('=')[0] for v in config.split()].index(port)
1092 state = [v.split('=')[1] for v in config.split()][index]
1093 bportobj.update_config(attr, '%s' %state)
1094 v = config.split()
1095 del v[index]
1096 config = ' '.join(v)
1097 else:
286a6b99
N
1098 bportobj.replace_config(attr, 'yes')
1099 bportobj.module_flags[self.name] = (
1100 bportobj.module_flags.setdefault(self.name,0) |
1101 mstpctlFlags.PORT_PROCESSED)
2e4dc724
N
1102 if config:
1103 ifaceobj.replace_config(attr, config)
2e4dc724
N
1104
1105
1106
15ef32ea
RP
1107 _run_ops = {'pre-up' : _up,
1108 'post-down' : _down,
1109 'query-checkcurr' : _query_check,
2e4dc724
N
1110 'query-running' : _query_running,
1111 'query' : _query}
15ef32ea
RP
1112
1113 def get_ops(self):
1114 """ returns list of ops supported by this module """
1115 return self._run_ops.keys()
1116
1117 def _init_command_handlers(self):
15ef32ea 1118 if not self.ipcmd:
fc5e1735 1119 self.ipcmd = iproute2()
15ef32ea 1120 if not self.brctlcmd:
fc5e1735 1121 self.brctlcmd = brctl()
15ef32ea 1122 if not self.mstpctlcmd:
fc5e1735 1123 self.mstpctlcmd = mstpctlutil()
15ef32ea 1124
84ca006f
RP
1125 def run(self, ifaceobj, operation, query_ifaceobj=None,
1126 ifaceobj_getfunc=None, **extra_args):
15ef32ea
RP
1127 """ run mstp configuration on the interface object passed as argument
1128
1129 Args:
1130 **ifaceobj** (object): iface object
1131
1132 **operation** (str): any of 'pre-up', 'post-down', 'query-checkcurr',
1133 'query-running'
1134 Kwargs:
1135 **query_ifaceobj** (object): query check ifaceobject. This is only
1136 valid when op is 'query-checkcurr'. It is an object same as
1137 ifaceobj, but contains running attribute values and its config
1138 status. The modules can use it to return queried running state
1139 of interfaces. status is success if the running state is same
1140 as user required state in ifaceobj. error otherwise.
1141 """
3e6ea735
RP
1142 if ifaceobj.type == ifaceType.BRIDGE_VLAN:
1143 return
15ef32ea
RP
1144 op_handler = self._run_ops.get(operation)
1145 if not op_handler:
1146 return
15ef32ea
RP
1147 self._init_command_handlers()
1148 if operation == 'query-checkcurr':
84ca006f
RP
1149 op_handler(self, ifaceobj, query_ifaceobj,
1150 ifaceobj_getfunc=ifaceobj_getfunc)
15ef32ea 1151 else:
84ca006f 1152 op_handler(self, ifaceobj, ifaceobj_getfunc=ifaceobj_getfunc)