wired: emit Speed value in PropertiesChanged signal, when changed (bgo #667091)

Speed is gotten via ethtool on 'carrier on' event. If there is a more suitable
netlink event we should use it instead. Nonetheless, it appears to be working
fine with carrier change, because interface speed change does emit carrier offi
and on events.
This commit is contained in:
Jiří Klimeš
2012-01-17 14:30:45 +01:00
parent f12c326ff2
commit 9f75f91f3a
3 changed files with 92 additions and 47 deletions

View File

@@ -15,7 +15,7 @@
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* *
* Copyright (C) 2005 - 2011 Red Hat, Inc. * Copyright (C) 2005 - 2012 Red Hat, Inc.
* Copyright (C) 2006 - 2008 Novell, Inc. * Copyright (C) 2006 - 2008 Novell, Inc.
*/ */
@@ -24,11 +24,8 @@
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <string.h> #include <string.h>
#include <net/ethernet.h>
#include <stdlib.h> #include <stdlib.h>
#include <linux/types.h>
#include <linux/sockios.h> #include <linux/sockios.h>
#include <linux/version.h>
#include <linux/ethtool.h> #include <linux/ethtool.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <unistd.h> #include <unistd.h>
@@ -407,46 +404,6 @@ nm_device_ethernet_new (const char *udi,
NULL); NULL);
} }
/* Returns speed in Mb/s */
static guint32
nm_device_ethernet_get_speed (NMDeviceEthernet *self)
{
int fd;
struct ifreq ifr;
struct ethtool_cmd edata = {
.cmd = ETHTOOL_GSET,
};
guint32 speed = 0;
g_return_val_if_fail (self != NULL, 0);
fd = socket (PF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
nm_log_warn (LOGD_HW, "couldn't open control socket.");
return 0;
}
memset (&ifr, 0, sizeof (struct ifreq));
strncpy (ifr.ifr_name, nm_device_get_iface (NM_DEVICE (self)), IFNAMSIZ);
ifr.ifr_data = (char *) &edata;
if (ioctl (fd, SIOCETHTOOL, &ifr) < 0)
goto out;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
speed = edata.speed;
#else
speed = ethtool_cmd_speed (&edata);
#endif
if (speed == G_MAXUINT16 || speed == G_MAXUINT32)
speed = 0;
out:
close (fd);
return speed;
}
static void static void
_update_hw_addr (NMDeviceEthernet *self, const guint8 *addr) _update_hw_addr (NMDeviceEthernet *self, const guint8 *addr)
{ {
@@ -1541,7 +1498,7 @@ get_property (GObject *object, guint prop_id,
g_value_take_string (value, nm_utils_hwaddr_ntoa (&priv->perm_hw_addr, ARPHRD_ETHER)); g_value_take_string (value, nm_utils_hwaddr_ntoa (&priv->perm_hw_addr, ARPHRD_ETHER));
break; break;
case PROP_SPEED: case PROP_SPEED:
g_value_set_uint (value, nm_device_ethernet_get_speed (self)); g_value_set_uint (value, nm_device_wired_get_speed (NM_DEVICE_WIRED (self)));
break; break;
case PROP_CARRIER: case PROP_CARRIER:
g_value_set_boolean (value, nm_device_wired_get_carrier (NM_DEVICE_WIRED (self))); g_value_set_boolean (value, nm_device_wired_get_carrier (NM_DEVICE_WIRED (self)));

View File

@@ -15,7 +15,7 @@
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* *
* Copyright (C) 2005 - 2011 Red Hat, Inc. * Copyright (C) 2005 - 2012 Red Hat, Inc.
* Copyright (C) 2006 - 2008 Novell, Inc. * Copyright (C) 2006 - 2008 Novell, Inc.
*/ */
@@ -25,6 +25,11 @@
#include <linux/if.h> #include <linux/if.h>
#include <linux/if_infiniband.h> #include <linux/if_infiniband.h>
#include <netinet/ether.h> #include <netinet/ether.h>
#include <linux/sockios.h>
#include <linux/version.h>
#include <linux/ethtool.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include "nm-device-wired.h" #include "nm-device-wired.h"
#include "nm-device-private.h" #include "nm-device-private.h"
@@ -48,6 +53,7 @@ typedef struct {
guint hw_addr_type; guint hw_addr_type;
guint hw_addr_len; guint hw_addr_len;
gboolean carrier; gboolean carrier;
guint32 speed;
NMNetlinkMonitor * monitor; NMNetlinkMonitor * monitor;
gulong link_connected_id; gulong link_connected_id;
@@ -56,6 +62,67 @@ typedef struct {
} NMDeviceWiredPrivate; } NMDeviceWiredPrivate;
/* Returns speed in Mb/s */
static guint32
ethtool_get_speed (NMDeviceWired *self)
{
int fd;
struct ifreq ifr;
struct ethtool_cmd edata = {
.cmd = ETHTOOL_GSET,
};
guint32 speed = 0;
g_return_val_if_fail (self != NULL, 0);
fd = socket (PF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
nm_log_warn (LOGD_HW, "couldn't open control socket.");
return 0;
}
memset (&ifr, 0, sizeof (struct ifreq));
strncpy (ifr.ifr_name, nm_device_get_iface (NM_DEVICE (self)), IFNAMSIZ);
ifr.ifr_data = (char *) &edata;
if (ioctl (fd, SIOCETHTOOL, &ifr) < 0)
goto out;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
speed = edata.speed;
#else
speed = ethtool_cmd_speed (&edata);
#endif
if (speed == G_MAXUINT16 || speed == G_MAXUINT32)
speed = 0;
out:
close (fd);
return speed;
}
static void
set_speed (NMDeviceWired *self, const guint32 speed)
{
NMDeviceWiredPrivate *priv;
g_return_if_fail (NM_IS_DEVICE (self));
priv = NM_DEVICE_WIRED_GET_PRIVATE (self);
if (priv->speed == speed)
return;
priv->speed = speed;
g_object_notify (G_OBJECT (self), "speed");
nm_log_dbg (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (NM_DEVICE (self)),
"(%s): speed is now %d Mb/s",
nm_device_get_iface (NM_DEVICE (self)),
speed);
}
static void static void
carrier_action_defer_clear (NMDeviceWired *self) carrier_action_defer_clear (NMDeviceWired *self)
{ {
@@ -139,6 +206,7 @@ carrier_on (NMNetlinkMonitor *monitor,
return; return;
set_carrier (self, TRUE, FALSE); set_carrier (self, TRUE, FALSE);
set_speed (self, ethtool_get_speed (self));
} }
} }
@@ -542,3 +610,22 @@ nm_device_wired_get_carrier (NMDeviceWired *dev)
priv = NM_DEVICE_WIRED_GET_PRIVATE (dev); priv = NM_DEVICE_WIRED_GET_PRIVATE (dev);
return priv->carrier; return priv->carrier;
} }
/**
* nm_device_wired_get_speed:
* @dev: an #NMDeviceWired
*
* Get @dev's speed
*
* Return value: @dev's speed in Mb/s
*/
guint32
nm_device_wired_get_speed (NMDeviceWired *dev)
{
NMDeviceWiredPrivate *priv;
g_return_val_if_fail (dev != NULL, 0);
priv = NM_DEVICE_WIRED_GET_PRIVATE (dev);
return priv->speed;
}

View File

@@ -15,7 +15,7 @@
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* *
* Copyright (C) 2005 - 2010 Red Hat, Inc. * Copyright (C) 2005 - 2012 Red Hat, Inc.
* Copyright (C) 2006 - 2008 Novell, Inc. * Copyright (C) 2006 - 2008 Novell, Inc.
*/ */
@@ -49,6 +49,7 @@ GType nm_device_wired_get_type (void);
guint8 *nm_device_wired_get_hwaddr (NMDeviceWired *dev); guint8 *nm_device_wired_get_hwaddr (NMDeviceWired *dev);
int nm_device_wired_get_hwaddr_type (NMDeviceWired *dev); int nm_device_wired_get_hwaddr_type (NMDeviceWired *dev);
gboolean nm_device_wired_get_carrier (NMDeviceWired *dev); gboolean nm_device_wired_get_carrier (NMDeviceWired *dev);
guint32 nm_device_wired_get_speed (NMDeviceWired *dev);
G_END_DECLS G_END_DECLS