all: merge branch 'th/device-statistics'

Add support to expose tx/rx statistics per device

https://mail.gnome.org/archives/networkmanager-list/2016-August/msg00045.html
This commit is contained in:
Thomas Haller
2016-08-17 16:13:16 +02:00
21 changed files with 304 additions and 14 deletions

View File

@@ -439,6 +439,8 @@ permission_to_string (NMClientPermission perm)
return NM_AUTH_PERMISSION_RELOAD;
case NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK:
return NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK;
case NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS:
return NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS;
default:
return _("unknown");
}

View File

@@ -73,6 +73,7 @@ content_files = \
$(top_builddir)/introspection/nmdbus-settings-org.freedesktop.NetworkManager.Settings.xml \
$(top_builddir)/introspection/nmdbus-device-ethernet-org.freedesktop.NetworkManager.Device.Wired.xml \
$(top_builddir)/introspection/nmdbus-ip4-config-org.freedesktop.NetworkManager.IP4Config.xml \
$(top_builddir)/introspection/nmdbus-device-statistics-org.freedesktop.NetworkManager.Device.Statistics.xml \
$(top_builddir)/libnm-core/nm-dbus-types.xml \
$(top_builddir)/libnm-core/nm-vpn-dbus-types.xml \
$(top_builddir)/man/nmcli.xml \

View File

@@ -98,6 +98,7 @@
<xi:include href="../../introspection/nmdbus-ip6-config-org.freedesktop.NetworkManager.IP6Config.xml"/>
<xi:include href="../../introspection/nmdbus-vpn-plugin-org.freedesktop.NetworkManager.VPN.Plugin.xml"/>
<xi:include href="../../introspection/nmdbus-secret-agent-org.freedesktop.NetworkManager.SecretAgent.xml"/>
<xi:include href="../../introspection/nmdbus-device-statistics-org.freedesktop.NetworkManager.Device.Statistics.xml"/>
</section>
<section id="dbus-types">
<title>Types</title>

View File

@@ -43,6 +43,8 @@ nodist_libnmdbus_la_SOURCES = \
nmdbus-device-modem.h \
nmdbus-device-olpc-mesh.c \
nmdbus-device-olpc-mesh.h \
nmdbus-device-statistics.c \
nmdbus-device-statistics.h \
nmdbus-device-team.c \
nmdbus-device-team.h \
nmdbus-device-tun.c \
@@ -114,7 +116,8 @@ DBUS_INTERFACE_DOCS = \
nmdbus-device-veth-org.freedesktop.NetworkManager.Device.Veth.xml \
nmdbus-settings-org.freedesktop.NetworkManager.Settings.xml \
nmdbus-device-ethernet-org.freedesktop.NetworkManager.Device.Wired.xml \
nmdbus-ip4-config-org.freedesktop.NetworkManager.IP4Config.xml
nmdbus-ip4-config-org.freedesktop.NetworkManager.IP4Config.xml \
nmdbus-device-statistics-org.freedesktop.NetworkManager.Device.Statistics.xml
define _make_nmdbus_rule
$(1): $(patsubst nmdbus-%.c,nm-%.xml,$(1))
@@ -154,6 +157,7 @@ EXTRA_DIST = \
nm-device-macvlan.xml \
nm-device-modem.xml \
nm-device-olpc-mesh.xml \
nm-device-statistics.xml \
nm-device-team.xml \
nm-device-tun.xml \
nm-device-veth.xml \

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/">
<interface name="org.freedesktop.NetworkManager.Device.Statistics">
<!--
RefreshRateMs:
Refresh rate of the rest of properties of this interface. The properties
are guaranteed to be refreshed each RefreshRateMs milliseconds in case
the underlying counter has changed too.
If zero, there is no guaranteed refresh rate of the properties.
-->
<property name="RefreshRateMs" type="u" access="readwrite"/>
<!--
TxBytes:
Number of transmitted bytes
-->
<property name="TxBytes" type="t" access="read"/>
<!--
RxBytes:
Number of received bytes
-->
<property name="RxBytes" type="t" access="read"/>
<!--
PropertiesChanged:
@properties: A dictionary mapping property names to variant boxed values
-->
<signal name="PropertiesChanged">
<arg name="properties" type="a{sv}"/>
</signal>
</interface>
</node>

View File

