summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2010-01-05 06:59:20 -0800
committerMarcel Holtmann <marcel@holtmann.org>2010-01-05 06:59:20 -0800
commitf33303b557c1c12313c42372fdd173c4e69ddef0 (patch)
tree1191ef752ba20b221a57043100e8bf6bbfbd9286 /src
parentf2af98906f063a65f2933e6133a293c344a1f011 (diff)
downloadconnman-f33303b557c1c12313c42372fdd173c4e69ddef0.tar.gz
connman-f33303b557c1c12313c42372fdd173c4e69ddef0.tar.bz2
connman-f33303b557c1c12313c42372fdd173c4e69ddef0.zip
Add support for exporting basic interface statistics
Diffstat (limited to 'src')
-rw-r--r--src/connman.h10
-rw-r--r--src/counter.c55
-rw-r--r--src/ipconfig.c63
-rw-r--r--src/rtnl.c39
4 files changed, 121 insertions, 46 deletions
diff --git a/src/connman.h b/src/connman.h
index 109ed8e5..0537bf09 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -69,6 +69,8 @@ int __connman_counter_register(const char *owner, const char *path,
unsigned int interval);
int __connman_counter_unregister(const char *owner, const char *path);
+void __connman_counter_notify(unsigned int rx_bytes, unsigned int tx_bytes);
+
int __connman_counter_init(void);
void __connman_counter_cleanup(void);
@@ -110,10 +112,13 @@ int __connman_security_check_privilege(DBusMessage *message,
int __connman_ipconfig_init(void);
void __connman_ipconfig_cleanup(void);
+struct rtnl_link_stats;
+
void __connman_ipconfig_newlink(int index, unsigned short type,
unsigned int flags, const char *address,
- unsigned short mtu);
-void __connman_ipconfig_dellink(int index);
+ unsigned short mtu,
+ struct rtnl_link_stats *stats);
+void __connman_ipconfig_dellink(int index, struct rtnl_link_stats *stats);
void __connman_ipconfig_newaddr(int index, const char *label,
unsigned char prefixlen, const char *address);
void __connman_ipconfig_deladdr(int index, const char *label,
@@ -427,4 +432,5 @@ int __connman_rtnl_init(void);
void __connman_rtnl_start(void);
void __connman_rtnl_cleanup(void);
+int __connman_rtnl_request_update(void);
int __connman_rtnl_send(const void *buf, size_t len);
diff --git a/src/counter.c b/src/counter.c
index 9dea4b7e..224d122e 100644
--- a/src/counter.c
+++ b/src/counter.c
@@ -37,6 +37,8 @@ struct connman_counter {
char *path;
guint timeout;
guint watch;
+ unsigned int rx_bytes;
+ unsigned int tx_bytes;
};
static void remove_counter(gpointer user_data)
@@ -69,18 +71,10 @@ static void owner_disconnect(DBusConnection *connection, void *user_data)
static gboolean counter_timeout(gpointer user_data)
{
struct connman_counter *counter = user_data;
- DBusMessage *message;
DBG("owner %s path %s", counter->owner, counter->path);
- message = dbus_message_new_method_call(counter->owner, counter->path,
- CONNMAN_COUNTER_INTERFACE, "Usage");
- if (message == NULL)
- return TRUE;
-
- dbus_message_set_no_reply(message, TRUE);
-
- g_dbus_send_message(connection, message);
+ __connman_rtnl_request_update();
return TRUE;
}
@@ -134,6 +128,49 @@ int __connman_counter_unregister(const char *owner, const char *path)
return 0;
}
+static void send_usage(struct connman_counter *counter)
+{
+ DBusMessage *message;
+ DBusMessageIter array, dict;
+
+ message = dbus_message_new_method_call(counter->owner, counter->path,
+ CONNMAN_COUNTER_INTERFACE, "Usage");
+ if (message == NULL)
+ return;
+
+ dbus_message_set_no_reply(message, TRUE);
+
+ dbus_message_iter_init_append(message, &array);
+
+ connman_dbus_dict_open(&array, &dict);
+
+ connman_dbus_dict_append_basic(&dict, "RX.Bytes",
+ DBUS_TYPE_UINT32, &counter->rx_bytes);
+ connman_dbus_dict_append_basic(&dict, "TX.Bytes",
+ DBUS_TYPE_UINT32, &counter->tx_bytes);
+
+ connman_dbus_dict_close(&array, &dict);
+
+ g_dbus_send_message(connection, message);
+}
+
+void __connman_counter_notify(unsigned int rx_bytes, unsigned int tx_bytes)
+{
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_hash_table_iter_init(&iter, counter_table);
+
+ while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
+ struct connman_counter *counter = value;
+
+ counter->rx_bytes = rx_bytes;
+ counter->tx_bytes = tx_bytes;
+
+ send_usage(counter);
+ }
+}
+
static void release_counter(gpointer key, gpointer value, gpointer user_data)
{
struct connman_counter *counter = value;
diff --git a/src/ipconfig.c b/src/ipconfig.c
index 77720fd5..0d0426e2 100644
--- a/src/ipconfig.c
+++ b/src/ipconfig.c
@@ -25,6 +25,7 @@
#include <net/if.h>
#include <net/if_arp.h>
+#include <linux/if_link.h>
#ifndef IFF_LOWER_UP
#define IFF_LOWER_UP 0x10000
@@ -46,9 +47,6 @@ struct connman_ipconfig {
enum connman_ipconfig_method method;
struct connman_ipaddress *address;
struct connman_ipaddress *system;
-
- char *eth;
- uint16_t mtu;
};
struct connman_ipdevice {
@@ -56,6 +54,10 @@ struct connman_ipdevice {
char *ifname;
unsigned short type;
unsigned int flags;
+ char *address;
+ uint16_t mtu;
+ uint32_t tx_bytes;
+ uint32_t rx_bytes;
GSList *address_list;
char *gateway;
@@ -231,6 +233,7 @@ static void free_ipdevice(gpointer data)
free_address_list(ipdevice);
g_free(ipdevice->gateway);
+ g_free(ipdevice->address);
g_free(ipdevice->ifname);
g_free(ipdevice);
}
@@ -337,9 +340,30 @@ static void __connman_ipconfig_lower_down(struct connman_ipdevice *ipdevice)
connman_inet_clear_address(ipdevice->index);
}
+static void update_stats(struct connman_ipdevice *ipdevice,
+ struct rtnl_link_stats *stats)
+{
+ if (stats->rx_packets == 0 && stats->tx_packets == 0)
+ return;
+
+ connman_info("%s {RX} %u packets %u bytes", ipdevice->ifname,
+ stats->rx_packets, stats->rx_bytes);
+ connman_info("%s {TX} %u packets %u bytes", ipdevice->ifname,
+ stats->tx_packets, stats->tx_bytes);
+
+ if (ipdevice->config == NULL)
+ return;
+
+ ipdevice->rx_bytes = stats->rx_bytes;
+ ipdevice->tx_bytes = stats->tx_bytes;
+
+ __connman_counter_notify(ipdevice->rx_bytes, ipdevice->tx_bytes);
+}
+
void __connman_ipconfig_newlink(int index, unsigned short type,
unsigned int flags, const char *address,
- unsigned short mtu)
+ unsigned short mtu,
+ struct rtnl_link_stats *stats)
{
struct connman_ipdevice *ipdevice;
GList *list;
@@ -375,17 +399,17 @@ void __connman_ipconfig_newlink(int index, unsigned short type,
ipdevice->ifname = ifname;
ipdevice->type = type;
+ ipdevice->address = g_strdup(address);
+
g_hash_table_insert(ipdevice_hash, GINT_TO_POINTER(index), ipdevice);
connman_info("%s {create} index %d type %d <%s>", ipdevice->ifname,
index, type, type2str(type));
update:
- if (ipdevice->config != NULL) {
- g_free(ipdevice->config->eth);
- ipdevice->config->eth = g_strdup(address);
- ipdevice->config->mtu = mtu;
- }
+ ipdevice->mtu = mtu;
+
+ update_stats(ipdevice, stats);
if (flags == ipdevice->flags)
return;
@@ -455,7 +479,7 @@ update:
__connman_ipconfig_lower_down(ipdevice);
}
-void __connman_ipconfig_dellink(int index)
+void __connman_ipconfig_dellink(int index, struct rtnl_link_stats *stats)
{
struct connman_ipdevice *ipdevice;
GList *list;
@@ -466,6 +490,8 @@ void __connman_ipconfig_dellink(int index)
if (ipdevice == NULL)
return;
+ update_stats(ipdevice, stats);
+
for (list = g_list_first(ipconfig_list); list;
list = g_list_next(list)) {
struct connman_ipconfig *ipconfig = list->data;
@@ -771,7 +797,6 @@ void connman_ipconfig_unref(struct connman_ipconfig *ipconfig)
connman_ipaddress_free(ipconfig->system);
connman_ipaddress_free(ipconfig->address);
- g_free(ipconfig->eth);
g_free(ipconfig);
}
}
@@ -1139,14 +1164,6 @@ void __connman_ipconfig_append_ethernet(struct connman_ipconfig *ipconfig,
connman_dbus_dict_append_basic(iter, "Method",
DBUS_TYPE_STRING, &method);
- if (ipconfig->eth != NULL)
- connman_dbus_dict_append_basic(iter, "Address",
- DBUS_TYPE_STRING, &ipconfig->eth);
-
- if (ipconfig->mtu > 0)
- connman_dbus_dict_append_basic(iter, "MTU",
- DBUS_TYPE_UINT16, &ipconfig->mtu);
-
ipdevice = g_hash_table_lookup(ipdevice_hash,
GINT_TO_POINTER(ipconfig->index));
if (ipdevice == NULL)
@@ -1155,6 +1172,14 @@ void __connman_ipconfig_append_ethernet(struct connman_ipconfig *ipconfig,
if (ipdevice->ifname != NULL)
connman_dbus_dict_append_basic(iter, "Interface",
DBUS_TYPE_STRING, &ipdevice->ifname);
+
+ if (ipdevice->address != NULL)
+ connman_dbus_dict_append_basic(iter, "Address",
+ DBUS_TYPE_STRING, &ipdevice->address);
+
+ if (ipdevice->mtu > 0)
+ connman_dbus_dict_append_basic(iter, "MTU",
+ DBUS_TYPE_UINT16, &ipdevice->mtu);
}
int __connman_ipconfig_load(struct connman_ipconfig *ipconfig,
diff --git a/src/rtnl.c b/src/rtnl.c
index 2137788a..12ebdcbe 100644
--- a/src/rtnl.c
+++ b/src/rtnl.c
@@ -242,9 +242,9 @@ static const char *operstate2str(unsigned char operstate)
static void extract_link(struct ifinfomsg *msg, int bytes,
struct ether_addr *address, const char **ifname,
- unsigned int *mtu, unsigned char *operstate)
+ unsigned int *mtu, unsigned char *operstate,
+ struct rtnl_link_stats *stats)
{
- struct rtnl_link_stats stats;
struct rtattr *attr;
for (attr = IFLA_RTA(msg); RTA_OK(attr, bytes);
@@ -263,12 +263,9 @@ static void extract_link(struct ifinfomsg *msg, int bytes,
*mtu = *((unsigned int *) RTA_DATA(attr));
break;
case IFLA_STATS:
- memcpy(&stats, RTA_DATA(attr),
+ if (stats != NULL)
+ memcpy(stats, RTA_DATA(attr),
sizeof(struct rtnl_link_stats));
- connman_info("%s {RX} %d packets %d bytes", *ifname,
- stats.rx_packets, stats.rx_bytes);
- connman_info("%s {TX} %d packets %d bytes", *ifname,
- stats.tx_packets, stats.tx_bytes);
break;
case IFLA_OPERSTATE:
if (operstate != NULL)
@@ -285,27 +282,30 @@ static void process_newlink(unsigned short type, int index, unsigned flags,
{
struct ether_addr address = {{ 0, 0, 0, 0, 0, 0 }};
struct ether_addr compare = {{ 0, 0, 0, 0, 0, 0 }};
+ struct rtnl_link_stats stats;
unsigned char operstate = 0xff;
const char *ifname = NULL;
unsigned int mtu = 0;
char str[18];
GSList *list;
- extract_link(msg, bytes, &address, &ifname, &mtu, &operstate);
+ memset(&stats, 0, sizeof(stats));
+ extract_link(msg, bytes, &address, &ifname, &mtu, &operstate, &stats);
snprintf(str, 18, "%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]);
+ 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]);
switch (type) {
case ARPHRD_ETHER:
case ARPHRD_LOOPBACK:
case ARPHRD_NONE:
- __connman_ipconfig_newlink(index, type, flags, str, mtu);
+ __connman_ipconfig_newlink(index, type, flags,
+ str, mtu, &stats);
break;
}
@@ -342,11 +342,13 @@ static void process_newlink(unsigned short type, int index, unsigned flags,
static void process_dellink(unsigned short type, int index, unsigned flags,
unsigned change, struct ifinfomsg *msg, int bytes)
{
+ struct rtnl_link_stats stats;
unsigned char operstate = 0xff;
const char *ifname = NULL;
GSList *list;
- extract_link(msg, bytes, NULL, &ifname, NULL, &operstate);
+ memset(&stats, 0, sizeof(stats));
+ extract_link(msg, bytes, NULL, &ifname, NULL, &operstate, &stats);
if (operstate != 0xff)
connman_info("%s {dellink} index %d operstate %u <%s>",
@@ -374,7 +376,7 @@ static void process_dellink(unsigned short type, int index, unsigned flags,
case ARPHRD_ETHER:
case ARPHRD_LOOPBACK:
case ARPHRD_NONE:
- __connman_ipconfig_dellink(index);
+ __connman_ipconfig_dellink(index, &stats);
break;
}
}
@@ -1049,6 +1051,11 @@ static int send_getroute(void)
return queue_request(req);
}
+int __connman_rtnl_request_update(void)
+{
+ return send_getlink();
+}
+
int __connman_rtnl_init(void)
{
struct sockaddr_nl addr;