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.
This commit is contained in:
+40
-14
@@ -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,6 +2066,38 @@ static int link_update_driver(Link *link, sd_netlink_message *message) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
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->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 (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;
|
||||
|
||||
@@ -2074,23 +2108,15 @@ static int link_update_permanent_hardware_address(Link *link, sd_netlink_message
|
||||
if (link->permanent_hw_addr.length > 0)
|
||||
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))
|
||||
return 0;
|
||||
|
||||
r = netlink_message_read_hw_addr(message, IFLA_PERM_ADDRESS, &link->permanent_hw_addr);
|
||||
if (r < 0) {
|
||||
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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user