@@ -68,6 +68,7 @@
#define NM_DBUS_INTERFACE_DEVICE_VXLAN NM_DBUS_INTERFACE_DEVICE ".Vxlan"
#define NM_DBUS_INTERFACE_DEVICE_GRE NM_DBUS_INTERFACE_DEVICE ".Gre"
#define NM_DBUS_INTERFACE_DEVICE_IP_TUNNEL NM_DBUS_INTERFACE_DEVICE ".IPTunnel"
#define NM_DBUS_INTERFACE_DEVICE_STATISTICS NM_DBUS_INTERFACE_DEVICE ".Statistics"
#define NM_DBUS_INTERFACE_SETTINGS "org.freedesktop.NetworkManager.Settings"
#define NM_DBUS_PATH_SETTINGS "/org/freedesktop/NetworkManager/Settings"

View File

@@ -240,6 +240,8 @@ nm_permission_to_client (const char *nm)
return NM_CLIENT_PERMISSION_RELOAD;
else if (!strcmp (nm, NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK))
return NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK;
else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS))
return NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS;
return NM_CLIENT_PERMISSION_NONE;
}

View File

@@ -89,6 +89,8 @@ G_BEGIN_DECLS
* @NM_CLIENT_PERMISSION_RELOAD: controls access to Reload.
* persistent hostname can be changed
* @NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK: permission to create checkpoints.
* @NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS: controls whether device
* statistics can be globally enabled or disabled
* @NM_CLIENT_PERMISSION_LAST: a reserved boundary value
*
* #NMClientPermission values indicate various permissions that NetworkManager
@@ -110,8 +112,9 @@ typedef enum {
NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS = 12,
NM_CLIENT_PERMISSION_RELOAD = 13,
NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK = 14,
NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS = 15,
NM_CLIENT_PERMISSION_LAST = 14,
NM_CLIENT_PERMISSION_LAST = 15,
} NMClientPermission;
/**

View File

@@ -98,6 +98,8 @@ G_BEGIN_DECLS
* DNS configuration
* @NM_CLIENT_PERMISSION_RELOAD: controls access to Reload.
* @NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK: permission to create checkpoints.
* @NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS: controls whether device
* statistics can be globally enabled or disabled
* @NM_CLIENT_PERMISSION_LAST: a reserved boundary value
*
* #NMClientPermission values indicate various permissions that NetworkManager
@@ -119,8 +121,9 @@ typedef enum {
NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS = 12,
NM_CLIENT_PERMISSION_RELOAD = 13,
NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK = 14,
NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS = 15,
NM_CLIENT_PERMISSION_LAST = 14,
NM_CLIENT_PERMISSION_LAST = 15,
} NMClientPermission;
/**

View File

@@ -234,6 +234,8 @@ nm_permission_to_client (const char *nm)
return NM_CLIENT_PERMISSION_RELOAD;
else if (!strcmp (nm, NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK))
return NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK;
else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS))
return NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS;
return NM_CLIENT_PERMISSION_NONE;
}

View File

@@ -142,5 +142,14 @@
</defaults>
</action>
<action id="org.freedesktop.NetworkManager.enable-disable-statistics">
<_description>Enable or disable device statistics</_description>
<_message>System policy prevents enabling or disabling device statistics</_message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>
</policyconfig>

View File

@@ -38,6 +38,7 @@
#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS "org.freedesktop.NetworkManager.settings.modify.global-dns"
#define NM_AUTH_PERMISSION_RELOAD "org.freedesktop.NetworkManager.reload"
#define NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK "org.freedesktop.NetworkManager.checkpoint-rollback"
#define NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS "org.freedesktop.NetworkManager.enable-disable-statistics"
#define NM_CLONED_MAC_PRESERVE "preserve"
#define NM_CLONED_MAC_PERMANENT "permanent"

View File

@@ -71,6 +71,7 @@
_LOG_DECLARE_SELF (NMDevice);
#include "nmdbus-device.h"
#include "nmdbus-device-statistics.h"
G_DEFINE_ABSTRACT_TYPE (NMDevice, nm_device, NM_TYPE_EXPORTED_OBJECT)
@@ -138,6 +139,9 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDevice,
PROP_LLDP_NEIGHBORS,
PROP_REAL,
PROP_SLAVES,
PROP_REFRESH_RATE_MS,
PROP_TX_BYTES,
PROP_RX_BYTES,
);
#define DEFAULT_AUTOCONNECT TRUE
@@ -407,6 +411,14 @@ typedef struct _NMDevicePrivate {
NMLldpListener *lldp_listener;
guint check_delete_unrealized_id;
struct {
guint timeout_id;
guint refresh_rate_ms;
guint64 tx_bytes;
guint64 rx_bytes;
} stats;
} NMDevicePrivate;
static gboolean nm_device_set_ip4_config (NMDevice *self,
@@ -769,6 +781,108 @@ nm_device_set_ip_iface (NMDevice *self, const char *iface)
g_free (old_ip_iface);
}
/*****************************************************************************/
static void
_stats_update_counters (NMDevice *self,
guint64 tx_bytes,
guint64 rx_bytes)
{
NMDevicePrivate *priv;
priv = NM_DEVICE_GET_PRIVATE (self);
if (priv->stats.tx_bytes != tx_bytes) {
priv->stats.tx_bytes = tx_bytes;
_notify (self, PROP_TX_BYTES);
}
if (priv->stats.rx_bytes != rx_bytes) {
priv->stats.rx_bytes = rx_bytes;
_notify (self, PROP_RX_BYTES);
}
}
static void
_stats_update_counters_from_pllink (NMDevice *self, const NMPlatformLink *pllink)
{
_stats_update_counters (self, pllink->tx_bytes, pllink->rx_bytes);
}
static gboolean
_stats_timeout_cb (gpointer user_data)
{
NMDevice *self = user_data;
int ifindex;
ifindex = nm_device_get_ip_ifindex (self);
_LOGT (LOGD_DEVICE, "stats: refresh %d", ifindex);
if (ifindex > 0)
nm_platform_link_refresh (NM_PLATFORM_GET, ifindex);
return G_SOURCE_CONTINUE;
}
static guint
_stats_refresh_rate_real (guint refresh_rate_ms)
{
const guint STATS_REFRESH_RATE_MS_MIN = 200;
if (refresh_rate_ms == 0)
return 0;
if (refresh_rate_ms < STATS_REFRESH_RATE_MS_MIN) {
/* you cannot set the refresh-rate arbitrarly small. E.g.
* setting to 1ms is just killing. Have a lowest number. */
return STATS_REFRESH_RATE_MS_MIN;
}
return refresh_rate_ms;
}
static void
_stats_set_refresh_rate (NMDevice *self, guint refresh_rate_ms)
{
NMDevicePrivate *priv;
int ifindex;
guint old_rate;
priv = NM_DEVICE_GET_PRIVATE (self);
if (priv->stats.refresh_rate_ms == refresh_rate_ms)
return;
old_rate = priv->stats.refresh_rate_ms;
priv->stats.refresh_rate_ms = refresh_rate_ms;
_notify (self, PROP_REFRESH_RATE_MS);
_LOGD (LOGD_DEVICE, "stats: set refresh to %u ms", priv->stats.refresh_rate_ms);
if (!nm_device_is_real (self))
return;
refresh_rate_ms = _stats_refresh_rate_real (refresh_rate_ms);
if (_stats_refresh_rate_real (old_rate) == refresh_rate_ms)
return;
nm_clear_g_source (&priv->stats.timeout_id);
if (!refresh_rate_ms)
return;
/* trigger an inital refresh of the data whenever the refresh-rate changes.
* As we process the result in an idle handler with device_link_changed(),
* we don't get the result right away. */
ifindex = nm_device_get_ip_ifindex (self);
if (ifindex > 0)
nm_platform_link_refresh (NM_PLATFORM_GET, ifindex);
priv->stats.timeout_id = g_timeout_add (refresh_rate_ms, _stats_timeout_cb, self);
}
/*****************************************************************************/
static gboolean
get_ip_iface_identifier (NMDevice *self, NMUtilsIPv6IfaceId *out_iid)
{
@@ -1712,6 +1826,9 @@ device_link_changed (NMDevice *self)
_notify (self, PROP_DRIVER);
}
if (ifindex == nm_device_get_ip_ifindex (self))
_stats_update_counters_from_pllink (self, &info);
had_hw_addr = (priv->hw_addr != NULL);
nm_device_update_hw_address (self);
got_hw_addr = (!had_hw_addr && priv->hw_addr);
@@ -1840,6 +1957,8 @@ device_ip_link_changed (NMDevice *self)
if (!pllink)
return G_SOURCE_REMOVE;
_stats_update_counters_from_pllink (self, pllink);
if (pllink->name[0] && g_strcmp0 (priv->ip_iface, pllink->name)) {
_LOGI (LOGD_DEVICE, "interface index %d renamed ip_iface (%d) from '%s' to '%s'",
priv->ifindex, nm_device_get_ip_ifindex (self),
@@ -1850,6 +1969,7 @@ device_ip_link_changed (NMDevice *self)
_notify (self, PROP_IP_IFACE);
nm_device_update_dynamic_ip_setup (self);
}
return G_SOURCE_REMOVE;
}
@@ -1955,6 +2075,8 @@ nm_device_realize_start (NMDevice *self,
gboolean *out_compatible,
GError **error)
{
NMPlatformLink plink_copy;
NM_SET_OUT (out_compatible, TRUE);
if (plink) {
@@ -1969,6 +2091,10 @@ nm_device_realize_start (NMDevice *self,
return FALSE;
}
if (plink) {
plink_copy = *plink;
plink = &plink_copy;
}
realize_start_setup (self, plink);
return TRUE;
@@ -2102,6 +2228,7 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink)
static guint32 id = 0;
NMDeviceCapabilities capabilities = 0;
NMConfig *config;
guint real_rate;
g_return_if_fail (NM_IS_DEVICE (self));
@@ -2125,6 +2252,7 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink)
if (plink) {
g_return_if_fail (link_type_compatible (self, plink->type, NULL, NULL));
update_device_from_platform_link (self, plink);
_stats_update_counters_from_pllink (self, plink);
}
if (priv->ifindex > 0) {
@@ -2193,6 +2321,11 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink)
priv->carrier = TRUE;
}
nm_assert (!priv->stats.timeout_id);
real_rate = _stats_refresh_rate_real (priv->stats.refresh_rate_ms);
if (real_rate)
priv->stats.timeout_id = g_timeout_add (real_rate, _stats_timeout_cb, self);
klass->realize_start_notify (self, plink);
/* Do not manage externally created software devices until they are IFF_UP
@@ -2365,6 +2498,9 @@ nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error)
_notify (self, PROP_PHYSICAL_PORT_ID);
}
nm_clear_g_source (&priv->stats.timeout_id);
_stats_update_counters (self, 0, 0);
priv->hw_addr_type = HW_ADDR_TYPE_UNSET;
g_clear_pointer (&priv->hw_addr_perm, g_free);
_notify (self, PROP_PERM_HW_ADDRESS);
@@ -12080,6 +12216,8 @@ dispose (GObject *object)
nm_clear_g_source (&priv->check_delete_unrealized_id);
nm_clear_g_source (&priv->stats.timeout_id);
link_disconnect_action_cancel (self);
if (priv->settings) {
@@ -12237,6 +12375,9 @@ set_property (GObject *object, guint prop_id,
/* construct only */
priv->hw_addr_perm = g_value_dup_string (value);
break;
case PROP_REFRESH_RATE_MS:
_stats_set_refresh_rate (self, g_value_get_uint (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -12399,6 +12540,15 @@ get_property (GObject *object, guint prop_id,
g_value_take_boxed (value, slave_list);
break;
}
case PROP_REFRESH_RATE_MS:
g_value_set_uint (value, priv->stats.refresh_rate_ms);
break;
case PROP_TX_BYTES:
g_value_set_uint64 (value, priv->stats.tx_bytes);
break;
case PROP_RX_BYTES:
g_value_set_uint64 (value, priv->stats.rx_bytes);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -12649,6 +12799,23 @@ nm_device_class_init (NMDeviceClass *klass)
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS);
/* Statistics */
obj_properties[PROP_REFRESH_RATE_MS] =
g_param_spec_uint (NM_DEVICE_STATISTICS_REFRESH_RATE_MS, "", "",
0, UINT32_MAX, 0,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS);
obj_properties[PROP_TX_BYTES] =
g_param_spec_uint64 (NM_DEVICE_STATISTICS_TX_BYTES, "", "",
0, UINT64_MAX, 0,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS);
obj_properties[PROP_RX_BYTES] =
g_param_spec_uint64 (NM_DEVICE_STATISTICS_RX_BYTES, "", "",
0, UINT64_MAX, 0,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
/* Signals */
@@ -12719,4 +12886,8 @@ nm_device_class_init (NMDeviceClass *klass)
"Disconnect", impl_device_disconnect,
"Delete", impl_device_delete,
NULL);
nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass),
NMDBUS_TYPE_DEVICE_STATISTICS_SKELETON,
NULL);
}

