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);
|
||||
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;
|
||||
if (priv->speed == speed)
|
||||
return;
|
||||
|
@@ -40,6 +40,13 @@
|
||||
/******************************************************************
|
||||
* 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
|
||||
ethtool_get (const char *name, gpointer edata)
|
||||
@@ -261,29 +268,85 @@ nmp_utils_ethtool_get_wake_on_lan (const char *ifname)
|
||||
}
|
||||
|
||||
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 = {
|
||||
.cmd = ETHTOOL_GSET,
|
||||
};
|
||||
guint32 speed;
|
||||
|
||||
if (!ethtool_get (ifname, &edata))
|
||||
return FALSE;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
|
||||
speed = edata.speed;
|
||||
#else
|
||||
if (out_autoneg)
|
||||
*out_autoneg = (edata.autoneg == AUTONEG_ENABLE);
|
||||
|
||||
if (out_speed) {
|
||||
guint32 speed;
|
||||
|
||||
speed = ethtool_cmd_speed (&edata);
|
||||
#endif
|
||||
if (speed == G_MAXUINT16 || speed == G_MAXUINT32)
|
||||
speed = 0;
|
||||
|
||||
if (out_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;
|
||||
}
|
||||
|
||||
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
|
||||
nmp_utils_ethtool_set_wake_on_lan (const char *ifname,
|
||||
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,
|
||||
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,
|
||||
char **out_driver_name,
|
||||
|
@@ -134,6 +134,17 @@ NM_DEFINE_SINGLETON_REGISTER (NMPlatform);
|
||||
(void) klass; \
|
||||
} 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:
|
||||
* @instance: the #NMPlatform instance
|
||||
@@ -2470,25 +2481,25 @@ _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_auto_pop_netns NMPNetns *netns = NULL;
|
||||
_CHECK_SELF (self, klass, FALSE);
|
||||
|
||||
if (!nm_platform_netns_push (self, &netns))
|
||||
return FALSE;
|
||||
_CHECK_SELF_NETNS (self, klass, netns, FALSE);
|
||||
|
||||
return nmp_utils_ethtool_set_wake_on_lan (ifname, wol, wol_password);
|
||||
}
|
||||
|
||||
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 (self, klass, FALSE);
|
||||
_CHECK_SELF_NETNS (self, klass, netns, FALSE);
|
||||
|
||||
if (!nm_platform_netns_push (self, &netns))
|
||||
return FALSE;
|
||||
return nmp_utils_ethtool_set_link_settings (ifname, autoneg, speed, duplex);
|
||||
}
|
||||
|
||||
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;
|
||||
} 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;
|
||||
@@ -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);
|
||||
|
||||
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__ */
|
||||
|
Reference in New Issue
Block a user