1243a2e63SVlad Yasevich #include <linux/kernel.h> 2243a2e63SVlad Yasevich #include <linux/netdevice.h> 3243a2e63SVlad Yasevich #include <linux/rtnetlink.h> 4243a2e63SVlad Yasevich #include <linux/slab.h> 57f109539SScott Feldman #include <net/switchdev.h> 6243a2e63SVlad Yasevich 7243a2e63SVlad Yasevich #include "br_private.h" 8efa5356bSRoopa Prabhu #include "br_private_tunnel.h" 9243a2e63SVlad Yasevich 102594e906SNikolay Aleksandrov static inline int br_vlan_cmp(struct rhashtable_compare_arg *arg, 112594e906SNikolay Aleksandrov const void *ptr) 12552406c4SVlad Yasevich { 132594e906SNikolay Aleksandrov const struct net_bridge_vlan *vle = ptr; 142594e906SNikolay Aleksandrov u16 vid = *(u16 *)arg->key; 152594e906SNikolay Aleksandrov 162594e906SNikolay Aleksandrov return vle->vid != vid; 172594e906SNikolay Aleksandrov } 182594e906SNikolay Aleksandrov 192594e906SNikolay Aleksandrov static const struct rhashtable_params br_vlan_rht_params = { 202594e906SNikolay Aleksandrov .head_offset = offsetof(struct net_bridge_vlan, vnode), 212594e906SNikolay Aleksandrov .key_offset = offsetof(struct net_bridge_vlan, vid), 222594e906SNikolay Aleksandrov .key_len = sizeof(u16), 238af78b64SNikolay Aleksandrov .nelem_hint = 3, 248af78b64SNikolay Aleksandrov .locks_mul = 1, 252594e906SNikolay Aleksandrov .max_size = VLAN_N_VID, 262594e906SNikolay Aleksandrov .obj_cmpfn = br_vlan_cmp, 272594e906SNikolay Aleksandrov .automatic_shrinking = true, 282594e906SNikolay Aleksandrov }; 292594e906SNikolay Aleksandrov 302594e906SNikolay Aleksandrov static struct net_bridge_vlan *br_vlan_lookup(struct rhashtable *tbl, u16 vid) 312594e906SNikolay Aleksandrov { 322594e906SNikolay Aleksandrov return rhashtable_lookup_fast(tbl, &vid, br_vlan_rht_params); 332594e906SNikolay Aleksandrov } 342594e906SNikolay Aleksandrov 35f418af63SNikolay Aleksandrov static bool __vlan_add_pvid(struct net_bridge_vlan_group *vg, u16 vid) 362594e906SNikolay Aleksandrov { 3777751ee8SNikolay Aleksandrov if (vg->pvid == vid) 38f418af63SNikolay Aleksandrov return false; 39552406c4SVlad Yasevich 40552406c4SVlad Yasevich smp_wmb(); 4177751ee8SNikolay Aleksandrov vg->pvid = vid; 42f418af63SNikolay Aleksandrov 43f418af63SNikolay Aleksandrov return true; 44552406c4SVlad Yasevich } 45552406c4SVlad Yasevich 46f418af63SNikolay Aleksandrov static bool __vlan_delete_pvid(struct net_bridge_vlan_group *vg, u16 vid) 47552406c4SVlad Yasevich { 4877751ee8SNikolay Aleksandrov if (vg->pvid != vid) 49f418af63SNikolay Aleksandrov return false; 50552406c4SVlad Yasevich 51552406c4SVlad Yasevich smp_wmb(); 5277751ee8SNikolay Aleksandrov vg->pvid = 0; 53f418af63SNikolay Aleksandrov 54f418af63SNikolay Aleksandrov return true; 55552406c4SVlad Yasevich } 56552406c4SVlad Yasevich 57f418af63SNikolay Aleksandrov /* return true if anything changed, false otherwise */ 58f418af63SNikolay Aleksandrov static bool __vlan_add_flags(struct net_bridge_vlan *v, u16 flags) 5935e03f3aSVlad Yasevich { 6077751ee8SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 61f418af63SNikolay Aleksandrov u16 old_flags = v->flags; 62f418af63SNikolay Aleksandrov bool ret; 6377751ee8SNikolay Aleksandrov 642594e906SNikolay Aleksandrov if (br_vlan_is_master(v)) 65907b1e6eSNikolay Aleksandrov vg = br_vlan_group(v->br); 66635126b7SVlad Yasevich else 67907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(v->port); 6877751ee8SNikolay Aleksandrov 6977751ee8SNikolay Aleksandrov if (flags & BRIDGE_VLAN_INFO_PVID) 70f418af63SNikolay Aleksandrov ret = __vlan_add_pvid(vg, v->vid); 712594e906SNikolay Aleksandrov else 72f418af63SNikolay Aleksandrov ret = __vlan_delete_pvid(vg, v->vid); 7335e03f3aSVlad Yasevich 7435e03f3aSVlad Yasevich if (flags & BRIDGE_VLAN_INFO_UNTAGGED) 752594e906SNikolay Aleksandrov v->flags |= BRIDGE_VLAN_INFO_UNTAGGED; 76635126b7SVlad Yasevich else 772594e906SNikolay Aleksandrov v->flags &= ~BRIDGE_VLAN_INFO_UNTAGGED; 78f418af63SNikolay Aleksandrov 79f418af63SNikolay Aleksandrov return ret || !!(old_flags ^ v->flags); 8035e03f3aSVlad Yasevich } 8135e03f3aSVlad Yasevich 827f109539SScott Feldman static int __vlan_vid_add(struct net_device *dev, struct net_bridge *br, 8327973793SIdo Schimmel struct net_bridge_vlan *v, u16 flags, 8427973793SIdo Schimmel struct netlink_ext_ack *extack) 857f109539SScott Feldman { 860944d6b5SJiri Pirko int err; 877f109539SScott Feldman 880944d6b5SJiri Pirko /* Try switchdev op first. In case it is not supported, fallback to 890944d6b5SJiri Pirko * 8021q add. 900944d6b5SJiri Pirko */ 9127973793SIdo Schimmel err = br_switchdev_port_vlan_add(dev, v->vid, flags, extack); 927f109539SScott Feldman if (err == -EOPNOTSUPP) 9327973793SIdo Schimmel return vlan_vid_add(dev, br->vlan_proto, v->vid); 9427973793SIdo Schimmel v->priv_flags |= BR_VLFLAG_ADDED_BY_SWITCHDEV; 957f109539SScott Feldman return err; 967f109539SScott Feldman } 977f109539SScott Feldman 982594e906SNikolay Aleksandrov static void __vlan_add_list(struct net_bridge_vlan *v) 99243a2e63SVlad Yasevich { 100907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 1012594e906SNikolay Aleksandrov struct list_head *headp, *hpos; 1022594e906SNikolay Aleksandrov struct net_bridge_vlan *vent; 103243a2e63SVlad Yasevich 104907b1e6eSNikolay Aleksandrov if (br_vlan_is_master(v)) 105907b1e6eSNikolay Aleksandrov vg = br_vlan_group(v->br); 106907b1e6eSNikolay Aleksandrov else 107907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(v->port); 108907b1e6eSNikolay Aleksandrov 109907b1e6eSNikolay Aleksandrov headp = &vg->vlan_list; 1102594e906SNikolay Aleksandrov list_for_each_prev(hpos, headp) { 1112594e906SNikolay Aleksandrov vent = list_entry(hpos, struct net_bridge_vlan, vlist); 1122594e906SNikolay Aleksandrov if (v->vid < vent->vid) 1132594e906SNikolay Aleksandrov continue; 1142594e906SNikolay Aleksandrov else 1152594e906SNikolay Aleksandrov break; 1162594e906SNikolay Aleksandrov } 117586c2b57SNikolay Aleksandrov list_add_rcu(&v->vlist, hpos); 118552406c4SVlad Yasevich } 119243a2e63SVlad Yasevich 1202594e906SNikolay Aleksandrov static void __vlan_del_list(struct net_bridge_vlan *v) 1212594e906SNikolay Aleksandrov { 122586c2b57SNikolay Aleksandrov list_del_rcu(&v->vlist); 123243a2e63SVlad Yasevich } 124243a2e63SVlad Yasevich 125bf361ad3SVivien Didelot static int __vlan_vid_del(struct net_device *dev, struct net_bridge *br, 12627973793SIdo Schimmel const struct net_bridge_vlan *v) 1277f109539SScott Feldman { 1280944d6b5SJiri Pirko int err; 1297f109539SScott Feldman 1300944d6b5SJiri Pirko /* Try switchdev op first. In case it is not supported, fallback to 1310944d6b5SJiri Pirko * 8021q del. 1320944d6b5SJiri Pirko */ 13327973793SIdo Schimmel err = br_switchdev_port_vlan_del(dev, v->vid); 13427973793SIdo Schimmel if (!(v->priv_flags & BR_VLFLAG_ADDED_BY_SWITCHDEV)) 13527973793SIdo Schimmel vlan_vid_del(dev, br->vlan_proto, v->vid); 13627973793SIdo Schimmel return err == -EOPNOTSUPP ? 0 : err; 1377f109539SScott Feldman } 1387f109539SScott Feldman 139f8ed289fSNikolay Aleksandrov /* Returns a master vlan, if it didn't exist it gets created. In all cases a 140f8ed289fSNikolay Aleksandrov * a reference is taken to the master vlan before returning. 141f8ed289fSNikolay Aleksandrov */ 142169327d5SPetr Machata static struct net_bridge_vlan * 143169327d5SPetr Machata br_vlan_get_master(struct net_bridge *br, u16 vid, 144169327d5SPetr Machata struct netlink_ext_ack *extack) 145f8ed289fSNikolay Aleksandrov { 146907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 147f8ed289fSNikolay Aleksandrov struct net_bridge_vlan *masterv; 148f8ed289fSNikolay Aleksandrov 149907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 150907b1e6eSNikolay Aleksandrov masterv = br_vlan_find(vg, vid); 151f8ed289fSNikolay Aleksandrov if (!masterv) { 152f418af63SNikolay Aleksandrov bool changed; 153f418af63SNikolay Aleksandrov 154f8ed289fSNikolay Aleksandrov /* missing global ctx, create it now */ 155169327d5SPetr Machata if (br_vlan_add(br, vid, 0, &changed, extack)) 156f8ed289fSNikolay Aleksandrov return NULL; 157907b1e6eSNikolay Aleksandrov masterv = br_vlan_find(vg, vid); 158f8ed289fSNikolay Aleksandrov if (WARN_ON(!masterv)) 159f8ed289fSNikolay Aleksandrov return NULL; 1600e5a82efSIdo Schimmel refcount_set(&masterv->refcnt, 1); 1610e5a82efSIdo Schimmel return masterv; 162f8ed289fSNikolay Aleksandrov } 16325127759SReshetova, Elena refcount_inc(&masterv->refcnt); 164f8ed289fSNikolay Aleksandrov 165f8ed289fSNikolay Aleksandrov return masterv; 166f8ed289fSNikolay Aleksandrov } 167f8ed289fSNikolay Aleksandrov 1686dada9b1SNikolay Aleksandrov static void br_master_vlan_rcu_free(struct rcu_head *rcu) 1696dada9b1SNikolay Aleksandrov { 1706dada9b1SNikolay Aleksandrov struct net_bridge_vlan *v; 1716dada9b1SNikolay Aleksandrov 1726dada9b1SNikolay Aleksandrov v = container_of(rcu, struct net_bridge_vlan, rcu); 1736dada9b1SNikolay Aleksandrov WARN_ON(!br_vlan_is_master(v)); 1746dada9b1SNikolay Aleksandrov free_percpu(v->stats); 1756dada9b1SNikolay Aleksandrov v->stats = NULL; 1766dada9b1SNikolay Aleksandrov kfree(v); 1776dada9b1SNikolay Aleksandrov } 1786dada9b1SNikolay Aleksandrov 179f8ed289fSNikolay Aleksandrov static void br_vlan_put_master(struct net_bridge_vlan *masterv) 180f8ed289fSNikolay Aleksandrov { 181907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 182907b1e6eSNikolay Aleksandrov 183f8ed289fSNikolay Aleksandrov if (!br_vlan_is_master(masterv)) 184f8ed289fSNikolay Aleksandrov return; 185f8ed289fSNikolay Aleksandrov 186907b1e6eSNikolay Aleksandrov vg = br_vlan_group(masterv->br); 18725127759SReshetova, Elena if (refcount_dec_and_test(&masterv->refcnt)) { 188907b1e6eSNikolay Aleksandrov rhashtable_remove_fast(&vg->vlan_hash, 189f8ed289fSNikolay Aleksandrov &masterv->vnode, br_vlan_rht_params); 190f8ed289fSNikolay Aleksandrov __vlan_del_list(masterv); 1916dada9b1SNikolay Aleksandrov call_rcu(&masterv->rcu, br_master_vlan_rcu_free); 192f8ed289fSNikolay Aleksandrov } 193f8ed289fSNikolay Aleksandrov } 194f8ed289fSNikolay Aleksandrov 1959163a0fcSNikolay Aleksandrov static void nbp_vlan_rcu_free(struct rcu_head *rcu) 1969163a0fcSNikolay Aleksandrov { 1979163a0fcSNikolay Aleksandrov struct net_bridge_vlan *v; 1989163a0fcSNikolay Aleksandrov 1999163a0fcSNikolay Aleksandrov v = container_of(rcu, struct net_bridge_vlan, rcu); 2009163a0fcSNikolay Aleksandrov WARN_ON(br_vlan_is_master(v)); 2019163a0fcSNikolay Aleksandrov /* if we had per-port stats configured then free them here */ 2029d332e69SNikolay Aleksandrov if (v->priv_flags & BR_VLFLAG_PER_PORT_STATS) 2039163a0fcSNikolay Aleksandrov free_percpu(v->stats); 2049163a0fcSNikolay Aleksandrov v->stats = NULL; 2059163a0fcSNikolay Aleksandrov kfree(v); 2069163a0fcSNikolay Aleksandrov } 2079163a0fcSNikolay Aleksandrov 2082594e906SNikolay Aleksandrov /* This is the shared VLAN add function which works for both ports and bridge 2092594e906SNikolay Aleksandrov * devices. There are four possible calls to this function in terms of the 2102594e906SNikolay Aleksandrov * vlan entry type: 2112594e906SNikolay Aleksandrov * 1. vlan is being added on a port (no master flags, global entry exists) 212ddd611d3SIdo Schimmel * 2. vlan is being added on a bridge (both master and brentry flags) 2132594e906SNikolay Aleksandrov * 3. vlan is being added on a port, but a global entry didn't exist which 214ddd611d3SIdo Schimmel * is being created right now (master flag set, brentry flag unset), the 2152594e906SNikolay Aleksandrov * global entry is used for global per-vlan features, but not for filtering 216ddd611d3SIdo Schimmel * 4. same as 3 but with both master and brentry flags set so the entry 2172594e906SNikolay Aleksandrov * will be used for filtering in both the port and the bridge 2182594e906SNikolay Aleksandrov */ 219169327d5SPetr Machata static int __vlan_add(struct net_bridge_vlan *v, u16 flags, 220169327d5SPetr Machata struct netlink_ext_ack *extack) 221243a2e63SVlad Yasevich { 2222594e906SNikolay Aleksandrov struct net_bridge_vlan *masterv = NULL; 2232594e906SNikolay Aleksandrov struct net_bridge_port *p = NULL; 2246be144f6SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 2252594e906SNikolay Aleksandrov struct net_device *dev; 2262594e906SNikolay Aleksandrov struct net_bridge *br; 227bf361ad3SVivien Didelot int err; 228bf361ad3SVivien Didelot 2292594e906SNikolay Aleksandrov if (br_vlan_is_master(v)) { 2302594e906SNikolay Aleksandrov br = v->br; 2312594e906SNikolay Aleksandrov dev = br->dev; 232907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 2332594e906SNikolay Aleksandrov } else { 2342594e906SNikolay Aleksandrov p = v->port; 2352594e906SNikolay Aleksandrov br = p->br; 2362594e906SNikolay Aleksandrov dev = p->dev; 237907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 2382594e906SNikolay Aleksandrov } 2392594e906SNikolay Aleksandrov 2402594e906SNikolay Aleksandrov if (p) { 2412594e906SNikolay Aleksandrov /* Add VLAN to the device filter if it is supported. 2422594e906SNikolay Aleksandrov * This ensures tagged traffic enters the bridge when 2432594e906SNikolay Aleksandrov * promiscuous mode is disabled by br_manage_promisc(). 2442594e906SNikolay Aleksandrov */ 24527973793SIdo Schimmel err = __vlan_vid_add(dev, br, v, flags, extack); 246bf361ad3SVivien Didelot if (err) 2472594e906SNikolay Aleksandrov goto out; 2482594e906SNikolay Aleksandrov 2492594e906SNikolay Aleksandrov /* need to work on the master vlan too */ 2502594e906SNikolay Aleksandrov if (flags & BRIDGE_VLAN_INFO_MASTER) { 251f418af63SNikolay Aleksandrov bool changed; 252f418af63SNikolay Aleksandrov 253f418af63SNikolay Aleksandrov err = br_vlan_add(br, v->vid, 254f418af63SNikolay Aleksandrov flags | BRIDGE_VLAN_INFO_BRENTRY, 255169327d5SPetr Machata &changed, extack); 2562594e906SNikolay Aleksandrov if (err) 2572594e906SNikolay Aleksandrov goto out_filt; 2582594e906SNikolay Aleksandrov } 2592594e906SNikolay Aleksandrov 260169327d5SPetr Machata masterv = br_vlan_get_master(br, v->vid, extack); 261f8ed289fSNikolay Aleksandrov if (!masterv) 2622594e906SNikolay Aleksandrov goto out_filt; 2632594e906SNikolay Aleksandrov v->brvlan = masterv; 2649163a0fcSNikolay Aleksandrov if (br_opt_get(br, BROPT_VLAN_STATS_PER_PORT)) { 2659163a0fcSNikolay Aleksandrov v->stats = netdev_alloc_pcpu_stats(struct br_vlan_stats); 2669163a0fcSNikolay Aleksandrov if (!v->stats) { 2679163a0fcSNikolay Aleksandrov err = -ENOMEM; 2689163a0fcSNikolay Aleksandrov goto out_filt; 2699163a0fcSNikolay Aleksandrov } 2709d332e69SNikolay Aleksandrov v->priv_flags |= BR_VLFLAG_PER_PORT_STATS; 2719163a0fcSNikolay Aleksandrov } else { 2726dada9b1SNikolay Aleksandrov v->stats = masterv->stats; 2739163a0fcSNikolay Aleksandrov } 2749c86ce2cSPetr Machata } else { 275169327d5SPetr Machata err = br_switchdev_port_vlan_add(dev, v->vid, flags, extack); 2769c86ce2cSPetr Machata if (err && err != -EOPNOTSUPP) 2779c86ce2cSPetr Machata goto out; 2782594e906SNikolay Aleksandrov } 2792594e906SNikolay Aleksandrov 2806be144f6SNikolay Aleksandrov /* Add the dev mac and count the vlan only if it's usable */ 2812594e906SNikolay Aleksandrov if (br_vlan_should_use(v)) { 2822594e906SNikolay Aleksandrov err = br_fdb_insert(br, p, dev->dev_addr, v->vid); 2832594e906SNikolay Aleksandrov if (err) { 2842594e906SNikolay Aleksandrov br_err(br, "failed insert local address into bridge forwarding table\n"); 2852594e906SNikolay Aleksandrov goto out_filt; 2862594e906SNikolay Aleksandrov } 2876be144f6SNikolay Aleksandrov vg->num_vlans++; 2882594e906SNikolay Aleksandrov } 2892594e906SNikolay Aleksandrov 2906be144f6SNikolay Aleksandrov err = rhashtable_lookup_insert_fast(&vg->vlan_hash, &v->vnode, 2916be144f6SNikolay Aleksandrov br_vlan_rht_params); 2922594e906SNikolay Aleksandrov if (err) 2932594e906SNikolay Aleksandrov goto out_fdb_insert; 2942594e906SNikolay Aleksandrov 2952594e906SNikolay Aleksandrov __vlan_add_list(v); 2962594e906SNikolay Aleksandrov __vlan_add_flags(v, flags); 2972594e906SNikolay Aleksandrov out: 2982594e906SNikolay Aleksandrov return err; 2992594e906SNikolay Aleksandrov 3002594e906SNikolay Aleksandrov out_fdb_insert: 3016be144f6SNikolay Aleksandrov if (br_vlan_should_use(v)) { 3026be144f6SNikolay Aleksandrov br_fdb_find_delete_local(br, p, dev->dev_addr, v->vid); 3036be144f6SNikolay Aleksandrov vg->num_vlans--; 3046be144f6SNikolay Aleksandrov } 3052594e906SNikolay Aleksandrov 3062594e906SNikolay Aleksandrov out_filt: 3072594e906SNikolay Aleksandrov if (p) { 30827973793SIdo Schimmel __vlan_vid_del(dev, br, v); 3092594e906SNikolay Aleksandrov if (masterv) { 3101a3aea25SLi RongQing if (v->stats && masterv->stats != v->stats) 3111a3aea25SLi RongQing free_percpu(v->stats); 3121a3aea25SLi RongQing v->stats = NULL; 3131a3aea25SLi RongQing 314f8ed289fSNikolay Aleksandrov br_vlan_put_master(masterv); 3152594e906SNikolay Aleksandrov v->brvlan = NULL; 3162594e906SNikolay Aleksandrov } 3179c86ce2cSPetr Machata } else { 3189c86ce2cSPetr Machata br_switchdev_port_vlan_del(dev, v->vid); 3192594e906SNikolay Aleksandrov } 3202594e906SNikolay Aleksandrov 3212594e906SNikolay Aleksandrov goto out; 3222594e906SNikolay Aleksandrov } 3232594e906SNikolay Aleksandrov 3242594e906SNikolay Aleksandrov static int __vlan_del(struct net_bridge_vlan *v) 3252594e906SNikolay Aleksandrov { 3262594e906SNikolay Aleksandrov struct net_bridge_vlan *masterv = v; 32777751ee8SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 3282594e906SNikolay Aleksandrov struct net_bridge_port *p = NULL; 3292594e906SNikolay Aleksandrov int err = 0; 3302594e906SNikolay Aleksandrov 3312594e906SNikolay Aleksandrov if (br_vlan_is_master(v)) { 332907b1e6eSNikolay Aleksandrov vg = br_vlan_group(v->br); 3332594e906SNikolay Aleksandrov } else { 3342594e906SNikolay Aleksandrov p = v->port; 335907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(v->port); 3362594e906SNikolay Aleksandrov masterv = v->brvlan; 3372594e906SNikolay Aleksandrov } 3382594e906SNikolay Aleksandrov 33977751ee8SNikolay Aleksandrov __vlan_delete_pvid(vg, v->vid); 3402594e906SNikolay Aleksandrov if (p) { 34127973793SIdo Schimmel err = __vlan_vid_del(p->dev, p->br, v); 3422594e906SNikolay Aleksandrov if (err) 3432594e906SNikolay Aleksandrov goto out; 3449c86ce2cSPetr Machata } else { 3459c86ce2cSPetr Machata err = br_switchdev_port_vlan_del(v->br->dev, v->vid); 3469c86ce2cSPetr Machata if (err && err != -EOPNOTSUPP) 3479c86ce2cSPetr Machata goto out; 3489c86ce2cSPetr Machata err = 0; 3492594e906SNikolay Aleksandrov } 3502594e906SNikolay Aleksandrov 3516be144f6SNikolay Aleksandrov if (br_vlan_should_use(v)) { 3522594e906SNikolay Aleksandrov v->flags &= ~BRIDGE_VLAN_INFO_BRENTRY; 3536be144f6SNikolay Aleksandrov vg->num_vlans--; 3542594e906SNikolay Aleksandrov } 3552594e906SNikolay Aleksandrov 3562594e906SNikolay Aleksandrov if (masterv != v) { 357efa5356bSRoopa Prabhu vlan_tunnel_info_del(vg, v); 35877751ee8SNikolay Aleksandrov rhashtable_remove_fast(&vg->vlan_hash, &v->vnode, 35977751ee8SNikolay Aleksandrov br_vlan_rht_params); 3602594e906SNikolay Aleksandrov __vlan_del_list(v); 3619163a0fcSNikolay Aleksandrov call_rcu(&v->rcu, nbp_vlan_rcu_free); 3622594e906SNikolay Aleksandrov } 3632594e906SNikolay Aleksandrov 364f8ed289fSNikolay Aleksandrov br_vlan_put_master(masterv); 3652594e906SNikolay Aleksandrov out: 366bf361ad3SVivien Didelot return err; 3678580e211SToshiaki Makita } 368243a2e63SVlad Yasevich 369f409d0edSNikolay Aleksandrov static void __vlan_group_free(struct net_bridge_vlan_group *vg) 370f409d0edSNikolay Aleksandrov { 371f409d0edSNikolay Aleksandrov WARN_ON(!list_empty(&vg->vlan_list)); 372f409d0edSNikolay Aleksandrov rhashtable_destroy(&vg->vlan_hash); 373efa5356bSRoopa Prabhu vlan_tunnel_deinit(vg); 374f409d0edSNikolay Aleksandrov kfree(vg); 375f409d0edSNikolay Aleksandrov } 376f409d0edSNikolay Aleksandrov 377f409d0edSNikolay Aleksandrov static void __vlan_flush(struct net_bridge_vlan_group *vg) 378243a2e63SVlad Yasevich { 3792594e906SNikolay Aleksandrov struct net_bridge_vlan *vlan, *tmp; 3802594e906SNikolay Aleksandrov 381f409d0edSNikolay Aleksandrov __vlan_delete_pvid(vg, vg->pvid); 382f409d0edSNikolay Aleksandrov list_for_each_entry_safe(vlan, tmp, &vg->vlan_list, vlist) 3832594e906SNikolay Aleksandrov __vlan_del(vlan); 384243a2e63SVlad Yasevich } 385243a2e63SVlad Yasevich 38678851988SVlad Yasevich struct sk_buff *br_handle_vlan(struct net_bridge *br, 38711538d03SRoopa Prabhu const struct net_bridge_port *p, 3882594e906SNikolay Aleksandrov struct net_bridge_vlan_group *vg, 389a37b85c9SVlad Yasevich struct sk_buff *skb) 390a37b85c9SVlad Yasevich { 3916dada9b1SNikolay Aleksandrov struct br_vlan_stats *stats; 3922594e906SNikolay Aleksandrov struct net_bridge_vlan *v; 393a37b85c9SVlad Yasevich u16 vid; 394a37b85c9SVlad Yasevich 39520adfa1aSVlad Yasevich /* If this packet was not filtered at input, let it pass */ 39620adfa1aSVlad Yasevich if (!BR_INPUT_SKB_CB(skb)->vlan_filtered) 39778851988SVlad Yasevich goto out; 39878851988SVlad Yasevich 3992594e906SNikolay Aleksandrov /* At this point, we know that the frame was filtered and contains 4002594e906SNikolay Aleksandrov * a valid vlan id. If the vlan id has untagged flag set, 4012594e906SNikolay Aleksandrov * send untagged; otherwise, send tagged. 4022594e906SNikolay Aleksandrov */ 4032594e906SNikolay Aleksandrov br_vlan_get_tag(skb, &vid); 4042594e906SNikolay Aleksandrov v = br_vlan_find(vg, vid); 4052594e906SNikolay Aleksandrov /* Vlan entry must be configured at this point. The 406fc92f745SVlad Yasevich * only exception is the bridge is set in promisc mode and the 407fc92f745SVlad Yasevich * packet is destined for the bridge device. In this case 408fc92f745SVlad Yasevich * pass the packet as is. 409fc92f745SVlad Yasevich */ 4102594e906SNikolay Aleksandrov if (!v || !br_vlan_should_use(v)) { 411fc92f745SVlad Yasevich if ((br->dev->flags & IFF_PROMISC) && skb->dev == br->dev) { 412fc92f745SVlad Yasevich goto out; 413fc92f745SVlad Yasevich } else { 414fc92f745SVlad Yasevich kfree_skb(skb); 415fc92f745SVlad Yasevich return NULL; 416fc92f745SVlad Yasevich } 417fc92f745SVlad Yasevich } 418ae75767eSNikolay Aleksandrov if (br_opt_get(br, BROPT_VLAN_STATS_ENABLED)) { 4196dada9b1SNikolay Aleksandrov stats = this_cpu_ptr(v->stats); 4206dada9b1SNikolay Aleksandrov u64_stats_update_begin(&stats->syncp); 4216dada9b1SNikolay Aleksandrov stats->tx_bytes += skb->len; 4226dada9b1SNikolay Aleksandrov stats->tx_packets++; 4236dada9b1SNikolay Aleksandrov u64_stats_update_end(&stats->syncp); 4246dada9b1SNikolay Aleksandrov } 4256dada9b1SNikolay Aleksandrov 4262594e906SNikolay Aleksandrov if (v->flags & BRIDGE_VLAN_INFO_UNTAGGED) 4275978f8a9SMichał Mirosław __vlan_hwaccel_clear_tag(skb); 42811538d03SRoopa Prabhu 42911538d03SRoopa Prabhu if (p && (p->flags & BR_VLAN_TUNNEL) && 43011538d03SRoopa Prabhu br_handle_egress_vlan_tunnel(skb, v)) { 43111538d03SRoopa Prabhu kfree_skb(skb); 43211538d03SRoopa Prabhu return NULL; 43311538d03SRoopa Prabhu } 43478851988SVlad Yasevich out: 43578851988SVlad Yasevich return skb; 43678851988SVlad Yasevich } 43778851988SVlad Yasevich 43878851988SVlad Yasevich /* Called under RCU */ 4396dada9b1SNikolay Aleksandrov static bool __allowed_ingress(const struct net_bridge *br, 4406dada9b1SNikolay Aleksandrov struct net_bridge_vlan_group *vg, 44178851988SVlad Yasevich struct sk_buff *skb, u16 *vid) 44278851988SVlad Yasevich { 4436dada9b1SNikolay Aleksandrov struct br_vlan_stats *stats; 4446dada9b1SNikolay Aleksandrov struct net_bridge_vlan *v; 4458580e211SToshiaki Makita bool tagged; 446a37b85c9SVlad Yasevich 44720adfa1aSVlad Yasevich BR_INPUT_SKB_CB(skb)->vlan_filtered = true; 44812464bb8SToshiaki Makita /* If vlan tx offload is disabled on bridge device and frame was 44912464bb8SToshiaki Makita * sent from vlan device on the bridge device, it does not have 45012464bb8SToshiaki Makita * HW accelerated vlan tag. 45112464bb8SToshiaki Makita */ 452df8a39deSJiri Pirko if (unlikely(!skb_vlan_tag_present(skb) && 4536dada9b1SNikolay Aleksandrov skb->protocol == br->vlan_proto)) { 4540d5501c1SVlad Yasevich skb = skb_vlan_untag(skb); 45512464bb8SToshiaki Makita if (unlikely(!skb)) 45612464bb8SToshiaki Makita return false; 45712464bb8SToshiaki Makita } 45812464bb8SToshiaki Makita 4598580e211SToshiaki Makita if (!br_vlan_get_tag(skb, vid)) { 4608580e211SToshiaki Makita /* Tagged frame */ 4616dada9b1SNikolay Aleksandrov if (skb->vlan_proto != br->vlan_proto) { 4628580e211SToshiaki Makita /* Protocol-mismatch, empty out vlan_tci for new tag */ 4638580e211SToshiaki Makita skb_push(skb, ETH_HLEN); 46462749e2cSJiri Pirko skb = vlan_insert_tag_set_proto(skb, skb->vlan_proto, 465df8a39deSJiri Pirko skb_vlan_tag_get(skb)); 4668580e211SToshiaki Makita if (unlikely(!skb)) 4678580e211SToshiaki Makita return false; 4688580e211SToshiaki Makita 4698580e211SToshiaki Makita skb_pull(skb, ETH_HLEN); 4708580e211SToshiaki Makita skb_reset_mac_len(skb); 4718580e211SToshiaki Makita *vid = 0; 4728580e211SToshiaki Makita tagged = false; 4738580e211SToshiaki Makita } else { 4748580e211SToshiaki Makita tagged = true; 4758580e211SToshiaki Makita } 4768580e211SToshiaki Makita } else { 4778580e211SToshiaki Makita /* Untagged frame */ 4788580e211SToshiaki Makita tagged = false; 4798580e211SToshiaki Makita } 4808580e211SToshiaki Makita 481b90356ceSToshiaki Makita if (!*vid) { 48277751ee8SNikolay Aleksandrov u16 pvid = br_get_pvid(vg); 48377751ee8SNikolay Aleksandrov 484b90356ceSToshiaki Makita /* Frame had a tag with VID 0 or did not have a tag. 485b90356ceSToshiaki Makita * See if pvid is set on this port. That tells us which 486b90356ceSToshiaki Makita * vlan untagged or priority-tagged traffic belongs to. 48778851988SVlad Yasevich */ 4883df6bf45SVlad Yasevich if (!pvid) 489eb707618SToshiaki Makita goto drop; 49078851988SVlad Yasevich 491b90356ceSToshiaki Makita /* PVID is set on this port. Any untagged or priority-tagged 492b90356ceSToshiaki Makita * ingress frame is considered to belong to this vlan. 49378851988SVlad Yasevich */ 494dfb5fa32SToshiaki Makita *vid = pvid; 4958580e211SToshiaki Makita if (likely(!tagged)) 496b90356ceSToshiaki Makita /* Untagged Frame. */ 4976dada9b1SNikolay Aleksandrov __vlan_hwaccel_put_tag(skb, br->vlan_proto, pvid); 498b90356ceSToshiaki Makita else 499b90356ceSToshiaki Makita /* Priority-tagged Frame. 5005978f8a9SMichał Mirosław * At this point, we know that skb->vlan_tci VID 5015978f8a9SMichał Mirosław * field was 0. 502b90356ceSToshiaki Makita * We update only VID field and preserve PCP field. 503b90356ceSToshiaki Makita */ 504b90356ceSToshiaki Makita skb->vlan_tci |= pvid; 505b90356ceSToshiaki Makita 5066dada9b1SNikolay Aleksandrov /* if stats are disabled we can avoid the lookup */ 507ae75767eSNikolay Aleksandrov if (!br_opt_get(br, BROPT_VLAN_STATS_ENABLED)) 50878851988SVlad Yasevich return true; 50978851988SVlad Yasevich } 51077751ee8SNikolay Aleksandrov v = br_vlan_find(vg, *vid); 5116dada9b1SNikolay Aleksandrov if (!v || !br_vlan_should_use(v)) 5126dada9b1SNikolay Aleksandrov goto drop; 5136dada9b1SNikolay Aleksandrov 514ae75767eSNikolay Aleksandrov if (br_opt_get(br, BROPT_VLAN_STATS_ENABLED)) { 5156dada9b1SNikolay Aleksandrov stats = this_cpu_ptr(v->stats); 5166dada9b1SNikolay Aleksandrov u64_stats_update_begin(&stats->syncp); 5176dada9b1SNikolay Aleksandrov stats->rx_bytes += skb->len; 5186dada9b1SNikolay Aleksandrov stats->rx_packets++; 5196dada9b1SNikolay Aleksandrov u64_stats_update_end(&stats->syncp); 5206dada9b1SNikolay Aleksandrov } 5216dada9b1SNikolay Aleksandrov 522a37b85c9SVlad Yasevich return true; 5236dada9b1SNikolay Aleksandrov 524eb707618SToshiaki Makita drop: 525eb707618SToshiaki Makita kfree_skb(skb); 526a37b85c9SVlad Yasevich return false; 527a37b85c9SVlad Yasevich } 528a37b85c9SVlad Yasevich 52977751ee8SNikolay Aleksandrov bool br_allowed_ingress(const struct net_bridge *br, 53077751ee8SNikolay Aleksandrov struct net_bridge_vlan_group *vg, struct sk_buff *skb, 5312594e906SNikolay Aleksandrov u16 *vid) 5322594e906SNikolay Aleksandrov { 5332594e906SNikolay Aleksandrov /* If VLAN filtering is disabled on the bridge, all packets are 5342594e906SNikolay Aleksandrov * permitted. 5352594e906SNikolay Aleksandrov */ 536ae75767eSNikolay Aleksandrov if (!br_opt_get(br, BROPT_VLAN_ENABLED)) { 5372594e906SNikolay Aleksandrov BR_INPUT_SKB_CB(skb)->vlan_filtered = false; 5382594e906SNikolay Aleksandrov return true; 5392594e906SNikolay Aleksandrov } 5402594e906SNikolay Aleksandrov 5416dada9b1SNikolay Aleksandrov return __allowed_ingress(br, vg, skb, vid); 5422594e906SNikolay Aleksandrov } 5432594e906SNikolay Aleksandrov 54485f46c6bSVlad Yasevich /* Called under RCU. */ 5452594e906SNikolay Aleksandrov bool br_allowed_egress(struct net_bridge_vlan_group *vg, 54685f46c6bSVlad Yasevich const struct sk_buff *skb) 54785f46c6bSVlad Yasevich { 5482594e906SNikolay Aleksandrov const struct net_bridge_vlan *v; 54985f46c6bSVlad Yasevich u16 vid; 55085f46c6bSVlad Yasevich 55120adfa1aSVlad Yasevich /* If this packet was not filtered at input, let it pass */ 55220adfa1aSVlad Yasevich if (!BR_INPUT_SKB_CB(skb)->vlan_filtered) 55385f46c6bSVlad Yasevich return true; 55485f46c6bSVlad Yasevich 55585f46c6bSVlad Yasevich br_vlan_get_tag(skb, &vid); 5562594e906SNikolay Aleksandrov v = br_vlan_find(vg, vid); 5572594e906SNikolay Aleksandrov if (v && br_vlan_should_use(v)) 55885f46c6bSVlad Yasevich return true; 55985f46c6bSVlad Yasevich 56085f46c6bSVlad Yasevich return false; 56185f46c6bSVlad Yasevich } 56285f46c6bSVlad Yasevich 563e0d7968aSToshiaki Makita /* Called under RCU */ 564e0d7968aSToshiaki Makita bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid) 565e0d7968aSToshiaki Makita { 566468e7944SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 567e0d7968aSToshiaki Makita struct net_bridge *br = p->br; 568e0d7968aSToshiaki Makita 56920adfa1aSVlad Yasevich /* If filtering was disabled at input, let it pass. */ 570ae75767eSNikolay Aleksandrov if (!br_opt_get(br, BROPT_VLAN_ENABLED)) 571e0d7968aSToshiaki Makita return true; 572e0d7968aSToshiaki Makita 573eca1e006SIdo Schimmel vg = nbp_vlan_group_rcu(p); 574468e7944SNikolay Aleksandrov if (!vg || !vg->num_vlans) 575e0d7968aSToshiaki Makita return false; 576e0d7968aSToshiaki Makita 5778580e211SToshiaki Makita if (!br_vlan_get_tag(skb, vid) && skb->vlan_proto != br->vlan_proto) 5788580e211SToshiaki Makita *vid = 0; 5798580e211SToshiaki Makita 580e0d7968aSToshiaki Makita if (!*vid) { 58177751ee8SNikolay Aleksandrov *vid = br_get_pvid(vg); 5823df6bf45SVlad Yasevich if (!*vid) 583e0d7968aSToshiaki Makita return false; 584e0d7968aSToshiaki Makita 585e0d7968aSToshiaki Makita return true; 586e0d7968aSToshiaki Makita } 587e0d7968aSToshiaki Makita 58877751ee8SNikolay Aleksandrov if (br_vlan_find(vg, *vid)) 589e0d7968aSToshiaki Makita return true; 590e0d7968aSToshiaki Makita 591e0d7968aSToshiaki Makita return false; 592e0d7968aSToshiaki Makita } 593e0d7968aSToshiaki Makita 594dbd6dc75SPetr Machata static int br_vlan_add_existing(struct net_bridge *br, 595dbd6dc75SPetr Machata struct net_bridge_vlan_group *vg, 596dbd6dc75SPetr Machata struct net_bridge_vlan *vlan, 597169327d5SPetr Machata u16 flags, bool *changed, 598169327d5SPetr Machata struct netlink_ext_ack *extack) 599dbd6dc75SPetr Machata { 600dbd6dc75SPetr Machata int err; 601dbd6dc75SPetr Machata 602169327d5SPetr Machata err = br_switchdev_port_vlan_add(br->dev, vlan->vid, flags, extack); 6039c86ce2cSPetr Machata if (err && err != -EOPNOTSUPP) 6049c86ce2cSPetr Machata return err; 6059c86ce2cSPetr Machata 606dbd6dc75SPetr Machata if (!br_vlan_is_brentry(vlan)) { 607dbd6dc75SPetr Machata /* Trying to change flags of non-existent bridge vlan */ 6089c86ce2cSPetr Machata if (!(flags & BRIDGE_VLAN_INFO_BRENTRY)) { 6099c86ce2cSPetr Machata err = -EINVAL; 6109c86ce2cSPetr Machata goto err_flags; 6119c86ce2cSPetr Machata } 612dbd6dc75SPetr Machata /* It was only kept for port vlans, now make it real */ 613dbd6dc75SPetr Machata err = br_fdb_insert(br, NULL, br->dev->dev_addr, 614dbd6dc75SPetr Machata vlan->vid); 615dbd6dc75SPetr Machata if (err) { 616dbd6dc75SPetr Machata br_err(br, "failed to insert local address into bridge forwarding table\n"); 6179c86ce2cSPetr Machata goto err_fdb_insert; 618dbd6dc75SPetr Machata } 619dbd6dc75SPetr Machata 620dbd6dc75SPetr Machata refcount_inc(&vlan->refcnt); 621dbd6dc75SPetr Machata vlan->flags |= BRIDGE_VLAN_INFO_BRENTRY; 622dbd6dc75SPetr Machata vg->num_vlans++; 623dbd6dc75SPetr Machata *changed = true; 624dbd6dc75SPetr Machata } 625dbd6dc75SPetr Machata 626dbd6dc75SPetr Machata if (__vlan_add_flags(vlan, flags)) 627dbd6dc75SPetr Machata *changed = true; 628dbd6dc75SPetr Machata 629dbd6dc75SPetr Machata return 0; 6309c86ce2cSPetr Machata 6319c86ce2cSPetr Machata err_fdb_insert: 6329c86ce2cSPetr Machata err_flags: 6339c86ce2cSPetr Machata br_switchdev_port_vlan_del(br->dev, vlan->vid); 6349c86ce2cSPetr Machata return err; 635dbd6dc75SPetr Machata } 636dbd6dc75SPetr Machata 6378adff41cSToshiaki Makita /* Must be protected by RTNL. 6388adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 639f418af63SNikolay Aleksandrov * changed must be true only if the vlan was created or updated 6408adff41cSToshiaki Makita */ 641169327d5SPetr Machata int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags, bool *changed, 642169327d5SPetr Machata struct netlink_ext_ack *extack) 643243a2e63SVlad Yasevich { 644907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 6452594e906SNikolay Aleksandrov struct net_bridge_vlan *vlan; 6462594e906SNikolay Aleksandrov int ret; 647243a2e63SVlad Yasevich 648243a2e63SVlad Yasevich ASSERT_RTNL(); 649243a2e63SVlad Yasevich 650f418af63SNikolay Aleksandrov *changed = false; 651907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 652907b1e6eSNikolay Aleksandrov vlan = br_vlan_find(vg, vid); 653dbd6dc75SPetr Machata if (vlan) 654169327d5SPetr Machata return br_vlan_add_existing(br, vg, vlan, flags, changed, 655169327d5SPetr Machata extack); 656243a2e63SVlad Yasevich 6572594e906SNikolay Aleksandrov vlan = kzalloc(sizeof(*vlan), GFP_KERNEL); 6582594e906SNikolay Aleksandrov if (!vlan) 659243a2e63SVlad Yasevich return -ENOMEM; 660243a2e63SVlad Yasevich 6616dada9b1SNikolay Aleksandrov vlan->stats = netdev_alloc_pcpu_stats(struct br_vlan_stats); 6626dada9b1SNikolay Aleksandrov if (!vlan->stats) { 6636dada9b1SNikolay Aleksandrov kfree(vlan); 6646dada9b1SNikolay Aleksandrov return -ENOMEM; 6656dada9b1SNikolay Aleksandrov } 6662594e906SNikolay Aleksandrov vlan->vid = vid; 6672594e906SNikolay Aleksandrov vlan->flags = flags | BRIDGE_VLAN_INFO_MASTER; 6682594e906SNikolay Aleksandrov vlan->flags &= ~BRIDGE_VLAN_INFO_PVID; 6692594e906SNikolay Aleksandrov vlan->br = br; 6702594e906SNikolay Aleksandrov if (flags & BRIDGE_VLAN_INFO_BRENTRY) 67125127759SReshetova, Elena refcount_set(&vlan->refcnt, 1); 672169327d5SPetr Machata ret = __vlan_add(vlan, flags, extack); 6736dada9b1SNikolay Aleksandrov if (ret) { 6746dada9b1SNikolay Aleksandrov free_percpu(vlan->stats); 6752594e906SNikolay Aleksandrov kfree(vlan); 676f418af63SNikolay Aleksandrov } else { 677f418af63SNikolay Aleksandrov *changed = true; 6786dada9b1SNikolay Aleksandrov } 679243a2e63SVlad Yasevich 6802594e906SNikolay Aleksandrov return ret; 681243a2e63SVlad Yasevich } 682243a2e63SVlad Yasevich 6838adff41cSToshiaki Makita /* Must be protected by RTNL. 6848adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 6858adff41cSToshiaki Makita */ 686243a2e63SVlad Yasevich int br_vlan_delete(struct net_bridge *br, u16 vid) 687243a2e63SVlad Yasevich { 688907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 6892594e906SNikolay Aleksandrov struct net_bridge_vlan *v; 690243a2e63SVlad Yasevich 691243a2e63SVlad Yasevich ASSERT_RTNL(); 692243a2e63SVlad Yasevich 693907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 694907b1e6eSNikolay Aleksandrov v = br_vlan_find(vg, vid); 6952594e906SNikolay Aleksandrov if (!v || !br_vlan_is_brentry(v)) 6962594e906SNikolay Aleksandrov return -ENOENT; 697243a2e63SVlad Yasevich 698424bb9c9SToshiaki Makita br_fdb_find_delete_local(br, NULL, br->dev->dev_addr, vid); 6993741873bSRoopa Prabhu br_fdb_delete_by_port(br, NULL, vid, 0); 700bc9a25d2SVlad Yasevich 701efa5356bSRoopa Prabhu vlan_tunnel_info_del(vg, v); 702efa5356bSRoopa Prabhu 7032594e906SNikolay Aleksandrov return __vlan_del(v); 704243a2e63SVlad Yasevich } 705243a2e63SVlad Yasevich 706243a2e63SVlad Yasevich void br_vlan_flush(struct net_bridge *br) 707243a2e63SVlad Yasevich { 708f409d0edSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 709f409d0edSNikolay Aleksandrov 710243a2e63SVlad Yasevich ASSERT_RTNL(); 711243a2e63SVlad Yasevich 712f409d0edSNikolay Aleksandrov vg = br_vlan_group(br); 713f409d0edSNikolay Aleksandrov __vlan_flush(vg); 714f409d0edSNikolay Aleksandrov RCU_INIT_POINTER(br->vlgrp, NULL); 715f409d0edSNikolay Aleksandrov synchronize_rcu(); 716f409d0edSNikolay Aleksandrov __vlan_group_free(vg); 717243a2e63SVlad Yasevich } 718243a2e63SVlad Yasevich 7192594e906SNikolay Aleksandrov struct net_bridge_vlan *br_vlan_find(struct net_bridge_vlan_group *vg, u16 vid) 7202b292fb4SToshiaki Makita { 7212594e906SNikolay Aleksandrov if (!vg) 7222594e906SNikolay Aleksandrov return NULL; 7232b292fb4SToshiaki Makita 7242594e906SNikolay Aleksandrov return br_vlan_lookup(&vg->vlan_hash, vid); 7252b292fb4SToshiaki Makita } 7262b292fb4SToshiaki Makita 727204177f3SToshiaki Makita /* Must be protected by RTNL. */ 728204177f3SToshiaki Makita static void recalculate_group_addr(struct net_bridge *br) 729204177f3SToshiaki Makita { 730be3664a0SNikolay Aleksandrov if (br_opt_get(br, BROPT_GROUP_ADDR_SET)) 731204177f3SToshiaki Makita return; 732204177f3SToshiaki Makita 733204177f3SToshiaki Makita spin_lock_bh(&br->lock); 734ae75767eSNikolay Aleksandrov if (!br_opt_get(br, BROPT_VLAN_ENABLED) || 735ae75767eSNikolay Aleksandrov br->vlan_proto == htons(ETH_P_8021Q)) { 736204177f3SToshiaki Makita /* Bridge Group Address */ 737204177f3SToshiaki Makita br->group_addr[5] = 0x00; 738204177f3SToshiaki Makita } else { /* vlan_enabled && ETH_P_8021AD */ 739204177f3SToshiaki Makita /* Provider Bridge Group Address */ 740204177f3SToshiaki Makita br->group_addr[5] = 0x08; 741204177f3SToshiaki Makita } 742204177f3SToshiaki Makita spin_unlock_bh(&br->lock); 743204177f3SToshiaki Makita } 744204177f3SToshiaki Makita 745204177f3SToshiaki Makita /* Must be protected by RTNL. */ 746204177f3SToshiaki Makita void br_recalculate_fwd_mask(struct net_bridge *br) 747204177f3SToshiaki Makita { 748ae75767eSNikolay Aleksandrov if (!br_opt_get(br, BROPT_VLAN_ENABLED) || 749ae75767eSNikolay Aleksandrov br->vlan_proto == htons(ETH_P_8021Q)) 750204177f3SToshiaki Makita br->group_fwd_mask_required = BR_GROUPFWD_DEFAULT; 751204177f3SToshiaki Makita else /* vlan_enabled && ETH_P_8021AD */ 752204177f3SToshiaki Makita br->group_fwd_mask_required = BR_GROUPFWD_8021AD & 753204177f3SToshiaki Makita ~(1u << br->group_addr[5]); 754204177f3SToshiaki Makita } 755204177f3SToshiaki Makita 756a7854037SNikolay Aleksandrov int __br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) 757243a2e63SVlad Yasevich { 7586b72a770SElad Raz struct switchdev_attr attr = { 7596b72a770SElad Raz .orig_dev = br->dev, 7606b72a770SElad Raz .id = SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING, 7616b72a770SElad Raz .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP, 7626b72a770SElad Raz .u.vlan_filtering = val, 7636b72a770SElad Raz }; 7646b72a770SElad Raz int err; 7656b72a770SElad Raz 766ae75767eSNikolay Aleksandrov if (br_opt_get(br, BROPT_VLAN_ENABLED) == !!val) 767a7854037SNikolay Aleksandrov return 0; 768243a2e63SVlad Yasevich 7696b72a770SElad Raz err = switchdev_port_attr_set(br->dev, &attr); 7706b72a770SElad Raz if (err && err != -EOPNOTSUPP) 7716b72a770SElad Raz return err; 7726b72a770SElad Raz 773ae75767eSNikolay Aleksandrov br_opt_toggle(br, BROPT_VLAN_ENABLED, !!val); 7742796d0c6SVlad Yasevich br_manage_promisc(br); 775204177f3SToshiaki Makita recalculate_group_addr(br); 776204177f3SToshiaki Makita br_recalculate_fwd_mask(br); 777243a2e63SVlad Yasevich 778a7854037SNikolay Aleksandrov return 0; 779a7854037SNikolay Aleksandrov } 780a7854037SNikolay Aleksandrov 781a7854037SNikolay Aleksandrov int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) 782a7854037SNikolay Aleksandrov { 783047831a9SXin Long return __br_vlan_filter_toggle(br, val); 784243a2e63SVlad Yasevich } 785243a2e63SVlad Yasevich 7861f51445aSIdo Schimmel bool br_vlan_enabled(const struct net_device *dev) 7871f51445aSIdo Schimmel { 7881f51445aSIdo Schimmel struct net_bridge *br = netdev_priv(dev); 7891f51445aSIdo Schimmel 790ae75767eSNikolay Aleksandrov return br_opt_get(br, BROPT_VLAN_ENABLED); 7911f51445aSIdo Schimmel } 7921f51445aSIdo Schimmel EXPORT_SYMBOL_GPL(br_vlan_enabled); 7931f51445aSIdo Schimmel 794d2d427b3SToshiaki Makita int __br_vlan_set_proto(struct net_bridge *br, __be16 proto) 795204177f3SToshiaki Makita { 796204177f3SToshiaki Makita int err = 0; 797204177f3SToshiaki Makita struct net_bridge_port *p; 7982594e906SNikolay Aleksandrov struct net_bridge_vlan *vlan; 799907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 800d2d427b3SToshiaki Makita __be16 oldproto; 801204177f3SToshiaki Makita 802204177f3SToshiaki Makita if (br->vlan_proto == proto) 803d2d427b3SToshiaki Makita return 0; 804204177f3SToshiaki Makita 805204177f3SToshiaki Makita /* Add VLANs for the new proto to the device filter. */ 806204177f3SToshiaki Makita list_for_each_entry(p, &br->port_list, list) { 807907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 808907b1e6eSNikolay Aleksandrov list_for_each_entry(vlan, &vg->vlan_list, vlist) { 8092594e906SNikolay Aleksandrov err = vlan_vid_add(p->dev, proto, vlan->vid); 810204177f3SToshiaki Makita if (err) 811204177f3SToshiaki Makita goto err_filt; 812204177f3SToshiaki Makita } 813204177f3SToshiaki Makita } 814204177f3SToshiaki Makita 815204177f3SToshiaki Makita oldproto = br->vlan_proto; 816204177f3SToshiaki Makita br->vlan_proto = proto; 817204177f3SToshiaki Makita 818204177f3SToshiaki Makita recalculate_group_addr(br); 819204177f3SToshiaki Makita br_recalculate_fwd_mask(br); 820204177f3SToshiaki Makita 821204177f3SToshiaki Makita /* Delete VLANs for the old proto from the device filter. */ 822907b1e6eSNikolay Aleksandrov 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 vlan_vid_del(p->dev, oldproto, vlan->vid); 826907b1e6eSNikolay Aleksandrov } 827204177f3SToshiaki Makita 828d2d427b3SToshiaki Makita return 0; 829204177f3SToshiaki Makita 830204177f3SToshiaki Makita err_filt: 831907b1e6eSNikolay Aleksandrov list_for_each_entry_continue_reverse(vlan, &vg->vlan_list, vlist) 8322594e906SNikolay Aleksandrov vlan_vid_del(p->dev, proto, vlan->vid); 833204177f3SToshiaki Makita 834907b1e6eSNikolay Aleksandrov list_for_each_entry_continue_reverse(p, &br->port_list, list) { 835907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 836907b1e6eSNikolay Aleksandrov list_for_each_entry(vlan, &vg->vlan_list, vlist) 8372594e906SNikolay Aleksandrov vlan_vid_del(p->dev, proto, vlan->vid); 838907b1e6eSNikolay Aleksandrov } 839204177f3SToshiaki Makita 840d2d427b3SToshiaki Makita return err; 841d2d427b3SToshiaki Makita } 842d2d427b3SToshiaki Makita 843d2d427b3SToshiaki Makita int br_vlan_set_proto(struct net_bridge *br, unsigned long val) 844d2d427b3SToshiaki Makita { 845d2d427b3SToshiaki Makita if (val != ETH_P_8021Q && val != ETH_P_8021AD) 846d2d427b3SToshiaki Makita return -EPROTONOSUPPORT; 847d2d427b3SToshiaki Makita 848047831a9SXin Long return __br_vlan_set_proto(br, htons(val)); 849204177f3SToshiaki Makita } 850204177f3SToshiaki Makita 8516dada9b1SNikolay Aleksandrov int br_vlan_set_stats(struct net_bridge *br, unsigned long val) 8526dada9b1SNikolay Aleksandrov { 8536dada9b1SNikolay Aleksandrov switch (val) { 8546dada9b1SNikolay Aleksandrov case 0: 8556dada9b1SNikolay Aleksandrov case 1: 856ae75767eSNikolay Aleksandrov br_opt_toggle(br, BROPT_VLAN_STATS_ENABLED, !!val); 8576dada9b1SNikolay Aleksandrov break; 8586dada9b1SNikolay Aleksandrov default: 8596dada9b1SNikolay Aleksandrov return -EINVAL; 8606dada9b1SNikolay Aleksandrov } 8616dada9b1SNikolay Aleksandrov 8626dada9b1SNikolay Aleksandrov return 0; 8636dada9b1SNikolay Aleksandrov } 8646dada9b1SNikolay Aleksandrov 8659163a0fcSNikolay Aleksandrov int br_vlan_set_stats_per_port(struct net_bridge *br, unsigned long val) 8669163a0fcSNikolay Aleksandrov { 8679163a0fcSNikolay Aleksandrov struct net_bridge_port *p; 8689163a0fcSNikolay Aleksandrov 8699163a0fcSNikolay Aleksandrov /* allow to change the option if there are no port vlans configured */ 8709163a0fcSNikolay Aleksandrov list_for_each_entry(p, &br->port_list, list) { 8719163a0fcSNikolay Aleksandrov struct net_bridge_vlan_group *vg = nbp_vlan_group(p); 8729163a0fcSNikolay Aleksandrov 8739163a0fcSNikolay Aleksandrov if (vg->num_vlans) 8749163a0fcSNikolay Aleksandrov return -EBUSY; 8759163a0fcSNikolay Aleksandrov } 8769163a0fcSNikolay Aleksandrov 8779163a0fcSNikolay Aleksandrov switch (val) { 8789163a0fcSNikolay Aleksandrov case 0: 8799163a0fcSNikolay Aleksandrov case 1: 8809163a0fcSNikolay Aleksandrov br_opt_toggle(br, BROPT_VLAN_STATS_PER_PORT, !!val); 8819163a0fcSNikolay Aleksandrov break; 8829163a0fcSNikolay Aleksandrov default: 8839163a0fcSNikolay Aleksandrov return -EINVAL; 8849163a0fcSNikolay Aleksandrov } 8859163a0fcSNikolay Aleksandrov 8869163a0fcSNikolay Aleksandrov return 0; 8879163a0fcSNikolay Aleksandrov } 8889163a0fcSNikolay Aleksandrov 88977751ee8SNikolay Aleksandrov static bool vlan_default_pvid(struct net_bridge_vlan_group *vg, u16 vid) 8905be5a2dfSVlad Yasevich { 8912594e906SNikolay Aleksandrov struct net_bridge_vlan *v; 8922594e906SNikolay Aleksandrov 89377751ee8SNikolay Aleksandrov if (vid != vg->pvid) 8942594e906SNikolay Aleksandrov return false; 8952594e906SNikolay Aleksandrov 8962594e906SNikolay Aleksandrov v = br_vlan_lookup(&vg->vlan_hash, vid); 8972594e906SNikolay Aleksandrov if (v && br_vlan_should_use(v) && 8982594e906SNikolay Aleksandrov (v->flags & BRIDGE_VLAN_INFO_UNTAGGED)) 8992594e906SNikolay Aleksandrov return true; 9002594e906SNikolay Aleksandrov 9012594e906SNikolay Aleksandrov return false; 9025be5a2dfSVlad Yasevich } 9035be5a2dfSVlad Yasevich 9045be5a2dfSVlad Yasevich static void br_vlan_disable_default_pvid(struct net_bridge *br) 9055be5a2dfSVlad Yasevich { 9065be5a2dfSVlad Yasevich struct net_bridge_port *p; 9075be5a2dfSVlad Yasevich u16 pvid = br->default_pvid; 9085be5a2dfSVlad Yasevich 9095be5a2dfSVlad Yasevich /* Disable default_pvid on all ports where it is still 9105be5a2dfSVlad Yasevich * configured. 9115be5a2dfSVlad Yasevich */ 912907b1e6eSNikolay Aleksandrov if (vlan_default_pvid(br_vlan_group(br), pvid)) 9135be5a2dfSVlad Yasevich br_vlan_delete(br, pvid); 9145be5a2dfSVlad Yasevich 9155be5a2dfSVlad Yasevich list_for_each_entry(p, &br->port_list, list) { 916907b1e6eSNikolay Aleksandrov if (vlan_default_pvid(nbp_vlan_group(p), pvid)) 9175be5a2dfSVlad Yasevich nbp_vlan_delete(p, pvid); 9185be5a2dfSVlad Yasevich } 9195be5a2dfSVlad Yasevich 9205be5a2dfSVlad Yasevich br->default_pvid = 0; 9215be5a2dfSVlad Yasevich } 9225be5a2dfSVlad Yasevich 923169327d5SPetr Machata int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid, 924169327d5SPetr Machata struct netlink_ext_ack *extack) 9255be5a2dfSVlad Yasevich { 9262594e906SNikolay Aleksandrov const struct net_bridge_vlan *pvent; 927907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 9285be5a2dfSVlad Yasevich struct net_bridge_port *p; 929f418af63SNikolay Aleksandrov unsigned long *changed; 930f418af63SNikolay Aleksandrov bool vlchange; 9315be5a2dfSVlad Yasevich u16 old_pvid; 9325be5a2dfSVlad Yasevich int err = 0; 9335be5a2dfSVlad Yasevich 9340f963b75SNikolay Aleksandrov if (!pvid) { 9350f963b75SNikolay Aleksandrov br_vlan_disable_default_pvid(br); 9360f963b75SNikolay Aleksandrov return 0; 9370f963b75SNikolay Aleksandrov } 9380f963b75SNikolay Aleksandrov 939459479daSAndy Shevchenko changed = bitmap_zalloc(BR_MAX_PORTS, GFP_KERNEL); 9405be5a2dfSVlad Yasevich if (!changed) 9415be5a2dfSVlad Yasevich return -ENOMEM; 9425be5a2dfSVlad Yasevich 9435be5a2dfSVlad Yasevich old_pvid = br->default_pvid; 9445be5a2dfSVlad Yasevich 9455be5a2dfSVlad Yasevich /* Update default_pvid config only if we do not conflict with 9465be5a2dfSVlad Yasevich * user configuration. 9475be5a2dfSVlad Yasevich */ 948907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 949907b1e6eSNikolay Aleksandrov pvent = br_vlan_find(vg, pvid); 950907b1e6eSNikolay Aleksandrov if ((!old_pvid || vlan_default_pvid(vg, old_pvid)) && 9512594e906SNikolay Aleksandrov (!pvent || !br_vlan_should_use(pvent))) { 9525be5a2dfSVlad Yasevich err = br_vlan_add(br, pvid, 9535be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_PVID | 9542594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED | 955f418af63SNikolay Aleksandrov BRIDGE_VLAN_INFO_BRENTRY, 956169327d5SPetr Machata &vlchange, extack); 9575be5a2dfSVlad Yasevich if (err) 9585be5a2dfSVlad Yasevich goto out; 9595be5a2dfSVlad Yasevich br_vlan_delete(br, old_pvid); 9605be5a2dfSVlad Yasevich set_bit(0, changed); 9615be5a2dfSVlad Yasevich } 9625be5a2dfSVlad Yasevich 9635be5a2dfSVlad Yasevich list_for_each_entry(p, &br->port_list, list) { 9645be5a2dfSVlad Yasevich /* Update default_pvid config only if we do not conflict with 9655be5a2dfSVlad Yasevich * user configuration. 9665be5a2dfSVlad Yasevich */ 967907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 9685be5a2dfSVlad Yasevich if ((old_pvid && 969907b1e6eSNikolay Aleksandrov !vlan_default_pvid(vg, old_pvid)) || 970907b1e6eSNikolay Aleksandrov br_vlan_find(vg, pvid)) 9715be5a2dfSVlad Yasevich continue; 9725be5a2dfSVlad Yasevich 9735be5a2dfSVlad Yasevich err = nbp_vlan_add(p, pvid, 9745be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_PVID | 975f418af63SNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED, 976169327d5SPetr Machata &vlchange, extack); 9775be5a2dfSVlad Yasevich if (err) 9785be5a2dfSVlad Yasevich goto err_port; 9795be5a2dfSVlad Yasevich nbp_vlan_delete(p, old_pvid); 9805be5a2dfSVlad Yasevich set_bit(p->port_no, changed); 9815be5a2dfSVlad Yasevich } 9825be5a2dfSVlad Yasevich 9835be5a2dfSVlad Yasevich br->default_pvid = pvid; 9845be5a2dfSVlad Yasevich 9855be5a2dfSVlad Yasevich out: 986459479daSAndy Shevchenko bitmap_free(changed); 9875be5a2dfSVlad Yasevich return err; 9885be5a2dfSVlad Yasevich 9895be5a2dfSVlad Yasevich err_port: 9905be5a2dfSVlad Yasevich list_for_each_entry_continue_reverse(p, &br->port_list, list) { 9915be5a2dfSVlad Yasevich if (!test_bit(p->port_no, changed)) 9925be5a2dfSVlad Yasevich continue; 9935be5a2dfSVlad Yasevich 9945be5a2dfSVlad Yasevich if (old_pvid) 9955be5a2dfSVlad Yasevich nbp_vlan_add(p, old_pvid, 9965be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_PVID | 997f418af63SNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED, 998169327d5SPetr Machata &vlchange, NULL); 9995be5a2dfSVlad Yasevich nbp_vlan_delete(p, pvid); 10005be5a2dfSVlad Yasevich } 10015be5a2dfSVlad Yasevich 10025be5a2dfSVlad Yasevich if (test_bit(0, changed)) { 10035be5a2dfSVlad Yasevich if (old_pvid) 10045be5a2dfSVlad Yasevich br_vlan_add(br, old_pvid, 10055be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_PVID | 10062594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED | 1007f418af63SNikolay Aleksandrov BRIDGE_VLAN_INFO_BRENTRY, 1008169327d5SPetr Machata &vlchange, NULL); 10095be5a2dfSVlad Yasevich br_vlan_delete(br, pvid); 10105be5a2dfSVlad Yasevich } 10115be5a2dfSVlad Yasevich goto out; 10125be5a2dfSVlad Yasevich } 10135be5a2dfSVlad Yasevich 101496a20d9dSVlad Yasevich int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val) 101596a20d9dSVlad Yasevich { 101696a20d9dSVlad Yasevich u16 pvid = val; 101796a20d9dSVlad Yasevich int err = 0; 101896a20d9dSVlad Yasevich 10195be5a2dfSVlad Yasevich if (val >= VLAN_VID_MASK) 102096a20d9dSVlad Yasevich return -EINVAL; 102196a20d9dSVlad Yasevich 102296a20d9dSVlad Yasevich if (pvid == br->default_pvid) 1023047831a9SXin Long goto out; 102496a20d9dSVlad Yasevich 102596a20d9dSVlad Yasevich /* Only allow default pvid change when filtering is disabled */ 1026ae75767eSNikolay Aleksandrov if (br_opt_get(br, BROPT_VLAN_ENABLED)) { 102796a20d9dSVlad Yasevich pr_info_once("Please disable vlan filtering to change default_pvid\n"); 102896a20d9dSVlad Yasevich err = -EPERM; 1029047831a9SXin Long goto out; 103096a20d9dSVlad Yasevich } 1031169327d5SPetr Machata err = __br_vlan_set_default_pvid(br, pvid, NULL); 1032047831a9SXin Long out: 103396a20d9dSVlad Yasevich return err; 103496a20d9dSVlad Yasevich } 103596a20d9dSVlad Yasevich 10365be5a2dfSVlad Yasevich int br_vlan_init(struct net_bridge *br) 10378580e211SToshiaki Makita { 1038907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 10392594e906SNikolay Aleksandrov int ret = -ENOMEM; 1040f418af63SNikolay Aleksandrov bool changed; 10412594e906SNikolay Aleksandrov 1042907b1e6eSNikolay Aleksandrov vg = kzalloc(sizeof(*vg), GFP_KERNEL); 1043907b1e6eSNikolay Aleksandrov if (!vg) 10442594e906SNikolay Aleksandrov goto out; 1045907b1e6eSNikolay Aleksandrov ret = rhashtable_init(&vg->vlan_hash, &br_vlan_rht_params); 10462594e906SNikolay Aleksandrov if (ret) 10472594e906SNikolay Aleksandrov goto err_rhtbl; 1048efa5356bSRoopa Prabhu ret = vlan_tunnel_init(vg); 1049efa5356bSRoopa Prabhu if (ret) 1050efa5356bSRoopa Prabhu goto err_tunnel_init; 1051907b1e6eSNikolay Aleksandrov INIT_LIST_HEAD(&vg->vlan_list); 10528580e211SToshiaki Makita br->vlan_proto = htons(ETH_P_8021Q); 105396a20d9dSVlad Yasevich br->default_pvid = 1; 1054907b1e6eSNikolay Aleksandrov rcu_assign_pointer(br->vlgrp, vg); 10552594e906SNikolay Aleksandrov ret = br_vlan_add(br, 1, 10562594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_PVID | BRIDGE_VLAN_INFO_UNTAGGED | 1057169327d5SPetr Machata BRIDGE_VLAN_INFO_BRENTRY, &changed, NULL); 10582594e906SNikolay Aleksandrov if (ret) 10592594e906SNikolay Aleksandrov goto err_vlan_add; 10602594e906SNikolay Aleksandrov 10612594e906SNikolay Aleksandrov out: 10622594e906SNikolay Aleksandrov return ret; 10632594e906SNikolay Aleksandrov 10642594e906SNikolay Aleksandrov err_vlan_add: 1065efa5356bSRoopa Prabhu vlan_tunnel_deinit(vg); 1066efa5356bSRoopa Prabhu err_tunnel_init: 1067907b1e6eSNikolay Aleksandrov rhashtable_destroy(&vg->vlan_hash); 10682594e906SNikolay Aleksandrov err_rhtbl: 1069907b1e6eSNikolay Aleksandrov kfree(vg); 10702594e906SNikolay Aleksandrov 10712594e906SNikolay Aleksandrov goto out; 10722594e906SNikolay Aleksandrov } 10732594e906SNikolay Aleksandrov 1074169327d5SPetr Machata int nbp_vlan_init(struct net_bridge_port *p, struct netlink_ext_ack *extack) 10752594e906SNikolay Aleksandrov { 1076404cdbf0SElad Raz struct switchdev_attr attr = { 1077404cdbf0SElad Raz .orig_dev = p->br->dev, 1078404cdbf0SElad Raz .id = SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING, 1079404cdbf0SElad Raz .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP, 1080ae75767eSNikolay Aleksandrov .u.vlan_filtering = br_opt_get(p->br, BROPT_VLAN_ENABLED), 1081404cdbf0SElad Raz }; 1082263344e6SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 10832594e906SNikolay Aleksandrov int ret = -ENOMEM; 10842594e906SNikolay Aleksandrov 1085263344e6SNikolay Aleksandrov vg = kzalloc(sizeof(struct net_bridge_vlan_group), GFP_KERNEL); 1086263344e6SNikolay Aleksandrov if (!vg) 10872594e906SNikolay Aleksandrov goto out; 10882594e906SNikolay Aleksandrov 1089404cdbf0SElad Raz ret = switchdev_port_attr_set(p->dev, &attr); 1090404cdbf0SElad Raz if (ret && ret != -EOPNOTSUPP) 1091404cdbf0SElad Raz goto err_vlan_enabled; 1092404cdbf0SElad Raz 1093263344e6SNikolay Aleksandrov ret = rhashtable_init(&vg->vlan_hash, &br_vlan_rht_params); 10942594e906SNikolay Aleksandrov if (ret) 10952594e906SNikolay Aleksandrov goto err_rhtbl; 1096efa5356bSRoopa Prabhu ret = vlan_tunnel_init(vg); 1097efa5356bSRoopa Prabhu if (ret) 1098efa5356bSRoopa Prabhu goto err_tunnel_init; 1099263344e6SNikolay Aleksandrov INIT_LIST_HEAD(&vg->vlan_list); 1100907b1e6eSNikolay Aleksandrov rcu_assign_pointer(p->vlgrp, vg); 11012594e906SNikolay Aleksandrov if (p->br->default_pvid) { 1102f418af63SNikolay Aleksandrov bool changed; 1103f418af63SNikolay Aleksandrov 11042594e906SNikolay Aleksandrov ret = nbp_vlan_add(p, p->br->default_pvid, 11052594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_PVID | 1106f418af63SNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED, 1107169327d5SPetr Machata &changed, extack); 11082594e906SNikolay Aleksandrov if (ret) 11092594e906SNikolay Aleksandrov goto err_vlan_add; 11102594e906SNikolay Aleksandrov } 11112594e906SNikolay Aleksandrov out: 11122594e906SNikolay Aleksandrov return ret; 11132594e906SNikolay Aleksandrov 11142594e906SNikolay Aleksandrov err_vlan_add: 111507bc588fSIdo Schimmel RCU_INIT_POINTER(p->vlgrp, NULL); 111607bc588fSIdo Schimmel synchronize_rcu(); 1117efa5356bSRoopa Prabhu vlan_tunnel_deinit(vg); 1118efa5356bSRoopa Prabhu err_tunnel_init: 1119efa5356bSRoopa Prabhu rhashtable_destroy(&vg->vlan_hash); 11202594e906SNikolay Aleksandrov err_rhtbl: 1121df2c4334SYotam Gigi err_vlan_enabled: 1122263344e6SNikolay Aleksandrov kfree(vg); 11232594e906SNikolay Aleksandrov 11242594e906SNikolay Aleksandrov goto out; 11258580e211SToshiaki Makita } 11268580e211SToshiaki Makita 11278adff41cSToshiaki Makita /* Must be protected by RTNL. 11288adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 1129f418af63SNikolay Aleksandrov * changed must be true only if the vlan was created or updated 11308adff41cSToshiaki Makita */ 1131f418af63SNikolay Aleksandrov int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags, 1132169327d5SPetr Machata bool *changed, struct netlink_ext_ack *extack) 1133243a2e63SVlad Yasevich { 11342594e906SNikolay Aleksandrov struct net_bridge_vlan *vlan; 11352594e906SNikolay Aleksandrov int ret; 1136243a2e63SVlad Yasevich 1137243a2e63SVlad Yasevich ASSERT_RTNL(); 1138243a2e63SVlad Yasevich 1139f418af63SNikolay Aleksandrov *changed = false; 1140907b1e6eSNikolay Aleksandrov vlan = br_vlan_find(nbp_vlan_group(port), vid); 11412594e906SNikolay Aleksandrov if (vlan) { 11427fbac984SIdo Schimmel /* Pass the flags to the hardware bridge */ 1143169327d5SPetr Machata ret = br_switchdev_port_vlan_add(port->dev, vid, flags, extack); 11447fbac984SIdo Schimmel if (ret && ret != -EOPNOTSUPP) 11457fbac984SIdo Schimmel return ret; 1146f418af63SNikolay Aleksandrov *changed = __vlan_add_flags(vlan, flags); 1147f418af63SNikolay Aleksandrov 11482594e906SNikolay Aleksandrov return 0; 1149243a2e63SVlad Yasevich } 1150243a2e63SVlad Yasevich 11512594e906SNikolay Aleksandrov vlan = kzalloc(sizeof(*vlan), GFP_KERNEL); 11522594e906SNikolay Aleksandrov if (!vlan) 11532594e906SNikolay Aleksandrov return -ENOMEM; 1154243a2e63SVlad Yasevich 11552594e906SNikolay Aleksandrov vlan->vid = vid; 11562594e906SNikolay Aleksandrov vlan->port = port; 1157169327d5SPetr Machata ret = __vlan_add(vlan, flags, extack); 11582594e906SNikolay Aleksandrov if (ret) 11592594e906SNikolay Aleksandrov kfree(vlan); 1160f418af63SNikolay Aleksandrov else 1161f418af63SNikolay Aleksandrov *changed = true; 1162243a2e63SVlad Yasevich 11632594e906SNikolay Aleksandrov return ret; 1164243a2e63SVlad Yasevich } 1165243a2e63SVlad Yasevich 11668adff41cSToshiaki Makita /* Must be protected by RTNL. 11678adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 11688adff41cSToshiaki Makita */ 1169243a2e63SVlad Yasevich int nbp_vlan_delete(struct net_bridge_port *port, u16 vid) 1170243a2e63SVlad Yasevich { 11712594e906SNikolay Aleksandrov struct net_bridge_vlan *v; 1172243a2e63SVlad Yasevich 1173243a2e63SVlad Yasevich ASSERT_RTNL(); 1174243a2e63SVlad Yasevich 1175907b1e6eSNikolay Aleksandrov v = br_vlan_find(nbp_vlan_group(port), vid); 11762594e906SNikolay Aleksandrov if (!v) 11772594e906SNikolay Aleksandrov return -ENOENT; 1178424bb9c9SToshiaki Makita br_fdb_find_delete_local(port->br, port, port->dev->dev_addr, vid); 11791ea2d020SNikolay Aleksandrov br_fdb_delete_by_port(port->br, port, vid, 0); 1180bc9a25d2SVlad Yasevich 11812594e906SNikolay Aleksandrov return __vlan_del(v); 1182243a2e63SVlad Yasevich } 1183243a2e63SVlad Yasevich 1184243a2e63SVlad Yasevich void nbp_vlan_flush(struct net_bridge_port *port) 1185243a2e63SVlad Yasevich { 1186f409d0edSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 1187f409d0edSNikolay Aleksandrov 1188243a2e63SVlad Yasevich ASSERT_RTNL(); 1189243a2e63SVlad Yasevich 1190f409d0edSNikolay Aleksandrov vg = nbp_vlan_group(port); 1191f409d0edSNikolay Aleksandrov __vlan_flush(vg); 1192f409d0edSNikolay Aleksandrov RCU_INIT_POINTER(port->vlgrp, NULL); 1193f409d0edSNikolay Aleksandrov synchronize_rcu(); 1194f409d0edSNikolay Aleksandrov __vlan_group_free(vg); 11955be5a2dfSVlad Yasevich } 1196a60c0903SNikolay Aleksandrov 1197a60c0903SNikolay Aleksandrov void br_vlan_get_stats(const struct net_bridge_vlan *v, 1198a60c0903SNikolay Aleksandrov struct br_vlan_stats *stats) 1199a60c0903SNikolay Aleksandrov { 1200a60c0903SNikolay Aleksandrov int i; 1201a60c0903SNikolay Aleksandrov 1202a60c0903SNikolay Aleksandrov memset(stats, 0, sizeof(*stats)); 1203a60c0903SNikolay Aleksandrov for_each_possible_cpu(i) { 1204a60c0903SNikolay Aleksandrov u64 rxpackets, rxbytes, txpackets, txbytes; 1205a60c0903SNikolay Aleksandrov struct br_vlan_stats *cpu_stats; 1206a60c0903SNikolay Aleksandrov unsigned int start; 1207a60c0903SNikolay Aleksandrov 1208a60c0903SNikolay Aleksandrov cpu_stats = per_cpu_ptr(v->stats, i); 1209a60c0903SNikolay Aleksandrov do { 1210a60c0903SNikolay Aleksandrov start = u64_stats_fetch_begin_irq(&cpu_stats->syncp); 1211a60c0903SNikolay Aleksandrov rxpackets = cpu_stats->rx_packets; 1212a60c0903SNikolay Aleksandrov rxbytes = cpu_stats->rx_bytes; 1213a60c0903SNikolay Aleksandrov txbytes = cpu_stats->tx_bytes; 1214a60c0903SNikolay Aleksandrov txpackets = cpu_stats->tx_packets; 1215a60c0903SNikolay Aleksandrov } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start)); 1216a60c0903SNikolay Aleksandrov 1217a60c0903SNikolay Aleksandrov stats->rx_packets += rxpackets; 1218a60c0903SNikolay Aleksandrov stats->rx_bytes += rxbytes; 1219a60c0903SNikolay Aleksandrov stats->tx_bytes += txbytes; 1220a60c0903SNikolay Aleksandrov stats->tx_packets += txpackets; 1221a60c0903SNikolay Aleksandrov } 1222a60c0903SNikolay Aleksandrov } 12234d4fd361SPetr Machata 12244d4fd361SPetr Machata int br_vlan_get_pvid(const struct net_device *dev, u16 *p_pvid) 12254d4fd361SPetr Machata { 12264d4fd361SPetr Machata struct net_bridge_vlan_group *vg; 12275a6db04cSIdo Schimmel struct net_bridge_port *p; 12284d4fd361SPetr Machata 12294d4fd361SPetr Machata ASSERT_RTNL(); 12305a6db04cSIdo Schimmel p = br_port_get_check_rtnl(dev); 12315a6db04cSIdo Schimmel if (p) 12325a6db04cSIdo Schimmel vg = nbp_vlan_group(p); 12335a6db04cSIdo Schimmel else if (netif_is_bridge_master(dev)) 12344d4fd361SPetr Machata vg = br_vlan_group(netdev_priv(dev)); 12354d4fd361SPetr Machata else 12364d4fd361SPetr Machata return -EINVAL; 12374d4fd361SPetr Machata 12384d4fd361SPetr Machata *p_pvid = br_get_pvid(vg); 12394d4fd361SPetr Machata return 0; 12404d4fd361SPetr Machata } 12414d4fd361SPetr Machata EXPORT_SYMBOL_GPL(br_vlan_get_pvid); 12424d4fd361SPetr Machata 12434d4fd361SPetr Machata int br_vlan_get_info(const struct net_device *dev, u16 vid, 12444d4fd361SPetr Machata struct bridge_vlan_info *p_vinfo) 12454d4fd361SPetr Machata { 12464d4fd361SPetr Machata struct net_bridge_vlan_group *vg; 12474d4fd361SPetr Machata struct net_bridge_vlan *v; 12484d4fd361SPetr Machata struct net_bridge_port *p; 12494d4fd361SPetr Machata 12504d4fd361SPetr Machata ASSERT_RTNL(); 12514d4fd361SPetr Machata p = br_port_get_check_rtnl(dev); 12524d4fd361SPetr Machata if (p) 12534d4fd361SPetr Machata vg = nbp_vlan_group(p); 12542b18d79eSPetr Machata else if (netif_is_bridge_master(dev)) 12552b18d79eSPetr Machata vg = br_vlan_group(netdev_priv(dev)); 12564d4fd361SPetr Machata else 12574d4fd361SPetr Machata return -EINVAL; 12584d4fd361SPetr Machata 12594d4fd361SPetr Machata v = br_vlan_find(vg, vid); 12604d4fd361SPetr Machata if (!v) 12614d4fd361SPetr Machata return -ENOENT; 12624d4fd361SPetr Machata 12634d4fd361SPetr Machata p_vinfo->vid = vid; 12644d4fd361SPetr Machata p_vinfo->flags = v->flags; 12654d4fd361SPetr Machata return 0; 12664d4fd361SPetr Machata } 12674d4fd361SPetr Machata EXPORT_SYMBOL_GPL(br_vlan_get_info); 1268