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 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, /* 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, /* force = */ true, /* update_wifi = */ false); +} + +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_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - return link_reconfigure_handler_internal(rtnl, m, link, 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); -} - -int link_reconfigure(Link *link, bool force) { +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); } }