summaryrefslogtreecommitdiff
path: root/src/network
diff options
context:
space:
mode:
authorLuca Boccassi <bluca@debian.org>2022-10-31 21:14:24 +0100
committerGitHub <noreply@github.com>2022-10-31 21:14:24 +0100
commit0be7f1936c2a8d5601cf899b197278403220a076 (patch)
tree7f32ce63cb96cd1eb1ff2409bbc9f09cab88dcf8 /src/network
parent9f913d37a01f71e559d099bff280827f8817d8c5 (diff)
parentfa4d3fed46a97ee45a4aeba4d9540015bf5cab7b (diff)
downloadsystemd-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.c126
-rw-r--r--src/network/networkd-link.h4
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;