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>
39 #define MAGIC 0xFA00B916
41 struct connman_stats_data {
42 unsigned int rx_packets;
43 unsigned int tx_packets;
44 unsigned int rx_bytes;
45 unsigned int tx_bytes;
46 unsigned int rx_errors;
47 unsigned int tx_errors;
48 unsigned int rx_dropped;
49 unsigned int tx_dropped;
53 struct stats_file_header {
64 struct connman_stats_data data;
76 struct stats_record *first;
77 struct stats_record *last;
78 struct stats_record *home_first;
79 struct stats_record *roaming_first;
82 static struct stats_file_header *get_hdr(struct stats_file *file)
84 return (struct stats_file_header *)file->addr;
87 static struct stats_record *get_begin(struct stats_file *file)
89 unsigned int off = get_hdr(file)->begin;
91 return (struct stats_record *)(file->addr + off);
94 static struct stats_record *get_end(struct stats_file *file)
96 unsigned int off = get_hdr(file)->end;
98 return (struct stats_record *)(file->addr + off);
101 static struct stats_record *get_home(struct stats_file *file)
103 struct stats_file_header *hdr;
107 if (hdr->home == UINT_MAX)
110 return (struct stats_record *)(file->addr + hdr->home);
113 static struct stats_record *get_roaming(struct stats_file *file)
115 struct stats_file_header *hdr;
119 if (hdr->roaming == UINT_MAX)
122 return (struct stats_record *)(file->addr + hdr->roaming);
125 static struct stats_record *get_next(struct stats_file *file,
126 struct stats_record *cur)
130 if (cur > file->last)
136 static int get_index(struct stats_file *file, struct stats_record *rec)
138 return rec - file->first;
141 static void stats_print_record(struct stats_record *rec)
145 strftime(buffer, 30, "%d-%m-%Y %T", localtime(&rec->ts));
146 printf("%p %s %01d %d %d %d %d %d %d %d %d %d\n", rec, buffer,
148 rec->data.rx_packets,
149 rec->data.tx_packets,
154 rec->data.rx_dropped,
155 rec->data.tx_dropped,
159 static void stats_hdr_info(struct stats_file *file)
161 struct stats_file_header *hdr;
162 struct stats_record *begin, *end, *home, *roaming;
163 unsigned int home_idx, roaming_idx;
166 begin = get_begin(file);
169 home = get_home(file);
173 home_idx = get_index(file, home);
175 roaming = get_roaming(file);
177 roaming_idx = UINT_MAX;
179 roaming_idx = get_index(file, roaming);
181 printf("Data Structure Sizes\n");
182 printf(" sizeof header %zd/0x%02zx\n",
183 sizeof(struct stats_file_header),
184 sizeof(struct stats_file_header));
185 printf(" sizeof entry %zd/0%02zx\n\n",
186 sizeof(struct stats_record),
187 sizeof(struct stats_record));
190 printf(" addr %p\n", file->addr);
191 printf(" len %zd\n", file->len);
193 printf(" max nr entries %d\n", file->max_nr);
194 printf(" nr entries %d\n\n", file->nr);
197 printf(" magic 0x%08x\n", hdr->magic);
198 printf(" begin [%d] 0x%08x\n",
199 get_index(file, begin), hdr->begin);
200 printf(" end [%d] 0x%08x\n",
201 get_index(file, end), hdr->end);
202 printf(" home [%d] 0x%08x\n",
203 home_idx, hdr->home);
204 printf(" roaming [%d] 0x%08x\n\n",
205 roaming_idx, hdr->roaming);
208 printf("Pointers\n");
209 printf(" hdr %p\n", hdr);
210 printf(" begin %p\n", begin);
211 printf(" end %p\n", end);
212 printf(" home %p\n", home);
213 printf(" romaing %p\n", roaming);
214 printf(" first %p\n", file->first);
215 printf(" last %p\n\n", file->last);
218 static void stats_print_entries(struct stats_file *file)
220 struct stats_record *it;
223 printf("[ idx] ptr ts roaming rx_packets tx_packets rx_bytes "
224 "tx_bytes rx_errors tx_errors rx_dropped tx_dropped time\n\n");
226 for (i = 0, it = file->first; it <= file->last; it++, i++) {
227 printf("[%04d] ", i);
228 stats_print_record(it);
232 static void stats_print_rec_diff(struct stats_record *begin,
233 struct stats_record *end)
235 printf("\trx_packets: %d\n",
236 end->data.rx_packets - begin->data.rx_packets);
237 printf("\ttx_packets: %d\n",
238 end->data.tx_packets - begin->data.tx_packets);
239 printf("\trx_bytes: %d\n",
240 end->data.rx_bytes - begin->data.rx_bytes);
241 printf("\ttx_bytes: %d\n",
242 end->data.tx_bytes - begin->data.tx_bytes);
243 printf("\trx_errors: %d\n",
244 end->data.rx_errors - begin->data.rx_errors);
245 printf("\ttx_errors: %d\n",
246 end->data.tx_errors - begin->data.tx_errors);
247 printf("\trx_dropped: %d\n",
248 end->data.rx_dropped - begin->data.rx_dropped);
249 printf("\ttx_dropped: %d\n",
250 end->data.tx_dropped - begin->data.tx_dropped);
251 printf("\ttime: %d\n",
252 end->data.time - begin->data.time);
255 static void stats_print_diff(struct stats_file *file)
257 struct stats_record *begin, *end;
259 begin = get_begin(file);
260 begin = get_next(file, begin);
263 printf("\n(begin + 1)\n");
264 printf("\t[%04d] ", get_index(file, begin));
265 stats_print_record(begin);
267 printf("\t[%04d] ", get_index(file, end));
268 stats_print_record(end);
270 if (file->home_first) {
272 stats_print_rec_diff(file->home_first, get_home(file));
275 if (file->roaming_first) {
276 printf("\roaming\n");
277 stats_print_rec_diff(file->roaming_first, get_roaming(file));
281 static void update_max_nr_entries(struct stats_file *file)
283 file->max_nr = (file->len - sizeof(struct stats_file_header)) /
284 sizeof(struct stats_record);
287 static void update_nr_entries(struct stats_file *file)
289 struct stats_record *begin, *end;
292 begin = get_begin(file);
295 nr = get_index(file, end) - get_index(file, begin);
303 static void update_first(struct stats_file *file)
305 file->first = (struct stats_record *)(file->addr +
306 sizeof(struct stats_file_header));
309 static void update_last(struct stats_file *file)
311 struct stats_record *last;
314 last += file->max_nr - 1;
319 static int stats_file_update_cache(struct stats_file *file)
321 struct stats_record *it;
323 update_max_nr_entries(file);
324 update_nr_entries(file);
328 for (it = file->first; it <= file->last &&
329 (file->home_first == NULL ||
330 file->roaming_first == NULL); it++) {
331 if (file->home_first == NULL && it->roaming == 0)
332 file->home_first = it;
334 if (file->roaming_first == NULL && it->roaming == 1)
335 file->roaming_first = it;
340 static int stats_file_mmap(struct stats_file *file, size_t size)
344 page_size = sysconf(_SC_PAGESIZE);
345 file->len = (size + page_size - 1) & ~(page_size - 1);
347 file->addr = mmap(NULL, file->len, PROT_READ,
348 MAP_SHARED, file->fd, 0);
350 if (file->addr == MAP_FAILED) {
351 fprintf(stderr, "mmap error %s for %s\n",
352 strerror(errno), file->name);
356 stats_file_update_cache(file);
361 int main(int argc, char *argv[])
363 struct stats_file _file, *file;
368 printf("Usage: %s [STATS_FILENAME]\n", argv[0]);
373 bzero(file, sizeof(struct stats_file));
375 file->name = argv[1];
377 file->fd = open(file->name, O_RDONLY, 0644);
378 if (file->fd == -1) {
379 fprintf(stderr, "open error %s for %s\n",
380 strerror(errno), file->name);
384 err = fstat(file->fd, &stat);
386 fprintf(stderr, "fstat error %s for %s\n",
387 strerror(errno), file->name);
391 err = stats_file_mmap(file, stat.st_size);
395 if (get_hdr(file)->magic != MAGIC) {
397 printf("No valid magic found\n");
400 stats_hdr_info(file);
401 stats_print_entries(file);
402 stats_print_diff(file);
404 munmap(file->addr, file->len);