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:
M | sbm.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