View File

@@ -88,6 +88,10 @@
#define NM_DEVICE_STATE_CHANGED "state-changed"
#define NM_DEVICE_LINK_INITIALIZED "link-initialized"
#define NM_DEVICE_STATISTICS_REFRESH_RATE_MS "refresh-rate-ms"
#define NM_DEVICE_STATISTICS_TX_BYTES "tx-bytes"
#define NM_DEVICE_STATISTICS_RX_BYTES "rx-bytes"
G_BEGIN_DECLS
#define NM_TYPE_DEVICE (nm_device_get_type ())

View File

@@ -57,6 +57,7 @@ typedef struct {
#define NM_AUDIT_OP_SLEEP_CONTROL "sleep-control"
#define NM_AUDIT_OP_NET_CONTROL "networking-control"
#define NM_AUDIT_OP_RADIO_CONTROL "radio-control"
#define NM_AUDIT_OP_STATISTICS "statistics"
#define NM_AUDIT_OP_DEVICE_AUTOCONNECT "device-autoconnect"
#define NM_AUDIT_OP_DEVICE_DISCONNECT "device-disconnect"

View File

@@ -257,12 +257,16 @@ nm_exported_object_class_add_interface (NMExportedObjectClass *object_class,
g_return_if_fail (NM_IS_EXPORTED_OBJECT_CLASS (object_class));
g_return_if_fail (g_type_is_a (dbus_skeleton_type, G_TYPE_DBUS_INTERFACE_SKELETON));
classinfo = g_type_get_qdata (G_TYPE_FROM_CLASS (object_class),
nm_exported_object_class_info_quark ());
if (!classinfo) {
classinfo = g_slice_new (NMExportedObjectClassInfo);
classinfo->skeleton_types = NULL;
classinfo->methods = g_array_new (FALSE, FALSE, sizeof (NMExportedObjectDBusMethodImpl));
classinfo->properties = g_hash_table_new (g_str_hash, g_str_equal);
g_type_set_qdata (G_TYPE_FROM_CLASS (object_class),
nm_exported_object_class_info_quark (), classinfo);
}
classinfo->skeleton_types = g_slist_prepend (classinfo->skeleton_types,
GSIZE_TO_POINTER (dbus_skeleton_type));
@@ -342,8 +346,6 @@ nm_exported_object_class_add_interface (NMExportedObjectClass *object_class,
}
}
g_assert_cmpint (n_method_signals, ==, classinfo->methods->len);
g_type_class_unref (dbus_object_class);
}

