From patchwork Wed Nov 9 03:16:40 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hangbin Liu X-Patchwork-Id: 692555 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 3tDBDj3ckyz9t1Q for ; Wed, 9 Nov 2016 14:17:08 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="MZQOcB0u"; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752013AbcKIDRE (ORCPT ); Tue, 8 Nov 2016 22:17:04 -0500 Received: from mail-pf0-f193.google.com ([209.85.192.193]:34758 "EHLO mail-pf0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751226AbcKIDRD (ORCPT ); Tue, 8 Nov 2016 22:17:03 -0500 Received: by mail-pf0-f193.google.com with SMTP id y68so21823307pfb.1 for ; Tue, 08 Nov 2016 19:17:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=nbYYl6sjYYfdV+NKNCBaFBreun9SDNrsltzaVosLroY=; b=MZQOcB0uLQUp3Mg9TUJ1fuRCIBfm2EE/GqwO4Z58xqZjwCPYO1Cph09hah7MwvjQdz SlRHEdAQ5t2iKqQmUYTVCKvpIwq1uU6bY6tgNYhBEqyhka5K6vb3OlBPSibbrsfpS7H6 5eXqxvXmD6UYKMZi6Ksvs+Lop69O6blzWgi4GyVX9e1l30jr6GB3lAQwH+tQEH70YgNC 2tShowqL63s3qpW0t6rwBv+EJ1kH11D6kjzuSH4sFQhVvlJG2N4HyRZtaYaWkH+GOvJy Dd4BtspAFFi3wcOdBNmADttId679ndp8kWqbe3jEgBlINS5hPDU5KuXqvOfsFhDM4IKo cTEw== 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=nbYYl6sjYYfdV+NKNCBaFBreun9SDNrsltzaVosLroY=; b=XUe/DNGTVrUIzpegCfZNVP/VcvisXCgMJi4bw65lO/YXXtlUc0CKbvD1T3BqN+oN4W ob8gPRAViOZBke5RhT5WACR1B8RZeaHdjg238iiRlaf3RoBq87vgshxsn1bF3CBH0bZl HsrUl2K3HquiKxSh7Ie+P0T+uPVhZctqCztV5fHKIi8dv+2JJvkpaABNz8p0okKbXXiW Rw6T3qC25cGtYNxIcrXMrI2Hu6MwS+1aKV+9yCS9vlCFd8Lq95EucOnoR5IEvzKxiWX1 fpGNy5oJwbCYgWed/Gl7yNgxHpUB0UU/X9mJsL/41ClA0KukgKgw+JDXT/SOogdqNTsx w04A== X-Gm-Message-State: ABUngvcYFzC2uix/VyqCgDZ0AvweMY47ROxCpV1jQw1EwTrFae/lChXuyr6HEwZUPp0Lmw== X-Received: by 10.99.140.77 with SMTP id q13mr12734397pgn.109.1478661422350; Tue, 08 Nov 2016 19:17:02 -0800 (PST) Received: from localhost (138.128.208.20.16clouds.com. [138.128.208.20]) by smtp.gmail.com with ESMTPSA id w15sm51269291paj.33.2016.11.08.19.17.00 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 08 Nov 2016 19:17:01 -0800 (PST) From: Hangbin Liu To: netdev@vger.kernel.org Cc: Hannes Frederic Sowa , Daniel Borkmann , Hangbin Liu Subject: [PATCHv2 net] igmp: do not remove igmp souce list info when set link down Date: Wed, 9 Nov 2016 11:16:40 +0800 Message-Id: <1478661400-10152-1-git-send-email-liuhangbin@gmail.com> X-Mailer: git-send-email 2.5.5 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org In commit 24cf3af(igmp: call ip_mc_clear_src...), we forgot to remove igmpv3_clear_delrec() in ip_mc_down(), which also called ip_mc_clear_src(). This make us clear all IGMPv3 source filter info after NETDEV_DOWN. Move igmpv3_clear_delrec() to ip_mc_destroy_dev() and then no need ip_mc_clear_src() in ip_mc_destroy_dev(). On the other hand, we should restore back instead of free all source filter info in igmpv3_del_delrec(). Or we will not able to restore IGMPv3 source filter info after NETDEV_UP and NETDEV_POST_TYPE_CHANGE. Signed-off-by: Hangbin Liu --- net/ipv4/igmp.c | 50 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 606cc3e..15db786 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -162,7 +162,7 @@ static int unsolicited_report_interval(struct in_device *in_dev) } static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im); -static void igmpv3_del_delrec(struct in_device *in_dev, __be32 multiaddr); +static void igmpv3_del_delrec(struct in_device *in_dev, struct ip_mc_list *im); static void igmpv3_clear_delrec(struct in_device *in_dev); static int sf_setstate(struct ip_mc_list *pmc); static void sf_markstate(struct ip_mc_list *pmc); @@ -1130,10 +1130,15 @@ static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im) spin_unlock_bh(&in_dev->mc_tomb_lock); } -static void igmpv3_del_delrec(struct in_device *in_dev, __be32 multiaddr) +/* + * restore ip_mc_list deleted records + */ +static void igmpv3_del_delrec(struct in_device *in_dev, struct ip_mc_list *im) { struct ip_mc_list *pmc, *pmc_prev; - struct ip_sf_list *psf, *psf_next; + struct ip_sf_list *psf; + struct net *net = dev_net(in_dev->dev); + __be32 multiaddr = im->multiaddr; spin_lock_bh(&in_dev->mc_tomb_lock); pmc_prev = NULL; @@ -1149,16 +1154,26 @@ static void igmpv3_del_delrec(struct in_device *in_dev, __be32 multiaddr) in_dev->mc_tomb = pmc->next; } spin_unlock_bh(&in_dev->mc_tomb_lock); + + spin_lock_bh(&im->lock); if (pmc) { - for (psf = pmc->tomb; psf; psf = psf_next) { - psf_next = psf->sf_next; - kfree(psf); + im->interface = pmc->interface; + im->crcount = in_dev->mr_qrv ?: net->ipv4.sysctl_igmp_qrv; + im->sfmode = pmc->sfmode; + if (pmc->sfmode == MCAST_INCLUDE) { + im->tomb = pmc->tomb; + im->sources = pmc->sources; + for (psf = im->sources; psf; psf = psf->sf_next) + psf->sf_crcount = im->crcount; } in_dev_put(pmc->interface); - kfree(pmc); } + spin_unlock_bh(&im->lock); } +/* + * flush ip_mc_list deleted records + */ static void igmpv3_clear_delrec(struct in_device *in_dev) { struct ip_mc_list *pmc, *nextpmc; @@ -1366,7 +1381,7 @@ void ip_mc_inc_group(struct in_device *in_dev, __be32 addr) ip_mc_hash_add(in_dev, im); #ifdef CONFIG_IP_MULTICAST - igmpv3_del_delrec(in_dev, im->multiaddr); + igmpv3_del_delrec(in_dev, im); #endif igmp_group_added(im); if (!in_dev->dead) @@ -1626,8 +1641,12 @@ void ip_mc_remap(struct in_device *in_dev) ASSERT_RTNL(); - for_each_pmc_rtnl(in_dev, pmc) + for_each_pmc_rtnl(in_dev, pmc) { +#ifdef CONFIG_IP_MULTICAST + igmpv3_del_delrec(in_dev, pmc); +#endif igmp_group_added(pmc); + } } /* Device going down */ @@ -1648,7 +1667,6 @@ void ip_mc_down(struct in_device *in_dev) in_dev->mr_gq_running = 0; if (del_timer(&in_dev->mr_gq_timer)) __in_dev_put(in_dev); - igmpv3_clear_delrec(in_dev); #endif ip_mc_dec_group(in_dev, IGMP_ALL_HOSTS); @@ -1688,8 +1706,12 @@ void ip_mc_up(struct in_device *in_dev) #endif ip_mc_inc_group(in_dev, IGMP_ALL_HOSTS); - for_each_pmc_rtnl(in_dev, pmc) + for_each_pmc_rtnl(in_dev, pmc) { +#ifdef CONFIG_IP_MULTICAST + igmpv3_del_delrec(in_dev, pmc); +#endif igmp_group_added(pmc); + } } /* @@ -1704,13 +1726,13 @@ void ip_mc_destroy_dev(struct in_device *in_dev) /* Deactivate timers */ ip_mc_down(in_dev); +#ifdef CONFIG_IP_MULTICAST + igmpv3_clear_delrec(in_dev); +#endif while ((i = rtnl_dereference(in_dev->mc_list)) != NULL) { in_dev->mc_list = i->next_rcu; in_dev->mc_count--; - - /* We've dropped the groups in ip_mc_down already */ - ip_mc_clear_src(i); ip_ma_put(i); } }