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); |
} |
} |