From 5a8f9d44b3c2e09a16fc0bf082ba30729c04e81a Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Wed, 20 Mar 2024 21:25:43 +0100 Subject: bridge: T6125: support 802.1ad (ethertype 0x88a8) VLAN filtering Linux bridge uses EtherType 0x8100 by default. In some scenarios, an EtherType value of 0x88A8 is required. Reusing CLI command from VIF-S (QinQ) interfaces: set interfaces bridge br0 protocol 802.1ad (cherry picked from commit 9c9b1febff6863ccd3632a04d9e307909b3efe7a) --- .../include/interface/vif-s.xml.i | 22 +------------- .../include/interface/vlan-protocol.xml.i | 23 +++++++++++++++ interface-definitions/interfaces_bridge.xml.in | 4 +++ python/vyos/ifconfig/bridge.py | 34 +++++++++++++++++++--- smoketest/scripts/cli/test_interfaces_bridge.py | 18 ++++++++++++ 5 files changed, 76 insertions(+), 25 deletions(-) create mode 100644 interface-definitions/include/interface/vlan-protocol.xml.i diff --git a/interface-definitions/include/interface/vif-s.xml.i b/interface-definitions/include/interface/vif-s.xml.i index fdd62b63d..02e7ab057 100644 --- a/interface-definitions/include/interface/vif-s.xml.i +++ b/interface-definitions/include/interface/vif-s.xml.i @@ -18,27 +18,7 @@ #include #include #include - - - Protocol used for service VLAN (default: 802.1ad) - - 802.1ad 802.1q - - - 802.1ad - Provider Bridging (IEEE 802.1ad, Q-inQ), ethertype 0x88a8 - - - 802.1q - VLAN-tagged frame (IEEE 802.1q), ethertype 0x8100 - - - (802.1q|802.1ad) - - Ethertype must be 802.1ad or 802.1q - - 802.1ad - + #include #include #include #include diff --git a/interface-definitions/include/interface/vlan-protocol.xml.i b/interface-definitions/include/interface/vlan-protocol.xml.i new file mode 100644 index 000000000..2fe8d65d7 --- /dev/null +++ b/interface-definitions/include/interface/vlan-protocol.xml.i @@ -0,0 +1,23 @@ + + + + Protocol used for service VLAN (default: 802.1ad) + + 802.1ad 802.1q + + + 802.1ad + Provider Bridging (IEEE 802.1ad, Q-inQ), ethertype 0x88a8 + + + 802.1q + VLAN-tagged frame (IEEE 802.1q), ethertype 0x8100 + + + (802.1q|802.1ad) + + Ethertype must be 802.1ad or 802.1q + + 802.1ad + + diff --git a/interface-definitions/interfaces_bridge.xml.in b/interface-definitions/interfaces_bridge.xml.in index d4d277cfc..7fb5f121a 100644 --- a/interface-definitions/interfaces_bridge.xml.in +++ b/interface-definitions/interfaces_bridge.xml.in @@ -98,6 +98,10 @@ + #include + + 802.1q + Interval at which neighbor bridges are removed diff --git a/python/vyos/ifconfig/bridge.py b/python/vyos/ifconfig/bridge.py index b29e71394..7936e3da5 100644 --- a/python/vyos/ifconfig/bridge.py +++ b/python/vyos/ifconfig/bridge.py @@ -1,4 +1,4 @@ -# Copyright 2019-2021 VyOS maintainers and contributors +# Copyright 2019-2024 VyOS maintainers and contributors # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -14,12 +14,11 @@ # License along with this library. If not, see . from netifaces import interfaces -import json from vyos.ifconfig.interface import Interface from vyos.utils.assertion import assert_boolean +from vyos.utils.assertion import assert_list from vyos.utils.assertion import assert_positive -from vyos.utils.process import cmd from vyos.utils.dict import dict_search from vyos.configdict import get_vlan_ids from vyos.configdict import list_diff @@ -86,6 +85,10 @@ class BridgeIf(Interface): 'validate': assert_boolean, 'location': '/sys/class/net/{ifname}/bridge/vlan_filtering', }, + 'vlan_protocol': { + 'validate': lambda v: assert_list(v, ['0x88a8', '0x8100']), + 'location': '/sys/class/net/{ifname}/bridge/vlan_protocol', + }, 'multicast_querier': { 'validate': assert_boolean, 'location': '/sys/class/net/{ifname}/bridge/multicast_querier', @@ -248,6 +251,26 @@ class BridgeIf(Interface): """ return self.set_interface('del_port', interface) + def set_vlan_protocol(self, protocol): + """ + Set protocol used for VLAN filtering. + The valid values are 0x8100(802.1q) or 0x88A8(802.1ad). + + Example: + >>> from vyos.ifconfig import Interface + >>> BridgeIf('br0').del_port('eth1') + """ + + if protocol not in ['802.1q', '802.1ad']: + raise ValueError() + + map = { + '802.1ad': '0x88a8', + '802.1q' : '0x8100' + } + + return self.set_interface('vlan_protocol', map[protocol]) + def update(self, config): """ General helper function which works on a dictionary retrived by get_config_dict(). It's main intention is to consolidate the scattered @@ -294,10 +317,13 @@ class BridgeIf(Interface): if member in interfaces(): self.del_port(member) - # enable/disable Vlan Filter + # enable/disable VLAN Filter tmp = '1' if 'enable_vlan' in config else '0' self.set_vlan_filter(tmp) + tmp = config.get('protocol') + self.set_vlan_protocol(tmp) + # add VLAN interfaces to local 'parent' bridge to allow forwarding if 'enable_vlan' in config: for vlan in config.get('vif_remove', {}): diff --git a/smoketest/scripts/cli/test_interfaces_bridge.py b/smoketest/scripts/cli/test_interfaces_bridge.py index 3500e97d6..124c1fbcb 100755 --- a/smoketest/scripts/cli/test_interfaces_bridge.py +++ b/smoketest/scripts/cli/test_interfaces_bridge.py @@ -182,6 +182,10 @@ class BridgeInterfaceTest(BasicInterfaceTest.TestCase): for interface in self._interfaces: cost = 1000 priority = 10 + + tmp = get_interface_config(interface) + self.assertEqual('802.1Q', tmp['linkinfo']['info_data']['vlan_protocol']) # default VLAN protocol + for member in self._members: tmp = get_interface_config(member) self.assertEqual(interface, tmp['master']) @@ -442,5 +446,19 @@ class BridgeInterfaceTest(BasicInterfaceTest.TestCase): self.cli_delete(['interfaces', 'tunnel', tunnel_if]) self.cli_delete(['interfaces', 'ethernet', 'eth0', 'address', eth0_addr]) + def test_bridge_vlan_protocol(self): + protocol = '802.1ad' + + # Add member interface to bridge and set VLAN filter + for interface in self._interfaces: + self.cli_set(self._base_path + [interface, 'protocol', protocol]) + + # commit config + self.cli_commit() + + for interface in self._interfaces: + tmp = get_interface_config(interface) + self.assertEqual(protocol, tmp['linkinfo']['info_data']['vlan_protocol']) + if __name__ == '__main__': unittest.main(verbosity=2) -- cgit v1.2.3