Add support for exporting basic interface statistics
authorMarcel Holtmann <marcel@holtmann.org>
Tue, 5 Jan 2010 14:59:20 +0000 (06:59 -0800)
committerMarcel Holtmann <marcel@holtmann.org>
Tue, 5 Jan 2010 14:59:20 +0000 (06:59 -0800)
src/connman.h
src/counter.c
src/ipconfig.c
src/rtnl.c
test/test-counter

index 109ed8e..0537bf0 100644 (file)
@@ -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);
index 9dea4b7..224d122 100644 (file)
@@ -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;
index 77720fd..0d0426e 100644 (file)
@@ -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,
index 2137788..12ebdcb 100644 (file)
@@ -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;
index b0173a4..d000a8d 100755 (executable)
@@ -14,9 +14,11 @@ class Counter(dbus.service.Object):
                mainloop.quit()
 
        @dbus.service.method("org.moblin.connman.Counter",
-                                       in_signature='', out_signature='')
-       def Usage(self):
-               print("Usage")
+                                       in_signature='a{sv}', out_signature='')
+       def Usage(self, stats):
+               for key in stats.keys():
+                       val = int(stats[key])
+                       print "%s = %s" % (key, val)
 
 if __name__ == '__main__':
        dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)