From 7e035196049ff0525b01020ac12689612bdda2cb Mon Sep 17 00:00:00 2001 From: l0crian1 Date: Mon, 5 May 2025 12:04:02 -0400 Subject: Bridge: T7430: Add BPDU Guard and Root Guard support This will add support for BPDU Guard and Root Guard to the bridge interface. Verification will come from: show log spanning-tree --- interface-definitions/interfaces_bridge.xml.in | 12 ++++++++++ op-mode-definitions/show-log.xml.in | 6 +++++ python/vyos/ifconfig/bridge.py | 10 ++++++++ python/vyos/ifconfig/interface.py | 32 +++++++++++++++++++++++++ smoketest/scripts/cli/test_interfaces_bridge.py | 25 +++++++++++++++++++ src/conf_mode/interfaces_bridge.py | 3 +++ 6 files changed, 88 insertions(+) diff --git a/interface-definitions/interfaces_bridge.xml.in b/interface-definitions/interfaces_bridge.xml.in index 667ae3b19..b360f34f1 100644 --- a/interface-definitions/interfaces_bridge.xml.in +++ b/interface-definitions/interfaces_bridge.xml.in @@ -201,6 +201,18 @@ + + + Enable BPDU Guard + + + + + + Enable Root Guard + + + diff --git a/op-mode-definitions/show-log.xml.in b/op-mode-definitions/show-log.xml.in index ee2e2bf70..b09d3c68b 100755 --- a/op-mode-definitions/show-log.xml.in +++ b/op-mode-definitions/show-log.xml.in @@ -831,6 +831,12 @@ journalctl --no-hostname --boot --unit snmpd.service + + + Show log for Spanning Tree Protocol (STP) + + journalctl --dmesg --no-hostname --boot --grep='br[0-9].*(stp|bpdu|blocking|disabled|forwarding|listening|root port)' + Show log for Secure Shell (SSH) diff --git a/python/vyos/ifconfig/bridge.py b/python/vyos/ifconfig/bridge.py index f81026965..69dae42d3 100644 --- a/python/vyos/ifconfig/bridge.py +++ b/python/vyos/ifconfig/bridge.py @@ -376,6 +376,16 @@ class BridgeIf(Interface): if 'priority' in interface_config: lower.set_path_priority(interface_config['priority']) + # set BPDU guard + tmp = dict_search('bpdu_guard', interface_config) + value = '1' if (tmp != None) else '0' + lower.set_bpdu_guard(value) + + # set root guard + tmp = dict_search('root_guard', interface_config) + value = '1' if (tmp != None) else '0' + lower.set_root_guard(value) + if 'enable_vlan' in config: add_vlan = [] native_vlan_id = None diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index 003a273c0..91b3a0c28 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -217,6 +217,16 @@ class Interface(Control): 'location': '/sys/class/net/{ifname}/brport/priority', 'errormsg': '{ifname} is not a bridge port member' }, + 'bpdu_guard': { + 'validate': assert_boolean, + 'location': '/sys/class/net/{ifname}/brport/bpdu_guard', + 'errormsg': '{ifname} is not a bridge port member' + }, + 'root_guard': { + 'validate': assert_boolean, + 'location': '/sys/class/net/{ifname}/brport/root_block', + 'errormsg': '{ifname} is not a bridge port member' + }, 'proxy_arp': { 'validate': assert_boolean, 'location': '/proc/sys/net/ipv4/conf/{ifname}/proxy_arp', @@ -1106,6 +1116,28 @@ class Interface(Control): """ self.set_interface('path_priority', priority) + def set_bpdu_guard(self, state): + """ + Set BPDU guard state for a bridge port. When enabled, the port will be + disabled if it receives a BPDU packet. + + Example: + >>> from vyos.ifconfig import Interface + >>> Interface('eth0').set_bpdu_guard(1) + """ + self.set_interface('bpdu_guard', state) + + def set_root_guard(self, state): + """ + Set root guard state for a bridge port. When enabled, the port will be + disabled if it receives a superior BPDU that would make it a root port. + + Example: + >>> from vyos.ifconfig import Interface + >>> Interface('eth0').set_root_guard(1) + """ + self.set_interface('root_guard', state) + def set_port_isolation(self, on_or_off): """ Controls whether a given port will be isolated, which means it will be diff --git a/smoketest/scripts/cli/test_interfaces_bridge.py b/smoketest/scripts/cli/test_interfaces_bridge.py index 4041b3ef3..c18be7e99 100755 --- a/smoketest/scripts/cli/test_interfaces_bridge.py +++ b/smoketest/scripts/cli/test_interfaces_bridge.py @@ -508,6 +508,31 @@ class BridgeInterfaceTest(BasicInterfaceTest.TestCase): self.cli_delete(['interfaces', 'vxlan', vxlan_if]) self.cli_delete(['interfaces', 'ethernet', 'eth0', 'address', eth0_addr]) + def test_bridge_root_bpdu_guard(self): + # Test if both bpdu_guard and root_guard configured + self.cli_set(['interfaces', 'bridge', 'br0', 'stp']) + self.cli_set(['interfaces', 'bridge', 'br0', 'member', 'interface', 'eth0', 'bpdu-guard']) + self.cli_set(['interfaces', 'bridge', 'br0', 'member', 'interface', 'eth0', 'root-guard']) + with self.assertRaises(ConfigSessionError): + self.cli_commit() + self.cli_discard() + + # Test if bpdu_guard configured + self.cli_set(['interfaces', 'bridge', 'br0', 'stp']) + self.cli_set(['interfaces', 'bridge', 'br0', 'member', 'interface', 'eth0', 'bpdu-guard']) + self.cli_commit() + + tmp = read_file(f'/sys/class/net/eth0/brport/bpdu_guard') + self.assertEqual(tmp, '1') + + # Test if root_guard configured + self.cli_delete(['interfaces', 'bridge', 'br0']) + self.cli_set(['interfaces', 'bridge', 'br0', 'stp']) + self.cli_set(['interfaces', 'bridge', 'br0', 'member', 'interface', 'eth0', 'root-guard']) + self.cli_commit() + + tmp = read_file(f'/sys/class/net/eth0/brport/root_block') + self.assertEqual(tmp, '1') if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/src/conf_mode/interfaces_bridge.py b/src/conf_mode/interfaces_bridge.py index 95dcc543e..956030289 100755 --- a/src/conf_mode/interfaces_bridge.py +++ b/src/conf_mode/interfaces_bridge.py @@ -167,6 +167,9 @@ def verify(bridge): if 'has_vrf' in interface_config: raise ConfigError(error_msg + 'it has a VRF assigned!') + if 'bpdu_guard' in interface_config and 'root_guard' in interface_config: + raise ConfigError(error_msg + 'bpdu_guard and root_guard cannot be configured at the same time!') + if 'enable_vlan' in bridge: if 'has_vlan' in interface_config: raise ConfigError(error_msg + 'it has VLAN subinterface(s) assigned!') -- cgit v1.2.3 From e5b613191a60f0de4a231d35aa48e3f0e90a05ab Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Mon, 26 May 2025 19:53:58 +0200 Subject: bridge: T7430: rephrase bpdu/root-guard error message --- src/conf_mode/interfaces_bridge.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conf_mode/interfaces_bridge.py b/src/conf_mode/interfaces_bridge.py index 956030289..c14e6a599 100755 --- a/src/conf_mode/interfaces_bridge.py +++ b/src/conf_mode/interfaces_bridge.py @@ -168,7 +168,7 @@ def verify(bridge): raise ConfigError(error_msg + 'it has a VRF assigned!') if 'bpdu_guard' in interface_config and 'root_guard' in interface_config: - raise ConfigError(error_msg + 'bpdu_guard and root_guard cannot be configured at the same time!') + raise ConfigError(error_msg + 'bpdu-guard and root-guard cannot be configured at the same time!') if 'enable_vlan' in bridge: if 'has_vlan' in interface_config: -- cgit v1.2.3