platform: add APIs to allow link negotiation management
Added platform functions to retrieve device link mode status and to switch from auto to manual link negotiation: nm_platform_ethtool_get_link_settings nm_platform_ethtool_set_link_settings
This commit is contained in:
@@ -1522,7 +1522,7 @@ get_link_speed (NMDevice *device)
|
|||||||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
|
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
|
||||||
guint32 speed;
|
guint32 speed;
|
||||||
|
|
||||||
if (!nm_platform_ethtool_get_link_speed (NM_PLATFORM_GET, nm_device_get_iface (device), &speed))
|
if (!nm_platform_ethtool_get_link_settings (NM_PLATFORM_GET, nm_device_get_iface (device), NULL, &speed, NULL))
|
||||||
return;
|
return;
|
||||||
if (priv->speed == speed)
|
if (priv->speed == speed)
|
||||||
return;
|
return;
|
||||||
|
@@ -40,6 +40,13 @@
|
|||||||
/******************************************************************
|
/******************************************************************
|
||||||
* ethtool
|
* ethtool
|
||||||
******************************************************************/
|
******************************************************************/
|
||||||
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
|
||||||
|
#define ethtool_cmd_speed(pedata) ((pedata)->speed)
|
||||||
|
|
||||||
|
#define ethtool_cmd_speed_set(pedata, speed) \
|
||||||
|
G_STMT_START { (pedata)->speed = (guint16) (speed); } G_STMT_END
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
ethtool_get (const char *name, gpointer edata)
|
ethtool_get (const char *name, gpointer edata)
|
||||||
@@ -261,29 +268,85 @@ nmp_utils_ethtool_get_wake_on_lan (const char *ifname)
|
|||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
nmp_utils_ethtool_get_link_speed (const char *ifname, guint32 *out_speed)
|
nmp_utils_ethtool_get_link_settings (const char *ifname,
|
||||||
|
gboolean *out_autoneg,
|
||||||
|
guint32 *out_speed,
|
||||||
|
NMPlatformLinkDuplexType *out_duplex)
|
||||||
{
|
{
|
||||||
struct ethtool_cmd edata = {
|
struct ethtool_cmd edata = {
|
||||||
.cmd = ETHTOOL_GSET,
|
.cmd = ETHTOOL_GSET,
|
||||||
};
|
};
|
||||||
guint32 speed;
|
|
||||||
|
|
||||||
if (!ethtool_get (ifname, &edata))
|
if (!ethtool_get (ifname, &edata))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
|
if (out_autoneg)
|
||||||
speed = edata.speed;
|
*out_autoneg = (edata.autoneg == AUTONEG_ENABLE);
|
||||||
#else
|
|
||||||
speed = ethtool_cmd_speed (&edata);
|
if (out_speed) {
|
||||||
#endif
|
guint32 speed;
|
||||||
if (speed == G_MAXUINT16 || speed == G_MAXUINT32)
|
|
||||||
speed = 0;
|
speed = ethtool_cmd_speed (&edata);
|
||||||
|
if (speed == G_MAXUINT16 || speed == G_MAXUINT32)
|
||||||
|
speed = 0;
|
||||||
|
|
||||||
if (out_speed)
|
|
||||||
*out_speed = speed;
|
*out_speed = speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out_duplex) {
|
||||||
|
switch (edata.duplex) {
|
||||||
|
case DUPLEX_HALF:
|
||||||
|
*out_duplex = NM_PLATFORM_LINK_DUPLEX_HALF;
|
||||||
|
break;
|
||||||
|
case DUPLEX_FULL:
|
||||||
|
*out_duplex = NM_PLATFORM_LINK_DUPLEX_FULL;
|
||||||
|
break;
|
||||||
|
default: /* DUPLEX_UNKNOWN */
|
||||||
|
*out_duplex = NM_PLATFORM_LINK_DUPLEX_UNKNOWN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nmp_utils_ethtool_set_link_settings (const char *ifname, gboolean autoneg, guint32 speed, NMPlatformLinkDuplexType duplex)
|
||||||
|
{
|
||||||
|
struct ethtool_cmd edata = {
|
||||||
|
.cmd = ETHTOOL_GSET,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* retrieve first current settings */
|
||||||
|
if (!ethtool_get (ifname, &edata))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* then change the needed ones */
|
||||||
|
edata.cmd = ETHTOOL_SSET;
|
||||||
|
if (autoneg) {
|
||||||
|
edata.autoneg = AUTONEG_ENABLE;
|
||||||
|
edata.advertising = edata.supported;
|
||||||
|
} else {
|
||||||
|
edata.autoneg = AUTONEG_DISABLE;
|
||||||
|
|
||||||
|
if (speed)
|
||||||
|
ethtool_cmd_speed_set (&edata, speed);
|
||||||
|
|
||||||
|
switch (duplex) {
|
||||||
|
case NM_PLATFORM_LINK_DUPLEX_HALF:
|
||||||
|
edata.duplex = DUPLEX_HALF;
|
||||||
|
break;
|
||||||
|
case NM_PLATFORM_LINK_DUPLEX_FULL:
|
||||||
|
edata.duplex = DUPLEX_FULL;
|
||||||
|
break;
|
||||||
|
default: /* NM_PLATFORM_LINK_DUPLEX_UNSET */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ethtool_get (ifname, &edata);
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
nmp_utils_ethtool_set_wake_on_lan (const char *ifname,
|
nmp_utils_ethtool_set_wake_on_lan (const char *ifname,
|
||||||
NMSettingWiredWakeOnLan wol,
|
NMSettingWiredWakeOnLan wol,
|
||||||
|
@@ -35,7 +35,8 @@ gboolean nmp_utils_ethtool_get_wake_on_lan (const char *ifname);
|
|||||||
gboolean nmp_utils_ethtool_set_wake_on_lan (const char *ifname, NMSettingWiredWakeOnLan wol,
|
gboolean nmp_utils_ethtool_set_wake_on_lan (const char *ifname, NMSettingWiredWakeOnLan wol,
|
||||||
const char *wol_password);
|
const char *wol_password);
|
||||||
|
|
||||||
gboolean nmp_utils_ethtool_get_link_speed (const char *ifname, guint32 *out_speed);
|
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_driver_info (const char *ifname,
|
gboolean nmp_utils_ethtool_get_driver_info (const char *ifname,
|
||||||
char **out_driver_name,
|
char **out_driver_name,
|
||||||
|
@@ -134,6 +134,17 @@ NM_DEFINE_SINGLETON_REGISTER (NMPlatform);
|
|||||||
(void) klass; \
|
(void) klass; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define _CHECK_SELF_NETNS(self, klass, netns, err_val) \
|
||||||
|
nm_auto_pop_netns NMPNetns *netns = NULL; \
|
||||||
|
NMPlatformClass *klass; \
|
||||||
|
do { \
|
||||||
|
g_return_val_if_fail (NM_IS_PLATFORM (self), err_val); \
|
||||||
|
klass = NM_PLATFORM_GET_CLASS (self); \
|
||||||
|
(void) klass; \
|
||||||
|
if (!nm_platform_netns_push (self, &netns)) \
|
||||||
|
return (err_val); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nm_platform_setup:
|
* nm_platform_setup:
|
||||||
* @instance: the #NMPlatform instance
|
* @instance: the #NMPlatform instance
|
||||||
@@ -2470,25 +2481,25 @@ _to_string_ifa_flags (guint32 ifa_flags, char *buf, gsize size)
|
|||||||
gboolean
|
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, const char *ifname, NMSettingWiredWakeOnLan wol, const char *wol_password)
|
||||||
{
|
{
|
||||||
nm_auto_pop_netns NMPNetns *netns = NULL;
|
_CHECK_SELF_NETNS (self, klass, netns, FALSE);
|
||||||
_CHECK_SELF (self, klass, FALSE);
|
|
||||||
|
|
||||||
if (!nm_platform_netns_push (self, &netns))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
return nmp_utils_ethtool_set_wake_on_lan (ifname, wol, wol_password);
|
return nmp_utils_ethtool_set_wake_on_lan (ifname, wol, wol_password);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
nm_platform_ethtool_get_link_speed (NMPlatform *self, const char *ifname, guint32 *out_speed)
|
nm_platform_ethtool_set_link_settings (NMPlatform *self, const char *ifname, gboolean autoneg, guint32 speed, NMPlatformLinkDuplexType duplex)
|
||||||
{
|
{
|
||||||
nm_auto_pop_netns NMPNetns *netns = NULL;
|
_CHECK_SELF_NETNS (self, klass, netns, FALSE);
|
||||||
_CHECK_SELF (self, klass, FALSE);
|
|
||||||
|
|
||||||
if (!nm_platform_netns_push (self, &netns))
|
return nmp_utils_ethtool_set_link_settings (ifname, autoneg, speed, duplex);
|
||||||
return FALSE;
|
}
|
||||||
|
|
||||||
return nmp_utils_ethtool_get_link_speed (ifname, out_speed);
|
gboolean
|
||||||
|
nm_platform_ethtool_get_link_settings (NMPlatform *self, const char *ifname, 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
@@ -481,6 +481,13 @@ typedef struct {
|
|||||||
bool multi_queue:1;
|
bool multi_queue:1;
|
||||||
} NMPlatformTunProperties;
|
} NMPlatformTunProperties;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NM_PLATFORM_LINK_DUPLEX_UNSET = 0,
|
||||||
|
NM_PLATFORM_LINK_DUPLEX_HALF,
|
||||||
|
NM_PLATFORM_LINK_DUPLEX_FULL,
|
||||||
|
NM_PLATFORM_LINK_DUPLEX_UNKNOWN,
|
||||||
|
} NMPlatformLinkDuplexType;
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
struct _NMPlatformPrivate;
|
struct _NMPlatformPrivate;
|
||||||
@@ -975,6 +982,7 @@ 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);
|
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_wake_on_lan (NMPlatform *self, const char *ifname, NMSettingWiredWakeOnLan wol, const char *wol_password);
|
||||||
gboolean nm_platform_ethtool_get_link_speed (NMPlatform *self, const char *ifname, guint32 *out_speed);
|
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);
|
||||||
|
|
||||||
#endif /* __NETWORKMANAGER_PLATFORM_H__ */
|
#endif /* __NETWORKMANAGER_PLATFORM_H__ */
|
||||||
|
Reference in New Issue
Block a user