diff options
author | Luca Boccassi <bluca@debian.org> | 2022-10-31 21:14:24 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-31 21:14:24 +0100 |
commit | 0be7f1936c2a8d5601cf899b197278403220a076 (patch) | |
tree | 7f32ce63cb96cd1eb1ff2409bbc9f09cab88dcf8 /src/network | |
parent | 9f913d37a01f71e559d099bff280827f8817d8c5 (diff) | |
parent | fa4d3fed46a97ee45a4aeba4d9540015bf5cab7b (diff) | |
download | systemd-0be7f1936c2a8d5601cf899b197278403220a076.tar.gz |
Merge pull request #25143 from yuwata/network-reconfigure-interface-when-renamed
network: reconfigure interface when renamed
Diffstat (limited to 'src/network')
-rw-r--r-- | src/network/networkd-link.c | 126 | ||||
-rw-r--r-- | src/network/networkd-link.h | 4 |
2 files changed, 84 insertions, 46 deletions
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 04e3432c94..151346f198 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1185,7 +1185,7 @@ static int link_reconfigure_impl(Link *link, bool force) { assert(link); - if (!IN_SET(link->state, LINK_STATE_INITIALIZED, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED, LINK_STATE_UNMANAGED)) + if (IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_LINGER)) return 0; r = netdev_get(link->manager, link->ifname, &netdev); @@ -1367,21 +1367,18 @@ static int link_initialized_and_synced(Link *link) { return 0; } - /* This may get called either from the asynchronous netlink callback, - * or directly from link_check_initialized() if running in a container. */ - if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_INITIALIZED)) - return 0; - - log_link_debug(link, "Link state is up-to-date"); - link_set_state(link, LINK_STATE_INITIALIZED); + if (link->state == LINK_STATE_PENDING) { + log_link_debug(link, "Link state is up-to-date"); + link_set_state(link, LINK_STATE_INITIALIZED); - r = link_new_bound_by_list(link); - if (r < 0) - return r; + r = link_new_bound_by_list(link); + if (r < 0) + return r; - r = link_handle_bound_by_list(link); - if (r < 0) - return r; + r = link_handle_bound_by_list(link); + if (r < 0) + return r; + } return link_reconfigure_impl(link, /* force = */ false); } @@ -1426,14 +1423,10 @@ static int link_initialized(Link *link, sd_device *device) { if (r < 0) log_link_warning_errno(link, r, "Failed to manage SR-IOV PF and VF ports, ignoring: %m"); - /* Do not ignore unamanaged state case here. If an interface is renamed after being once - * configured, and the corresponding .network file has Name= in [Match] section, then the - * interface may be already in unmanaged state. See #20657. */ - if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_UNMANAGED)) - return 0; + if (link->state != LINK_STATE_PENDING) + return link_reconfigure(link, /* force = */ false); log_link_debug(link, "udev initialized link"); - link_set_state(link, LINK_STATE_INITIALIZED); /* udev has initialized the link, but we don't know if we have yet * processed the NEWLINK messages with the latest state. Do a GETLINK, @@ -1549,15 +1542,12 @@ static int link_carrier_gained(Link *link) { force_reconfigure = link->previous_ssid && !streq_ptr(link->previous_ssid, link->ssid); link->previous_ssid = mfree(link->previous_ssid); - if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_FAILED, LINK_STATE_LINGER)) { - /* 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); - if (r != 0) - return r; - } + /* 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); + if (r != 0) + return r; r = link_handle_bound_by_list(link); if (r < 0) @@ -2043,15 +2033,17 @@ static int link_update_driver(Link *link, sd_netlink_message *message) { assert(message); /* Driver is already read. Assuming the driver is never changed. */ - if (link->driver) + if (link->ethtool_driver_read) return 0; /* When udevd is running, read the driver after the interface is initialized by udevd. * Otherwise, ethtool may not work correctly. See issue #22538. * When udevd is not running, read the value when the interface is detected. */ - if (link->state != (udev_available() ? LINK_STATE_INITIALIZED : LINK_STATE_PENDING)) + if (udev_available() && !link->dev) return 0; + link->ethtool_driver_read = true; + r = ethtool_get_driver(&link->manager->ethtool_fd, link->ifname, &link->driver); if (r < 0) { log_link_debug_errno(link, r, "Failed to get driver, continuing without: %m"); @@ -2076,23 +2068,49 @@ static int link_update_driver(Link *link, sd_netlink_message *message) { link->dsa_master_ifindex = (int) dsa_master_ifindex; } - return 0; + return 1; /* needs reconfigure */ } -static int link_update_permanent_hardware_address(Link *link, sd_netlink_message *message) { +static int link_update_permanent_hardware_address_from_ethtool(Link *link, sd_netlink_message *message) { int r; assert(link); assert(link->manager); assert(message); - if (link->permanent_hw_addr.length > 0) + if (link->ethtool_permanent_hw_addr_read) return 0; /* When udevd is running, read the permanent hardware address after the interface is * initialized by udevd. Otherwise, ethtool may not work correctly. See issue #22538. * When udevd is not running, read the value when the interface is detected. */ - if (link->state != (udev_available() ? LINK_STATE_INITIALIZED : LINK_STATE_PENDING)) + if (udev_available() && !link->dev) + return 0; + + /* If the interface does not have a hardware address, then it will not have a permanent address either. */ + r = netlink_message_read_hw_addr(message, IFLA_ADDRESS, NULL); + if (r == -ENODATA) + return 0; + if (r < 0) + return log_link_debug_errno(link, r, "Failed to read IFLA_ADDRESS attribute: %m"); + + link->ethtool_permanent_hw_addr_read = true; + + r = ethtool_get_permanent_hw_addr(&link->manager->ethtool_fd, link->ifname, &link->permanent_hw_addr); + if (r < 0) + log_link_debug_errno(link, r, "Permanent hardware address not found, continuing without: %m"); + + return 0; +} + +static int link_update_permanent_hardware_address(Link *link, sd_netlink_message *message) { + int r; + + assert(link); + assert(link->manager); + assert(message); + + if (link->permanent_hw_addr.length > 0) return 0; r = netlink_message_read_hw_addr(message, IFLA_PERM_ADDRESS, &link->permanent_hw_addr); @@ -2100,18 +2118,16 @@ static int link_update_permanent_hardware_address(Link *link, sd_netlink_message if (r != -ENODATA) return log_link_debug_errno(link, r, "Failed to read IFLA_PERM_ADDRESS attribute: %m"); - if (netlink_message_read_hw_addr(message, IFLA_ADDRESS, NULL) >= 0) { - /* Fallback to ethtool, if the link has a hardware address. */ - r = ethtool_get_permanent_hw_addr(&link->manager->ethtool_fd, link->ifname, &link->permanent_hw_addr); - if (r < 0) - log_link_debug_errno(link, r, "Permanent hardware address not found, continuing without: %m"); - } + /* Fallback to ethtool for older kernels. */ + r = link_update_permanent_hardware_address_from_ethtool(link, message); + if (r < 0) + return r; } if (link->permanent_hw_addr.length > 0) log_link_debug(link, "Saved permanent hardware address: %s", HW_ADDR_TO_STR(&link->permanent_hw_addr)); - return 0; + return 1; /* needs reconfigure */ } static int link_update_hardware_address(Link *link, sd_netlink_message *message) { @@ -2194,7 +2210,7 @@ static int link_update_hardware_address(Link *link, sd_netlink_message *message) return log_link_debug_errno(link, r, "Could not update MAC address for LLDP Tx: %m"); } - return 0; + return 1; /* needs reconfigure */ } static int link_update_mtu(Link *link, sd_netlink_message *message) { @@ -2286,7 +2302,7 @@ static int link_update_alternative_names(Link *link, sd_netlink_message *message return log_link_debug_errno(link, r, "Failed to manage link by its new alternative names: %m"); } - return 0; + return 1; /* needs reconfigure */ } static int link_update_name(Link *link, sd_netlink_message *message) { @@ -2382,10 +2398,11 @@ static int link_update_name(Link *link, sd_netlink_message *message) { if (r < 0) return log_link_debug_errno(link, r, "Failed to update interface name in IPv4ACD client: %m"); - return 0; + return 1; /* needs reconfigure */ } static int link_update(Link *link, sd_netlink_message *message) { + bool needs_reconfigure = false; int r; assert(link); @@ -2394,10 +2411,12 @@ static int link_update(Link *link, sd_netlink_message *message) { r = link_update_name(link, message); if (r < 0) return r; + needs_reconfigure = needs_reconfigure || r > 0; r = link_update_alternative_names(link, message); if (r < 0) return r; + needs_reconfigure = needs_reconfigure || r > 0; r = link_update_mtu(link, message); if (r < 0) @@ -2406,14 +2425,17 @@ static int link_update(Link *link, sd_netlink_message *message) { r = link_update_driver(link, message); if (r < 0) return r; + needs_reconfigure = needs_reconfigure || r > 0; r = link_update_permanent_hardware_address(link, message); if (r < 0) return r; + needs_reconfigure = needs_reconfigure || r > 0; r = link_update_hardware_address(link, message); if (r < 0) return r; + needs_reconfigure = needs_reconfigure || r > 0; r = link_update_master(link, message); if (r < 0) @@ -2423,7 +2445,11 @@ static int link_update(Link *link, sd_netlink_message *message) { if (r < 0) return r; - return link_update_flags(link, message); + r = link_update_flags(link, message); + if (r < 0) + return r; + + return needs_reconfigure; } static Link *link_drop_or_unref(Link *link) { @@ -2612,6 +2638,14 @@ int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, Man link_enter_failed(link); return 0; } + if (r > 0) { + r = link_reconfigure_impl(link, /* force = */ false); + if (r < 0) { + log_link_warning_errno(link, r, "Failed to reconfigure interface: %m"); + link_enter_failed(link); + return 0; + } + } } break; diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 9f1cdca312..4d397da79a 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -72,6 +72,10 @@ typedef struct Link { sd_device *dev; char *driver; + /* to prevent multiple ethtool calls */ + bool ethtool_driver_read; + bool ethtool_permanent_hw_addr_read; + /* link-local addressing */ IPv6LinkLocalAddressGenMode ipv6ll_address_gen_mode; |