Compare commits
47 Commits
coverity_s
...
master
Author | SHA1 | Date | |
---|---|---|---|
969cebd4ae | |||
|
5677863e61 | ||
|
ed8528cf9c | ||
|
737c642819 | ||
|
b44d0152c4 | ||
|
fdd139ada2 | ||
|
49ce252ec5 | ||
|
14db0bff4c | ||
|
3413751795 | ||
|
1b3f11bde3 | ||
|
af8923b779 | ||
|
3e4970485d | ||
|
f312679738 | ||
|
2efc2f4a60 | ||
|
a3d894000b | ||
|
8b2638c349 | ||
|
a5301347f6 | ||
|
29fb4317d7 | ||
|
32d8c76b18 | ||
|
577112870d | ||
|
5b938e05c7 | ||
|
5cd24ffd6a | ||
|
702df3c0a1 | ||
|
7317715e15 | ||
|
86f6da0703 | ||
|
723f6a5b47 | ||
|
ddcd5e7d24 | ||
|
df271c43a4 | ||
|
8f39217bd7 | ||
|
e47a376f70 | ||
|
828b5b5368 | ||
|
1c25eacc95 | ||
|
f177718f24 | ||
|
cc22e4e35d | ||
|
19c35e4990 | ||
|
70e6f97b65 | ||
|
a6c635dc96 | ||
|
f78c0e5b98 | ||
|
0e08ec1b79 | ||
|
74770b8806 | ||
|
fa6abf3a80 | ||
|
0103671f1f | ||
|
4efaa8ce9e | ||
|
1f79ea4396 | ||
|
67b6ee3bd6 | ||
|
cbcdab6669 | ||
|
8dcd666db6 |
42
.travis.yml
42
.travis.yml
@ -1,10 +1,40 @@
|
||||
language: c
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
env:
|
||||
global:
|
||||
- secure: "C87Pgf5AVDoyQfm9MIv81g"
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
before_install:
|
||||
- sudo apt-get install libconfuse-dev
|
||||
- sudo apt-get install libnl-3-dev libnl-route-3-dev
|
||||
- sudo apt-get install libncurses-dev
|
||||
# Change this to your needs
|
||||
script: ./.travis/run.sh
|
||||
|
||||
# container-based builds
|
||||
sudo: false
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
# 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
|
||||
|
24
NEWS
24
NEWS
@ -1,34 +1,46 @@
|
||||
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
|
||||
----------------------
|
||||
* Bugfixes
|
||||
* blank screen with config file
|
||||
* quick-help toggle with '?' in curses
|
||||
* Better bmon.conf example
|
||||
|
||||
v3.3 - July 6, 2014
|
||||
-------------------
|
||||
* MacOS X port
|
||||
* Only initialize curses module if actually used
|
||||
* Assorted bug and spelling fixes
|
||||
|
60
README.md
60
README.md
@ -18,7 +18,47 @@ interface and a programmable text output for scripting.
|
||||
```
|
||||
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
|
||||
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
|
||||
@ -27,8 +67,13 @@ bmon
|
||||
```
|
||||
|
||||
-------------
|
||||
## New in 3.8
|
||||
* Don't disable Netlink if TC stats are unavailable
|
||||
## 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
|
||||
|
||||
-------------
|
||||
### Usage
|
||||
@ -44,12 +89,15 @@ provided via:
|
||||
|
||||
## Screenshots
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
## Copyright
|
||||
|
||||
> *Copyright (c) 2001-2014 Thomas Graf <tgraf@suug.ch>*
|
||||
Various authors, see git commit log.
|
||||
|
||||
> *Copyright (c) 2001-2016 Thomas Graf <tgraf@suug.ch>*
|
||||
> *Copyright (c) 2013 Red Hat, Inc.*
|
||||
|
||||
Please see the [LICENSE.BSD](https://github.com/tgraf/bmon/blob/master/LICENSE.BSD)
|
||||
|
19
configure.ac
19
configure.ac
@ -1,7 +1,7 @@
|
||||
#
|
||||
# configure.in Configure Script
|
||||
#
|
||||
# Copyright (c) 2001-2013 Thomas Graf <tgraf@suug.ch>
|
||||
# Copyright (c) 2001-2016 Thomas Graf <tgraf@suug.ch>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||
# 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
|
||||
# DEALINGS IN THE SOFTWARE.
|
||||
|
||||
AC_INIT(bmon, 3.8, [], [], [http://www.infradead.org/~tgr/bmon/])
|
||||
AC_INIT(bmon, 4.0, [], [], [https://github.com/tgraf/bmon])
|
||||
AC_CONFIG_HEADERS(include/bmon/defs.h)
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
@ -58,10 +58,18 @@ AC_CHECK_HEADERS(sys/param.h sys/socket.h)
|
||||
|
||||
AC_CHECK_TYPES(suseconds_t)
|
||||
|
||||
AC_CHECK_FUNCS(atexit gettimeofday memset pow socket strcasecmp)
|
||||
AC_CHECK_FUNCS(atexit clock_gettime memset pow socket strcasecmp)
|
||||
AC_CHECK_FUNCS(strchr strdup strerror strncasecmp strstr strtol)
|
||||
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
|
||||
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])
|
||||
@ -78,6 +86,9 @@ esac
|
||||
|
||||
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=""
|
||||
|
||||
#####################################################################
|
||||
@ -164,7 +175,7 @@ case ${target_os} in
|
||||
AC_DEFINE_UNQUOTED(SYS_SUNOS, "1", [operating system])
|
||||
;;
|
||||
|
||||
*bsd*)
|
||||
*bsd*|dragonfly*)
|
||||
AC_DEFINE_UNQUOTED(SYS_BSD, "1", [operating system])
|
||||
;;
|
||||
|
||||
|
@ -11,10 +11,10 @@
|
||||
|
||||
/*
|
||||
* element eth0 {
|
||||
* description = { "My description" }
|
||||
* rxmax = { 10000 }
|
||||
* txmax = { 10000 }
|
||||
* max = { 12500000 }
|
||||
* description = "My description"
|
||||
* rxmax = 10000
|
||||
* txmax = 10000
|
||||
* max = 12500000
|
||||
* }
|
||||
*/
|
||||
|
||||
@ -86,3 +86,27 @@ history day {
|
||||
interval = 86400.
|
||||
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,4 +16,5 @@ noinst_HEADERS = \
|
||||
bmon/module.h \
|
||||
bmon/output.h \
|
||||
bmon/unit.h \
|
||||
bmon/layout.h \
|
||||
bmon/utils.h
|
||||
|
@ -42,6 +42,9 @@ struct rate
|
||||
/* Value of r_current at last read */
|
||||
uint64_t r_prev;
|
||||
|
||||
/* Reset value to substract to emulate statistics reset */
|
||||
uint64_t r_reset;
|
||||
|
||||
/* Rate per second calculated every `rate_interval' */
|
||||
float r_rate;
|
||||
|
||||
@ -49,6 +52,8 @@ struct rate
|
||||
timestamp_t r_last_calc;
|
||||
};
|
||||
|
||||
extern uint64_t rate_get_total(struct rate *);
|
||||
|
||||
enum {
|
||||
ATTR_TYPE_UNSPEC,
|
||||
ATTR_TYPE_COUNTER,
|
||||
@ -134,5 +139,6 @@ extern struct attr * attr_select_prev(void);
|
||||
extern struct attr * attr_current(void);
|
||||
|
||||
extern void attr_start_collecting_history(struct attr *);
|
||||
extern void attr_reset_counter(struct attr *a);
|
||||
|
||||
#endif
|
||||
|
@ -74,6 +74,8 @@ enum {
|
||||
LAYOUT_HEADER,
|
||||
LAYOUT_LIST,
|
||||
LAYOUT_SELECTED,
|
||||
LAYOUT_RX_GRAPH,
|
||||
LAYOUT_TX_GRAPH,
|
||||
__LAYOUT_MAX
|
||||
};
|
||||
|
||||
|
@ -48,7 +48,7 @@
|
||||
#include <dirent.h>
|
||||
#ifdef SYS_BSD
|
||||
# include <float.h>
|
||||
#else
|
||||
#elif !defined(__ANDROID__)
|
||||
# include <values.h>
|
||||
#endif
|
||||
|
||||
|
@ -9,6 +9,9 @@
|
||||
/* Define to 1 if you have the `atexit' function. */
|
||||
#undef HAVE_ATEXIT
|
||||
|
||||
/* Define to 1 if you have the `clock_gettime' function. */
|
||||
#undef HAVE_CLOCK_GETTIME
|
||||
|
||||
/* have curses */
|
||||
#undef HAVE_CURSES
|
||||
|
||||
@ -39,15 +42,15 @@
|
||||
/* Define to 1 if you have the <getopt.h> header file. */
|
||||
#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. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the `m' library (-lm). */
|
||||
#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. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
|
130
include/bmon/layout.h
Normal file
130
include/bmon/layout.h
Normal file
@ -0,0 +1,130 @@
|
||||
|
||||
#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_ */
|
14
man/bmon.8
14
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.
|
||||
.RE
|
||||
.PP
|
||||
\fB \-o\fR, \fB\-\-output\fRMODULE[:OPTIONS][,MODULE...]
|
||||
\fB \-o\fR, \fB\-\-output=\fRMODULE[:OPTIONS][,MODULE...]
|
||||
.RS 4
|
||||
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
|
||||
@ -58,7 +58,7 @@ Set policy defining which network interfaces to display. See
|
||||
INTERFACE SELECTION for more details.
|
||||
.RE
|
||||
.PP
|
||||
\fB \-a\fR, \fB\-\-show\-all=\fR
|
||||
\fB \-a\fR, \fB\-\-show\-all\fR
|
||||
.RS 4
|
||||
Display all interfaces, even interface that are administratively down.
|
||||
.RE
|
||||
@ -137,7 +137,7 @@ The following output modules exist:
|
||||
.TP
|
||||
\fBcurses\fR
|
||||
Interactive curses based text user interface providing real time rate
|
||||
estimations and a graphical representatio nof each attribute. Press '?'
|
||||
estimations and a graphical representation of each attribute. Press '?'
|
||||
to display the quick reference guide. This is the default output mode.
|
||||
|
||||
.TP
|
||||
@ -220,6 +220,14 @@ and eth1:
|
||||
.RS 4
|
||||
\fBbmon \-p eth0,eth1 \-o curses\fP
|
||||
.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"
|
||||
/etc/bmon.conf
|
||||
|
13
src/attr.c
13
src/attr.c
@ -524,6 +524,11 @@ static float __calc_usage(double rate, uint64_t max)
|
||||
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,
|
||||
uint64_t rxmax, uint64_t txmax)
|
||||
{
|
||||
@ -626,6 +631,14 @@ 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)
|
||||
{
|
||||
struct attr_def *ad, *n;
|
||||
|
@ -67,14 +67,14 @@ static char *usage_text =
|
||||
" Examples:\n" \
|
||||
" -o curses:ngraph=2\n" \
|
||||
" -o list # Shows a list of available modules\n" \
|
||||
" -o curses:help # Shows a help text for html module\n" \
|
||||
" -o curses:help # Shows a help text for curses module\n" \
|
||||
"\n" \
|
||||
"Interface selection:\n" \
|
||||
" policy := [!]simple_regexp,[!]simple_regexp,...\n" \
|
||||
"\n" \
|
||||
" Example: -p 'eth*,lo*,!eth1'\n" \
|
||||
"\n" \
|
||||
"Please see the bmon(1) man pages for full documentation.\n";
|
||||
"Please see the bmon(8) man pages for full documentation.\n";
|
||||
|
||||
static void do_shutdown(void)
|
||||
{
|
||||
|
100
src/conf.c
100
src/conf.c
@ -30,6 +30,7 @@
|
||||
#include <bmon/element.h>
|
||||
#include <bmon/element_cfg.h>
|
||||
#include <bmon/history.h>
|
||||
#include <bmon/layout.h>
|
||||
#include <bmon/utils.h>
|
||||
|
||||
cfg_t *cfg;
|
||||
@ -69,6 +70,16 @@ static cfg_opt_t unit_opts[] = {
|
||||
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[] = {
|
||||
CFG_FLOAT("read_interval", 1.0f, CFGF_NONE),
|
||||
CFG_FLOAT("rate_interval", 1.0f, CFGF_NONE),
|
||||
@ -87,6 +98,7 @@ static cfg_opt_t global_opts[] = {
|
||||
CFG_SEC("attr", attr_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("layout", layout_opts, CFGF_MULTI | CFGF_TITLE),
|
||||
CFG_END()
|
||||
};
|
||||
|
||||
@ -103,22 +115,26 @@ static char * configfile = NULL;
|
||||
#if defined HAVE_USE_DEFAULT_COLORS
|
||||
struct layout cfg_layout[] =
|
||||
{
|
||||
{-1, -1, 0}, /* dummy, not used */
|
||||
{-1, -1, 0}, /* default */
|
||||
{-1, -1, A_REVERSE}, /* statusbar */
|
||||
{-1, -1, 0}, /* header */
|
||||
{-1, -1, 0}, /* list */
|
||||
{-1, -1, A_REVERSE}, /* selected */
|
||||
{-1, -1, 0}, /* dummy, not used */
|
||||
{-1, -1, 0}, /* default */
|
||||
{-1, -1, A_REVERSE}, /* statusbar */
|
||||
{-1, -1, 0}, /* header */
|
||||
{-1, -1, 0}, /* list */
|
||||
{-1, -1, A_REVERSE}, /* selected */
|
||||
{-1, -1, 0}, /* RX graph */
|
||||
{-1, -1, 0}, /* TX graph */
|
||||
};
|
||||
#else
|
||||
struct layout cfg_layout[] =
|
||||
{
|
||||
{0, 0, 0}, /* dummy, not used */
|
||||
{COLOR_BLACK, COLOR_WHITE, 0}, /* default */
|
||||
{COLOR_BLACK, COLOR_WHITE, A_REVERSE}, /* statusbar */
|
||||
{COLOR_BLACK, COLOR_WHITE, 0}, /* header */
|
||||
{COLOR_BLACK, COLOR_WHITE, 0}, /* list */
|
||||
{COLOR_BLACK, COLOR_WHITE, A_REVERSE}, /* selected */
|
||||
{0, 0, 0}, /* dummy, not used */
|
||||
{COLOR_WHITE, COLOR_BLACK, 0}, /* default */
|
||||
{COLOR_BLUE, COLOR_GREEN, A_REVERSE}, /* statusbar */
|
||||
{COLOR_GREEN, COLOR_BLACK, 0}, /* header */
|
||||
{COLOR_WHITE, COLOR_BLACK, 0}, /* list */
|
||||
{COLOR_YELLOW, COLOR_BLACK, A_REVERSE}, /* selected */
|
||||
{COLOR_GREEN, COLOR_BLACK, 0}, /* RX graph */
|
||||
{COLOR_RED, COLOR_BLACK, 0}, /* TX graph */
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
@ -423,6 +439,41 @@ 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)
|
||||
{
|
||||
int err;
|
||||
@ -450,6 +501,7 @@ static void conf_read(const char *path, int must)
|
||||
configfile_read_history();
|
||||
configfile_read_attrs();
|
||||
configfile_read_element_cfg();
|
||||
configfile_read_layout_cfg();
|
||||
}
|
||||
|
||||
static const char default_config[] = \
|
||||
@ -508,6 +560,29 @@ static const char default_config[] = \
|
||||
"history day {" \
|
||||
" interval = 86400.0" \
|
||||
" 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)
|
||||
@ -524,6 +599,7 @@ static void conf_read_default(void)
|
||||
configfile_read_history();
|
||||
configfile_read_attrs();
|
||||
configfile_read_element_cfg();
|
||||
configfile_read_layout_cfg();
|
||||
}
|
||||
|
||||
void configfile_read(void)
|
||||
|
@ -201,12 +201,6 @@ void element_free(struct element *e)
|
||||
struct attr *a, *an;
|
||||
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)
|
||||
element_free(c);
|
||||
|
||||
@ -221,6 +215,12 @@ void element_free(struct element *e)
|
||||
list_for_each_entry_safe(a, an, &e->e_attrhash[i], a_list)
|
||||
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);
|
||||
e->e_group->g_nelements--;
|
||||
|
||||
@ -358,6 +358,26 @@ int element_set_usage_attr(struct element *e, const char *usage)
|
||||
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_group *g;
|
||||
@ -365,8 +385,12 @@ struct element *element_current(void)
|
||||
if (!(g = group_current()))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* If no element is picked yet, pick a default interface according to
|
||||
* the selection policy.
|
||||
*/
|
||||
if (!g->g_current)
|
||||
element_select_first();
|
||||
element_pick_from_policy(g);
|
||||
|
||||
return g->g_current;
|
||||
}
|
||||
|
@ -261,7 +261,7 @@ static void __init group_init(void)
|
||||
{
|
||||
DBG("init");
|
||||
|
||||
group_new_hdr("intf", "Interfaces",
|
||||
group_new_hdr(DEFAULT_GROUP, "Interfaces",
|
||||
"RX bps", "pps", "TX bps", "pps");
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,11 @@ static void dummy_read(void)
|
||||
char gname[32];
|
||||
struct element_group *group;
|
||||
|
||||
snprintf(gname, sizeof(gname), "group%02d", gidx);
|
||||
if (gidx == 0)
|
||||
snprintf(gname, sizeof(gname), "%s", DEFAULT_GROUP);
|
||||
else
|
||||
snprintf(gname, sizeof(gname), "group%02d", gidx);
|
||||
|
||||
group = group_lookup(gname, GROUP_CREATE);
|
||||
|
||||
for (n = 0; n < c_numdev; n++) {
|
||||
|
@ -60,6 +60,11 @@ static struct bmon_module netlink_ops;
|
||||
# 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[] = {
|
||||
{
|
||||
.name = "bytes",
|
||||
@ -101,6 +106,14 @@ static struct attr_map link_attrs[] = {
|
||||
.rxid = RTNL_LINK_RX_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",
|
||||
.type = ATTR_TYPE_COUNTER,
|
||||
|
@ -226,17 +226,19 @@ sysctl_read(void)
|
||||
attr_update(e, m->attrid, rx, tx, flags);
|
||||
}
|
||||
|
||||
snprintf(info_buf, sizeof(info_buf), "%u", ifm->ifm_data.ifi_mtu);
|
||||
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), "%u", ifm->ifm_data.ifi_metric);
|
||||
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_lifesign(e, 1);
|
||||
|
@ -101,10 +101,10 @@ static void print_attr_detail(struct element *e, struct attr *a, void *arg)
|
||||
char *rx_u, *tx_u;
|
||||
int rxprec, txprec;
|
||||
|
||||
double rx = unit_value2str(a->a_rx_rate.r_total,
|
||||
double rx = unit_value2str(rate_get_total(&a->a_rx_rate),
|
||||
a->a_def->ad_unit,
|
||||
&rx_u, &rxprec);
|
||||
double tx = unit_value2str(a->a_tx_rate.r_total,
|
||||
double tx = unit_value2str(rate_get_total(&a->a_tx_rate),
|
||||
a->a_def->ad_unit,
|
||||
&tx_u, &txprec);
|
||||
|
||||
@ -212,6 +212,7 @@ static void ascii_draw_group(struct element_group *g, void *arg)
|
||||
static void ascii_draw(void)
|
||||
{
|
||||
group_foreach(ascii_draw_group, NULL);
|
||||
fflush(stdout);
|
||||
|
||||
if (c_quit_after > 0)
|
||||
if (--c_quit_after == 0)
|
||||
|
@ -45,6 +45,8 @@ enum {
|
||||
KEY_TOGGLE_DETAILS = 'd',
|
||||
KEY_TOGGLE_INFO = 'i',
|
||||
KEY_COLLECT_HISTORY = 'h',
|
||||
KEY_CTRL_N = 14,
|
||||
KEY_CTRL_P = 16,
|
||||
};
|
||||
|
||||
#define DETAILS_COLS 40
|
||||
@ -147,22 +149,24 @@ static char *float2str(double value, int width, int prec, char *buf, size_t len)
|
||||
static void put_line(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char buf[2048];
|
||||
char *buf;
|
||||
int len;
|
||||
int x, y __unused__;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
getyx(stdscr, y, x);
|
||||
|
||||
len = cols - x;
|
||||
buf = xcalloc(len+1, 1);
|
||||
|
||||
va_start(args, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
vsnprintf(buf, len+1, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if (strlen(buf) > cols-x)
|
||||
buf[cols - x] = '\0';
|
||||
else
|
||||
memset(&buf[strlen(buf)], ' ', cols - strlen(buf)-x);
|
||||
if (strlen(buf) < len)
|
||||
memset(&buf[strlen(buf)], ' ', len - strlen(buf));
|
||||
|
||||
addstr(buf);
|
||||
xfree(buf);
|
||||
}
|
||||
|
||||
static void center_text(const char *fmt, ...)
|
||||
@ -241,10 +245,10 @@ static void draw_attr_detail(struct element *e, struct attr *a, void *arg)
|
||||
int rxprec, txprec, ncol;
|
||||
struct detail_arg *da = arg;
|
||||
|
||||
double rx = unit_value2str(a->a_rx_rate.r_total,
|
||||
double rx = unit_value2str(rate_get_total(&a->a_rx_rate),
|
||||
a->a_def->ad_unit,
|
||||
&rx_u, &rxprec);
|
||||
double tx = unit_value2str(a->a_tx_rate.r_total,
|
||||
double tx = unit_value2str(rate_get_total(&a->a_tx_rate),
|
||||
a->a_def->ad_unit,
|
||||
&tx_u, &txprec);
|
||||
|
||||
@ -258,7 +262,7 @@ static void draw_attr_detail(struct element *e, struct attr *a, void *arg)
|
||||
if (ncol > 0)
|
||||
addch(ACS_VLINE);
|
||||
|
||||
put_line(" %-14.14s %8s%-3s %8s%-3s\n",
|
||||
put_line(" %-14.14s %8s%-3s %8s%-3s",
|
||||
a->a_def->ad_description,
|
||||
(a->a_flags & ATTR_RX_ENABLED) ?
|
||||
float2str(rx, 8, rxprec, buf1, sizeof(buf1)) : "-", rx_u,
|
||||
@ -392,6 +396,7 @@ static void draw_help(void)
|
||||
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+17, x+3, "<, > Change number of graphs", -1);
|
||||
mvaddnstr(y+18, x+3, "r Reset counter of element", -1);
|
||||
|
||||
attroff(A_STANDOUT);
|
||||
|
||||
@ -419,6 +424,7 @@ static void draw_header(void)
|
||||
move(row, COLS - strlen(PACKAGE_STRING) - 1);
|
||||
put_line("%s", PACKAGE_STRING);
|
||||
move(row, 0);
|
||||
apply_layout(LAYOUT_LIST);
|
||||
}
|
||||
|
||||
static int lines_required_for_statusbar(void)
|
||||
@ -631,6 +637,7 @@ static void draw_element(struct element_group *g, struct element *e,
|
||||
|
||||
static void draw_group(struct element_group *g, void *arg)
|
||||
{
|
||||
apply_layout(LAYOUT_HEADER);
|
||||
int *line = arg;
|
||||
|
||||
if (line_visible(*line)) {
|
||||
@ -683,7 +690,7 @@ static void draw_graph_centered(struct graph *g, int row, int ncol,
|
||||
|
||||
static void draw_table(struct graph *g, struct graph_table *tbl,
|
||||
struct attr *a, struct history *h,
|
||||
const char *hdr, int ncol)
|
||||
const char *hdr, int ncol, int layout)
|
||||
{
|
||||
int i, save_row;
|
||||
char buf[32];
|
||||
@ -708,11 +715,14 @@ static void draw_table(struct graph *g, struct graph_table *tbl,
|
||||
//move(row, ncol + g->g_cfg.gc_width - 3);
|
||||
//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--) {
|
||||
move(++row, ncol);
|
||||
put_line("%'8.2f %s",
|
||||
tbl->gt_scale[i],
|
||||
tbl->gt_table + (i * graph_row_size(&g->g_cfg)));
|
||||
sprintf(buf, "%'8.2f ", tbl->gt_scale[i]);
|
||||
addstr(buf);
|
||||
apply_layout(layout);
|
||||
put_line("%s", tbl->gt_table + (i * graph_row_size(&g->g_cfg)));
|
||||
apply_layout(LAYOUT_LIST);
|
||||
}
|
||||
|
||||
move(++row, ncol);
|
||||
@ -746,14 +756,14 @@ static void draw_history_graph(struct attr *a, struct history *h)
|
||||
graph_refill(g, h);
|
||||
|
||||
save_row = row;
|
||||
draw_table(g, &g->g_rx, a, h, "RX", ncol);
|
||||
draw_table(g, &g->g_rx, a, h, "RX", ncol, LAYOUT_RX_GRAPH);
|
||||
|
||||
if (graph_display == GRAPH_DISPLAY_SIDE_BY_SIDE) {
|
||||
ncol = cols / 2;
|
||||
row = save_row;
|
||||
}
|
||||
|
||||
draw_table(g, &g->g_tx, a, h, "TX", ncol);
|
||||
draw_table(g, &g->g_tx, a, h, "TX", ncol, LAYOUT_TX_GRAPH);
|
||||
|
||||
graph_free(g);
|
||||
}
|
||||
@ -973,8 +983,10 @@ draw:
|
||||
*/
|
||||
NEXT_ROW();
|
||||
hline(ACS_HLINE, cols);
|
||||
mvaddch(row, LIST_COL_1, ACS_BTEE);
|
||||
mvaddch(row, LIST_COL_2, ACS_BTEE);
|
||||
if (c_show_list) {
|
||||
mvaddch(row, LIST_COL_1, ACS_BTEE);
|
||||
mvaddch(row, LIST_COL_2, ACS_BTEE);
|
||||
}
|
||||
|
||||
if (!c_show_graph)
|
||||
center_text(" Press %c to enable graphical statistics ",
|
||||
@ -1016,6 +1028,12 @@ draw:
|
||||
NEXT_ROW();
|
||||
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)
|
||||
center_text(" Press %c to enable additional information ",
|
||||
KEY_TOGGLE_INFO);
|
||||
@ -1079,6 +1097,16 @@ out:
|
||||
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)
|
||||
{
|
||||
switch (ch)
|
||||
@ -1160,10 +1188,12 @@ static int handle_input(int ch)
|
||||
return 1;
|
||||
|
||||
case KEY_DOWN:
|
||||
case KEY_CTRL_N:
|
||||
element_select_next();
|
||||
return 1;
|
||||
|
||||
case KEY_UP:
|
||||
case KEY_CTRL_P:
|
||||
element_select_prev();
|
||||
return 1;
|
||||
|
||||
@ -1198,6 +1228,10 @@ static int handle_input(int ch)
|
||||
case '\t':
|
||||
history_select_next();
|
||||
return 1;
|
||||
|
||||
case 'r':
|
||||
reset_counters();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1232,7 +1266,7 @@ static void print_module_help(void)
|
||||
" Author: Thomas Graf <tgraf@suug.ch>\n" \
|
||||
"\n" \
|
||||
" Options:\n" \
|
||||
" fgchar=CHAR Foreground character (default: '*')\n" \
|
||||
" fgchar=CHAR Foreground character (default: '|')\n" \
|
||||
" bgchar=CHAR Background character (default: '.')\n" \
|
||||
" nchar=CHAR Noise character (default: ':')\n" \
|
||||
" uchar=CHAR Unknown character (default: '?')\n" \
|
||||
@ -1242,6 +1276,7 @@ static void print_module_help(void)
|
||||
" nocolors Do not use colors\n" \
|
||||
" graph Show graphical 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");
|
||||
}
|
||||
|
||||
@ -1264,6 +1299,8 @@ static void curses_parse_opt(const char *type, const char *value)
|
||||
c_show_graph = !!c_ngraph;
|
||||
} else if (!strcasecmp(type, "details"))
|
||||
c_show_details = 1;
|
||||
else if (!strcasecmp(type, "info"))
|
||||
c_show_info = 1;
|
||||
else if (!strcasecmp(type, "nocolors"))
|
||||
c_use_colors = 0;
|
||||
else if (!strcasecmp(type, "minlist") && value)
|
||||
|
@ -123,17 +123,18 @@ static char *get_token(struct element_group *g, struct element *e,
|
||||
goto out;
|
||||
|
||||
if (!strncasecmp(type, "rx:", 3)) {
|
||||
snprintf(buf, len, "%" PRIu64, a->a_rx_rate.r_total);
|
||||
snprintf(buf, len, "%" PRIu64, rate_get_total(&a->a_rx_rate));
|
||||
return buf;
|
||||
} else if (!strncasecmp(type, "tx:", 3)) {
|
||||
snprintf(buf, len, "%" PRIu64, a->a_tx_rate.r_total);
|
||||
snprintf(buf, len, "%" PRIu64, rate_get_total(&a->a_tx_rate));
|
||||
return buf;
|
||||
} else if (!strncasecmp(type, "rxrate:", 7)) {
|
||||
snprintf(buf, len, "%.2f", a->a_rx_rate.r_rate);
|
||||
return buf;
|
||||
} else if (!strncasecmp(token+5, "txrate:", 7))
|
||||
} else if (!strncasecmp(type, "txrate:", 7)) {
|
||||
snprintf(buf, len, "%.2f", a->a_tx_rate.r_rate);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "Unknown field \"%s\"\n", token);
|
||||
@ -165,6 +166,7 @@ static void draw_element(struct element_group *g, struct element *e, void *arg)
|
||||
static void format_draw(void)
|
||||
{
|
||||
group_foreach_recursive(draw_element, NULL);
|
||||
fflush(stdout);
|
||||
|
||||
if (c_quit_after > 0)
|
||||
if (--c_quit_after == 0)
|
||||
@ -319,15 +321,15 @@ static void print_help(void)
|
||||
" Supported Escape Sequences: \\n, \\t, \\r, \\v, \\b, \\f, \\a\n" \
|
||||
"\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" \
|
||||
"\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" \
|
||||
"\n" \
|
||||
" \"Item: $(element:name)\\n\" \\\n" \
|
||||
" \"Bytes Rate: $(attr:rxrate:bytes)/$(attr:txrate:bytes)\\n\" \\\n" \
|
||||
" \"Packets Rate: $(attr:rxrate:packets)/$(attr:txrate:packets)\\n\"\n" \
|
||||
" 'Item: $(element:name)\\nBytes Rate: $(attr:rxrate:bytes)/" \
|
||||
"$(attr:txrate:bytes)\\nPackets Rate: $(attr:rxrate:packets)/" \
|
||||
"$(attr:txrate:packets)\\n'\n" \
|
||||
" Item: eth0\n" \
|
||||
" Bytes Rate: 49130/2119\n" \
|
||||
" Packets Rate: 40/11\n" \
|
||||
|
22
src/utils.c
22
src/utils.c
@ -27,6 +27,11 @@
|
||||
#include <bmon/conf.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 *d = calloc(n, s);
|
||||
@ -112,12 +117,21 @@ int timestamp_is_negative(timestamp_t *ts)
|
||||
|
||||
void update_timestamp(timestamp_t *dst)
|
||||
{
|
||||
struct timeval tv;
|
||||
#ifdef __MACH__
|
||||
clock_serv_t cclock;
|
||||
mach_timespec_t tp;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
|
||||
clock_get_time(cclock, &tp);
|
||||
mach_port_deallocate(mach_task_self(), cclock);
|
||||
#else
|
||||
struct timespec tp;
|
||||
|
||||
dst->tv_sec = tv.tv_sec;
|
||||
dst->tv_usec = tv.tv_usec;
|
||||
clock_gettime(CLOCK_MONOTONIC, &tp);
|
||||
#endif
|
||||
|
||||
dst->tv_sec = tp.tv_sec;
|
||||
dst->tv_usec = tp.tv_nsec / 1000;
|
||||
}
|
||||
|
||||
void copy_timestamp(timestamp_t *ts1, timestamp_t *ts2)
|
||||
|
Loading…
x
Reference in New Issue
Block a user