Annotation of embedaddon/bmon/src/bmon.c, revision 1.1.1.3

1.1       misho       1: /*
                      2:  * src/bmon.c             Bandwidth Monitor
                      3:  *
1.1.1.2   misho       4:  * Copyright (c) 2001-2013 Thomas Graf <tgraf@suug.ch>
                      5:  * Copyright (c) 2013 Red Hat, Inc.
1.1       misho       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 <bmon/bmon.h>
                     27: #include <bmon/conf.h>
1.1.1.2   misho      28: #include <bmon/attr.h>
                     29: #include <bmon/utils.h>
1.1       misho      30: #include <bmon/input.h>
                     31: #include <bmon/output.h>
1.1.1.2   misho      32: #include <bmon/module.h>
                     33: #include <bmon/group.h>
1.1       misho      34: 
                     35: int start_time;
                     36: 
                     37: struct reader_timing rtiming;
1.1.1.2   misho      38: 
1.1       misho      39: static char *usage_text =
                     40: "Usage: bmon [OPTION]...\n" \
                     41: "\n" \
                     42: "Options:\n" \
1.1.1.2   misho      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" \
1.1       misho      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" \
1.1.1.2   misho      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 html module\n" \
1.1       misho      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(1) 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;
1.1.1.2   misho      85:                module_shutdown();
1.1       misho      86:        }
                     87: }
                     88: 
1.1.1.3 ! misho      89: static void sig_exit(void)
1.1       misho      90: {
                     91:        do_shutdown();
                     92: }
                     93: 
                     94: void quit(const char *fmt, ...)
                     95: {
                     96:        static int done;
                     97:        va_list args;
                     98: 
1.1.1.2   misho      99:        va_start(args, fmt);
                    100:        vfprintf(stderr, fmt, args);
                    101:        va_end(args);
                    102: 
1.1       misho     103:        if (!done) {
                    104:                done = 1;
                    105:                do_shutdown();
                    106:        }
                    107: 
                    108:        exit(1);
                    109: }
                    110: 
1.1.1.2   misho     111: static inline void print_version(void)
1.1       misho     112: {
                    113:        printf("bmon %s\n", PACKAGE_VERSION);
1.1.1.3 ! misho     114:        printf("Copyright (C) 2001-2015 by Thomas Graf <tgraf@suug.ch>\n");
1.1.1.2   misho     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");
1.1       misho     119: }
                    120: 
1.1.1.2   misho     121: static void parse_args_pre(int argc, char *argv[])
1.1       misho     122: {
1.1.1.2   misho     123:        DBG("Parsing arguments pre state");
                    124: 
1.1       misho     125:        for (;;)
                    126:        {
1.1.1.2   misho     127:                char *gostr = "+:hvVf:";
1.1       misho     128: 
1.1.1.2   misho     129:                struct option long_opts[] = {
1.1.1.3 ! misho     130:                        {"help", 0, NULL, 'h'},
        !           131:                        {"version", 0, NULL, 'v'},
        !           132:                        {"configfile", 1, NULL, 'f'},
        !           133:                        {NULL, 0, NULL, 0},
1.1.1.2   misho     134:                };
                    135:                int c = getopt_long(argc, argv, gostr, long_opts, NULL);
1.1       misho     136:                if (c == -1)
                    137:                        break;
                    138:                
                    139:                switch (c)
                    140:                {
1.1.1.2   misho     141:                        case 'f':
                    142:                                set_configfile(optarg);
1.1       misho     143:                                break;
                    144: 
1.1.1.2   misho     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: }
1.1       misho     156: 
1.1.1.2   misho     157: static int parse_args_post(int argc, char *argv[])
                    158: {
                    159:        DBG("Parsing arguments post state");
1.1       misho     160: 
1.1.1.2   misho     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[] = {
1.1.1.3 ! misho     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},
1.1.1.2   misho     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;
1.1       misho     190:                                break;
                    191: 
1.1.1.2   misho     192:                        case 'o':
                    193:                                if (output_set(optarg))
                    194:                                        return 1;
1.1       misho     195:                                break;
                    196: 
1.1.1.2   misho     197:                        case 'p':
                    198:                                cfg_setstr(cfg, "policy", optarg);
1.1       misho     199:                                break;
                    200: 
                    201:                        case 'r':
1.1.1.2   misho     202:                                cfg_setfloat(cfg, "read_interval", strtod(optarg, NULL));
1.1       misho     203:                                break;
                    204: 
                    205:                        case 'R':
1.1.1.2   misho     206:                                cfg_setfloat(cfg, "rate_interval", strtod(optarg, NULL));
1.1       misho     207:                                break;
                    208: 
                    209:                        case 's':
1.1.1.2   misho     210:                                cfg_setint(cfg, "sleep_time", strtoul(optarg, NULL, 0));
1.1       misho     211:                                break;
                    212: 
                    213:                        case 'a':
1.1.1.3 ! misho     214:                                cfg_setbool(cfg, "show_all", cfg_true);
1.1       misho     215:                                break;
                    216: 
1.1.1.2   misho     217:                        case 'U':
                    218:                                cfg_setbool(cfg, "use_si", cfg_true);
1.1       misho     219:                                break;
                    220: 
1.1.1.2   misho     221:                        case 'b':
                    222:                                cfg_setbool(cfg, "use_bit", cfg_true);
1.1       misho     223:                                break;
                    224: 
1.1.1.2   misho     225:                        case 'L':
                    226:                                cfg_setint(cfg, "lifetime", strtoul(optarg, NULL, 0));
1.1       misho     227:                                break;
                    228: 
1.1.1.2   misho     229:                        case 'f':
                    230:                                /* Already handled in pre getopt loop */
