ethtool -S获取接口统计信息总共分三步:
1、获取统计项个数,使用SIOCETHTOOL+ETHTOOL_GSSET_INFO
2、(可选)获取统计项名字,使用SIOCETHTOOL+ETHTOOL_GSTRINGS,需要使用第1步中获取的统计项个数来申请足够大的内存
3、获取统计值,使用SIOCETHTOOL+ETHTOOL_GSTATS,需要使用第1步中获取的统计项个数来申请足够大的内存
上代码:
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <net/if.h> #include <linux/sockios.h>
#include <linux/ethtool.h> int main(int argc, char* argv[])
{
int fd;
int ret;
unsigned int n_stats, i;
struct ifreq ifr;
struct {
struct ethtool_sset_info hdr;
unsigned int buf[];
} sset_info;
struct ethtool_stats *stats;
struct ethtool_gstrings *strings;
unsigned int sz_stats; fd = socket(AF_INET, SOCK_DGRAM, ); sset_info.hdr.cmd = ETHTOOL_GSSET_INFO;
sset_info.hdr.reserved = ;
sset_info.hdr.sset_mask = 1ULL << ETH_SS_STATS; memset(&ifr, , sizeof(ifr));
strcpy(ifr.ifr_name, "eth2");
ifr.ifr_data = (void*)&sset_info;
ret = ioctl(fd, SIOCETHTOOL, &ifr);
if ( != ret) {
printf("ETHTOOL_GSSET_INFO errno=%d\n", errno);
return -;
} n_stats = sset_info.hdr.sset_mask ? sset_info.hdr.data[] : ;
printf("stats n_stats=%d\n", n_stats); /*strings = calloc(1, sizeof(*strings) + n_stats * ETH_GSTRING_LEN);
if (!strings)
return -1; strings->cmd = ETHTOOL_GSTRINGS;
strings->string_set = ETH_SS_STATS;
strings->len = n_stats; memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, "eth2");
ifr.ifr_data = (void*)strings;
ret = ioctl(fd, SIOCETHTOOL, &ifr);
if (0 != ret) {
printf("ETH_SS_STATS, errno=%d\n", errno);
return -1;
}
*/
sz_stats = n_stats * sizeof(unsigned long long);
stats = calloc(, sz_stats + sizeof(struct ethtool_stats));
stats->cmd = ETHTOOL_GSTATS;
stats->n_stats = n_stats; memset(&ifr, , sizeof(ifr));
strcpy(ifr.ifr_name, "eth2");
ifr.ifr_data = (void*)stats;
ret = ioctl(fd, SIOCETHTOOL, &ifr);
if ( != ret) {
printf("ETHTOOL_GSTATS errno=%d\n", errno);
return -;
} for (i = ; i < n_stats; i++) {
printf("%llu\n", stats->data[i]);
} return ;
}