sbm

simple bandwidth monitor
git clone git://git.2f30.org/sbm.git
Log | Files | Refs | LICENSE

commit b1cc4843e941f5cc44243bb547baa00a21a7a651
parent f66a43898ddc9ebff38ccc3a297e1013a192a43c
Author: sin <sin@2f30.org>
Date:   Mon Feb 22 12:31:08 +0000

Add delay support

Diffstat:
sbm.1 | 15++++++++++-----
sbm.c | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
2 files changed, 73 insertions(+), 21 deletions(-)
diff --git a/sbm.1 b/sbm.1 @@ -6,23 +6,28 @@ .Nd simple bandwidth monitor .Sh SYNOPSIS .Nm sbm -.Op Fl i Ar interface .Op Fl c Ar count +.Op Fl d Ar delay +.Op Fl i Ar interface .Sh DESCRIPTION .Nm is a simple bandwidth monitor. .Sh OPTIONS .Bl -tag -width "-i interface" -.It Fl i Ar interface -Monitor the selected -.Ar interface . -If not provided the first active, non-loopback interface will be used. .It Fl c Ar count Stop monitoring after .Ar count samples. If .Ar count is 0, it will loop forever. This is the default. +.It Fl d Ar delay +Sample interface statistics every +.Ar delay +ms. The default is 1000 ms. +.It Fl i Ar interface +Monitor the selected +.Ar interface . +If not provided the first active, non-loopback interface will be used. .El .Sh AUTHORS .An Dimitris Papastamos Aq Mt sin@2f30.org diff --git a/sbm.c b/sbm.c @@ -15,6 +15,7 @@ */ #include <sys/types.h> +#include <sys/time.h> #include <sys/socket.h> #include <net/if.h> @@ -33,6 +34,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <time.h> #include <unistd.h> #include "arg.h" @@ -176,37 +178,74 @@ print(char *ifname, unsigned long long rxbits, unsigned long long txbits, ifname, rxbits, rxsuffix, txbits, txsuffix, rxpps, txpps); } +int +clock_gettime_tv(clockid_t clock_id, struct timeval *tv) +{ + struct timespec ts; + int ret; + + ret = clock_gettime(clock_id, &ts); + tv->tv_sec = ts.tv_sec; + tv->tv_usec = ts.tv_nsec / 1000; + return ret; +} + +void +ms2tv(struct timeval *tv, long ms) +{ + tv->tv_sec = ms / 1000; + tv->tv_usec = (ms % 1000) * 1000; +} + +long +tv2ms(struct timeval *tv) +{ + return (tv->tv_sec * 1000) + ((tv->tv_usec + 500) / 1000); +} + void -loop(char *ifname, long count) +loop(char *ifname, long count, struct timeval *delay) { + struct timeval old, now, diff; unsigned long long oldrxbytes, rxbytes; unsigned long long oldtxbytes, txbytes; unsigned long long oldrxpps, rxpps; unsigned long long oldtxpps, txpps; + unsigned long long diffrxbits, difftxbits; + unsigned long long diffrxpps, difftxpps; long n = 0; + clock_gettime_tv(CLOCK_MONOTONIC, &old); sample(ifname, &oldrxbytes, &oldtxbytes, &oldrxpps, &oldtxpps); for (;;) { - sleep(1); + usleep(1000); /* sleep for 1ms */ sample(ifname, &rxbytes, &txbytes, &rxpps, &txpps); - print(ifname, - (rxbytes - oldrxbytes) * 8, - (txbytes - oldtxbytes) * 8, - rxpps - oldrxpps, - txpps - oldtxpps); - oldrxbytes = rxbytes; - oldtxbytes = txbytes; - oldrxpps = rxpps; - oldtxpps = txpps; - if (count && ++n >= count) - break; + clock_gettime_tv(CLOCK_MONOTONIC, &now); + timersub(&now, &old, &diff); + if (timercmp(&diff, delay, >=)) { + clock_gettime_tv(CLOCK_MONOTONIC, &old); + diffrxbits = (rxbytes - oldrxbytes) * 8; + difftxbits = (txbytes - oldtxbytes) * 8; + diffrxbits = diffrxbits * 1000 / tv2ms(&diff); + difftxbits = difftxbits * 1000 / tv2ms(&diff); + diffrxpps = (rxpps - oldrxpps) * 1000 / tv2ms(&diff); + difftxpps = (txpps - txpps) * 1000 / tv2ms(&diff); + print(ifname, diffrxbits, difftxbits, + diffrxpps, difftxpps); + oldrxbytes = rxbytes; + oldtxbytes = txbytes; + oldrxpps = rxpps; + oldtxpps = txpps; + if (count && ++n >= count) + break; + } } } void usage(void) { - fprintf(stderr, "usage: %s [-c count] [-i interface]\n", argv0); + fprintf(stderr, "usage: %s [-c count] [-d delay] [-i interface]\n", argv0); exit(1); } @@ -215,7 +254,8 @@ main(int argc, char *argv[]) { char ifname[IF_NAMESIZE] = ""; char *end; - long count = 0; + struct timeval tv; + long count = 0, delay = 1000; ARGBEGIN { case 'c': @@ -224,6 +264,12 @@ main(int argc, char *argv[]) if (*end != '\0' || errno) errx(1, "invalid count"); break; + case 'd': + errno = 0; + delay = strtol(EARGF(usage()), &end, 10); + if (*end != '\0' || errno) + errx(1, "invalid delay"); + break; case 'i': strncpy(ifname, EARGF(usage()), sizeof(ifname)); ifname[IF_NAMESIZE - 1] = '\0'; @@ -232,7 +278,8 @@ main(int argc, char *argv[]) usage(); } ARGEND + ms2tv(&tv, delay); scan(ifname); - loop(ifname, count); + loop(ifname, count, &tv); return 0; }