Blame SOURCES/0024-utils-fix-get_rtnl_link_stats_rta-stats-parsing.patch

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