Keep a list of all port-VLANs that have been created within their
master VLAN. The list is rcu-safe and will be used for optimizing
the flood path.

Signed-off-by: Nikolay Aleksandrov <[email protected]>
---
 net/bridge/br_private.h |  2 ++
 net/bridge/br_vlan.c    | 11 +++++++++--
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index bda25f851342..b2a12b6298cb 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -210,6 +210,7 @@ enum {
  * @port_mcast_ctx: if MASTER flag unset, this is the per-port/vlan multicast
  *                  context
  * @msti: if MASTER flag set, this holds the VLANs MST instance
+ * @port_vlist: if MASTER flag set, this is the port-VLAN list
  * @vlist: sorted list of VLAN entries
  * @rcu: used for entry destruction
  *
@@ -244,6 +245,7 @@ struct net_bridge_vlan {
 
        u16                             msti;
 
+       struct list_head                port_vlist;
        struct list_head                vlist;
 
        struct rcu_head                 rcu;
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index bfedd13e3fd4..34d1df59d190 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -130,10 +130,12 @@ static void __vlan_add_list(struct net_bridge_vlan *v)
        struct list_head *headp, *hpos;
        struct net_bridge_vlan *vent;
 
-       if (br_vlan_is_master(v))
+       if (br_vlan_is_master(v)) {
                vg = br_vlan_group(v->br);
-       else
+       } else {
                vg = nbp_vlan_group(v->port);
+               list_add_rcu(&v->port_vlist, &v->brvlan->port_vlist);
+       }
 
        headp = &vg->vlan_list;
        list_for_each_prev(hpos, headp) {
@@ -147,6 +149,10 @@ static void __vlan_add_list(struct net_bridge_vlan *v)
 static void __vlan_del_list(struct net_bridge_vlan *v)
 {
        list_del_rcu(&v->vlist);
+       if (br_vlan_is_master(v))
+               WARN_ON(!list_empty(&v->port_vlist));
+       else
+               list_del_rcu(&v->port_vlist);
 }
 
 static int __vlan_vid_del(struct net_device *dev, struct net_bridge *br,
@@ -335,6 +341,7 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags,
                }
                br_multicast_ctx_init(br, v, &v->br_mcast_ctx);
                v->priv_flags |= BR_VLFLAG_GLOBAL_MCAST_ENABLED;
+               INIT_LIST_HEAD(&v->port_vlist);
        }
 
        /* Add the dev mac and count the vlan only if it's usable */
-- 
2.47.3


Reply via email to