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:
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user