netspeed.c (2379B)
1 #include <ctype.h> 2 #include <err.h> 3 #include <inttypes.h> 4 #include <limits.h> 5 #include <stdint.h> 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <string.h> 9 #include "util.h" 10 11 extern int delay; 12 13 static const char *humansztbl[] = { " B", "kB", "MB", "GB", "TB", "PB", "EB", 14 "ZB", "YB" }; 15 16 static int 17 humansz(size_t n) 18 { 19 int i; 20 for (i = 0; i < LEN(humansztbl) && n >= 1024; i++) 21 n /= 1024; 22 return i; 23 } 24 25 static void 26 updatenetspeed(char *buf, size_t len, uint64_t rxbytes, uint64_t txbytes) 27 { 28 static uint64_t oldrxbytes, oldtxbytes; 29 uint64_t rx, tx; 30 int irx, itx; 31 rx = (rxbytes - oldrxbytes) / delay; 32 tx = (txbytes - oldtxbytes) / delay; 33 irx = humansz(rx); 34 itx = humansz(tx); 35 snprintf(buf, len, "D:%6.1f%s/s U:%6.1f%s/s", rx 36 / (double)(1 << (10 * irx)), humansztbl[irx], tx 37 / (double)(1 << (10 * itx)), humansztbl[itx]); 38 oldrxbytes = rxbytes; 39 oldtxbytes = txbytes; 40 } 41 42 #ifdef __OpenBSD__ 43 #include <sys/socket.h> 44 #include <sys/types.h> 45 #include <net/if.h> /* struct if_data */ 46 #include <ifaddrs.h> 47 48 int 49 netspeedread(void *arg, char *buf, size_t len) 50 { 51 char *ifa_name = arg; 52 struct if_data *ifa_data; 53 struct ifaddrs *ifa, *ifap; 54 uint64_t rxbytes, txbytes; 55 56 if (getifaddrs(&ifap) == -1) { 57 warn("getifaddrs"); 58 return -1; 59 } 60 61 rxbytes = txbytes = 0; 62 63 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 64 if (strcmp(ifa_name, ifa->ifa_name) != 0) 65 continue; 66 if (ifa->ifa_data == NULL) 67 continue; 68 ifa_data = ifa->ifa_data; 69 rxbytes += ifa_data->ifi_ibytes; 70 txbytes += ifa_data->ifi_obytes; 71 } 72 73 updatenetspeed(buf, len, rxbytes, txbytes); 74 freeifaddrs(ifap); 75 76 return 0; 77 } 78 #elif __linux__ 79 int 80 netspeedread(void *arg, char *buf, size_t len) 81 { 82 char path[PATH_MAX]; 83 FILE *fp; 84 char *ifname = arg; 85 unsigned long long rxbytes, txbytes; 86 87 (void)snprintf(path, sizeof(path), "/sys/class/net/%s/statistics/rx_bytes", ifname); 88 if (!(fp = fopen(path, "r"))) { 89 warn("fopen %s", path); 90 return -1; 91 } 92 if (fscanf(fp, "%llu", &rxbytes) != 1) { 93 warn("fscanf %s", path); 94 fclose(fp); 95 return -1; 96 } 97 fclose(fp); 98 (void)snprintf(path, sizeof(path), "/sys/class/net/%s/statistics/tx_bytes", ifname); 99 if (!(fp = fopen(path, "r"))) { 100 warn("fopen %s", path); 101 return -1; 102 } 103 if (fscanf(fp, "%llu", &txbytes) != 1) { 104 warn("fscanf %s", path); 105 fclose(fp); 106 return -1; 107 } 108 fclose(fp); 109 110 updatenetspeed(buf, len, rxbytes, txbytes); 111 return 0; 112 } 113 #endif