View File

@@ -4415,6 +4415,7 @@ get_permissions_done_cb (NMAuthChain *chain,
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_RELOAD);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS);
g_dbus_method_invocation_return_value (context,
g_variant_new ("(a{ss})", &results));
@@ -4455,6 +4456,7 @@ impl_manager_get_permissions (NMManager *self,
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS, FALSE);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_RELOAD, FALSE);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK, FALSE);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS, FALSE);
}
static void
@@ -4915,6 +4917,10 @@ prop_set_auth_done_cb (NMAuthChain *chain,
/* ... but set the property on the @object itself. It would be correct to set the property
* on the skeleton interface, but as it is now, the result is the same. */
g_object_set (object, pfd->glib_propname, value, NULL);
} else if (!strcmp (pfd->glib_propname, NM_DEVICE_STATISTICS_REFRESH_RATE_MS)) {
g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32));
/* the same here */
g_object_set (object, pfd->glib_propname, (guint) g_variant_get_uint32 (value), NULL);
} else {
g_assert (g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN));
/* the same here */
@@ -5049,6 +5055,15 @@ prop_filter (GDBusConnection *connection,
} else
return message;
interface_type = NMDBUS_TYPE_DEVICE_SKELETON;
} else if (!strcmp (propiface, NM_DBUS_INTERFACE_DEVICE_STATISTICS)) {
if (!strcmp (propname, "RefreshRateMs")) {
glib_propname = NM_DEVICE_STATISTICS_REFRESH_RATE_MS;
permission = NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS;
audit_op = NM_AUDIT_OP_STATISTICS;
expected_type = G_VARIANT_TYPE ("u");
} else
return message;
interface_type = NMDBUS_TYPE_DEVICE_SKELETON;
} else
return message;

