From 559dd60a3bdb5866eb81c332d594a8b91529c4a4 Mon Sep 17 00:00:00 2001 From: l0crian1 Date: Fri, 31 Oct 2025 18:12:46 -0400 Subject: wlb: T7977: Fix weight calculation for multiple interfaces - Fixed issue in T7977 - Added smoketest for 3 or more interfaces in rule - Added wait_for function to utils/misc.py --- python/vyos/utils/misc.py | 23 +++++++++++++++++++++++ python/vyos/wanloadbalance.py | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) (limited to 'python') diff --git a/python/vyos/utils/misc.py b/python/vyos/utils/misc.py index c7f7e7343..b8b25b860 100644 --- a/python/vyos/utils/misc.py +++ b/python/vyos/utils/misc.py @@ -12,6 +12,9 @@ # # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see . +import time + +from typing import Callable, Any def begin(*args): """ @@ -64,3 +67,23 @@ def install_into_config(conf, config_paths, override_prompt=True): if count > 0: print(f'{count} value(s) installed. Use "compare" to see the pending changes, and "commit" to apply.') + +def wait_for(func: Callable[[], Any], interval: float = 1.0, timeout: float = 5.0) -> bool: + """ + Repeatedly calls `func()` until it returns True or the timeout expires. + + Args: + func: A function with no arguments that returns a truthy value when ready. + interval: Seconds to wait between calls (default: 1.0). + timeout: Maximum time to wait in seconds (default: 5.0). + + Returns: + True if the function returned True within the timeout, otherwise False. + """ + start = time.monotonic() + while True: + if func(): + return True + if (time.monotonic() - start) >= timeout: + return False + time.sleep(interval) diff --git a/python/vyos/wanloadbalance.py b/python/vyos/wanloadbalance.py index afe005731..05ae6b536 100644 --- a/python/vyos/wanloadbalance.py +++ b/python/vyos/wanloadbalance.py @@ -154,7 +154,7 @@ def wlb_weight_interfaces(rule_conf, health_state): for ifname, weight in sorted(interfaces, key=lambda i: i[1]): # build weight ranges end = start + weight - 1 out.append((ifname, f'{start}-{end}' if end > start else start)) - start = weight + start += weight return out, total_weight -- cgit v1.2.3 From 354517677fb9eceb82e478f33a7c481c469b248a Mon Sep 17 00:00:00 2001 From: l0crian1 Date: Tue, 4 Nov 2025 11:25:42 -0500 Subject: wlb: T7977: Updated smoketest to validate nft vmap weight buckets --- python/vyos/utils/misc.py | 10 ++++-- smoketest/scripts/cli/test_load-balancing_wan.py | 41 +++++++++++------------- 2 files changed, 27 insertions(+), 24 deletions(-) (limited to 'python') diff --git a/python/vyos/utils/misc.py b/python/vyos/utils/misc.py index b8b25b860..20e3de746 100644 --- a/python/vyos/utils/misc.py +++ b/python/vyos/utils/misc.py @@ -68,7 +68,13 @@ def install_into_config(conf, config_paths, override_prompt=True): if count > 0: print(f'{count} value(s) installed. Use "compare" to see the pending changes, and "commit" to apply.') -def wait_for(func: Callable[[], Any], interval: float = 1.0, timeout: float = 5.0) -> bool: +def wait_for( + func: Callable[..., Any], + *args, + interval: float = 1.0, + timeout: float = 5.0, + **kwargs +) -> bool: """ Repeatedly calls `func()` until it returns True or the timeout expires. @@ -82,7 +88,7 @@ def wait_for(func: Callable[[], Any], interval: float = 1.0, timeout: float = 5. """ start = time.monotonic() while True: - if func(): + if func(*args, **kwargs): return True if (time.monotonic() - start) >= timeout: return False diff --git a/smoketest/scripts/cli/test_load-balancing_wan.py b/smoketest/scripts/cli/test_load-balancing_wan.py index 255203e91..3b956a12e 100755 --- a/smoketest/scripts/cli/test_load-balancing_wan.py +++ b/smoketest/scripts/cli/test_load-balancing_wan.py @@ -442,20 +442,17 @@ echo "$ifname - $state" > {hook_output_path} self.cli_set(['interfaces', 'ethernet', 'eth0', 'vif', '201', 'address', '203.0.113.14/30']) self.cli_set(['interfaces', 'ethernet', 'eth0', 'vif', '202', 'address', '203.0.113.18/30']) self.cli_set(['interfaces', 'ethernet', 'eth0', 'vif', '203', 'address', '203.0.113.22/30']) + self.cli_set(['interfaces', 'ethernet', 'eth0', 'vif', '204', 'address', '203.0.113.26/30']) + self.cli_set(['interfaces', 'ethernet', 'eth0', 'vif', '205', 'address', '203.0.113.30/30']) + self.cli_set(['interfaces', 'ethernet', lan_iface, 'vif', '100', 'address', '198.51.100.2/30']) self.cli_set(['interfaces', 'ethernet', lan_iface, 'vif', '200', 'address', '198.51.100.6/30']) # Health checks for equal weight test self.cli_set(base_path + ['wan', 'interface-health', 'eth0.101', 'nexthop', '203.0.113.2']) - self.cli_set(base_path + ['wan', 'interface-health', 'eth0.101', 'success-count', '1']) - self.cli_set(base_path + ['wan', 'interface-health', 'eth0.101', 'failure-count', '1']) self.cli_set(base_path + ['wan', 'interface-health', 'eth0.102', 'nexthop', '203.0.113.6']) - self.cli_set(base_path + ['wan', 'interface-health', 'eth0.102', 'success-count', '1']) - self.cli_set(base_path + ['wan', 'interface-health', 'eth0.102', 'failure-count', '1']) self.cli_set(base_path + ['wan', 'interface-health', 'eth0.103', 'nexthop', '203.0.113.10']) - self.cli_set(base_path + ['wan', 'interface-health', 'eth0.103', 'success-count', '1']) - self.cli_set(base_path + ['wan', 'interface-health', 'eth0.103', 'failure-count', '1']) self.cli_set(base_path + ['wan', 'rule', '10', 'inbound-interface', f'{lan_iface}.100']) self.cli_set(base_path + ['wan', 'rule', '10', 'interface', 'eth0.101']) self.cli_set(base_path + ['wan', 'rule', '10', 'interface', 'eth0.102']) @@ -463,18 +460,16 @@ echo "$ifname - $state" > {hook_output_path} # Health checks for unequal weight test self.cli_set(base_path + ['wan', 'interface-health', 'eth0.201', 'nexthop', '203.0.113.14']) - self.cli_set(base_path + ['wan', 'interface-health', 'eth0.201', 'success-count', '1']) - self.cli_set(base_path + ['wan', 'interface-health', 'eth0.201', 'failure-count', '1']) self.cli_set(base_path + ['wan', 'interface-health', 'eth0.202', 'nexthop', '203.0.113.18']) - self.cli_set(base_path + ['wan', 'interface-health', 'eth0.202', 'success-count', '1']) - self.cli_set(base_path + ['wan', 'interface-health', 'eth0.202', 'failure-count', '1']) self.cli_set(base_path + ['wan', 'interface-health', 'eth0.203', 'nexthop', '203.0.113.22']) - self.cli_set(base_path + ['wan', 'interface-health', 'eth0.203', 'success-count', '1']) - self.cli_set(base_path + ['wan', 'interface-health', 'eth0.203', 'failure-count', '1']) + self.cli_set(base_path + ['wan', 'interface-health', 'eth0.204', 'nexthop', '203.0.113.26']) + self.cli_set(base_path + ['wan', 'interface-health', 'eth0.205', 'nexthop', '203.0.113.30']) self.cli_set(base_path + ['wan', 'rule', '20', 'inbound-interface', f'{lan_iface}.200']) - self.cli_set(base_path + ['wan', 'rule', '20', 'interface', 'eth0.201']) - self.cli_set(base_path + ['wan', 'rule', '20', 'interface', 'eth0.202', 'weight', '2']) - self.cli_set(base_path + ['wan', 'rule', '20', 'interface', 'eth0.203', 'weight', '3']) + self.cli_set(base_path + ['wan', 'rule', '20', 'interface', 'eth0.201', 'weight', '2']) + self.cli_set(base_path + ['wan', 'rule', '20', 'interface', 'eth0.202', 'weight', '4']) + self.cli_set(base_path + ['wan', 'rule', '20', 'interface', 'eth0.203', 'weight', '4']) + self.cli_set(base_path + ['wan', 'rule', '20', 'interface', 'eth0.204', 'weight', '7']) + self.cli_set(base_path + ['wan', 'rule', '20', 'interface', 'eth0.205', 'weight', '4']) # commit changes self.cli_commit() @@ -490,17 +485,19 @@ echo "$ifname - $state" > {hook_output_path} # check total count of 'jump' across all matching lines total_jumps = sum(l.count('jump') for l in lines) - return total_jumps == 6 + return total_jumps == 8 wait_for(check_wlb_status) nftables_search = [ - ['jump wlb_mangle_isp_eth0.101'], - ['jump wlb_mangle_isp_eth0.102'], - ['jump wlb_mangle_isp_eth0.103'], - ['jump wlb_mangle_isp_eth0.201'], - ['jump wlb_mangle_isp_eth0.202'], - ['jump wlb_mangle_isp_eth0.203'], + ['0 : jump wlb_mangle_isp_eth0.101', + '1 : jump wlb_mangle_isp_eth0.102', + '2 : jump wlb_mangle_isp_eth0.103'], + ['0-1 : jump wlb_mangle_isp_eth0.201', + '2-5 : jump wlb_mangle_isp_eth0.202', + '6-9 : jump wlb_mangle_isp_eth0.203', + '10-13 : jump wlb_mangle_isp_eth0.205', + '14-20 : jump wlb_mangle_isp_eth0.204'], ] self.verify_nftables_chain(nftables_search, 'ip vyos_wanloadbalance', 'wlb_mangle_prerouting') -- cgit v1.2.3