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
Unified · Split
| @@ -156,6 +156,7 @@ enum · 155 unmodified lines | ||
| 156 | 156 | UDP_MIB_RCVBUFERRORS, /* RcvbufErrors */ |
| 157 | 157 | UDP_MIB_SNDBUFERRORS, /* SndbufErrors */ |
| 158 | 158 | UDP_MIB_CSUMERRORS, /* InCsumErrors */ |
| 159 | + UDP_MIB_IGNOREDMULTI, /* IgnoredMulti */ | |
| 159 | 160 | __UDP_MIB_MAX |
| 160 | 161 | }; |
| 161 | 162 | |
| @@ -181,6 +181,7 @@ static const struct snmp_mib snmp4_udp_list[] = { · 180 unmodified lines | ||
| 181 | 181 | SNMP_MIB_ITEM("RcvbufErrors", UDP_MIB_RCVBUFERRORS), |
| 182 | 182 | SNMP_MIB_ITEM("SndbufErrors", UDP_MIB_SNDBUFERRORS), |
| 183 | 183 | SNMP_MIB_ITEM("InCsumErrors", UDP_MIB_CSUMERRORS), |
| 184 | + SNMP_MIB_ITEM("IgnoredMulti", UDP_MIB_IGNOREDMULTI), | |
| 184 | 185 | SNMP_MIB_SENTINEL |
| 185 | 186 | }; |
| 186 | 187 | |
| @@ -1647,7 +1647,8 @@ static void udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst) · 1646 unmodified lines | ||
| 1647 | 1647 | static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb, |
| 1648 | 1648 | struct udphdr *uh, |
| 1649 | 1649 | __be32 saddr, __be32 daddr, |
| 1650 | − struct udp_table *udptable) | |
| 1650 | + struct udp_table *udptable, | |
| 1651 | + int proto) | |
| 1651 | 1652 | { |
| 1652 | 1653 | struct sock *sk, *stack[256 / sizeof(struct sock *)]; |
| 1653 | 1654 | struct hlist_nulls_node *node; |
| @@ -1656,6 +1657,7 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb, · 2 unmodified lines | ||
| 1656 | 1657 | int dif = skb->dev->ifindex; |
| 1657 | 1658 | unsigned int count = 0, offset = offsetof(typeof(*sk), sk_nulls_node); |
| 1658 | 1659 | unsigned int hash2 = 0, hash2_any = 0, use_hash2 = (hslot->count > 10); |
| 1660 | + bool inner_flushed = false; | |
| 1659 | 1661 | |
| 1660 | 1662 | if (use_hash2) { |
| 1661 | 1663 | hash2_any = udp4_portaddr_hash(net, htonl(INADDR_ANY), hnum) & |
| @@ -1674,6 +1676,7 @@ start_lookup: · 12 unmodified lines | ||
| 1674 | 1676 | dif, hnum)) { |
| 1675 | 1677 | if (unlikely(count == ARRAY_SIZE(stack))) { |
| 1676 | 1678 | flush_stack(stack, count, skb, ~0); |
| 1679 | + inner_flushed = true; | |
| 1677 | 1680 | count = 0; |
| 1678 | 1681 | } |
| 1679 | 1682 | stack[count++] = sk; |
| @@ -1695,7 +1698,10 @@ start_lookup: · 15 unmodified lines | ||
| 1695 | 1698 | if (count) { |
| 1696 | 1699 | flush_stack(stack, count, skb, count - 1); |
| 1697 | 1700 | } else { |
| 1698 | − kfree_skb(skb); | |
| 1701 | + if (!inner_flushed) | |
| 1702 | + UDP_INC_STATS_BH(net, UDP_MIB_IGNOREDMULTI, | |
| 1703 | + proto == IPPROTO_UDPLITE); | |
| 1704 | + consume_skb(skb); | |
| 1699 | 1705 | } |
| 1700 | 1706 | return 0; |
| 1701 | 1707 | } |
| @@ -1781,7 +1787,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, · 79 unmodified lines | ||
| 1781 | 1787 | |
| 1782 | 1788 | if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST)) |
| 1783 | 1789 | return __udp4_lib_mcast_deliver(net, skb, uh, |
| 1784 | − saddr, daddr, udptable); | |
| 1790 | + saddr, daddr, udptable, proto); | |
| 1785 | 1791 | |
| 1786 | 1792 | sk = __udp4_lib_lookup_skb(skb, uh->source, uh->dest, udptable); |
| 1787 | 1793 | if (sk != NULL) { |
| @@ -136,6 +136,7 @@ static const struct snmp_mib snmp6_udp6_list[] = { · 135 unmodified lines | ||
| 136 | 136 | SNMP_MIB_ITEM("Udp6RcvbufErrors", UDP_MIB_RCVBUFERRORS), |
| 137 | 137 | SNMP_MIB_ITEM("Udp6SndbufErrors", UDP_MIB_SNDBUFERRORS), |
| 138 | 138 | SNMP_MIB_ITEM("Udp6InCsumErrors", UDP_MIB_CSUMERRORS), |
| 139 | + SNMP_MIB_ITEM("Udp6IgnoredMulti", UDP_MIB_IGNOREDMULTI), | |
| 139 | 140 | SNMP_MIB_SENTINEL |
| 140 | 141 | }; |
| 141 | 142 | |
| @@ -771,7 +771,7 @@ static void udp6_csum_zero_error(struct sk_buff *skb) · 770 unmodified lines | ||
| 771 | 771 | */ |
| 772 | 772 | static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, |
| 773 | 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 | 776 | struct sock *sk, *stack[256 / sizeof(struct sock *)]; |
| 777 | 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, · 3 unmodified lines | ||
| 781 | 781 | int dif = inet6_iif(skb); |
| 782 | 782 | unsigned int count = 0, offset = offsetof(typeof(*sk), sk_nulls_node); |
| 783 | 783 | unsigned int hash2 = 0, hash2_any = 0, use_hash2 = (hslot->count > 10); |
| 784 | + bool inner_flushed = false; | |
| 784 | 785 | |
| 785 | 786 | if (use_hash2) { |
| 786 | 787 | hash2_any = udp6_portaddr_hash(net, &in6addr_any, hnum) & |
| @@ -803,6 +804,7 @@ start_lookup: · 16 unmodified lines | ||
| 803 | 804 | (uh->check || udp_sk(sk)->no_check6_rx)) { |
| 804 | 805 | if (unlikely(count == ARRAY_SIZE(stack))) { |
| 805 | 806 | flush_stack(stack, count, skb, ~0); |
| 807 | + inner_flushed = true; | |
| 806 | 808 | count = 0; |
| 807 | 809 | } |
| 808 | 810 | stack[count++] = sk; |
| @@ -821,7 +823,10 @@ start_lookup: · 12 unmodified lines | ||
| 821 | 823 | if (count) { |
| 822 | 824 | flush_stack(stack, count, skb, count - 1); |
| 823 | 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 | 831 | return 0; |
| 827 | 832 | } |
| @@ -873,7 +878,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, · 45 unmodified lines | ||
| 873 | 878 | */ |
| 874 | 879 | if (ipv6_addr_is_multicast(daddr)) |
| 875 | 880 | return __udp6_lib_mcast_deliver(net, skb, |
| 876 | − saddr, daddr, udptable); | |
| 881 | + saddr, daddr, udptable, proto); | |
| 877 | 882 | |
| 878 | 883 | /* Unicast */ |
| 879 | 884 | |