summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--interface-definitions/include/interface/vif.xml.i14
-rw-r--r--python/vyos/ifconfig/interface.py47
-rw-r--r--smoketest/scripts/cli/base_interfaces_test.py101
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_bridge.py8
4 files changed, 161 insertions, 9 deletions
diff --git a/interface-definitions/include/interface/vif.xml.i b/interface-definitions/include/interface/vif.xml.i
index 0355054a4..9e89cbbf6 100644
--- a/interface-definitions/include/interface/vif.xml.i
+++ b/interface-definitions/include/interface/vif.xml.i
@@ -22,9 +22,10 @@
<leafNode name="egress-qos">
<properties>
<help>VLAN egress QoS</help>
- <completionHelp>
- <script>echo Format for qos mapping, e.g.: '0:1 1:6 7:6'</script>
- </completionHelp>
+ <valueHelp>
+ <format>txt</format>
+ <description>Format for qos mapping, e.g.: '0:1 1:6 7:6'</description>
+ </valueHelp>
<constraint>
<regex>[:0-7 ]+$</regex>
</constraint>
@@ -34,9 +35,10 @@
<leafNode name="ingress-qos">
<properties>
<help>VLAN ingress QoS</help>
- <completionHelp>
- <script>echo Format for qos mapping '0:1 1:6 7:6'</script>
- </completionHelp>
+ <valueHelp>
+ <format>txt</format>
+ <description>Format for qos mapping, e.g.: '0:1 1:6 7:6'</description>
+ </valueHelp>
<constraint>
<regex>[:0-7 ]+$</regex>
</constraint>
diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py
index 048a2cd19..6a66d958f 100644
--- a/python/vyos/ifconfig/interface.py
+++ b/python/vyos/ifconfig/interface.py
@@ -1345,12 +1345,55 @@ class Interface(Control):
# create/update 802.1q VLAN interfaces
for vif_id, vif_config in config.get('vif', {}).items():
+
+ vif_ifname = f'{ifname}.{vif_id}'
+ vif_config['ifname'] = vif_ifname
+
tmp = deepcopy(VLANIf.get_config())
tmp['source_interface'] = ifname
tmp['vlan_id'] = vif_id
+
+ # We need to ensure that the string format is consistent, and we need to exclude redundant spaces.
+ sep = ' '
+ if 'egress_qos' in vif_config:
+ # Unwrap strings into arrays
+ egress_qos_array = vif_config['egress_qos'].split()
+ # The split array is spliced according to the fixed format
+ tmp['egress_qos'] = sep.join(egress_qos_array)
+
+ if 'ingress_qos' in vif_config:
+ # Unwrap strings into arrays
+ ingress_qos_array = vif_config['ingress_qos'].split()
+ # The split array is spliced according to the fixed format
+ tmp['ingress_qos'] = sep.join(ingress_qos_array)
+
+ # Since setting the QoS control parameters in the later stage will
+ # not completely delete the old settings,
+ # we still need to delete the VLAN encapsulation interface in order to
+ # ensure that the changed settings are effective.
+ cur_cfg = get_interface_config(vif_ifname)
+ qos_str = ''
+ tmp2 = dict_search('linkinfo.info_data.ingress_qos', cur_cfg)
+ if 'ingress_qos' in tmp and tmp2:
+ for item in tmp2:
+ from_key = item['from']
+ to_key = item['to']
+ qos_str += f'{from_key}:{to_key} '
+ if qos_str != tmp['ingress_qos']:
+ if self.exists(vif_ifname):
+ VLANIf(vif_ifname).remove()
+
+ qos_str = ''
+ tmp2 = dict_search('linkinfo.info_data.egress_qos', cur_cfg)
+ if 'egress_qos' in tmp and tmp2:
+ for item in tmp2:
+ from_key = item['from']
+ to_key = item['to']
+ qos_str += f'{from_key}:{to_key} '
+ if qos_str != tmp['egress_qos']:
+ if self.exists(vif_ifname):
+ VLANIf(vif_ifname).remove()
- vif_ifname = f'{ifname}.{vif_id}'
- vif_config['ifname'] = vif_ifname
vlan = VLANIf(vif_ifname, **tmp)
vlan.update(vif_config)
diff --git a/smoketest/scripts/cli/base_interfaces_test.py b/smoketest/scripts/cli/base_interfaces_test.py
index 56e436afc..b83091ea6 100644
--- a/smoketest/scripts/cli/base_interfaces_test.py
+++ b/smoketest/scripts/cli/base_interfaces_test.py
@@ -278,18 +278,119 @@ class BasicInterfaceTest:
self.cli_set(base + ['mtu', self._mtu])
for address in self._test_addr:
self.cli_set(base + ['address', address])
+ self.cli_set(base + ['ingress-qos', '0:1'])
+ self.cli_set(base + ['egress-qos', '1:6'])
self.cli_commit()
for intf in self._interfaces:
for vlan in self._vlan_range:
vif = f'{intf}.{vlan}'
+ tmp = get_interface_config(f'{vif}')
+
+ tmp2 = dict_search('linkinfo.info_data.ingress_qos', tmp)
+ for item in tmp2 if tmp2 else []:
+ from_key = item['from']
+ to_key = item['to']
+ self.assertEqual(from_key, 0)
+ self.assertEqual(to_key, 1)
+
+ tmp2 = dict_search('linkinfo.info_data.egress_qos', tmp)
+ for item in tmp2 if tmp2 else []:
+ from_key = item['from']
+ to_key = item['to']
+ self.assertEqual(from_key, 1)
+ self.assertEqual(to_key, 6)
+
for address in self._test_addr:
self.assertTrue(is_intf_addr_assigned(vif, address))
tmp = read_file(f'/sys/class/net/{vif}/mtu')
self.assertEqual(tmp, self._mtu)
self.assertEqual(Interface(vif).get_admin_state(), 'up')
+
+ def test_vif_qos_change(self):
+ # XXX: This testcase is not allowed to run as first testcase, reason
+ # is the Wireless test will first load the wifi kernel hwsim module
+ # which creates a wlan0 and wlan1 interface which will fail the
+ # tearDown() test in the end that no interface is allowed to survive!
+ if not self._test_vlan:
+ self.skipTest('not supported')
+
+ for interface in self._interfaces:
+ base = self._base_path + [interface]
+ for option in self._options.get(interface, []):
+ self.cli_set(base + option.split())
+
+ for vlan in self._vlan_range:
+ base = self._base_path + [interface, 'vif', vlan]
+ self.cli_set(base + ['mtu', self._mtu])
+ for address in self._test_addr:
+ self.cli_set(base + ['address', address])
+ self.cli_set(base + ['ingress-qos', '0:1'])
+ self.cli_set(base + ['egress-qos', '1:6'])
+
+ self.cli_commit()
+
+ for intf in self._interfaces:
+ for vlan in self._vlan_range:
+ vif = f'{intf}.{vlan}'
+ tmp = get_interface_config(f'{vif}')
+
+ tmp2 = dict_search('linkinfo.info_data.ingress_qos', tmp)
+ for item in tmp2 if tmp2 else []:
+ from_key = item['from']
+ to_key = item['to']
+ self.assertEqual(from_key, 0)
+ self.assertEqual(to_key, 1)
+
+ tmp2 = dict_search('linkinfo.info_data.egress_qos', tmp)
+ for item in tmp2 if tmp2 else []:
+ from_key = item['from']
+ to_key = item['to']
+ self.assertEqual(from_key, 1)
+ self.assertEqual(to_key, 6)
+
+ for address in self._test_addr:
+ self.assertTrue(is_intf_addr_assigned(vif, address))
+
+ tmp = read_file(f'/sys/class/net/{vif}/mtu')
+ self.assertEqual(tmp, self._mtu)
+ self.assertEqual(Interface(vif).get_admin_state(), 'up')
+
+ new_ingress_qos_from = 1
+ new_ingress_qos_to = 6
+ new_egress_qos_from = 2
+ new_egress_qos_to = 7
+ for interface in self._interfaces:
+ base = self._base_path + [interface]
+ for vlan in self._vlan_range:
+ base = self._base_path + [interface, 'vif', vlan]
+ self.cli_delete(base + ['ingress-qos', '0:1'])
+ self.cli_delete(base + ['egress-qos', '1:6'])
+ self.cli_set(base + ['ingress-qos', f'{new_ingress_qos_from}:{new_ingress_qos_to}'])
+ self.cli_set(base + ['egress-qos', f'{new_egress_qos_from}:{new_egress_qos_to}'])
+
+ self.cli_commit()
+
+ for intf in self._interfaces:
+ for vlan in self._vlan_range:
+ vif = f'{intf}.{vlan}'
+ tmp = get_interface_config(f'{vif}')
+
+ tmp2 = dict_search('linkinfo.info_data.ingress_qos', tmp)
+ if tmp2:
+ from_key = tmp2[0]['from']
+ to_key = tmp2[0]['to']
+ self.assertEqual(from_key, new_ingress_qos_from)
+ self.assertEqual(to_key, new_ingress_qos_to)
+
+ tmp2 = dict_search('linkinfo.info_data.egress_qos', tmp)
+ if tmp2:
+ from_key = tmp2[0]['from']
+ to_key = tmp2[0]['to']
+ self.assertEqual(from_key, new_egress_qos_from)
+ self.assertEqual(to_key, new_egress_qos_to)
def test_vif_8021q_lower_up_down(self):
# Testcase for https://phabricator.vyos.net/T3349
diff --git a/smoketest/scripts/cli/test_interfaces_bridge.py b/smoketest/scripts/cli/test_interfaces_bridge.py
index 21f20c781..6865d3a8a 100755
--- a/smoketest/scripts/cli/test_interfaces_bridge.py
+++ b/smoketest/scripts/cli/test_interfaces_bridge.py
@@ -134,7 +134,13 @@ class BridgeInterfaceTest(BasicInterfaceTest.TestCase):
for interface in self._interfaces:
base = self._base_path + [interface]
self.cli_set(base + ['enable-vlan'])
- super().test_vif_8021q_interfaces()
+ super().test_vif_8021q_lower_up_down()
+
+ def test_vif_qos_change(self):
+ for interface in self._interfaces:
+ base = self._base_path + [interface]
+ self.cli_set(base + ['enable-vlan'])
+ super().test_vif_qos_change()
def test_bridge_vlan_filter(self):
vif_vlan = 2