Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 2795

kernel-2.6.18-238.el5.src.rpm

From: Ed Pollard <epollard@redhat.com>
Date: Thu, 10 Jan 2008 16:07:38 -0500
Subject: [net] IPV6 SNMP counters fix
Message-id: 4786891A.1040104@redhat.com
O-Subject: [RHE 5.2 PATCH] RHBZ#421401 IPV6 SNMP counters fix
Bugzilla: 421401

RHBZ#:
------
https://bugzilla.redhat.com/show_bug.cgi?id=421401

Description:
------------
The feature request patch at LTC Bugzilla #37879, RedHat Bugzilla #253278,
"Kernel enhancements to support IPv6 requirements to meet US DoD and US
Federal Govt. Mandates" has some minor bugs in some of the SNMP statistics where the
following counters are not properly updated:

 IPv4 - InNoRoutes
 IPv4 - OutNoRoutes
 IPv6 - OutNoRoutes
 Icmp6OutRouterSolicits
 Icmp6OutNeighborSolicits
 Icmp6OutNeighborAdvertisements

RHEL Version Found:
------------------
NA  Fix for Feature going into 5.2

kABI Status:
------------
No symbols were harmed.

Upstream Status:
----------------
I checked and this is in upstream 2.6.24.rc7

Test Status:
------------
The SNMP counters do move after the patched kernel is applied.

Proposed Patch:
---------------
This patch is based on 2.6.18-58 and applies cleanly to 2.6.18-65, and 2.6.18-66.

Acked-by: "David S. Miller" <davem@redhat.com>
Acked-by: Herbert Xu <herbert.xu@redhat.com>
Acked-by: Neil Horman <nhorman@redhat.com>

diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c
index 5836e1e..9105aeb 100644
--- a/net/ipv4/datagram.c
+++ b/net/ipv4/datagram.c
@@ -50,8 +50,12 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 			       RT_CONN_FLAGS(sk), oif,
 			       sk->sk_protocol,
 			       inet->sport, usin->sin_port, sk, 1);
-	if (err)
+	if (err) {
+		if (err == -ENETUNREACH)
+			IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
 		return err;
+	}
+
 	if ((rt->rt_flags & RTCF_BROADCAST) && !sock_flag(sk, SOCK_BROADCAST)) {
 		ip_rt_put(rt);
 		return -EACCES;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index f722729..5fd3ed0 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1354,6 +1354,7 @@ static int ip_error(struct sk_buff *skb)
 			break;
 		case ENETUNREACH:
 			code = ICMP_NET_UNREACH;
+			IP_INC_STATS_BH(IPSTATS_MIB_INNOROUTES);
 			break;
 		case EACCES:
 			code = ICMP_PKT_FILTERED;
@@ -2056,6 +2057,8 @@ no_route:
 	RT_CACHE_STAT_INC(in_no_route);
 	spec_dst = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE);
 	res.type = RTN_UNREACHABLE;
+	if (err == -ESRCH)
+		err = -ENETUNREACH;
 	goto local_input;
 
 	/*
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 35a6e26..4f58a8d 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -180,8 +180,11 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 			       RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
 			       IPPROTO_TCP,
 			       inet->sport, usin->sin_port, sk, 1);
-	if (tmp < 0)
+	if (tmp < 0) {
+		if (tmp == -ENETUNREACH)
+			IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
 		return tmp;
+	}
 
 	if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
 		ip_rt_put(rt);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index a6cf50a..0bf7923 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -605,8 +605,11 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 						 .dport = dport } } };
 		security_sk_classify_flow(sk, &fl);
 		err = ip_route_output_flow(&rt, &fl, sk, 1);
-		if (err)
+		if (err) {
+			if (err == -ENETUNREACH)
+				IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
 			goto out;
+		}
 
 		err = -EACCES;
 		if ((rt->rt_flags & RTCF_BROADCAST) &&
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 9f647f2..5770ba7 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -847,6 +847,8 @@ static int ip6_dst_lookup_tail(struct sock *sk,
 	return 0;
 
 out_err_release:
+	if (err == -ENETUNREACH)
+		IP6_INC_STATS_BH(NULL, IPSTATS_MIB_OUTNOROUTES);
 	dst_release(*dst);
 	*dst = NULL;
 	return err;
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index dacb4c2..f63001f 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -518,6 +518,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
 	IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS);
 	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
 	if (!err) {
+		ICMP6MSGOUT_INC_STATS(idev, NDISC_NEIGHBOUR_ADVERTISEMENT);
 		ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
 	}
 
@@ -602,6 +603,7 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
 	IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS);
 	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
 	if (!err) {
+		ICMP6MSGOUT_INC_STATS(idev, NDISC_NEIGHBOUR_SOLICITATION);
 		ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
 	}
 
@@ -696,6 +698,7 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
 	IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS);
 	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output);
 	if (!err) {
+		ICMP6MSGOUT_INC_STATS(idev, NDISC_ROUTER_SOLICITATION);
 		ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
 	}