diff options
author | jack9603301 <jack9603301@163.com> | 2020-12-10 23:23:44 +0800 |
---|---|---|
committer | jack9603301 <jack9603301@163.com> | 2020-12-13 02:12:45 +0800 |
commit | c4048b2047f693436b38196632cddf65beb67a86 (patch) | |
tree | 62a140416830d1c9f72636f3e72680f15279dbb3 | |
parent | e6e87c839f8dc458dcf2962ea936329e972fbafc (diff) | |
download | vyos-1x-c4048b2047f693436b38196632cddf65beb67a86.tar.gz vyos-1x-c4048b2047f693436b38196632cddf65beb67a86.zip |
interfaces: T3114: Fix VLAN-aware bridge setting failure
-rw-r--r-- | python/vyos/ifconfig/bridge.py | 37 | ||||
-rw-r--r-- | python/vyos/ifconfig/interface.py | 59 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_interfaces_bridge.py | 16 |
3 files changed, 106 insertions, 6 deletions
diff --git a/python/vyos/ifconfig/bridge.py b/python/vyos/ifconfig/bridge.py index d0d5da881..959345f2f 100644 --- a/python/vyos/ifconfig/bridge.py +++ b/python/vyos/ifconfig/bridge.py @@ -14,6 +14,7 @@ # License along with this library. If not, see <http://www.gnu.org/licenses/>. from netifaces import interfaces +import json from vyos.ifconfig.interface import Interface from vyos.validate import assert_boolean @@ -208,6 +209,35 @@ class BridgeIf(Interface): """ return self.set_interface('del_port', interface) + def get_vlan_ids(self): + """ + Get the VLAN ID of the interface bound to the bridge + + is_trunk is 1 means to obtain the VLAN ID of Trunk mode, otherwise obtain the VLAN ID of Access mode + + Example: + >>> from vyos.ifconfig import BridgeIf + >>> Interface('br0').get_vlan_id() + None + """ + interface = self.config['ifname'] + + vlan_ids = [] + + bridge_status = cmd('bridge -j vlan show', shell=True) + vlan_filter_status = json.loads(bridge_status) + + if vlan_filter_status is not None: + for interface_status in vlan_filter_status: + ifname = interface_status['ifname'] + if interface == ifname: + vlans_status = interface_status['vlans'] + for vlan_status in vlans_status: + vlan_id = vlan_status['vlan'] + vlan_ids.append(vlan_id) + + return vlan_ids + 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 @@ -309,7 +339,7 @@ class BridgeIf(Interface): cmd = f'bridge vlan del dev {interface} vid 1' self._cmd(cmd) vlan_id = interface_config['native_vlan'] - if vlan_id != 1: + if int(vlan_id) != 1: vlan_del.add(1) cmd = f'bridge vlan add dev {interface} vid {vlan_id} pvid untagged master' self._cmd(cmd) @@ -329,16 +359,11 @@ class BridgeIf(Interface): self._cmd(cmd) vlan_add.add(vlan) - - - for vlan in vlan_del: if isinstance(vlan,str) and vlan.isnumeric(): if int(vlan) == 1: cmd = f'bridge vlan del dev {ifname} vid {vlan} self' self._cmd(cmd) - cmd = f'bridge vlan add dev {ifname} vid {vlan} pvid untagged self' - self._cmd(cmd) else: cmd = f'bridge vlan del dev {ifname} vid {vlan} self' self._cmd(cmd) diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index 6e6a83f36..eda3fadd6 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -731,6 +731,7 @@ class Interface(Control): >>> Interface('eth0').set_proxy_arp_pvlan(1) """ self.set_interface('proxy_arp_pvlan', enable) + def get_addr(self): """ @@ -898,6 +899,64 @@ class Interface(Control): # set bridge port path priority if 'priority' in bridge_config: self.set_path_cost(bridge_config['priority']) + + vlan_filter = 0 + + vlan_del = set() + vlan_add = set() + + if 'native_vlan' in bridge_config: + vlan_filter = 1 + cmd = f'bridge vlan del dev {self.ifname} vid 1' + self._cmd(cmd) + vlan_id = bridge_config['native_vlan'] + if int(vlan_id) != 1: + vlan_del.add(1) + cmd = f'bridge vlan add dev {self.ifname} vid {vlan_id} pvid untagged master' + self._cmd(cmd) + vlan_add.add(vlan_id) + + if 'allowed_vlan' in bridge_config: + vlan_filter = 1 + + if vlan_filter: + if 'native_vlan' not in bridge_config: + cmd = f'bridge vlan del dev {self.ifname} vid 1' + self._cmd(cmd) + + if 'allowed_vlan' in bridge_config: + for vlan in bridge_config['allowed_vlan']: + cmd = f'bridge vlan add dev {self.ifname} vid {vlan} master' + self._cmd(cmd) + vlan_add.add(vlan) + + vlan_bridge_ids = Section.klass(bridge)(bridge, create=True).get_vlan_ids() + + # Delete VLAN ID for the bridge + for vlan in vlan_del: + if int(vlan) == 1: + cmd = f'bridge vlan del dev {bridge} vid {vlan} self' + self._cmd(cmd) + + # Setting VLAN ID for the bridge + for vlan in vlan_add: + if isinstance(vlan,str) and vlan.isnumeric(): + if int(vlan) not in vlan_bridge_ids: + cmd = f'bridge vlan add dev {bridge} vid {vlan} self' + self._cmd(cmd) + elif isinstance(vlan,str) and not vlan.isnumeric(): + vlan_range = vlan.split('-') + for vlan_id in range(int(vlan_range[0]),int(vlan_range[1]) + 1): + if int(vlan_id) not in vlan_bridge_ids: + cmd = f'bridge vlan add dev {bridge} vid {vlan_id} self' + self._cmd(cmd) + else: + if vlan not in vlan_bridge_ids: + cmd = f'bridge vlan add dev {bridge} vid {vlan} self' + self._cmd(cmd) + + # enable/disable Vlan Filter + Section.klass(bridge)(bridge, create=True).set_vlan_filter(vlan_filter) def set_dhcp(self, enable): """ diff --git a/smoketest/scripts/cli/test_interfaces_bridge.py b/smoketest/scripts/cli/test_interfaces_bridge.py index 9bddede31..0072a4d3b 100755 --- a/smoketest/scripts/cli/test_interfaces_bridge.py +++ b/smoketest/scripts/cli/test_interfaces_bridge.py @@ -45,10 +45,25 @@ class BridgeInterfaceTest(BasicInterfaceTest.BaseTest): for tmp in Section.interfaces("ethernet"): if not '.' in tmp: self._members.append(tmp) + + self.session.set(['interfaces','dummy','dum0']) + self.session.set(['interfaces','dummy','dum1']) + self.session.commit() + self.session.set(['interfaces','bonding','bond1','member','interface','dum0']) + self.session.set(['interfaces','bonding','bond1','member','interface','dum1']) + self.session.commit() + for tmp in Section.interfaces("bonding"): + if not '.' in tmp: + self._members.append(tmp) self._options['br0'] = [] for member in self._members: self._options['br0'].append(f'member interface {member}') + + def tearDown(self): + self.session.delete(['interfaces','bonding']) + self.session.delete(['interfaces','dummy']) + super().tearDown() def test_add_remove_member(self): """ Add member interfaces to bridge and set STP cost/priority """ @@ -56,6 +71,7 @@ class BridgeInterfaceTest(BasicInterfaceTest.BaseTest): base = self._base_path + [interface] self.session.set(base + ['stp']) self.session.set(base + ['address', '192.0.2.1/24']) + self.session.commit() cost = 1000 priority = 10 |