Skip to content

Instantly share code, notes, and snippets.

@upa
Last active August 29, 2015 14:06
Show Gist options
  • Save upa/26a32d128d9e35fc31d7 to your computer and use it in GitHub Desktop.
Save upa/26a32d128d9e35fc31d7 to your computer and use it in GitHub Desktop.
linux interface counter for bps pps
#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