summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2021-06-12 05:01:42 +0200
committerYu Watanabe <watanabe.yu+github@gmail.com>2021-08-10 07:43:34 +0200
commitd09a179e6973fb1da4a0366c25d9d16679655f2d (patch)
treef5e1302f90002b2cf25c1f479e9f3b9f1682895c
parentUpdate traditional Chinese Translation (diff)
downloadsystemd-d09a179e6973fb1da4a0366c25d9d16679655f2d.tar.xz
systemd-d09a179e6973fb1da4a0366c25d9d16679655f2d.zip
network: reconfigure link after coming back from sleep
Previously, link was reconfigured with `link_carrier_reset()`, but it just re-request to configure static addresses, routes, etc, and restart engines (e.g. DHCP client). However, after coming back from sleep, several link information may be changed, especially the wifi access point may be different. So, we may need to reconfigure the interface.
-rw-r--r--src/network/networkd-link.c97
-rw-r--r--src/network/networkd-link.h2
-rw-r--r--src/network/networkd-manager.c4
3 files changed, 73 insertions, 30 deletions
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 17fb932f81..2cf84b0f13 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1284,44 +1284,107 @@ static 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) {
+static int link_reconfigure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, bool force, bool update_wifi) {
+ bool link_was_lower_up;
int r;
+ assert(link);
+
+ link_was_lower_up = link->flags & IFF_LOWER_UP;
+
r = link_getlink_handler_internal(rtnl, m, link, "Failed to update link state");
if (r <= 0)
return r;
+ if (update_wifi && link_was_lower_up && link->flags & IFF_LOWER_UP) {
+ /* If the interface's L1 was not up, then wifi_get_info() is already called in
+ * link_update_flags(). So, it is not necessary to re-call here. */
+ r = wifi_get_info(link);
+ if (r < 0) {
+ link_enter_failed(link);
+ return 0;
+ }
+ }
+
r = link_reconfigure_impl(link, force);
- if (r < 0)
+ if (r < 0) {
link_enter_failed(link);
+ return 0;
+ }
- 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, false);
+ return link_reconfigure_handler_internal(rtnl, m, link, /* force = */ false, /* update_wifi = */ false);
}
static int link_force_reconfigure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
- return link_reconfigure_handler_internal(rtnl, m, link, true);
+ return link_reconfigure_handler_internal(rtnl, m, link, /* force = */ true, /* update_wifi = */ false);
}
-int link_reconfigure(Link *link, bool force) {
+static int link_reconfigure_after_sleep_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
+ assert(link);
+
+ r = link_reconfigure_handler_internal(rtnl, m, link, /* force = */ false, /* update_wifi = */ true);
+ if (r != 0)
+ return r;
+
+ /* r == 0 means an error occurs, the link is unmanaged, or the matching network file is unchanged. */
+ if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
+ return 0;
+
+ /* re-request static configs, and restart engines. */
+ r = link_stop_engines(link, false);
+ if (r < 0) {
+ link_enter_failed(link);
+ return 0;
+ }
+
+ r = link_acquire_dynamic_conf(link);
+ if (r < 0) {
+ link_enter_failed(link);
+ return 0;
+ }
+
+ r = link_request_static_configs(link);
+ if (r < 0) {
+ link_enter_failed(link);
+ return 0;
+ }
+
+ return 0;
+}
+
+static int link_reconfigure_internal(Link *link, link_netlink_message_handler_t callback) {
+ int r;
+
+ assert(link);
+ assert(callback);
+
/* 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);
+ r = link_call_getlink(link, callback);
if (r < 0)
return r;
return 1; /* 1 means the interface will be reconfigured. */
}
+int link_reconfigure(Link *link, bool force) {
+ return link_reconfigure_internal(link, force ? link_force_reconfigure_handler : link_reconfigure_handler);
+}
+
+int link_reconfigure_after_sleep(Link *link) {
+ return link_reconfigure_internal(link, link_reconfigure_after_sleep_handler);
+}
+
static int link_initialized_and_synced(Link *link) {
Network *network;
int r;
@@ -1570,26 +1633,6 @@ static int link_carrier_lost(Link *link) {
return 0;
}
-int link_carrier_reset(Link *link) {
- int r;
-
- assert(link);
-
- if (!link_has_carrier(link))
- return 0;
-
- r = link_carrier_lost(link);
- if (r < 0)
- return r;
-
- r = link_carrier_gained(link);
- if (r < 0)
- return r;
-
- log_link_info(link, "Reset carrier");
- return 0;
-}
-
static int link_admin_state_up(Link *link) {
int r;
diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h
index 4077ccaf09..79400dee2e 100644
--- a/src/network/networkd-link.h
+++ b/src/network/networkd-link.h
@@ -232,7 +232,6 @@ void link_check_ready(Link *link);
void link_update_operstate(Link *link, bool also_update_bond_master);
-int link_carrier_reset(Link *link);
bool link_has_carrier(Link *link);
bool link_ipv6_enabled(Link *link);
@@ -247,6 +246,7 @@ const char* link_state_to_string(LinkState s) _const_;
LinkState link_state_from_string(const char *s) _pure_;
int link_reconfigure(Link *link, bool force);
+int link_reconfigure_after_sleep(Link *link);
int manager_udev_process_link(sd_device_monitor *monitor, sd_device *device, void *userdata);
int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index 374d27bef3..82aecf1c76 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -59,9 +59,9 @@ static int manager_reset_all(Manager *m) {
assert(m);
HASHMAP_FOREACH(link, m->links_by_index) {
- r = link_carrier_reset(link);
+ r = link_reconfigure_after_sleep(link);
if (r < 0) {
- log_link_warning_errno(link, r, "Could not reset carrier: %m");
+ log_link_warning_errno(link, r, "Failed to reconfigure interface: %m");
link_enter_failed(link);
}
}