mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-27 03:21:32 +03:00
Merge pull request #22540 from yuwata/network-call-ethtool-after-initialized
network: call ethtool after link is initialized by udevd
This commit is contained in:
commit
48c08560f4
@ -59,7 +59,6 @@
|
||||
#include "networkd-sysctl.h"
|
||||
#include "set.h"
|
||||
#include "socket-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "stdio-util.h"
|
||||
#include "string-table.h"
|
||||
#include "strv.h"
|
||||
@ -1451,8 +1450,7 @@ static int link_check_initialized(Link *link) {
|
||||
|
||||
assert(link);
|
||||
|
||||
if (path_is_read_only_fs("/sys") > 0)
|
||||
/* no udev */
|
||||
if (!udev_available())
|
||||
return link_initialized_and_synced(link);
|
||||
|
||||
/* udev should be around */
|
||||
@ -2024,6 +2022,85 @@ static int link_update_master(Link *link, sd_netlink_message *message) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_update_driver(Link *link, sd_netlink_message *message) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->manager);
|
||||
assert(message);
|
||||
|
||||
/* Driver is already read. Assuming the driver is never changed. */
|
||||
if (link->driver)
|
||||
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))
|
||||
return 0;
|
||||
|
||||
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");
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_link_debug(link, "Found driver: %s", strna(link->driver));
|
||||
|
||||
if (streq_ptr(link->driver, "dsa")) {
|
||||
uint32_t dsa_master_ifindex = 0;
|
||||
|
||||
r = sd_netlink_message_read_u32(message, IFLA_LINK, &dsa_master_ifindex);
|
||||
if (r < 0 && r != -ENODATA)
|
||||
return log_link_debug_errno(link, r, "rtnl: failed to read ifindex of the DSA master interface: %m");
|
||||
|
||||
if (dsa_master_ifindex > INT_MAX) {
|
||||
log_link_debug(link, "rtnl: received too large DSA master ifindex (%"PRIu32" > INT_MAX), ignoring.",
|
||||
dsa_master_ifindex);
|
||||
dsa_master_ifindex = 0;
|
||||
}
|
||||
|
||||
link->dsa_master_ifindex = (int) dsa_master_ifindex;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/* 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");
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static int link_update_hardware_address(Link *link, sd_netlink_message *message) {
|
||||
struct hw_addr_data addr;
|
||||
int r;
|
||||
@ -2311,6 +2388,14 @@ static int link_update(Link *link, sd_netlink_message *message) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = link_update_driver(link, message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = link_update_permanent_hardware_address(link, message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = link_update_hardware_address(link, message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -2423,44 +2508,6 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
|
||||
log_link_debug(link, "Saved new link: ifindex=%i, iftype=%s(%u), kind=%s",
|
||||
link->ifindex, strna(arphrd_to_name(link->iftype)), link->iftype, strna(link->kind));
|
||||
|
||||
r = netlink_message_read_hw_addr(message, IFLA_PERM_ADDRESS, &link->permanent_hw_addr);
|
||||
if (r < 0) {
|
||||
if (r != -ENODATA)
|
||||
log_link_debug_errno(link, r, "Failed to read IFLA_PERM_ADDRESS attribute, ignoring: %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(&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");
|
||||
}
|
||||
}
|
||||
if (link->permanent_hw_addr.length > 0)
|
||||
log_link_debug(link, "Saved permanent hardware address: %s", HW_ADDR_TO_STR(&link->permanent_hw_addr));
|
||||
|
||||
r = ethtool_get_driver(&manager->ethtool_fd, link->ifname, &link->driver);
|
||||
if (r < 0)
|
||||
log_link_debug_errno(link, r, "Failed to get driver, continuing without: %m");
|
||||
else
|
||||
log_link_debug(link, "Found driver: %s", strna(link->driver));
|
||||
|
||||
if (streq_ptr(link->driver, "dsa")) {
|
||||
uint32_t dsa_master_ifindex;
|
||||
|
||||
r = sd_netlink_message_read_u32(message, IFLA_LINK, &dsa_master_ifindex);
|
||||
if (r < 0) {
|
||||
dsa_master_ifindex = 0;
|
||||
if (r != -ENODATA)
|
||||
log_link_warning_errno(link, r, "rtnl: failed to read ifindex of the DSA master interface, ignoring: %m");
|
||||
} else if (dsa_master_ifindex > INT_MAX) {
|
||||
dsa_master_ifindex = 0;
|
||||
log_link_warning(link, "rtnl: received too large DSA master ifindex (%"PRIu32" > INT_MAX), ignoring.",
|
||||
dsa_master_ifindex);
|
||||
}
|
||||
|
||||
link->dsa_master_ifindex = (int) dsa_master_ifindex;
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(link);
|
||||
return 0;
|
||||
}
|
||||
|
@ -55,6 +55,7 @@
|
||||
#include "sysctl-util.h"
|
||||
#include "tclass.h"
|
||||
#include "tmpfile-util.h"
|
||||
#include "udev-util.h"
|
||||
|
||||
/* use 128 MB for receive socket kernel queue. */
|
||||
#define RCVBUF_SIZE (128*1024*1024)
|
||||
@ -172,7 +173,7 @@ static int manager_connect_udev(Manager *m) {
|
||||
|
||||
/* udev does not initialize devices inside containers, so we rely on them being already
|
||||
* initialized before entering the container. */
|
||||
if (path_is_read_only_fs("/sys") > 0)
|
||||
if (!udev_available())
|
||||
return 0;
|
||||
|
||||
r = sd_device_monitor_new(&m->device_monitor);
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "path-util.h"
|
||||
#include "signal-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
#include "strxcpyx.h"
|
||||
@ -723,3 +724,17 @@ int on_ac_power(void) {
|
||||
|
||||
return found_online || !found_offline;
|
||||
}
|
||||
|
||||
bool udev_available(void) {
|
||||
static int cache = -1;
|
||||
|
||||
/* The service systemd-udevd is started only when /sys is read write.
|
||||
* See systemd-udevd.service: ConditionPathIsReadWrite=/sys
|
||||
* Also, our container interface (http://systemd.io/CONTAINER_INTERFACE/) states that /sys must
|
||||
* be mounted in read-only mode in containers. */
|
||||
|
||||
if (cache >= 0)
|
||||
return cache;
|
||||
|
||||
return (cache = path_is_read_only_fs("/sys/") <= 0);
|
||||
}
|
||||
|
@ -55,6 +55,8 @@ int udev_queue_init(void);
|
||||
|
||||
int on_ac_power(void);
|
||||
|
||||
bool udev_available(void);
|
||||
|
||||
#if HAVE_SYS_SDT_H
|
||||
|
||||
/* Each trace point can have different number of additional arguments. Note that when the macro is used only
|
||||
|
Loading…
Reference in New Issue
Block a user