summaryrefslogtreecommitdiff
path: root/src/network
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2022-10-26 11:43:46 +0900
committerYu Watanabe <watanabe.yu+github@gmail.com>2022-10-31 09:34:41 +0900
commit6625c39e70128d5aa8d3791c8232e33f624cfe49 (patch)
tree669130b1387f9d65ca97e8214eefcc1e1a035169 /src/network
parent4faca0a361011806e546f35e8f49467be3951acb (diff)
downloadsystemd-6625c39e70128d5aa8d3791c8232e33f624cfe49.tar.gz
network: simplify the logic of reading driver and permanent HW address
No functional changes, just refactoring and preparation for later commits. Note, `link->dev` should always exist when link state is initialized or later.
Diffstat (limited to 'src/network')
-rw-r--r--src/network/networkd-link.c48
-rw-r--r--src/network/networkd-link.h4
2 files changed, 41 insertions, 11 deletions
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 0759fbd9eb..d3dafb2458 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -2028,15 +2028,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");
@@ -2064,20 +2066,46 @@ static int link_update_driver(Link *link, sd_netlink_message *message) {
return 0;
}
-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);
@@ -2085,12 +2113,10 @@ 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)
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;