2 Commits

Author SHA1 Message Date
eed0cadf35 tmp 2014-08-25 00:20:33 +02:00
13cf9440c4 build: fail CI builds if a new warning is introduced
Signed-off-by: Thomas Graf <tgraf@suug.ch>
2014-08-25 00:19:54 +02:00
33 changed files with 191 additions and 952 deletions

View File

@ -1,40 +1,10 @@
language: c language: c
os:
- linux
- osx
env:
global:
- secure: "C87Pgf5AVDoyQfm9MIv81g"
compiler: compiler:
- gcc - gcc
- clang - clang
before_install:
# container-based builds - sudo apt-get install libconfuse-dev
sudo: false - sudo apt-get install libnl-3-dev libnl-route-3-dev
addons: - sudo apt-get install libncurses-dev
apt: # Change this to your needs
packages: script: ./.travis/run.sh
# packages list: https://github.com/travis-ci/apt-package-whitelist/blob/master/ubuntu-precise
- libconfuse-dev
- libncurses5-dev
- libnl-3-dev
- libnl-route-3-dev
coverity_scan:
project:
name: "tgraf/bmon"
description: "bandwidth monitor"
notification_email: tgraf@suug.ch
build_command_prepend: "./autogen.sh && ./configure"
build_command: "make -j2"
branch_pattern: coverity_scan
install:
- if [ "$TRAVIS_BRANCH" = "coverity_scan" ] && ! [ "$TRAVIS_OS_NAME" = "linux" -a "$CC" = "gcc" ]; then exit ; fi
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update > /dev/null && brew install confuse ; fi
script:
- ./.travis/run.sh

View File

@ -6,4 +6,4 @@ if [ $CC = "clang" ]; then
FLAGS="$FLAGS -Wno-error=unused-command-line-argument" FLAGS="$FLAGS -Wno-error=unused-command-line-argument"
fi fi
./autogen.sh && ./configure && make CFLAGS="$FLAGS" && make distcheck ./autogen.sh && ./configure && make CFLAGS="$FLAGS"

View File

@ -4,4 +4,4 @@ ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src man include examples SUBDIRS = src man include examples
EXTRA_DIST = ChangeLog LICENSE.BSD LICENSE.MIT NEWS README.md EXTRA_DIST = ChangeLog LICENSE.BSD LICENSE.MIT NEWS README.adoc

38
NEWS
View File

@ -1,46 +1,12 @@
HEAD
v4.0 - Dec 13, 2016
* Use monotonic clock instead of realtime clock
* Pick default selected interface based on policy
* Collect RX NoHandler statistics if available (Linux)
* CentOS installation instructions
* Proper stdout flush in ASCII mode
* Bugfixes
v3.9 - Jul 19, 2016
* Color support
* Add ability to reset statistics from curses UI
* NetBSD compile fix
* Option to enable info display by default
* Additional IPv6 statistics
* Various fixes
v3.8 - July 25, 2015
* Don't disable Netlink if TC stats are unavailable
v3.7 - November 22, 2014
* Bugfixes
* Documentation updates
* Provide minimal interface information on BSD
v3.6 - November 22, 2014
* Build fix for uclinux
* Fix LICENSE links
v3.5 - August 30, 2014
* Fixes for all defects identified by coverity
* Fix accuracy issue on total rate calculation
* Travis-CI support
* Various other small bugfixes
v3.4 - August 24, 2014 v3.4 - August 24, 2014
----------------------
* Bugfixes * Bugfixes
* blank screen with config file * blank screen with config file
* quick-help toggle with '?' in curses * quick-help toggle with '?' in curses
* Better bmon.conf example * Better bmon.conf example
v3.3 - July 6, 2014 v3.3 - July 6, 2014
-------------------
* MacOS X port * MacOS X port
* Only initialize curses module if actually used * Only initialize curses module if actually used
* Assorted bug and spelling fixes * Assorted bug and spelling fixes

View File

