5 * Copyright (C) 2010 BMW Car IT GmbH. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 #include <sys/types.h>
40 #define MAGIC 0xFA00B915
42 struct connman_stats_data {
43 unsigned int rx_packets;
44 unsigned int tx_packets;
45 unsigned int rx_bytes;
46 unsigned int tx_bytes;
47 unsigned int rx_errors;
48 unsigned int tx_errors;
49 unsigned int rx_dropped;
50 unsigned int tx_dropped;
54 struct stats_file_header {
62 struct connman_stats_data data;
74 struct stats_record *first;
75 struct stats_record *last;
78 static struct stats_file_header *get_hdr(struct stats_file *file)
80 return (struct stats_file_header *)file->addr;
83 static struct stats_record *get_begin(struct stats_file *file)
85 unsigned int off = get_hdr(file)->begin;
87 return (struct stats_record *)(file->addr + off);
90 static struct stats_record *get_end(struct stats_file *file)
92 unsigned int off = get_hdr(file)->end;
94 return (struct stats_record *)(file->addr + off);
97 static struct stats_record *get_next(struct stats_file *file,
98 struct stats_record *cur)
102 if (cur > file->last)
108 static int get_index(struct stats_file *file, struct stats_record *rec)
110 return rec - file->first;
113 static void stats_print_record(struct stats_record *rec)
117 strftime(buffer, 30, "%d-%m-%Y %T", localtime(&rec->ts));
118 printf("%p %s %d %d %d %d %d %d %d %d %d\n", rec, buffer,
119 rec->data.rx_packets,
120 rec->data.tx_packets,
125 rec->data.rx_dropped,
126 rec->data.tx_dropped,
130 static void stats_hdr_info(struct stats_file *file)
132 struct stats_file_header *hdr;
133 struct stats_record *begin, *end;
136 begin = get_begin(file);
139 printf("Data Structure Sizes\n");
140 printf(" sizeof header %zd/0x%02zx\n",
141 sizeof(struct stats_file_header),
142 sizeof(struct stats_file_header));
143 printf(" sizeof entry %zd/0%02zx\n\n",
144 sizeof(struct stats_record),
145 sizeof(struct stats_record));
148 printf(" addr %p\n", file->addr);
149 printf(" len %zd\n", file->len);
151 printf(" max nr entries %d\n", file->max_nr);
152 printf(" nr entries %d\n\n", file->nr);
155 printf(" magic 0x%08x\n", hdr->magic);
156 printf(" begin [%d] 0x%08x\n",
157 get_index(file, begin), hdr->begin);
158 printf(" end [%d] 0x%08x\n\n",
159 get_index(file, end), hdr->end);
161 printf("Pointers\n");
162 printf(" hdr %p\n", hdr);
163 printf(" begin %p\n", begin);
164 printf(" end %p\n", end);
165 printf(" first %p\n", file->first);
166 printf(" last %p\n\n", file->last);
169 static void stats_print_entries(struct stats_file *file)
171 struct stats_record *it;
174 printf("[ idx] ptr ts rx_packets tx_packets rx_bytes "
175 "tx_bytes rx_errors tx_errors rx_dropped tx_dropped time\n\n");
177 for (i = 0, it = file->first; it <= file->last; it++, i++) {
178 printf("[%04d] ", i);
179 stats_print_record(it);
183 static void stats_print_diff(struct stats_file *file)
185 struct stats_record *begin, *end;
187 begin = get_begin(file);
188 begin = get_next(file, begin);
191 printf("\n(begin + 1)\n");
192 printf("\t[%04d] ", get_index(file, begin));
193 stats_print_record(begin);
195 printf("\t[%04d] ", get_index(file, end));
196 stats_print_record(end);
198 printf("\nend - (begin + 1):\n");
199 printf("\trx_packets: %d\n",
200 end->data.rx_packets - begin->data.rx_packets);
201 printf("\ttx_packets: %d\n",
202 end->data.tx_packets - begin->data.tx_packets);
203 printf("\trx_bytes: %d\n",
204 end->data.rx_bytes - begin->data.rx_bytes);
205 printf("\ttx_bytes: %d\n",
206 end->data.tx_bytes - begin->data.tx_bytes);
207 printf("\trx_errors: %d\n",
208 end->data.rx_errors - begin->data.rx_errors);
209 printf("\ttx_errors: %d\n",
210 end->data.tx_errors - begin->data.tx_errors);
211 printf("\trx_dropped: %d\n",
212 end->data.rx_dropped - begin->data.rx_dropped);
213 printf("\ttx_dropped: %d\n",
214 end->data.tx_dropped - begin->data.tx_dropped);
215 printf("\ttime: %d\n",
216 end->data.time - begin->data.time);
219 static void update_max_nr_entries(struct stats_file *file)
221 file->max_nr = (file->len - sizeof(struct stats_file_header)) /
222 sizeof(struct stats_record);
225 static void update_nr_entries(struct stats_file *file)
227 struct stats_record *begin, *end;
230 begin = get_begin(file);
233 nr = get_index(file, end) - get_index(file, begin);
241 static void update_first(struct stats_file *file)
243 file->first = (struct stats_record *)(file->addr +
244 sizeof(struct stats_file_header));
247 static void update_last(struct stats_file *file)
249 struct stats_record *last;
252 last += file->max_nr - 1;
257 static int stats_file_update_cache(struct stats_file *file)
259 update_max_nr_entries(file);
260 update_nr_entries(file);
267 static int stats_file_mmap(struct stats_file *file, size_t size)
271 page_size = sysconf(_SC_PAGESIZE);
272 file->len = (size + page_size - 1) & ~(page_size - 1);
274 file->addr = mmap(NULL, file->len, PROT_READ,
275 MAP_SHARED, file->fd, 0);
277 if (file->addr == MAP_FAILED) {
278 fprintf(stderr, "mmap error %s for %s\n",
279 strerror(errno), file->name);
283 stats_file_update_cache(file);
288 int main(int argc, char *argv[])
290 struct stats_file _file, *file;
295 printf("Usage: %s [STATS_FILENAME]\n", argv[0]);
300 bzero(file, sizeof(struct stats_file));
302 file->name = argv[1];
304 file->fd = open(file->name, O_RDONLY, 0644);
305 if (file->fd == -1) {
306 fprintf(stderr, "open error %s for %s\n",
307 strerror(errno), file->name);
311 err = fstat(file->fd, &stat);
313 fprintf(stderr, "fstat error %s for %s\n",
314 strerror(errno), file->name);
318 err = stats_file_mmap(file, stat.st_size);
322 if (get_hdr(file)->magic != MAGIC) {
324 printf("No valid magic found\n");
327 stats_hdr_info(file);
328 stats_print_entries(file);
329 stats_print_diff(file);
331 munmap(file->addr, file->len);