diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 5c87a6c9c76..57a9ceb2298 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -1158,6 +1158,9 @@ static bool address_is_ready_to_configure(Link *link, const Address *address) { if (!link_is_ready_to_configure(link, false)) return false; + if (address_is_removing(address)) + return false; + if (!ipv4acd_bound(address)) return false; diff --git a/src/network/networkd-util.h b/src/network/networkd-util.h index f75fb1f8685..8ffe4b5b5be 100644 --- a/src/network/networkd-util.h +++ b/src/network/networkd-util.h @@ -70,7 +70,7 @@ int network_config_state_to_string_alloc(NetworkConfigState s, char **ret); \ t->state = (t->state & ~mask) | (value & mask); \ } \ - static inline bool name##_exists(type *t) { \ + static inline bool name##_exists(const type *t) { \ assert(t); \ \ if ((t->state & (NETWORK_CONFIG_STATE_CONFIGURING | \ @@ -90,7 +90,7 @@ int network_config_state_to_string_alloc(NetworkConfigState s, char **ret); NETWORK_CONFIG_STATE_REQUESTING, \ 0); \ } \ - static inline bool name##_is_requesting(type *t) { \ + static inline bool name##_is_requesting(const type *t) { \ assert(t); \ return FLAGS_SET(t->state, NETWORK_CONFIG_STATE_REQUESTING); \ } \ @@ -115,7 +115,7 @@ int network_config_state_to_string_alloc(NetworkConfigState s, char **ret); static inline void name##_unmark(type *t) { \ name##_update_state(t, NETWORK_CONFIG_STATE_MARKED, 0); \ } \ - static inline bool name##_is_marked(type *t) { \ + static inline bool name##_is_marked(const type *t) { \ assert(t); \ return FLAGS_SET(t->state, NETWORK_CONFIG_STATE_MARKED); \ } \ @@ -125,6 +125,10 @@ int network_config_state_to_string_alloc(NetworkConfigState s, char **ret); NETWORK_CONFIG_STATE_REMOVING, \ NETWORK_CONFIG_STATE_REMOVING); \ } \ + static inline bool name##_is_removing(const type *t) { \ + assert(t); \ + return FLAGS_SET(t->state, NETWORK_CONFIG_STATE_REMOVING); \ + } \ static inline void name##_enter_removed(type *t) { \ name##_update_state(t, \ NETWORK_CONFIG_STATE_CONFIGURED | \ diff --git a/test/test-network/conf/25-route-preferred-source.network b/test/test-network/conf/25-route-preferred-source.network new file mode 100644 index 00000000000..5a55460349b --- /dev/null +++ b/test/test-network/conf/25-route-preferred-source.network @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[Match] +Name=dummy98 + +[Network] +Address=2001:1234:56:8f63::1/64 +IPv6AcceptRA=no + +[Route] +Destination=abcd::/16 +Gateway=2001:1234:56:8f63::1:1 +PreferredSource=2001:1234:56:8f63::1 diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 9f55456fa4b..902614712e8 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -2973,9 +2973,22 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): output = check_output('ip -6 route list dev bond199') print(output) - self.assertRegex(output, 'abcd::/16') - self.assertRegex(output, 'src') - self.assertRegex(output, '2001:1234:56:8f63::2') + self.assertIn('abcd::/16 via 2001:1234:56:8f63::1:1 proto static src 2001:1234:56:8f63::2', output) + + def test_route_preferred_source_with_existing_address(self): + # See issue #28009. + copy_network_unit('25-route-preferred-source.network', '12-dummy.netdev') + start_networkd() + + for i in range(3): + if i != 0: + networkctl_reconfigure('dummy98') + + self.wait_online(['dummy98:routable']) + + output = check_output('ip -6 route list dev dummy98') + print(output) + self.assertIn('abcd::/16 via 2001:1234:56:8f63::1:1 proto static src 2001:1234:56:8f63::1', output) def test_ip_link_mac_address(self): copy_network_unit('25-address-link-section.network', '12-dummy.netdev')