aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorDavid Held <drheld@google.com>2014-07-15 23:28:31 -0400
committerDavid S. Miller <davem@davemloft.net>2014-07-17 02:29:52 -0400
commit5cf3d46192fccf68b4a4759e4d7346e41c669a76 (patch)
treeb2a162b9ee42c0842e3178eefb7759d64ebb0416 /net/ipv6
parent3e1c0f0b06e38b50bfca197a6443d639353bb035 (diff)
udp: Simplify __udp*_lib_mcast_deliver.
Switch to using sk_nulls_for_each which shortens the code and makes it easier to update. Signed-off-by: David Held <drheld@google.com> Acked-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/udp.c88
1 files changed, 35 insertions, 53 deletions
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index b4481df3d5fa..7d3bd80085be 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -702,43 +702,26 @@ drop:
702 return -1; 702 return -1;
703} 703}
704 704
705static struct sock *udp_v6_mcast_next(struct net *net, struct sock *sk, 705static bool __udp_v6_is_mcast_sock(struct net *net, struct sock *sk,
706 __be16 loc_port, const struct in6_addr *loc_addr, 706 __be16 loc_port, const struct in6_addr *loc_addr,
707 __be16 rmt_port, const struct in6_addr *rmt_addr, 707 __be16 rmt_port, const struct in6_addr *rmt_addr,
708 int dif) 708 int dif, unsigned short hnum)
709{ 709{
710 struct hlist_nulls_node *node; 710 struct inet_sock *inet = inet_sk(sk);
711 unsigned short num = ntohs(loc_port);
712
713 sk_nulls_for_each_from(sk, node) {
714 struct inet_sock *inet = inet_sk(sk);
715
716 if (!net_eq(sock_net(sk), net))
717 continue;
718
719 if (udp_sk(sk)->udp_port_hash == num &&
720 sk->sk_family == PF_INET6) {
721 if (inet->inet_dport) {
722 if (inet->inet_dport != rmt_port)
723 continue;
724 }
725 if (!ipv6_addr_any(&sk->sk_v6_daddr) &&
726 !ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr))
727 continue;
728
729 if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif)
730 continue;
731 711
732 if (!ipv6_addr_any(&sk->sk_v6_rcv_saddr)) { 712 if (!net_eq(sock_net(sk), net))
733 if (!ipv6_addr_equal(&sk->sk_v6_rcv_saddr, loc_addr)) 713 return false;
734 continue; 714
735 } 715 if (udp_sk(sk)->udp_port_hash != hnum ||
736 if (!inet6_mc_check(sk, loc_addr, rmt_addr)) 716 sk->sk_family != PF_INET6 ||
737 continue; 717 (inet->inet_dport && inet->inet_dport != rmt_port) ||
738 return sk; 718 (!ipv6_addr_any(&sk->sk_v6_daddr) &&
739 } 719 !ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr)) ||
740 } 720 (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif))
741 return NULL; 721 return false;
722 if (!inet6_mc_check(sk, loc_addr, rmt_addr))
723 return false;
724 return true;
742} 725}
743 726
744static void flush_stack(struct sock **stack, unsigned int count, 727static void flush_stack(struct sock **stack, unsigned int count,
@@ -787,28 +770,27 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
787{ 770{
788 struct sock *sk, *stack[256 / sizeof(struct sock *)]; 771 struct sock *sk, *stack[256 / sizeof(struct sock *)];
789 const struct udphdr *uh = udp_hdr(skb); 772 const struct udphdr *uh = udp_hdr(skb);
790 struct udp_hslot *hslot = udp_hashslot(udptable, net, ntohs(uh->dest)); 773 struct hlist_nulls_node *node;
791 int dif; 774 unsigned short hnum = ntohs(uh->dest);
775 struct udp_hslot *hslot = udp_hashslot(udptable, net, hnum);
776 int dif = inet6_iif(skb);
792 unsigned int i, count = 0; 777 unsigned int i, count = 0;
793 778
794 spin_lock(&hslot->lock); 779 spin_lock(&hslot->lock);
795 sk = sk_nulls_head(&hslot->head); 780 sk_nulls_for_each(sk, node, &hslot->head) {
796 dif = inet6_iif(skb); 781 if (__udp_v6_is_mcast_sock(net, sk,
797 sk = udp_v6_mcast_next(net, sk, uh->dest, daddr, uh->source, saddr, dif); 782 uh->dest, daddr,
798 while (sk) { 783 uh->source, saddr,
799 /* If zero checksum and no_check is not on for 784 dif, hnum) &&
800 * the socket then skip it. 785 /* If zero checksum and no_check is not on for
801 */ 786 * the socket then skip it.
802 if (uh->check || udp_sk(sk)->no_check6_rx) 787 */
788 (uh->check || udp_sk(sk)->no_check6_rx)) {
789 if (unlikely(count == ARRAY_SIZE(stack))) {
790 flush_stack(stack, count, skb, ~0);
791 count = 0;
792 }
803 stack[count++] = sk; 793 stack[count++] = sk;
804
805 sk = udp_v6_mcast_next(net, sk_nulls_next(sk), uh->dest, daddr,
806 uh->source, saddr, dif);
807 if (unlikely(count == ARRAY_SIZE(stack))) {
808 if (!sk)
809 break;
810 flush_stack(stack, count, skb, ~0);
811 count = 0;
812 } 794 }
813 } 795 }
814 /* 796 /*