From patchwork Wed Feb 18 01:19:05 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Madhu Challa X-Patchwork-Id: 440777 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id D5AA3140180 for ; Wed, 18 Feb 2015 12:34:49 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751799AbbBRBep (ORCPT ); Tue, 17 Feb 2015 20:34:45 -0500 Received: from mail-pd0-f170.google.com ([209.85.192.170]:41811 "EHLO mail-pd0-f170.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751549AbbBRBeo (ORCPT ); Tue, 17 Feb 2015 20:34:44 -0500 Received: by pdno5 with SMTP id o5so47776772pdn.8 for ; Tue, 17 Feb 2015 17:34:44 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=b0PG464jxApFuCHqTrpc4Uf9ekMYmjvyzs+DMKCfFNQ=; b=JlJry6dC3O6ybd63F3gQfTNey7YolDEU5BmEiB1JiYlE2siPz3mj5UMvwdfL4QOdA/ 5yR89irQ8HcLab77yN4tLcRqe90Fkg+gbH/lvCsM7whIsryoqgFm4QAKLs7HAoeH6/Di StaAWraR2T9Hn6HHu9UuF0YJELl4Ncw50cLIh5kniFKw95i4zjHPPvRJR8WUwAeysK/P 3Jo2JQJswEJM/m6ok7ILU/3FAQGN3wKOdWWsPYbOIxDEgCwBjLrO/MdDpinch4zzQ7Rl o00se5c6Oepz1UGWRzvKDpMTpHzTngaBDpBKnuXOdkdSvJ2fv2zGmisd1K761l/goYGv NVfQ== X-Gm-Message-State: ALoCoQnbIsNTo11D5xqPH4riTVf6Xg4XLwE+htBEX6GGiIh3swEKDQTcTOVDXUr4vOKnuMKhOAsy X-Received: by 10.70.25.228 with SMTP id f4mr48592874pdg.90.1424223284100; Tue, 17 Feb 2015 17:34:44 -0800 (PST) Received: from localhost.localdomain ([173.36.240.158]) by mx.google.com with ESMTPSA id bs2sm2833129pbd.74.2015.02.17.17.34.43 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 17 Feb 2015 17:34:43 -0800 (PST) From: Madhu Challa To: eric.dumazet@gmail.com, netdev@vger.kernel.org Cc: Madhu Challa Subject: [PATCH v2 net-next 1/2] igmp v6: add __ipv6_sock_mc_join and __ipv6_sock_mc_drop Date: Tue, 17 Feb 2015 17:19:05 -0800 Message-Id: <1424222346-12736-1-git-send-email-challa@noironetworks.com> X-Mailer: git-send-email 1.9.1 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Based on the igmp v4 changes from Eric Dumazet. These changes are needed to perform igmp v6 join/leave while RTNL is held. Make ipv6_sock_mc_join and ipv6_sock_mc_drop wrappers around __ipv6_sock_mc_join and __ipv6_sock_mc_drop to avoid proliferation of work queues. Signed-off-by: Madhu Challa --- include/net/ipv6.h | 8 ++++++++ net/ipv6/mcast.c | 41 ++++++++++++++++++++++++++++++++--------- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 4c9fe22..b767306 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -940,4 +940,12 @@ int ipv6_sysctl_register(void); void ipv6_sysctl_unregister(void); #endif +int ipv6_sock_mc_join(struct sock *sk, int ifindex, + const struct in6_addr *addr); +int __ipv6_sock_mc_join(struct sock *sk, int ifindex, + const struct in6_addr *addr); +int ipv6_sock_mc_drop(struct sock *sk, int ifindex, + const struct in6_addr *addr); +int __ipv6_sock_mc_drop(struct sock *sk, int ifindex, + const struct in6_addr *addr); #endif /* _NET_IPV6_H */ diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 5ce107c..f4a76b1 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -132,7 +132,7 @@ static int unsolicited_report_interval(struct inet6_dev *idev) return iv > 0 ? iv : 1; } -int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) +int __ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) { struct net_device *dev = NULL; struct ipv6_mc_socklist *mc_lst; @@ -140,6 +140,8 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) struct net *net = sock_net(sk); int err; + ASSERT_RTNL(); + if (!ipv6_addr_is_multicast(addr)) return -EINVAL; @@ -161,7 +163,6 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) mc_lst->next = NULL; mc_lst->addr = *addr; - rtnl_lock(); if (ifindex == 0) { struct rt6_info *rt; rt = rt6_lookup(net, addr, NULL, 0, 0); @@ -173,7 +174,6 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) dev = __dev_get_by_index(net, ifindex); if (dev == NULL) { - rtnl_unlock(); sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); return -ENODEV; } @@ -190,7 +190,6 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) err = ipv6_dev_mc_inc(dev, addr); if (err) { - rtnl_unlock(); sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); return err; } @@ -198,25 +197,38 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) mc_lst->next = np->ipv6_mc_list; rcu_assign_pointer(np->ipv6_mc_list, mc_lst); - rtnl_unlock(); return 0; } +EXPORT_SYMBOL(__ipv6_sock_mc_join); + +int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) +{ + int ret; + + rtnl_lock(); + ret = __ipv6_sock_mc_join(sk, ifindex, addr); + rtnl_unlock(); + + return ret; +} +EXPORT_SYMBOL(ipv6_sock_mc_join); /* * socket leave on multicast group */ -int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) +int __ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) { struct ipv6_pinfo *np = inet6_sk(sk); struct ipv6_mc_socklist *mc_lst; struct ipv6_mc_socklist __rcu **lnk; struct net *net = sock_net(sk); + ASSERT_RTNL(); + if (!ipv6_addr_is_multicast(addr)) return -EINVAL; - rtnl_lock(); for (lnk = &np->ipv6_mc_list; (mc_lst = rtnl_dereference(*lnk)) != NULL; lnk = &mc_lst->next) { @@ -235,17 +247,28 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) __ipv6_dev_mc_dec(idev, &mc_lst->addr); } else (void) ip6_mc_leave_src(sk, mc_lst, NULL); - rtnl_unlock(); atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc); kfree_rcu(mc_lst, rcu); return 0; } } - rtnl_unlock(); return -EADDRNOTAVAIL; } +EXPORT_SYMBOL(__ipv6_sock_mc_drop); + +int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) +{ + int ret; + + rtnl_lock(); + ret = __ipv6_sock_mc_drop(sk, ifindex, addr); + rtnl_unlock(); + + return ret; +} +EXPORT_SYMBOL(ipv6_sock_mc_drop); /* called with rcu_read_lock() */ static struct inet6_dev *ip6_mc_find_dev_rcu(struct net *net,