1.1       misho     231:                                break;
                    232: 
                    233:                        default:
                    234:                                quit("Aborting...\n");
1.1.1.2   misho     235:                                break;
                    236: 
1.1       misho     237:                }
                    238:        }
1.1.1.2   misho     239: 
                    240:        return 0;
1.1       misho     241: }
                    242: 
1.1.1.2   misho     243: #if 0
1.1       misho     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: }
1.1.1.2   misho     257: #endif
1.1       misho     258: 
                    259: int main(int argc, char *argv[])
                    260: {
1.1.1.2   misho     261:        unsigned long sleep_time;
                    262:        double read_interval;
                    263:        
1.1.1.3 ! misho     264:        start_time = time(NULL);
1.1.1.2   misho     265:        memset(&rtiming, 0, sizeof(rtiming));
                    266:        rtiming.rt_variance.v_min = FLT_MAX;
1.1       misho     267: 
1.1.1.2   misho     268:        /*
                    269:         * Early initialization before reading config
                    270:         */
                    271:        conf_init_pre();
                    272:        parse_args_pre(argc, argv);
1.1       misho     273: 
1.1.1.2   misho     274:        /*
                    275:         * Reading the configuration file */
                    276:        configfile_read();
1.1       misho     277: 
1.1.1.2   misho     278:        /*
                    279:         * Late initialization after reading config
                    280:         */
                    281:        if (parse_args_post(argc, argv))
                    282:                return 1;
                    283:        conf_init_post();
1.1       misho     284: 
1.1.1.2   misho     285:        module_init();
1.1       misho     286: 
1.1.1.2   misho     287:        read_interval = cfg_read_interval;
                    288:        sleep_time = cfg_getint(cfg, "sleep_time");
1.1       misho     289: 
1.1.1.2   misho     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 {
1.1       misho     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: 
1.1.1.2   misho     307:                float_to_timestamp(&ri, read_interval);
1.1       misho     308: 
                    309:                /*
1.1.1.2   misho     310:                 * NR := NOW
1.1       misho     311:                 */
1.1.1.2   misho     312:                update_timestamp(&rtiming.rt_next_read);
1.1       misho     313:                
                    314:                for (;;) {
                    315:                        output_pre();
                    316: 
                    317:                        /*
1.1.1.2   misho     318:                         * E := NOW
1.1       misho     319:                         */
1.1.1.2   misho     320:                        update_timestamp(&e);
1.1       misho     321: 
                    322:                        /*
                    323:                         * IF NR <= E THEN
                    324:                         */
1.1.1.2   misho     325:                        if (timestamp_le(&rtiming.rt_next_read, &e)) {
1.1       misho     326:                                timestamp_t c;
                    327: 
                    328:                                /*
                    329:                                 * C :=  (NR - E)
                    330:                                 */
1.1.1.2   misho     331:                                timestamp_sub(&c, &rtiming.rt_next_read, &e);
1.1       misho     332: 
1.1.1.2   misho     333:                                //calc_variance(&c, &ri);
1.1       misho     334: 
                    335:                                /*
                    336:                                 * LR := E
                    337:                                 */
1.1.1.2   misho     338:                                copy_timestamp(&rtiming.rt_last_read, &e);
1.1       misho     339: 
                    340:                                /*
                    341:                                 * NR := E + RI + C
                    342:                                 */
1.1.1.2   misho     343:                                timestamp_add(&rtiming.rt_next_read, &e, &ri);
                    344:                                timestamp_add(&rtiming.rt_next_read,
                    345:                                       &rtiming.rt_next_read, &c);
                    346: 
1.1       misho     347: 
1.1.1.2   misho     348:                                reset_update_flags();
1.1       misho     349:                                input_read();
1.1.1.2   misho     350:                                free_unused_elements();
1.1       misho     351:                                output_draw();
                    352:                                output_post();
                    353:                        }
                    354: 
                    355:                        /*
                    356:                         * ST := Configured ST
                    357:                         */
1.1.1.2   misho     358:                        st = sleep_time;
1.1       misho     359: 
                    360:                        /*
                    361:                         * IF (NR - E) < ST THEN
                    362:                         */
1.1.1.2   misho     363:                        timestamp_sub(&tmp, &rtiming.rt_next_read, &e);
1.1       misho     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:                }
1.1.1.2   misho     382:        } while (0);
                    383: 
1.1       misho     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: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>