94 lines
3.1 KiB
Diff
94 lines
3.1 KiB
Diff
|
From 2e4e707b662df2cf505147ca19da94ef97b6ea25 Mon Sep 17 00:00:00 2001
|
||
|
From: Phil Sutter <psutter@redhat.com>
|
||
|
Date: Thu, 18 Oct 2018 12:51:12 +0200
|
||
|
Subject: [PATCH] utils: fix get_rtnl_link_stats_rta stats parsing
|
||
|
|
||
|
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1626306
|
||
|
Upstream Status: iproute2.git commit c7a3b22961f52
|
||
|
|
||
|
commit c7a3b22961f528760766aa85095eb1ab04a39797
|
||
|
Author: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
|
||
|
Date: Wed Oct 10 17:00:58 2018 +0200
|
||
|
|
||
|
utils: fix get_rtnl_link_stats_rta stats parsing
|
||
|
|
||
|
iproute2 walks through the list of available tunnels using netlink
|
||
|
protocol in order to get device info instead of reading
|
||
|
them from proc filesystem. However the kernel reports device statistics
|
||
|
using IFLA_INET6_STATS/IFLA_INET6_ICMP6STATS attributes nested in
|
||
|
IFLA_PROTINFO one but iproutes expects these info in
|
||
|
IFLA_STATS64/IFLA_STATS attributes.
|
||
|
The issue can be triggered with the following reproducer:
|
||
|
|
||
|
$ip link add ip6d0 type ip6tnl mode ip6ip6 local 1111::1 remote 2222::1
|
||
|
$ip -6 -d -s tunnel show ip6d0
|
||
|
ip6d0: ipv6/ipv6 remote 2222::1 local 1111::1 encaplimit 4 hoplimit 64
|
||
|
tclass 0x00 flowlabel 0x00000 (flowinfo 0x00000000)
|
||
|
Dump terminated
|
||
|
|
||
|
Fix the issue introducing IFLA_INET6_STATS attribute parsing
|
||
|
|
||
|
Fixes: 3e953938717f ("iptunnel/ip6tunnel: Use netlink to walk through
|
||
|
tunnels list")
|
||
|
|
||
|
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
|
||
|
---
|
||
|
lib/utils.c | 27 +++++++++++++++++++++++++++
|
||
|
1 file changed, 27 insertions(+)
|
||
|
|
||
|
diff --git a/lib/utils.c b/lib/utils.c
|
||
|
index e87ecf3..7be2d6b 100644
|
||
|
--- a/lib/utils.c
|
||
|
+++ b/lib/utils.c
|
||
|
@@ -27,6 +27,7 @@
|
||
|
#include <linux/param.h>
|
||
|
#include <linux/if_arp.h>
|
||
|
#include <linux/mpls.h>
|
||
|
+#include <linux/snmp.h>
|
||
|
#include <time.h>
|
||
|
#include <sys/time.h>
|
||
|
#include <errno.h>
|
||
|
@@ -1549,6 +1550,24 @@ static void copy_rtnl_link_stats64(struct rtnl_link_stats64 *stats64,
|
||
|
*a++ = *b++;
|
||
|
}
|
||
|
|
||
|
+#define IPSTATS_MIB_MAX_LEN (__IPSTATS_MIB_MAX * sizeof(__u64))
|
||
|
+static void get_snmp_counters(struct rtnl_link_stats64 *stats64,
|
||
|
+ struct rtattr *s)
|
||
|
+{
|
||
|
+ __u64 *mib = (__u64 *)RTA_DATA(s);
|
||
|
+
|
||
|
+ memset(stats64, 0, sizeof(*stats64));
|
||
|
+
|
||
|
+ stats64->rx_packets = mib[IPSTATS_MIB_INPKTS];
|
||
|
+ stats64->rx_bytes = mib[IPSTATS_MIB_INOCTETS];
|
||
|
+ stats64->tx_packets = mib[IPSTATS_MIB_OUTPKTS];
|
||
|
+ stats64->tx_bytes = mib[IPSTATS_MIB_OUTOCTETS];
|
||
|
+ stats64->rx_errors = mib[IPSTATS_MIB_INDISCARDS];
|
||
|
+ stats64->tx_errors = mib[IPSTATS_MIB_OUTDISCARDS];
|
||
|
+ stats64->multicast = mib[IPSTATS_MIB_INMCASTPKTS];
|
||
|
+ stats64->rx_frame_errors = mib[IPSTATS_MIB_CSUMERRORS];
|
||
|
+}
|
||
|
+
|
||
|
int get_rtnl_link_stats_rta(struct rtnl_link_stats64 *stats64,
|
||
|
struct rtattr *tb[])
|
||
|
{
|
||
|
@@ -1565,6 +1584,14 @@ int get_rtnl_link_stats_rta(struct rtnl_link_stats64 *stats64,
|
||
|
rta = tb[IFLA_STATS];
|
||
|
size = sizeof(struct rtnl_link_stats);
|
||
|
s = &stats;
|
||
|
+ } else if (tb[IFLA_PROTINFO]) {
|
||
|
+ struct rtattr *ptb[IPSTATS_MIB_MAX_LEN + 1];
|
||
|
+
|
||
|
+ parse_rtattr_nested(ptb, IPSTATS_MIB_MAX_LEN,
|
||
|
+ tb[IFLA_PROTINFO]);
|
||
|
+ if (ptb[IFLA_INET6_STATS])
|
||
|
+ get_snmp_counters(stats64, ptb[IFLA_INET6_STATS]);
|
||
|
+ return sizeof(*stats64);
|
||
|
} else {
|
||
|
return -1;
|
||
|
}
|
||
|
--
|
||
|
1.8.3.1
|
||
|
|