Initial import
This commit is contained in:
397
src/bmon.c
Normal file
397
src/bmon.c
Normal file
@ -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);
|
||||
}
|
Reference in New Issue
Block a user