diff --git a/src/network/networkd-link-bus.c b/src/network/networkd-link-bus.c index af36b645f9..58d487570a 100644 --- a/src/network/networkd-link-bus.c +++ b/src/network/networkd-link-bus.c @@ -111,8 +111,7 @@ int bus_link_method_set_ntp_servers(sd_bus_message *message, void *userdata, sd_ strv_free_and_replace(l->ntp, ntp); - link_dirty(l); - r = link_save_and_clean(l); + r = link_save_and_clean_full(l, /* also_save_manager = */ true); if (r < 0) return r; @@ -153,8 +152,7 @@ static int bus_link_method_set_dns_servers_internal(sd_bus_message *message, voi free_and_replace(l->dns, dns); l->n_dns = n; - link_dirty(l); - r = link_save_and_clean(l); + r = link_save_and_clean_full(l, /* also_save_manager = */ true); if (r < 0) return r; @@ -247,8 +245,7 @@ int bus_link_method_set_domains(sd_bus_message *message, void *userdata, sd_bus_ l->search_domains = TAKE_PTR(search_domains); l->route_domains = TAKE_PTR(route_domains); - link_dirty(l); - r = link_save_and_clean(l); + r = link_save_and_clean_full(l, /* also_save_manager = */ true); if (r < 0) return r; @@ -281,8 +278,7 @@ int bus_link_method_set_default_route(sd_bus_message *message, void *userdata, s if (l->dns_default_route != b) { l->dns_default_route = b; - link_dirty(l); - r = link_save_and_clean(l); + r = link_save_and_clean_full(l, /* also_save_manager = */ true); if (r < 0) return r; } @@ -326,8 +322,7 @@ int bus_link_method_set_llmnr(sd_bus_message *message, void *userdata, sd_bus_er if (l->llmnr != mode) { l->llmnr = mode; - link_dirty(l); - r = link_save_and_clean(l); + r = link_save_and_clean_full(l, /* also_save_manager = */ true); if (r < 0) return r; } @@ -371,8 +366,7 @@ int bus_link_method_set_mdns(sd_bus_message *message, void *userdata, sd_bus_err if (l->mdns != mode) { l->mdns = mode; - link_dirty(l); - r = link_save_and_clean(l); + r = link_save_and_clean_full(l, /* also_save_manager = */ true); if (r < 0) return r; } @@ -416,8 +410,7 @@ int bus_link_method_set_dns_over_tls(sd_bus_message *message, void *userdata, sd if (l->dns_over_tls_mode != mode) { l->dns_over_tls_mode = mode; - link_dirty(l); - r = link_save_and_clean(l); + r = link_save_and_clean_full(l, /* also_save_manager = */ true); if (r < 0) return r; } @@ -461,8 +454,7 @@ int bus_link_method_set_dnssec(sd_bus_message *message, void *userdata, sd_bus_e if (l->dnssec_mode != mode) { l->dnssec_mode = mode; - link_dirty(l); - r = link_save_and_clean(l); + r = link_save_and_clean_full(l, /* also_save_manager = */ true); if (r < 0) return r; } @@ -516,8 +508,7 @@ int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, v set_free_free(l->dnssec_negative_trust_anchors); l->dnssec_negative_trust_anchors = TAKE_PTR(ns); - link_dirty(l); - r = link_save_and_clean(l); + r = link_save_and_clean_full(l, /* also_save_manager = */ true); if (r < 0) return r; @@ -545,8 +536,7 @@ int bus_link_method_revert_ntp(sd_bus_message *message, void *userdata, sd_bus_e link_ntp_settings_clear(l); - link_dirty(l); - r = link_save_and_clean(l); + r = link_save_and_clean_full(l, /* also_save_manager = */ true); if (r < 0) return r; @@ -574,8 +564,7 @@ int bus_link_method_revert_dns(sd_bus_message *message, void *userdata, sd_bus_e link_dns_settings_clear(l); - link_dirty(l); - r = link_save_and_clean(l); + r = link_save_and_clean_full(l, /* also_save_manager = */ true); if (r < 0) return r; @@ -654,7 +643,7 @@ int bus_link_method_reconfigure(sd_bus_message *message, void *userdata, sd_bus_ return r; if (r > 0) { link_set_state(l, LINK_STATE_INITIALIZED); - r = link_save_and_clean(l); + r = link_save_and_clean_full(l, /* also_save_manager = */ true); if (r < 0) return r; } diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index f597eb358b..e02d0992b4 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -692,7 +692,7 @@ int manager_start(Manager *m) { log_warning_errno(r, "Failed to update state file %s, ignoring: %m", m->state_file); HASHMAP_FOREACH(link, m->links_by_index) { - r = link_save(link); + r = link_save_and_clean(link); if (r < 0) log_link_warning_errno(link, r, "Failed to update link state file %s, ignoring: %m", link->state_file); } diff --git a/src/network/networkd-state-file.c b/src/network/networkd-state-file.c index 03146c62c7..3a95ba8d8b 100644 --- a/src/network/networkd-state-file.c +++ b/src/network/networkd-state-file.c @@ -567,7 +567,7 @@ static void link_save_domains(Link *link, FILE *f, OrderedSet *static_domains, D } } -int link_save(Link *link) { +static int link_save(Link *link) { const char *admin_state, *oper_state, *carrier_state, *address_state, *ipv4_address_state, *ipv6_address_state, *captive_portal; _cleanup_(unlink_and_freep) char *temp_path = NULL; @@ -845,13 +845,19 @@ void link_clean(Link *link) { link_unref(set_remove(link->manager->dirty_links, link)); } -int link_save_and_clean(Link *link) { - int r; +int link_save_and_clean_full(Link *link, bool also_save_manager) { + int r, k = 0; + + assert(link); + assert(link->manager); + + if (also_save_manager) + k = manager_save(link->manager); r = link_save(link); if (r < 0) return r; link_clean(link); - return 0; + return k; } diff --git a/src/network/networkd-state-file.h b/src/network/networkd-state-file.h index 44a109fdfd..684f0d154e 100644 --- a/src/network/networkd-state-file.h +++ b/src/network/networkd-state-file.h @@ -6,7 +6,9 @@ typedef struct Manager Manager; void link_dirty(Link *link); void link_clean(Link *link); -int link_save(Link *link); -int link_save_and_clean(Link *link); +int link_save_and_clean_full(Link *link, bool also_save_manager); +static inline int link_save_and_clean(Link *link) { + return link_save_and_clean_full(link, false); +} int manager_save(Manager *m); diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 122f9e875d..58c289748d 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -5122,6 +5122,15 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): ra_mode='ra-stateless') self.wait_online(['veth99:routable', 'veth-peer:routable']) + # DHCPv6 REPLY for INFORMATION-REQUEST may be received after the link entered configured state. + # Let's wait for the expected DNS server being listed in the state file. + for _ in range(100): + output = read_link_state_file('veth99') + print(output) + if 'DNS=2600::ee' in output: + break + time.sleep(.2) + # Check link state file print('## link state file') output = read_link_state_file('veth99') @@ -5169,6 +5178,9 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): print(output) self.assertRegex(output, 'token :: dev veth99') + # Make manager and link state file updated + check_output(*resolvectl_cmd, 'revert', 'veth99', env=env) + # Check link state file print('## link state file') output = read_link_state_file('veth99') @@ -5215,6 +5227,9 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): print(output) self.assertRegex(output, 'via fe80::1034:56ff:fe78:9abd') + # Make manager and link state file updated + check_output(*resolvectl_cmd, 'revert', 'veth99', env=env) + # Check link state file print('## link state file') output = read_link_state_file('veth99')