]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: bridge: vlan: add global and per-port multicast context
authorNikolay Aleksandrov <nikolay@nvidia.com>
Mon, 19 Jul 2021 17:06:26 +0000 (20:06 +0300)
committerDavid S. Miller <davem@davemloft.net>
Tue, 20 Jul 2021 12:41:19 +0000 (05:41 -0700)
Add global and per-port vlan multicast context, only initialized but
still not used. No functional changes intended.

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/bridge/br_multicast.c
net/bridge/br_private.h
net/bridge/br_vlan.c

index 64145e48a0a5d48fc5714a13b722a3ef91077a2d..6f803f7892176a6a8365d2e1f4127adbd7496e14 100644 (file)
@@ -80,6 +80,7 @@ __br_multicast_add_group(struct net_bridge_mcast *brmctx,
                         bool blocked);
 static void br_multicast_find_del_pg(struct net_bridge *br,
                                     struct net_bridge_port_group *pg);
+static void __br_multicast_stop(struct net_bridge_mcast *brmctx);
 
 static struct net_bridge_port_group *
 br_sg_port_find(struct net_bridge *br,
@@ -1696,10 +1697,12 @@ static int br_mc_disabled_update(struct net_device *dev, bool value,
        return switchdev_port_attr_set(dev, &attr, extack);
 }
 
-static void br_multicast_port_ctx_init(struct net_bridge_port *port,
-                                      struct net_bridge_mcast_port *pmctx)
+void br_multicast_port_ctx_init(struct net_bridge_port *port,
+                               struct net_bridge_vlan *vlan,
+                               struct net_bridge_mcast_port *pmctx)
 {
        pmctx->port = port;
+       pmctx->vlan = vlan;
        pmctx->multicast_router = MDB_RTR_TYPE_TEMP_QUERY;
        timer_setup(&pmctx->ip4_mc_router_timer,
                    br_ip4_multicast_router_expired, 0);
@@ -1713,7 +1716,7 @@ static void br_multicast_port_ctx_init(struct net_bridge_port *port,
 #endif
 }
 
-static void br_multicast_port_ctx_deinit(struct net_bridge_mcast_port *pmctx)
+void br_multicast_port_ctx_deinit(struct net_bridge_mcast_port *pmctx)
 {
 #if IS_ENABLED(CONFIG_IPV6)
        del_timer_sync(&pmctx->ip6_mc_router_timer);
@@ -1726,7 +1729,7 @@ int br_multicast_add_port(struct net_bridge_port *port)
        int err;
 
        port->multicast_eht_hosts_limit = BR_MCAST_DEFAULT_EHT_HOSTS_LIMIT;
-       br_multicast_port_ctx_init(port, &port->multicast_ctx);
+       br_multicast_port_ctx_init(port, NULL, &port->multicast_ctx);
 
        err = br_mc_disabled_update(port->dev,
                                    br_opt_get(port->br,
@@ -3571,48 +3574,63 @@ static void br_multicast_gc_work(struct work_struct *work)
        br_multicast_gc(&deleted_head);
 }
 
-void br_multicast_init(struct net_bridge *br)
+void br_multicast_ctx_init(struct net_bridge *br,
+                          struct net_bridge_vlan *vlan,
+                          struct net_bridge_mcast *brmctx)
 {
-       br->hash_max = BR_MULTICAST_DEFAULT_HASH_MAX;
+       brmctx->br = br;
+       brmctx->vlan = vlan;
+       brmctx->multicast_router = MDB_RTR_TYPE_TEMP_QUERY;
+       brmctx->multicast_last_member_count = 2;
+       brmctx->multicast_startup_query_count = 2;
 
-       br->multicast_ctx.br = br;
-       br->multicast_ctx.multicast_router = MDB_RTR_TYPE_TEMP_QUERY;
-       br->multicast_ctx.multicast_last_member_count = 2;
-       br->multicast_ctx.multicast_startup_query_count = 2;
-
-       br->multicast_ctx.multicast_last_member_interval = HZ;
-       br->multicast_ctx.multicast_query_response_interval = 10 * HZ;
-       br->multicast_ctx.multicast_startup_query_interval = 125 * HZ / 4;
-       br->multicast_ctx.multicast_query_interval = 125 * HZ;
-       br->multicast_ctx.multicast_querier_interval = 255 * HZ;
-       br->multicast_ctx.multicast_membership_interval = 260 * HZ;
-
-       br->multicast_ctx.ip4_other_query.delay_time = 0;
-       br->multicast_ctx.ip4_querier.port = NULL;
-       br->multicast_ctx.multicast_igmp_version = 2;
+       brmctx->multicast_last_member_interval = HZ;
+       brmctx->multicast_query_response_interval = 10 * HZ;
+       brmctx->multicast_startup_query_interval = 125 * HZ / 4;
+       brmctx->multicast_query_interval = 125 * HZ;
+       brmctx->multicast_querier_interval = 255 * HZ;
+       brmctx->multicast_membership_interval = 260 * HZ;
+
+       brmctx->ip4_other_query.delay_time = 0;
+       brmctx->ip4_querier.port = NULL;
+       brmctx->multicast_igmp_version = 2;
 #if IS_ENABLED(CONFIG_IPV6)
-       br->multicast_ctx.multicast_mld_version = 1;
-       br->multicast_ctx.ip6_other_query.delay_time = 0;
-       br->multicast_ctx.ip6_querier.port = NULL;
+       brmctx->multicast_mld_version = 1;
+       brmctx->ip6_other_query.delay_time = 0;
+       brmctx->ip6_querier.port = NULL;
 #endif
-       br_opt_toggle(br, BROPT_MULTICAST_ENABLED, true);
-       br_opt_toggle(br, BROPT_HAS_IPV6_ADDR, true);
 
-       spin_lock_init(&br->multicast_lock);
-       timer_setup(&br->multicast_ctx.ip4_mc_router_timer,
+       timer_setup(&brmctx->ip4_mc_router_timer,
                    br_ip4_multicast_local_router_expired, 0);
-       timer_setup(&br->multicast_ctx.ip4_other_query.timer,
+       timer_setup(&brmctx->ip4_other_query.timer,
                    br_ip4_multicast_querier_expired, 0);
-       timer_setup(&br->multicast_ctx.ip4_own_query.timer,
+       timer_setup(&brmctx->ip4_own_query.timer,
                    br_ip4_multicast_query_expired, 0);
 #if IS_ENABLED(CONFIG_IPV6)
-       timer_setup(&br->multicast_ctx.ip6_mc_router_timer,
+       timer_setup(&brmctx->ip6_mc_router_timer,
                    br_ip6_multicast_local_router_expired, 0);
-       timer_setup(&br->multicast_ctx.ip6_other_query.timer,
+       timer_setup(&brmctx->ip6_other_query.timer,
                    br_ip6_multicast_querier_expired, 0);
-       timer_setup(&br->multicast_ctx.ip6_own_query.timer,
+       timer_setup(&brmctx->ip6_own_query.timer,
                    br_ip6_multicast_query_expired, 0);
 #endif
+}
+
+void br_multicast_ctx_deinit(struct net_bridge_mcast *brmctx)
+{
+       __br_multicast_stop(brmctx);
+}
+
+void br_multicast_init(struct net_bridge *br)
+{
+       br->hash_max = BR_MULTICAST_DEFAULT_HASH_MAX;
+
+       br_multicast_ctx_init(br, NULL, &br->multicast_ctx);
+
+       br_opt_toggle(br, BROPT_MULTICAST_ENABLED, true);
+       br_opt_toggle(br, BROPT_HAS_IPV6_ADDR, true);
+
+       spin_lock_init(&br->multicast_lock);
        INIT_HLIST_HEAD(&br->mdb_list);
        INIT_HLIST_HEAD(&br->mcast_gc_list);
        INIT_WORK(&br->mcast_gc_work, br_multicast_gc_work);
@@ -3699,18 +3717,23 @@ void br_multicast_open(struct net_bridge *br)
 #endif
 }
 
-void br_multicast_stop(struct net_bridge *br)
+static void __br_multicast_stop(struct net_bridge_mcast *brmctx)
 {
-       del_timer_sync(&br->multicast_ctx.ip4_mc_router_timer);
-       del_timer_sync(&br->multicast_ctx.ip4_other_query.timer);
-       del_timer_sync(&br->multicast_ctx.ip4_own_query.timer);
+       del_timer_sync(&brmctx->ip4_mc_router_timer);
+       del_timer_sync(&brmctx->ip4_other_query.timer);
+       del_timer_sync(&brmctx->ip4_own_query.timer);
 #if IS_ENABLED(CONFIG_IPV6)
-       del_timer_sync(&br->multicast_ctx.ip6_mc_router_timer);
-       del_timer_sync(&br->multicast_ctx.ip6_other_query.timer);
-       del_timer_sync(&br->multicast_ctx.ip6_own_query.timer);
+       del_timer_sync(&brmctx->ip6_mc_router_timer);
+       del_timer_sync(&brmctx->ip6_other_query.timer);
+       del_timer_sync(&brmctx->ip6_own_query.timer);
 #endif
 }
 
+void br_multicast_stop(struct net_bridge *br)
+{
+       __br_multicast_stop(&br->multicast_ctx);
+}
+
 void br_multicast_dev_del(struct net_bridge *br)
 {
        struct net_bridge_mdb_entry *mp;
@@ -3723,6 +3746,7 @@ void br_multicast_dev_del(struct net_bridge *br)
        hlist_move_list(&br->mcast_gc_list, &deleted_head);
        spin_unlock_bh(&br->multicast_lock);
 
+       br_multicast_ctx_deinit(&br->multicast_ctx);
        br_multicast_gc(&deleted_head);
        cancel_work_sync(&br->mcast_gc_work);
 
index eea582ead40a50d02da0a01acdce05684919f96f..5762e5e86d6cbe3066dddc0e01b35387bb4bfa8d 100644 (file)
@@ -93,6 +93,7 @@ struct bridge_mcast_stats {
 struct net_bridge_mcast_port {
 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
        struct net_bridge_port          *port;
+       struct net_bridge_vlan          *vlan;
 
        struct bridge_mcast_own_query   ip4_own_query;
        struct timer_list               ip4_mc_router_timer;
@@ -110,6 +111,7 @@ struct net_bridge_mcast_port {
 struct net_bridge_mcast {
 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
        struct net_bridge               *br;
+       struct net_bridge_vlan          *vlan;
 
        u32                             multicast_last_member_count;
        u32                             multicast_startup_query_count;
@@ -165,6 +167,9 @@ enum {
  * @refcnt: if MASTER flag set, this is bumped for each port referencing it
  * @brvlan: if MASTER flag unset, this points to the global per-VLAN context
  *          for this VLAN entry
+ * @br_mcast_ctx: if MASTER flag set, this is the global vlan multicast context
+ * @port_mcast_ctx: if MASTER flag unset, this is the per-port/vlan multicast
+ *                  context
  * @vlist: sorted list of VLAN entries
  * @rcu: used for entry destruction
  *
@@ -192,6 +197,11 @@ struct net_bridge_vlan {
 
        struct br_tunnel_info           tinfo;
 
+       union {
+               struct net_bridge_mcast         br_mcast_ctx;
+               struct net_bridge_mcast_port    port_mcast_ctx;
+       };
+
        struct list_head                vlist;
 
        struct rcu_head                 rcu;
@@ -883,6 +893,14 @@ struct net_bridge_group_src *
 br_multicast_find_group_src(struct net_bridge_port_group *pg, struct br_ip *ip);
 void br_multicast_del_group_src(struct net_bridge_group_src *src,
                                bool fastleave);
+void br_multicast_ctx_init(struct net_bridge *br,
+                          struct net_bridge_vlan *vlan,
+                          struct net_bridge_mcast *brmctx);
+void br_multicast_ctx_deinit(struct net_bridge_mcast *brmctx);
+void br_multicast_port_ctx_init(struct net_bridge_port *port,
+                               struct net_bridge_vlan *vlan,
+                               struct net_bridge_mcast_port *pmctx);
+void br_multicast_port_ctx_deinit(struct net_bridge_mcast_port *pmctx);
 
 static inline bool br_group_is_l2(const struct br_ip *group)
 {
@@ -1157,6 +1175,26 @@ static inline int br_multicast_igmp_type(const struct sk_buff *skb)
 {
        return 0;
 }
+
+static inline void br_multicast_ctx_init(struct net_bridge *br,
+                                        struct net_bridge_vlan *vlan,
+                                        struct net_bridge_mcast *brmctx)
+{
+}
+
+static inline void br_multicast_ctx_deinit(struct net_bridge_mcast *brmctx)
+{
+}
+
+static inline void br_multicast_port_ctx_init(struct net_bridge_port *port,
+                                             struct net_bridge_vlan *vlan,
+                                             struct net_bridge_mcast_port *pmctx)
+{
+}
+
+static inline void br_multicast_port_ctx_deinit(struct net_bridge_mcast_port *pmctx)
+{
+}
 #endif
 
 /* br_vlan.c */
index a08e9f19300939c6a4d398e64accf41f61ac4cc7..e7b7bb0a005bc7de425268f067b30b7cd998a66b 100644 (file)
@@ -190,6 +190,7 @@ static void br_vlan_put_master(struct net_bridge_vlan *masterv)
                rhashtable_remove_fast(&vg->vlan_hash,
                                       &masterv->vnode, br_vlan_rht_params);
                __vlan_del_list(masterv);
+               br_multicast_ctx_deinit(&masterv->br_mcast_ctx);
                call_rcu(&masterv->rcu, br_master_vlan_rcu_free);
        }
 }
@@ -280,10 +281,12 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags,
                } else {
                        v->stats = masterv->stats;
                }
+               br_multicast_port_ctx_init(p, v, &v->port_mcast_ctx);
        } else {
                err = br_switchdev_port_vlan_add(dev, v->vid, flags, extack);
                if (err && err != -EOPNOTSUPP)
                        goto out;
+               br_multicast_ctx_init(br, v, &v->br_mcast_ctx);
        }
 
        /* Add the dev mac and count the vlan only if it's usable */
@@ -374,6 +377,7 @@ static int __vlan_del(struct net_bridge_vlan *v)
                                       br_vlan_rht_params);
                __vlan_del_list(v);
                nbp_vlan_set_vlan_dev_state(p, v->vid);
+               br_multicast_port_ctx_deinit(&v->port_mcast_ctx);
                call_rcu(&v->rcu, nbp_vlan_rcu_free);
        }