mirror of
https://github.com/systemd/systemd.git
synced 2024-11-23 02:03:37 +08:00
network: several cleanups for link_reconfigure()
Effectively no functional changes, just refactoring and preparation for later changes. - convert boolean flag 'force' to LinkReconfigurationFlag enum, - merge link_reconfigure() and reconfigure_handler_on_bus_method_reload() as link_reconfigure_full(), - Rename ReconfigureData -> LinkReconfigurationData, - make Reconfigure() DBus message wait for reconfiguration being started before sending reply.
This commit is contained in:
parent
5a1ef6dffb
commit
2b07a3211b
@ -665,11 +665,9 @@ int bus_link_method_reconfigure(sd_bus_message *message, void *userdata, sd_bus_
|
||||
if (r == 0)
|
||||
return 1; /* Polkit will call us back */
|
||||
|
||||
r = link_reconfigure(l, /* force = */ true);
|
||||
if (r > 0)
|
||||
r = link_save_and_clean_full(l, /* also_save_manager = */ true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = link_reconfigure_full(l, LINK_RECONFIGURE_UNCONDITIONALLY, message, /* counter = */ NULL);
|
||||
if (r != 0)
|
||||
return r; /* Will reply later when r > 0. */
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
}
|
||||
|
@ -445,7 +445,7 @@ void link_enter_failed(Link *link) {
|
||||
}
|
||||
|
||||
log_link_info(link, "Trying to reconfigure the interface.");
|
||||
if (link_reconfigure(link, /* force = */ true) > 0)
|
||||
if (link_reconfigure(link, LINK_RECONFIGURE_UNCONDITIONALLY) > 0)
|
||||
return;
|
||||
|
||||
stop:
|
||||
@ -1344,7 +1344,7 @@ static void link_enter_unmanaged(Link *link) {
|
||||
link_set_state(link, LINK_STATE_UNMANAGED);
|
||||
}
|
||||
|
||||
int link_reconfigure_impl(Link *link, bool force) {
|
||||
int link_reconfigure_impl(Link *link, LinkReconfigurationFlag flags) {
|
||||
Network *network = NULL;
|
||||
int r;
|
||||
|
||||
@ -1367,7 +1367,7 @@ int link_reconfigure_impl(Link *link, bool force) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (link->network == network && !force)
|
||||
if (link->network == network && !FLAGS_SET(flags, LINK_RECONFIGURE_UNCONDITIONALLY))
|
||||
return 0;
|
||||
|
||||
_cleanup_free_ char *joined = strv_join(network->dropins, ", ");
|
||||
@ -1393,7 +1393,7 @@ int link_reconfigure_impl(Link *link, bool force) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!force && network->keep_configuration != KEEP_CONFIGURATION_YES)
|
||||
if (!FLAGS_SET(flags, LINK_RECONFIGURE_UNCONDITIONALLY) && network->keep_configuration != KEEP_CONFIGURATION_YES)
|
||||
/* When a new/updated .network file is assigned, first make all configs (addresses,
|
||||
* routes, and so on) foreign, and then drop unnecessary configs later by
|
||||
* link_drop_foreign_config() in link_configure().
|
||||
@ -1433,63 +1433,14 @@ int link_reconfigure_impl(Link *link, bool force) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int link_reconfigure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, bool force) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
r = link_getlink_handler_internal(rtnl, m, link, "Failed to update link state");
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
r = link_reconfigure_impl(link, force);
|
||||
if (r < 0) {
|
||||
link_enter_failed(link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int link_reconfigure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
return link_reconfigure_handler_internal(rtnl, m, link, /* force = */ false);
|
||||
}
|
||||
|
||||
static int link_force_reconfigure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
return link_reconfigure_handler_internal(rtnl, m, link, /* force = */ true);
|
||||
}
|
||||
|
||||
int link_reconfigure(Link *link, bool force) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
/* When link in pending or initialized state, then link_configure() will be called. To prevent
|
||||
* the function from being called multiple times simultaneously, refuse to reconfigure the
|
||||
* interface in these cases. */
|
||||
if (IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_INITIALIZED, LINK_STATE_LINGER))
|
||||
return 0; /* 0 means no-op. */
|
||||
|
||||
r = link_call_getlink(link, force ? link_force_reconfigure_handler : link_reconfigure_handler);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "Failed to reconfigure interface: %m");
|
||||
link_enter_failed(link);
|
||||
return r;
|
||||
}
|
||||
|
||||
if (force || link->state == LINK_STATE_FAILED)
|
||||
link_set_state(link, LINK_STATE_INITIALIZED);
|
||||
|
||||
return 1; /* 1 means the interface will be reconfigured. */
|
||||
}
|
||||
|
||||
typedef struct ReconfigureData {
|
||||
typedef struct LinkReconfigurationData {
|
||||
Link *link;
|
||||
Manager *manager;
|
||||
LinkReconfigurationFlag flags;
|
||||
sd_bus_message *message;
|
||||
} ReconfigureData;
|
||||
unsigned *counter;
|
||||
} LinkReconfigurationData;
|
||||
|
||||
static ReconfigureData* reconfigure_data_free(ReconfigureData *data) {
|
||||
static LinkReconfigurationData* link_reconfiguration_data_free(LinkReconfigurationData *data) {
|
||||
if (!data)
|
||||
return NULL;
|
||||
|
||||
@ -1499,56 +1450,72 @@ static ReconfigureData* reconfigure_data_free(ReconfigureData *data) {
|
||||
return mfree(data);
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(ReconfigureData*, reconfigure_data_free);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(LinkReconfigurationData*, link_reconfiguration_data_free);
|
||||
|
||||
static void reconfigure_data_destroy_callback(ReconfigureData *data) {
|
||||
static void link_reconfiguration_data_destroy_callback(LinkReconfigurationData *data) {
|
||||
int r;
|
||||
|
||||
assert(data);
|
||||
assert(data->manager);
|
||||
assert(data->manager->reloading > 0);
|
||||
assert(data->message);
|
||||
|
||||
data->manager->reloading--;
|
||||
if (data->manager->reloading <= 0) {
|
||||
r = sd_bus_reply_method_return(data->message, NULL);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to send reply for 'Reload' DBus method, ignoring: %m");
|
||||
if (data->message) {
|
||||
if (data->counter) {
|
||||
assert(*data->counter > 0);
|
||||
(*data->counter)--;
|
||||
}
|
||||
|
||||
if (!data->counter || *data->counter <= 0) {
|
||||
r = sd_bus_reply_method_return(data->message, NULL);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to reply for DBus method, ignoring: %m");
|
||||
}
|
||||
}
|
||||
|
||||
reconfigure_data_free(data);
|
||||
link_reconfiguration_data_free(data);
|
||||
}
|
||||
|
||||
static int reconfigure_handler_on_bus_method_reload(sd_netlink *rtnl, sd_netlink_message *m, ReconfigureData *data) {
|
||||
assert(data);
|
||||
assert(data->link);
|
||||
return link_reconfigure_handler_internal(rtnl, m, data->link, /* force = */ false);
|
||||
static int link_reconfigure_handler(sd_netlink *rtnl, sd_netlink_message *m, LinkReconfigurationData *data) {
|
||||
Link *link = ASSERT_PTR(ASSERT_PTR(data)->link);
|
||||
int r;
|
||||
|
||||
r = link_getlink_handler_internal(rtnl, m, link, "Failed to update link state");
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
r = link_reconfigure_impl(link, data->flags);
|
||||
if (r < 0) {
|
||||
link_enter_failed(link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int link_reconfigure_on_bus_method_reload(Link *link, sd_bus_message *message) {
|
||||
int link_reconfigure_full(Link *link, LinkReconfigurationFlag flags, sd_bus_message *message, unsigned *counter) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
|
||||
_cleanup_(reconfigure_data_freep) ReconfigureData *data = NULL;
|
||||
_cleanup_(link_reconfiguration_data_freep) LinkReconfigurationData *data = NULL;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
assert(link->manager->rtnl);
|
||||
assert(message);
|
||||
|
||||
/* See comments in link_reconfigure() above. */
|
||||
/* When the link is in the pending or initialized state, link_reconfigure_impl() will be called later
|
||||
* by link_initialized() or link_initialized_and_synced(). To prevent the function from being called
|
||||
* multiple times simultaneously, let's refuse to reconfigure the interface here in such cases. */
|
||||
if (IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_INITIALIZED, LINK_STATE_LINGER))
|
||||
return 0;
|
||||
return 0; /* 0 means no-op. */
|
||||
|
||||
data = new(ReconfigureData, 1);
|
||||
data = new(LinkReconfigurationData, 1);
|
||||
if (!data) {
|
||||
r = -ENOMEM;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
*data = (ReconfigureData) {
|
||||
*data = (LinkReconfigurationData) {
|
||||
.link = link_ref(link),
|
||||
.manager = link->manager,
|
||||
.message = sd_bus_message_ref(message),
|
||||
.flags = flags,
|
||||
.message = sd_bus_message_ref(message), /* message may be NULL, but _ref() works fine. */
|
||||
.counter = counter,
|
||||
};
|
||||
|
||||
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_GETLINK, link->ifindex);
|
||||
@ -1556,18 +1523,19 @@ int link_reconfigure_on_bus_method_reload(Link *link, sd_bus_message *message) {
|
||||
goto failed;
|
||||
|
||||
r = netlink_call_async(link->manager->rtnl, NULL, req,
|
||||
reconfigure_handler_on_bus_method_reload,
|
||||
reconfigure_data_destroy_callback, data);
|
||||
link_reconfigure_handler,
|
||||
link_reconfiguration_data_destroy_callback, data);
|
||||
if (r < 0)
|
||||
goto failed;
|
||||
|
||||
TAKE_PTR(data);
|
||||
link->manager->reloading++;
|
||||
if (counter)
|
||||
(*counter)++;
|
||||
|
||||
if (link->state == LINK_STATE_FAILED)
|
||||
link_set_state(link, LINK_STATE_INITIALIZED);
|
||||
|
||||
return 0;
|
||||
return 1; /* 1 means the interface will be reconfigured, and bus method will be replied later. */
|
||||
|
||||
failed:
|
||||
log_link_warning_errno(link, r, "Failed to reconfigure interface: %m");
|
||||
@ -1594,7 +1562,7 @@ static int link_initialized_and_synced(Link *link) {
|
||||
return r;
|
||||
}
|
||||
|
||||
return link_reconfigure_impl(link, /* force = */ false);
|
||||
return link_reconfigure_impl(link, /* flags = */ 0);
|
||||
}
|
||||
|
||||
static int link_initialized_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
@ -1638,7 +1606,7 @@ static int link_initialized(Link *link, sd_device *device) {
|
||||
log_link_warning_errno(link, r, "Failed to manage SR-IOV PF and VF ports, ignoring: %m");
|
||||
|
||||
if (link->state != LINK_STATE_PENDING)
|
||||
return link_reconfigure(link, /* force = */ false);
|
||||
return link_reconfigure(link, /* flags = */ 0);
|
||||
|
||||
log_link_debug(link, "udev initialized link");
|
||||
|
||||
@ -1740,7 +1708,7 @@ int manager_udev_process_link(Manager *m, sd_device *device, sd_device_action_t
|
||||
}
|
||||
|
||||
static int link_carrier_gained(Link *link) {
|
||||
bool force_reconfigure;
|
||||
LinkReconfigurationFlag flags = 0;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
@ -1766,11 +1734,12 @@ static int link_carrier_gained(Link *link) {
|
||||
* already assigned to the interface (in that case, the .network file does not have the SSID=
|
||||
* setting in the [Match] section), and the interface is already being configured. Of course,
|
||||
* there may exist another .network file with higher priority and a matching SSID= setting. But
|
||||
* in that case, link_reconfigure_impl() can handle that without the force_reconfigure flag.
|
||||
* in that case, link_reconfigure_impl() can handle that without any flags.
|
||||
*
|
||||
* For non-wireless interfaces, we have no way to detect the connected network change. So,
|
||||
* setting force_reconfigure = false. Note, both ssid and previous_ssid are NULL in that case. */
|
||||
force_reconfigure = link->previous_ssid && !streq_ptr(link->previous_ssid, link->ssid);
|
||||
* we do not set any flags here. Note, both ssid and previous_ssid are NULL in that case. */
|
||||
if (link->previous_ssid && !streq_ptr(link->previous_ssid, link->ssid))
|
||||
flags |= LINK_RECONFIGURE_UNCONDITIONALLY;
|
||||
link->previous_ssid = mfree(link->previous_ssid);
|
||||
|
||||
/* AP and P2P-GO interfaces may have a new SSID - update the link properties in case a new .network
|
||||
@ -1785,7 +1754,7 @@ static int link_carrier_gained(Link *link) {
|
||||
/* At this stage, both wlan and link information should be up-to-date. Hence, it is not necessary to
|
||||
* call RTM_GETLINK, NL80211_CMD_GET_INTERFACE, or NL80211_CMD_GET_STATION commands, and simply call
|
||||
* link_reconfigure_impl(). Note, link_reconfigure_impl() returns 1 when the link is reconfigured. */
|
||||
r = link_reconfigure_impl(link, force_reconfigure);
|
||||
r = link_reconfigure_impl(link, flags);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
@ -2880,7 +2849,7 @@ int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, Man
|
||||
if (manager->enumerating)
|
||||
return 0;
|
||||
|
||||
r = link_reconfigure_impl(link, /* force = */ false);
|
||||
r = link_reconfigure_impl(link, /* flags = */ 0);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "Failed to reconfigure interface: %m");
|
||||
link_enter_failed(link);
|
||||
|
@ -42,6 +42,10 @@ typedef enum LinkState {
|
||||
_LINK_STATE_INVALID = -EINVAL,
|
||||
} LinkState;
|
||||
|
||||
typedef enum LinkReconfigurationFlag {
|
||||
LINK_RECONFIGURE_UNCONDITIONALLY = 1 << 0, /* Reconfigure an interface even if .network file is unchanged. */
|
||||
} LinkReconfigurationFlag;
|
||||
|
||||
typedef struct Manager Manager;
|
||||
typedef struct Network Network;
|
||||
typedef struct NetDev NetDev;
|
||||
@ -259,9 +263,11 @@ LinkState link_state_from_string(const char *s) _pure_;
|
||||
|
||||
int link_request_stacked_netdevs(Link *link, NetDevLocalAddressType type);
|
||||
|
||||
int link_reconfigure_impl(Link *link, bool force);
|
||||
int link_reconfigure(Link *link, bool force);
|
||||
int link_reconfigure_on_bus_method_reload(Link *link, sd_bus_message *message);
|
||||
int link_reconfigure_impl(Link *link, LinkReconfigurationFlag flags);
|
||||
int link_reconfigure_full(Link *link, LinkReconfigurationFlag flags, sd_bus_message *message, unsigned *counter);
|
||||
static inline int link_reconfigure(Link *link, LinkReconfigurationFlag flags) {
|
||||
return link_reconfigure_full(link, flags, NULL, NULL);
|
||||
}
|
||||
|
||||
int link_check_initialized(Link *link);
|
||||
|
||||
|
@ -89,7 +89,7 @@ static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_b
|
||||
log_debug("Coming back from suspend, reconfiguring all connections...");
|
||||
|
||||
HASHMAP_FOREACH(link, m->links_by_index)
|
||||
(void) link_reconfigure(link, /* force = */ true);
|
||||
(void) link_reconfigure(link, LINK_RECONFIGURE_UNCONDITIONALLY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1219,12 +1219,9 @@ int manager_reload(Manager *m, sd_bus_message *message) {
|
||||
goto finish;
|
||||
}
|
||||
|
||||
HASHMAP_FOREACH(link, m->links_by_index) {
|
||||
if (message)
|
||||
(void) link_reconfigure_on_bus_method_reload(link, message);
|
||||
else
|
||||
(void) link_reconfigure(link, /* force = */ false);
|
||||
}
|
||||
HASHMAP_FOREACH(link, m->links_by_index)
|
||||
(void) link_reconfigure_full(link, /* flags = */ 0, message,
|
||||
/* counter = */ message ? &m->reloading : NULL);
|
||||
|
||||
log_debug("Reloaded.");
|
||||
r = 0;
|
||||
|
@ -287,7 +287,7 @@ int manager_genl_process_nl80211_mlme(sd_netlink *genl, sd_netlink_message *mess
|
||||
* To make SSID= or other WiFi related settings in [Match] section work, let's try to
|
||||
* reconfigure the interface. */
|
||||
if (link->ssid && link_has_carrier(link)) {
|
||||
r = link_reconfigure_impl(link, /* force = */ false);
|
||||
r = link_reconfigure_impl(link, /* flags = */ 0);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "Failed to reconfigure interface: %m");
|
||||
link_enter_failed(link);
|
||||
@ -326,7 +326,7 @@ int manager_genl_process_nl80211_mlme(sd_netlink *genl, sd_netlink_message *mess
|
||||
}
|
||||
|
||||
/* If necessary, reconfigure based on those new properties */
|
||||
r = link_reconfigure_impl(link, /* force = */ false);
|
||||
r = link_reconfigure_impl(link, /* flags = */ 0);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "Failed to reconfigure interface: %m");
|
||||
link_enter_failed(link);
|
||||
|
Loading…
Reference in New Issue
Block a user