diff options
-rw-r--r-- | src/network/netdev/netdev.c | 2 | ||||
-rw-r--r-- | src/network/networkd-can.c | 37 | ||||
-rw-r--r-- | src/network/networkd-link.c | 103 | ||||
-rw-r--r-- | src/network/networkd-link.h | 3 | ||||
-rw-r--r-- | src/network/networkd-queue.c | 15 | ||||
-rw-r--r-- | src/network/networkd-queue.h | 1 | ||||
-rw-r--r-- | src/network/networkd-setlink.c | 157 | ||||
-rw-r--r-- | src/network/networkd-setlink.h | 6 |
8 files changed, 196 insertions, 128 deletions
diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index a0b6706aad..5c1927cdfc 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -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"); } diff --git a/src/network/networkd-can.c b/src/network/networkd-can.c index 787cfd711e..41b946b44d 100644 --- a/src/network/networkd-can.c +++ b/src/network/networkd-can.c @@ -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); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 7570775744..00bcb5b0bc 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -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 diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 600b5f5ee1..15a0cdd7d0 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -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); diff --git a/src/network/networkd-queue.c b/src/network/networkd-queue.c index 3a17a06b2c..acda4994f0 100644 --- a/src/network/networkd-queue.c +++ b/src/network/networkd-queue.c @@ -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; diff --git a/src/network/networkd-queue.h b/src/network/networkd-queue.h index 697fbf3bfd..4fb49c48bc 100644 --- a/src/network/networkd-queue.h +++ b/src/network/networkd-queue.h @@ -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, diff --git a/src/network/networkd-setlink.c b/src/network/networkd-setlink.c index 1184fbfb43..5abe379b6b 100644 --- a/src/network/networkd-setlink.c +++ b/src/network/networkd-setlink.c @@ -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; +} diff --git a/src/network/networkd-setlink.h b/src/network/networkd-setlink.h index 7c28fff259..463a2d114f 100644 --- a/src/network/networkd-setlink.h +++ b/src/network/networkd-setlink.h @@ -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); |