network: introduce link_request_to_activate()

The request will be processed after all setlink requests are processed.
The function will be used in later commits.
This commit is contained in:
Yu Watanabe
2021-06-08 06:39:48 +09:00
parent 0e397560cc
commit 112a0972a2
8 changed files with 196 additions and 128 deletions
+1 -1
View 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");
}
+8 -29
View 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);
+9 -94
View 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
+1 -2
View 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);
+14 -1
View 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;
+1
View 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,
+156 -1
View 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;
}
+6
View 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);