From: Daniel Wagner <[email protected]>

This tool prints the statistic ring buffer.
---
 Makefile.am                   |    3 +-
 tools/stats-ringbuffer-test.c |  283 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 285 insertions(+), 1 deletions(-)
 create mode 100644 tools/stats-ringbuffer-test.c

diff --git a/Makefile.am b/Makefile.am
index e146528..448aa66 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -128,7 +128,8 @@ if TOOLS
 noinst_PROGRAMS += tools/wifi-scan tools/supplicant-test tools/dhcp-test \
                        tools/addr-test tools/web-test tools/resolv-test \
                        tools/dbus-test tools/polkit-test tools/portal-test \
-                       tools/iptables-test tools/tap-test tools/wpad-test
+                       tools/iptables-test tools/tap-test tools/wpad-test \
+                       tools/stats-ringbuffer-test
 
 tools_wifi_scan_LDADD = @GLIB_LIBS@ @NETLINK_LIBS@
 
diff --git a/tools/stats-ringbuffer-test.c b/tools/stats-ringbuffer-test.c
new file mode 100644
index 0000000..1ea92c1
--- /dev/null
+++ b/tools/stats-ringbuffer-test.c
@@ -0,0 +1,283 @@
+/*
+ *
+ *  Connection Manager
+ *
+ *  Copyright (C) 2010  BMW Car IT GmbH. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#define _GNU_SOURCE
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <sys/time.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#define MAGIC 0xFA00B905
+
+struct connman_stats_data {
+       unsigned int rx_packets;
+       unsigned int tx_packets;
+       unsigned int rx_bytes;
+       unsigned int tx_bytes;
+       unsigned int rx_errors;
+       unsigned int tx_errors;
+       unsigned int rx_dropped;
+       unsigned int tx_dropped;
+       unsigned int time;
+};
+
+struct stats_file_header {
+       unsigned int magic;
+       unsigned int first;
+       unsigned int last;
+       unsigned int total;
+};
+
+struct stats_record {
+       struct timeval tv;
+       struct connman_stats_data data;
+};
+
+struct stats_file {
+       int fd;
+       char *addr;
+       size_t len;
+       size_t max_len;
+};
+
+static struct stats_file_header *get_hdr(struct stats_file *file)
+{
+       return (struct stats_file_header *)file->addr;
+}
+
+static struct stats_record *get_first(struct stats_file *file)
+{
+       return (struct stats_record *)(file->addr + get_hdr(file)->first);
+}
+
+static struct stats_record *get_last(struct stats_file *file)
+{
+       return (struct stats_record *)(file->addr + get_hdr(file)->last);
+}
+
+static struct stats_record *rec_inc_wrap(struct stats_file *file, 
+                                       struct stats_record *cur)
+{
+       char *next, *next_end;
+
+       next = (char *)(cur + 1);
+       next_end = (char *)(cur + 2);
+
+       if (next_end >= file->addr + file->max_len)
+               next = file->addr + sizeof(struct stats_file_header);
+
+       return (struct stats_record *)next;
+}
+
+static void stats_print_record(struct stats_record *rec)
+{
+       char buffer[30];
+       time_t curtime;
+       
+       curtime=rec->tv.tv_sec;
+
+       strftime(buffer,30,"%d-%m-%Y %T", localtime(&curtime));
+       printf("%p %s %d %d %d %d %d %d %d %d %d\n", rec, buffer, 
+               rec->data.rx_packets,
+               rec->data.tx_packets,
+               rec->data.tx_bytes,
+               rec->data.tx_bytes,
+               rec->data.rx_errors,
+               rec->data.tx_errors,
+               rec->data.rx_dropped,
+               rec->data.tx_dropped,
+               rec->data.time);
+}
+
+static int stats_collect(struct stats_file *file)
+{
+       struct stats_record *it, *first, *last, *prev;
+       struct stats_file_header *hdr;
+       int i;
+       int nr, max_nr, hdr_first_idx, hdr_last_idx;
+       struct connman_stats_data sum = { 0, };
+
+       /* assume the file is valid */
+       hdr = get_hdr(file);
+       first = get_first(file);
+       last = get_last(file);
+       hdr_first_idx = (hdr->first - sizeof(struct stats_file_header)) / 
sizeof(struct stats_record);
+       hdr_last_idx = (hdr->last - sizeof(struct stats_file_header)) / 
sizeof(struct stats_record);
+       nr = hdr_last_idx - hdr_first_idx;
+       max_nr = (file->len - sizeof(struct stats_file_header)) / sizeof(struct 
stats_record);
+
+       if (nr < 0)
+               nr += max_nr;
+
+       printf("sizeof header:  %ld/0x%02lx\n", sizeof(struct 
stats_file_header), sizeof(struct stats_file_header));
+       printf("sizeof entry:   %ld/0x%02lx\n", sizeof(struct stats_record), 
sizeof(struct stats_record));
+       printf("hdr:            %p\n", hdr);
+       printf("first:          %p\n", first);
+       printf("last:           %p\n", last);
+       printf("hdr magic:      0x%08x\n", hdr->magic);
+       printf("hdr first:      [%d] 0x%08x\n", hdr_first_idx, hdr->first);
+       printf("hdr last:       [%d] 0x%08x\n", hdr_last_idx, hdr->last);
+       printf("file addr:      %p\n", file->addr);
+       printf("file len:       %ld\n", file->len);
+       printf("file max_len:   %ld\n", file->max_len);
+       printf("nr entries:     %d\n", nr);
+       printf("max nr entries: %d\n\n", max_nr);
+
+       if (first == last) {
+               /* empty */
+               return 0;
+       }
+
+       printf("[idx] ptr ts rx_packets tx_packets rx_bytes tx_bytes rx_errors 
tx_errors rx_dropped tx_dropped time\n");
+
+       it = rec_inc_wrap(file, first);
+       i = 0;
+       prev = NULL;
+
+       do {
+               printf("[%03d] ", i);
+               stats_print_record(it);
+
+               if (prev != NULL) {
+                       sum.rx_packets += it->data.rx_packets - 
prev->data.rx_packets;
+                       sum.tx_packets += it->data.tx_packets - 
prev->data.tx_packets;
+                       sum.rx_bytes += it->data.rx_bytes - prev->data.rx_bytes;
+                       sum.tx_bytes += it->data.tx_bytes - prev->data.tx_bytes;
+                       sum.rx_errors += it->data.rx_errors - 
prev->data.rx_errors;
+                       sum.tx_errors += it->data.tx_errors - 
prev->data.tx_errors;
+                       sum.rx_dropped += it->data.rx_dropped - 
prev->data.rx_dropped;
+                       sum.tx_dropped += it->data.tx_dropped - 
prev->data.tx_dropped;
+                       sum.time += it->data.time - prev->data.time;
+               }
+
+               prev = it;
+               it = rec_inc_wrap(file, it);
+               i++;
+       } while (it != rec_inc_wrap(file,last) && i < nr);
+
+       printf("\nDiff Sum:\n");
+       printf("\trx_packets: %d\n", sum.rx_packets);
+       printf("\ttx_packets: %d\n", sum.tx_packets);
+       printf("\trx_bytes:   %d\n", sum.rx_bytes);
+       printf("\ttx_bytes:   %d\n", sum.tx_bytes);
+       printf("\trx_errors:  %d\n", sum.rx_errors);
+       printf("\ttx_errors:  %d\n", sum.tx_errors);
+       printf("\trx_dropped: %d\n", sum.rx_dropped);
+       printf("\ttx_dropped: %d\n", sum.tx_dropped);
+       printf("\ttime:       %d\n", sum.time);
+       
+       printf("\nDiff Calc:\n");
+
+       first = rec_inc_wrap(file, first);
+
+       stats_print_record(first);
+       stats_print_record(last);
+
+       printf("\trx_packets: %d\n", last->data.rx_packets - 
first->data.rx_packets);
+       printf("\ttx_packets: %d\n", last->data.tx_packets - 
first->data.tx_packets);
+       printf("\trx_bytes:   %d\n", last->data.rx_bytes - 
first->data.rx_bytes);
+       printf("\ttx_bytes:   %d\n", last->data.tx_bytes - 
first->data.tx_bytes);
+       printf("\trx_errors:  %d\n", last->data.rx_errors - 
first->data.rx_errors);
+       printf("\ttx_errors:  %d\n", last->data.tx_errors - 
first->data.tx_errors);
+       printf("\trx_dropped: %d\n", last->data.rx_dropped - 
first->data.rx_dropped);
+       printf("\ttx_dropped: %d\n", last->data.tx_dropped - 
first->data.tx_dropped);
+       printf("\ttime:       %d\n", last->data.time - first->data.time);
+
+       return 0;
+}
+
+static int stats_file_remap(struct stats_file *file, size_t size)
+{
+       size_t ps, ns;
+       void *np;
+       int err;
+
+       ps = sysconf(_SC_PAGESIZE);
+       ns = (size + ps - 1) & ~(ps - 1);
+       
+       if (size < ns) {
+               err = ftruncate(file->fd, ns);
+               if (err < 0)
+                       return -errno;
+       }
+
+       if (file->addr == NULL) {
+               np = mmap(NULL, ns, PROT_READ, MAP_SHARED, file->fd, 0);
+       } else {
+               np = mremap(file->addr, file->len, ns, MREMAP_MAYMOVE);
+       }
+
+       if (np == MAP_FAILED)
+               return -errno;
+
+       file->addr = np;
+       file->len = ns;
+
+       return 0;
+}
+
+int main(int argc, char *argv[])
+{
+       struct stats_file _file, *file;
+       const char *filename;
+       struct stat stat;
+       int err;
+
+       if (argc < 2) {
+               printf("%s FILENAME\n", argv[0]);
+               exit(0);
+       }
+               
+       filename = argv[1];
+
+       file = &_file;
+
+       bzero(file, sizeof(struct stats_file));
+
+       file->fd = open(filename, O_RDONLY, 0644);
+       if (file->fd == -1)
+               return -errno;
+
+       err = fstat(file->fd, &stat);
+       if (err < 0)
+               return -errno;
+
+       file->max_len = stat.st_size;
+       err = stats_file_remap(file, stat.st_size);
+       if (err < 0)
+               return err;
+
+       stats_collect(file);
+
+       munmap(file->addr, file->len);
+       close(file->fd);
+               
+       return 0;
+}
-- 
1.7.2.2

_______________________________________________
connman mailing list
[email protected]
http://lists.connman.net/listinfo/connman

Reply via email to