Merge ~alfonsosanchezbeato/network-manager/+git/ubuntu:touch-vivid-add-statitics into network-manager:touch-vivid

Proposed by Alfonso Sanchez-Beato
Status: Merged
Merged at revision: 92ac043cd375662fa7546ccdd0cc7aecbc275929
Proposed branch: ~alfonsosanchezbeato/network-manager/+git/ubuntu:touch-vivid-add-statitics
Merge into: network-manager:touch-vivid
Diff against target: 856 lines (+842/-0)
2 files modified
debian/patches/Add-statistics-interface.patch (+841/-0)
debian/patches/series (+1/-0)
Reviewer Review Type Date Requested Status
Tony Espy Approve
Review via email: mp+296433@code.launchpad.net

Commit message

ubuntu: Add statistics interface

Description of the change

ubuntu: Add statistics interface

To post a comment you must log in.
Revision history for this message
Tony Espy (awe) :
review: Needs Fixing
Revision history for this message
Alfonso Sanchez-Beato (alfonsosanchezbeato) wrote :

Branch refreshed after addressing comments.

Revision history for this message
Alfonso Sanchez-Beato (alfonsosanchezbeato) wrote :

Some compilation warning fixed.

Revision history for this message
Tony Espy (awe) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/debian/patches/Add-statistics-interface.patch b/debian/patches/Add-statistics-interface.patch
2new file mode 100644
3index 0000000..2c3dcd2
4--- /dev/null
5+++ b/debian/patches/Add-statistics-interface.patch
6@@ -0,0 +1,841 @@
7+From: Alfonso Sanchez-Beato <alfonso.sanchez-beato@canonical.com>
8+Date: Fri, 3 Jun 2016 14:55:22 +0200
9+Subject: Add statistics interface
10+
11+---
12+ introspection/Makefile.am | 6 +-
13+ introspection/nm-device-statistics.xml | 43 ++++
14+ libnm-core/nm-dbus-interface.h | 1 +
15+ src/Makefile.am | 2 +
16+ src/devices/nm-device-private.h | 3 +
17+ src/devices/nm-device-statistics.c | 407 +++++++++++++++++++++++++++++++++
18+ src/devices/nm-device-statistics.h | 33 +++
19+ src/devices/nm-device.c | 102 ++++++++-
20+ src/devices/nm-device.h | 4 +
21+ src/nm-exported-object.c | 18 +-
22+ src/nm-types.h | 1 +
23+ 11 files changed, 610 insertions(+), 10 deletions(-)
24+ create mode 100644 introspection/nm-device-statistics.xml
25+ create mode 100644 src/devices/nm-device-statistics.c
26+ create mode 100644 src/devices/nm-device-statistics.h
27+
28+diff --git a/introspection/Makefile.am b/introspection/Makefile.am
29+index 3a62793..f72703d 100644
30+--- a/introspection/Makefile.am
31++++ b/introspection/Makefile.am
32+@@ -41,6 +41,8 @@ nodist_libnmdbus_la_SOURCES = \
33+ nmdbus-device-modem.h \
34+ nmdbus-device-olpc-mesh.c \
35+ nmdbus-device-olpc-mesh.h \
36++ nmdbus-device-statistics.c \
37++ nmdbus-device-statistics.h \
38+ nmdbus-device-team.c \
39+ nmdbus-device-team.h \
40+ nmdbus-device-tun.c \
41+@@ -111,7 +113,8 @@ DBUS_INTERFACE_DOCS = \
42+ nmdbus-device-veth-org.freedesktop.NetworkManager.Device.Veth.xml \
43+ nmdbus-settings-org.freedesktop.NetworkManager.Settings.xml \
44+ nmdbus-device-ethernet-org.freedesktop.NetworkManager.Device.Wired.xml \
45+- nmdbus-ip4-config-org.freedesktop.NetworkManager.IP4Config.xml
46++ nmdbus-ip4-config-org.freedesktop.NetworkManager.IP4Config.xml \
47++ nmdbus-device-statistics-org.freedesktop.NetworkManager.Device.Statistics.xml
48+
49+ define _make_nmdbus_rule
50+ $(1): $(patsubst nmdbus-%.c,nm-%.xml,$(1))
51+@@ -150,6 +153,7 @@ EXTRA_DIST = \
52+ nm-device-macvlan.xml \
53+ nm-device-modem.xml \
54+ nm-device-olpc-mesh.xml \
55++ nm-device-statistics.xml \
56+ nm-device-team.xml \
57+ nm-device-tun.xml \
58+ nm-device-veth.xml \
59+diff --git a/introspection/nm-device-statistics.xml b/introspection/nm-device-statistics.xml
60+new file mode 100644
61+index 0000000..08a700e
62+--- /dev/null
63++++ b/introspection/nm-device-statistics.xml
64+@@ -0,0 +1,43 @@
65++<?xml version="1.0" encoding="UTF-8"?>
66++<node name="/">
67++ <interface name="org.freedesktop.NetworkManager.Device.Statistics">
68++
69++ <!--
70++ RefreshRateMs:
71++
72++ Rate of change of the rest of properties of this interface. If zero, the
73++ properties do not change. Othewise, the properties are refreshed each
74++ RefreshRateMs milliseconds in case the underlaying counter has changed
75++ too.
76++
77++ Returns: Unsigned 32-bit integer
78++ -->
79++ <property name="RefreshRateMs" type="u" access="readwrite"/>
80++
81++ <!--
82++ TxBytes:
83++
84++ Number of transmitted bytes
85++
86++ Returns: Unsigned 64-bit integer
87++ -->
88++ <property name="TxBytes" type="t" access="read"/>
89++
90++ <!--
91++ RxBytes:
92++
93++ Number of received bytes
94++
95++ Returns: Unsigned 64-bit integer
96++ -->
97++ <property name="RxBytes" type="t" access="read"/>
98++
99++ <!--
100++ PropertiesChanged:
101++ @properties: A dictionary mapping property names to variant boxed values
102++ -->
103++ <signal name="PropertiesChanged">
104++ <arg name="properties" type="a{sv}"/>
105++ </signal>
106++ </interface>
107++</node>
108+diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus-interface.h
109+index f3d7945..6f0fc23 100644
110+--- a/libnm-core/nm-dbus-interface.h
111++++ b/libnm-core/nm-dbus-interface.h
112+@@ -68,6 +68,7 @@
113+ #define NM_DBUS_INTERFACE_DEVICE_VXLAN NM_DBUS_INTERFACE_DEVICE ".Vxlan"
114+ #define NM_DBUS_INTERFACE_DEVICE_GRE NM_DBUS_INTERFACE_DEVICE ".Gre"
115+ #define NM_DBUS_INTERFACE_DEVICE_IP_TUNNEL NM_DBUS_INTERFACE_DEVICE ".IPTunnel"
116++#define NM_DBUS_INTERFACE_DEVICE_STATISTICS NM_DBUS_INTERFACE_DEVICE ".Statistics"
117+
118+ #define NM_DBUS_INTERFACE_SETTINGS "org.freedesktop.NetworkManager.Settings"
119+ #define NM_DBUS_PATH_SETTINGS "/org/freedesktop/NetworkManager/Settings"
120+diff --git a/src/Makefile.am b/src/Makefile.am
121+index 49028f1..1b749e3 100644
122+--- a/src/Makefile.am
123++++ b/src/Makefile.am
124+@@ -286,6 +286,8 @@ libNetworkManager_la_SOURCES = \
125+ devices/nm-device-generic.h \
126+ devices/nm-device-logging.h \
127+ devices/nm-device-private.h \
128++ devices/nm-device-statistics.c \
129++ devices/nm-device-statistics.h \
130+ \
131+ dhcp-manager/nm-dhcp-client.c \
132+ dhcp-manager/nm-dhcp-client.h \
133+diff --git a/src/devices/nm-device-private.h b/src/devices/nm-device-private.h
134+index 602c2c8..f84460a 100644
135+--- a/src/devices/nm-device-private.h
136++++ b/src/devices/nm-device-private.h
137+@@ -105,6 +105,9 @@ void nm_device_set_wwan_ip6_config (NMDevice *device, NMIP6Config *config);
138+
139+ gboolean nm_device_ipv6_sysctl_set (NMDevice *self, const char *property, const char *value);
140+
141++void nm_device_set_tx_bytes (NMDevice *self, guint64 tx_bytes);
142++void nm_device_set_rx_bytes (NMDevice *self, guint64 rx_bytes);
143++
144+ #define NM_DEVICE_CLASS_DECLARE_TYPES(klass, conn_type, ...) \
145+ NM_DEVICE_CLASS (klass)->connection_type = conn_type; \
146+ { \
147+diff --git a/src/devices/nm-device-statistics.c b/src/devices/nm-device-statistics.c
148+new file mode 100644
149+index 0000000..daf67f1
150+--- /dev/null
151++++ b/src/devices/nm-device-statistics.c
152+@@ -0,0 +1,407 @@
153++/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
154++/* This program is free software; you can redistribute it and/or modify
155++ * it under the terms of the GNU General Public License as published by
156++ * the Free Software Foundation; either version 2, or (at your option)
157++ * any later version.
158++ *
159++ * This program is distributed in the hope that it will be useful,
160++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
161++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
162++ * GNU General Public License for more details.
163++ *
164++ * You should have received a copy of the GNU General Public License along
165++ * with this program; if not, write to the Free Software Foundation, Inc.,
166++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
167++ *
168++ * Copyright (C) 2016 Canonical Ltd
169++ *
170++ */
171++
172++#include "nm-default.h"
173++
174++#include <errno.h>
175++#include <stdio.h>
176++#include <unistd.h>
177++#include <string.h>
178++#include <sys/socket.h>
179++#include <sys/ioctl.h>
180++#include <arpa/inet.h>
181++#include <netinet/ether.h>
182++#include <netinet/icmp6.h>
183++#include <net/if_arp.h>
184++#include <linux/if.h>
185++#include <linux/netlink.h>
186++#include <linux/rtnetlink.h>
187++#include <linux/wireless.h>
188++
189++#include "nm-device-private.h"
190++#include "nm-device-statistics.h"
191++
192++#define _NMLOG_DOMAIN LOGD_DEVICE
193++#define _NMLOG_PREFIX_NAME "device (stats)"
194++#define _NMLOG(level, ...) \
195++ G_STMT_START { \
196++ nm_log ((level), _NMLOG_DOMAIN, \
197++ "%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
198++ _NMLOG_PREFIX_NAME": " \
199++ _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
200++ } G_STMT_END
201++
202++struct rtnl_request {
203++ struct nlmsghdr hdr;
204++ struct rtgenmsg msg;
205++};
206++
207++#define RTNL_REQUEST_SIZE (sizeof (struct nlmsghdr) + sizeof (struct rtgenmsg))
208++#define SOCK_RX_BUFF_SIZE 4096
209++
210++struct _NMDeviceStatistics {
211++ NMDevice *device;
212++ char *iface;
213++ GIOChannel *channel;
214++ guint channel_watch;
215++ guint stats_update_id;
216++ gboolean req_pending;
217++ guint32 request_seq;
218++ unsigned char buf[SOCK_RX_BUFF_SIZE];
219++};
220++
221++static const char *
222++type_to_string (uint16_t type)
223++{
224++ switch (type) {
225++ case NLMSG_NOOP:
226++ return "NOOP";
227++ case NLMSG_ERROR:
228++ return "ERROR";
229++ case NLMSG_DONE:
230++ return "DONE";
231++ case NLMSG_OVERRUN:
232++ return "OVERRUN";
233++ case RTM_GETLINK:
234++ return "GETLINK";
235++ case RTM_NEWLINK:
236++ return "NEWLINK";
237++ case RTM_DELLINK:
238++ return "DELLINK";
239++ case RTM_GETADDR:
240++ return "GETADDR";
241++ case RTM_NEWADDR:
242++ return "NEWADDR";
243++ case RTM_DELADDR:
244++ return "DELADDR";
245++ case RTM_GETROUTE:
246++ return "GETROUTE";
247++ case RTM_NEWROUTE:
248++ return "NEWROUTE";
249++ case RTM_DELROUTE:
250++ return "DELROUTE";
251++ case RTM_NEWNDUSEROPT:
252++ return "NEWNDUSEROPT";
253++ default:
254++ return "UNKNOWN";
255++ }
256++}
257++
258++static const char *
259++operstate_to_str (unsigned char operstate)
260++{
261++ switch (operstate) {
262++ case IF_OPER_UNKNOWN:
263++ return "UNKNOWN";
264++ case IF_OPER_NOTPRESENT:
265++ return "NOT-PRESENT";
266++ case IF_OPER_DOWN:
267++ return "DOWN";
268++ case IF_OPER_LOWERLAYERDOWN:
269++ return "LOWER-LAYER-DOWN";
270++ case IF_OPER_TESTING:
271++ return "TESTING";
272++ case IF_OPER_DORMANT:
273++ return "DORMANT";
274++ case IF_OPER_UP:
275++ return "UP";
276++ default:
277++ return "";
278++ }
279++}
280++
281++static gboolean
282++extract_link (struct ifinfomsg *msg, int bytes,
283++ struct ether_addr *address, const char **ifname,
284++ unsigned int *mtu, unsigned char *operstate,
285++ struct rtnl_link_stats *stats)
286++{
287++ struct rtattr *attr;
288++
289++ for (attr = IFLA_RTA (msg); RTA_OK (attr, bytes);
290++ attr = RTA_NEXT (attr, bytes)) {
291++
292++ switch (attr->rta_type) {
293++ case IFLA_ADDRESS:
294++ if (address)
295++ memcpy (address, RTA_DATA (attr), ETH_ALEN);
296++ break;
297++ case IFLA_IFNAME:
298++ if (ifname)
299++ *ifname = RTA_DATA (attr);
300++ break;
301++ case IFLA_MTU:
302++ if (mtu)
303++ *mtu = *(unsigned int *) RTA_DATA (attr);
304++ break;
305++ case IFLA_STATS:
306++ if (stats)
307++ memcpy (stats, RTA_DATA (attr),
308++ sizeof (struct rtnl_link_stats));
309++ break;
310++ case IFLA_OPERSTATE:
311++ if (operstate)
312++ *operstate = *(unsigned char *) RTA_DATA (attr);
313++ break;
314++ case IFLA_LINKMODE:
315++ break;
316++ case IFLA_WIRELESS:
317++ return FALSE;
318++ }
319++ }
320++
321++ return TRUE;
322++}
323++
324++static void
325++process_newlink (NMDeviceStatistics *self, unsigned short type, int index,
326++ unsigned flags, unsigned change, struct ifinfomsg *msg,
327++ int bytes)
328++{
329++ struct ether_addr address = { { 0, 0, 0, 0, 0, 0 } };
330++ struct rtnl_link_stats stats = { 0 };
331++ unsigned char operstate = 0xFF;
332++ const char *ifname = NULL;
333++ unsigned int mtu = 0;
334++ char hw_addr[3 * sizeof (address)];
335++
336++ if (!extract_link (msg, bytes, &address, &ifname, &mtu, &operstate, &stats))
337++ return;
338++
339++ if (g_strcmp0 (ifname, self->iface) != 0)
340++ return;
341++
342++ snprintf(hw_addr, sizeof (hw_addr), "%02X:%02X:%02X:%02X:%02X:%02X",
343++ address.ether_addr_octet[0],
344++ address.ether_addr_octet[1],
345++ address.ether_addr_octet[2],
346++ address.ether_addr_octet[3],
347++ address.ether_addr_octet[4],
348++ address.ether_addr_octet[5]);
349++
350++ if (flags & IFF_SLAVE) {
351++ _LOGD ("%s {newlink} ignoring slave, index %d address %s",
352++ ifname, index, hw_addr);
353++ return;
354++ }
355++
356++ _LOGD ("%s {newlink} index %d address %s mtu %u operstate %u <%s>",
357++ ifname, index, hw_addr, mtu, operstate, operstate_to_str (operstate));
358++ _LOGD ("%s {RX} %u packets %u bytes", ifname,
359++ stats.rx_packets, stats.rx_bytes);
360++ _LOGD ("%s {TX} %u packets %u bytes", ifname,
361++ stats.tx_packets, stats.tx_bytes);
362++
363++ nm_device_set_tx_bytes (self->device, stats.tx_bytes);
364++ nm_device_set_rx_bytes (self->device, stats.rx_bytes);
365++}
366++
367++static void
368++rtnl_newlink (NMDeviceStatistics *self, struct nlmsghdr *hdr)
369++{
370++ struct ifinfomsg *msg = (struct ifinfomsg *) NLMSG_DATA (hdr);
371++
372++ if (hdr->nlmsg_type == IFLA_WIRELESS)
373++ _LOGW ("Obsolete WEXT WiFi driver detected");
374++
375++ process_newlink (self, msg->ifi_type, msg->ifi_index, msg->ifi_flags,
376++ msg->ifi_change, msg, IFA_PAYLOAD (hdr));
377++}
378++
379++static void
380++rtnl_message (NMDeviceStatistics *self, unsigned char *buf, size_t len)
381++{
382++ while (len > 0) {
383++ struct nlmsghdr *hdr = (struct nlmsghdr *) buf;
384++ struct nlmsgerr *err;
385++
386++ if (!NLMSG_OK (hdr, len))
387++ break;
388++
389++ switch (hdr->nlmsg_type) {
390++ case NLMSG_NOOP:
391++ case NLMSG_OVERRUN:
392++ return;
393++ case NLMSG_DONE:
394++ if (hdr->nlmsg_seq == self->request_seq - 1)
395++ self->req_pending = FALSE;
396++ return;
397++ case NLMSG_ERROR:
398++ err = NLMSG_DATA (hdr);
399++ return;
400++ case RTM_NEWLINK:
401++ rtnl_newlink (self, hdr);
402++ break;
403++ case RTM_DELLINK:
404++ case RTM_NEWADDR:
405++ case RTM_DELADDR:
406++ case RTM_NEWROUTE:
407++ case RTM_DELROUTE:
408++ case RTM_NEWNDUSEROPT:
409++ break;
410++ }
411++
412++ len -= hdr->nlmsg_len;
413++ buf += hdr->nlmsg_len;
414++ }
415++}
416++
417++static gboolean
418++netlink_event (GIOChannel *chan, GIOCondition cond, gpointer data)
419++{
420++ struct sockaddr_nl nladdr = { 0 };
421++ socklen_t addr_len = sizeof (nladdr);
422++ ssize_t status;
423++ int fd;
424++ NMDeviceStatistics *self = data;
425++
426++ if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
427++ _LOGE ("netlink socket error %d", errno);
428++ return FALSE;
429++ }
430++
431++ fd = g_io_channel_unix_get_fd (chan);
432++
433++ status = recvfrom (fd, self->buf, sizeof (self->buf), 0,
434++ (struct sockaddr *) &nladdr, &addr_len);
435++ if (status < 0) {
436++ if (errno == EINTR || errno == EAGAIN)
437++ return TRUE;
438++
439++ _LOGE ("error %d on receiving from netlink socket", errno);
440++ return FALSE;
441++ }
442++
443++ /* EOF, remove callback */
444++ if (status == 0)
445++ return FALSE;
446++
447++ /* not sent by kernel, ignore */
448++ if (nladdr.nl_pid != 0)
449++ return TRUE;
450++
451++ rtnl_message (self, self->buf, status);
452++
453++ return TRUE;
454++}
455++
456++static int
457++send_getlink (NMDeviceStatistics *self)
458++{
459++ struct rtnl_request req = { 0 };
460++ struct sockaddr_nl addr = { 0 };
461++ int sk;
462++
463++ req.hdr.nlmsg_len = RTNL_REQUEST_SIZE;
464++ req.hdr.nlmsg_type = RTM_GETLINK;
465++ req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
466++ req.hdr.nlmsg_pid = 0;
467++ req.hdr.nlmsg_seq = self->request_seq++;
468++ req.msg.rtgen_family = AF_UNSPEC;
469++
470++ _LOGD ("Sending %s len %d type %d flags 0x%04x seq %d",
471++ type_to_string (req.hdr.nlmsg_type),
472++ req.hdr.nlmsg_len, req.hdr.nlmsg_type,
473++ req.hdr.nlmsg_flags, req.hdr.nlmsg_seq);
474++
475++ sk = g_io_channel_unix_get_fd(self->channel);
476++
477++ addr.nl_family = AF_NETLINK;
478++
479++ self->req_pending = TRUE;
480++
481++ return sendto (sk, &req, req.hdr.nlmsg_len, 0,
482++ (struct sockaddr *) &addr, sizeof (addr));
483++}
484++
485++static gboolean
486++update_stats (gpointer user_data)
487++{
488++ NMDeviceStatistics *self = user_data;
489++
490++ if (self->req_pending) {
491++ _LOGD ("no response yet for pending netlink request");
492++ return TRUE;
493++ }
494++
495++ send_getlink (self);
496++ return TRUE;
497++}
498++
499++/********************************************/
500++
501++NMDeviceStatistics *
502++nm_device_statistics_create (NMDevice *device, const char *iface, unsigned rate_ms)
503++{
504++ NMDeviceStatistics *self;
505++ struct sockaddr_nl addr = { 0 };
506++ int sk;
507++ GIOChannel *channel = NULL;
508++ guint channel_watch = 0;
509++
510++ self = g_malloc0 (sizeof (*self));
511++
512++ sk = socket (PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_ROUTE);
513++ if (sk < 0) {
514++ _LOGE ("Cannot create netlink socket: %d", errno);
515++ goto error;
516++ }
517++
518++ addr.nl_family = AF_NETLINK;
519++ addr.nl_groups = RTMGRP_LINK;
520++
521++ if (bind (sk, (struct sockaddr *) &addr, sizeof (addr)) < 0) {
522++ close (sk);
523++ _LOGE ("Cannot bind to netlink socket: %d", errno);
524++ goto error;
525++ }
526++
527++ channel = g_io_channel_unix_new (sk);
528++
529++ g_io_channel_set_close_on_unref (channel, TRUE);
530++ g_io_channel_set_encoding (channel, NULL, NULL);
531++ g_io_channel_set_buffered (channel, FALSE);
532++
533++ channel_watch =
534++ g_io_add_watch (channel,
535++ G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
536++ netlink_event, self);
537++
538++ self->device = device;
539++ self->iface = g_strdup (iface);
540++ self->channel = channel;
541++ self->channel_watch = channel_watch;
542++ self->stats_update_id = g_timeout_add (rate_ms, update_stats, self);
543++
544++ return self;
545++
546++error:
547++ g_free (self);
548++ return NULL;
549++}
550++
551++void
552++nm_device_statistics_remove (NMDeviceStatistics *self)
553++{
554++ g_source_remove (self->stats_update_id);
555++ g_source_remove (self->channel_watch);
556++ g_io_channel_unref (self->channel);
557++ g_free (self->iface);
558++ g_free (self);
559++}
560+diff --git a/src/devices/nm-device-statistics.h b/src/devices/nm-device-statistics.h
561+new file mode 100644
562+index 0000000..496cecc
563+--- /dev/null
564++++ b/src/devices/nm-device-statistics.h
565+@@ -0,0 +1,33 @@
566++/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
567++/* This program is free software; you can redistribute it and/or modify
568++ * it under the terms of the GNU General Public License as published by
569++ * the Free Software Foundation; either version 2, or (at your option)
570++ * any later version.
571++ *
572++ * This program is distributed in the hope that it will be useful,
573++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
574++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
575++ * GNU General Public License for more details.
576++ *
577++ * You should have received a copy of the GNU General Public License along
578++ * with this program; if not, write to the Free Software Foundation, Inc.,
579++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
580++ *
581++ * Copyright (C) 2016 Canonical Ltd
582++ */
583++
584++#ifndef __NETWORKMANAGER_DEVICE_STATISTICS_H__
585++#define __NETWORKMANAGER_DEVICE_STATISTICS_H__
586++
587++#include <stdlib.h>
588++
589++#include "nm-default.h"
590++
591++typedef struct _NMDeviceStatistics NMDeviceStatistics;
592++
593++NMDeviceStatistics *
594++nm_device_statistics_create (NMDevice *device, const char *iface, unsigned rate_ms);
595++
596++void nm_device_statistics_remove (NMDeviceStatistics *self);
597++
598++#endif /* __NETWORKMANAGER_DEVICE_STATISTICS_H__ */
599+diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
600+index 8472ff8..eddd0ad 100644
601+--- a/src/devices/nm-device.c
602++++ b/src/devices/nm-device.c
603+@@ -64,11 +64,13 @@
604+ #include "sd-ipv4ll.h"
605+ #include "nm-audit-manager.h"
606+ #include "nm-arping-manager.h"
607++#include "nm-device-statistics.h"
608+
609+ #include "nm-device-logging.h"
610+ _LOG_DECLARE_SELF (NMDevice);
611+
612+ #include "nmdbus-device.h"
613++#include "nmdbus-device-statistics.h"
614+
615+ G_DEFINE_ABSTRACT_TYPE (NMDevice, nm_device, NM_TYPE_EXPORTED_OBJECT)
616+
617+@@ -124,6 +126,9 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDevice,
618+ PROP_LLDP_NEIGHBORS,
619+ PROP_REAL,
620+ PROP_SLAVES,
621++ PROP_REFRESH_RATE_MS,
622++ PROP_TX_BYTES,
623++ PROP_RX_BYTES,
624+ );
625+
626+ #define DEFAULT_AUTOCONNECT TRUE
627+@@ -369,6 +374,13 @@ typedef struct _NMDevicePrivate {
628+ NMLldpListener *lldp_listener;
629+
630+ guint check_delete_unrealized_id;
631++
632++ guint32 refresh_rate_ms;
633++ guint64 tx_bytes;
634++ guint64 rx_bytes;
635++
636++ NMDeviceStatistics *statistics;
637++
638+ } NMDevicePrivate;
639+
640+ static gboolean nm_device_set_ip4_config (NMDevice *self,
641+@@ -656,6 +668,36 @@ nm_device_set_ip_iface (NMDevice *self, const char *iface)
642+ g_free (old_ip_iface);
643+ }
644+
645++void
646++nm_device_set_tx_bytes (NMDevice *self, guint64 tx_bytes)
647++{
648++ NMDevicePrivate *priv;
649++
650++ g_return_if_fail (NM_IS_DEVICE (self));
651++
652++ priv = NM_DEVICE_GET_PRIVATE (self);
653++ if (tx_bytes == priv->tx_bytes)
654++ return;
655++
656++ priv->tx_bytes = tx_bytes;
657++ _notify (self, PROP_TX_BYTES);
658++}
659++
660++void
661++nm_device_set_rx_bytes (NMDevice *self, guint64 rx_bytes)
662++{
663++ NMDevicePrivate *priv;
664++
665++ g_return_if_fail (NM_IS_DEVICE (self));
666++
667++ priv = NM_DEVICE_GET_PRIVATE (self);
668++ if (rx_bytes == priv->rx_bytes)
669++ return;
670++
671++ priv->rx_bytes = rx_bytes;
672++ _notify (self, PROP_RX_BYTES);
673++}
674++
675+ static gboolean
676+ get_ip_iface_identifier (NMDevice *self, NMUtilsIPv6IfaceId *out_iid)
677+ {
678+@@ -11157,6 +11199,11 @@ nm_device_init (NMDevice *self)
679+
680+ priv->v4_commit_first_time = TRUE;
681+ priv->v6_commit_first_time = TRUE;
682++
683++ priv->refresh_rate_ms = 0;
684++ priv->tx_bytes = 0;
685++ priv->rx_bytes = 0;
686++ priv->statistics = NULL;
687+ }
688+
689+ static GObject*
690+@@ -11295,6 +11342,11 @@ dispose (GObject *object)
691+ g_clear_object (&priv->lldp_listener);
692+ }
693+
694++ if (priv->statistics) {
695++ nm_device_statistics_remove (priv->statistics);
696++ priv->statistics = NULL;
697++ }
698++
699+ G_OBJECT_CLASS (nm_device_parent_class)->dispose (object);
700+
701+ if (nm_clear_g_source (&priv->queued_state.id)) {
702+@@ -11342,7 +11394,7 @@ set_property (GObject *object, guint prop_id,
703+ NMDevice *self = NM_DEVICE (object);
704+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
705+ const char *hw_addr, *p;
706+- guint count;
707++ guint count, refresh_rate_ms;
708+
709+ switch (prop_id) {
710+ case PROP_UDI:
711+@@ -11447,6 +11499,24 @@ set_property (GObject *object, guint prop_id,
712+ priv->hw_addr = NULL;
713+ }
714+ break;
715++ case PROP_REFRESH_RATE_MS:
716++ refresh_rate_ms = g_value_get_uint (value);
717++ if (priv->refresh_rate_ms == refresh_rate_ms)
718++ break;
719++
720++ priv->refresh_rate_ms = g_value_get_uint (value);
721++ _LOGI (LOGD_DEVICE, "statistics refresh rate set to %u ms", priv->refresh_rate_ms);
722++
723++ if (priv->statistics) {
724++ nm_device_statistics_remove (priv->statistics);
725++ priv->statistics = NULL;
726++ }
727++ if (priv->refresh_rate_ms)
728++ priv->statistics =
729++ nm_device_statistics_create (self,
730++ nm_device_get_ip_iface (self),
731++ priv->refresh_rate_ms);
732++ break;
733+ default:
734+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
735+ break;
736+@@ -11605,6 +11675,15 @@ get_property (GObject *object, guint prop_id,
737+ g_value_take_boxed (value, slave_list);
738+ break;
739+ }
740++ case PROP_REFRESH_RATE_MS:
741++ g_value_set_uint (value, priv->refresh_rate_ms);
742++ break;
743++ case PROP_TX_BYTES:
744++ g_value_set_uint64 (value, priv->tx_bytes);
745++ break;
746++ case PROP_RX_BYTES:
747++ g_value_set_uint64 (value, priv->rx_bytes);
748++ break;
749+ default:
750+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
751+ break;
752+@@ -11848,6 +11927,23 @@ nm_device_class_init (NMDeviceClass *klass)
753+ G_PARAM_READABLE |
754+ G_PARAM_STATIC_STRINGS);
755+
756++ /* Statistics */
757++ obj_properties[PROP_REFRESH_RATE_MS] =
758++ g_param_spec_uint (NM_DEVICE_STATISTICS_REFRESH_RATE_MS, "", "",
759++ 0, UINT_MAX, 0,
760++ G_PARAM_READWRITE |
761++ G_PARAM_STATIC_STRINGS);
762++ obj_properties[PROP_TX_BYTES] =
763++ g_param_spec_uint64 (NM_DEVICE_STATISTICS_TX_BYTES, "", "",
764++ 0, UINT64_MAX, 0,
765++ G_PARAM_READABLE |
766++ G_PARAM_STATIC_STRINGS);
767++ obj_properties[PROP_RX_BYTES] =
768++ g_param_spec_uint64 (NM_DEVICE_STATISTICS_RX_BYTES, "", "",
769++ 0, UINT64_MAX, 0,
770++ G_PARAM_READABLE |
771++ G_PARAM_STATIC_STRINGS);
772++
773+ g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
774+
775+ /* Signals */
776+@@ -11918,4 +12014,8 @@ nm_device_class_init (NMDeviceClass *klass)
777+ "Disconnect", impl_device_disconnect,
778+ "Delete", impl_device_delete,
779+ NULL);
780++
781++ nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass),
782++ NMDBUS_TYPE_DEVICE_STATISTICS_SKELETON,
783++ NULL);
784+ }
785+diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h
786+index 9f68985..f226d45 100644
787+--- a/src/devices/nm-device.h
788++++ b/src/devices/nm-device.h
789+@@ -84,6 +84,10 @@
790+ #define NM_DEVICE_STATE_CHANGED "state-changed"
791+ #define NM_DEVICE_LINK_INITIALIZED "link-initialized"
792+
793++#define NM_DEVICE_STATISTICS_REFRESH_RATE_MS "refresh-rate-ms"
794++#define NM_DEVICE_STATISTICS_TX_BYTES "tx-bytes"
795++#define NM_DEVICE_STATISTICS_RX_BYTES "rx-bytes"
796++
797+ G_BEGIN_DECLS
798+
799+ #define NM_TYPE_DEVICE (nm_device_get_type ())
800+diff --git a/src/nm-exported-object.c b/src/nm-exported-object.c
801+index 10f7d23..2fdb27c 100644
802+--- a/src/nm-exported-object.c
803++++ b/src/nm-exported-object.c
804+@@ -257,12 +257,16 @@ nm_exported_object_class_add_interface (NMExportedObjectClass *object_class,
805+ g_return_if_fail (NM_IS_EXPORTED_OBJECT_CLASS (object_class));
806+ g_return_if_fail (g_type_is_a (dbus_skeleton_type, G_TYPE_DBUS_INTERFACE_SKELETON));
807+
808+- classinfo = g_slice_new (NMExportedObjectClassInfo);
809+- classinfo->skeleton_types = NULL;
810+- classinfo->methods = g_array_new (FALSE, FALSE, sizeof (NMExportedObjectDBusMethodImpl));
811+- classinfo->properties = g_hash_table_new (g_str_hash, g_str_equal);
812+- g_type_set_qdata (G_TYPE_FROM_CLASS (object_class),
813+- nm_exported_object_class_info_quark (), classinfo);
814++ classinfo = g_type_get_qdata (G_TYPE_FROM_CLASS (object_class),
815++ nm_exported_object_class_info_quark ());
816++ if (!classinfo) {
817++ classinfo = g_slice_new (NMExportedObjectClassInfo);
818++ classinfo->skeleton_types = NULL;
819++ classinfo->methods = g_array_new (FALSE, FALSE, sizeof (NMExportedObjectDBusMethodImpl));
820++ classinfo->properties = g_hash_table_new (g_str_hash, g_str_equal);
821++ g_type_set_qdata (G_TYPE_FROM_CLASS (object_class),
822++ nm_exported_object_class_info_quark (), classinfo);
823++ }
824+
825+ classinfo->skeleton_types = g_slist_prepend (classinfo->skeleton_types,
826+ GSIZE_TO_POINTER (dbus_skeleton_type));
827+@@ -342,8 +346,6 @@ nm_exported_object_class_add_interface (NMExportedObjectClass *object_class,
828+ }
829+ }
830+
831+- g_assert_cmpint (n_method_signals, ==, classinfo->methods->len);
832+-
833+ g_type_class_unref (dbus_object_class);
834+ }
835+
836+diff --git a/src/nm-types.h b/src/nm-types.h
837+index 997723e..8f859e8 100644
838+--- a/src/nm-types.h
839++++ b/src/nm-types.h
840+@@ -40,6 +40,7 @@ typedef struct _NMConnectionProvider NMConnectionProvider;
841+ typedef struct _NMConnectivity NMConnectivity;
842+ typedef struct _NMDefaultRouteManager NMDefaultRouteManager;
843+ typedef struct _NMDevice NMDevice;
844++typedef struct _NMDeviceStatistics NMDeviceStatistics;
845+ typedef struct _NMDhcp4Config NMDhcp4Config;
846+ typedef struct _NMDhcp6Config NMDhcp6Config;
847+ typedef struct _NMIP4Config NMIP4Config;
848diff --git a/debian/patches/series b/debian/patches/series
849index f0a8f73..4bd2565 100644
850--- a/debian/patches/series
851+++ b/debian/patches/series
852@@ -22,3 +22,4 @@ Modify-NMDeviceModem-s-available-logic.patch
853 Track-killswitch-change-signals-from-urfkill.patch
854 Only-test-team-devices-if-we-built-support-for-them.patch
855 Disable-general-with-expect-which-tends-to-fail-on-p.patch
856+Add-statistics-interface.patch

Subscribers

People subscribed via source and target branches