sbm

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

commit 9ef3c9a6b531f8ce2540b7efa26248038410ac0f
parent fab651ea9c4029a12ec6d84040c19d28ee7833d7
Author: sin <sin@2f30.org>
Date:   Mon, 26 Sep 2016 11:46:54 +0100

Use sysfs for statistics gathering on Linux

The link API exposes 32-bit counters.  This was a problem
for long running sessions.

There is a 64-bit version of the link API but sysfs is probably
the better way to go on Linux systems.

Diffstat:
Msbm.c | 59++++++++++++++++++++++++++++++++++++-----------------------
1 file changed, 36 insertions(+), 23 deletions(-)

diff --git a/sbm.c b/sbm.c @@ -5,7 +5,6 @@ #include <net/if.h> #ifdef __linux__ -#include <linux/if_link.h> #else #include <sys/sysctl.h> #include <net/if_dl.h> @@ -78,32 +77,46 @@ scan(void) } #ifdef __linux__ +int +readcounter(char *filename, uint64_t *v) +{ + char path[PATH_MAX]; + char buf[BUFSIZ]; + char *endptr; + FILE *fp; + + snprintf(path, sizeof(path), + "/sys/class/net/%s/statistics/%s", + ifname, filename); + fp = fopen(path, "r"); + if (fp == NULL) { + *v = 0; + return -1; + } + if (fgets(buf, sizeof(buf), fp) == NULL) { + fclose(fp); + *v = 0; + return -1; + } + fclose(fp); + buf[strcspn(buf, "\n")] = '\0'; + errno = 0; + *v = strtoull(buf, &endptr, 10); + if (*endptr != '\0' || errno != 0) { + *v = 0; + return -1; + } + return 0; +} + void sample(uint64_t *rxbytes, uint64_t *txbytes, uint64_t *rxpps, uint64_t *txpps) { - struct ifaddrs *ifas, *ifa; - struct rtnl_link_stats *stats = NULL; - - if (getifaddrs(&ifas) < 0) - err(1, "getifaddrs"); - for (ifa = ifas; ifa; ifa = ifa->ifa_next) { - if (strcmp(ifa->ifa_name, ifname)) - continue; - if (!ifa->ifa_data || !ifa->ifa_addr) - break; - if (ifa->ifa_addr->sa_family == AF_PACKET) { - stats = ifa->ifa_data; - *rxbytes = stats->rx_bytes; - *txbytes = stats->tx_bytes; - *rxpps = stats->rx_packets; - *txpps = stats->tx_packets; - break; - } - } - freeifaddrs(ifas); - if (!stats) - errx(1, "interface %s cannot be sampled", ifname); + readcounter("rx_bytes", rxbytes); + readcounter("tx_bytes", txbytes); + readcounter("rx_packets", rxpps); + readcounter("tx_packets", txpps); } #else void