From: Yu Watanabe Date: Sat, 12 Jun 2021 03:01:42 +0000 (+0900) Subject: network: reconfigure link after coming back from sleep X-Git-Tag: v250-rc1~857^2~5 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d09a179e6973fb1da4a0366c25d9d16679655f2d;p=thirdparty%2Fsystemd.git 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. --- diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 17fb932f81a..2cf84b0f139 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 4077ccaf09c..79400dee2e9 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 374d27bef34..82aecf1c76b 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); } }