mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-14 14:18:07 +02:00
platform: lookup ifname for ethtool/mii ioctl immediately before use
The ioctl APIs ethtool/mii require an interface ifname. That is inherrently
racy as interfaces can be renamed. This cannot be fixed, we can only
minimize the time between verifying the ifname and calling ioctl.
We already had problems with that when ethtool would access an interface
by name that didn't exists. See commit ab41c13b06 .
Checking for an existing interface only helps avoiding races when an interface
gets deleted. It does not help against renaming.
Go one step further, and instead of checking whether such an ifname
exists, try to get the ifname based on the ifindex immediately before
we need it.
This brings an additional overhead for each ethtool access.
This commit is contained in:
parent
da7b8dd850
commit
3641178508
8 changed files with 177 additions and 127 deletions
|
|
@ -827,7 +827,7 @@ link_negotiation_set (NMDevice *device)
|
|||
}
|
||||
}
|
||||
|
||||
if (!nm_platform_ethtool_get_link_settings (NM_PLATFORM_GET, nm_device_get_iface (device),
|
||||
if (!nm_platform_ethtool_get_link_settings (NM_PLATFORM_GET, nm_device_get_ifindex (device),
|
||||
&link_autoneg, &link_speed, &link_duplex)) {
|
||||
_LOGW (LOGD_DEVICE, "set-link: unable to retrieve link negotiation");
|
||||
return;
|
||||
|
|
@ -852,7 +852,7 @@ link_negotiation_set (NMDevice *device)
|
|||
}
|
||||
|
||||
if (!nm_platform_ethtool_set_link_settings (NM_PLATFORM_GET,
|
||||
nm_device_get_iface (device),
|
||||
nm_device_get_ifindex (device),
|
||||
autoneg,
|
||||
speed,
|
||||
duplex)) {
|
||||
|
|
@ -1243,7 +1243,7 @@ wake_on_lan_enable (NMDevice *device)
|
|||
}
|
||||
wol = NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE;
|
||||
found:
|
||||
return nm_platform_ethtool_set_wake_on_lan (NM_PLATFORM_GET, nm_device_get_iface (device), wol, password);
|
||||
return nm_platform_ethtool_set_wake_on_lan (NM_PLATFORM_GET, nm_device_get_ifindex (device), wol, password);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -1609,7 +1609,7 @@ get_link_speed (NMDevice *device)
|
|||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
|
||||
guint32 speed;
|
||||
|
||||
if (!nm_platform_ethtool_get_link_settings (NM_PLATFORM_GET, nm_device_get_iface (device), NULL, &speed, NULL))
|
||||
if (!nm_platform_ethtool_get_link_settings (NM_PLATFORM_GET, nm_device_get_ifindex (device), NULL, &speed, NULL))
|
||||
return;
|
||||
if (priv->speed == speed)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -682,7 +682,7 @@ _linktype_get_type (NMPlatform *platform,
|
|||
char ifname_verified[IFNAMSIZ];
|
||||
|
||||
/* Fallback OVS detection for kernel <= 3.16 */
|
||||
if (nmp_utils_ethtool_get_driver_info (ifname, &driver, NULL, NULL)) {
|
||||
if (nmp_utils_ethtool_get_driver_info (ifindex, &driver, NULL, NULL)) {
|
||||
if (!g_strcmp0 (driver, "openvswitch"))
|
||||
return NM_LINK_TYPE_OPENVSWITCH;
|
||||
|
||||
|
|
@ -4451,10 +4451,6 @@ static gboolean
|
|||
link_supports_carrier_detect (NMPlatform *platform, int ifindex)
|
||||
{
|
||||
nm_auto_pop_netns NMPNetns *netns = NULL;
|
||||
const char *name = nm_platform_link_get_name (platform, ifindex);
|
||||
|
||||
if (!name)
|
||||
return FALSE;
|
||||
|
||||
if (!nm_platform_netns_push (platform, &netns))
|
||||
return FALSE;
|
||||
|
|
@ -4463,7 +4459,7 @@ link_supports_carrier_detect (NMPlatform *platform, int ifindex)
|
|||
* us whether the device actually supports carrier detection in the first
|
||||
* place. We assume any device that does implements one of these two APIs.
|
||||
*/
|
||||
return nmp_utils_ethtool_supports_carrier_detect (name) || nmp_utils_mii_supports_carrier_detect (name);
|
||||
return nmp_utils_ethtool_supports_carrier_detect (ifindex) || nmp_utils_mii_supports_carrier_detect (ifindex);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -4481,7 +4477,7 @@ link_supports_vlans (NMPlatform *platform, int ifindex)
|
|||
if (!nm_platform_netns_push (platform, &netns))
|
||||
return FALSE;
|
||||
|
||||
return nmp_utils_ethtool_supports_vlans (obj->link.name);
|
||||
return nmp_utils_ethtool_supports_vlans (ifindex);
|
||||
}
|
||||
|
||||
static NMPlatformError
|
||||
|
|
@ -4549,7 +4545,7 @@ link_get_permanent_address (NMPlatform *platform,
|
|||
if (!nm_platform_netns_push (platform, &netns))
|
||||
return FALSE;
|
||||
|
||||
return nmp_utils_ethtool_get_permanent_address (nm_platform_link_get_name (platform, ifindex), buf, length);
|
||||
return nmp_utils_ethtool_get_permanent_address (ifindex, buf, length);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -5519,7 +5515,7 @@ link_get_wake_on_lan (NMPlatform *platform, int ifindex)
|
|||
return FALSE;
|
||||
|
||||
if (type == NM_LINK_TYPE_ETHERNET)
|
||||
return nmp_utils_ethtool_get_wake_on_lan (nm_platform_link_get_name (platform, ifindex));
|
||||
return nmp_utils_ethtool_get_wake_on_lan (ifindex);
|
||||
else if (type == NM_LINK_TYPE_WIFI) {
|
||||
WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex);
|
||||
|
||||
|
|
@ -5543,7 +5539,7 @@ link_get_driver_info (NMPlatform *platform,
|
|||
if (!nm_platform_netns_push (platform, &netns))
|
||||
return FALSE;
|
||||
|
||||
return nmp_utils_ethtool_get_driver_info (nm_platform_link_get_name (platform, ifindex),
|
||||
return nmp_utils_ethtool_get_driver_info (ifindex,
|
||||
out_driver_name,
|
||||
out_driver_version,
|
||||
out_fw_version);
|
||||
|
|
|
|||
|
|
@ -44,6 +44,26 @@ extern char *if_indextoname (unsigned int __ifindex, char *__ifname);
|
|||
* ethtool
|
||||
******************************************************************/
|
||||
|
||||
NM_UTILS_ENUM2STR_DEFINE_STATIC (_ethtool_cmd_to_string, guint32,
|
||||
NM_UTILS_ENUM2STR (ETHTOOL_GDRVINFO, "ETHTOOL_GDRVINFO"),
|
||||
NM_UTILS_ENUM2STR (ETHTOOL_GFEATURES, "ETHTOOL_GFEATURES"),
|
||||
NM_UTILS_ENUM2STR (ETHTOOL_GLINK, "ETHTOOL_GLINK"),
|
||||
NM_UTILS_ENUM2STR (ETHTOOL_GPERMADDR, "ETHTOOL_GPERMADDR"),
|
||||
NM_UTILS_ENUM2STR (ETHTOOL_GSET, "ETHTOOL_GSET"),
|
||||
NM_UTILS_ENUM2STR (ETHTOOL_GSSET_INFO, "ETHTOOL_GSSET_INFO"),
|
||||
NM_UTILS_ENUM2STR (ETHTOOL_GSTATS, "ETHTOOL_GSTATS"),
|
||||
NM_UTILS_ENUM2STR (ETHTOOL_GSTRINGS, "ETHTOOL_GSTRINGS"),
|
||||
NM_UTILS_ENUM2STR (ETHTOOL_GWOL, "ETHTOOL_GWOL"),
|
||||
NM_UTILS_ENUM2STR (ETHTOOL_SSET, "ETHTOOL_SSET"),
|
||||
NM_UTILS_ENUM2STR (ETHTOOL_SWOL, "ETHTOOL_SWOL"),
|
||||
);
|
||||
|
||||
static const char *
|
||||
_ethtool_data_to_string (gconstpointer edata, char *buf, gsize len)
|
||||
{
|
||||
return _ethtool_cmd_to_string (*((guint32 *) edata), buf, len);
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
|
||||
#define ethtool_cmd_speed(pedata) ((pedata)->speed)
|
||||
|
||||
|
|
@ -52,53 +72,83 @@ extern char *if_indextoname (unsigned int __ifindex, char *__ifname);
|
|||
#endif
|
||||
|
||||
static gboolean
|
||||
ethtool_get (const char *name, gpointer edata)
|
||||
ethtool_get (int ifindex, gpointer edata)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
int fd;
|
||||
char ifname[IFNAMSIZ];
|
||||
char sbuf[50];
|
||||
|
||||
if (!name || !*name)
|
||||
return FALSE;
|
||||
nm_assert (ifindex > 0);
|
||||
|
||||
if (!nmp_utils_device_exists (name))
|
||||
return FALSE;
|
||||
/* ethtool ioctl API uses the ifname to refer to an interface. That is racy
|
||||
* as interfaces can be renamed *sigh*.
|
||||
*
|
||||
* Note that we anyway have to verify whether the interface exists, before
|
||||
* calling ioctl for a non-existing ifname. This is to prevent autoloading
|
||||
* of kernel modules *sigh*.
|
||||
* Thus, as we anyway verify the existence of ifname before doing the call,
|
||||
* go one step further and lookup the ifname everytime anew.
|
||||
*
|
||||
* This does not solve the renaming race, but it minimizes the time for
|
||||
* the race to happen as much as possible. */
|
||||
|
||||
/* nmp_utils_device_exists() already errors out if @name is invalid. */
|
||||
nm_assert (strlen (name) < IFNAMSIZ);
|
||||
|
||||
memset (&ifr, 0, sizeof (ifr));
|
||||
nm_utils_ifname_cpy (ifr.ifr_name, name);
|
||||
ifr.ifr_data = edata;
|
||||
|
||||
fd = socket (PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
|
||||
if (fd < 0) {
|
||||
nm_log_err (LOGD_PLATFORM, "ethtool: Could not open socket.");
|
||||
if (!if_indextoname (ifindex, ifname)) {
|
||||
nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s: request fails resolving ifindex: %s",
|
||||
ifindex,
|
||||
_ethtool_data_to_string (edata, sbuf, sizeof (sbuf)),
|
||||
g_strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (ioctl (fd, SIOCETHTOOL, &ifr) < 0) {
|
||||
nm_log_dbg (LOGD_PLATFORM, "ethtool: Request failed: %s", strerror (errno));
|
||||
close (fd);
|
||||
return FALSE;
|
||||
}
|
||||
{
|
||||
nm_auto_close int fd = -1;
|
||||
struct ifreq ifr = {
|
||||
.ifr_data = edata,
|
||||
};
|
||||
|
||||
close (fd);
|
||||
return TRUE;
|
||||
memcpy (ifr.ifr_name, ifname, sizeof (ifname));
|
||||
|
||||
fd = socket (PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
|
||||
if (fd < 0) {
|
||||
nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s, %s: failed creating socket for ioctl: %s",
|
||||
ifindex,
|
||||
_ethtool_data_to_string (edata, sbuf, sizeof (sbuf)),
|
||||
ifname,
|
||||
g_strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (ioctl (fd, SIOCETHTOOL, &ifr) < 0) {
|
||||
nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s, %s: failed: %s",
|
||||
ifindex,
|
||||
_ethtool_data_to_string (edata, sbuf, sizeof (sbuf)),
|
||||
ifname,
|
||||
strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
nm_log_trace (LOGD_PLATFORM, "ethtool[%d]: %s, %s: success",
|
||||
ifindex,
|
||||
_ethtool_data_to_string (edata, sbuf, sizeof (sbuf)),
|
||||
ifname);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ethtool_get_stringset_index (const char *ifname, int stringset_id, const char *string)
|
||||
ethtool_get_stringset_index (int ifindex, int stringset_id, const char *string)
|
||||
{
|
||||
gs_free struct ethtool_sset_info *info = NULL;
|
||||
gs_free struct ethtool_gstrings *strings = NULL;
|
||||
guint32 len, i;
|
||||
|
||||
g_return_val_if_fail (ifindex > 0, -1);
|
||||
|
||||
info = g_malloc0 (sizeof (*info) + sizeof (guint32));
|
||||
info->cmd = ETHTOOL_GSSET_INFO;
|
||||
info->reserved = 0;
|
||||
info->sset_mask = 1ULL << stringset_id;
|
||||
|
||||
if (!ethtool_get (ifname, info))
|
||||
if (!ethtool_get (ifindex, info))
|
||||
return -1;
|
||||
if (!info->sset_mask)
|
||||
return -1;
|
||||
|
|
@ -109,7 +159,7 @@ ethtool_get_stringset_index (const char *ifname, int stringset_id, const char *s
|
|||
strings->cmd = ETHTOOL_GSTRINGS;
|
||||
strings->string_set = stringset_id;
|
||||
strings->len = len;
|
||||
if (!ethtool_get (ifname, strings))
|
||||
if (!ethtool_get (ifindex, strings))
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
|
|
@ -121,18 +171,17 @@ ethtool_get_stringset_index (const char *ifname, int stringset_id, const char *s
|
|||
}
|
||||
|
||||
gboolean
|
||||
nmp_utils_ethtool_get_driver_info (const char *ifname,
|
||||
nmp_utils_ethtool_get_driver_info (int ifindex,
|
||||
char **out_driver_name,
|
||||
char **out_driver_version,
|
||||
char **out_fw_version)
|
||||
{
|
||||
struct ethtool_drvinfo drvinfo = { 0 };
|
||||
|
||||
if (!ifname)
|
||||
return FALSE;
|
||||
g_return_val_if_fail (ifindex > 0, FALSE);
|
||||
|
||||
drvinfo.cmd = ETHTOOL_GDRVINFO;
|
||||
if (!ethtool_get (ifname, &drvinfo))
|
||||
if (!ethtool_get (ifindex, &drvinfo))
|
||||
return FALSE;
|
||||
|
||||
if (out_driver_name)
|
||||
|
|
@ -146,7 +195,7 @@ nmp_utils_ethtool_get_driver_info (const char *ifname,
|
|||
}
|
||||
|
||||
gboolean
|
||||
nmp_utils_ethtool_get_permanent_address (const char *ifname,
|
||||
nmp_utils_ethtool_get_permanent_address (int ifindex,
|
||||
guint8 *buf,
|
||||
size_t *length)
|
||||
{
|
||||
|
|
@ -156,14 +205,13 @@ nmp_utils_ethtool_get_permanent_address (const char *ifname,
|
|||
} edata;
|
||||
guint i;
|
||||
|
||||
if (!ifname)
|
||||
return FALSE;
|
||||
g_return_val_if_fail (ifindex > 0, FALSE);
|
||||
|
||||
memset (&edata, 0, sizeof (edata));
|
||||
edata.e.cmd = ETHTOOL_GPERMADDR;
|
||||
edata.e.size = NM_UTILS_HWADDR_LEN_MAX;
|
||||
|
||||
if (!ethtool_get (ifname, &edata.e))
|
||||
if (!ethtool_get (ifindex, &edata.e))
|
||||
return FALSE;
|
||||
|
||||
if (edata.e.size > NM_UTILS_HWADDR_LEN_MAX)
|
||||
|
|
@ -190,29 +238,30 @@ not_all_0or1:
|
|||
}
|
||||
|
||||
gboolean
|
||||
nmp_utils_ethtool_supports_carrier_detect (const char *ifname)
|
||||
nmp_utils_ethtool_supports_carrier_detect (int ifindex)
|
||||
{
|
||||
struct ethtool_cmd edata = { .cmd = ETHTOOL_GLINK };
|
||||
|
||||
g_return_val_if_fail (ifindex > 0, FALSE);
|
||||
|
||||
/* We ignore the result. If the ETHTOOL_GLINK call succeeded, then we
|
||||
* assume the device supports carrier-detect, otherwise we assume it
|
||||
* doesn't.
|
||||
*/
|
||||
return ethtool_get (ifname, &edata);
|
||||
return ethtool_get (ifindex, &edata);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nmp_utils_ethtool_supports_vlans (const char *ifname)
|
||||
nmp_utils_ethtool_supports_vlans (int ifindex)
|
||||
{
|
||||
gs_free struct ethtool_gfeatures *features = NULL;
|
||||
int idx, block, bit, size;
|
||||
|
||||
if (!ifname)
|
||||
return FALSE;
|
||||
g_return_val_if_fail (ifindex > 0, FALSE);
|
||||
|
||||
idx = ethtool_get_stringset_index (ifname, ETH_SS_FEATURES, "vlan-challenged");
|
||||
idx = ethtool_get_stringset_index (ifindex, ETH_SS_FEATURES, "vlan-challenged");
|
||||
if (idx == -1) {
|
||||
nm_log_dbg (LOGD_PLATFORM, "ethtool: vlan-challenged ethtool feature does not exist for %s?", ifname);
|
||||
nm_log_dbg (LOGD_PLATFORM, "ethtool: vlan-challenged ethtool feature does not exist for %d?", ifindex);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -224,54 +273,52 @@ nmp_utils_ethtool_supports_vlans (const char *ifname)
|
|||
features->cmd = ETHTOOL_GFEATURES;
|
||||
features->size = size;
|
||||
|
||||
if (!ethtool_get (ifname, features))
|
||||
if (!ethtool_get (ifindex, features))
|
||||
return FALSE;
|
||||
|
||||
return !(features->features[block].active & (1 << bit));
|
||||
}
|
||||
|
||||
int
|
||||
nmp_utils_ethtool_get_peer_ifindex (const char *ifname)
|
||||
nmp_utils_ethtool_get_peer_ifindex (int ifindex)
|
||||
{
|
||||
gs_free struct ethtool_stats *stats = NULL;
|
||||
int peer_ifindex_stat;
|
||||
|
||||
if (!ifname)
|
||||
return 0;
|
||||
g_return_val_if_fail (ifindex > 0, 0);
|
||||
|
||||
peer_ifindex_stat = ethtool_get_stringset_index (ifname, ETH_SS_STATS, "peer_ifindex");
|
||||
peer_ifindex_stat = ethtool_get_stringset_index (ifindex, ETH_SS_STATS, "peer_ifindex");
|
||||
if (peer_ifindex_stat == -1) {
|
||||
nm_log_dbg (LOGD_PLATFORM, "ethtool: peer_ifindex stat for %s does not exist?", ifname);
|
||||
nm_log_dbg (LOGD_PLATFORM, "ethtool: peer_ifindex stat for %d does not exist?", ifindex);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
stats = g_malloc0 (sizeof (*stats) + (peer_ifindex_stat + 1) * sizeof (guint64));
|
||||
stats->cmd = ETHTOOL_GSTATS;
|
||||
stats->n_stats = peer_ifindex_stat + 1;
|
||||
if (!ethtool_get (ifname, stats))
|
||||
if (!ethtool_get (ifindex, stats))
|
||||
return 0;
|
||||
|
||||
return stats->data[peer_ifindex_stat];
|
||||
}
|
||||
|
||||
gboolean
|
||||
nmp_utils_ethtool_get_wake_on_lan (const char *ifname)
|
||||
nmp_utils_ethtool_get_wake_on_lan (int ifindex)
|
||||
{
|
||||
struct ethtool_wolinfo wol;
|
||||
|
||||
if (!ifname)
|
||||
return FALSE;
|
||||
g_return_val_if_fail (ifindex > 0, FALSE);
|
||||
|
||||
memset (&wol, 0, sizeof (wol));
|
||||
wol.cmd = ETHTOOL_GWOL;
|
||||
if (!ethtool_get (ifname, &wol))
|
||||
if (!ethtool_get (ifindex, &wol))
|
||||
return FALSE;
|
||||
|
||||
return wol.wolopts != 0;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nmp_utils_ethtool_get_link_settings (const char *ifname,
|
||||
nmp_utils_ethtool_get_link_settings (int ifindex,
|
||||
gboolean *out_autoneg,
|
||||
guint32 *out_speed,
|
||||
NMPlatformLinkDuplexType *out_duplex)
|
||||
|
|
@ -280,7 +327,9 @@ nmp_utils_ethtool_get_link_settings (const char *ifname,
|
|||
.cmd = ETHTOOL_GSET,
|
||||
};
|
||||
|
||||
if (!ethtool_get (ifname, &edata))
|
||||
g_return_val_if_fail (ifindex > 0, FALSE);
|
||||
|
||||
if (!ethtool_get (ifindex, &edata))
|
||||
return FALSE;
|
||||
|
||||
if (out_autoneg)
|
||||
|
|
@ -314,14 +363,19 @@ nmp_utils_ethtool_get_link_settings (const char *ifname,
|
|||
}
|
||||
|
||||
gboolean
|
||||
nmp_utils_ethtool_set_link_settings (const char *ifname, gboolean autoneg, guint32 speed, NMPlatformLinkDuplexType duplex)
|
||||
nmp_utils_ethtool_set_link_settings (int ifindex,
|
||||
gboolean autoneg,
|
||||
guint32 speed,
|
||||
NMPlatformLinkDuplexType duplex)
|
||||
{
|
||||
struct ethtool_cmd edata = {
|
||||
.cmd = ETHTOOL_GSET,
|
||||
};
|
||||
|
||||
g_return_val_if_fail (ifindex > 0, FALSE);
|
||||
|
||||
/* retrieve first current settings */
|
||||
if (!ethtool_get (ifname, &edata))
|
||||
if (!ethtool_get (ifindex, &edata))
|
||||
return FALSE;
|
||||
|
||||
/* then change the needed ones */
|
||||
|
|
@ -349,16 +403,18 @@ nmp_utils_ethtool_set_link_settings (const char *ifname, gboolean autoneg, guint
|
|||
}
|
||||
}
|
||||
|
||||
return ethtool_get (ifname, &edata);
|
||||
return ethtool_get (ifindex, &edata);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nmp_utils_ethtool_set_wake_on_lan (const char *ifname,
|
||||
nmp_utils_ethtool_set_wake_on_lan (int ifindex,
|
||||
NMSettingWiredWakeOnLan wol,
|
||||
const char *wol_password)
|
||||
{
|
||||
struct ethtool_wolinfo wol_info = { };
|
||||
|
||||
g_return_val_if_fail (ifindex > 0, FALSE);
|
||||
|
||||
if (wol == NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE)
|
||||
return TRUE;
|
||||
|
||||
|
|
@ -389,7 +445,7 @@ nmp_utils_ethtool_set_wake_on_lan (const char *ifname,
|
|||
wol_info.wolopts |= WAKE_MAGICSECURE;
|
||||
}
|
||||
|
||||
return ethtool_get (ifname, &wol_info);
|
||||
return ethtool_get (ifindex, &wol_info);
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
|
|
@ -397,51 +453,45 @@ nmp_utils_ethtool_set_wake_on_lan (const char *ifname,
|
|||
******************************************************************/
|
||||
|
||||
gboolean
|
||||
nmp_utils_mii_supports_carrier_detect (const char *ifname)
|
||||
nmp_utils_mii_supports_carrier_detect (int ifindex)
|
||||
{
|
||||
int fd, errsv;
|
||||
char ifname[IFNAMSIZ];
|
||||
nm_auto_close int fd = -1;
|
||||
struct ifreq ifr;
|
||||
struct mii_ioctl_data *mii;
|
||||
gboolean supports_mii = FALSE;
|
||||
|
||||
if (!ifname)
|
||||
return FALSE;
|
||||
g_return_val_if_fail (ifindex > 0, FALSE);
|
||||
|
||||
if (!nmp_utils_device_exists (ifname))
|
||||
if (!if_indextoname (ifindex, ifname)) {
|
||||
nm_log_trace (LOGD_PLATFORM, "mii[%d]: carrier-detect no: request fails resolving ifindex: %s", ifindex, g_strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fd = socket (PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
|
||||
if (fd < 0) {
|
||||
nm_log_err (LOGD_PLATFORM, "mii: couldn't open control socket (%s)", ifname);
|
||||
nm_log_trace (LOGD_PLATFORM, "mii[%d,%s]: carrier-detect no: couldn't open control socket: %s", ifindex, ifname, g_strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
memset (&ifr, 0, sizeof (struct ifreq));
|
||||
nm_utils_ifname_cpy (ifr.ifr_name, ifname);
|
||||
memcpy (ifr.ifr_name, ifname, IFNAMSIZ);
|
||||
|
||||
errno = 0;
|
||||
if (ioctl (fd, SIOCGMIIPHY, &ifr) < 0) {
|
||||
errsv = errno;
|
||||
nm_log_dbg (LOGD_PLATFORM, "mii: SIOCGMIIPHY failed: %s (%d) (%s)", strerror (errsv), errsv, ifname);
|
||||
goto out;
|
||||
nm_log_trace (LOGD_PLATFORM, "mii[%d,%s]: carrier-detect no: SIOCGMIIPHY failed: %s", ifindex, ifname, strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* If we can read the BMSR register, we assume that the card supports MII link detection */
|
||||
mii = (struct mii_ioctl_data *) &ifr.ifr_ifru;
|
||||
mii->reg_num = MII_BMSR;
|
||||
|
||||
if (ioctl (fd, SIOCGMIIREG, &ifr) == 0) {
|
||||
nm_log_dbg (LOGD_PLATFORM, "mii: SIOCGMIIREG result 0x%X (%s)", mii->val_out, ifname);
|
||||
supports_mii = TRUE;
|
||||
} else {
|
||||
errsv = errno;
|
||||
nm_log_dbg (LOGD_PLATFORM, "mii: SIOCGMIIREG failed: %s (%d) (%s)", strerror (errsv), errsv, ifname);
|
||||
if (ioctl (fd, SIOCGMIIREG, &ifr) != 0) {
|
||||
nm_log_trace (LOGD_PLATFORM, "mii[%d,%s]: carrier-detect no: SIOCGMIIREG failed: %s", ifindex, ifname, strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
out:
|
||||
close (fd);
|
||||
nm_log_dbg (LOGD_PLATFORM, "mii: MII %s supported (%s)", supports_mii ? "is" : "not", ifname);
|
||||
return supports_mii;
|
||||
nm_log_trace (LOGD_PLATFORM, "mii[%d,%s]: carrier-detect yes: SIOCGMIIREG result 0x%X", ifindex, ifname, mii->val_out);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
|
|
|
|||
|
|
@ -27,28 +27,28 @@
|
|||
#include "nm-setting-wired.h"
|
||||
|
||||
|
||||
const char *nmp_utils_ethtool_get_driver (const char *ifname);
|
||||
gboolean nmp_utils_ethtool_supports_carrier_detect (const char *ifname);
|
||||
gboolean nmp_utils_ethtool_supports_vlans (const char *ifname);
|
||||
int nmp_utils_ethtool_get_peer_ifindex (const char *ifname);
|
||||
gboolean nmp_utils_ethtool_get_wake_on_lan (const char *ifname);
|
||||
gboolean nmp_utils_ethtool_set_wake_on_lan (const char *ifname, NMSettingWiredWakeOnLan wol,
|
||||
const char *nmp_utils_ethtool_get_driver (int ifindex);
|
||||
gboolean nmp_utils_ethtool_supports_carrier_detect (int ifindex);
|
||||
gboolean nmp_utils_ethtool_supports_vlans (int ifindex);
|
||||
int nmp_utils_ethtool_get_peer_ifindex (int ifindex);
|
||||
gboolean nmp_utils_ethtool_get_wake_on_lan (int ifindex);
|
||||
gboolean nmp_utils_ethtool_set_wake_on_lan (int ifindex, NMSettingWiredWakeOnLan wol,
|
||||
const char *wol_password);
|
||||
|
||||
gboolean nmp_utils_ethtool_get_link_settings (const char *ifname, gboolean *out_autoneg, guint32 *out_speed, NMPlatformLinkDuplexType *out_duplex);
|
||||
gboolean nmp_utils_ethtool_set_link_settings (const char *ifname, gboolean autoneg, guint32 speed, NMPlatformLinkDuplexType duplex);
|
||||
gboolean nmp_utils_ethtool_get_link_settings (int ifindex, gboolean *out_autoneg, guint32 *out_speed, NMPlatformLinkDuplexType *out_duplex);
|
||||
gboolean nmp_utils_ethtool_set_link_settings (int ifindex, gboolean autoneg, guint32 speed, NMPlatformLinkDuplexType duplex);
|
||||
|
||||
gboolean nmp_utils_ethtool_get_driver_info (const char *ifname,
|
||||
gboolean nmp_utils_ethtool_get_driver_info (int ifindex,
|
||||
char **out_driver_name,
|
||||
char **out_driver_version,
|
||||
char **out_fw_version);
|
||||
|
||||
gboolean nmp_utils_ethtool_get_permanent_address (const char *ifname,
|
||||
gboolean nmp_utils_ethtool_get_permanent_address (int ifindex,
|
||||
guint8 *buf,
|
||||
size_t *length);
|
||||
|
||||
|
||||
gboolean nmp_utils_mii_supports_carrier_detect (const char *ifname);
|
||||
gboolean nmp_utils_mii_supports_carrier_detect (int ifindex);
|
||||
|
||||
|
||||
const char *nmp_utils_udev_get_driver (GUdevDevice *device);
|
||||
|
|
|
|||
|
|
@ -2259,7 +2259,7 @@ nm_platform_link_veth_get_properties (NMPlatform *self, int ifindex, int *out_pe
|
|||
|
||||
if (!nm_platform_netns_push (self, &netns))
|
||||
return FALSE;
|
||||
peer_ifindex = nmp_utils_ethtool_get_peer_ifindex (plink->name);
|
||||
peer_ifindex = nmp_utils_ethtool_get_peer_ifindex (plink->ifindex);
|
||||
if (peer_ifindex <= 0)
|
||||
return FALSE;
|
||||
|
||||
|
|
@ -2507,27 +2507,33 @@ _to_string_ifa_flags (guint32 ifa_flags, char *buf, gsize size)
|
|||
/*****************************************************************************/
|
||||
|
||||
gboolean
|
||||
nm_platform_ethtool_set_wake_on_lan (NMPlatform *self, const char *ifname, NMSettingWiredWakeOnLan wol, const char *wol_password)
|
||||
nm_platform_ethtool_set_wake_on_lan (NMPlatform *self, int ifindex, NMSettingWiredWakeOnLan wol, const char *wol_password)
|
||||
{
|
||||
_CHECK_SELF_NETNS (self, klass, netns, FALSE);
|
||||
|
||||
return nmp_utils_ethtool_set_wake_on_lan (ifname, wol, wol_password);
|
||||
g_return_val_if_fail (ifindex > 0, FALSE);
|
||||
|
||||
return nmp_utils_ethtool_set_wake_on_lan (ifindex, wol, wol_password);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_platform_ethtool_set_link_settings (NMPlatform *self, const char *ifname, gboolean autoneg, guint32 speed, NMPlatformLinkDuplexType duplex)
|
||||
nm_platform_ethtool_set_link_settings (NMPlatform *self, int ifindex, gboolean autoneg, guint32 speed, NMPlatformLinkDuplexType duplex)
|
||||
{
|
||||
_CHECK_SELF_NETNS (self, klass, netns, FALSE);
|
||||
|
||||
return nmp_utils_ethtool_set_link_settings (ifname, autoneg, speed, duplex);
|
||||
g_return_val_if_fail (ifindex > 0, FALSE);
|
||||
|
||||
return nmp_utils_ethtool_set_link_settings (ifindex, autoneg, speed, duplex);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_platform_ethtool_get_link_settings (NMPlatform *self, const char *ifname, gboolean *out_autoneg, guint32 *out_speed, NMPlatformLinkDuplexType *out_duplex)
|
||||
nm_platform_ethtool_get_link_settings (NMPlatform *self, int ifindex, gboolean *out_autoneg, guint32 *out_speed, NMPlatformLinkDuplexType *out_duplex)
|
||||
{
|
||||
_CHECK_SELF_NETNS (self, klass, netns, FALSE);
|
||||
|
||||
return nmp_utils_ethtool_get_link_settings (ifname, out_autoneg, out_speed, out_duplex);
|
||||
g_return_val_if_fail (ifindex > 0, FALSE);
|
||||
|
||||
return nmp_utils_ethtool_get_link_settings (ifindex, out_autoneg, out_speed, out_duplex);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -992,8 +992,8 @@ const char *nm_platform_route_scope2str (int scope, char *buf, gsize len);
|
|||
|
||||
int nm_platform_ip_address_cmp_expiry (const NMPlatformIPAddress *a, const NMPlatformIPAddress *b);
|
||||
|
||||
gboolean nm_platform_ethtool_set_wake_on_lan (NMPlatform *self, const char *ifname, NMSettingWiredWakeOnLan wol, const char *wol_password);
|
||||
gboolean nm_platform_ethtool_set_link_settings (NMPlatform *self, const char *ifname, gboolean autoneg, guint32 speed, NMPlatformLinkDuplexType duplex);
|
||||
gboolean nm_platform_ethtool_get_link_settings (NMPlatform *self, const char *ifname, gboolean *out_autoneg, guint32 *out_speed, NMPlatformLinkDuplexType *out_duplex);
|
||||
gboolean nm_platform_ethtool_set_wake_on_lan (NMPlatform *self, int ifindex, NMSettingWiredWakeOnLan wol, const char *wol_password);
|
||||
gboolean nm_platform_ethtool_set_link_settings (NMPlatform *self, int ifindex, gboolean autoneg, guint32 speed, NMPlatformLinkDuplexType duplex);
|
||||
gboolean nm_platform_ethtool_get_link_settings (NMPlatform *self, int ifindex, gboolean *out_autoneg, guint32 *out_speed, NMPlatformLinkDuplexType *out_duplex);
|
||||
|
||||
#endif /* __NETWORKMANAGER_PLATFORM_H__ */
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ _vlan_xgress_qos_mappings_cpy (guint *dst_n_map,
|
|||
/*****************************************************************************/
|
||||
|
||||
static const char *
|
||||
_link_get_driver (GUdevDevice *udev_device, const char *kind, const char *ifname)
|
||||
_link_get_driver (GUdevDevice *udev_device, const char *kind, int ifindex)
|
||||
{
|
||||
const char *driver = NULL;
|
||||
|
||||
|
|
@ -140,10 +140,10 @@ _link_get_driver (GUdevDevice *udev_device, const char *kind, const char *ifname
|
|||
if (kind)
|
||||
return kind;
|
||||
|
||||
if (ifname) {
|
||||
if (ifindex > 0) {
|
||||
char *d;
|
||||
|
||||
if (nmp_utils_ethtool_get_driver_info (ifname, &d, NULL, NULL)) {
|
||||
if (nmp_utils_ethtool_get_driver_info (ifindex, &d, NULL, NULL)) {
|
||||
driver = d && d[0] ? g_intern_string (d) : NULL;
|
||||
g_free (d);
|
||||
if (driver)
|
||||
|
|
@ -169,7 +169,7 @@ _nmp_object_fixup_link_udev_fields (NMPObject *obj, gboolean use_udev)
|
|||
if (obj->_link.netlink.is_in_netlink) {
|
||||
driver = _link_get_driver (obj->_link.udev.device,
|
||||
obj->link.kind,
|
||||
obj->link.name);
|
||||
obj->link.ifindex);
|
||||
if (obj->_link.udev.device)
|
||||
initialized = TRUE;
|
||||
else if (!use_udev) {
|
||||
|
|
|
|||
|
|
@ -2026,9 +2026,8 @@ test_netns_general (gpointer fixture, gconstpointer test_data)
|
|||
* skip asserts that are known to fail. */
|
||||
ethtool_support = nmtstp_run_command ("ethtool -i dummy1_ > /dev/null") == 0;
|
||||
if (ethtool_support) {
|
||||
g_assert ( nmp_utils_ethtool_get_driver_info ("dummy1_", NULL, NULL, NULL));
|
||||
g_assert ( nmp_utils_ethtool_get_driver_info ("dummy2a", NULL, NULL, NULL));
|
||||
g_assert (!nmp_utils_ethtool_get_driver_info ("dummy2b", NULL, NULL, NULL));
|
||||
g_assert (nmp_utils_ethtool_get_driver_info (nmtstp_link_get_typed (platform_1, 0, "dummy1_", NM_LINK_TYPE_DUMMY)->ifindex, NULL, NULL, NULL));
|
||||
g_assert (nmp_utils_ethtool_get_driver_info (nmtstp_link_get_typed (platform_1, 0, "dummy2a", NM_LINK_TYPE_DUMMY)->ifindex, NULL, NULL, NULL));
|
||||
g_assert_cmpint (nmtstp_run_command ("ethtool -i dummy1_ > /dev/null"), ==, 0);
|
||||
g_assert_cmpint (nmtstp_run_command ("ethtool -i dummy2a > /dev/null"), ==, 0);
|
||||
g_assert_cmpint (nmtstp_run_command ("ethtool -i dummy2b 2> /dev/null"), !=, 0);
|
||||
|
|
@ -2037,9 +2036,8 @@ test_netns_general (gpointer fixture, gconstpointer test_data)
|
|||
g_assert (nm_platform_netns_push (platform_2, &netns_tmp));
|
||||
|
||||
if (ethtool_support) {
|
||||
g_assert ( nmp_utils_ethtool_get_driver_info ("dummy1_", NULL, NULL, NULL));
|
||||
g_assert (!nmp_utils_ethtool_get_driver_info ("dummy2a", NULL, NULL, NULL));
|
||||
g_assert ( nmp_utils_ethtool_get_driver_info ("dummy2b", NULL, NULL, NULL));
|
||||
g_assert (nmp_utils_ethtool_get_driver_info (nmtstp_link_get_typed (platform_2, 0, "dummy1_", NM_LINK_TYPE_DUMMY)->ifindex, NULL, NULL, NULL));
|
||||
g_assert (nmp_utils_ethtool_get_driver_info (nmtstp_link_get_typed (platform_2, 0, "dummy2b", NM_LINK_TYPE_DUMMY)->ifindex, NULL, NULL, NULL));
|
||||
g_assert_cmpint (nmtstp_run_command ("ethtool -i dummy1_ > /dev/null"), ==, 0);
|
||||
g_assert_cmpint (nmtstp_run_command ("ethtool -i dummy2a 2> /dev/null"), !=, 0);
|
||||
g_assert_cmpint (nmtstp_run_command ("ethtool -i dummy2b > /dev/null"), ==, 0);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue