From patchwork Wed Sep 2 11:25:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1355674 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.a=rsa-sha256 header.s=google header.b=Gu53H7KU; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BhMDN0BH3z9sTv for ; Wed, 2 Sep 2020 21:29:56 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726927AbgIBL3x (ORCPT ); Wed, 2 Sep 2020 07:29:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41018 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726177AbgIBL3M (ORCPT ); Wed, 2 Sep 2020 07:29:12 -0400 Received: from mail-wr1-x441.google.com (mail-wr1-x441.google.com [IPv6:2a00:1450:4864:20::441]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1C71BC061245 for ; Wed, 2 Sep 2020 04:29:11 -0700 (PDT) Received: by mail-wr1-x441.google.com with SMTP id t10so3998670wrv.1 for ; Wed, 02 Sep 2020 04:29:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=nDPaNY6uULGl6w+zVk/xRhftdiMNqXaciWDwCjq2kwk=; b=Gu53H7KUgfZBNNpa4067GYBOmGvciq/0MwHhdQww5zmdtIRjqRUV5GKBOMB4icFePH fQOO/dxkUznueovCd9bc4fTGkCK9wyLhJgKXozG5uosU7znnWMcHJ47IUkpNsd22CB8f J0JNlUMm04xwqlzfEGrmkl6Ci/2UlTvcjgkKw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=nDPaNY6uULGl6w+zVk/xRhftdiMNqXaciWDwCjq2kwk=; b=Hty6XS/aF+9OUE6g3N62rWyGKR/Nr//YT8+4i4r09EKQw/dqATMfsxmFi0uptYIB+m mG/kZDeh5Kf20KdfC/iz7PDuay7nJOWvDW2JA1hVNwSrqF/Xp2dUKytoRWTOzY9XKS+o UR4ucMqhxEmBRTx+pXwG3k1vzc4yr6JgeV4perUmbrAv/RObR9W3gQ69AzlClP4rcKcz arVj/41F69L1m2y66IYiQ58ynAQkDEvsLUQgmGI3fFeisB2GPxpzlxzE7dnw4Zr28WE2 CYT9GZjzuPUhsTl7ranawOEe+hgYxbMSX/K9cFCbuxKfJFjEtRZ8Dr7PWs018+AZAxMT sJZQ== X-Gm-Message-State: AOAM533vP5+M69PYAg5H5+7YHJwud3csjUkwP8W+ruGADuAKq3Bb4Vrp CMXfd1YAA1sVaFLTBkdBDbWPD9LlAITivkLJ X-Google-Smtp-Source: ABdhPJztgZIAZY6hQYZlguadJQSoUJtvPZ5Aw+s3Bx1BMlATLWTtkDtXEg6V01LmTnfrH1uDB4/sKA== X-Received: by 2002:adf:f7d0:: with SMTP id a16mr6378759wrq.381.1599046149367; Wed, 02 Sep 2020 04:29:09 -0700 (PDT) Received: from localhost.localdomain (84-238-136-197.ip.btc-net.bg. [84.238.136.197]) by smtp.gmail.com with ESMTPSA id 5sm5985172wmz.22.2020.09.02.04.29.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Sep 2020 04:29:08 -0700 (PDT) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@nvidia.com, bridge@lists.linux-foundation.org, davem@davemloft.net, Nikolay Aleksandrov Subject: [PATCH net-next v2 01/15] net: bridge: mdb: arrange internal structs so fast-path fields are close Date: Wed, 2 Sep 2020 14:25:15 +0300 Message-Id: <20200902112529.1570040-2-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> References: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Before this patch we'd need 2 cache lines for fast-path, now all used fields are in the first cache line. Signed-off-by: Nikolay Aleksandrov --- net/bridge/br_private.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index baa1500f384f..357b6905ecef 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -217,23 +217,27 @@ struct net_bridge_fdb_entry { struct net_bridge_port_group { struct net_bridge_port *port; struct net_bridge_port_group __rcu *next; - struct hlist_node mglist; - struct rcu_head rcu; - struct timer_list timer; struct br_ip addr; unsigned char eth_addr[ETH_ALEN] __aligned(2); unsigned char flags; + + struct timer_list timer; + struct hlist_node mglist; + + struct rcu_head rcu; }; struct net_bridge_mdb_entry { struct rhash_head rhnode; struct net_bridge *br; struct net_bridge_port_group __rcu *ports; - struct rcu_head rcu; - struct timer_list timer; struct br_ip addr; bool host_joined; + + struct timer_list timer; struct hlist_node mdb_node; + + struct rcu_head rcu; }; struct net_bridge_port { From patchwork Wed Sep 2 11:25:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1355676 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.a=rsa-sha256 header.s=google header.b=A0g9W14s; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BhMDl3mG4z9sTv for ; Wed, 2 Sep 2020 21:30:15 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726967AbgIBLaN (ORCPT ); Wed, 2 Sep 2020 07:30:13 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41024 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726183AbgIBL3N (ORCPT ); Wed, 2 Sep 2020 07:29:13 -0400 Received: from mail-wr1-x442.google.com (mail-wr1-x442.google.com [IPv6:2a00:1450:4864:20::442]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8EF0AC061246 for ; Wed, 2 Sep 2020 04:29:12 -0700 (PDT) Received: by mail-wr1-x442.google.com with SMTP id z1so4850984wrt.3 for ; Wed, 02 Sep 2020 04:29:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=KnPLirI9bx/JX93C1Mqh9PJa9DSM38HJhHVkqeMWmgU=; b=A0g9W14sjywgCbhRZcKGgODjWg1iMNVOt06gt6XtT9dQHeETXJnwa6T/vpag2JgzZ8 3AIhRt2ZXD9XpoYbzncTYOEIw2Qb4+RvF/7WZ3wraAgzSqd6qwwIwiwt+dOYxGpp2dVe 3JdzYwa6h7AErbwVcEnHy+JuePpgena28cVBg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=KnPLirI9bx/JX93C1Mqh9PJa9DSM38HJhHVkqeMWmgU=; b=XIr5MUeQBpK9Z6tspcqpoAEHg2CqyAcuDFfqvz+n1WpRYJBxDxn2MeheGJJRFwBphY 2X38tm8uNPfSGWEv3NaRkIiyIgZDCWnnvlW4pdprp1UplQw9GQEfBpP4Nkh7wDpDBx6V 6TRa37zFuZraptlx9QTtfZgecYVlzMK0Xjb13ZMej8Zdp6xzzE2tQrraVxz9eD7Q319C 1Jefeh+zl+nmTbdlY/EJYJ7cBL6dNRvA6N83u3NBZyxIuzZbq6SgfMBqXz8455n20g0z A0z+i1jEBKJOb/efCco7kzud/iKXKrDaisQ4FvhDRcTgW2MCUnHxi1uMT1AirzKTp+6j fbGQ== X-Gm-Message-State: AOAM532LamTRy1a94L/1I4kgk3dHGNAOlu3Tf+LoP+PEIJEOSz0/cnZt +E7lOCnrmG0ZE4a6VDRfvx3hbXbATKju7ioo X-Google-Smtp-Source: ABdhPJy+hbqbYUhMVW0rugn0bPh76BfKw3nHPLhk7PrSI1suJHIiF2bkiVxwdqbTSZDfWBhqdNzs5A== X-Received: by 2002:adf:f544:: with SMTP id j4mr1581808wrp.74.1599046150772; Wed, 02 Sep 2020 04:29:10 -0700 (PDT) Received: from localhost.localdomain (84-238-136-197.ip.btc-net.bg. [84.238.136.197]) by smtp.gmail.com with ESMTPSA id 5sm5985172wmz.22.2020.09.02.04.29.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Sep 2020 04:29:10 -0700 (PDT) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@nvidia.com, bridge@lists.linux-foundation.org, davem@davemloft.net, Nikolay Aleksandrov Subject: [PATCH net-next v2 02/15] net: bridge: mcast: add support for group source list Date: Wed, 2 Sep 2020 14:25:16 +0300 Message-Id: <20200902112529.1570040-3-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> References: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Initial functions for group source lists which are needed for IGMPv3 include/exclude lists. Currently only IPv4 sources are supported. User-added mdb entries are created with exclude filter mode, we can extend that later to allow user-supplied mode. When group src entries are deleted, they're freed from a workqueue to make sure their timers are not still running. Source entries are protected by the multicast_lock and rcu. The number of src groups per port group is limited to 32. v2: allow src groups to be traversed under rcu Signed-off-by: Nikolay Aleksandrov --- net/bridge/br_mdb.c | 6 ++ net/bridge/br_multicast.c | 129 ++++++++++++++++++++++++++++++++++++++ net/bridge/br_private.h | 23 +++++++ 3 files changed, 158 insertions(+) diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index da5ed4cf9233..025a5aff2b2f 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -641,6 +641,7 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port, p = br_multicast_new_port_group(port, group, *pp, state, NULL); if (unlikely(!p)) return -ENOMEM; + p->filter_mode = MCAST_EXCLUDE; rcu_assign_pointer(*pp, p); if (state == MDB_TEMPORARY) mod_timer(&p->timer, now + br->multicast_membership_interval); @@ -761,6 +762,11 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry) if (!p->port || p->port->dev->ifindex != entry->ifindex) continue; + if (!hlist_empty(&p->src_list)) { + err = -EINVAL; + goto unlock; + } + if (p->port->state == BR_STATE_DISABLED) goto unlock; diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 4c4a93abde68..9269d62884e5 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -163,12 +163,24 @@ static void br_multicast_group_expired(struct timer_list *t) spin_unlock(&br->multicast_lock); } +static void br_multicast_del_group_src(struct net_bridge_group_src *src) +{ + struct net_bridge *br = src->pg->port->br; + + hlist_del_init_rcu(&src->node); + src->pg->src_ents--; + hlist_add_head(&src->del_node, &br->src_gc_list); + queue_work(system_long_wq, &br->src_gc_work); +} + static void br_multicast_del_pg(struct net_bridge *br, struct net_bridge_port_group *pg) { struct net_bridge_mdb_entry *mp; struct net_bridge_port_group *p; struct net_bridge_port_group __rcu **pp; + struct net_bridge_group_src *ent; + struct hlist_node *tmp; mp = br_mdb_ip_get(br, &pg->addr); if (WARN_ON(!mp)) @@ -183,6 +195,8 @@ static void br_multicast_del_pg(struct net_bridge *br, rcu_assign_pointer(*pp, p->next); hlist_del_init(&p->mglist); del_timer(&p->timer); + hlist_for_each_entry_safe(ent, tmp, &pg->src_list, node) + br_multicast_del_group_src(ent); br_mdb_notify(br->dev, p->port, &pg->addr, RTM_DELMDB, p->flags); kfree_rcu(p, rcu); @@ -470,6 +484,83 @@ struct net_bridge_mdb_entry *br_multicast_new_group(struct net_bridge *br, return mp; } +static void br_multicast_group_src_expired(struct timer_list *t) +{ + struct net_bridge_group_src *src = from_timer(src, t, timer); + struct net_bridge_port_group *pg; + struct net_bridge *br = src->br; + + spin_lock(&br->multicast_lock); + if (hlist_unhashed(&src->node) || !netif_running(br->dev) || + timer_pending(&src->timer)) + goto out; + + pg = src->pg; + br_debug(br, "port %s: src %pI4 group %pI4 filter mode %u timer expired\n", + pg->port->dev->name, &src->addr.u.ip4, &src->pg->addr.u.ip4, + src->pg->filter_mode); + + if (pg->filter_mode == MCAST_INCLUDE) { + br_multicast_del_group_src(src); + if (!hlist_empty(&pg->src_list)) + goto out; + br_multicast_del_pg(br, pg); + } +out: + spin_unlock(&br->multicast_lock); +} + +static struct net_bridge_group_src * +br_multicast_find_group_src(struct net_bridge_port_group *pg, struct br_ip *ip) +{ + struct net_bridge_group_src *ent; + + hlist_for_each_entry(ent, &pg->src_list, node) { + if (ent->addr.proto != ip->proto) + continue; + + switch (ip->proto) { + case htons(ETH_P_IP): + if (ip->u.ip4 == ent->addr.u.ip4) + return ent; + break; + } + } + + return NULL; +} + +static struct net_bridge_group_src * +br_multicast_new_group_src(struct net_bridge_port_group *pg, struct br_ip *src_ip) +{ + struct net_bridge_group_src *grp_src; + + if (unlikely(pg->src_ents >= PG_SRC_ENT_LIMIT)) + return NULL; + + switch (src_ip->proto) { + case htons(ETH_P_IP): + if (ipv4_is_zeronet(src_ip->u.ip4) || + ipv4_is_multicast(src_ip->u.ip4)) + return NULL; + break; + } + + grp_src = kzalloc(sizeof(*grp_src), GFP_ATOMIC); + if (unlikely(!grp_src)) + return NULL; + + grp_src->pg = pg; + grp_src->br = pg->port->br; + grp_src->addr = *src_ip; + timer_setup(&grp_src->timer, br_multicast_group_src_expired, 0); + + hlist_add_head_rcu(&grp_src->node, &pg->src_list); + pg->src_ents++; + + return grp_src; +} + struct net_bridge_port_group *br_multicast_new_port_group( struct net_bridge_port *port, struct br_ip *group, @@ -486,6 +577,12 @@ struct net_bridge_port_group *br_multicast_new_port_group( p->addr = *group; p->port = port; p->flags = flags; + if (group->proto == htons(ETH_P_IP) && + port->br->multicast_igmp_version == 3) + p->filter_mode = MCAST_INCLUDE; + else + p->filter_mode = MCAST_EXCLUDE; + INIT_HLIST_HEAD(&p->src_list); rcu_assign_pointer(p->next, next); hlist_add_head(&p->mglist, &port->mglist); timer_setup(&p->timer, br_multicast_port_group_expired, 0); @@ -1781,6 +1878,31 @@ static void br_ip6_multicast_query_expired(struct timer_list *t) } #endif +static void __grp_src_gc(struct hlist_head *head) +{ + struct net_bridge_group_src *ent; + struct hlist_node *tmp; + + hlist_for_each_entry_safe(ent, tmp, head, del_node) { + hlist_del_init(&ent->del_node); + del_timer_sync(&ent->timer); + kfree_rcu(ent, rcu); + } +} + +static void br_multicast_src_gc(struct work_struct *work) +{ + struct net_bridge *br = container_of(work, struct net_bridge, + src_gc_work); + HLIST_HEAD(deleted_head); + + spin_lock_bh(&br->multicast_lock); + hlist_move_list(&br->src_gc_list, &deleted_head); + spin_unlock_bh(&br->multicast_lock); + + __grp_src_gc(&deleted_head); +} + void br_multicast_init(struct net_bridge *br) { br->hash_max = BR_MULTICAST_DEFAULT_HASH_MAX; @@ -1821,6 +1943,8 @@ void br_multicast_init(struct net_bridge *br) br_ip6_multicast_query_expired, 0); #endif INIT_HLIST_HEAD(&br->mdb_list); + INIT_HLIST_HEAD(&br->src_gc_list); + INIT_WORK(&br->src_gc_work, br_multicast_src_gc); } static void br_ip4_multicast_join_snoopers(struct net_bridge *br) @@ -1924,6 +2048,7 @@ void br_multicast_stop(struct net_bridge *br) void br_multicast_dev_del(struct net_bridge *br) { struct net_bridge_mdb_entry *mp; + HLIST_HEAD(deleted_head); struct hlist_node *tmp; spin_lock_bh(&br->multicast_lock); @@ -1934,8 +2059,12 @@ void br_multicast_dev_del(struct net_bridge *br) hlist_del_rcu(&mp->mdb_node); kfree_rcu(mp, rcu); } + hlist_move_list(&br->src_gc_list, &deleted_head); spin_unlock_bh(&br->multicast_lock); + __grp_src_gc(&deleted_head); + cancel_work_sync(&br->src_gc_work); + rcu_barrier(); } diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 357b6905ecef..311ad0e402dc 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -214,13 +214,34 @@ struct net_bridge_fdb_entry { #define MDB_PG_FLAGS_OFFLOAD BIT(1) #define MDB_PG_FLAGS_FAST_LEAVE BIT(2) +#define PG_SRC_ENT_LIMIT 32 + +#define BR_SGRP_F_DELETE BIT(0) +#define BR_SGRP_F_SEND BIT(1) + +struct net_bridge_group_src { + struct hlist_node node; + + struct br_ip addr; + struct net_bridge_port_group *pg; + u8 flags; + struct timer_list timer; + + struct net_bridge *br; + struct hlist_node del_node; + struct rcu_head rcu; +}; + struct net_bridge_port_group { struct net_bridge_port *port; struct net_bridge_port_group __rcu *next; struct br_ip addr; unsigned char eth_addr[ETH_ALEN] __aligned(2); unsigned char flags; + unsigned char filter_mode; + struct hlist_head src_list; + unsigned int src_ents; struct timer_list timer; struct hlist_node mglist; @@ -410,6 +431,7 @@ struct net_bridge { struct rhashtable mdb_hash_tbl; + struct hlist_head src_gc_list; struct hlist_head mdb_list; struct hlist_head router_list; @@ -423,6 +445,7 @@ struct net_bridge { struct bridge_mcast_own_query ip6_own_query; struct bridge_mcast_querier ip6_querier; #endif /* IS_ENABLED(CONFIG_IPV6) */ + struct work_struct src_gc_work; #endif struct timer_list hello_timer; From patchwork Wed Sep 2 11:25:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1355675 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.a=rsa-sha256 header.s=google header.b=hzyzT4z9; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BhMDg4nTlz9sTv for ; Wed, 2 Sep 2020 21:30:11 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726938AbgIBLaC (ORCPT ); Wed, 2 Sep 2020 07:30:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41032 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726210AbgIBL3O (ORCPT ); Wed, 2 Sep 2020 07:29:14 -0400 Received: from mail-wm1-x334.google.com (mail-wm1-x334.google.com [IPv6:2a00:1450:4864:20::334]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 38326C061247 for ; Wed, 2 Sep 2020 04:29:14 -0700 (PDT) Received: by mail-wm1-x334.google.com with SMTP id o21so4158360wmc.0 for ; Wed, 02 Sep 2020 04:29:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=PxlKJ4ahUAq7ZO378zucziaWSAnWLkeVKcRNgDqTEgE=; b=hzyzT4z9tsJSGX5KsB78lEvOa14nrrCThaXwCAD6/HtTDRPJO+3rLAqoMht+ulFrPh UzhXV5wmjS2kCV7q5voNdfCgSvlglGxSEn1BLhnbjPJpb/LRFNqH+m4trypod2HA4skX vP/K7MeuGZmzjwmN70ENE9Pl9NCyMJq9Zy1/E= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=PxlKJ4ahUAq7ZO378zucziaWSAnWLkeVKcRNgDqTEgE=; b=EBz12lQKj4K+MgGirzFAB16cQuZKsD+WRnE447UuPIYTc0HUslcoI3YmGtCTojqlWJ wwuTrkQsHhV3cr+0+EGe6WG2EYgS1YlRBGgEEQ6f8Xg3ptNJu7gGZyLJGSlW4mdQ9VIA NeGqHzwpRW11Erg77wcRffm3CCBGU4Rqb6ZgBDYSDJp6eBDbloYp97BMGbzTOsfjR6pE KAVFcdu1uNG6uTBhjpKR0SdZNp9C1L2jFbild/Nui9uWqYN5rxSDj7wnMpfZk7DK8sOD 4OvmM645lznqzFVWE7nSPNCTVt+xYE7KjDI6rEgZS7r2v9BMCbpYQ8XknHgUXmYYbX6J Dtaw== X-Gm-Message-State: AOAM53119hdHpJWn/xLajEQDrWK8i7RYG2I/jAYa1i/D4TllYtLDNd2l J/OV6cSzcu8AAkZ2KbBwqu5fyL8LPZh/BZy7 X-Google-Smtp-Source: ABdhPJxHkDwqJTwkBNZA+GsZwUANqoOrgkFte6aTlrzkTIgcSScCA9XFBIWx9jRROdVbqLvdEKYGQw== X-Received: by 2002:a1c:2854:: with SMTP id o81mr181241wmo.61.1599046152199; Wed, 02 Sep 2020 04:29:12 -0700 (PDT) Received: from localhost.localdomain (84-238-136-197.ip.btc-net.bg. [84.238.136.197]) by smtp.gmail.com with ESMTPSA id 5sm5985172wmz.22.2020.09.02.04.29.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Sep 2020 04:29:11 -0700 (PDT) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@nvidia.com, bridge@lists.linux-foundation.org, davem@davemloft.net, Nikolay Aleksandrov Subject: [PATCH net-next v2 03/15] net: bridge: mcast: add support for src list and filter mode dumping Date: Wed, 2 Sep 2020 14:25:17 +0300 Message-Id: <20200902112529.1570040-4-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> References: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Support per port group src list (address and timer) and filter mode dumping. Protected by either multicast_lock or rcu and currently limited only to IPv4. v2: require RCU or multicast_lock to traverse src groups Signed-off-by: Nikolay Aleksandrov --- include/uapi/linux/if_bridge.h | 21 +++++++++++ net/bridge/br_mdb.c | 67 +++++++++++++++++++++++++++++++++- 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h index c1227aecd38f..75a2ac479247 100644 --- a/include/uapi/linux/if_bridge.h +++ b/include/uapi/linux/if_bridge.h @@ -455,10 +455,31 @@ enum { enum { MDBA_MDB_EATTR_UNSPEC, MDBA_MDB_EATTR_TIMER, + MDBA_MDB_EATTR_SRC_LIST, + MDBA_MDB_EATTR_GROUP_MODE, __MDBA_MDB_EATTR_MAX }; #define MDBA_MDB_EATTR_MAX (__MDBA_MDB_EATTR_MAX - 1) +/* per mdb entry source */ +enum { + MDBA_MDB_SRCLIST_UNSPEC, + MDBA_MDB_SRCLIST_ENTRY, + __MDBA_MDB_SRCLIST_MAX +}; +#define MDBA_MDB_SRCLIST_MAX (__MDBA_MDB_SRCLIST_MAX - 1) + +/* per mdb entry per source attributes + * these are embedded in MDBA_MDB_SRCLIST_ENTRY + */ +enum { + MDBA_MDB_SRCATTR_UNSPEC, + MDBA_MDB_SRCATTR_ADDRESS, + MDBA_MDB_SRCATTR_TIMER, + __MDBA_MDB_SRCATTR_MAX +}; +#define MDBA_MDB_SRCATTR_MAX (__MDBA_MDB_SRCATTR_MAX - 1) + /* multicast router types */ enum { MDB_RTR_TYPE_DISABLED, diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 025a5aff2b2f..7d4d064a49e3 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -77,6 +77,53 @@ static void __mdb_entry_to_br_ip(struct br_mdb_entry *entry, struct br_ip *ip) #endif } +static int __mdb_fill_srcs(struct sk_buff *skb, + struct net_bridge_port_group *p) +{ + struct net_bridge_group_src *ent; + struct nlattr *nest, *nest_ent; + + if (hlist_empty(&p->src_list)) + return 0; + + nest = nla_nest_start(skb, MDBA_MDB_EATTR_SRC_LIST); + if (!nest) + return -EMSGSIZE; + + hlist_for_each_entry_rcu(ent, &p->src_list, node, + lockdep_is_held(&p->port->br->multicast_lock)) { + nest_ent = nla_nest_start(skb, MDBA_MDB_SRCLIST_ENTRY); + if (!nest_ent) + goto out_cancel_err; + switch (ent->addr.proto) { + case htons(ETH_P_IP): + if (nla_put_in_addr(skb, MDBA_MDB_SRCATTR_ADDRESS, + ent->addr.u.ip4)) { + nla_nest_cancel(skb, nest_ent); + goto out_cancel_err; + } + break; + default: + nla_nest_cancel(skb, nest_ent); + continue; + } + if (nla_put_u32(skb, MDBA_MDB_SRCATTR_TIMER, + br_timer_value(&ent->timer))) { + nla_nest_cancel(skb, nest_ent); + goto out_cancel_err; + } + nla_nest_end(skb, nest_ent); + } + + nla_nest_end(skb, nest); + + return 0; + +out_cancel_err: + nla_nest_cancel(skb, nest); + return -EMSGSIZE; +} + static int __mdb_fill_info(struct sk_buff *skb, struct net_bridge_mdb_entry *mp, struct net_bridge_port_group *p) @@ -119,6 +166,15 @@ static int __mdb_fill_info(struct sk_buff *skb, nla_nest_cancel(skb, nest_ent); return -EMSGSIZE; } + if (p && + mp->br->multicast_igmp_version == 3 && + mp->addr.proto == htons(ETH_P_IP) && + (__mdb_fill_srcs(skb, p) || + nla_put_u8(skb, MDBA_MDB_EATTR_GROUP_MODE, p->filter_mode))) { + nla_nest_cancel(skb, nest_ent); + return -EMSGSIZE; + } + nla_nest_end(skb, nest_ent); return 0; @@ -127,7 +183,7 @@ static int __mdb_fill_info(struct sk_buff *skb, static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb, struct net_device *dev) { - int idx = 0, s_idx = cb->args[1], err = 0; + int idx = 0, s_idx = cb->args[1], err = 0, pidx = 0, s_pidx = cb->args[2]; struct net_bridge *br = netdev_priv(dev); struct net_bridge_mdb_entry *mp; struct nlattr *nest, *nest2; @@ -152,7 +208,7 @@ static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb, break; } - if (mp->host_joined) { + if (!s_pidx && mp->host_joined) { err = __mdb_fill_info(skb, mp, NULL); if (err) { nla_nest_cancel(skb, nest2); @@ -164,13 +220,19 @@ static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb, pp = &p->next) { if (!p->port) continue; + if (pidx < s_pidx) + goto skip_pg; err = __mdb_fill_info(skb, mp, p); if (err) { nla_nest_cancel(skb, nest2); goto out; } +skip_pg: + pidx++; } + pidx = 0; + s_pidx = 0; nla_nest_end(skb, nest2); skip: idx++; @@ -178,6 +240,7 @@ static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb, out: cb->args[1] = idx; + cb->args[2] = pidx; nla_nest_end(skb, nest); return err; } From patchwork Wed Sep 2 11:25:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1355677 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.a=rsa-sha256 header.s=google header.b=exjWCWkg; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BhMFF1CJvz9sTv for ; Wed, 2 Sep 2020 21:30:41 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726984AbgIBLaf (ORCPT ); Wed, 2 Sep 2020 07:30:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41038 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726268AbgIBL3Q (ORCPT ); Wed, 2 Sep 2020 07:29:16 -0400 Received: from mail-wr1-x441.google.com (mail-wr1-x441.google.com [IPv6:2a00:1450:4864:20::441]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9AC72C061244 for ; Wed, 2 Sep 2020 04:29:15 -0700 (PDT) Received: by mail-wr1-x441.google.com with SMTP id z4so4842237wrr.4 for ; Wed, 02 Sep 2020 04:29:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=fGIqJuD0krFkah838uWkiOllNByDMPwKPRmMq8PCBxs=; b=exjWCWkgkKarFORnUeLxjCZDRe9evlecnDHUJw/psT9TpuS/yQv+cCvXtrWgK2UevJ SB6iVCnb0oIZLXRZ7TN4u7mdH4hatmqEBEBtq8mRasgCTqLI/AqEMnrCkEF0KqYNpQaB d5GiKd1DKg6xt1CVUjlQMQwlkI1IIiMEXC5Hk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=fGIqJuD0krFkah838uWkiOllNByDMPwKPRmMq8PCBxs=; b=SRzUO2FT4FN+i274QArvFUVI2kI8Bjww/EKOxA+OT2gqTLdr9YPBCaMgSgKr6RwR4c FPIQMLNAoxrg9Oi9Segx8hWA7Q5V6dRnaR884V7TYLAiDpz9jWK6PrsvqR3PtPrVoq8a vWgJeAXE7M+dRHBXKJCUJ86/tyVn/jskVjhrPCSYrWuIKGNvt6r7Gt07qGMoHyRuntIy rBpFud+26IOZtrrHnzEYoTYYZo/y66uJLovpty3SFFR6F8o8uyMqNWebItkypi+pw3Zj brlo6KQWGMElcTUFH9/BztNm1+ochMTYkwqvobtUd8Hbk2LTo8VGcpfsofUP7G/kvyks OSLA== X-Gm-Message-State: AOAM5322XxSWJ+7+wgWB5NIv/uSQu7rblbO06FGOBRqlbTDdgaXR4lY/ asviJYN45t3Yf03+TCCFtcM1tzRcAz0Ah1dn X-Google-Smtp-Source: ABdhPJzgF/NfAQuCn0/3jEjnjUTcjWFrDgBVonX/ADfomExIMv6nA4LpPgmllNdZE/zhq/Xlck6WFA== X-Received: by 2002:adf:8481:: with SMTP id 1mr1574705wrg.231.1599046153815; Wed, 02 Sep 2020 04:29:13 -0700 (PDT) Received: from localhost.localdomain (84-238-136-197.ip.btc-net.bg. [84.238.136.197]) by smtp.gmail.com with ESMTPSA id 5sm5985172wmz.22.2020.09.02.04.29.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Sep 2020 04:29:13 -0700 (PDT) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@nvidia.com, bridge@lists.linux-foundation.org, davem@davemloft.net, Nikolay Aleksandrov Subject: [PATCH net-next v2 04/15] net: bridge: mcast: add support for group-and-source specific queries Date: Wed, 2 Sep 2020 14:25:18 +0300 Message-Id: <20200902112529.1570040-5-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> References: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Allows br_ip4_multicast_alloc_query to build queries with the port group's source lists and sends a query for sources over and under lmqt when necessary as per RFC 3376 with the suppress flag set appropriately. Signed-off-by: Nikolay Aleksandrov Reported-by: kernel test robot Reported-by: Dan Carpenter --- net/bridge/br_multicast.c | 126 +++++++++++++++++++++++++++++--------- net/bridge/br_private.h | 1 + 2 files changed, 99 insertions(+), 28 deletions(-) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 9269d62884e5..8a415672764a 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -228,21 +228,50 @@ static void br_multicast_port_group_expired(struct timer_list *t) } static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge *br, - __be32 group, - u8 *igmp_type) + struct net_bridge_port_group *pg, + __be32 ip_dst, __be32 group, + bool with_srcs, bool over_lmqt, + u8 sflag, u8 *igmp_type) { + struct net_bridge_port *p = pg ? pg->port : NULL; + struct net_bridge_group_src *ent; + size_t pkt_size, igmp_hdr_size; + unsigned long now = jiffies; struct igmpv3_query *ihv3; - size_t igmp_hdr_size; + void *csum_start = NULL; + __sum16 *csum = NULL; struct sk_buff *skb; struct igmphdr *ih; struct ethhdr *eth; + unsigned long lmqt; struct iphdr *iph; + u16 lmqt_srcs = 0; igmp_hdr_size = sizeof(*ih); - if (br->multicast_igmp_version == 3) + if (br->multicast_igmp_version == 3) { igmp_hdr_size = sizeof(*ihv3); - skb = netdev_alloc_skb_ip_align(br->dev, sizeof(*eth) + sizeof(*iph) + - igmp_hdr_size + 4); + if (pg && with_srcs) { + lmqt = now + (br->multicast_last_member_interval * + br->multicast_last_member_count); + hlist_for_each_entry(ent, &pg->src_list, node) { + if (over_lmqt == time_after(ent->timer.expires, + lmqt) && + ent->src_query_rexmit_cnt > 0) + lmqt_srcs++; + } + + if (!lmqt_srcs) + return NULL; + igmp_hdr_size += lmqt_srcs * sizeof(__be32); + } + } + + pkt_size = sizeof(*eth) + sizeof(*iph) + 4 + igmp_hdr_size; + if ((p && pkt_size > p->dev->mtu) || + pkt_size > br->dev->mtu) + return NULL; + + skb = netdev_alloc_skb_ip_align(br->dev, pkt_size); if (!skb) goto out; @@ -252,29 +281,24 @@ static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge *br, eth = eth_hdr(skb); ether_addr_copy(eth->h_source, br->dev->dev_addr); - eth->h_dest[0] = 1; - eth->h_dest[1] = 0; - eth->h_dest[2] = 0x5e; - eth->h_dest[3] = 0; - eth->h_dest[4] = 0; - eth->h_dest[5] = 1; + ip_eth_mc_map(ip_dst, eth->h_dest); eth->h_proto = htons(ETH_P_IP); skb_put(skb, sizeof(*eth)); skb_set_network_header(skb, skb->len); iph = ip_hdr(skb); + iph->tot_len = htons(pkt_size - sizeof(*eth)); iph->version = 4; iph->ihl = 6; iph->tos = 0xc0; - iph->tot_len = htons(sizeof(*iph) + igmp_hdr_size + 4); iph->id = 0; iph->frag_off = htons(IP_DF); iph->ttl = 1; iph->protocol = IPPROTO_IGMP; iph->saddr = br_opt_get(br, BROPT_MULTICAST_QUERY_USE_IFADDR) ? inet_select_addr(br->dev, 0, RT_SCOPE_LINK) : 0; - iph->daddr = htonl(INADDR_ALLHOSTS_GROUP); + iph->daddr = ip_dst; ((u8 *)&iph[1])[0] = IPOPT_RA; ((u8 *)&iph[1])[1] = 4; ((u8 *)&iph[1])[2] = 0; @@ -294,7 +318,8 @@ static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge *br, (HZ / IGMP_TIMER_SCALE); ih->group = group; ih->csum = 0; - ih->csum = ip_compute_csum((void *)ih, sizeof(*ih)); + csum = &ih->csum; + csum_start = (void *)ih; break; case 3: ihv3 = igmpv3_query_hdr(skb); @@ -304,15 +329,38 @@ static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge *br, (HZ / IGMP_TIMER_SCALE); ihv3->group = group; ihv3->qqic = br->multicast_query_interval / HZ; - ihv3->nsrcs = 0; + ihv3->nsrcs = htons(lmqt_srcs); ihv3->resv = 0; - ihv3->suppress = 0; + ihv3->suppress = sflag; ihv3->qrv = 2; ihv3->csum = 0; - ihv3->csum = ip_compute_csum((void *)ihv3, sizeof(*ihv3)); + csum = &ihv3->csum; + csum_start = (void *)ihv3; + if (!pg || !with_srcs) + break; + + lmqt_srcs = 0; + hlist_for_each_entry(ent, &pg->src_list, node) { + if (over_lmqt == time_after(ent->timer.expires, + lmqt) && + ent->src_query_rexmit_cnt > 0) { + ihv3->srcs[lmqt_srcs++] = ent->addr.u.ip4; + ent->src_query_rexmit_cnt--; + } + } + if (WARN_ON(lmqt_srcs != ntohs(ihv3->nsrcs))) { + kfree_skb(skb); + return NULL; + } break; } + if (WARN_ON(!csum || !csum_start)) { + kfree(skb); + return NULL; + } + + *csum = ip_compute_csum(csum_start, igmp_hdr_size); skb_put(skb, igmp_hdr_size); __skb_pull(skb, sizeof(*eth)); @@ -435,15 +483,24 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br, #endif static struct sk_buff *br_multicast_alloc_query(struct net_bridge *br, - struct br_ip *addr, - u8 *igmp_type) + struct net_bridge_port_group *pg, + struct br_ip *ip_dst, + struct br_ip *group, + bool with_srcs, bool over_lmqt, + u8 sflag, u8 *igmp_type) { - switch (addr->proto) { + __be32 ip4_dst; + + switch (group->proto) { case htons(ETH_P_IP): - return br_ip4_multicast_alloc_query(br, addr->u.ip4, igmp_type); + ip4_dst = ip_dst ? ip_dst->u.ip4 : htonl(INADDR_ALLHOSTS_GROUP); + return br_ip4_multicast_alloc_query(br, pg, + ip4_dst, group->u.ip4, + with_srcs, over_lmqt, + sflag, igmp_type); #if IS_ENABLED(CONFIG_IPV6) case htons(ETH_P_IPV6): - return br_ip6_multicast_alloc_query(br, &addr->u.ip6, + return br_ip6_multicast_alloc_query(br, &group->u.ip6, igmp_type); #endif } @@ -808,12 +865,19 @@ static void br_multicast_select_own_querier(struct net_bridge *br, static void __br_multicast_send_query(struct net_bridge *br, struct net_bridge_port *port, - struct br_ip *ip) + struct net_bridge_port_group *pg, + struct br_ip *ip_dst, + struct br_ip *group, + bool with_srcs, + u8 sflag) { + bool over_lmqt = !!sflag; struct sk_buff *skb; u8 igmp_type; - skb = br_multicast_alloc_query(br, ip, &igmp_type); +again_under_lmqt: + skb = br_multicast_alloc_query(br, pg, ip_dst, group, with_srcs, + over_lmqt, sflag, &igmp_type); if (!skb) return; @@ -824,8 +888,13 @@ static void __br_multicast_send_query(struct net_bridge *br, NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, dev_net(port->dev), NULL, skb, NULL, skb->dev, br_dev_queue_push_xmit); + + if (over_lmqt && with_srcs && sflag) { + over_lmqt = false; + goto again_under_lmqt; + } } else { - br_multicast_select_own_querier(br, ip, skb); + br_multicast_select_own_querier(br, group, skb); br_multicast_count(br, port, skb, igmp_type, BR_MCAST_DIR_RX); netif_rx(skb); @@ -861,7 +930,7 @@ static void br_multicast_send_query(struct net_bridge *br, if (!other_query || timer_pending(&other_query->timer)) return; - __br_multicast_send_query(br, port, &br_group); + __br_multicast_send_query(br, port, NULL, NULL, &br_group, false, 0); time = jiffies; time += own_query->startup_sent < br->multicast_startup_query_count ? @@ -1522,7 +1591,8 @@ br_multicast_leave_group(struct net_bridge *br, goto out; if (br_opt_get(br, BROPT_MULTICAST_QUERIER)) { - __br_multicast_send_query(br, port, &mp->addr); + __br_multicast_send_query(br, port, NULL, NULL, &mp->addr, + false, 0); time = jiffies + br->multicast_last_member_count * br->multicast_last_member_interval; diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 311ad0e402dc..87610d6c0b3f 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -225,6 +225,7 @@ struct net_bridge_group_src { struct br_ip addr; struct net_bridge_port_group *pg; u8 flags; + u8 src_query_rexmit_cnt; struct timer_list timer; struct net_bridge *br; From patchwork Wed Sep 2 11:25:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1355679 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.a=rsa-sha256 header.s=google header.b=g7V5t0d+; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BhMFb0dB4z9sV7 for ; Wed, 2 Sep 2020 21:30:59 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727020AbgIBLaw (ORCPT ); Wed, 2 Sep 2020 07:30:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41040 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726355AbgIBL3T (ORCPT ); Wed, 2 Sep 2020 07:29:19 -0400 Received: from mail-wr1-x443.google.com (mail-wr1-x443.google.com [IPv6:2a00:1450:4864:20::443]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2F3FFC061249 for ; Wed, 2 Sep 2020 04:29:17 -0700 (PDT) Received: by mail-wr1-x443.google.com with SMTP id c18so4828173wrm.9 for ; Wed, 02 Sep 2020 04:29:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=2iclW78xK5wy/jYYYTgbMHWLGP+hCzvvFTm6EyYG9yU=; b=g7V5t0d+kk6TB3jlvbfNikV4B1FGIJVc1sQAKlAyQ5W6g3pKwIUXoWHLMxjd3+ea5N s80i0zzq+gsPcHIrlqHPIX/3G8wfmJkgTPnXiKZ2ZNr3StUiqZYF4fDc9qakf9SF6waY uL5vdEjS66edy8Er+ZPQ0kmbx7nzx9jI358Is= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=2iclW78xK5wy/jYYYTgbMHWLGP+hCzvvFTm6EyYG9yU=; b=oTB7vHaAM9+auOSfdHY50wFm4zuQQ+VhLELb0vhr+0VDyEQO21fqoT5foSPqW+ektS 760iuGh/V1IzxesGRnOcYCACyqr3ZF+/X8SqkVJ+0JGgE5YrxGDY6lArMTmNh6nvVK94 fg95eghSBH5ftrAYk29ZCKtlBC5iXe0LqFAFf2dfF4pUWF5uK+CQBSbM/dCElMznsq/U Q6DIiCt/rPAmaMXQzv/x7kjMwpgX8flro7lt/d+W2CR6F+1LCq0dmaWm4EItLH5RUJLd DIuhOJQKpPV8aOk4+O/HKGcull9qhMfWna3qCDjURwGCPLNHjcS/STLBoaK0hn0gtQhG Wriw== X-Gm-Message-State: AOAM532OL3EeEP5IG1JW4iUS+6E281GlmGMyy1G613NFPn7m07/+Rm+9 Bci5VjAiOHhUepzVfvzSjLPtDbIaU/IDctMn X-Google-Smtp-Source: ABdhPJyDWZIaBSYuPz9DtNVDSgtugI9YKCsBueZYid8ZHC+yQYzgs2nX8bp/lJGENY92WulXzTu/aA== X-Received: by 2002:adf:e8c5:: with SMTP id k5mr6798968wrn.352.1599046155443; Wed, 02 Sep 2020 04:29:15 -0700 (PDT) Received: from localhost.localdomain (84-238-136-197.ip.btc-net.bg. [84.238.136.197]) by smtp.gmail.com with ESMTPSA id 5sm5985172wmz.22.2020.09.02.04.29.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Sep 2020 04:29:14 -0700 (PDT) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@nvidia.com, bridge@lists.linux-foundation.org, davem@davemloft.net, Nikolay Aleksandrov Subject: [PATCH net-next v2 05/15] net: bridge: mcast: factor out port group del Date: Wed, 2 Sep 2020 14:25:19 +0300 Message-Id: <20200902112529.1570040-6-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> References: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org In order to avoid future errors and reduce code duplication we should factor out the port group del sequence. This allows us to have one function which takes care of all details when removing a port group. Signed-off-by: Nikolay Aleksandrov --- net/bridge/br_mdb.c | 15 +--------- net/bridge/br_multicast.c | 59 +++++++++++++++++++-------------------- net/bridge/br_private.h | 3 ++ 3 files changed, 32 insertions(+), 45 deletions(-) diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 7d4d064a49e3..7625db4b7fb9 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -825,24 +825,11 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry) if (!p->port || p->port->dev->ifindex != entry->ifindex) continue; - if (!hlist_empty(&p->src_list)) { - err = -EINVAL; - goto unlock; - } - if (p->port->state == BR_STATE_DISABLED) goto unlock; - __mdb_entry_fill_flags(entry, p->flags); - rcu_assign_pointer(*pp, p->next); - hlist_del_init(&p->mglist); - del_timer(&p->timer); - kfree_rcu(p, rcu); + br_multicast_del_pg(mp, p, pp); err = 0; - - if (!mp->ports && !mp->host_joined && - netif_running(br->dev)) - mod_timer(&mp->timer, jiffies); break; } diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 8a415672764a..ff73d1760b2f 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -173,14 +173,32 @@ static void br_multicast_del_group_src(struct net_bridge_group_src *src) queue_work(system_long_wq, &br->src_gc_work); } -static void br_multicast_del_pg(struct net_bridge *br, - struct net_bridge_port_group *pg) +void br_multicast_del_pg(struct net_bridge_mdb_entry *mp, + struct net_bridge_port_group *pg, + struct net_bridge_port_group __rcu **pp) +{ + struct net_bridge *br = pg->port->br; + struct net_bridge_group_src *ent; + struct hlist_node *tmp; + + rcu_assign_pointer(*pp, pg->next); + hlist_del_init(&pg->mglist); + del_timer(&pg->timer); + hlist_for_each_entry_safe(ent, tmp, &pg->src_list, node) + br_multicast_del_group_src(ent); + br_mdb_notify(br->dev, pg->port, &pg->addr, RTM_DELMDB, pg->flags); + kfree_rcu(pg, rcu); + + if (!mp->ports && !mp->host_joined && netif_running(br->dev)) + mod_timer(&mp->timer, jiffies); +} + +static void br_multicast_find_del_pg(struct net_bridge *br, + struct net_bridge_port_group *pg) { struct net_bridge_mdb_entry *mp; struct net_bridge_port_group *p; struct net_bridge_port_group __rcu **pp; - struct net_bridge_group_src *ent; - struct hlist_node *tmp; mp = br_mdb_ip_get(br, &pg->addr); if (WARN_ON(!mp)) @@ -192,19 +210,7 @@ static void br_multicast_del_pg(struct net_bridge *br, if (p != pg) continue; - rcu_assign_pointer(*pp, p->next); - hlist_del_init(&p->mglist); - del_timer(&p->timer); - hlist_for_each_entry_safe(ent, tmp, &pg->src_list, node) - br_multicast_del_group_src(ent); - br_mdb_notify(br->dev, p->port, &pg->addr, RTM_DELMDB, - p->flags); - kfree_rcu(p, rcu); - - if (!mp->ports && !mp->host_joined && - netif_running(br->dev)) - mod_timer(&mp->timer, jiffies); - + br_multicast_del_pg(mp, pg, pp); return; } @@ -221,7 +227,7 @@ static void br_multicast_port_group_expired(struct timer_list *t) hlist_unhashed(&pg->mglist) || pg->flags & MDB_PG_FLAGS_PERMANENT) goto out; - br_multicast_del_pg(br, pg); + br_multicast_find_del_pg(br, pg); out: spin_unlock(&br->multicast_lock); @@ -561,7 +567,7 @@ static void br_multicast_group_src_expired(struct timer_list *t) br_multicast_del_group_src(src); if (!hlist_empty(&pg->src_list)) goto out; - br_multicast_del_pg(br, pg); + br_multicast_find_del_pg(br, pg); } out: spin_unlock(&br->multicast_lock); @@ -1018,7 +1024,7 @@ void br_multicast_del_port(struct net_bridge_port *port) /* Take care of the remaining groups, only perm ones should be left */ spin_lock_bh(&br->multicast_lock); hlist_for_each_entry_safe(pg, n, &port->mglist, mglist) - br_multicast_del_pg(br, pg); + br_multicast_find_del_pg(br, pg); spin_unlock_bh(&br->multicast_lock); del_timer_sync(&port->multicast_router_timer); free_percpu(port->mcast_stats); @@ -1067,7 +1073,7 @@ void br_multicast_disable_port(struct net_bridge_port *port) spin_lock(&br->multicast_lock); hlist_for_each_entry_safe(pg, n, &port->mglist, mglist) if (!(pg->flags & MDB_PG_FLAGS_PERMANENT)) - br_multicast_del_pg(br, pg); + br_multicast_find_del_pg(br, pg); __del_port_router(port); @@ -1573,16 +1579,7 @@ br_multicast_leave_group(struct net_bridge *br, if (p->flags & MDB_PG_FLAGS_PERMANENT) break; - rcu_assign_pointer(*pp, p->next); - hlist_del_init(&p->mglist); - del_timer(&p->timer); - kfree_rcu(p, rcu); - br_mdb_notify(br->dev, port, group, RTM_DELMDB, - p->flags | MDB_PG_FLAGS_FAST_LEAVE); - - if (!mp->ports && !mp->host_joined && - netif_running(br->dev)) - mod_timer(&mp->timer, jiffies); + br_multicast_del_pg(mp, p, pp); } goto out; } diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 87610d6c0b3f..e363b508db92 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -801,6 +801,9 @@ void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port, struct br_ip *group, int type, u8 flags); void br_rtr_notify(struct net_device *dev, struct net_bridge_port *port, int type); +void br_multicast_del_pg(struct net_bridge_mdb_entry *mp, + struct net_bridge_port_group *pg, + struct net_bridge_port_group __rcu **pp); void br_multicast_count(struct net_bridge *br, const struct net_bridge_port *p, const struct sk_buff *skb, u8 type, u8 dir); int br_multicast_init_stats(struct net_bridge *br); From patchwork Wed Sep 2 11:25:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1355678 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.a=rsa-sha256 header.s=google header.b=AlUkBgmh; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BhMFL22lZz9sVC for ; Wed, 2 Sep 2020 21:30:46 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727001AbgIBLal (ORCPT ); Wed, 2 Sep 2020 07:30:41 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41048 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726310AbgIBL3T (ORCPT ); Wed, 2 Sep 2020 07:29:19 -0400 Received: from mail-wr1-x442.google.com (mail-wr1-x442.google.com [IPv6:2a00:1450:4864:20::442]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A1C18C06124F for ; Wed, 2 Sep 2020 04:29:18 -0700 (PDT) Received: by mail-wr1-x442.google.com with SMTP id c15so4813397wrs.11 for ; Wed, 02 Sep 2020 04:29:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=HBNLBluIZymXlbxockG9JX9MFPU4PXTUDWmgPXcXp64=; b=AlUkBgmh4tDtGIgYPfVnGR/ylyZtEPU6eqaDFkbqefrNcrprF6tMnyJ3RyO9cKkKRb 21u/wMwulWxqObvcBWPE6Kn8448z1PrWMZpnxkdatTlLhy3pFktrln6DSfeeoFxTayqr 3E5vsbJFjmp97Z1DJvhtC6lV81P8pXA0qpjlk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=HBNLBluIZymXlbxockG9JX9MFPU4PXTUDWmgPXcXp64=; b=GdbMIFMVqv+SsPgrog+6cuogN+vacNd68qudTZXTJq0m3bzdGFW/RI3Zcm784WyF6f kzmoJUrdEakqeux3BJxrVVc39k/uJiGSQ0+bRh3efPxRrchPQ+7XmvfND7oqzZynRzju m7Nj5etQLtt+Co8tQoRoXDo6sj88ty8i0d4oyxN1czm7aGT0APD9PR8ZLqG1My4xd03Z P3hYfdjVnjC6mcgUh8tL0oAB5QdJXYjsGmvnhnBjTJm7Nxf/ho2vcMlJunGxFipfJUmj Pjbpx64vK4wN9Y8OR3lOdP8izZokf7SdwOW+i20OY6/rScywWJ2QW7oiZ2CiKFXuWWTM 23oQ== X-Gm-Message-State: AOAM532OYbVSjeimNiWk14poKxFG/yG1BZDaHYexC4aUAivvMy0w+gEr iJJl3ifFZTnVjzhR9XIJQq/VBmzuQmlt97nx X-Google-Smtp-Source: ABdhPJze8VnlMPLNbjtzp/vh1kJqw5OmgH8gnu10/i1lYyWw23z44SNaBN8dd1PuYGE9y9gJe5A8ZQ== X-Received: by 2002:adf:aa9e:: with SMTP id h30mr6396838wrc.377.1599046156874; Wed, 02 Sep 2020 04:29:16 -0700 (PDT) Received: from localhost.localdomain (84-238-136-197.ip.btc-net.bg. [84.238.136.197]) by smtp.gmail.com with ESMTPSA id 5sm5985172wmz.22.2020.09.02.04.29.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Sep 2020 04:29:16 -0700 (PDT) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@nvidia.com, bridge@lists.linux-foundation.org, davem@davemloft.net, Nikolay Aleksandrov Subject: [PATCH net-next v2 06/15] net: bridge: mcast: add support for group query retransmit Date: Wed, 2 Sep 2020 14:25:20 +0300 Message-Id: <20200902112529.1570040-7-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> References: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org We need to be able to retransmit group-specific and group-and-source specific queries. The new timer takes care of those. Signed-off-by: Nikolay Aleksandrov --- net/bridge/br_multicast.c | 65 ++++++++++++++++++++++++++++++++++----- net/bridge/br_private.h | 8 +++++ 2 files changed, 65 insertions(+), 8 deletions(-) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index ff73d1760b2f..1a910f139ee2 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -50,6 +50,7 @@ static void br_ip4_multicast_leave_group(struct net_bridge *br, __be32 group, __u16 vid, const unsigned char *src); +static void br_multicast_port_group_rexmit(struct timer_list *t); static void __del_port_router(struct net_bridge_port *p); #if IS_ENABLED(CONFIG_IPV6) @@ -184,6 +185,7 @@ void br_multicast_del_pg(struct net_bridge_mdb_entry *mp, rcu_assign_pointer(*pp, pg->next); hlist_del_init(&pg->mglist); del_timer(&pg->timer); + del_timer(&pg->rexmit_timer); hlist_for_each_entry_safe(ent, tmp, &pg->src_list, node) br_multicast_del_group_src(ent); br_mdb_notify(br->dev, pg->port, &pg->addr, RTM_DELMDB, pg->flags); @@ -237,7 +239,8 @@ static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge *br, struct net_bridge_port_group *pg, __be32 ip_dst, __be32 group, bool with_srcs, bool over_lmqt, - u8 sflag, u8 *igmp_type) + u8 sflag, u8 *igmp_type, + bool *need_rexmit) { struct net_bridge_port *p = pg ? pg->port : NULL; struct net_bridge_group_src *ent; @@ -352,6 +355,8 @@ static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge *br, ent->src_query_rexmit_cnt > 0) { ihv3->srcs[lmqt_srcs++] = ent->addr.u.ip4; ent->src_query_rexmit_cnt--; + if (need_rexmit && ent->src_query_rexmit_cnt) + *need_rexmit = true; } } if (WARN_ON(lmqt_srcs != ntohs(ihv3->nsrcs))) { @@ -493,7 +498,8 @@ static struct sk_buff *br_multicast_alloc_query(struct net_bridge *br, struct br_ip *ip_dst, struct br_ip *group, bool with_srcs, bool over_lmqt, - u8 sflag, u8 *igmp_type) + u8 sflag, u8 *igmp_type, + bool *need_rexmit) { __be32 ip4_dst; @@ -503,7 +509,8 @@ static struct sk_buff *br_multicast_alloc_query(struct net_bridge *br, return br_ip4_multicast_alloc_query(br, pg, ip4_dst, group->u.ip4, with_srcs, over_lmqt, - sflag, igmp_type); + sflag, igmp_type, + need_rexmit); #if IS_ENABLED(CONFIG_IPV6) case htons(ETH_P_IPV6): return br_ip6_multicast_alloc_query(br, &group->u.ip6, @@ -647,8 +654,9 @@ struct net_bridge_port_group *br_multicast_new_port_group( p->filter_mode = MCAST_EXCLUDE; INIT_HLIST_HEAD(&p->src_list); rcu_assign_pointer(p->next, next); - hlist_add_head(&p->mglist, &port->mglist); timer_setup(&p->timer, br_multicast_port_group_expired, 0); + timer_setup(&p->rexmit_timer, br_multicast_port_group_rexmit, 0); + hlist_add_head(&p->mglist, &port->mglist); if (src) memcpy(p->eth_addr, src, ETH_ALEN); @@ -875,7 +883,8 @@ static void __br_multicast_send_query(struct net_bridge *br, struct br_ip *ip_dst, struct br_ip *group, bool with_srcs, - u8 sflag) + u8 sflag, + bool *need_rexmit) { bool over_lmqt = !!sflag; struct sk_buff *skb; @@ -883,7 +892,8 @@ static void __br_multicast_send_query(struct net_bridge *br, again_under_lmqt: skb = br_multicast_alloc_query(br, pg, ip_dst, group, with_srcs, - over_lmqt, sflag, &igmp_type); + over_lmqt, sflag, &igmp_type, + need_rexmit); if (!skb) return; @@ -936,7 +946,8 @@ static void br_multicast_send_query(struct net_bridge *br, if (!other_query || timer_pending(&other_query->timer)) return; - __br_multicast_send_query(br, port, NULL, NULL, &br_group, false, 0); + __br_multicast_send_query(br, port, NULL, NULL, &br_group, false, 0, + NULL); time = jiffies; time += own_query->startup_sent < br->multicast_startup_query_count ? @@ -981,6 +992,44 @@ static void br_ip6_multicast_port_query_expired(struct timer_list *t) } #endif +static void br_multicast_port_group_rexmit(struct timer_list *t) +{ + struct net_bridge_port_group *pg = from_timer(pg, t, rexmit_timer); + struct bridge_mcast_other_query *other_query = NULL; + struct net_bridge *br = pg->port->br; + bool need_rexmit = false; + + spin_lock(&br->multicast_lock); + if (!netif_running(br->dev) || hlist_unhashed(&pg->mglist) || + !br_opt_get(br, BROPT_MULTICAST_ENABLED) || + !br_opt_get(br, BROPT_MULTICAST_QUERIER)) + goto out; + + if (pg->addr.proto == htons(ETH_P_IP)) + other_query = &br->ip4_other_query; +#if IS_ENABLED(CONFIG_IPV6) + else + other_query = &br->ip6_other_query; +#endif + + if (!other_query || timer_pending(&other_query->timer)) + goto out; + + if (pg->grp_query_rexmit_cnt) { + pg->grp_query_rexmit_cnt--; + __br_multicast_send_query(br, pg->port, pg, &pg->addr, + &pg->addr, false, 1, NULL); + } + __br_multicast_send_query(br, pg->port, pg, &pg->addr, + &pg->addr, true, 0, &need_rexmit); + + if (pg->grp_query_rexmit_cnt || need_rexmit) + mod_timer(&pg->rexmit_timer, jiffies + + br->multicast_last_member_interval); +out: + spin_unlock(&br->multicast_lock); +} + static void br_mc_disabled_update(struct net_device *dev, bool value) { struct switchdev_attr attr = { @@ -1589,7 +1638,7 @@ br_multicast_leave_group(struct net_bridge *br, if (br_opt_get(br, BROPT_MULTICAST_QUERIER)) { __br_multicast_send_query(br, port, NULL, NULL, &mp->addr, - false, 0); + false, 0, NULL); time = jiffies + br->multicast_last_member_count * br->multicast_last_member_interval; diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index e363b508db92..34acad4a455a 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -240,10 +240,12 @@ struct net_bridge_port_group { unsigned char eth_addr[ETH_ALEN] __aligned(2); unsigned char flags; unsigned char filter_mode; + unsigned char grp_query_rexmit_cnt; struct hlist_head src_list; unsigned int src_ents; struct timer_list timer; + struct timer_list rexmit_timer; struct hlist_node mglist; struct rcu_head rcu; @@ -867,6 +869,12 @@ static inline int br_multicast_igmp_type(const struct sk_buff *skb) { return BR_INPUT_SKB_CB(skb)->igmp; } + +static inline unsigned long br_multicast_lmqt(const struct net_bridge *br) +{ + return br->multicast_last_member_interval * + br->multicast_last_member_count; +} #else static inline int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port, From patchwork Wed Sep 2 11:25:21 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1355680 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.a=rsa-sha256 header.s=google header.b=O2Wn5E7x; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BhMFh7568z9sTv for ; Wed, 2 Sep 2020 21:31:04 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726355AbgIBLbC (ORCPT ); Wed, 2 Sep 2020 07:31:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41054 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726406AbgIBL3U (ORCPT ); Wed, 2 Sep 2020 07:29:20 -0400 Received: from mail-wm1-x344.google.com (mail-wm1-x344.google.com [IPv6:2a00:1450:4864:20::344]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2CE86C061245 for ; Wed, 2 Sep 2020 04:29:20 -0700 (PDT) Received: by mail-wm1-x344.google.com with SMTP id w2so4041197wmi.1 for ; Wed, 02 Sep 2020 04:29:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=cCKiL+huUrH+G1EiQAvHJFnQDyxaz+24nbHZqfy+tlk=; b=O2Wn5E7xy4EtZF31dxZX87O9prirrlpqXwkl8F3lkwddVWjcD3oaoo7IRly/Soa5lE dk+JSfuuXSizTq4YqJEjwCWzEVIB0FPt4+kYPJZG5ckbdp/AUK9zRJuEBcRj6Z2UHnm1 phf1rvUsPNzq05j6VF43ag2fWXm6weyRKdPjc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=cCKiL+huUrH+G1EiQAvHJFnQDyxaz+24nbHZqfy+tlk=; b=Qr96b0PuK7QN1STItx1eMxapFYFVTd0N81wP6ONr3DqtBAxMg/o19OOa2hJvs7PY08 B1sfKhl7CupDaWnJKaKM03j530H2oapzQgVPNXSstwlP9U9O+27j5jVigxIsjHhjmNhD nlg62SKKlZsFF+T8TPNcXWzggdPlWCMkFg2U49vwOkxsIAjOfzto+tOf5FAkTmtdtSMh 7pGyJn4xrVmRlJHr28IhrJdDEfZZVjqakmCvMHDof4nq5AEzXd/9GzxDQRyP14pxYqlU g2eIYCJ71zbPYcKydupWByCpiX6oSq/0GtGYtbV5n4nYpz4rJWkzlY7sw7e6VJdoDEb3 cODA== X-Gm-Message-State: AOAM533ndj8J/G8HguAFI4DslmHc/ukXqKJZJEt2PQZXjLU3CXbflwaW Dk+eD8ZMsP80OywPuPtzCcSfp9Q2Leg2nuMx X-Google-Smtp-Source: ABdhPJxThDesuGtk+f3NFSRZOHXQJOkxC6i7fwHHE1dc1fOabR8DLP1N52Qg05KgKVG1tYCSeQNLMA== X-Received: by 2002:a05:600c:20c:: with SMTP id 12mr245194wmi.40.1599046158499; Wed, 02 Sep 2020 04:29:18 -0700 (PDT) Received: from localhost.localdomain (84-238-136-197.ip.btc-net.bg. [84.238.136.197]) by smtp.gmail.com with ESMTPSA id 5sm5985172wmz.22.2020.09.02.04.29.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Sep 2020 04:29:17 -0700 (PDT) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@nvidia.com, bridge@lists.linux-foundation.org, davem@davemloft.net, Nikolay Aleksandrov Subject: [PATCH net-next v2 07/15] net: bridge: mdb: push notifications in __br_mdb_add/del Date: Wed, 2 Sep 2020 14:25:21 +0300 Message-Id: <20200902112529.1570040-8-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> References: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This change is in preparation for using the mdb port group entries when sending a notification, so their full state and additional attributes can be filled in. Signed-off-by: Nikolay Aleksandrov --- net/bridge/br_mdb.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 7625db4b7fb9..f5290021310a 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -663,7 +663,7 @@ static int br_mdb_parse(struct sk_buff *skb, struct nlmsghdr *nlh, } static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port, - struct br_ip *group, unsigned char state) + struct br_ip *group, struct br_mdb_entry *entry) { struct net_bridge_mdb_entry *mp; struct net_bridge_port_group *p; @@ -682,12 +682,13 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port, /* host join */ if (!port) { /* don't allow any flags for host-joined groups */ - if (state) + if (entry->state) return -EINVAL; if (mp->host_joined) return -EEXIST; br_multicast_host_join(mp, false); + __br_mdb_notify(br->dev, NULL, entry, RTM_NEWMDB); return 0; } @@ -701,13 +702,14 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port, break; } - p = br_multicast_new_port_group(port, group, *pp, state, NULL); + p = br_multicast_new_port_group(port, group, *pp, entry->state, NULL); if (unlikely(!p)) return -ENOMEM; p->filter_mode = MCAST_EXCLUDE; rcu_assign_pointer(*pp, p); - if (state == MDB_TEMPORARY) + if (entry->state == MDB_TEMPORARY) mod_timer(&p->timer, now + br->multicast_membership_interval); + __br_mdb_notify(br->dev, port, entry, RTM_NEWMDB); return 0; } @@ -736,7 +738,7 @@ static int __br_mdb_add(struct net *net, struct net_bridge *br, __mdb_entry_to_br_ip(entry, &ip); spin_lock_bh(&br->multicast_lock); - ret = br_mdb_add_group(br, p, &ip, entry->state); + ret = br_mdb_add_group(br, p, &ip, entry); spin_unlock_bh(&br->multicast_lock); return ret; } @@ -781,12 +783,9 @@ static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, err = __br_mdb_add(net, br, entry); if (err) break; - __br_mdb_notify(dev, p, entry, RTM_NEWMDB); } } else { err = __br_mdb_add(net, br, entry); - if (!err) - __br_mdb_notify(dev, p, entry, RTM_NEWMDB); } return err; @@ -814,6 +813,7 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry) if (entry->ifindex == mp->br->dev->ifindex && mp->host_joined) { br_multicast_host_leave(mp, false); err = 0; + __br_mdb_notify(br->dev, NULL, entry, RTM_DELMDB); if (!mp->ports && netif_running(br->dev)) mod_timer(&mp->timer, jiffies); goto unlock; @@ -876,13 +876,9 @@ static int br_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, list_for_each_entry(v, &vg->vlan_list, vlist) { entry->vid = v->vid; err = __br_mdb_del(br, entry); - if (!err) - __br_mdb_notify(dev, p, entry, RTM_DELMDB); } } else { err = __br_mdb_del(br, entry); - if (!err) - __br_mdb_notify(dev, p, entry, RTM_DELMDB); } return err; From patchwork Wed Sep 2 11:25:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1355688 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.a=rsa-sha256 header.s=google header.b=LXw+OSfz; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BhMGN5BXVz9sTv for ; Wed, 2 Sep 2020 21:31:40 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727776AbgIBLbh (ORCPT ); Wed, 2 Sep 2020 07:31:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41062 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726526AbgIBL3X (ORCPT ); Wed, 2 Sep 2020 07:29:23 -0400 Received: from mail-wm1-x336.google.com (mail-wm1-x336.google.com [IPv6:2a00:1450:4864:20::336]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4A1A6C061251 for ; Wed, 2 Sep 2020 04:29:22 -0700 (PDT) Received: by mail-wm1-x336.google.com with SMTP id a65so4022752wme.5 for ; Wed, 02 Sep 2020 04:29:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=SI/CpXlFQ7+5EWD3QL4KtZZw/p3is0KCLqq/AGio+PE=; b=LXw+OSfzeSqGm1c1zUhvmHElOpxCvsj+MXlezmJETVamECG0VNJtasWL8BrC1hobsd SiGa34pv6dcFIsL50LdTOKixKDIsdJRIafWQYFtbqFSKOvNNxfdt0tZVwWZzr6cDJ4oU 7kyiEOar1Sh7a5B5Hdi6093d7IjSOZ5WPf/kk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=SI/CpXlFQ7+5EWD3QL4KtZZw/p3is0KCLqq/AGio+PE=; b=kpzRK5JEV56MrzDEMUD8wIGmIxsouJwmM6tdL0R2pXQ2zUSku5/uKjZ5uErpKxyWkb VuV4Ugpo31EFLQiCZoun5SSGt0oTX+LyhTmbBJ/jcmGtfVwFeAJSEFnfPNCpFYfUQVed eOBXN9UIWdD36QLt0CudHMm8Y0hPVx5XK5/3OfdycFYUEYig36vnbEVLk584thGbGXXI Ar5Ubl6ky2LBDVRWEdt9gQWSCZOQRiR6SA6wpl92CicKrDVpZEYKBUGr7/EmoRm7Ag/l uV+VQtmPiHztG9K99VZc7ItUSmWcWuZS6gp1sCI16ON7H9lOQsF74GoG8zlbBOe+4AD/ 92gA== X-Gm-Message-State: AOAM5327LgxlOXtqlR9nzXFk8KUqgSzqQ/zMq9Mruncl5pshNMXU/2k5 G5F4eO0CLOGSN4ZORw1YHpdQ+LOctygJtmFZ X-Google-Smtp-Source: ABdhPJwM+osvJBbu+Y7kCNjinlUsW2K0wBQMewe8pEHrmJjmwKC3Cu6h5P6M9ItfmqC+qIiaelfBfA== X-Received: by 2002:a7b:cb4e:: with SMTP id v14mr222424wmj.140.1599046159842; Wed, 02 Sep 2020 04:29:19 -0700 (PDT) Received: from localhost.localdomain (84-238-136-197.ip.btc-net.bg. [84.238.136.197]) by smtp.gmail.com with ESMTPSA id 5sm5985172wmz.22.2020.09.02.04.29.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Sep 2020 04:29:19 -0700 (PDT) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@nvidia.com, bridge@lists.linux-foundation.org, davem@davemloft.net, Nikolay Aleksandrov Subject: [PATCH net-next v2 08/15] net: bridge: mdb: use mdb and port entries in notifications Date: Wed, 2 Sep 2020 14:25:22 +0300 Message-Id: <20200902112529.1570040-9-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> References: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org We have to use mdb and port entries when sending mdb notifications in order to fill in all group attributes properly. Before this change we would've used a fake br_mdb_entry struct to fill in only partial information about the mdb. Now we can also reuse the mdb dump fill function and thus have only a single central place which fills the mdb attributes. Signed-off-by: Nikolay Aleksandrov --- net/bridge/br_mdb.c | 131 ++++++++++++++++++++------------------ net/bridge/br_multicast.c | 10 +-- net/bridge/br_private.h | 4 +- 3 files changed, 77 insertions(+), 68 deletions(-) diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index f5290021310a..33236c2a14a3 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -326,14 +326,15 @@ static int br_mdb_dump(struct sk_buff *skb, struct netlink_callback *cb) static int nlmsg_populate_mdb_fill(struct sk_buff *skb, struct net_device *dev, - struct br_mdb_entry *entry, u32 pid, - u32 seq, int type, unsigned int flags) + struct net_bridge_mdb_entry *mp, + struct net_bridge_port_group *pg, + int type) { struct nlmsghdr *nlh; struct br_port_msg *bpm; struct nlattr *nest, *nest2; - nlh = nlmsg_put(skb, pid, seq, type, sizeof(*bpm), 0); + nlh = nlmsg_put(skb, 0, 0, type, sizeof(*bpm), 0); if (!nlh) return -EMSGSIZE; @@ -348,7 +349,7 @@ static int nlmsg_populate_mdb_fill(struct sk_buff *skb, if (nest2 == NULL) goto end; - if (nla_put(skb, MDBA_MDB_ENTRY_INFO, sizeof(*entry), entry)) + if (__mdb_fill_info(skb, mp, pg)) goto end; nla_nest_end(skb, nest2); @@ -363,10 +364,34 @@ static int nlmsg_populate_mdb_fill(struct sk_buff *skb, return -EMSGSIZE; } -static inline size_t rtnl_mdb_nlmsg_size(void) +static size_t rtnl_mdb_nlmsg_size(struct net_bridge_port_group *pg) { - return NLMSG_ALIGN(sizeof(struct br_port_msg)) - + nla_total_size(sizeof(struct br_mdb_entry)); + size_t nlmsg_size = NLMSG_ALIGN(sizeof(struct br_port_msg)) + + nla_total_size(sizeof(struct br_mdb_entry)) + + nla_total_size(sizeof(u32)); + + if (pg && pg->port->br->multicast_igmp_version == 3 && + pg->addr.proto == htons(ETH_P_IP)) { + struct net_bridge_group_src *ent; + + /* MDBA_MDB_EATTR_GROUP_MODE */ + nlmsg_size += nla_total_size(sizeof(u8)); + + /* MDBA_MDB_EATTR_SRC_LIST nested attr */ + if (!hlist_empty(&pg->src_list)) + nlmsg_size += nla_total_size(0); + + hlist_for_each_entry(ent, &pg->src_list, node) { + /* MDBA_MDB_SRCLIST_ENTRY nested attr + + * MDBA_MDB_SRCATTR_ADDRESS + MDBA_MDB_SRCATTR_TIMER + */ + nlmsg_size += nla_total_size(0) + + nla_total_size(sizeof(__be32)) + + nla_total_size(sizeof(u32)); + } + } + + return nlmsg_size; } struct br_mdb_complete_info { @@ -404,21 +429,22 @@ static void br_mdb_complete(struct net_device *dev, int err, void *priv) static void br_mdb_switchdev_host_port(struct net_device *dev, struct net_device *lower_dev, - struct br_mdb_entry *entry, int type) + struct net_bridge_mdb_entry *mp, + int type) { struct switchdev_obj_port_mdb mdb = { .obj = { .id = SWITCHDEV_OBJ_ID_HOST_MDB, .flags = SWITCHDEV_F_DEFER, }, - .vid = entry->vid, + .vid = mp->addr.vid, }; - if (entry->addr.proto == htons(ETH_P_IP)) - ip_eth_mc_map(entry->addr.u.ip4, mdb.addr); + if (mp->addr.proto == htons(ETH_P_IP)) + ip_eth_mc_map(mp->addr.u.ip4, mdb.addr); #if IS_ENABLED(CONFIG_IPV6) else - ipv6_eth_mc_map(&entry->addr.u.ip6, mdb.addr); + ipv6_eth_mc_map(&mp->addr.u.ip6, mdb.addr); #endif mdb.obj.orig_dev = dev; @@ -433,17 +459,19 @@ static void br_mdb_switchdev_host_port(struct net_device *dev, } static void br_mdb_switchdev_host(struct net_device *dev, - struct br_mdb_entry *entry, int type) + struct net_bridge_mdb_entry *mp, int type) { struct net_device *lower_dev; struct list_head *iter; netdev_for_each_lower_dev(dev, lower_dev, iter) - br_mdb_switchdev_host_port(dev, lower_dev, entry, type); + br_mdb_switchdev_host_port(dev, lower_dev, mp, type); } -static void __br_mdb_notify(struct net_device *dev, struct net_bridge_port *p, - struct br_mdb_entry *entry, int type) +void br_mdb_notify(struct net_device *dev, + struct net_bridge_mdb_entry *mp, + struct net_bridge_port_group *pg, + int type) { struct br_mdb_complete_info *complete_info; struct switchdev_obj_port_mdb mdb = { @@ -451,44 +479,45 @@ static void __br_mdb_notify(struct net_device *dev, struct net_bridge_port *p, .id = SWITCHDEV_OBJ_ID_PORT_MDB, .flags = SWITCHDEV_F_DEFER, }, - .vid = entry->vid, + .vid = mp->addr.vid, }; - struct net_device *port_dev; struct net *net = dev_net(dev); struct sk_buff *skb; int err = -ENOBUFS; - port_dev = __dev_get_by_index(net, entry->ifindex); - if (entry->addr.proto == htons(ETH_P_IP)) - ip_eth_mc_map(entry->addr.u.ip4, mdb.addr); + if (pg) { + if (mp->addr.proto == htons(ETH_P_IP)) + ip_eth_mc_map(mp->addr.u.ip4, mdb.addr); #if IS_ENABLED(CONFIG_IPV6) - else - ipv6_eth_mc_map(&entry->addr.u.ip6, mdb.addr); + else + ipv6_eth_mc_map(&mp->addr.u.ip6, mdb.addr); #endif - - mdb.obj.orig_dev = port_dev; - if (p && port_dev && type == RTM_NEWMDB) { - complete_info = kmalloc(sizeof(*complete_info), GFP_ATOMIC); - if (complete_info) { - complete_info->port = p; - __mdb_entry_to_br_ip(entry, &complete_info->ip); + mdb.obj.orig_dev = pg->port->dev; + switch (type) { + case RTM_NEWMDB: + complete_info = kmalloc(sizeof(*complete_info), GFP_ATOMIC); + if (!complete_info) + break; + complete_info->port = pg->port; + complete_info->ip = mp->addr; mdb.obj.complete_priv = complete_info; mdb.obj.complete = br_mdb_complete; - if (switchdev_port_obj_add(port_dev, &mdb.obj, NULL)) + if (switchdev_port_obj_add(pg->port->dev, &mdb.obj, NULL)) kfree(complete_info); + break; + case RTM_DELMDB: + switchdev_port_obj_del(pg->port->dev, &mdb.obj); + break; } - } else if (p && port_dev && type == RTM_DELMDB) { - switchdev_port_obj_del(port_dev, &mdb.obj); + } else { + br_mdb_switchdev_host(dev, mp, type); } - if (!p) - br_mdb_switchdev_host(dev, entry, type); - - skb = nlmsg_new(rtnl_mdb_nlmsg_size(), GFP_ATOMIC); + skb = nlmsg_new(rtnl_mdb_nlmsg_size(pg), GFP_ATOMIC); if (!skb) goto errout; - err = nlmsg_populate_mdb_fill(skb, dev, entry, 0, 0, type, NTF_SELF); + err = nlmsg_populate_mdb_fill(skb, dev, mp, pg, type); if (err < 0) { kfree_skb(skb); goto errout; @@ -500,26 +529,6 @@ static void __br_mdb_notify(struct net_device *dev, struct net_bridge_port *p, rtnl_set_sk_err(net, RTNLGRP_MDB, err); } -void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port, - struct br_ip *group, int type, u8 flags) -{ - struct br_mdb_entry entry; - - memset(&entry, 0, sizeof(entry)); - if (port) - entry.ifindex = port->dev->ifindex; - else - entry.ifindex = dev->ifindex; - entry.addr.proto = group->proto; - entry.addr.u.ip4 = group->u.ip4; -#if IS_ENABLED(CONFIG_IPV6) - entry.addr.u.ip6 = group->u.ip6; -#endif - entry.vid = group->vid; - __mdb_entry_fill_flags(&entry, flags); - __br_mdb_notify(dev, port, &entry, type); -} - static int nlmsg_populate_rtr_fill(struct sk_buff *skb, struct net_device *dev, int ifindex, u32 pid, @@ -688,7 +697,7 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port, return -EEXIST; br_multicast_host_join(mp, false); - __br_mdb_notify(br->dev, NULL, entry, RTM_NEWMDB); + br_mdb_notify(br->dev, mp, NULL, RTM_NEWMDB); return 0; } @@ -709,7 +718,7 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port, rcu_assign_pointer(*pp, p); if (entry->state == MDB_TEMPORARY) mod_timer(&p->timer, now + br->multicast_membership_interval); - __br_mdb_notify(br->dev, port, entry, RTM_NEWMDB); + br_mdb_notify(br->dev, mp, p, RTM_NEWMDB); return 0; } @@ -813,7 +822,7 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry) if (entry->ifindex == mp->br->dev->ifindex && mp->host_joined) { br_multicast_host_leave(mp, false); err = 0; - __br_mdb_notify(br->dev, NULL, entry, RTM_DELMDB); + br_mdb_notify(br->dev, mp, NULL, RTM_DELMDB); if (!mp->ports && netif_running(br->dev)) mod_timer(&mp->timer, jiffies); goto unlock; diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 1a910f139ee2..0ec43d549137 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -188,7 +188,7 @@ void br_multicast_del_pg(struct net_bridge_mdb_entry *mp, del_timer(&pg->rexmit_timer); hlist_for_each_entry_safe(ent, tmp, &pg->src_list, node) br_multicast_del_group_src(ent); - br_mdb_notify(br->dev, pg->port, &pg->addr, RTM_DELMDB, pg->flags); + br_mdb_notify(br->dev, mp, pg, RTM_DELMDB); kfree_rcu(pg, rcu); if (!mp->ports && !mp->host_joined && netif_running(br->dev)) @@ -684,8 +684,7 @@ void br_multicast_host_join(struct net_bridge_mdb_entry *mp, bool notify) if (!mp->host_joined) { mp->host_joined = true; if (notify) - br_mdb_notify(mp->br->dev, NULL, &mp->addr, - RTM_NEWMDB, 0); + br_mdb_notify(mp->br->dev, mp, NULL, RTM_NEWMDB); } mod_timer(&mp->timer, jiffies + mp->br->multicast_membership_interval); } @@ -697,7 +696,7 @@ void br_multicast_host_leave(struct net_bridge_mdb_entry *mp, bool notify) mp->host_joined = false; if (notify) - br_mdb_notify(mp->br->dev, NULL, &mp->addr, RTM_DELMDB, 0); + br_mdb_notify(mp->br->dev, mp, NULL, RTM_DELMDB); } static int br_multicast_add_group(struct net_bridge *br, @@ -739,10 +738,11 @@ static int br_multicast_add_group(struct net_bridge *br, if (unlikely(!p)) goto err; rcu_assign_pointer(*pp, p); - br_mdb_notify(br->dev, port, group, RTM_NEWMDB, 0); + br_mdb_notify(br->dev, mp, p, RTM_NEWMDB); found: mod_timer(&p->timer, now + br->multicast_membership_interval); + out: err = 0; diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 34acad4a455a..78822d3a3b7c 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -799,8 +799,8 @@ br_multicast_new_port_group(struct net_bridge_port *port, struct br_ip *group, unsigned char flags, const unsigned char *src); int br_mdb_hash_init(struct net_bridge *br); void br_mdb_hash_fini(struct net_bridge *br); -void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port, - struct br_ip *group, int type, u8 flags); +void br_mdb_notify(struct net_device *dev, struct net_bridge_mdb_entry *mp, + struct net_bridge_port_group *pg, int type); void br_rtr_notify(struct net_device *dev, struct net_bridge_port *port, int type); void br_multicast_del_pg(struct net_bridge_mdb_entry *mp, From patchwork Wed Sep 2 11:25:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1355681 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.a=rsa-sha256 header.s=google header.b=L6onOfTb; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BhMFq0wKPz9sTv for ; Wed, 2 Sep 2020 21:31:11 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727037AbgIBLbJ (ORCPT ); Wed, 2 Sep 2020 07:31:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41064 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726618AbgIBL3X (ORCPT ); Wed, 2 Sep 2020 07:29:23 -0400 Received: from mail-wr1-x443.google.com (mail-wr1-x443.google.com [IPv6:2a00:1450:4864:20::443]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CA19DC061258 for ; Wed, 2 Sep 2020 04:29:22 -0700 (PDT) Received: by mail-wr1-x443.google.com with SMTP id k15so4832279wrn.10 for ; Wed, 02 Sep 2020 04:29:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=1xzox0HjSFnJFTMxOWtROlHBfTBMie+4N7AnHWjIyZM=; b=L6onOfTbzpay30OwwGg3IPcHaxE6d6LIyT3W+yvrZkoAFdhvAS6+k/NLY7IMoA17v7 dtE+Gvy69CJwftPTFsZUS/VMMgi7rV9/jdHrOqs8fni2FFwbb9U4AIW/jYFftY7aDRd6 El/asmGfPS8cdjhnuVzmPsI4Uq2mIIl9nXass= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=1xzox0HjSFnJFTMxOWtROlHBfTBMie+4N7AnHWjIyZM=; b=Bq0tPEiBn4uI/X4mi1aF82iNdujGLChTmyYIXxkeyebhaL2t0L/qUaL1c35kIWYJQ0 ocBz7FJxWoF0JfK+YPIqqJsR7St0XQxvpp2rUnTJR7cQJGvL8I71WlqTISMuhD2IEA42 HyjsK/OkNl0JxrgKkv86rETYkCz/uKGU0lMKbO40LB/AcQJKDRo20S6PlZXL0xf1LQ/c cckAk15ZtIVdjGYIWil20ZTuIAmcOcQP0l2iYqtepSQD1Re8i2ThzWGmKgPVwA6oTyH5 Fa8rhUTgnKotFP7/uq5B39o67y0ACMvAcdMFzjwLCYC5EKbSHECBpuxL6fWJfg3gQRld N+vw== X-Gm-Message-State: AOAM531Y6WcXc2Kdm0nuE2bPwANFew9ceEWksPdBhHeGulZffTwGJTaD z7OWe7PhHLOndtJngWaW/hbbdPDmEotJLoz4 X-Google-Smtp-Source: ABdhPJxNR+Dh/hCzJXb2xVVsTj6lnlI25agF3VeDIbDMoJyG+2SG6lIPvj2+KQ5vMWWV6KBpzXQ42A== X-Received: by 2002:adf:ea01:: with SMTP id q1mr5257060wrm.97.1599046161074; Wed, 02 Sep 2020 04:29:21 -0700 (PDT) Received: from localhost.localdomain (84-238-136-197.ip.btc-net.bg. [84.238.136.197]) by smtp.gmail.com with ESMTPSA id 5sm5985172wmz.22.2020.09.02.04.29.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Sep 2020 04:29:20 -0700 (PDT) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@nvidia.com, bridge@lists.linux-foundation.org, davem@davemloft.net, Nikolay Aleksandrov Subject: [PATCH net-next v2 09/15] net: bridge: mcast: delete expired port groups without srcs Date: Wed, 2 Sep 2020 14:25:23 +0300 Message-Id: <20200902112529.1570040-10-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> References: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org If an expired port group is in EXCLUDE mode, then we have to turn it into INCLUDE mode, remove all srcs with zero timer and finally remove the group itself if there are no more srcs with an active timer. For IGMPv2 use there would be no sources, so this will reduce to just removing the group as before. Signed-off-by: Nikolay Aleksandrov --- net/bridge/br_multicast.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 0ec43d549137..aabb1fcc7fa1 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -222,15 +222,34 @@ static void br_multicast_find_del_pg(struct net_bridge *br, static void br_multicast_port_group_expired(struct timer_list *t) { struct net_bridge_port_group *pg = from_timer(pg, t, timer); + struct net_bridge_group_src *src_ent; struct net_bridge *br = pg->port->br; + struct hlist_node *tmp; + bool changed; spin_lock(&br->multicast_lock); if (!netif_running(br->dev) || timer_pending(&pg->timer) || hlist_unhashed(&pg->mglist) || pg->flags & MDB_PG_FLAGS_PERMANENT) goto out; - br_multicast_find_del_pg(br, pg); + changed = !!(pg->filter_mode == MCAST_EXCLUDE); + pg->filter_mode = MCAST_INCLUDE; + hlist_for_each_entry_safe(src_ent, tmp, &pg->src_list, node) { + if (!timer_pending(&src_ent->timer)) { + br_multicast_del_group_src(src_ent); + changed = true; + } + } + if (hlist_empty(&pg->src_list)) { + br_multicast_find_del_pg(br, pg); + } else if (changed) { + struct net_bridge_mdb_entry *mp = br_mdb_ip_get(br, &pg->addr); + + if (WARN_ON(!mp)) + goto out; + br_mdb_notify(br->dev, mp, pg, RTM_NEWMDB); + } out: spin_unlock(&br->multicast_lock); } From patchwork Wed Sep 2 11:25:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1355682 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.a=rsa-sha256 header.s=google header.b=WXO6Aitb; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BhMFs5kxdz9sTv for ; Wed, 2 Sep 2020 21:31:13 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727049AbgIBLbM (ORCPT ); Wed, 2 Sep 2020 07:31:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41070 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726722AbgIBL30 (ORCPT ); Wed, 2 Sep 2020 07:29:26 -0400 Received: from mail-wr1-x441.google.com (mail-wr1-x441.google.com [IPv6:2a00:1450:4864:20::441]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5065BC061246 for ; Wed, 2 Sep 2020 04:29:24 -0700 (PDT) Received: by mail-wr1-x441.google.com with SMTP id m6so4867178wrn.0 for ; Wed, 02 Sep 2020 04:29:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=WQVx57lpxhwPFsPNQAezt/1bPQj12DWcBPV6SR3gQ/k=; b=WXO6Aitb6qbbLzLHlic8rETcl8AstqmpqHPyudTpfEGpjpV4Fi5Md4ZCmHs6yrt8cz wPhvXdbfGnCc5rY7Id7Hc6tKVds33+nheokk9grQA+Mssh8C+PVbVSo3jxS8Ul2r+cjx QDTAqWc8crQxNaSRWRtpiUE7gzlXe75TucPM4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=WQVx57lpxhwPFsPNQAezt/1bPQj12DWcBPV6SR3gQ/k=; b=H39/Q52Ckp2HGnKKq6+LDqq5NdaxATJ7/kQFrlCu6YEhmHlg2f9U9jc+VeeZhisR9n NjzCF1VPP/2PJ804UolbbKEBA7pXnDrYFLu/3KqHb0YVtSuFUbVrX9gGvaxkGzYVubFo YDOCxaSj37w1G5c9ZlyrSNq13sk7RmjCYFwAcKMAScG7QIJK7ZDPAjylv6WnEGc4Wmni qcDzz7LEy/z0rEQhKOvbglbJYhotCx81yliw9jGYwUaUwfR7bt3UjB9a5Qh5pBGOLtco s3KxIpnSpcqOZQ/AjKH55YL/dMBwSF4e3/oXTAj6sBFytjsRg/BMDSRR3P1jYni+rBG7 2x7A== X-Gm-Message-State: AOAM532wFGafvDVDeiZRbfEd5ZpPxZlc7qOlOHuL0SpEXuOwBOJJeJlY Nm+HlKHnwWRVKtVerZhQPb8FTTQw9uBh5nc8 X-Google-Smtp-Source: ABdhPJyQThJ2XLtwUPjTHB/cKdi1MxOJvKLFZ645vrIuBJKHK6txIEqw5+r/H8kkZinVRFHf/gsaQQ== X-Received: by 2002:a5d:514e:: with SMTP id u14mr1914235wrt.211.1599046162468; Wed, 02 Sep 2020 04:29:22 -0700 (PDT) Received: from localhost.localdomain (84-238-136-197.ip.btc-net.bg. [84.238.136.197]) by smtp.gmail.com with ESMTPSA id 5sm5985172wmz.22.2020.09.02.04.29.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Sep 2020 04:29:21 -0700 (PDT) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@nvidia.com, bridge@lists.linux-foundation.org, davem@davemloft.net, Nikolay Aleksandrov Subject: [PATCH net-next v2 10/15] net: bridge: mcast: support for IGMPv3 IGMPV3_ALLOW_NEW_SOURCES report Date: Wed, 2 Sep 2020 14:25:24 +0300 Message-Id: <20200902112529.1570040-11-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> References: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This patch adds handling for the IGMPV3_ALLOW_NEW_SOURCES IGMPv3 report type and limits it only when multicast_igmp_version == 3. Now that IGMPv3 handling functions will be managing timers we need to delay their activation, thus a new argument is added which controls if the timer should be updated. We also disable host IGMPv3 handling as it's not yet implemented and could cause inconsistent group state, the host can only join a group as EXCLUDE {} or leave it. Signed-off-by: Nikolay Aleksandrov --- net/bridge/br_multicast.c | 113 ++++++++++++++++++++++++++++++++------ net/bridge/br_private.h | 7 +++ 2 files changed, 103 insertions(+), 17 deletions(-) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index aabb1fcc7fa1..93771309f59f 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -721,7 +721,8 @@ void br_multicast_host_leave(struct net_bridge_mdb_entry *mp, bool notify) static int br_multicast_add_group(struct net_bridge *br, struct net_bridge_port *port, struct br_ip *group, - const unsigned char *src) + const unsigned char *src, + bool update_timer) { struct net_bridge_port_group __rcu **pp; struct net_bridge_port_group *p; @@ -760,7 +761,8 @@ static int br_multicast_add_group(struct net_bridge *br, br_mdb_notify(br->dev, mp, p, RTM_NEWMDB); found: - mod_timer(&p->timer, now + br->multicast_membership_interval); + if (update_timer) + mod_timer(&p->timer, now + br->multicast_membership_interval); out: err = 0; @@ -774,7 +776,8 @@ static int br_ip4_multicast_add_group(struct net_bridge *br, struct net_bridge_port *port, __be32 group, __u16 vid, - const unsigned char *src) + const unsigned char *src, + bool update_timer) { struct br_ip br_group; @@ -786,7 +789,7 @@ static int br_ip4_multicast_add_group(struct net_bridge *br, br_group.proto = htons(ETH_P_IP); br_group.vid = vid; - return br_multicast_add_group(br, port, &br_group, src); + return br_multicast_add_group(br, port, &br_group, src, update_timer); } #if IS_ENABLED(CONFIG_IPV6) @@ -806,7 +809,7 @@ static int br_ip6_multicast_add_group(struct net_bridge *br, br_group.proto = htons(ETH_P_IPV6); br_group.vid = vid; - return br_multicast_add_group(br, port, &br_group, src); + return br_multicast_add_group(br, port, &br_group, src, true); } #endif @@ -1153,20 +1156,71 @@ void br_multicast_disable_port(struct net_bridge_port *port) spin_unlock(&br->multicast_lock); } +/* State Msg type New state Actions + * INCLUDE (A) IS_IN (B) INCLUDE (A+B) (B)=GMI + * INCLUDE (A) ALLOW (B) INCLUDE (A+B) (B)=GMI + * EXCLUDE (X,Y) ALLOW (A) EXCLUDE (X+A,Y-A) (A)=GMI + */ +static bool br_multicast_isinc_allow(struct net_bridge_port_group *pg, + __be32 *srcs, u32 nsrcs) +{ + struct net_bridge *br = pg->port->br; + struct net_bridge_group_src *ent; + unsigned long now = jiffies; + bool changed = false; + struct br_ip src_ip; + u32 src_idx; + + memset(&src_ip, 0, sizeof(src_ip)); + src_ip.proto = htons(ETH_P_IP); + for (src_idx = 0; src_idx < nsrcs; src_idx++) { + src_ip.u.ip4 = srcs[src_idx]; + ent = br_multicast_find_group_src(pg, &src_ip); + if (!ent) { + ent = br_multicast_new_group_src(pg, &src_ip); + if (ent) + changed = true; + } + + if (ent) + mod_timer(&ent->timer, now + br_multicast_gmi(br)); + } + + return changed; +} + +static struct net_bridge_port_group * +br_multicast_find_port(struct net_bridge_mdb_entry *mp, + struct net_bridge_port *p, + const unsigned char *src) +{ + struct net_bridge_port_group *pg; + struct net_bridge *br = mp->br; + + for (pg = mlock_dereference(mp->ports, br); + pg; + pg = mlock_dereference(pg->next, br)) + if (br_port_group_equal(pg, p, src)) + return pg; + + return NULL; +} + static int br_ip4_multicast_igmp3_report(struct net_bridge *br, struct net_bridge_port *port, struct sk_buff *skb, u16 vid) { + bool igmpv2 = br->multicast_igmp_version == 2; + struct net_bridge_mdb_entry *mdst; + struct net_bridge_port_group *pg; const unsigned char *src; struct igmpv3_report *ih; struct igmpv3_grec *grec; - int i; - int len; - int num; - int type; - int err = 0; + int i, len, num, type; + bool changed = false; __be32 group; + int err = 0; u16 nsrcs; ih = igmpv3_report_hdr(skb); @@ -1187,7 +1241,6 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br, if (!ip_mc_may_pull(skb, len)) return -EINVAL; - /* We treat this as an IGMPv2 report for now. */ switch (type) { case IGMPV3_MODE_IS_INCLUDE: case IGMPV3_MODE_IS_EXCLUDE: @@ -1202,16 +1255,41 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br, } src = eth_hdr(skb)->h_source; - if ((type == IGMPV3_CHANGE_TO_INCLUDE || - type == IGMPV3_MODE_IS_INCLUDE) && - nsrcs == 0) { - br_ip4_multicast_leave_group(br, port, group, vid, src); + if (nsrcs == 0 && + (type == IGMPV3_CHANGE_TO_INCLUDE || + type == IGMPV3_MODE_IS_INCLUDE)) { + if (igmpv2 || !port) { + br_ip4_multicast_leave_group(br, port, group, vid, src); + continue; + } } else { err = br_ip4_multicast_add_group(br, port, group, vid, - src); + src, igmpv2); if (err) break; } + + if (!port || igmpv2) + continue; + + spin_lock_bh(&br->multicast_lock); + mdst = br_mdb_ip4_get(br, group, vid); + if (!mdst) + goto unlock_continue; + pg = br_multicast_find_port(mdst, port, src); + if (!pg || (pg->flags & MDB_PG_FLAGS_PERMANENT)) + goto unlock_continue; + /* reload grec */ + grec = (void *)(skb->data + len - sizeof(*grec) - (nsrcs * 4)); + switch (type) { + case IGMPV3_ALLOW_NEW_SOURCES: + changed = br_multicast_isinc_allow(pg, grec->grec_src, nsrcs); + break; + } + if (changed) + br_mdb_notify(br->dev, mdst, pg, RTM_NEWMDB); +unlock_continue: + spin_unlock_bh(&br->multicast_lock); } return err; @@ -1859,7 +1937,8 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, case IGMP_HOST_MEMBERSHIP_REPORT: case IGMPV2_HOST_MEMBERSHIP_REPORT: BR_INPUT_SKB_CB(skb)->mrouters_only = 1; - err = br_ip4_multicast_add_group(br, port, ih->group, vid, src); + err = br_ip4_multicast_add_group(br, port, ih->group, vid, src, + true); break; case IGMPV3_HOST_MEMBERSHIP_REPORT: err = br_ip4_multicast_igmp3_report(br, port, skb, vid); diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 78822d3a3b7c..a18bd67dab34 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -875,6 +875,13 @@ static inline unsigned long br_multicast_lmqt(const struct net_bridge *br) return br->multicast_last_member_interval * br->multicast_last_member_count; } + +static inline unsigned long br_multicast_gmi(const struct net_bridge *br) +{ + /* use the RFC default of 2 for QRV */ + return 2 * br->multicast_query_interval + + br->multicast_query_response_interval; +} #else static inline int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port, From patchwork Wed Sep 2 11:25:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1355686 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.a=rsa-sha256 header.s=google header.b=O5Z9tyxp; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BhMGG1rJpz9sTv for ; Wed, 2 Sep 2020 21:31:34 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727115AbgIBLb3 (ORCPT ); Wed, 2 Sep 2020 07:31:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41078 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726802AbgIBL30 (ORCPT ); Wed, 2 Sep 2020 07:29:26 -0400 Received: from mail-wr1-x443.google.com (mail-wr1-x443.google.com [IPv6:2a00:1450:4864:20::443]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B149FC061247 for ; Wed, 2 Sep 2020 04:29:25 -0700 (PDT) Received: by mail-wr1-x443.google.com with SMTP id x14so4829581wrl.12 for ; Wed, 02 Sep 2020 04:29:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=CBvvkGoY63ume+BxSWZf+l7R9g82AVslqqYoUts1Shc=; b=O5Z9tyxp6OnjDBLSi9g3fiKfHZ7PW632yiPWLi51OWRKsvw/R+JfnDekiC1upI8Ytr rATDVwXd3kF4pz8Ak1yZwMOrYYo1UWgwSj2ZUBPizujRmHRJDJzRLxLYfeVJiwj+dBmi IezWTA5xiRTOUDBE7m9fsHOOzgGHIDv47eP8A= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=CBvvkGoY63ume+BxSWZf+l7R9g82AVslqqYoUts1Shc=; b=MIe+AvOYcshTzJ0THNQXjjCwldUMMRG7jO7LsDCFpB+DGwUX3fV2n9Oxn/cFxQVz2I 9viAKVFKZgk4obJbQ7bTy+vh5uozCPaBW+YLSquI3AxH5n796QyM3edY/DipSCVs6ArI vuQrhv4v9ZNN7yztM99b9MyfCDtmrgUWZFIUsAVopAWOutxzJhTAOa6HrdvY8Hp1c4wv 2ztzt2H7qBcYxGvsXE6Xy7lnlo18ZHCVuoQmCHrEwye4TY9zF0TeQRm6yD+/g7Iost/Z p0AK/eoW3v4IFMtr/b4zbBRQBn56ZSdiY618BkwnyTT9HTY5iHf4jegdPVDH2a3I2zK4 R2Qw== X-Gm-Message-State: AOAM530YjeydGHvRvfw1g/8QfXBE7GXM4Iu6REBSFCayNoXO8U4aYdrb 1YAOhdQxPzwvDw+pcIVq9833NDsJuNXXHCgT X-Google-Smtp-Source: ABdhPJySQtkjup00yd9q/tLwPyt8+rze7l+ADZf7utaSFMEs/M1Tm+VPSWMP+yD4rmFZP0+RXcAg9A== X-Received: by 2002:adf:aa9e:: with SMTP id h30mr6397204wrc.377.1599046163943; Wed, 02 Sep 2020 04:29:23 -0700 (PDT) Received: from localhost.localdomain (84-238-136-197.ip.btc-net.bg. [84.238.136.197]) by smtp.gmail.com with ESMTPSA id 5sm5985172wmz.22.2020.09.02.04.29.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Sep 2020 04:29:23 -0700 (PDT) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@nvidia.com, bridge@lists.linux-foundation.org, davem@davemloft.net, Nikolay Aleksandrov Subject: [PATCH net-next v2 11/15] net: bridge: mcast: support for IGMPV3_MODE_IS_INCLUDE/EXCLUDE report Date: Wed, 2 Sep 2020 14:25:25 +0300 Message-Id: <20200902112529.1570040-12-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> References: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org In order to process IGMPV3_MODE_IS_INCLUDE/EXCLUDE report types we need some new helpers which allow us to set/clear flags for all current entries and later delete marked entries after the report sources have been processed. v2: drop flag helpers and directly do flag bit operations Signed-off-by: Nikolay Aleksandrov --- net/bridge/br_multicast.c | 114 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 93771309f59f..9e0c8a462343 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1156,6 +1156,21 @@ void br_multicast_disable_port(struct net_bridge_port *port) spin_unlock(&br->multicast_lock); } +static int __grp_src_delete_marked(struct net_bridge_port_group *pg) +{ + struct net_bridge_group_src *ent; + struct hlist_node *tmp; + int deleted = 0; + + hlist_for_each_entry_safe(ent, tmp, &pg->src_list, node) + if (ent->flags & BR_SGRP_F_DELETE) { + br_multicast_del_group_src(ent); + deleted++; + } + + return deleted; +} + /* State Msg type New state Actions * INCLUDE (A) IS_IN (B) INCLUDE (A+B) (B)=GMI * INCLUDE (A) ALLOW (B) INCLUDE (A+B) (B)=GMI @@ -1189,6 +1204,99 @@ static bool br_multicast_isinc_allow(struct net_bridge_port_group *pg, return changed; } +/* State Msg type New state Actions + * INCLUDE (A) IS_EX (B) EXCLUDE (A*B,B-A) (B-A)=0 + * Delete (A-B) + * Group Timer=GMI + */ +static void __grp_src_isexc_incl(struct net_bridge_port_group *pg, + __be32 *srcs, u32 nsrcs) +{ + struct net_bridge_group_src *ent; + struct br_ip src_ip; + u32 src_idx; + + hlist_for_each_entry(ent, &pg->src_list, node) + ent->flags |= BR_SGRP_F_DELETE; + + memset(&src_ip, 0, sizeof(src_ip)); + src_ip.proto = htons(ETH_P_IP); + for (src_idx = 0; src_idx < nsrcs; src_idx++) { + src_ip.u.ip4 = srcs[src_idx]; + ent = br_multicast_find_group_src(pg, &src_ip); + if (ent) + ent->flags &= ~BR_SGRP_F_DELETE; + else + br_multicast_new_group_src(pg, &src_ip); + } + + __grp_src_delete_marked(pg); +} + +/* State Msg type New state Actions + * EXCLUDE (X,Y) IS_EX (A) EXCLUDE (A-Y,Y*A) (A-X-Y)=GMI + * Delete (X-A) + * Delete (Y-A) + * Group Timer=GMI + */ +static bool __grp_src_isexc_excl(struct net_bridge_port_group *pg, + __be32 *srcs, u32 nsrcs) +{ + struct net_bridge *br = pg->port->br; + struct net_bridge_group_src *ent; + unsigned long now = jiffies; + bool changed = false; + struct br_ip src_ip; + u32 src_idx; + + hlist_for_each_entry(ent, &pg->src_list, node) + ent->flags |= BR_SGRP_F_DELETE; + + memset(&src_ip, 0, sizeof(src_ip)); + src_ip.proto = htons(ETH_P_IP); + for (src_idx = 0; src_idx < nsrcs; src_idx++) { + src_ip.u.ip4 = srcs[src_idx]; + ent = br_multicast_find_group_src(pg, &src_ip); + if (ent) { + ent->flags &= ~BR_SGRP_F_DELETE; + } else { + ent = br_multicast_new_group_src(pg, &src_ip); + if (ent) { + mod_timer(&ent->timer, + now + br_multicast_gmi(br)); + changed = true; + } + } + } + + if (__grp_src_delete_marked(pg)) + changed = true; + + return changed; +} + +static bool br_multicast_isexc(struct net_bridge_port_group *pg, + __be32 *srcs, u32 nsrcs) +{ + struct net_bridge *br = pg->port->br; + bool changed = false; + + switch (pg->filter_mode) { + case MCAST_INCLUDE: + __grp_src_isexc_incl(pg, srcs, nsrcs); + changed = true; + break; + case MCAST_EXCLUDE: + changed = __grp_src_isexc_excl(pg, srcs, nsrcs); + break; + } + + pg->filter_mode = MCAST_EXCLUDE; + mod_timer(&pg->timer, jiffies + br_multicast_gmi(br)); + + return changed; +} + static struct net_bridge_port_group * br_multicast_find_port(struct net_bridge_mdb_entry *mp, struct net_bridge_port *p, @@ -1285,6 +1393,12 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br, case IGMPV3_ALLOW_NEW_SOURCES: changed = br_multicast_isinc_allow(pg, grec->grec_src, nsrcs); break; + case IGMPV3_MODE_IS_INCLUDE: + changed = br_multicast_isinc_allow(pg, grec->grec_src, nsrcs); + break; + case IGMPV3_MODE_IS_EXCLUDE: + changed = br_multicast_isexc(pg, grec->grec_src, nsrcs); + break; } if (changed) br_mdb_notify(br->dev, mdst, pg, RTM_NEWMDB); From patchwork Wed Sep 2 11:25:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1355683 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.a=rsa-sha256 header.s=google header.b=hRSJ6L0t; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BhMFw0Qtsz9sTv for ; Wed, 2 Sep 2020 21:31:16 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727065AbgIBLbO (ORCPT ); Wed, 2 Sep 2020 07:31:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41084 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726510AbgIBL32 (ORCPT ); Wed, 2 Sep 2020 07:29:28 -0400 Received: from mail-wr1-x441.google.com (mail-wr1-x441.google.com [IPv6:2a00:1450:4864:20::441]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3F4DCC06125C for ; Wed, 2 Sep 2020 04:29:27 -0700 (PDT) Received: by mail-wr1-x441.google.com with SMTP id x14so4829647wrl.12 for ; Wed, 02 Sep 2020 04:29:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=olba7YZuiOdWVUbjISlgCiVJSPh8C9vBzXfaBWot4Mc=; b=hRSJ6L0t+RNja36ZrAPNOblNCrdrS9id03SD2bRb2wJpdAldPj2wvLyPv7Ozd+zvvh JReShKgAE0xEprpBqnm7bcb67ZLW3FWCC1gLh3X3WgC+LyNbK8t64t3mP/+7MIhN0oMb ibScBC1cAlNC1S55teclgRBd7Xm7M0oSx73Qc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=olba7YZuiOdWVUbjISlgCiVJSPh8C9vBzXfaBWot4Mc=; b=qGdGjeXCuLQzz7wZ2uG75mkoacD5EtqwC6J4/zcVJZ+qx44Qd3ful/RwSbv/ylXH90 vXaflVFIzB0kzvTbfY3IDDSOKg5FggO7RI43e5nhegqsFa5rj9CPjz8KaOmL1o7svQv7 HSmmsU2vbaX76lkeX9cQ3yCBn4cp0W2eW42WCpF3yfeTXqEhrtLR3KxWl1/KeVZcOAMV 5IUhGKIMLrk+gZvhreYp80Rs+SSG1dTX9xsxB1YRGsMA7U5HDQ4FMtLZd8zw2IrzB6hR lpVZixt8DfdQD8aq4WBoNRh68lmOhrMKohWh7q4wemzFaoIGcFYiVzpYALnUXaFWNq8F M8hw== X-Gm-Message-State: AOAM5331ycY3rOanZGpneXu1JKwf95PGZFYUwsScyRZqiTlvU164Nj7U q31fZBGIbi8ibTQKE6uO3ntw5PnRTn55diW6 X-Google-Smtp-Source: ABdhPJzXkB8FbknQNEC5zLAeOgTeng6UPpBsB1rTt7FgWt8hEby7T+JsUeMgVUl9zda2cTedZja5Gg== X-Received: by 2002:adf:fed1:: with SMTP id q17mr6432862wrs.85.1599046165394; Wed, 02 Sep 2020 04:29:25 -0700 (PDT) Received: from localhost.localdomain (84-238-136-197.ip.btc-net.bg. [84.238.136.197]) by smtp.gmail.com with ESMTPSA id 5sm5985172wmz.22.2020.09.02.04.29.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Sep 2020 04:29:24 -0700 (PDT) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@nvidia.com, bridge@lists.linux-foundation.org, davem@davemloft.net, Nikolay Aleksandrov Subject: [PATCH net-next v2 12/15] net: bridge: mcast: support for IGMPV3_CHANGE_TO_INCLUDE/EXCLUDE report Date: Wed, 2 Sep 2020 14:25:26 +0300 Message-Id: <20200902112529.1570040-13-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> References: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org In order to process IGMPV3_CHANGE_TO_INCLUDE/EXCLUDE report types we need new helpers which allow us to mark entries based on their timer state and to query only marked entries. v2: directly do flag bit operations Signed-off-by: Nikolay Aleksandrov --- net/bridge/br_multicast.c | 267 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 267 insertions(+) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 9e0c8a462343..0dffd5a26110 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1171,6 +1171,61 @@ static int __grp_src_delete_marked(struct net_bridge_port_group *pg) return deleted; } +static void __grp_src_query_marked_and_rexmit(struct net_bridge_port_group *pg) +{ + struct net_bridge *br = pg->port->br; + u32 lmqc = br->multicast_last_member_count; + unsigned long lmqt, lmi, now = jiffies; + struct net_bridge_group_src *ent; + + lmqt = now + br_multicast_lmqt(br); + hlist_for_each_entry(ent, &pg->src_list, node) { + if (ent->flags & BR_SGRP_F_SEND) { + ent->flags &= ~BR_SGRP_F_SEND; + if (ent->timer.expires > lmqt) { + if (br_opt_get(br, BROPT_MULTICAST_QUERIER) && + !timer_pending(&br->ip4_other_query.timer)) + ent->src_query_rexmit_cnt = lmqc; + mod_timer(&ent->timer, lmqt); + } + } + } + + if (!br_opt_get(br, BROPT_MULTICAST_QUERIER) || + timer_pending(&br->ip4_other_query.timer)) + return; + + __br_multicast_send_query(br, pg->port, pg, &pg->addr, + &pg->addr, true, 1, NULL); + + lmi = now + br->multicast_last_member_interval; + if (!timer_pending(&pg->rexmit_timer) || + time_after(pg->rexmit_timer.expires, lmi)) + mod_timer(&pg->rexmit_timer, lmi); +} + +static void __grp_send_query_and_rexmit(struct net_bridge_port_group *pg) +{ + struct net_bridge *br = pg->port->br; + unsigned long now = jiffies, lmi; + + if (br_opt_get(br, BROPT_MULTICAST_QUERIER) && + timer_pending(&br->ip4_other_query.timer)) { + lmi = now + br->multicast_last_member_interval; + pg->grp_query_rexmit_cnt = br->multicast_last_member_count - 1; + __br_multicast_send_query(br, pg->port, pg, &pg->addr, + &pg->addr, false, 0, NULL); + if (!timer_pending(&pg->rexmit_timer) || + time_after(pg->rexmit_timer.expires, lmi)) + mod_timer(&pg->rexmit_timer, lmi); + } + + if (pg->filter_mode == MCAST_EXCLUDE && + (!timer_pending(&pg->timer) || + time_after(pg->timer.expires, now + br_multicast_lmqt(br)))) + mod_timer(&pg->timer, now + br_multicast_lmqt(br)); +} + /* State Msg type New state Actions * INCLUDE (A) IS_IN (B) INCLUDE (A+B) (B)=GMI * INCLUDE (A) ALLOW (B) INCLUDE (A+B) (B)=GMI @@ -1297,6 +1352,212 @@ static bool br_multicast_isexc(struct net_bridge_port_group *pg, return changed; } +/* State Msg type New state Actions + * INCLUDE (A) TO_IN (B) INCLUDE (A+B) (B)=GMI + * Send Q(G,A-B) + */ +static bool __grp_src_toin_incl(struct net_bridge_port_group *pg, + __be32 *srcs, u32 nsrcs) +{ + struct net_bridge *br = pg->port->br; + u32 src_idx, to_send = pg->src_ents; + struct net_bridge_group_src *ent; + unsigned long now = jiffies; + bool changed = false; + struct br_ip src_ip; + + hlist_for_each_entry(ent, &pg->src_list, node) + ent->flags |= BR_SGRP_F_SEND; + + memset(&src_ip, 0, sizeof(src_ip)); + src_ip.proto = htons(ETH_P_IP); + for (src_idx = 0; src_idx < nsrcs; src_idx++) { + src_ip.u.ip4 = srcs[src_idx]; + ent = br_multicast_find_group_src(pg, &src_ip); + if (ent) { + ent->flags &= ~BR_SGRP_F_SEND; + to_send--; + } else { + ent = br_multicast_new_group_src(pg, &src_ip); + if (ent) + changed = true; + } + if (ent) + mod_timer(&ent->timer, now + br_multicast_gmi(br)); + } + + if (to_send) + __grp_src_query_marked_and_rexmit(pg); + + return changed; +} + +/* State Msg type New state Actions + * EXCLUDE (X,Y) TO_IN (A) EXCLUDE (X+A,Y-A) (A)=GMI + * Send Q(G,X-A) + * Send Q(G) + */ +static bool __grp_src_toin_excl(struct net_bridge_port_group *pg, + __be32 *srcs, u32 nsrcs) +{ + struct net_bridge *br = pg->port->br; + u32 src_idx, to_send = pg->src_ents; + struct net_bridge_group_src *ent; + unsigned long now = jiffies; + bool changed = false; + struct br_ip src_ip; + + hlist_for_each_entry(ent, &pg->src_list, node) + if (timer_pending(&ent->timer)) + ent->flags |= BR_SGRP_F_SEND; + + memset(&src_ip, 0, sizeof(src_ip)); + src_ip.proto = htons(ETH_P_IP); + for (src_idx = 0; src_idx < nsrcs; src_idx++) { + src_ip.u.ip4 = srcs[src_idx]; + ent = br_multicast_find_group_src(pg, &src_ip); + if (ent) { + if (timer_pending(&ent->timer)) { + ent->flags &= ~BR_SGRP_F_SEND; + to_send--; + } + } else { + ent = br_multicast_new_group_src(pg, &src_ip); + if (ent) + changed = true; + } + if (ent) + mod_timer(&ent->timer, now + br_multicast_gmi(br)); + } + + if (to_send) + __grp_src_query_marked_and_rexmit(pg); + + __grp_send_query_and_rexmit(pg); + + return changed; +} + +static bool br_multicast_toin(struct net_bridge_port_group *pg, + __be32 *srcs, u32 nsrcs) +{ + bool changed = false; + + switch (pg->filter_mode) { + case MCAST_INCLUDE: + changed = __grp_src_toin_incl(pg, srcs, nsrcs); + break; + case MCAST_EXCLUDE: + changed = __grp_src_toin_excl(pg, srcs, nsrcs); + break; + } + + return changed; +} + +/* State Msg type New state Actions + * INCLUDE (A) TO_EX (B) EXCLUDE (A*B,B-A) (B-A)=0 + * Delete (A-B) + * Send Q(G,A*B) + * Group Timer=GMI + */ +static void __grp_src_toex_incl(struct net_bridge_port_group *pg, + __be32 *srcs, u32 nsrcs) +{ + struct net_bridge_group_src *ent; + u32 src_idx, to_send = 0; + struct br_ip src_ip; + + hlist_for_each_entry(ent, &pg->src_list, node) + ent->flags = (ent->flags & ~BR_SGRP_F_SEND) | BR_SGRP_F_DELETE; + + memset(&src_ip, 0, sizeof(src_ip)); + src_ip.proto = htons(ETH_P_IP); + for (src_idx = 0; src_idx < nsrcs; src_idx++) { + src_ip.u.ip4 = srcs[src_idx]; + ent = br_multicast_find_group_src(pg, &src_ip); + if (ent) { + ent->flags = (ent->flags & ~BR_SGRP_F_DELETE) | + BR_SGRP_F_SEND; + to_send++; + } else { + br_multicast_new_group_src(pg, &src_ip); + } + } + + __grp_src_delete_marked(pg); + if (to_send) + __grp_src_query_marked_and_rexmit(pg); +} + +/* State Msg type New state Actions + * EXCLUDE (X,Y) TO_EX (A) EXCLUDE (A-Y,Y*A) (A-X-Y)=Group Timer + * Delete (X-A) + * Delete (Y-A) + * Send Q(G,A-Y) + * Group Timer=GMI + */ +static bool __grp_src_toex_excl(struct net_bridge_port_group *pg, + __be32 *srcs, u32 nsrcs) +{ + struct net_bridge_group_src *ent; + u32 src_idx, to_send = 0; + bool changed = false; + struct br_ip src_ip; + + hlist_for_each_entry(ent, &pg->src_list, node) + ent->flags = (ent->flags & ~BR_SGRP_F_SEND) | BR_SGRP_F_DELETE; + + memset(&src_ip, 0, sizeof(src_ip)); + src_ip.proto = htons(ETH_P_IP); + for (src_idx = 0; src_idx < nsrcs; src_idx++) { + src_ip.u.ip4 = srcs[src_idx]; + ent = br_multicast_find_group_src(pg, &src_ip); + if (ent) { + ent->flags &= ~BR_SGRP_F_DELETE; + } else { + ent = br_multicast_new_group_src(pg, &src_ip); + if (ent) { + mod_timer(&ent->timer, pg->timer.expires); + changed = true; + } + } + if (ent && timer_pending(&ent->timer)) { + ent->flags |= BR_SGRP_F_SEND; + to_send++; + } + } + + if (__grp_src_delete_marked(pg)) + changed = true; + if (to_send) + __grp_src_query_marked_and_rexmit(pg); + + return changed; +} + +static bool br_multicast_toex(struct net_bridge_port_group *pg, + __be32 *srcs, u32 nsrcs) +{ + struct net_bridge *br = pg->port->br; + bool changed = false; + + switch (pg->filter_mode) { + case MCAST_INCLUDE: + __grp_src_toex_incl(pg, srcs, nsrcs); + changed = true; + break; + case MCAST_EXCLUDE: + __grp_src_toex_excl(pg, srcs, nsrcs); + break; + } + + pg->filter_mode = MCAST_EXCLUDE; + mod_timer(&pg->timer, jiffies + br_multicast_gmi(br)); + + return changed; +} + static struct net_bridge_port_group * br_multicast_find_port(struct net_bridge_mdb_entry *mp, struct net_bridge_port *p, @@ -1399,6 +1660,12 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br, case IGMPV3_MODE_IS_EXCLUDE: changed = br_multicast_isexc(pg, grec->grec_src, nsrcs); break; + case IGMPV3_CHANGE_TO_INCLUDE: + changed = br_multicast_toin(pg, grec->grec_src, nsrcs); + break; + case IGMPV3_CHANGE_TO_EXCLUDE: + changed = br_multicast_toex(pg, grec->grec_src, nsrcs); + break; } if (changed) br_mdb_notify(br->dev, mdst, pg, RTM_NEWMDB); From patchwork Wed Sep 2 11:25:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1355685 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.a=rsa-sha256 header.s=google header.b=dQCacWcl; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BhMG82Jsgz9sTv for ; Wed, 2 Sep 2020 21:31:28 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727095AbgIBLb1 (ORCPT ); Wed, 2 Sep 2020 07:31:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41038 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726853AbgIBL3g (ORCPT ); Wed, 2 Sep 2020 07:29:36 -0400 Received: from mail-wm1-x334.google.com (mail-wm1-x334.google.com [IPv6:2a00:1450:4864:20::334]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9E87DC06125E for ; Wed, 2 Sep 2020 04:29:28 -0700 (PDT) Received: by mail-wm1-x334.google.com with SMTP id v4so4123996wmj.5 for ; Wed, 02 Sep 2020 04:29:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=TzhrU1X5QK7zN9nZRqOyfgvddTz2HYLjcgzS650iqOY=; b=dQCacWclRvKUoroMCZyEzf8Y0w/TlGmaQVejCerdl7W1g6J/0c6ioHmIsv+/+Aa7F5 8DuAYRlg7lJb9fl7a8wPRhv7KMZCA2x44X7zuZewQBmsZ80stg7l5nDkhQuAQoTiAHNy hG00WySylt9FmCYn83mn/GwozFXoEdsQUjb5s= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=TzhrU1X5QK7zN9nZRqOyfgvddTz2HYLjcgzS650iqOY=; b=F3bG+NK88+DDIgdfR09jRcpWtiItspZt/6DDG5b64Vk+4R9n3bmWx4ZpeLHLP233z3 x25O+LdX3f5VbA0m2tny5/nQBvlN/Hn1ehNwglTv6M1LS1TfNuyJTb5MWeUKmsFtPgG3 TF/EQ/0DdZoP4P5OoyW249MLphYEX7baBC47S3d096OU4BgxfH76jZ132CR/mKlGzkYH tnuqhtW/S/Jx93r7Vn6nGZjzyWmDLiGA0vvUHgcLc2jg8d0StFyw7QnKvjA9eSEpwdMX K4KwwNjdHtWqRzSCJPrl48ChgnBls/O8fdbA9TdD+xpd8R00a494jcDbtW7ItMbAOpkH LD0A== X-Gm-Message-State: AOAM532dLc9plbfDTBSSDWDcAQcyy7khNr8Qne8nS5SFoMkKvAUjCRKp ekv9b4hf+e0+6MQsYGhU7Hf/lvv0TzSdvJMo X-Google-Smtp-Source: ABdhPJxx70Tnqtku1r/LXj+0qZlA8oiunwxX6hK53RqVd7boHBOwsGlZjrMuO6gks8hAUU3i5Ic7nw== X-Received: by 2002:a05:600c:2f8f:: with SMTP id t15mr204386wmn.41.1599046166896; Wed, 02 Sep 2020 04:29:26 -0700 (PDT) Received: from localhost.localdomain (84-238-136-197.ip.btc-net.bg. [84.238.136.197]) by smtp.gmail.com with ESMTPSA id 5sm5985172wmz.22.2020.09.02.04.29.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Sep 2020 04:29:26 -0700 (PDT) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@nvidia.com, bridge@lists.linux-foundation.org, davem@davemloft.net, Nikolay Aleksandrov Subject: [PATCH net-next v2 13/15] net: bridge: mcast: support for IGMPV3_BLOCK_OLD_SOURCES report Date: Wed, 2 Sep 2020 14:25:27 +0300 Message-Id: <20200902112529.1570040-14-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> References: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org We already have all necessary helpers, so process IGMPV3_BLOCK_OLD_SOURCES as per the RFC. v2: directly do flag bit operations Signed-off-by: Nikolay Aleksandrov --- net/bridge/br_multicast.c | 90 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 0dffd5a26110..7df192e9ec50 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1558,6 +1558,93 @@ static bool br_multicast_toex(struct net_bridge_port_group *pg, return changed; } +/* State Msg type New state Actions + * INCLUDE (A) BLOCK (B) INCLUDE (A) Send Q(G,A*B) + */ +static void __grp_src_block_incl(struct net_bridge_port_group *pg, + __be32 *srcs, u32 nsrcs) +{ + struct net_bridge_group_src *ent; + u32 src_idx, to_send = 0; + struct br_ip src_ip; + + hlist_for_each_entry(ent, &pg->src_list, node) + ent->flags &= ~BR_SGRP_F_SEND; + + memset(&src_ip, 0, sizeof(src_ip)); + src_ip.proto = htons(ETH_P_IP); + for (src_idx = 0; src_idx < nsrcs; src_idx++) { + src_ip.u.ip4 = srcs[src_idx]; + ent = br_multicast_find_group_src(pg, &src_ip); + if (ent) { + ent->flags |= BR_SGRP_F_SEND; + to_send++; + } + } + + if (to_send) + __grp_src_query_marked_and_rexmit(pg); + + if (pg->filter_mode == MCAST_INCLUDE && hlist_empty(&pg->src_list)) + br_multicast_find_del_pg(pg->port->br, pg); +} + +/* State Msg type New state Actions + * EXCLUDE (X,Y) BLOCK (A) EXCLUDE (X+(A-Y),Y) (A-X-Y)=Group Timer + * Send Q(G,A-Y) + */ +static bool __grp_src_block_excl(struct net_bridge_port_group *pg, + __be32 *srcs, u32 nsrcs) +{ + struct net_bridge_group_src *ent; + u32 src_idx, to_send = 0; + bool changed = false; + struct br_ip src_ip; + + hlist_for_each_entry(ent, &pg->src_list, node) + ent->flags &= ~BR_SGRP_F_SEND; + + memset(&src_ip, 0, sizeof(src_ip)); + src_ip.proto = htons(ETH_P_IP); + for (src_idx = 0; src_idx < nsrcs; src_idx++) { + src_ip.u.ip4 = srcs[src_idx]; + ent = br_multicast_find_group_src(pg, &src_ip); + if (!ent) { + ent = br_multicast_new_group_src(pg, &src_ip); + if (ent) { + mod_timer(&ent->timer, pg->timer.expires); + changed = true; + } + } + if (ent && timer_pending(&ent->timer)) { + ent->flags |= BR_SGRP_F_SEND; + to_send++; + } + } + + if (to_send) + __grp_src_query_marked_and_rexmit(pg); + + return changed; +} + +static bool br_multicast_block(struct net_bridge_port_group *pg, + __be32 *srcs, u32 nsrcs) +{ + bool changed = false; + + switch (pg->filter_mode) { + case MCAST_INCLUDE: + __grp_src_block_incl(pg, srcs, nsrcs); + break; + case MCAST_EXCLUDE: + changed = __grp_src_block_excl(pg, srcs, nsrcs); + break; + } + + return changed; +} + static struct net_bridge_port_group * br_multicast_find_port(struct net_bridge_mdb_entry *mp, struct net_bridge_port *p, @@ -1666,6 +1753,9 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br, case IGMPV3_CHANGE_TO_EXCLUDE: changed = br_multicast_toex(pg, grec->grec_src, nsrcs); break; + case IGMPV3_BLOCK_OLD_SOURCES: + changed = br_multicast_block(pg, grec->grec_src, nsrcs); + break; } if (changed) br_mdb_notify(br->dev, mdst, pg, RTM_NEWMDB); From patchwork Wed Sep 2 11:25:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1355684 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.a=rsa-sha256 header.s=google header.b=WtJ+zPac; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BhMG44dwXz9sTv for ; Wed, 2 Sep 2020 21:31:24 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727081AbgIBLbQ (ORCPT ); Wed, 2 Sep 2020 07:31:16 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41106 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726858AbgIBL3g (ORCPT ); Wed, 2 Sep 2020 07:29:36 -0400 Received: from mail-wm1-x344.google.com (mail-wm1-x344.google.com [IPv6:2a00:1450:4864:20::344]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F16A1C06125F for ; Wed, 2 Sep 2020 04:29:29 -0700 (PDT) Received: by mail-wm1-x344.google.com with SMTP id v4so4124060wmj.5 for ; Wed, 02 Sep 2020 04:29:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=YcxPQNiqZGfjRlM3agi/H9CXj/hoWpM61eljrbx6rLE=; b=WtJ+zPacVL8leVdtVXhM/VcdHCc/XQ9ai2STnwz8leWk31wiLaqlOt4eJpqcbJO0Sq omwLsTen3quNV8QaUHx6W920vl9qgqGcnzOYdB1oHEfs4RZsBHc7PegoeW64P5uLh40A SA0/iIlq973XfFHEOvdPYmsp3fdub8HKL/diU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=YcxPQNiqZGfjRlM3agi/H9CXj/hoWpM61eljrbx6rLE=; b=pV13AqPjVBP7XoVtr/R+L/mMfZLAgtyJ8zY9w8zOUi6/8dP3QPZWFSJsNAOIhCQxat RBpP2mo1hilUoD/+tvpLdrv2M/dZR5uvudwJy8OX0Ksb4bPQ1u4EVT2hkqP6wqVZW0C3 GgB20IjYIE/3lDlfn9jE5dSjBTGhZ7TdxzsQqxhy2weEDAHDeZFvc5q+NvPfiC8EPyk5 +1yXZGZDS9/rt4YTgVBAhHYzmkCaKSl0XChIMPJyNwwn0Vmn7+YRZbr7TXQ4KL0RWhAu mAtoDiMc+weJUwJV098GXcuVKtHmUIAV6YF6ARbMQVtxz3ioFbCk59RKcSgn310GnDno rTbQ== X-Gm-Message-State: AOAM533NbdJyBqhq6tx8TS2zd8K1v6+ClVPM73B7uL94bShphIJRmTJI 626/15USk3GCBBAA7t8R1MCB7b50tBh0OdaX X-Google-Smtp-Source: ABdhPJyTnKSDWgIjCNX+g1r3pUsps04FY1kk8UesBPXAGa3Pty7u7ysUK4vXKBa88zmU+DtF9+Lusw== X-Received: by 2002:a1c:7c13:: with SMTP id x19mr198001wmc.45.1599046168215; Wed, 02 Sep 2020 04:29:28 -0700 (PDT) Received: from localhost.localdomain (84-238-136-197.ip.btc-net.bg. [84.238.136.197]) by smtp.gmail.com with ESMTPSA id 5sm5985172wmz.22.2020.09.02.04.29.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Sep 2020 04:29:27 -0700 (PDT) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@nvidia.com, bridge@lists.linux-foundation.org, davem@davemloft.net, Nikolay Aleksandrov Subject: [PATCH net-next v2 14/15] net: bridge: mcast: improve v3 query processing Date: Wed, 2 Sep 2020 14:25:28 +0300 Message-Id: <20200902112529.1570040-15-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> References: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org When an IGMPv3 query is received and we're operating in v3 mode then we need to avoid updating group timers if the suppress flag is set. Also we should update only timers for groups in exclude mode. Signed-off-by: Nikolay Aleksandrov --- net/bridge/br_multicast.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 7df192e9ec50..db4b2621631c 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -2034,7 +2034,8 @@ static void br_ip4_multicast_query(struct net_bridge *br, } } else if (transport_len >= sizeof(*ih3)) { ih3 = igmpv3_query_hdr(skb); - if (ih3->nsrcs) + if (ih3->nsrcs || + (br->multicast_igmp_version == 3 && group && ih3->suppress)) goto out; max_delay = ih3->code ? @@ -2069,7 +2070,9 @@ static void br_ip4_multicast_query(struct net_bridge *br, pp = &p->next) { if (timer_pending(&p->timer) ? time_after(p->timer.expires, now + max_delay) : - try_to_del_timer_sync(&p->timer) >= 0) + try_to_del_timer_sync(&p->timer) >= 0 && + (br->multicast_igmp_version == 2 || + p->filter_mode == MCAST_EXCLUDE)) mod_timer(&p->timer, now + max_delay); } From patchwork Wed Sep 2 11:25:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Aleksandrov X-Patchwork-Id: 1355687 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=cumulusnetworks.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=cumulusnetworks.com header.i=@cumulusnetworks.com header.a=rsa-sha256 header.s=google header.b=Uxb6bQWN; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BhMGH6vCGz9sTv for ; Wed, 2 Sep 2020 21:31:35 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727119AbgIBLbf (ORCPT ); Wed, 2 Sep 2020 07:31:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41048 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726892AbgIBL3j (ORCPT ); Wed, 2 Sep 2020 07:29:39 -0400 Received: from mail-wr1-x441.google.com (mail-wr1-x441.google.com [IPv6:2a00:1450:4864:20::441]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 99584C061260 for ; Wed, 2 Sep 2020 04:29:31 -0700 (PDT) Received: by mail-wr1-x441.google.com with SMTP id e16so4849982wrm.2 for ; Wed, 02 Sep 2020 04:29:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cumulusnetworks.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=akPfJNrj4KjH/LglWoRkFNBDUDP/QfPnKtDYjDA1e0o=; b=Uxb6bQWN2TGyn7kZ24wYSC+FgbuPoMK7369Xkm9W9vi2DehgkF5mgsWwmA+01z920l 5sdy1Qe0guSEDsSx1WN1ogRhnXy+E/lgzs2w1XX9n7KHlv2EinENgzxEUTzP/KeO38kt WsT1y/X2CJcgP6awQ640/vSB9vrZOCcgXVpj0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=akPfJNrj4KjH/LglWoRkFNBDUDP/QfPnKtDYjDA1e0o=; b=HOpDGusNHbCsoo0ZWmbPC0QYspk0A0kYDYXttwi5LdAqCvMg2U8qKtdDPzlwGUPnt7 DNh164Nb/kEmCHQmc/Pw4aaI8n4miZyz7n1TtASIYleP8UnKOU0I5/KRb8afEoS+swDA qLnP4WqFfSnlZO8Q3qlxxIy0etuWlkshF844WzaqLKUOdT+tnWginb8ZwSWPSpiHFWG7 nVsv3fMMjcQO13r7SlwjRu9zpUJGwQgSA6sgWyxHvMDaKMC9JjUzCp5z+9NuGlK0jPfe e9BQbrZQL6y+lM4UHVOL7O9RdxsyftFJFlV7n4NU5LB8HUggWqQseEA2EijKQaKBP9w1 jkGQ== X-Gm-Message-State: AOAM530lgfMQnFh8josknXRUKzwiRYrPMbqq55hXUEPPWKEZlGLKjywc nUOPtwrp871PQzM5nQPVAr2Ae6ZBVrl5ReMO X-Google-Smtp-Source: ABdhPJyMtquxS4bWH7ZyUqmFgEbfyqrcWdzXB2vkT8czNoS7e1cHWINgxPxzFKDGUbKXXz6fm79SWA== X-Received: by 2002:adf:df87:: with SMTP id z7mr6944867wrl.239.1599046169828; Wed, 02 Sep 2020 04:29:29 -0700 (PDT) Received: from localhost.localdomain (84-238-136-197.ip.btc-net.bg. [84.238.136.197]) by smtp.gmail.com with ESMTPSA id 5sm5985172wmz.22.2020.09.02.04.29.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Sep 2020 04:29:29 -0700 (PDT) From: Nikolay Aleksandrov To: netdev@vger.kernel.org Cc: roopa@nvidia.com, bridge@lists.linux-foundation.org, davem@davemloft.net, Nikolay Aleksandrov Subject: [PATCH net-next v2 15/15] net: bridge: mcast: destroy all entries via gc Date: Wed, 2 Sep 2020 14:25:29 +0300 Message-Id: <20200902112529.1570040-16-nikolay@cumulusnetworks.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> References: <20200902112529.1570040-1-nikolay@cumulusnetworks.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Since each entry type has timers that can be running simultaneously we need to make sure that entries are not freed before their timers have finished. In order to do that generalize the src gc work to mcast gc work and use a callback to free the entries (mdb, port group or src). Signed-off-by: Nikolay Aleksandrov --- net/bridge/br_multicast.c | 103 ++++++++++++++++++++++++++------------ net/bridge/br_private.h | 13 +++-- 2 files changed, 80 insertions(+), 36 deletions(-) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index db4b2621631c..f5fdd1e63f31 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -140,6 +140,29 @@ struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, return br_mdb_ip_get_rcu(br, &ip); } +static void br_multicast_destroy_mdb_entry(struct net_bridge_mcast_gc *gc) +{ + struct net_bridge_mdb_entry *mp; + + mp = container_of(gc, struct net_bridge_mdb_entry, mcast_gc); + WARN_ON(!hlist_unhashed(&mp->mdb_node)); + WARN_ON(mp->ports); + + del_timer_sync(&mp->timer); + kfree_rcu(mp, rcu); +} + +static void br_multicast_del_mdb_entry(struct net_bridge_mdb_entry *mp) +{ + struct net_bridge *br = mp->br; + + rhashtable_remove_fast(&br->mdb_hash_tbl, &mp->rhnode, + br_mdb_rht_params); + hlist_del_init_rcu(&mp->mdb_node); + hlist_add_head(&mp->mcast_gc.gc_node, &br->mcast_gc_list); + queue_work(system_long_wq, &br->mcast_gc_work); +} + static void br_multicast_group_expired(struct timer_list *t) { struct net_bridge_mdb_entry *mp = from_timer(mp, t, timer); @@ -153,15 +176,20 @@ static void br_multicast_group_expired(struct timer_list *t) if (mp->ports) goto out; + br_multicast_del_mdb_entry(mp); +out: + spin_unlock(&br->multicast_lock); +} - rhashtable_remove_fast(&br->mdb_hash_tbl, &mp->rhnode, - br_mdb_rht_params); - hlist_del_rcu(&mp->mdb_node); +static void br_multicast_destroy_group_src(struct net_bridge_mcast_gc *gc) +{ + struct net_bridge_group_src *src; - kfree_rcu(mp, rcu); + src = container_of(gc, struct net_bridge_group_src, mcast_gc); + WARN_ON(!hlist_unhashed(&src->node)); -out: - spin_unlock(&br->multicast_lock); + del_timer_sync(&src->timer); + kfree_rcu(src, rcu); } static void br_multicast_del_group_src(struct net_bridge_group_src *src) @@ -170,8 +198,21 @@ static void br_multicast_del_group_src(struct net_bridge_group_src *src) hlist_del_init_rcu(&src->node); src->pg->src_ents--; - hlist_add_head(&src->del_node, &br->src_gc_list); - queue_work(system_long_wq, &br->src_gc_work); + hlist_add_head(&src->mcast_gc.gc_node, &br->mcast_gc_list); + queue_work(system_long_wq, &br->mcast_gc_work); +} + +static void br_multicast_destroy_port_group(struct net_bridge_mcast_gc *gc) +{ + struct net_bridge_port_group *pg; + + pg = container_of(gc, struct net_bridge_port_group, mcast_gc); + WARN_ON(!hlist_unhashed(&pg->mglist)); + WARN_ON(!hlist_empty(&pg->src_list)); + + del_timer_sync(&pg->rexmit_timer); + del_timer_sync(&pg->timer); + kfree_rcu(pg, rcu); } void br_multicast_del_pg(struct net_bridge_mdb_entry *mp, @@ -184,12 +225,11 @@ void br_multicast_del_pg(struct net_bridge_mdb_entry *mp, rcu_assign_pointer(*pp, pg->next); hlist_del_init(&pg->mglist); - del_timer(&pg->timer); - del_timer(&pg->rexmit_timer); hlist_for_each_entry_safe(ent, tmp, &pg->src_list, node) br_multicast_del_group_src(ent); br_mdb_notify(br->dev, mp, pg, RTM_DELMDB); - kfree_rcu(pg, rcu); + hlist_add_head(&pg->mcast_gc.gc_node, &br->mcast_gc_list); + queue_work(system_long_wq, &br->mcast_gc_work); if (!mp->ports && !mp->host_joined && netif_running(br->dev)) mod_timer(&mp->timer, jiffies); @@ -560,6 +600,7 @@ struct net_bridge_mdb_entry *br_multicast_new_group(struct net_bridge *br, mp->br = br; mp->addr = *group; + mp->mcast_gc.destroy = br_multicast_destroy_mdb_entry; timer_setup(&mp->timer, br_multicast_group_expired, 0); err = rhashtable_lookup_insert_fast(&br->mdb_hash_tbl, &mp->rhnode, br_mdb_rht_params); @@ -642,6 +683,7 @@ br_multicast_new_group_src(struct net_bridge_port_group *pg, struct br_ip *src_i grp_src->pg = pg; grp_src->br = pg->port->br; grp_src->addr = *src_ip; + grp_src->mcast_gc.destroy = br_multicast_destroy_group_src; timer_setup(&grp_src->timer, br_multicast_group_src_expired, 0); hlist_add_head_rcu(&grp_src->node, &pg->src_list); @@ -671,6 +713,7 @@ struct net_bridge_port_group *br_multicast_new_port_group( p->filter_mode = MCAST_INCLUDE; else p->filter_mode = MCAST_EXCLUDE; + p->mcast_gc.destroy = br_multicast_destroy_port_group; INIT_HLIST_HEAD(&p->src_list); rcu_assign_pointer(p->next, next); timer_setup(&p->timer, br_multicast_port_group_expired, 0); @@ -2566,29 +2609,28 @@ static void br_ip6_multicast_query_expired(struct timer_list *t) } #endif -static void __grp_src_gc(struct hlist_head *head) +static void br_multicast_do_gc(struct hlist_head *head) { - struct net_bridge_group_src *ent; + struct net_bridge_mcast_gc *gcent; struct hlist_node *tmp; - hlist_for_each_entry_safe(ent, tmp, head, del_node) { - hlist_del_init(&ent->del_node); - del_timer_sync(&ent->timer); - kfree_rcu(ent, rcu); + hlist_for_each_entry_safe(gcent, tmp, head, gc_node) { + hlist_del_init(&gcent->gc_node); + gcent->destroy(gcent); } } -static void br_multicast_src_gc(struct work_struct *work) +static void br_multicast_gc(struct work_struct *work) { struct net_bridge *br = container_of(work, struct net_bridge, - src_gc_work); + mcast_gc_work); HLIST_HEAD(deleted_head); spin_lock_bh(&br->multicast_lock); - hlist_move_list(&br->src_gc_list, &deleted_head); + hlist_move_list(&br->mcast_gc_list, &deleted_head); spin_unlock_bh(&br->multicast_lock); - __grp_src_gc(&deleted_head); + br_multicast_do_gc(&deleted_head); } void br_multicast_init(struct net_bridge *br) @@ -2631,8 +2673,8 @@ void br_multicast_init(struct net_bridge *br) br_ip6_multicast_query_expired, 0); #endif INIT_HLIST_HEAD(&br->mdb_list); - INIT_HLIST_HEAD(&br->src_gc_list); - INIT_WORK(&br->src_gc_work, br_multicast_src_gc); + INIT_HLIST_HEAD(&br->mcast_gc_list); + INIT_WORK(&br->mcast_gc_work, br_multicast_gc); } static void br_ip4_multicast_join_snoopers(struct net_bridge *br) @@ -2740,18 +2782,13 @@ void br_multicast_dev_del(struct net_bridge *br) struct hlist_node *tmp; spin_lock_bh(&br->multicast_lock); - hlist_for_each_entry_safe(mp, tmp, &br->mdb_list, mdb_node) { - del_timer(&mp->timer); - rhashtable_remove_fast(&br->mdb_hash_tbl, &mp->rhnode, - br_mdb_rht_params); - hlist_del_rcu(&mp->mdb_node); - kfree_rcu(mp, rcu); - } - hlist_move_list(&br->src_gc_list, &deleted_head); + hlist_for_each_entry_safe(mp, tmp, &br->mdb_list, mdb_node) + br_multicast_del_mdb_entry(mp); + hlist_move_list(&br->mcast_gc_list, &deleted_head); spin_unlock_bh(&br->multicast_lock); - __grp_src_gc(&deleted_head); - cancel_work_sync(&br->src_gc_work); + br_multicast_do_gc(&deleted_head); + cancel_work_sync(&br->mcast_gc_work); rcu_barrier(); } diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index a18bd67dab34..478857563957 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -219,6 +219,11 @@ struct net_bridge_fdb_entry { #define BR_SGRP_F_DELETE BIT(0) #define BR_SGRP_F_SEND BIT(1) +struct net_bridge_mcast_gc { + struct hlist_node gc_node; + void (*destroy)(struct net_bridge_mcast_gc *gc); +}; + struct net_bridge_group_src { struct hlist_node node; @@ -229,7 +234,7 @@ struct net_bridge_group_src { struct timer_list timer; struct net_bridge *br; - struct hlist_node del_node; + struct net_bridge_mcast_gc mcast_gc; struct rcu_head rcu; }; @@ -248,6 +253,7 @@ struct net_bridge_port_group { struct timer_list rexmit_timer; struct hlist_node mglist; + struct net_bridge_mcast_gc mcast_gc; struct rcu_head rcu; }; @@ -261,6 +267,7 @@ struct net_bridge_mdb_entry { struct timer_list timer; struct hlist_node mdb_node; + struct net_bridge_mcast_gc mcast_gc; struct rcu_head rcu; }; @@ -434,7 +441,7 @@ struct net_bridge { struct rhashtable mdb_hash_tbl; - struct hlist_head src_gc_list; + struct hlist_head mcast_gc_list; struct hlist_head mdb_list; struct hlist_head router_list; @@ -448,7 +455,7 @@ struct net_bridge { struct bridge_mcast_own_query ip6_own_query; struct bridge_mcast_querier ip6_querier; #endif /* IS_ENABLED(CONFIG_IPV6) */ - struct work_struct src_gc_work; + struct work_struct mcast_gc_work; #endif struct timer_list hello_timer;