From: Thomas Graf <tgraf@redhat.com> Date: Thu, 7 Feb 2008 17:47:21 +0100 Subject: [net] ipv6: fixes to meet DoD requirements Message-id: 20080207164721.GA11531@deb O-Subject: [PATCH RHEL5.2] BZ431718: IPv6 bugfixes to meet DoD requirements Bugzilla: 431718 This patch combines a series of IPv6 bugfixes required to meet the DoD requirements. They've all been accepted upstream already. The patches are: 5b4d383a1a562de6955cacd72e20809064ee137f [ICMP]: ICMP_MIB_OUTMSGS increment duplicated c964ff4ffbef4586ec63dbeb008563078114e6dc [IPV6]: ICMP6_MIB_OUTMSGS increment duplicated fa95c28322a312a798a688c655458ab2079b72eb [IPV6]: RFC 2011 compatibility broken d647b36a69bf0a630ebf981bde3c0651e2779e5e [SNMP]: Fix SNMP counters with PREEMPT cb75994ec311b2cd50e5205efdcc0696abd6675d [UDP]: Defer InDataGrams increment until recvmsg() does checksum 1ac4f008857487bf45b709248d71c5b3f4cae7b5 [IPV6]: IPV6_MULTICAST_IF setting is ignored on link-local connect() Please ACK. diff --git a/include/net/snmp.h b/include/net/snmp.h index 63f37f8..52f49a7 100644 --- a/include/net/snmp.h +++ b/include/net/snmp.h @@ -23,6 +23,7 @@ #include <linux/cache.h> #include <linux/snmp.h> +#include <linux/smp.h> /* * Mibs are stored in array of unsigned long. @@ -143,14 +144,26 @@ struct linux_mib { #define SNMP_INC_STATS_OFFSET_BH(mib, field, offset) \ (per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field + (offset)]++) #define SNMP_INC_STATS_USER(mib, field) \ - (per_cpu_ptr(mib[1], raw_smp_processor_id())->mibs[field]++) + do { \ + per_cpu_ptr(mib[1], get_cpu())->mibs[field]++; \ + put_cpu(); \ + } while (0) #define SNMP_INC_STATS(mib, field) \ - (per_cpu_ptr(mib[!in_softirq()], raw_smp_processor_id())->mibs[field]++) + do { \ + per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field]++; \ + put_cpu(); \ + } while (0) #define SNMP_DEC_STATS(mib, field) \ - (per_cpu_ptr(mib[!in_softirq()], raw_smp_processor_id())->mibs[field]--) + do { \ + per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field]--; \ + put_cpu(); \ + } while (0) #define SNMP_ADD_STATS_BH(mib, field, addend) \ (per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field] += addend) #define SNMP_ADD_STATS_USER(mib, field, addend) \ - (per_cpu_ptr(mib[1], raw_smp_processor_id())->mibs[field] += addend) + do { \ + per_cpu_ptr(mib[1], get_cpu())->mibs[field] += addend; \ + put_cpu(); \ + } while (0) #endif diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index f8d0789..83ff7c0 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -534,7 +534,6 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info) icmp_param.data.icmph.checksum = 0; icmp_param.skb = skb_in; icmp_param.offset = skb_in->nh.raw - skb_in->data; - icmp_out_count(icmp_param.data.icmph.type); inet_sk(icmp_socket->sk)->tos = tos; ipc.addr = iph->saddr; ipc.opt = &icmp_param.replyopts; diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index e443cff..8223397 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -837,6 +837,8 @@ try_again: if (err) goto out_free; + UDP_INC_STATS_USER(UDP_MIB_INDATAGRAMS); + sock_recv_timestamp(msg, sk, skb); /* Copy the address. */ @@ -1031,7 +1033,6 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) if (ret < 0) { /* process the ESP packet */ ret = xfrm4_rcv_encap(skb, up->encap_type); - UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS); return -ret; } /* FALLTHROUGH -- it's a UDP Packet */ @@ -1051,7 +1052,6 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) kfree_skb(skb); return -1; } - UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS); return 0; } diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 99bae51..621e8c8 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -124,11 +124,11 @@ ipv4_connected: goto out; } sk->sk_bound_dev_if = usin->sin6_scope_id; - if (!sk->sk_bound_dev_if && - (addr_type & IPV6_ADDR_MULTICAST)) - fl.oif = np->mcast_oif; } + if (!sk->sk_bound_dev_if && (addr_type & IPV6_ADDR_MULTICAST)) + sk->sk_bound_dev_if = np->mcast_oif; + /* Connect to link-local address requires an interface */ if (!sk->sk_bound_dev_if) { err = -EINVAL; diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index a3d2aa9..bfad9b8 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -468,8 +468,6 @@ route_done: } err = icmpv6_push_pending_frames(sk, &fl, &tmp_hdr, len + sizeof(struct icmp6hdr)); - ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS); - out_put: if (likely(idev != NULL)) in6_dev_put(idev); diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index 7394590..cc34bba 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c @@ -98,7 +98,7 @@ static char *icmp6type2name[256] = { [ICMPV6_PKT_TOOBIG] = "PktTooBigs", [ICMPV6_TIME_EXCEED] = "TimeExcds", [ICMPV6_PARAMPROB] = "ParmProblems", - [ICMPV6_ECHO_REQUEST] = "EchoRequest", + [ICMPV6_ECHO_REQUEST] = "Echos", [ICMPV6_ECHO_REPLY] = "EchoReplies", [ICMPV6_MGM_QUERY] = "GroupMembQueries", [ICMPV6_MGM_REPORT] = "GroupMembResponses", @@ -108,7 +108,7 @@ static char *icmp6type2name[256] = { [NDISC_ROUTER_SOLICITATION] = "RouterSolicits", [NDISC_NEIGHBOUR_ADVERTISEMENT] = "NeighborAdvertisements", [NDISC_NEIGHBOUR_SOLICITATION] = "NeighborSolicits", - [NDISC_REDIRECT] = "NeighborRedirects", + [NDISC_REDIRECT] = "Redirects", }; diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 1d3047c..56a69b4 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -258,6 +258,8 @@ try_again: if (err) goto out_free; + UDP6_INC_STATS_USER(UDP_MIB_INDATAGRAMS); + sock_recv_timestamp(msg, sk, skb); /* Copy the address. */ @@ -363,7 +365,6 @@ static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) kfree_skb(skb); return 0; } - UDP6_INC_STATS_BH(UDP_MIB_INDATAGRAMS); return 0; }