diff options
author | Stephen Hemminger <stephen@networkplumber.org> | 2024-02-28 20:37:28 -0800 |
---|---|---|
committer | David Ahern <dsahern@kernel.org> | 2024-03-06 16:20:49 +0000 |
commit | 2558ab97c0c5ad8635a0db963a654cbfec65d924 (patch) | |
tree | 8a573e859d50b5ed12153e10584ec4593bfeb86a /misc/ifstat.c | |
parent | b69e1e0445ab3cf2a90738317507a29a483c26b3 (diff) |
ifstat: support 64 interface stats
The 32 bit statistics are problematic since 32 bit value can
easily wraparound at high speed. Use 64 bit stats if available.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: David Ahern <dsahern@kernel.org>
Diffstat (limited to 'misc/ifstat.c')
-rw-r--r-- | misc/ifstat.c | 37 |
1 files changed, 32 insertions, 5 deletions
diff --git a/misc/ifstat.c b/misc/ifstat.c index 18171a2c..0eef8245 100644 --- a/misc/ifstat.c +++ b/misc/ifstat.c @@ -51,7 +51,7 @@ int sub_type; char info_source[128]; int source_mismatch; -#define MAXS (sizeof(struct rtnl_link_stats)/sizeof(__u32)) +#define MAXS (sizeof(struct rtnl_link_stats64)/sizeof(__u64)) #define NO_SUB_TYPE 0xffff struct ifstat_ent { @@ -60,7 +60,7 @@ struct ifstat_ent { int ifindex; unsigned long long val[MAXS]; double rate[MAXS]; - __u32 ival[MAXS]; + __u64 ival[MAXS]; }; static const char *stats[MAXS] = { @@ -74,19 +74,25 @@ static const char *stats[MAXS] = { "tx_dropped", "multicast", "collisions", + "rx_length_errors", "rx_over_errors", "rx_crc_errors", "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", + "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", "tx_heartbeat_errors", "tx_window_errors", + "rx_compressed", - "tx_compressed" + "tx_compressed", + "rx_nohandler", + + "rx_otherhost_dropped", }; struct ifstat_ent *kern_db; @@ -174,7 +180,7 @@ static int get_nlmsg(struct nlmsghdr *m, void *arg) return 0; parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); - if (tb[IFLA_IFNAME] == NULL || tb[IFLA_STATS] == NULL) + if (tb[IFLA_IFNAME] == NULL) return 0; n = malloc(sizeof(*n)); @@ -182,10 +188,31 @@ static int get_nlmsg(struct nlmsghdr *m, void *arg) errno = ENOMEM; return -1; } + n->ifindex = ifi->ifi_index; n->name = strdup(RTA_DATA(tb[IFLA_IFNAME])); - memcpy(&n->ival, RTA_DATA(tb[IFLA_STATS]), sizeof(n->ival)); + if (!n->name) { + free(n); + errno = ENOMEM; + return -1; + } + memset(&n->rate, 0, sizeof(n->rate)); + + if (tb[IFLA_STATS64]) { + memcpy(&n->ival, RTA_DATA(tb[IFLA_STATS64]), sizeof(n->ival)); + } else if (tb[IFLA_STATS]) { + __u32 *stats = RTA_DATA(tb[IFLA_STATS]); + + /* expand 32 bit values to 64 bit */ + for (i = 0; i < MAXS; i++) + n->ival[i] = stats[i]; + } else { + /* missing stats? */ + free(n); + return 0; + } + for (i = 0; i < MAXS; i++) n->val[i] = n->ival[i]; n->next = kern_db; |