]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: wait for previous address removal before configuring static addresses 16697/head
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 8 Aug 2020 03:36:18 +0000 (12:36 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 8 Aug 2020 03:41:03 +0000 (12:41 +0900)
Fixes #16696.

src/network/networkd-link.c
src/network/networkd-link.h

index 7bfdb4f84e21ce7a4de72ffbc052980e21fe48b6..c3bc3415a8bde40a54590b819a949543b7b07082 100644 (file)
@@ -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)) {
index 7f99c0f47b2ac4932fbedf4a262da3c684f4b609..ab5c3fd26a09d89482b0d10b2cfd237a4abe0699 100644 (file)
@@ -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;