summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2020-08-08 12:36:18 +0900
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2020-08-19 11:01:50 +0200
commit7875daf52bbba49f6537222cf11f30dac66bcc6c (patch)
tree4518d6cca06310fe8a0bf8836902f9a86bb429c3
parent120064b4a1a34952cc058e30e67bd3ec848f93c0 (diff)
downloadsystemd-7875daf52bbba49f6537222cf11f30dac66bcc6c.tar.gz
network: wait for previous address removal before configuring static addresses
Fixes #16696. (cherry picked from commit 9b966cee435fecfdee79f3e0aff0dec0a4e68f14)
-rw-r--r--src/network/networkd-link.c40
-rw-r--r--src/network/networkd-link.h2
2 files changed, 41 insertions, 1 deletions
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 0057d184f7..1597f1ed56 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1365,7 +1365,14 @@ static int link_request_set_addresses(Link *link) {
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 @@ static int link_drop_foreign_config(Link *link) {
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,10 +2932,12 @@ static int link_drop_config(Link *link) {
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) {
if (address_equal(address, pool_address)) {
diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h
index 7f99c0f47b..ab5c3fd26a 100644
--- a/src/network/networkd-link.h
+++ b/src/network/networkd-link.h
@@ -75,6 +75,7 @@ typedef struct Link {
LinkAddressState address_state;
unsigned address_messages;
+ unsigned address_remove_messages;
unsigned address_label_messages;
unsigned neighbor_messages;
unsigned route_messages;
@@ -111,6 +112,7 @@ typedef struct Link {
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;