summaryrefslogtreecommitdiffstats
path: root/src/bmon.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bmon.c')
-rw-r--r--src/bmon.c397
1 files changed, 397 insertions, 0 deletions
diff --git a/src/bmon.c b/src/bmon.c
new file mode 100644
index 0000000..22492d0
--- /dev/null
+++ b/src/bmon.c
@@ -0,0 +1,397 @@
+/*
+ * src/bmon.c Bandwidth Monitor
+ *
+ * Copyright (c) 2001-2013 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2013 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <bmon/bmon.h>
+#include <bmon/conf.h>
+#include <bmon/attr.h>
+#include <bmon/utils.h>
+#include <bmon/input.h>
+#include <bmon/output.h>
+#include <bmon/module.h>
+#include <bmon/group.h>
+
+int start_time;
+int do_quit = 0;
+int is_daemon = 0;
+
+struct reader_timing rtiming;
+
+static char *usage_text =
+"Usage: bmon [OPTION]...\n" \
+"\n" \
+"Options:\n" \
+"Startup:\n" \
+" -i, --input=MODPARM Input module(s)\n" \
+" -o, --output=MODPARM Ouptut module(s)\n" \
+" -f, --configfile=PATH Alternative path to configuration file\n" \
+" -h, --help Show this help text\n" \
+" -V, --version Show version\n" \
+"\n" \
+"Input:\n" \
+" -p, --policy=POLICY Element display policy (see below)\n" \
+" -a, --show-all Show all elements (even disabled elements)\n" \
+" -r, --read-interval=FLOAT Read interval in seconds (float)\n" \
+" -R, --rate-internval=FLOAT Rate interval in seconds (float)\n" \
+" -s, --sleep-interval=FLOAT Sleep time in seconds (float)\n" \
+" -L, --lifetime=LIFETIME Lifetime of an element in seconds (float)\n" \
+"\n" \
+"Output:\n" \
+" -U, --use-si Use SI units\n" \
+"\n" \
+"Module configuration:\n" \
+" modparm := MODULE:optlist,MODULE:optlist,...\n" \
+" optlist := option;option;...\n" \
+" option := TYPE[=VALUE]\n" \
+"\n" \
+" Examples:\n" \
+" -o curses:ngraph=2\n" \
+" -o list # Shows a list of available modules\n" \
+" -o curses:help # Shows a help text for html module\n" \
+"\n" \
+"Interface selection:\n" \
+" policy := [!]simple_regexp,[!]simple_regexp,...\n" \
+"\n" \
+" Example: -p 'eth*,lo*,!eth1'\n" \
+"\n" \
+"Please see the bmon(1) man pages for full documentation.\n";
+
+static void do_shutdown(void)
+{
+ static int done;
+
+ if (!done) {
+ done = 1;
+ module_shutdown();
+ }
+}
+
+RETSIGTYPE sig_int(int unused)
+{
+ if (do_quit)
+ exit(-1);
+ do_quit = 1;
+}
+
+void sig_exit(void)
+{
+ do_shutdown();
+}
+
+void quit(const char *fmt, ...)
+{
+ static int done;
+ va_list args;
+
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+
+ if (!done) {
+ done = 1;
+ do_shutdown();
+ }
+
+ exit(1);
+}
+
+static inline void print_version(void)
+{
+ printf("bmon %s\n", PACKAGE_VERSION);
+ printf("Copyright (C) 2001-2013 by Thomas Graf <tgraf@suug.ch>\n");
+ printf("Copyright (C) 2013 Red Hat, Inc.\n");
+ printf("bmon comes with ABSOLUTELY NO WARRANTY. This is free " \
+ "software, and you\nare welcome to redistribute it under " \
+ "certain conditions. See the source\ncode for details.\n");
+}
+
+static void parse_args_pre(int argc, char *argv[])
+{
+ DBG("Parsing arguments pre state");
+
+ for (;;)
+ {
+ char *gostr = "+:hvVf:";
+
+ struct option long_opts[] = {
+ {"help", 0, 0, 'h'},
+ {"version", 0, 0, 'v'},
+ {"configfile", 1, 0, 'f'},
+ {0, 0, 0, 0},
+ };
+ int c = getopt_long(argc, argv, gostr, long_opts, NULL);
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case 'f':
+ set_configfile(optarg);
+ break;
+
+ case 'h':
+ print_version();
+ printf("\n%s", usage_text);
+ exit(1);
+ case 'V':
+ case 'v':
+ print_version();
+ exit(0);
+ }
+ }
+}
+
+static int parse_args_post(int argc, char *argv[])
+{
+ DBG("Parsing arguments post state");
+
+ optind = 1;
+
+ for (;;)
+ {
+ char *gostr = "i:o:p:r:R:s:aU" \
+ "L:hvVf:";
+
+ struct option long_opts[] = {
+ {"input", 1, 0, 'i'},
+ {"output", 1, 0, 'o'},
+ {"policy", 1, 0, 'p'},
+ {"read-interval", 1, 0, 'r'},
+ {"rate-interval", 1, 0, 'R'},
+ {"sleep-interval", 1, 0, 's'},
+ {"show-all", 0, 0, 'a'},
+ {"use-si", 0, 0, 'U'},
+ {"lifetime", 1, 0, 'L'},
+ {0, 0, 0, 0},
+ };
+ int c = getopt_long(argc, argv, gostr, long_opts, NULL);
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case 'i':
+ if (input_set(optarg))
+ return 1;
+ break;
+
+ case 'o':
+ if (output_set(optarg))
+ return 1;
+ break;
+
+ case 'p':
+ cfg_setstr(cfg, "policy", optarg);
+ break;
+
+ case 'r':
+ cfg_setfloat(cfg, "read_interval", strtod(optarg, NULL));
+ break;
+
+ case 'R':
+ cfg_setfloat(cfg, "rate_interval", strtod(optarg, NULL));
+ break;
+
+ case 's':
+ cfg_setint(cfg, "sleep_time", strtoul(optarg, NULL, 0));
+ break;
+
+ case 'a':
+ cfg_setint(cfg, "show_all", 1);
+ break;
+
+ case 'U':
+ cfg_setbool(cfg, "use_si", cfg_true);
+ break;
+
+ case 'L':
+ cfg_setint(cfg, "lifetime", strtoul(optarg, NULL, 0));
+ break;
+
+ case 'f':
+ /* Already handled in pre getopt loop */
+ break;
+
+ default:
+ quit("Aborting...\n");
+ break;
+
+ }
+ }
+
+ return 0;
+}
+
+#if 0
+static void calc_variance(timestamp_t *c, timestamp_t *ri)
+{
+ float v = (ts_to_float(c) / ts_to_float(ri)) * 100.0f;
+
+ rtiming.rt_variance.v_error = v;
+ rtiming.rt_variance.v_total += v;
+
+ if (v > rtiming.rt_variance.v_max)
+ rtiming.rt_variance.v_max = v;
+
+ if (v < rtiming.rt_variance.v_min)
+ rtiming.rt_variance.v_min = v;
+}
+#endif
+
+int main(int argc, char *argv[])
+{
+ unsigned long sleep_time;
+ double read_interval;
+
+ start_time = time(0);
+ memset(&rtiming, 0, sizeof(rtiming));
+ rtiming.rt_variance.v_min = FLT_MAX;
+
+ /*
+ * Early initialization before reading config
+ */
+ conf_init_pre();
+ parse_args_pre(argc, argv);
+
+ /*
+ * Reading the configuration file */
+ configfile_read();
+
+ /*
+ * Late initialization after reading config
+ */
+ if (parse_args_post(argc, argv))
+ return 1;
+ conf_init_post();
+
+ module_init();
+
+ read_interval = cfg_read_interval;
+ sleep_time = cfg_getint(cfg, "sleep_time");
+
+ if (((double) sleep_time / 1000000.0f) > read_interval)
+ sleep_time = (unsigned long) (read_interval * 1000000.0f);
+
+ DBG("Entering mainloop...");
+
+ do {
+ /*
+ * E := Elapsed time
+ * NR := Next Read
+ * LR := Last Read
+ * RI := Read Interval
+ * ST := Sleep Time
+ * C := Correction
+ */
+ timestamp_t e, ri, tmp;
+ unsigned long st;
+
+ float_to_timestamp(&ri, read_interval);
+
+ /*
+ * NR := NOW
+ */
+ update_timestamp(&rtiming.rt_next_read);
+
+ for (;;) {
+ output_pre();
+
+ /*
+ * E := NOW
+ */
+ update_timestamp(&e);
+
+ /*
+ * IF NR <= E THEN
+ */
+ if (timestamp_le(&rtiming.rt_next_read, &e)) {
+ timestamp_t c;
+
+ /*
+ * C := (NR - E)
+ */
+ timestamp_sub(&c, &rtiming.rt_next_read, &e);
+
+ //calc_variance(&c, &ri);
+
+ /*
+ * LR := E
+ */
+ copy_timestamp(&rtiming.rt_last_read, &e);
+
+ /*
+ * NR := E + RI + C
+ */
+ timestamp_add(&rtiming.rt_next_read, &e, &ri);
+ timestamp_add(&rtiming.rt_next_read,
+ &rtiming.rt_next_read, &c);
+
+
+ reset_update_flags();
+ input_read();
+ free_unused_elements();
+ output_draw();
+ output_post();
+ }
+
+ if (do_quit)
+ exit(0);
+
+ /*
+ * ST := Configured ST
+ */
+ st = sleep_time;
+
+ /*
+ * IF (NR - E) < ST THEN
+ */
+ timestamp_sub(&tmp, &rtiming.rt_next_read, &e);
+
+ if (tmp.tv_sec < 0)
+ continue;
+
+ if (tmp.tv_sec == 0 && tmp.tv_usec < st) {
+ if (tmp.tv_usec < 0)
+ continue;
+ /*
+ * ST := (NR - E)
+ */
+ st = tmp.tv_usec;
+ }
+
+ /*
+ * SLEEP(ST)
+ */
+ usleep(st);
+ }
+ } while (0);
+
+ return 0; /* buddha says i'll never be reached */
+}
+
+static void __init bmon_init(void)
+{
+ atexit(&sig_exit);
+ //signal(SIGINT, &sig_int);
+}