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 37a580c76dSNikolay Aleksandrov static bool __vlan_add_pvid(struct net_bridge_vlan_group *vg, 38a580c76dSNikolay Aleksandrov const struct net_bridge_vlan *v) 392594e906SNikolay Aleksandrov { 40a580c76dSNikolay Aleksandrov if (vg->pvid == v->vid) 41f418af63SNikolay Aleksandrov return false; 42552406c4SVlad Yasevich 43552406c4SVlad Yasevich smp_wmb(); 44a580c76dSNikolay Aleksandrov br_vlan_set_pvid_state(vg, v->state); 45a580c76dSNikolay Aleksandrov vg->pvid = v->vid; 46f418af63SNikolay Aleksandrov 47f418af63SNikolay Aleksandrov return true; 48552406c4SVlad Yasevich } 49552406c4SVlad Yasevich 50f418af63SNikolay Aleksandrov static bool __vlan_delete_pvid(struct net_bridge_vlan_group *vg, u16 vid) 51552406c4SVlad Yasevich { 5277751ee8SNikolay Aleksandrov if (vg->pvid != vid) 53f418af63SNikolay Aleksandrov return false; 54552406c4SVlad Yasevich 55552406c4SVlad Yasevich smp_wmb(); 5677751ee8SNikolay Aleksandrov vg->pvid = 0; 57f418af63SNikolay Aleksandrov 58f418af63SNikolay Aleksandrov return true; 59552406c4SVlad Yasevich } 60552406c4SVlad Yasevich 61f418af63SNikolay Aleksandrov /* return true if anything changed, false otherwise */ 62f418af63SNikolay Aleksandrov static bool __vlan_add_flags(struct net_bridge_vlan *v, u16 flags) 6335e03f3aSVlad Yasevich { 6477751ee8SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 65f418af63SNikolay Aleksandrov u16 old_flags = v->flags; 66f418af63SNikolay Aleksandrov bool ret; 6777751ee8SNikolay Aleksandrov 682594e906SNikolay Aleksandrov if (br_vlan_is_master(v)) 69907b1e6eSNikolay Aleksandrov vg = br_vlan_group(v->br); 70635126b7SVlad Yasevich else 71907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(v->port); 7277751ee8SNikolay Aleksandrov 7377751ee8SNikolay Aleksandrov if (flags & BRIDGE_VLAN_INFO_PVID) 74a580c76dSNikolay Aleksandrov ret = __vlan_add_pvid(vg, v); 752594e906SNikolay Aleksandrov else 76f418af63SNikolay Aleksandrov ret = __vlan_delete_pvid(vg, v->vid); 7735e03f3aSVlad Yasevich 7835e03f3aSVlad Yasevich if (flags & BRIDGE_VLAN_INFO_UNTAGGED) 792594e906SNikolay Aleksandrov v->flags |= BRIDGE_VLAN_INFO_UNTAGGED; 80635126b7SVlad Yasevich else 812594e906SNikolay Aleksandrov v->flags &= ~BRIDGE_VLAN_INFO_UNTAGGED; 82f418af63SNikolay Aleksandrov 83f418af63SNikolay Aleksandrov return ret || !!(old_flags ^ v->flags); 8435e03f3aSVlad Yasevich } 8535e03f3aSVlad Yasevich 867f109539SScott Feldman static int __vlan_vid_add(struct net_device *dev, struct net_bridge *br, 8727973793SIdo Schimmel struct net_bridge_vlan *v, u16 flags, 8827973793SIdo Schimmel struct netlink_ext_ack *extack) 897f109539SScott Feldman { 900944d6b5SJiri Pirko int err; 917f109539SScott Feldman 920944d6b5SJiri Pirko /* Try switchdev op first. In case it is not supported, fallback to 930944d6b5SJiri Pirko * 8021q add. 940944d6b5SJiri Pirko */ 9527973793SIdo Schimmel err = br_switchdev_port_vlan_add(dev, v->vid, flags, extack); 967f109539SScott Feldman if (err == -EOPNOTSUPP) 9727973793SIdo Schimmel return vlan_vid_add(dev, br->vlan_proto, v->vid); 9827973793SIdo Schimmel v->priv_flags |= BR_VLFLAG_ADDED_BY_SWITCHDEV; 997f109539SScott Feldman return err; 1007f109539SScott Feldman } 1017f109539SScott Feldman 1022594e906SNikolay Aleksandrov static void __vlan_add_list(struct net_bridge_vlan *v) 103243a2e63SVlad Yasevich { 104907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 1052594e906SNikolay Aleksandrov struct list_head *headp, *hpos; 1062594e906SNikolay Aleksandrov struct net_bridge_vlan *vent; 107243a2e63SVlad Yasevich 108907b1e6eSNikolay Aleksandrov if (br_vlan_is_master(v)) 109907b1e6eSNikolay Aleksandrov vg = br_vlan_group(v->br); 110907b1e6eSNikolay Aleksandrov else 111907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(v->port); 112907b1e6eSNikolay Aleksandrov 113907b1e6eSNikolay Aleksandrov headp = &vg->vlan_list; 1142594e906SNikolay Aleksandrov list_for_each_prev(hpos, headp) { 1152594e906SNikolay Aleksandrov vent = list_entry(hpos, struct net_bridge_vlan, vlist); 1162594e906SNikolay Aleksandrov if (v->vid < vent->vid) 1172594e906SNikolay Aleksandrov continue; 1182594e906SNikolay Aleksandrov else 1192594e906SNikolay Aleksandrov break; 1202594e906SNikolay Aleksandrov } 121586c2b57SNikolay Aleksandrov list_add_rcu(&v->vlist, hpos); 122552406c4SVlad Yasevich } 123243a2e63SVlad Yasevich 1242594e906SNikolay Aleksandrov static void __vlan_del_list(struct net_bridge_vlan *v) 1252594e906SNikolay Aleksandrov { 126586c2b57SNikolay Aleksandrov list_del_rcu(&v->vlist); 127243a2e63SVlad Yasevich } 128243a2e63SVlad Yasevich 129bf361ad3SVivien Didelot static int __vlan_vid_del(struct net_device *dev, struct net_bridge *br, 13027973793SIdo Schimmel const struct net_bridge_vlan *v) 1317f109539SScott Feldman { 1320944d6b5SJiri Pirko int err; 1337f109539SScott Feldman 1340944d6b5SJiri Pirko /* Try switchdev op first. In case it is not supported, fallback to 1350944d6b5SJiri Pirko * 8021q del. 1360944d6b5SJiri Pirko */ 13727973793SIdo Schimmel err = br_switchdev_port_vlan_del(dev, v->vid); 13827973793SIdo Schimmel if (!(v->priv_flags & BR_VLFLAG_ADDED_BY_SWITCHDEV)) 13927973793SIdo Schimmel vlan_vid_del(dev, br->vlan_proto, v->vid); 14027973793SIdo Schimmel return err == -EOPNOTSUPP ? 0 : err; 1417f109539SScott Feldman } 1427f109539SScott Feldman 1434bbd026cSRandy Dunlap /* Returns a master vlan, if it didn't exist it gets created. In all cases 144f8ed289fSNikolay Aleksandrov * a reference is taken to the master vlan before returning. 145f8ed289fSNikolay Aleksandrov */ 146169327d5SPetr Machata static struct net_bridge_vlan * 147169327d5SPetr Machata br_vlan_get_master(struct net_bridge *br, u16 vid, 148169327d5SPetr Machata struct netlink_ext_ack *extack) 149f8ed289fSNikolay Aleksandrov { 150907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 151f8ed289fSNikolay Aleksandrov struct net_bridge_vlan *masterv; 152f8ed289fSNikolay Aleksandrov 153907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 154907b1e6eSNikolay Aleksandrov masterv = br_vlan_find(vg, vid); 155f8ed289fSNikolay Aleksandrov if (!masterv) { 156f418af63SNikolay Aleksandrov bool changed; 157f418af63SNikolay Aleksandrov 158f8ed289fSNikolay Aleksandrov /* missing global ctx, create it now */ 159169327d5SPetr Machata if (br_vlan_add(br, vid, 0, &changed, extack)) 160f8ed289fSNikolay Aleksandrov return NULL; 161907b1e6eSNikolay Aleksandrov masterv = br_vlan_find(vg, vid); 162f8ed289fSNikolay Aleksandrov if (WARN_ON(!masterv)) 163f8ed289fSNikolay Aleksandrov return NULL; 1640e5a82efSIdo Schimmel refcount_set(&masterv->refcnt, 1); 1650e5a82efSIdo Schimmel return masterv; 166f8ed289fSNikolay Aleksandrov } 16725127759SReshetova, Elena refcount_inc(&masterv->refcnt); 168f8ed289fSNikolay Aleksandrov 169f8ed289fSNikolay Aleksandrov return masterv; 170f8ed289fSNikolay Aleksandrov } 171f8ed289fSNikolay Aleksandrov 1726dada9b1SNikolay Aleksandrov static void br_master_vlan_rcu_free(struct rcu_head *rcu) 1736dada9b1SNikolay Aleksandrov { 1746dada9b1SNikolay Aleksandrov struct net_bridge_vlan *v; 1756dada9b1SNikolay Aleksandrov 1766dada9b1SNikolay Aleksandrov v = container_of(rcu, struct net_bridge_vlan, rcu); 1776dada9b1SNikolay Aleksandrov WARN_ON(!br_vlan_is_master(v)); 1786dada9b1SNikolay Aleksandrov free_percpu(v->stats); 1796dada9b1SNikolay Aleksandrov v->stats = NULL; 1806dada9b1SNikolay Aleksandrov kfree(v); 1816dada9b1SNikolay Aleksandrov } 1826dada9b1SNikolay Aleksandrov 183f8ed289fSNikolay Aleksandrov static void br_vlan_put_master(struct net_bridge_vlan *masterv) 184f8ed289fSNikolay Aleksandrov { 185907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 186907b1e6eSNikolay Aleksandrov 187f8ed289fSNikolay Aleksandrov if (!br_vlan_is_master(masterv)) 188f8ed289fSNikolay Aleksandrov return; 189f8ed289fSNikolay Aleksandrov 190907b1e6eSNikolay Aleksandrov vg = br_vlan_group(masterv->br); 19125127759SReshetova, Elena if (refcount_dec_and_test(&masterv->refcnt)) { 192907b1e6eSNikolay Aleksandrov rhashtable_remove_fast(&vg->vlan_hash, 193f8ed289fSNikolay Aleksandrov &masterv->vnode, br_vlan_rht_params); 194f8ed289fSNikolay Aleksandrov __vlan_del_list(masterv); 1956dada9b1SNikolay Aleksandrov call_rcu(&masterv->rcu, br_master_vlan_rcu_free); 196f8ed289fSNikolay Aleksandrov } 197f8ed289fSNikolay Aleksandrov } 198f8ed289fSNikolay Aleksandrov 1999163a0fcSNikolay Aleksandrov static void nbp_vlan_rcu_free(struct rcu_head *rcu) 2009163a0fcSNikolay Aleksandrov { 2019163a0fcSNikolay Aleksandrov struct net_bridge_vlan *v; 2029163a0fcSNikolay Aleksandrov 2039163a0fcSNikolay Aleksandrov v = container_of(rcu, struct net_bridge_vlan, rcu); 2049163a0fcSNikolay Aleksandrov WARN_ON(br_vlan_is_master(v)); 2059163a0fcSNikolay Aleksandrov /* if we had per-port stats configured then free them here */ 2069d332e69SNikolay Aleksandrov if (v->priv_flags & BR_VLFLAG_PER_PORT_STATS) 2079163a0fcSNikolay Aleksandrov free_percpu(v->stats); 2089163a0fcSNikolay Aleksandrov v->stats = NULL; 2099163a0fcSNikolay Aleksandrov kfree(v); 2109163a0fcSNikolay Aleksandrov } 2119163a0fcSNikolay Aleksandrov 2122594e906SNikolay Aleksandrov /* This is the shared VLAN add function which works for both ports and bridge 2132594e906SNikolay Aleksandrov * devices. There are four possible calls to this function in terms of the 2142594e906SNikolay Aleksandrov * vlan entry type: 2152594e906SNikolay Aleksandrov * 1. vlan is being added on a port (no master flags, global entry exists) 216ddd611d3SIdo Schimmel * 2. vlan is being added on a bridge (both master and brentry flags) 2172594e906SNikolay Aleksandrov * 3. vlan is being added on a port, but a global entry didn't exist which 218ddd611d3SIdo Schimmel * is being created right now (master flag set, brentry flag unset), the 2192594e906SNikolay Aleksandrov * global entry is used for global per-vlan features, but not for filtering 220ddd611d3SIdo Schimmel * 4. same as 3 but with both master and brentry flags set so the entry 2212594e906SNikolay Aleksandrov * will be used for filtering in both the port and the bridge 2222594e906SNikolay Aleksandrov */ 223169327d5SPetr Machata static int __vlan_add(struct net_bridge_vlan *v, u16 flags, 224169327d5SPetr Machata struct netlink_ext_ack *extack) 225243a2e63SVlad Yasevich { 2262594e906SNikolay Aleksandrov struct net_bridge_vlan *masterv = NULL; 2272594e906SNikolay Aleksandrov struct net_bridge_port *p = NULL; 2286be144f6SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 2292594e906SNikolay Aleksandrov struct net_device *dev; 2302594e906SNikolay Aleksandrov struct net_bridge *br; 231bf361ad3SVivien Didelot int err; 232bf361ad3SVivien Didelot 2332594e906SNikolay Aleksandrov if (br_vlan_is_master(v)) { 2342594e906SNikolay Aleksandrov br = v->br; 2352594e906SNikolay Aleksandrov dev = br->dev; 236907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 2372594e906SNikolay Aleksandrov } else { 2382594e906SNikolay Aleksandrov p = v->port; 2392594e906SNikolay Aleksandrov br = p->br; 2402594e906SNikolay Aleksandrov dev = p->dev; 241907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 2422594e906SNikolay Aleksandrov } 2432594e906SNikolay Aleksandrov 2442594e906SNikolay Aleksandrov if (p) { 2452594e906SNikolay Aleksandrov /* Add VLAN to the device filter if it is supported. 2462594e906SNikolay Aleksandrov * This ensures tagged traffic enters the bridge when 2472594e906SNikolay Aleksandrov * promiscuous mode is disabled by br_manage_promisc(). 2482594e906SNikolay Aleksandrov */ 24927973793SIdo Schimmel err = __vlan_vid_add(dev, br, v, flags, extack); 250bf361ad3SVivien Didelot if (err) 2512594e906SNikolay Aleksandrov goto out; 2522594e906SNikolay Aleksandrov 2532594e906SNikolay Aleksandrov /* need to work on the master vlan too */ 2542594e906SNikolay Aleksandrov if (flags & BRIDGE_VLAN_INFO_MASTER) { 255f418af63SNikolay Aleksandrov bool changed; 256f418af63SNikolay Aleksandrov 257f418af63SNikolay Aleksandrov err = br_vlan_add(br, v->vid, 258f418af63SNikolay Aleksandrov flags | BRIDGE_VLAN_INFO_BRENTRY, 259169327d5SPetr Machata &changed, extack); 2602594e906SNikolay Aleksandrov if (err) 2612594e906SNikolay Aleksandrov goto out_filt; 262f545923bSNikolay Aleksandrov 263f545923bSNikolay Aleksandrov if (changed) 264f545923bSNikolay Aleksandrov br_vlan_notify(br, NULL, v->vid, 0, 265f545923bSNikolay Aleksandrov RTM_NEWVLAN); 2662594e906SNikolay Aleksandrov } 2672594e906SNikolay Aleksandrov 268169327d5SPetr Machata masterv = br_vlan_get_master(br, v->vid, extack); 269f8ed289fSNikolay Aleksandrov if (!masterv) 2702594e906SNikolay Aleksandrov goto out_filt; 2712594e906SNikolay Aleksandrov v->brvlan = masterv; 2729163a0fcSNikolay Aleksandrov if (br_opt_get(br, BROPT_VLAN_STATS_PER_PORT)) { 2739163a0fcSNikolay Aleksandrov v->stats = netdev_alloc_pcpu_stats(struct br_vlan_stats); 2749163a0fcSNikolay Aleksandrov if (!v->stats) { 2759163a0fcSNikolay Aleksandrov err = -ENOMEM; 2769163a0fcSNikolay Aleksandrov goto out_filt; 2779163a0fcSNikolay Aleksandrov } 2789d332e69SNikolay Aleksandrov v->priv_flags |= BR_VLFLAG_PER_PORT_STATS; 2799163a0fcSNikolay Aleksandrov } else { 2806dada9b1SNikolay Aleksandrov v->stats = masterv->stats; 2819163a0fcSNikolay Aleksandrov } 2829c86ce2cSPetr Machata } else { 283169327d5SPetr Machata err = br_switchdev_port_vlan_add(dev, v->vid, flags, extack); 2849c86ce2cSPetr Machata if (err && err != -EOPNOTSUPP) 2859c86ce2cSPetr Machata goto out; 2862594e906SNikolay Aleksandrov } 2872594e906SNikolay Aleksandrov 2886be144f6SNikolay Aleksandrov /* Add the dev mac and count the vlan only if it's usable */ 2892594e906SNikolay Aleksandrov if (br_vlan_should_use(v)) { 2902594e906SNikolay Aleksandrov err = br_fdb_insert(br, p, dev->dev_addr, v->vid); 2912594e906SNikolay Aleksandrov if (err) { 2922594e906SNikolay Aleksandrov br_err(br, "failed insert local address into bridge forwarding table\n"); 2932594e906SNikolay Aleksandrov goto out_filt; 2942594e906SNikolay Aleksandrov } 2956be144f6SNikolay Aleksandrov vg->num_vlans++; 2962594e906SNikolay Aleksandrov } 2972594e906SNikolay Aleksandrov 298a580c76dSNikolay Aleksandrov /* set the state before publishing */ 299a580c76dSNikolay Aleksandrov v->state = BR_STATE_FORWARDING; 300a580c76dSNikolay Aleksandrov 3016be144f6SNikolay Aleksandrov err = rhashtable_lookup_insert_fast(&vg->vlan_hash, &v->vnode, 3026be144f6SNikolay Aleksandrov br_vlan_rht_params); 3032594e906SNikolay Aleksandrov if (err) 3042594e906SNikolay Aleksandrov goto out_fdb_insert; 3052594e906SNikolay Aleksandrov 3062594e906SNikolay Aleksandrov __vlan_add_list(v); 3072594e906SNikolay Aleksandrov __vlan_add_flags(v, flags); 30880900acdSMike Manning 30980900acdSMike Manning if (p) 31080900acdSMike Manning nbp_vlan_set_vlan_dev_state(p, v->vid); 3112594e906SNikolay Aleksandrov out: 3122594e906SNikolay Aleksandrov return err; 3132594e906SNikolay Aleksandrov 3142594e906SNikolay Aleksandrov out_fdb_insert: 3156be144f6SNikolay Aleksandrov if (br_vlan_should_use(v)) { 3166be144f6SNikolay Aleksandrov br_fdb_find_delete_local(br, p, dev->dev_addr, v->vid); 3176be144f6SNikolay Aleksandrov vg->num_vlans--; 3186be144f6SNikolay Aleksandrov } 3192594e906SNikolay Aleksandrov 3202594e906SNikolay Aleksandrov out_filt: 3212594e906SNikolay Aleksandrov if (p) { 32227973793SIdo Schimmel __vlan_vid_del(dev, br, v); 3232594e906SNikolay Aleksandrov if (masterv) { 3241a3aea25SLi RongQing if (v->stats && masterv->stats != v->stats) 3251a3aea25SLi RongQing free_percpu(v->stats); 3261a3aea25SLi RongQing v->stats = NULL; 3271a3aea25SLi RongQing 328f8ed289fSNikolay Aleksandrov br_vlan_put_master(masterv); 3292594e906SNikolay Aleksandrov v->brvlan = NULL; 3302594e906SNikolay Aleksandrov } 3319c86ce2cSPetr Machata } else { 3329c86ce2cSPetr Machata br_switchdev_port_vlan_del(dev, v->vid); 3332594e906SNikolay Aleksandrov } 3342594e906SNikolay Aleksandrov 3352594e906SNikolay Aleksandrov goto out; 3362594e906SNikolay Aleksandrov } 3372594e906SNikolay Aleksandrov 3382594e906SNikolay Aleksandrov static int __vlan_del(struct net_bridge_vlan *v) 3392594e906SNikolay Aleksandrov { 3402594e906SNikolay Aleksandrov struct net_bridge_vlan *masterv = v; 34177751ee8SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 3422594e906SNikolay Aleksandrov struct net_bridge_port *p = NULL; 3432594e906SNikolay Aleksandrov int err = 0; 3442594e906SNikolay Aleksandrov 3452594e906SNikolay Aleksandrov if (br_vlan_is_master(v)) { 346907b1e6eSNikolay Aleksandrov vg = br_vlan_group(v->br); 3472594e906SNikolay Aleksandrov } else { 3482594e906SNikolay Aleksandrov p = v->port; 349907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(v->port); 3502594e906SNikolay Aleksandrov masterv = v->brvlan; 3512594e906SNikolay Aleksandrov } 3522594e906SNikolay Aleksandrov 35377751ee8SNikolay Aleksandrov __vlan_delete_pvid(vg, v->vid); 3542594e906SNikolay Aleksandrov if (p) { 35527973793SIdo Schimmel err = __vlan_vid_del(p->dev, p->br, v); 3562594e906SNikolay Aleksandrov if (err) 3572594e906SNikolay Aleksandrov goto out; 3589c86ce2cSPetr Machata } else { 3599c86ce2cSPetr Machata err = br_switchdev_port_vlan_del(v->br->dev, v->vid); 3609c86ce2cSPetr Machata if (err && err != -EOPNOTSUPP) 3619c86ce2cSPetr Machata goto out; 3629c86ce2cSPetr Machata err = 0; 3632594e906SNikolay Aleksandrov } 3642594e906SNikolay Aleksandrov 3656be144f6SNikolay Aleksandrov if (br_vlan_should_use(v)) { 3662594e906SNikolay Aleksandrov v->flags &= ~BRIDGE_VLAN_INFO_BRENTRY; 3676be144f6SNikolay Aleksandrov vg->num_vlans--; 3682594e906SNikolay Aleksandrov } 3692594e906SNikolay Aleksandrov 3702594e906SNikolay Aleksandrov if (masterv != v) { 371efa5356bSRoopa Prabhu vlan_tunnel_info_del(vg, v); 37277751ee8SNikolay Aleksandrov rhashtable_remove_fast(&vg->vlan_hash, &v->vnode, 37377751ee8SNikolay Aleksandrov br_vlan_rht_params); 3742594e906SNikolay Aleksandrov __vlan_del_list(v); 37580900acdSMike Manning nbp_vlan_set_vlan_dev_state(p, v->vid); 3769163a0fcSNikolay Aleksandrov call_rcu(&v->rcu, nbp_vlan_rcu_free); 3772594e906SNikolay Aleksandrov } 3782594e906SNikolay Aleksandrov 379f8ed289fSNikolay Aleksandrov br_vlan_put_master(masterv); 3802594e906SNikolay Aleksandrov out: 381bf361ad3SVivien Didelot return err; 3828580e211SToshiaki Makita } 383243a2e63SVlad Yasevich 384f409d0edSNikolay Aleksandrov static void __vlan_group_free(struct net_bridge_vlan_group *vg) 385f409d0edSNikolay Aleksandrov { 386f409d0edSNikolay Aleksandrov WARN_ON(!list_empty(&vg->vlan_list)); 387f409d0edSNikolay Aleksandrov rhashtable_destroy(&vg->vlan_hash); 388efa5356bSRoopa Prabhu vlan_tunnel_deinit(vg); 389f409d0edSNikolay Aleksandrov kfree(vg); 390f409d0edSNikolay Aleksandrov } 391f409d0edSNikolay Aleksandrov 392f545923bSNikolay Aleksandrov static void __vlan_flush(const struct net_bridge *br, 393f545923bSNikolay Aleksandrov const struct net_bridge_port *p, 394f545923bSNikolay Aleksandrov struct net_bridge_vlan_group *vg) 395243a2e63SVlad Yasevich { 3962594e906SNikolay Aleksandrov struct net_bridge_vlan *vlan, *tmp; 397f545923bSNikolay Aleksandrov u16 v_start = 0, v_end = 0; 3982594e906SNikolay Aleksandrov 399f409d0edSNikolay Aleksandrov __vlan_delete_pvid(vg, vg->pvid); 400f545923bSNikolay Aleksandrov list_for_each_entry_safe(vlan, tmp, &vg->vlan_list, vlist) { 401f545923bSNikolay Aleksandrov /* take care of disjoint ranges */ 402f545923bSNikolay Aleksandrov if (!v_start) { 403f545923bSNikolay Aleksandrov v_start = vlan->vid; 404f545923bSNikolay Aleksandrov } else if (vlan->vid - v_end != 1) { 405f545923bSNikolay Aleksandrov /* found range end, notify and start next one */ 406f545923bSNikolay Aleksandrov br_vlan_notify(br, p, v_start, v_end, RTM_DELVLAN); 407f545923bSNikolay Aleksandrov v_start = vlan->vid; 408f545923bSNikolay Aleksandrov } 409f545923bSNikolay Aleksandrov v_end = vlan->vid; 410f545923bSNikolay Aleksandrov 4112594e906SNikolay Aleksandrov __vlan_del(vlan); 412243a2e63SVlad Yasevich } 413243a2e63SVlad Yasevich 414f545923bSNikolay Aleksandrov /* notify about the last/whole vlan range */ 415f545923bSNikolay Aleksandrov if (v_start) 416f545923bSNikolay Aleksandrov br_vlan_notify(br, p, v_start, v_end, RTM_DELVLAN); 417f545923bSNikolay Aleksandrov } 418f545923bSNikolay Aleksandrov 41978851988SVlad Yasevich struct sk_buff *br_handle_vlan(struct net_bridge *br, 42011538d03SRoopa Prabhu const struct net_bridge_port *p, 4212594e906SNikolay Aleksandrov struct net_bridge_vlan_group *vg, 422a37b85c9SVlad Yasevich struct sk_buff *skb) 423a37b85c9SVlad Yasevich { 4246dada9b1SNikolay Aleksandrov struct br_vlan_stats *stats; 4252594e906SNikolay Aleksandrov struct net_bridge_vlan *v; 426a37b85c9SVlad Yasevich u16 vid; 427a37b85c9SVlad Yasevich 42820adfa1aSVlad Yasevich /* If this packet was not filtered at input, let it pass */ 42920adfa1aSVlad Yasevich if (!BR_INPUT_SKB_CB(skb)->vlan_filtered) 43078851988SVlad Yasevich goto out; 43178851988SVlad Yasevich 4322594e906SNikolay Aleksandrov /* At this point, we know that the frame was filtered and contains 4332594e906SNikolay Aleksandrov * a valid vlan id. If the vlan id has untagged flag set, 4342594e906SNikolay Aleksandrov * send untagged; otherwise, send tagged. 4352594e906SNikolay Aleksandrov */ 4362594e906SNikolay Aleksandrov br_vlan_get_tag(skb, &vid); 4372594e906SNikolay Aleksandrov v = br_vlan_find(vg, vid); 4382594e906SNikolay Aleksandrov /* Vlan entry must be configured at this point. The 439fc92f745SVlad Yasevich * only exception is the bridge is set in promisc mode and the 440fc92f745SVlad Yasevich * packet is destined for the bridge device. In this case 441fc92f745SVlad Yasevich * pass the packet as is. 442fc92f745SVlad Yasevich */ 4432594e906SNikolay Aleksandrov if (!v || !br_vlan_should_use(v)) { 444fc92f745SVlad Yasevich if ((br->dev->flags & IFF_PROMISC) && skb->dev == br->dev) { 445fc92f745SVlad Yasevich goto out; 446fc92f745SVlad Yasevich } else { 447fc92f745SVlad Yasevich kfree_skb(skb); 448fc92f745SVlad Yasevich return NULL; 449fc92f745SVlad Yasevich } 450fc92f745SVlad Yasevich } 451ae75767eSNikolay Aleksandrov if (br_opt_get(br, BROPT_VLAN_STATS_ENABLED)) { 4526dada9b1SNikolay Aleksandrov stats = this_cpu_ptr(v->stats); 4536dada9b1SNikolay Aleksandrov u64_stats_update_begin(&stats->syncp); 4546dada9b1SNikolay Aleksandrov stats->tx_bytes += skb->len; 4556dada9b1SNikolay Aleksandrov stats->tx_packets++; 4566dada9b1SNikolay Aleksandrov u64_stats_update_end(&stats->syncp); 4576dada9b1SNikolay Aleksandrov } 4586dada9b1SNikolay Aleksandrov 4592594e906SNikolay Aleksandrov if (v->flags & BRIDGE_VLAN_INFO_UNTAGGED) 4605978f8a9SMichał Mirosław __vlan_hwaccel_clear_tag(skb); 46111538d03SRoopa Prabhu 46211538d03SRoopa Prabhu if (p && (p->flags & BR_VLAN_TUNNEL) && 46311538d03SRoopa Prabhu br_handle_egress_vlan_tunnel(skb, v)) { 46411538d03SRoopa Prabhu kfree_skb(skb); 46511538d03SRoopa Prabhu return NULL; 46611538d03SRoopa Prabhu } 46778851988SVlad Yasevich out: 46878851988SVlad Yasevich return skb; 46978851988SVlad Yasevich } 47078851988SVlad Yasevich 47178851988SVlad Yasevich /* Called under RCU */ 4726dada9b1SNikolay Aleksandrov static bool __allowed_ingress(const struct net_bridge *br, 4736dada9b1SNikolay Aleksandrov struct net_bridge_vlan_group *vg, 474a580c76dSNikolay Aleksandrov struct sk_buff *skb, u16 *vid, 475a580c76dSNikolay Aleksandrov u8 *state) 47678851988SVlad Yasevich { 4776dada9b1SNikolay Aleksandrov struct br_vlan_stats *stats; 4786dada9b1SNikolay Aleksandrov struct net_bridge_vlan *v; 4798580e211SToshiaki Makita bool tagged; 480a37b85c9SVlad Yasevich 48120adfa1aSVlad Yasevich BR_INPUT_SKB_CB(skb)->vlan_filtered = true; 48212464bb8SToshiaki Makita /* If vlan tx offload is disabled on bridge device and frame was 48312464bb8SToshiaki Makita * sent from vlan device on the bridge device, it does not have 48412464bb8SToshiaki Makita * HW accelerated vlan tag. 48512464bb8SToshiaki Makita */ 486df8a39deSJiri Pirko if (unlikely(!skb_vlan_tag_present(skb) && 4876dada9b1SNikolay Aleksandrov skb->protocol == br->vlan_proto)) { 4880d5501c1SVlad Yasevich skb = skb_vlan_untag(skb); 48912464bb8SToshiaki Makita if (unlikely(!skb)) 49012464bb8SToshiaki Makita return false; 49112464bb8SToshiaki Makita } 49212464bb8SToshiaki Makita 4938580e211SToshiaki Makita if (!br_vlan_get_tag(skb, vid)) { 4948580e211SToshiaki Makita /* Tagged frame */ 4956dada9b1SNikolay Aleksandrov if (skb->vlan_proto != br->vlan_proto) { 4968580e211SToshiaki Makita /* Protocol-mismatch, empty out vlan_tci for new tag */ 4978580e211SToshiaki Makita skb_push(skb, ETH_HLEN); 49862749e2cSJiri Pirko skb = vlan_insert_tag_set_proto(skb, skb->vlan_proto, 499df8a39deSJiri Pirko skb_vlan_tag_get(skb)); 5008580e211SToshiaki Makita if (unlikely(!skb)) 5018580e211SToshiaki Makita return false; 5028580e211SToshiaki Makita 5038580e211SToshiaki Makita skb_pull(skb, ETH_HLEN); 5048580e211SToshiaki Makita skb_reset_mac_len(skb); 5058580e211SToshiaki Makita *vid = 0; 5068580e211SToshiaki Makita tagged = false; 5078580e211SToshiaki Makita } else { 5088580e211SToshiaki Makita tagged = true; 5098580e211SToshiaki Makita } 5108580e211SToshiaki Makita } else { 5118580e211SToshiaki Makita /* Untagged frame */ 5128580e211SToshiaki Makita tagged = false; 5138580e211SToshiaki Makita } 5148580e211SToshiaki Makita 515b90356ceSToshiaki Makita if (!*vid) { 51677751ee8SNikolay Aleksandrov u16 pvid = br_get_pvid(vg); 51777751ee8SNikolay Aleksandrov 518b90356ceSToshiaki Makita /* Frame had a tag with VID 0 or did not have a tag. 519b90356ceSToshiaki Makita * See if pvid is set on this port. That tells us which 520b90356ceSToshiaki Makita * vlan untagged or priority-tagged traffic belongs to. 52178851988SVlad Yasevich */ 5223df6bf45SVlad Yasevich if (!pvid) 523eb707618SToshiaki Makita goto drop; 52478851988SVlad Yasevich 525b90356ceSToshiaki Makita /* PVID is set on this port. Any untagged or priority-tagged 526b90356ceSToshiaki Makita * ingress frame is considered to belong to this vlan. 52778851988SVlad Yasevich */ 528dfb5fa32SToshiaki Makita *vid = pvid; 5298580e211SToshiaki Makita if (likely(!tagged)) 530b90356ceSToshiaki Makita /* Untagged Frame. */ 5316dada9b1SNikolay Aleksandrov __vlan_hwaccel_put_tag(skb, br->vlan_proto, pvid); 532b90356ceSToshiaki Makita else 533b90356ceSToshiaki Makita /* Priority-tagged Frame. 5345978f8a9SMichał Mirosław * At this point, we know that skb->vlan_tci VID 5355978f8a9SMichał Mirosław * field was 0. 536b90356ceSToshiaki Makita * We update only VID field and preserve PCP field. 537b90356ceSToshiaki Makita */ 538b90356ceSToshiaki Makita skb->vlan_tci |= pvid; 539b90356ceSToshiaki Makita 5406dada9b1SNikolay Aleksandrov /* if stats are disabled we can avoid the lookup */ 541a580c76dSNikolay Aleksandrov if (!br_opt_get(br, BROPT_VLAN_STATS_ENABLED)) { 542a580c76dSNikolay Aleksandrov if (*state == BR_STATE_FORWARDING) { 543a580c76dSNikolay Aleksandrov *state = br_vlan_get_pvid_state(vg); 544a580c76dSNikolay Aleksandrov return br_vlan_state_allowed(*state, true); 545a580c76dSNikolay Aleksandrov } else { 54678851988SVlad Yasevich return true; 54778851988SVlad Yasevich } 548a580c76dSNikolay Aleksandrov } 549a580c76dSNikolay Aleksandrov } 55077751ee8SNikolay Aleksandrov v = br_vlan_find(vg, *vid); 5516dada9b1SNikolay Aleksandrov if (!v || !br_vlan_should_use(v)) 5526dada9b1SNikolay Aleksandrov goto drop; 5536dada9b1SNikolay Aleksandrov 554a580c76dSNikolay Aleksandrov if (*state == BR_STATE_FORWARDING) { 555a580c76dSNikolay Aleksandrov *state = br_vlan_get_state(v); 556a580c76dSNikolay Aleksandrov if (!br_vlan_state_allowed(*state, true)) 557a580c76dSNikolay Aleksandrov goto drop; 558a580c76dSNikolay Aleksandrov } 559a580c76dSNikolay Aleksandrov 560ae75767eSNikolay Aleksandrov if (br_opt_get(br, BROPT_VLAN_STATS_ENABLED)) { 5616dada9b1SNikolay Aleksandrov stats = this_cpu_ptr(v->stats); 5626dada9b1SNikolay Aleksandrov u64_stats_update_begin(&stats->syncp); 5636dada9b1SNikolay Aleksandrov stats->rx_bytes += skb->len; 5646dada9b1SNikolay Aleksandrov stats->rx_packets++; 5656dada9b1SNikolay Aleksandrov u64_stats_update_end(&stats->syncp); 5666dada9b1SNikolay Aleksandrov } 5676dada9b1SNikolay Aleksandrov 568a37b85c9SVlad Yasevich return true; 5696dada9b1SNikolay Aleksandrov 570eb707618SToshiaki Makita drop: 571eb707618SToshiaki Makita kfree_skb(skb); 572a37b85c9SVlad Yasevich return false; 573a37b85c9SVlad Yasevich } 574a37b85c9SVlad Yasevich 57577751ee8SNikolay Aleksandrov bool br_allowed_ingress(const struct net_bridge *br, 57677751ee8SNikolay Aleksandrov struct net_bridge_vlan_group *vg, struct sk_buff *skb, 577a580c76dSNikolay Aleksandrov u16 *vid, u8 *state) 5782594e906SNikolay Aleksandrov { 5792594e906SNikolay Aleksandrov /* If VLAN filtering is disabled on the bridge, all packets are 5802594e906SNikolay Aleksandrov * permitted. 5812594e906SNikolay Aleksandrov */ 582ae75767eSNikolay Aleksandrov if (!br_opt_get(br, BROPT_VLAN_ENABLED)) { 5832594e906SNikolay Aleksandrov BR_INPUT_SKB_CB(skb)->vlan_filtered = false; 5842594e906SNikolay Aleksandrov return true; 5852594e906SNikolay Aleksandrov } 5862594e906SNikolay Aleksandrov 587a580c76dSNikolay Aleksandrov return __allowed_ingress(br, vg, skb, vid, state); 5882594e906SNikolay Aleksandrov } 5892594e906SNikolay Aleksandrov 59085f46c6bSVlad Yasevich /* Called under RCU. */ 5912594e906SNikolay Aleksandrov bool br_allowed_egress(struct net_bridge_vlan_group *vg, 59285f46c6bSVlad Yasevich const struct sk_buff *skb) 59385f46c6bSVlad Yasevich { 5942594e906SNikolay Aleksandrov const struct net_bridge_vlan *v; 59585f46c6bSVlad Yasevich u16 vid; 59685f46c6bSVlad Yasevich 59720adfa1aSVlad Yasevich /* If this packet was not filtered at input, let it pass */ 59820adfa1aSVlad Yasevich if (!BR_INPUT_SKB_CB(skb)->vlan_filtered) 59985f46c6bSVlad Yasevich return true; 60085f46c6bSVlad Yasevich 60185f46c6bSVlad Yasevich br_vlan_get_tag(skb, &vid); 6022594e906SNikolay Aleksandrov v = br_vlan_find(vg, vid); 603a580c76dSNikolay Aleksandrov if (v && br_vlan_should_use(v) && 604a580c76dSNikolay Aleksandrov br_vlan_state_allowed(br_vlan_get_state(v), false)) 60585f46c6bSVlad Yasevich return true; 60685f46c6bSVlad Yasevich 60785f46c6bSVlad Yasevich return false; 60885f46c6bSVlad Yasevich } 60985f46c6bSVlad Yasevich 610e0d7968aSToshiaki Makita /* Called under RCU */ 611e0d7968aSToshiaki Makita bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid) 612e0d7968aSToshiaki Makita { 613468e7944SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 614e0d7968aSToshiaki Makita struct net_bridge *br = p->br; 615a580c76dSNikolay Aleksandrov struct net_bridge_vlan *v; 616e0d7968aSToshiaki Makita 61720adfa1aSVlad Yasevich /* If filtering was disabled at input, let it pass. */ 618ae75767eSNikolay Aleksandrov if (!br_opt_get(br, BROPT_VLAN_ENABLED)) 619e0d7968aSToshiaki Makita return true; 620e0d7968aSToshiaki Makita 621eca1e006SIdo Schimmel vg = nbp_vlan_group_rcu(p); 622468e7944SNikolay Aleksandrov if (!vg || !vg->num_vlans) 623e0d7968aSToshiaki Makita return false; 624e0d7968aSToshiaki Makita 6258580e211SToshiaki Makita if (!br_vlan_get_tag(skb, vid) && skb->vlan_proto != br->vlan_proto) 6268580e211SToshiaki Makita *vid = 0; 6278580e211SToshiaki Makita 628e0d7968aSToshiaki Makita if (!*vid) { 62977751ee8SNikolay Aleksandrov *vid = br_get_pvid(vg); 630a580c76dSNikolay Aleksandrov if (!*vid || 631a580c76dSNikolay Aleksandrov !br_vlan_state_allowed(br_vlan_get_pvid_state(vg), true)) 632e0d7968aSToshiaki Makita return false; 633e0d7968aSToshiaki Makita 634e0d7968aSToshiaki Makita return true; 635e0d7968aSToshiaki Makita } 636e0d7968aSToshiaki Makita 637a580c76dSNikolay Aleksandrov v = br_vlan_find(vg, *vid); 638a580c76dSNikolay Aleksandrov if (v && br_vlan_state_allowed(br_vlan_get_state(v), true)) 639e0d7968aSToshiaki Makita return true; 640e0d7968aSToshiaki Makita 641e0d7968aSToshiaki Makita return false; 642e0d7968aSToshiaki Makita } 643e0d7968aSToshiaki Makita 644dbd6dc75SPetr Machata static int br_vlan_add_existing(struct net_bridge *br, 645dbd6dc75SPetr Machata struct net_bridge_vlan_group *vg, 646dbd6dc75SPetr Machata struct net_bridge_vlan *vlan, 647169327d5SPetr Machata u16 flags, bool *changed, 648169327d5SPetr Machata struct netlink_ext_ack *extack) 649dbd6dc75SPetr Machata { 650dbd6dc75SPetr Machata int err; 651dbd6dc75SPetr Machata 652169327d5SPetr Machata err = br_switchdev_port_vlan_add(br->dev, vlan->vid, flags, extack); 6539c86ce2cSPetr Machata if (err && err != -EOPNOTSUPP) 6549c86ce2cSPetr Machata return err; 6559c86ce2cSPetr Machata 656dbd6dc75SPetr Machata if (!br_vlan_is_brentry(vlan)) { 657dbd6dc75SPetr Machata /* Trying to change flags of non-existent bridge vlan */ 6589c86ce2cSPetr Machata if (!(flags & BRIDGE_VLAN_INFO_BRENTRY)) { 6599c86ce2cSPetr Machata err = -EINVAL; 6609c86ce2cSPetr Machata goto err_flags; 6619c86ce2cSPetr Machata } 662dbd6dc75SPetr Machata /* It was only kept for port vlans, now make it real */ 663dbd6dc75SPetr Machata err = br_fdb_insert(br, NULL, br->dev->dev_addr, 664dbd6dc75SPetr Machata vlan->vid); 665dbd6dc75SPetr Machata if (err) { 666dbd6dc75SPetr Machata br_err(br, "failed to insert local address into bridge forwarding table\n"); 6679c86ce2cSPetr Machata goto err_fdb_insert; 668dbd6dc75SPetr Machata } 669dbd6dc75SPetr Machata 670dbd6dc75SPetr Machata refcount_inc(&vlan->refcnt); 671dbd6dc75SPetr Machata vlan->flags |= BRIDGE_VLAN_INFO_BRENTRY; 672dbd6dc75SPetr Machata vg->num_vlans++; 673dbd6dc75SPetr Machata *changed = true; 674dbd6dc75SPetr Machata } 675dbd6dc75SPetr Machata 676dbd6dc75SPetr Machata if (__vlan_add_flags(vlan, flags)) 677dbd6dc75SPetr Machata *changed = true; 678dbd6dc75SPetr Machata 679dbd6dc75SPetr Machata return 0; 6809c86ce2cSPetr Machata 6819c86ce2cSPetr Machata err_fdb_insert: 6829c86ce2cSPetr Machata err_flags: 6839c86ce2cSPetr Machata br_switchdev_port_vlan_del(br->dev, vlan->vid); 6849c86ce2cSPetr Machata return err; 685dbd6dc75SPetr Machata } 686dbd6dc75SPetr Machata 6878adff41cSToshiaki Makita /* Must be protected by RTNL. 6888adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 689f418af63SNikolay Aleksandrov * changed must be true only if the vlan was created or updated 6908adff41cSToshiaki Makita */ 691169327d5SPetr Machata int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags, bool *changed, 692169327d5SPetr Machata struct netlink_ext_ack *extack) 693243a2e63SVlad Yasevich { 694907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 6952594e906SNikolay Aleksandrov struct net_bridge_vlan *vlan; 6962594e906SNikolay Aleksandrov int ret; 697243a2e63SVlad Yasevich 698243a2e63SVlad Yasevich ASSERT_RTNL(); 699243a2e63SVlad Yasevich 700f418af63SNikolay Aleksandrov *changed = false; 701907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 702907b1e6eSNikolay Aleksandrov vlan = br_vlan_find(vg, vid); 703dbd6dc75SPetr Machata if (vlan) 704169327d5SPetr Machata return br_vlan_add_existing(br, vg, vlan, flags, changed, 705169327d5SPetr Machata extack); 706243a2e63SVlad Yasevich 7072594e906SNikolay Aleksandrov vlan = kzalloc(sizeof(*vlan), GFP_KERNEL); 7082594e906SNikolay Aleksandrov if (!vlan) 709243a2e63SVlad Yasevich return -ENOMEM; 710243a2e63SVlad Yasevich 7116dada9b1SNikolay Aleksandrov vlan->stats = netdev_alloc_pcpu_stats(struct br_vlan_stats); 7126dada9b1SNikolay Aleksandrov if (!vlan->stats) { 7136dada9b1SNikolay Aleksandrov kfree(vlan); 7146dada9b1SNikolay Aleksandrov return -ENOMEM; 7156dada9b1SNikolay Aleksandrov } 7162594e906SNikolay Aleksandrov vlan->vid = vid; 7172594e906SNikolay Aleksandrov vlan->flags = flags | BRIDGE_VLAN_INFO_MASTER; 7182594e906SNikolay Aleksandrov vlan->flags &= ~BRIDGE_VLAN_INFO_PVID; 7192594e906SNikolay Aleksandrov vlan->br = br; 7202594e906SNikolay Aleksandrov if (flags & BRIDGE_VLAN_INFO_BRENTRY) 72125127759SReshetova, Elena refcount_set(&vlan->refcnt, 1); 722169327d5SPetr Machata ret = __vlan_add(vlan, flags, extack); 7236dada9b1SNikolay Aleksandrov if (ret) { 7246dada9b1SNikolay Aleksandrov free_percpu(vlan->stats); 7252594e906SNikolay Aleksandrov kfree(vlan); 726f418af63SNikolay Aleksandrov } else { 727f418af63SNikolay Aleksandrov *changed = true; 7286dada9b1SNikolay Aleksandrov } 729243a2e63SVlad Yasevich 7302594e906SNikolay Aleksandrov return ret; 731243a2e63SVlad Yasevich } 732243a2e63SVlad Yasevich 7338adff41cSToshiaki Makita /* Must be protected by RTNL. 7348adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 7358adff41cSToshiaki Makita */ 736243a2e63SVlad Yasevich int br_vlan_delete(struct net_bridge *br, u16 vid) 737243a2e63SVlad Yasevich { 738907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 7392594e906SNikolay Aleksandrov struct net_bridge_vlan *v; 740243a2e63SVlad Yasevich 741243a2e63SVlad Yasevich ASSERT_RTNL(); 742243a2e63SVlad Yasevich 743907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 744907b1e6eSNikolay Aleksandrov v = br_vlan_find(vg, vid); 7452594e906SNikolay Aleksandrov if (!v || !br_vlan_is_brentry(v)) 7462594e906SNikolay Aleksandrov return -ENOENT; 747243a2e63SVlad Yasevich 748424bb9c9SToshiaki Makita br_fdb_find_delete_local(br, NULL, br->dev->dev_addr, vid); 7493741873bSRoopa Prabhu br_fdb_delete_by_port(br, NULL, vid, 0); 750bc9a25d2SVlad Yasevich 751efa5356bSRoopa Prabhu vlan_tunnel_info_del(vg, v); 752efa5356bSRoopa Prabhu 7532594e906SNikolay Aleksandrov return __vlan_del(v); 754243a2e63SVlad Yasevich } 755243a2e63SVlad Yasevich 756243a2e63SVlad Yasevich void br_vlan_flush(struct net_bridge *br) 757243a2e63SVlad Yasevich { 758f409d0edSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 759f409d0edSNikolay Aleksandrov 760243a2e63SVlad Yasevich ASSERT_RTNL(); 761243a2e63SVlad Yasevich 762f409d0edSNikolay Aleksandrov vg = br_vlan_group(br); 763f545923bSNikolay Aleksandrov __vlan_flush(br, NULL, vg); 764f409d0edSNikolay Aleksandrov RCU_INIT_POINTER(br->vlgrp, NULL); 765f409d0edSNikolay Aleksandrov synchronize_rcu(); 766f409d0edSNikolay Aleksandrov __vlan_group_free(vg); 767243a2e63SVlad Yasevich } 768243a2e63SVlad Yasevich 7692594e906SNikolay Aleksandrov struct net_bridge_vlan *br_vlan_find(struct net_bridge_vlan_group *vg, u16 vid) 7702b292fb4SToshiaki Makita { 7712594e906SNikolay Aleksandrov if (!vg) 7722594e906SNikolay Aleksandrov return NULL; 7732b292fb4SToshiaki Makita 7742594e906SNikolay Aleksandrov return br_vlan_lookup(&vg->vlan_hash, vid); 7752b292fb4SToshiaki Makita } 7762b292fb4SToshiaki Makita 777204177f3SToshiaki Makita /* Must be protected by RTNL. */ 778204177f3SToshiaki Makita static void recalculate_group_addr(struct net_bridge *br) 779204177f3SToshiaki Makita { 780be3664a0SNikolay Aleksandrov if (br_opt_get(br, BROPT_GROUP_ADDR_SET)) 781204177f3SToshiaki Makita return; 782204177f3SToshiaki Makita 783204177f3SToshiaki Makita spin_lock_bh(&br->lock); 784ae75767eSNikolay Aleksandrov if (!br_opt_get(br, BROPT_VLAN_ENABLED) || 785ae75767eSNikolay Aleksandrov br->vlan_proto == htons(ETH_P_8021Q)) { 786204177f3SToshiaki Makita /* Bridge Group Address */ 787204177f3SToshiaki Makita br->group_addr[5] = 0x00; 788204177f3SToshiaki Makita } else { /* vlan_enabled && ETH_P_8021AD */ 789204177f3SToshiaki Makita /* Provider Bridge Group Address */ 790204177f3SToshiaki Makita br->group_addr[5] = 0x08; 791204177f3SToshiaki Makita } 792204177f3SToshiaki Makita spin_unlock_bh(&br->lock); 793204177f3SToshiaki Makita } 794204177f3SToshiaki Makita 795204177f3SToshiaki Makita /* Must be protected by RTNL. */ 796204177f3SToshiaki Makita void br_recalculate_fwd_mask(struct net_bridge *br) 797204177f3SToshiaki Makita { 798ae75767eSNikolay Aleksandrov if (!br_opt_get(br, BROPT_VLAN_ENABLED) || 799ae75767eSNikolay Aleksandrov br->vlan_proto == htons(ETH_P_8021Q)) 800204177f3SToshiaki Makita br->group_fwd_mask_required = BR_GROUPFWD_DEFAULT; 801204177f3SToshiaki Makita else /* vlan_enabled && ETH_P_8021AD */ 802204177f3SToshiaki Makita br->group_fwd_mask_required = BR_GROUPFWD_8021AD & 803204177f3SToshiaki Makita ~(1u << br->group_addr[5]); 804204177f3SToshiaki Makita } 805204177f3SToshiaki Makita 806a7854037SNikolay Aleksandrov int __br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) 807243a2e63SVlad Yasevich { 8086b72a770SElad Raz struct switchdev_attr attr = { 8096b72a770SElad Raz .orig_dev = br->dev, 8106b72a770SElad Raz .id = SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING, 8116b72a770SElad Raz .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP, 8126b72a770SElad Raz .u.vlan_filtering = val, 8136b72a770SElad Raz }; 8146b72a770SElad Raz int err; 8156b72a770SElad Raz 816ae75767eSNikolay Aleksandrov if (br_opt_get(br, BROPT_VLAN_ENABLED) == !!val) 817a7854037SNikolay Aleksandrov return 0; 818243a2e63SVlad Yasevich 8196b72a770SElad Raz err = switchdev_port_attr_set(br->dev, &attr); 8206b72a770SElad Raz if (err && err != -EOPNOTSUPP) 8216b72a770SElad Raz return err; 8226b72a770SElad Raz 823ae75767eSNikolay Aleksandrov br_opt_toggle(br, BROPT_VLAN_ENABLED, !!val); 8242796d0c6SVlad Yasevich br_manage_promisc(br); 825204177f3SToshiaki Makita recalculate_group_addr(br); 826204177f3SToshiaki Makita br_recalculate_fwd_mask(br); 827243a2e63SVlad Yasevich 828a7854037SNikolay Aleksandrov return 0; 829a7854037SNikolay Aleksandrov } 830a7854037SNikolay Aleksandrov 831a7854037SNikolay Aleksandrov int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) 832a7854037SNikolay Aleksandrov { 833047831a9SXin Long return __br_vlan_filter_toggle(br, val); 834243a2e63SVlad Yasevich } 835243a2e63SVlad Yasevich 8361f51445aSIdo Schimmel bool br_vlan_enabled(const struct net_device *dev) 8371f51445aSIdo Schimmel { 8381f51445aSIdo Schimmel struct net_bridge *br = netdev_priv(dev); 8391f51445aSIdo Schimmel 840ae75767eSNikolay Aleksandrov return br_opt_get(br, BROPT_VLAN_ENABLED); 8411f51445aSIdo Schimmel } 8421f51445aSIdo Schimmel EXPORT_SYMBOL_GPL(br_vlan_enabled); 8431f51445aSIdo Schimmel 84431aed46fSwenxu int br_vlan_get_proto(const struct net_device *dev, u16 *p_proto) 84531aed46fSwenxu { 84631aed46fSwenxu struct net_bridge *br = netdev_priv(dev); 84731aed46fSwenxu 84831aed46fSwenxu *p_proto = ntohs(br->vlan_proto); 84931aed46fSwenxu 85031aed46fSwenxu return 0; 85131aed46fSwenxu } 85231aed46fSwenxu EXPORT_SYMBOL_GPL(br_vlan_get_proto); 85331aed46fSwenxu 854d2d427b3SToshiaki Makita int __br_vlan_set_proto(struct net_bridge *br, __be16 proto) 855204177f3SToshiaki Makita { 856204177f3SToshiaki Makita int err = 0; 857204177f3SToshiaki Makita struct net_bridge_port *p; 8582594e906SNikolay Aleksandrov struct net_bridge_vlan *vlan; 859907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 860d2d427b3SToshiaki Makita __be16 oldproto; 861204177f3SToshiaki Makita 862204177f3SToshiaki Makita if (br->vlan_proto == proto) 863d2d427b3SToshiaki Makita return 0; 864204177f3SToshiaki Makita 865204177f3SToshiaki Makita /* Add VLANs for the new proto to the device filter. */ 866204177f3SToshiaki Makita list_for_each_entry(p, &br->port_list, list) { 867907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 868907b1e6eSNikolay Aleksandrov list_for_each_entry(vlan, &vg->vlan_list, vlist) { 8692594e906SNikolay Aleksandrov err = vlan_vid_add(p->dev, proto, vlan->vid); 870204177f3SToshiaki Makita if (err) 871204177f3SToshiaki Makita goto err_filt; 872204177f3SToshiaki Makita } 873204177f3SToshiaki Makita } 874204177f3SToshiaki Makita 875204177f3SToshiaki Makita oldproto = br->vlan_proto; 876204177f3SToshiaki Makita br->vlan_proto = proto; 877204177f3SToshiaki Makita 878204177f3SToshiaki Makita recalculate_group_addr(br); 879204177f3SToshiaki Makita br_recalculate_fwd_mask(br); 880204177f3SToshiaki Makita 881204177f3SToshiaki Makita /* Delete VLANs for the old proto from the device filter. */ 882907b1e6eSNikolay Aleksandrov list_for_each_entry(p, &br->port_list, list) { 883907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 884907b1e6eSNikolay Aleksandrov list_for_each_entry(vlan, &vg->vlan_list, vlist) 8852594e906SNikolay Aleksandrov vlan_vid_del(p->dev, oldproto, vlan->vid); 886907b1e6eSNikolay Aleksandrov } 887204177f3SToshiaki Makita 888d2d427b3SToshiaki Makita return 0; 889204177f3SToshiaki Makita 890204177f3SToshiaki Makita err_filt: 891907b1e6eSNikolay Aleksandrov list_for_each_entry_continue_reverse(vlan, &vg->vlan_list, vlist) 8922594e906SNikolay Aleksandrov vlan_vid_del(p->dev, proto, vlan->vid); 893204177f3SToshiaki Makita 894907b1e6eSNikolay Aleksandrov list_for_each_entry_continue_reverse(p, &br->port_list, list) { 895907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 896907b1e6eSNikolay Aleksandrov list_for_each_entry(vlan, &vg->vlan_list, vlist) 8972594e906SNikolay Aleksandrov vlan_vid_del(p->dev, proto, vlan->vid); 898907b1e6eSNikolay Aleksandrov } 899204177f3SToshiaki Makita 900d2d427b3SToshiaki Makita return err; 901d2d427b3SToshiaki Makita } 902d2d427b3SToshiaki Makita 903d2d427b3SToshiaki Makita int br_vlan_set_proto(struct net_bridge *br, unsigned long val) 904d2d427b3SToshiaki Makita { 905d2d427b3SToshiaki Makita if (val != ETH_P_8021Q && val != ETH_P_8021AD) 906d2d427b3SToshiaki Makita return -EPROTONOSUPPORT; 907d2d427b3SToshiaki Makita 908047831a9SXin Long return __br_vlan_set_proto(br, htons(val)); 909204177f3SToshiaki Makita } 910204177f3SToshiaki Makita 9116dada9b1SNikolay Aleksandrov int br_vlan_set_stats(struct net_bridge *br, unsigned long val) 9126dada9b1SNikolay Aleksandrov { 9136dada9b1SNikolay Aleksandrov switch (val) { 9146dada9b1SNikolay Aleksandrov case 0: 9156dada9b1SNikolay Aleksandrov case 1: 916ae75767eSNikolay Aleksandrov br_opt_toggle(br, BROPT_VLAN_STATS_ENABLED, !!val); 9176dada9b1SNikolay Aleksandrov break; 9186dada9b1SNikolay Aleksandrov default: 9196dada9b1SNikolay Aleksandrov return -EINVAL; 9206dada9b1SNikolay Aleksandrov } 9216dada9b1SNikolay Aleksandrov 9226dada9b1SNikolay Aleksandrov return 0; 9236dada9b1SNikolay Aleksandrov } 9246dada9b1SNikolay Aleksandrov 9259163a0fcSNikolay Aleksandrov int br_vlan_set_stats_per_port(struct net_bridge *br, unsigned long val) 9269163a0fcSNikolay Aleksandrov { 9279163a0fcSNikolay Aleksandrov struct net_bridge_port *p; 9289163a0fcSNikolay Aleksandrov 9299163a0fcSNikolay Aleksandrov /* allow to change the option if there are no port vlans configured */ 9309163a0fcSNikolay Aleksandrov list_for_each_entry(p, &br->port_list, list) { 9319163a0fcSNikolay Aleksandrov struct net_bridge_vlan_group *vg = nbp_vlan_group(p); 9329163a0fcSNikolay Aleksandrov 9339163a0fcSNikolay Aleksandrov if (vg->num_vlans) 9349163a0fcSNikolay Aleksandrov return -EBUSY; 9359163a0fcSNikolay Aleksandrov } 9369163a0fcSNikolay Aleksandrov 9379163a0fcSNikolay Aleksandrov switch (val) { 9389163a0fcSNikolay Aleksandrov case 0: 9399163a0fcSNikolay Aleksandrov case 1: 9409163a0fcSNikolay Aleksandrov br_opt_toggle(br, BROPT_VLAN_STATS_PER_PORT, !!val); 9419163a0fcSNikolay Aleksandrov break; 9429163a0fcSNikolay Aleksandrov default: 9439163a0fcSNikolay Aleksandrov return -EINVAL; 9449163a0fcSNikolay Aleksandrov } 9459163a0fcSNikolay Aleksandrov 9469163a0fcSNikolay Aleksandrov return 0; 9479163a0fcSNikolay Aleksandrov } 9489163a0fcSNikolay Aleksandrov 94977751ee8SNikolay Aleksandrov static bool vlan_default_pvid(struct net_bridge_vlan_group *vg, u16 vid) 9505be5a2dfSVlad Yasevich { 9512594e906SNikolay Aleksandrov struct net_bridge_vlan *v; 9522594e906SNikolay Aleksandrov 95377751ee8SNikolay Aleksandrov if (vid != vg->pvid) 9542594e906SNikolay Aleksandrov return false; 9552594e906SNikolay Aleksandrov 9562594e906SNikolay Aleksandrov v = br_vlan_lookup(&vg->vlan_hash, vid); 9572594e906SNikolay Aleksandrov if (v && br_vlan_should_use(v) && 9582594e906SNikolay Aleksandrov (v->flags & BRIDGE_VLAN_INFO_UNTAGGED)) 9592594e906SNikolay Aleksandrov return true; 9602594e906SNikolay Aleksandrov 9612594e906SNikolay Aleksandrov return false; 9625be5a2dfSVlad Yasevich } 9635be5a2dfSVlad Yasevich 9645be5a2dfSVlad Yasevich static void br_vlan_disable_default_pvid(struct net_bridge *br) 9655be5a2dfSVlad Yasevich { 9665be5a2dfSVlad Yasevich struct net_bridge_port *p; 9675be5a2dfSVlad Yasevich u16 pvid = br->default_pvid; 9685be5a2dfSVlad Yasevich 9695be5a2dfSVlad Yasevich /* Disable default_pvid on all ports where it is still 9705be5a2dfSVlad Yasevich * configured. 9715be5a2dfSVlad Yasevich */ 972f545923bSNikolay Aleksandrov if (vlan_default_pvid(br_vlan_group(br), pvid)) { 973f545923bSNikolay Aleksandrov if (!br_vlan_delete(br, pvid)) 974f545923bSNikolay Aleksandrov br_vlan_notify(br, NULL, pvid, 0, RTM_DELVLAN); 975f545923bSNikolay Aleksandrov } 9765be5a2dfSVlad Yasevich 9775be5a2dfSVlad Yasevich list_for_each_entry(p, &br->port_list, list) { 978f545923bSNikolay Aleksandrov if (vlan_default_pvid(nbp_vlan_group(p), pvid) && 979f545923bSNikolay Aleksandrov !nbp_vlan_delete(p, pvid)) 980f545923bSNikolay Aleksandrov br_vlan_notify(br, p, pvid, 0, RTM_DELVLAN); 9815be5a2dfSVlad Yasevich } 9825be5a2dfSVlad Yasevich 9835be5a2dfSVlad Yasevich br->default_pvid = 0; 9845be5a2dfSVlad Yasevich } 9855be5a2dfSVlad Yasevich 986169327d5SPetr Machata int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid, 987169327d5SPetr Machata struct netlink_ext_ack *extack) 9885be5a2dfSVlad Yasevich { 9892594e906SNikolay Aleksandrov const struct net_bridge_vlan *pvent; 990907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 9915be5a2dfSVlad Yasevich struct net_bridge_port *p; 992f418af63SNikolay Aleksandrov unsigned long *changed; 993f418af63SNikolay Aleksandrov bool vlchange; 9945be5a2dfSVlad Yasevich u16 old_pvid; 9955be5a2dfSVlad Yasevich int err = 0; 9965be5a2dfSVlad Yasevich 9970f963b75SNikolay Aleksandrov if (!pvid) { 9980f963b75SNikolay Aleksandrov br_vlan_disable_default_pvid(br); 9990f963b75SNikolay Aleksandrov return 0; 10000f963b75SNikolay Aleksandrov } 10010f963b75SNikolay Aleksandrov 1002459479daSAndy Shevchenko changed = bitmap_zalloc(BR_MAX_PORTS, GFP_KERNEL); 10035be5a2dfSVlad Yasevich if (!changed) 10045be5a2dfSVlad Yasevich return -ENOMEM; 10055be5a2dfSVlad Yasevich 10065be5a2dfSVlad Yasevich old_pvid = br->default_pvid; 10075be5a2dfSVlad Yasevich 10085be5a2dfSVlad Yasevich /* Update default_pvid config only if we do not conflict with 10095be5a2dfSVlad Yasevich * user configuration. 10105be5a2dfSVlad Yasevich */ 1011907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 1012907b1e6eSNikolay Aleksandrov pvent = br_vlan_find(vg, pvid); 1013907b1e6eSNikolay Aleksandrov if ((!old_pvid || vlan_default_pvid(vg, old_pvid)) && 10142594e906SNikolay Aleksandrov (!pvent || !br_vlan_should_use(pvent))) { 10155be5a2dfSVlad Yasevich err = br_vlan_add(br, pvid, 10165be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_PVID | 10172594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED | 1018f418af63SNikolay Aleksandrov BRIDGE_VLAN_INFO_BRENTRY, 1019169327d5SPetr Machata &vlchange, extack); 10205be5a2dfSVlad Yasevich if (err) 10215be5a2dfSVlad Yasevich goto out; 1022f545923bSNikolay Aleksandrov 1023f545923bSNikolay Aleksandrov if (br_vlan_delete(br, old_pvid)) 1024f545923bSNikolay Aleksandrov br_vlan_notify(br, NULL, old_pvid, 0, RTM_DELVLAN); 1025f545923bSNikolay Aleksandrov br_vlan_notify(br, NULL, pvid, 0, RTM_NEWVLAN); 10265be5a2dfSVlad Yasevich set_bit(0, changed); 10275be5a2dfSVlad Yasevich } 10285be5a2dfSVlad Yasevich 10295be5a2dfSVlad Yasevich list_for_each_entry(p, &br->port_list, list) { 10305be5a2dfSVlad Yasevich /* Update default_pvid config only if we do not conflict with 10315be5a2dfSVlad Yasevich * user configuration. 10325be5a2dfSVlad Yasevich */ 1033907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 10345be5a2dfSVlad Yasevich if ((old_pvid && 1035907b1e6eSNikolay Aleksandrov !vlan_default_pvid(vg, old_pvid)) || 1036907b1e6eSNikolay Aleksandrov br_vlan_find(vg, pvid)) 10375be5a2dfSVlad Yasevich continue; 10385be5a2dfSVlad Yasevich 10395be5a2dfSVlad Yasevich err = nbp_vlan_add(p, pvid, 10405be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_PVID | 1041f418af63SNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED, 1042169327d5SPetr Machata &vlchange, extack); 10435be5a2dfSVlad Yasevich if (err) 10445be5a2dfSVlad Yasevich goto err_port; 1045f545923bSNikolay Aleksandrov if (nbp_vlan_delete(p, old_pvid)) 1046f545923bSNikolay Aleksandrov br_vlan_notify(br, p, old_pvid, 0, RTM_DELVLAN); 1047f545923bSNikolay Aleksandrov br_vlan_notify(p->br, p, pvid, 0, RTM_NEWVLAN); 10485be5a2dfSVlad Yasevich set_bit(p->port_no, changed); 10495be5a2dfSVlad Yasevich } 10505be5a2dfSVlad Yasevich 10515be5a2dfSVlad Yasevich br->default_pvid = pvid; 10525be5a2dfSVlad Yasevich 10535be5a2dfSVlad Yasevich out: 1054459479daSAndy Shevchenko bitmap_free(changed); 10555be5a2dfSVlad Yasevich return err; 10565be5a2dfSVlad Yasevich 10575be5a2dfSVlad Yasevich err_port: 10585be5a2dfSVlad Yasevich list_for_each_entry_continue_reverse(p, &br->port_list, list) { 10595be5a2dfSVlad Yasevich if (!test_bit(p->port_no, changed)) 10605be5a2dfSVlad Yasevich continue; 10615be5a2dfSVlad Yasevich 1062f545923bSNikolay Aleksandrov if (old_pvid) { 10635be5a2dfSVlad Yasevich nbp_vlan_add(p, old_pvid, 10645be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_PVID | 1065f418af63SNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED, 1066169327d5SPetr Machata &vlchange, NULL); 1067f545923bSNikolay Aleksandrov br_vlan_notify(p->br, p, old_pvid, 0, RTM_NEWVLAN); 1068f545923bSNikolay Aleksandrov } 10695be5a2dfSVlad Yasevich nbp_vlan_delete(p, pvid); 1070f545923bSNikolay Aleksandrov br_vlan_notify(br, p, pvid, 0, RTM_DELVLAN); 10715be5a2dfSVlad Yasevich } 10725be5a2dfSVlad Yasevich 10735be5a2dfSVlad Yasevich if (test_bit(0, changed)) { 1074f545923bSNikolay Aleksandrov if (old_pvid) { 10755be5a2dfSVlad Yasevich br_vlan_add(br, old_pvid, 10765be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_PVID | 10772594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED | 1078f418af63SNikolay Aleksandrov BRIDGE_VLAN_INFO_BRENTRY, 1079169327d5SPetr Machata &vlchange, NULL); 1080f545923bSNikolay Aleksandrov br_vlan_notify(br, NULL, old_pvid, 0, RTM_NEWVLAN); 1081f545923bSNikolay Aleksandrov } 10825be5a2dfSVlad Yasevich br_vlan_delete(br, pvid); 1083f545923bSNikolay Aleksandrov br_vlan_notify(br, NULL, pvid, 0, RTM_DELVLAN); 10845be5a2dfSVlad Yasevich } 10855be5a2dfSVlad Yasevich goto out; 10865be5a2dfSVlad Yasevich } 10875be5a2dfSVlad Yasevich 108896a20d9dSVlad Yasevich int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val) 108996a20d9dSVlad Yasevich { 109096a20d9dSVlad Yasevich u16 pvid = val; 109196a20d9dSVlad Yasevich int err = 0; 109296a20d9dSVlad Yasevich 10935be5a2dfSVlad Yasevich if (val >= VLAN_VID_MASK) 109496a20d9dSVlad Yasevich return -EINVAL; 109596a20d9dSVlad Yasevich 109696a20d9dSVlad Yasevich if (pvid == br->default_pvid) 1097047831a9SXin Long goto out; 109896a20d9dSVlad Yasevich 109996a20d9dSVlad Yasevich /* Only allow default pvid change when filtering is disabled */ 1100ae75767eSNikolay Aleksandrov if (br_opt_get(br, BROPT_VLAN_ENABLED)) { 110196a20d9dSVlad Yasevich pr_info_once("Please disable vlan filtering to change default_pvid\n"); 110296a20d9dSVlad Yasevich err = -EPERM; 1103047831a9SXin Long goto out; 110496a20d9dSVlad Yasevich } 1105169327d5SPetr Machata err = __br_vlan_set_default_pvid(br, pvid, NULL); 1106047831a9SXin Long out: 110796a20d9dSVlad Yasevich return err; 110896a20d9dSVlad Yasevich } 110996a20d9dSVlad Yasevich 11105be5a2dfSVlad Yasevich int br_vlan_init(struct net_bridge *br) 11118580e211SToshiaki Makita { 1112907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 11132594e906SNikolay Aleksandrov int ret = -ENOMEM; 11142594e906SNikolay Aleksandrov 1115907b1e6eSNikolay Aleksandrov vg = kzalloc(sizeof(*vg), GFP_KERNEL); 1116907b1e6eSNikolay Aleksandrov if (!vg) 11172594e906SNikolay Aleksandrov goto out; 1118907b1e6eSNikolay Aleksandrov ret = rhashtable_init(&vg->vlan_hash, &br_vlan_rht_params); 11192594e906SNikolay Aleksandrov if (ret) 11202594e906SNikolay Aleksandrov goto err_rhtbl; 1121efa5356bSRoopa Prabhu ret = vlan_tunnel_init(vg); 1122efa5356bSRoopa Prabhu if (ret) 1123efa5356bSRoopa Prabhu goto err_tunnel_init; 1124907b1e6eSNikolay Aleksandrov INIT_LIST_HEAD(&vg->vlan_list); 11258580e211SToshiaki Makita br->vlan_proto = htons(ETH_P_8021Q); 112696a20d9dSVlad Yasevich br->default_pvid = 1; 1127907b1e6eSNikolay Aleksandrov rcu_assign_pointer(br->vlgrp, vg); 11282594e906SNikolay Aleksandrov 11292594e906SNikolay Aleksandrov out: 11302594e906SNikolay Aleksandrov return ret; 11312594e906SNikolay Aleksandrov 1132efa5356bSRoopa Prabhu err_tunnel_init: 1133907b1e6eSNikolay Aleksandrov rhashtable_destroy(&vg->vlan_hash); 11342594e906SNikolay Aleksandrov err_rhtbl: 1135907b1e6eSNikolay Aleksandrov kfree(vg); 11362594e906SNikolay Aleksandrov 11372594e906SNikolay Aleksandrov goto out; 11382594e906SNikolay Aleksandrov } 11392594e906SNikolay Aleksandrov 1140169327d5SPetr Machata int nbp_vlan_init(struct net_bridge_port *p, struct netlink_ext_ack *extack) 11412594e906SNikolay Aleksandrov { 1142404cdbf0SElad Raz struct switchdev_attr attr = { 1143404cdbf0SElad Raz .orig_dev = p->br->dev, 1144404cdbf0SElad Raz .id = SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING, 1145404cdbf0SElad Raz .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP, 1146ae75767eSNikolay Aleksandrov .u.vlan_filtering = br_opt_get(p->br, BROPT_VLAN_ENABLED), 1147404cdbf0SElad Raz }; 1148263344e6SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 11492594e906SNikolay Aleksandrov int ret = -ENOMEM; 11502594e906SNikolay Aleksandrov 1151263344e6SNikolay Aleksandrov vg = kzalloc(sizeof(struct net_bridge_vlan_group), GFP_KERNEL); 1152263344e6SNikolay Aleksandrov if (!vg) 11532594e906SNikolay Aleksandrov goto out; 11542594e906SNikolay Aleksandrov 1155404cdbf0SElad Raz ret = switchdev_port_attr_set(p->dev, &attr); 1156404cdbf0SElad Raz if (ret && ret != -EOPNOTSUPP) 1157404cdbf0SElad Raz goto err_vlan_enabled; 1158404cdbf0SElad Raz 1159263344e6SNikolay Aleksandrov ret = rhashtable_init(&vg->vlan_hash, &br_vlan_rht_params); 11602594e906SNikolay Aleksandrov if (ret) 11612594e906SNikolay Aleksandrov goto err_rhtbl; 1162efa5356bSRoopa Prabhu ret = vlan_tunnel_init(vg); 1163efa5356bSRoopa Prabhu if (ret) 1164efa5356bSRoopa Prabhu goto err_tunnel_init; 1165263344e6SNikolay Aleksandrov INIT_LIST_HEAD(&vg->vlan_list); 1166907b1e6eSNikolay Aleksandrov rcu_assign_pointer(p->vlgrp, vg); 11672594e906SNikolay Aleksandrov if (p->br->default_pvid) { 1168f418af63SNikolay Aleksandrov bool changed; 1169f418af63SNikolay Aleksandrov 11702594e906SNikolay Aleksandrov ret = nbp_vlan_add(p, p->br->default_pvid, 11712594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_PVID | 1172f418af63SNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED, 1173169327d5SPetr Machata &changed, extack); 11742594e906SNikolay Aleksandrov if (ret) 11752594e906SNikolay Aleksandrov goto err_vlan_add; 1176f545923bSNikolay Aleksandrov br_vlan_notify(p->br, p, p->br->default_pvid, 0, RTM_NEWVLAN); 11772594e906SNikolay Aleksandrov } 11782594e906SNikolay Aleksandrov out: 11792594e906SNikolay Aleksandrov return ret; 11802594e906SNikolay Aleksandrov 11812594e906SNikolay Aleksandrov err_vlan_add: 118207bc588fSIdo Schimmel RCU_INIT_POINTER(p->vlgrp, NULL); 118307bc588fSIdo Schimmel synchronize_rcu(); 1184efa5356bSRoopa Prabhu vlan_tunnel_deinit(vg); 1185efa5356bSRoopa Prabhu err_tunnel_init: 1186efa5356bSRoopa Prabhu rhashtable_destroy(&vg->vlan_hash); 11872594e906SNikolay Aleksandrov err_rhtbl: 1188df2c4334SYotam Gigi err_vlan_enabled: 1189263344e6SNikolay Aleksandrov kfree(vg); 11902594e906SNikolay Aleksandrov 11912594e906SNikolay Aleksandrov goto out; 11928580e211SToshiaki Makita } 11938580e211SToshiaki Makita 11948adff41cSToshiaki Makita /* Must be protected by RTNL. 11958adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 1196f418af63SNikolay Aleksandrov * changed must be true only if the vlan was created or updated 11978adff41cSToshiaki Makita */ 1198f418af63SNikolay Aleksandrov int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags, 1199169327d5SPetr Machata bool *changed, struct netlink_ext_ack *extack) 1200243a2e63SVlad Yasevich { 12012594e906SNikolay Aleksandrov struct net_bridge_vlan *vlan; 12022594e906SNikolay Aleksandrov int ret; 1203243a2e63SVlad Yasevich 1204243a2e63SVlad Yasevich ASSERT_RTNL(); 1205243a2e63SVlad Yasevich 1206f418af63SNikolay Aleksandrov *changed = false; 1207907b1e6eSNikolay Aleksandrov vlan = br_vlan_find(nbp_vlan_group(port), vid); 12082594e906SNikolay Aleksandrov if (vlan) { 12097fbac984SIdo Schimmel /* Pass the flags to the hardware bridge */ 1210169327d5SPetr Machata ret = br_switchdev_port_vlan_add(port->dev, vid, flags, extack); 12117fbac984SIdo Schimmel if (ret && ret != -EOPNOTSUPP) 12127fbac984SIdo Schimmel return ret; 1213f418af63SNikolay Aleksandrov *changed = __vlan_add_flags(vlan, flags); 1214f418af63SNikolay Aleksandrov 12152594e906SNikolay Aleksandrov return 0; 1216243a2e63SVlad Yasevich } 1217243a2e63SVlad Yasevich 12182594e906SNikolay Aleksandrov vlan = kzalloc(sizeof(*vlan), GFP_KERNEL); 12192594e906SNikolay Aleksandrov if (!vlan) 12202594e906SNikolay Aleksandrov return -ENOMEM; 1221243a2e63SVlad Yasevich 12222594e906SNikolay Aleksandrov vlan->vid = vid; 12232594e906SNikolay Aleksandrov vlan->port = port; 1224169327d5SPetr Machata ret = __vlan_add(vlan, flags, extack); 12252594e906SNikolay Aleksandrov if (ret) 12262594e906SNikolay Aleksandrov kfree(vlan); 1227f418af63SNikolay Aleksandrov else 1228f418af63SNikolay Aleksandrov *changed = true; 1229243a2e63SVlad Yasevich 12302594e906SNikolay Aleksandrov return ret; 1231243a2e63SVlad Yasevich } 1232243a2e63SVlad Yasevich 12338adff41cSToshiaki Makita /* Must be protected by RTNL. 12348adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 12358adff41cSToshiaki Makita */ 1236243a2e63SVlad Yasevich int nbp_vlan_delete(struct net_bridge_port *port, u16 vid) 1237243a2e63SVlad Yasevich { 12382594e906SNikolay Aleksandrov struct net_bridge_vlan *v; 1239243a2e63SVlad Yasevich 1240243a2e63SVlad Yasevich ASSERT_RTNL(); 1241243a2e63SVlad Yasevich 1242907b1e6eSNikolay Aleksandrov v = br_vlan_find(nbp_vlan_group(port), vid); 12432594e906SNikolay Aleksandrov if (!v) 12442594e906SNikolay Aleksandrov return -ENOENT; 1245424bb9c9SToshiaki Makita br_fdb_find_delete_local(port->br, port, port->dev->dev_addr, vid); 12461ea2d020SNikolay Aleksandrov br_fdb_delete_by_port(port->br, port, vid, 0); 1247bc9a25d2SVlad Yasevich 12482594e906SNikolay Aleksandrov return __vlan_del(v); 1249243a2e63SVlad Yasevich } 1250243a2e63SVlad Yasevich 1251243a2e63SVlad Yasevich void nbp_vlan_flush(struct net_bridge_port *port) 1252243a2e63SVlad Yasevich { 1253f409d0edSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 1254f409d0edSNikolay Aleksandrov 1255243a2e63SVlad Yasevich ASSERT_RTNL(); 1256243a2e63SVlad Yasevich 1257f409d0edSNikolay Aleksandrov vg = nbp_vlan_group(port); 1258f545923bSNikolay Aleksandrov __vlan_flush(port->br, port, vg); 1259f409d0edSNikolay Aleksandrov RCU_INIT_POINTER(port->vlgrp, NULL); 1260f409d0edSNikolay Aleksandrov synchronize_rcu(); 1261f409d0edSNikolay Aleksandrov __vlan_group_free(vg); 12625be5a2dfSVlad Yasevich } 1263a60c0903SNikolay Aleksandrov 1264a60c0903SNikolay Aleksandrov void br_vlan_get_stats(const struct net_bridge_vlan *v, 1265a60c0903SNikolay Aleksandrov struct br_vlan_stats *stats) 1266a60c0903SNikolay Aleksandrov { 1267a60c0903SNikolay Aleksandrov int i; 1268a60c0903SNikolay Aleksandrov 1269a60c0903SNikolay Aleksandrov memset(stats, 0, sizeof(*stats)); 1270a60c0903SNikolay Aleksandrov for_each_possible_cpu(i) { 1271a60c0903SNikolay Aleksandrov u64 rxpackets, rxbytes, txpackets, txbytes; 1272a60c0903SNikolay Aleksandrov struct br_vlan_stats *cpu_stats; 1273a60c0903SNikolay Aleksandrov unsigned int start; 1274a60c0903SNikolay Aleksandrov 1275a60c0903SNikolay Aleksandrov cpu_stats = per_cpu_ptr(v->stats, i); 1276a60c0903SNikolay Aleksandrov do { 1277a60c0903SNikolay Aleksandrov start = u64_stats_fetch_begin_irq(&cpu_stats->syncp); 1278a60c0903SNikolay Aleksandrov rxpackets = cpu_stats->rx_packets; 1279a60c0903SNikolay Aleksandrov rxbytes = cpu_stats->rx_bytes; 1280a60c0903SNikolay Aleksandrov txbytes = cpu_stats->tx_bytes; 1281a60c0903SNikolay Aleksandrov txpackets = cpu_stats->tx_packets; 1282a60c0903SNikolay Aleksandrov } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start)); 1283a60c0903SNikolay Aleksandrov 1284a60c0903SNikolay Aleksandrov stats->rx_packets += rxpackets; 1285a60c0903SNikolay Aleksandrov stats->rx_bytes += rxbytes; 1286a60c0903SNikolay Aleksandrov stats->tx_bytes += txbytes; 1287a60c0903SNikolay Aleksandrov stats->tx_packets += txpackets; 1288a60c0903SNikolay Aleksandrov } 1289a60c0903SNikolay Aleksandrov } 12904d4fd361SPetr Machata 12917582f5b7SPablo Neira Ayuso static int __br_vlan_get_pvid(const struct net_device *dev, 12927582f5b7SPablo Neira Ayuso struct net_bridge_port *p, u16 *p_pvid) 12934d4fd361SPetr Machata { 12944d4fd361SPetr Machata struct net_bridge_vlan_group *vg; 12954d4fd361SPetr Machata 12965a6db04cSIdo Schimmel if (p) 12975a6db04cSIdo Schimmel vg = nbp_vlan_group(p); 12985a6db04cSIdo Schimmel else if (netif_is_bridge_master(dev)) 12994d4fd361SPetr Machata vg = br_vlan_group(netdev_priv(dev)); 13004d4fd361SPetr Machata else 13014d4fd361SPetr Machata return -EINVAL; 13024d4fd361SPetr Machata 13034d4fd361SPetr Machata *p_pvid = br_get_pvid(vg); 13044d4fd361SPetr Machata return 0; 13054d4fd361SPetr Machata } 13067582f5b7SPablo Neira Ayuso 13077582f5b7SPablo Neira Ayuso int br_vlan_get_pvid(const struct net_device *dev, u16 *p_pvid) 13087582f5b7SPablo Neira Ayuso { 13097582f5b7SPablo Neira Ayuso ASSERT_RTNL(); 13107582f5b7SPablo Neira Ayuso 13117582f5b7SPablo Neira Ayuso return __br_vlan_get_pvid(dev, br_port_get_check_rtnl(dev), p_pvid); 13127582f5b7SPablo Neira Ayuso } 13134d4fd361SPetr Machata EXPORT_SYMBOL_GPL(br_vlan_get_pvid); 13144d4fd361SPetr Machata 13157582f5b7SPablo Neira Ayuso int br_vlan_get_pvid_rcu(const struct net_device *dev, u16 *p_pvid) 13167582f5b7SPablo Neira Ayuso { 13177582f5b7SPablo Neira Ayuso return __br_vlan_get_pvid(dev, br_port_get_check_rcu(dev), p_pvid); 13187582f5b7SPablo Neira Ayuso } 13197582f5b7SPablo Neira Ayuso EXPORT_SYMBOL_GPL(br_vlan_get_pvid_rcu); 13207582f5b7SPablo Neira Ayuso 13214d4fd361SPetr Machata int br_vlan_get_info(const struct net_device *dev, u16 vid, 13224d4fd361SPetr Machata struct bridge_vlan_info *p_vinfo) 13234d4fd361SPetr Machata { 13244d4fd361SPetr Machata struct net_bridge_vlan_group *vg; 13254d4fd361SPetr Machata struct net_bridge_vlan *v; 13264d4fd361SPetr Machata struct net_bridge_port *p; 13274d4fd361SPetr Machata 13284d4fd361SPetr Machata ASSERT_RTNL(); 13294d4fd361SPetr Machata p = br_port_get_check_rtnl(dev); 13304d4fd361SPetr Machata if (p) 13314d4fd361SPetr Machata vg = nbp_vlan_group(p); 13322b18d79eSPetr Machata else if (netif_is_bridge_master(dev)) 13332b18d79eSPetr Machata vg = br_vlan_group(netdev_priv(dev)); 13344d4fd361SPetr Machata else 13354d4fd361SPetr Machata return -EINVAL; 13364d4fd361SPetr Machata 13374d4fd361SPetr Machata v = br_vlan_find(vg, vid); 13384d4fd361SPetr Machata if (!v) 13394d4fd361SPetr Machata return -ENOENT; 13404d4fd361SPetr Machata 13414d4fd361SPetr Machata p_vinfo->vid = vid; 13424d4fd361SPetr Machata p_vinfo->flags = v->flags; 1343f40d9b20SVladimir Oltean if (vid == br_get_pvid(vg)) 1344f40d9b20SVladimir Oltean p_vinfo->flags |= BRIDGE_VLAN_INFO_PVID; 13454d4fd361SPetr Machata return 0; 13464d4fd361SPetr Machata } 13474d4fd361SPetr Machata EXPORT_SYMBOL_GPL(br_vlan_get_info); 13489c0ec2e7SMike Manning 13499c0ec2e7SMike Manning static int br_vlan_is_bind_vlan_dev(const struct net_device *dev) 13509c0ec2e7SMike Manning { 13519c0ec2e7SMike Manning return is_vlan_dev(dev) && 13529c0ec2e7SMike Manning !!(vlan_dev_priv(dev)->flags & VLAN_FLAG_BRIDGE_BINDING); 13539c0ec2e7SMike Manning } 13549c0ec2e7SMike Manning 13559c0ec2e7SMike Manning static int br_vlan_is_bind_vlan_dev_fn(struct net_device *dev, 13569c0ec2e7SMike Manning __always_unused void *data) 13579c0ec2e7SMike Manning { 13589c0ec2e7SMike Manning return br_vlan_is_bind_vlan_dev(dev); 13599c0ec2e7SMike Manning } 13609c0ec2e7SMike Manning 13619c0ec2e7SMike Manning static bool br_vlan_has_upper_bind_vlan_dev(struct net_device *dev) 13629c0ec2e7SMike Manning { 13639c0ec2e7SMike Manning int found; 13649c0ec2e7SMike Manning 13659c0ec2e7SMike Manning rcu_read_lock(); 13669c0ec2e7SMike Manning found = netdev_walk_all_upper_dev_rcu(dev, br_vlan_is_bind_vlan_dev_fn, 13679c0ec2e7SMike Manning NULL); 13689c0ec2e7SMike Manning rcu_read_unlock(); 13699c0ec2e7SMike Manning 13709c0ec2e7SMike Manning return !!found; 13719c0ec2e7SMike Manning } 13729c0ec2e7SMike Manning 13739c0ec2e7SMike Manning struct br_vlan_bind_walk_data { 13749c0ec2e7SMike Manning u16 vid; 13759c0ec2e7SMike Manning struct net_device *result; 13769c0ec2e7SMike Manning }; 13779c0ec2e7SMike Manning 13789c0ec2e7SMike Manning static int br_vlan_match_bind_vlan_dev_fn(struct net_device *dev, 13799c0ec2e7SMike Manning void *data_in) 13809c0ec2e7SMike Manning { 13819c0ec2e7SMike Manning struct br_vlan_bind_walk_data *data = data_in; 13829c0ec2e7SMike Manning int found = 0; 13839c0ec2e7SMike Manning 13849c0ec2e7SMike Manning if (br_vlan_is_bind_vlan_dev(dev) && 13859c0ec2e7SMike Manning vlan_dev_priv(dev)->vlan_id == data->vid) { 13869c0ec2e7SMike Manning data->result = dev; 13879c0ec2e7SMike Manning found = 1; 13889c0ec2e7SMike Manning } 13899c0ec2e7SMike Manning 13909c0ec2e7SMike Manning return found; 13919c0ec2e7SMike Manning } 13929c0ec2e7SMike Manning 13939c0ec2e7SMike Manning static struct net_device * 13949c0ec2e7SMike Manning br_vlan_get_upper_bind_vlan_dev(struct net_device *dev, u16 vid) 13959c0ec2e7SMike Manning { 13969c0ec2e7SMike Manning struct br_vlan_bind_walk_data data = { 13979c0ec2e7SMike Manning .vid = vid, 13989c0ec2e7SMike Manning }; 13999c0ec2e7SMike Manning 14009c0ec2e7SMike Manning rcu_read_lock(); 14019c0ec2e7SMike Manning netdev_walk_all_upper_dev_rcu(dev, br_vlan_match_bind_vlan_dev_fn, 14029c0ec2e7SMike Manning &data); 14039c0ec2e7SMike Manning rcu_read_unlock(); 14049c0ec2e7SMike Manning 14059c0ec2e7SMike Manning return data.result; 14069c0ec2e7SMike Manning } 14079c0ec2e7SMike Manning 14089c0ec2e7SMike Manning static bool br_vlan_is_dev_up(const struct net_device *dev) 14099c0ec2e7SMike Manning { 14109c0ec2e7SMike Manning return !!(dev->flags & IFF_UP) && netif_oper_up(dev); 14119c0ec2e7SMike Manning } 14129c0ec2e7SMike Manning 14139c0ec2e7SMike Manning static void br_vlan_set_vlan_dev_state(const struct net_bridge *br, 14149c0ec2e7SMike Manning struct net_device *vlan_dev) 14159c0ec2e7SMike Manning { 14169c0ec2e7SMike Manning u16 vid = vlan_dev_priv(vlan_dev)->vlan_id; 14179c0ec2e7SMike Manning struct net_bridge_vlan_group *vg; 14189c0ec2e7SMike Manning struct net_bridge_port *p; 14199c0ec2e7SMike Manning bool has_carrier = false; 14209c0ec2e7SMike Manning 14218e1acd4fSMike Manning if (!netif_carrier_ok(br->dev)) { 14228e1acd4fSMike Manning netif_carrier_off(vlan_dev); 14238e1acd4fSMike Manning return; 14248e1acd4fSMike Manning } 14258e1acd4fSMike Manning 14269c0ec2e7SMike Manning list_for_each_entry(p, &br->port_list, list) { 14279c0ec2e7SMike Manning vg = nbp_vlan_group(p); 14289c0ec2e7SMike Manning if (br_vlan_find(vg, vid) && br_vlan_is_dev_up(p->dev)) { 14299c0ec2e7SMike Manning has_carrier = true; 14309c0ec2e7SMike Manning break; 14319c0ec2e7SMike Manning } 14329c0ec2e7SMike Manning } 14339c0ec2e7SMike Manning 14349c0ec2e7SMike Manning if (has_carrier) 14359c0ec2e7SMike Manning netif_carrier_on(vlan_dev); 14369c0ec2e7SMike Manning else 14379c0ec2e7SMike Manning netif_carrier_off(vlan_dev); 14389c0ec2e7SMike Manning } 14399c0ec2e7SMike Manning 14409c0ec2e7SMike Manning static void br_vlan_set_all_vlan_dev_state(struct net_bridge_port *p) 14419c0ec2e7SMike Manning { 14429c0ec2e7SMike Manning struct net_bridge_vlan_group *vg = nbp_vlan_group(p); 14439c0ec2e7SMike Manning struct net_bridge_vlan *vlan; 14449c0ec2e7SMike Manning struct net_device *vlan_dev; 14459c0ec2e7SMike Manning 14469c0ec2e7SMike Manning list_for_each_entry(vlan, &vg->vlan_list, vlist) { 14479c0ec2e7SMike Manning vlan_dev = br_vlan_get_upper_bind_vlan_dev(p->br->dev, 14489c0ec2e7SMike Manning vlan->vid); 14499c0ec2e7SMike Manning if (vlan_dev) { 14508e1acd4fSMike Manning if (br_vlan_is_dev_up(p->dev)) { 14518e1acd4fSMike Manning if (netif_carrier_ok(p->br->dev)) 14529c0ec2e7SMike Manning netif_carrier_on(vlan_dev); 14538e1acd4fSMike Manning } else { 14549c0ec2e7SMike Manning br_vlan_set_vlan_dev_state(p->br, vlan_dev); 14559c0ec2e7SMike Manning } 14569c0ec2e7SMike Manning } 14579c0ec2e7SMike Manning } 14588e1acd4fSMike Manning } 14599c0ec2e7SMike Manning 14609c0ec2e7SMike Manning static void br_vlan_upper_change(struct net_device *dev, 14619c0ec2e7SMike Manning struct net_device *upper_dev, 14629c0ec2e7SMike Manning bool linking) 14639c0ec2e7SMike Manning { 14649c0ec2e7SMike Manning struct net_bridge *br = netdev_priv(dev); 14659c0ec2e7SMike Manning 14669c0ec2e7SMike Manning if (!br_vlan_is_bind_vlan_dev(upper_dev)) 14679c0ec2e7SMike Manning return; 14689c0ec2e7SMike Manning 14699c0ec2e7SMike Manning if (linking) { 14709c0ec2e7SMike Manning br_vlan_set_vlan_dev_state(br, upper_dev); 14719c0ec2e7SMike Manning br_opt_toggle(br, BROPT_VLAN_BRIDGE_BINDING, true); 14729c0ec2e7SMike Manning } else { 14739c0ec2e7SMike Manning br_opt_toggle(br, BROPT_VLAN_BRIDGE_BINDING, 14749c0ec2e7SMike Manning br_vlan_has_upper_bind_vlan_dev(dev)); 14759c0ec2e7SMike Manning } 14769c0ec2e7SMike Manning } 14779c0ec2e7SMike Manning 14788e1acd4fSMike Manning struct br_vlan_link_state_walk_data { 14798e1acd4fSMike Manning struct net_bridge *br; 14808e1acd4fSMike Manning }; 14818e1acd4fSMike Manning 14828e1acd4fSMike Manning static int br_vlan_link_state_change_fn(struct net_device *vlan_dev, 14838e1acd4fSMike Manning void *data_in) 14848e1acd4fSMike Manning { 14858e1acd4fSMike Manning struct br_vlan_link_state_walk_data *data = data_in; 14868e1acd4fSMike Manning 14878e1acd4fSMike Manning if (br_vlan_is_bind_vlan_dev(vlan_dev)) 14888e1acd4fSMike Manning br_vlan_set_vlan_dev_state(data->br, vlan_dev); 14898e1acd4fSMike Manning 14908e1acd4fSMike Manning return 0; 14918e1acd4fSMike Manning } 14928e1acd4fSMike Manning 14938e1acd4fSMike Manning static void br_vlan_link_state_change(struct net_device *dev, 14948e1acd4fSMike Manning struct net_bridge *br) 14958e1acd4fSMike Manning { 14968e1acd4fSMike Manning struct br_vlan_link_state_walk_data data = { 14978e1acd4fSMike Manning .br = br 14988e1acd4fSMike Manning }; 14998e1acd4fSMike Manning 15008e1acd4fSMike Manning rcu_read_lock(); 15018e1acd4fSMike Manning netdev_walk_all_upper_dev_rcu(dev, br_vlan_link_state_change_fn, 15028e1acd4fSMike Manning &data); 15038e1acd4fSMike Manning rcu_read_unlock(); 15048e1acd4fSMike Manning } 15058e1acd4fSMike Manning 15069c0ec2e7SMike Manning /* Must be protected by RTNL. */ 150780900acdSMike Manning static void nbp_vlan_set_vlan_dev_state(struct net_bridge_port *p, u16 vid) 150880900acdSMike Manning { 150980900acdSMike Manning struct net_device *vlan_dev; 151080900acdSMike Manning 151180900acdSMike Manning if (!br_opt_get(p->br, BROPT_VLAN_BRIDGE_BINDING)) 151280900acdSMike Manning return; 151380900acdSMike Manning 151480900acdSMike Manning vlan_dev = br_vlan_get_upper_bind_vlan_dev(p->br->dev, vid); 151580900acdSMike Manning if (vlan_dev) 151680900acdSMike Manning br_vlan_set_vlan_dev_state(p->br, vlan_dev); 151780900acdSMike Manning } 151880900acdSMike Manning 151980900acdSMike Manning /* Must be protected by RTNL. */ 1520091adf9bSNikolay Aleksandrov int br_vlan_bridge_event(struct net_device *dev, unsigned long event, void *ptr) 15219c0ec2e7SMike Manning { 15229c0ec2e7SMike Manning struct netdev_notifier_changeupper_info *info; 1523091adf9bSNikolay Aleksandrov struct net_bridge *br = netdev_priv(dev); 1524f545923bSNikolay Aleksandrov int vlcmd = 0, ret = 0; 1525f545923bSNikolay Aleksandrov bool changed = false; 15269c0ec2e7SMike Manning 15279c0ec2e7SMike Manning switch (event) { 1528091adf9bSNikolay Aleksandrov case NETDEV_REGISTER: 1529091adf9bSNikolay Aleksandrov ret = br_vlan_add(br, br->default_pvid, 1530091adf9bSNikolay Aleksandrov BRIDGE_VLAN_INFO_PVID | 1531091adf9bSNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED | 1532091adf9bSNikolay Aleksandrov BRIDGE_VLAN_INFO_BRENTRY, &changed, NULL); 1533f545923bSNikolay Aleksandrov vlcmd = RTM_NEWVLAN; 1534091adf9bSNikolay Aleksandrov break; 1535091adf9bSNikolay Aleksandrov case NETDEV_UNREGISTER: 1536f545923bSNikolay Aleksandrov changed = !br_vlan_delete(br, br->default_pvid); 1537f545923bSNikolay Aleksandrov vlcmd = RTM_DELVLAN; 1538091adf9bSNikolay Aleksandrov break; 15399c0ec2e7SMike Manning case NETDEV_CHANGEUPPER: 15409c0ec2e7SMike Manning info = ptr; 15419c0ec2e7SMike Manning br_vlan_upper_change(dev, info->upper_dev, info->linking); 15429c0ec2e7SMike Manning break; 15438e1acd4fSMike Manning 15448e1acd4fSMike Manning case NETDEV_CHANGE: 15458e1acd4fSMike Manning case NETDEV_UP: 15468e1acd4fSMike Manning if (!br_opt_get(br, BROPT_VLAN_BRIDGE_BINDING)) 1547091adf9bSNikolay Aleksandrov break; 15488e1acd4fSMike Manning br_vlan_link_state_change(dev, br); 15498e1acd4fSMike Manning break; 15509c0ec2e7SMike Manning } 1551f545923bSNikolay Aleksandrov if (changed) 1552f545923bSNikolay Aleksandrov br_vlan_notify(br, NULL, br->default_pvid, 0, vlcmd); 1553091adf9bSNikolay Aleksandrov 1554091adf9bSNikolay Aleksandrov return ret; 15559c0ec2e7SMike Manning } 15569c0ec2e7SMike Manning 15579c0ec2e7SMike Manning /* Must be protected by RTNL. */ 15589c0ec2e7SMike Manning void br_vlan_port_event(struct net_bridge_port *p, unsigned long event) 15599c0ec2e7SMike Manning { 15609c0ec2e7SMike Manning if (!br_opt_get(p->br, BROPT_VLAN_BRIDGE_BINDING)) 15619c0ec2e7SMike Manning return; 15629c0ec2e7SMike Manning 15639c0ec2e7SMike Manning switch (event) { 15649c0ec2e7SMike Manning case NETDEV_CHANGE: 15659c0ec2e7SMike Manning case NETDEV_DOWN: 15669c0ec2e7SMike Manning case NETDEV_UP: 15679c0ec2e7SMike Manning br_vlan_set_all_vlan_dev_state(p); 15689c0ec2e7SMike Manning break; 15699c0ec2e7SMike Manning } 15709c0ec2e7SMike Manning } 15718dcea187SNikolay Aleksandrov 157256d09976SNikolay Aleksandrov static bool br_vlan_stats_fill(struct sk_buff *skb, 157356d09976SNikolay Aleksandrov const struct net_bridge_vlan *v) 157456d09976SNikolay Aleksandrov { 157556d09976SNikolay Aleksandrov struct br_vlan_stats stats; 157656d09976SNikolay Aleksandrov struct nlattr *nest; 157756d09976SNikolay Aleksandrov 157856d09976SNikolay Aleksandrov nest = nla_nest_start(skb, BRIDGE_VLANDB_ENTRY_STATS); 157956d09976SNikolay Aleksandrov if (!nest) 158056d09976SNikolay Aleksandrov return false; 158156d09976SNikolay Aleksandrov 158256d09976SNikolay Aleksandrov br_vlan_get_stats(v, &stats); 158356d09976SNikolay Aleksandrov if (nla_put_u64_64bit(skb, BRIDGE_VLANDB_STATS_RX_BYTES, stats.rx_bytes, 158456d09976SNikolay Aleksandrov BRIDGE_VLANDB_STATS_PAD) || 158556d09976SNikolay Aleksandrov nla_put_u64_64bit(skb, BRIDGE_VLANDB_STATS_RX_PACKETS, 158656d09976SNikolay Aleksandrov stats.rx_packets, BRIDGE_VLANDB_STATS_PAD) || 158756d09976SNikolay Aleksandrov nla_put_u64_64bit(skb, BRIDGE_VLANDB_STATS_TX_BYTES, stats.tx_bytes, 158856d09976SNikolay Aleksandrov BRIDGE_VLANDB_STATS_PAD) || 158956d09976SNikolay Aleksandrov nla_put_u64_64bit(skb, BRIDGE_VLANDB_STATS_TX_PACKETS, 159056d09976SNikolay Aleksandrov stats.tx_packets, BRIDGE_VLANDB_STATS_PAD)) 159156d09976SNikolay Aleksandrov goto out_err; 159256d09976SNikolay Aleksandrov 159356d09976SNikolay Aleksandrov nla_nest_end(skb, nest); 159456d09976SNikolay Aleksandrov 159556d09976SNikolay Aleksandrov return true; 159656d09976SNikolay Aleksandrov 159756d09976SNikolay Aleksandrov out_err: 159856d09976SNikolay Aleksandrov nla_nest_cancel(skb, nest); 159956d09976SNikolay Aleksandrov return false; 160056d09976SNikolay Aleksandrov } 160156d09976SNikolay Aleksandrov 16027a53e718SNikolay Aleksandrov /* v_opts is used to dump the options which must be equal in the whole range */ 16030ab55879SNikolay Aleksandrov static bool br_vlan_fill_vids(struct sk_buff *skb, u16 vid, u16 vid_range, 16047a53e718SNikolay Aleksandrov const struct net_bridge_vlan *v_opts, 160556d09976SNikolay Aleksandrov u16 flags, 160656d09976SNikolay Aleksandrov bool dump_stats) 16078dcea187SNikolay Aleksandrov { 16088dcea187SNikolay Aleksandrov struct bridge_vlan_info info; 16098dcea187SNikolay Aleksandrov struct nlattr *nest; 16108dcea187SNikolay Aleksandrov 16118dcea187SNikolay Aleksandrov nest = nla_nest_start(skb, BRIDGE_VLANDB_ENTRY); 16128dcea187SNikolay Aleksandrov if (!nest) 16138dcea187SNikolay Aleksandrov return false; 16148dcea187SNikolay Aleksandrov 16158dcea187SNikolay Aleksandrov memset(&info, 0, sizeof(info)); 16168dcea187SNikolay Aleksandrov info.vid = vid; 16178dcea187SNikolay Aleksandrov if (flags & BRIDGE_VLAN_INFO_UNTAGGED) 16188dcea187SNikolay Aleksandrov info.flags |= BRIDGE_VLAN_INFO_UNTAGGED; 16198dcea187SNikolay Aleksandrov if (flags & BRIDGE_VLAN_INFO_PVID) 16208dcea187SNikolay Aleksandrov info.flags |= BRIDGE_VLAN_INFO_PVID; 16218dcea187SNikolay Aleksandrov 16228dcea187SNikolay Aleksandrov if (nla_put(skb, BRIDGE_VLANDB_ENTRY_INFO, sizeof(info), &info)) 16238dcea187SNikolay Aleksandrov goto out_err; 16248dcea187SNikolay Aleksandrov 16250ab55879SNikolay Aleksandrov if (vid_range && vid < vid_range && 16260ab55879SNikolay Aleksandrov !(flags & BRIDGE_VLAN_INFO_PVID) && 16270ab55879SNikolay Aleksandrov nla_put_u16(skb, BRIDGE_VLANDB_ENTRY_RANGE, vid_range)) 16280ab55879SNikolay Aleksandrov goto out_err; 16290ab55879SNikolay Aleksandrov 163056d09976SNikolay Aleksandrov if (v_opts) { 163156d09976SNikolay Aleksandrov if (!br_vlan_opts_fill(skb, v_opts)) 16327a53e718SNikolay Aleksandrov goto out_err; 16337a53e718SNikolay Aleksandrov 163456d09976SNikolay Aleksandrov if (dump_stats && !br_vlan_stats_fill(skb, v_opts)) 163556d09976SNikolay Aleksandrov goto out_err; 163656d09976SNikolay Aleksandrov } 163756d09976SNikolay Aleksandrov 16388dcea187SNikolay Aleksandrov nla_nest_end(skb, nest); 16398dcea187SNikolay Aleksandrov 16408dcea187SNikolay Aleksandrov return true; 16418dcea187SNikolay Aleksandrov 16428dcea187SNikolay Aleksandrov out_err: 16438dcea187SNikolay Aleksandrov nla_nest_cancel(skb, nest); 16448dcea187SNikolay Aleksandrov return false; 16458dcea187SNikolay Aleksandrov } 16468dcea187SNikolay Aleksandrov 1647cf5bddb9SNikolay Aleksandrov static size_t rtnl_vlan_nlmsg_size(void) 1648cf5bddb9SNikolay Aleksandrov { 1649cf5bddb9SNikolay Aleksandrov return NLMSG_ALIGN(sizeof(struct br_vlan_msg)) 1650cf5bddb9SNikolay Aleksandrov + nla_total_size(0) /* BRIDGE_VLANDB_ENTRY */ 1651cf5bddb9SNikolay Aleksandrov + nla_total_size(sizeof(u16)) /* BRIDGE_VLANDB_ENTRY_RANGE */ 16527a53e718SNikolay Aleksandrov + nla_total_size(sizeof(struct bridge_vlan_info)) /* BRIDGE_VLANDB_ENTRY_INFO */ 16537a53e718SNikolay Aleksandrov + br_vlan_opts_nl_size(); /* bridge vlan options */ 1654cf5bddb9SNikolay Aleksandrov } 1655cf5bddb9SNikolay Aleksandrov 1656cf5bddb9SNikolay Aleksandrov void br_vlan_notify(const struct net_bridge *br, 1657cf5bddb9SNikolay Aleksandrov const struct net_bridge_port *p, 1658cf5bddb9SNikolay Aleksandrov u16 vid, u16 vid_range, 1659cf5bddb9SNikolay Aleksandrov int cmd) 1660cf5bddb9SNikolay Aleksandrov { 1661cf5bddb9SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 16627a53e718SNikolay Aleksandrov struct net_bridge_vlan *v = NULL; 1663cf5bddb9SNikolay Aleksandrov struct br_vlan_msg *bvm; 1664cf5bddb9SNikolay Aleksandrov struct nlmsghdr *nlh; 1665cf5bddb9SNikolay Aleksandrov struct sk_buff *skb; 1666cf5bddb9SNikolay Aleksandrov int err = -ENOBUFS; 1667cf5bddb9SNikolay Aleksandrov struct net *net; 1668cf5bddb9SNikolay Aleksandrov u16 flags = 0; 1669cf5bddb9SNikolay Aleksandrov int ifindex; 1670cf5bddb9SNikolay Aleksandrov 1671cf5bddb9SNikolay Aleksandrov /* right now notifications are done only with rtnl held */ 1672cf5bddb9SNikolay Aleksandrov ASSERT_RTNL(); 1673cf5bddb9SNikolay Aleksandrov 1674cf5bddb9SNikolay Aleksandrov if (p) { 1675cf5bddb9SNikolay Aleksandrov ifindex = p->dev->ifindex; 1676cf5bddb9SNikolay Aleksandrov vg = nbp_vlan_group(p); 1677cf5bddb9SNikolay Aleksandrov net = dev_net(p->dev); 1678cf5bddb9SNikolay Aleksandrov } else { 1679cf5bddb9SNikolay Aleksandrov ifindex = br->dev->ifindex; 1680cf5bddb9SNikolay Aleksandrov vg = br_vlan_group(br); 1681cf5bddb9SNikolay Aleksandrov net = dev_net(br->dev); 1682cf5bddb9SNikolay Aleksandrov } 1683cf5bddb9SNikolay Aleksandrov 1684cf5bddb9SNikolay Aleksandrov skb = nlmsg_new(rtnl_vlan_nlmsg_size(), GFP_KERNEL); 1685cf5bddb9SNikolay Aleksandrov if (!skb) 1686cf5bddb9SNikolay Aleksandrov goto out_err; 1687cf5bddb9SNikolay Aleksandrov 1688cf5bddb9SNikolay Aleksandrov err = -EMSGSIZE; 1689cf5bddb9SNikolay Aleksandrov nlh = nlmsg_put(skb, 0, 0, cmd, sizeof(*bvm), 0); 1690cf5bddb9SNikolay Aleksandrov if (!nlh) 1691cf5bddb9SNikolay Aleksandrov goto out_err; 1692cf5bddb9SNikolay Aleksandrov bvm = nlmsg_data(nlh); 1693cf5bddb9SNikolay Aleksandrov memset(bvm, 0, sizeof(*bvm)); 1694cf5bddb9SNikolay Aleksandrov bvm->family = AF_BRIDGE; 1695cf5bddb9SNikolay Aleksandrov bvm->ifindex = ifindex; 1696cf5bddb9SNikolay Aleksandrov 1697cf5bddb9SNikolay Aleksandrov switch (cmd) { 1698cf5bddb9SNikolay Aleksandrov case RTM_NEWVLAN: 1699cf5bddb9SNikolay Aleksandrov /* need to find the vlan due to flags/options */ 1700cf5bddb9SNikolay Aleksandrov v = br_vlan_find(vg, vid); 1701cf5bddb9SNikolay Aleksandrov if (!v || !br_vlan_should_use(v)) 1702cf5bddb9SNikolay Aleksandrov goto out_kfree; 1703cf5bddb9SNikolay Aleksandrov 1704cf5bddb9SNikolay Aleksandrov flags = v->flags; 1705cf5bddb9SNikolay Aleksandrov if (br_get_pvid(vg) == v->vid) 1706cf5bddb9SNikolay Aleksandrov flags |= BRIDGE_VLAN_INFO_PVID; 1707cf5bddb9SNikolay Aleksandrov break; 1708cf5bddb9SNikolay Aleksandrov case RTM_DELVLAN: 1709cf5bddb9SNikolay Aleksandrov break; 1710cf5bddb9SNikolay Aleksandrov default: 1711cf5bddb9SNikolay Aleksandrov goto out_kfree; 1712cf5bddb9SNikolay Aleksandrov } 1713cf5bddb9SNikolay Aleksandrov 171456d09976SNikolay Aleksandrov if (!br_vlan_fill_vids(skb, vid, vid_range, v, flags, false)) 1715cf5bddb9SNikolay Aleksandrov goto out_err; 1716cf5bddb9SNikolay Aleksandrov 1717cf5bddb9SNikolay Aleksandrov nlmsg_end(skb, nlh); 1718cf5bddb9SNikolay Aleksandrov rtnl_notify(skb, net, 0, RTNLGRP_BRVLAN, NULL, GFP_KERNEL); 1719cf5bddb9SNikolay Aleksandrov return; 1720cf5bddb9SNikolay Aleksandrov 1721cf5bddb9SNikolay Aleksandrov out_err: 1722cf5bddb9SNikolay Aleksandrov rtnl_set_sk_err(net, RTNLGRP_BRVLAN, err); 1723cf5bddb9SNikolay Aleksandrov out_kfree: 1724cf5bddb9SNikolay Aleksandrov kfree_skb(skb); 1725cf5bddb9SNikolay Aleksandrov } 1726cf5bddb9SNikolay Aleksandrov 17270ab55879SNikolay Aleksandrov /* check if v_curr can enter a range ending in range_end */ 1728a5d29ae2SNikolay Aleksandrov bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, 17290ab55879SNikolay Aleksandrov const struct net_bridge_vlan *range_end) 17300ab55879SNikolay Aleksandrov { 17310ab55879SNikolay Aleksandrov return v_curr->vid - range_end->vid == 1 && 17327a53e718SNikolay Aleksandrov range_end->flags == v_curr->flags && 173399f7c5e0SNikolay Aleksandrov br_vlan_opts_eq_range(v_curr, range_end); 17340ab55879SNikolay Aleksandrov } 17350ab55879SNikolay Aleksandrov 17368dcea187SNikolay Aleksandrov static int br_vlan_dump_dev(const struct net_device *dev, 17378dcea187SNikolay Aleksandrov struct sk_buff *skb, 173856d09976SNikolay Aleksandrov struct netlink_callback *cb, 173956d09976SNikolay Aleksandrov u32 dump_flags) 17408dcea187SNikolay Aleksandrov { 17410ab55879SNikolay Aleksandrov struct net_bridge_vlan *v, *range_start = NULL, *range_end = NULL; 174256d09976SNikolay Aleksandrov bool dump_stats = !!(dump_flags & BRIDGE_VLANDB_DUMPF_STATS); 17438dcea187SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 17448dcea187SNikolay Aleksandrov int idx = 0, s_idx = cb->args[1]; 17458dcea187SNikolay Aleksandrov struct nlmsghdr *nlh = NULL; 17468dcea187SNikolay Aleksandrov struct net_bridge_port *p; 17478dcea187SNikolay Aleksandrov struct br_vlan_msg *bvm; 17488dcea187SNikolay Aleksandrov struct net_bridge *br; 17498dcea187SNikolay Aleksandrov int err = 0; 17508dcea187SNikolay Aleksandrov u16 pvid; 17518dcea187SNikolay Aleksandrov 17528dcea187SNikolay Aleksandrov if (!netif_is_bridge_master(dev) && !netif_is_bridge_port(dev)) 17538dcea187SNikolay Aleksandrov return -EINVAL; 17548dcea187SNikolay Aleksandrov 17558dcea187SNikolay Aleksandrov if (netif_is_bridge_master(dev)) { 17568dcea187SNikolay Aleksandrov br = netdev_priv(dev); 17578dcea187SNikolay Aleksandrov vg = br_vlan_group_rcu(br); 17588dcea187SNikolay Aleksandrov p = NULL; 17598dcea187SNikolay Aleksandrov } else { 17608dcea187SNikolay Aleksandrov p = br_port_get_rcu(dev); 17618dcea187SNikolay Aleksandrov if (WARN_ON(!p)) 17628dcea187SNikolay Aleksandrov return -EINVAL; 17638dcea187SNikolay Aleksandrov vg = nbp_vlan_group_rcu(p); 17648dcea187SNikolay Aleksandrov br = p->br; 17658dcea187SNikolay Aleksandrov } 17668dcea187SNikolay Aleksandrov 17678dcea187SNikolay Aleksandrov if (!vg) 17688dcea187SNikolay Aleksandrov return 0; 17698dcea187SNikolay Aleksandrov 17708dcea187SNikolay Aleksandrov nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, 17718dcea187SNikolay Aleksandrov RTM_NEWVLAN, sizeof(*bvm), NLM_F_MULTI); 17728dcea187SNikolay Aleksandrov if (!nlh) 17738dcea187SNikolay Aleksandrov return -EMSGSIZE; 17748dcea187SNikolay Aleksandrov bvm = nlmsg_data(nlh); 17758dcea187SNikolay Aleksandrov memset(bvm, 0, sizeof(*bvm)); 17768dcea187SNikolay Aleksandrov bvm->family = PF_BRIDGE; 17778dcea187SNikolay Aleksandrov bvm->ifindex = dev->ifindex; 17788dcea187SNikolay Aleksandrov pvid = br_get_pvid(vg); 17798dcea187SNikolay Aleksandrov 17800ab55879SNikolay Aleksandrov /* idx must stay at range's beginning until it is filled in */ 17818dcea187SNikolay Aleksandrov list_for_each_entry_rcu(v, &vg->vlan_list, vlist) { 17828dcea187SNikolay Aleksandrov if (!br_vlan_should_use(v)) 17838dcea187SNikolay Aleksandrov continue; 17840ab55879SNikolay Aleksandrov if (idx < s_idx) { 17850ab55879SNikolay Aleksandrov idx++; 17860ab55879SNikolay Aleksandrov continue; 17870ab55879SNikolay Aleksandrov } 17880ab55879SNikolay Aleksandrov 17890ab55879SNikolay Aleksandrov if (!range_start) { 17900ab55879SNikolay Aleksandrov range_start = v; 17910ab55879SNikolay Aleksandrov range_end = v; 17920ab55879SNikolay Aleksandrov continue; 17930ab55879SNikolay Aleksandrov } 17940ab55879SNikolay Aleksandrov 179556d09976SNikolay Aleksandrov if (dump_stats || v->vid == pvid || 179656d09976SNikolay Aleksandrov !br_vlan_can_enter_range(v, range_end)) { 179756d09976SNikolay Aleksandrov u16 vlan_flags = br_vlan_flags(range_start, pvid); 17980ab55879SNikolay Aleksandrov 17990ab55879SNikolay Aleksandrov if (!br_vlan_fill_vids(skb, range_start->vid, 18007a53e718SNikolay Aleksandrov range_end->vid, range_start, 180156d09976SNikolay Aleksandrov vlan_flags, dump_stats)) { 18028dcea187SNikolay Aleksandrov err = -EMSGSIZE; 18038dcea187SNikolay Aleksandrov break; 18048dcea187SNikolay Aleksandrov } 18050ab55879SNikolay Aleksandrov /* advance number of filled vlans */ 18060ab55879SNikolay Aleksandrov idx += range_end->vid - range_start->vid + 1; 18070ab55879SNikolay Aleksandrov 18080ab55879SNikolay Aleksandrov range_start = v; 18098dcea187SNikolay Aleksandrov } 18100ab55879SNikolay Aleksandrov range_end = v; 18110ab55879SNikolay Aleksandrov } 18120ab55879SNikolay Aleksandrov 18130ab55879SNikolay Aleksandrov /* err will be 0 and range_start will be set in 3 cases here: 18140ab55879SNikolay Aleksandrov * - first vlan (range_start == range_end) 18150ab55879SNikolay Aleksandrov * - last vlan (range_start == range_end, not in range) 18160ab55879SNikolay Aleksandrov * - last vlan range (range_start != range_end, in range) 18170ab55879SNikolay Aleksandrov */ 18180ab55879SNikolay Aleksandrov if (!err && range_start && 18190ab55879SNikolay Aleksandrov !br_vlan_fill_vids(skb, range_start->vid, range_end->vid, 182056d09976SNikolay Aleksandrov range_start, br_vlan_flags(range_start, pvid), 182156d09976SNikolay Aleksandrov dump_stats)) 18220ab55879SNikolay Aleksandrov err = -EMSGSIZE; 18230ab55879SNikolay Aleksandrov 18240ab55879SNikolay Aleksandrov cb->args[1] = err ? idx : 0; 18250ab55879SNikolay Aleksandrov 18268dcea187SNikolay Aleksandrov nlmsg_end(skb, nlh); 18278dcea187SNikolay Aleksandrov 18288dcea187SNikolay Aleksandrov return err; 18298dcea187SNikolay Aleksandrov } 18308dcea187SNikolay Aleksandrov 183156d09976SNikolay Aleksandrov static const struct nla_policy br_vlan_db_dump_pol[BRIDGE_VLANDB_DUMP_MAX + 1] = { 183256d09976SNikolay Aleksandrov [BRIDGE_VLANDB_DUMP_FLAGS] = { .type = NLA_U32 }, 183356d09976SNikolay Aleksandrov }; 183456d09976SNikolay Aleksandrov 18358dcea187SNikolay Aleksandrov static int br_vlan_rtm_dump(struct sk_buff *skb, struct netlink_callback *cb) 18368dcea187SNikolay Aleksandrov { 183756d09976SNikolay Aleksandrov struct nlattr *dtb[BRIDGE_VLANDB_DUMP_MAX + 1]; 18388dcea187SNikolay Aleksandrov int idx = 0, err = 0, s_idx = cb->args[0]; 18398dcea187SNikolay Aleksandrov struct net *net = sock_net(skb->sk); 18408dcea187SNikolay Aleksandrov struct br_vlan_msg *bvm; 18418dcea187SNikolay Aleksandrov struct net_device *dev; 184256d09976SNikolay Aleksandrov u32 dump_flags = 0; 18438dcea187SNikolay Aleksandrov 184456d09976SNikolay Aleksandrov err = nlmsg_parse(cb->nlh, sizeof(*bvm), dtb, BRIDGE_VLANDB_DUMP_MAX, 184556d09976SNikolay Aleksandrov br_vlan_db_dump_pol, cb->extack); 18468dcea187SNikolay Aleksandrov if (err < 0) 18478dcea187SNikolay Aleksandrov return err; 18488dcea187SNikolay Aleksandrov 18498dcea187SNikolay Aleksandrov bvm = nlmsg_data(cb->nlh); 185056d09976SNikolay Aleksandrov if (dtb[BRIDGE_VLANDB_DUMP_FLAGS]) 185156d09976SNikolay Aleksandrov dump_flags = nla_get_u32(dtb[BRIDGE_VLANDB_DUMP_FLAGS]); 18528dcea187SNikolay Aleksandrov 18538dcea187SNikolay Aleksandrov rcu_read_lock(); 18548dcea187SNikolay Aleksandrov if (bvm->ifindex) { 18558dcea187SNikolay Aleksandrov dev = dev_get_by_index_rcu(net, bvm->ifindex); 18568dcea187SNikolay Aleksandrov if (!dev) { 18578dcea187SNikolay Aleksandrov err = -ENODEV; 18588dcea187SNikolay Aleksandrov goto out_err; 18598dcea187SNikolay Aleksandrov } 186056d09976SNikolay Aleksandrov err = br_vlan_dump_dev(dev, skb, cb, dump_flags); 18618dcea187SNikolay Aleksandrov if (err && err != -EMSGSIZE) 18628dcea187SNikolay Aleksandrov goto out_err; 18638dcea187SNikolay Aleksandrov } else { 18648dcea187SNikolay Aleksandrov for_each_netdev_rcu(net, dev) { 18658dcea187SNikolay Aleksandrov if (idx < s_idx) 18668dcea187SNikolay Aleksandrov goto skip; 18678dcea187SNikolay Aleksandrov 186856d09976SNikolay Aleksandrov err = br_vlan_dump_dev(dev, skb, cb, dump_flags); 18698dcea187SNikolay Aleksandrov if (err == -EMSGSIZE) 18708dcea187SNikolay Aleksandrov break; 18718dcea187SNikolay Aleksandrov skip: 18728dcea187SNikolay Aleksandrov idx++; 18738dcea187SNikolay Aleksandrov } 18748dcea187SNikolay Aleksandrov } 18758dcea187SNikolay Aleksandrov cb->args[0] = idx; 18768dcea187SNikolay Aleksandrov rcu_read_unlock(); 18778dcea187SNikolay Aleksandrov 18788dcea187SNikolay Aleksandrov return skb->len; 18798dcea187SNikolay Aleksandrov 18808dcea187SNikolay Aleksandrov out_err: 18818dcea187SNikolay Aleksandrov rcu_read_unlock(); 18828dcea187SNikolay Aleksandrov 18838dcea187SNikolay Aleksandrov return err; 18848dcea187SNikolay Aleksandrov } 18858dcea187SNikolay Aleksandrov 1886f26b2965SNikolay Aleksandrov static const struct nla_policy br_vlan_db_policy[BRIDGE_VLANDB_ENTRY_MAX + 1] = { 18878140860cSJohannes Berg [BRIDGE_VLANDB_ENTRY_INFO] = 18888140860cSJohannes Berg NLA_POLICY_EXACT_LEN(sizeof(struct bridge_vlan_info)), 18890ab55879SNikolay Aleksandrov [BRIDGE_VLANDB_ENTRY_RANGE] = { .type = NLA_U16 }, 1890a580c76dSNikolay Aleksandrov [BRIDGE_VLANDB_ENTRY_STATE] = { .type = NLA_U8 }, 1891fa388f29SNikolay Aleksandrov [BRIDGE_VLANDB_ENTRY_TUNNEL_INFO] = { .type = NLA_NESTED }, 1892f26b2965SNikolay Aleksandrov }; 1893f26b2965SNikolay Aleksandrov 1894f26b2965SNikolay Aleksandrov static int br_vlan_rtm_process_one(struct net_device *dev, 1895f26b2965SNikolay Aleksandrov const struct nlattr *attr, 1896f26b2965SNikolay Aleksandrov int cmd, struct netlink_ext_ack *extack) 1897f26b2965SNikolay Aleksandrov { 18980ab55879SNikolay Aleksandrov struct bridge_vlan_info *vinfo, vrange_end, *vinfo_last = NULL; 1899f26b2965SNikolay Aleksandrov struct nlattr *tb[BRIDGE_VLANDB_ENTRY_MAX + 1]; 1900a5d29ae2SNikolay Aleksandrov bool changed = false, skip_processing = false; 1901f26b2965SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 1902f26b2965SNikolay Aleksandrov struct net_bridge_port *p = NULL; 1903f26b2965SNikolay Aleksandrov int err = 0, cmdmap = 0; 1904f26b2965SNikolay Aleksandrov struct net_bridge *br; 1905f26b2965SNikolay Aleksandrov 1906f26b2965SNikolay Aleksandrov if (netif_is_bridge_master(dev)) { 1907f26b2965SNikolay Aleksandrov br = netdev_priv(dev); 1908f26b2965SNikolay Aleksandrov vg = br_vlan_group(br); 1909f26b2965SNikolay Aleksandrov } else { 1910f26b2965SNikolay Aleksandrov p = br_port_get_rtnl(dev); 1911f26b2965SNikolay Aleksandrov if (WARN_ON(!p)) 1912f26b2965SNikolay Aleksandrov return -ENODEV; 1913f26b2965SNikolay Aleksandrov br = p->br; 1914f26b2965SNikolay Aleksandrov vg = nbp_vlan_group(p); 1915f26b2965SNikolay Aleksandrov } 1916f26b2965SNikolay Aleksandrov 1917f26b2965SNikolay Aleksandrov if (WARN_ON(!vg)) 1918f26b2965SNikolay Aleksandrov return -ENODEV; 1919f26b2965SNikolay Aleksandrov 1920f26b2965SNikolay Aleksandrov err = nla_parse_nested(tb, BRIDGE_VLANDB_ENTRY_MAX, attr, 1921f26b2965SNikolay Aleksandrov br_vlan_db_policy, extack); 1922f26b2965SNikolay Aleksandrov if (err) 1923f26b2965SNikolay Aleksandrov return err; 1924f26b2965SNikolay Aleksandrov 1925f26b2965SNikolay Aleksandrov if (!tb[BRIDGE_VLANDB_ENTRY_INFO]) { 1926f26b2965SNikolay Aleksandrov NL_SET_ERR_MSG_MOD(extack, "Missing vlan entry info"); 1927f26b2965SNikolay Aleksandrov return -EINVAL; 1928f26b2965SNikolay Aleksandrov } 19290ab55879SNikolay Aleksandrov memset(&vrange_end, 0, sizeof(vrange_end)); 1930f26b2965SNikolay Aleksandrov 1931f26b2965SNikolay Aleksandrov vinfo = nla_data(tb[BRIDGE_VLANDB_ENTRY_INFO]); 1932f26b2965SNikolay Aleksandrov if (vinfo->flags & (BRIDGE_VLAN_INFO_RANGE_BEGIN | 1933f26b2965SNikolay Aleksandrov BRIDGE_VLAN_INFO_RANGE_END)) { 1934f26b2965SNikolay Aleksandrov NL_SET_ERR_MSG_MOD(extack, "Old-style vlan ranges are not allowed when using RTM vlan calls"); 1935f26b2965SNikolay Aleksandrov return -EINVAL; 1936f26b2965SNikolay Aleksandrov } 1937f26b2965SNikolay Aleksandrov if (!br_vlan_valid_id(vinfo->vid, extack)) 1938f26b2965SNikolay Aleksandrov return -EINVAL; 1939f26b2965SNikolay Aleksandrov 19400ab55879SNikolay Aleksandrov if (tb[BRIDGE_VLANDB_ENTRY_RANGE]) { 19410ab55879SNikolay Aleksandrov vrange_end.vid = nla_get_u16(tb[BRIDGE_VLANDB_ENTRY_RANGE]); 19420ab55879SNikolay Aleksandrov /* validate user-provided flags without RANGE_BEGIN */ 19430ab55879SNikolay Aleksandrov vrange_end.flags = BRIDGE_VLAN_INFO_RANGE_END | vinfo->flags; 19440ab55879SNikolay Aleksandrov vinfo->flags |= BRIDGE_VLAN_INFO_RANGE_BEGIN; 19450ab55879SNikolay Aleksandrov 19460ab55879SNikolay Aleksandrov /* vinfo_last is the range start, vinfo the range end */ 19470ab55879SNikolay Aleksandrov vinfo_last = vinfo; 19480ab55879SNikolay Aleksandrov vinfo = &vrange_end; 19490ab55879SNikolay Aleksandrov 19500ab55879SNikolay Aleksandrov if (!br_vlan_valid_id(vinfo->vid, extack) || 19510ab55879SNikolay Aleksandrov !br_vlan_valid_range(vinfo, vinfo_last, extack)) 19520ab55879SNikolay Aleksandrov return -EINVAL; 19530ab55879SNikolay Aleksandrov } 19540ab55879SNikolay Aleksandrov 1955f26b2965SNikolay Aleksandrov switch (cmd) { 1956f26b2965SNikolay Aleksandrov case RTM_NEWVLAN: 1957f26b2965SNikolay Aleksandrov cmdmap = RTM_SETLINK; 1958a5d29ae2SNikolay Aleksandrov skip_processing = !!(vinfo->flags & BRIDGE_VLAN_INFO_ONLY_OPTS); 1959f26b2965SNikolay Aleksandrov break; 1960adb3ce9bSNikolay Aleksandrov case RTM_DELVLAN: 1961adb3ce9bSNikolay Aleksandrov cmdmap = RTM_DELLINK; 1962adb3ce9bSNikolay Aleksandrov break; 1963f26b2965SNikolay Aleksandrov } 1964f26b2965SNikolay Aleksandrov 1965a5d29ae2SNikolay Aleksandrov if (!skip_processing) { 1966a5d29ae2SNikolay Aleksandrov struct bridge_vlan_info *tmp_last = vinfo_last; 1967a5d29ae2SNikolay Aleksandrov 1968a5d29ae2SNikolay Aleksandrov /* br_process_vlan_info may overwrite vinfo_last */ 1969a5d29ae2SNikolay Aleksandrov err = br_process_vlan_info(br, p, cmdmap, vinfo, &tmp_last, 1970a5d29ae2SNikolay Aleksandrov &changed, extack); 1971a5d29ae2SNikolay Aleksandrov 1972a5d29ae2SNikolay Aleksandrov /* notify first if anything changed */ 1973f26b2965SNikolay Aleksandrov if (changed) 1974f26b2965SNikolay Aleksandrov br_ifinfo_notify(cmdmap, br, p); 1975f26b2965SNikolay Aleksandrov 1976a5d29ae2SNikolay Aleksandrov if (err) 1977a5d29ae2SNikolay Aleksandrov return err; 1978a5d29ae2SNikolay Aleksandrov } 1979a5d29ae2SNikolay Aleksandrov 1980a5d29ae2SNikolay Aleksandrov /* deal with options */ 1981a5d29ae2SNikolay Aleksandrov if (cmd == RTM_NEWVLAN) { 1982a5d29ae2SNikolay Aleksandrov struct net_bridge_vlan *range_start, *range_end; 1983a5d29ae2SNikolay Aleksandrov 1984a5d29ae2SNikolay Aleksandrov if (vinfo_last) { 1985a5d29ae2SNikolay Aleksandrov range_start = br_vlan_find(vg, vinfo_last->vid); 1986a5d29ae2SNikolay Aleksandrov range_end = br_vlan_find(vg, vinfo->vid); 1987a5d29ae2SNikolay Aleksandrov } else { 1988a5d29ae2SNikolay Aleksandrov range_start = br_vlan_find(vg, vinfo->vid); 1989a5d29ae2SNikolay Aleksandrov range_end = range_start; 1990a5d29ae2SNikolay Aleksandrov } 1991a5d29ae2SNikolay Aleksandrov 1992a5d29ae2SNikolay Aleksandrov err = br_vlan_process_options(br, p, range_start, range_end, 1993a5d29ae2SNikolay Aleksandrov tb, extack); 1994a5d29ae2SNikolay Aleksandrov } 1995a5d29ae2SNikolay Aleksandrov 1996f26b2965SNikolay Aleksandrov return err; 1997f26b2965SNikolay Aleksandrov } 1998f26b2965SNikolay Aleksandrov 1999f26b2965SNikolay Aleksandrov static int br_vlan_rtm_process(struct sk_buff *skb, struct nlmsghdr *nlh, 2000f26b2965SNikolay Aleksandrov struct netlink_ext_ack *extack) 2001f26b2965SNikolay Aleksandrov { 2002f26b2965SNikolay Aleksandrov struct net *net = sock_net(skb->sk); 2003f26b2965SNikolay Aleksandrov struct br_vlan_msg *bvm; 2004f26b2965SNikolay Aleksandrov struct net_device *dev; 2005f26b2965SNikolay Aleksandrov struct nlattr *attr; 2006f26b2965SNikolay Aleksandrov int err, vlans = 0; 2007f26b2965SNikolay Aleksandrov int rem; 2008f26b2965SNikolay Aleksandrov 2009f26b2965SNikolay Aleksandrov /* this should validate the header and check for remaining bytes */ 2010f26b2965SNikolay Aleksandrov err = nlmsg_parse(nlh, sizeof(*bvm), NULL, BRIDGE_VLANDB_MAX, NULL, 2011f26b2965SNikolay Aleksandrov extack); 2012f26b2965SNikolay Aleksandrov if (err < 0) 2013f26b2965SNikolay Aleksandrov return err; 2014f26b2965SNikolay Aleksandrov 2015f26b2965SNikolay Aleksandrov bvm = nlmsg_data(nlh); 2016f26b2965SNikolay Aleksandrov dev = __dev_get_by_index(net, bvm->ifindex); 2017f26b2965SNikolay Aleksandrov if (!dev) 2018f26b2965SNikolay Aleksandrov return -ENODEV; 2019f26b2965SNikolay Aleksandrov 2020f26b2965SNikolay Aleksandrov if (!netif_is_bridge_master(dev) && !netif_is_bridge_port(dev)) { 2021f26b2965SNikolay Aleksandrov NL_SET_ERR_MSG_MOD(extack, "The device is not a valid bridge or bridge port"); 2022f26b2965SNikolay Aleksandrov return -EINVAL; 2023f26b2965SNikolay Aleksandrov } 2024f26b2965SNikolay Aleksandrov 2025f26b2965SNikolay Aleksandrov nlmsg_for_each_attr(attr, nlh, sizeof(*bvm), rem) { 2026f26b2965SNikolay Aleksandrov if (nla_type(attr) != BRIDGE_VLANDB_ENTRY) 2027f26b2965SNikolay Aleksandrov continue; 2028f26b2965SNikolay Aleksandrov 2029f26b2965SNikolay Aleksandrov vlans++; 2030f26b2965SNikolay Aleksandrov err = br_vlan_rtm_process_one(dev, attr, nlh->nlmsg_type, 2031f26b2965SNikolay Aleksandrov extack); 2032f26b2965SNikolay Aleksandrov if (err) 2033f26b2965SNikolay Aleksandrov break; 2034f26b2965SNikolay Aleksandrov } 2035f26b2965SNikolay Aleksandrov if (!vlans) { 2036f26b2965SNikolay Aleksandrov NL_SET_ERR_MSG_MOD(extack, "No vlans found to process"); 2037f26b2965SNikolay Aleksandrov err = -EINVAL; 2038f26b2965SNikolay Aleksandrov } 2039f26b2965SNikolay Aleksandrov 2040f26b2965SNikolay Aleksandrov return err; 2041f26b2965SNikolay Aleksandrov } 2042f26b2965SNikolay Aleksandrov 20438dcea187SNikolay Aleksandrov void br_vlan_rtnl_init(void) 20448dcea187SNikolay Aleksandrov { 20458dcea187SNikolay Aleksandrov rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_GETVLAN, NULL, 20468dcea187SNikolay Aleksandrov br_vlan_rtm_dump, 0); 2047f26b2965SNikolay Aleksandrov rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_NEWVLAN, 2048f26b2965SNikolay Aleksandrov br_vlan_rtm_process, NULL, 0); 2049adb3ce9bSNikolay Aleksandrov rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_DELVLAN, 2050adb3ce9bSNikolay Aleksandrov br_vlan_rtm_process, NULL, 0); 20518dcea187SNikolay Aleksandrov } 20528dcea187SNikolay Aleksandrov 20538dcea187SNikolay Aleksandrov void br_vlan_rtnl_uninit(void) 20548dcea187SNikolay Aleksandrov { 20558dcea187SNikolay Aleksandrov rtnl_unregister(PF_BRIDGE, RTM_GETVLAN); 2056f26b2965SNikolay Aleksandrov rtnl_unregister(PF_BRIDGE, RTM_NEWVLAN); 2057adb3ce9bSNikolay Aleksandrov rtnl_unregister(PF_BRIDGE, RTM_DELVLAN); 20588dcea187SNikolay Aleksandrov } 2059