1
0
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:
Roopa Prabhu
2015-11-08 12:13:16 -08:00
parent 74a4a724c3
commit 641cbd1e7d
2 changed files with 67 additions and 27 deletions

View File

@@ -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

View File

@@ -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