@ -8,74 +8,20 @@ statistics and prepare them visually in a human friendly way. It
features various output methods including an interactive curses user features various output methods including an interactive curses user
interface and a programmable text output for scripting. interface and a programmable text output for scripting.
## Download ## Changes
* [Latest Release](https://github.com/tgraf/bmon/releases/latest) ### New in 3.4
* [Older Releases](https://github.com/tgraf/bmon/releases)
## Debian/Ubuntu Installation
```
git clone https://github.com/tgraf/bmon.git
cd bmon
apt-get install build-essential make libconfuse-dev libnl-3-dev libnl-route-3-dev libncurses-dev pkg-config dh-autoreconf
./autogen.sh
./configure
make
make install
bmon
```
## CentOS (6) Installation
```
git clone https://github.com/tgraf/bmon.git
cd bmon
yum install make libconfuse-devel libnl3-devel libnl-route3-devel ncurses-devel
./autogen.sh
./configure
make
make install
bmon
```
## OSX Installation
### Brew
```
brew install bmon
```
### Compile yourself
Install libconfuse
```
wget https://github.com/martinh/libconfuse/releases/download/v2.8/confuse-2.8.zip
unzip confuse-2.8.zip && cd confuse-2.8
PATH=/usr/local/opt/gettext/bin:$PATH ./configure
make
make install
```
Install bmon
```
git clone https://github.com/tgraf/bmon.git
cd bmon
./autogen.sh
./configure
make
make install
bmon
```
-------------
## New in 4.0
* Use monotonic clock instead of realtime clock
* Pick default selected interface based on policy
* Collect RX NoHandler statistics if available (Linux)
* CentOS installation instructions
* Proper stdout flush in ASCII mode
* Bugfixes * Bugfixes
* blank screen with config file
* quick-help toggle with '?' in curses
* Better bmon.conf example
## New in 3.3
* MacOS X port
* Only initialize curses module if actually used
* Assorted bug and spelling fixes
* Various build fixes
-------------
### Usage ### Usage
To run bmon in the default curses mode: To run bmon in the default curses mode:
@ -89,18 +35,14 @@ provided via:
## Screenshots ## Screenshots
![Screenshot 1](https://github.com/tgraf/bmon/raw/gh-pages/images/shot3.png) ![Screenshot 1](https://github.com/tgraf/bmon/raw/gh-pages/images/shot1.png)
![Screenshot 2](https://github.com/tgraf/bmon/raw/gh-pages/images/shot1.png) ![Screenshot 2](https://github.com/tgraf/bmon/raw/gh-pages/images/shot2.png)
![Screenshot 3](https://github.com/tgraf/bmon/raw/gh-pages/images/shot2.png)
## Copyright ## Copyright
Various authors, see git commit log. > *Copyright (c) 2001-2014 Thomas Graf <tgraf@suug.ch>
> Copyright (c) 2013 Red Hat, Inc.*
> *Copyright (c) 2001-2016 Thomas Graf <tgraf@suug.ch>* Please see the [LICENSE](https://github.com/tgraf/bmon/blob/master/LICENSE)
> *Copyright (c) 2013 Red Hat, Inc.* file for additional details.
Please see the [LICENSE.BSD](https://github.com/tgraf/bmon/blob/master/LICENSE.BSD)
and [LICENSE.MIT](https://github.com/tgraf/bmon/blob/master/LICENSE.MIT) files for
additional details.

View File

@ -1,7 +1,7 @@
# #
# configure.in Configure Script # configure.in Configure Script
# #
# Copyright (c) 2001-2016 Thomas Graf <tgraf@suug.ch> # Copyright (c) 2001-2013 Thomas Graf <tgraf@suug.ch>
# #
# 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"),
@ -21,7 +21,7 @@
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE. # DEALINGS IN THE SOFTWARE.
AC_INIT(bmon, 4.0, [], [], [https://github.com/tgraf/bmon]) AC_INIT(bmon, 3.4, [], [], [http://www.infradead.org/~tgr/bmon/])
AC_CONFIG_HEADERS(include/bmon/defs.h) AC_CONFIG_HEADERS(include/bmon/defs.h)
AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
@ -58,18 +58,10 @@ AC_CHECK_HEADERS(sys/param.h sys/socket.h)
AC_CHECK_TYPES(suseconds_t) AC_CHECK_TYPES(suseconds_t)
AC_CHECK_FUNCS(atexit clock_gettime memset pow socket strcasecmp) AC_CHECK_FUNCS(atexit gettimeofday memset pow socket strcasecmp)
AC_CHECK_FUNCS(strchr strdup strerror strncasecmp strstr strtol) AC_CHECK_FUNCS(strchr strdup strerror strncasecmp strstr strtol)
AC_CHECK_FUNCS(uname getdate) AC_CHECK_FUNCS(uname getdate)
AC_PATH_PROG([PKG_CONFIG], [pkg-config], [no])
AS_IF([test "x$PKG_CONFIG" = "xno"],[
AC_MSG_ERROR([
*** The pkg-config script could not be found. Make sure it is
*** in your path, or set the PKG_CONFIG environment variable
*** to the full path to pkg-config.])
])
AX_WITH_CURSES AX_WITH_CURSES
if test "x$ax_cv_curses" != xyes || test "x$ax_cv_curses_color" != xyes; then if test "x$ax_cv_curses" != xyes || test "x$ax_cv_curses_color" != xyes; then
AC_MSG_ERROR([requires an X/Open-compatible Curses library with color]) AC_MSG_ERROR([requires an X/Open-compatible Curses library with color])
@ -78,7 +70,7 @@ fi
PKG_CHECK_MODULES([CONFUSE], [libconfuse], [], AC_MSG_ERROR([requires libconfuse])) PKG_CHECK_MODULES([CONFUSE], [libconfuse], [], AC_MSG_ERROR([requires libconfuse]))
case ${target_os} in case ${target_os} in
linux*|uclinux*) linux*)
PKG_CHECK_MODULES([LIBNL], [libnl-3.0], [], AC_MSG_ERROR([requires libnl3-dev])) PKG_CHECK_MODULES([LIBNL], [libnl-3.0], [], AC_MSG_ERROR([requires libnl3-dev]))
PKG_CHECK_MODULES([LIBNL_ROUTE], [libnl-route-3.0], [], AC_MSG_ERROR([requires libnl3-route])) PKG_CHECK_MODULES([LIBNL_ROUTE], [libnl-route-3.0], [], AC_MSG_ERROR([requires libnl3-route]))
;; ;;
@ -86,9 +78,6 @@ esac
AC_CHECK_LIB(m, pow, [], AC_MSG_ERROR([requires libm])) AC_CHECK_LIB(m, pow, [], AC_MSG_ERROR([requires libm]))
# Don't fail if not found (for instance, OS X does not have clock_gettime)
AC_CHECK_LIB(rt, clock_gettime, [], [])
BMON_LIB="" BMON_LIB=""
##################################################################### #####################################################################
@ -175,7 +164,7 @@ case ${target_os} in
AC_DEFINE_UNQUOTED(SYS_SUNOS, "1", [operating system]) AC_DEFINE_UNQUOTED(SYS_SUNOS, "1", [operating system])
;; ;;
*bsd*|dragonfly*) *bsd*)
AC_DEFINE_UNQUOTED(SYS_BSD, "1", [operating system]) AC_DEFINE_UNQUOTED(SYS_BSD, "1", [operating system])
;; ;;

View File

@ -11,10 +11,10 @@
/* /*
* element eth0 { * element eth0 {
* description = "My description" * description = { "My description" }
* rxmax = 10000 * rxmax = { 10000 }
* txmax = 10000 * txmax = { 10000 }
* max = 12500000 * max = { 12500000 }
* } * }
*/ */
@ -86,27 +86,3 @@ history day {
interval = 86400. interval = 86400.
size = 60 size = 60
} }
layout colors {
color default {
color_pair = {"white", "black"}
}
color statusbar {
color_pair = {"blue", "white", "reverse"}
}
color header {
color_pair = {"yellow", "black"}
}
color list {
color_pair = {"white", "black"}
}
color selected {
color_pair = {"white", "black", "reverse"}
}
color RX_graph {
color_pair = {"green", "black"}
}
color TX_graph {
color_pair = {"red", "black"}
}
}

View File

@ -16,5 +16,4 @@ noinst_HEADERS = \
bmon/module.h \ bmon/module.h \
bmon/output.h \ bmon/output.h \
bmon/unit.h \ bmon/unit.h \
bmon/layout.h \
bmon/utils.h bmon/utils.h

View File

@ -42,9 +42,6 @@ struct rate
/* Value of r_current at last read */ /* Value of r_current at last read */
uint64_t r_prev; uint64_t r_prev;
/* Reset value to substract to emulate statistics reset */
uint64_t r_reset;
/* Rate per second calculated every `rate_interval' */ /* Rate per second calculated every `rate_interval' */
float r_rate; float r_rate;
@ -52,8 +49,6 @@ struct rate
timestamp_t r_last_calc; timestamp_t r_last_calc;
}; };
extern uint64_t rate_get_total(struct rate *);
enum { enum {
ATTR_TYPE_UNSPEC, ATTR_TYPE_UNSPEC,
ATTR_TYPE_COUNTER, ATTR_TYPE_COUNTER,
@ -139,6 +134,5 @@ extern struct attr * attr_select_prev(void);
extern struct attr * attr_current(void); extern struct attr * attr_current(void);
extern void attr_start_collecting_history(struct attr *); extern void attr_start_collecting_history(struct attr *);
extern void attr_reset_counter(struct attr *a);
#endif #endif

View File

@ -60,11 +60,9 @@ enum {
#if defined __GNUC__ #if defined __GNUC__
#define __init __attribute__ ((constructor)) #define __init __attribute__ ((constructor))
#define __exit __attribute__ ((destructor)) #define __exit __attribute__ ((destructor))
#define __unused__ __attribute__ ((unused))
#else #else
#define __init #define __init
#define __exit #define __exit
#define __unused__
#endif #endif
#ifdef DEBUG #ifdef DEBUG

View File

@ -74,8 +74,6 @@ enum {
LAYOUT_HEADER, LAYOUT_HEADER,
LAYOUT_LIST, LAYOUT_LIST,
LAYOUT_SELECTED, LAYOUT_SELECTED,
LAYOUT_RX_GRAPH,
LAYOUT_TX_GRAPH,
__LAYOUT_MAX __LAYOUT_MAX
}; };

View File

@ -48,7 +48,7 @@
#include <dirent.h> #include <dirent.h>
#ifdef SYS_BSD #ifdef SYS_BSD
# include <float.h> # include <float.h>
#elif !defined(__ANDROID__) #else
# include <values.h> # include <values.h>
#endif #endif

View File

@ -9,9 +9,6 @@
/* Define to 1 if you have the `atexit' function. */ /* Define to 1 if you have the `atexit' function. */
#undef HAVE_ATEXIT #undef HAVE_ATEXIT
/* Define to 1 if you have the `clock_gettime' function. */
#undef HAVE_CLOCK_GETTIME
/* have curses */ /* have curses */
#undef HAVE_CURSES #undef HAVE_CURSES
@ -42,15 +39,15 @@
/* Define to 1 if you have the <getopt.h> header file. */ /* Define to 1 if you have the <getopt.h> header file. */
#undef HAVE_GETOPT_H #undef HAVE_GETOPT_H
/* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY
/* Define to 1 if you have the <inttypes.h> header file. */ /* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H #undef HAVE_INTTYPES_H
/* Define to 1 if you have the `m' library (-lm). */ /* Define to 1 if you have the `m' library (-lm). */
#undef HAVE_LIBM #undef HAVE_LIBM
/* Define to 1 if you have the `rt' library (-lrt). */
#undef HAVE_LIBRT
/* Define to 1 if you have the <memory.h> header file. */ /* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H #undef HAVE_MEMORY_H

View File

@ -1,130 +0,0 @@
#ifndef __BMON_LAYOUT_H_
#define __BMON_LAYOUT_H_
#include <bmon/bmon.h>
#include <bmon/conf.h>
#include <bmon/unit.h>
#include <bmon/utils.h>
static int parse_color(const char* color)
{
int color_code = -1;
if ((strcasestr(color, "red") != NULL))
color_code = COLOR_RED;
else if ((strcasestr(color, "green") != NULL))
color_code = COLOR_GREEN;
else if ((strcasestr(color, "white") != NULL))
color_code = COLOR_WHITE;
else if ((strcasestr(color, "black") != NULL))
color_code = COLOR_BLACK;
else if ((strcasestr(color, "blue") != NULL))
color_code = COLOR_BLUE;
else if ((strcasestr(color, "yellow") != NULL))
color_code = COLOR_YELLOW;
else if ((strcasestr(color, "magenta") != NULL))
color_code = COLOR_MAGENTA;
else if ((strcasestr(color, "cyan") != NULL))
color_code = COLOR_CYAN;
else if ((atoi(color) >= 0))
color_code = atoi(color);
return color_code;
}
/*
A_NORMAL Normal display (no highlight)
A_STANDOUT Best highlighting mode of the terminal.
A_UNDERLINE Underlining
A_REVERSE Reverse video
A_BLINK Blinking
A_DIM Half bright
A_BOLD Extra bright or bold
A_PROTECT Protected mode
A_INVIS Invisible or blank mode
A_ALTCHARSET Alternate character set
A_CHARTEXT Bit-mask to extract a character
*/
static int parse_attribute(const char* attr)
{
/* no attribute is valid, so we have nothing to do */
if (attr == NULL)
return 0;
if ((strcasestr(attr, "normal") != NULL))
return A_NORMAL;
else if ((strcasestr(attr, "standout") != NULL))
return A_STANDOUT;
else if ((strcasestr(attr, "underline") != NULL))
return A_UNDERLINE;
else if ((strcasestr(attr, "reverse") != NULL))
return A_REVERSE;
else if ((strcasestr(attr, "blink") != NULL))
return A_BLINK;
else if ((strcasestr(attr, "dim") != NULL))
return A_DIM;
else if ((strcasestr(attr, "bold") != NULL))
return A_BOLD;
else if ((strcasestr(attr, "protect") != NULL))
return A_PROTECT;
else if ((strcasestr(attr, "invis") != NULL))
return A_INVIS;
else if ((strcasestr(attr, "altcharset") != NULL))
return A_ALTCHARSET;
else if ((strcasestr(attr, "chartext") != NULL))
return A_CHARTEXT;
return -1;
}
static void add_layout(const char *layout_name, cfg_t *color_cfg)
{
const char *fg, *bg, *attr_str = NULL;
int size = -1, fg_code, bg_code, attr_mask, layout_idx = 0;
size = cfg_size(color_cfg, "color_pair");
fg = cfg_getnstr(color_cfg, "color_pair", 0);
bg = cfg_getnstr(color_cfg, "color_pair", 1);
if (size > 2)
attr_str = cfg_getnstr(color_cfg, "color_pair", 2);
fg_code = parse_color(fg);
bg_code = parse_color(bg);
if (fg_code == -1 || bg_code == -1) {
quit("Unknown color [%s]: %s\n", (fg_code == -1) ? "fg" : "bg",
(fg_code == -1) ? fg : bg);
}
attr_mask = parse_attribute(attr_str);
if (attr_mask == -1) {
quit("Unknown attribute: '%s'\n", attr_str);
}
DBG("%s:\tfg: %s bg: %s attr: %s\n", layout_name, fg, bg, attr_str);
if ((strcasecmp(layout_name, "default") == 0))
layout_idx = LAYOUT_DEFAULT;
else if ((strcasecmp(layout_name, "statusbar") == 0))
layout_idx = LAYOUT_STATUSBAR;
else if ((strcasecmp(layout_name, "header") == 0))
layout_idx = LAYOUT_HEADER;
else if ((strcasecmp(layout_name, "list") == 0))
layout_idx = LAYOUT_LIST;
else if ((strcasecmp(layout_name, "selected") == 0))
layout_idx = LAYOUT_SELECTED;
else if ((strcasecmp(layout_name, "rx_graph") == 0))
layout_idx = LAYOUT_RX_GRAPH;
else if ((strcasecmp(layout_name, "tx_graph") == 0))
layout_idx = LAYOUT_TX_GRAPH;
else {
quit("Unknown layout name: '%s'\n", layout_name);
}
struct layout l = { fg_code, bg_code, attr_mask};
cfg_layout[layout_idx] = l;
}
#endif /* __BMON_LAYOUT_H_ */

View File

@ -34,7 +34,7 @@ in parallel. bmon automatically loads a useful and working input module
by default. See INPUT MODULES for more details. by default. See INPUT MODULES for more details.
.RE .RE
.PP .PP
\fB \-o\fR, \fB\-\-output=\fRMODULE[:OPTIONS][,MODULE...] \fB \-o\fR, \fB\-\-ouptut\fRMODULE[:OPTIONS][,MODULE...]
.RS 4 .RS 4
Set list of output modules to load and use. Multiple modules can be used Set list of output modules to load and use. Multiple modules can be used
in parallel. By default, bmon will use the curses output mode, if that is in parallel. By default, bmon will use the curses output mode, if that is
@ -44,7 +44,7 @@ text mode. See OUTPUT MODULES for more details.
.PP .PP
\fB \-U\fR, \fB\-\-use\-si\fR \fB \-U\fR, \fB\-\-use\-si\fR
.RS 4 .RS 4
Use SI unit system (1KB = 1'000 bytes) instead of 1KB = 1'024 bytes. Use SI unit system instead of 1KB = 1'024 bytes.
.RE .RE
.PP .PP
\fB \-f\fR, \fB\-\-configfile=\fRFILE \fB \-f\fR, \fB\-\-configfile=\fRFILE
@ -58,7 +58,7 @@ Set policy defining which network interfaces to display. See
INTERFACE SELECTION for more details. INTERFACE SELECTION for more details.
.RE .RE
.PP .PP
\fB \-a\fR, \fB\-\-show\-all\fR \fB \-a\fR, \fB\-\-show\-all=\fR
.RS 4 .RS 4
Display all interfaces, even interface that are administratively down. Display all interfaces, even interface that are administratively down.
.RE .RE
@ -75,11 +75,6 @@ Set interval in seconds in which the rate per counter is calculated.
The default is 1.0 seconds. The default is 1.0 seconds.
.RE .RE
.PP .PP
\fB \-b\fR, \fB\-\-use\-bit\fR
.RS 4
Show rates in bits per second instead of bytes per second.
.RE
.PP
\fB \-L\fR, \fB\-\-lifetime=\fRFLOAT \fB \-L\fR, \fB\-\-lifetime=\fRFLOAT
.RS 4 .RS 4
Set lifetime of an element in seconds before it is no longer displayed Set lifetime of an element in seconds before it is no longer displayed
@ -137,7 +132,7 @@ The following output modules exist:
.TP .TP
\fBcurses\fR \fBcurses\fR
Interactive curses based text user interface providing real time rate Interactive curses based text user interface providing real time rate
estimations and a graphical representation of each attribute. Press '?' estimations and a graphical representatio nof each attribute. Press '?'
to display the quick reference guide. This is the default output mode. to display the quick reference guide. This is the default output mode.
.TP .TP
@ -220,14 +215,6 @@ and eth1:
.RS 4 .RS 4
\fBbmon \-p eth0,eth1 \-o curses\fP \fBbmon \-p eth0,eth1 \-o curses\fP
.RE .RE
.PP
To run bmon in format mode, monitoring any eth* interfaces, with a specified
format string:
.PP
.RS 4
\fBbmon \-p \(aqeth*\(aq \-o format:fmt=\(aq$(element:name) $(attr:rxrate:packets)\en\(aq\fP
.RE
.PP
.SH "FILES" .SH "FILES"
/etc/bmon.conf /etc/bmon.conf

View File

@ -7,7 +7,6 @@ bmon_CFLAGS = \
-I${top_builddir}/include \ -I${top_builddir}/include \
-DSYSCONFDIR=\"$(sysconfdir)\" \ -DSYSCONFDIR=\"$(sysconfdir)\" \
-D_GNU_SOURCE \ -D_GNU_SOURCE \
-Wall \
$(CURSES_CFLAGS) \ $(CURSES_CFLAGS) \
$(CONFUSE_CFLAGS) \ $(CONFUSE_CFLAGS) \
$(LIBNL_CFLAGS) \ $(LIBNL_CFLAGS) \
@ -41,5 +40,4 @@ bmon_SOURCES = \
out_null.c \ out_null.c \
out_format.c \ out_format.c \
out_ascii.c \ out_ascii.c \
out_curses.c \ out_curses.c
out_trigger.c

View File

@ -111,7 +111,7 @@ int attr_def_add(const char *name, const char *desc, struct unit *unit,
return def->ad_id; return def->ad_id;
} }
static void attr_def_free(struct attr_def *def) void attr_def_free(struct attr_def *def)
{ {
if (!def) if (!def)
return; return;
@ -524,11 +524,6 @@ static float __calc_usage(double rate, uint64_t max)
return 100.0f / ((double) max / (rate * cfg_rate_interval)); return 100.0f / ((double) max / (rate * cfg_rate_interval));
} }
uint64_t rate_get_total(struct rate *r)
{
return r->r_total - r->r_reset;
}
void attr_calc_usage(struct attr *a, float *rx, float *tx, void attr_calc_usage(struct attr *a, float *rx, float *tx,
uint64_t rxmax, uint64_t txmax) uint64_t rxmax, uint64_t txmax)
{ {
@ -631,14 +626,6 @@ void attr_notify_update(struct attr *a, timestamp_t *ts)
} }
} }
void attr_reset_counter(struct attr *a)
{
if (a->a_def->ad_type == ATTR_TYPE_COUNTER) {
a->a_rx_rate.r_reset = a->a_rx_rate.r_total;
a->a_tx_rate.r_reset = a->a_tx_rate.r_total;
}
}
static void __exit attr_exit(void) static void __exit attr_exit(void)
{ {
struct attr_def *ad, *n; struct attr_def *ad, *n;

View File

@ -33,6 +33,8 @@
#include <bmon/group.h> #include <bmon/group.h>
int start_time; int start_time;
int do_quit = 0;
int is_daemon = 0;
struct reader_timing rtiming; struct reader_timing rtiming;
@ -67,14 +69,14 @@ static char *usage_text =
" Examples:\n" \ " Examples:\n" \
" -o curses:ngraph=2\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 curses:help # Shows a help text for curses 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" \
"Please see the bmon(8) man pages for full documentation.\n"; "Please see the bmon(1) man pages for full documentation.\n";
static void do_shutdown(void) static void do_shutdown(void)
{ {
@ -86,7 +88,14 @@ static void do_shutdown(void)
} }
} }
static void sig_exit(void) RETSIGTYPE sig_int(int unused)
{
if (do_quit)
exit(-1);
do_quit = 1;
}
void sig_exit(void)
{ {
do_shutdown(); do_shutdown();
} }
@ -111,7 +120,7 @@ void quit(const char *fmt, ...)
static inline 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-2015 by Thomas Graf <tgraf@suug.ch>\n"); printf("Copyright (C) 2001-2013 by Thomas Graf <tgraf@suug.ch>\n");
printf("Copyright (C) 2013 Red Hat, Inc.\n"); printf("Copyright (C) 2013 Red Hat, Inc.\n");
printf("bmon comes with ABSOLUTELY NO WARRANTY. This is free " \ printf("bmon comes with ABSOLUTELY NO WARRANTY. This is free " \
"software, and you\nare welcome to redistribute it under " \ "software, and you\nare welcome to redistribute it under " \
@ -127,10 +136,10 @@ static void parse_args_pre(int argc, char *argv[])
char *gostr = "+:hvVf:"; char *gostr = "+:hvVf:";
struct option long_opts[] = { struct option long_opts[] = {
{"help", 0, NULL, 'h'}, {"help", 0, 0, 'h'},
{"version", 0, NULL, 'v'}, {"version", 0, 0, 'v'},
{"configfile", 1, NULL, 'f'}, {"configfile", 1, 0, 'f'},
{NULL, 0, NULL, 0}, {0, 0, 0, 0},
}; };
int c = getopt_long(argc, argv, gostr, long_opts, NULL); int c = getopt_long(argc, argv, gostr, long_opts, NULL);
if (c == -1) if (c == -1)
@ -166,17 +175,17 @@ static int parse_args_post(int argc, char *argv[])
"L:hvVf:"; "L:hvVf:";
struct option long_opts[] = { struct option long_opts[] = {
{"input", 1, NULL, 'i'}, {"input", 1, 0, 'i'},
{"output", 1, NULL, 'o'}, {"output", 1, 0, 'o'},
{"policy", 1, NULL, 'p'}, {"policy", 1, 0, 'p'},
{"read-interval", 1, NULL, 'r'}, {"read-interval", 1, 0, 'r'},
{"rate-interval", 1, NULL, 'R'}, {"rate-interval", 1, 0, 'R'},
{"sleep-interval", 1, NULL, 's'}, {"sleep-interval", 1, 0, 's'},
{"show-all", 0, NULL, 'a'}, {"show-all", 0, 0, 'a'},
{"use-si", 0, NULL, 'U'}, {"use-si", 0, 0, 'U'},
{"use-bit", 0, NULL, 'b'}, {"use-bit", 0, 0, 'b'},
{"lifetime", 1, NULL, 'L'}, {"lifetime", 1, 0, 'L'},
{NULL, 0, NULL, 0}, {0, 0, 0, 0},
}; };
int c = getopt_long(argc, argv, gostr, long_opts, NULL); int c = getopt_long(argc, argv, gostr, long_opts, NULL);
if (c == -1) if (c == -1)
@ -211,7 +220,7 @@ static int parse_args_post(int argc, char *argv[])
break; break;
case 'a': case 'a':
cfg_setbool(cfg, "show_all", cfg_true); cfg_setint(cfg, "show_all", 1);
break; break;
case 'U': case 'U':
@ -260,8 +269,9 @@ int main(int argc, char *argv[])
{ {
unsigned long sleep_time; unsigned long sleep_time;
double read_interval; double read_interval;
int unused;
start_time = time(NULL); start_time = time(0);
memset(&rtiming, 0, sizeof(rtiming)); memset(&rtiming, 0, sizeof(rtiming));
rtiming.rt_variance.v_min = FLT_MAX; rtiming.rt_variance.v_min = FLT_MAX;
@ -352,6 +362,9 @@ int main(int argc, char *argv[])
output_post(); output_post();
} }
if (do_quit)
exit(0);
/* /*
* ST := Configured ST * ST := Configured ST
*/ */
@ -387,4 +400,5 @@ int main(int argc, char *argv[])
static void __init bmon_init(void) static void __init bmon_init(void)
{ {
atexit(&sig_exit); atexit(&sig_exit);
//signal(SIGINT, &sig_int);
} }

View File

@ -30,7 +30,6 @@
#include <bmon/element.h> #include <bmon/element.h>
#include <bmon/element_cfg.h> #include <bmon/element_cfg.h>
#include <bmon/history.h> #include <bmon/history.h>
#include <bmon/layout.h>
#include <bmon/utils.h> #include <bmon/utils.h>
cfg_t *cfg; cfg_t *cfg;
@ -70,16 +69,6 @@ static cfg_opt_t unit_opts[] = {
CFG_END() CFG_END()
}; };
static cfg_opt_t color_opts[] = {
CFG_STR_LIST("color_pair", "", CFGF_NONE),
CFG_END()
};
static cfg_opt_t layout_opts[] = {
CFG_SEC("color", color_opts, CFGF_MULTI | CFGF_TITLE),
CFG_END()
};
static cfg_opt_t global_opts[] = { static cfg_opt_t global_opts[] = {
CFG_FLOAT("read_interval", 1.0f, CFGF_NONE), CFG_FLOAT("read_interval", 1.0f, CFGF_NONE),
CFG_FLOAT("rate_interval", 1.0f, CFGF_NONE), CFG_FLOAT("rate_interval", 1.0f, CFGF_NONE),
@ -98,7 +87,6 @@ static cfg_opt_t global_opts[] = {
CFG_SEC("attr", attr_opts, CFGF_MULTI | CFGF_TITLE), CFG_SEC("attr", attr_opts, CFGF_MULTI | CFGF_TITLE),
CFG_SEC("history", history_opts, CFGF_MULTI | CFGF_TITLE), CFG_SEC("history", history_opts, CFGF_MULTI | CFGF_TITLE),
CFG_SEC("element", element_opts, CFGF_MULTI | CFGF_TITLE), CFG_SEC("element", element_opts, CFGF_MULTI | CFGF_TITLE),
CFG_SEC("layout", layout_opts, CFGF_MULTI | CFGF_TITLE),
CFG_END() CFG_END()
}; };
@ -115,26 +103,22 @@ static char * configfile = NULL;
#if defined HAVE_USE_DEFAULT_COLORS #if defined HAVE_USE_DEFAULT_COLORS
struct layout cfg_layout[] = struct layout cfg_layout[] =
{ {
{-1, -1, 0}, /* dummy, not used */ {-1, -1, 0}, /* dummy, not used */
{-1, -1, 0}, /* default */ {-1, -1, 0}, /* default */
{-1, -1, A_REVERSE}, /* statusbar */ {-1, -1, A_REVERSE}, /* statusbar */
{-1, -1, 0}, /* header */ {-1, -1, 0}, /* header */
{-1, -1, 0}, /* list */ {-1, -1, 0}, /* list */
{-1, -1, A_REVERSE}, /* selected */ {-1, -1, A_REVERSE}, /* selected */
{-1, -1, 0}, /* RX graph */
{-1, -1, 0}, /* TX graph */
}; };
#else #else
struct layout cfg_layout[] = struct layout cfg_layout[] =
{ {
{0, 0, 0}, /* dummy, not used */ {0, 0, 0}, /* dummy, not used */
{COLOR_WHITE, COLOR_BLACK, 0}, /* default */ {COLOR_BLACK, COLOR_WHITE, 0}, /* default */
{COLOR_BLUE, COLOR_GREEN, A_REVERSE}, /* statusbar */ {COLOR_BLACK, COLOR_WHITE, A_REVERSE}, /* statusbar */
{COLOR_GREEN, COLOR_BLACK, 0}, /* header */ {COLOR_BLACK, COLOR_WHITE, 0}, /* header */
{COLOR_WHITE, COLOR_BLACK, 0}, /* list */ {COLOR_BLACK, COLOR_WHITE, 0}, /* list */
{COLOR_YELLOW, COLOR_BLACK, A_REVERSE}, /* selected */ {COLOR_BLACK, COLOR_WHITE, A_REVERSE}, /* selected */
{COLOR_GREEN, COLOR_BLACK, 0}, /* RX graph */
{COLOR_RED, COLOR_BLACK, 0}, /* TX graph */
}; };
#endif #endif
#endif #endif
@ -387,7 +371,7 @@ static void configfile_read_units(void)
static void configfile_read_attrs(void) static void configfile_read_attrs(void)
{ {
int i, nattrs, t = 0; int i, nattrs, t;
nattrs = cfg_size(cfg, "attr"); nattrs = cfg_size(cfg, "attr");
@ -439,41 +423,6 @@ static void configfile_read_attrs(void)
} }
} }
static void configfile_read_layout_cfg(void)
{
int i, nlayouts;
cfg_t *lout;
nlayouts = cfg_size(cfg, "layout");
for (i = 0; i < nlayouts; i++)
{
int c, ncolors;
const char *name;
if (!(lout = cfg_getnsec(cfg, "layout", i)))
BUG();
if (!(name = cfg_title(lout)))
BUG();
ncolors = cfg_size(lout, "color");
if (ncolors > LAYOUT_MAX) {
fprintf(stderr, "Warning excceeded maximum number of layouts\n");
ncolors = LAYOUT_MAX;
}
for (c = 0; c < ncolors; c++) {
cfg_t *color_pair;
if (!(color_pair = cfg_getnsec(lout, "color", c)))
BUG();
if (!(name = cfg_title(color_pair)))
BUG();
add_layout(name, color_pair);
}
}
}
static void conf_read(const char *path, int must) static void conf_read(const char *path, int must)
{ {
int err; int err;
@ -501,7 +450,6 @@ static void conf_read(const char *path, int must)
configfile_read_history(); configfile_read_history();
configfile_read_attrs(); configfile_read_attrs();
configfile_read_element_cfg(); configfile_read_element_cfg();
configfile_read_layout_cfg();
} }
static const char default_config[] = \ static const char default_config[] = \
@ -560,29 +508,6 @@ static const char default_config[] = \
"history day {" \ "history day {" \
" interval = 86400.0" \ " interval = 86400.0" \
" size = 60" \ " size = 60" \
"}"
"layout colors {" \
" color default {" \
" color_pair = { \"white\", \"black\" }" \
" }" \
" color statusbar{" \
" color_pair = { \"blue\", \"white\", \"reverse\" }" \
" }" \
" color header {" \
" color_pair = { \"yellow\", \"black\" }" \
" }" \
" color list {" \
" color_pair = { \"white\", \"black\" }" \
" }" \
" color selected {" \
" color_pair = { \"yellow\", \"black\", \"reverse\" }" \
" }" \
" color rx_graph {" \
" color_pair = { \"green\", \"black\" }" \
" }" \
" color tx_graph {" \
" color_pair = { \"red\", \"black\" }" \
" }" \
"}"; "}";
static void conf_read_default(void) static void conf_read_default(void)
@ -599,7 +524,6 @@ static void conf_read_default(void)
configfile_read_history(); configfile_read_history();
configfile_read_attrs(); configfile_read_attrs();
configfile_read_element_cfg(); configfile_read_element_cfg();
configfile_read_layout_cfg();
} }
void configfile_read(void) void configfile_read(void)

View File

@ -113,9 +113,8 @@ void element_parse_policy(const char *policy)
xfree(copy); xfree(copy);
} }
static struct element *__lookup_element(struct element_group *group, struct element *__lookup_element(struct element_group *group, const char *name,
const char *name, uint32_t id, uint32_t id, struct element *parent)
struct element *parent)
{ {
struct list_head *list; struct list_head *list;
struct element *e; struct element *e;
@ -201,6 +200,12 @@ void element_free(struct element *e)
struct attr *a, *an; struct attr *a, *an;
int i; int i;
if (e->e_group->g_current == e) {
element_select_prev();
if (e->e_group->g_current == e)
e->e_group->g_current = NULL;
}
list_for_each_entry_safe(c, cnext, &e->e_childs, e_list) list_for_each_entry_safe(c, cnext, &e->e_childs, e_list)
element_free(c); element_free(c);
@ -215,12 +220,6 @@ void element_free(struct element *e)
list_for_each_entry_safe(a, an, &e->e_attrhash[i], a_list) list_for_each_entry_safe(a, an, &e->e_attrhash[i], a_list)
attr_free(a); attr_free(a);
if (e->e_group->g_current == e) {
element_select_prev();
if (e->e_group->g_current == e)
e->e_group->g_current = NULL;
}
list_del(&e->e_list); list_del(&e->e_list);
e->e_group->g_nelements--; e->e_group->g_nelements--;
@ -358,26 +357,6 @@ int element_set_usage_attr(struct element *e, const char *usage)
return 0; return 0;
} }
void element_pick_from_policy(struct element_group *g)
{
if (!list_empty(&allowed)) {
struct policy *p;
list_for_each_entry(p, &allowed, p_list) {
struct element *e;
list_for_each_entry(e, &g->g_elements, e_list) {
if (match_mask(p, e->e_name)) {
g->g_current = e;
return;
}
}
}
}
element_select_first();
}
struct element *element_current(void) struct element *element_current(void)
{ {
struct element_group *g; struct element_group *g;
@ -385,12 +364,8 @@ struct element *element_current(void)
if (!(g = group_current())) if (!(g = group_current()))
return NULL; return NULL;
/*
* If no element is picked yet, pick a default interface according to
* the selection policy.
*/
if (!g->g_current) if (!g->g_current)
element_pick_from_policy(g); element_select_first();
return g->g_current; return g->g_current;
} }

View File

@ -58,6 +58,26 @@ static inline char *tbl_pos(struct graph_cfg *cfg, char *tbl, int nrow, int ncol
return at_col(at_row(cfg, tbl, nrow), ncol); return at_col(at_row(cfg, tbl, nrow), ncol);
} }
static void write_column(struct graph_cfg *cfg, struct graph_table *tbl, int ncol,
uint64_t value, double *scale, double half_step)
{
char *col = at_col(tbl->gt_table, ncol);
int i;
#if 0
if (value == UNK_DATA) {
for (i = 0; i < height; i++)
*(at_row(g, col, i)) = unk_char;
#endif
if (value) {
*(at_row(cfg, col, 0)) = ':';
for (i = 0; i < cfg->gc_height; i++)
if (value >= (scale[i] - half_step))
*(at_row(cfg, col, i)) = cfg->gc_foreground;
}
}
static void fill_table(struct graph *g, struct graph_table *tbl, static void fill_table(struct graph *g, struct graph_table *tbl,
struct history *h, struct history_store *data) struct history *h, struct history_store *data)
{ {

View File

@ -261,7 +261,7 @@ static void __init group_init(void)
{ {
DBG("init"); DBG("init");
group_new_hdr(DEFAULT_GROUP, "Interfaces", group_new_hdr("intf", "Interfaces",
"RX bps", "pps", "TX bps", "pps"); "RX bps", "pps", "TX bps", "pps");
} }

View File

@ -89,11 +89,7 @@ static void dummy_read(void)
char gname[32]; char gname[32];
struct element_group *group; struct element_group *group;
if (gidx == 0) snprintf(gname, sizeof(gname), "group%02d", gidx);
snprintf(gname, sizeof(gname), "%s", DEFAULT_GROUP);
else
snprintf(gname, sizeof(gname), "group%02d", gidx);
group = group_lookup(gname, GROUP_CREATE); group = group_lookup(gname, GROUP_CREATE);
for (n = 0; n < c_numdev; n++) { for (n = 0; n < c_numdev; n++) {
@ -189,7 +185,7 @@ static void dummy_parse_opt(const char *type, const char *value)
c_numdev = strtol(value, NULL, 0); c_numdev = strtol(value, NULL, 0);
else if (!strcasecmp(type, "randomize")) { else if (!strcasecmp(type, "randomize")) {
c_randomize = 1; c_randomize = 1;
srand(time(NULL)); srand(time(0));
} else if (!strcasecmp(type, "seed") && value) } else if (!strcasecmp(type, "seed") && value)
srand(strtol(value, NULL, 0)); srand(strtol(value, NULL, 0));
else if (!strcasecmp(type, "mtu") && value) else if (!strcasecmp(type, "mtu") && value)

View File

@ -37,8 +37,6 @@ static int c_notc = 0;
static struct element_group *grp; static struct element_group *grp;
static struct bmon_module netlink_ops; static struct bmon_module netlink_ops;
#include <linux/if.h>
#include <netlink/netlink.h> #include <netlink/netlink.h>
#include <netlink/cache.h> #include <netlink/cache.h>
#include <netlink/utils.h> #include <netlink/utils.h>
@ -49,22 +47,6 @@ static struct bmon_module netlink_ops;
#include <netlink/route/classifier.h> #include <netlink/route/classifier.h>
#include <netlink/route/qdisc/htb.h> #include <netlink/route/qdisc/htb.h>
/* These counters are not available prior to libnl 3.2.25. Set them to -1 so
* rtnl_link_get_stat() won't be called for them. */
#if LIBNL_CURRENT < 220
# define RTNL_LINK_ICMP6_CSUMERRORS -1
# define RTNL_LINK_IP6_CSUMERRORS -1
# define RTNL_LINK_IP6_NOECTPKTS -1
# define RTNL_LINK_IP6_ECT1PKTS -1
# define RTNL_LINK_IP6_ECT0PKTS -1
# define RTNL_LINK_IP6_CEPKTS -1
#endif
/* Not available prior to libnl 3.2.29 */
#if LIBNL_CURRENT < 224
# define RTNL_LINK_RX_NOHANDLER -1
#endif
static struct attr_map link_attrs[] = { static struct attr_map link_attrs[] = {
{ {
.name = "bytes", .name = "bytes",
@ -106,14 +88,6 @@ static struct attr_map link_attrs[] = {
.rxid = RTNL_LINK_RX_COMPRESSED, .rxid = RTNL_LINK_RX_COMPRESSED,
.txid = RTNL_LINK_TX_COMPRESSED, .txid = RTNL_LINK_TX_COMPRESSED,
}, },
{
.name = "nohandler",
.type = ATTR_TYPE_COUNTER,
.unit = UNIT_NUMBER,
.description = "No Handler",
.rxid = RTNL_LINK_RX_NOHANDLER,
.txid = -1,
},
{ {
.name = "fifoerr", .name = "fifoerr",
.type = ATTR_TYPE_COUNTER, .type = ATTR_TYPE_COUNTER,
@ -306,14 +280,6 @@ static struct attr_map link_attrs[] = {
.rxid = RTNL_LINK_ICMP6_INERRORS, .rxid = RTNL_LINK_ICMP6_INERRORS,
.txid = RTNL_LINK_ICMP6_OUTERRORS, .txid = RTNL_LINK_ICMP6_OUTERRORS,
}, },
{
.name = "icmp6csumerr",
.type = ATTR_TYPE_COUNTER,
.unit = UNIT_NUMBER,
.description = "ICMPv6 Checksum Errors",
.rxid = RTNL_LINK_ICMP6_CSUMERRORS,
.txid = -1,
},
{ {
.name = "ip6inhdrerr", .name = "ip6inhdrerr",
.type = ATTR_TYPE_COUNTER, .type = ATTR_TYPE_COUNTER,
@ -354,14 +320,6 @@ static struct attr_map link_attrs[] = {
.rxid = RTNL_LINK_IP6_INADDRERRORS, .rxid = RTNL_LINK_IP6_INADDRERRORS,
.txid = -1, .txid = -1,
}, },
{
.name = "ip6csumerr",
.type = ATTR_TYPE_COUNTER,
.unit = UNIT_NUMBER,
.description = "Ip6 Checksum Error",
.rxid = RTNL_LINK_IP6_CSUMERRORS,
.txid = -1,
},
{ {
.name = "ip6reasmtimeo", .name = "ip6reasmtimeo",
.type = ATTR_TYPE_COUNTER, .type = ATTR_TYPE_COUNTER,
@ -393,38 +351,6 @@ static struct attr_map link_attrs[] = {
.description = "Ip6 Reasm/Frag Requests", .description = "Ip6 Reasm/Frag Requests",
.rxid = RTNL_LINK_IP6_REASMREQDS, .rxid = RTNL_LINK_IP6_REASMREQDS,
.txid = RTNL_LINK_IP6_FRAGCREATES, .txid = RTNL_LINK_IP6_FRAGCREATES,
},
{
.name = "ip6noectpkts",
.type = ATTR_TYPE_COUNTER,
.unit = UNIT_NUMBER,
.description = "Ip6 Non-ECT Packets",
.rxid = RTNL_LINK_IP6_NOECTPKTS,
.txid = -1,
},
{
.name = "ip6ect1pkts",
.type = ATTR_TYPE_COUNTER,
.unit = UNIT_NUMBER,
.description = "Ip6 ECT(1) Packets",
.rxid = RTNL_LINK_IP6_ECT1PKTS,
.txid = -1,
},
{
.name = "ip6ect0pkts",
.type = ATTR_TYPE_COUNTER,
.unit = UNIT_NUMBER,
.description = "Ip6 ECT(0) Packets",
.rxid = RTNL_LINK_IP6_ECT0PKTS,
.txid = -1,
},
{
.name = "ip6cepkts",
.type = ATTR_TYPE_COUNTER,
.unit = UNIT_NUMBER,
.description = "Ip6 CE Packets",
.rxid = RTNL_LINK_IP6_CEPKTS,
.txid = -1,
} }
}; };
@ -504,13 +430,12 @@ static struct attr_map tc_attrs[] = {
}; };
struct rdata { struct rdata {
struct nl_cache * class_cache;
struct element * parent; struct element * parent;
int level; int level;
}; };
static struct nl_sock *sock; static struct nl_sock *sock;
static struct nl_cache *link_cache, *qdisc_cache; static struct nl_cache *link_cache, *qdisc_cache, *class_cache;
static void update_tc_attrs(struct element *e, struct rtnl_tc *tc) static void update_tc_attrs(struct element *e, struct rtnl_tc *tc)
{ {
@ -545,10 +470,10 @@ static void update_tc_infos(struct element *e, struct rtnl_tc *tc)
static void handle_qdisc(struct nl_object *obj, void *); static void handle_qdisc(struct nl_object *obj, void *);
static void find_classes(uint32_t, struct rdata *); static void find_classes(uint32_t, struct rdata *);
static void find_qdiscs(int, uint32_t, struct rdata *); static void find_qdiscs(uint32_t, struct rdata *);
static struct element *handle_tc_obj(struct rtnl_tc *tc, const char *prefix, static struct element *handle_tc_obj(struct rtnl_tc *tc, const char *prefix,
const struct rdata *rdata) struct rdata *rdata)
{ {
char buf[IFNAME_MAX], name[IFNAME_MAX]; char buf[IFNAME_MAX], name[IFNAME_MAX];
uint32_t id = rtnl_tc_get_handle(tc); uint32_t id = rtnl_tc_get_handle(tc);
@ -558,14 +483,11 @@ static struct element *handle_tc_obj(struct rtnl_tc *tc, const char *prefix,
snprintf(name, sizeof(name), "%s %s (%s)", snprintf(name, sizeof(name), "%s %s (%s)",
prefix, buf, rtnl_tc_get_kind(tc)); prefix, buf, rtnl_tc_get_kind(tc));
if (!rdata || !rdata->parent) if (!(e = element_lookup(grp, name, id, rdata ? rdata->parent : NULL, ELEMENT_CREAT)))
BUG();
if (!(e = element_lookup(grp, name, id, rdata->parent, ELEMENT_CREAT)))
return NULL; return NULL;
if (e->e_flags & ELEMENT_FLAG_CREATED) { if (e->e_flags & ELEMENT_FLAG_CREATED) {
e->e_level = rdata->level; e->e_level = rdata ? rdata->level : 0;
if (element_set_key_attr(e, "tc_bytes", "tc_packets") || if (element_set_key_attr(e, "tc_bytes", "tc_packets") ||
element_set_usage_attr(e, "tc_bytes")) element_set_usage_attr(e, "tc_bytes"))
@ -596,9 +518,8 @@ static void handle_class(struct nl_object *obj, void *arg)
{ {
struct rtnl_tc *tc = (struct rtnl_tc *) obj; struct rtnl_tc *tc = (struct rtnl_tc *) obj;
struct element *e; struct element *e;
const struct rdata *rdata = arg; struct rdata *rdata = arg;
struct rdata ndata = { struct rdata ndata = {
.class_cache = rdata->class_cache,
.level = rdata->level + 1, .level = rdata->level + 1,
}; };
@ -611,10 +532,10 @@ static void handle_class(struct nl_object *obj, void *arg)
element_set_txmax(e, rtnl_htb_get_rate((struct rtnl_class *) tc)); element_set_txmax(e, rtnl_htb_get_rate((struct rtnl_class *) tc));
find_classes(rtnl_tc_get_handle(tc), &ndata); find_classes(rtnl_tc_get_handle(tc), &ndata);
find_qdiscs(rtnl_tc_get_ifindex(tc), rtnl_tc_get_handle(tc), &ndata); find_qdiscs(rtnl_tc_get_handle(tc), &ndata);
} }
static void find_qdiscs(int ifindex, uint32_t parent, struct rdata *rdata) static void find_qdiscs(uint32_t parent, struct rdata *rdata)
{ {
struct rtnl_qdisc *filter; struct rtnl_qdisc *filter;
@ -622,7 +543,6 @@ static void find_qdiscs(int ifindex, uint32_t parent, struct rdata *rdata)
return; return;
rtnl_tc_set_parent((struct rtnl_tc *) filter, parent); rtnl_tc_set_parent((struct rtnl_tc *) filter, parent);
rtnl_tc_set_ifindex((struct rtnl_tc *) filter, ifindex);
nl_cache_foreach_filter(qdisc_cache, OBJ_CAST(filter), nl_cache_foreach_filter(qdisc_cache, OBJ_CAST(filter),
handle_qdisc, rdata); handle_qdisc, rdata);
@ -651,7 +571,7 @@ static void find_classes(uint32_t parent, struct rdata *rdata)
rtnl_tc_set_parent((struct rtnl_tc *) filter, parent); rtnl_tc_set_parent((struct rtnl_tc *) filter, parent);
nl_cache_foreach_filter(rdata->class_cache, OBJ_CAST(filter), nl_cache_foreach_filter(class_cache, OBJ_CAST(filter),
handle_class, rdata); handle_class, rdata);
rtnl_class_put(filter); rtnl_class_put(filter);
@ -661,9 +581,8 @@ static void handle_qdisc(struct nl_object *obj, void *arg)
{ {
struct rtnl_tc *tc = (struct rtnl_tc *) obj; struct rtnl_tc *tc = (struct rtnl_tc *) obj;
struct element *e; struct element *e;
const struct rdata *rdata = arg; struct rdata *rdata = arg;
struct rdata ndata = { struct rdata ndata = {
.class_cache = rdata->class_cache,
.level = rdata->level + 1, .level = rdata->level + 1,
}; };
@ -685,7 +604,6 @@ static void handle_qdisc(struct nl_object *obj, void *arg)
static void handle_tc(struct element *e, struct rtnl_link *link) static void handle_tc(struct element *e, struct rtnl_link *link)
{ {
struct rtnl_qdisc *qdisc; struct rtnl_qdisc *qdisc;
struct nl_cache *class_cache;
int ifindex = rtnl_link_get_ifindex(link); int ifindex = rtnl_link_get_ifindex(link);
struct rdata rdata = { struct rdata rdata = {
.level = 1, .level = 1,
@ -695,8 +613,6 @@ static void handle_tc(struct element *e, struct rtnl_link *link)
if (rtnl_class_alloc_cache(sock, ifindex, &class_cache) < 0) if (rtnl_class_alloc_cache(sock, ifindex, &class_cache) < 0)
return; return;
rdata.class_cache = class_cache;
qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, TC_H_ROOT); qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, TC_H_ROOT);
if (qdisc) { if (qdisc) {
handle_qdisc(OBJ_CAST(qdisc), &rdata); handle_qdisc(OBJ_CAST(qdisc), &rdata);
@ -820,7 +736,7 @@ static void do_link(struct nl_object *obj, void *arg)
attr_update(e, m->attrid, c_rx, c_tx, flags); attr_update(e, m->attrid, c_rx, c_tx, flags);
} }
if (!c_notc && qdisc_cache) if (!c_notc)
handle_tc(e, link); handle_tc(e, link);
element_notify_update(e, NULL); element_notify_update(e, NULL);
@ -836,8 +752,7 @@ static void netlink_read(void)
goto disable; goto disable;
} }
if (qdisc_cache && if ((err = nl_cache_resync(sock, qdisc_cache, NULL, NULL)) < 0) {
(err = nl_cache_resync(sock, qdisc_cache, NULL, NULL)) < 0) {
fprintf(stderr, "Unable to resync qdisc cache: %s\n", nl_geterror(err)); fprintf(stderr, "Unable to resync qdisc cache: %s\n", nl_geterror(err));
goto disable; goto disable;
} }
@ -857,20 +772,9 @@ static void netlink_shutdown(void)
nl_socket_free(sock); nl_socket_free(sock);
} }
static void netlink_use_bit(struct attr_map *map, const int size)
{
if(cfg_getbool(cfg, "use_bit")) {
for(int i = 0; i < size; ++i) {
if(!strcmp(map[i].description, "Bytes")) {
map[i].description = "Bits";
}
}
}
}
static int netlink_do_init(void) static int netlink_do_init(void)
{ {
int err; int err, i;
if (!(sock = nl_socket_alloc())) { if (!(sock = nl_socket_alloc())) {
fprintf(stderr, "Unable to allocate netlink socket\n"); fprintf(stderr, "Unable to allocate netlink socket\n");
@ -888,13 +792,10 @@ static int netlink_do_init(void)
} }
if ((err = rtnl_qdisc_alloc_cache(sock, &qdisc_cache)) < 0) { if ((err = rtnl_qdisc_alloc_cache(sock, &qdisc_cache)) < 0) {
fprintf(stderr, "Warning: Unable to allocate qdisc cache: %s\n", nl_geterror(err)); fprintf(stderr, "Unable to allocate qdisc cache: %s\n", nl_geterror(err));
fprintf(stderr, "Disabling QoS statistics.\n"); goto disable;
qdisc_cache = NULL;
} }
netlink_use_bit(link_attrs, ARRAY_SIZE(link_attrs));
netlink_use_bit(tc_attrs, ARRAY_SIZE(tc_attrs));
if (attr_map_load(link_attrs, ARRAY_SIZE(link_attrs)) || if (attr_map_load(link_attrs, ARRAY_SIZE(link_attrs)) ||
attr_map_load(tc_attrs, ARRAY_SIZE(tc_attrs))) attr_map_load(tc_attrs, ARRAY_SIZE(tc_attrs)))
BUG(); BUG();

View File

@ -101,7 +101,7 @@ static void proc_read(void)
{ {
struct element *e; struct element *e;
FILE *fd; FILE *fd;
char buf[512], *p, *s, *unused __unused__; char buf[512], *p, *s, *unused;
int w; int w;
if (!(fd = fopen(c_path, "r"))) if (!(fd = fopen(c_path, "r")))

View File

@ -163,7 +163,6 @@ sysctl_read(void)
struct element *e, *e_parent = NULL; struct element *e, *e_parent = NULL;
struct if_msghdr *ifm, *nextifm; struct if_msghdr *ifm, *nextifm;
struct sockaddr_dl *sdl; struct sockaddr_dl *sdl;
char info_buf[64];
ifm = (struct if_msghdr *) next; ifm = (struct if_msghdr *) next;
if (ifm->ifm_type != RTM_IFINFO) if (ifm->ifm_type != RTM_IFINFO)
@ -226,20 +225,6 @@ sysctl_read(void)
attr_update(e, m->attrid, rx, tx, flags); attr_update(e, m->attrid, rx, tx, flags);
} }
snprintf(info_buf, sizeof(info_buf), "%ju", (uintmax_t)ifm->ifm_data.ifi_mtu);
element_update_info(e, "MTU", info_buf);
snprintf(info_buf, sizeof(info_buf), "%ju", (uintmax_t)ifm->ifm_data.ifi_metric);
element_update_info(e, "Metric", info_buf);
#if !(defined(__NetBSD__) || defined(__FreeBSD__))
snprintf(info_buf, sizeof(info_buf), "%u", ifm->ifm_data.ifi_recvquota);
element_update_info(e, "RX-Quota", info_buf);
snprintf(info_buf, sizeof(info_buf), "%u", ifm->ifm_data.ifi_xmitquota);
element_update_info(e, "TX-Quota", info_buf);
#endif
element_notify_update(e, NULL); element_notify_update(e, NULL);
element_lifesign(e, 1); element_lifesign(e, 1);
} }

View File

@ -130,6 +130,7 @@ static void __auto_load(struct bmon_module *m)
int module_set(struct bmon_subsys *ss, const char *name) int module_set(struct bmon_subsys *ss, const char *name)
{ {
struct bmon_module *mod; struct bmon_module *mod;
struct list_head *list;
LIST_HEAD(tmp_list); LIST_HEAD(tmp_list);
module_conf_t *m; module_conf_t *m;

View File

@ -101,10 +101,10 @@ static void print_attr_detail(struct element *e, struct attr *a, void *arg)
char *rx_u, *tx_u; char *rx_u, *tx_u;
int rxprec, txprec; int rxprec, txprec;
double rx = unit_value2str(rate_get_total(&a->a_rx_rate), double rx = unit_value2str(a->a_rx_rate.r_total,
a->a_def->ad_unit, a->a_def->ad_unit,
&rx_u, &rxprec); &rx_u, &rxprec);
double tx = unit_value2str(rate_get_total(&a->a_tx_rate), double tx = unit_value2str(a->a_tx_rate.r_total,
a->a_def->ad_unit, a->a_def->ad_unit,
&tx_u, &txprec); &tx_u, &txprec);
@ -212,7 +212,6 @@ static void ascii_draw_group(struct element_group *g, void *arg)
static void ascii_draw(void) static void ascii_draw(void)
{ {
group_foreach(ascii_draw_group, NULL); group_foreach(ascii_draw_group, NULL);
fflush(stdout);
if (c_quit_after > 0) if (c_quit_after > 0)
if (--c_quit_after == 0) if (--c_quit_after == 0)

View File

@ -45,8 +45,6 @@ enum {
KEY_TOGGLE_DETAILS = 'd', KEY_TOGGLE_DETAILS = 'd',
KEY_TOGGLE_INFO = 'i', KEY_TOGGLE_INFO = 'i',
KEY_COLLECT_HISTORY = 'h', KEY_COLLECT_HISTORY = 'h',
KEY_CTRL_N = 14,
KEY_CTRL_P = 16,
}; };
#define DETAILS_COLS 40 #define DETAILS_COLS 40
@ -139,7 +137,7 @@ static void apply_layout(int layout)
attrset(cfg_layout[layout].l_attr); attrset(cfg_layout[layout].l_attr);
} }
static char *float2str(double value, int width, int prec, char *buf, size_t len) char *float2str(double value, int width, int prec, char *buf, size_t len)
{ {
snprintf(buf, len, "%'*.*f", width, value == 0.0f ? 0 : prec, value); snprintf(buf, len, "%'*.*f", width, value == 0.0f ? 0 : prec, value);
@ -149,24 +147,22 @@ static char *float2str(double value, int width, int prec, char *buf, size_t len)
static void put_line(const char *fmt, ...) static void put_line(const char *fmt, ...)
{ {
va_list args; va_list args;
char *buf; char buf[2048];
int len; int x, y;
int x, y __unused__;
memset(buf, 0, sizeof(buf));
getyx(stdscr, y, x); getyx(stdscr, y, x);
len = cols - x;
buf = xcalloc(len+1, 1);
va_start(args, fmt); va_start(args, fmt);
vsnprintf(buf, len+1, fmt, args); vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args); va_end(args);
if (strlen(buf) < len) if (strlen(buf) > cols-x)
memset(&buf[strlen(buf)], ' ', len - strlen(buf)); buf[cols - x] = '\0';
else
memset(&buf[strlen(buf)], ' ', cols - strlen(buf)-x);
addstr(buf); addstr(buf);
xfree(buf);
} }
static void center_text(const char *fmt, ...) static void center_text(const char *fmt, ...)
@ -245,10 +241,10 @@ static void draw_attr_detail(struct element *e, struct attr *a, void *arg)
int rxprec, txprec, ncol; int rxprec, txprec, ncol;
struct detail_arg *da = arg; struct detail_arg *da = arg;
double rx = unit_value2str(rate_get_total(&a->a_rx_rate), double rx = unit_value2str(a->a_rx_rate.r_total,
a->a_def->ad_unit, a->a_def->ad_unit,
&rx_u, &rxprec); &rx_u, &rxprec);
double tx = unit_value2str(rate_get_total(&a->a_tx_rate), double tx = unit_value2str(a->a_tx_rate.r_total,
a->a_def->ad_unit, a->a_def->ad_unit,
&tx_u, &txprec); &tx_u, &txprec);
@ -262,7 +258,7 @@ static void draw_attr_detail(struct element *e, struct attr *a, void *arg)
if (ncol > 0) if (ncol > 0)
addch(ACS_VLINE); addch(ACS_VLINE);
put_line(" %-14.14s %8s%-3s %8s%-3s", put_line(" %-14.14s %8s%-3s %8s%-3s\n",
a->a_def->ad_description, a->a_def->ad_description,
(a->a_flags & ATTR_RX_ENABLED) ? (a->a_flags & ATTR_RX_ENABLED) ?
float2str(rx, 8, rxprec, buf1, sizeof(buf1)) : "-", rx_u, float2str(rx, 8, rxprec, buf1, sizeof(buf1)) : "-", rx_u,
@ -396,7 +392,6 @@ static void draw_help(void)
mvaddnstr(y+15, x+3, "H Start recording history data", -1); mvaddnstr(y+15, x+3, "H Start recording history data", -1);
mvaddnstr(y+16, x+3, "TAB Switch time unit of graph", -1); mvaddnstr(y+16, x+3, "TAB Switch time unit of graph", -1);
mvaddnstr(y+17, x+3, "<, > Change number of graphs", -1); mvaddnstr(y+17, x+3, "<, > Change number of graphs", -1);
mvaddnstr(y+18, x+3, "r Reset counter of element", -1);
attroff(A_STANDOUT); attroff(A_STANDOUT);
@ -424,7 +419,6 @@ static void draw_header(void)
move(row, COLS - strlen(PACKAGE_STRING) - 1); move(row, COLS - strlen(PACKAGE_STRING) - 1);
put_line("%s", PACKAGE_STRING); put_line("%s", PACKAGE_STRING);
move(row, 0); move(row, 0);
apply_layout(LAYOUT_LIST);
} }
static int lines_required_for_statusbar(void) static int lines_required_for_statusbar(void)
@ -436,7 +430,7 @@ static void draw_statusbar(void)
{ {
static const char *help_text = "Press ? for help"; static const char *help_text = "Press ? for help";
char s[27]; char s[27];
time_t t = time(NULL); time_t t = time(0);
apply_layout(LAYOUT_STATUSBAR); apply_layout(LAYOUT_STATUSBAR);
@ -637,7 +631,6 @@ static void draw_element(struct element_group *g, struct element *e,
static void draw_group(struct element_group *g, void *arg) static void draw_group(struct element_group *g, void *arg)
{ {
apply_layout(LAYOUT_HEADER);
int *line = arg; int *line = arg;
if (line_visible(*line)) { if (line_visible(*line)) {
@ -690,7 +683,7 @@ static void draw_graph_centered(struct graph *g, int row, int ncol,
static void draw_table(struct graph *g, struct graph_table *tbl, static void draw_table(struct graph *g, struct graph_table *tbl,
struct attr *a, struct history *h, struct attr *a, struct history *h,
const char *hdr, int ncol, int layout) const char *hdr, int ncol)
{ {
int i, save_row; int i, save_row;
char buf[32]; char buf[32];
@ -715,14 +708,11 @@ static void draw_table(struct graph *g, struct graph_table *tbl,
//move(row, ncol + g->g_cfg.gc_width - 3); //move(row, ncol + g->g_cfg.gc_width - 3);
//put_line("[err %.2f%%]", rtiming.rt_variance.v_error); //put_line("[err %.2f%%]", rtiming.rt_variance.v_error);
memset(buf, 0, strlen(buf));
for (i = (g->g_cfg.gc_height - 1); i >= 0; i--) { for (i = (g->g_cfg.gc_height - 1); i >= 0; i--) {
move(++row, ncol); move(++row, ncol);
sprintf(buf, "%'8.2f ", tbl->gt_scale[i]); put_line("%'8.2f %s",
addstr(buf); tbl->gt_scale[i],
apply_layout(layout); tbl->gt_table + (i * graph_row_size(&g->g_cfg)));
put_line("%s", tbl->gt_table + (i * graph_row_size(&g->g_cfg)));
apply_layout(LAYOUT_LIST);
} }
move(++row, ncol); move(++row, ncol);
@ -756,14 +746,14 @@ static void draw_history_graph(struct attr *a, struct history *h)
graph_refill(g, h); graph_refill(g, h);
save_row = row; save_row = row;
draw_table(g, &g->g_rx, a, h, "RX", ncol, LAYOUT_RX_GRAPH); draw_table(g, &g->g_rx, a, h, "RX", ncol);
if (graph_display == GRAPH_DISPLAY_SIDE_BY_SIDE) { if (graph_display == GRAPH_DISPLAY_SIDE_BY_SIDE) {
ncol = cols / 2; ncol = cols / 2;
row = save_row; row = save_row;
} }
draw_table(g, &g->g_tx, a, h, "TX", ncol, LAYOUT_TX_GRAPH); draw_table(g, &g->g_tx, a, h, "TX", ncol);
graph_free(g); graph_free(g);
} }
@ -983,10 +973,8 @@ draw:
*/ */
NEXT_ROW(); NEXT_ROW();
hline(ACS_HLINE, cols); hline(ACS_HLINE, cols);
if (c_show_list) { mvaddch(row, LIST_COL_1, ACS_BTEE);
mvaddch(row, LIST_COL_1, ACS_BTEE); mvaddch(row, LIST_COL_2, ACS_BTEE);
mvaddch(row, LIST_COL_2, ACS_BTEE);
}
if (!c_show_graph) if (!c_show_graph)
center_text(" Press %c to enable graphical statistics ", center_text(" Press %c to enable graphical statistics ",
@ -1028,12 +1016,6 @@ draw:
NEXT_ROW(); NEXT_ROW();
hline(ACS_HLINE, cols); hline(ACS_HLINE, cols);
if (c_show_details) {
int i;
for (i = 1; i < detail_cols; i++)
mvaddch(row, (i * DETAILS_COLS) - 1, ACS_BTEE);
}
if (!c_show_info) if (!c_show_info)
center_text(" Press %c to enable additional information ", center_text(" Press %c to enable additional information ",
KEY_TOGGLE_INFO); KEY_TOGGLE_INFO);
@ -1097,16 +1079,6 @@ out:
refresh(); refresh();
} }
static void __reset_attr_counter(struct element *e, struct attr *a, void *arg)
{
attr_reset_counter(a);
}
static void reset_counters(void)
{
element_foreach_attr(current_element, __reset_attr_counter, NULL);
}
static int handle_input(int ch) static int handle_input(int ch)
{ {
switch (ch) switch (ch)
@ -1188,12 +1160,10 @@ static int handle_input(int ch)
return 1; return 1;
case KEY_DOWN: case KEY_DOWN:
case KEY_CTRL_N:
element_select_next(); element_select_next();
return 1; return 1;
case KEY_UP: case KEY_UP:
case KEY_CTRL_P:
element_select_prev(); element_select_prev();
return 1; return 1;
@ -1228,10 +1198,6 @@ static int handle_input(int ch)
case '\t': case '\t':
history_select_next(); history_select_next();
return 1; return 1;
case 'r':
reset_counters();
return 1;
} }
return 0; return 0;
@ -1266,7 +1232,7 @@ static void print_module_help(void)
" Author: Thomas Graf <tgraf@suug.ch>\n" \ " Author: Thomas Graf <tgraf@suug.ch>\n" \
"\n" \ "\n" \
" Options:\n" \ " Options:\n" \
" fgchar=CHAR Foreground character (default: '|')\n" \ " fgchar=CHAR Foreground character (default: '*')\n" \
" bgchar=CHAR Background character (default: '.')\n" \ " bgchar=CHAR Background character (default: '.')\n" \
" nchar=CHAR Noise character (default: ':')\n" \ " nchar=CHAR Noise character (default: ':')\n" \
" uchar=CHAR Unknown character (default: '?')\n" \ " uchar=CHAR Unknown character (default: '?')\n" \
@ -1276,7 +1242,6 @@ static void print_module_help(void)
" nocolors Do not use colors\n" \ " nocolors Do not use colors\n" \
" graph Show graphical stats by default\n" \ " graph Show graphical stats by default\n" \
" details Show detailed stats by default\n" \ " details Show detailed stats by default\n" \
" info Show additional info screen by default\n" \
" minlist=INT Minimum item list length\n"); " minlist=INT Minimum item list length\n");
} }
@ -1299,8 +1264,6 @@ static void curses_parse_opt(const char *type, const char *value)
c_show_graph = !!c_ngraph; c_show_graph = !!c_ngraph;
} else if (!strcasecmp(type, "details")) } else if (!strcasecmp(type, "details"))
c_show_details = 1; c_show_details = 1;
else if (!strcasecmp(type, "info"))
c_show_info = 1;
else if (!strcasecmp(type, "nocolors")) else if (!strcasecmp(type, "nocolors"))
c_use_colors = 0; c_use_colors = 0;
else if (!strcasecmp(type, "minlist") && value) else if (!strcasecmp(type, "minlist") && value)

View File

@ -119,22 +119,24 @@ static char *get_token(struct element_group *g, struct element *e,
goto out; goto out;
} }
if (!(a = attr_lookup(e, def->ad_id))) if (!(a = attr_lookup(e, def->ad_id))) {
fprintf(stderr, "Unable to find attribute %u (%s)\n",
def->ad_id, name);
goto out; goto out;
}
if (!strncasecmp(type, "rx:", 3)) { if (!strncasecmp(type, "rx:", 3)) {
snprintf(buf, len, "%" PRIu64, rate_get_total(&a->a_rx_rate)); snprintf(buf, len, "%" PRIu64, a->a_rx_rate.r_total);
return buf; return buf;
} else if (!strncasecmp(type, "tx:", 3)) { } else if (!strncasecmp(type, "tx:", 3)) {
snprintf(buf, len, "%" PRIu64, rate_get_total(&a->a_tx_rate)); snprintf(buf, len, "%" PRIu64, a->a_tx_rate.r_total);
return buf; return buf;
} else if (!strncasecmp(type, "rxrate:", 7)) { } else if (!strncasecmp(type, "rxrate:", 7)) {
snprintf(buf, len, "%.2f", a->a_rx_rate.r_rate); snprintf(buf, len, "%.2f", a->a_rx_rate.r_rate);
return buf; return buf;
} else if (!strncasecmp(type, "txrate:", 7)) { } else if (!strncasecmp(token+5, "txrate:", 7))
snprintf(buf, len, "%.2f", a->a_tx_rate.r_rate); snprintf(buf, len, "%.2f", a->a_tx_rate.r_rate);
return buf; return buf;
}
} }
fprintf(stderr, "Unknown field \"%s\"\n", token); fprintf(stderr, "Unknown field \"%s\"\n", token);
@ -166,7 +168,6 @@ static void draw_element(struct element_group *g, struct element *e, void *arg)
static void format_draw(void) static void format_draw(void)
{ {
group_foreach_recursive(draw_element, NULL); group_foreach_recursive(draw_element, NULL);
fflush(stdout);
if (c_quit_after > 0) if (c_quit_after > 0)
if (--c_quit_after == 0) if (--c_quit_after == 0)
@ -321,15 +322,15 @@ static void print_help(void)
" Supported Escape Sequences: \\n, \\t, \\r, \\v, \\b, \\f, \\a\n" \ " Supported Escape Sequences: \\n, \\t, \\r, \\v, \\b, \\f, \\a\n" \
"\n" \ "\n" \
" Examples:\n" \ " Examples:\n" \
" '$(element:name)\\t$(attr:rx:bytes)\\t$(attr:tx:bytes)\\n'\n" \ " \"$(element:name)\\t$(attr:rx:bytes)\\t$(attr:tx:bytes)\\n\"\n" \
" lo 12074 12074\n" \ " lo 12074 12074\n" \
"\n" \ "\n" \
" '$(element:name) $(attr:rxrate:packets) $(attr:txrate:packets)\\n'\n" \ " \"$(element:name) $(attr:rxrate:packets) $(attr:txrate:packets)\\n\"\n" \
" eth0 33 5\n" \ " eth0 33 5\n" \
"\n" \ "\n" \
" 'Item: $(element:name)\\nBytes Rate: $(attr:rxrate:bytes)/" \ " \"Element: $(element:name)\\nBytes Rate: \" \\\n" \
"$(attr:txrate:bytes)\\nPackets Rate: $(attr:rxrate:packets)/" \ " \"$(attr:rxrate:bytes)/$(attr:txrate:bytes)\\nPackets Rate: \" \\\n" \
"$(attr:txrate:packets)\\n'\n" \ " \"$(attr:rxrate:packets)/$(attr:txrate:packets)\\n\"\n" \
" Item: eth0\n" \ " Item: eth0\n" \
" Bytes Rate: 49130/2119\n" \ " Bytes Rate: 49130/2119\n" \
" Packets Rate: 40/11\n" \ " Packets Rate: 40/11\n" \

View File

@ -1,197 +0,0 @@
/*
* out_trigger.c Trigger based on traffic pattern
*
* Copyright (c) 2018 Babak Farrokhi <babak@farrokhi.net>
*
* 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/graph.h>
#include <bmon/conf.h>
#include <bmon/output.h>
#include <bmon/group.h>
#include <bmon/element.h>
#include <bmon/input.h>
#include <bmon/utils.h>
#include <bmon/attr.h>
#define RECENT_SIZE 3
static int c_quit_after_trigger = 0;
static long c_threshold_high = -1;
static long c_threshold_low = -1;
static unsigned long recent_l[RECENT_SIZE];
static unsigned long recent_count = 0;
static unsigned long recent_avg = 0;
static unsigned long triggered = 0;
static char *c_format;
static FILE *c_fd;
static char *get_token(struct element_group *g, struct element *e,
const char *token, char *buf, size_t len)
{
char *name = strchr(token, ':');
struct attr_def *def;
struct attr *a;
if (!name)
quit("Invalid attribute field \"%s\"\n", token);
name++;
def = attr_def_lookup(name);
if (!def)
quit("Undefined attribute \"%s\"\n", name);
if (!(a = attr_lookup(e, def->ad_id)))
quit("Invalid attribute \"%s\"\n", name);
if (!strncasecmp(token, "rxrate:", 7)) {
snprintf(buf, len, "%.2f", a->a_rx_rate.r_rate);
return buf;
} else if (!strncasecmp(token, "txrate:", 7)) {
snprintf(buf, len, "%.2f", a->a_tx_rate.r_rate);
return buf;
}
quit("Unknown field \"%s\"\n", token);
return NULL;
}
static void run_trigger()
{
// TODO: Run the command
if (++triggered >= c_quit_after_trigger)
exit(0);
}
static void trigger_check()
{
if (recent_count < RECENT_SIZE)
return;
if (c_threshold_high > 0 && recent_avg > c_threshold_high) {
fprintf(c_fd, "TRIGGER: Passed high threshold: %li > %li\n", recent_avg, c_threshold_high);
run_trigger();
return;
}
if (c_threshold_low > 0 && recent_avg < c_threshold_low) {
fprintf(c_fd, "TRIGGER: Droppped below threshold: %li < %li\n", recent_avg, c_threshold_low);
run_trigger();
return;
}
}
static void trigger_process(struct element_group *g, struct element *e, void *arg)
{
char buf[128];
char *p;
p = get_token(g, e, c_format, buf, sizeof(buf));
if (p)
{
int i;
unsigned long total = 0;
recent_l[recent_count % RECENT_SIZE] = strtol(p, NULL, 0);
for (i=0; i < RECENT_SIZE; i++)
{
fprintf(c_fd, "%li ", recent_l[i]);
total += recent_l[i];
}
recent_avg = (unsigned long) total / RECENT_SIZE;
fprintf(c_fd, " avg: %li\n", recent_avg);
trigger_check();
recent_count++;
}
}
static void trigger_do(void)
{
group_foreach_recursive(trigger_process, NULL);
fflush(stdout);
}
static void print_help(void)
{
printf(
"trigger - Run actions based on traffic patterns\n" \
"\n" \
" Monitors a given probe and triggers an action if the criteria is met.\n" \
" Criterias could be going above or dropping below a given threshold of traffic.\n" \
" Probes could be Bytes/sec or Packets/sec on TX or RX\n" \
"\n" \
"\n" \
" Author: Babak Farrokhi <babak@farrokhi.net>\n" \
"\n" \
" Options:\n" \
" probe=ELEMENT Element to monitor for threshold\n" \
" action=PROGRAM Program or script to run when triggered\n" \
" below=THRESHOLD Minimum acceptable level for given element (average in past three seconds)\n" \
" above=THRESHOLD Maximum acceptable level for given element (average in past three seconds)\n" \
" quittriggers=NUM Quit after NUM triggers\n" \
"\n" \
" Probe Elements:\n" \
" rxrate:packets RX packet rate\n" \
" txrate:packets TX packet rate\n" \
" rxrate:bytes RX traffic rate (bytes)\n" \
" txrate:bytes TX traffic rate (bytes)\n" \
"\n" \
" Examples:\n" \
" bmon -p eth0 -o 'trigger:probe=rxrate:packets;below=5000;quittriggers=3;action=/opt/bin/alert'\n" \
"\n");
}
static void trigger_parse_opt(const char *type, const char *value)
{
if (!strcasecmp(type, "above") && value)
c_threshold_high = strtol(value, NULL, 0);
else if (!strcasecmp(type, "below") && value)
c_threshold_low = strtol(value, NULL, 0);
else if (!strcasecmp(type, "quittriggers") && value)
c_quit_after_trigger = strtol(value, NULL, 0);
else if (!strcasecmp(type, "probe")) {
if (c_format)
free(c_format);
c_format = strdup(value);
}
else if (!strcasecmp(type, "help")) {
print_help();
exit(0);
}
}
static struct bmon_module trigger_ops = {
.m_name = "trigger",
.m_do = trigger_do,
.m_parse_opt = trigger_parse_opt,
};
static void __init ascii_init(void)
{
c_fd = stdout;
c_format = strdup("$(rxrate:packets)\\n");
output_register(&trigger_ops);
}

View File

@ -28,7 +28,7 @@
#include <bmon/utils.h> #include <bmon/utils.h>
#include <bmon/unit.h> #include <bmon/unit.h>
static struct unit *byte_unit, *bit_unit; static struct unit *byte_unit, *bit_unit, *number_unit;
static LIST_HEAD(units); static LIST_HEAD(units);

View File

@ -27,11 +27,6 @@
#include <bmon/conf.h> #include <bmon/conf.h>
#include <bmon/utils.h> #include <bmon/utils.h>
#ifdef __MACH__
#include <mach/clock.h>
#include <mach/mach.h>
#endif
void *xcalloc(size_t n, size_t s) void *xcalloc(size_t n, size_t s)
{ {
void *d = calloc(n, s); void *d = calloc(n, s);
@ -117,21 +112,12 @@ int timestamp_is_negative(timestamp_t *ts)
void update_timestamp(timestamp_t *dst) void update_timestamp(timestamp_t *dst)
{ {
#ifdef __MACH__ struct timeval tv;
clock_serv_t cclock;
mach_timespec_t tp;
host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); gettimeofday(&tv, NULL);
clock_get_time(cclock, &tp);
mach_port_deallocate(mach_task_self(), cclock);
#else
struct timespec tp;
clock_gettime(CLOCK_MONOTONIC, &tp); dst->tv_sec = tv.tv_sec;
#endif dst->tv_usec = tv.tv_usec;
dst->tv_sec = tp.tv_sec;
dst->tv_usec = tp.tv_nsec / 1000;
} }
void copy_timestamp(timestamp_t *ts1, timestamp_t *ts2) void copy_timestamp(timestamp_t *ts1, timestamp_t *ts2)