mirror of
https://github.com/CumulusNetworks/ifupdown2.git
synced 2024-05-06 15:54:50 +00:00
rework mstpctl attribute ordering problem with bridge stp processing
Ticket: CM-6626
Reviewed By: CCR-3768
Testing Done: Tested with testcase specified in bug
There was an earlier implementation for this for 2.5.4 (CCR-3599 a quick
fix for 2.5.4). This patch re-implements the fix.
This patch essentially handles stp set before and after the port is
processed. It replaces the below commit with the patch in this review
{noformat}
commit 3af351f0a005236e747913bb499c6165e3ec43a4
Author: Roopa Prabhu <roopa@cumulusnetworks.com>
Date: Tue Sep 29 10:12:07 2015 -0700
Fix mstp settings ordering issues when bridge stp is toggled on and
off
(when mstp settings are specified under the port)
Ticket: CM-6626
Reviewed By: CCR-3599
Testing Done: Tested the problem case mentioned in the bug (Plan to
re-work the fix a bit for 2.5.5)
{noformat}
Example:
{noformat}
auto host1
iface host1
mtu 9000
bond-slaves glob swp[25-26]
bond-mode 802.3ad
bond-miimon 100
bond-use-carrier 1
bond-lacp-rate 1
bond-min-links 1
bond-xmit-hash-policy layer3+4
clag-id 1
mstpctl-portadminedge yes
mstpctl-bpduguard yes
auto bridge
iface bridge
mtu 9000
bridge-vlan-aware yes
bridge-ports peerlink host1
bridge-stp on
bridge-vids 1000-3000
bridge-pvid 1
info log stmts:
--------------------
info: host1: ignoring mstpctl-portadminedge config (stp on bridge bridge
is not on yet)
info: host1: ignoring mstpctl-bpduguard config (stp on bridge bridge is
not on yet)
<snip>
info: bridge: processing bridge config for port host1
info: bridge: processing mstp config for port host1
info: executing /sbin/mstpctl showportdetail bridge host1
admin-edge-port
info: executing /sbin/mstpctl setportadminedge bridge host1 yes
info: executing /sbin/mstpctl showportdetail bridge host1
bpdu-guard-port
info: executing /sbin/mstpctl setbpduguard bridge host1 yes
{noformat}
This commit is contained in:
@@ -17,6 +17,7 @@ import time
|
||||
|
||||
class bridgeFlags:
|
||||
PORT_PROCESSED = 0x1
|
||||
PORT_PROCESSED_OVERRIDE = 0x2
|
||||
|
||||
class bridge(moduleBase):
|
||||
""" ifupdown2 addon module to configure linux bridges """
|
||||
@@ -539,16 +540,39 @@ class bridge(moduleBase):
|
||||
# if running_vids:
|
||||
# self.ipcmd.bridge_vids_del(ifaceobj.name, running_vids)
|
||||
|
||||
|
||||
def _is_running_stp_state_on(self, bridgename):
|
||||
""" Returns True if running stp state is on, else False """
|
||||
|
||||
stp_state_file = '/sys/class/net/%s/bridge/stp_state' %bridgename
|
||||
if not stp_state_file:
|
||||
return False
|
||||
running_stp_state = self.read_file_oneline(stp_state_file)
|
||||
if running_stp_state and running_stp_state != '0':
|
||||
return True
|
||||
return False
|
||||
|
||||
def _is_config_stp_state_on(self, ifaceobj):
|
||||
""" Returns true if user specified stp state is on, else False """
|
||||
|
||||
stp_attr = ifaceobj.get_attr_value_first('bridge-stp')
|
||||
if (stp_attr and (stp_attr == 'on' or stp_attr == 'yes')):
|
||||
return True
|
||||
return False
|
||||
|
||||
def _apply_bridge_settings(self, ifaceobj):
|
||||
try:
|
||||
stp = ifaceobj.get_attr_value_first('bridge-stp')
|
||||
if stp:
|
||||
self.brctlcmd.set_stp(ifaceobj.name, stp)
|
||||
if self._is_config_stp_state_on(ifaceobj):
|
||||
if not self._is_running_stp_state_on(ifaceobj.name):
|
||||
self.brctlcmd.set_stp(ifaceobj.name, "on")
|
||||
self.logger.info('%s: stp state reset, reapplying port '
|
||||
'settings' %ifaceobj.name)
|
||||
ifaceobj.module_flags[ifaceobj.name] = \
|
||||
ifaceobj.module_flags.setdefault(self.name,0) | \
|
||||
bridgeFlags.PORT_PROCESSED_OVERRIDE
|
||||
else:
|
||||
# If stp not specified and running stp state on, set it to off
|
||||
running_stp_state = self.read_file_oneline(
|
||||
'/sys/class/net/%s/bridge/stp_state' %ifaceobj.name)
|
||||
if running_stp_state and running_stp_state != '0':
|
||||
if self._is_running_stp_state_on(ifaceobj.name):
|
||||
self.brctlcmd.set_stp(ifaceobj.name, 'no')
|
||||
|
||||
if ifaceobj.get_attr_value_first('bridge-vlan-aware') == 'yes':
|
||||
@@ -868,6 +892,12 @@ class bridge(moduleBase):
|
||||
else:
|
||||
bridge_pvid = None
|
||||
|
||||
if (ifaceobj.module_flags.get(self.name, 0x0) &
|
||||
bridgeFlags.PORT_PROCESSED_OVERRIDE):
|
||||
port_processed_override = True
|
||||
else:
|
||||
port_processed_override = False
|
||||
|
||||
bridgeports = self._get_bridge_port_list(ifaceobj)
|
||||
if not bridgeports:
|
||||
self.logger.debug('%s: cannot find bridgeports' %ifaceobj.name)
|
||||
@@ -886,8 +916,10 @@ class bridge(moduleBase):
|
||||
continue
|
||||
for bportifaceobj in bportifaceobjlist:
|
||||
# Dont process bridge port if it already has been processed
|
||||
if (bportifaceobj.module_flags.get(self.name,0x0) & \
|
||||
bridgeFlags.PORT_PROCESSED):
|
||||
# and there is no override on port_processed
|
||||
if (not port_processed_override and
|
||||
(bportifaceobj.module_flags.get(self.name,0x0) &
|
||||
bridgeFlags.PORT_PROCESSED)):
|
||||
continue
|
||||
try:
|
||||
# Add attributes specific to the vlan aware bridge
|
||||
|
||||
@@ -295,27 +295,23 @@ class mstpctl(moduleBase):
|
||||
pass
|
||||
|
||||
def _apply_bridge_port_settings(self, ifaceobj, bridgename=None,
|
||||
bridgeifaceobj=None, stp_on=True,
|
||||
bridgeifaceobj=None,
|
||||
stp_running_on=True,
|
||||
mstpd_running=True):
|
||||
check = False if self.PERFMODE else True
|
||||
applied = False
|
||||
if not bridgename and bridgeifaceobj:
|
||||
bridgename = bridgeifaceobj.name
|
||||
# set bridge port attributes
|
||||
for attrname, dstattrname in self._port_attrs_map.items():
|
||||
attrval = ifaceobj.get_attr_value_first(attrname)
|
||||
if not attrval:
|
||||
#if bridgeifaceobj:
|
||||
# # If bridge object available, check if the bridge
|
||||
# # has the attribute set, in which case,
|
||||
# # inherit it from the bridge
|
||||
# attrval = bridgeifaceobj.get_attr_value_first(attrname)
|
||||
# if not attrval:
|
||||
# continue
|
||||
#else:
|
||||
continue
|
||||
if not stp_on:
|
||||
self.logger.warn('%s: cannot set %s (stp on bridge %s not on)\n'
|
||||
%(ifaceobj.name, attrname, bridgename))
|
||||
if not stp_running_on:
|
||||
# stp may get turned on at a later point
|
||||
self.logger.info('%s: ignoring %s config'
|
||||
%(ifaceobj.name, attrname) +
|
||||
' (stp on bridge %s is not on yet)' %bridgename)
|
||||
continue
|
||||
if not mstpd_running:
|
||||
continue
|
||||
@@ -325,9 +321,11 @@ class mstpctl(moduleBase):
|
||||
try:
|
||||
self.mstpctlcmd.set_bridgeport_attr(bridgename,
|
||||
ifaceobj.name, dstattrname, attrval, check)
|
||||
applied = True
|
||||
except Exception, e:
|
||||
self.log_warn('%s: error setting %s (%s)'
|
||||
%(ifaceobj.name, attrname, str(e)))
|
||||
return applied
|
||||
|
||||
def _apply_bridge_port_settings_all(self, ifaceobj,
|
||||
ifaceobj_getfunc=None):
|
||||
@@ -359,19 +357,29 @@ class mstpctl(moduleBase):
|
||||
except Exception, e:
|
||||
self.log_warn(str(e))
|
||||
|
||||
def _is_running_userspace_stp_state_on(self, bridgename):
|
||||
stp_state_file = '/sys/class/net/%s/bridge/stp_state' %bridgename
|
||||
if not stp_state_file:
|
||||
return False
|
||||
running_stp_state = self.read_file_oneline(stp_state_file)
|
||||
if running_stp_state and running_stp_state == '2':
|
||||
return True
|
||||
return False
|
||||
|
||||
def _up(self, ifaceobj, ifaceobj_getfunc=None):
|
||||
# Check if bridge port
|
||||
bridgename = self.ipcmd.bridge_port_get_bridge_name(ifaceobj.name)
|
||||
if bridgename:
|
||||
mstpd_running = (True if self.mstpctlcmd.is_mstpd_running()
|
||||
else False)
|
||||
stp_on = (True if self.read_file_oneline(
|
||||
'/sys/class/net/%s/bridge/stp_state'
|
||||
%bridgename) == '2' else False)
|
||||
self._apply_bridge_port_settings(ifaceobj, bridgename, None,
|
||||
stp_on, mstpd_running)
|
||||
ifaceobj.module_flags[self.name] = ifaceobj.module_flags.setdefault(self.name,0) | \
|
||||
mstpctlFlags.PORT_PROCESSED
|
||||
stp_running_on = self._is_running_userspace_stp_state_on(bridgename)
|
||||
applied = self._apply_bridge_port_settings(ifaceobj, bridgename,
|
||||
None, stp_running_on,
|
||||
mstpd_running)
|
||||
if applied:
|
||||
ifaceobj.module_flags[self.name] = \
|
||||
ifaceobj.module_flags.setdefault(self.name,0) | \
|
||||
mstpctlFlags.PORT_PROCESSED
|
||||
return
|
||||
if not self._is_bridge(ifaceobj):
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user