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

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