View File

@@ -1476,6 +1476,15 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr
nl_info_data = li[IFLA_INFO_DATA];
}
if (tb[IFLA_STATS64]) {
struct rtnl_link_stats64 *stats = nla_data (tb[IFLA_STATS64]);
obj->link.rx_packets = stats->rx_packets;
obj->link.rx_bytes = stats->rx_bytes;
obj->link.tx_packets = stats->tx_packets;
obj->link.tx_bytes = stats->tx_bytes;
}
obj->link.n_ifi_flags = ifi->ifi_flags;
obj->link.connected = NM_FLAGS_HAS (obj->link.n_ifi_flags, IFF_LOWER_UP);
obj->link.arptype = ifi->ifi_type;
@@ -1568,7 +1577,8 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr
&& ( lnk_data_complete_from_cache
|| address_complete_from_cache
|| !af_inet6_token_valid
|| !af_inet6_addr_gen_mode_valid)) {
|| !af_inet6_addr_gen_mode_valid
|| !tb[IFLA_STATS64])) {
_lookup_cached_link (cache, obj->link.ifindex, completed_from_cache, &link_cached);
if (link_cached) {
if ( lnk_data_complete_from_cache
@@ -1591,6 +1601,12 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr
obj->link.inet6_token = link_cached->link.inet6_token;
if (!af_inet6_addr_gen_mode_valid)
obj->link.inet6_addr_gen_mode_inv = link_cached->link.inet6_addr_gen_mode_inv;
if (!tb[IFLA_STATS64]) {
obj->link.rx_packets = link_cached->link.rx_packets;
obj->link.rx_bytes = link_cached->link.rx_bytes;
obj->link.tx_packets = link_cached->link.tx_packets;
obj->link.tx_bytes = link_cached->link.tx_bytes;
}
}
}
@@ -3732,6 +3748,7 @@ event_valid_msg (NMPlatform *platform, struct nl_msg *msg, gboolean handle_event
case RTM_NEWLINK:
case RTM_NEWADDR:
case RTM_NEWROUTE:
case RTM_GETLINK:
cache_op = nmp_cache_update_netlink (priv->cache, obj, &obj_cache, &was_visible, cache_pre_hook, platform);
cache_post (platform, msghdr, cache_op, obj, obj_cache);

View File

@@ -3115,6 +3115,8 @@ nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len)
"%s%s" /* addr */
"%s%s" /* inet6_token */
"%s%s" /* driver */
" rx:%"G_GUINT64_FORMAT",%"G_GUINT64_FORMAT
" tx:%"G_GUINT64_FORMAT",%"G_GUINT64_FORMAT
,
link->ifindex,
link->name,
@@ -3133,7 +3135,9 @@ nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len)
link->inet6_token.id ? " inet6token " : "",
link->inet6_token.id ? nm_utils_inet6_interface_identifier_to_token (link->inet6_token, str_inet6_token) : "",
link->driver ? " driver " : "",
link->driver ? link->driver : "");
link->driver ? link->driver : "",
link->rx_packets, link->rx_bytes,
link->tx_packets, link->tx_bytes);
g_string_free (str_flags, TRUE);
return buf;
}
@@ -3794,6 +3798,10 @@ nm_platform_link_cmp (const NMPlatformLink *a, const NMPlatformLink *b)
if (a->addr.len)
_CMP_FIELD_MEMCMP_LEN (a, b, addr.data, a->addr.len);
_CMP_FIELD_MEMCMP (a, b, inet6_token);
_CMP_FIELD (a, b, rx_packets);
_CMP_FIELD (a, b, rx_bytes);
_CMP_FIELD (a, b, tx_packets);
_CMP_FIELD (a, b, tx_bytes);
return 0;
}

View File

@@ -156,6 +156,12 @@ struct _NMPlatformLink {
* initialized with memset(0) has and unset value.*/
guint8 inet6_addr_gen_mode_inv;
/* Statistics */
guint64 rx_packets;
guint64 rx_bytes;
guint64 tx_packets;
guint64 tx_bytes;
/* @connected is mostly identical to (@n_ifi_flags & IFF_UP). Except for bridge/bond masters,
* where we coerce the link as disconnect if it has no slaves. */
bool connected:1;

View File

@@ -567,7 +567,7 @@ test_internal (void)
g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, ifindex, NULL));
g_assert (nm_platform_link_is_up (NM_PLATFORM_GET, ifindex));
g_assert (nm_platform_link_is_connected (NM_PLATFORM_GET, ifindex));
accept_signal (link_changed);
accept_signals (link_changed, 1, 2);
g_assert (nm_platform_link_set_down (NM_PLATFORM_GET, ifindex));
g_assert (!nm_platform_link_is_up (NM_PLATFORM_GET, ifindex));
g_assert (!nm_platform_link_is_connected (NM_PLATFORM_GET, ifindex));