Last active
August 29, 2015 14:06
-
-
Save upa/26a32d128d9e35fc31d7 to your computer and use it in GitHub Desktop.
linux interface counter for bps pps
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <sys/time.h> | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
#include <net/if.h> | |
#include <net/if_arp.h> | |
#include <linux/rtnetlink.h> | |
#define INTFMAX 16 | |
struct link_stats { | |
char * ifname; | |
struct rtnl_link_stats * stats; | |
}; | |
int | |
get_link_stats (char * buf, size_t len, struct link_stats * stats) | |
{ | |
int fd, n, i; | |
struct sockaddr_nl sa; | |
struct nlmsghdr * nlh; | |
struct ifinfomsg * ifi; | |
struct { | |
struct nlmsghdr nlh; | |
struct ifinfomsg ifi; | |
} req; | |
fd = socket (AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); | |
if (fd < 0) { | |
perror ("sock"); | |
return -1; | |
} | |
memset (&sa, 0, sizeof (sa)); | |
sa.nl_family = AF_NETLINK; | |
sa.nl_pid = 0; | |
sa.nl_groups = 0; | |
memset (&req, 0, sizeof (req)); | |
req.nlh.nlmsg_len = sizeof (req); | |
req.nlh.nlmsg_type = RTM_GETLINK; | |
req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_REQUEST; | |
req.nlh.nlmsg_pid = 0; | |
req.nlh.nlmsg_seq = 100; | |
req.ifi.ifi_family = ARPHRD_ETHER; | |
n = sendto (fd, &req, sizeof (req), 0, | |
(struct sockaddr *) &sa, sizeof (sa)); | |
if (n < 0) { | |
perror ("sendto"); | |
close (fd); | |
return -1; | |
} | |
n = recv (fd, buf, len, 0); | |
if (n < 0) { | |
perror ("recv"); | |
close (fd); | |
return -1; | |
} | |
i = 0; | |
for (nlh = (struct nlmsghdr *) buf; NLMSG_OK (nlh, n); | |
nlh = NLMSG_NEXT (nlh, n)) { | |
int rtalist_len; | |
struct rtattr * rta; | |
if (nlh->nlmsg_type != RTM_NEWLINK) { | |
printf ("invalid nlmsg_type : %d\n", nlh->nlmsg_type); | |
continue; | |
} | |
ifi = NLMSG_DATA (nlh); | |
rtalist_len = nlh->nlmsg_len - | |
NLMSG_LENGTH (sizeof (struct ifinfomsg)); | |
for (rta = IFLA_RTA (ifi); RTA_OK (rta, rtalist_len); | |
rta = RTA_NEXT (rta, rtalist_len)) { | |
switch (rta->rta_type) { | |
case IFLA_IFNAME : | |
stats[i].ifname = RTA_DATA (rta); | |
break; | |
case IFLA_STATS : | |
stats[i].stats = RTA_DATA (rta); | |
break; | |
} | |
} | |
if (INTFMAX - 1 < ++i) | |
break; | |
} | |
close (fd); | |
return 1; | |
} | |
struct link_stats * | |
find_stats_by_name (struct link_stats * stats, char * ifname) | |
{ | |
int n; | |
for (n = 0; n < INTFMAX && stats[n].ifname != NULL; n++) { | |
if (strncmp (stats[n].ifname, ifname, IFNAMSIZ) == 0) | |
return &stats[n]; | |
} | |
return NULL; | |
} | |
int | |
main (int argc, char ** argv) | |
{ | |
int n; | |
char buf1[8192], buf2[8192], * prefix = ""; | |
struct link_stats * sts, sts1[INTFMAX], sts2[INTFMAX]; | |
struct timeval tv1, tv2; | |
memset (buf1, 0, sizeof (buf1)); | |
memset (buf2, 0, sizeof (buf2)); | |
memset (sts1, 0, sizeof (sts1)); | |
memset (sts2, 0, sizeof (sts2)); | |
if (argc > 1) | |
prefix = argv[1]; | |
gettimeofday (&tv1, NULL); | |
get_link_stats (buf1, sizeof (buf1), sts1); | |
sleep (1); | |
gettimeofday (&tv2, NULL); | |
get_link_stats (buf2, sizeof (buf2), sts2); | |
for (n = 0; n < INTFMAX && sts2[n].ifname != NULL; n++) { | |
unsigned int txpps, rxpps, txbps, rxbps; | |
sts = find_stats_by_name (sts1, sts2[n].ifname); | |
if (!sts) | |
continue; | |
txpps = sts2[n].stats->tx_packets - sts->stats->tx_packets; | |
rxpps = sts2[n].stats->rx_packets - sts->stats->rx_packets; | |
txbps = (sts2[n].stats->tx_bytes - sts->stats->tx_bytes) * 8; | |
rxbps = (sts2[n].stats->rx_bytes - sts->stats->rx_bytes) * 8; | |
printf ("%s: %s: txpps:%u rxpps:%u txbps:%u rxbps:%u\n", | |
prefix, sts2[n].ifname, | |
txpps, rxpps, txbps, rxbps); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment