]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: introduce link_request_to_activate()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 28 May 2021 15:31:37 +0000 (00:31 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 7 Jun 2021 21:39:48 +0000 (06:39 +0900)
The request will be processed after all setlink requests are processed.
The function will be used in later commits.

src/network/netdev/netdev.c
src/network/networkd-can.c
src/network/networkd-link.c
src/network/networkd-link.h
src/network/networkd-queue.c
src/network/networkd-queue.h
src/network/networkd-setlink.c
src/network/networkd-setlink.h

index a0b6706aad96989b12d9b6feb8fb013e395461c1..5c1927cdfce8352ad44eef223875e055d80a4b72 100644 (file)
@@ -272,7 +272,7 @@ static int netdev_enslave_ready(NetDev *netdev, Link* link, link_netlink_message
 
         if (link->flags & IFF_UP && netdev->kind == NETDEV_KIND_BOND) {
                 log_netdev_debug(netdev, "Link '%s' was up when attempting to enslave it. Bringing link down.", link->ifname);
-                r = link_down(link, NULL);
+                r = link_down(link);
                 if (r < 0)
                         return log_netdev_error_errno(netdev, r, "Could not bring link down: %m");
         }
index 787cfd711e7e2acf4f74932e8aaedb99043a3310..41b946b44d3b9861101d63d79d868bb72033d1ad 100644 (file)
@@ -7,6 +7,7 @@
 #include "networkd-can.h"
 #include "networkd-link.h"
 #include "networkd-manager.h"
+#include "networkd-setlink.h"
 #include "parse-util.h"
 #include "string-util.h"
 
@@ -229,28 +230,6 @@ static int link_set_can(Link *link) {
         return 0;
 }
 
-static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
-        int r;
-
-        assert(link);
-
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
-                return 1;
-
-        r = sd_netlink_message_get_errno(m);
-        if (r < 0) {
-                log_link_message_warning_errno(link, m, r, "Could not bring down interface");
-                link_enter_failed(link);
-                return 1;
-        }
-
-        r = link_set_can(link);
-        if (r < 0)
-                link_enter_failed(link);
-
-        return 1;
-}
-
 int link_configure_can(Link *link) {
         int r;
 
@@ -258,13 +237,13 @@ int link_configure_can(Link *link) {
 
         if (streq_ptr(link->kind, "can")) {
                 /* The CAN interface must be down to configure bitrate, etc... */
-                if ((link->flags & IFF_UP))
-                        r = link_down(link, link_down_handler);
-                else
-                        r = link_set_can(link);
-                if (r < 0)
-                        link_enter_failed(link);
-                return r;
+                if (link->flags & IFF_UP) {
+                        r = link_down(link);
+                        if (r < 0)
+                                return r;
+                }
+
+                return link_set_can(link);
         }
 
         r = link_activate(link);
index 75707757443c2325fd504f24008a2c7ff4f527a4..00bcb5b0bc6a2f55bb090eed857dbb9be1bb3f60 100644 (file)
@@ -159,6 +159,11 @@ bool link_is_ready_to_configure(Link *link, bool allow_unmanaged) {
                 return false;
         */
 
+        /* TODO: enable this check when link_request_to_activate() is used.
+        if (!link->activated)
+                return false;
+        */
+
         return true;
 }
 
@@ -754,97 +759,7 @@ int link_ipv6ll_gained(Link *link, const struct in6_addr *address) {
         return 0;
 }
 
-static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
-        int r;
-
-        assert(link);
-
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
-                return 1;
-
-        r = sd_netlink_message_get_errno(m);
-        if (r < 0)
-                /* we warn but don't fail the link, as it may be brought up later */
-                log_link_message_warning_errno(link, m, r, "Could not bring up interface");
-
-        return 1;
-}
-
-int link_up(Link *link) {
-        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
-        int r;
-
-        assert(link);
-        assert(link->network);
-        assert(link->manager);
-        assert(link->manager->rtnl);
-
-        log_link_debug(link, "Bringing link up");
-
-        r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
-
-        r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not set link flags: %m");
-
-        r = netlink_call_async(link->manager->rtnl, NULL, req, link_up_handler,
-                               link_netlink_destroy_callback, link);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
-
-        link_ref(link);
-
-        return 0;
-}
-
-static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
-        int r;
-
-        assert(link);
-
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
-                return 1;
-
-        r = sd_netlink_message_get_errno(m);
-        if (r < 0)
-                log_link_message_warning_errno(link, m, r, "Could not bring down interface");
-
-        return 1;
-}
-
-int link_down(Link *link, link_netlink_message_handler_t callback) {
-        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
-        int r;
-
-        assert(link);
-        assert(link->manager);
-        assert(link->manager->rtnl);
-
-        log_link_debug(link, "Bringing link down");
-
-        r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
-                                     RTM_SETLINK, link->ifindex);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
-
-        r = sd_rtnl_message_link_set_flags(req, 0, IFF_UP);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not set link flags: %m");
-
-        r = netlink_call_async(link->manager->rtnl, NULL, req,
-                               callback ?: link_down_handler,
-                               link_netlink_destroy_callback, link);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
-
-        link_ref(link);
-
-        return 0;
-}
-
-static int link_handle_bound_to_list(Link *link) {
+int link_handle_bound_to_list(Link *link) {
         bool required_up = false;
         bool link_is_up = false;
         Link *l;
@@ -864,7 +779,7 @@ static int link_handle_bound_to_list(Link *link) {
                 }
 
         if (!required_up && link_is_up)
-                return link_down(link, NULL);
+                return link_down(link);
         if (required_up && !link_is_up)
                 return link_up(link);
 
@@ -1141,7 +1056,7 @@ int link_activate(Link *link) {
                         break;
                 _fallthrough_;
         case ACTIVATION_POLICY_ALWAYS_DOWN:
-                r = link_down(link, NULL);
+                r = link_down(link);
                 if (r < 0)
                         return r;
                 break;
@@ -1945,7 +1860,7 @@ static int link_admin_state_up(Link *link) {
 
         if (link->network->activation_policy == ACTIVATION_POLICY_ALWAYS_DOWN) {
                 log_link_info(link, "ActivationPolicy is \"always-off\", forcing link down");
-                return link_down(link, NULL);
+                return link_down(link);
         }
 
         /* We set the ipv6 mtu after the device mtu, but the kernel resets
index 600b5f5ee129e8a84057cd51ccb1fec8be036602..15a0cdd7d0ad407ada3f75e7ef129dc1a3f3ba57 100644 (file)
@@ -224,9 +224,8 @@ int link_get_master(Link *link, Link **ret);
 
 int link_getlink_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, const char *error_msg);
 int link_call_getlink(Link *link, link_netlink_message_handler_t callback);
-int link_up(Link *link);
-int link_down(Link *link, link_netlink_message_handler_t callback);
 int link_activate(Link *link);
+int link_handle_bound_to_list(Link *link);
 
 int link_enter_join_netdev(Link *link);
 void link_enter_failed(Link *link);
index 3a17a06b2c2d72b7eb3e0c254f26522461759d8d..acda4994f081a5b3b9f3e1647d4dfb2cb4df389d 100644 (file)
@@ -15,6 +15,8 @@
 
 static void request_free_object(RequestType type, void *object) {
         switch(type) {
+        case REQUEST_TYPE_ACTIVATE_LINK:
+                break;
         case REQUEST_TYPE_ADDRESS:
                 address_free(object);
                 break;
@@ -89,6 +91,8 @@ static void request_hash_func(const Request *req, struct siphash *state) {
         siphash24_compress(&req->type, sizeof(req->type), state);
 
         switch(req->type) {
+        case REQUEST_TYPE_ACTIVATE_LINK:
+                break;
         case REQUEST_TYPE_ADDRESS:
                 address_hash_func(req->address, state);
                 break;
@@ -143,6 +147,8 @@ static int request_compare_func(const struct Request *a, const struct Request *b
                 return r;
 
         switch (a->type) {
+        case REQUEST_TYPE_ACTIVATE_LINK:
+                return 0;
         case REQUEST_TYPE_ADDRESS:
                 return address_compare_func(a->address, b->address);
         case REQUEST_TYPE_ADDRESS_LABEL:
@@ -192,7 +198,11 @@ int link_queue_request(
         assert(link);
         assert(link->manager);
         assert(type >= 0 && type < _REQUEST_TYPE_MAX);
-        assert(IN_SET(type, REQUEST_TYPE_DHCP_SERVER, REQUEST_TYPE_SET_LINK) || object);
+        assert(IN_SET(type,
+                      REQUEST_TYPE_ACTIVATE_LINK,
+                      REQUEST_TYPE_DHCP_SERVER,
+                      REQUEST_TYPE_SET_LINK) ||
+               object);
         assert(type == REQUEST_TYPE_DHCP_SERVER || netlink_handler);
 
         req = new(Request, 1);
@@ -247,6 +257,9 @@ int manager_process_requests(sd_event_source *s, void *userdata) {
 
                 ORDERED_SET_FOREACH(req, manager->request_queue) {
                         switch(req->type) {
+                        case REQUEST_TYPE_ACTIVATE_LINK:
+                                r = request_process_activation(req);
+                                break;
                         case REQUEST_TYPE_ADDRESS:
                                 r = request_process_address(req);
                                 break;
index 697fbf3bfd14a70c513ae8c688790e54e7915929..4fb49c48bc02f2304bb1ea72d78e5b482f19cbe1 100644 (file)
@@ -22,6 +22,7 @@ typedef int (*request_after_configure_handler_t)(Request*, void*);
 typedef void (*request_on_free_handler_t)(Request*);
 
 typedef enum RequestType {
+        REQUEST_TYPE_ACTIVATE_LINK,
         REQUEST_TYPE_ADDRESS,
         REQUEST_TYPE_ADDRESS_LABEL,
         REQUEST_TYPE_BRIDGE_FDB,
index 1184fbfb43b77f5772e98c3a6e7a9d55a0d538e2..5abe379b6b8b6089f3e4f5be1f189df04f576153 100644 (file)
@@ -464,7 +464,7 @@ static bool link_is_ready_to_call_set_link(Request *req) {
 
                         if (FLAGS_SET(link->flags, IFF_UP)) {
                                 /* link must be down when joining to bond master. */
-                                r = link_down(link, NULL);
+                                r = link_down(link);
                                 if (r < 0) {
                                         link_enter_failed(link);
                                         return false;
@@ -711,3 +711,158 @@ int link_configure_mtu(Link *link) {
 
         return link_request_to_set_mtu(link, mtu);
 }
+
+static int link_up_or_down_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, bool up, bool check_ready) {
+        int r;
+
+        assert(m);
+        assert(link);
+
+        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+                return 0;
+
+        r = sd_netlink_message_get_errno(m);
+        if (r < 0)
+                log_link_message_warning_errno(link, m, r, up ?
+                                               "Could not bring up interface, ignoring" :
+                                               "Could not bring down interface, ignoring");
+
+        if (check_ready) {
+                link->activated = true;
+                link_check_ready(link);
+        }
+
+        return 0;
+}
+
+static int link_activate_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+        return link_up_or_down_handler_internal(rtnl, m, link, true, true);
+}
+
+static int link_activate_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+        return link_up_or_down_handler_internal(rtnl, m, link, false, true);
+}
+
+static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+        return link_up_or_down_handler_internal(rtnl, m, link, true, false);
+}
+
+static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+        return link_up_or_down_handler_internal(rtnl, m, link, false, false);
+}
+
+static int link_up_or_down(Link *link, bool up, link_netlink_message_handler_t callback) {
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+        int r;
+
+        assert(link);
+        assert(link->manager);
+        assert(link->manager->rtnl);
+        assert(callback);
+
+        log_link_debug(link, "Bringing link %s", up ? "up" : "down");
+
+        r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
+        if (r < 0)
+                return log_link_debug_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
+
+        r = sd_rtnl_message_link_set_flags(req, up ? IFF_UP : 0, IFF_UP);
+        if (r < 0)
+                return log_link_debug_errno(link, r, "Could not set link flags: %m");
+
+        r = netlink_call_async(link->manager->rtnl, NULL, req, callback,
+                               link_netlink_destroy_callback, link);
+        if (r < 0)
+                return log_link_debug_errno(link, r, "Could not send rtnetlink message: %m");
+
+        link_ref(link);
+
+        return 0;
+}
+
+int link_up(Link *link) {
+        return link_up_or_down(link, true, link_up_handler);
+}
+
+int link_down(Link *link) {
+        return link_up_or_down(link, false, link_down_handler);
+}
+
+static bool link_is_ready_to_activate(Link *link) {
+        assert(link);
+
+        if (!IN_SET(link->state, LINK_STATE_INITIALIZED, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
+                return false;
+
+        if (link->set_link_messages > 0)
+                return false;
+
+        return true;
+}
+
+int request_process_activation(Request *req) {
+        Link *link;
+        bool up;
+        int r;
+
+        assert(req);
+        assert(req->link);
+        assert(req->type == REQUEST_TYPE_ACTIVATE_LINK);
+        assert(req->netlink_handler);
+
+        link = req->link;
+        up = PTR_TO_INT(req->userdata);
+
+        if (!link_is_ready_to_activate(link))
+                return 0;
+
+        r = link_up_or_down(link, up, req->netlink_handler);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Failed to bring %s: %m", up ? "up" : "down");
+
+        return 1;
+}
+
+int link_request_to_activate(Link *link) {
+        Request *req;
+        bool up;
+        int r;
+
+        assert(link);
+        assert(link->network);
+
+        switch (link->network->activation_policy) {
+        case ACTIVATION_POLICY_BOUND:
+                /* FIXME: also use request queue to handle the list. */
+                r = link_handle_bound_to_list(link);
+                if (r < 0)
+                        return r;
+                _fallthrough_;
+        case ACTIVATION_POLICY_MANUAL:
+                link->activated = true;
+                link_check_ready(link);
+                return 0;
+        case ACTIVATION_POLICY_UP:
+        case ACTIVATION_POLICY_ALWAYS_UP:
+                up = true;
+                break;
+        case ACTIVATION_POLICY_DOWN:
+        case ACTIVATION_POLICY_ALWAYS_DOWN:
+                up = false;
+                break;
+        default:
+                assert_not_reached("invalid activation policy");
+        }
+
+        link->activated = false;
+
+        r = link_queue_request(link, REQUEST_TYPE_ACTIVATE_LINK, NULL, false, NULL,
+                               up ? link_activate_up_handler : link_activate_down_handler, &req);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Failed to request to activate link: %m");
+
+        req->userdata = INT_TO_PTR(up);
+
+        log_link_debug(link, "Requested to activate link");
+        return 0;
+}
index 7c28fff259103b34e42e10bdb8b2f610de886645..463a2d114f5ad994851777b7cdf14b9c9c098141 100644 (file)
@@ -33,3 +33,9 @@ int link_request_to_set_mtu(Link *link, uint32_t mtu);
 int link_configure_mtu(Link *link);
 
 int request_process_set_link(Request *req);
+
+int link_up(Link *link);
+int link_down(Link *link);
+
+int request_process_activation(Request *req);
+int link_request_to_activate(Link *link);