device/ethernet: check and apply link negotiation properties
This will allow to enforce link mode (autonegotiation, speed and duplex) as specified in 802-3-ethernet properties.
This commit is contained in:
@@ -782,6 +782,97 @@ supplicant_interface_init (NMDeviceEthernet *self)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
link_duplex_to_string (NMPlatformLinkDuplexType duplex)
|
||||||
|
{
|
||||||
|
switch (duplex) {
|
||||||
|
case NM_PLATFORM_LINK_DUPLEX_FULL:
|
||||||
|
return "full";
|
||||||
|
break;
|
||||||
|
case NM_PLATFORM_LINK_DUPLEX_HALF:
|
||||||
|
return "half";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return "unknown";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static NMPlatformLinkDuplexType
|
||||||
|
link_duplex_to_platform (const char *duplex)
|
||||||
|
{
|
||||||
|
if (!duplex)
|
||||||
|
return NM_PLATFORM_LINK_DUPLEX_UNSET;
|
||||||
|
|
||||||
|
if (nm_streq (duplex, "full"))
|
||||||
|
return NM_PLATFORM_LINK_DUPLEX_FULL;
|
||||||
|
|
||||||
|
if (nm_streq (duplex, "half"))
|
||||||
|
return NM_PLATFORM_LINK_DUPLEX_HALF;
|
||||||
|
|
||||||
|
return NM_PLATFORM_LINK_DUPLEX_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
link_negotiation_set (NMDevice *device)
|
||||||
|
{
|
||||||
|
NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device);
|
||||||
|
NMSettingWired *s_wired;
|
||||||
|
gboolean autoneg = TRUE, link_autoneg;
|
||||||
|
NMPlatformLinkDuplexType link_duplex, duplex = NM_PLATFORM_LINK_DUPLEX_UNSET;
|
||||||
|
guint32 speed = 0, link_speed;
|
||||||
|
|
||||||
|
s_wired = (NMSettingWired *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_WIRED);
|
||||||
|
if (s_wired) {
|
||||||
|
autoneg = nm_setting_wired_get_auto_negotiate (s_wired);
|
||||||
|
if (!autoneg) {
|
||||||
|
speed = nm_setting_wired_get_speed (s_wired);
|
||||||
|
duplex = link_duplex_to_platform (nm_setting_wired_get_duplex (s_wired));
|
||||||
|
if (!speed && !duplex) {
|
||||||
|
_LOGD (LOGD_DEVICE, "set-link: ignore link negotiation");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nm_platform_ethtool_get_link_settings (NM_PLATFORM_GET, nm_device_get_iface (device),
|
||||||
|
&link_autoneg, &link_speed, &link_duplex)) {
|
||||||
|
_LOGW (LOGD_DEVICE, "set-link: unable to retrieve link negotiation");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If link negotiation setting are already in place do nothing and return with success */
|
||||||
|
if (autoneg != link_autoneg)
|
||||||
|
goto set_link;
|
||||||
|
|
||||||
|
if (speed && (speed != link_speed))
|
||||||
|
goto set_link;
|
||||||
|
|
||||||
|
if (duplex && (duplex != link_duplex))
|
||||||
|
goto set_link;
|
||||||
|
|
||||||
|
_LOGW (LOGD_DEVICE, "set-link: link negotiation is already configured");
|
||||||
|
return;
|
||||||
|
|
||||||
|
set_link:
|
||||||
|
if (!nm_platform_ethtool_set_link_settings (NM_PLATFORM_GET,
|
||||||
|
nm_device_get_iface (device),
|
||||||
|
autoneg,
|
||||||
|
speed,
|
||||||
|
duplex)) {
|
||||||
|
_LOGW (LOGD_DEVICE, "set-link: failure to set link negotiation");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (autoneg)
|
||||||
|
_LOGD (LOGD_DEVICE, "set-link: configure autonegotiation");
|
||||||
|
else {
|
||||||
|
_LOGD (LOGD_DEVICE, "set-link: configure static negotiation (%u Mbit - %s duplex)",
|
||||||
|
speed ?: link_speed,
|
||||||
|
duplex ? link_duplex_to_string (duplex) : link_duplex_to_string (link_duplex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
pppoe_reconnect_delay (gpointer user_data)
|
pppoe_reconnect_delay (gpointer user_data)
|
||||||
{
|
{
|
||||||
@@ -807,6 +898,8 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
|
|||||||
if (ret != NM_ACT_STAGE_RETURN_SUCCESS)
|
if (ret != NM_ACT_STAGE_RETURN_SUCCESS)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
link_negotiation_set (dev);
|
||||||
|
|
||||||
if (!nm_device_hw_addr_set_cloned (dev, nm_device_get_applied_connection (dev), FALSE))
|
if (!nm_device_hw_addr_set_cloned (dev, nm_device_get_applied_connection (dev), FALSE))
|
||||||
return NM_ACT_STAGE_RETURN_FAILURE;
|
return NM_ACT_STAGE_RETURN_FAILURE;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user