Hey Dan, On Wed, Jul 27, 2016 at 5:49 PM, Dan Williams <d...@redhat.com> wrote:
> On Thu, 2016-06-23 at 15:25 +0200, Alfonso Sanchez-Beato wrote: > > Add statistics interface to all device instances. When active, the > > properties of this interface are refreshed whenever there is network > > activity for the device. > > > > Activation is performed by changing RefreshRateMs property. If set to > > zero, the interface is deactivated. If set to other value, the rest > > of > > the interface properties are refreshed whenever the related network > > metric changes, being RefreshRateMs the minimum time between property > > changes, in milliseconds. > > Alfonso, any chance you can update the patches for review comments and > re-send? They're useful and would be nice to get them in :) > Will try to do soon. I got very busy lately, and had some holidays after that ;-) > > Thanks! > > > --- > > introspection/Makefile.am | 6 +- > > introspection/nm-device-statistics.xml | 43 ++++ > > libnm-core/nm-dbus-interface.h | 1 + > > src/Makefile.am | 2 + > > src/devices/nm-device-private.h | 3 + > > src/devices/nm-device-statistics.c | 401 > > +++++++++++++++++++++++++++++++++ > > src/devices/nm-device-statistics.h | 33 +++ > > src/devices/nm-device.c | 112 ++++++++- > > src/devices/nm-device.h | 4 + > > 9 files changed, 603 insertions(+), 2 deletions(-) > > create mode 100644 introspection/nm-device-statistics.xml > > create mode 100644 src/devices/nm-device-statistics.c > > create mode 100644 src/devices/nm-device-statistics.h > > > > diff --git a/introspection/Makefile.am b/introspection/Makefile.am > > index 3a62793..f72703d 100644 > > --- a/introspection/Makefile.am > > +++ b/introspection/Makefile.am > > @@ -41,6 +41,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 \ > > @@ -111,7 +113,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)) > > @@ -150,6 +153,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 \ > > diff --git a/introspection/nm-device-statistics.xml > > b/introspection/nm-device-statistics.xml > > new file mode 100644 > > index 0000000..08a700e > > --- /dev/null > > +++ b/introspection/nm-device-statistics.xml > > @@ -0,0 +1,43 @@ > > +<?xml version="1.0" encoding="UTF-8"?> > > +<node name="/"> > > + <interface > > name="org.freedesktop.NetworkManager.Device.Statistics"> > > + > > + <!-- > > + RefreshRateMs: > > + > > + Rate of change of the rest of properties of this interface. > > If zero, the > > + properties do not change. Othewise, the properties are > > refreshed each > > + RefreshRateMs milliseconds in case the underlaying counter > > has changed > > + too. > > + > > + Returns: Unsigned 32-bit integer > > + --> > > + <property name="RefreshRateMs" type="u" access="readwrite"/> > > + > > + <!-- > > + TxBytes: > > + > > + Number of transmitted bytes > > + > > + Returns: Unsigned 64-bit integer > > + --> > > + <property name="TxBytes" type="t" access="read"/> > > + > > + <!-- > > + RxBytes: > > + > > + Number of received bytes > > + > > + Returns: Unsigned 64-bit integer > > + --> > > + <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> > > diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus- > > interface.h > > index 1e0fbe6..20eccb8 100644 > > --- a/libnm-core/nm-dbus-interface.h > > +++ b/libnm-core/nm-dbus-interface.h > > @@ -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.Set > > tings" > > #define > > NM_DBUS_PATH_SETTINGS "/org/freedesktop/NetworkManager/Se > > ttings" > > diff --git a/src/Makefile.am b/src/Makefile.am > > index 5e289d9..92ee9b9 100644 > > --- a/src/Makefile.am > > +++ b/src/Makefile.am > > @@ -289,6 +289,8 @@ libNetworkManager_la_SOURCES = \ > > devices/nm-device-generic.h \ > > devices/nm-device-logging.h \ > > devices/nm-device-private.h \ > > + devices/nm-device-statistics.c \ > > + devices/nm-device-statistics.h \ > > \ > > dhcp-manager/nm-dhcp-client.c \ > > dhcp-manager/nm-dhcp-client.h \ > > diff --git a/src/devices/nm-device-private.h b/src/devices/nm-device- > > private.h > > index 418ae2d..addeda0 100644 > > --- a/src/devices/nm-device-private.h > > +++ b/src/devices/nm-device-private.h > > @@ -111,6 +111,9 @@ void nm_device_ip_method_failed (NMDevice *self, > > int family, NMDeviceStateReason > > > > gboolean nm_device_ipv6_sysctl_set (NMDevice *self, const char > > *property, const char *value); > > > > +void nm_device_set_tx_bytes (NMDevice *self, guint64 tx_bytes); > > +void nm_device_set_rx_bytes (NMDevice *self, guint64 rx_bytes); > > + > > #define NM_DEVICE_CLASS_DECLARE_TYPES(klass, conn_type, ...) \ > > NM_DEVICE_CLASS (klass)->connection_type = conn_type; \ > > { \ > > diff --git a/src/devices/nm-device-statistics.c b/src/devices/nm- > > device-statistics.c > > new file mode 100644 > > index 0000000..0f6a714 > > --- /dev/null > > +++ b/src/devices/nm-device-statistics.c > > @@ -0,0 +1,401 @@ > > +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 > > -*- */ > > +/* This program is free software; you can redistribute it and/or > > modify > > + * it under the terms of the GNU General Public License as published > > by > > + * the Free Software Foundation; either version 2, or (at your > > option) > > + * any later version. > > + * > > + * This program is distributed in the hope that it will be useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + * > > + * You should have received a copy of the GNU General Public License > > along > > + * with this program; if not, write to the Free Software Foundation, > > Inc., > > + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. > > + * > > + * Copyright (C) 2016 Canonical Ltd > > + * > > + */ > > + > > +#include "nm-default.h" > > + > > +#include <errno.h> > > +#include <stdio.h> > > +#include <unistd.h> > > +#include <string.h> > > +#include <sys/socket.h> > > +#include <sys/ioctl.h> > > +#include <arpa/inet.h> > > +#include <netinet/ether.h> > > +#include <netinet/icmp6.h> > > +#include <net/if_arp.h> > > +#include <linux/if.h> > > +#include <linux/netlink.h> > > +#include <linux/rtnetlink.h> > > +#include <linux/wireless.h> > > + > > +#include "nm-device-private.h" > > +#include "nm-device-statistics.h" > > + > > +#define _NMLOG_DOMAIN LOGD_DEVICE > > +#define _NMLOG(level, ...) \ > > + nm_log_obj ((level), _NMLOG_DOMAIN, (self->device), "device- > > stats", \ > > + "(%s): " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), > > \ > > + nm_device_get_iface (self->device) > > ?: "(none)" \ > > + _NM_UTILS_MACRO_REST(__VA_ARGS__)) > > + > > +struct rtnl_request { > > + struct nlmsghdr hdr; > > + struct rtgenmsg msg; > > +}; > > + > > +#define RTNL_REQUEST_SIZE (sizeof (struct nlmsghdr) + sizeof > > (struct rtgenmsg)) > > +#define SOCK_RX_BUFF_SIZE 4096 > > + > > +struct _NMDeviceStatistics { > > + NMDevice *device; > > + GIOChannel *channel; > > + guint channel_watch; > > + guint stats_update_id; > > + gboolean req_pending; > > + guint32 request_seq; > > + unsigned char buf[SOCK_RX_BUFF_SIZE]; > > +}; > > + > > +static const char * > > +type_to_string (uint16_t type) > > +{ > > + switch (type) { > > + case NLMSG_NOOP: > > + return "NOOP"; > > + case NLMSG_ERROR: > > + return "ERROR"; > > + case NLMSG_DONE: > > + return "DONE"; > > + case NLMSG_OVERRUN: > > + return "OVERRUN"; > > + case RTM_GETLINK: > > + return "GETLINK"; > > + case RTM_NEWLINK: > > + return "NEWLINK"; > > + case RTM_DELLINK: > > + return "DELLINK"; > > + case RTM_GETADDR: > > + return "GETADDR"; > > + case RTM_NEWADDR: > > + return "NEWADDR"; > > + case RTM_DELADDR: > > + return "DELADDR"; > > + case RTM_GETROUTE: > > + return "GETROUTE"; > > + case RTM_NEWROUTE: > > + return "NEWROUTE"; > > + case RTM_DELROUTE: > > + return "DELROUTE"; > > + case RTM_NEWNDUSEROPT: > > + return "NEWNDUSEROPT"; > > + default: > > + return "UNKNOWN"; > > + } > > +} > > + > > +static const char * > > +operstate_to_str (unsigned char operstate) > > +{ > > + switch (operstate) { > > + case IF_OPER_UNKNOWN: > > + return "UNKNOWN"; > > + case IF_OPER_NOTPRESENT: > > + return "NOT-PRESENT"; > > + case IF_OPER_DOWN: > > + return "DOWN"; > > + case IF_OPER_LOWERLAYERDOWN: > > + return "LOWER-LAYER-DOWN"; > > + case IF_OPER_TESTING: > > + return "TESTING"; > > + case IF_OPER_DORMANT: > > + return "DORMANT"; > > + case IF_OPER_UP: > > + return "UP"; > > + default: > > + return ""; > > + } > > +} > > + > > +static gboolean > > +extract_link (struct ifinfomsg *msg, int bytes, > > + struct ether_addr *address, const char **ifname, > > + unsigned int *mtu, unsigned char *operstate, > > + struct rtnl_link_stats *stats) > > +{ > > + struct rtattr *attr; > > + > > + for (attr = IFLA_RTA (msg); RTA_OK (attr, bytes); > > + attr = RTA_NEXT (attr, bytes)) { > > + > > + switch (attr->rta_type) { > > + case IFLA_ADDRESS: > > + if (address) > > + memcpy (address, RTA_DATA (attr), > > ETH_ALEN); > > + break; > > + case IFLA_IFNAME: > > + if (ifname) > > + *ifname = RTA_DATA (attr); > > + break; > > + case IFLA_MTU: > > + if (mtu) > > + *mtu = *(unsigned int *) RTA_DATA > > (attr); > > + break; > > + case IFLA_STATS: > > + if (stats) > > + memcpy (stats, RTA_DATA (attr), > > + sizeof (struct > > rtnl_link_stats)); > > + break; > > + case IFLA_OPERSTATE: > > + if (operstate) > > + *operstate = *(unsigned char *) > > RTA_DATA (attr); > > + break; > > + case IFLA_LINKMODE: > > + break; > > + case IFLA_WIRELESS: > > + return FALSE; > > + } > > + } > > + > > + return TRUE; > > +} > > + > > +static void > > +process_newlink (NMDeviceStatistics *self, unsigned short type, int > > index, > > + unsigned flags, unsigned change, struct ifinfomsg > > *msg, > > + int bytes) > > +{ > > + struct ether_addr address = { { 0, 0, 0, 0, 0, 0 } }; > > + struct rtnl_link_stats stats = { 0 }; > > + unsigned char operstate = 0xFF; > > + const char *ifname = NULL; > > + unsigned int mtu = 0; > > + char hw_addr[3 * sizeof (address)]; > > + > > + if (!extract_link (msg, bytes, &address, &ifname, &mtu, > > &operstate, &stats)) > > + return; > > + > > + if (g_strcmp0 (ifname, nm_device_get_ip_iface (self- > > >device)) != 0) > > + return; > > + > > + snprintf(hw_addr, sizeof (hw_addr), > > "%02X:%02X:%02X:%02X:%02X:%02X", > > + address.ether_addr_octet[0], > > + address.ether_addr_octet[1], > > + address.ether_addr_octet[2], > > + address.ether_addr_octet[3], > > + address.ether_addr_octet[4], > > + address.ether_addr_octet[5]); > > + > > + if (flags & IFF_SLAVE) { > > + _LOGD ("%s {newlink} ignoring slave, index %d > > address %s", > > + ifname, index, hw_addr); > > + return; > > + } > > + > > + _LOGD ("%s {newlink} index %d address %s mtu %u operstate %u > > <%s>", > > + ifname, index, hw_addr, mtu, operstate, > > operstate_to_str (operstate)); > > + _LOGD ("%s {RX} %u packets %u bytes", ifname, > > + stats.rx_packets, stats.rx_bytes); > > + _LOGD ("%s {TX} %u packets %u bytes", ifname, > > + stats.tx_packets, stats.tx_bytes); > > + > > + nm_device_set_tx_bytes (self->device, stats.tx_bytes); > > + nm_device_set_rx_bytes (self->device, stats.rx_bytes); > > +} > > + > > +static void > > +rtnl_newlink (NMDeviceStatistics *self, struct nlmsghdr *hdr) > > +{ > > + struct ifinfomsg *msg = (struct ifinfomsg *) NLMSG_DATA > > (hdr); > > + > > + if (hdr->nlmsg_type == IFLA_WIRELESS) > > + _LOGW ("Obsolete WEXT WiFi driver detected"); > > + > > + process_newlink (self, msg->ifi_type, msg->ifi_index, msg- > > >ifi_flags, > > + msg->ifi_change, msg, IFA_PAYLOAD (hdr)); > > +} > > + > > +static void > > +rtnl_message (NMDeviceStatistics *self, unsigned char *buf, size_t > > len) > > +{ > > + while (len > 0) { > > + struct nlmsghdr *hdr = (struct nlmsghdr *) buf; > > + struct nlmsgerr *err; > > + > > + if (!NLMSG_OK (hdr, len)) > > + break; > > + > > + switch (hdr->nlmsg_type) { > > + case NLMSG_NOOP: > > + case NLMSG_OVERRUN: > > + return; > > + case NLMSG_DONE: > > + if (hdr->nlmsg_seq == self->request_seq - 1) > > + self->req_pending = FALSE; > > + return; > > + case NLMSG_ERROR: > > + err = NLMSG_DATA (hdr); > > + return; > > + case RTM_NEWLINK: > > + rtnl_newlink (self, hdr); > > + break; > > + case RTM_DELLINK: > > + case RTM_NEWADDR: > > + case RTM_DELADDR: > > + case RTM_NEWROUTE: > > + case RTM_DELROUTE: > > + case RTM_NEWNDUSEROPT: > > + break; > > + } > > + > > + len -= hdr->nlmsg_len; > > + buf += hdr->nlmsg_len; > > + } > > +} > > + > > +static gboolean > > +netlink_event (GIOChannel *chan, GIOCondition cond, gpointer data) > > +{ > > + struct sockaddr_nl nladdr = { 0 }; > > + socklen_t addr_len = sizeof (nladdr); > > + ssize_t status; > > + int fd; > > + NMDeviceStatistics *self = data; > > + > > + if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) { > > + _LOGE ("netlink socket error %d", errno); > > + return FALSE; > > + } > > + > > + fd = g_io_channel_unix_get_fd (chan); > > + > > + status = recvfrom (fd, self->buf, sizeof (self->buf), 0, > > + (struct sockaddr *) &nladdr, &addr_len); > > + if (status < 0) { > > + if (errno == EINTR || errno == EAGAIN) > > + return TRUE; > > + > > + _LOGE ("error %d on receiving from netlink socket", > > errno); > > + return FALSE; > > + } > > + > > + /* EOF, remove callback */ > > + if (status == 0) > > + return FALSE; > > + > > + /* not sent by kernel, ignore */ > > + if (nladdr.nl_pid != 0) > > + return TRUE; > > + > > + rtnl_message (self, self->buf, status); > > + > > + return TRUE; > > +} > > + > > +static int > > +send_getlink (NMDeviceStatistics *self) > > +{ > > + struct rtnl_request req = { 0 }; > > + struct sockaddr_nl addr = { 0 }; > > + int sk; > > + > > + req.hdr.nlmsg_len = RTNL_REQUEST_SIZE; > > + req.hdr.nlmsg_type = RTM_GETLINK; > > + req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; > > + req.hdr.nlmsg_pid = 0; > > + req.hdr.nlmsg_seq = self->request_seq++; > > + req.msg.rtgen_family = AF_UNSPEC; > > + > > + _LOGD ("Sending %s len %d type %d flags 0x%04x seq %d", > > + type_to_string (req.hdr.nlmsg_type), > > + req.hdr.nlmsg_len, req.hdr.nlmsg_type, > > + req.hdr.nlmsg_flags, req.hdr.nlmsg_seq); > > + > > + sk = g_io_channel_unix_get_fd(self->channel); > > + > > + addr.nl_family = AF_NETLINK; > > + > > + self->req_pending = TRUE; > > + > > + return sendto (sk, &req, req.hdr.nlmsg_len, 0, > > + (struct sockaddr *) &addr, sizeof (addr)); > > +} > > + > > +static gboolean > > +update_stats (gpointer user_data) > > +{ > > + NMDeviceStatistics *self = user_data; > > + > > + if (self->req_pending) { > > + _LOGD ("no response yet for pending netlink > > request"); > > + return TRUE; > > + } > > + > > + send_getlink (self); > > + return TRUE; > > +} > > + > > +/********************************************/ > > + > > +NMDeviceStatistics * > > +nm_device_statistics_create (NMDevice *device, unsigned rate_ms) > > +{ > > + NMDeviceStatistics *self; > > + struct sockaddr_nl addr = { 0 }; > > + int sk; > > + GIOChannel *channel = NULL; > > + guint channel_watch = 0; > > + > > + self = g_malloc0 (sizeof (*self)); > > + self->device = device; > > + > > + sk = socket (PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, > > NETLINK_ROUTE); > > + if (sk < 0) { > > + _LOGE ("Cannot create netlink socket: %d", errno); > > + goto error; > > + } > > + > > + addr.nl_family = AF_NETLINK; > > + addr.nl_groups = RTMGRP_LINK; > > + > > + if (bind (sk, (struct sockaddr *) &addr, sizeof (addr)) < 0) > > { > > + close (sk); > > + _LOGE ("Cannot bind to netlink socket: %d", errno); > > + goto error; > > + } > > + > > + channel = g_io_channel_unix_new (sk); > > + > > + g_io_channel_set_close_on_unref (channel, TRUE); > > + g_io_channel_set_encoding (channel, NULL, NULL); > > + g_io_channel_set_buffered (channel, FALSE); > > + > > + channel_watch = > > + g_io_add_watch (channel, > > + G_IO_IN | G_IO_NVAL | G_IO_HUP | > > G_IO_ERR, > > + netlink_event, self); > > + > > + self->channel = channel; > > + self->channel_watch = channel_watch; > > + self->stats_update_id = g_timeout_add (rate_ms, > > update_stats, self); > > + > > + return self; > > + > > +error: > > + g_free (self); > > + return NULL; > > +} > > + > > +void > > +nm_device_statistics_remove (NMDeviceStatistics *self) > > +{ > > + g_source_remove (self->stats_update_id); > > + g_source_remove (self->channel_watch); > > + g_io_channel_unref (self->channel); > > + g_free (self); > > +} > > diff --git a/src/devices/nm-device-statistics.h b/src/devices/nm- > > device-statistics.h > > new file mode 100644 > > index 0000000..910e430 > > --- /dev/null > > +++ b/src/devices/nm-device-statistics.h > > @@ -0,0 +1,33 @@ > > +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 > > -*- */ > > +/* This program is free software; you can redistribute it and/or > > modify > > + * it under the terms of the GNU General Public License as published > > by > > + * the Free Software Foundation; either version 2, or (at your > > option) > > + * any later version. > > + * > > + * This program is distributed in the hope that it will be useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + * > > + * You should have received a copy of the GNU General Public License > > along > > + * with this program; if not, write to the Free Software Foundation, > > Inc., > > + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. > > + * > > + * Copyright (C) 2016 Canonical Ltd > > + */ > > + > > +#ifndef __NETWORKMANAGER_DEVICE_STATISTICS_H__ > > +#define __NETWORKMANAGER_DEVICE_STATISTICS_H__ > > + > > +#include <stdlib.h> > > + > > +#include "nm-default.h" > > + > > +typedef struct _NMDeviceStatistics NMDeviceStatistics; > > + > > +NMDeviceStatistics * > > +nm_device_statistics_create (NMDevice *device, unsigned rate_ms); > > + > > +void nm_device_statistics_remove (NMDeviceStatistics *self); > > + > > +#endif /* __NETWORKMANAGER_DEVICE_STATISTICS_H__ */ > > diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c > > index 5fd0bf3..eaa4fce 100644 > > --- a/src/devices/nm-device.c > > +++ b/src/devices/nm-device.c > > @@ -66,11 +66,13 @@ > > #include "sd-ipv4ll.h" > > #include "nm-audit-manager.h" > > #include "nm-arping-manager.h" > > +#include "nm-device-statistics.h" > > > > #include "nm-device-logging.h" > > _LOG_DECLARE_SELF (NMDevice); > > > > #include "nmdbus-device.h" > > +#include "nmdbus-device-statistics.h" > > > > G_DEFINE_ABSTRACT_TYPE (NMDevice, nm_device, > > NM_TYPE_EXPORTED_OBJECT) > > > > @@ -137,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 > > @@ -394,6 +399,13 @@ typedef struct _NMDevicePrivate { > > NMLldpListener *lldp_listener; > > > > guint check_delete_unrealized_id; > > + > > + guint32 refresh_rate_ms; > > + guint64 tx_bytes; > > + guint64 rx_bytes; > > + > > + NMDeviceStatistics *statistics; > > + > > } NMDevicePrivate; > > > > static gboolean nm_device_set_ip4_config (NMDevice *self, > > @@ -732,6 +744,36 @@ nm_device_set_ip_iface (NMDevice *self, const > > char *iface) > > g_free (old_ip_iface); > > } > > > > +void > > +nm_device_set_tx_bytes (NMDevice *self, guint64 tx_bytes) > > +{ > > + NMDevicePrivate *priv; > > + > > + g_return_if_fail (NM_IS_DEVICE (self)); > > + > > + priv = NM_DEVICE_GET_PRIVATE (self); > > + if (tx_bytes == priv->tx_bytes) > > + return; > > + > > + priv->tx_bytes = tx_bytes; > > + _notify (self, PROP_TX_BYTES); > > +} > > + > > +void > > +nm_device_set_rx_bytes (NMDevice *self, guint64 rx_bytes) > > +{ > > + NMDevicePrivate *priv; > > + > > + g_return_if_fail (NM_IS_DEVICE (self)); > > + > > + priv = NM_DEVICE_GET_PRIVATE (self); > > + if (rx_bytes == priv->rx_bytes) > > + return; > > + > > + priv->rx_bytes = rx_bytes; > > + _notify (self, PROP_RX_BYTES); > > +} > > + > > static gboolean > > get_ip_iface_identifier (NMDevice *self, NMUtilsIPv6IfaceId > > *out_iid) > > { > > @@ -2145,6 +2187,10 @@ realize_start_setup (NMDevice *self, const > > NMPlatformLink *plink) > > priv->carrier = TRUE; > > } > > > > + if (priv->refresh_rate_ms && !priv->statistics) > > + priv->statistics = nm_device_statistics_create > > (self, > > + > > priv->refresh_rate_ms); > > + > > klass->realize_start_notify (self, plink); > > > > /* Do not manage externally created software devices until > > they are IFF_UP > > @@ -2315,6 +2361,14 @@ nm_device_unrealize (NMDevice *self, gboolean > > remove_resources, GError **error) > > g_clear_pointer (&priv->physical_port_id, g_free); > > _notify (self, PROP_PHYSICAL_PORT_ID); > > } > > + if (priv->statistics) { > > + nm_device_statistics_remove (priv->statistics); > > + priv->statistics = NULL; > > + priv->tx_bytes = 0; > > + priv->tx_bytes = 0; > > + _notify (self, PROP_TX_BYTES); > > + _notify (self, PROP_RX_BYTES); > > + } > > > > g_clear_pointer (&priv->perm_hw_addr, g_free); > > g_clear_pointer (&priv->initial_hw_addr, g_free); > > @@ -11542,6 +11596,11 @@ nm_device_init (NMDevice *self) > > > > priv->v4_commit_first_time = TRUE; > > priv->v6_commit_first_time = TRUE; > > + > > + priv->refresh_rate_ms = 0; > > + priv->tx_bytes = 0; > > + priv->rx_bytes = 0; > > + priv->statistics = NULL; > > } > > > > static GObject* > > @@ -11678,6 +11737,11 @@ dispose (GObject *object) > > g_clear_object (&priv->lldp_listener); > > } > > > > + if (priv->statistics) { > > + nm_device_statistics_remove (priv->statistics); > > + priv->statistics = NULL; > > + } > > + > > G_OBJECT_CLASS (nm_device_parent_class)->dispose (object); > > > > if (nm_clear_g_source (&priv->queued_state.id)) { > > @@ -11730,7 +11794,7 @@ set_property (GObject *object, guint prop_id, > > NMDevice *self = NM_DEVICE (object); > > NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); > > const char *hw_addr, *p; > > - guint count; > > + guint count, refresh_rate_ms; > > > > switch (prop_id) { > > case PROP_UDI: > > @@ -11835,6 +11899,22 @@ set_property (GObject *object, guint > > prop_id, > > priv->hw_addr = NULL; > > } > > break; > > + case PROP_REFRESH_RATE_MS: > > + refresh_rate_ms = g_value_get_uint (value); > > + if (priv->refresh_rate_ms == refresh_rate_ms) > > + break; > > + > > + priv->refresh_rate_ms = g_value_get_uint (value); > > + _LOGI (LOGD_DEVICE, "statistics refresh rate set to > > %u ms", priv->refresh_rate_ms); > > + > > + if (priv->statistics) { > > + nm_device_statistics_remove (priv- > > >statistics); > > + priv->statistics = NULL; > > + } > > + if (priv->refresh_rate_ms) > > + priv->statistics = > > + nm_device_statistics_create (self, > > priv->refresh_rate_ms); > > + break; > > default: > > G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, > > pspec); > > break; > > @@ -11993,6 +12073,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->refresh_rate_ms); > > + break; > > + case PROP_TX_BYTES: > > + g_value_set_uint64 (value, priv->tx_bytes); > > + break; > > + case PROP_RX_BYTES: > > + g_value_set_uint64 (value, priv->rx_bytes); > > + break; > > default: > > G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, > > pspec); > > break; > > @@ -12236,6 +12325,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, UINT_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 */ > > @@ -12306,4 +12412,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_S > > TATISTICS_SKELETON, > > + NULL); > > } > > diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h > > index 4b365d6..386cb94 100644 > > --- a/src/devices/nm-device.h > > +++ b/src/devices/nm-device.h > > @@ -83,6 +83,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 ()) >
_______________________________________________ networkmanager-list mailing list networkmanager-list@gnome.org https://mail.gnome.org/mailman/listinfo/networkmanager-list