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