├── .gitignore ├── .travis.yml ├── .travis └── run.sh ├── ChangeLog ├── LICENSE.BSD ├── LICENSE.MIT ├── Makefile.am ├── NEWS ├── README.md ├── autogen.sh ├── configure.ac ├── examples ├── Makefile.am └── bmon.conf ├── include ├── Makefile.am └── bmon │ ├── .gitignore │ ├── attr.h │ ├── bmon.h │ ├── compile-fixes.h │ ├── conf.h │ ├── config.h │ ├── defs.h.in │ ├── element.h │ ├── element_cfg.h │ ├── graph.h │ ├── group.h │ ├── history.h │ ├── info.h │ ├── input.h │ ├── layout.h │ ├── list.h │ ├── module.h │ ├── output.h │ ├── unit.h │ └── utils.h ├── m4 └── ax_with_curses.m4 ├── man ├── Makefile.am └── bmon.8 └── src ├── .gitignore ├── Makefile.am ├── attr.c ├── bmon.c ├── conf.c ├── element.c ├── element_cfg.c ├── graph.c ├── group.c ├── history.c ├── in_dummy.c ├── in_netlink.c ├── in_null.c ├── in_proc.c ├── in_sysctl.c ├── input.c ├── module.c ├── out_ascii.c ├── out_curses.c ├── out_format.c ├── out_null.c ├── output.c ├── unit.c └── utils.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.a 3 | *.so 4 | *.so.* 5 | *.swp 6 | .deps 7 | Makefile.in 8 | Makefile 9 | /autom4te.cache 10 | /cscope.* 11 | /build-aux/ 12 | /aclocal.m4 13 | /configure 14 | /config.* 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | 3 | os: 4 | - linux 5 | - osx 6 | 7 | env: 8 | global: 9 | - secure: "C87Pgf5AVDoyQfm9MIv81g" 10 | 11 | compiler: 12 | - gcc 13 | - clang 14 | 15 | # container-based builds 16 | sudo: false 17 | addons: 18 | apt: 19 | packages: 20 | # packages list: https://github.com/travis-ci/apt-package-whitelist/blob/master/ubuntu-precise 21 | - libconfuse-dev 22 | - libncurses5-dev 23 | - libnl-3-dev 24 | - libnl-route-3-dev 25 | coverity_scan: 26 | project: 27 | name: "tgraf/bmon" 28 | description: "bandwidth monitor" 29 | notification_email: tgraf@suug.ch 30 | build_command_prepend: "./autogen.sh && ./configure" 31 | build_command: "make -j2" 32 | branch_pattern: coverity_scan 33 | 34 | 35 | install: 36 | - if [ "$TRAVIS_BRANCH" = "coverity_scan" ] && ! [ "$TRAVIS_OS_NAME" = "linux" -a "$CC" = "gcc" ]; then exit ; fi 37 | - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update > /dev/null && brew install confuse ; fi 38 | 39 | script: 40 | - ./.travis/run.sh 41 | -------------------------------------------------------------------------------- /.travis/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | FLAGS="-Werror" 4 | 5 | if [ $CC = "clang" ]; then 6 | FLAGS="$FLAGS -Wno-error=unused-command-line-argument" 7 | fi 8 | 9 | ./autogen.sh && ./configure && make CFLAGS="$FLAGS" && make distcheck 10 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tgraf/bmon/def45f59a830cd1c07f2cd0a56f7262e18f3a8a8/ChangeLog -------------------------------------------------------------------------------- /LICENSE.BSD: -------------------------------------------------------------------------------- 1 | Redistribution and use in source and binary forms, with or without 2 | modification, are permitted provided that the following conditions 3 | are met: 4 | 5 | 1. Redistributions of source code must retain the above copyright 6 | notice, this list of conditions and the following disclaimer. 7 | 2. Redistributions in binary form must reproduce the above copyright 8 | notice, this list of conditions and the following disclaimer in the 9 | documentation and/or other materials provided with the distribution. 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 12 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 13 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 14 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 15 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 16 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 17 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 18 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 19 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 20 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 21 | -------------------------------------------------------------------------------- /LICENSE.MIT: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any person 2 | obtaining a copy of this software and associated documentation files 3 | (the "Software"), to deal in the Software without restriction, 4 | including without limitation the rights to use, copy, modify, merge, 5 | publish, distribute, sublicense, and/or sell copies of the Software, 6 | and to permit persons to whom the Software is furnished to do so, 7 | subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be 10 | included in all copies or substantial portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 13 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 14 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 15 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 16 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 17 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | # -*- Makefile -*- 2 | 3 | ACLOCAL_AMFLAGS = -I m4 4 | 5 | SUBDIRS = src man include examples 6 | 7 | EXTRA_DIST = ChangeLog LICENSE.BSD LICENSE.MIT NEWS README.md 8 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | HEAD 2 | 3 | v4.0 - Dec 13, 2016 4 | * Use monotonic clock instead of realtime clock 5 | * Pick default selected interface based on policy 6 | * Collect RX NoHandler statistics if available (Linux) 7 | * CentOS installation instructions 8 | * Proper stdout flush in ASCII mode 9 | * Bugfixes 10 | 11 | v3.9 - Jul 19, 2016 12 | * Color support 13 | * Add ability to reset statistics from curses UI 14 | * NetBSD compile fix 15 | * Option to enable info display by default 16 | * Additional IPv6 statistics 17 | * Various fixes 18 | 19 | v3.8 - July 25, 2015 20 | * Don't disable Netlink if TC stats are unavailable 21 | 22 | v3.7 - November 22, 2014 23 | * Bugfixes 24 | * Documentation updates 25 | * Provide minimal interface information on BSD 26 | 27 | v3.6 - November 22, 2014 28 | * Build fix for uclinux 29 | * Fix LICENSE links 30 | 31 | v3.5 - August 30, 2014 32 | * Fixes for all defects identified by coverity 33 | * Fix accuracy issue on total rate calculation 34 | * Travis-CI support 35 | * Various other small bugfixes 36 | 37 | v3.4 - August 24, 2014 38 | * Bugfixes 39 | * blank screen with config file 40 | * quick-help toggle with '?' in curses 41 | * Better bmon.conf example 42 | 43 | v3.3 - July 6, 2014 44 | * MacOS X port 45 | * Only initialize curses module if actually used 46 | * Assorted bug and spelling fixes 47 | * Various build fixes 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bmon - Bandwidth Monitor 2 | 3 | [![Build Status](https://travis-ci.org/tgraf/bmon.svg?branch=master)](https://travis-ci.org/tgraf/bmon) 4 | [![Coverity Status](https://scan.coverity.com/projects/2864/badge.svg)](https://scan.coverity.com/projects/2864) 5 | 6 | bmon is a monitoring and debugging tool to capture networking related 7 | statistics and prepare them visually in a human friendly way. It 8 | features various output methods including an interactive curses user 9 | interface and a programmable text output for scripting. 10 | 11 | ## Download 12 | 13 | * [Latest Release](https://github.com/tgraf/bmon/releases/latest) 14 | * [Older Releases](https://github.com/tgraf/bmon/releases) 15 | 16 | ## Debian/Ubuntu Installation 17 | 18 | ``` 19 | git clone https://github.com/tgraf/bmon.git 20 | cd bmon 21 | apt-get install build-essential make libconfuse-dev libnl-3-dev libnl-route-3-dev libncurses-dev pkg-config dh-autoreconf 22 | ./autogen.sh 23 | ./configure 24 | make 25 | make install 26 | bmon 27 | ``` 28 | ## CentOS 6 Installation 29 | 30 | ``` 31 | git clone https://github.com/tgraf/bmon.git 32 | cd bmon 33 | yum install make libconfuse-devel libnl3-devel libnl-route3-devel ncurses-devel 34 | ./autogen.sh 35 | ./configure 36 | make 37 | make install 38 | bmon 39 | ``` 40 | 41 | ## CentOS 7 Installation 42 | 43 | ``` 44 | yum install bmon 45 | ``` 46 | 47 | ## Fedora Installation 48 | 49 | ``` 50 | dnf install bmon 51 | ``` 52 | 53 | ## OSX Installation 54 | 55 | ### Brew 56 | ``` 57 | brew install bmon 58 | ``` 59 | 60 | ### Compile yourself 61 | Install libconfuse 62 | ``` 63 | wget https://github.com/martinh/libconfuse/releases/download/v2.8/confuse-2.8.zip 64 | unzip confuse-2.8.zip && cd confuse-2.8 65 | PATH=/usr/local/opt/gettext/bin:$PATH ./configure 66 | make 67 | make install 68 | ``` 69 | 70 | Install bmon 71 | ``` 72 | git clone https://github.com/tgraf/bmon.git 73 | cd bmon 74 | ./autogen.sh 75 | ./configure 76 | make 77 | make install 78 | bmon 79 | ``` 80 | 81 | ------------- 82 | ## New in 4.0 83 | * Use monotonic clock instead of realtime clock 84 | * Pick default selected interface based on policy 85 | * Collect RX NoHandler statistics if available (Linux) 86 | * CentOS installation instructions 87 | * Proper stdout flush in ASCII mode 88 | * Bugfixes 89 | 90 | ------------- 91 | ### Usage 92 | 93 | To run bmon in the default curses mode: 94 | 95 | > bmon 96 | 97 | There are many other options available and full help is 98 | provided via: 99 | 100 | > bmon --help 101 | 102 | ## Screenshots 103 | 104 | ![Screenshot 1](https://github.com/tgraf/bmon/raw/gh-pages/images/shot3.png) 105 | ![Screenshot 2](https://github.com/tgraf/bmon/raw/gh-pages/images/shot1.png) 106 | ![Screenshot 3](https://github.com/tgraf/bmon/raw/gh-pages/images/shot2.png) 107 | 108 | ## Copyright 109 | 110 | Various authors, see git commit log. 111 | 112 | > *Copyright (c) 2001-2016 Thomas Graf * 113 | > *Copyright (c) 2013 Red Hat, Inc.* 114 | 115 | Please see the [LICENSE.BSD](https://github.com/tgraf/bmon/blob/master/LICENSE.BSD) 116 | and [LICENSE.MIT](https://github.com/tgraf/bmon/blob/master/LICENSE.MIT) files for 117 | additional details. 118 | 119 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | autoreconf -fi; 4 | rm -Rf autom4te.cache; 5 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # 2 | # configure.in Configure Script 3 | # 4 | # Copyright (c) 2001-2016 Thomas Graf 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a 7 | # copy of this software and associated documentation files (the "Software"), 8 | # to deal in the Software without restriction, including without limitation 9 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | # and/or sell copies of the Software, and to permit persons to whom the 11 | # Software is furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included 14 | # in all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 | # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | # DEALINGS IN THE SOFTWARE. 23 | 24 | AC_INIT(bmon, 4.0, [], [], [https://github.com/tgraf/bmon]) 25 | AC_CONFIG_HEADERS(include/bmon/defs.h) 26 | AC_CONFIG_AUX_DIR([build-aux]) 27 | AC_CONFIG_MACRO_DIR([m4]) 28 | 29 | AC_CANONICAL_TARGET 30 | AC_CANONICAL_SYSTEM 31 | 32 | AM_INIT_AUTOMAKE([-Wall foreign subdir-objects]) 33 | m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES(yes)], []) 34 | 35 | AC_ISC_POSIX 36 | AC_PROG_CC 37 | AC_PROG_CC_STDC 38 | AC_PROG_CPP 39 | AC_PROG_MAKE_SET 40 | AC_PROG_INSTALL 41 | 42 | AC_C_CONST 43 | AC_C_INLINE 44 | 45 | AC_HEADER_TIME 46 | AC_HEADER_DIRENT 47 | 48 | AC_TYPE_SIZE_T 49 | AC_TYPE_SIGNAL 50 | AC_TYPE_PID_T 51 | 52 | AC_FUNC_FORK 53 | 54 | AC_CHECK_HEADERS(getopt.h ncurses/ncurses.h ncurses.h curses.h) 55 | AC_CHECK_HEADERS(dirent.h sys/utsname.h sys/sockio.h netinet6/in6.h) 56 | AC_CHECK_HEADERS(fcntl.h netdb.h netinet/in.h sysctl/ioctl.h) 57 | AC_CHECK_HEADERS(sys/param.h sys/socket.h) 58 | 59 | AC_CHECK_TYPES(suseconds_t) 60 | 61 | AC_CHECK_FUNCS(atexit clock_gettime memset pow socket strcasecmp) 62 | AC_CHECK_FUNCS(strchr strdup strerror strncasecmp strstr strtol) 63 | AC_CHECK_FUNCS(uname getdate) 64 | 65 | AC_PATH_PROG([PKG_CONFIG], [pkg-config], [no]) 66 | AS_IF([test "x$PKG_CONFIG" = "xno"],[ 67 | AC_MSG_ERROR([ 68 | *** The pkg-config script could not be found. Make sure it is 69 | *** in your path, or set the PKG_CONFIG environment variable 70 | *** to the full path to pkg-config.]) 71 | ]) 72 | 73 | AX_WITH_CURSES 74 | if test "x$ax_cv_curses" != xyes || test "x$ax_cv_curses_color" != xyes; then 75 | AC_MSG_ERROR([requires an X/Open-compatible Curses library with color]) 76 | fi 77 | 78 | PKG_CHECK_MODULES([CONFUSE], [libconfuse], [], AC_MSG_ERROR([requires libconfuse])) 79 | 80 | case ${target_os} in 81 | linux*|uclinux*) 82 | PKG_CHECK_MODULES([LIBNL], [libnl-3.0], [], AC_MSG_ERROR([requires libnl3-dev])) 83 | PKG_CHECK_MODULES([LIBNL_ROUTE], [libnl-route-3.0], [], AC_MSG_ERROR([requires libnl3-route])) 84 | ;; 85 | esac 86 | 87 | AC_CHECK_LIB(m, pow, [], AC_MSG_ERROR([requires libm])) 88 | 89 | # Don't fail if not found (for instance, OS X does not have clock_gettime) 90 | AC_CHECK_LIB(rt, clock_gettime, [], []) 91 | 92 | BMON_LIB="" 93 | 94 | ##################################################################### 95 | ## 96 | ## libcurses check 97 | ## 98 | ##################################################################### 99 | CURSES="No " 100 | AC_CHECK_LIB(ncurses, initscr, [ 101 | AC_DEFINE_UNQUOTED(HAVE_NCURSES, "1", [have ncurses]) 102 | LCURSES="ncurses" 103 | CURSES="Yes" 104 | ],[ 105 | AC_CHECK_LIB(curses,initscr, [ 106 | AC_DEFINE_UNQUOTED(HAVE_CURSES, "1", [have curses]) 107 | LCURSES="curses" 108 | CURSES="Yes" 109 | ],[ 110 | echo 111 | echo "*** Warning: Building bmon w/o curses support ***" 112 | echo 113 | ]) 114 | ]) 115 | 116 | LIBCURSES="-l$LCURSES" 117 | 118 | AC_CHECK_LIB($LCURSES, redrawwin, [ 119 | AC_DEFINE_UNQUOTED(HAVE_REDRAWWIN, "1", [have redrawwin]) 120 | ]) 121 | 122 | AC_CHECK_LIB($LCURSES, use_default_colors, [ 123 | AC_DEFINE_UNQUOTED(HAVE_USE_DEFAULT_COLORS, "1", [have udc]) 124 | ]) 125 | 126 | ##################################################################### 127 | ## 128 | ## interface counter overflow workaround 129 | ## 130 | ##################################################################### 131 | AC_ARG_ENABLE(cnt-workaround, 132 | [ --disable-cnt-workaround Disables interface counter overflow workaround],[ 133 | if test x$enableval = xno; then 134 | AC_DEFINE_UNQUOTED(DISABLE_OVERFLOW_WORKAROUND,"1",[no overflow workaround]) 135 | fi 136 | ]) 137 | 138 | ##################################################################### 139 | ## 140 | ## curses 141 | ## 142 | ##################################################################### 143 | AC_ARG_ENABLE(curses, 144 | [ --disable-curses Disables curses output],[ 145 | if test x$enableval = xno; then 146 | CURSES="No " 147 | fi 148 | ]) 149 | 150 | ##################################################################### 151 | ## 152 | ## debug check 153 | ## 154 | ##################################################################### 155 | DEBUG=0 156 | AC_ARG_ENABLE(debug, 157 | [ --enable-debug Enable debug mode (default disabled)],[ 158 | if test x$enableval = xyes; then 159 | AC_DEFINE_UNQUOTED(DEBUG, "1", [enable debugging]) 160 | DEBUG=1; 161 | fi 162 | ]) 163 | 164 | ##################################################################### 165 | ## 166 | ## target os eval 167 | ## 168 | ##################################################################### 169 | case ${target_os} in 170 | linux*) 171 | AC_DEFINE_UNQUOTED(SYS_LINUX, "1", [operating system]) 172 | ;; 173 | 174 | *solaris*) 175 | AC_DEFINE_UNQUOTED(SYS_SUNOS, "1", [operating system]) 176 | ;; 177 | 178 | *bsd*|dragonfly*) 179 | AC_DEFINE_UNQUOTED(SYS_BSD, "1", [operating system]) 180 | ;; 181 | 182 | *darwin*) 183 | AC_DEFINE_UNQUOTED(SYS_BSD, "1", [operating system]) 184 | ;; 185 | 186 | *) 187 | AC_DEFINE_UNQUOTED(SYS_OTHER, "1", [operating system]) 188 | ;; 189 | esac 190 | 191 | ##################################################################### 192 | ## 193 | ## export variables 194 | ## 195 | ##################################################################### 196 | AC_SUBST(DEBUG) 197 | AC_SUBST(STATIC) 198 | AC_SUBST(SYS) 199 | AC_SUBST(ARCH) 200 | 201 | AC_SUBST(CURSES) 202 | 203 | AC_CONFIG_FILES([ 204 | Makefile 205 | include/Makefile 206 | src/Makefile 207 | man/Makefile 208 | examples/Makefile 209 | ]) 210 | 211 | AC_OUTPUT 212 | -------------------------------------------------------------------------------- /examples/Makefile.am: -------------------------------------------------------------------------------- 1 | # -*- Makefile -*- 2 | 3 | exampledir = $(datarootdir)/doc/@PACKAGE@/examples 4 | example_DATA = bmon.conf 5 | 6 | EXTRA_DIST = $(example_DATA) 7 | -------------------------------------------------------------------------------- /examples/bmon.conf: -------------------------------------------------------------------------------- 1 | /* 2 | * read_interval = 1.0 3 | * rate_interval = 1.0 4 | * variance = 0.1 5 | * history_variance = 0.1 6 | * sleep_time = 20000 7 | * lifetime = 30.0 8 | * show_all = true 9 | * policy = "" 10 | */ 11 | 12 | /* 13 | * element eth0 { 14 | * description = "My description" 15 | * rxmax = 10000 16 | * txmax = 10000 17 | * max = 12500000 18 | * } 19 | */ 20 | 21 | /* 22 | * Default configuration 23 | * 24 | * The following definitions is what is compiled into bmon and used 25 | * by default. 26 | */ 27 | unit byte { 28 | variant default { 29 | div = { 1, 1024, 1048576, 1073741824, 1099511627776} 30 | txt = { "B", "KiB", "MiB", "GiB", "TiB" } 31 | } 32 | variant si { 33 | div = { 1, 1000, 1000000, 1000000000, 1000000000000 } 34 | txt = { "B", "KB", "MB", "GB", "TB" } 35 | } 36 | variant bit { 37 | div = { 0.125, 125, 125000, 125000000, 125000000000 } 38 | txt = { "b", "Kb", "Mb", "Gb", "Tb" } 39 | } 40 | } 41 | 42 | unit bit { 43 | variant default { 44 | div = { 1, 1000, 1000000, 1000000000, 1000000000000 } 45 | txt = { "b", "Kb", "Mb", "Gb", "Tb" } 46 | } 47 | variant si { 48 | div = { 1, 1000, 1000000, 1000000000, 1000000000000 } 49 | txt = { "b", "Kb", "Mb", "Gb", "Tb" } 50 | } 51 | variant bit { 52 | div = { 1, 1000, 1000000, 1000000000, 1000000000000 } 53 | txt = { "b", "Kb", "Mb", "Gb", "Tb" } 54 | } 55 | } 56 | 57 | unit number { 58 | variant default { 59 | div = { 1, 1000, 1000000, 1000000000, 1000000000000 } 60 | txt = { "", "K", "M", "G", "T" } 61 | } 62 | } 63 | unit percent { 64 | variant default { 65 | div = 1. 66 | txt = "%" 67 | } 68 | } 69 | 70 | history second { 71 | interval = 1. 72 | size = 60 73 | } 74 | 75 | history minute { 76 | interval = 60. 77 | size = 60 78 | } 79 | 80 | history hour { 81 | interval = 3600. 82 | size = 60 83 | } 84 | 85 | history day { 86 | interval = 86400. 87 | size = 60 88 | } 89 | 90 | layout colors { 91 | color default { 92 | color_pair = {"white", "black"} 93 | } 94 | color statusbar { 95 | color_pair = {"blue", "white", "reverse"} 96 | } 97 | color header { 98 | color_pair = {"yellow", "black"} 99 | } 100 | color list { 101 | color_pair = {"white", "black"} 102 | } 103 | color selected { 104 | color_pair = {"white", "black", "reverse"} 105 | } 106 | color RX_graph { 107 | color_pair = {"green", "black"} 108 | } 109 | color TX_graph { 110 | color_pair = {"red", "black"} 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /include/Makefile.am: -------------------------------------------------------------------------------- 1 | noinst_HEADERS = \ 2 | bmon/attr.h \ 3 | bmon/bmon.h \ 4 | bmon/compile-fixes.h \ 5 | bmon/conf.h \ 6 | bmon/config.h \ 7 | bmon/defs.h \ 8 | bmon/element_cfg.h \ 9 | bmon/element.h \ 10 | bmon/graph.h \ 11 | bmon/group.h \ 12 | bmon/history.h \ 13 | bmon/info.h \ 14 | bmon/input.h \ 15 | bmon/list.h \ 16 | bmon/module.h \ 17 | bmon/output.h \ 18 | bmon/unit.h \ 19 | bmon/layout.h \ 20 | bmon/utils.h 21 | -------------------------------------------------------------------------------- /include/bmon/.gitignore: -------------------------------------------------------------------------------- 1 | defs.h* 2 | stamp-h1 3 | -------------------------------------------------------------------------------- /include/bmon/attr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * bmon/attr.h Attributes 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef __BMON_ATTR_H_ 27 | #define __BMON_ATTR_H_ 28 | 29 | #include 30 | #include 31 | 32 | struct element; 33 | 34 | struct rate 35 | { 36 | /* Total value of attribute with eventual overflows accumulated. */ 37 | uint64_t r_total; 38 | 39 | /* Current value of counter */ 40 | uint64_t r_current; 41 | 42 | /* Value of r_current at last read */ 43 | uint64_t r_prev; 44 | 45 | /* Reset value to substract to emulate statistics reset */ 46 | uint64_t r_reset; 47 | 48 | /* Rate per second calculated every `rate_interval' */ 49 | float r_rate; 50 | 51 | /* Time of last calculation */ 52 | timestamp_t r_last_calc; 53 | }; 54 | 55 | extern uint64_t rate_get_total(struct rate *); 56 | 57 | enum { 58 | ATTR_TYPE_UNSPEC, 59 | ATTR_TYPE_COUNTER, 60 | ATTR_TYPE_RATE, 61 | ATTR_TYPE_PERCENT, 62 | }; 63 | 64 | struct attr_def { 65 | int ad_id; 66 | char * ad_name; 67 | char * ad_description; 68 | int ad_type; 69 | int ad_flags; 70 | struct unit * ad_unit; 71 | 72 | struct list_head ad_list; 73 | }; 74 | 75 | struct attr_map { 76 | const char * name; 77 | const char * description; 78 | const char * unit; 79 | int attrid, 80 | type, 81 | rxid, 82 | txid, 83 | flags; 84 | }; 85 | 86 | extern int attr_def_add(const char *, const char *, 87 | struct unit *, int, int); 88 | extern struct attr_def * attr_def_lookup(const char *); 89 | extern struct attr_def * attr_def_lookup_id(int); 90 | 91 | extern int attr_map_load(struct attr_map *map, size_t size); 92 | 93 | #define ATTR_FORCE_HISTORY 0x01 /* collect history */ 94 | #define ATTR_IGNORE_OVERFLOWS 0x02 95 | #define ATTR_TRUE_64BIT 0x04 96 | #define ATTR_RX_ENABLED 0x08 /* has RX counter */ 97 | #define ATTR_TX_ENABLED 0x10 /* has TX counter */ 98 | #define ATTR_DOING_HISTORY 0x20 /* history collected */ 99 | 100 | struct attr 101 | { 102 | struct rate a_rx_rate, 103 | a_tx_rate; 104 | 105 | uint8_t a_flags; 106 | struct attr_def * a_def; 107 | timestamp_t a_last_update; 108 | 109 | struct list_head a_history_list; 110 | 111 | struct list_head a_list; 112 | struct list_head a_sort_list; 113 | }; 114 | 115 | extern struct attr * attr_lookup(const struct element *, int); 116 | extern void attr_update(struct element *, int, 117 | uint64_t, uint64_t , int ); 118 | extern void attr_notify_update(struct attr *, 119 | timestamp_t *); 120 | extern void attr_free(struct attr *); 121 | 122 | extern void attr_rate2float(struct attr *, 123 | double *, char **, int *, 124 | double *, char **, int *); 125 | 126 | extern void attr_calc_usage(struct attr *, float *, float *, 127 | uint64_t, uint64_t); 128 | 129 | #define ATTR_HASH_SIZE 32 130 | 131 | #define UPDATE_FLAG_RX 0x01 132 | #define UPDATE_FLAG_TX 0x02 133 | #define UPDATE_FLAG_64BIT 0x04 134 | 135 | extern struct attr * attr_select_first(void); 136 | extern struct attr * attr_select_last(void); 137 | extern struct attr * attr_select_next(void); 138 | extern struct attr * attr_select_prev(void); 139 | extern struct attr * attr_current(void); 140 | 141 | extern void attr_start_collecting_history(struct attr *); 142 | extern void attr_reset_counter(struct attr *a); 143 | 144 | #endif 145 | -------------------------------------------------------------------------------- /include/bmon/bmon.h: -------------------------------------------------------------------------------- 1 | /* 2 | * bmon.h All-include Header 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef __BMON_BMON_H_ 27 | #define __BMON_BMON_H_ 28 | 29 | #include 30 | #include 31 | 32 | extern int start_time; 33 | 34 | typedef struct timestamp_s 35 | { 36 | int64_t tv_sec; 37 | int64_t tv_usec; 38 | } timestamp_t; 39 | 40 | typedef struct xdate_s 41 | { 42 | struct tm d_tm; 43 | unsigned int d_usec; 44 | } xdate_t; 45 | 46 | enum { 47 | EMPTY_LIST = 1, 48 | END_OF_LIST = 2 49 | }; 50 | 51 | #define BUG() \ 52 | do { \ 53 | fprintf(stderr, "BUG: %s:%d\n", __FILE__, __LINE__); \ 54 | assert(0); \ 55 | exit(EINVAL); \ 56 | } while (0); 57 | 58 | #define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0])) 59 | 60 | #if defined __GNUC__ 61 | #define __init __attribute__ ((constructor)) 62 | #define __exit __attribute__ ((destructor)) 63 | #define __unused__ __attribute__ ((unused)) 64 | #else 65 | #define __init 66 | #define __exit 67 | #define __unused__ 68 | #endif 69 | 70 | #ifdef DEBUG 71 | #define DBG(FMT, ARG...) \ 72 | do { \ 73 | fprintf(stderr, \ 74 | "[DBG] %20s:%-4u %s: " FMT "\n", \ 75 | __FILE__, __LINE__, \ 76 | __PRETTY_FUNCTION__, ##ARG); \ 77 | } while (0) 78 | #else 79 | #define DBG(FMT, ARG...) \ 80 | do { \ 81 | } while (0) 82 | #endif 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /include/bmon/compile-fixes.h: -------------------------------------------------------------------------------- 1 | /* 2 | * compile_fixes.h 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef __BMON_COMPILE_FIXES_H_ 27 | #define __BMON_COMPILE_FIXES_H_ 28 | 29 | #include 30 | 31 | #ifndef HAVE_SUSECONDS_T 32 | typedef long suseconds_t; 33 | #endif 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /include/bmon/conf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * conf.h Config Crap 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef __BMON_CONF_H_ 27 | #define __BMON_CONF_H_ 28 | 29 | #include 30 | 31 | extern cfg_t *cfg; 32 | 33 | extern float cfg_read_interval; 34 | extern float cfg_rate_interval; 35 | extern float cfg_rate_variance; 36 | extern float cfg_history_variance; 37 | extern int cfg_show_all; 38 | extern int cfg_unit_exp; 39 | 40 | extern void conf_init_pre(void); 41 | extern void conf_init_post(void); 42 | extern void configfile_read(void); 43 | extern void set_configfile(const char *); 44 | 45 | extern unsigned int get_lifecycles(void); 46 | 47 | extern void conf_set_float(const char *, double); 48 | extern double conf_get_float(const char *); 49 | extern void conf_set_int(const char *, long); 50 | extern long conf_get_int(const char *); 51 | extern void conf_set_string(const char *, const char *); 52 | extern const char * conf_get_string(const char *); 53 | 54 | typedef struct tv_s 55 | { 56 | char * tv_type; 57 | char * tv_value; 58 | struct list_head tv_list; 59 | } tv_t; 60 | 61 | typedef struct module_conf_s 62 | { 63 | char * m_name; 64 | struct list_head m_attrs; 65 | struct list_head m_list; 66 | } module_conf_t; 67 | 68 | extern int parse_module_param(const char *, struct list_head *); 69 | 70 | enum { 71 | LAYOUT_UNSPEC, 72 | LAYOUT_DEFAULT, 73 | LAYOUT_STATUSBAR, 74 | LAYOUT_HEADER, 75 | LAYOUT_LIST, 76 | LAYOUT_SELECTED, 77 | LAYOUT_RX_GRAPH, 78 | LAYOUT_TX_GRAPH, 79 | __LAYOUT_MAX 80 | }; 81 | 82 | #define LAYOUT_MAX (__LAYOUT_MAX - 1) 83 | 84 | struct layout 85 | { 86 | int l_fg, 87 | l_bg, 88 | l_attr; 89 | }; 90 | 91 | extern struct layout cfg_layout[]; 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /include/bmon/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * config.h Global Config 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef __BMON_CONFIG_H_ 27 | #define __BMON_CONFIG_H_ 28 | 29 | #include 30 | #include 31 | 32 | #if STDC_HEADERS != 1 33 | #error "*** ERROR: ANSI C headers required for compilation ***" 34 | #endif 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #ifdef SYS_BSD 50 | # include 51 | #elif !defined(__ANDROID__) 52 | # include 53 | #endif 54 | 55 | #if TIME_WITH_SYS_TIME 56 | # include 57 | # include 58 | #else 59 | # if HAVE_SYS_TIME_H 60 | # include 61 | # else 62 | # include 63 | # endif 64 | #endif 65 | 66 | #ifdef HAVE_VFORK_H 67 | #include 68 | #endif 69 | 70 | #if !HAVE_WORKING_VFORK 71 | #define vfork fork 72 | #endif 73 | 74 | #if defined HAVE_STRING_H 75 | #include 76 | #elif defined HAVE_STRINGS_H 77 | #include 78 | #else 79 | #error "*** ERROR: No string header file found ***" 80 | #endif 81 | 82 | #ifdef HAVE_UNISTD_H 83 | #include 84 | #endif 85 | 86 | #ifdef HAVE_STDLIB_H 87 | #include 88 | #endif 89 | 90 | #ifdef HAVE_STDINT_H 91 | #include 92 | #endif 93 | 94 | #ifdef HAVE_INITTYPES_H 95 | #include 96 | #endif 97 | 98 | #ifdef HAVE_SYS_TYPES_H 99 | #include 100 | #endif 101 | 102 | #if defined HAVE_GETOPT_H 103 | #include 104 | #endif 105 | 106 | #include 107 | #include 108 | #include 109 | #include 110 | 111 | #if defined HAVE_SYS_UTSNAME_H 112 | #include 113 | #endif 114 | 115 | #if defined HAVE_NCURSESW_CURSES_H 116 | # include 117 | #elif defined HAVE_NCURSESW_H 118 | # include 119 | #elif defined HAVE_NCURSES_CURSES_H 120 | # include 121 | #elif defined HAVE_NCURSES_H 122 | # include 123 | #elif defined HAVE_CURSES_H 124 | # include 125 | #else 126 | # error "SysV or X/Open-compatible Curses header file required" 127 | #endif 128 | 129 | #include 130 | 131 | #if defined HAVE_NETINET6_IN6_H 132 | #include 133 | #endif 134 | 135 | #include 136 | #include 137 | 138 | #include 139 | 140 | #ifndef IFNAMSIZ 141 | #define IFNAMSIZ 16 142 | #endif 143 | 144 | #ifndef SCNu64 145 | #define SCNu64 "llu" 146 | #endif 147 | 148 | #ifndef PRIu64 149 | #define PRIu64 "llu" 150 | #endif 151 | 152 | #ifndef PRId64 153 | #define PRId64 "lld" 154 | #endif 155 | 156 | #ifndef PRIX64 157 | #define PRIX64 "X" 158 | #endif 159 | 160 | #define DEFAULT_GROUP "intf" 161 | 162 | #endif 163 | -------------------------------------------------------------------------------- /include/bmon/defs.h.in: -------------------------------------------------------------------------------- 1 | /* include/bmon/defs.h.in. Generated from configure.ac by autoheader. */ 2 | 3 | /* enable debugging */ 4 | #undef DEBUG 5 | 6 | /* no overflow workaround */ 7 | #undef DISABLE_OVERFLOW_WORKAROUND 8 | 9 | /* Define to 1 if you have the `atexit' function. */ 10 | #undef HAVE_ATEXIT 11 | 12 | /* Define to 1 if you have the `clock_gettime' function. */ 13 | #undef HAVE_CLOCK_GETTIME 14 | 15 | /* have curses */ 16 | #undef HAVE_CURSES 17 | 18 | /* Define to 1 if library supports color (enhanced functions) */ 19 | #undef HAVE_CURSES_COLOR 20 | 21 | /* Define to 1 if library supports X/Open Enhanced functions */ 22 | #undef HAVE_CURSES_ENHANCED 23 | 24 | /* Define to 1 if is present */ 25 | #undef HAVE_CURSES_H 26 | 27 | /* Define to 1 if library supports certain obsolete features */ 28 | #undef HAVE_CURSES_OBSOLETE 29 | 30 | /* Define to 1 if you have the header file. */ 31 | #undef HAVE_DIRENT_H 32 | 33 | /* Define to 1 if you have the header file. */ 34 | #undef HAVE_FCNTL_H 35 | 36 | /* Define to 1 if you have the `fork' function. */ 37 | #undef HAVE_FORK 38 | 39 | /* Define to 1 if you have the `getdate' function. */ 40 | #undef HAVE_GETDATE 41 | 42 | /* Define to 1 if you have the header file. */ 43 | #undef HAVE_GETOPT_H 44 | 45 | /* Define to 1 if you have the header file. */ 46 | #undef HAVE_INTTYPES_H 47 | 48 | /* Define to 1 if you have the `m' library (-lm). */ 49 | #undef HAVE_LIBM 50 | 51 | /* Define to 1 if you have the `rt' library (-lrt). */ 52 | #undef HAVE_LIBRT 53 | 54 | /* Define to 1 if you have the header file. */ 55 | #undef HAVE_MEMORY_H 56 | 57 | /* Define to 1 if you have the `memset' function. */ 58 | #undef HAVE_MEMSET 59 | 60 | /* have ncurses */ 61 | #undef HAVE_NCURSES 62 | 63 | /* Define to 1 if the NcursesW library is present */ 64 | #undef HAVE_NCURSESW 65 | 66 | /* Define to 1 if is present */ 67 | #undef HAVE_NCURSESW_CURSES_H 68 | 69 | /* Define to 1 if is present */ 70 | #undef HAVE_NCURSESW_H 71 | 72 | /* Define to 1 if is present */ 73 | #undef HAVE_NCURSES_CURSES_H 74 | 75 | /* Define to 1 if is present */ 76 | #undef HAVE_NCURSES_H 77 | 78 | /* Define to 1 if you have the header file. */ 79 | #undef HAVE_NCURSES_NCURSES_H 80 | 81 | /* Define to 1 if you have the header file, and it defines `DIR'. */ 82 | #undef HAVE_NDIR_H 83 | 84 | /* Define to 1 if you have the header file. */ 85 | #undef HAVE_NETDB_H 86 | 87 | /* Define to 1 if you have the header file. */ 88 | #undef HAVE_NETINET6_IN6_H 89 | 90 | /* Define to 1 if you have the header file. */ 91 | #undef HAVE_NETINET_IN_H 92 | 93 | /* Define to 1 if you have the `pow' function. */ 94 | #undef HAVE_POW 95 | 96 | /* have redrawwin */ 97 | #undef HAVE_REDRAWWIN 98 | 99 | /* Define to 1 if you have the `socket' function. */ 100 | #undef HAVE_SOCKET 101 | 102 | /* Define to 1 if you have the header file. */ 103 | #undef HAVE_STDINT_H 104 | 105 | /* Define to 1 if you have the header file. */ 106 | #undef HAVE_STDLIB_H 107 | 108 | /* Define to 1 if you have the `strcasecmp' function. */ 109 | #undef HAVE_STRCASECMP 110 | 111 | /* Define to 1 if you have the `strchr' function. */ 112 | #undef HAVE_STRCHR 113 | 114 | /* Define to 1 if you have the `strdup' function. */ 115 | #undef HAVE_STRDUP 116 | 117 | /* Define to 1 if you have the `strerror' function. */ 118 | #undef HAVE_STRERROR 119 | 120 | /* Define to 1 if you have the header file. */ 121 | #undef HAVE_STRINGS_H 122 | 123 | /* Define to 1 if you have the header file. */ 124 | #undef HAVE_STRING_H 125 | 126 | /* Define to 1 if you have the `strncasecmp' function. */ 127 | #undef HAVE_STRNCASECMP 128 | 129 | /* Define to 1 if you have the `strstr' function. */ 130 | #undef HAVE_STRSTR 131 | 132 | /* Define to 1 if you have the `strtol' function. */ 133 | #undef HAVE_STRTOL 134 | 135 | /* Define to 1 if the system has the type `suseconds_t'. */ 136 | #undef HAVE_SUSECONDS_T 137 | 138 | /* Define to 1 if you have the header file. */ 139 | #undef HAVE_SYSCTL_IOCTL_H 140 | 141 | /* Define to 1 if you have the header file, and it defines `DIR'. 142 | */ 143 | #undef HAVE_SYS_DIR_H 144 | 145 | /* Define to 1 if you have the header file, and it defines `DIR'. 146 | */ 147 | #undef HAVE_SYS_NDIR_H 148 | 149 | /* Define to 1 if you have the header file. */ 150 | #undef HAVE_SYS_PARAM_H 151 | 152 | /* Define to 1 if you have the header file. */ 153 | #undef HAVE_SYS_SOCKET_H 154 | 155 | /* Define to 1 if you have the header file. */ 156 | #undef HAVE_SYS_SOCKIO_H 157 | 158 | /* Define to 1 if you have the header file. */ 159 | #undef HAVE_SYS_STAT_H 160 | 161 | /* Define to 1 if you have the header file. */ 162 | #undef HAVE_SYS_TYPES_H 163 | 164 | /* Define to 1 if you have the header file. */ 165 | #undef HAVE_SYS_UTSNAME_H 166 | 167 | /* Define to 1 if you have the `uname' function. */ 168 | #undef HAVE_UNAME 169 | 170 | /* Define to 1 if you have the header file. */ 171 | #undef HAVE_UNISTD_H 172 | 173 | /* have udc */ 174 | #undef HAVE_USE_DEFAULT_COLORS 175 | 176 | /* Define to 1 if you have the `vfork' function. */ 177 | #undef HAVE_VFORK 178 | 179 | /* Define to 1 if you have the header file. */ 180 | #undef HAVE_VFORK_H 181 | 182 | /* Define to 1 if `fork' works. */ 183 | #undef HAVE_WORKING_FORK 184 | 185 | /* Define to 1 if `vfork' works. */ 186 | #undef HAVE_WORKING_VFORK 187 | 188 | /* Name of package */ 189 | #undef PACKAGE 190 | 191 | /* Define to the address where bug reports for this package should be sent. */ 192 | #undef PACKAGE_BUGREPORT 193 | 194 | /* Define to the full name of this package. */ 195 | #undef PACKAGE_NAME 196 | 197 | /* Define to the full name and version of this package. */ 198 | #undef PACKAGE_STRING 199 | 200 | /* Define to the one symbol short name of this package. */ 201 | #undef PACKAGE_TARNAME 202 | 203 | /* Define to the home page for this package. */ 204 | #undef PACKAGE_URL 205 | 206 | /* Define to the version of this package. */ 207 | #undef PACKAGE_VERSION 208 | 209 | /* Define as the return type of signal handlers (`int' or `void'). */ 210 | #undef RETSIGTYPE 211 | 212 | /* Define to 1 if you have the ANSI C header files. */ 213 | #undef STDC_HEADERS 214 | 215 | /* operating system */ 216 | #undef SYS_BSD 217 | 218 | /* operating system */ 219 | #undef SYS_LINUX 220 | 221 | /* operating system */ 222 | #undef SYS_OTHER 223 | 224 | /* operating system */ 225 | #undef SYS_SUNOS 226 | 227 | /* Define to 1 if you can safely include both and . */ 228 | #undef TIME_WITH_SYS_TIME 229 | 230 | /* Version number of package */ 231 | #undef VERSION 232 | 233 | /* Define to empty if `const' does not conform to ANSI C. */ 234 | #undef const 235 | 236 | /* Define to `__inline__' or `__inline' if that's what the C compiler 237 | calls it, or to nothing if 'inline' is not supported under any name. */ 238 | #ifndef __cplusplus 239 | #undef inline 240 | #endif 241 | 242 | /* Define to `int' if does not define. */ 243 | #undef pid_t 244 | 245 | /* Define to `unsigned int' if does not define. */ 246 | #undef size_t 247 | 248 | /* Define as `fork' if `vfork' does not work. */ 249 | #undef vfork 250 | -------------------------------------------------------------------------------- /include/bmon/element.h: -------------------------------------------------------------------------------- 1 | /* 2 | * bmon/element.h Elements 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef __BMON_ELEMENT_H_ 27 | #define __BMON_ELEMENT_H_ 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #define MAX_GRAPHS 32 34 | #define IFNAME_MAX 32 35 | 36 | struct policy 37 | { 38 | char * p_rule; 39 | struct list_head p_list; 40 | }; 41 | 42 | struct element_cfg; 43 | 44 | struct info 45 | { 46 | char * i_name; 47 | char * i_value; 48 | struct list_head i_list; 49 | }; 50 | 51 | struct element 52 | { 53 | char * e_name; 54 | char * e_description; 55 | uint32_t e_id; 56 | uint32_t e_flags; 57 | unsigned int e_lifecycles; 58 | unsigned int e_level; /* recursion level */ 59 | 60 | struct element * e_parent; 61 | struct element_group * e_group; 62 | 63 | struct list_head e_list; 64 | struct list_head e_childs; 65 | 66 | unsigned int e_nattrs; 67 | struct list_head e_attrhash[ATTR_HASH_SIZE]; 68 | struct list_head e_attr_sorted; 69 | 70 | unsigned int e_ninfo; 71 | struct list_head e_info_list; 72 | 73 | struct attr_def * e_key_attr[__GT_MAX]; 74 | struct attr_def * e_usage_attr; 75 | 76 | float e_rx_usage, 77 | e_tx_usage; 78 | 79 | struct element_cfg * e_cfg; 80 | 81 | struct attr * e_current_attr; 82 | }; 83 | 84 | #define ELEMENT_CREAT (1 << 0) 85 | 86 | extern struct element * element_lookup(struct element_group *, 87 | const char *, uint32_t, 88 | struct element *, int); 89 | 90 | extern void element_free(struct element *); 91 | 92 | extern void element_reset_update_flag(struct element_group *, 93 | struct element *, 94 | void *); 95 | extern void element_notify_update(struct element *, 96 | timestamp_t *); 97 | extern void element_lifesign(struct element *, int); 98 | extern void element_check_if_dead(struct element_group *, 99 | struct element *, void *); 100 | 101 | extern int element_set_key_attr(struct element *, const char *, const char *); 102 | extern int element_set_usage_attr(struct element *, const char *); 103 | 104 | #define ELEMENT_FLAG_FOLDED (1 << 0) 105 | #define ELEMENT_FLAG_UPDATED (1 << 1) 106 | #define ELEMENT_FLAG_EXCLUDE (1 << 2) 107 | #define ELEMENT_FLAG_CREATED (1 << 3) 108 | 109 | extern void element_foreach_attr(struct element *, 110 | void (*cb)(struct element *, 111 | struct attr *, void *), 112 | void *); 113 | 114 | extern struct element * element_current(void); 115 | extern struct element * element_select_first(void); 116 | extern struct element * element_select_last(void); 117 | extern struct element * element_select_next(void); 118 | extern struct element * element_select_prev(void); 119 | 120 | extern int element_allowed(const char *, struct element_cfg *); 121 | extern void element_parse_policy(const char *); 122 | 123 | extern void element_update_info(struct element *, 124 | const char *, 125 | const char *); 126 | 127 | extern void element_set_txmax(struct element *, uint64_t); 128 | extern void element_set_rxmax(struct element *, uint64_t); 129 | 130 | #endif 131 | -------------------------------------------------------------------------------- /include/bmon/element_cfg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * element_cfg.h Element Configuration 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef __BMON_ELEMENT_CFG_H_ 27 | #define __BMON_ELEMENT_CFG_H_ 28 | 29 | #include 30 | #include 31 | 32 | #define ELEMENT_CFG_SHOW (1 << 0) 33 | #define ELEMENT_CFG_HIDE (1 << 1) 34 | 35 | struct element_cfg 36 | { 37 | char * ec_name; /* Name of element config */ 38 | char * ec_parent; /* Name of parent */ 39 | char * ec_description; /* Human readable description */ 40 | uint64_t ec_rxmax; /* Maximum RX value expected */ 41 | uint64_t ec_txmax; /* Minimum TX value expected */ 42 | unsigned int ec_flags; /* Flags */ 43 | 44 | struct list_head ec_list; /* Internal, do not modify */ 45 | int ec_refcnt; /* Internal, do not modify */ 46 | }; 47 | 48 | extern struct element_cfg * element_cfg_alloc(const char *); 49 | extern struct element_cfg * element_cfg_create(const char *); 50 | extern void element_cfg_free(struct element_cfg *); 51 | extern struct element_cfg * element_cfg_lookup(const char *); 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /include/bmon/graph.h: -------------------------------------------------------------------------------- 1 | /* 2 | * bmon/graph.h Graph creation utility 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef __BMON_GRAPH_H_ 27 | #define __BMON_GRAPH_H_ 28 | 29 | #include 30 | #include 31 | 32 | struct history; 33 | 34 | struct graph_cfg { 35 | int gc_height, 36 | gc_width, 37 | gc_flags; 38 | 39 | char gc_background, 40 | gc_foreground, 41 | gc_noise, 42 | gc_unknown; 43 | 44 | struct unit * gc_unit; 45 | }; 46 | 47 | struct graph_table { 48 | char * gt_table; 49 | char * gt_y_unit; 50 | float * gt_scale; 51 | }; 52 | 53 | struct graph { 54 | struct graph_cfg g_cfg; 55 | struct graph_table g_rx, 56 | g_tx; 57 | 58 | struct list_head g_list; 59 | }; 60 | 61 | extern void graph_free(struct graph *); 62 | extern struct graph * graph_alloc(struct history *, struct graph_cfg *); 63 | extern void graph_refill(struct graph *, struct history *); 64 | 65 | extern size_t graph_row_size(struct graph_cfg *); 66 | 67 | extern void new_graph(void); 68 | extern void del_graph(void); 69 | extern int next_graph(void); 70 | extern int prev_graph(void); 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /include/bmon/group.h: -------------------------------------------------------------------------------- 1 | /* 2 | * bmon/group.h Group Management 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef __BMON_GROUP_H_ 27 | #define __BMON_GROUP_H_ 28 | 29 | #include 30 | 31 | struct element; 32 | 33 | enum { 34 | GT_MAJOR, 35 | GT_MINOR, 36 | __GT_MAX, 37 | }; 38 | 39 | #define GT_MAX (__GT_MAX - 1) 40 | 41 | #define GROUP_COL_MAX (__GT_MAX * 2) 42 | 43 | struct group_hdr 44 | { 45 | char * gh_name; 46 | char * gh_title; 47 | char * gh_column[GROUP_COL_MAX]; 48 | struct list_head gh_list; 49 | }; 50 | 51 | extern struct group_hdr * group_lookup_hdr(const char *); 52 | extern int group_new_hdr(const char *, const char *, 53 | const char *, const char *, 54 | const char *, const char *); 55 | extern int group_new_derived_hdr(const char *, 56 | const char *, 57 | const char *); 58 | 59 | struct element_group 60 | { 61 | char * g_name; 62 | struct group_hdr * g_hdr; 63 | 64 | struct list_head g_elements; 65 | unsigned int g_nelements; 66 | 67 | /* Currently selected element in this group */ 68 | struct element * g_current; 69 | 70 | struct list_head g_list; 71 | }; 72 | 73 | #define GROUP_CREATE 1 74 | 75 | extern struct element_group * group_lookup(const char *, int); 76 | extern void reset_update_flags(void); 77 | extern void free_unused_elements(void); 78 | extern void calc_rates(void); 79 | 80 | extern void group_foreach( 81 | void (*cb)(struct element_group *, 82 | void *), 83 | void *); 84 | extern void group_foreach_recursive( 85 | void (*cb)(struct element_group *, 86 | struct element *, void *), 87 | void *); 88 | 89 | extern void group_foreach_element(struct element_group *, 90 | void (*cb)(struct element_group *, 91 | struct element *, void *), 92 | void *); 93 | 94 | extern struct element_group * group_current(void); 95 | extern struct element_group * group_select_first(void); 96 | extern struct element_group * group_select_last(void); 97 | extern struct element_group * group_select_next(void); 98 | extern struct element_group * group_select_prev(void); 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /include/bmon/history.h: -------------------------------------------------------------------------------- 1 | /* 2 | * bmon/history.h History Management 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef __BMON_HISTORY_H_ 27 | #define __BMON_HISTORY_H_ 28 | 29 | #include 30 | #include 31 | 32 | #define HISTORY_UNKNOWN ((uint64_t) -1) 33 | #define HBEAT_TRIGGER 60.0f 34 | 35 | enum { 36 | HISTORY_TYPE_8 = 1, 37 | HISTORY_TYPE_16 = 2, 38 | HISTORY_TYPE_32 = 4, 39 | HISTORY_TYPE_64 = 8, 40 | }; 41 | 42 | struct history_def 43 | { 44 | char * hd_name; 45 | int hd_size, 46 | hd_type; 47 | float hd_interval; 48 | 49 | struct list_head hd_list; 50 | }; 51 | 52 | struct history_store 53 | { 54 | /* TODO? store error ratio? */ 55 | void * hs_data; 56 | uint64_t hs_prev_total; 57 | }; 58 | 59 | struct history 60 | { 61 | /* index to current entry in data array */ 62 | int h_index; 63 | struct history_def * h_definition; 64 | /* time of last history update */ 65 | timestamp_t h_last_update; 66 | struct list_head h_list; 67 | 68 | float h_min_interval, 69 | h_max_interval; 70 | 71 | struct history_store h_rx, 72 | h_tx; 73 | 74 | }; 75 | 76 | extern struct history_def * history_def_lookup(const char *); 77 | extern struct history_def * history_def_alloc(const char *); 78 | 79 | extern uint64_t history_data(struct history *, 80 | struct history_store *, int); 81 | extern void history_update(struct attr *, 82 | struct history *, timestamp_t *); 83 | extern struct history * history_alloc(struct history_def *); 84 | extern void history_free(struct history *); 85 | extern void history_attach(struct attr *); 86 | 87 | extern struct history_def * history_select_first(void); 88 | extern struct history_def * history_select_last(void); 89 | extern struct history_def * history_select_next(void); 90 | extern struct history_def * history_select_prev(void); 91 | extern struct history_def * history_current(void); 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /include/bmon/info.h: -------------------------------------------------------------------------------- 1 | /* 2 | * bmon/info.h Info Attributes 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef __BMON_INFO_H_ 27 | #define __BMON_INFO_H_ 28 | 29 | #include 30 | #include 31 | 32 | struct element; 33 | 34 | struct info 35 | { 36 | char * i_name; 37 | char * i_value; 38 | 39 | struct list_head i_list; 40 | }; 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /include/bmon/input.h: -------------------------------------------------------------------------------- 1 | /* 2 | * input.h Input API 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef __BMON_INPUT_H_ 27 | #define __BMON_INPUT_H_ 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | extern int input_set(const char *); 34 | extern void input_register(struct bmon_module *); 35 | extern void input_read(void); 36 | 37 | struct reader_timing 38 | { 39 | timestamp_t rt_last_read; /* timestamp taken before read */ 40 | timestamp_t rt_next_read; /* estimated next read */ 41 | 42 | struct { 43 | float v_error; 44 | float v_max; 45 | float v_min; 46 | float v_total; 47 | } rt_variance; 48 | }; 49 | 50 | extern struct reader_timing rtiming; 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /include/bmon/layout.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __BMON_LAYOUT_H_ 3 | #define __BMON_LAYOUT_H_ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | static int parse_color(const char* color) 12 | { 13 | int color_code = -1; 14 | 15 | if ((strcasestr(color, "red") != NULL)) 16 | color_code = COLOR_RED; 17 | else if ((strcasestr(color, "green") != NULL)) 18 | color_code = COLOR_GREEN; 19 | else if ((strcasestr(color, "white") != NULL)) 20 | color_code = COLOR_WHITE; 21 | else if ((strcasestr(color, "black") != NULL)) 22 | color_code = COLOR_BLACK; 23 | else if ((strcasestr(color, "blue") != NULL)) 24 | color_code = COLOR_BLUE; 25 | else if ((strcasestr(color, "yellow") != NULL)) 26 | color_code = COLOR_YELLOW; 27 | else if ((strcasestr(color, "magenta") != NULL)) 28 | color_code = COLOR_MAGENTA; 29 | else if ((strcasestr(color, "cyan") != NULL)) 30 | color_code = COLOR_CYAN; 31 | else if ((atoi(color) >= 0)) 32 | color_code = atoi(color); 33 | 34 | return color_code; 35 | } 36 | 37 | /* 38 | A_NORMAL Normal display (no highlight) 39 | A_STANDOUT Best highlighting mode of the terminal. 40 | A_UNDERLINE Underlining 41 | A_REVERSE Reverse video 42 | A_BLINK Blinking 43 | A_DIM Half bright 44 | A_BOLD Extra bright or bold 45 | A_PROTECT Protected mode 46 | A_INVIS Invisible or blank mode 47 | A_ALTCHARSET Alternate character set 48 | A_CHARTEXT Bit-mask to extract a character 49 | */ 50 | 51 | static int parse_attribute(const char* attr) 52 | { 53 | /* no attribute is valid, so we have nothing to do */ 54 | if (attr == NULL) 55 | return 0; 56 | 57 | if ((strcasestr(attr, "normal") != NULL)) 58 | return A_NORMAL; 59 | else if ((strcasestr(attr, "standout") != NULL)) 60 | return A_STANDOUT; 61 | else if ((strcasestr(attr, "underline") != NULL)) 62 | return A_UNDERLINE; 63 | else if ((strcasestr(attr, "reverse") != NULL)) 64 | return A_REVERSE; 65 | else if ((strcasestr(attr, "blink") != NULL)) 66 | return A_BLINK; 67 | else if ((strcasestr(attr, "dim") != NULL)) 68 | return A_DIM; 69 | else if ((strcasestr(attr, "bold") != NULL)) 70 | return A_BOLD; 71 | else if ((strcasestr(attr, "protect") != NULL)) 72 | return A_PROTECT; 73 | else if ((strcasestr(attr, "invis") != NULL)) 74 | return A_INVIS; 75 | else if ((strcasestr(attr, "altcharset") != NULL)) 76 | return A_ALTCHARSET; 77 | else if ((strcasestr(attr, "chartext") != NULL)) 78 | return A_CHARTEXT; 79 | 80 | return -1; 81 | } 82 | 83 | 84 | static void add_layout(const char *layout_name, cfg_t *color_cfg) 85 | { 86 | const char *fg, *bg, *attr_str = NULL; 87 | int size = -1, fg_code, bg_code, attr_mask, layout_idx = 0; 88 | 89 | size = cfg_size(color_cfg, "color_pair"); 90 | fg = cfg_getnstr(color_cfg, "color_pair", 0); 91 | bg = cfg_getnstr(color_cfg, "color_pair", 1); 92 | if (size > 2) 93 | attr_str = cfg_getnstr(color_cfg, "color_pair", 2); 94 | 95 | fg_code = parse_color(fg); 96 | bg_code = parse_color(bg); 97 | if (fg_code == -1 || bg_code == -1) { 98 | quit("Unknown color [%s]: %s\n", (fg_code == -1) ? "fg" : "bg", 99 | (fg_code == -1) ? fg : bg); 100 | } 101 | attr_mask = parse_attribute(attr_str); 102 | if (attr_mask == -1) { 103 | quit("Unknown attribute: '%s'\n", attr_str); 104 | } 105 | 106 | DBG("%s:\tfg: %s bg: %s attr: %s\n", layout_name, fg, bg, attr_str); 107 | 108 | if ((strcasecmp(layout_name, "default") == 0)) 109 | layout_idx = LAYOUT_DEFAULT; 110 | else if ((strcasecmp(layout_name, "statusbar") == 0)) 111 | layout_idx = LAYOUT_STATUSBAR; 112 | else if ((strcasecmp(layout_name, "header") == 0)) 113 | layout_idx = LAYOUT_HEADER; 114 | else if ((strcasecmp(layout_name, "list") == 0)) 115 | layout_idx = LAYOUT_LIST; 116 | else if ((strcasecmp(layout_name, "selected") == 0)) 117 | layout_idx = LAYOUT_SELECTED; 118 | else if ((strcasecmp(layout_name, "rx_graph") == 0)) 119 | layout_idx = LAYOUT_RX_GRAPH; 120 | else if ((strcasecmp(layout_name, "tx_graph") == 0)) 121 | layout_idx = LAYOUT_TX_GRAPH; 122 | else { 123 | quit("Unknown layout name: '%s'\n", layout_name); 124 | } 125 | 126 | struct layout l = { fg_code, bg_code, attr_mask}; 127 | cfg_layout[layout_idx] = l; 128 | } 129 | 130 | #endif /* __BMON_LAYOUT_H_ */ 131 | -------------------------------------------------------------------------------- /include/bmon/list.h: -------------------------------------------------------------------------------- 1 | /* 2 | * bmon/list.h Kernel List Implementation 3 | * 4 | * Copied and adapted from the kernel sources 5 | * 6 | */ 7 | 8 | #ifndef BMON_LIST_H_ 9 | #define BMON_LIST_H_ 10 | 11 | #ifdef __APPLE__ 12 | /* Apple systems define these macros in system headers, so we undef 13 | * them prior to inclusion of this file */ 14 | #undef LIST_HEAD 15 | #undef LIST_HEAD_INIT 16 | #undef INIT_LIST_HEAD 17 | #endif 18 | 19 | struct list_head 20 | { 21 | struct list_head * next; 22 | struct list_head * prev; 23 | }; 24 | 25 | static inline void INIT_LIST_HEAD(struct list_head *list) 26 | { 27 | list->next = list; 28 | list->prev = list; 29 | } 30 | 31 | static inline void __list_add(struct list_head *obj, struct list_head *prev, 32 | struct list_head *next) 33 | { 34 | prev->next = obj; 35 | obj->prev = prev; 36 | next->prev = obj; 37 | obj->next = next; 38 | } 39 | 40 | static inline void list_add_tail(struct list_head *obj, struct list_head *head) 41 | { 42 | __list_add(obj, head->prev, head); 43 | } 44 | 45 | static inline void list_add_head(struct list_head *obj, struct list_head *head) 46 | { 47 | __list_add(obj, head, head->next); 48 | } 49 | 50 | static inline void list_del(struct list_head *obj) 51 | { 52 | obj->next->prev = obj->prev; 53 | obj->prev->next = obj->next; 54 | } 55 | 56 | static inline int list_empty(struct list_head *head) 57 | { 58 | return head->next == head; 59 | } 60 | 61 | #define container_of(ptr, type, member) ({ \ 62 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 63 | (type *)( (char *)__mptr - ((size_t) &((type *)0)->member));}) 64 | 65 | #define list_entry(ptr, type, member) \ 66 | container_of(ptr, type, member) 67 | 68 | #define list_at_tail(pos, head, member) \ 69 | ((pos)->member.next == (head)) 70 | 71 | #define list_at_head(pos, head, member) \ 72 | ((pos)->member.prev == (head)) 73 | 74 | #define LIST_SELF(name) { &(name), &(name) } 75 | 76 | #define LIST_HEAD(name) \ 77 | struct list_head name = { &(name), &(name) } 78 | 79 | #define list_first_entry(head, type, member) \ 80 | list_entry((head)->next, type, member) 81 | 82 | #define list_for_each_entry(pos, head, member) \ 83 | for (pos = list_entry((head)->next, typeof(*pos), member); \ 84 | &(pos)->member != (head); \ 85 | (pos) = list_entry((pos)->member.next, typeof(*(pos)), member)) 86 | 87 | #define list_for_each_entry_reverse(pos, head, member) \ 88 | for (pos = list_entry((head)->prev, typeof(*pos), member); \ 89 | &pos->member != (head); \ 90 | pos = list_entry(pos->member.prev, typeof(*pos), member)) 91 | 92 | #define list_for_each_entry_safe(pos, n, head, member) \ 93 | for (pos = list_entry((head)->next, typeof(*pos), member), \ 94 | n = list_entry(pos->member.next, typeof(*pos), member); \ 95 | &(pos)->member != (head); \ 96 | pos = n, n = list_entry(n->member.next, typeof(*n), member)) 97 | 98 | #define init_list_head(head) \ 99 | do { (head)->next = (head); (head)->prev = (head); } while (0) 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /include/bmon/module.h: -------------------------------------------------------------------------------- 1 | /* 2 | * module.h Module API 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef __BMON_MODULE_H_ 27 | #define __BMON_MODULE_H_ 28 | 29 | #include 30 | #include 31 | 32 | #define BMON_MODULE_ENABLED (1 << 0) /* Enabled */ 33 | #define BMON_MODULE_DEFAULT (1 << 1) /* Suitable as default */ 34 | #define BMON_MODULE_AUTO (1 << 2) /* Auto enable */ 35 | 36 | struct bmon_subsys; 37 | 38 | struct bmon_module 39 | { 40 | char * m_name; 41 | 42 | int (*m_init)(void); 43 | int (*m_probe)(void); 44 | void (*m_shutdown)(void); 45 | 46 | void (*m_parse_opt)(const char *, const char *); 47 | 48 | void (*m_pre)(void); 49 | void (*m_do)(void); 50 | void (*m_post)(void); 51 | 52 | int m_flags; 53 | struct list_head m_list; 54 | struct bmon_subsys *m_subsys; 55 | }; 56 | 57 | struct bmon_subsys 58 | { 59 | char * s_name; 60 | int s_nmod; 61 | struct list_head s_mod_list; 62 | 63 | void (*s_activate_default)(void); 64 | 65 | struct list_head s_list; 66 | }; 67 | 68 | extern void module_foreach_run_enabled_pre(struct bmon_subsys *); 69 | extern void module_foreach_run_enabled(struct bmon_subsys *); 70 | extern void module_foreach_run_enabled_post(struct bmon_subsys *); 71 | 72 | extern int module_register(struct bmon_subsys *, struct bmon_module *); 73 | extern int module_set(struct bmon_subsys *, const char *); 74 | 75 | extern void module_init(void); 76 | extern void module_shutdown(void); 77 | extern void module_register_subsys(struct bmon_subsys *); 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /include/bmon/output.h: -------------------------------------------------------------------------------- 1 | /* 2 | * output.h Output API 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef __BMON_OUTPUT_H_ 27 | #define __BMON_OUTPUT_H_ 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | extern void output_register(struct bmon_module *); 34 | extern int output_set(const char *); 35 | extern void output_pre(void); 36 | extern void output_draw(void); 37 | extern void output_post(void); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /include/bmon/unit.h: -------------------------------------------------------------------------------- 1 | /* 2 | * bmon/unit.h Units 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef __BMON_UNIT_H_ 27 | #define __BMON_UNIT_H_ 28 | 29 | #include 30 | 31 | #define DYNAMIC_EXP (-1) 32 | 33 | enum { 34 | UNIT_DEFAULT, 35 | UNIT_SI, 36 | UNIT_BIT, 37 | __UNIT_MAX, 38 | }; 39 | 40 | #define UNIT_MAX (__UNIT_MAX - 1) 41 | 42 | #define UNIT_BYTE "byte" 43 | #define UNIT_NUMBER "number" 44 | 45 | struct fraction { 46 | float f_divisor; 47 | char * f_name; 48 | 49 | struct list_head f_list; 50 | }; 51 | 52 | struct unit { 53 | char * u_name; 54 | struct list_head u_div[__UNIT_MAX]; 55 | 56 | struct list_head u_list; 57 | }; 58 | 59 | extern struct unit * unit_lookup(const char *); 60 | extern struct unit * unit_add(const char *name); 61 | extern void unit_add_div(struct unit *, int, const char *, float); 62 | extern double unit_divisor(uint64_t, struct unit *, char **, int *); 63 | extern double unit_value2str(uint64_t, struct unit *, char **, int *); 64 | extern void fraction_free(struct fraction *); 65 | 66 | extern char * unit_bytes2str(uint64_t, char *, size_t); 67 | extern char * unit_bit2str(uint64_t, char *, size_t); 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /include/bmon/utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * utils.h General purpose utilities 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef __BMON_UTILS_H_ 27 | #define __BMON_UTILS_H_ 28 | 29 | #include 30 | 31 | extern void * xcalloc(size_t, size_t); 32 | extern void * xrealloc(void *, size_t); 33 | extern void xfree(void *); 34 | extern void quit (const char *, ...); 35 | 36 | extern float timestamp_to_float(timestamp_t *); 37 | extern int64_t timestamp_to_int(timestamp_t *); 38 | 39 | extern void float_to_timestamp(timestamp_t *, float); 40 | extern void int_to_timestamp(timestamp_t *, int); 41 | 42 | extern void timestamp_add(timestamp_t *, timestamp_t *, timestamp_t *); 43 | extern void timestamp_sub(timestamp_t *, timestamp_t *, timestamp_t *); 44 | 45 | extern int timestamp_le(timestamp_t *, timestamp_t *); 46 | extern int timestamp_is_negative(timestamp_t *ts); 47 | 48 | extern void update_timestamp(timestamp_t *); 49 | extern void copy_timestamp(timestamp_t *, timestamp_t *); 50 | 51 | extern float timestamp_diff(timestamp_t *, timestamp_t *); 52 | 53 | #if 0 54 | 55 | 56 | 57 | #if __BYTE_ORDER == __BIG_ENDIAN 58 | #define xntohll(N) (N) 59 | #define xhtonll(N) (N) 60 | #else 61 | #define xntohll(N) ((((uint64_t) ntohl(N)) << 32) + ntohl((N) >> 32)) 62 | #define xhtonll(N) ((((uint64_t) htonl(N)) << 32) + htonl((N) >> 32)) 63 | #endif 64 | 65 | enum { 66 | U_NUMBER, 67 | U_BYTES, 68 | U_BITS 69 | }; 70 | 71 | extern float read_delta; 72 | 73 | 74 | const char * xinet_ntop(struct sockaddr *, char *, socklen_t); 75 | 76 | 77 | extern float time_diff(timestamp_t *, timestamp_t *); 78 | extern float diff_now(timestamp_t *); 79 | 80 | extern uint64_t parse_size(const char *); 81 | 82 | extern int parse_date(const char *str, xdate_t *dst); 83 | 84 | #ifndef HAVE_STRDUP 85 | extern char *strdup(const char *); 86 | #endif 87 | 88 | extern char * timestamp2str(timestamp_t *ts, char *buf, size_t len); 89 | 90 | static inline char *xstrncat(char *dest, const char *src, size_t n) 91 | { 92 | return strncat(dest, src, n - strlen(dest) - 1); 93 | } 94 | 95 | static inline void xdate_to_ts(timestamp_t *dst, xdate_t *src) 96 | { 97 | dst->tv_sec = mktime(&src->d_tm); 98 | dst->tv_usec = src->d_usec; 99 | }; 100 | #endif 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /man/Makefile.am: -------------------------------------------------------------------------------- 1 | # -*- Makefile -*- 2 | 3 | dist_man8_MANS = bmon.8 4 | -------------------------------------------------------------------------------- /man/bmon.8: -------------------------------------------------------------------------------- 1 | .TH "bmon" "8" "" "Bandwidth Monitor" "bmon" 2 | .SH "NAME" 3 | bmon \- bandwidth monitor and rate estimator 4 | .SH "SYNOPSIS" 5 | .B bmon 6 | [\fB\-\-show\-all\fR] 7 | [\fB\-\-use\-si\fR] 8 | [\fB\-\-input\fR=\fIMODULE\fR] 9 | [\fB\-\-output\fR=\fIMODULE\fR] 10 | [OPTIONS...] 11 | 12 | .SH "DESCRIPTION" 13 | bmon is a monitoring and debugging tool to capture networking related 14 | statistics and prepare them visually in a human friendly way. It 15 | features various output methods including an interactive curses user 16 | interface and a programmable text output for scripting. 17 | 18 | .SH "OPTIONS" 19 | .PP 20 | \fB \-h\fR, \fB\-\-help\fR 21 | .RS 4 22 | Prints a short help text and exits\&. 23 | .RE 24 | .PP 25 | \fB \-V\fR, \fB\-\-version\fR 26 | .RS 4 27 | Prints the versioning identifier and exits\&. 28 | .RE 29 | .PP 30 | \fB \-i\fR, \fB\-\-input=\fRMODULE[:OPTIONS][,MODULE...] 31 | .RS 4 32 | Set list of input modules to load and use. Multiple modules can be used 33 | in parallel. bmon automatically loads a useful and working input module 34 | by default. See INPUT MODULES for more details. 35 | .RE 36 | .PP 37 | \fB \-o\fR, \fB\-\-output=\fRMODULE[:OPTIONS][,MODULE...] 38 | .RS 4 39 | Set list of output modules to load and use. Multiple modules can be used 40 | in parallel. By default, bmon will use the curses output mode, if that is 41 | not available due to an incompatible console it will fall back to a simple 42 | text mode. See OUTPUT MODULES for more details. 43 | .RE 44 | .PP 45 | \fB \-U\fR, \fB\-\-use\-si\fR 46 | .RS 4 47 | Use SI unit system (1KB = 1'000 bytes) instead of 1KB = 1'024 bytes. 48 | .RE 49 | .PP 50 | \fB \-f\fR, \fB\-\-configfile=\fRFILE 51 | .RS 4 52 | Set alternative path to configuration file. 53 | .RE 54 | .PP 55 | \fB \-p\fR, \fB\-\-policy=\fRPOLICY 56 | .RS 4 57 | Set policy defining which network interfaces to display. See 58 | INTERFACE SELECTION for more details. 59 | .RE 60 | .PP 61 | \fB \-a\fR, \fB\-\-show\-all\fR 62 | .RS 4 63 | Display all interfaces, even interface that are administratively down. 64 | .RE 65 | .PP 66 | \fB \-r\fR, \fB\-\-read\-interval=\fRFLOAT 67 | .RS 4 68 | Set interval in seconds in which input modules read statistics from their 69 | source. The default is 1.0 seconds. 70 | .RE 71 | .PP 72 | \fB \-R\fR, \fB\-\-rate\-interval=\fRFLOAT 73 | .RS 4 74 | Set interval in seconds in which the rate per counter is calculated. 75 | The default is 1.0 seconds. 76 | .RE 77 | .PP 78 | \fB \-b\fR, \fB\-\-use\-bit\fR 79 | .RS 4 80 | Show rates in bits per second instead of bytes per second. 81 | .RE 82 | .PP 83 | \fB \-L\fR, \fB\-\-lifetime=\fRFLOAT 84 | .RS 4 85 | Set lifetime of an element in seconds before it is no longer displayed 86 | without receiving any statistical updates. The default is 30 seconds. 87 | .RE 88 | 89 | .SH "INPUT MODULES" 90 | .PP 91 | Input modules provide statistical data about elements. Each element consists 92 | of attributes which represents a counter, a rate, or a percentage. Elements 93 | may carry additional child elements to represent a hierarchy. Each element is 94 | assigned to a group defined by the input module. Input modules are polled in 95 | the frequence of the configured read interval. 96 | .PP 97 | The following input modules are available: 98 | .TP 99 | \fBnetlink\fR 100 | Uses the Netlink protocol to collect interface and traffic control statistics 101 | from the kernel. This is the default input module. 102 | 103 | .TP 104 | \fBproc\fR 105 | Reads interface statistics from the /proc/net/dev file. This is considered a 106 | legacy interface and provided for backwards compatibily reasons. This is a 107 | fallback module if the Netlink interface is not available. 108 | 109 | .TP 110 | \fBdummy\fR 111 | Programmable input module for debugging and testing purposes. 112 | 113 | .TP 114 | \fBnull\fR 115 | No data collected. 116 | 117 | .PP 118 | To receive additional information about a module, run the module with the 119 | "help" option set like this: 120 | 121 | .PP 122 | .RS 4 123 | bmon \-i netlink:help 124 | .RE 125 | 126 | See MODULE CONFIGURATION for more details. 127 | 128 | .SH "OUTPUT MODULES" 129 | .PP 130 | Output modules display or export the statistical data collected by input 131 | modules. Multiple output modules can be run at the same time. bmon will 132 | not prevent possible conflicts such as multiple output modules writing to 133 | the console. 134 | .PP 135 | The following output modules exist: 136 | 137 | .TP 138 | \fBcurses\fR 139 | Interactive curses based text user interface providing real time rate 140 | estimations and a graphical representation of each attribute. Press '?' 141 | to display the quick reference guide. This is the default output mode. 142 | 143 | .TP 144 | \fBascii\fR 145 | Simple programmable text output intended for human consumption. Capable 146 | of printing list of interfaces, detailed counters and graphs to the 147 | console. This is the default fallback output mode if curses is not 148 | available. 149 | 150 | .TP 151 | \fBformat\fR 152 | Fully scriptable output mode inteded for consumption by other programs. 153 | See the module help text for additional information. 154 | 155 | .TP 156 | \fBnull\fR 157 | Disable output. 158 | 159 | .PP 160 | To receive additional information about a module, run the module with the 161 | "help" option set like this: 162 | 163 | .PP 164 | .RS 4 165 | bmon \-o curses:help 166 | .RE 167 | 168 | See MODULE CONFIGURATION for more details. 169 | 170 | .SH "MODULE CONFIGURATION" 171 | .PP 172 | The syntax to configure modules is as follows: 173 | .PP 174 | .RS 4 175 | ARGUMENT ::= mod1[:OPTS][,mod2[:OPTS]...] 176 | .br 177 | OPTS ::= OPTION[;OPTION...] 178 | .br 179 | OPTION ::= option[=value] 180 | .RE 181 | 182 | .PP 183 | Run the module with option "help" to receive the list of options for each 184 | module: 185 | 186 | .PP 187 | .RS 4 188 | bmon \-i module:help 189 | .RE 190 | 191 | .SH "INTERFACE SELECTION" 192 | .PP 193 | The following syntax is used to define the interface selection policy: 194 | .PP 195 | .RS 4 196 | SELECTION ::= NAME[,NAME[,...]] 197 | .br 198 | NAME ::= [!]interface 199 | .RE 200 | 201 | .PP 202 | The interface name may contain the character '*' which will act as a wildcard 203 | and represents any number of any character type, e.g. eth*, h*0, ... 204 | 205 | .PP 206 | Examples: 207 | 208 | .PP 209 | .RS 4 210 | lo,eth0,eth1 211 | .br 212 | eth*,!eth0 213 | .RE 214 | 215 | .SH "EXAMPLES" 216 | .PP 217 | To run bmon in curses mode monitoring the interfaces eth0 218 | and eth1: 219 | .PP 220 | .RS 4 221 | \fBbmon \-p eth0,eth1 \-o curses\fP 222 | .RE 223 | .PP 224 | To run bmon in format mode, monitoring any eth* interfaces, with a specified 225 | format string: 226 | .PP 227 | .RS 4 228 | \fBbmon \-p \(aqeth*\(aq \-o format:fmt=\(aq$(element:name) $(attr:rxrate:packets)\en\(aq\fP 229 | .RE 230 | .PP 231 | 232 | .SH "FILES" 233 | /etc/bmon.conf 234 | .br 235 | $HOME/.bmonrc 236 | 237 | .SH "SEE ALSO" 238 | .PP 239 | \fBip\fR(8), 240 | \fBnetstat\fR(8), 241 | \fBifconfig\fR(8), 242 | \fBnetlink\fR(7), 243 | 244 | .SH "AUTHOR" 245 | Thomas Graf among others 246 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | bmon 3 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | # -*- Makefile -*- 2 | 3 | bin_PROGRAMS = bmon 4 | 5 | bmon_CFLAGS = \ 6 | -I${top_srcdir}/include \ 7 | -I${top_builddir}/include \ 8 | -DSYSCONFDIR=\"$(sysconfdir)\" \ 9 | -D_GNU_SOURCE \ 10 | -Wall \ 11 | $(CURSES_CFLAGS) \ 12 | $(CONFUSE_CFLAGS) \ 13 | $(LIBNL_CFLAGS) \ 14 | $(LIBNL_ROUTE_CFLAGS) 15 | 16 | bmon_LDADD = \ 17 | $(CURSES_LIB) \ 18 | $(CONFUSE_LIBS) \ 19 | $(LIBNL_LIBS) \ 20 | $(LIBNL_ROUTE_LIBS) 21 | 22 | bmon_SOURCES = \ 23 | utils.c \ 24 | unit.c \ 25 | conf.c \ 26 | input.c \ 27 | output.c \ 28 | group.c \ 29 | element.c \ 30 | attr.c \ 31 | element_cfg.c \ 32 | history.c \ 33 | graph.c \ 34 | bmon.c \ 35 | module.c \ 36 | in_netlink.c \ 37 | in_null.c \ 38 | in_dummy.c \ 39 | in_proc.c \ 40 | in_sysctl.c \ 41 | out_null.c \ 42 | out_format.c \ 43 | out_ascii.c \ 44 | out_curses.c 45 | -------------------------------------------------------------------------------- /src/bmon.c: -------------------------------------------------------------------------------- 1 | /* 2 | * src/bmon.c Bandwidth Monitor 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | int start_time; 36 | 37 | struct reader_timing rtiming; 38 | 39 | static char *usage_text = 40 | "Usage: bmon [OPTION]...\n" \ 41 | "\n" \ 42 | "Options:\n" \ 43 | "Startup:\n" \ 44 | " -i, --input=MODPARM Input module(s)\n" \ 45 | " -o, --output=MODPARM Output module(s)\n" \ 46 | " -f, --configfile=PATH Alternative path to configuration file\n" \ 47 | " -h, --help Show this help text\n" \ 48 | " -V, --version Show version\n" \ 49 | "\n" \ 50 | "Input:\n" \ 51 | " -p, --policy=POLICY Element display policy (see below)\n" \ 52 | " -a, --show-all Show all elements (even disabled elements)\n" \ 53 | " -r, --read-interval=FLOAT Read interval in seconds (float)\n" \ 54 | " -R, --rate-interval=FLOAT Rate interval in seconds (float)\n" \ 55 | " -s, --sleep-interval=FLOAT Sleep time in seconds (float)\n" \ 56 | " -L, --lifetime=LIFETIME Lifetime of an element in seconds (float)\n" \ 57 | "\n" \ 58 | "Output:\n" \ 59 | " -U, --use-si Use SI units\n" \ 60 | " -b, --use-bit Display in bits instead of bytes\n" \ 61 | "\n" \ 62 | "Module configuration:\n" \ 63 | " modparm := MODULE:optlist,MODULE:optlist,...\n" \ 64 | " optlist := option;option;...\n" \ 65 | " option := TYPE[=VALUE]\n" \ 66 | "\n" \ 67 | " Examples:\n" \ 68 | " -o curses:ngraph=2\n" \ 69 | " -o list # Shows a list of available modules\n" \ 70 | " -o curses:help # Shows a help text for curses module\n" \ 71 | "\n" \ 72 | "Interface selection:\n" \ 73 | " policy := [!]simple_regexp,[!]simple_regexp,...\n" \ 74 | "\n" \ 75 | " Example: -p 'eth*,lo*,!eth1'\n" \ 76 | "\n" \ 77 | "Please see the bmon(8) man pages for full documentation.\n"; 78 | 79 | static void do_shutdown(void) 80 | { 81 | static int done; 82 | 83 | if (!done) { 84 | done = 1; 85 | module_shutdown(); 86 | } 87 | } 88 | 89 | static void sig_exit(void) 90 | { 91 | do_shutdown(); 92 | } 93 | 94 | void quit(const char *fmt, ...) 95 | { 96 | static int done; 97 | va_list args; 98 | 99 | va_start(args, fmt); 100 | vfprintf(stderr, fmt, args); 101 | va_end(args); 102 | 103 | if (!done) { 104 | done = 1; 105 | do_shutdown(); 106 | } 107 | 108 | exit(1); 109 | } 110 | 111 | static inline void print_version(void) 112 | { 113 | printf("bmon %s\n", PACKAGE_VERSION); 114 | printf("Copyright (C) 2001-2015 by Thomas Graf \n"); 115 | printf("Copyright (C) 2013 Red Hat, Inc.\n"); 116 | printf("bmon comes with ABSOLUTELY NO WARRANTY. This is free " \ 117 | "software, and you\nare welcome to redistribute it under " \ 118 | "certain conditions. See the source\ncode for details.\n"); 119 | } 120 | 121 | static void parse_args_pre(int argc, char *argv[]) 122 | { 123 | DBG("Parsing arguments pre state"); 124 | 125 | for (;;) 126 | { 127 | char *gostr = "+:hvVf:"; 128 | 129 | struct option long_opts[] = { 130 | {"help", 0, NULL, 'h'}, 131 | {"version", 0, NULL, 'v'}, 132 | {"configfile", 1, NULL, 'f'}, 133 | {NULL, 0, NULL, 0}, 134 | }; 135 | int c = getopt_long(argc, argv, gostr, long_opts, NULL); 136 | if (c == -1) 137 | break; 138 | 139 | switch (c) 140 | { 141 | case 'f': 142 | set_configfile(optarg); 143 | break; 144 | 145 | case 'h': 146 | print_version(); 147 | printf("\n%s", usage_text); 148 | exit(1); 149 | case 'V': 150 | case 'v': 151 | print_version(); 152 | exit(0); 153 | } 154 | } 155 | } 156 | 157 | static int parse_args_post(int argc, char *argv[]) 158 | { 159 | DBG("Parsing arguments post state"); 160 | 161 | optind = 1; 162 | 163 | for (;;) 164 | { 165 | char *gostr = "i:o:p:r:R:s:aUb" \ 166 | "L:hvVf:"; 167 | 168 | struct option long_opts[] = { 169 | {"input", 1, NULL, 'i'}, 170 | {"output", 1, NULL, 'o'}, 171 | {"policy", 1, NULL, 'p'}, 172 | {"read-interval", 1, NULL, 'r'}, 173 | {"rate-interval", 1, NULL, 'R'}, 174 | {"sleep-interval", 1, NULL, 's'}, 175 | {"show-all", 0, NULL, 'a'}, 176 | {"use-si", 0, NULL, 'U'}, 177 | {"use-bit", 0, NULL, 'b'}, 178 | {"lifetime", 1, NULL, 'L'}, 179 | {NULL, 0, NULL, 0}, 180 | }; 181 | int c = getopt_long(argc, argv, gostr, long_opts, NULL); 182 | if (c == -1) 183 | break; 184 | 185 | switch (c) 186 | { 187 | case 'i': 188 | if (input_set(optarg)) 189 | return 1; 190 | break; 191 | 192 | case 'o': 193 | if (output_set(optarg)) 194 | return 1; 195 | break; 196 | 197 | case 'p': 198 | cfg_setstr(cfg, "policy", optarg); 199 | break; 200 | 201 | case 'r': 202 | cfg_setfloat(cfg, "read_interval", strtod(optarg, NULL)); 203 | break; 204 | 205 | case 'R': 206 | cfg_setfloat(cfg, "rate_interval", strtod(optarg, NULL)); 207 | break; 208 | 209 | case 's': 210 | cfg_setint(cfg, "sleep_time", strtoul(optarg, NULL, 0)); 211 | break; 212 | 213 | case 'a': 214 | cfg_setbool(cfg, "show_all", cfg_true); 215 | break; 216 | 217 | case 'U': 218 | cfg_setbool(cfg, "use_si", cfg_true); 219 | break; 220 | 221 | case 'b': 222 | cfg_setbool(cfg, "use_bit", cfg_true); 223 | break; 224 | 225 | case 'L': 226 | cfg_setint(cfg, "lifetime", strtoul(optarg, NULL, 0)); 227 | break; 228 | 229 | case 'f': 230 | /* Already handled in pre getopt loop */ 231 | break; 232 | 233 | default: 234 | quit("Aborting...\n"); 235 | break; 236 | 237 | } 238 | } 239 | 240 | return 0; 241 | } 242 | 243 | #if 0 244 | static void calc_variance(timestamp_t *c, timestamp_t *ri) 245 | { 246 | float v = (ts_to_float(c) / ts_to_float(ri)) * 100.0f; 247 | 248 | rtiming.rt_variance.v_error = v; 249 | rtiming.rt_variance.v_total += v; 250 | 251 | if (v > rtiming.rt_variance.v_max) 252 | rtiming.rt_variance.v_max = v; 253 | 254 | if (v < rtiming.rt_variance.v_min) 255 | rtiming.rt_variance.v_min = v; 256 | } 257 | #endif 258 | 259 | int main(int argc, char *argv[]) 260 | { 261 | unsigned long sleep_time; 262 | double read_interval; 263 | 264 | start_time = time(NULL); 265 | memset(&rtiming, 0, sizeof(rtiming)); 266 | rtiming.rt_variance.v_min = FLT_MAX; 267 | 268 | /* 269 | * Early initialization before reading config 270 | */ 271 | conf_init_pre(); 272 | parse_args_pre(argc, argv); 273 | 274 | /* 275 | * Reading the configuration file */ 276 | configfile_read(); 277 | 278 | /* 279 | * Late initialization after reading config 280 | */ 281 | if (parse_args_post(argc, argv)) 282 | return 1; 283 | conf_init_post(); 284 | 285 | module_init(); 286 | 287 | read_interval = cfg_read_interval; 288 | sleep_time = cfg_getint(cfg, "sleep_time"); 289 | 290 | if (((double) sleep_time / 1000000.0f) > read_interval) 291 | sleep_time = (unsigned long) (read_interval * 1000000.0f); 292 | 293 | DBG("Entering mainloop..."); 294 | 295 | do { 296 | /* 297 | * E := Elapsed time 298 | * NR := Next Read 299 | * LR := Last Read 300 | * RI := Read Interval 301 | * ST := Sleep Time 302 | * C := Correction 303 | */ 304 | timestamp_t e, ri, tmp; 305 | unsigned long st; 306 | 307 | float_to_timestamp(&ri, read_interval); 308 | 309 | /* 310 | * NR := NOW 311 | */ 312 | update_timestamp(&rtiming.rt_next_read); 313 | 314 | for (;;) { 315 | output_pre(); 316 | 317 | /* 318 | * E := NOW 319 | */ 320 | update_timestamp(&e); 321 | 322 | /* 323 | * IF NR <= E THEN 324 | */ 325 | if (timestamp_le(&rtiming.rt_next_read, &e)) { 326 | timestamp_t c; 327 | 328 | /* 329 | * C := (NR - E) 330 | */ 331 | timestamp_sub(&c, &rtiming.rt_next_read, &e); 332 | 333 | //calc_variance(&c, &ri); 334 | 335 | /* 336 | * LR := E 337 | */ 338 | copy_timestamp(&rtiming.rt_last_read, &e); 339 | 340 | /* 341 | * NR := E + RI + C 342 | */ 343 | timestamp_add(&rtiming.rt_next_read, &e, &ri); 344 | timestamp_add(&rtiming.rt_next_read, 345 | &rtiming.rt_next_read, &c); 346 | 347 | 348 | reset_update_flags(); 349 | input_read(); 350 | free_unused_elements(); 351 | output_draw(); 352 | output_post(); 353 | } 354 | 355 | /* 356 | * ST := Configured ST 357 | */ 358 | st = sleep_time; 359 | 360 | /* 361 | * IF (NR - E) < ST THEN 362 | */ 363 | timestamp_sub(&tmp, &rtiming.rt_next_read, &e); 364 | 365 | if (tmp.tv_sec < 0) 366 | continue; 367 | 368 | if (tmp.tv_sec == 0 && tmp.tv_usec < st) { 369 | if (tmp.tv_usec < 0) 370 | continue; 371 | /* 372 | * ST := (NR - E) 373 | */ 374 | st = tmp.tv_usec; 375 | } 376 | 377 | /* 378 | * SLEEP(ST) 379 | */ 380 | usleep(st); 381 | } 382 | } while (0); 383 | 384 | return 0; /* buddha says i'll never be reached */ 385 | } 386 | 387 | static void __init bmon_init(void) 388 | { 389 | atexit(&sig_exit); 390 | } 391 | -------------------------------------------------------------------------------- /src/element.c: -------------------------------------------------------------------------------- 1 | /* 2 | * src/element.c Elements 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | static LIST_HEAD(allowed); 35 | static LIST_HEAD(denied); 36 | 37 | static int match_mask(const struct policy *p, const char *str) 38 | { 39 | int i, n; 40 | char c; 41 | 42 | if (!p || !str) 43 | return 0; 44 | 45 | for (i = 0, n = 0; p->p_rule[i] != '\0'; i++) { 46 | if (p->p_rule[i] == '*') { 47 | c = tolower(p->p_rule[i + 1]); 48 | 49 | if (c == '\0') 50 | return 1; 51 | 52 | while (tolower(str[n]) != c) 53 | if (str[n++] == '\0') 54 | return 0; 55 | } else if (tolower(p->p_rule[i]) != tolower(str[n++])) 56 | return 0; 57 | } 58 | 59 | return str[n] == '\0' ? 1 : 0; 60 | } 61 | 62 | int element_allowed(const char *name, struct element_cfg *cfg) 63 | { 64 | struct policy *p; 65 | 66 | if (cfg) { 67 | if (cfg->ec_flags & ELEMENT_CFG_HIDE) 68 | return 0; 69 | else if (cfg->ec_flags & ELEMENT_CFG_SHOW) 70 | return 1; 71 | } 72 | 73 | list_for_each_entry(p, &denied, p_list) 74 | if (match_mask(p, name)) 75 | return 0; 76 | 77 | if (!list_empty(&allowed)) { 78 | list_for_each_entry(p, &allowed, p_list) 79 | if (match_mask(p, name)) 80 | return 1; 81 | 82 | return 0; 83 | } 84 | 85 | return 1; 86 | } 87 | 88 | void element_parse_policy(const char *policy) 89 | { 90 | char *start, *copy, *save = NULL, *tok; 91 | struct policy *p; 92 | 93 | if (!policy) 94 | return; 95 | 96 | copy = strdup(policy); 97 | start = copy; 98 | 99 | while ((tok = strtok_r(start, ",", &save)) != NULL) { 100 | start = NULL; 101 | 102 | p = xcalloc(1, sizeof(*p)); 103 | 104 | if (*tok == '!') { 105 | p->p_rule = strdup(++tok); 106 | list_add_tail(&p->p_list, &denied); 107 | } else { 108 | p->p_rule = strdup(tok); 109 | list_add_tail(&p->p_list, &allowed); 110 | } 111 | } 112 | 113 | xfree(copy); 114 | } 115 | 116 | static struct element *__lookup_element(struct element_group *group, 117 | const char *name, uint32_t id, 118 | struct element *parent) 119 | { 120 | struct list_head *list; 121 | struct element *e; 122 | 123 | if (parent) 124 | list = &parent->e_childs; 125 | else 126 | list = &group->g_elements; 127 | 128 | list_for_each_entry(e, list, e_list) 129 | if (!strcmp(name, e->e_name) && e->e_id == id) 130 | return e; 131 | 132 | return NULL; 133 | } 134 | 135 | struct element *element_lookup(struct element_group *group, const char *name, 136 | uint32_t id, struct element *parent, int flags) 137 | { 138 | struct element_cfg *cfg; 139 | struct element *e; 140 | int i; 141 | 142 | if (!group) 143 | BUG(); 144 | 145 | if ((e = __lookup_element(group, name, id, parent))) 146 | return e; 147 | 148 | if (!(flags & ELEMENT_CREAT)) 149 | return NULL; 150 | 151 | cfg = element_cfg_lookup(name); 152 | if (!element_allowed(name, cfg)) 153 | return NULL; 154 | 155 | DBG("Creating element %d \"%s\"", id, name); 156 | 157 | e = xcalloc(1, sizeof(*e)); 158 | 159 | init_list_head(&e->e_list); 160 | init_list_head(&e->e_childs); 161 | init_list_head(&e->e_info_list); 162 | init_list_head(&e->e_attr_sorted); 163 | 164 | for (i = 0; i < ATTR_HASH_SIZE; i++) 165 | init_list_head(&e->e_attrhash[i]); 166 | 167 | e->e_name = strdup(name); 168 | e->e_id = id; 169 | e->e_parent = parent; 170 | e->e_group = group; 171 | e->e_lifecycles = get_lifecycles(); 172 | e->e_flags = ELEMENT_FLAG_CREATED; 173 | e->e_cfg = cfg; 174 | 175 | if (e->e_cfg) { 176 | if (e->e_cfg->ec_description) 177 | element_update_info(e, "Description", 178 | e->e_cfg->ec_description); 179 | 180 | element_set_rxmax(e, e->e_cfg->ec_rxmax); 181 | element_set_txmax(e, e->e_cfg->ec_txmax); 182 | } 183 | 184 | if (parent) { 185 | DBG("Attached to parent %d \"%s\"", parent->e_id, parent->e_name); 186 | list_add_tail(&e->e_list, &parent->e_childs); 187 | } else { 188 | DBG("Attached to group %s", group->g_name); 189 | list_add_tail(&e->e_list, &group->g_elements); 190 | } 191 | 192 | group->g_nelements++; 193 | 194 | return e; 195 | } 196 | 197 | void element_free(struct element *e) 198 | { 199 | struct info *info, *ninfo; 200 | struct element *c, *cnext; 201 | struct attr *a, *an; 202 | int i; 203 | 204 | list_for_each_entry_safe(c, cnext, &e->e_childs, e_list) 205 | element_free(c); 206 | 207 | list_for_each_entry_safe(info, ninfo, &e->e_info_list, i_list) { 208 | xfree(info->i_name); 209 | xfree(info->i_value); 210 | list_del(&info->i_list); 211 | xfree(info); 212 | } 213 | 214 | for (i = 0; i < ATTR_HASH_SIZE; i++) 215 | list_for_each_entry_safe(a, an, &e->e_attrhash[i], a_list) 216 | attr_free(a); 217 | 218 | if (e->e_group->g_current == e) { 219 | element_select_prev(); 220 | if (e->e_group->g_current == e) 221 | e->e_group->g_current = NULL; 222 | } 223 | 224 | list_del(&e->e_list); 225 | e->e_group->g_nelements--; 226 | 227 | xfree(e->e_name); 228 | xfree(e); 229 | } 230 | 231 | #if 0 232 | if (item->i_group->g_selected == item) { 233 | if (item_select_prev() == END_OF_LIST) { 234 | if (group_select_prev() == END_OF_LIST) { 235 | if (node_select_prev() != END_OF_LIST) 236 | item_select_last(); 237 | } else 238 | item_select_last(); 239 | } 240 | } 241 | #endif 242 | 243 | #if 0 244 | 245 | void item_delete(struct item *item) 246 | { 247 | int m; 248 | struct item *child; 249 | 250 | for (m = 0; m < ATTR_HASH_MAX; m++) { 251 | struct attr *a, *next; 252 | for (a = item->i_attrs[m]; a; a = next) { 253 | next = a->a_next; 254 | xfree(a); 255 | } 256 | } 257 | 258 | if (item->i_group->g_selected == item) { 259 | if (item_select_prev() == END_OF_LIST) { 260 | if (group_select_prev() == END_OF_LIST) { 261 | if (node_select_prev() != END_OF_LIST) 262 | item_select_last(); 263 | } else 264 | item_select_last(); 265 | } 266 | } 267 | 268 | unlink_item(item); 269 | item->i_group->g_nitems--; 270 | 271 | for (child = item->i_childs; child; child = child->i_next) 272 | item_delete(child); 273 | 274 | if (item->i_path) 275 | xfree(item->i_path); 276 | 277 | xfree(item); 278 | } 279 | 280 | #endif 281 | 282 | void element_reset_update_flag(struct element_group *g, 283 | struct element *e, void *arg) 284 | { 285 | DBG("Reseting update flag of %s", e->e_name); 286 | e->e_flags &= ~ELEMENT_FLAG_UPDATED; 287 | } 288 | 289 | /** 290 | * Needs to be called after updating all attributes of an element 291 | */ 292 | void element_notify_update(struct element *e, timestamp_t *ts) 293 | { 294 | struct attr *a; 295 | int i; 296 | 297 | e->e_flags |= ELEMENT_FLAG_UPDATED; 298 | 299 | if (ts == NULL) 300 | ts = &rtiming.rt_last_read; 301 | 302 | for (i = 0; i < ATTR_HASH_SIZE; i++) 303 | list_for_each_entry(a, &e->e_attrhash[i], a_list) 304 | attr_notify_update(a, ts); 305 | 306 | if (e->e_usage_attr && e->e_cfg && 307 | (a = attr_lookup(e, e->e_usage_attr->ad_id))) { 308 | attr_calc_usage(a, &e->e_rx_usage, &e->e_tx_usage, 309 | e->e_cfg->ec_rxmax, e->e_cfg->ec_txmax); 310 | } else { 311 | e->e_rx_usage = FLT_MAX; 312 | e->e_tx_usage = FLT_MAX; 313 | } 314 | } 315 | 316 | void element_lifesign(struct element *e, int n) 317 | { 318 | e->e_lifecycles = n * get_lifecycles(); 319 | } 320 | 321 | void element_check_if_dead(struct element_group *g, 322 | struct element *e, void *arg) 323 | { 324 | if (--(e->e_lifecycles) <= 0) { 325 | element_free(e); 326 | DBG("Deleting dead element %s", e->e_name); 327 | } 328 | } 329 | 330 | void element_foreach_attr(struct element *e, 331 | void (*cb)(struct element *e, 332 | struct attr *, void *), 333 | void *arg) 334 | { 335 | struct attr *a; 336 | 337 | list_for_each_entry(a, &e->e_attr_sorted, a_sort_list) 338 | cb(e, a, arg); 339 | } 340 | 341 | int element_set_key_attr(struct element *e, const char *major, 342 | const char * minor) 343 | { 344 | if (!(e->e_key_attr[GT_MAJOR] = attr_def_lookup(major))) 345 | return -ENOENT; 346 | 347 | if (!(e->e_key_attr[GT_MINOR] = attr_def_lookup(minor))) 348 | return -ENOENT; 349 | 350 | return 0; 351 | } 352 | 353 | int element_set_usage_attr(struct element *e, const char *usage) 354 | { 355 | if (!(e->e_usage_attr = attr_def_lookup(usage))) 356 | return -ENOENT; 357 | 358 | return 0; 359 | } 360 | 361 | void element_pick_from_policy(struct element_group *g) 362 | { 363 | if (!list_empty(&allowed)) { 364 | struct policy *p; 365 | 366 | list_for_each_entry(p, &allowed, p_list) { 367 | struct element *e; 368 | 369 | list_for_each_entry(e, &g->g_elements, e_list) { 370 | if (match_mask(p, e->e_name)) { 371 | g->g_current = e; 372 | return; 373 | } 374 | } 375 | } 376 | } 377 | 378 | element_select_first(); 379 | } 380 | 381 | struct element *element_current(void) 382 | { 383 | struct element_group *g; 384 | 385 | if (!(g = group_current())) 386 | return NULL; 387 | 388 | /* 389 | * If no element is picked yet, pick a default interface according to 390 | * the selection policy. 391 | */ 392 | if (!g->g_current) 393 | element_pick_from_policy(g); 394 | 395 | return g->g_current; 396 | } 397 | 398 | struct element *element_select_first(void) 399 | { 400 | struct element_group *g; 401 | 402 | if (!(g = group_current())) 403 | return NULL; 404 | 405 | if (list_empty(&g->g_elements)) 406 | g->g_current = NULL; 407 | else 408 | g->g_current = list_first_entry(&g->g_elements, 409 | struct element, e_list); 410 | 411 | return g->g_current; 412 | } 413 | 414 | struct element *element_select_last(void) 415 | { 416 | struct element_group *g; 417 | 418 | if (!(g = group_current())) 419 | return NULL; 420 | 421 | if (list_empty(&g->g_elements)) 422 | g->g_current = NULL; 423 | else { 424 | struct element *e; 425 | 426 | e = list_entry(g->g_elements.prev, struct element, e_list); 427 | 428 | while (!list_empty(&e->e_childs)) 429 | e = list_entry(e->e_childs.prev, struct element, 430 | e_list); 431 | 432 | g->g_current = e; 433 | } 434 | 435 | return g->g_current; 436 | } 437 | 438 | struct element *element_select_next(void) 439 | { 440 | struct element_group *g; 441 | struct element *e; 442 | 443 | if (!(g = group_current())) 444 | return NULL; 445 | 446 | if (!(e = g->g_current)) 447 | return element_select_first(); 448 | 449 | if (!list_empty(&e->e_childs)) 450 | e = list_first_entry(&e->e_childs, struct element, e_list); 451 | else { 452 | /* 453 | * move upwards until we have no parent or there is a next 454 | * entry in the list 455 | */ 456 | while (e->e_parent && e->e_list.next == &e->e_parent->e_childs) 457 | e = e->e_parent; 458 | 459 | if (!e->e_parent && e->e_list.next == &g->g_elements) { 460 | group_select_next(); 461 | return element_select_first(); 462 | } else 463 | e = list_entry(e->e_list.next, struct element, e_list); 464 | } 465 | 466 | g->g_current = e; 467 | 468 | return e; 469 | } 470 | 471 | struct element *element_select_prev(void) 472 | { 473 | struct element_group *g; 474 | struct element *e; 475 | 476 | if (!(g = group_current())) 477 | return NULL; 478 | 479 | if (!(e = g->g_current)) 480 | return element_select_last(); 481 | 482 | if (!e->e_parent && e->e_list.prev == &g->g_elements) { 483 | group_select_prev(); 484 | return element_select_last(); 485 | } 486 | 487 | if (e->e_parent && e->e_list.prev == &e->e_parent->e_childs) 488 | e = e->e_parent; 489 | else { 490 | e = list_entry(e->e_list.prev, struct element, e_list); 491 | 492 | while (!list_empty(&e->e_childs)) 493 | e = list_entry(e->e_childs.prev, struct element, 494 | e_list); 495 | } 496 | 497 | g->g_current = e; 498 | 499 | return e; 500 | } 501 | 502 | static struct info *element_info_lookup(struct element *e, const char *name) 503 | { 504 | struct info *i; 505 | 506 | list_for_each_entry(i, &e->e_info_list, i_list) 507 | if (!strcmp(i->i_name, name)) 508 | return i; 509 | 510 | return NULL; 511 | } 512 | 513 | void element_update_info(struct element *e, const char *name, const char *value) 514 | { 515 | struct info *i; 516 | 517 | if ((i = element_info_lookup(e, name))) { 518 | xfree(i->i_value); 519 | i->i_value = strdup(value); 520 | return; 521 | } 522 | 523 | DBG("Created element info %s (\"%s\")", name, value); 524 | 525 | i = xcalloc(1, sizeof(*i)); 526 | i->i_name = strdup(name); 527 | i->i_value = strdup(value); 528 | 529 | e->e_ninfo++; 530 | 531 | list_add_tail(&i->i_list, &e->e_info_list); 532 | } 533 | 534 | void element_set_txmax(struct element *e, uint64_t max) 535 | { 536 | char buf[32]; 537 | 538 | if (!e->e_cfg) 539 | e->e_cfg = element_cfg_create(e->e_name); 540 | 541 | if (e->e_cfg->ec_txmax != max) 542 | e->e_cfg->ec_txmax = max; 543 | 544 | unit_bit2str(e->e_cfg->ec_txmax * 8, buf, sizeof(buf)); 545 | element_update_info(e, "TxMax", buf); 546 | } 547 | 548 | void element_set_rxmax(struct element *e, uint64_t max) 549 | { 550 | char buf[32]; 551 | 552 | if (!e->e_cfg) 553 | e->e_cfg = element_cfg_create(e->e_name); 554 | 555 | if (e->e_cfg->ec_rxmax != max) 556 | e->e_cfg->ec_rxmax = max; 557 | 558 | unit_bit2str(e->e_cfg->ec_rxmax * 8, buf, sizeof(buf)); 559 | element_update_info(e, "RxMax", buf); 560 | } 561 | -------------------------------------------------------------------------------- /src/element_cfg.c: -------------------------------------------------------------------------------- 1 | /* 2 | * element_cfg.c Element Configuration 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | static LIST_HEAD(cfg_list); 33 | 34 | struct element_cfg *element_cfg_alloc(const char *name) 35 | { 36 | struct element_cfg *ec; 37 | 38 | if ((ec = element_cfg_lookup(name))) { 39 | ec->ec_refcnt++; 40 | return ec; 41 | } 42 | 43 | ec = xcalloc(1, sizeof(*ec)); 44 | ec->ec_name = strdup(name); 45 | ec->ec_refcnt = 1; 46 | 47 | list_add_tail(&ec->ec_list, &cfg_list); 48 | 49 | return ec; 50 | } 51 | 52 | struct element_cfg *element_cfg_create(const char *name) 53 | { 54 | struct element_cfg *cfg; 55 | 56 | if (!(cfg = element_cfg_lookup(name))) 57 | cfg = element_cfg_alloc(name); 58 | 59 | return cfg; 60 | } 61 | 62 | static void __element_cfg_free(struct element_cfg *ec) 63 | { 64 | list_del(&ec->ec_list); 65 | 66 | xfree(ec->ec_name); 67 | xfree(ec->ec_description); 68 | xfree(ec); 69 | } 70 | 71 | void element_cfg_free(struct element_cfg *ec) 72 | { 73 | if (!ec || --ec->ec_refcnt) 74 | return; 75 | 76 | __element_cfg_free(ec); 77 | } 78 | 79 | struct element_cfg *element_cfg_lookup(const char *name) 80 | { 81 | struct element_cfg *ec; 82 | 83 | list_for_each_entry(ec, &cfg_list, ec_list) 84 | if (!strcmp(name, ec->ec_name)) 85 | return ec; 86 | 87 | return NULL; 88 | } 89 | 90 | static void __exit __element_cfg_exit(void) 91 | { 92 | struct element_cfg *ec, *n; 93 | 94 | list_for_each_entry_safe(ec, n, &cfg_list, ec_list) 95 | __element_cfg_free(ec); 96 | } 97 | -------------------------------------------------------------------------------- /src/graph.c: -------------------------------------------------------------------------------- 1 | /* 2 | * graph.c Graph creation utility 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | size_t graph_row_size(struct graph_cfg *cfg) 36 | { 37 | /* +1 for trailing \0 */ 38 | return cfg->gc_width + 1; 39 | } 40 | 41 | static inline size_t table_size(struct graph_cfg *cfg) 42 | { 43 | return cfg->gc_height * graph_row_size(cfg); 44 | } 45 | 46 | static inline char *at_row(struct graph_cfg *cfg, char *col, int nrow) 47 | { 48 | return col + (nrow * graph_row_size(cfg)); 49 | } 50 | 51 | static inline char *at_col(char *row, int ncol) 52 | { 53 | return row + ncol; 54 | } 55 | 56 | static inline char *tbl_pos(struct graph_cfg *cfg, char *tbl, int nrow, int ncol) 57 | { 58 | return at_col(at_row(cfg, tbl, nrow), ncol); 59 | } 60 | 61 | static void fill_table(struct graph *g, struct graph_table *tbl, 62 | struct history *h, struct history_store *data) 63 | { 64 | struct graph_cfg *cfg = &g->g_cfg; 65 | uint64_t max = 0; 66 | double v; 67 | int i, n, t; 68 | float half_step, step; 69 | 70 | if (!tbl->gt_table) { 71 | tbl->gt_table = xcalloc(table_size(cfg), sizeof(char)); 72 | tbl->gt_scale = xcalloc(cfg->gc_height, sizeof(double)); 73 | } 74 | 75 | memset(tbl->gt_table, cfg->gc_background, table_size(cfg)); 76 | 77 | /* end each line with a \0 */ 78 | for (i = 0; i < cfg->gc_height; i++) 79 | *tbl_pos(cfg, tbl->gt_table, i, cfg->gc_width) = '\0'; 80 | 81 | /* leave table blank if there is no data */ 82 | if (!h || !data->hs_data) 83 | return; 84 | 85 | if (cfg->gc_width > h->h_definition->hd_size) 86 | BUG(); 87 | 88 | /* find the largest peak */ 89 | for (n = h->h_index, i = 0; i < cfg->gc_width; i++) { 90 | if (--n < 0) 91 | n = h->h_definition->hd_size - 1; 92 | v = history_data(h, data, n); 93 | if (v != HISTORY_UNKNOWN && max < v) 94 | max = v; 95 | } 96 | 97 | step = (double) max / (double) cfg->gc_height; 98 | half_step = step / 2.0f; 99 | 100 | for (i = 0; i < cfg->gc_height; i++) 101 | tbl->gt_scale[i] = (double) (i + 1) * step; 102 | 103 | for (n = h->h_index, i = 0; i < cfg->gc_width; i++) { 104 | char * col = at_col(tbl->gt_table, i); 105 | 106 | if (--n < 0) 107 | n = h->h_definition->hd_size - 1; 108 | v = history_data(h, data, n); 109 | 110 | if (v == HISTORY_UNKNOWN) { 111 | for (t = 0; t < cfg->gc_height; t++) 112 | *(at_row(cfg, col, t)) = cfg->gc_unknown; 113 | } else if (v > 0) { 114 | *(at_row(cfg, col, 0)) = cfg->gc_noise; 115 | 116 | for (t = 0; t < cfg->gc_height; t++) 117 | if (v >= (tbl->gt_scale[t] - half_step)) 118 | *(at_row(cfg, col, t)) = cfg->gc_foreground; 119 | } 120 | } 121 | 122 | n = (cfg->gc_height / 3) * 2; 123 | if (n >= cfg->gc_height) 124 | n = (cfg->gc_height - 1); 125 | 126 | v = unit_divisor(tbl->gt_scale[n], cfg->gc_unit, 127 | &tbl->gt_y_unit, NULL); 128 | 129 | for (i = 0; i < cfg->gc_height; i++) 130 | tbl->gt_scale[i] /= v; 131 | } 132 | 133 | struct graph *graph_alloc(struct history *h, struct graph_cfg *cfg) 134 | { 135 | struct graph *g; 136 | 137 | if (!cfg->gc_height) 138 | BUG(); 139 | 140 | g = xcalloc(1, sizeof(*g)); 141 | 142 | memcpy(&g->g_cfg, cfg, sizeof(*cfg)); 143 | 144 | if (h != NULL && 145 | (cfg->gc_width > h->h_definition->hd_size || !cfg->gc_width)) 146 | g->g_cfg.gc_width = h->h_definition->hd_size; 147 | 148 | if (!g->g_cfg.gc_width) 149 | BUG(); 150 | 151 | return g; 152 | } 153 | 154 | void graph_refill(struct graph *g, struct history *h) 155 | { 156 | fill_table(g, &g->g_rx, h, h ? &h->h_rx : NULL); 157 | fill_table(g, &g->g_tx, h, h ? &h->h_tx : NULL); 158 | } 159 | 160 | void graph_free(struct graph *g) 161 | { 162 | if (!g) 163 | return; 164 | 165 | xfree(g->g_rx.gt_table); 166 | xfree(g->g_rx.gt_scale); 167 | xfree(g->g_tx.gt_table); 168 | xfree(g->g_tx.gt_scale); 169 | xfree(g); 170 | } 171 | 172 | #if 0 173 | 174 | void new_graph(void) 175 | { 176 | if (ngraphs >= (MAX_GRAPHS - 1)) 177 | return; 178 | set_ngraphs_hard(ngraphs + 1); 179 | } 180 | 181 | void del_graph(void) 182 | { 183 | if (ngraphs <= 1) 184 | return; 185 | set_ngraphs_hard(ngraphs - 1); 186 | } 187 | 188 | int next_graph(void) 189 | { 190 | struct item *it = item_current(); 191 | if (it == NULL) 192 | return EMPTY_LIST; 193 | 194 | if (it->i_graph_sel >= (ngraphs - 1)) 195 | it->i_graph_sel = 0; 196 | else 197 | it->i_graph_sel++; 198 | 199 | return 0; 200 | } 201 | 202 | int prev_graph(void) 203 | { 204 | struct item *it = item_current(); 205 | if (it == NULL) 206 | return EMPTY_LIST; 207 | 208 | if (it->i_graph_sel <= 0) 209 | it->i_graph_sel = ngraphs - 1; 210 | else 211 | it->i_graph_sel--; 212 | 213 | return 0; 214 | } 215 | 216 | #endif 217 | -------------------------------------------------------------------------------- /src/group.c: -------------------------------------------------------------------------------- 1 | /* 2 | * group.c Group Management 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | static LIST_HEAD(titles_list); 32 | static LIST_HEAD(group_list); 33 | static unsigned int ngroups; 34 | static struct element_group *current_group; 35 | 36 | static void __group_foreach_element(struct element_group *g, 37 | struct list_head *list, 38 | void (*cb)(struct element_group *, 39 | struct element *, void *), 40 | void *arg) 41 | { 42 | struct element *e, *n; 43 | 44 | list_for_each_entry_safe(e, n, list, e_list) { 45 | cb(g, e, arg); 46 | 47 | if (!list_empty(&e->e_childs)) 48 | __group_foreach_element(g, &e->e_childs, cb, arg); 49 | } 50 | } 51 | 52 | void group_foreach_element(struct element_group *g, 53 | void (*cb)(struct element_group *, 54 | struct element *, void *), 55 | void *arg) 56 | { 57 | __group_foreach_element(g, &g->g_elements, cb, arg); 58 | } 59 | 60 | void group_foreach_recursive(void (*cb)(struct element_group *, 61 | struct element *, void *), 62 | void *arg) 63 | { 64 | struct element_group *g, *n; 65 | 66 | list_for_each_entry_safe(g, n, &group_list, g_list) 67 | __group_foreach_element(g, &g->g_elements, cb, arg); 68 | } 69 | 70 | void group_foreach(void (*cb)(struct element_group *, void *), void *arg) 71 | { 72 | struct element_group *g, *n; 73 | 74 | list_for_each_entry_safe(g, n, &group_list, g_list) 75 | cb(g, arg); 76 | } 77 | 78 | struct element_group *group_select_first(void) 79 | { 80 | if (list_empty(&group_list)) 81 | current_group = NULL; 82 | else 83 | current_group = list_first_entry(&group_list, 84 | struct element_group, g_list); 85 | 86 | return current_group; 87 | } 88 | 89 | struct element_group *group_select_last(void) 90 | { 91 | if (list_empty(&group_list)) 92 | current_group = NULL; 93 | else 94 | current_group = list_entry(group_list.prev, 95 | struct element_group, g_list); 96 | 97 | return current_group; 98 | } 99 | 100 | struct element_group *group_select_next(void) 101 | { 102 | if (!current_group) 103 | return group_select_first(); 104 | 105 | if (current_group->g_list.next != &group_list) 106 | current_group = list_entry(current_group->g_list.next, 107 | struct element_group, 108 | g_list); 109 | else 110 | return group_select_first(); 111 | 112 | return current_group; 113 | } 114 | 115 | struct element_group *group_select_prev(void) 116 | { 117 | if (!current_group) 118 | return group_select_last(); 119 | 120 | if (current_group->g_list.prev != &group_list) 121 | current_group = list_entry(current_group->g_list.prev, 122 | struct element_group, 123 | g_list); 124 | else 125 | return group_select_last(); 126 | 127 | return current_group; 128 | } 129 | 130 | struct element_group *group_current(void) 131 | { 132 | if (current_group == NULL) 133 | current_group = group_select_first(); 134 | 135 | return current_group; 136 | } 137 | 138 | struct element_group *group_lookup(const char *name, int flags) 139 | { 140 | struct element_group *g; 141 | struct group_hdr *hdr; 142 | 143 | list_for_each_entry(g, &group_list, g_list) 144 | if (!strcmp(name, g->g_name)) 145 | return g; 146 | 147 | if (!(flags & GROUP_CREATE)) 148 | return NULL; 149 | 150 | if (!(hdr = group_lookup_hdr(name))) { 151 | fprintf(stderr, "Cannot find title for group \"%s\"\n", name); 152 | return NULL; 153 | } 154 | 155 | g = xcalloc(1, sizeof(*g)); 156 | 157 | init_list_head(&g->g_elements); 158 | 159 | g->g_name = hdr->gh_name; 160 | g->g_hdr = hdr; 161 | 162 | list_add_tail(&g->g_list, &group_list); 163 | ngroups++; 164 | 165 | return g; 166 | } 167 | 168 | static void group_free(struct element_group *g) 169 | { 170 | struct element *e, *n; 171 | struct element_group *next; 172 | 173 | if (current_group == g) { 174 | next = group_select_next(); 175 | if (!next || next == g) 176 | current_group = NULL; 177 | } 178 | 179 | list_for_each_entry_safe(e, n, &g->g_elements, e_list) 180 | element_free(e); 181 | 182 | xfree(g); 183 | } 184 | 185 | void reset_update_flags(void) 186 | { 187 | group_foreach_recursive(&element_reset_update_flag, NULL); 188 | } 189 | 190 | void free_unused_elements(void) 191 | { 192 | group_foreach_recursive(&element_check_if_dead, NULL); 193 | } 194 | 195 | struct group_hdr *group_lookup_hdr(const char *name) 196 | { 197 | struct group_hdr *hdr; 198 | 199 | list_for_each_entry(hdr, &titles_list, gh_list) 200 | if (!strcmp(hdr->gh_name, name)) 201 | return hdr; 202 | 203 | return NULL; 204 | } 205 | 206 | int group_new_hdr(const char *name, const char *title, 207 | const char *col1, const char *col2, 208 | const char *col3, const char *col4) 209 | { 210 | struct group_hdr *hdr; 211 | 212 | if (group_lookup_hdr(name)) 213 | return -EEXIST; 214 | 215 | hdr = xcalloc(1, sizeof(*hdr)); 216 | 217 | init_list_head(&hdr->gh_list); 218 | 219 | hdr->gh_name = strdup(name); 220 | hdr->gh_title = strdup(title); 221 | 222 | hdr->gh_column[0] = strdup(col1); 223 | hdr->gh_column[1] = strdup(col2); 224 | hdr->gh_column[2] = strdup(col3); 225 | hdr->gh_column[3] = strdup(col4); 226 | 227 | list_add_tail(&hdr->gh_list, &titles_list); 228 | 229 | DBG("New group title %s \"%s\"", name, title); 230 | 231 | return 0; 232 | } 233 | 234 | int group_new_derived_hdr(const char *name, const char *title, 235 | const char *template) 236 | { 237 | struct group_hdr *t; 238 | 239 | if (group_lookup_hdr(name)) 240 | return -EEXIST; 241 | 242 | if (!(t = group_lookup_hdr(template))) 243 | return -ENOENT; 244 | 245 | return group_new_hdr(name, title, t->gh_column[0], t->gh_column[1], 246 | t->gh_column[2], t->gh_column[3]); 247 | } 248 | 249 | static void group_hdr_free(struct group_hdr *hdr) 250 | { 251 | xfree(hdr->gh_name); 252 | xfree(hdr->gh_title); 253 | xfree(hdr->gh_column[0]); 254 | xfree(hdr->gh_column[1]); 255 | xfree(hdr->gh_column[2]); 256 | xfree(hdr->gh_column[3]); 257 | xfree(hdr); 258 | } 259 | 260 | static void __init group_init(void) 261 | { 262 | DBG("init"); 263 | 264 | group_new_hdr(DEFAULT_GROUP, "Interfaces", 265 | "RX bps", "pps", "TX bps", "pps"); 266 | } 267 | 268 | static void __exit group_exit(void) 269 | { 270 | struct element_group *g, *next; 271 | struct group_hdr *hdr, *gnext; 272 | 273 | list_for_each_entry_safe(g, next, &group_list, g_list) 274 | group_free(g); 275 | 276 | list_for_each_entry_safe(hdr, gnext, &titles_list, gh_list) 277 | group_hdr_free(hdr); 278 | } 279 | -------------------------------------------------------------------------------- /src/history.c: -------------------------------------------------------------------------------- 1 | /* 2 | * history.c History Management 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | static LIST_HEAD(def_list); 32 | 33 | static struct history_def *current_history; 34 | 35 | struct history_def *history_def_lookup(const char *name) 36 | { 37 | struct history_def *def; 38 | 39 | list_for_each_entry(def, &def_list, hd_list) 40 | if (!strcmp(def->hd_name, name)) 41 | return def; 42 | 43 | return NULL; 44 | } 45 | 46 | struct history_def *history_def_alloc(const char *name) 47 | { 48 | struct history_def *def; 49 | 50 | if ((def = history_def_lookup(name))) 51 | return def; 52 | 53 | def = xcalloc(1, sizeof(*def)); 54 | def->hd_name = strdup(name); 55 | 56 | list_add_tail(&def->hd_list, &def_list); 57 | 58 | DBG("New history definition %s", name); 59 | 60 | return def; 61 | } 62 | 63 | static void history_def_free(struct history_def *def) 64 | { 65 | if (!def) 66 | return; 67 | 68 | xfree(def->hd_name); 69 | xfree(def); 70 | } 71 | 72 | static void *history_alloc_data(struct history_def *def) 73 | { 74 | return xcalloc(def->hd_size, def->hd_type); 75 | } 76 | 77 | static void history_store_data(struct history *h, struct history_store *hs, 78 | uint64_t total, float diff) 79 | { 80 | uint64_t delta; 81 | 82 | if (!hs->hs_data) { 83 | if (total == HISTORY_UNKNOWN) 84 | return; 85 | 86 | hs->hs_data = history_alloc_data(h->h_definition); 87 | } 88 | 89 | if (total == HISTORY_UNKNOWN) 90 | delta = HISTORY_UNKNOWN; 91 | else { 92 | delta = (total - hs->hs_prev_total); 93 | 94 | if (delta > 0) 95 | delta /= diff; 96 | hs->hs_prev_total = total; 97 | } 98 | 99 | switch (h->h_definition->hd_type) { 100 | case HISTORY_TYPE_8: 101 | ((uint8_t *) hs->hs_data)[h->h_index] = (uint8_t) delta; 102 | break; 103 | 104 | case HISTORY_TYPE_16: 105 | ((uint16_t *) hs->hs_data)[h->h_index] = (uint16_t) delta; 106 | break; 107 | 108 | case HISTORY_TYPE_32: 109 | ((uint32_t *) hs->hs_data)[h->h_index] = (uint32_t) delta; 110 | break; 111 | 112 | case HISTORY_TYPE_64: 113 | ((uint64_t *) hs->hs_data)[h->h_index] = (uint64_t) delta; 114 | break; 115 | 116 | default: 117 | BUG(); 118 | } 119 | } 120 | 121 | static inline void inc_history_index(struct history *h) 122 | { 123 | if (h->h_index < (h->h_definition->hd_size - 1)) 124 | h->h_index++; 125 | else 126 | h->h_index = 0; 127 | } 128 | 129 | uint64_t history_data(struct history *h, struct history_store *hs, int index) 130 | { 131 | switch (h->h_definition->hd_type) { 132 | case HISTORY_TYPE_8: { 133 | uint8_t v = ((uint8_t *) hs->hs_data)[index]; 134 | return (v == (uint8_t) -1) ? HISTORY_UNKNOWN : v; 135 | } 136 | 137 | case HISTORY_TYPE_16: { 138 | uint16_t v = ((uint16_t *) hs->hs_data)[index]; 139 | return (v == (uint16_t) -1) ? HISTORY_UNKNOWN : v; 140 | } 141 | 142 | case HISTORY_TYPE_32: { 143 | uint32_t v = ((uint32_t *) hs->hs_data)[index]; 144 | return (v == (uint32_t) -1) ? HISTORY_UNKNOWN : v; 145 | } 146 | 147 | case HISTORY_TYPE_64: { 148 | uint64_t v = ((uint64_t *) hs->hs_data)[index]; 149 | return (v == (uint64_t) -1) ? HISTORY_UNKNOWN : v; 150 | } 151 | 152 | default: 153 | BUG(); 154 | } 155 | } 156 | 157 | void history_update(struct attr *a, struct history *h, timestamp_t *ts) 158 | { 159 | struct history_def *def = h->h_definition; 160 | float timediff; 161 | 162 | if (h->h_last_update.tv_sec) 163 | timediff = timestamp_diff(&h->h_last_update, ts); 164 | else { 165 | timediff = 0.0f; /* initial history update */ 166 | 167 | /* Need a delta when working with counters */ 168 | if (a->a_def->ad_type == ATTR_TYPE_COUNTER) 169 | goto update_prev_total; 170 | } 171 | 172 | /* 173 | * A read interval greater than the desired history interval 174 | * can't possibly result in anything useful. Discard it and 175 | * mark history data as invalid. The user has to adjust the 176 | * read interval. 177 | */ 178 | if (cfg_read_interval > def->hd_interval) 179 | goto discard; 180 | 181 | /* 182 | * If the history interval matches the read interval it makes 183 | * sense to update upon every read. The reader timing already 184 | * took care of being as close as possible to the desired 185 | * interval. 186 | */ 187 | if (cfg_read_interval == def->hd_interval) 188 | goto update; 189 | 190 | if (timediff > h->h_max_interval) 191 | goto discard; 192 | 193 | if (timediff < h->h_min_interval) 194 | return; 195 | 196 | update: 197 | history_store_data(h, &h->h_rx, a->a_rx_rate.r_total, timediff); 198 | history_store_data(h, &h->h_tx, a->a_tx_rate.r_total, timediff); 199 | inc_history_index(h); 200 | 201 | goto update_ts; 202 | 203 | discard: 204 | while(timediff >= (def->hd_interval / 2)) { 205 | history_store_data(h, &h->h_rx, HISTORY_UNKNOWN, 0.0f); 206 | history_store_data(h, &h->h_tx, HISTORY_UNKNOWN, 0.0f); 207 | 208 | inc_history_index(h); 209 | timediff -= def->hd_interval; 210 | } 211 | 212 | update_prev_total: 213 | h->h_rx.hs_prev_total = a->a_rx_rate.r_total; 214 | h->h_tx.hs_prev_total = a->a_tx_rate.r_total; 215 | 216 | update_ts: 217 | copy_timestamp(&h->h_last_update, ts); 218 | } 219 | 220 | struct history *history_alloc(struct history_def *def) 221 | { 222 | struct history *h; 223 | 224 | h = xcalloc(1, sizeof(*h)); 225 | 226 | init_list_head(&h->h_list); 227 | 228 | h->h_definition = def; 229 | 230 | h->h_min_interval = (def->hd_interval - (cfg_read_interval / 2.0f)); 231 | h->h_max_interval = (def->hd_interval / cfg_history_variance); 232 | 233 | return h; 234 | } 235 | 236 | void history_free(struct history *h) 237 | { 238 | if (!h) 239 | return; 240 | 241 | xfree(h->h_rx.hs_data); 242 | xfree(h->h_tx.hs_data); 243 | 244 | list_del(&h->h_list); 245 | 246 | xfree(h); 247 | } 248 | 249 | void history_attach(struct attr *attr) 250 | { 251 | struct history_def *def; 252 | struct history *h; 253 | 254 | list_for_each_entry(def, &def_list, hd_list) { 255 | h = history_alloc(def); 256 | list_add_tail(&h->h_list, &attr->a_history_list); 257 | } 258 | } 259 | 260 | struct history_def *history_select_first(void) 261 | { 262 | if (list_empty(&def_list)) 263 | current_history = NULL; 264 | else 265 | current_history = list_first_entry(&def_list, 266 | struct history_def, hd_list); 267 | 268 | return current_history; 269 | } 270 | 271 | struct history_def *history_select_last(void) 272 | { 273 | if (list_empty(&def_list)) 274 | current_history = NULL; 275 | else 276 | current_history = list_entry(def_list.prev, 277 | struct history_def, hd_list); 278 | 279 | return current_history; 280 | } 281 | 282 | struct history_def *history_select_next(void) 283 | { 284 | if (current_history && current_history->hd_list.next != &def_list) { 285 | current_history = list_entry(current_history->hd_list.next, 286 | struct history_def, hd_list); 287 | return current_history; 288 | } 289 | 290 | return history_select_first(); 291 | } 292 | 293 | struct history_def *history_select_prev(void) 294 | { 295 | if (current_history && current_history->hd_list.prev != &def_list) { 296 | current_history = list_entry(current_history->hd_list.prev, 297 | struct history_def, hd_list); 298 | return current_history; 299 | } 300 | 301 | return history_select_last(); 302 | } 303 | 304 | struct history_def *history_current(void) 305 | { 306 | if (!current_history) 307 | current_history = history_select_first(); 308 | 309 | return current_history; 310 | } 311 | 312 | static void __exit history_exit(void) 313 | { 314 | struct history_def *def, *n; 315 | 316 | list_for_each_entry_safe(def, n, &def_list, hd_list) 317 | history_def_free(def); 318 | } 319 | -------------------------------------------------------------------------------- /src/in_dummy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * in_dummy.c Dummy Input Method 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #define MAXDEVS 32 34 | 35 | static uint64_t c_rx_b_inc = 1000000000; 36 | static uint64_t c_tx_b_inc = 80000000; 37 | static uint64_t c_rx_p_inc = 1000; 38 | static uint64_t c_tx_p_inc = 800; 39 | static int c_numdev = 5; 40 | static int c_randomize = 0; 41 | static int c_mtu = 1540; 42 | static int c_maxpps = 100000; 43 | static int c_numgroups = 2; 44 | 45 | static uint64_t *cnts; 46 | 47 | enum { 48 | DUMMY_BYTES, 49 | DUMMY_PACKETS, 50 | NUM_DUMMY_VALUE, 51 | }; 52 | 53 | static struct attr_map link_attrs[NUM_DUMMY_VALUE] = { 54 | { 55 | .name = "bytes", 56 | .type = ATTR_TYPE_COUNTER, 57 | .unit = UNIT_BYTE, 58 | .description = "Bytes", 59 | }, 60 | { 61 | .name = "packets", 62 | .type = ATTR_TYPE_COUNTER, 63 | .unit = UNIT_NUMBER, 64 | .description = "Packets", 65 | } 66 | }; 67 | 68 | /* cnts[ngroups][ndevs][2][2] */ 69 | 70 | static inline int cnt_size(void) 71 | { 72 | return c_numgroups * c_numdev * 2 * 2; 73 | } 74 | 75 | static inline uint64_t *cnt(int group, int dev, int unit, 76 | int direction) 77 | { 78 | return cnts + (group * c_numdev * 2 * 2) + 79 | (dev * 2 * 2) + 80 | (unit * 2) + 81 | direction; 82 | } 83 | 84 | static void dummy_read(void) 85 | { 86 | int gidx, n; 87 | 88 | for (gidx = 0; gidx < c_numgroups; gidx++) { 89 | char gname[32]; 90 | struct element_group *group; 91 | 92 | if (gidx == 0) 93 | snprintf(gname, sizeof(gname), "%s", DEFAULT_GROUP); 94 | else 95 | snprintf(gname, sizeof(gname), "group%02d", gidx); 96 | 97 | group = group_lookup(gname, GROUP_CREATE); 98 | 99 | for (n = 0; n < c_numdev; n++) { 100 | char ifname[IFNAMSIZ]; 101 | struct element *e; 102 | int i; 103 | 104 | snprintf(ifname, sizeof(ifname), "dummy%d", n); 105 | 106 | if (!(e = element_lookup(group, ifname, 0, NULL, ELEMENT_CREAT))) 107 | return; 108 | 109 | if (e->e_flags & ELEMENT_FLAG_CREATED) { 110 | if (element_set_key_attr(e, "bytes", "packets") || 111 | element_set_usage_attr(e, "bytes")) 112 | BUG(); 113 | e->e_flags &= ~ELEMENT_FLAG_CREATED; 114 | } 115 | 116 | if (e->e_flags & ELEMENT_FLAG_UPDATED) 117 | continue; 118 | 119 | if (c_randomize) { 120 | uint64_t rx = rand() % c_maxpps; 121 | uint64_t tx = rand() % c_maxpps; 122 | 123 | *cnt(gidx, n, 0, 0) += rx; 124 | *cnt(gidx, n, 0, 1) += tx; 125 | *cnt(gidx, n, 1, 0) += rx * (rand() % c_mtu); 126 | *cnt(gidx, n, 1, 1) += tx * (rand() % c_mtu); 127 | } else { 128 | *cnt(gidx, n, 0, 0) += c_rx_p_inc; 129 | *cnt(gidx, n, 0, 1) += c_tx_p_inc; 130 | *cnt(gidx, n, 1, 0) += c_rx_b_inc; 131 | *cnt(gidx, n, 1, 1) += c_tx_b_inc; 132 | } 133 | 134 | for (i = 0; i < ARRAY_SIZE(link_attrs); i++) { 135 | struct attr_map *m = &link_attrs[i]; 136 | 137 | attr_update(e, m->attrid, 138 | *cnt(gidx, n, i, 0), 139 | *cnt(gidx, n, i, 1), 140 | UPDATE_FLAG_RX | UPDATE_FLAG_TX | 141 | UPDATE_FLAG_64BIT); 142 | } 143 | 144 | element_notify_update(e, NULL); 145 | element_lifesign(e, 1); 146 | } 147 | } 148 | } 149 | 150 | static void print_help(void) 151 | { 152 | printf( 153 | "dummy - Statistic generator module (dummy)\n" \ 154 | "\n" \ 155 | " Basic statistic generator for testing purposes. Can produce a\n" \ 156 | " constant or random statistic flow with configurable parameters.\n" \ 157 | " Author: Thomas Graf \n" \ 158 | "\n" \ 159 | " Options:\n" \ 160 | " rxb=NUM RX bytes increment amount (default: 10^9)\n" \ 161 | " txb=NUM TX bytes increment amount (default: 8*10^7)\n" \ 162 | " rxp=NUM RX packets increment amount (default: 1K)\n" \ 163 | " txp=NUM TX packets increment amount (default: 800)\n" \ 164 | " num=NUM Number of devices (default: 5)\n" \ 165 | " numgroups=NUM Number of groups (default: 2)\n" \ 166 | " randomize Randomize counters (default: off)\n" \ 167 | " seed=NUM Seed for randomizer (default: time(0))\n" \ 168 | " mtu=NUM Maximal Transmission Unit (default: 1540)\n" \ 169 | " maxpps=NUM Upper limit for packets per second (default: 100K)\n" \ 170 | "\n" \ 171 | " Randomizer:\n" \ 172 | " RX-packets := Rand() %% maxpps\n" \ 173 | " TX-packets := Rand() %% maxpps\n" \ 174 | " RX-bytes := RX-packets * (Rand() %% mtu)\n" \ 175 | " TX-bytes := TX-packets * (Rand() %% mtu)\n"); 176 | } 177 | 178 | static void dummy_parse_opt(const char *type, const char *value) 179 | { 180 | if (!strcasecmp(type, "rxb") && value) 181 | c_rx_b_inc = strtol(value, NULL, 0); 182 | else if (!strcasecmp(type, "txb") && value) 183 | c_tx_b_inc = strtol(value, NULL, 0); 184 | else if (!strcasecmp(type, "rxp") && value) 185 | c_rx_p_inc = strtol(value, NULL, 0); 186 | else if (!strcasecmp(type, "txp") && value) 187 | c_tx_p_inc = strtol(value, NULL, 0); 188 | else if (!strcasecmp(type, "num") && value) 189 | c_numdev = strtol(value, NULL, 0); 190 | else if (!strcasecmp(type, "randomize")) { 191 | c_randomize = 1; 192 | srand(time(NULL)); 193 | } else if (!strcasecmp(type, "seed") && value) 194 | srand(strtol(value, NULL, 0)); 195 | else if (!strcasecmp(type, "mtu") && value) 196 | c_mtu = strtol(value, NULL, 0); 197 | else if (!strcasecmp(type, "maxpps") && value) 198 | c_maxpps = strtol(value, NULL, 0); 199 | else if (!strcasecmp(type, "numgroups") && value) 200 | c_numgroups = strtol(value, NULL, 0); 201 | else if (!strcasecmp(type, "help")) { 202 | print_help(); 203 | exit(0); 204 | } 205 | } 206 | 207 | static int dummy_do_init(void) 208 | { 209 | if (attr_map_load(link_attrs, ARRAY_SIZE(link_attrs))) 210 | BUG(); 211 | 212 | return 0; 213 | } 214 | 215 | static int dummy_probe(void) 216 | { 217 | int i; 218 | 219 | if (c_numdev >= MAXDEVS) { 220 | fprintf(stderr, "numdev must be in range 0..%d\n", MAXDEVS); 221 | return 0; 222 | } 223 | 224 | cnts = xcalloc(cnt_size(), sizeof(uint64_t)); 225 | 226 | for (i = 0; i < c_numgroups; i++) { 227 | char groupname[32]; 228 | snprintf(groupname, sizeof(groupname), "group%02d", i); 229 | 230 | group_new_derived_hdr(groupname, groupname, DEFAULT_GROUP); 231 | } 232 | 233 | return 1; 234 | } 235 | 236 | static struct bmon_module dummy_ops = { 237 | .m_name = "dummy", 238 | .m_do = dummy_read, 239 | .m_parse_opt = dummy_parse_opt, 240 | .m_probe = dummy_probe, 241 | .m_init = dummy_do_init, 242 | }; 243 | 244 | static void __init dummy_init(void) 245 | { 246 | input_register(&dummy_ops); 247 | } 248 | -------------------------------------------------------------------------------- /src/in_null.c: -------------------------------------------------------------------------------- 1 | /* 2 | * in_null.c Null Input Method 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | static void null_read(void) 31 | { 32 | DBG("null: reading..."); 33 | } 34 | 35 | static void print_help(void) 36 | { 37 | printf( 38 | "null - Do not collect statistics at all\n" \ 39 | "\n" \ 40 | " Will not collect any statistics at all, used to disable \n" \ 41 | " local statistics collection.\n" \ 42 | " Author: Thomas Graf \n"); 43 | } 44 | 45 | static void null_parse_opt(const char *type, const char *value) 46 | { 47 | if (!strcasecmp(type, "help")) { 48 | print_help(); 49 | exit(0); 50 | } 51 | } 52 | 53 | static struct bmon_module null_ops = { 54 | .m_name = "null", 55 | .m_do = null_read, 56 | .m_parse_opt = null_parse_opt, 57 | }; 58 | 59 | static void __init null_init(void) 60 | { 61 | input_register(&null_ops); 62 | } 63 | -------------------------------------------------------------------------------- /src/in_proc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * in_proc.c /proc/net/dev Input (Linux) 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | static const char *c_path = "/proc/net/dev"; 34 | static const char *c_group = DEFAULT_GROUP; 35 | static struct element_group *grp; 36 | 37 | enum { 38 | PROC_BYTES, 39 | PROC_PACKETS, 40 | PROC_ERRORS, 41 | PROC_DROP, 42 | PROC_COMPRESSED, 43 | PROC_FIFO, 44 | PROC_FRAME, 45 | PROC_MCAST, 46 | NUM_PROC_VALUE, 47 | }; 48 | 49 | static struct attr_map link_attrs[NUM_PROC_VALUE] = { 50 | { 51 | .name = "bytes", 52 | .type = ATTR_TYPE_COUNTER, 53 | .unit = UNIT_BYTE, 54 | .description = "Bytes", 55 | }, 56 | { 57 | .name = "packets", 58 | .type = ATTR_TYPE_COUNTER, 59 | .unit = UNIT_NUMBER, 60 | .description = "Packets", 61 | }, 62 | { 63 | .name = "errors", 64 | .type = ATTR_TYPE_COUNTER, 65 | .unit = UNIT_NUMBER, 66 | .description = "Errors", 67 | }, 68 | { 69 | .name = "drop", 70 | .type = ATTR_TYPE_COUNTER, 71 | .unit = UNIT_NUMBER, 72 | .description = "Dropped", 73 | }, 74 | { 75 | .name = "compressed", 76 | .type = ATTR_TYPE_COUNTER, 77 | .unit = UNIT_NUMBER, 78 | .description = "Compressed", 79 | }, 80 | { 81 | .name = "fifoerr", 82 | .type = ATTR_TYPE_COUNTER, 83 | .unit = UNIT_NUMBER, 84 | .description = "FIFO Error", 85 | }, 86 | { 87 | .name = "frameerr", 88 | .type = ATTR_TYPE_COUNTER, 89 | .unit = UNIT_NUMBER, 90 | .description = "Frame Error", 91 | }, 92 | { 93 | .name = "mcast", 94 | .type = ATTR_TYPE_COUNTER, 95 | .unit = UNIT_NUMBER, 96 | .description = "Multicast", 97 | } 98 | }; 99 | 100 | static void proc_read(void) 101 | { 102 | struct element *e; 103 | FILE *fd; 104 | char buf[512], *p, *s, *unused __unused__; 105 | int w; 106 | 107 | if (!(fd = fopen(c_path, "r"))) 108 | quit("Unable to open file %s: %s\n", c_path, strerror(errno)); 109 | 110 | /* Ignore header */ 111 | unused = fgets(buf, sizeof(buf), fd); 112 | unused = fgets(buf, sizeof(buf), fd); 113 | 114 | for (; fgets(buf, sizeof(buf), fd);) { 115 | uint64_t data[NUM_PROC_VALUE][2]; 116 | int i; 117 | 118 | if (buf[0] == '\r' || buf[0] == '\n') 119 | continue; 120 | 121 | if (!(p = strchr(buf, ':'))) 122 | continue; 123 | *p = '\0'; 124 | s = (p + 1); 125 | 126 | for (p = &buf[0]; *p == ' '; p++); 127 | 128 | w = sscanf(s, "%" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64 " " 129 | "%" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64 " " 130 | "%" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64 " " 131 | "%" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64 132 | "\n", 133 | &data[PROC_BYTES][0], 134 | &data[PROC_PACKETS][0], 135 | &data[PROC_ERRORS][0], 136 | &data[PROC_DROP][0], 137 | &data[PROC_FIFO][0], 138 | &data[PROC_FRAME][0], 139 | &data[PROC_COMPRESSED][0], 140 | &data[PROC_MCAST][0], 141 | &data[PROC_BYTES][1], 142 | &data[PROC_PACKETS][1], 143 | &data[PROC_ERRORS][1], 144 | &data[PROC_DROP][1], 145 | &data[PROC_FIFO][1], 146 | &data[PROC_FRAME][1], 147 | &data[PROC_COMPRESSED][1], 148 | &data[PROC_MCAST][1]); 149 | 150 | if (w != 16) 151 | continue; 152 | 153 | if (!(e = element_lookup(grp, p, 0, NULL, ELEMENT_CREAT))) 154 | goto skip; 155 | 156 | if (e->e_flags & ELEMENT_FLAG_CREATED) { 157 | if (element_set_key_attr(e, "bytes", "packets") || 158 | element_set_usage_attr(e, "bytes")) 159 | BUG(); 160 | 161 | e->e_flags &= ~ELEMENT_FLAG_CREATED; 162 | } 163 | 164 | for (i = 0; i < ARRAY_SIZE(link_attrs); i++) { 165 | struct attr_map *m = &link_attrs[i]; 166 | 167 | attr_update(e, m->attrid, data[i][0], data[i][1], 168 | UPDATE_FLAG_RX | UPDATE_FLAG_TX); 169 | } 170 | 171 | element_notify_update(e, NULL); 172 | element_lifesign(e, 1); 173 | } 174 | skip: 175 | fclose(fd); 176 | } 177 | 178 | static void print_help(void) 179 | { 180 | printf( 181 | "proc - procfs statistic collector for Linux" \ 182 | "\n" \ 183 | " Reads statistics from procfs (/proc/net/dev)\n" \ 184 | " Author: Thomas Graf \n" \ 185 | "\n" \ 186 | " Options:\n" \ 187 | " file=PATH Path to statistics file (default: /proc/net/dev)\n" 188 | " group=NAME Name of group\n"); 189 | } 190 | 191 | static void proc_parse_opt(const char *type, const char *value) 192 | { 193 | if (!strcasecmp(type, "file") && value) 194 | c_path = value; 195 | else if (!strcasecmp(type, "group") && value) 196 | c_group = value; 197 | else if (!strcasecmp(type, "help")) { 198 | print_help(); 199 | exit(0); 200 | } 201 | } 202 | 203 | static int proc_do_init(void) 204 | { 205 | if (attr_map_load(link_attrs, ARRAY_SIZE(link_attrs)) || 206 | !(grp = group_lookup(c_group, GROUP_CREATE))) 207 | BUG(); 208 | 209 | return 0; 210 | } 211 | 212 | static int proc_probe(void) 213 | { 214 | FILE *fd = fopen(c_path, "r"); 215 | 216 | if (fd) { 217 | fclose(fd); 218 | return 1; 219 | } 220 | return 0; 221 | } 222 | 223 | static struct bmon_module proc_ops = { 224 | .m_name = "proc", 225 | .m_do = proc_read, 226 | .m_parse_opt = proc_parse_opt, 227 | .m_probe = proc_probe, 228 | .m_init = proc_do_init, 229 | }; 230 | 231 | static void __init proc_init(void) 232 | { 233 | input_register(&proc_ops); 234 | } 235 | -------------------------------------------------------------------------------- /src/in_sysctl.c: -------------------------------------------------------------------------------- 1 | /* 2 | * in_sysctl.c sysctl (BSD) 3 | * 4 | * $Id: in_sysctl.c 20 2004-10-30 22:46:16Z tgr $ 5 | * 6 | * Copyright (c) 2001-2004 Thomas Graf 7 | * Copyright (c) 2014 Žilvinas Valinskas 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining a 10 | * copy of this software and associated documentation files (the "Software"), 11 | * to deal in the Software without restriction, including without limitation 12 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | * and/or sell copies of the Software, and to permit persons to whom the 14 | * Software is furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included 17 | * in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | * DEALINGS IN THE SOFTWARE. 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #if defined SYS_BSD 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | static int c_debug = 0; 44 | static struct element_group *grp; 45 | 46 | enum { 47 | SYSCTL_RX_BYTES = 0x100, 48 | SYSCTL_TX_BYTES, 49 | SYSCTL_RX_PACKETS, 50 | SYSCTL_TX_PACKETS, 51 | SYSCTL_RX_ERRORS, 52 | SYSCTL_TX_ERRORS, 53 | SYSCTL_RX_DROPS, 54 | SYSCTL_RX_MCAST, 55 | SYSCTL_TX_MCAST, 56 | SYSCTL_TX_COLLS, 57 | }; 58 | static struct attr_map link_attrs[] = { 59 | { 60 | .name = "bytes", 61 | .type = ATTR_TYPE_COUNTER, 62 | .unit = UNIT_BYTE, 63 | .rxid = SYSCTL_RX_BYTES, 64 | .txid = SYSCTL_TX_BYTES, 65 | .description = "Bytes", 66 | }, 67 | { 68 | .name = "packets", 69 | .type = ATTR_TYPE_COUNTER, 70 | .unit = UNIT_NUMBER, 71 | .rxid = SYSCTL_RX_PACKETS, 72 | .txid = SYSCTL_TX_PACKETS, 73 | .description = "Packets", 74 | }, 75 | { 76 | .name = "errors", 77 | .type = ATTR_TYPE_COUNTER, 78 | .unit = UNIT_NUMBER, 79 | .rxid = SYSCTL_RX_ERRORS, 80 | .txid = SYSCTL_TX_ERRORS, 81 | .description = "Errors", 82 | }, 83 | { 84 | .name = "drop", 85 | .type = ATTR_TYPE_COUNTER, 86 | .unit = UNIT_NUMBER, 87 | .rxid = SYSCTL_RX_DROPS, 88 | .description = "Dropped", 89 | }, 90 | { 91 | .name = "coll", 92 | .type = ATTR_TYPE_COUNTER, 93 | .unit = UNIT_NUMBER, 94 | .txid = SYSCTL_TX_COLLS, 95 | .description = "Collisions", 96 | }, 97 | { 98 | .name = "mcast", 99 | .type = ATTR_TYPE_COUNTER, 100 | .unit = UNIT_NUMBER, 101 | .rxid = SYSCTL_RX_MCAST, 102 | .txid = SYSCTL_TX_MCAST, 103 | .description = "Multicast", 104 | } 105 | }; 106 | 107 | uint64_t sysctl_get_stats(const struct if_msghdr *ifm, int what) 108 | { 109 | switch(what) { 110 | case SYSCTL_RX_BYTES: 111 | return ifm->ifm_data.ifi_ibytes; 112 | case SYSCTL_TX_BYTES: 113 | return ifm->ifm_data.ifi_obytes; 114 | 115 | case SYSCTL_RX_PACKETS: 116 | return ifm->ifm_data.ifi_ipackets; 117 | case SYSCTL_TX_PACKETS: 118 | return ifm->ifm_data.ifi_opackets; 119 | 120 | case SYSCTL_RX_ERRORS: 121 | return ifm->ifm_data.ifi_ierrors; 122 | case SYSCTL_TX_ERRORS: 123 | return ifm->ifm_data.ifi_oerrors; 124 | 125 | case SYSCTL_RX_DROPS: 126 | return ifm->ifm_data.ifi_iqdrops; 127 | 128 | case SYSCTL_RX_MCAST: 129 | return ifm->ifm_data.ifi_imcasts; 130 | case SYSCTL_TX_MCAST: 131 | return ifm->ifm_data.ifi_omcasts; 132 | case SYSCTL_TX_COLLS: 133 | return ifm->ifm_data.ifi_collisions; 134 | 135 | default: 136 | return 0; 137 | }; 138 | } 139 | 140 | static void 141 | sysctl_read(void) 142 | { 143 | int mib[] = {CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0}; 144 | size_t n; 145 | char *buf, *next, *lim; 146 | 147 | if (sysctl(mib, 6, NULL, &n, NULL, 0) < 0) 148 | quit("sysctl() failed"); 149 | 150 | if (c_debug) 151 | fprintf(stderr, "sysctl 1-pass n=%zd\n", n); 152 | 153 | buf = xcalloc(1, n); 154 | 155 | if (sysctl(mib, 6, buf, &n, NULL, 0) < 0) 156 | quit("sysctl() failed"); 157 | 158 | if (c_debug) 159 | fprintf(stderr, "sysctl 2-pass n=%zd\n", n); 160 | 161 | lim = (buf + n); 162 | for (next = buf; next < lim; ) { 163 | struct element *e, *e_parent = NULL; 164 | struct if_msghdr *ifm, *nextifm; 165 | struct sockaddr_dl *sdl; 166 | char info_buf[64]; 167 | 168 | ifm = (struct if_msghdr *) next; 169 | if (ifm->ifm_type != RTM_IFINFO) 170 | break; 171 | 172 | next += ifm->ifm_msglen; 173 | 174 | while (next < lim) { 175 | nextifm = (struct if_msghdr *) next; 176 | if (nextifm->ifm_type != RTM_NEWADDR) 177 | break; 178 | next += nextifm->ifm_msglen; 179 | } 180 | 181 | sdl = (struct sockaddr_dl *) (ifm + 1); 182 | 183 | if (!cfg_show_all && !(ifm->ifm_flags & IFF_UP)) 184 | continue; 185 | 186 | if (sdl->sdl_family != AF_LINK) 187 | continue; 188 | 189 | if (c_debug) 190 | fprintf(stderr, "Processing %s\n", sdl->sdl_data); 191 | 192 | sdl->sdl_data[sdl->sdl_nlen] = '\0'; 193 | e = element_lookup(grp, 194 | sdl->sdl_data, sdl->sdl_index, 195 | e_parent, ELEMENT_CREAT); 196 | if (!e) 197 | continue; 198 | 199 | if (e->e_flags & ELEMENT_FLAG_CREATED) { 200 | if (e->e_parent) 201 | e->e_level = e->e_parent->e_level + 1; 202 | 203 | if (element_set_key_attr(e, "bytes", "packets") || 204 | element_set_usage_attr(e, "bytes")) 205 | BUG(); 206 | 207 | e->e_flags &= ~ELEMENT_FLAG_CREATED; 208 | } 209 | 210 | int i; 211 | for (i = 0; i < ARRAY_SIZE(link_attrs); i++) { 212 | struct attr_map *m = &link_attrs[i]; 213 | uint64_t rx = 0, tx = 0; 214 | int flags = 0; 215 | 216 | if (m->rxid) { 217 | rx = sysctl_get_stats(ifm, m->rxid); 218 | flags |= UPDATE_FLAG_RX; 219 | } 220 | 221 | if (m->txid) { 222 | tx = sysctl_get_stats(ifm, m->txid); 223 | flags |= UPDATE_FLAG_TX; 224 | } 225 | 226 | attr_update(e, m->attrid, rx, tx, flags); 227 | } 228 | 229 | snprintf(info_buf, sizeof(info_buf), "%ju", (uintmax_t)ifm->ifm_data.ifi_mtu); 230 | element_update_info(e, "MTU", info_buf); 231 | 232 | snprintf(info_buf, sizeof(info_buf), "%ju", (uintmax_t)ifm->ifm_data.ifi_metric); 233 | element_update_info(e, "Metric", info_buf); 234 | 235 | #if !(defined(__NetBSD__) || defined(__FreeBSD__)) 236 | snprintf(info_buf, sizeof(info_buf), "%u", ifm->ifm_data.ifi_recvquota); 237 | element_update_info(e, "RX-Quota", info_buf); 238 | 239 | snprintf(info_buf, sizeof(info_buf), "%u", ifm->ifm_data.ifi_xmitquota); 240 | element_update_info(e, "TX-Quota", info_buf); 241 | #endif 242 | 243 | element_notify_update(e, NULL); 244 | element_lifesign(e, 1); 245 | } 246 | 247 | xfree(buf); 248 | } 249 | 250 | static void 251 | print_help(void) 252 | { 253 | printf( 254 | "sysctl - sysctl statistic collector for BSD and Darwin\n" \ 255 | "\n" \ 256 | " BSD and Darwin statistic collector using sysctl()\n" \ 257 | " Author: Thomas Graf \n" \ 258 | "\n"); 259 | } 260 | 261 | static void 262 | sysctl_set_opts(const char* type, const char* value) 263 | { 264 | if (!strcasecmp(type, "debug")) 265 | c_debug = 1; 266 | else if (!strcasecmp(type, "help")) { 267 | print_help(); 268 | exit(0); 269 | } 270 | } 271 | 272 | static int 273 | sysctl_probe(void) 274 | { 275 | size_t n; 276 | int mib[] = {CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0}; 277 | if (sysctl(mib, 6, NULL, &n, NULL, 0) < 0) 278 | return 0; 279 | return 1; 280 | } 281 | 282 | static int sysctl_do_init(void) 283 | { 284 | if (attr_map_load(link_attrs, ARRAY_SIZE(link_attrs))) 285 | BUG(); 286 | 287 | grp = group_lookup(DEFAULT_GROUP, GROUP_CREATE); 288 | if (!grp) 289 | BUG(); 290 | 291 | return 0; 292 | } 293 | 294 | static struct bmon_module kstat_ops = { 295 | .m_name = "sysctl", 296 | .m_do = sysctl_read, 297 | .m_parse_opt = sysctl_set_opts, 298 | .m_probe = sysctl_probe, 299 | .m_init = sysctl_do_init, 300 | }; 301 | 302 | static void __init 303 | sysctl_init(void) 304 | { 305 | input_register(&kstat_ops); 306 | } 307 | 308 | #endif 309 | -------------------------------------------------------------------------------- /src/input.c: -------------------------------------------------------------------------------- 1 | /* 2 | * input.c Input API 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | static struct bmon_subsys input_subsys; 32 | 33 | void input_register(struct bmon_module *m) 34 | { 35 | module_register(&input_subsys, m); 36 | } 37 | 38 | static void activate_default(void) 39 | { 40 | /* 41 | * Try to activate a default input module if the user did not make 42 | * a selection 43 | */ 44 | if (!input_subsys.s_nmod) { 45 | struct bmon_module *m; 46 | 47 | #ifdef SYS_LINUX 48 | if (!input_set("netlink")) 49 | return; 50 | 51 | if (!input_set("proc")) 52 | return; 53 | #endif 54 | 55 | #ifdef SYS_BSD 56 | if (!input_set("sysctl")) 57 | return; 58 | #endif 59 | 60 | /* Fall back to anything that could act as default */ 61 | list_for_each_entry(m, &input_subsys.s_mod_list, m_list) { 62 | if (m->m_flags & BMON_MODULE_DEFAULT) 63 | if (!input_set(m->m_name)) 64 | return; 65 | } 66 | 67 | quit("No input module found\n"); 68 | } 69 | } 70 | 71 | void input_read(void) 72 | { 73 | module_foreach_run_enabled(&input_subsys); 74 | } 75 | 76 | int input_set(const char *name) 77 | { 78 | return module_set(&input_subsys, name); 79 | } 80 | 81 | static struct bmon_subsys input_subsys = { 82 | .s_name = "input", 83 | .s_activate_default = &activate_default, 84 | .s_mod_list = LIST_SELF(input_subsys.s_mod_list), 85 | }; 86 | 87 | static void __init __input_init(void) 88 | { 89 | module_register_subsys(&input_subsys); 90 | } 91 | -------------------------------------------------------------------------------- /src/module.c: -------------------------------------------------------------------------------- 1 | /* 2 | * module.c Module API 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | static LIST_HEAD(subsys_list); 31 | 32 | static void module_foreach(struct bmon_subsys *ss, void (*cb)(struct bmon_module *)) 33 | { 34 | struct bmon_module *m; 35 | 36 | list_for_each_entry(m, &ss->s_mod_list, m_list) 37 | cb(m); 38 | } 39 | 40 | void module_foreach_run_enabled_pre(struct bmon_subsys *ss) 41 | { 42 | struct bmon_module *m; 43 | 44 | list_for_each_entry(m, &ss->s_mod_list, m_list) 45 | if (m->m_flags & BMON_MODULE_ENABLED && m->m_pre) 46 | m->m_pre(); 47 | } 48 | 49 | void module_foreach_run_enabled(struct bmon_subsys *ss) 50 | { 51 | struct bmon_module *m; 52 | 53 | list_for_each_entry(m, &ss->s_mod_list, m_list) 54 | if (m->m_flags & BMON_MODULE_ENABLED && m->m_do) 55 | m->m_do(); 56 | } 57 | 58 | void module_foreach_run_enabled_post(struct bmon_subsys *ss) 59 | { 60 | struct bmon_module *m; 61 | 62 | list_for_each_entry(m, &ss->s_mod_list, m_list) 63 | if (m->m_flags & BMON_MODULE_ENABLED && m->m_post) 64 | m->m_post(); 65 | } 66 | 67 | static struct bmon_module *module_lookup(struct bmon_subsys *ss, const char *name) 68 | { 69 | struct bmon_module *m; 70 | 71 | list_for_each_entry(m, &ss->s_mod_list, m_list) 72 | if (!strcmp(m->m_name, name)) 73 | return m; 74 | 75 | return NULL; 76 | } 77 | 78 | static void module_list(struct bmon_subsys *ss, struct list_head *list) 79 | { 80 | printf("%s modules:\n", ss->s_name); 81 | if (list_empty(list)) 82 | printf("\tNo %s modules found.\n", ss->s_name); 83 | else { 84 | struct bmon_module *m; 85 | 86 | list_for_each_entry(m, list, m_list) 87 | printf("\t%s\n", m->m_name); 88 | } 89 | } 90 | 91 | static int module_configure(struct bmon_module *m, module_conf_t *cfg) 92 | { 93 | DBG("Configuring module %s", m->m_name); 94 | 95 | if (m->m_parse_opt && cfg) { 96 | tv_t *tv; 97 | 98 | list_for_each_entry(tv, &cfg->m_attrs, tv_list) 99 | m->m_parse_opt(tv->tv_type, tv->tv_value); 100 | } 101 | 102 | if (m->m_probe && !m->m_probe()) 103 | return -EINVAL; 104 | 105 | m->m_flags |= BMON_MODULE_ENABLED; 106 | m->m_subsys->s_nmod++; 107 | 108 | return 0; 109 | } 110 | 111 | int module_register(struct bmon_subsys *ss, struct bmon_module *m) 112 | { 113 | if (m->m_subsys) 114 | return -EBUSY; 115 | 116 | list_add_tail(&m->m_list, &ss->s_mod_list); 117 | m->m_subsys = ss; 118 | return 0; 119 | } 120 | 121 | static void __auto_load(struct bmon_module *m) 122 | { 123 | if ((m->m_flags & BMON_MODULE_AUTO) && 124 | !(m->m_flags & BMON_MODULE_ENABLED)) { 125 | if (module_configure(m, NULL) == 0) 126 | DBG("Auto-enabled module %s", m->m_name); 127 | } 128 | } 129 | 130 | int module_set(struct bmon_subsys *ss, const char *name) 131 | { 132 | struct bmon_module *mod; 133 | LIST_HEAD(tmp_list); 134 | module_conf_t *m; 135 | 136 | if (!name || !strcasecmp(name, "list")) { 137 | module_list(ss, &ss->s_mod_list); 138 | return 1; 139 | } 140 | 141 | parse_module_param(name, &tmp_list); 142 | 143 | list_for_each_entry(m, &tmp_list, m_list) { 144 | if (!(mod = module_lookup(ss, m->m_name))) 145 | quit("Unknown %s module: %s\n", ss->s_name, m->m_name); 146 | 147 | if (module_configure(mod, m) == 0) 148 | DBG("Enabled module %s", mod->m_name); 149 | } 150 | 151 | module_foreach(ss, __auto_load); 152 | 153 | if (!ss->s_nmod) 154 | quit("No working %s module found\n", ss->s_name); 155 | 156 | DBG("Configured modules"); 157 | 158 | return 0; 159 | } 160 | 161 | static void __module_init(struct bmon_module *m) 162 | { 163 | if (m->m_init) { 164 | DBG("Initializing %s...", m->m_name); 165 | if (m->m_init()) 166 | m->m_flags &= ~BMON_MODULE_ENABLED; 167 | } 168 | } 169 | 170 | void module_init(void) 171 | { 172 | struct bmon_subsys *ss; 173 | 174 | DBG("Initializing modules"); 175 | 176 | list_for_each_entry(ss, &subsys_list, s_list) { 177 | if (ss->s_activate_default) 178 | ss->s_activate_default(); 179 | 180 | module_foreach(ss, __module_init); 181 | } 182 | } 183 | 184 | static void __module_shutdown(struct bmon_module *m) 185 | { 186 | if (m->m_shutdown) { 187 | DBG("Shutting down %s...", m->m_name); 188 | m->m_shutdown(); 189 | m->m_flags &= ~BMON_MODULE_ENABLED; 190 | } 191 | } 192 | 193 | void module_shutdown(void) 194 | { 195 | DBG("Shutting down modules"); 196 | 197 | struct bmon_subsys *ss; 198 | 199 | list_for_each_entry(ss, &subsys_list, s_list) 200 | module_foreach(ss, __module_shutdown); 201 | } 202 | 203 | void module_register_subsys(struct bmon_subsys *ss) 204 | { 205 | DBG("Module %s registered", ss->s_name); 206 | 207 | list_add_tail(&ss->s_list, &subsys_list); 208 | } 209 | -------------------------------------------------------------------------------- /src/out_ascii.c: -------------------------------------------------------------------------------- 1 | /* 2 | * out_ascii.c ASCII Output 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | typedef enum diagram_type_e { 37 | D_LIST, 38 | D_GRAPH, 39 | D_DETAILS 40 | } diagram_type_t; 41 | 42 | static struct graph_cfg graph_cfg = { 43 | .gc_foreground = '*', 44 | .gc_background = ' ', 45 | .gc_noise = '.', 46 | .gc_unknown = '?', 47 | .gc_height = 6, 48 | }; 49 | 50 | static diagram_type_t c_diagram_type = D_LIST; 51 | static char *c_hist = "second"; 52 | static int c_quit_after = -1; 53 | 54 | static void print_list(struct element *e) 55 | { 56 | char *rxu1 = "", *txu1 = "", *rxu2 = "", *txu2 = ""; 57 | double rx1 = 0.0f, tx1 = 0.0f, rx2 = 0.0f, tx2 = 0.0f; 58 | int rx1prec = 0, tx1prec = 0, rx2prec = 0, tx2prec = 0; 59 | char pad[IFNAMSIZ + 32]; 60 | struct attr *a; 61 | 62 | if (e->e_key_attr[GT_MAJOR] && 63 | (a = attr_lookup(e, e->e_key_attr[GT_MAJOR]->ad_id))) 64 | attr_rate2float(a, &rx1, &rxu1, &rx1prec, 65 | &tx1, &txu1, &tx1prec); 66 | 67 | if (e->e_key_attr[GT_MINOR] && 68 | (a = attr_lookup(e, e->e_key_attr[GT_MINOR]->ad_id))) 69 | attr_rate2float(a, &rx2, &rxu2, &rx2prec, 70 | &tx2, &txu2, &tx2prec); 71 | 72 | memset(pad, 0, sizeof(pad)); 73 | memset(pad, ' ', e->e_level < 15 ? e->e_level : 15); 74 | 75 | strncat(pad, e->e_name, sizeof(pad) - strlen(pad) - 1); 76 | 77 | if (e->e_description) { 78 | strncat(pad, " (", sizeof(pad) - strlen(pad) - 1); 79 | strncat(pad, e->e_description, sizeof(pad) - strlen(pad) - 1); 80 | strncat(pad, ")", sizeof(pad) - strlen(pad) - 1); 81 | } 82 | 83 | printf(" %-36s %8.*f%-3s %8.*f%-3s ", 84 | pad, rx1prec, rx1, rxu1, rx2prec, rx2, rxu2); 85 | 86 | if (e->e_rx_usage == FLT_MAX) 87 | printf(" "); 88 | else 89 | printf("%2.0f%%", e->e_rx_usage); 90 | 91 | printf(" %8.*f%-3s %8.*f%-3s ", tx1prec, tx1, txu1, tx2prec, tx2, txu2); 92 | 93 | if (e->e_tx_usage == FLT_MAX) 94 | printf(" \n"); 95 | else 96 | printf("%2.0f%%\n", e->e_tx_usage); 97 | } 98 | 99 | static void print_attr_detail(struct element *e, struct attr *a, void *arg) 100 | { 101 | char *rx_u, *tx_u; 102 | int rxprec, txprec; 103 | 104 | double rx = unit_value2str(rate_get_total(&a->a_rx_rate), 105 | a->a_def->ad_unit, 106 | &rx_u, &rxprec); 107 | double tx = unit_value2str(rate_get_total(&a->a_tx_rate), 108 | a->a_def->ad_unit, 109 | &tx_u, &txprec); 110 | 111 | printf(" %-36s %12.*f%-3s %12.*f%-3s\n", 112 | a->a_def->ad_description, rxprec, rx, rx_u, txprec, tx, tx_u); 113 | } 114 | 115 | static void print_details(struct element *e) 116 | { 117 | printf(" %s", e->e_name); 118 | 119 | if (e->e_id) 120 | printf(" (%u)", e->e_id); 121 | 122 | printf("\n"); 123 | 124 | element_foreach_attr(e, print_attr_detail, NULL); 125 | 126 | printf("\n"); 127 | } 128 | 129 | static void print_table(struct graph *g, struct graph_table *tbl, const char *hdr) 130 | { 131 | int i; 132 | 133 | if (!tbl->gt_table) 134 | return; 135 | 136 | printf("%s %s\n", hdr, tbl->gt_y_unit); 137 | 138 | for (i = (g->g_cfg.gc_height - 1); i >= 0; i--) 139 | printf("%8.2f %s\n", tbl->gt_scale[i], 140 | tbl->gt_table + (i * graph_row_size(&g->g_cfg))); 141 | 142 | printf(" 1 5 10 15 20 25 30 35 40 " \ 143 | "45 50 55 60\n"); 144 | } 145 | 146 | static void __print_graph(struct element *e, struct attr *a, void *arg) 147 | { 148 | struct history *h; 149 | struct graph *g; 150 | 151 | if (!(a->a_flags & ATTR_DOING_HISTORY)) 152 | return; 153 | 154 | graph_cfg.gc_unit = a->a_def->ad_unit; 155 | 156 | list_for_each_entry(h, &a->a_history_list, h_list) { 157 | if (strcasecmp(c_hist, h->h_definition->hd_name)) 158 | continue; 159 | 160 | g = graph_alloc(h, &graph_cfg); 161 | graph_refill(g, h); 162 | 163 | printf("Interface: %s\n", e->e_name); 164 | printf("Attribute: %s\n", a->a_def->ad_description); 165 | 166 | print_table(g, &g->g_rx, "RX"); 167 | print_table(g, &g->g_tx, "TX"); 168 | 169 | graph_free(g); 170 | 171 | } 172 | } 173 | 174 | static void print_graph(struct element *e) 175 | { 176 | element_foreach_attr(e, __print_graph, NULL); 177 | } 178 | 179 | static void ascii_draw_element(struct element_group *g, struct element *e, 180 | void *arg) 181 | { 182 | switch (c_diagram_type) { 183 | case D_LIST: 184 | print_list(e); 185 | break; 186 | 187 | case D_DETAILS: 188 | print_details(e); 189 | break; 190 | 191 | case D_GRAPH: 192 | print_graph(e); 193 | break; 194 | } 195 | } 196 | 197 | static void ascii_draw_group(struct element_group *g, void *arg) 198 | { 199 | if (c_diagram_type == D_LIST) 200 | printf("%-37s%10s %11s %%%10s %11s %%\n", 201 | g->g_hdr->gh_title, 202 | g->g_hdr->gh_column[0], 203 | g->g_hdr->gh_column[1], 204 | g->g_hdr->gh_column[2], 205 | g->g_hdr->gh_column[3]); 206 | else 207 | printf("%s\n", g->g_hdr->gh_title); 208 | 209 | group_foreach_element(g, ascii_draw_element, NULL); 210 | } 211 | 212 | static void ascii_draw(void) 213 | { 214 | group_foreach(ascii_draw_group, NULL); 215 | fflush(stdout); 216 | 217 | if (c_quit_after > 0) 218 | if (--c_quit_after == 0) 219 | exit(0); 220 | } 221 | 222 | static void print_help(void) 223 | { 224 | printf( 225 | "ascii - ASCII Output\n" \ 226 | "\n" \ 227 | " Plain configurable ASCII output.\n" \ 228 | "\n" \ 229 | " scriptable: (output graph for eth1 10 times)\n" \ 230 | " bmon -p eth1 -o 'ascii:diagram=graph;quitafter=10'\n" \ 231 | " show details for all ethernet interfaces:\n" \ 232 | " bmon -p 'eth*' -o 'ascii:diagram=details;quitafter=1'\n" \ 233 | "\n" \ 234 | " Author: Thomas Graf \n" \ 235 | "\n" \ 236 | " Options:\n" \ 237 | " diagram=TYPE Diagram type\n" \ 238 | " fgchar=CHAR Foreground character (default: '*')\n" \ 239 | " bgchar=CHAR Background character (default: '.')\n" \ 240 | " nchar=CHAR Noise character (default: ':')\n" \ 241 | " uchar=CHAR Unknown character (default: '?')\n" \ 242 | " height=NUM Height of graph (default: 6)\n" \ 243 | " xunit=UNIT X-Axis Unit (default: seconds)\n" \ 244 | " yunit=UNIT Y-Axis Unit (default: dynamic)\n" \ 245 | " quitafter=NUM Quit bmon after NUM outputs\n"); 246 | } 247 | 248 | static void ascii_parse_opt(const char *type, const char *value) 249 | { 250 | if (!strcasecmp(type, "diagram") && value) { 251 | if (tolower(*value) == 'l') 252 | c_diagram_type = D_LIST; 253 | else if (tolower(*value) == 'g') 254 | c_diagram_type = D_GRAPH; 255 | else if (tolower(*value) == 'd') 256 | c_diagram_type = D_DETAILS; 257 | else 258 | quit("Unknown diagram type '%s'\n", value); 259 | } else if (!strcasecmp(type, "fgchar") && value) 260 | graph_cfg.gc_foreground = value[0]; 261 | else if (!strcasecmp(type, "bgchar") && value) 262 | graph_cfg.gc_background = value[0]; 263 | else if (!strcasecmp(type, "nchar") && value) 264 | graph_cfg.gc_noise = value[0]; 265 | #if 0 266 | else if (!strcasecmp(type, "uchar") && value) 267 | set_unk_char(value[0]); 268 | #endif 269 | else if (!strcasecmp(type, "xunit") && value) 270 | c_hist = strdup(value); 271 | #if 0 272 | else if (!strcasecmp(type, "yunit") && value) { 273 | struct unit *u; 274 | 275 | if (!(u = unit_lookup(value))) 276 | quit("Unknown unit '%s'\n", value); 277 | 278 | graph_cfg.gc_unit = u; 279 | #endif 280 | else if (!strcasecmp(type, "height") && value) 281 | graph_cfg.gc_height = strtol(value, NULL, 0); 282 | else if (!strcasecmp(type, "quitafter") && value) 283 | c_quit_after = strtol(value, NULL, 0); 284 | else if (!strcasecmp(type, "help")) { 285 | print_help(); 286 | exit(0); 287 | } else 288 | quit("Unknown module option '%s'\n", type); 289 | } 290 | 291 | static struct bmon_module ascii_ops = { 292 | .m_name = "ascii", 293 | .m_do = ascii_draw, 294 | .m_parse_opt = ascii_parse_opt, 295 | }; 296 | 297 | static void __init ascii_init(void) 298 | { 299 | output_register(&ascii_ops); 300 | } 301 | -------------------------------------------------------------------------------- /src/out_format.c: -------------------------------------------------------------------------------- 1 | /* 2 | * out_format.c Formatted Output 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | static int c_quit_after = -1; 37 | static char *c_format; 38 | static int c_debug = 0; 39 | static FILE *c_fd; 40 | 41 | enum { 42 | OT_STRING, 43 | OT_TOKEN 44 | }; 45 | 46 | static struct out_token { 47 | int ot_type; 48 | char *ot_str; 49 | } *out_tokens; 50 | 51 | static int token_index; 52 | static int out_tokens_size; 53 | 54 | static char *get_token(struct element_group *g, struct element *e, 55 | const char *token, char *buf, size_t len) 56 | { 57 | if (!strncasecmp(token, "group:", 6)) { 58 | const char *n = token + 6; 59 | 60 | if (!strcasecmp(n, "nelements")) { 61 | snprintf(buf, len, "%u", g->g_nelements); 62 | return buf; 63 | } else if (!strcasecmp(n, "name")) 64 | return g->g_name; 65 | else if (!strcasecmp(n, "title")) 66 | return g->g_hdr->gh_title; 67 | 68 | } else if (!strncasecmp(token, "element:", 8)) { 69 | const char *n = token + 8; 70 | 71 | if (!strcasecmp(n, "name")) 72 | return e->e_name; 73 | else if (!strcasecmp(n, "description")) 74 | return e->e_description; 75 | else if (!strcasecmp(n, "nattrs")) { 76 | snprintf(buf, len, "%u", e->e_nattrs); 77 | return buf; 78 | } else if (!strcasecmp(n, "lifecycles")) { 79 | snprintf(buf, len, "%u", e->e_lifecycles); 80 | return buf; 81 | } else if (!strcasecmp(n, "level")) { 82 | snprintf(buf, len, "%u", e->e_level); 83 | return buf; 84 | } else if (!strcasecmp(n, "parent")) 85 | return e->e_parent ? e->e_parent->e_name : ""; 86 | else if (!strcasecmp(n, "id")) { 87 | snprintf(buf, len, "%u", e->e_id); 88 | return buf; 89 | } else if (!strcasecmp(n, "rxusage")) { 90 | snprintf(buf, len, "%2.0f", 91 | e->e_rx_usage == FLT_MAX ? e->e_rx_usage : 0.0f); 92 | return buf; 93 | } else if (!strcasecmp(n, "txusage")) { 94 | snprintf(buf, len, "%2.0f", 95 | e->e_tx_usage == FLT_MAX ? e->e_tx_usage : 0.0f); 96 | return buf; 97 | } else if (!strcasecmp(n, "haschilds")) { 98 | snprintf(buf, len, "%u", 99 | list_empty(&e->e_childs) ? 0 : 1); 100 | return buf; 101 | } 102 | } else if (!strncasecmp(token, "attr:", 5)) { 103 | const char *type = token + 5; 104 | char *name = strchr(type, ':'); 105 | struct attr_def *def; 106 | struct attr *a; 107 | 108 | if (!name) { 109 | fprintf(stderr, "Invalid attribute field \"%s\"\n", 110 | type); 111 | goto out; 112 | } 113 | 114 | name++; 115 | 116 | def = attr_def_lookup(name); 117 | if (!def) { 118 | fprintf(stderr, "Undefined attribute \"%s\"\n", name); 119 | goto out; 120 | } 121 | 122 | if (!(a = attr_lookup(e, def->ad_id))) 123 | goto out; 124 | 125 | if (!strncasecmp(type, "rx:", 3)) { 126 | snprintf(buf, len, "%" PRIu64, rate_get_total(&a->a_rx_rate)); 127 | return buf; 128 | } else if (!strncasecmp(type, "tx:", 3)) { 129 | snprintf(buf, len, "%" PRIu64, rate_get_total(&a->a_tx_rate)); 130 | return buf; 131 | } else if (!strncasecmp(type, "rxrate:", 7)) { 132 | snprintf(buf, len, "%.2f", a->a_rx_rate.r_rate); 133 | return buf; 134 | } else if (!strncasecmp(type, "txrate:", 7)) { 135 | snprintf(buf, len, "%.2f", a->a_tx_rate.r_rate); 136 | return buf; 137 | } 138 | } 139 | 140 | fprintf(stderr, "Unknown field \"%s\"\n", token); 141 | out: 142 | return "unknown"; 143 | } 144 | 145 | static void draw_element(struct element_group *g, struct element *e, void *arg) 146 | { 147 | int i; 148 | 149 | for (i = 0; i < token_index; i++) { 150 | char buf[128]; 151 | char *p; 152 | 153 | if (out_tokens[i].ot_type == OT_STRING) 154 | p = out_tokens[i].ot_str; 155 | else if (out_tokens[i].ot_type == OT_TOKEN) 156 | p = get_token(g, e, out_tokens[i].ot_str, 157 | buf, sizeof(buf)); 158 | else 159 | BUG(); 160 | 161 | if (p) 162 | fprintf(c_fd, "%s", p); 163 | } 164 | } 165 | 166 | static void format_draw(void) 167 | { 168 | group_foreach_recursive(draw_element, NULL); 169 | fflush(stdout); 170 | 171 | if (c_quit_after > 0) 172 | if (--c_quit_after == 0) 173 | exit(0); 174 | } 175 | 176 | static inline void add_token(int type, char *data) 177 | { 178 | if (!out_tokens_size) { 179 | out_tokens_size = 32; 180 | out_tokens = calloc(out_tokens_size, sizeof(struct out_token)); 181 | if (out_tokens == NULL) 182 | quit("Cannot allocate out token array\n"); 183 | } 184 | 185 | if (out_tokens_size <= token_index) { 186 | out_tokens_size += 32; 187 | out_tokens = realloc(out_tokens, out_tokens_size * sizeof(struct out_token)); 188 | if (out_tokens == NULL) 189 | quit("Cannot reallocate out token array\n"); 190 | } 191 | 192 | 193 | out_tokens[token_index].ot_type = type; 194 | out_tokens[token_index].ot_str = data; 195 | token_index++; 196 | } 197 | 198 | static int format_probe(void) 199 | { 200 | int new_one = 1; 201 | char *p, *e; 202 | 203 | for (p = c_format; *p; p++) { 204 | if (*p == '$') { 205 | char *s = p; 206 | s++; 207 | if (*s == '(') { 208 | s++; 209 | if (!*s) 210 | goto unexpected_end; 211 | e = strchr(s, ')'); 212 | if (e == NULL) 213 | goto invalid; 214 | 215 | *p = '\0'; 216 | *e = '\0'; 217 | add_token(OT_TOKEN, s); 218 | new_one = 1; 219 | p = e; 220 | continue; 221 | } 222 | } 223 | 224 | if (*p == '\\') { 225 | char *s = p; 226 | s++; 227 | switch (*s) { 228 | case 'n': 229 | *s = '\n'; 230 | goto finish_escape; 231 | case 't': 232 | *s = '\t'; 233 | goto finish_escape; 234 | case 'r': 235 | *s = '\r'; 236 | goto finish_escape; 237 | case 'v': 238 | *s = '\v'; 239 | goto finish_escape; 240 | case 'b': 241 | *s = '\b'; 242 | goto finish_escape; 243 | case 'f': 244 | *s = '\f'; 245 | goto finish_escape; 246 | case 'a': 247 | *s = '\a'; 248 | goto finish_escape; 249 | } 250 | 251 | goto out; 252 | 253 | finish_escape: 254 | *p = '\0'; 255 | add_token(OT_STRING, s); 256 | p = s; 257 | new_one = 0; 258 | continue; 259 | } 260 | 261 | out: 262 | if (new_one) { 263 | add_token(OT_STRING, p); 264 | new_one = 0; 265 | } 266 | } 267 | 268 | if (c_debug) { 269 | int i; 270 | for (i = 0; i < token_index; i++) 271 | printf(">>%s<\n", out_tokens[i].ot_str); 272 | } 273 | 274 | return 1; 275 | 276 | unexpected_end: 277 | fprintf(stderr, "Unexpected end of format string\n"); 278 | return 0; 279 | 280 | invalid: 281 | fprintf(stderr, "Missing ')' in format string\n"); 282 | return 0; 283 | } 284 | 285 | static void print_help(void) 286 | { 287 | printf( 288 | "format - Formatable Output\n" \ 289 | "\n" \ 290 | " Formatable ASCII output for scripts. Calls a drawing function for\n" \ 291 | " every item per node and outputs according to the specified format\n" \ 292 | " string. The format string consists of normal text and placeholders\n" \ 293 | " in the form of $(placeholder).\n" \ 294 | "\n" \ 295 | " Author: Thomas Graf \n" \ 296 | "\n" \ 297 | " Options:\n" \ 298 | " fmt=FORMAT Format string\n" \ 299 | " stderr Write to stderr instead of stdout\n" \ 300 | " quitafter=NUM Quit bmon after NUM outputs\n" \ 301 | "\n" \ 302 | " Placeholders:\n" \ 303 | " group:nelements Number of elements this group\n" \ 304 | " :name Name of group\n" \ 305 | " :title Title of group\n" \ 306 | " element:name Name of element\n" \ 307 | " :desc Description of element\n" \ 308 | " :nattrs Number of attributes\n" \ 309 | " :lifecycles Number of lifecycles\n" \ 310 | " :level Indentation level\n" \ 311 | " :parent Name of parent element\n" \ 312 | " :rxusage RX usage in percent\n" \ 313 | " :txusage TX usage in percent)\n" \ 314 | " :id ID of element\n" \ 315 | " :haschilds Indicate if element has children (0|1)\n" \ 316 | " attr:rx: RX counter of attribute \n" \ 317 | " :tx: TX counter of attribute \n" \ 318 | " :rxrate: RX rate of attribute \n" \ 319 | " :txrate: TX rate of attribute \n" \ 320 | "\n" \ 321 | " Supported Escape Sequences: \\n, \\t, \\r, \\v, \\b, \\f, \\a\n" \ 322 | "\n" \ 323 | " Examples:\n" \ 324 | " '$(element:name)\\t$(attr:rx:bytes)\\t$(attr:tx:bytes)\\n'\n" \ 325 | " lo 12074 12074\n" \ 326 | "\n" \ 327 | " '$(element:name) $(attr:rxrate:packets) $(attr:txrate:packets)\\n'\n" \ 328 | " eth0 33 5\n" \ 329 | "\n" \ 330 | " 'Item: $(element:name)\\nBytes Rate: $(attr:rxrate:bytes)/" \ 331 | "$(attr:txrate:bytes)\\nPackets Rate: $(attr:rxrate:packets)/" \ 332 | "$(attr:txrate:packets)\\n'\n" \ 333 | " Item: eth0\n" \ 334 | " Bytes Rate: 49130/2119\n" \ 335 | " Packets Rate: 40/11\n" \ 336 | "\n"); 337 | } 338 | 339 | static void format_parse_opt(const char *type, const char *value) 340 | { 341 | if (!strcasecmp(type, "stderr")) 342 | c_fd = stderr; 343 | else if (!strcasecmp(type, "debug")) 344 | c_debug = 1; 345 | else if (!strcasecmp(type, "fmt")) { 346 | if (c_format) 347 | free(c_format); 348 | c_format = strdup(value); 349 | } else if (!strcasecmp(type, "quitafter") && 350 | value) 351 | c_quit_after = strtol(value, NULL, 0); 352 | else if (!strcasecmp(type, "help")) { 353 | print_help(); 354 | exit(0); 355 | } 356 | } 357 | 358 | static struct bmon_module format_ops = { 359 | .m_name = "format", 360 | .m_do = format_draw, 361 | .m_probe = format_probe, 362 | .m_parse_opt = format_parse_opt, 363 | }; 364 | 365 | static void __init ascii_init(void) 366 | { 367 | c_fd = stdout; 368 | c_format = strdup("$(element:name) $(attr:rx:bytes) $(attr:tx:bytes) " \ 369 | "$(attr:rx:packets) $(attr:tx:packets)\\n"); 370 | 371 | output_register(&format_ops); 372 | } 373 | -------------------------------------------------------------------------------- /src/out_null.c: -------------------------------------------------------------------------------- 1 | /* 2 | * out_null.c Null Output 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | static void print_help(void) 31 | { 32 | printf( 33 | "null - No output\n" \ 34 | "\n" \ 35 | " Disable primary output method\n" \ 36 | " Author: Thomas Graf \n" \ 37 | "\n"); 38 | } 39 | 40 | static void null_parse_opt(const char *type, const char *value) 41 | { 42 | if (!strcasecmp(type, "help")) { 43 | print_help(); 44 | exit(0); 45 | } 46 | } 47 | 48 | static struct bmon_module null_ops = { 49 | .m_name = "null", 50 | .m_parse_opt = null_parse_opt, 51 | }; 52 | 53 | static void __init null_init(void) 54 | { 55 | output_register(&null_ops); 56 | } 57 | -------------------------------------------------------------------------------- /src/output.c: -------------------------------------------------------------------------------- 1 | /* 2 | * output.c Output API 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | static struct bmon_subsys output_subsys; 34 | 35 | void output_register(struct bmon_module *m) 36 | { 37 | module_register(&output_subsys, m); 38 | } 39 | 40 | static void activate_default(void) 41 | { 42 | /* 43 | * Try to activate a default output module if the user did not make 44 | * a selection 45 | */ 46 | if (!output_subsys.s_nmod) { 47 | struct bmon_module *m; 48 | 49 | if (!output_set("curses")) 50 | return; 51 | 52 | if (!output_set("ascii")) 53 | return; 54 | 55 | /* Fall back to anything that could act as default */ 56 | list_for_each_entry(m, &output_subsys.s_mod_list, m_list) { 57 | if (m->m_flags & BMON_MODULE_DEFAULT) 58 | if (!output_set(m->m_name)) 59 | return; 60 | } 61 | 62 | quit("No output module found\n"); 63 | } 64 | } 65 | 66 | void output_pre(void) 67 | { 68 | module_foreach_run_enabled_pre(&output_subsys); 69 | } 70 | 71 | void output_draw(void) 72 | { 73 | module_foreach_run_enabled(&output_subsys); 74 | } 75 | 76 | void output_post(void) 77 | { 78 | module_foreach_run_enabled_post(&output_subsys); 79 | } 80 | 81 | int output_set(const char *name) 82 | { 83 | return module_set(&output_subsys, name); 84 | } 85 | 86 | static struct bmon_subsys output_subsys = { 87 | .s_name = "output", 88 | .s_activate_default = &activate_default, 89 | .s_mod_list = LIST_SELF(output_subsys.s_mod_list), 90 | }; 91 | 92 | static void __init __output_init(void) 93 | { 94 | return module_register_subsys(&output_subsys); 95 | } 96 | -------------------------------------------------------------------------------- /src/unit.c: -------------------------------------------------------------------------------- 1 | /* 2 | * unit.c Unit Definitions 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | static struct unit *byte_unit, *bit_unit; 32 | 33 | static LIST_HEAD(units); 34 | 35 | static struct list_head *get_flist(struct unit *unit) 36 | { 37 | int div = UNIT_DEFAULT; 38 | 39 | if (cfg_getbool(cfg, "use_bit")) 40 | div = UNIT_BIT; 41 | else if (cfg_getbool(cfg, "use_si")) 42 | div = UNIT_SI; 43 | 44 | if (!list_empty(&unit->u_div[div])) 45 | return &unit->u_div[div]; 46 | else 47 | return &unit->u_div[UNIT_DEFAULT]; 48 | } 49 | 50 | struct unit *unit_lookup(const char *name) 51 | { 52 | struct unit *unit; 53 | 54 | list_for_each_entry(unit, &units, u_list) 55 | if (!strcmp(name, unit->u_name)) 56 | return unit; 57 | 58 | return NULL; 59 | } 60 | 61 | /** 62 | * Lookup best divisor to use for a certain situation 63 | * @hint Value in question (for DYNAMIC_EXP) 64 | * @unit Unit of value 65 | * @name Place to store name of divisor used 66 | * @prec Place to store suggested precision 67 | * 68 | * Searches for the best divisor to be used depending on the unit 69 | * exponent configured by the user. If a dynamic exponent is 70 | * configured, the divisor is selected based on the value of hint 71 | * so that hint is dividied into a small float >= 1.0. The name 72 | * of the divisor used is stored in *name. 73 | * 74 | * If prec points to a vaild integer, a number of precision digits 75 | * is suggested to avoid n.00 to make pretty printing easier. 76 | */ 77 | double unit_divisor(uint64_t hint, struct unit *unit, char **name, 78 | int *prec) 79 | { 80 | struct list_head *flist = get_flist(unit); 81 | struct fraction *f; 82 | 83 | if (prec) 84 | *prec = 2; 85 | 86 | if (cfg_unit_exp == DYNAMIC_EXP) { 87 | list_for_each_entry_reverse(f, flist, f_list) { 88 | if (hint >= f->f_divisor) 89 | goto found_it; 90 | } 91 | } else { 92 | int n = cfg_unit_exp; 93 | list_for_each_entry(f, flist, f_list) { 94 | if (--n == 0) 95 | goto found_it; 96 | } 97 | } 98 | 99 | *name = ""; 100 | return 1; 101 | 102 | found_it: 103 | if (f->f_divisor == 1.0f && prec) 104 | *prec = 0; 105 | 106 | *name = f->f_name; 107 | return f->f_divisor; 108 | } 109 | 110 | double unit_value2str(uint64_t value, struct unit *unit, 111 | char **name, int *prec) 112 | { 113 | double div = unit_divisor(value, unit, name, prec); 114 | double v = (double) value; 115 | 116 | if (fmod(v, div) == 0.0f && prec) 117 | *prec = 0; 118 | 119 | return v / div; 120 | } 121 | 122 | void fraction_free(struct fraction *f) 123 | { 124 | if (!f) 125 | return; 126 | 127 | list_del(&f->f_list); 128 | xfree(f->f_name); 129 | xfree(f); 130 | } 131 | 132 | void unit_add_div(struct unit *unit, int type, const char *txt, float div) 133 | { 134 | struct fraction *f; 135 | 136 | if (!unit) 137 | BUG(); 138 | 139 | f = xcalloc(1, sizeof(*f)); 140 | 141 | init_list_head(&f->f_list); 142 | 143 | f->f_divisor = div; 144 | f->f_name = strdup(txt); 145 | 146 | list_add_tail(&f->f_list, &unit->u_div[type]); 147 | } 148 | 149 | struct unit *unit_add(const char *name) 150 | { 151 | struct unit *unit; 152 | int i; 153 | 154 | if (!(unit = unit_lookup(name))) { 155 | unit = xcalloc(1, sizeof(*unit)); 156 | unit->u_name = strdup(name); 157 | 158 | for (i = 0; i < __UNIT_MAX; i++) 159 | init_list_head(&unit->u_div[i]); 160 | 161 | list_add_tail(&unit->u_list, &units); 162 | } 163 | 164 | return unit; 165 | } 166 | 167 | static void unit_free(struct unit *u) 168 | { 169 | struct fraction *f, *n; 170 | 171 | if (!u) 172 | return; 173 | 174 | list_for_each_entry_safe(f, n, &u->u_div[UNIT_DEFAULT], f_list) 175 | fraction_free(f); 176 | 177 | list_for_each_entry_safe(f, n, &u->u_div[UNIT_SI], f_list) 178 | fraction_free(f); 179 | 180 | xfree(u->u_name); 181 | xfree(u); 182 | } 183 | 184 | char *unit_bytes2str(uint64_t bytes, char *buf, size_t len) 185 | { 186 | char *ustr; 187 | int prec; 188 | double v; 189 | 190 | if (byte_unit) { 191 | v = unit_value2str(bytes, byte_unit, &ustr, &prec); 192 | snprintf(buf, len, "%'.*f%3s", prec, v, ustr); 193 | } else 194 | snprintf(buf, len, "%" PRIu64, bytes); 195 | 196 | return buf; 197 | } 198 | 199 | char *unit_bit2str(uint64_t bits, char *buf, size_t len) 200 | { 201 | char *ustr; 202 | int prec; 203 | double v; 204 | 205 | if (bit_unit) { 206 | v = unit_value2str(bits, bit_unit, &ustr, &prec); 207 | snprintf(buf, len, "%'.*f%3s", prec, v, ustr); 208 | } else 209 | snprintf(buf, len, "%" PRIu64, bits); 210 | 211 | return buf; 212 | } 213 | 214 | static void __exit unit_exit(void) 215 | { 216 | struct unit *u, *n; 217 | 218 | list_for_each_entry_safe(u, n, &units, u_list) 219 | unit_free(u); 220 | } 221 | -------------------------------------------------------------------------------- /src/utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * utils.c General purpose utilities 3 | * 4 | * Copyright (c) 2001-2013 Thomas Graf 5 | * Copyright (c) 2013 Red Hat, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a 8 | * copy of this software and associated documentation files (the "Software"), 9 | * to deal in the Software without restriction, including without limitation 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | * and/or sell copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #ifdef __MACH__ 31 | #include 32 | #include 33 | #endif 34 | 35 | void *xcalloc(size_t n, size_t s) 36 | { 37 | void *d = calloc(n, s); 38 | 39 | if (NULL == d) { 40 | fprintf(stderr, "xalloc: Out of memory\n"); 41 | exit(ENOMEM); 42 | } 43 | 44 | return d; 45 | } 46 | 47 | void *xrealloc(void *p, size_t s) 48 | { 49 | void *d = realloc(p, s); 50 | 51 | if (NULL == d) { 52 | fprintf(stderr, "xrealloc: Out of memory!\n"); 53 | exit(ENOMEM); 54 | } 55 | 56 | return d; 57 | } 58 | 59 | void xfree(void *d) 60 | { 61 | if (d) 62 | free(d); 63 | } 64 | 65 | float timestamp_to_float(timestamp_t *src) 66 | { 67 | return (float) src->tv_sec + ((float) src->tv_usec / 1000000.0f); 68 | } 69 | 70 | int64_t timestamp_to_int(timestamp_t *src) 71 | { 72 | return (src->tv_sec * 1000000ULL) + src->tv_usec; 73 | } 74 | 75 | void float_to_timestamp(timestamp_t *dst, float src) 76 | { 77 | dst->tv_sec = (time_t) src; 78 | dst->tv_usec = (src - ((float) ((time_t) src))) * 1000000.0f; 79 | } 80 | 81 | void timestamp_add(timestamp_t *dst, timestamp_t *src1, timestamp_t *src2) 82 | { 83 | dst->tv_sec = src1->tv_sec + src2->tv_sec; 84 | dst->tv_usec = src1->tv_usec + src2->tv_usec; 85 | 86 | if (dst->tv_usec >= 1000000) { 87 | dst->tv_sec++; 88 | dst->tv_usec -= 1000000; 89 | } 90 | } 91 | 92 | void timestamp_sub(timestamp_t *dst, timestamp_t *src1, timestamp_t *src2) 93 | { 94 | dst->tv_sec = src1->tv_sec - src2->tv_sec; 95 | dst->tv_usec = src1->tv_usec - src2->tv_usec; 96 | if (dst->tv_usec < 0) { 97 | dst->tv_sec--; 98 | dst->tv_usec += 1000000; 99 | } 100 | } 101 | 102 | int timestamp_le(timestamp_t *a, timestamp_t *b) 103 | { 104 | if (a->tv_sec > b->tv_sec) 105 | return 0; 106 | 107 | if (a->tv_sec < b->tv_sec || a->tv_usec <= b->tv_usec) 108 | return 1; 109 | 110 | return 0; 111 | } 112 | 113 | int timestamp_is_negative(timestamp_t *ts) 114 | { 115 | return (ts->tv_sec < 0 || ts->tv_usec < 0); 116 | } 117 | 118 | void update_timestamp(timestamp_t *dst) 119 | { 120 | #ifdef __MACH__ 121 | clock_serv_t cclock; 122 | mach_timespec_t tp; 123 | 124 | host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); 125 | clock_get_time(cclock, &tp); 126 | mach_port_deallocate(mach_task_self(), cclock); 127 | #else 128 | struct timespec tp; 129 | 130 | clock_gettime(CLOCK_MONOTONIC, &tp); 131 | #endif 132 | 133 | dst->tv_sec = tp.tv_sec; 134 | dst->tv_usec = tp.tv_nsec / 1000; 135 | } 136 | 137 | void copy_timestamp(timestamp_t *ts1, timestamp_t *ts2) 138 | { 139 | ts1->tv_sec = ts2->tv_sec; 140 | ts1->tv_usec = ts2->tv_usec; 141 | } 142 | 143 | float timestamp_diff(timestamp_t *t1, timestamp_t *t2) 144 | { 145 | float diff; 146 | 147 | diff = t2->tv_sec - t1->tv_sec; 148 | diff += (((float) t2->tv_usec - (float) t1->tv_usec) / 1000000.0f); 149 | 150 | return diff; 151 | } 152 | 153 | #if 0 154 | 155 | 156 | float diff_now(timestamp_t *t1) 157 | { 158 | timestamp_t now; 159 | update_ts(&now); 160 | return time_diff(t1, &now); 161 | } 162 | 163 | const char *xinet_ntop(struct sockaddr *src, char *dst, socklen_t cnt) 164 | { 165 | void *s; 166 | int family; 167 | 168 | if (src->sa_family == AF_INET6) { 169 | s = &((struct sockaddr_in6 *) src)->sin6_addr; 170 | family = AF_INET6; 171 | } else if (src->sa_family == AF_INET) { 172 | s = &((struct sockaddr_in *) src)->sin_addr; 173 | family = AF_INET; 174 | } else 175 | return NULL; 176 | 177 | return inet_ntop(family, s, dst, cnt); 178 | } 179 | 180 | uint64_t parse_size(const char *str) 181 | { 182 | char *p; 183 | uint64_t l = strtol(str, &p, 0); 184 | if (p == str) 185 | return -1; 186 | 187 | if (*p) { 188 | if (!strcasecmp(p, "kb") || !strcasecmp(p, "k")) 189 | l *= 1024; 190 | else if (!strcasecmp(p, "gb") || !strcasecmp(p, "g")) 191 | l *= 1024*1024*1024; 192 | else if (!strcasecmp(p, "gbit")) 193 | l *= 1024*1024*1024/8; 194 | else if (!strcasecmp(p, "mb") || !strcasecmp(p, "m")) 195 | l *= 1024*1024; 196 | else if (!strcasecmp(p, "mbit")) 197 | l *= 1024*1024/8; 198 | else if (!strcasecmp(p, "kbit")) 199 | l *= 1024/8; 200 | else if (strcasecmp(p, "b") != 0) 201 | return -1; 202 | } 203 | 204 | return l; 205 | } 206 | 207 | #ifndef HAVE_STRDUP 208 | char *strdup(const char *s) 209 | { 210 | char *t = xcalloc(1, strlen(s) + 1); 211 | memcpy(t, s, strlen(s)); 212 | return s; 213 | } 214 | #endif 215 | 216 | char *timestamp2str(timestamp_t *ts, char *buf, size_t len) 217 | { 218 | int i, split[5]; 219 | char *units[] = {"d", "h", "m", "s", "usec"}; 220 | time_t sec = ts->tv_sec; 221 | 222 | #define _SPLIT(idx, unit) if ((split[idx] = sec / unit) > 0) sec %= unit 223 | _SPLIT(0, 86400); /* days */ 224 | _SPLIT(1, 3600); /* hours */ 225 | _SPLIT(2, 60); /* minutes */ 226 | _SPLIT(3, 1); /* seconds */ 227 | #undef _SPLIT 228 | split[4] = ts->tv_usec; 229 | 230 | memset(buf, 0, len); 231 | 232 | for (i = 0; i < ARRAY_SIZE(split); i++) { 233 | if (split[i] > 0) { 234 | char t[64]; 235 | snprintf(t, sizeof(t), "%s%d%s", 236 | strlen(buf) ? " " : "", split[i], units[i]); 237 | strncat(buf, t, len - strlen(buf) - 1); 238 | } 239 | } 240 | 241 | return buf; 242 | } 243 | 244 | int parse_date(const char *str, xdate_t *dst) 245 | { 246 | time_t now = time(NULL); 247 | struct tm *now_tm = localtime(&now); 248 | const char *next; 249 | char *p; 250 | struct tm backup; 251 | 252 | memset(dst, 0, sizeof(*dst)); 253 | 254 | if (strchr(str, '-')) { 255 | next = strptime(str, "%Y-%m-%d", &dst->d_tm); 256 | if (next == NULL || 257 | (*next != '\0' && *next != ' ')) 258 | goto invalid_date; 259 | } else { 260 | dst->d_tm.tm_mday = now_tm->tm_mday; 261 | dst->d_tm.tm_mon = now_tm->tm_mon; 262 | dst->d_tm.tm_year = now_tm->tm_year; 263 | dst->d_tm.tm_wday = now_tm->tm_wday; 264 | dst->d_tm.tm_yday = now_tm->tm_yday; 265 | dst->d_tm.tm_isdst = now_tm->tm_isdst; 266 | next = str; 267 | } 268 | 269 | if (*next == '\0') 270 | return 0; 271 | 272 | while (*next == ' ') 273 | next++; 274 | 275 | if (*next == '.') 276 | goto read_us; 277 | 278 | /* Make a backup, we can't rely on strptime to not screw 279 | * up what we've got so far. */ 280 | memset(&backup, 0, sizeof(backup)); 281 | memcpy(&backup, &dst->d_tm, sizeof(backup)); 282 | 283 | next = strptime(next, "%H:%M:%S", &dst->d_tm); 284 | if (next == NULL || 285 | (*next != '\0' && *next != '.')) 286 | goto invalid_date; 287 | 288 | dst->d_tm.tm_mday = backup.tm_mday; 289 | dst->d_tm.tm_mon = backup.tm_mon; 290 | dst->d_tm.tm_year = backup.tm_year; 291 | dst->d_tm.tm_wday = backup.tm_wday; 292 | dst->d_tm.tm_yday = backup.tm_yday; 293 | dst->d_tm.tm_isdst = backup.tm_isdst; 294 | 295 | if (*next == '\0') 296 | return 0; 297 | read_us: 298 | if (*next == '.') 299 | next++; 300 | else 301 | BUG(); 302 | 303 | dst->d_usec = strtoul(next, &p, 10); 304 | 305 | if (*p != '\0') 306 | goto invalid_date; 307 | 308 | return 0; 309 | 310 | invalid_date: 311 | fprintf(stderr, "Invalid date \"%s\"\n", str); 312 | return -1; 313 | } 314 | 315 | static inline void print_token(FILE *fd, struct db_token *tok) 316 | { 317 | fprintf(fd, "%s", tok->t_name); 318 | 319 | if (tok->t_flags & DB_T_ATTR) 320 | fprintf(fd, ""); 321 | } 322 | 323 | void db_print_filter(FILE *fd, struct db_filter *filter) 324 | { 325 | if (filter->f_node) 326 | print_token(fd, filter->f_node); 327 | 328 | if (filter->f_group) { 329 | fprintf(fd, "."); 330 | print_token(fd, filter->f_group); 331 | } 332 | 333 | if (filter->f_item) { 334 | fprintf(fd, "."); 335 | print_token(fd, filter->f_item); 336 | } 337 | 338 | if (filter->f_attr) { 339 | fprintf(fd, "."); 340 | print_token(fd, filter->f_attr); 341 | } 342 | 343 | if (filter->f_field) 344 | fprintf(fd, "@%s", filter->f_field); 345 | } 346 | 347 | void *db_filter__scan_string(const char *); 348 | void db_filter__switch_to_buffer(void *); 349 | int db_filter_parse(void); 350 | 351 | struct db_filter * parse_db_filter(const char *buf) 352 | { 353 | struct db_filter *f; 354 | struct db_token *tok, *t; 355 | 356 | void *state = db_filter__scan_string(buf); 357 | db_filter__switch_to_buffer(state); 358 | 359 | if (db_filter_parse()) { 360 | fprintf(stderr, "Failed to parse filter \"%s\"\n", buf); 361 | return NULL; 362 | } 363 | 364 | tok = db_filter_out; /* generated by yacc */ 365 | if (tok == NULL) 366 | return NULL; 367 | 368 | f = xcalloc(1, sizeof(*f)); 369 | 370 | f->f_node = tok; 371 | 372 | if (!tok->t_next) 373 | goto out; 374 | tok = tok->t_next; 375 | 376 | if (tok->t_flags & DB_T_ATTR) { 377 | fprintf(stderr, "Node may not contain an attribute field\n"); 378 | goto errout; 379 | } 380 | 381 | f->f_group = tok; 382 | if (!tok->t_next) 383 | goto out; 384 | tok = tok->t_next; 385 | 386 | if (tok->t_flags & DB_T_ATTR) { 387 | fprintf(stderr, "Group may not contain an attribute field\n"); 388 | goto errout; 389 | } 390 | 391 | f->f_item = tok; 392 | 393 | if (!tok->t_next) 394 | goto out; 395 | tok = tok->t_next; 396 | 397 | if (tok->t_flags & DB_T_ATTR) { 398 | if (!tok->t_name) 399 | BUG(); 400 | f->f_field = tok->t_name; 401 | goto out; 402 | } else 403 | f->f_attr = tok; 404 | 405 | if (!tok->t_next) 406 | goto out; 407 | tok = tok->t_next; 408 | 409 | if (tok->t_flags & DB_T_ATTR) { 410 | if (!tok->t_name) 411 | BUG(); 412 | f->f_field = tok->t_name; 413 | } else { 414 | fprintf(stderr, "Unexpected additional token after attribute\n"); 415 | goto errout; 416 | } 417 | 418 | out: 419 | /* free unused tokens */ 420 | for (tok = tok->t_next ; tok; tok = t) { 421 | t = tok->t_next; 422 | if (tok->t_name) 423 | free(tok->t_name); 424 | free(tok); 425 | } 426 | 427 | return f; 428 | 429 | errout: 430 | free(f); 431 | f = NULL; 432 | tok = db_filter_out; 433 | goto out; 434 | } 435 | #endif 436 | --------------------------------------------------------------------------------