1457c8996SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2243a2e63SVlad Yasevich #include <linux/kernel.h> 3243a2e63SVlad Yasevich #include <linux/netdevice.h> 4243a2e63SVlad Yasevich #include <linux/rtnetlink.h> 5243a2e63SVlad Yasevich #include <linux/slab.h> 67f109539SScott Feldman #include <net/switchdev.h> 7243a2e63SVlad Yasevich 8243a2e63SVlad Yasevich #include "br_private.h" 9efa5356bSRoopa Prabhu #include "br_private_tunnel.h" 10243a2e63SVlad Yasevich 1180900acdSMike Manning static void nbp_vlan_set_vlan_dev_state(struct net_bridge_port *p, u16 vid); 1280900acdSMike Manning 132594e906SNikolay Aleksandrov static inline int br_vlan_cmp(struct rhashtable_compare_arg *arg, 142594e906SNikolay Aleksandrov const void *ptr) 15552406c4SVlad Yasevich { 162594e906SNikolay Aleksandrov const struct net_bridge_vlan *vle = ptr; 172594e906SNikolay Aleksandrov u16 vid = *(u16 *)arg->key; 182594e906SNikolay Aleksandrov 192594e906SNikolay Aleksandrov return vle->vid != vid; 202594e906SNikolay Aleksandrov } 212594e906SNikolay Aleksandrov 222594e906SNikolay Aleksandrov static const struct rhashtable_params br_vlan_rht_params = { 232594e906SNikolay Aleksandrov .head_offset = offsetof(struct net_bridge_vlan, vnode), 242594e906SNikolay Aleksandrov .key_offset = offsetof(struct net_bridge_vlan, vid), 252594e906SNikolay Aleksandrov .key_len = sizeof(u16), 268af78b64SNikolay Aleksandrov .nelem_hint = 3, 272594e906SNikolay Aleksandrov .max_size = VLAN_N_VID, 282594e906SNikolay Aleksandrov .obj_cmpfn = br_vlan_cmp, 292594e906SNikolay Aleksandrov .automatic_shrinking = true, 302594e906SNikolay Aleksandrov }; 312594e906SNikolay Aleksandrov 322594e906SNikolay Aleksandrov static struct net_bridge_vlan *br_vlan_lookup(struct rhashtable *tbl, u16 vid) 332594e906SNikolay Aleksandrov { 342594e906SNikolay Aleksandrov return rhashtable_lookup_fast(tbl, &vid, br_vlan_rht_params); 352594e906SNikolay Aleksandrov } 362594e906SNikolay Aleksandrov 37f418af63SNikolay Aleksandrov static bool __vlan_add_pvid(struct net_bridge_vlan_group *vg, u16 vid) 382594e906SNikolay Aleksandrov { 3977751ee8SNikolay Aleksandrov if (vg->pvid == vid) 40f418af63SNikolay Aleksandrov return false; 41552406c4SVlad Yasevich 42552406c4SVlad Yasevich smp_wmb(); 4377751ee8SNikolay Aleksandrov vg->pvid = vid; 44f418af63SNikolay Aleksandrov 45f418af63SNikolay Aleksandrov return true; 46552406c4SVlad Yasevich } 47552406c4SVlad Yasevich 48f418af63SNikolay Aleksandrov static bool __vlan_delete_pvid(struct net_bridge_vlan_group *vg, u16 vid) 49552406c4SVlad Yasevich { 5077751ee8SNikolay Aleksandrov if (vg->pvid != vid) 51f418af63SNikolay Aleksandrov return false; 52552406c4SVlad Yasevich 53552406c4SVlad Yasevich smp_wmb(); 5477751ee8SNikolay Aleksandrov vg->pvid = 0; 55f418af63SNikolay Aleksandrov 56f418af63SNikolay Aleksandrov return true; 57552406c4SVlad Yasevich } 58552406c4SVlad Yasevich 59f418af63SNikolay Aleksandrov /* return true if anything changed, false otherwise */ 60f418af63SNikolay Aleksandrov static bool __vlan_add_flags(struct net_bridge_vlan *v, u16 flags) 6135e03f3aSVlad Yasevich { 6277751ee8SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 63f418af63SNikolay Aleksandrov u16 old_flags = v->flags; 64f418af63SNikolay Aleksandrov bool ret; 6577751ee8SNikolay Aleksandrov 662594e906SNikolay Aleksandrov if (br_vlan_is_master(v)) 67907b1e6eSNikolay Aleksandrov vg = br_vlan_group(v->br); 68635126b7SVlad Yasevich else 69907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(v->port); 7077751ee8SNikolay Aleksandrov 7177751ee8SNikolay Aleksandrov if (flags & BRIDGE_VLAN_INFO_PVID) 72f418af63SNikolay Aleksandrov ret = __vlan_add_pvid(vg, v->vid); 732594e906SNikolay Aleksandrov else 74f418af63SNikolay Aleksandrov ret = __vlan_delete_pvid(vg, v->vid); 7535e03f3aSVlad Yasevich 7635e03f3aSVlad Yasevich if (flags & BRIDGE_VLAN_INFO_UNTAGGED) 772594e906SNikolay Aleksandrov v->flags |= BRIDGE_VLAN_INFO_UNTAGGED; 78635126b7SVlad Yasevich else 792594e906SNikolay Aleksandrov v->flags &= ~BRIDGE_VLAN_INFO_UNTAGGED; 80f418af63SNikolay Aleksandrov 81f418af63SNikolay Aleksandrov return ret || !!(old_flags ^ v->flags); 8235e03f3aSVlad Yasevich } 8335e03f3aSVlad Yasevich 847f109539SScott Feldman static int __vlan_vid_add(struct net_device *dev, struct net_bridge *br, 8527973793SIdo Schimmel struct net_bridge_vlan *v, u16 flags, 8627973793SIdo Schimmel struct netlink_ext_ack *extack) 877f109539SScott Feldman { 880944d6b5SJiri Pirko int err; 897f109539SScott Feldman 900944d6b5SJiri Pirko /* Try switchdev op first. In case it is not supported, fallback to 910944d6b5SJiri Pirko * 8021q add. 920944d6b5SJiri Pirko */ 9327973793SIdo Schimmel err = br_switchdev_port_vlan_add(dev, v->vid, flags, extack); 947f109539SScott Feldman if (err == -EOPNOTSUPP) 9527973793SIdo Schimmel return vlan_vid_add(dev, br->vlan_proto, v->vid); 9627973793SIdo Schimmel v->priv_flags |= BR_VLFLAG_ADDED_BY_SWITCHDEV; 977f109539SScott Feldman return err; 987f109539SScott Feldman } 997f109539SScott Feldman 1002594e906SNikolay Aleksandrov static void __vlan_add_list(struct net_bridge_vlan *v) 101243a2e63SVlad Yasevich { 102907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 1032594e906SNikolay Aleksandrov struct list_head *headp, *hpos; 1042594e906SNikolay Aleksandrov struct net_bridge_vlan *vent; 105243a2e63SVlad Yasevich 106907b1e6eSNikolay Aleksandrov if (br_vlan_is_master(v)) 107907b1e6eSNikolay Aleksandrov vg = br_vlan_group(v->br); 108907b1e6eSNikolay Aleksandrov else 109907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(v->port); 110907b1e6eSNikolay Aleksandrov 111907b1e6eSNikolay Aleksandrov headp = &vg->vlan_list; 1122594e906SNikolay Aleksandrov list_for_each_prev(hpos, headp) { 1132594e906SNikolay Aleksandrov vent = list_entry(hpos, struct net_bridge_vlan, vlist); 1142594e906SNikolay Aleksandrov if (v->vid < vent->vid) 1152594e906SNikolay Aleksandrov continue; 1162594e906SNikolay Aleksandrov else 1172594e906SNikolay Aleksandrov break; 1182594e906SNikolay Aleksandrov } 119586c2b57SNikolay Aleksandrov list_add_rcu(&v->vlist, hpos); 120552406c4SVlad Yasevich } 121243a2e63SVlad Yasevich 1222594e906SNikolay Aleksandrov static void __vlan_del_list(struct net_bridge_vlan *v) 1232594e906SNikolay Aleksandrov { 124586c2b57SNikolay Aleksandrov list_del_rcu(&v->vlist); 125243a2e63SVlad Yasevich } 126243a2e63SVlad Yasevich 127bf361ad3SVivien Didelot static int __vlan_vid_del(struct net_device *dev, struct net_bridge *br, 12827973793SIdo Schimmel const struct net_bridge_vlan *v) 1297f109539SScott Feldman { 1300944d6b5SJiri Pirko int err; 1317f109539SScott Feldman 1320944d6b5SJiri Pirko /* Try switchdev op first. In case it is not supported, fallback to 1330944d6b5SJiri Pirko * 8021q del. 1340944d6b5SJiri Pirko */ 13527973793SIdo Schimmel err = br_switchdev_port_vlan_del(dev, v->vid); 13627973793SIdo Schimmel if (!(v->priv_flags & BR_VLFLAG_ADDED_BY_SWITCHDEV)) 13727973793SIdo Schimmel vlan_vid_del(dev, br->vlan_proto, v->vid); 13827973793SIdo Schimmel return err == -EOPNOTSUPP ? 0 : err; 1397f109539SScott Feldman } 1407f109539SScott Feldman 141f8ed289fSNikolay Aleksandrov /* Returns a master vlan, if it didn't exist it gets created. In all cases a 142f8ed289fSNikolay Aleksandrov * a reference is taken to the master vlan before returning. 143f8ed289fSNikolay Aleksandrov */ 144169327d5SPetr Machata static struct net_bridge_vlan * 145169327d5SPetr Machata br_vlan_get_master(struct net_bridge *br, u16 vid, 146169327d5SPetr Machata struct netlink_ext_ack *extack) 147f8ed289fSNikolay Aleksandrov { 148907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 149f8ed289fSNikolay Aleksandrov struct net_bridge_vlan *masterv; 150f8ed289fSNikolay Aleksandrov 151907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 152907b1e6eSNikolay Aleksandrov masterv = br_vlan_find(vg, vid); 153f8ed289fSNikolay Aleksandrov if (!masterv) { 154f418af63SNikolay Aleksandrov bool changed; 155f418af63SNikolay Aleksandrov 156f8ed289fSNikolay Aleksandrov /* missing global ctx, create it now */ 157169327d5SPetr Machata if (br_vlan_add(br, vid, 0, &changed, extack)) 158f8ed289fSNikolay Aleksandrov return NULL; 159907b1e6eSNikolay Aleksandrov masterv = br_vlan_find(vg, vid); 160f8ed289fSNikolay Aleksandrov if (WARN_ON(!masterv)) 161f8ed289fSNikolay Aleksandrov return NULL; 1620e5a82efSIdo Schimmel refcount_set(&masterv->refcnt, 1); 1630e5a82efSIdo Schimmel return masterv; 164f8ed289fSNikolay Aleksandrov } 16525127759SReshetova, Elena refcount_inc(&masterv->refcnt); 166f8ed289fSNikolay Aleksandrov 167f8ed289fSNikolay Aleksandrov return masterv; 168f8ed289fSNikolay Aleksandrov } 169f8ed289fSNikolay Aleksandrov 1706dada9b1SNikolay Aleksandrov static void br_master_vlan_rcu_free(struct rcu_head *rcu) 1716dada9b1SNikolay Aleksandrov { 1726dada9b1SNikolay Aleksandrov struct net_bridge_vlan *v; 1736dada9b1SNikolay Aleksandrov 1746dada9b1SNikolay Aleksandrov v = container_of(rcu, struct net_bridge_vlan, rcu); 1756dada9b1SNikolay Aleksandrov WARN_ON(!br_vlan_is_master(v)); 1766dada9b1SNikolay Aleksandrov free_percpu(v->stats); 1776dada9b1SNikolay Aleksandrov v->stats = NULL; 1786dada9b1SNikolay Aleksandrov kfree(v); 1796dada9b1SNikolay Aleksandrov } 1806dada9b1SNikolay Aleksandrov 181f8ed289fSNikolay Aleksandrov static void br_vlan_put_master(struct net_bridge_vlan *masterv) 182f8ed289fSNikolay Aleksandrov { 183907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 184907b1e6eSNikolay Aleksandrov 185f8ed289fSNikolay Aleksandrov if (!br_vlan_is_master(masterv)) 186f8ed289fSNikolay Aleksandrov return; 187f8ed289fSNikolay Aleksandrov 188907b1e6eSNikolay Aleksandrov vg = br_vlan_group(masterv->br); 18925127759SReshetova, Elena if (refcount_dec_and_test(&masterv->refcnt)) { 190907b1e6eSNikolay Aleksandrov rhashtable_remove_fast(&vg->vlan_hash, 191f8ed289fSNikolay Aleksandrov &masterv->vnode, br_vlan_rht_params); 192f8ed289fSNikolay Aleksandrov __vlan_del_list(masterv); 1936dada9b1SNikolay Aleksandrov call_rcu(&masterv->rcu, br_master_vlan_rcu_free); 194f8ed289fSNikolay Aleksandrov } 195f8ed289fSNikolay Aleksandrov } 196f8ed289fSNikolay Aleksandrov 1979163a0fcSNikolay Aleksandrov static void nbp_vlan_rcu_free(struct rcu_head *rcu) 1989163a0fcSNikolay Aleksandrov { 1999163a0fcSNikolay Aleksandrov struct net_bridge_vlan *v; 2009163a0fcSNikolay Aleksandrov 2019163a0fcSNikolay Aleksandrov v = container_of(rcu, struct net_bridge_vlan, rcu); 2029163a0fcSNikolay Aleksandrov WARN_ON(br_vlan_is_master(v)); 2039163a0fcSNikolay Aleksandrov /* if we had per-port stats configured then free them here */ 2049d332e69SNikolay Aleksandrov if (v->priv_flags & BR_VLFLAG_PER_PORT_STATS) 2059163a0fcSNikolay Aleksandrov free_percpu(v->stats); 2069163a0fcSNikolay Aleksandrov v->stats = NULL; 2079163a0fcSNikolay Aleksandrov kfree(v); 2089163a0fcSNikolay Aleksandrov } 2099163a0fcSNikolay Aleksandrov 2102594e906SNikolay Aleksandrov /* This is the shared VLAN add function which works for both ports and bridge 2112594e906SNikolay Aleksandrov * devices. There are four possible calls to this function in terms of the 2122594e906SNikolay Aleksandrov * vlan entry type: 2132594e906SNikolay Aleksandrov * 1. vlan is being added on a port (no master flags, global entry exists) 214ddd611d3SIdo Schimmel * 2. vlan is being added on a bridge (both master and brentry flags) 2152594e906SNikolay Aleksandrov * 3. vlan is being added on a port, but a global entry didn't exist which 216ddd611d3SIdo Schimmel * is being created right now (master flag set, brentry flag unset), the 2172594e906SNikolay Aleksandrov * global entry is used for global per-vlan features, but not for filtering 218ddd611d3SIdo Schimmel * 4. same as 3 but with both master and brentry flags set so the entry 2192594e906SNikolay Aleksandrov * will be used for filtering in both the port and the bridge 2202594e906SNikolay Aleksandrov */ 221169327d5SPetr Machata static int __vlan_add(struct net_bridge_vlan *v, u16 flags, 222169327d5SPetr Machata struct netlink_ext_ack *extack) 223243a2e63SVlad Yasevich { 2242594e906SNikolay Aleksandrov struct net_bridge_vlan *masterv = NULL; 2252594e906SNikolay Aleksandrov struct net_bridge_port *p = NULL; 2266be144f6SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 2272594e906SNikolay Aleksandrov struct net_device *dev; 2282594e906SNikolay Aleksandrov struct net_bridge *br; 229bf361ad3SVivien Didelot int err; 230bf361ad3SVivien Didelot 2312594e906SNikolay Aleksandrov if (br_vlan_is_master(v)) { 2322594e906SNikolay Aleksandrov br = v->br; 2332594e906SNikolay Aleksandrov dev = br->dev; 234907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 2352594e906SNikolay Aleksandrov } else { 2362594e906SNikolay Aleksandrov p = v->port; 2372594e906SNikolay Aleksandrov br = p->br; 2382594e906SNikolay Aleksandrov dev = p->dev; 239907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 2402594e906SNikolay Aleksandrov } 2412594e906SNikolay Aleksandrov 2422594e906SNikolay Aleksandrov if (p) { 2432594e906SNikolay Aleksandrov /* Add VLAN to the device filter if it is supported. 2442594e906SNikolay Aleksandrov * This ensures tagged traffic enters the bridge when 2452594e906SNikolay Aleksandrov * promiscuous mode is disabled by br_manage_promisc(). 2462594e906SNikolay Aleksandrov */ 24727973793SIdo Schimmel err = __vlan_vid_add(dev, br, v, flags, extack); 248bf361ad3SVivien Didelot if (err) 2492594e906SNikolay Aleksandrov goto out; 2502594e906SNikolay Aleksandrov 2512594e906SNikolay Aleksandrov /* need to work on the master vlan too */ 2522594e906SNikolay Aleksandrov if (flags & BRIDGE_VLAN_INFO_MASTER) { 253f418af63SNikolay Aleksandrov bool changed; 254f418af63SNikolay Aleksandrov 255f418af63SNikolay Aleksandrov err = br_vlan_add(br, v->vid, 256f418af63SNikolay Aleksandrov flags | BRIDGE_VLAN_INFO_BRENTRY, 257169327d5SPetr Machata &changed, extack); 2582594e906SNikolay Aleksandrov if (err) 2592594e906SNikolay Aleksandrov goto out_filt; 2602594e906SNikolay Aleksandrov } 2612594e906SNikolay Aleksandrov 262169327d5SPetr Machata masterv = br_vlan_get_master(br, v->vid, extack); 263f8ed289fSNikolay Aleksandrov if (!masterv) 2642594e906SNikolay Aleksandrov goto out_filt; 2652594e906SNikolay Aleksandrov v->brvlan = masterv; 2669163a0fcSNikolay Aleksandrov if (br_opt_get(br, BROPT_VLAN_STATS_PER_PORT)) { 2679163a0fcSNikolay Aleksandrov v->stats = netdev_alloc_pcpu_stats(struct br_vlan_stats); 2689163a0fcSNikolay Aleksandrov if (!v->stats) { 2699163a0fcSNikolay Aleksandrov err = -ENOMEM; 2709163a0fcSNikolay Aleksandrov goto out_filt; 2719163a0fcSNikolay Aleksandrov } 2729d332e69SNikolay Aleksandrov v->priv_flags |= BR_VLFLAG_PER_PORT_STATS; 2739163a0fcSNikolay Aleksandrov } else { 2746dada9b1SNikolay Aleksandrov v->stats = masterv->stats; 2759163a0fcSNikolay Aleksandrov } 2769c86ce2cSPetr Machata } else { 277169327d5SPetr Machata err = br_switchdev_port_vlan_add(dev, v->vid, flags, extack); 2789c86ce2cSPetr Machata if (err && err != -EOPNOTSUPP) 2799c86ce2cSPetr Machata goto out; 2802594e906SNikolay Aleksandrov } 2812594e906SNikolay Aleksandrov 2826be144f6SNikolay Aleksandrov /* Add the dev mac and count the vlan only if it's usable */ 2832594e906SNikolay Aleksandrov if (br_vlan_should_use(v)) { 2842594e906SNikolay Aleksandrov err = br_fdb_insert(br, p, dev->dev_addr, v->vid); 2852594e906SNikolay Aleksandrov if (err) { 2862594e906SNikolay Aleksandrov br_err(br, "failed insert local address into bridge forwarding table\n"); 2872594e906SNikolay Aleksandrov goto out_filt; 2882594e906SNikolay Aleksandrov } 2896be144f6SNikolay Aleksandrov vg->num_vlans++; 2902594e906SNikolay Aleksandrov } 2912594e906SNikolay Aleksandrov 2926be144f6SNikolay Aleksandrov err = rhashtable_lookup_insert_fast(&vg->vlan_hash, &v->vnode, 2936be144f6SNikolay Aleksandrov br_vlan_rht_params); 2942594e906SNikolay Aleksandrov if (err) 2952594e906SNikolay Aleksandrov goto out_fdb_insert; 2962594e906SNikolay Aleksandrov 2972594e906SNikolay Aleksandrov __vlan_add_list(v); 2982594e906SNikolay Aleksandrov __vlan_add_flags(v, flags); 29980900acdSMike Manning 30080900acdSMike Manning if (p) 30180900acdSMike Manning nbp_vlan_set_vlan_dev_state(p, v->vid); 3022594e906SNikolay Aleksandrov out: 3032594e906SNikolay Aleksandrov return err; 3042594e906SNikolay Aleksandrov 3052594e906SNikolay Aleksandrov out_fdb_insert: 3066be144f6SNikolay Aleksandrov if (br_vlan_should_use(v)) { 3076be144f6SNikolay Aleksandrov br_fdb_find_delete_local(br, p, dev->dev_addr, v->vid); 3086be144f6SNikolay Aleksandrov vg->num_vlans--; 3096be144f6SNikolay Aleksandrov } 3102594e906SNikolay Aleksandrov 3112594e906SNikolay Aleksandrov out_filt: 3122594e906SNikolay Aleksandrov if (p) { 31327973793SIdo Schimmel __vlan_vid_del(dev, br, v); 3142594e906SNikolay Aleksandrov if (masterv) { 3151a3aea25SLi RongQing if (v->stats && masterv->stats != v->stats) 3161a3aea25SLi RongQing free_percpu(v->stats); 3171a3aea25SLi RongQing v->stats = NULL; 3181a3aea25SLi RongQing 319f8ed289fSNikolay Aleksandrov br_vlan_put_master(masterv); 3202594e906SNikolay Aleksandrov v->brvlan = NULL; 3212594e906SNikolay Aleksandrov } 3229c86ce2cSPetr Machata } else { 3239c86ce2cSPetr Machata br_switchdev_port_vlan_del(dev, v->vid); 3242594e906SNikolay Aleksandrov } 3252594e906SNikolay Aleksandrov 3262594e906SNikolay Aleksandrov goto out; 3272594e906SNikolay Aleksandrov } 3282594e906SNikolay Aleksandrov 3292594e906SNikolay Aleksandrov static int __vlan_del(struct net_bridge_vlan *v) 3302594e906SNikolay Aleksandrov { 3312594e906SNikolay Aleksandrov struct net_bridge_vlan *masterv = v; 33277751ee8SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 3332594e906SNikolay Aleksandrov struct net_bridge_port *p = NULL; 3342594e906SNikolay Aleksandrov int err = 0; 3352594e906SNikolay Aleksandrov 3362594e906SNikolay Aleksandrov if (br_vlan_is_master(v)) { 337907b1e6eSNikolay Aleksandrov vg = br_vlan_group(v->br); 3382594e906SNikolay Aleksandrov } else { 3392594e906SNikolay Aleksandrov p = v->port; 340907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(v->port); 3412594e906SNikolay Aleksandrov masterv = v->brvlan; 3422594e906SNikolay Aleksandrov } 3432594e906SNikolay Aleksandrov 34477751ee8SNikolay Aleksandrov __vlan_delete_pvid(vg, v->vid); 3452594e906SNikolay Aleksandrov if (p) { 34627973793SIdo Schimmel err = __vlan_vid_del(p->dev, p->br, v); 3472594e906SNikolay Aleksandrov if (err) 3482594e906SNikolay Aleksandrov goto out; 3499c86ce2cSPetr Machata } else { 3509c86ce2cSPetr Machata err = br_switchdev_port_vlan_del(v->br->dev, v->vid); 3519c86ce2cSPetr Machata if (err && err != -EOPNOTSUPP) 3529c86ce2cSPetr Machata goto out; 3539c86ce2cSPetr Machata err = 0; 3542594e906SNikolay Aleksandrov } 3552594e906SNikolay Aleksandrov 3566be144f6SNikolay Aleksandrov if (br_vlan_should_use(v)) { 3572594e906SNikolay Aleksandrov v->flags &= ~BRIDGE_VLAN_INFO_BRENTRY; 3586be144f6SNikolay Aleksandrov vg->num_vlans--; 3592594e906SNikolay Aleksandrov } 3602594e906SNikolay Aleksandrov 3612594e906SNikolay Aleksandrov if (masterv != v) { 362efa5356bSRoopa Prabhu vlan_tunnel_info_del(vg, v); 36377751ee8SNikolay Aleksandrov rhashtable_remove_fast(&vg->vlan_hash, &v->vnode, 36477751ee8SNikolay Aleksandrov br_vlan_rht_params); 3652594e906SNikolay Aleksandrov __vlan_del_list(v); 36680900acdSMike Manning nbp_vlan_set_vlan_dev_state(p, v->vid); 3679163a0fcSNikolay Aleksandrov call_rcu(&v->rcu, nbp_vlan_rcu_free); 3682594e906SNikolay Aleksandrov } 3692594e906SNikolay Aleksandrov 370f8ed289fSNikolay Aleksandrov br_vlan_put_master(masterv); 3712594e906SNikolay Aleksandrov out: 372bf361ad3SVivien Didelot return err; 3738580e211SToshiaki Makita } 374243a2e63SVlad Yasevich 375f409d0edSNikolay Aleksandrov static void __vlan_group_free(struct net_bridge_vlan_group *vg) 376f409d0edSNikolay Aleksandrov { 377f409d0edSNikolay Aleksandrov WARN_ON(!list_empty(&vg->vlan_list)); 378f409d0edSNikolay Aleksandrov rhashtable_destroy(&vg->vlan_hash); 379efa5356bSRoopa Prabhu vlan_tunnel_deinit(vg); 380f409d0edSNikolay Aleksandrov kfree(vg); 381f409d0edSNikolay Aleksandrov } 382f409d0edSNikolay Aleksandrov 383f409d0edSNikolay Aleksandrov static void __vlan_flush(struct net_bridge_vlan_group *vg) 384243a2e63SVlad Yasevich { 3852594e906SNikolay Aleksandrov struct net_bridge_vlan *vlan, *tmp; 3862594e906SNikolay Aleksandrov 387f409d0edSNikolay Aleksandrov __vlan_delete_pvid(vg, vg->pvid); 388f409d0edSNikolay Aleksandrov list_for_each_entry_safe(vlan, tmp, &vg->vlan_list, vlist) 3892594e906SNikolay Aleksandrov __vlan_del(vlan); 390243a2e63SVlad Yasevich } 391243a2e63SVlad Yasevich 39278851988SVlad Yasevich struct sk_buff *br_handle_vlan(struct net_bridge *br, 39311538d03SRoopa Prabhu const struct net_bridge_port *p, 3942594e906SNikolay Aleksandrov struct net_bridge_vlan_group *vg, 395a37b85c9SVlad Yasevich struct sk_buff *skb) 396a37b85c9SVlad Yasevich { 3976dada9b1SNikolay Aleksandrov struct br_vlan_stats *stats; 3982594e906SNikolay Aleksandrov struct net_bridge_vlan *v; 399a37b85c9SVlad Yasevich u16 vid; 400a37b85c9SVlad Yasevich 40120adfa1aSVlad Yasevich /* If this packet was not filtered at input, let it pass */ 40220adfa1aSVlad Yasevich if (!BR_INPUT_SKB_CB(skb)->vlan_filtered) 40378851988SVlad Yasevich goto out; 40478851988SVlad Yasevich 4052594e906SNikolay Aleksandrov /* At this point, we know that the frame was filtered and contains 4062594e906SNikolay Aleksandrov * a valid vlan id. If the vlan id has untagged flag set, 4072594e906SNikolay Aleksandrov * send untagged; otherwise, send tagged. 4082594e906SNikolay Aleksandrov */ 4092594e906SNikolay Aleksandrov br_vlan_get_tag(skb, &vid); 4102594e906SNikolay Aleksandrov v = br_vlan_find(vg, vid); 4112594e906SNikolay Aleksandrov /* Vlan entry must be configured at this point. The 412fc92f745SVlad Yasevich * only exception is the bridge is set in promisc mode and the 413fc92f745SVlad Yasevich * packet is destined for the bridge device. In this case 414fc92f745SVlad Yasevich * pass the packet as is. 415fc92f745SVlad Yasevich */ 4162594e906SNikolay Aleksandrov if (!v || !br_vlan_should_use(v)) { 417fc92f745SVlad Yasevich if ((br->dev->flags & IFF_PROMISC) && skb->dev == br->dev) { 418fc92f745SVlad Yasevich goto out; 419fc92f745SVlad Yasevich } else { 420fc92f745SVlad Yasevich kfree_skb(skb); 421fc92f745SVlad Yasevich return NULL; 422fc92f745SVlad Yasevich } 423fc92f745SVlad Yasevich } 424ae75767eSNikolay Aleksandrov if (br_opt_get(br, BROPT_VLAN_STATS_ENABLED)) { 4256dada9b1SNikolay Aleksandrov stats = this_cpu_ptr(v->stats); 4266dada9b1SNikolay Aleksandrov u64_stats_update_begin(&stats->syncp); 4276dada9b1SNikolay Aleksandrov stats->tx_bytes += skb->len; 4286dada9b1SNikolay Aleksandrov stats->tx_packets++; 4296dada9b1SNikolay Aleksandrov u64_stats_update_end(&stats->syncp); 4306dada9b1SNikolay Aleksandrov } 4316dada9b1SNikolay Aleksandrov 4322594e906SNikolay Aleksandrov if (v->flags & BRIDGE_VLAN_INFO_UNTAGGED) 4335978f8a9SMichał Mirosław __vlan_hwaccel_clear_tag(skb); 43411538d03SRoopa Prabhu 43511538d03SRoopa Prabhu if (p && (p->flags & BR_VLAN_TUNNEL) && 43611538d03SRoopa Prabhu br_handle_egress_vlan_tunnel(skb, v)) { 43711538d03SRoopa Prabhu kfree_skb(skb); 43811538d03SRoopa Prabhu return NULL; 43911538d03SRoopa Prabhu } 44078851988SVlad Yasevich out: 44178851988SVlad Yasevich return skb; 44278851988SVlad Yasevich } 44378851988SVlad Yasevich 44478851988SVlad Yasevich /* Called under RCU */ 4456dada9b1SNikolay Aleksandrov static bool __allowed_ingress(const struct net_bridge *br, 4466dada9b1SNikolay Aleksandrov struct net_bridge_vlan_group *vg, 44778851988SVlad Yasevich struct sk_buff *skb, u16 *vid) 44878851988SVlad Yasevich { 4496dada9b1SNikolay Aleksandrov struct br_vlan_stats *stats; 4506dada9b1SNikolay Aleksandrov struct net_bridge_vlan *v; 4518580e211SToshiaki Makita bool tagged; 452a37b85c9SVlad Yasevich 45320adfa1aSVlad Yasevich BR_INPUT_SKB_CB(skb)->vlan_filtered = true; 45412464bb8SToshiaki Makita /* If vlan tx offload is disabled on bridge device and frame was 45512464bb8SToshiaki Makita * sent from vlan device on the bridge device, it does not have 45612464bb8SToshiaki Makita * HW accelerated vlan tag. 45712464bb8SToshiaki Makita */ 458df8a39deSJiri Pirko if (unlikely(!skb_vlan_tag_present(skb) && 4596dada9b1SNikolay Aleksandrov skb->protocol == br->vlan_proto)) { 4600d5501c1SVlad Yasevich skb = skb_vlan_untag(skb); 46112464bb8SToshiaki Makita if (unlikely(!skb)) 46212464bb8SToshiaki Makita return false; 46312464bb8SToshiaki Makita } 46412464bb8SToshiaki Makita 4658580e211SToshiaki Makita if (!br_vlan_get_tag(skb, vid)) { 4668580e211SToshiaki Makita /* Tagged frame */ 4676dada9b1SNikolay Aleksandrov if (skb->vlan_proto != br->vlan_proto) { 4688580e211SToshiaki Makita /* Protocol-mismatch, empty out vlan_tci for new tag */ 4698580e211SToshiaki Makita skb_push(skb, ETH_HLEN); 47062749e2cSJiri Pirko skb = vlan_insert_tag_set_proto(skb, skb->vlan_proto, 471df8a39deSJiri Pirko skb_vlan_tag_get(skb)); 4728580e211SToshiaki Makita if (unlikely(!skb)) 4738580e211SToshiaki Makita return false; 4748580e211SToshiaki Makita 4758580e211SToshiaki Makita skb_pull(skb, ETH_HLEN); 4768580e211SToshiaki Makita skb_reset_mac_len(skb); 4778580e211SToshiaki Makita *vid = 0; 4788580e211SToshiaki Makita tagged = false; 4798580e211SToshiaki Makita } else { 4808580e211SToshiaki Makita tagged = true; 4818580e211SToshiaki Makita } 4828580e211SToshiaki Makita } else { 4838580e211SToshiaki Makita /* Untagged frame */ 4848580e211SToshiaki Makita tagged = false; 4858580e211SToshiaki Makita } 4868580e211SToshiaki Makita 487b90356ceSToshiaki Makita if (!*vid) { 48877751ee8SNikolay Aleksandrov u16 pvid = br_get_pvid(vg); 48977751ee8SNikolay Aleksandrov 490b90356ceSToshiaki Makita /* Frame had a tag with VID 0 or did not have a tag. 491b90356ceSToshiaki Makita * See if pvid is set on this port. That tells us which 492b90356ceSToshiaki Makita * vlan untagged or priority-tagged traffic belongs to. 49378851988SVlad Yasevich */ 4943df6bf45SVlad Yasevich if (!pvid) 495eb707618SToshiaki Makita goto drop; 49678851988SVlad Yasevich 497b90356ceSToshiaki Makita /* PVID is set on this port. Any untagged or priority-tagged 498b90356ceSToshiaki Makita * ingress frame is considered to belong to this vlan. 49978851988SVlad Yasevich */ 500dfb5fa32SToshiaki Makita *vid = pvid; 5018580e211SToshiaki Makita if (likely(!tagged)) 502b90356ceSToshiaki Makita /* Untagged Frame. */ 5036dada9b1SNikolay Aleksandrov __vlan_hwaccel_put_tag(skb, br->vlan_proto, pvid); 504b90356ceSToshiaki Makita else 505b90356ceSToshiaki Makita /* Priority-tagged Frame. 5065978f8a9SMichał Mirosław * At this point, we know that skb->vlan_tci VID 5075978f8a9SMichał Mirosław * field was 0. 508b90356ceSToshiaki Makita * We update only VID field and preserve PCP field. 509b90356ceSToshiaki Makita */ 510b90356ceSToshiaki Makita skb->vlan_tci |= pvid; 511b90356ceSToshiaki Makita 5126dada9b1SNikolay Aleksandrov /* if stats are disabled we can avoid the lookup */ 513ae75767eSNikolay Aleksandrov if (!br_opt_get(br, BROPT_VLAN_STATS_ENABLED)) 51478851988SVlad Yasevich return true; 51578851988SVlad Yasevich } 51677751ee8SNikolay Aleksandrov v = br_vlan_find(vg, *vid); 5176dada9b1SNikolay Aleksandrov if (!v || !br_vlan_should_use(v)) 5186dada9b1SNikolay Aleksandrov goto drop; 5196dada9b1SNikolay Aleksandrov 520ae75767eSNikolay Aleksandrov if (br_opt_get(br, BROPT_VLAN_STATS_ENABLED)) { 5216dada9b1SNikolay Aleksandrov stats = this_cpu_ptr(v->stats); 5226dada9b1SNikolay Aleksandrov u64_stats_update_begin(&stats->syncp); 5236dada9b1SNikolay Aleksandrov stats->rx_bytes += skb->len; 5246dada9b1SNikolay Aleksandrov stats->rx_packets++; 5256dada9b1SNikolay Aleksandrov u64_stats_update_end(&stats->syncp); 5266dada9b1SNikolay Aleksandrov } 5276dada9b1SNikolay Aleksandrov 528a37b85c9SVlad Yasevich return true; 5296dada9b1SNikolay Aleksandrov 530eb707618SToshiaki Makita drop: 531eb707618SToshiaki Makita kfree_skb(skb); 532a37b85c9SVlad Yasevich return false; 533a37b85c9SVlad Yasevich } 534a37b85c9SVlad Yasevich 53577751ee8SNikolay Aleksandrov bool br_allowed_ingress(const struct net_bridge *br, 53677751ee8SNikolay Aleksandrov struct net_bridge_vlan_group *vg, struct sk_buff *skb, 5372594e906SNikolay Aleksandrov u16 *vid) 5382594e906SNikolay Aleksandrov { 5392594e906SNikolay Aleksandrov /* If VLAN filtering is disabled on the bridge, all packets are 5402594e906SNikolay Aleksandrov * permitted. 5412594e906SNikolay Aleksandrov */ 542ae75767eSNikolay Aleksandrov if (!br_opt_get(br, BROPT_VLAN_ENABLED)) { 5432594e906SNikolay Aleksandrov BR_INPUT_SKB_CB(skb)->vlan_filtered = false; 5442594e906SNikolay Aleksandrov return true; 5452594e906SNikolay Aleksandrov } 5462594e906SNikolay Aleksandrov 5476dada9b1SNikolay Aleksandrov return __allowed_ingress(br, vg, skb, vid); 5482594e906SNikolay Aleksandrov } 5492594e906SNikolay Aleksandrov 55085f46c6bSVlad Yasevich /* Called under RCU. */ 5512594e906SNikolay Aleksandrov bool br_allowed_egress(struct net_bridge_vlan_group *vg, 55285f46c6bSVlad Yasevich const struct sk_buff *skb) 55385f46c6bSVlad Yasevich { 5542594e906SNikolay Aleksandrov const struct net_bridge_vlan *v; 55585f46c6bSVlad Yasevich u16 vid; 55685f46c6bSVlad Yasevich 55720adfa1aSVlad Yasevich /* If this packet was not filtered at input, let it pass */ 55820adfa1aSVlad Yasevich if (!BR_INPUT_SKB_CB(skb)->vlan_filtered) 55985f46c6bSVlad Yasevich return true; 56085f46c6bSVlad Yasevich 56185f46c6bSVlad Yasevich br_vlan_get_tag(skb, &vid); 5622594e906SNikolay Aleksandrov v = br_vlan_find(vg, vid); 5632594e906SNikolay Aleksandrov if (v && br_vlan_should_use(v)) 56485f46c6bSVlad Yasevich return true; 56585f46c6bSVlad Yasevich 56685f46c6bSVlad Yasevich return false; 56785f46c6bSVlad Yasevich } 56885f46c6bSVlad Yasevich 569e0d7968aSToshiaki Makita /* Called under RCU */ 570e0d7968aSToshiaki Makita bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid) 571e0d7968aSToshiaki Makita { 572468e7944SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 573e0d7968aSToshiaki Makita struct net_bridge *br = p->br; 574e0d7968aSToshiaki Makita 57520adfa1aSVlad Yasevich /* If filtering was disabled at input, let it pass. */ 576ae75767eSNikolay Aleksandrov if (!br_opt_get(br, BROPT_VLAN_ENABLED)) 577e0d7968aSToshiaki Makita return true; 578e0d7968aSToshiaki Makita 579eca1e006SIdo Schimmel vg = nbp_vlan_group_rcu(p); 580468e7944SNikolay Aleksandrov if (!vg || !vg->num_vlans) 581e0d7968aSToshiaki Makita return false; 582e0d7968aSToshiaki Makita 5838580e211SToshiaki Makita if (!br_vlan_get_tag(skb, vid) && skb->vlan_proto != br->vlan_proto) 5848580e211SToshiaki Makita *vid = 0; 5858580e211SToshiaki Makita 586e0d7968aSToshiaki Makita if (!*vid) { 58777751ee8SNikolay Aleksandrov *vid = br_get_pvid(vg); 5883df6bf45SVlad Yasevich if (!*vid) 589e0d7968aSToshiaki Makita return false; 590e0d7968aSToshiaki Makita 591e0d7968aSToshiaki Makita return true; 592e0d7968aSToshiaki Makita } 593e0d7968aSToshiaki Makita 59477751ee8SNikolay Aleksandrov if (br_vlan_find(vg, *vid)) 595e0d7968aSToshiaki Makita return true; 596e0d7968aSToshiaki Makita 597e0d7968aSToshiaki Makita return false; 598e0d7968aSToshiaki Makita } 599e0d7968aSToshiaki Makita 600dbd6dc75SPetr Machata static int br_vlan_add_existing(struct net_bridge *br, 601dbd6dc75SPetr Machata struct net_bridge_vlan_group *vg, 602dbd6dc75SPetr Machata struct net_bridge_vlan *vlan, 603169327d5SPetr Machata u16 flags, bool *changed, 604169327d5SPetr Machata struct netlink_ext_ack *extack) 605dbd6dc75SPetr Machata { 606dbd6dc75SPetr Machata int err; 607dbd6dc75SPetr Machata 608169327d5SPetr Machata err = br_switchdev_port_vlan_add(br->dev, vlan->vid, flags, extack); 6099c86ce2cSPetr Machata if (err && err != -EOPNOTSUPP) 6109c86ce2cSPetr Machata return err; 6119c86ce2cSPetr Machata 612dbd6dc75SPetr Machata if (!br_vlan_is_brentry(vlan)) { 613dbd6dc75SPetr Machata /* Trying to change flags of non-existent bridge vlan */ 6149c86ce2cSPetr Machata if (!(flags & BRIDGE_VLAN_INFO_BRENTRY)) { 6159c86ce2cSPetr Machata err = -EINVAL; 6169c86ce2cSPetr Machata goto err_flags; 6179c86ce2cSPetr Machata } 618dbd6dc75SPetr Machata /* It was only kept for port vlans, now make it real */ 619dbd6dc75SPetr Machata err = br_fdb_insert(br, NULL, br->dev->dev_addr, 620dbd6dc75SPetr Machata vlan->vid); 621dbd6dc75SPetr Machata if (err) { 622dbd6dc75SPetr Machata br_err(br, "failed to insert local address into bridge forwarding table\n"); 6239c86ce2cSPetr Machata goto err_fdb_insert; 624dbd6dc75SPetr Machata } 625dbd6dc75SPetr Machata 626dbd6dc75SPetr Machata refcount_inc(&vlan->refcnt); 627dbd6dc75SPetr Machata vlan->flags |= BRIDGE_VLAN_INFO_BRENTRY; 628dbd6dc75SPetr Machata vg->num_vlans++; 629dbd6dc75SPetr Machata *changed = true; 630dbd6dc75SPetr Machata } 631dbd6dc75SPetr Machata 632dbd6dc75SPetr Machata if (__vlan_add_flags(vlan, flags)) 633dbd6dc75SPetr Machata *changed = true; 634dbd6dc75SPetr Machata 635dbd6dc75SPetr Machata return 0; 6369c86ce2cSPetr Machata 6379c86ce2cSPetr Machata err_fdb_insert: 6389c86ce2cSPetr Machata err_flags: 6399c86ce2cSPetr Machata br_switchdev_port_vlan_del(br->dev, vlan->vid); 6409c86ce2cSPetr Machata return err; 641dbd6dc75SPetr Machata } 642dbd6dc75SPetr Machata 6438adff41cSToshiaki Makita /* Must be protected by RTNL. 6448adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 645f418af63SNikolay Aleksandrov * changed must be true only if the vlan was created or updated 6468adff41cSToshiaki Makita */ 647169327d5SPetr Machata int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags, bool *changed, 648169327d5SPetr Machata struct netlink_ext_ack *extack) 649243a2e63SVlad Yasevich { 650907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 6512594e906SNikolay Aleksandrov struct net_bridge_vlan *vlan; 6522594e906SNikolay Aleksandrov int ret; 653243a2e63SVlad Yasevich 654243a2e63SVlad Yasevich ASSERT_RTNL(); 655243a2e63SVlad Yasevich 656f418af63SNikolay Aleksandrov *changed = false; 657907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 658907b1e6eSNikolay Aleksandrov vlan = br_vlan_find(vg, vid); 659dbd6dc75SPetr Machata if (vlan) 660169327d5SPetr Machata return br_vlan_add_existing(br, vg, vlan, flags, changed, 661169327d5SPetr Machata extack); 662243a2e63SVlad Yasevich 6632594e906SNikolay Aleksandrov vlan = kzalloc(sizeof(*vlan), GFP_KERNEL); 6642594e906SNikolay Aleksandrov if (!vlan) 665243a2e63SVlad Yasevich return -ENOMEM; 666243a2e63SVlad Yasevich 6676dada9b1SNikolay Aleksandrov vlan->stats = netdev_alloc_pcpu_stats(struct br_vlan_stats); 6686dada9b1SNikolay Aleksandrov if (!vlan->stats) { 6696dada9b1SNikolay Aleksandrov kfree(vlan); 6706dada9b1SNikolay Aleksandrov return -ENOMEM; 6716dada9b1SNikolay Aleksandrov } 6722594e906SNikolay Aleksandrov vlan->vid = vid; 6732594e906SNikolay Aleksandrov vlan->flags = flags | BRIDGE_VLAN_INFO_MASTER; 6742594e906SNikolay Aleksandrov vlan->flags &= ~BRIDGE_VLAN_INFO_PVID; 6752594e906SNikolay Aleksandrov vlan->br = br; 6762594e906SNikolay Aleksandrov if (flags & BRIDGE_VLAN_INFO_BRENTRY) 67725127759SReshetova, Elena refcount_set(&vlan->refcnt, 1); 678169327d5SPetr Machata ret = __vlan_add(vlan, flags, extack); 6796dada9b1SNikolay Aleksandrov if (ret) { 6806dada9b1SNikolay Aleksandrov free_percpu(vlan->stats); 6812594e906SNikolay Aleksandrov kfree(vlan); 682f418af63SNikolay Aleksandrov } else { 683f418af63SNikolay Aleksandrov *changed = true; 6846dada9b1SNikolay Aleksandrov } 685243a2e63SVlad Yasevich 6862594e906SNikolay Aleksandrov return ret; 687243a2e63SVlad Yasevich } 688243a2e63SVlad Yasevich 6898adff41cSToshiaki Makita /* Must be protected by RTNL. 6908adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 6918adff41cSToshiaki Makita */ 692243a2e63SVlad Yasevich int br_vlan_delete(struct net_bridge *br, u16 vid) 693243a2e63SVlad Yasevich { 694907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 6952594e906SNikolay Aleksandrov struct net_bridge_vlan *v; 696243a2e63SVlad Yasevich 697243a2e63SVlad Yasevich ASSERT_RTNL(); 698243a2e63SVlad Yasevich 699907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 700907b1e6eSNikolay Aleksandrov v = br_vlan_find(vg, vid); 7012594e906SNikolay Aleksandrov if (!v || !br_vlan_is_brentry(v)) 7022594e906SNikolay Aleksandrov return -ENOENT; 703243a2e63SVlad Yasevich 704424bb9c9SToshiaki Makita br_fdb_find_delete_local(br, NULL, br->dev->dev_addr, vid); 7053741873bSRoopa Prabhu br_fdb_delete_by_port(br, NULL, vid, 0); 706bc9a25d2SVlad Yasevich 707efa5356bSRoopa Prabhu vlan_tunnel_info_del(vg, v); 708efa5356bSRoopa Prabhu 7092594e906SNikolay Aleksandrov return __vlan_del(v); 710243a2e63SVlad Yasevich } 711243a2e63SVlad Yasevich 712243a2e63SVlad Yasevich void br_vlan_flush(struct net_bridge *br) 713243a2e63SVlad Yasevich { 714f409d0edSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 715f409d0edSNikolay Aleksandrov 716243a2e63SVlad Yasevich ASSERT_RTNL(); 717243a2e63SVlad Yasevich 718f409d0edSNikolay Aleksandrov vg = br_vlan_group(br); 719f409d0edSNikolay Aleksandrov __vlan_flush(vg); 720f409d0edSNikolay Aleksandrov RCU_INIT_POINTER(br->vlgrp, NULL); 721f409d0edSNikolay Aleksandrov synchronize_rcu(); 722f409d0edSNikolay Aleksandrov __vlan_group_free(vg); 723243a2e63SVlad Yasevich } 724243a2e63SVlad Yasevich 7252594e906SNikolay Aleksandrov struct net_bridge_vlan *br_vlan_find(struct net_bridge_vlan_group *vg, u16 vid) 7262b292fb4SToshiaki Makita { 7272594e906SNikolay Aleksandrov if (!vg) 7282594e906SNikolay Aleksandrov return NULL; 7292b292fb4SToshiaki Makita 7302594e906SNikolay Aleksandrov return br_vlan_lookup(&vg->vlan_hash, vid); 7312b292fb4SToshiaki Makita } 7322b292fb4SToshiaki Makita 733204177f3SToshiaki Makita /* Must be protected by RTNL. */ 734204177f3SToshiaki Makita static void recalculate_group_addr(struct net_bridge *br) 735204177f3SToshiaki Makita { 736be3664a0SNikolay Aleksandrov if (br_opt_get(br, BROPT_GROUP_ADDR_SET)) 737204177f3SToshiaki Makita return; 738204177f3SToshiaki Makita 739204177f3SToshiaki Makita spin_lock_bh(&br->lock); 740ae75767eSNikolay Aleksandrov if (!br_opt_get(br, BROPT_VLAN_ENABLED) || 741ae75767eSNikolay Aleksandrov br->vlan_proto == htons(ETH_P_8021Q)) { 742204177f3SToshiaki Makita /* Bridge Group Address */ 743204177f3SToshiaki Makita br->group_addr[5] = 0x00; 744204177f3SToshiaki Makita } else { /* vlan_enabled && ETH_P_8021AD */ 745204177f3SToshiaki Makita /* Provider Bridge Group Address */ 746204177f3SToshiaki Makita br->group_addr[5] = 0x08; 747204177f3SToshiaki Makita } 748204177f3SToshiaki Makita spin_unlock_bh(&br->lock); 749204177f3SToshiaki Makita } 750204177f3SToshiaki Makita 751204177f3SToshiaki Makita /* Must be protected by RTNL. */ 752204177f3SToshiaki Makita void br_recalculate_fwd_mask(struct net_bridge *br) 753204177f3SToshiaki Makita { 754ae75767eSNikolay Aleksandrov if (!br_opt_get(br, BROPT_VLAN_ENABLED) || 755ae75767eSNikolay Aleksandrov br->vlan_proto == htons(ETH_P_8021Q)) 756204177f3SToshiaki Makita br->group_fwd_mask_required = BR_GROUPFWD_DEFAULT; 757204177f3SToshiaki Makita else /* vlan_enabled && ETH_P_8021AD */ 758204177f3SToshiaki Makita br->group_fwd_mask_required = BR_GROUPFWD_8021AD & 759204177f3SToshiaki Makita ~(1u << br->group_addr[5]); 760204177f3SToshiaki Makita } 761204177f3SToshiaki Makita 762a7854037SNikolay Aleksandrov int __br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) 763243a2e63SVlad Yasevich { 7646b72a770SElad Raz struct switchdev_attr attr = { 7656b72a770SElad Raz .orig_dev = br->dev, 7666b72a770SElad Raz .id = SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING, 7676b72a770SElad Raz .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP, 7686b72a770SElad Raz .u.vlan_filtering = val, 7696b72a770SElad Raz }; 7706b72a770SElad Raz int err; 7716b72a770SElad Raz 772ae75767eSNikolay Aleksandrov if (br_opt_get(br, BROPT_VLAN_ENABLED) == !!val) 773a7854037SNikolay Aleksandrov return 0; 774243a2e63SVlad Yasevich 7756b72a770SElad Raz err = switchdev_port_attr_set(br->dev, &attr); 7766b72a770SElad Raz if (err && err != -EOPNOTSUPP) 7776b72a770SElad Raz return err; 7786b72a770SElad Raz 779ae75767eSNikolay Aleksandrov br_opt_toggle(br, BROPT_VLAN_ENABLED, !!val); 7802796d0c6SVlad Yasevich br_manage_promisc(br); 781204177f3SToshiaki Makita recalculate_group_addr(br); 782204177f3SToshiaki Makita br_recalculate_fwd_mask(br); 783243a2e63SVlad Yasevich 784a7854037SNikolay Aleksandrov return 0; 785a7854037SNikolay Aleksandrov } 786a7854037SNikolay Aleksandrov 787a7854037SNikolay Aleksandrov int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) 788a7854037SNikolay Aleksandrov { 789047831a9SXin Long return __br_vlan_filter_toggle(br, val); 790243a2e63SVlad Yasevich } 791243a2e63SVlad Yasevich 7921f51445aSIdo Schimmel bool br_vlan_enabled(const struct net_device *dev) 7931f51445aSIdo Schimmel { 7941f51445aSIdo Schimmel struct net_bridge *br = netdev_priv(dev); 7951f51445aSIdo Schimmel 796ae75767eSNikolay Aleksandrov return br_opt_get(br, BROPT_VLAN_ENABLED); 7971f51445aSIdo Schimmel } 7981f51445aSIdo Schimmel EXPORT_SYMBOL_GPL(br_vlan_enabled); 7991f51445aSIdo Schimmel 80031aed46fSwenxu int br_vlan_get_proto(const struct net_device *dev, u16 *p_proto) 80131aed46fSwenxu { 80231aed46fSwenxu struct net_bridge *br = netdev_priv(dev); 80331aed46fSwenxu 80431aed46fSwenxu *p_proto = ntohs(br->vlan_proto); 80531aed46fSwenxu 80631aed46fSwenxu return 0; 80731aed46fSwenxu } 80831aed46fSwenxu EXPORT_SYMBOL_GPL(br_vlan_get_proto); 80931aed46fSwenxu 810d2d427b3SToshiaki Makita int __br_vlan_set_proto(struct net_bridge *br, __be16 proto) 811204177f3SToshiaki Makita { 812204177f3SToshiaki Makita int err = 0; 813204177f3SToshiaki Makita struct net_bridge_port *p; 8142594e906SNikolay Aleksandrov struct net_bridge_vlan *vlan; 815907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 816d2d427b3SToshiaki Makita __be16 oldproto; 817204177f3SToshiaki Makita 818204177f3SToshiaki Makita if (br->vlan_proto == proto) 819d2d427b3SToshiaki Makita return 0; 820204177f3SToshiaki Makita 821204177f3SToshiaki Makita /* Add VLANs for the new proto to the device filter. */ 822204177f3SToshiaki Makita list_for_each_entry(p, &br->port_list, list) { 823907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 824907b1e6eSNikolay Aleksandrov list_for_each_entry(vlan, &vg->vlan_list, vlist) { 8252594e906SNikolay Aleksandrov err = vlan_vid_add(p->dev, proto, vlan->vid); 826204177f3SToshiaki Makita if (err) 827204177f3SToshiaki Makita goto err_filt; 828204177f3SToshiaki Makita } 829204177f3SToshiaki Makita } 830204177f3SToshiaki Makita 831204177f3SToshiaki Makita oldproto = br->vlan_proto; 832204177f3SToshiaki Makita br->vlan_proto = proto; 833204177f3SToshiaki Makita 834204177f3SToshiaki Makita recalculate_group_addr(br); 835204177f3SToshiaki Makita br_recalculate_fwd_mask(br); 836204177f3SToshiaki Makita 837204177f3SToshiaki Makita /* Delete VLANs for the old proto from the device filter. */ 838907b1e6eSNikolay Aleksandrov list_for_each_entry(p, &br->port_list, list) { 839907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 840907b1e6eSNikolay Aleksandrov list_for_each_entry(vlan, &vg->vlan_list, vlist) 8412594e906SNikolay Aleksandrov vlan_vid_del(p->dev, oldproto, vlan->vid); 842907b1e6eSNikolay Aleksandrov } 843204177f3SToshiaki Makita 844d2d427b3SToshiaki Makita return 0; 845204177f3SToshiaki Makita 846204177f3SToshiaki Makita err_filt: 847907b1e6eSNikolay Aleksandrov list_for_each_entry_continue_reverse(vlan, &vg->vlan_list, vlist) 8482594e906SNikolay Aleksandrov vlan_vid_del(p->dev, proto, vlan->vid); 849204177f3SToshiaki Makita 850907b1e6eSNikolay Aleksandrov list_for_each_entry_continue_reverse(p, &br->port_list, list) { 851907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 852907b1e6eSNikolay Aleksandrov list_for_each_entry(vlan, &vg->vlan_list, vlist) 8532594e906SNikolay Aleksandrov vlan_vid_del(p->dev, proto, vlan->vid); 854907b1e6eSNikolay Aleksandrov } 855204177f3SToshiaki Makita 856d2d427b3SToshiaki Makita return err; 857d2d427b3SToshiaki Makita } 858d2d427b3SToshiaki Makita 859d2d427b3SToshiaki Makita int br_vlan_set_proto(struct net_bridge *br, unsigned long val) 860d2d427b3SToshiaki Makita { 861d2d427b3SToshiaki Makita if (val != ETH_P_8021Q && val != ETH_P_8021AD) 862d2d427b3SToshiaki Makita return -EPROTONOSUPPORT; 863d2d427b3SToshiaki Makita 864047831a9SXin Long return __br_vlan_set_proto(br, htons(val)); 865204177f3SToshiaki Makita } 866204177f3SToshiaki Makita 8676dada9b1SNikolay Aleksandrov int br_vlan_set_stats(struct net_bridge *br, unsigned long val) 8686dada9b1SNikolay Aleksandrov { 8696dada9b1SNikolay Aleksandrov switch (val) { 8706dada9b1SNikolay Aleksandrov case 0: 8716dada9b1SNikolay Aleksandrov case 1: 872ae75767eSNikolay Aleksandrov br_opt_toggle(br, BROPT_VLAN_STATS_ENABLED, !!val); 8736dada9b1SNikolay Aleksandrov break; 8746dada9b1SNikolay Aleksandrov default: 8756dada9b1SNikolay Aleksandrov return -EINVAL; 8766dada9b1SNikolay Aleksandrov } 8776dada9b1SNikolay Aleksandrov 8786dada9b1SNikolay Aleksandrov return 0; 8796dada9b1SNikolay Aleksandrov } 8806dada9b1SNikolay Aleksandrov 8819163a0fcSNikolay Aleksandrov int br_vlan_set_stats_per_port(struct net_bridge *br, unsigned long val) 8829163a0fcSNikolay Aleksandrov { 8839163a0fcSNikolay Aleksandrov struct net_bridge_port *p; 8849163a0fcSNikolay Aleksandrov 8859163a0fcSNikolay Aleksandrov /* allow to change the option if there are no port vlans configured */ 8869163a0fcSNikolay Aleksandrov list_for_each_entry(p, &br->port_list, list) { 8879163a0fcSNikolay Aleksandrov struct net_bridge_vlan_group *vg = nbp_vlan_group(p); 8889163a0fcSNikolay Aleksandrov 8899163a0fcSNikolay Aleksandrov if (vg->num_vlans) 8909163a0fcSNikolay Aleksandrov return -EBUSY; 8919163a0fcSNikolay Aleksandrov } 8929163a0fcSNikolay Aleksandrov 8939163a0fcSNikolay Aleksandrov switch (val) { 8949163a0fcSNikolay Aleksandrov case 0: 8959163a0fcSNikolay Aleksandrov case 1: 8969163a0fcSNikolay Aleksandrov br_opt_toggle(br, BROPT_VLAN_STATS_PER_PORT, !!val); 8979163a0fcSNikolay Aleksandrov break; 8989163a0fcSNikolay Aleksandrov default: 8999163a0fcSNikolay Aleksandrov return -EINVAL; 9009163a0fcSNikolay Aleksandrov } 9019163a0fcSNikolay Aleksandrov 9029163a0fcSNikolay Aleksandrov return 0; 9039163a0fcSNikolay Aleksandrov } 9049163a0fcSNikolay Aleksandrov 90577751ee8SNikolay Aleksandrov static bool vlan_default_pvid(struct net_bridge_vlan_group *vg, u16 vid) 9065be5a2dfSVlad Yasevich { 9072594e906SNikolay Aleksandrov struct net_bridge_vlan *v; 9082594e906SNikolay Aleksandrov 90977751ee8SNikolay Aleksandrov if (vid != vg->pvid) 9102594e906SNikolay Aleksandrov return false; 9112594e906SNikolay Aleksandrov 9122594e906SNikolay Aleksandrov v = br_vlan_lookup(&vg->vlan_hash, vid); 9132594e906SNikolay Aleksandrov if (v && br_vlan_should_use(v) && 9142594e906SNikolay Aleksandrov (v->flags & BRIDGE_VLAN_INFO_UNTAGGED)) 9152594e906SNikolay Aleksandrov return true; 9162594e906SNikolay Aleksandrov 9172594e906SNikolay Aleksandrov return false; 9185be5a2dfSVlad Yasevich } 9195be5a2dfSVlad Yasevich 9205be5a2dfSVlad Yasevich static void br_vlan_disable_default_pvid(struct net_bridge *br) 9215be5a2dfSVlad Yasevich { 9225be5a2dfSVlad Yasevich struct net_bridge_port *p; 9235be5a2dfSVlad Yasevich u16 pvid = br->default_pvid; 9245be5a2dfSVlad Yasevich 9255be5a2dfSVlad Yasevich /* Disable default_pvid on all ports where it is still 9265be5a2dfSVlad Yasevich * configured. 9275be5a2dfSVlad Yasevich */ 928907b1e6eSNikolay Aleksandrov if (vlan_default_pvid(br_vlan_group(br), pvid)) 9295be5a2dfSVlad Yasevich br_vlan_delete(br, pvid); 9305be5a2dfSVlad Yasevich 9315be5a2dfSVlad Yasevich list_for_each_entry(p, &br->port_list, list) { 932907b1e6eSNikolay Aleksandrov if (vlan_default_pvid(nbp_vlan_group(p), pvid)) 9335be5a2dfSVlad Yasevich nbp_vlan_delete(p, pvid); 9345be5a2dfSVlad Yasevich } 9355be5a2dfSVlad Yasevich 9365be5a2dfSVlad Yasevich br->default_pvid = 0; 9375be5a2dfSVlad Yasevich } 9385be5a2dfSVlad Yasevich 939169327d5SPetr Machata int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid, 940169327d5SPetr Machata struct netlink_ext_ack *extack) 9415be5a2dfSVlad Yasevich { 9422594e906SNikolay Aleksandrov const struct net_bridge_vlan *pvent; 943907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 9445be5a2dfSVlad Yasevich struct net_bridge_port *p; 945f418af63SNikolay Aleksandrov unsigned long *changed; 946f418af63SNikolay Aleksandrov bool vlchange; 9475be5a2dfSVlad Yasevich u16 old_pvid; 9485be5a2dfSVlad Yasevich int err = 0; 9495be5a2dfSVlad Yasevich 9500f963b75SNikolay Aleksandrov if (!pvid) { 9510f963b75SNikolay Aleksandrov br_vlan_disable_default_pvid(br); 9520f963b75SNikolay Aleksandrov return 0; 9530f963b75SNikolay Aleksandrov } 9540f963b75SNikolay Aleksandrov 955459479daSAndy Shevchenko changed = bitmap_zalloc(BR_MAX_PORTS, GFP_KERNEL); 9565be5a2dfSVlad Yasevich if (!changed) 9575be5a2dfSVlad Yasevich return -ENOMEM; 9585be5a2dfSVlad Yasevich 9595be5a2dfSVlad Yasevich old_pvid = br->default_pvid; 9605be5a2dfSVlad Yasevich 9615be5a2dfSVlad Yasevich /* Update default_pvid config only if we do not conflict with 9625be5a2dfSVlad Yasevich * user configuration. 9635be5a2dfSVlad Yasevich */ 964907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 965907b1e6eSNikolay Aleksandrov pvent = br_vlan_find(vg, pvid); 966907b1e6eSNikolay Aleksandrov if ((!old_pvid || vlan_default_pvid(vg, old_pvid)) && 9672594e906SNikolay Aleksandrov (!pvent || !br_vlan_should_use(pvent))) { 9685be5a2dfSVlad Yasevich err = br_vlan_add(br, pvid, 9695be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_PVID | 9702594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED | 971f418af63SNikolay Aleksandrov BRIDGE_VLAN_INFO_BRENTRY, 972169327d5SPetr Machata &vlchange, extack); 9735be5a2dfSVlad Yasevich if (err) 9745be5a2dfSVlad Yasevich goto out; 9755be5a2dfSVlad Yasevich br_vlan_delete(br, old_pvid); 9765be5a2dfSVlad Yasevich set_bit(0, changed); 9775be5a2dfSVlad Yasevich } 9785be5a2dfSVlad Yasevich 9795be5a2dfSVlad Yasevich list_for_each_entry(p, &br->port_list, list) { 9805be5a2dfSVlad Yasevich /* Update default_pvid config only if we do not conflict with 9815be5a2dfSVlad Yasevich * user configuration. 9825be5a2dfSVlad Yasevich */ 983907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 9845be5a2dfSVlad Yasevich if ((old_pvid && 985907b1e6eSNikolay Aleksandrov !vlan_default_pvid(vg, old_pvid)) || 986907b1e6eSNikolay Aleksandrov br_vlan_find(vg, pvid)) 9875be5a2dfSVlad Yasevich continue; 9885be5a2dfSVlad Yasevich 9895be5a2dfSVlad Yasevich err = nbp_vlan_add(p, pvid, 9905be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_PVID | 991f418af63SNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED, 992169327d5SPetr Machata &vlchange, extack); 9935be5a2dfSVlad Yasevich if (err) 9945be5a2dfSVlad Yasevich goto err_port; 9955be5a2dfSVlad Yasevich nbp_vlan_delete(p, old_pvid); 9965be5a2dfSVlad Yasevich set_bit(p->port_no, changed); 9975be5a2dfSVlad Yasevich } 9985be5a2dfSVlad Yasevich 9995be5a2dfSVlad Yasevich br->default_pvid = pvid; 10005be5a2dfSVlad Yasevich 10015be5a2dfSVlad Yasevich out: 1002459479daSAndy Shevchenko bitmap_free(changed); 10035be5a2dfSVlad Yasevich return err; 10045be5a2dfSVlad Yasevich 10055be5a2dfSVlad Yasevich err_port: 10065be5a2dfSVlad Yasevich list_for_each_entry_continue_reverse(p, &br->port_list, list) { 10075be5a2dfSVlad Yasevich if (!test_bit(p->port_no, changed)) 10085be5a2dfSVlad Yasevich continue; 10095be5a2dfSVlad Yasevich 10105be5a2dfSVlad Yasevich if (old_pvid) 10115be5a2dfSVlad Yasevich nbp_vlan_add(p, old_pvid, 10125be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_PVID | 1013f418af63SNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED, 1014169327d5SPetr Machata &vlchange, NULL); 10155be5a2dfSVlad Yasevich nbp_vlan_delete(p, pvid); 10165be5a2dfSVlad Yasevich } 10175be5a2dfSVlad Yasevich 10185be5a2dfSVlad Yasevich if (test_bit(0, changed)) { 10195be5a2dfSVlad Yasevich if (old_pvid) 10205be5a2dfSVlad Yasevich br_vlan_add(br, old_pvid, 10215be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_PVID | 10222594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED | 1023f418af63SNikolay Aleksandrov BRIDGE_VLAN_INFO_BRENTRY, 1024169327d5SPetr Machata &vlchange, NULL); 10255be5a2dfSVlad Yasevich br_vlan_delete(br, pvid); 10265be5a2dfSVlad Yasevich } 10275be5a2dfSVlad Yasevich goto out; 10285be5a2dfSVlad Yasevich } 10295be5a2dfSVlad Yasevich 103096a20d9dSVlad Yasevich int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val) 103196a20d9dSVlad Yasevich { 103296a20d9dSVlad Yasevich u16 pvid = val; 103396a20d9dSVlad Yasevich int err = 0; 103496a20d9dSVlad Yasevich 10355be5a2dfSVlad Yasevich if (val >= VLAN_VID_MASK) 103696a20d9dSVlad Yasevich return -EINVAL; 103796a20d9dSVlad Yasevich 103896a20d9dSVlad Yasevich if (pvid == br->default_pvid) 1039047831a9SXin Long goto out; 104096a20d9dSVlad Yasevich 104196a20d9dSVlad Yasevich /* Only allow default pvid change when filtering is disabled */ 1042ae75767eSNikolay Aleksandrov if (br_opt_get(br, BROPT_VLAN_ENABLED)) { 104396a20d9dSVlad Yasevich pr_info_once("Please disable vlan filtering to change default_pvid\n"); 104496a20d9dSVlad Yasevich err = -EPERM; 1045047831a9SXin Long goto out; 104696a20d9dSVlad Yasevich } 1047169327d5SPetr Machata err = __br_vlan_set_default_pvid(br, pvid, NULL); 1048047831a9SXin Long out: 104996a20d9dSVlad Yasevich return err; 105096a20d9dSVlad Yasevich } 105196a20d9dSVlad Yasevich 10525be5a2dfSVlad Yasevich int br_vlan_init(struct net_bridge *br) 10538580e211SToshiaki Makita { 1054907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 10552594e906SNikolay Aleksandrov int ret = -ENOMEM; 10562594e906SNikolay Aleksandrov 1057907b1e6eSNikolay Aleksandrov vg = kzalloc(sizeof(*vg), GFP_KERNEL); 1058907b1e6eSNikolay Aleksandrov if (!vg) 10592594e906SNikolay Aleksandrov goto out; 1060907b1e6eSNikolay Aleksandrov ret = rhashtable_init(&vg->vlan_hash, &br_vlan_rht_params); 10612594e906SNikolay Aleksandrov if (ret) 10622594e906SNikolay Aleksandrov goto err_rhtbl; 1063efa5356bSRoopa Prabhu ret = vlan_tunnel_init(vg); 1064efa5356bSRoopa Prabhu if (ret) 1065efa5356bSRoopa Prabhu goto err_tunnel_init; 1066907b1e6eSNikolay Aleksandrov INIT_LIST_HEAD(&vg->vlan_list); 10678580e211SToshiaki Makita br->vlan_proto = htons(ETH_P_8021Q); 106896a20d9dSVlad Yasevich br->default_pvid = 1; 1069907b1e6eSNikolay Aleksandrov rcu_assign_pointer(br->vlgrp, vg); 10702594e906SNikolay Aleksandrov 10712594e906SNikolay Aleksandrov out: 10722594e906SNikolay Aleksandrov return ret; 10732594e906SNikolay Aleksandrov 1074efa5356bSRoopa Prabhu err_tunnel_init: 1075907b1e6eSNikolay Aleksandrov rhashtable_destroy(&vg->vlan_hash); 10762594e906SNikolay Aleksandrov err_rhtbl: 1077907b1e6eSNikolay Aleksandrov kfree(vg); 10782594e906SNikolay Aleksandrov 10792594e906SNikolay Aleksandrov goto out; 10802594e906SNikolay Aleksandrov } 10812594e906SNikolay Aleksandrov 1082169327d5SPetr Machata int nbp_vlan_init(struct net_bridge_port *p, struct netlink_ext_ack *extack) 10832594e906SNikolay Aleksandrov { 1084404cdbf0SElad Raz struct switchdev_attr attr = { 1085404cdbf0SElad Raz .orig_dev = p->br->dev, 1086404cdbf0SElad Raz .id = SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING, 1087404cdbf0SElad Raz .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP, 1088ae75767eSNikolay Aleksandrov .u.vlan_filtering = br_opt_get(p->br, BROPT_VLAN_ENABLED), 1089404cdbf0SElad Raz }; 1090263344e6SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 10912594e906SNikolay Aleksandrov int ret = -ENOMEM; 10922594e906SNikolay Aleksandrov 1093263344e6SNikolay Aleksandrov vg = kzalloc(sizeof(struct net_bridge_vlan_group), GFP_KERNEL); 1094263344e6SNikolay Aleksandrov if (!vg) 10952594e906SNikolay Aleksandrov goto out; 10962594e906SNikolay Aleksandrov 1097404cdbf0SElad Raz ret = switchdev_port_attr_set(p->dev, &attr); 1098404cdbf0SElad Raz if (ret && ret != -EOPNOTSUPP) 1099404cdbf0SElad Raz goto err_vlan_enabled; 1100404cdbf0SElad Raz 1101263344e6SNikolay Aleksandrov ret = rhashtable_init(&vg->vlan_hash, &br_vlan_rht_params); 11022594e906SNikolay Aleksandrov if (ret) 11032594e906SNikolay Aleksandrov goto err_rhtbl; 1104efa5356bSRoopa Prabhu ret = vlan_tunnel_init(vg); 1105efa5356bSRoopa Prabhu if (ret) 1106efa5356bSRoopa Prabhu goto err_tunnel_init; 1107263344e6SNikolay Aleksandrov INIT_LIST_HEAD(&vg->vlan_list); 1108907b1e6eSNikolay Aleksandrov rcu_assign_pointer(p->vlgrp, vg); 11092594e906SNikolay Aleksandrov if (p->br->default_pvid) { 1110f418af63SNikolay Aleksandrov bool changed; 1111f418af63SNikolay Aleksandrov 11122594e906SNikolay Aleksandrov ret = nbp_vlan_add(p, p->br->default_pvid, 11132594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_PVID | 1114f418af63SNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED, 1115169327d5SPetr Machata &changed, extack); 11162594e906SNikolay Aleksandrov if (ret) 11172594e906SNikolay Aleksandrov goto err_vlan_add; 11182594e906SNikolay Aleksandrov } 11192594e906SNikolay Aleksandrov out: 11202594e906SNikolay Aleksandrov return ret; 11212594e906SNikolay Aleksandrov 11222594e906SNikolay Aleksandrov err_vlan_add: 112307bc588fSIdo Schimmel RCU_INIT_POINTER(p->vlgrp, NULL); 112407bc588fSIdo Schimmel synchronize_rcu(); 1125efa5356bSRoopa Prabhu vlan_tunnel_deinit(vg); 1126efa5356bSRoopa Prabhu err_tunnel_init: 1127efa5356bSRoopa Prabhu rhashtable_destroy(&vg->vlan_hash); 11282594e906SNikolay Aleksandrov err_rhtbl: 1129df2c4334SYotam Gigi err_vlan_enabled: 1130263344e6SNikolay Aleksandrov kfree(vg); 11312594e906SNikolay Aleksandrov 11322594e906SNikolay Aleksandrov goto out; 11338580e211SToshiaki Makita } 11348580e211SToshiaki Makita 11358adff41cSToshiaki Makita /* Must be protected by RTNL. 11368adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 1137f418af63SNikolay Aleksandrov * changed must be true only if the vlan was created or updated 11388adff41cSToshiaki Makita */ 1139f418af63SNikolay Aleksandrov int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags, 1140169327d5SPetr Machata bool *changed, struct netlink_ext_ack *extack) 1141243a2e63SVlad Yasevich { 11422594e906SNikolay Aleksandrov struct net_bridge_vlan *vlan; 11432594e906SNikolay Aleksandrov int ret; 1144243a2e63SVlad Yasevich 1145243a2e63SVlad Yasevich ASSERT_RTNL(); 1146243a2e63SVlad Yasevich 1147f418af63SNikolay Aleksandrov *changed = false; 1148907b1e6eSNikolay Aleksandrov vlan = br_vlan_find(nbp_vlan_group(port), vid); 11492594e906SNikolay Aleksandrov if (vlan) { 11507fbac984SIdo Schimmel /* Pass the flags to the hardware bridge */ 1151169327d5SPetr Machata ret = br_switchdev_port_vlan_add(port->dev, vid, flags, extack); 11527fbac984SIdo Schimmel if (ret && ret != -EOPNOTSUPP) 11537fbac984SIdo Schimmel return ret; 1154f418af63SNikolay Aleksandrov *changed = __vlan_add_flags(vlan, flags); 1155f418af63SNikolay Aleksandrov 11562594e906SNikolay Aleksandrov return 0; 1157243a2e63SVlad Yasevich } 1158243a2e63SVlad Yasevich 11592594e906SNikolay Aleksandrov vlan = kzalloc(sizeof(*vlan), GFP_KERNEL); 11602594e906SNikolay Aleksandrov if (!vlan) 11612594e906SNikolay Aleksandrov return -ENOMEM; 1162243a2e63SVlad Yasevich 11632594e906SNikolay Aleksandrov vlan->vid = vid; 11642594e906SNikolay Aleksandrov vlan->port = port; 1165169327d5SPetr Machata ret = __vlan_add(vlan, flags, extack); 11662594e906SNikolay Aleksandrov if (ret) 11672594e906SNikolay Aleksandrov kfree(vlan); 1168f418af63SNikolay Aleksandrov else 1169f418af63SNikolay Aleksandrov *changed = true; 1170243a2e63SVlad Yasevich 11712594e906SNikolay Aleksandrov return ret; 1172243a2e63SVlad Yasevich } 1173243a2e63SVlad Yasevich 11748adff41cSToshiaki Makita /* Must be protected by RTNL. 11758adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 11768adff41cSToshiaki Makita */ 1177243a2e63SVlad Yasevich int nbp_vlan_delete(struct net_bridge_port *port, u16 vid) 1178243a2e63SVlad Yasevich { 11792594e906SNikolay Aleksandrov struct net_bridge_vlan *v; 1180243a2e63SVlad Yasevich 1181243a2e63SVlad Yasevich ASSERT_RTNL(); 1182243a2e63SVlad Yasevich 1183907b1e6eSNikolay Aleksandrov v = br_vlan_find(nbp_vlan_group(port), vid); 11842594e906SNikolay Aleksandrov if (!v) 11852594e906SNikolay Aleksandrov return -ENOENT; 1186424bb9c9SToshiaki Makita br_fdb_find_delete_local(port->br, port, port->dev->dev_addr, vid); 11871ea2d020SNikolay Aleksandrov br_fdb_delete_by_port(port->br, port, vid, 0); 1188bc9a25d2SVlad Yasevich 11892594e906SNikolay Aleksandrov return __vlan_del(v); 1190243a2e63SVlad Yasevich } 1191243a2e63SVlad Yasevich 1192243a2e63SVlad Yasevich void nbp_vlan_flush(struct net_bridge_port *port) 1193243a2e63SVlad Yasevich { 1194f409d0edSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 1195f409d0edSNikolay Aleksandrov 1196243a2e63SVlad Yasevich ASSERT_RTNL(); 1197243a2e63SVlad Yasevich 1198f409d0edSNikolay Aleksandrov vg = nbp_vlan_group(port); 1199f409d0edSNikolay Aleksandrov __vlan_flush(vg); 1200f409d0edSNikolay Aleksandrov RCU_INIT_POINTER(port->vlgrp, NULL); 1201f409d0edSNikolay Aleksandrov synchronize_rcu(); 1202f409d0edSNikolay Aleksandrov __vlan_group_free(vg); 12035be5a2dfSVlad Yasevich } 1204a60c0903SNikolay Aleksandrov 1205a60c0903SNikolay Aleksandrov void br_vlan_get_stats(const struct net_bridge_vlan *v, 1206a60c0903SNikolay Aleksandrov struct br_vlan_stats *stats) 1207a60c0903SNikolay Aleksandrov { 1208a60c0903SNikolay Aleksandrov int i; 1209a60c0903SNikolay Aleksandrov 1210a60c0903SNikolay Aleksandrov memset(stats, 0, sizeof(*stats)); 1211a60c0903SNikolay Aleksandrov for_each_possible_cpu(i) { 1212a60c0903SNikolay Aleksandrov u64 rxpackets, rxbytes, txpackets, txbytes; 1213a60c0903SNikolay Aleksandrov struct br_vlan_stats *cpu_stats; 1214a60c0903SNikolay Aleksandrov unsigned int start; 1215a60c0903SNikolay Aleksandrov 1216a60c0903SNikolay Aleksandrov cpu_stats = per_cpu_ptr(v->stats, i); 1217a60c0903SNikolay Aleksandrov do { 1218a60c0903SNikolay Aleksandrov start = u64_stats_fetch_begin_irq(&cpu_stats->syncp); 1219a60c0903SNikolay Aleksandrov rxpackets = cpu_stats->rx_packets; 1220a60c0903SNikolay Aleksandrov rxbytes = cpu_stats->rx_bytes; 1221a60c0903SNikolay Aleksandrov txbytes = cpu_stats->tx_bytes; 1222a60c0903SNikolay Aleksandrov txpackets = cpu_stats->tx_packets; 1223a60c0903SNikolay Aleksandrov } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start)); 1224a60c0903SNikolay Aleksandrov 1225a60c0903SNikolay Aleksandrov stats->rx_packets += rxpackets; 1226a60c0903SNikolay Aleksandrov stats->rx_bytes += rxbytes; 1227a60c0903SNikolay Aleksandrov stats->tx_bytes += txbytes; 1228a60c0903SNikolay Aleksandrov stats->tx_packets += txpackets; 1229a60c0903SNikolay Aleksandrov } 1230a60c0903SNikolay Aleksandrov } 12314d4fd361SPetr Machata 12327582f5b7SPablo Neira Ayuso static int __br_vlan_get_pvid(const struct net_device *dev, 12337582f5b7SPablo Neira Ayuso struct net_bridge_port *p, u16 *p_pvid) 12344d4fd361SPetr Machata { 12354d4fd361SPetr Machata struct net_bridge_vlan_group *vg; 12364d4fd361SPetr Machata 12375a6db04cSIdo Schimmel if (p) 12385a6db04cSIdo Schimmel vg = nbp_vlan_group(p); 12395a6db04cSIdo Schimmel else if (netif_is_bridge_master(dev)) 12404d4fd361SPetr Machata vg = br_vlan_group(netdev_priv(dev)); 12414d4fd361SPetr Machata else 12424d4fd361SPetr Machata return -EINVAL; 12434d4fd361SPetr Machata 12444d4fd361SPetr Machata *p_pvid = br_get_pvid(vg); 12454d4fd361SPetr Machata return 0; 12464d4fd361SPetr Machata } 12477582f5b7SPablo Neira Ayuso 12487582f5b7SPablo Neira Ayuso int br_vlan_get_pvid(const struct net_device *dev, u16 *p_pvid) 12497582f5b7SPablo Neira Ayuso { 12507582f5b7SPablo Neira Ayuso ASSERT_RTNL(); 12517582f5b7SPablo Neira Ayuso 12527582f5b7SPablo Neira Ayuso return __br_vlan_get_pvid(dev, br_port_get_check_rtnl(dev), p_pvid); 12537582f5b7SPablo Neira Ayuso } 12544d4fd361SPetr Machata EXPORT_SYMBOL_GPL(br_vlan_get_pvid); 12554d4fd361SPetr Machata 12567582f5b7SPablo Neira Ayuso int br_vlan_get_pvid_rcu(const struct net_device *dev, u16 *p_pvid) 12577582f5b7SPablo Neira Ayuso { 12587582f5b7SPablo Neira Ayuso return __br_vlan_get_pvid(dev, br_port_get_check_rcu(dev), p_pvid); 12597582f5b7SPablo Neira Ayuso } 12607582f5b7SPablo Neira Ayuso EXPORT_SYMBOL_GPL(br_vlan_get_pvid_rcu); 12617582f5b7SPablo Neira Ayuso 12624d4fd361SPetr Machata int br_vlan_get_info(const struct net_device *dev, u16 vid, 12634d4fd361SPetr Machata struct bridge_vlan_info *p_vinfo) 12644d4fd361SPetr Machata { 12654d4fd361SPetr Machata struct net_bridge_vlan_group *vg; 12664d4fd361SPetr Machata struct net_bridge_vlan *v; 12674d4fd361SPetr Machata struct net_bridge_port *p; 12684d4fd361SPetr Machata 12694d4fd361SPetr Machata ASSERT_RTNL(); 12704d4fd361SPetr Machata p = br_port_get_check_rtnl(dev); 12714d4fd361SPetr Machata if (p) 12724d4fd361SPetr Machata vg = nbp_vlan_group(p); 12732b18d79eSPetr Machata else if (netif_is_bridge_master(dev)) 12742b18d79eSPetr Machata vg = br_vlan_group(netdev_priv(dev)); 12754d4fd361SPetr Machata else 12764d4fd361SPetr Machata return -EINVAL; 12774d4fd361SPetr Machata 12784d4fd361SPetr Machata v = br_vlan_find(vg, vid); 12794d4fd361SPetr Machata if (!v) 12804d4fd361SPetr Machata return -ENOENT; 12814d4fd361SPetr Machata 12824d4fd361SPetr Machata p_vinfo->vid = vid; 12834d4fd361SPetr Machata p_vinfo->flags = v->flags; 1284f40d9b20SVladimir Oltean if (vid == br_get_pvid(vg)) 1285f40d9b20SVladimir Oltean p_vinfo->flags |= BRIDGE_VLAN_INFO_PVID; 12864d4fd361SPetr Machata return 0; 12874d4fd361SPetr Machata } 12884d4fd361SPetr Machata EXPORT_SYMBOL_GPL(br_vlan_get_info); 12899c0ec2e7SMike Manning 12909c0ec2e7SMike Manning static int br_vlan_is_bind_vlan_dev(const struct net_device *dev) 12919c0ec2e7SMike Manning { 12929c0ec2e7SMike Manning return is_vlan_dev(dev) && 12939c0ec2e7SMike Manning !!(vlan_dev_priv(dev)->flags & VLAN_FLAG_BRIDGE_BINDING); 12949c0ec2e7SMike Manning } 12959c0ec2e7SMike Manning 12969c0ec2e7SMike Manning static int br_vlan_is_bind_vlan_dev_fn(struct net_device *dev, 12979c0ec2e7SMike Manning __always_unused void *data) 12989c0ec2e7SMike Manning { 12999c0ec2e7SMike Manning return br_vlan_is_bind_vlan_dev(dev); 13009c0ec2e7SMike Manning } 13019c0ec2e7SMike Manning 13029c0ec2e7SMike Manning static bool br_vlan_has_upper_bind_vlan_dev(struct net_device *dev) 13039c0ec2e7SMike Manning { 13049c0ec2e7SMike Manning int found; 13059c0ec2e7SMike Manning 13069c0ec2e7SMike Manning rcu_read_lock(); 13079c0ec2e7SMike Manning found = netdev_walk_all_upper_dev_rcu(dev, br_vlan_is_bind_vlan_dev_fn, 13089c0ec2e7SMike Manning NULL); 13099c0ec2e7SMike Manning rcu_read_unlock(); 13109c0ec2e7SMike Manning 13119c0ec2e7SMike Manning return !!found; 13129c0ec2e7SMike Manning } 13139c0ec2e7SMike Manning 13149c0ec2e7SMike Manning struct br_vlan_bind_walk_data { 13159c0ec2e7SMike Manning u16 vid; 13169c0ec2e7SMike Manning struct net_device *result; 13179c0ec2e7SMike Manning }; 13189c0ec2e7SMike Manning 13199c0ec2e7SMike Manning static int br_vlan_match_bind_vlan_dev_fn(struct net_device *dev, 13209c0ec2e7SMike Manning void *data_in) 13219c0ec2e7SMike Manning { 13229c0ec2e7SMike Manning struct br_vlan_bind_walk_data *data = data_in; 13239c0ec2e7SMike Manning int found = 0; 13249c0ec2e7SMike Manning 13259c0ec2e7SMike Manning if (br_vlan_is_bind_vlan_dev(dev) && 13269c0ec2e7SMike Manning vlan_dev_priv(dev)->vlan_id == data->vid) { 13279c0ec2e7SMike Manning data->result = dev; 13289c0ec2e7SMike Manning found = 1; 13299c0ec2e7SMike Manning } 13309c0ec2e7SMike Manning 13319c0ec2e7SMike Manning return found; 13329c0ec2e7SMike Manning } 13339c0ec2e7SMike Manning 13349c0ec2e7SMike Manning static struct net_device * 13359c0ec2e7SMike Manning br_vlan_get_upper_bind_vlan_dev(struct net_device *dev, u16 vid) 13369c0ec2e7SMike Manning { 13379c0ec2e7SMike Manning struct br_vlan_bind_walk_data data = { 13389c0ec2e7SMike Manning .vid = vid, 13399c0ec2e7SMike Manning }; 13409c0ec2e7SMike Manning 13419c0ec2e7SMike Manning rcu_read_lock(); 13429c0ec2e7SMike Manning netdev_walk_all_upper_dev_rcu(dev, br_vlan_match_bind_vlan_dev_fn, 13439c0ec2e7SMike Manning &data); 13449c0ec2e7SMike Manning rcu_read_unlock(); 13459c0ec2e7SMike Manning 13469c0ec2e7SMike Manning return data.result; 13479c0ec2e7SMike Manning } 13489c0ec2e7SMike Manning 13499c0ec2e7SMike Manning static bool br_vlan_is_dev_up(const struct net_device *dev) 13509c0ec2e7SMike Manning { 13519c0ec2e7SMike Manning return !!(dev->flags & IFF_UP) && netif_oper_up(dev); 13529c0ec2e7SMike Manning } 13539c0ec2e7SMike Manning 13549c0ec2e7SMike Manning static void br_vlan_set_vlan_dev_state(const struct net_bridge *br, 13559c0ec2e7SMike Manning struct net_device *vlan_dev) 13569c0ec2e7SMike Manning { 13579c0ec2e7SMike Manning u16 vid = vlan_dev_priv(vlan_dev)->vlan_id; 13589c0ec2e7SMike Manning struct net_bridge_vlan_group *vg; 13599c0ec2e7SMike Manning struct net_bridge_port *p; 13609c0ec2e7SMike Manning bool has_carrier = false; 13619c0ec2e7SMike Manning 13628e1acd4fSMike Manning if (!netif_carrier_ok(br->dev)) { 13638e1acd4fSMike Manning netif_carrier_off(vlan_dev); 13648e1acd4fSMike Manning return; 13658e1acd4fSMike Manning } 13668e1acd4fSMike Manning 13679c0ec2e7SMike Manning list_for_each_entry(p, &br->port_list, list) { 13689c0ec2e7SMike Manning vg = nbp_vlan_group(p); 13699c0ec2e7SMike Manning if (br_vlan_find(vg, vid) && br_vlan_is_dev_up(p->dev)) { 13709c0ec2e7SMike Manning has_carrier = true; 13719c0ec2e7SMike Manning break; 13729c0ec2e7SMike Manning } 13739c0ec2e7SMike Manning } 13749c0ec2e7SMike Manning 13759c0ec2e7SMike Manning if (has_carrier) 13769c0ec2e7SMike Manning netif_carrier_on(vlan_dev); 13779c0ec2e7SMike Manning else 13789c0ec2e7SMike Manning netif_carrier_off(vlan_dev); 13799c0ec2e7SMike Manning } 13809c0ec2e7SMike Manning 13819c0ec2e7SMike Manning static void br_vlan_set_all_vlan_dev_state(struct net_bridge_port *p) 13829c0ec2e7SMike Manning { 13839c0ec2e7SMike Manning struct net_bridge_vlan_group *vg = nbp_vlan_group(p); 13849c0ec2e7SMike Manning struct net_bridge_vlan *vlan; 13859c0ec2e7SMike Manning struct net_device *vlan_dev; 13869c0ec2e7SMike Manning 13879c0ec2e7SMike Manning list_for_each_entry(vlan, &vg->vlan_list, vlist) { 13889c0ec2e7SMike Manning vlan_dev = br_vlan_get_upper_bind_vlan_dev(p->br->dev, 13899c0ec2e7SMike Manning vlan->vid); 13909c0ec2e7SMike Manning if (vlan_dev) { 13918e1acd4fSMike Manning if (br_vlan_is_dev_up(p->dev)) { 13928e1acd4fSMike Manning if (netif_carrier_ok(p->br->dev)) 13939c0ec2e7SMike Manning netif_carrier_on(vlan_dev); 13948e1acd4fSMike Manning } else { 13959c0ec2e7SMike Manning br_vlan_set_vlan_dev_state(p->br, vlan_dev); 13969c0ec2e7SMike Manning } 13979c0ec2e7SMike Manning } 13989c0ec2e7SMike Manning } 13998e1acd4fSMike Manning } 14009c0ec2e7SMike Manning 14019c0ec2e7SMike Manning static void br_vlan_upper_change(struct net_device *dev, 14029c0ec2e7SMike Manning struct net_device *upper_dev, 14039c0ec2e7SMike Manning bool linking) 14049c0ec2e7SMike Manning { 14059c0ec2e7SMike Manning struct net_bridge *br = netdev_priv(dev); 14069c0ec2e7SMike Manning 14079c0ec2e7SMike Manning if (!br_vlan_is_bind_vlan_dev(upper_dev)) 14089c0ec2e7SMike Manning return; 14099c0ec2e7SMike Manning 14109c0ec2e7SMike Manning if (linking) { 14119c0ec2e7SMike Manning br_vlan_set_vlan_dev_state(br, upper_dev); 14129c0ec2e7SMike Manning br_opt_toggle(br, BROPT_VLAN_BRIDGE_BINDING, true); 14139c0ec2e7SMike Manning } else { 14149c0ec2e7SMike Manning br_opt_toggle(br, BROPT_VLAN_BRIDGE_BINDING, 14159c0ec2e7SMike Manning br_vlan_has_upper_bind_vlan_dev(dev)); 14169c0ec2e7SMike Manning } 14179c0ec2e7SMike Manning } 14189c0ec2e7SMike Manning 14198e1acd4fSMike Manning struct br_vlan_link_state_walk_data { 14208e1acd4fSMike Manning struct net_bridge *br; 14218e1acd4fSMike Manning }; 14228e1acd4fSMike Manning 14238e1acd4fSMike Manning static int br_vlan_link_state_change_fn(struct net_device *vlan_dev, 14248e1acd4fSMike Manning void *data_in) 14258e1acd4fSMike Manning { 14268e1acd4fSMike Manning struct br_vlan_link_state_walk_data *data = data_in; 14278e1acd4fSMike Manning 14288e1acd4fSMike Manning if (br_vlan_is_bind_vlan_dev(vlan_dev)) 14298e1acd4fSMike Manning br_vlan_set_vlan_dev_state(data->br, vlan_dev); 14308e1acd4fSMike Manning 14318e1acd4fSMike Manning return 0; 14328e1acd4fSMike Manning } 14338e1acd4fSMike Manning 14348e1acd4fSMike Manning static void br_vlan_link_state_change(struct net_device *dev, 14358e1acd4fSMike Manning struct net_bridge *br) 14368e1acd4fSMike Manning { 14378e1acd4fSMike Manning struct br_vlan_link_state_walk_data data = { 14388e1acd4fSMike Manning .br = br 14398e1acd4fSMike Manning }; 14408e1acd4fSMike Manning 14418e1acd4fSMike Manning rcu_read_lock(); 14428e1acd4fSMike Manning netdev_walk_all_upper_dev_rcu(dev, br_vlan_link_state_change_fn, 14438e1acd4fSMike Manning &data); 14448e1acd4fSMike Manning rcu_read_unlock(); 14458e1acd4fSMike Manning } 14468e1acd4fSMike Manning 14479c0ec2e7SMike Manning /* Must be protected by RTNL. */ 144880900acdSMike Manning static void nbp_vlan_set_vlan_dev_state(struct net_bridge_port *p, u16 vid) 144980900acdSMike Manning { 145080900acdSMike Manning struct net_device *vlan_dev; 145180900acdSMike Manning 145280900acdSMike Manning if (!br_opt_get(p->br, BROPT_VLAN_BRIDGE_BINDING)) 145380900acdSMike Manning return; 145480900acdSMike Manning 145580900acdSMike Manning vlan_dev = br_vlan_get_upper_bind_vlan_dev(p->br->dev, vid); 145680900acdSMike Manning if (vlan_dev) 145780900acdSMike Manning br_vlan_set_vlan_dev_state(p->br, vlan_dev); 145880900acdSMike Manning } 145980900acdSMike Manning 146080900acdSMike Manning /* Must be protected by RTNL. */ 1461091adf9bSNikolay Aleksandrov int br_vlan_bridge_event(struct net_device *dev, unsigned long event, void *ptr) 14629c0ec2e7SMike Manning { 14639c0ec2e7SMike Manning struct netdev_notifier_changeupper_info *info; 1464091adf9bSNikolay Aleksandrov struct net_bridge *br = netdev_priv(dev); 1465091adf9bSNikolay Aleksandrov bool changed; 1466091adf9bSNikolay Aleksandrov int ret = 0; 14679c0ec2e7SMike Manning 14689c0ec2e7SMike Manning switch (event) { 1469091adf9bSNikolay Aleksandrov case NETDEV_REGISTER: 1470091adf9bSNikolay Aleksandrov ret = br_vlan_add(br, br->default_pvid, 1471091adf9bSNikolay Aleksandrov BRIDGE_VLAN_INFO_PVID | 1472091adf9bSNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED | 1473091adf9bSNikolay Aleksandrov BRIDGE_VLAN_INFO_BRENTRY, &changed, NULL); 1474091adf9bSNikolay Aleksandrov break; 1475091adf9bSNikolay Aleksandrov case NETDEV_UNREGISTER: 1476091adf9bSNikolay Aleksandrov br_vlan_delete(br, br->default_pvid); 1477091adf9bSNikolay Aleksandrov break; 14789c0ec2e7SMike Manning case NETDEV_CHANGEUPPER: 14799c0ec2e7SMike Manning info = ptr; 14809c0ec2e7SMike Manning br_vlan_upper_change(dev, info->upper_dev, info->linking); 14819c0ec2e7SMike Manning break; 14828e1acd4fSMike Manning 14838e1acd4fSMike Manning case NETDEV_CHANGE: 14848e1acd4fSMike Manning case NETDEV_UP: 14858e1acd4fSMike Manning if (!br_opt_get(br, BROPT_VLAN_BRIDGE_BINDING)) 1486091adf9bSNikolay Aleksandrov break; 14878e1acd4fSMike Manning br_vlan_link_state_change(dev, br); 14888e1acd4fSMike Manning break; 14899c0ec2e7SMike Manning } 1490091adf9bSNikolay Aleksandrov 1491091adf9bSNikolay Aleksandrov return ret; 14929c0ec2e7SMike Manning } 14939c0ec2e7SMike Manning 14949c0ec2e7SMike Manning /* Must be protected by RTNL. */ 14959c0ec2e7SMike Manning void br_vlan_port_event(struct net_bridge_port *p, unsigned long event) 14969c0ec2e7SMike Manning { 14979c0ec2e7SMike Manning if (!br_opt_get(p->br, BROPT_VLAN_BRIDGE_BINDING)) 14989c0ec2e7SMike Manning return; 14999c0ec2e7SMike Manning 15009c0ec2e7SMike Manning switch (event) { 15019c0ec2e7SMike Manning case NETDEV_CHANGE: 15029c0ec2e7SMike Manning case NETDEV_DOWN: 15039c0ec2e7SMike Manning case NETDEV_UP: 15049c0ec2e7SMike Manning br_vlan_set_all_vlan_dev_state(p); 15059c0ec2e7SMike Manning break; 15069c0ec2e7SMike Manning } 15079c0ec2e7SMike Manning } 1508