summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--interface-definitions/include/version/bgp-version.xml.i2
-rw-r--r--python/vyos/qos/trafficshaper.py12
-rwxr-xr-xsrc/conf_mode/protocols_bgp.py10
-rwxr-xr-xsrc/migration-scripts/bgp/4-to-567
-rwxr-xr-xsrc/migration-scripts/policy/4-to-548
-rwxr-xr-xsrc/migration-scripts/qos/1-to-248
6 files changed, 181 insertions, 6 deletions
diff --git a/interface-definitions/include/version/bgp-version.xml.i b/interface-definitions/include/version/bgp-version.xml.i
index 1386ea9bc..6bed7189f 100644
--- a/interface-definitions/include/version/bgp-version.xml.i
+++ b/interface-definitions/include/version/bgp-version.xml.i
@@ -1,3 +1,3 @@
<!-- include start from include/version/bgp-version.xml.i -->
-<syntaxVersion component='bgp' version='4'></syntaxVersion>
+<syntaxVersion component='bgp' version='5'></syntaxVersion>
<!-- include end -->
diff --git a/python/vyos/qos/trafficshaper.py b/python/vyos/qos/trafficshaper.py
index 1f3b03680..d6705cc77 100644
--- a/python/vyos/qos/trafficshaper.py
+++ b/python/vyos/qos/trafficshaper.py
@@ -99,7 +99,11 @@ class TrafficShaper(QoSBase):
self._cmd(tmp)
if 'default' in config:
- rate = self._rate_convert(config['default']['bandwidth'])
+ if config['default']['bandwidth'].endswith('%'):
+ percent = config['default']['bandwidth'].rstrip('%')
+ rate = self._rate_convert(config['bandwidth']) * int(percent) // 100
+ else:
+ rate = self._rate_convert(config['default']['bandwidth'])
burst = config['default']['burst']
quantum = config['default']['codel_quantum']
tmp = f'tc class replace dev {self._interface} parent {self._parent:x}:1 classid {self._parent:x}:{default_minor_id:x} htb rate {rate} burst {burst} quantum {quantum}'
@@ -107,7 +111,11 @@ class TrafficShaper(QoSBase):
priority = config['default']['priority']
tmp += f' prio {priority}'
if 'ceiling' in config['default']:
- f_ceil = self._rate_convert(config['default']['ceiling'])
+ if config['default']['ceiling'].endswith('%'):
+ percent = config['default']['ceiling'].rstrip('%')
+ f_ceil = self._rate_convert(config['bandwidth']) * int(percent) // 100
+ else:
+ f_ceil = self._rate_convert(config['default']['ceiling'])
tmp += f' ceil {f_ceil}'
self._cmd(tmp)
diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py
index f6f3370c3..d90dfe45b 100755
--- a/src/conf_mode/protocols_bgp.py
+++ b/src/conf_mode/protocols_bgp.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2020-2023 VyOS maintainers and contributors
+# Copyright (C) 2020-2024 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -509,6 +509,14 @@ def verify(bgp):
if verify_vrf_as_import(vrf_name, afi, bgp['dependent_vrfs']):
raise ConfigError(
'Command "import vrf" conflicts with "route-target vpn both" command!')
+ if dict_search('route_target.vpn.export', afi_config):
+ raise ConfigError(
+ 'Command "route-target vpn export" conflicts '\
+ 'with "route-target vpn both" command!')
+ if dict_search('route_target.vpn.import', afi_config):
+ raise ConfigError(
+ 'Command "route-target vpn import" conflicts '\
+ 'with "route-target vpn both" command!')
if dict_search('route_target.vpn.import', afi_config):
if verify_vrf_as_import(vrf_name, afi, bgp['dependent_vrfs']):
diff --git a/src/migration-scripts/bgp/4-to-5 b/src/migration-scripts/bgp/4-to-5
new file mode 100755
index 000000000..c4eb9ec72
--- /dev/null
+++ b/src/migration-scripts/bgp/4-to-5
@@ -0,0 +1,67 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2024 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Delete 'protocols bgp address-family ipv6-unicast route-target vpn
+# import/export', if 'protocols bgp address-family ipv6-unicast
+# route-target vpn both' exists
+
+from sys import argv
+from sys import exit
+
+from vyos.configtree import ConfigTree
+
+if len(argv) < 2:
+ print("Must specify file name!")
+ exit(1)
+
+file_name = argv[1]
+
+with open(file_name, 'r') as f:
+ config_file = f.read()
+
+config = ConfigTree(config_file)
+
+bgp_base = ['protocols', 'bgp']
+# Delete 'import/export' in default vrf if 'both' exists
+if config.exists(bgp_base):
+ for address_family in ['ipv4-unicast', 'ipv6-unicast']:
+ rt_path = bgp_base + ['address-family', address_family, 'route-target',
+ 'vpn']
+ if config.exists(rt_path + ['both']):
+ if config.exists(rt_path + ['import']):
+ config.delete(rt_path + ['import'])
+ if config.exists(rt_path + ['export']):
+ config.delete(rt_path + ['export'])
+
+# Delete import/export in vrfs if both exists
+if config.exists(['vrf', 'name']):
+ for vrf in config.list_nodes(['vrf', 'name']):
+ vrf_base = ['vrf', 'name', vrf]
+ for address_family in ['ipv4-unicast', 'ipv6-unicast']:
+ rt_path = vrf_base + bgp_base + ['address-family', address_family,
+ 'route-target', 'vpn']
+ if config.exists(rt_path + ['both']):
+ if config.exists(rt_path + ['import']):
+ config.delete(rt_path + ['import'])
+ if config.exists(rt_path + ['export']):
+ config.delete(rt_path + ['export'])
+
+try:
+ with open(file_name, 'w') as f:
+ f.write(config.to_string())
+except OSError as e:
+ print(f'Failed to save the modified config: {e}')
+ exit(1)
diff --git a/src/migration-scripts/policy/4-to-5 b/src/migration-scripts/policy/4-to-5
index f6f889c35..5b8fee17e 100755
--- a/src/migration-scripts/policy/4-to-5
+++ b/src/migration-scripts/policy/4-to-5
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2022 VyOS maintainers and contributors
+# Copyright (C) 2022-2024 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -37,7 +37,53 @@ base4 = ['policy', 'route']
base6 = ['policy', 'route6']
config = ConfigTree(config_file)
+
+def delete_orphaned_interface_policy(config, iftype, ifname, vif=None, vifs=None, vifc=None):
+ """Delete unexpected policy on interfaces in cases when
+ policy does not exist but inreface has a policy configuration
+ Example T5941:
+ set interfaces bonding bond0 vif 995 policy
+ """
+ if_path = ['interfaces', iftype, ifname]
+
+ if vif:
+ if_path += ['vif', vif]
+ elif vifs:
+ if_path += ['vif-s', vifs]
+ if vifc:
+ if_path += ['vif-c', vifc]
+
+ if not config.exists(if_path + ['policy']):
+ return
+
+ config.delete(if_path + ['policy'])
+
+
if not config.exists(base4) and not config.exists(base6):
+ # Delete orphaned nodes on interfaces T5941
+ for iftype in config.list_nodes(['interfaces']):
+ for ifname in config.list_nodes(['interfaces', iftype]):
+ delete_orphaned_interface_policy(config, iftype, ifname)
+
+ if config.exists(['interfaces', iftype, ifname, 'vif']):
+ for vif in config.list_nodes(['interfaces', iftype, ifname, 'vif']):
+ delete_orphaned_interface_policy(config, iftype, ifname, vif=vif)
+
+ if config.exists(['interfaces', iftype, ifname, 'vif-s']):
+ for vifs in config.list_nodes(['interfaces', iftype, ifname, 'vif-s']):
+ delete_orphaned_interface_policy(config, iftype, ifname, vifs=vifs)
+
+ if config.exists(['interfaces', iftype, ifname, 'vif-s', vifs, 'vif-c']):
+ for vifc in config.list_nodes(['interfaces', iftype, ifname, 'vif-s', vifs, 'vif-c']):
+ delete_orphaned_interface_policy(config, iftype, ifname, vifs=vifs, vifc=vifc)
+
+ try:
+ with open(file_name, 'w') as f:
+ f.write(config.to_string())
+ except OSError as e:
+ print("Failed to save the modified config: {}".format(e))
+ exit(1)
+
# Nothing to do
exit(0)
diff --git a/src/migration-scripts/qos/1-to-2 b/src/migration-scripts/qos/1-to-2
index cca32d06e..666811e5a 100755
--- a/src/migration-scripts/qos/1-to-2
+++ b/src/migration-scripts/qos/1-to-2
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2022 VyOS maintainers and contributors
+# Copyright (C) 2022-2024 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -40,7 +40,53 @@ with open(file_name, 'r') as f:
base = ['traffic-policy']
config = ConfigTree(config_file)
+
+def delete_orphaned_interface_policy(config, iftype, ifname, vif=None, vifs=None, vifc=None):
+ """Delete unexpected traffic-policy on interfaces in cases when
+ policy does not exist but inreface has a policy configuration
+ Example T5941:
+ set interfaces bonding bond0 vif 995 traffic-policy
+ """
+ if_path = ['interfaces', iftype, ifname]
+
+ if vif:
+ if_path += ['vif', vif]
+ elif vifs:
+ if_path += ['vif-s', vifs]
+ if vifc:
+ if_path += ['vif-c', vifc]
+
+ if not config.exists(if_path + ['traffic-policy']):
+ return
+
+ config.delete(if_path + ['traffic-policy'])
+
+
if not config.exists(base):
+ # Delete orphaned nodes on interfaces T5941
+ for iftype in config.list_nodes(['interfaces']):
+ for ifname in config.list_nodes(['interfaces', iftype]):
+ delete_orphaned_interface_policy(config, iftype, ifname)
+
+ if config.exists(['interfaces', iftype, ifname, 'vif']):
+ for vif in config.list_nodes(['interfaces', iftype, ifname, 'vif']):
+ delete_orphaned_interface_policy(config, iftype, ifname, vif=vif)
+
+ if config.exists(['interfaces', iftype, ifname, 'vif-s']):
+ for vifs in config.list_nodes(['interfaces', iftype, ifname, 'vif-s']):
+ delete_orphaned_interface_policy(config, iftype, ifname, vifs=vifs)
+
+ if config.exists(['interfaces', iftype, ifname, 'vif-s', vifs, 'vif-c']):
+ for vifc in config.list_nodes(['interfaces', iftype, ifname, 'vif-s', vifs, 'vif-c']):
+ delete_orphaned_interface_policy(config, iftype, ifname, vifs=vifs, vifc=vifc)
+
+ try:
+ with open(file_name, 'w') as f:
+ f.write(config.to_string())
+ except OSError as e:
+ print("Failed to save the modified config: {}".format(e))
+ exit(1)
+
# Nothing to do
exit(0)