aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorRick Jones <rick.jones2@hp.com>2014-11-06 13:37:54 -0500
committerDavid S. Miller <davem@davemloft.net>2014-11-07 15:45:50 -0500
commit36cbb2452cbafca64dcdd3578047433787900cf0 (patch)
tree3e50381574c3850fc2a6c76a14777daa821f85a0 /net/ipv6
parentf46ad73ac6965f71d1a2ba217c4eb5b644e62949 (diff)
udp: Increment UDP_MIB_IGNOREDMULTI for arriving unmatched multicasts
As NIC multicast filtering isn't perfect, and some platforms are quite content to spew broadcasts, we should not trigger an event for skb:kfree_skb when we do not have a match for such an incoming datagram. We do though want to avoid sweeping the matter under the rug entirely, so increment a suitable statistic. This incorporates feedback from David L. Stevens, Karl Neiss and Eric Dumazet. V3 - use bool per David Miller Signed-off-by: Rick Jones <rick.jones2@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/proc.c1
-rw-r--r--net/ipv6/udp.c11
2 files changed, 9 insertions, 3 deletions
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 1752cd0b4882..679253d0af84 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -136,6 +136,7 @@ static const struct snmp_mib snmp6_udp6_list[] = {
136 SNMP_MIB_ITEM("Udp6RcvbufErrors", UDP_MIB_RCVBUFERRORS), 136 SNMP_MIB_ITEM("Udp6RcvbufErrors", UDP_MIB_RCVBUFERRORS),
137 SNMP_MIB_ITEM("Udp6SndbufErrors", UDP_MIB_SNDBUFERRORS), 137 SNMP_MIB_ITEM("Udp6SndbufErrors", UDP_MIB_SNDBUFERRORS),
138 SNMP_MIB_ITEM("Udp6InCsumErrors", UDP_MIB_CSUMERRORS), 138 SNMP_MIB_ITEM("Udp6InCsumErrors", UDP_MIB_CSUMERRORS),
139 SNMP_MIB_ITEM("Udp6IgnoredMulti", UDP_MIB_IGNOREDMULTI),
139 SNMP_MIB_SENTINEL 140 SNMP_MIB_SENTINEL
140}; 141};
141 142
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 9b6809232b17..b756355e9739 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -771,7 +771,7 @@ static void udp6_csum_zero_error(struct sk_buff *skb)
771 */ 771 */
772static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, 772static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
773 const struct in6_addr *saddr, const struct in6_addr *daddr, 773 const struct in6_addr *saddr, const struct in6_addr *daddr,
774 struct udp_table *udptable) 774 struct udp_table *udptable, int proto)
775{ 775{
776 struct sock *sk, *stack[256 / sizeof(struct sock *)]; 776 struct sock *sk, *stack[256 / sizeof(struct sock *)];
777 const struct udphdr *uh = udp_hdr(skb); 777 const struct udphdr *uh = udp_hdr(skb);
@@ -781,6 +781,7 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
781 int dif = inet6_iif(skb); 781 int dif = inet6_iif(skb);
782 unsigned int count = 0, offset = offsetof(typeof(*sk), sk_nulls_node); 782 unsigned int count = 0, offset = offsetof(typeof(*sk), sk_nulls_node);
783 unsigned int hash2 = 0, hash2_any = 0, use_hash2 = (hslot->count > 10); 783 unsigned int hash2 = 0, hash2_any = 0, use_hash2 = (hslot->count > 10);
784 bool inner_flushed = false;
784 785
785 if (use_hash2) { 786 if (use_hash2) {
786 hash2_any = udp6_portaddr_hash(net, &in6addr_any, hnum) & 787 hash2_any = udp6_portaddr_hash(net, &in6addr_any, hnum) &
@@ -803,6 +804,7 @@ start_lookup:
803 (uh->check || udp_sk(sk)->no_check6_rx)) { 804 (uh->check || udp_sk(sk)->no_check6_rx)) {
804 if (unlikely(count == ARRAY_SIZE(stack))) { 805 if (unlikely(count == ARRAY_SIZE(stack))) {
805 flush_stack(stack, count, skb, ~0); 806 flush_stack(stack, count, skb, ~0);
807 inner_flushed = true;
806 count = 0; 808 count = 0;
807 } 809 }
808 stack[count++] = sk; 810 stack[count++] = sk;
@@ -821,7 +823,10 @@ start_lookup:
821 if (count) { 823 if (count) {
822 flush_stack(stack, count, skb, count - 1); 824 flush_stack(stack, count, skb, count - 1);
823 } else { 825 } else {
824 kfree_skb(skb); 826 if (!inner_flushed)
827 UDP_INC_STATS_BH(net, UDP_MIB_IGNOREDMULTI,
828 proto == IPPROTO_UDPLITE);
829 consume_skb(skb);
825 } 830 }
826 return 0; 831 return 0;
827} 832}
@@ -873,7 +878,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
873 */ 878 */
874 if (ipv6_addr_is_multicast(daddr)) 879 if (ipv6_addr_is_multicast(daddr))
875 return __udp6_lib_mcast_deliver(net, skb, 880 return __udp6_lib_mcast_deliver(net, skb,
876 saddr, daddr, udptable); 881 saddr, daddr, udptable, proto);
877 882
878 /* Unicast */ 883 /* Unicast */
879 884