From bc45d9c9592d3fcd24894199be1902704f48d62c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 5 Feb 2025 09:14:51 +0900 Subject: [PATCH 1/2] network/routing-policy-rule: fix compare func Previously, when comparing an existing and requested routing policy rules, `all` flag was unset, thus the from and to addresses in the two rules were not compared. Hence, a new request with from and/or to addresses might be considered as it already exists even the addresses of existing one were different from the newly requested one. All existing rules have valid family, i.e. AF_INET or AF_INET6. And, all requesting rules with from and/or to addresses also have a valid family. Hence, even `all` flag is unset, the addresses can be and must be compared in that case. Fixes a regression caused by fc58350aa464cd2414b6fe9fec089412120c7d52 (v257). Fixes #35874. --- src/network/networkd-routing-policy-rule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index 87dcaa4fc4..0c95b7d34f 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -318,7 +318,7 @@ static int routing_policy_rule_compare_func_full(const RoutingPolicyRule *a, con if (r != 0) return r; - if (all) { + if (a->family == b->family && a->family != AF_UNSPEC) { r = memcmp(&a->from.address, &b->from.address, FAMILY_ADDRESS_SIZE(a->family)); if (r != 0) return r; From a10172b0355f3ff5c301010d81aea1f2fba986e7 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 5 Feb 2025 09:40:31 +0900 Subject: [PATCH 2/2] test-network: add test case for issue #35874 --- .../conf/25-routing-policy-rule-test1.network | 18 ++++++++++++++++++ test/test-network/systemd-networkd-tests.py | 16 ++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/test/test-network/conf/25-routing-policy-rule-test1.network b/test/test-network/conf/25-routing-policy-rule-test1.network index 2cec4334fd..6e67f3f105 100644 --- a/test/test-network/conf/25-routing-policy-rule-test1.network +++ b/test/test-network/conf/25-routing-policy-rule-test1.network @@ -47,3 +47,21 @@ IncomingInterface=test1 From=10.1.0.0/16 Priority=104 Table=12 + +# The four routing policy rules below intentionally have the same config +# excepts for their To= addresses. See issue #35874. +[RoutingPolicyRule] +To=192.0.2.0/26 +Table=1001 + +[RoutingPolicyRule] +To=192.0.2.64/26 +Table=1001 + +[RoutingPolicyRule] +To=192.0.2.128/26 +Table=1001 + +[RoutingPolicyRule] +To=192.0.2.192/26 +Table=1001 diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index c865fbdbe3..53de32c4b1 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -3847,6 +3847,22 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): print(output) self.assertIn('104: from 10.1.0.0/16 iif test1 lookup 12 nop', output) + output = check_output('ip rule list to 192.0.2.0/26') + print(output) + self.assertIn('to 192.0.2.0/26 lookup 1001', output) + + output = check_output('ip rule list to 192.0.2.64/26') + print(output) + self.assertIn('to 192.0.2.64/26 lookup 1001', output) + + output = check_output('ip rule list to 192.0.2.128/26') + print(output) + self.assertIn('to 192.0.2.128/26 lookup 1001', output) + + output = check_output('ip rule list to 192.0.2.192/26') + print(output) + self.assertIn('to 192.0.2.192/26 lookup 1001', output) + def check_routing_policy_rule_dummy98(self): print('### Checking routing policy rules requested by dummy98')