diff --git a/src/networkd.c b/src/networkd.c index 982781e0d..23798376c 100644 --- a/src/networkd.c +++ b/src/networkd.c @@ -1493,12 +1493,16 @@ _netplan_networkd_write_wait_online(const NetplanState* np_state, const char* ro */ if (!(def->optional || def->activation_mode)) { // Check if we have any IP configuration + // bond and bridge members will never ask for link-local addresses (see above) struct address_iter* addr_iter = _netplan_netdef_new_address_iter(def); - gboolean any_ips = _netplan_address_iter_next(addr_iter) != NULL + gboolean routable = _netplan_address_iter_next(addr_iter) != NULL || netplan_netdef_get_dhcp4(def) - || netplan_netdef_get_dhcp6(def) - || netplan_netdef_get_link_local_ipv4(def) - || netplan_netdef_get_link_local_ipv6(def); + || netplan_netdef_get_dhcp6(def); + gboolean degraded = ( netplan_netdef_get_link_local_ipv4(def) + && !(netplan_netdef_get_bond_link(def) || netplan_netdef_get_bridge_link(def))) + || ( netplan_netdef_get_link_local_ipv6(def) + && !(netplan_netdef_get_bond_link(def) || netplan_netdef_get_bridge_link(def))); + gboolean any_ips = routable || degraded; _netplan_address_iter_free(addr_iter); // no matching => single physical interface, ignoring non-existing interfaces diff --git a/tests/generator/test_args.py b/tests/generator/test_args.py index b48291a36..291d164fa 100644 --- a/tests/generator/test_args.py +++ b/tests/generator/test_args.py @@ -134,9 +134,20 @@ def test_systemd_generator(self): optional: true lo: addresses: ["127.0.0.1/8", "::1/128"] + vlans: + eth99.42: + link: eth99 + id: 42 + link-local: [ipv4, ipv6] # this is ignored for bridge-members + eth99.43: + link: eth99 + id: 43 + link-local: [] + addresses: [10.0.0.2/24] bridges: br0: - dhcp4: true''') + dhcp4: true + interfaces: [eth99.42, eth99.43]''') outdir = os.path.join(self.workdir.name, 'out') os.mkdir(outdir) @@ -167,12 +178,13 @@ def test_systemd_generator(self): override = os.path.join(service_dir, 'systemd-networkd-wait-online.service.d', '10-netplan.conf') self.assertTrue(os.path.isfile(override)) with open(override, 'r') as f: + # eth99 does not exist on the system, so will not be listed self.assertEqual(f.read(), '''[Unit] ConditionPathIsSymbolicLink=/run/systemd/generator/network-online.target.wants/systemd-networkd-wait-online.service [Service] ExecStart= -ExecStart=/lib/systemd/systemd-networkd-wait-online -i br0:degraded -i lo:carrier\n''') # eth99 does not exist on the system +ExecStart=/lib/systemd/systemd-networkd-wait-online -i eth99.43:degraded -i br0:degraded -i lo:carrier -i eth99.42:carrier\n''') # should be a no-op the second time while the stamp exists out = subprocess.check_output([generator, '--root-dir', self.workdir.name, outdir, outdir, outdir],