|
version 1.1.1.1, 2012/02/21 22:19:56
|
version 1.1.1.2, 2014/07/30 07:55:27
|
|
Line 1
|
Line 1
|
| /* |
/* |
| * src/bmon.c Bandwidth Monitor |
* src/bmon.c Bandwidth Monitor |
| * |
* |
| * Copyright (c) 2001-2005 Thomas Graf <tgraf@suug.ch> | * 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 |
* Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
* copy of this software and associated documentation files (the "Software"), |
|
Line 24
|
Line 25
|
| |
|
| #include <bmon/bmon.h> |
#include <bmon/bmon.h> |
| #include <bmon/conf.h> |
#include <bmon/conf.h> |
| #include <bmon/item.h> | #include <bmon/attr.h> |
| #include <bmon/itemtab.h> | #include <bmon/utils.h> |
| #include <bmon/input.h> |
#include <bmon/input.h> |
| #include <bmon/output.h> |
#include <bmon/output.h> |
| #include <bmon/signal.h> | #include <bmon/module.h> |
| #include <bmon/utils.h> | #include <bmon/group.h> |
| |
|
| int start_time; |
int start_time; |
| int do_quit = 0; |
int do_quit = 0; |
| |
int is_daemon = 0; |
| |
|
| struct reader_timing rtiming; |
struct reader_timing rtiming; |
| |
|
| static char *usage_text = |
static char *usage_text = |
| "Usage: bmon [OPTION]...\n" \ |
"Usage: bmon [OPTION]...\n" \ |
| "\n" \ |
"\n" \ |
| "Options:\n" \ |
"Options:\n" \ |
| " -i <modparm> Primary input module\n" \ | "Startup:\n" \ |
| " -o <modparm> Primary ouptut module\n" \ | " -i, --input=MODPARM Input module(s)\n" \ |
| " -I <modparm> Secondary input modules\n" \ | " -o, --output=MODPARM Output module(s)\n" \ |
| " -O <modparm> Secondary output modules\n" \ | " -f, --configfile=PATH Alternative path to configuration file\n" \ |
| " -f <path> Alternative path to configuration file\n" \ | " -h, --help Show this help text\n" \ |
| " -p <policy> Interface acceptance policy\n" \ | " -V, --version Show version\n" \ |
| " -a Accept interfaces even if they are down\n" \ | |
| " -A <attrs> Attributes history configuration\n" \ | |
| " -r <float> Read interval in seconds\n" \ | |
| " -R <float> Rate interval in seconds\n" \ | |
| " -H <hbeat> Heartbeat factor (0..1)\n" \ | |
| " -L <lifetime> Lifetime of a item in seconds\n" \ | |
| " -c Use SI units\n" \ | |
| " -t <path> Alternative path to itemtab file\n" \ | |
| " -N <num> Number of graphs to draw\n" \ | |
| " -s <float> Sleep time in seconds\n" \ | |
| " -w Signal driven output intervals\n" \ | |
| " -S <pid> Send SIGUSR1 to a running bmon instance\n" \ | |
| " -u <uid> Drop privileges and change UID\n" \ | |
| " -g <gid> Drop privileges and change GID\n" \ | |
| " -h show this help text\n" \ | |
| " -V show version\n" \ | |
| "\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-interval=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" \ |
| |
" -b, --use-bit Display in bits instead of bytes\n" \ |
| |
"\n" \ |
| "Module configuration:\n" \ |
"Module configuration:\n" \ |
| " modparm := MODULE:optlist,MODULE:optlist,...\n" \ |
" modparm := MODULE:optlist,MODULE:optlist,...\n" \ |
| " optlist := option;option;...\n" \ |
" optlist := option;option;...\n" \ |
| " option := TYPE[=VALUE]\n" \ |
" option := TYPE[=VALUE]\n" \ |
| "\n" \ |
"\n" \ |
| " Examples:\n" \ |
" Examples:\n" \ |
| " -O html:path=/var/www/html,distribution:port=2444;debug\n" \ | " -o curses:ngraph=2\n" \ |
| " -O list # Shows a list of available modules\n" \ | " -o list # Shows a list of available modules\n" \ |
| " -O html:help # Shows a help text for html module\n" \ | " -o curses:help # Shows a help text for html module\n" \ |
| "\n" \ |
"\n" \ |
| "Interface selection:\n" \ |
"Interface selection:\n" \ |
| " policy := [!]simple_regexp,[!]simple_regexp,...\n" \ |
" policy := [!]simple_regexp,[!]simple_regexp,...\n" \ |
| "\n" \ |
"\n" \ |
| " Example: -p 'eth*,lo*,!eth1'\n" \ |
" Example: -p 'eth*,lo*,!eth1'\n" \ |
| "\n" \ |
"\n" \ |
| "Attributes selection:\n" \ |
|
| " attrs := [!]name,[!]name,...\n" \ |
|
| "\n" \ |
|
| " Example: -A !hbeat_err\n" \ |
|
| "\n" \ |
|
| "Please see the bmon(1) man pages for full documentation.\n"; |
"Please see the bmon(1) man pages for full documentation.\n"; |
| |
|
| static char *uid, *gid; |
|
| |
|
| static void do_shutdown(void) |
static void do_shutdown(void) |
| { |
{ |
| static int done; |
static int done; |
| |
|
| if (!done) { |
if (!done) { |
| done = 1; |
done = 1; |
| input_shutdown(); | module_shutdown(); |
| output_shutdown(); | |
| } |
} |
| } |
} |
| |
|
|
Line 114 void quit(const char *fmt, ...)
|
Line 105 void quit(const char *fmt, ...)
|
| static int done; |
static int done; |
| va_list args; |
va_list args; |
| |
|
| |
va_start(args, fmt); |
| |
vfprintf(stderr, fmt, args); |
| |
va_end(args); |
| |
|
| if (!done) { |
if (!done) { |
| done = 1; |
done = 1; |
| do_shutdown(); |
do_shutdown(); |
| } |
} |
| |
|
| va_start(args, fmt); |
|
| vfprintf(stderr, fmt, args); |
|
| va_end(args); |
|
| |
|
| exit(1); |
exit(1); |
| } |
} |
| |
|
| static void print_version(void) | static inline void print_version(void) |
| { |
{ |
| printf("bmon %s\n", PACKAGE_VERSION); |
printf("bmon %s\n", PACKAGE_VERSION); |
| printf("Copyright (C) 2001-2005 by Thomas Graf <tgraf@suug.ch>\n"); | printf("Copyright (C) 2001-2013 by Thomas Graf <tgraf@suug.ch>\n"); |
| printf("bmon comes with ABSOLUTELY NO WARRANTY. This is free software, " \ | printf("Copyright (C) 2013 Red Hat, Inc.\n"); |
| "and you\nare welcome to redistribute it under certain conditions. " \ | printf("bmon comes with ABSOLUTELY NO WARRANTY. This is free " \ |
| "See the source\ncode for details.\n"); | "software, and you\nare welcome to redistribute it under " \ |
| | "certain conditions. See the source\ncode for details.\n"); |
| } |
} |
| |
|
| static void parse_args(int argc, char *argv[]) | static void parse_args_pre(int argc, char *argv[]) |
| { |
{ |
| |
DBG("Parsing arguments pre state"); |
| |
|
| for (;;) |
for (;;) |
| { |
{ |
| int c = getopt(argc, argv, "hVf:i:I:o:O:p:r:s:S:waA:cN" \ | char *gostr = "+:hvVf:"; |
| ":u:g:H:R:L:t:"); | |
| |
|
| |
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) |
if (c == -1) |
| break; |
break; |
| |
|
| switch (c) |
switch (c) |
| { |
{ |
| case 'i': | case 'f': |
| set_input(optarg); | set_configfile(optarg); |
| break; |
break; |
| |
|
| case 'I': | case 'h': |
| set_sec_input(optarg); | 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:aUb" \ |
| | "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'}, |
| | {"use-bit", 0, 0, 'b'}, |
| | {"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; |
break; |
| |
|
| case 'o': |
case 'o': |
| set_output(optarg); | if (output_set(optarg)) |
| | return 1; |
| break; |
break; |
| |
|
| case 'O': |
|
| set_sec_output(optarg); |
|
| break; |
|
| |
|
| case 'f': |
|
| set_configfile(optarg); |
|
| break; |
|
| |
|
| case 'p': |
case 'p': |
| item_parse_policy(optarg); | cfg_setstr(cfg, "policy", optarg); |
| break; |
break; |
| |
|
| case 'A': |
|
| parse_attr_policy(optarg); |
|
| break; |
|
| |
|
| case 'r': |
case 'r': |
| set_read_interval(optarg); | cfg_setfloat(cfg, "read_interval", strtod(optarg, NULL)); |
| break; |
break; |
| |
|
| case 'R': |
case 'R': |
| set_rate_interval(optarg); | cfg_setfloat(cfg, "rate_interval", strtod(optarg, NULL)); |
| break; |
break; |
| |
|
| case 'L': |
|
| set_lifetime(optarg); |
|
| break; |
|
| |
|
| case 's': |
case 's': |
| set_sleep_time(optarg); | cfg_setint(cfg, "sleep_time", strtoul(optarg, NULL, 0)); |
| break; |
break; |
| |
|
| case 'S': |
|
| send_signal(optarg); |
|
| exit(0); |
|
| |
|
| case 'w': |
|
| set_signal_output(1); |
|
| break; |
|
| |
|
| case 'a': |
case 'a': |
| set_show_only_running(0); | cfg_setint(cfg, "show_all", 1); |
| break; |
break; |
| |
|
| case 'h': | case 'U': |
| print_version(); | cfg_setbool(cfg, "use_si", cfg_true); |
| printf("\n%s", usage_text); | |
| exit(1); | |
| |
| case 'N': | |
| set_ngraphs(strtol(optarg, NULL, 0)); | |
| break; |
break; |
| |
|
| case 'c': | case 'b': |
| set_use_si(); | cfg_setbool(cfg, "use_bit", cfg_true); |
| break; |
break; |
| |
|
| case 'u': |
|
| uid = strdup(optarg); |
|
| break; |
|
| |
|
| case 'g': | case 'L': |
| gid = strdup(optarg); | cfg_setint(cfg, "lifetime", strtoul(optarg, NULL, 0)); |
| break; |
break; |
| |
|
| case 'H': | case 'f': |
| set_hb_factor(optarg); | /* Already handled in pre getopt loop */ |
| break; |
break; |
| |
|
| case 't': |
|
| set_itemtab(optarg); |
|
| break; |
|
| |
|
| case 'V': |
|
| case 'v': |
|
| print_version(); |
|
| exit(0); |
|
| |
|
| default: |
default: |
| quit("Aborting...\n"); |
quit("Aborting...\n"); |
| |
break; |
| |
|
| } |
} |
| } |
} |
| |
|
| |
return 0; |
| } |
} |
| |
|
| |
#if 0 |
| static void calc_variance(timestamp_t *c, timestamp_t *ri) |
static void calc_variance(timestamp_t *c, timestamp_t *ri) |
| { |
{ |
| float v = (ts_to_float(c) / ts_to_float(ri)) * 100.0f; |
float v = (ts_to_float(c) / ts_to_float(ri)) * 100.0f; |
|
Line 256 static void calc_variance(timestamp_t *c, timestamp_t
|
Line 263 static void calc_variance(timestamp_t *c, timestamp_t
|
| if (v < rtiming.rt_variance.v_min) |
if (v < rtiming.rt_variance.v_min) |
| rtiming.rt_variance.v_min = v; |
rtiming.rt_variance.v_min = v; |
| } |
} |
| |
#endif |
| |
|
| static void drop_privs(void) |
|
| { |
|
| struct passwd *uentry = NULL; |
|
| struct group *gentry = NULL; |
|
| |
|
| if (gid) |
|
| gentry = getgrnam(gid); |
|
| |
|
| if (uid) |
|
| uentry = getpwnam(uid); |
|
| |
|
| if (gentry) |
|
| if (setgid(gentry->gr_gid) < 0) |
|
| quit("Unable to set group id %d: %s\n", |
|
| gentry->gr_gid, strerror(errno)); |
|
| |
|
| if (uentry) |
|
| if (setuid(uentry->pw_uid) < 0) |
|
| quit("Unable to set user id %d: %s\n", |
|
| uentry->pw_uid, strerror(errno)); |
|
| } |
|
| |
|
| int main(int argc, char *argv[]) |
int main(int argc, char *argv[]) |
| { |
{ |
| unsigned long c_sleep_time; | unsigned long sleep_time; |
| float read_interval; | double read_interval; |
| |
| start_time = time(0); |
start_time = time(0); |
| |
memset(&rtiming, 0, sizeof(rtiming)); |
| |
rtiming.rt_variance.v_min = FLT_MAX; |
| |
|
| parse_args(argc, argv); | /* |
| read_configfile(); | * Early initialization before reading config |
| read_itemtab(); | */ |
| | conf_init_pre(); |
| | parse_args_pre(argc, argv); |
| |
|
| c_sleep_time = get_sleep_time(); | /* |
| read_interval = get_read_interval(); | * Reading the configuration file */ |
| | configfile_read(); |
| |
|
| if (((double) c_sleep_time/1000000.0f) > read_interval) | /* |
| c_sleep_time = (unsigned long) (read_interval * 1000000.0f); | * Late initialization after reading config |
| | */ |
| | if (parse_args_post(argc, argv)) |
| | return 1; |
| | conf_init_post(); |
| |
|
| input_init(); | module_init(); |
| output_init(); | |
| |
|
| drop_privs(); | 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 |
* E := Elapsed time |
| * NR := Next Read |
* NR := Next Read |
|
Line 313 int main(int argc, char *argv[])
|
Line 313 int main(int argc, char *argv[])
|
| timestamp_t e, ri, tmp; |
timestamp_t e, ri, tmp; |
| unsigned long st; |
unsigned long st; |
| |
|
| get_read_interval_as_ts(&ri); | float_to_timestamp(&ri, read_interval); |
| |
|
| /* |
/* |
| * E := NOW() | * NR := NOW |
| */ |
*/ |
| update_ts(&e); | update_timestamp(&rtiming.rt_next_read); |
| |
|
| /* |
|
| * NR := E |
|
| */ |
|
| COPY_TS(&rtiming.rt_next_read, &e); |
|
| |
|
| for (;;) { |
for (;;) { |
| output_pre(); |
output_pre(); |
| |
|
| /* |
/* |
| * E := NOW() | * E := NOW |
| */ |
*/ |
| update_ts(&e); | update_timestamp(&e); |
| |
|
| /* |
/* |
| * IF NR <= E THEN |
* IF NR <= E THEN |
| */ |
*/ |
| if (ts_le(&rtiming.rt_next_read, &e)) { | if (timestamp_le(&rtiming.rt_next_read, &e)) { |
| timestamp_t c; |
timestamp_t c; |
| |
|
| /* |
/* |
| * C := (NR - E) |
* C := (NR - E) |
| */ |
*/ |
| ts_sub(&c, &rtiming.rt_next_read, &e); | timestamp_sub(&c, &rtiming.rt_next_read, &e); |
| |
|
| calc_variance(&c, &ri); | //calc_variance(&c, &ri); |
| |
|
| /* |
/* |
| * LR := E |
* LR := E |
| */ |
*/ |
| COPY_TS(&rtiming.rt_last_read, &e); | copy_timestamp(&rtiming.rt_last_read, &e); |
| |
|
| /* |
/* |
| * NR := E + RI + C |
* NR := E + RI + C |
| */ |
*/ |
| ts_add(&rtiming.rt_next_read, &e, &ri); | timestamp_add(&rtiming.rt_next_read, &e, &ri); |
| ts_add(&rtiming.rt_next_read, &rtiming.rt_next_read, &c); | timestamp_add(&rtiming.rt_next_read, |
| | &rtiming.rt_next_read, &c); |
| |
|
| |
|
| |
reset_update_flags(); |
| input_read(); |
input_read(); |
| |
free_unused_elements(); |
| output_draw(); |
output_draw(); |
| |
|
| output_post(); |
output_post(); |
| } |
} |
| |
|
| if (do_quit) |
if (do_quit) |
| exit(0); |
exit(0); |
| |
|
| if (got_resized()) |
|
| output_resize(); |
|
| |
|
| /* |
/* |
| * ST := Configured ST |
* ST := Configured ST |
| */ |
*/ |
| st = c_sleep_time; | st = sleep_time; |
| |
|
| /* |
/* |
| * IF (NR - E) < ST THEN |
* IF (NR - E) < ST THEN |
| */ |
*/ |
| ts_sub(&tmp, &rtiming.rt_next_read, &e); | timestamp_sub(&tmp, &rtiming.rt_next_read, &e); |
| |
|
| if (tmp.tv_sec < 0) |
if (tmp.tv_sec < 0) |
| continue; |
continue; |
|
Line 396 int main(int argc, char *argv[])
|
Line 391 int main(int argc, char *argv[])
|
| */ |
*/ |
| usleep(st); |
usleep(st); |
| } |
} |
| } | } while (0); |
| | |
| return 0; /* buddha says i'll never be reached */ |
return 0; /* buddha says i'll never be reached */ |
| } |
} |
| |
|
| static void __init bmon_init(void) |
static void __init bmon_init(void) |
| { |
{ |
| memset(&rtiming, 0, sizeof(rtiming)); |
|
| rtiming.rt_variance.v_min = 10000000.0f; |
|
| atexit(&sig_exit); |
atexit(&sig_exit); |
| signal(SIGINT, &sig_int); | //signal(SIGINT, &sig_int); |
| } |
} |