diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2022-10-26 11:43:46 +0900 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2022-10-31 09:34:41 +0900 |
commit | 6625c39e70128d5aa8d3791c8232e33f624cfe49 (patch) | |
tree | 669130b1387f9d65ca97e8214eefcc1e1a035169 /src/network | |
parent | 4faca0a361011806e546f35e8f49467be3951acb (diff) | |
download | systemd-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.c | 48 | ||||
-rw-r--r-- | src/network/networkd-link.h | 4 |
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; |