Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
eed0cadf35 | |||
13cf9440c4 |
42
.travis.yml
42
.travis.yml
@ -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
|
|
||||||
|
@ -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"
|
||||||
|
@ -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
38
NEWS
@ -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
|
||||||
|
92
README.md
92
README.md
@ -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
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||

|
|
||||||
|
|
||||||
## 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.
|
|
||||||
|
|
||||||
|
21
configure.ac
21
configure.ac
@ -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])
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
@ -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"}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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_ */
|
|
21
man/bmon.8
21
man/bmon.8
@ -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
|
||||||
|
@ -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
|
|
||||||
|
15
src/attr.c
15
src/attr.c
@ -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;
|
||||||
|
56
src/bmon.c
56
src/bmon.c
@ -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);
|
||||||
}
|
}
|
||||||
|
88
src/conf.c
88
src/conf.c
@ -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()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -121,20 +109,16 @@ struct layout cfg_layout[] =
|
|||||||
{-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)
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
20
src/graph.c
20
src/graph.c
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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), "%s", DEFAULT_GROUP);
|
|
||||||
else
|
|
||||||
snprintf(gname, sizeof(gname), "group%02d", gidx);
|
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)
|
||||||
|
129
src/in_netlink.c
129
src/in_netlink.c
@ -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();
|
||||||
|
@ -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")))
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -119,23 +119,25 @@ 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);
|
||||||
out:
|
out:
|
||||||
@ -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" \
|
||||||
|
@ -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);
|
|
||||||
}
|
|
@ -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);
|
||||||
|
|
||||||
|
22
src/utils.c
22
src/utils.c
@ -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)
|
||||||
|
Reference in New Issue
Block a user