Annotation of embedaddon/bmon/src/bmon.c, revision 1.1.1.2
1.1 misho 1: /*
2: * src/bmon.c Bandwidth Monitor
3: *
1.1.1.2 ! misho 4: * Copyright (c) 2001-2013 Thomas Graf <tgraf@suug.ch>
! 5: * Copyright (c) 2013 Red Hat, Inc.
1.1 misho 6: *
7: * Permission is hereby granted, free of charge, to any person obtaining a
8: * copy of this software and associated documentation files (the "Software"),
9: * to deal in the Software without restriction, including without limitation
10: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11: * and/or sell copies of the Software, and to permit persons to whom the
12: * Software is furnished to do so, subject to the following conditions:
13: *
14: * The above copyright notice and this permission notice shall be included
15: * in all copies or substantial portions of the Software.
16: *
17: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22: * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23: * DEALINGS IN THE SOFTWARE.
24: */
25:
26: #include <bmon/bmon.h>
27: #include <bmon/conf.h>
1.1.1.2 ! misho 28: #include <bmon/attr.h>
! 29: #include <bmon/utils.h>
1.1 misho 30: #include <bmon/input.h>
31: #include <bmon/output.h>
1.1.1.2 ! misho 32: #include <bmon/module.h>
! 33: #include <bmon/group.h>
1.1 misho 34:
35: int start_time;
36: int do_quit = 0;
1.1.1.2 ! misho 37: int is_daemon = 0;
1.1 misho 38:
39: struct reader_timing rtiming;
1.1.1.2 ! misho 40:
1.1 misho 41: static char *usage_text =
42: "Usage: bmon [OPTION]...\n" \
43: "\n" \
44: "Options:\n" \
1.1.1.2 ! misho 45: "Startup:\n" \
! 46: " -i, --input=MODPARM Input module(s)\n" \
! 47: " -o, --output=MODPARM Output module(s)\n" \
! 48: " -f, --configfile=PATH Alternative path to configuration file\n" \
! 49: " -h, --help Show this help text\n" \
! 50: " -V, --version Show version\n" \
! 51: "\n" \
! 52: "Input:\n" \
! 53: " -p, --policy=POLICY Element display policy (see below)\n" \
! 54: " -a, --show-all Show all elements (even disabled elements)\n" \
! 55: " -r, --read-interval=FLOAT Read interval in seconds (float)\n" \
! 56: " -R, --rate-interval=FLOAT Rate interval in seconds (float)\n" \
! 57: " -s, --sleep-interval=FLOAT Sleep time in seconds (float)\n" \
! 58: " -L, --lifetime=LIFETIME Lifetime of an element in seconds (float)\n" \
! 59: "\n" \
! 60: "Output:\n" \
! 61: " -U, --use-si Use SI units\n" \
! 62: " -b, --use-bit Display in bits instead of bytes\n" \
1.1 misho 63: "\n" \
64: "Module configuration:\n" \
65: " modparm := MODULE:optlist,MODULE:optlist,...\n" \
66: " optlist := option;option;...\n" \
67: " option := TYPE[=VALUE]\n" \
68: "\n" \
69: " Examples:\n" \
1.1.1.2 ! misho 70: " -o curses:ngraph=2\n" \
! 71: " -o list # Shows a list of available modules\n" \
! 72: " -o curses:help # Shows a help text for html module\n" \
1.1 misho 73: "\n" \
74: "Interface selection:\n" \
75: " policy := [!]simple_regexp,[!]simple_regexp,...\n" \
76: "\n" \
77: " Example: -p 'eth*,lo*,!eth1'\n" \
78: "\n" \
79: "Please see the bmon(1) man pages for full documentation.\n";
80:
81: static void do_shutdown(void)
82: {
83: static int done;
84:
85: if (!done) {
86: done = 1;
1.1.1.2 ! misho 87: module_shutdown();
1.1 misho 88: }
89: }
90:
91: RETSIGTYPE sig_int(int unused)
92: {
93: if (do_quit)
94: exit(-1);
95: do_quit = 1;
96: }
97:
98: void sig_exit(void)
99: {
100: do_shutdown();
101: }
102:
103: void quit(const char *fmt, ...)
104: {
105: static int done;
106: va_list args;
107:
1.1.1.2 ! misho 108: va_start(args, fmt);
! 109: vfprintf(stderr, fmt, args);
! 110: va_end(args);
! 111:
1.1 misho 112: if (!done) {
113: done = 1;
114: do_shutdown();
115: }
116:
117: exit(1);
118: }
119:
1.1.1.2 ! misho 120: static inline void print_version(void)
1.1 misho 121: {
122: printf("bmon %s\n", PACKAGE_VERSION);
1.1.1.2 ! misho 123: printf("Copyright (C) 2001-2013 by Thomas Graf <tgraf@suug.ch>\n");
! 124: printf("Copyright (C) 2013 Red Hat, Inc.\n");
! 125: printf("bmon comes with ABSOLUTELY NO WARRANTY. This is free " \
! 126: "software, and you\nare welcome to redistribute it under " \
! 127: "certain conditions. See the source\ncode for details.\n");
1.1 misho 128: }
129:
1.1.1.2 ! misho 130: static void parse_args_pre(int argc, char *argv[])
1.1 misho 131: {
1.1.1.2 ! misho 132: DBG("Parsing arguments pre state");
! 133:
1.1 misho 134: for (;;)
135: {
1.1.1.2 ! misho 136: char *gostr = "+:hvVf:";
1.1 misho 137:
1.1.1.2 ! misho 138: struct option long_opts[] = {
! 139: {"help", 0, 0, 'h'},
! 140: {"version", 0, 0, 'v'},
! 141: {"configfile", 1, 0, 'f'},
! 142: {0, 0, 0, 0},
! 143: };
! 144: int c = getopt_long(argc, argv, gostr, long_opts, NULL);
1.1 misho 145: if (c == -1)
146: break;
147:
148: switch (c)
149: {
1.1.1.2 ! misho 150: case 'f':
! 151: set_configfile(optarg);
1.1 misho 152: break;
153:
1.1.1.2 ! misho 154: case 'h':
! 155: print_version();
! 156: printf("\n%s", usage_text);
! 157: exit(1);
! 158: case 'V':
! 159: case 'v':
! 160: print_version();
! 161: exit(0);
! 162: }
! 163: }
! 164: }
1.1 misho 165:
1.1.1.2 ! misho 166: static int parse_args_post(int argc, char *argv[])
! 167: {
! 168: DBG("Parsing arguments post state");
1.1 misho 169:
1.1.1.2 ! misho 170: optind = 1;
! 171:
! 172: for (;;)
! 173: {
! 174: char *gostr = "i:o:p:r:R:s:aUb" \
! 175: "L:hvVf:";
! 176:
! 177: struct option long_opts[] = {
! 178: {"input", 1, 0, 'i'},
! 179: {"output", 1, 0, 'o'},
! 180: {"policy", 1, 0, 'p'},
! 181: {"read-interval", 1, 0, 'r'},
! 182: {"rate-interval", 1, 0, 'R'},
! 183: {"sleep-interval", 1, 0, 's'},
! 184: {"show-all", 0, 0, 'a'},
! 185: {"use-si", 0, 0, 'U'},
! 186: {"use-bit", 0, 0, 'b'},
! 187: {"lifetime", 1, 0, 'L'},
! 188: {0, 0, 0, 0},
! 189: };
! 190: int c = getopt_long(argc, argv, gostr, long_opts, NULL);
! 191: if (c == -1)
! 192: break;
! 193:
! 194: switch (c)
! 195: {
! 196: case 'i':
! 197: if (input_set(optarg))
! 198: return 1;
1.1 misho 199: break;
200:
1.1.1.2 ! misho 201: case 'o':
! 202: if (output_set(optarg))
! 203: return 1;
1.1 misho 204: break;
205:
1.1.1.2 ! misho 206: case 'p':
! 207: cfg_setstr(cfg, "policy", optarg);
1.1 misho 208: break;
209:
210: case 'r':
1.1.1.2 ! misho 211: cfg_setfloat(cfg, "read_interval", strtod(optarg, NULL));
1.1 misho 212: break;
213:
214: case 'R':
1.1.1.2 ! misho 215: cfg_setfloat(cfg, "rate_interval", strtod(optarg, NULL));
1.1 misho 216: break;
217:
218: case 's':
1.1.1.2 ! misho 219: cfg_setint(cfg, "sleep_time", strtoul(optarg, NULL, 0));
1.1 misho 220: break;
221:
222: case 'a':
1.1.1.2 ! misho 223: cfg_setint(cfg, "show_all", 1);
1.1 misho 224: break;
225:
1.1.1.2 ! misho 226: case 'U':
! 227: cfg_setbool(cfg, "use_si", cfg_true);
1.1 misho 228: break;
229:
1.1.1.2 ! misho 230: case 'b':
! 231: cfg_setbool(cfg, "use_bit", cfg_true);
1.1 misho 232: break;
233:
1.1.1.2 ! misho 234: case 'L':
! 235: cfg_setint(cfg, "lifetime", strtoul(optarg, NULL, 0));
1.1 misho 236: break;
237:
1.1.1.2 ! misho 238: case 'f':
! 239: /* Already handled in pre getopt loop */
1.1 misho 240: break;
241:
242: default:
243: quit("Aborting...\n");
1.1.1.2 ! misho 244: break;
! 245:
1.1 misho 246: }
247: }
1.1.1.2 ! misho 248:
! 249: return 0;
1.1 misho 250: }
251:
1.1.1.2 ! misho 252: #if 0
1.1 misho 253: static void calc_variance(timestamp_t *c, timestamp_t *ri)
254: {
255: float v = (ts_to_float(c) / ts_to_float(ri)) * 100.0f;
256:
257: rtiming.rt_variance.v_error = v;
258: rtiming.rt_variance.v_total += v;
259:
260: if (v > rtiming.rt_variance.v_max)
261: rtiming.rt_variance.v_max = v;
262:
263: if (v < rtiming.rt_variance.v_min)
264: rtiming.rt_variance.v_min = v;
265: }
1.1.1.2 ! misho 266: #endif
1.1 misho 267:
268: int main(int argc, char *argv[])
269: {
1.1.1.2 ! misho 270: unsigned long sleep_time;
! 271: double read_interval;
! 272:
1.1 misho 273: start_time = time(0);
1.1.1.2 ! misho 274: memset(&rtiming, 0, sizeof(rtiming));
! 275: rtiming.rt_variance.v_min = FLT_MAX;
1.1 misho 276:
1.1.1.2 ! misho 277: /*
! 278: * Early initialization before reading config
! 279: */
! 280: conf_init_pre();
! 281: parse_args_pre(argc, argv);
1.1 misho 282:
1.1.1.2 ! misho 283: /*
! 284: * Reading the configuration file */
! 285: configfile_read();
1.1 misho 286:
1.1.1.2 ! misho 287: /*
! 288: * Late initialization after reading config
! 289: */
! 290: if (parse_args_post(argc, argv))
! 291: return 1;
! 292: conf_init_post();
1.1 misho 293:
1.1.1.2 ! misho 294: module_init();
1.1 misho 295:
1.1.1.2 ! misho 296: read_interval = cfg_read_interval;
! 297: sleep_time = cfg_getint(cfg, "sleep_time");
1.1 misho 298:
1.1.1.2 ! misho 299: if (((double) sleep_time / 1000000.0f) > read_interval)
! 300: sleep_time = (unsigned long) (read_interval * 1000000.0f);
! 301:
! 302: DBG("Entering mainloop...");
! 303:
! 304: do {
1.1 misho 305: /*
306: * E := Elapsed time
307: * NR := Next Read
308: * LR := Last Read
309: * RI := Read Interval
310: * ST := Sleep Time
311: * C := Correction
312: */
313: timestamp_t e, ri, tmp;
314: unsigned long st;
315:
1.1.1.2 ! misho 316: float_to_timestamp(&ri, read_interval);
1.1 misho 317:
318: /*
1.1.1.2 ! misho 319: * NR := NOW
1.1 misho 320: */
1.1.1.2 ! misho 321: update_timestamp(&rtiming.rt_next_read);
1.1 misho 322:
323: for (;;) {
324: output_pre();
325:
326: /*
1.1.1.2 ! misho 327: * E := NOW
1.1 misho 328: */
1.1.1.2 ! misho 329: update_timestamp(&e);
1.1 misho 330:
331: /*
332: * IF NR <= E THEN
333: */
1.1.1.2 ! misho 334: if (timestamp_le(&rtiming.rt_next_read, &e)) {
1.1 misho 335: timestamp_t c;
336:
337: /*
338: * C := (NR - E)
339: */
1.1.1.2 ! misho 340: timestamp_sub(&c, &rtiming.rt_next_read, &e);
1.1 misho 341:
1.1.1.2 ! misho 342: //calc_variance(&c, &ri);
1.1 misho 343:
344: /*
345: * LR := E
346: */
1.1.1.2 ! misho 347: copy_timestamp(&rtiming.rt_last_read, &e);
1.1 misho 348:
349: /*
350: * NR := E + RI + C
351: */
1.1.1.2 ! misho 352: timestamp_add(&rtiming.rt_next_read, &e, &ri);
! 353: timestamp_add(&rtiming.rt_next_read,
! 354: &rtiming.rt_next_read, &c);
! 355:
1.1 misho 356:
1.1.1.2 ! misho 357: reset_update_flags();
1.1 misho 358: input_read();
1.1.1.2 ! misho 359: free_unused_elements();
1.1 misho 360: output_draw();
361: output_post();
362: }
363:
364: if (do_quit)
365: exit(0);
366:
367: /*
368: * ST := Configured ST
369: */
1.1.1.2 ! misho 370: st = sleep_time;
1.1 misho 371:
372: /*
373: * IF (NR - E) < ST THEN
374: */
1.1.1.2 ! misho 375: timestamp_sub(&tmp, &rtiming.rt_next_read, &e);
1.1 misho 376:
377: if (tmp.tv_sec < 0)
378: continue;
379:
380: if (tmp.tv_sec == 0 && tmp.tv_usec < st) {
381: if (tmp.tv_usec < 0)
382: continue;
383: /*
384: * ST := (NR - E)
385: */
386: st = tmp.tv_usec;
387: }
388:
389: /*
390: * SLEEP(ST)
391: */
392: usleep(st);
393: }
1.1.1.2 ! misho 394: } while (0);
! 395:
1.1 misho 396: return 0; /* buddha says i'll never be reached */
397: }
398:
399: static void __init bmon_init(void)
400: {
401: atexit(&sig_exit);
1.1.1.2 ! misho 402: //signal(SIGINT, &sig_int);
1.1 misho 403: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>