diff -ur systemd-246.old/src/network/networkd-address.c systemd-246/src/network/networkd-address.c --- systemd-246.old/src/network/networkd-address.c 2020-07-30 22:02:36.000000000 +0300 +++ systemd-246/src/network/networkd-address.c 2020-11-01 18:35:26.198135829 +0200 @@ -487,7 +487,7 @@ r = sd_netlink_message_get_errno(m); if (r < 0 && r != -EADDRNOTAVAIL) log_link_message_warning_errno(link, m, r, "Could not drop address"); - else + else if (r >= 0) (void) manager_rtnl_process_address(rtnl, m, link->manager); return 1; diff -ur systemd-246.old/src/network/networkd-link.c systemd-246/src/network/networkd-link.c --- systemd-246.old/src/network/networkd-link.c 2020-07-30 22:02:36.000000000 +0300 +++ systemd-246/src/network/networkd-link.c 2020-11-01 18:40:10.079443390 +0200 @@ -1365,7 +1365,14 @@ assert(link->network); assert(link->state != _LINK_STATE_INVALID); + if (link->address_remove_messages != 0) { + log_link_debug(link, "Removing old addresses, new addresses will be configured later."); + link->request_static_addresses = true; + return 0; + } + /* Reset all *_configured flags we are configuring. */ + link->request_static_addresses = false; link->addresses_configured = false; link->addresses_ready = false; link->neighbors_configured = false; @@ -2884,6 +2891,35 @@ return 0; } +static int remove_static_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(m); + assert(link); + assert(link->ifname); + assert(link->address_remove_messages > 0); + + link->address_remove_messages--; + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EADDRNOTAVAIL) + log_link_message_warning_errno(link, m, r, "Could not drop address"); + else if (r >= 0) + (void) manager_rtnl_process_address(rtnl, m, link->manager); + + if (link->address_remove_messages == 0 && link->request_static_addresses) { + link_set_state(link, LINK_STATE_CONFIGURING); + r = link_request_set_addresses(link); + if (r < 0) + link_enter_failed(link); + } + + return 1; +} + static int link_drop_config(Link *link) { Address *address, *pool_address; Neighbor *neighbor; @@ -2896,18 +2932,19 @@ if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1 && link_ipv6ll_enabled(link)) continue; - r = address_remove(address, link, NULL); + r = address_remove(address, link, remove_static_address_handler); if (r < 0) return r; + link->address_remove_messages++; + /* If this address came from an address pool, clean up the pool */ - LIST_FOREACH(addresses, pool_address, link->pool_addresses) { + LIST_FOREACH(addresses, pool_address, link->pool_addresses) if (address_equal(address, pool_address)) { LIST_REMOVE(addresses, link->pool_addresses, pool_address); address_free(pool_address); break; } - } } SET_FOREACH(neighbor, link->neighbors, i) { diff -ur systemd-246.old/src/network/networkd-link.h systemd-246/src/network/networkd-link.h --- systemd-246.old/src/network/networkd-link.h 2020-07-30 22:02:36.000000000 +0300 +++ systemd-246/src/network/networkd-link.h 2020-11-01 18:41:14.007511684 +0200 @@ -75,6 +75,7 @@ LinkAddressState address_state; unsigned address_messages; + unsigned address_remove_messages; unsigned address_label_messages; unsigned neighbor_messages; unsigned route_messages; @@ -111,6 +112,7 @@ sd_ipv4ll *ipv4ll; bool ipv4ll_address_configured:1; + bool request_static_addresses:1; bool addresses_configured:1; bool addresses_ready:1; bool neighbors_configured:1;