1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-26 03:22:00 +03:00

Merge pull request #19901 from yuwata/network-reconfigure-after-sleep

network: reconfigure interface after coming back from sleep
This commit is contained in:
Yu Watanabe 2021-08-10 19:43:54 +09:00 committed by GitHub
commit 5e739f7eed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 136 additions and 105 deletions

View File

@ -690,6 +690,12 @@ static int link_acquire_dynamic_conf(Link *link) {
if (r < 0)
return log_link_warning_errno(link, r, "Failed to start LLDP transmission: %m");
if (link->lldp) {
r = sd_lldp_start(link->lldp);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to start LLDP client: %m");
}
return 0;
}
@ -999,6 +1005,16 @@ static int link_drop_foreign_config(Link *link) {
assert(link);
assert(link->manager);
/* Drop foreign config, but ignore unmanaged, loopback, or critical interfaces. We do not want
* to remove loopback address or addresses used for root NFS. */
if (IN_SET(link->state, LINK_STATE_UNMANAGED, LINK_STATE_PENDING, LINK_STATE_INITIALIZED))
return 0;
if (FLAGS_SET(link->flags, IFF_LOOPBACK))
return 0;
if (link->network->keep_configuration == KEEP_CONFIGURATION_YES)
return 0;
r = link_drop_foreign_routes(link);
k = link_drop_foreign_nexthops(link);
@ -1151,14 +1167,9 @@ static int link_configure(Link *link) {
if (r < 0)
return r;
/* Drop foreign config, but ignore loopback or critical devices.
* We do not want to remove loopback address or addresses used for root NFS. */
if (!(link->flags & IFF_LOOPBACK) &&
link->network->keep_configuration != KEEP_CONFIGURATION_YES) {
r = link_drop_foreign_config(link);
if (r < 0)
return r;
}
r = link_request_static_configs(link);
if (r < 0)
@ -1224,23 +1235,22 @@ static int link_get_network(Link *link, Network **ret) {
}
static int link_reconfigure_impl(Link *link, bool force) {
Network *network;
Network *network = NULL;
int r;
assert(link);
r = link_get_network(link, &network);
if (r == -ENOENT) {
link_set_state(link, LINK_STATE_UNMANAGED);
return 0;
}
if (r < 0)
if (r < 0 && r != -ENOENT)
return r;
if (link->network == network && !force)
return 0;
log_link_info(link, "Re-configuring with %s", network->filename);
if (network)
log_link_info(link, "Reconfiguring with %s.", network->filename);
else
log_link_info(link, "Unmanaging interface.");
/* Dropping old .network file */
r = link_stop_engines(link, false);
@ -1253,18 +1263,16 @@ static int link_reconfigure_impl(Link *link, bool force) {
if (r < 0)
return r;
if (!IN_SET(link->state, LINK_STATE_UNMANAGED, LINK_STATE_PENDING, LINK_STATE_INITIALIZED)) {
log_link_debug(link, "State is %s, dropping foreign config", link_state_to_string(link->state));
r = link_drop_foreign_config(link);
if (r < 0)
return r;
}
link_free_carrier_maps(link);
link_free_engines(link);
link->network = network_unref(link->network);
link_unref(set_remove(link->manager->links_requesting_uuid, link));
if (!network) {
link_set_state(link, LINK_STATE_UNMANAGED);
return 0;
}
/* Then, apply new .network file */
link->network = network_ref(network);
link_update_operstate(link, true);
@ -1284,44 +1292,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;
r = link_reconfigure_impl(link, force);
if (r < 0)
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) {
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;
@ -1560,34 +1631,7 @@ static int link_carrier_lost(Link *link) {
if (r < 0)
return r;
if (!IN_SET(link->state, LINK_STATE_UNMANAGED, LINK_STATE_PENDING, LINK_STATE_INITIALIZED)) {
log_link_debug(link, "State is %s, dropping foreign config", link_state_to_string(link->state));
r = link_drop_foreign_config(link);
if (r < 0)
return r;
}
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;
return link_drop_foreign_config(link);
}
static int link_admin_state_up(Link *link) {
@ -1943,10 +1987,6 @@ static int link_update_flags(Link *link, sd_netlink_message *message) {
return r;
}
r = link_update_lldp(link);
if (r < 0)
return r;
if (!had_carrier && link_has_carrier(link)) {
log_link_info(link, "Gained carrier");

View File

@ -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);

View File

@ -103,38 +103,9 @@ int link_lldp_rx_configure(Link *link) {
if (r < 0)
return r;
r = link_update_lldp(link);
if (r < 0)
return r;
return 0;
}
int link_update_lldp(Link *link) {
int r;
assert(link);
if (!link->lldp)
return 0;
if (link->flags & IFF_UP) {
r = sd_lldp_start(link->lldp);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to start LLDP: %m");
if (r > 0)
log_link_debug(link, "Started LLDP.");
} else {
r = sd_lldp_stop(link->lldp);
if (r < 0)
return log_link_warning_errno(link, r, "Failed to stop LLDP: %m");
if (r > 0)
log_link_debug(link, "Stopped LLDP.");
}
return r;
}
int link_lldp_save(Link *link) {
_cleanup_(unlink_and_freep) char *temp_path = NULL;
_cleanup_fclose_ FILE *f = NULL;

View File

@ -14,7 +14,6 @@ typedef enum LLDPMode {
} LLDPMode;
int link_lldp_rx_configure(Link *link);
int link_update_lldp(Link *link);
int link_lldp_save(Link *link);
const char* lldp_mode_to_string(LLDPMode m) _const_;

View File

@ -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);
}
}

View File

@ -674,9 +674,9 @@ class NetworkctlTests(unittest.TestCase, Utilities):
output = check_output('ip -4 address show dev dummy98')
print(output)
self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
self.assertIn('inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98', output)
self.assertIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output)
self.assertIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output)
check_output('ip address del 10.1.2.3/16 dev dummy98')
check_output('ip address del 10.1.2.4/16 dev dummy98')
@ -687,9 +687,30 @@ class NetworkctlTests(unittest.TestCase, Utilities):
output = check_output('ip -4 address show dev dummy98')
print(output)
self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
self.assertIn('inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98', output)
self.assertIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output)
self.assertIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output)
remove_unit_from_networkd_path(['25-address-static.network'])
check_output(*networkctl_cmd, 'reload', env=env)
self.wait_operstate('dummy98', 'degraded', setup_state='unmanaged')
output = check_output('ip -4 address show dev dummy98')
print(output)
self.assertNotIn('inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98', output)
self.assertNotIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output)
self.assertNotIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output)
copy_unit_to_networkd_unit_path('25-address-static.network')
check_output(*networkctl_cmd, 'reload', env=env)
self.wait_online(['dummy98:routable'])
output = check_output('ip -4 address show dev dummy98')
print(output)
self.assertIn('inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98', output)
self.assertIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output)
self.assertIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output)
def test_reload(self):
start_networkd(3)