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 61*cab2cd77SVladimir Oltean /* Returns true if the BRIDGE_VLAN_INFO_PVID and BRIDGE_VLAN_INFO_UNTAGGED bits 62*cab2cd77SVladimir Oltean * of @flags produced any change onto @v, false otherwise 63*cab2cd77SVladimir Oltean */ 64f418af63SNikolay Aleksandrov static bool __vlan_add_flags(struct net_bridge_vlan *v, u16 flags) 6535e03f3aSVlad Yasevich { 6677751ee8SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 67f418af63SNikolay Aleksandrov u16 old_flags = v->flags; 68f418af63SNikolay Aleksandrov bool ret; 6977751ee8SNikolay Aleksandrov 702594e906SNikolay Aleksandrov if (br_vlan_is_master(v)) 71907b1e6eSNikolay Aleksandrov vg = br_vlan_group(v->br); 72635126b7SVlad Yasevich else 73907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(v->port); 7477751ee8SNikolay Aleksandrov 7577751ee8SNikolay Aleksandrov if (flags & BRIDGE_VLAN_INFO_PVID) 76a580c76dSNikolay Aleksandrov ret = __vlan_add_pvid(vg, v); 772594e906SNikolay Aleksandrov else 78f418af63SNikolay Aleksandrov ret = __vlan_delete_pvid(vg, v->vid); 7935e03f3aSVlad Yasevich 8035e03f3aSVlad Yasevich if (flags & BRIDGE_VLAN_INFO_UNTAGGED) 812594e906SNikolay Aleksandrov v->flags |= BRIDGE_VLAN_INFO_UNTAGGED; 82635126b7SVlad Yasevich else 832594e906SNikolay Aleksandrov v->flags &= ~BRIDGE_VLAN_INFO_UNTAGGED; 84f418af63SNikolay Aleksandrov 85*cab2cd77SVladimir Oltean return ret || !!((old_flags ^ v->flags) & BRIDGE_VLAN_INFO_UNTAGGED); 8635e03f3aSVlad Yasevich } 8735e03f3aSVlad Yasevich 887f109539SScott Feldman static int __vlan_vid_add(struct net_device *dev, struct net_bridge *br, 8927973793SIdo Schimmel struct net_bridge_vlan *v, u16 flags, 9027973793SIdo Schimmel struct netlink_ext_ack *extack) 917f109539SScott Feldman { 920944d6b5SJiri Pirko int err; 937f109539SScott Feldman 940944d6b5SJiri Pirko /* Try switchdev op first. In case it is not supported, fallback to 950944d6b5SJiri Pirko * 8021q add. 960944d6b5SJiri Pirko */ 9727973793SIdo Schimmel err = br_switchdev_port_vlan_add(dev, v->vid, flags, extack); 987f109539SScott Feldman if (err == -EOPNOTSUPP) 9927973793SIdo Schimmel return vlan_vid_add(dev, br->vlan_proto, v->vid); 10027973793SIdo Schimmel v->priv_flags |= BR_VLFLAG_ADDED_BY_SWITCHDEV; 1017f109539SScott Feldman return err; 1027f109539SScott Feldman } 1037f109539SScott Feldman 1042594e906SNikolay Aleksandrov static void __vlan_add_list(struct net_bridge_vlan *v) 105243a2e63SVlad Yasevich { 106907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 1072594e906SNikolay Aleksandrov struct list_head *headp, *hpos; 1082594e906SNikolay Aleksandrov struct net_bridge_vlan *vent; 109243a2e63SVlad Yasevich 110907b1e6eSNikolay Aleksandrov if (br_vlan_is_master(v)) 111907b1e6eSNikolay Aleksandrov vg = br_vlan_group(v->br); 112907b1e6eSNikolay Aleksandrov else 113907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(v->port); 114907b1e6eSNikolay Aleksandrov 115907b1e6eSNikolay Aleksandrov headp = &vg->vlan_list; 1162594e906SNikolay Aleksandrov list_for_each_prev(hpos, headp) { 1172594e906SNikolay Aleksandrov vent = list_entry(hpos, struct net_bridge_vlan, vlist); 118040c1257SColin Ian King if (v->vid >= vent->vid) 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); 1957b54aaafSNikolay Aleksandrov br_multicast_toggle_one_vlan(masterv, false); 196613d61dbSNikolay Aleksandrov br_multicast_ctx_deinit(&masterv->br_mcast_ctx); 1976dada9b1SNikolay Aleksandrov call_rcu(&masterv->rcu, br_master_vlan_rcu_free); 198f8ed289fSNikolay Aleksandrov } 199f8ed289fSNikolay Aleksandrov } 200f8ed289fSNikolay Aleksandrov 2019163a0fcSNikolay Aleksandrov static void nbp_vlan_rcu_free(struct rcu_head *rcu) 2029163a0fcSNikolay Aleksandrov { 2039163a0fcSNikolay Aleksandrov struct net_bridge_vlan *v; 2049163a0fcSNikolay Aleksandrov 2059163a0fcSNikolay Aleksandrov v = container_of(rcu, struct net_bridge_vlan, rcu); 2069163a0fcSNikolay Aleksandrov WARN_ON(br_vlan_is_master(v)); 2079163a0fcSNikolay Aleksandrov /* if we had per-port stats configured then free them here */ 2089d332e69SNikolay Aleksandrov if (v->priv_flags & BR_VLFLAG_PER_PORT_STATS) 2099163a0fcSNikolay Aleksandrov free_percpu(v->stats); 2109163a0fcSNikolay Aleksandrov v->stats = NULL; 2119163a0fcSNikolay Aleksandrov kfree(v); 2129163a0fcSNikolay Aleksandrov } 2139163a0fcSNikolay Aleksandrov 2142594e906SNikolay Aleksandrov /* This is the shared VLAN add function which works for both ports and bridge 2152594e906SNikolay Aleksandrov * devices. There are four possible calls to this function in terms of the 2162594e906SNikolay Aleksandrov * vlan entry type: 2172594e906SNikolay Aleksandrov * 1. vlan is being added on a port (no master flags, global entry exists) 218ddd611d3SIdo Schimmel * 2. vlan is being added on a bridge (both master and brentry flags) 2192594e906SNikolay Aleksandrov * 3. vlan is being added on a port, but a global entry didn't exist which 220ddd611d3SIdo Schimmel * is being created right now (master flag set, brentry flag unset), the 2212594e906SNikolay Aleksandrov * global entry is used for global per-vlan features, but not for filtering 222ddd611d3SIdo Schimmel * 4. same as 3 but with both master and brentry flags set so the entry 2232594e906SNikolay Aleksandrov * will be used for filtering in both the port and the bridge 2242594e906SNikolay Aleksandrov */ 225169327d5SPetr Machata static int __vlan_add(struct net_bridge_vlan *v, u16 flags, 226169327d5SPetr Machata struct netlink_ext_ack *extack) 227243a2e63SVlad Yasevich { 2282594e906SNikolay Aleksandrov struct net_bridge_vlan *masterv = NULL; 2292594e906SNikolay Aleksandrov struct net_bridge_port *p = NULL; 2306be144f6SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 2312594e906SNikolay Aleksandrov struct net_device *dev; 2322594e906SNikolay Aleksandrov struct net_bridge *br; 233bf361ad3SVivien Didelot int err; 234bf361ad3SVivien Didelot 2352594e906SNikolay Aleksandrov if (br_vlan_is_master(v)) { 2362594e906SNikolay Aleksandrov br = v->br; 2372594e906SNikolay Aleksandrov dev = br->dev; 238907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 2392594e906SNikolay Aleksandrov } else { 2402594e906SNikolay Aleksandrov p = v->port; 2412594e906SNikolay Aleksandrov br = p->br; 2422594e906SNikolay Aleksandrov dev = p->dev; 243907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 2442594e906SNikolay Aleksandrov } 2452594e906SNikolay Aleksandrov 2462594e906SNikolay Aleksandrov if (p) { 2472594e906SNikolay Aleksandrov /* Add VLAN to the device filter if it is supported. 2482594e906SNikolay Aleksandrov * This ensures tagged traffic enters the bridge when 2492594e906SNikolay Aleksandrov * promiscuous mode is disabled by br_manage_promisc(). 2502594e906SNikolay Aleksandrov */ 25127973793SIdo Schimmel err = __vlan_vid_add(dev, br, v, flags, extack); 252bf361ad3SVivien Didelot if (err) 2532594e906SNikolay Aleksandrov goto out; 2542594e906SNikolay Aleksandrov 2552594e906SNikolay Aleksandrov /* need to work on the master vlan too */ 2562594e906SNikolay Aleksandrov if (flags & BRIDGE_VLAN_INFO_MASTER) { 257f418af63SNikolay Aleksandrov bool changed; 258f418af63SNikolay Aleksandrov 259f418af63SNikolay Aleksandrov err = br_vlan_add(br, v->vid, 260f418af63SNikolay Aleksandrov flags | BRIDGE_VLAN_INFO_BRENTRY, 261169327d5SPetr Machata &changed, extack); 2622594e906SNikolay Aleksandrov if (err) 2632594e906SNikolay Aleksandrov goto out_filt; 264f545923bSNikolay Aleksandrov 265f545923bSNikolay Aleksandrov if (changed) 266f545923bSNikolay Aleksandrov br_vlan_notify(br, NULL, v->vid, 0, 267f545923bSNikolay Aleksandrov RTM_NEWVLAN); 2682594e906SNikolay Aleksandrov } 2692594e906SNikolay Aleksandrov 270169327d5SPetr Machata masterv = br_vlan_get_master(br, v->vid, extack); 271ee4f52a8SZhang Changzhong if (!masterv) { 272ee4f52a8SZhang Changzhong err = -ENOMEM; 2732594e906SNikolay Aleksandrov goto out_filt; 274ee4f52a8SZhang Changzhong } 2752594e906SNikolay Aleksandrov v->brvlan = masterv; 2769163a0fcSNikolay Aleksandrov if (br_opt_get(br, BROPT_VLAN_STATS_PER_PORT)) { 277281cc284SHeiner Kallweit v->stats = 278281cc284SHeiner Kallweit netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); 2799163a0fcSNikolay Aleksandrov if (!v->stats) { 2809163a0fcSNikolay Aleksandrov err = -ENOMEM; 2819163a0fcSNikolay Aleksandrov goto out_filt; 2829163a0fcSNikolay Aleksandrov } 2839d332e69SNikolay Aleksandrov v->priv_flags |= BR_VLFLAG_PER_PORT_STATS; 2849163a0fcSNikolay Aleksandrov } else { 2856dada9b1SNikolay Aleksandrov v->stats = masterv->stats; 2869163a0fcSNikolay Aleksandrov } 287613d61dbSNikolay Aleksandrov br_multicast_port_ctx_init(p, v, &v->port_mcast_ctx); 2889c86ce2cSPetr Machata } else { 2893116ad06SVladimir Oltean if (br_vlan_should_use(v)) { 2903116ad06SVladimir Oltean err = br_switchdev_port_vlan_add(dev, v->vid, flags, 2913116ad06SVladimir Oltean extack); 2929c86ce2cSPetr Machata if (err && err != -EOPNOTSUPP) 2939c86ce2cSPetr Machata goto out; 2943116ad06SVladimir Oltean } 295613d61dbSNikolay Aleksandrov br_multicast_ctx_init(br, v, &v->br_mcast_ctx); 2967b54aaafSNikolay Aleksandrov v->priv_flags |= BR_VLFLAG_GLOBAL_MCAST_ENABLED; 2972594e906SNikolay Aleksandrov } 2982594e906SNikolay Aleksandrov 2996be144f6SNikolay Aleksandrov /* Add the dev mac and count the vlan only if it's usable */ 3002594e906SNikolay Aleksandrov if (br_vlan_should_use(v)) { 301f6814fdcSVladimir Oltean err = br_fdb_add_local(br, p, dev->dev_addr, v->vid); 3022594e906SNikolay Aleksandrov if (err) { 3032594e906SNikolay Aleksandrov br_err(br, "failed insert local address into bridge forwarding table\n"); 3042594e906SNikolay Aleksandrov goto out_filt; 3052594e906SNikolay Aleksandrov } 3066be144f6SNikolay Aleksandrov vg->num_vlans++; 3072594e906SNikolay Aleksandrov } 3082594e906SNikolay Aleksandrov 309a580c76dSNikolay Aleksandrov /* set the state before publishing */ 310a580c76dSNikolay Aleksandrov v->state = BR_STATE_FORWARDING; 311a580c76dSNikolay Aleksandrov 3126be144f6SNikolay Aleksandrov err = rhashtable_lookup_insert_fast(&vg->vlan_hash, &v->vnode, 3136be144f6SNikolay Aleksandrov br_vlan_rht_params); 3142594e906SNikolay Aleksandrov if (err) 3152594e906SNikolay Aleksandrov goto out_fdb_insert; 3162594e906SNikolay Aleksandrov 3172594e906SNikolay Aleksandrov __vlan_add_list(v); 3182594e906SNikolay Aleksandrov __vlan_add_flags(v, flags); 3197b54aaafSNikolay Aleksandrov br_multicast_toggle_one_vlan(v, true); 32080900acdSMike Manning 32180900acdSMike Manning if (p) 32280900acdSMike Manning nbp_vlan_set_vlan_dev_state(p, v->vid); 3232594e906SNikolay Aleksandrov out: 3242594e906SNikolay Aleksandrov return err; 3252594e906SNikolay Aleksandrov 3262594e906SNikolay Aleksandrov out_fdb_insert: 3276be144f6SNikolay Aleksandrov if (br_vlan_should_use(v)) { 3286be144f6SNikolay Aleksandrov br_fdb_find_delete_local(br, p, dev->dev_addr, v->vid); 3296be144f6SNikolay Aleksandrov vg->num_vlans--; 3306be144f6SNikolay Aleksandrov } 3312594e906SNikolay Aleksandrov 3322594e906SNikolay Aleksandrov out_filt: 3332594e906SNikolay Aleksandrov if (p) { 33427973793SIdo Schimmel __vlan_vid_del(dev, br, v); 3352594e906SNikolay Aleksandrov if (masterv) { 3361a3aea25SLi RongQing if (v->stats && masterv->stats != v->stats) 3371a3aea25SLi RongQing free_percpu(v->stats); 3381a3aea25SLi RongQing v->stats = NULL; 3391a3aea25SLi RongQing 340f8ed289fSNikolay Aleksandrov br_vlan_put_master(masterv); 3412594e906SNikolay Aleksandrov v->brvlan = NULL; 3422594e906SNikolay Aleksandrov } 3439c86ce2cSPetr Machata } else { 3449c86ce2cSPetr Machata br_switchdev_port_vlan_del(dev, v->vid); 3452594e906SNikolay Aleksandrov } 3462594e906SNikolay Aleksandrov 3472594e906SNikolay Aleksandrov goto out; 3482594e906SNikolay Aleksandrov } 3492594e906SNikolay Aleksandrov 3502594e906SNikolay Aleksandrov static int __vlan_del(struct net_bridge_vlan *v) 3512594e906SNikolay Aleksandrov { 3522594e906SNikolay Aleksandrov struct net_bridge_vlan *masterv = v; 35377751ee8SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 3542594e906SNikolay Aleksandrov struct net_bridge_port *p = NULL; 3552594e906SNikolay Aleksandrov int err = 0; 3562594e906SNikolay Aleksandrov 3572594e906SNikolay Aleksandrov if (br_vlan_is_master(v)) { 358907b1e6eSNikolay Aleksandrov vg = br_vlan_group(v->br); 3592594e906SNikolay Aleksandrov } else { 3602594e906SNikolay Aleksandrov p = v->port; 361907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(v->port); 3622594e906SNikolay Aleksandrov masterv = v->brvlan; 3632594e906SNikolay Aleksandrov } 3642594e906SNikolay Aleksandrov 36577751ee8SNikolay Aleksandrov __vlan_delete_pvid(vg, v->vid); 3662594e906SNikolay Aleksandrov if (p) { 36727973793SIdo Schimmel err = __vlan_vid_del(p->dev, p->br, v); 3682594e906SNikolay Aleksandrov if (err) 3692594e906SNikolay Aleksandrov goto out; 3709c86ce2cSPetr Machata } else { 3719c86ce2cSPetr Machata err = br_switchdev_port_vlan_del(v->br->dev, v->vid); 3729c86ce2cSPetr Machata if (err && err != -EOPNOTSUPP) 3739c86ce2cSPetr Machata goto out; 3749c86ce2cSPetr Machata err = 0; 3752594e906SNikolay Aleksandrov } 3762594e906SNikolay Aleksandrov 3776be144f6SNikolay Aleksandrov if (br_vlan_should_use(v)) { 3782594e906SNikolay Aleksandrov v->flags &= ~BRIDGE_VLAN_INFO_BRENTRY; 3796be144f6SNikolay Aleksandrov vg->num_vlans--; 3802594e906SNikolay Aleksandrov } 3812594e906SNikolay Aleksandrov 3822594e906SNikolay Aleksandrov if (masterv != v) { 383efa5356bSRoopa Prabhu vlan_tunnel_info_del(vg, v); 38477751ee8SNikolay Aleksandrov rhashtable_remove_fast(&vg->vlan_hash, &v->vnode, 38577751ee8SNikolay Aleksandrov br_vlan_rht_params); 3862594e906SNikolay Aleksandrov __vlan_del_list(v); 38780900acdSMike Manning nbp_vlan_set_vlan_dev_state(p, v->vid); 3887b54aaafSNikolay Aleksandrov br_multicast_toggle_one_vlan(v, false); 389613d61dbSNikolay Aleksandrov br_multicast_port_ctx_deinit(&v->port_mcast_ctx); 3909163a0fcSNikolay Aleksandrov call_rcu(&v->rcu, nbp_vlan_rcu_free); 3912594e906SNikolay Aleksandrov } 3922594e906SNikolay Aleksandrov 393f8ed289fSNikolay Aleksandrov br_vlan_put_master(masterv); 3942594e906SNikolay Aleksandrov out: 395bf361ad3SVivien Didelot return err; 3968580e211SToshiaki Makita } 397243a2e63SVlad Yasevich 398f409d0edSNikolay Aleksandrov static void __vlan_group_free(struct net_bridge_vlan_group *vg) 399f409d0edSNikolay Aleksandrov { 400f409d0edSNikolay Aleksandrov WARN_ON(!list_empty(&vg->vlan_list)); 401f409d0edSNikolay Aleksandrov rhashtable_destroy(&vg->vlan_hash); 402efa5356bSRoopa Prabhu vlan_tunnel_deinit(vg); 403f409d0edSNikolay Aleksandrov kfree(vg); 404f409d0edSNikolay Aleksandrov } 405f409d0edSNikolay Aleksandrov 406f545923bSNikolay Aleksandrov static void __vlan_flush(const struct net_bridge *br, 407f545923bSNikolay Aleksandrov const struct net_bridge_port *p, 408f545923bSNikolay Aleksandrov struct net_bridge_vlan_group *vg) 409243a2e63SVlad Yasevich { 4102594e906SNikolay Aleksandrov struct net_bridge_vlan *vlan, *tmp; 411f545923bSNikolay Aleksandrov u16 v_start = 0, v_end = 0; 4125454f5c2SVladimir Oltean int err; 4132594e906SNikolay Aleksandrov 414f409d0edSNikolay Aleksandrov __vlan_delete_pvid(vg, vg->pvid); 415f545923bSNikolay Aleksandrov list_for_each_entry_safe(vlan, tmp, &vg->vlan_list, vlist) { 416f545923bSNikolay Aleksandrov /* take care of disjoint ranges */ 417f545923bSNikolay Aleksandrov if (!v_start) { 418f545923bSNikolay Aleksandrov v_start = vlan->vid; 419f545923bSNikolay Aleksandrov } else if (vlan->vid - v_end != 1) { 420f545923bSNikolay Aleksandrov /* found range end, notify and start next one */ 421f545923bSNikolay Aleksandrov br_vlan_notify(br, p, v_start, v_end, RTM_DELVLAN); 422f545923bSNikolay Aleksandrov v_start = vlan->vid; 423f545923bSNikolay Aleksandrov } 424f545923bSNikolay Aleksandrov v_end = vlan->vid; 425f545923bSNikolay Aleksandrov 4265454f5c2SVladimir Oltean err = __vlan_del(vlan); 4275454f5c2SVladimir Oltean if (err) { 4285454f5c2SVladimir Oltean br_err(br, 4295454f5c2SVladimir Oltean "port %u(%s) failed to delete vlan %d: %pe\n", 4305454f5c2SVladimir Oltean (unsigned int) p->port_no, p->dev->name, 4315454f5c2SVladimir Oltean vlan->vid, ERR_PTR(err)); 4325454f5c2SVladimir Oltean } 433243a2e63SVlad Yasevich } 434243a2e63SVlad Yasevich 435f545923bSNikolay Aleksandrov /* notify about the last/whole vlan range */ 436f545923bSNikolay Aleksandrov if (v_start) 437f545923bSNikolay Aleksandrov br_vlan_notify(br, p, v_start, v_end, RTM_DELVLAN); 438f545923bSNikolay Aleksandrov } 439f545923bSNikolay Aleksandrov 44078851988SVlad Yasevich struct sk_buff *br_handle_vlan(struct net_bridge *br, 44111538d03SRoopa Prabhu const struct net_bridge_port *p, 4422594e906SNikolay Aleksandrov struct net_bridge_vlan_group *vg, 443a37b85c9SVlad Yasevich struct sk_buff *skb) 444a37b85c9SVlad Yasevich { 445281cc284SHeiner Kallweit struct pcpu_sw_netstats *stats; 4462594e906SNikolay Aleksandrov struct net_bridge_vlan *v; 447a37b85c9SVlad Yasevich u16 vid; 448a37b85c9SVlad Yasevich 44920adfa1aSVlad Yasevich /* If this packet was not filtered at input, let it pass */ 45020adfa1aSVlad Yasevich if (!BR_INPUT_SKB_CB(skb)->vlan_filtered) 45178851988SVlad Yasevich goto out; 45278851988SVlad Yasevich 4532594e906SNikolay Aleksandrov /* At this point, we know that the frame was filtered and contains 4542594e906SNikolay Aleksandrov * a valid vlan id. If the vlan id has untagged flag set, 4552594e906SNikolay Aleksandrov * send untagged; otherwise, send tagged. 4562594e906SNikolay Aleksandrov */ 4572594e906SNikolay Aleksandrov br_vlan_get_tag(skb, &vid); 4582594e906SNikolay Aleksandrov v = br_vlan_find(vg, vid); 4592594e906SNikolay Aleksandrov /* Vlan entry must be configured at this point. The 460fc92f745SVlad Yasevich * only exception is the bridge is set in promisc mode and the 461fc92f745SVlad Yasevich * packet is destined for the bridge device. In this case 462fc92f745SVlad Yasevich * pass the packet as is. 463fc92f745SVlad Yasevich */ 4642594e906SNikolay Aleksandrov if (!v || !br_vlan_should_use(v)) { 465fc92f745SVlad Yasevich if ((br->dev->flags & IFF_PROMISC) && skb->dev == br->dev) { 466fc92f745SVlad Yasevich goto out; 467fc92f745SVlad Yasevich } else { 468fc92f745SVlad Yasevich kfree_skb(skb); 469fc92f745SVlad Yasevich return NULL; 470fc92f745SVlad Yasevich } 471fc92f745SVlad Yasevich } 472ae75767eSNikolay Aleksandrov if (br_opt_get(br, BROPT_VLAN_STATS_ENABLED)) { 4736dada9b1SNikolay Aleksandrov stats = this_cpu_ptr(v->stats); 4746dada9b1SNikolay Aleksandrov u64_stats_update_begin(&stats->syncp); 4756dada9b1SNikolay Aleksandrov stats->tx_bytes += skb->len; 4766dada9b1SNikolay Aleksandrov stats->tx_packets++; 4776dada9b1SNikolay Aleksandrov u64_stats_update_end(&stats->syncp); 4786dada9b1SNikolay Aleksandrov } 4796dada9b1SNikolay Aleksandrov 48047211192STobias Waldekranz /* If the skb will be sent using forwarding offload, the assumption is 48147211192STobias Waldekranz * that the switchdev will inject the packet into hardware together 48247211192STobias Waldekranz * with the bridge VLAN, so that it can be forwarded according to that 48347211192STobias Waldekranz * VLAN. The switchdev should deal with popping the VLAN header in 48447211192STobias Waldekranz * hardware on each egress port as appropriate. So only strip the VLAN 48547211192STobias Waldekranz * header if forwarding offload is not being used. 48647211192STobias Waldekranz */ 48747211192STobias Waldekranz if (v->flags & BRIDGE_VLAN_INFO_UNTAGGED && 48847211192STobias Waldekranz !br_switchdev_frame_uses_tx_fwd_offload(skb)) 4895978f8a9SMichał Mirosław __vlan_hwaccel_clear_tag(skb); 49011538d03SRoopa Prabhu 49111538d03SRoopa Prabhu if (p && (p->flags & BR_VLAN_TUNNEL) && 49211538d03SRoopa Prabhu br_handle_egress_vlan_tunnel(skb, v)) { 49311538d03SRoopa Prabhu kfree_skb(skb); 49411538d03SRoopa Prabhu return NULL; 49511538d03SRoopa Prabhu } 49678851988SVlad Yasevich out: 49778851988SVlad Yasevich return skb; 49878851988SVlad Yasevich } 49978851988SVlad Yasevich 50078851988SVlad Yasevich /* Called under RCU */ 5016dada9b1SNikolay Aleksandrov static bool __allowed_ingress(const struct net_bridge *br, 5026dada9b1SNikolay Aleksandrov struct net_bridge_vlan_group *vg, 503a580c76dSNikolay Aleksandrov struct sk_buff *skb, u16 *vid, 504f4b7002aSNikolay Aleksandrov u8 *state, 505f4b7002aSNikolay Aleksandrov struct net_bridge_vlan **vlan) 50678851988SVlad Yasevich { 507281cc284SHeiner Kallweit struct pcpu_sw_netstats *stats; 5086dada9b1SNikolay Aleksandrov struct net_bridge_vlan *v; 5098580e211SToshiaki Makita bool tagged; 510a37b85c9SVlad Yasevich 51120adfa1aSVlad Yasevich BR_INPUT_SKB_CB(skb)->vlan_filtered = true; 51212464bb8SToshiaki Makita /* If vlan tx offload is disabled on bridge device and frame was 51312464bb8SToshiaki Makita * sent from vlan device on the bridge device, it does not have 51412464bb8SToshiaki Makita * HW accelerated vlan tag. 51512464bb8SToshiaki Makita */ 516df8a39deSJiri Pirko if (unlikely(!skb_vlan_tag_present(skb) && 5176dada9b1SNikolay Aleksandrov skb->protocol == br->vlan_proto)) { 5180d5501c1SVlad Yasevich skb = skb_vlan_untag(skb); 51912464bb8SToshiaki Makita if (unlikely(!skb)) 52012464bb8SToshiaki Makita return false; 52112464bb8SToshiaki Makita } 52212464bb8SToshiaki Makita 5238580e211SToshiaki Makita if (!br_vlan_get_tag(skb, vid)) { 5248580e211SToshiaki Makita /* Tagged frame */ 5256dada9b1SNikolay Aleksandrov if (skb->vlan_proto != br->vlan_proto) { 5268580e211SToshiaki Makita /* Protocol-mismatch, empty out vlan_tci for new tag */ 5278580e211SToshiaki Makita skb_push(skb, ETH_HLEN); 52862749e2cSJiri Pirko skb = vlan_insert_tag_set_proto(skb, skb->vlan_proto, 529df8a39deSJiri Pirko skb_vlan_tag_get(skb)); 5308580e211SToshiaki Makita if (unlikely(!skb)) 5318580e211SToshiaki Makita return false; 5328580e211SToshiaki Makita 5338580e211SToshiaki Makita skb_pull(skb, ETH_HLEN); 5348580e211SToshiaki Makita skb_reset_mac_len(skb); 5358580e211SToshiaki Makita *vid = 0; 5368580e211SToshiaki Makita tagged = false; 5378580e211SToshiaki Makita } else { 5388580e211SToshiaki Makita tagged = true; 5398580e211SToshiaki Makita } 5408580e211SToshiaki Makita } else { 5418580e211SToshiaki Makita /* Untagged frame */ 5428580e211SToshiaki Makita tagged = false; 5438580e211SToshiaki Makita } 5448580e211SToshiaki Makita 545b90356ceSToshiaki Makita if (!*vid) { 54677751ee8SNikolay Aleksandrov u16 pvid = br_get_pvid(vg); 54777751ee8SNikolay Aleksandrov 548b90356ceSToshiaki Makita /* Frame had a tag with VID 0 or did not have a tag. 549b90356ceSToshiaki Makita * See if pvid is set on this port. That tells us which 550b90356ceSToshiaki Makita * vlan untagged or priority-tagged traffic belongs to. 55178851988SVlad Yasevich */ 5523df6bf45SVlad Yasevich if (!pvid) 553eb707618SToshiaki Makita goto drop; 55478851988SVlad Yasevich 555b90356ceSToshiaki Makita /* PVID is set on this port. Any untagged or priority-tagged 556b90356ceSToshiaki Makita * ingress frame is considered to belong to this vlan. 55778851988SVlad Yasevich */ 558dfb5fa32SToshiaki Makita *vid = pvid; 5598580e211SToshiaki Makita if (likely(!tagged)) 560b90356ceSToshiaki Makita /* Untagged Frame. */ 5616dada9b1SNikolay Aleksandrov __vlan_hwaccel_put_tag(skb, br->vlan_proto, pvid); 562b90356ceSToshiaki Makita else 563b90356ceSToshiaki Makita /* Priority-tagged Frame. 5645978f8a9SMichał Mirosław * At this point, we know that skb->vlan_tci VID 5655978f8a9SMichał Mirosław * field was 0. 566b90356ceSToshiaki Makita * We update only VID field and preserve PCP field. 567b90356ceSToshiaki Makita */ 568b90356ceSToshiaki Makita skb->vlan_tci |= pvid; 569b90356ceSToshiaki Makita 570f4b7002aSNikolay Aleksandrov /* if snooping and stats are disabled we can avoid the lookup */ 571f4b7002aSNikolay Aleksandrov if (!br_opt_get(br, BROPT_MCAST_VLAN_SNOOPING_ENABLED) && 572f4b7002aSNikolay Aleksandrov !br_opt_get(br, BROPT_VLAN_STATS_ENABLED)) { 573a580c76dSNikolay Aleksandrov if (*state == BR_STATE_FORWARDING) { 574a580c76dSNikolay Aleksandrov *state = br_vlan_get_pvid_state(vg); 575fd20d973STim Yi if (!br_vlan_state_allowed(*state, true)) 576fd20d973STim Yi goto drop; 57778851988SVlad Yasevich } 578fd20d973STim Yi return true; 579a580c76dSNikolay Aleksandrov } 580a580c76dSNikolay Aleksandrov } 58177751ee8SNikolay Aleksandrov v = br_vlan_find(vg, *vid); 5826dada9b1SNikolay Aleksandrov if (!v || !br_vlan_should_use(v)) 5836dada9b1SNikolay Aleksandrov goto drop; 5846dada9b1SNikolay Aleksandrov 585a580c76dSNikolay Aleksandrov if (*state == BR_STATE_FORWARDING) { 586a580c76dSNikolay Aleksandrov *state = br_vlan_get_state(v); 587a580c76dSNikolay Aleksandrov if (!br_vlan_state_allowed(*state, true)) 588a580c76dSNikolay Aleksandrov goto drop; 589a580c76dSNikolay Aleksandrov } 590a580c76dSNikolay Aleksandrov 591ae75767eSNikolay Aleksandrov if (br_opt_get(br, BROPT_VLAN_STATS_ENABLED)) { 5926dada9b1SNikolay Aleksandrov stats = this_cpu_ptr(v->stats); 5936dada9b1SNikolay Aleksandrov u64_stats_update_begin(&stats->syncp); 5946dada9b1SNikolay Aleksandrov stats->rx_bytes += skb->len; 5956dada9b1SNikolay Aleksandrov stats->rx_packets++; 5966dada9b1SNikolay Aleksandrov u64_stats_update_end(&stats->syncp); 5976dada9b1SNikolay Aleksandrov } 5986dada9b1SNikolay Aleksandrov 599f4b7002aSNikolay Aleksandrov *vlan = v; 600f4b7002aSNikolay Aleksandrov 601a37b85c9SVlad Yasevich return true; 6026dada9b1SNikolay Aleksandrov 603eb707618SToshiaki Makita drop: 604eb707618SToshiaki Makita kfree_skb(skb); 605a37b85c9SVlad Yasevich return false; 606a37b85c9SVlad Yasevich } 607a37b85c9SVlad Yasevich 60877751ee8SNikolay Aleksandrov bool br_allowed_ingress(const struct net_bridge *br, 60977751ee8SNikolay Aleksandrov struct net_bridge_vlan_group *vg, struct sk_buff *skb, 610f4b7002aSNikolay Aleksandrov u16 *vid, u8 *state, 611f4b7002aSNikolay Aleksandrov struct net_bridge_vlan **vlan) 6122594e906SNikolay Aleksandrov { 6132594e906SNikolay Aleksandrov /* If VLAN filtering is disabled on the bridge, all packets are 6142594e906SNikolay Aleksandrov * permitted. 6152594e906SNikolay Aleksandrov */ 616f4b7002aSNikolay Aleksandrov *vlan = NULL; 617ae75767eSNikolay Aleksandrov if (!br_opt_get(br, BROPT_VLAN_ENABLED)) { 6182594e906SNikolay Aleksandrov BR_INPUT_SKB_CB(skb)->vlan_filtered = false; 6192594e906SNikolay Aleksandrov return true; 6202594e906SNikolay Aleksandrov } 6212594e906SNikolay Aleksandrov 622f4b7002aSNikolay Aleksandrov return __allowed_ingress(br, vg, skb, vid, state, vlan); 6232594e906SNikolay Aleksandrov } 6242594e906SNikolay Aleksandrov 62585f46c6bSVlad Yasevich /* Called under RCU. */ 6262594e906SNikolay Aleksandrov bool br_allowed_egress(struct net_bridge_vlan_group *vg, 62785f46c6bSVlad Yasevich const struct sk_buff *skb) 62885f46c6bSVlad Yasevich { 6292594e906SNikolay Aleksandrov const struct net_bridge_vlan *v; 63085f46c6bSVlad Yasevich u16 vid; 63185f46c6bSVlad Yasevich 63220adfa1aSVlad Yasevich /* If this packet was not filtered at input, let it pass */ 63320adfa1aSVlad Yasevich if (!BR_INPUT_SKB_CB(skb)->vlan_filtered) 63485f46c6bSVlad Yasevich return true; 63585f46c6bSVlad Yasevich 63685f46c6bSVlad Yasevich br_vlan_get_tag(skb, &vid); 6372594e906SNikolay Aleksandrov v = br_vlan_find(vg, vid); 638a580c76dSNikolay Aleksandrov if (v && br_vlan_should_use(v) && 639a580c76dSNikolay Aleksandrov br_vlan_state_allowed(br_vlan_get_state(v), false)) 64085f46c6bSVlad Yasevich return true; 64185f46c6bSVlad Yasevich 64285f46c6bSVlad Yasevich return false; 64385f46c6bSVlad Yasevich } 64485f46c6bSVlad Yasevich 645e0d7968aSToshiaki Makita /* Called under RCU */ 646e0d7968aSToshiaki Makita bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid) 647e0d7968aSToshiaki Makita { 648468e7944SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 649e0d7968aSToshiaki Makita struct net_bridge *br = p->br; 650a580c76dSNikolay Aleksandrov struct net_bridge_vlan *v; 651e0d7968aSToshiaki Makita 65220adfa1aSVlad Yasevich /* If filtering was disabled at input, let it pass. */ 653ae75767eSNikolay Aleksandrov if (!br_opt_get(br, BROPT_VLAN_ENABLED)) 654e0d7968aSToshiaki Makita return true; 655e0d7968aSToshiaki Makita 656eca1e006SIdo Schimmel vg = nbp_vlan_group_rcu(p); 657468e7944SNikolay Aleksandrov if (!vg || !vg->num_vlans) 658e0d7968aSToshiaki Makita return false; 659e0d7968aSToshiaki Makita 6608580e211SToshiaki Makita if (!br_vlan_get_tag(skb, vid) && skb->vlan_proto != br->vlan_proto) 6618580e211SToshiaki Makita *vid = 0; 6628580e211SToshiaki Makita 663e0d7968aSToshiaki Makita if (!*vid) { 66477751ee8SNikolay Aleksandrov *vid = br_get_pvid(vg); 665a580c76dSNikolay Aleksandrov if (!*vid || 666a580c76dSNikolay Aleksandrov !br_vlan_state_allowed(br_vlan_get_pvid_state(vg), true)) 667e0d7968aSToshiaki Makita return false; 668e0d7968aSToshiaki Makita 669e0d7968aSToshiaki Makita return true; 670e0d7968aSToshiaki Makita } 671e0d7968aSToshiaki Makita 672a580c76dSNikolay Aleksandrov v = br_vlan_find(vg, *vid); 673a580c76dSNikolay Aleksandrov if (v && br_vlan_state_allowed(br_vlan_get_state(v), true)) 674e0d7968aSToshiaki Makita return true; 675e0d7968aSToshiaki Makita 676e0d7968aSToshiaki Makita return false; 677e0d7968aSToshiaki Makita } 678e0d7968aSToshiaki Makita 679dbd6dc75SPetr Machata static int br_vlan_add_existing(struct net_bridge *br, 680dbd6dc75SPetr Machata struct net_bridge_vlan_group *vg, 681dbd6dc75SPetr Machata struct net_bridge_vlan *vlan, 682169327d5SPetr Machata u16 flags, bool *changed, 683169327d5SPetr Machata struct netlink_ext_ack *extack) 684dbd6dc75SPetr Machata { 685dbd6dc75SPetr Machata int err; 686dbd6dc75SPetr Machata 687b2bc58d4SVladimir Oltean /* Trying to change flags of non-existent bridge vlan */ 688b2bc58d4SVladimir Oltean if (!br_vlan_is_brentry(vlan) && !(flags & BRIDGE_VLAN_INFO_BRENTRY)) 689b2bc58d4SVladimir Oltean return -EINVAL; 690b2bc58d4SVladimir Oltean 691169327d5SPetr Machata err = br_switchdev_port_vlan_add(br->dev, vlan->vid, flags, extack); 6929c86ce2cSPetr Machata if (err && err != -EOPNOTSUPP) 6939c86ce2cSPetr Machata return err; 6949c86ce2cSPetr Machata 695dbd6dc75SPetr Machata if (!br_vlan_is_brentry(vlan)) { 696dbd6dc75SPetr Machata /* It was only kept for port vlans, now make it real */ 697f6814fdcSVladimir Oltean err = br_fdb_add_local(br, NULL, br->dev->dev_addr, vlan->vid); 698dbd6dc75SPetr Machata if (err) { 699dbd6dc75SPetr Machata br_err(br, "failed to insert local address into bridge forwarding table\n"); 7009c86ce2cSPetr Machata goto err_fdb_insert; 701dbd6dc75SPetr Machata } 702dbd6dc75SPetr Machata 703dbd6dc75SPetr Machata refcount_inc(&vlan->refcnt); 704dbd6dc75SPetr Machata vlan->flags |= BRIDGE_VLAN_INFO_BRENTRY; 705dbd6dc75SPetr Machata vg->num_vlans++; 706dbd6dc75SPetr Machata *changed = true; 707b92dace3SNikolay Aleksandrov br_multicast_toggle_one_vlan(vlan, true); 708dbd6dc75SPetr Machata } 709dbd6dc75SPetr Machata 710dbd6dc75SPetr Machata if (__vlan_add_flags(vlan, flags)) 711dbd6dc75SPetr Machata *changed = true; 712dbd6dc75SPetr Machata 713dbd6dc75SPetr Machata return 0; 7149c86ce2cSPetr Machata 7159c86ce2cSPetr Machata err_fdb_insert: 7169c86ce2cSPetr Machata br_switchdev_port_vlan_del(br->dev, vlan->vid); 7179c86ce2cSPetr Machata return err; 718dbd6dc75SPetr Machata } 719dbd6dc75SPetr Machata 7208adff41cSToshiaki Makita /* Must be protected by RTNL. 7218adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 722f418af63SNikolay Aleksandrov * changed must be true only if the vlan was created or updated 7238adff41cSToshiaki Makita */ 724169327d5SPetr Machata int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags, bool *changed, 725169327d5SPetr Machata struct netlink_ext_ack *extack) 726243a2e63SVlad Yasevich { 727907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 7282594e906SNikolay Aleksandrov struct net_bridge_vlan *vlan; 7292594e906SNikolay Aleksandrov int ret; 730243a2e63SVlad Yasevich 731243a2e63SVlad Yasevich ASSERT_RTNL(); 732243a2e63SVlad Yasevich 733f418af63SNikolay Aleksandrov *changed = false; 734907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 735907b1e6eSNikolay Aleksandrov vlan = br_vlan_find(vg, vid); 736dbd6dc75SPetr Machata if (vlan) 737169327d5SPetr Machata return br_vlan_add_existing(br, vg, vlan, flags, changed, 738169327d5SPetr Machata extack); 739243a2e63SVlad Yasevich 7402594e906SNikolay Aleksandrov vlan = kzalloc(sizeof(*vlan), GFP_KERNEL); 7412594e906SNikolay Aleksandrov if (!vlan) 742243a2e63SVlad Yasevich return -ENOMEM; 743243a2e63SVlad Yasevich 744281cc284SHeiner Kallweit vlan->stats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); 7456dada9b1SNikolay Aleksandrov if (!vlan->stats) { 7466dada9b1SNikolay Aleksandrov kfree(vlan); 7476dada9b1SNikolay Aleksandrov return -ENOMEM; 7486dada9b1SNikolay Aleksandrov } 7492594e906SNikolay Aleksandrov vlan->vid = vid; 7502594e906SNikolay Aleksandrov vlan->flags = flags | BRIDGE_VLAN_INFO_MASTER; 7512594e906SNikolay Aleksandrov vlan->flags &= ~BRIDGE_VLAN_INFO_PVID; 7522594e906SNikolay Aleksandrov vlan->br = br; 7532594e906SNikolay Aleksandrov if (flags & BRIDGE_VLAN_INFO_BRENTRY) 75425127759SReshetova, Elena refcount_set(&vlan->refcnt, 1); 755169327d5SPetr Machata ret = __vlan_add(vlan, flags, extack); 7566dada9b1SNikolay Aleksandrov if (ret) { 7576dada9b1SNikolay Aleksandrov free_percpu(vlan->stats); 7582594e906SNikolay Aleksandrov kfree(vlan); 759f418af63SNikolay Aleksandrov } else { 760f418af63SNikolay Aleksandrov *changed = true; 7616dada9b1SNikolay Aleksandrov } 762243a2e63SVlad Yasevich 7632594e906SNikolay Aleksandrov return ret; 764243a2e63SVlad Yasevich } 765243a2e63SVlad Yasevich 7668adff41cSToshiaki Makita /* Must be protected by RTNL. 7678adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 7688adff41cSToshiaki Makita */ 769243a2e63SVlad Yasevich int br_vlan_delete(struct net_bridge *br, u16 vid) 770243a2e63SVlad Yasevich { 771907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 7722594e906SNikolay Aleksandrov struct net_bridge_vlan *v; 773243a2e63SVlad Yasevich 774243a2e63SVlad Yasevich ASSERT_RTNL(); 775243a2e63SVlad Yasevich 776907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 777907b1e6eSNikolay Aleksandrov v = br_vlan_find(vg, vid); 7782594e906SNikolay Aleksandrov if (!v || !br_vlan_is_brentry(v)) 7792594e906SNikolay Aleksandrov return -ENOENT; 780243a2e63SVlad Yasevich 781424bb9c9SToshiaki Makita br_fdb_find_delete_local(br, NULL, br->dev->dev_addr, vid); 7823741873bSRoopa Prabhu br_fdb_delete_by_port(br, NULL, vid, 0); 783bc9a25d2SVlad Yasevich 784efa5356bSRoopa Prabhu vlan_tunnel_info_del(vg, v); 785efa5356bSRoopa Prabhu 7862594e906SNikolay Aleksandrov return __vlan_del(v); 787243a2e63SVlad Yasevich } 788243a2e63SVlad Yasevich 789243a2e63SVlad Yasevich void br_vlan_flush(struct net_bridge *br) 790243a2e63SVlad Yasevich { 791f409d0edSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 792f409d0edSNikolay Aleksandrov 793243a2e63SVlad Yasevich ASSERT_RTNL(); 794243a2e63SVlad Yasevich 795f409d0edSNikolay Aleksandrov vg = br_vlan_group(br); 796f545923bSNikolay Aleksandrov __vlan_flush(br, NULL, vg); 797f409d0edSNikolay Aleksandrov RCU_INIT_POINTER(br->vlgrp, NULL); 798f409d0edSNikolay Aleksandrov synchronize_rcu(); 799f409d0edSNikolay Aleksandrov __vlan_group_free(vg); 800243a2e63SVlad Yasevich } 801243a2e63SVlad Yasevich 8022594e906SNikolay Aleksandrov struct net_bridge_vlan *br_vlan_find(struct net_bridge_vlan_group *vg, u16 vid) 8032b292fb4SToshiaki Makita { 8042594e906SNikolay Aleksandrov if (!vg) 8052594e906SNikolay Aleksandrov return NULL; 8062b292fb4SToshiaki Makita 8072594e906SNikolay Aleksandrov return br_vlan_lookup(&vg->vlan_hash, vid); 8082b292fb4SToshiaki Makita } 8092b292fb4SToshiaki Makita 810204177f3SToshiaki Makita /* Must be protected by RTNL. */ 811204177f3SToshiaki Makita static void recalculate_group_addr(struct net_bridge *br) 812204177f3SToshiaki Makita { 813be3664a0SNikolay Aleksandrov if (br_opt_get(br, BROPT_GROUP_ADDR_SET)) 814204177f3SToshiaki Makita return; 815204177f3SToshiaki Makita 816204177f3SToshiaki Makita spin_lock_bh(&br->lock); 817ae75767eSNikolay Aleksandrov if (!br_opt_get(br, BROPT_VLAN_ENABLED) || 818ae75767eSNikolay Aleksandrov br->vlan_proto == htons(ETH_P_8021Q)) { 819204177f3SToshiaki Makita /* Bridge Group Address */ 820204177f3SToshiaki Makita br->group_addr[5] = 0x00; 821204177f3SToshiaki Makita } else { /* vlan_enabled && ETH_P_8021AD */ 822204177f3SToshiaki Makita /* Provider Bridge Group Address */ 823204177f3SToshiaki Makita br->group_addr[5] = 0x08; 824204177f3SToshiaki Makita } 825204177f3SToshiaki Makita spin_unlock_bh(&br->lock); 826204177f3SToshiaki Makita } 827204177f3SToshiaki Makita 828204177f3SToshiaki Makita /* Must be protected by RTNL. */ 829204177f3SToshiaki Makita void br_recalculate_fwd_mask(struct net_bridge *br) 830204177f3SToshiaki Makita { 831ae75767eSNikolay Aleksandrov if (!br_opt_get(br, BROPT_VLAN_ENABLED) || 832ae75767eSNikolay Aleksandrov br->vlan_proto == htons(ETH_P_8021Q)) 833204177f3SToshiaki Makita br->group_fwd_mask_required = BR_GROUPFWD_DEFAULT; 834204177f3SToshiaki Makita else /* vlan_enabled && ETH_P_8021AD */ 835204177f3SToshiaki Makita br->group_fwd_mask_required = BR_GROUPFWD_8021AD & 836204177f3SToshiaki Makita ~(1u << br->group_addr[5]); 837204177f3SToshiaki Makita } 838204177f3SToshiaki Makita 8399e781401SVladimir Oltean int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val, 8409e781401SVladimir Oltean struct netlink_ext_ack *extack) 841243a2e63SVlad Yasevich { 8426b72a770SElad Raz struct switchdev_attr attr = { 8436b72a770SElad Raz .orig_dev = br->dev, 8446b72a770SElad Raz .id = SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING, 8456b72a770SElad Raz .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP, 8466b72a770SElad Raz .u.vlan_filtering = val, 8476b72a770SElad Raz }; 8486b72a770SElad Raz int err; 8496b72a770SElad Raz 850ae75767eSNikolay Aleksandrov if (br_opt_get(br, BROPT_VLAN_ENABLED) == !!val) 851a7854037SNikolay Aleksandrov return 0; 852243a2e63SVlad Yasevich 853ae75767eSNikolay Aleksandrov br_opt_toggle(br, BROPT_VLAN_ENABLED, !!val); 854f7cdb3ecSVladimir Oltean 855f7cdb3ecSVladimir Oltean err = switchdev_port_attr_set(br->dev, &attr, extack); 856f7cdb3ecSVladimir Oltean if (err && err != -EOPNOTSUPP) { 857f7cdb3ecSVladimir Oltean br_opt_toggle(br, BROPT_VLAN_ENABLED, !val); 858f7cdb3ecSVladimir Oltean return err; 859f7cdb3ecSVladimir Oltean } 860f7cdb3ecSVladimir Oltean 8612796d0c6SVlad Yasevich br_manage_promisc(br); 862204177f3SToshiaki Makita recalculate_group_addr(br); 863204177f3SToshiaki Makita br_recalculate_fwd_mask(br); 864f4b7002aSNikolay Aleksandrov if (!val && br_opt_get(br, BROPT_MCAST_VLAN_SNOOPING_ENABLED)) { 865f4b7002aSNikolay Aleksandrov br_info(br, "vlan filtering disabled, automatically disabling multicast vlan snooping\n"); 866f4b7002aSNikolay Aleksandrov br_multicast_toggle_vlan_snooping(br, false, NULL); 867f4b7002aSNikolay Aleksandrov } 868243a2e63SVlad Yasevich 869a7854037SNikolay Aleksandrov return 0; 870a7854037SNikolay Aleksandrov } 871a7854037SNikolay Aleksandrov 8721f51445aSIdo Schimmel bool br_vlan_enabled(const struct net_device *dev) 8731f51445aSIdo Schimmel { 8741f51445aSIdo Schimmel struct net_bridge *br = netdev_priv(dev); 8751f51445aSIdo Schimmel 876ae75767eSNikolay Aleksandrov return br_opt_get(br, BROPT_VLAN_ENABLED); 8771f51445aSIdo Schimmel } 8781f51445aSIdo Schimmel EXPORT_SYMBOL_GPL(br_vlan_enabled); 8791f51445aSIdo Schimmel 88031aed46fSwenxu int br_vlan_get_proto(const struct net_device *dev, u16 *p_proto) 88131aed46fSwenxu { 88231aed46fSwenxu struct net_bridge *br = netdev_priv(dev); 88331aed46fSwenxu 88431aed46fSwenxu *p_proto = ntohs(br->vlan_proto); 88531aed46fSwenxu 88631aed46fSwenxu return 0; 88731aed46fSwenxu } 88831aed46fSwenxu EXPORT_SYMBOL_GPL(br_vlan_get_proto); 88931aed46fSwenxu 890dcbdf135SVladimir Oltean int __br_vlan_set_proto(struct net_bridge *br, __be16 proto, 891dcbdf135SVladimir Oltean struct netlink_ext_ack *extack) 892204177f3SToshiaki Makita { 89322ec19f3SDanielle Ratson struct switchdev_attr attr = { 89422ec19f3SDanielle Ratson .orig_dev = br->dev, 89522ec19f3SDanielle Ratson .id = SWITCHDEV_ATTR_ID_BRIDGE_VLAN_PROTOCOL, 89622ec19f3SDanielle Ratson .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP, 89722ec19f3SDanielle Ratson .u.vlan_protocol = ntohs(proto), 89822ec19f3SDanielle Ratson }; 899204177f3SToshiaki Makita int err = 0; 900204177f3SToshiaki Makita struct net_bridge_port *p; 9012594e906SNikolay Aleksandrov struct net_bridge_vlan *vlan; 902907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 90322ec19f3SDanielle Ratson __be16 oldproto = br->vlan_proto; 904204177f3SToshiaki Makita 905204177f3SToshiaki Makita if (br->vlan_proto == proto) 906d2d427b3SToshiaki Makita return 0; 907204177f3SToshiaki Makita 908dcbdf135SVladimir Oltean err = switchdev_port_attr_set(br->dev, &attr, extack); 90922ec19f3SDanielle Ratson if (err && err != -EOPNOTSUPP) 91022ec19f3SDanielle Ratson return err; 91122ec19f3SDanielle Ratson 912204177f3SToshiaki Makita /* Add VLANs for the new proto to the device filter. */ 913204177f3SToshiaki Makita list_for_each_entry(p, &br->port_list, list) { 914907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 915907b1e6eSNikolay Aleksandrov list_for_each_entry(vlan, &vg->vlan_list, vlist) { 9162594e906SNikolay Aleksandrov err = vlan_vid_add(p->dev, proto, vlan->vid); 917204177f3SToshiaki Makita if (err) 918204177f3SToshiaki Makita goto err_filt; 919204177f3SToshiaki Makita } 920204177f3SToshiaki Makita } 921204177f3SToshiaki Makita 922204177f3SToshiaki Makita br->vlan_proto = proto; 923204177f3SToshiaki Makita 924204177f3SToshiaki Makita recalculate_group_addr(br); 925204177f3SToshiaki Makita br_recalculate_fwd_mask(br); 926204177f3SToshiaki Makita 927204177f3SToshiaki Makita /* Delete VLANs for the old proto from the device filter. */ 928907b1e6eSNikolay Aleksandrov list_for_each_entry(p, &br->port_list, list) { 929907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 930907b1e6eSNikolay Aleksandrov list_for_each_entry(vlan, &vg->vlan_list, vlist) 9312594e906SNikolay Aleksandrov vlan_vid_del(p->dev, oldproto, vlan->vid); 932907b1e6eSNikolay Aleksandrov } 933204177f3SToshiaki Makita 934d2d427b3SToshiaki Makita return 0; 935204177f3SToshiaki Makita 936204177f3SToshiaki Makita err_filt: 93722ec19f3SDanielle Ratson attr.u.vlan_protocol = ntohs(oldproto); 938dcbdf135SVladimir Oltean switchdev_port_attr_set(br->dev, &attr, NULL); 93922ec19f3SDanielle Ratson 940907b1e6eSNikolay Aleksandrov list_for_each_entry_continue_reverse(vlan, &vg->vlan_list, vlist) 9412594e906SNikolay Aleksandrov vlan_vid_del(p->dev, proto, vlan->vid); 942204177f3SToshiaki Makita 943907b1e6eSNikolay Aleksandrov list_for_each_entry_continue_reverse(p, &br->port_list, list) { 944907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 945907b1e6eSNikolay Aleksandrov list_for_each_entry(vlan, &vg->vlan_list, vlist) 9462594e906SNikolay Aleksandrov vlan_vid_del(p->dev, proto, vlan->vid); 947907b1e6eSNikolay Aleksandrov } 948204177f3SToshiaki Makita 949d2d427b3SToshiaki Makita return err; 950d2d427b3SToshiaki Makita } 951d2d427b3SToshiaki Makita 9529e781401SVladimir Oltean int br_vlan_set_proto(struct net_bridge *br, unsigned long val, 9539e781401SVladimir Oltean struct netlink_ext_ack *extack) 954d2d427b3SToshiaki Makita { 955a98c0c47SMenglong Dong if (!eth_type_vlan(htons(val))) 956d2d427b3SToshiaki Makita return -EPROTONOSUPPORT; 957d2d427b3SToshiaki Makita 958dcbdf135SVladimir Oltean return __br_vlan_set_proto(br, htons(val), extack); 959204177f3SToshiaki Makita } 960204177f3SToshiaki Makita 9616dada9b1SNikolay Aleksandrov int br_vlan_set_stats(struct net_bridge *br, unsigned long val) 9626dada9b1SNikolay Aleksandrov { 9636dada9b1SNikolay Aleksandrov switch (val) { 9646dada9b1SNikolay Aleksandrov case 0: 9656dada9b1SNikolay Aleksandrov case 1: 966ae75767eSNikolay Aleksandrov br_opt_toggle(br, BROPT_VLAN_STATS_ENABLED, !!val); 9676dada9b1SNikolay Aleksandrov break; 9686dada9b1SNikolay Aleksandrov default: 9696dada9b1SNikolay Aleksandrov return -EINVAL; 9706dada9b1SNikolay Aleksandrov } 9716dada9b1SNikolay Aleksandrov 9726dada9b1SNikolay Aleksandrov return 0; 9736dada9b1SNikolay Aleksandrov } 9746dada9b1SNikolay Aleksandrov 9759163a0fcSNikolay Aleksandrov int br_vlan_set_stats_per_port(struct net_bridge *br, unsigned long val) 9769163a0fcSNikolay Aleksandrov { 9779163a0fcSNikolay Aleksandrov struct net_bridge_port *p; 9789163a0fcSNikolay Aleksandrov 9799163a0fcSNikolay Aleksandrov /* allow to change the option if there are no port vlans configured */ 9809163a0fcSNikolay Aleksandrov list_for_each_entry(p, &br->port_list, list) { 9819163a0fcSNikolay Aleksandrov struct net_bridge_vlan_group *vg = nbp_vlan_group(p); 9829163a0fcSNikolay Aleksandrov 9839163a0fcSNikolay Aleksandrov if (vg->num_vlans) 9849163a0fcSNikolay Aleksandrov return -EBUSY; 9859163a0fcSNikolay Aleksandrov } 9869163a0fcSNikolay Aleksandrov 9879163a0fcSNikolay Aleksandrov switch (val) { 9889163a0fcSNikolay Aleksandrov case 0: 9899163a0fcSNikolay Aleksandrov case 1: 9909163a0fcSNikolay Aleksandrov br_opt_toggle(br, BROPT_VLAN_STATS_PER_PORT, !!val); 9919163a0fcSNikolay Aleksandrov break; 9929163a0fcSNikolay Aleksandrov default: 9939163a0fcSNikolay Aleksandrov return -EINVAL; 9949163a0fcSNikolay Aleksandrov } 9959163a0fcSNikolay Aleksandrov 9969163a0fcSNikolay Aleksandrov return 0; 9979163a0fcSNikolay Aleksandrov } 9989163a0fcSNikolay Aleksandrov 99977751ee8SNikolay Aleksandrov static bool vlan_default_pvid(struct net_bridge_vlan_group *vg, u16 vid) 10005be5a2dfSVlad Yasevich { 10012594e906SNikolay Aleksandrov struct net_bridge_vlan *v; 10022594e906SNikolay Aleksandrov 100377751ee8SNikolay Aleksandrov if (vid != vg->pvid) 10042594e906SNikolay Aleksandrov return false; 10052594e906SNikolay Aleksandrov 10062594e906SNikolay Aleksandrov v = br_vlan_lookup(&vg->vlan_hash, vid); 10072594e906SNikolay Aleksandrov if (v && br_vlan_should_use(v) && 10082594e906SNikolay Aleksandrov (v->flags & BRIDGE_VLAN_INFO_UNTAGGED)) 10092594e906SNikolay Aleksandrov return true; 10102594e906SNikolay Aleksandrov 10112594e906SNikolay Aleksandrov return false; 10125be5a2dfSVlad Yasevich } 10135be5a2dfSVlad Yasevich 10145be5a2dfSVlad Yasevich static void br_vlan_disable_default_pvid(struct net_bridge *br) 10155be5a2dfSVlad Yasevich { 10165be5a2dfSVlad Yasevich struct net_bridge_port *p; 10175be5a2dfSVlad Yasevich u16 pvid = br->default_pvid; 10185be5a2dfSVlad Yasevich 10195be5a2dfSVlad Yasevich /* Disable default_pvid on all ports where it is still 10205be5a2dfSVlad Yasevich * configured. 10215be5a2dfSVlad Yasevich */ 1022f545923bSNikolay Aleksandrov if (vlan_default_pvid(br_vlan_group(br), pvid)) { 1023f545923bSNikolay Aleksandrov if (!br_vlan_delete(br, pvid)) 1024f545923bSNikolay Aleksandrov br_vlan_notify(br, NULL, pvid, 0, RTM_DELVLAN); 1025f545923bSNikolay Aleksandrov } 10265be5a2dfSVlad Yasevich 10275be5a2dfSVlad Yasevich list_for_each_entry(p, &br->port_list, list) { 1028f545923bSNikolay Aleksandrov if (vlan_default_pvid(nbp_vlan_group(p), pvid) && 1029f545923bSNikolay Aleksandrov !nbp_vlan_delete(p, pvid)) 1030f545923bSNikolay Aleksandrov br_vlan_notify(br, p, pvid, 0, RTM_DELVLAN); 10315be5a2dfSVlad Yasevich } 10325be5a2dfSVlad Yasevich 10335be5a2dfSVlad Yasevich br->default_pvid = 0; 10345be5a2dfSVlad Yasevich } 10355be5a2dfSVlad Yasevich 1036169327d5SPetr Machata int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid, 1037169327d5SPetr Machata struct netlink_ext_ack *extack) 10385be5a2dfSVlad Yasevich { 10392594e906SNikolay Aleksandrov const struct net_bridge_vlan *pvent; 1040907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 10415be5a2dfSVlad Yasevich struct net_bridge_port *p; 1042f418af63SNikolay Aleksandrov unsigned long *changed; 1043f418af63SNikolay Aleksandrov bool vlchange; 10445be5a2dfSVlad Yasevich u16 old_pvid; 10455be5a2dfSVlad Yasevich int err = 0; 10465be5a2dfSVlad Yasevich 10470f963b75SNikolay Aleksandrov if (!pvid) { 10480f963b75SNikolay Aleksandrov br_vlan_disable_default_pvid(br); 10490f963b75SNikolay Aleksandrov return 0; 10500f963b75SNikolay Aleksandrov } 10510f963b75SNikolay Aleksandrov 1052459479daSAndy Shevchenko changed = bitmap_zalloc(BR_MAX_PORTS, GFP_KERNEL); 10535be5a2dfSVlad Yasevich if (!changed) 10545be5a2dfSVlad Yasevich return -ENOMEM; 10555be5a2dfSVlad Yasevich 10565be5a2dfSVlad Yasevich old_pvid = br->default_pvid; 10575be5a2dfSVlad Yasevich 10585be5a2dfSVlad Yasevich /* Update default_pvid config only if we do not conflict with 10595be5a2dfSVlad Yasevich * user configuration. 10605be5a2dfSVlad Yasevich */ 1061907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 1062907b1e6eSNikolay Aleksandrov pvent = br_vlan_find(vg, pvid); 1063907b1e6eSNikolay Aleksandrov if ((!old_pvid || vlan_default_pvid(vg, old_pvid)) && 10642594e906SNikolay Aleksandrov (!pvent || !br_vlan_should_use(pvent))) { 10655be5a2dfSVlad Yasevich err = br_vlan_add(br, pvid, 10665be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_PVID | 10672594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED | 1068f418af63SNikolay Aleksandrov BRIDGE_VLAN_INFO_BRENTRY, 1069169327d5SPetr Machata &vlchange, extack); 10705be5a2dfSVlad Yasevich if (err) 10715be5a2dfSVlad Yasevich goto out; 1072f545923bSNikolay Aleksandrov 1073f545923bSNikolay Aleksandrov if (br_vlan_delete(br, old_pvid)) 1074f545923bSNikolay Aleksandrov br_vlan_notify(br, NULL, old_pvid, 0, RTM_DELVLAN); 1075f545923bSNikolay Aleksandrov br_vlan_notify(br, NULL, pvid, 0, RTM_NEWVLAN); 1076442b03c3SXin Long __set_bit(0, changed); 10775be5a2dfSVlad Yasevich } 10785be5a2dfSVlad Yasevich 10795be5a2dfSVlad Yasevich list_for_each_entry(p, &br->port_list, list) { 10805be5a2dfSVlad Yasevich /* Update default_pvid config only if we do not conflict with 10815be5a2dfSVlad Yasevich * user configuration. 10825be5a2dfSVlad Yasevich */ 1083907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 10845be5a2dfSVlad Yasevich if ((old_pvid && 1085907b1e6eSNikolay Aleksandrov !vlan_default_pvid(vg, old_pvid)) || 1086907b1e6eSNikolay Aleksandrov br_vlan_find(vg, pvid)) 10875be5a2dfSVlad Yasevich continue; 10885be5a2dfSVlad Yasevich 10895be5a2dfSVlad Yasevich err = nbp_vlan_add(p, pvid, 10905be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_PVID | 1091f418af63SNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED, 1092169327d5SPetr Machata &vlchange, extack); 10935be5a2dfSVlad Yasevich if (err) 10945be5a2dfSVlad Yasevich goto err_port; 1095f545923bSNikolay Aleksandrov if (nbp_vlan_delete(p, old_pvid)) 1096f545923bSNikolay Aleksandrov br_vlan_notify(br, p, old_pvid, 0, RTM_DELVLAN); 1097f545923bSNikolay Aleksandrov br_vlan_notify(p->br, p, pvid, 0, RTM_NEWVLAN); 1098442b03c3SXin Long __set_bit(p->port_no, changed); 10995be5a2dfSVlad Yasevich } 11005be5a2dfSVlad Yasevich 11015be5a2dfSVlad Yasevich br->default_pvid = pvid; 11025be5a2dfSVlad Yasevich 11035be5a2dfSVlad Yasevich out: 1104459479daSAndy Shevchenko bitmap_free(changed); 11055be5a2dfSVlad Yasevich return err; 11065be5a2dfSVlad Yasevich 11075be5a2dfSVlad Yasevich err_port: 11085be5a2dfSVlad Yasevich list_for_each_entry_continue_reverse(p, &br->port_list, list) { 11095be5a2dfSVlad Yasevich if (!test_bit(p->port_no, changed)) 11105be5a2dfSVlad Yasevich continue; 11115be5a2dfSVlad Yasevich 1112f545923bSNikolay Aleksandrov if (old_pvid) { 11135be5a2dfSVlad Yasevich nbp_vlan_add(p, old_pvid, 11145be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_PVID | 1115f418af63SNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED, 1116169327d5SPetr Machata &vlchange, NULL); 1117f545923bSNikolay Aleksandrov br_vlan_notify(p->br, p, old_pvid, 0, RTM_NEWVLAN); 1118f545923bSNikolay Aleksandrov } 11195be5a2dfSVlad Yasevich nbp_vlan_delete(p, pvid); 1120f545923bSNikolay Aleksandrov br_vlan_notify(br, p, pvid, 0, RTM_DELVLAN); 11215be5a2dfSVlad Yasevich } 11225be5a2dfSVlad Yasevich 11235be5a2dfSVlad Yasevich if (test_bit(0, changed)) { 1124f545923bSNikolay Aleksandrov if (old_pvid) { 11255be5a2dfSVlad Yasevich br_vlan_add(br, old_pvid, 11265be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_PVID | 11272594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED | 1128f418af63SNikolay Aleksandrov BRIDGE_VLAN_INFO_BRENTRY, 1129169327d5SPetr Machata &vlchange, NULL); 1130f545923bSNikolay Aleksandrov br_vlan_notify(br, NULL, old_pvid, 0, RTM_NEWVLAN); 1131f545923bSNikolay Aleksandrov } 11325be5a2dfSVlad Yasevich br_vlan_delete(br, pvid); 1133f545923bSNikolay Aleksandrov br_vlan_notify(br, NULL, pvid, 0, RTM_DELVLAN); 11345be5a2dfSVlad Yasevich } 11355be5a2dfSVlad Yasevich goto out; 11365be5a2dfSVlad Yasevich } 11375be5a2dfSVlad Yasevich 11389e781401SVladimir Oltean int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val, 11399e781401SVladimir Oltean struct netlink_ext_ack *extack) 114096a20d9dSVlad Yasevich { 114196a20d9dSVlad Yasevich u16 pvid = val; 114296a20d9dSVlad Yasevich int err = 0; 114396a20d9dSVlad Yasevich 11445be5a2dfSVlad Yasevich if (val >= VLAN_VID_MASK) 114596a20d9dSVlad Yasevich return -EINVAL; 114696a20d9dSVlad Yasevich 114796a20d9dSVlad Yasevich if (pvid == br->default_pvid) 1148047831a9SXin Long goto out; 114996a20d9dSVlad Yasevich 115096a20d9dSVlad Yasevich /* Only allow default pvid change when filtering is disabled */ 1151ae75767eSNikolay Aleksandrov if (br_opt_get(br, BROPT_VLAN_ENABLED)) { 115296a20d9dSVlad Yasevich pr_info_once("Please disable vlan filtering to change default_pvid\n"); 115396a20d9dSVlad Yasevich err = -EPERM; 1154047831a9SXin Long goto out; 115596a20d9dSVlad Yasevich } 11569e781401SVladimir Oltean err = __br_vlan_set_default_pvid(br, pvid, extack); 1157047831a9SXin Long out: 115896a20d9dSVlad Yasevich return err; 115996a20d9dSVlad Yasevich } 116096a20d9dSVlad Yasevich 11615be5a2dfSVlad Yasevich int br_vlan_init(struct net_bridge *br) 11628580e211SToshiaki Makita { 1163907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 11642594e906SNikolay Aleksandrov int ret = -ENOMEM; 11652594e906SNikolay Aleksandrov 1166907b1e6eSNikolay Aleksandrov vg = kzalloc(sizeof(*vg), GFP_KERNEL); 1167907b1e6eSNikolay Aleksandrov if (!vg) 11682594e906SNikolay Aleksandrov goto out; 1169907b1e6eSNikolay Aleksandrov ret = rhashtable_init(&vg->vlan_hash, &br_vlan_rht_params); 11702594e906SNikolay Aleksandrov if (ret) 11712594e906SNikolay Aleksandrov goto err_rhtbl; 1172efa5356bSRoopa Prabhu ret = vlan_tunnel_init(vg); 1173efa5356bSRoopa Prabhu if (ret) 1174efa5356bSRoopa Prabhu goto err_tunnel_init; 1175907b1e6eSNikolay Aleksandrov INIT_LIST_HEAD(&vg->vlan_list); 11768580e211SToshiaki Makita br->vlan_proto = htons(ETH_P_8021Q); 117796a20d9dSVlad Yasevich br->default_pvid = 1; 1178907b1e6eSNikolay Aleksandrov rcu_assign_pointer(br->vlgrp, vg); 11792594e906SNikolay Aleksandrov 11802594e906SNikolay Aleksandrov out: 11812594e906SNikolay Aleksandrov return ret; 11822594e906SNikolay Aleksandrov 1183efa5356bSRoopa Prabhu err_tunnel_init: 1184907b1e6eSNikolay Aleksandrov rhashtable_destroy(&vg->vlan_hash); 11852594e906SNikolay Aleksandrov err_rhtbl: 1186907b1e6eSNikolay Aleksandrov kfree(vg); 11872594e906SNikolay Aleksandrov 11882594e906SNikolay Aleksandrov goto out; 11892594e906SNikolay Aleksandrov } 11902594e906SNikolay Aleksandrov 1191169327d5SPetr Machata int nbp_vlan_init(struct net_bridge_port *p, struct netlink_ext_ack *extack) 11922594e906SNikolay Aleksandrov { 1193404cdbf0SElad Raz struct switchdev_attr attr = { 1194404cdbf0SElad Raz .orig_dev = p->br->dev, 1195404cdbf0SElad Raz .id = SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING, 1196404cdbf0SElad Raz .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP, 1197ae75767eSNikolay Aleksandrov .u.vlan_filtering = br_opt_get(p->br, BROPT_VLAN_ENABLED), 1198404cdbf0SElad Raz }; 1199263344e6SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 12002594e906SNikolay Aleksandrov int ret = -ENOMEM; 12012594e906SNikolay Aleksandrov 1202263344e6SNikolay Aleksandrov vg = kzalloc(sizeof(struct net_bridge_vlan_group), GFP_KERNEL); 1203263344e6SNikolay Aleksandrov if (!vg) 12042594e906SNikolay Aleksandrov goto out; 12052594e906SNikolay Aleksandrov 1206dcbdf135SVladimir Oltean ret = switchdev_port_attr_set(p->dev, &attr, extack); 1207404cdbf0SElad Raz if (ret && ret != -EOPNOTSUPP) 1208404cdbf0SElad Raz goto err_vlan_enabled; 1209404cdbf0SElad Raz 1210263344e6SNikolay Aleksandrov ret = rhashtable_init(&vg->vlan_hash, &br_vlan_rht_params); 12112594e906SNikolay Aleksandrov if (ret) 12122594e906SNikolay Aleksandrov goto err_rhtbl; 1213efa5356bSRoopa Prabhu ret = vlan_tunnel_init(vg); 1214efa5356bSRoopa Prabhu if (ret) 1215efa5356bSRoopa Prabhu goto err_tunnel_init; 1216263344e6SNikolay Aleksandrov INIT_LIST_HEAD(&vg->vlan_list); 1217907b1e6eSNikolay Aleksandrov rcu_assign_pointer(p->vlgrp, vg); 12182594e906SNikolay Aleksandrov if (p->br->default_pvid) { 1219f418af63SNikolay Aleksandrov bool changed; 1220f418af63SNikolay Aleksandrov 12212594e906SNikolay Aleksandrov ret = nbp_vlan_add(p, p->br->default_pvid, 12222594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_PVID | 1223f418af63SNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED, 1224169327d5SPetr Machata &changed, extack); 12252594e906SNikolay Aleksandrov if (ret) 12262594e906SNikolay Aleksandrov goto err_vlan_add; 1227f545923bSNikolay Aleksandrov br_vlan_notify(p->br, p, p->br->default_pvid, 0, RTM_NEWVLAN); 12282594e906SNikolay Aleksandrov } 12292594e906SNikolay Aleksandrov out: 12302594e906SNikolay Aleksandrov return ret; 12312594e906SNikolay Aleksandrov 12322594e906SNikolay Aleksandrov err_vlan_add: 123307bc588fSIdo Schimmel RCU_INIT_POINTER(p->vlgrp, NULL); 123407bc588fSIdo Schimmel synchronize_rcu(); 1235efa5356bSRoopa Prabhu vlan_tunnel_deinit(vg); 1236efa5356bSRoopa Prabhu err_tunnel_init: 1237efa5356bSRoopa Prabhu rhashtable_destroy(&vg->vlan_hash); 12382594e906SNikolay Aleksandrov err_rhtbl: 1239df2c4334SYotam Gigi err_vlan_enabled: 1240263344e6SNikolay Aleksandrov kfree(vg); 12412594e906SNikolay Aleksandrov 12422594e906SNikolay Aleksandrov goto out; 12438580e211SToshiaki Makita } 12448580e211SToshiaki Makita 12458adff41cSToshiaki Makita /* Must be protected by RTNL. 12468adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 1247f418af63SNikolay Aleksandrov * changed must be true only if the vlan was created or updated 12488adff41cSToshiaki Makita */ 1249f418af63SNikolay Aleksandrov int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags, 1250169327d5SPetr Machata bool *changed, struct netlink_ext_ack *extack) 1251243a2e63SVlad Yasevich { 12522594e906SNikolay Aleksandrov struct net_bridge_vlan *vlan; 12532594e906SNikolay Aleksandrov int ret; 1254243a2e63SVlad Yasevich 1255243a2e63SVlad Yasevich ASSERT_RTNL(); 1256243a2e63SVlad Yasevich 1257f418af63SNikolay Aleksandrov *changed = false; 1258907b1e6eSNikolay Aleksandrov vlan = br_vlan_find(nbp_vlan_group(port), vid); 12592594e906SNikolay Aleksandrov if (vlan) { 12607fbac984SIdo Schimmel /* Pass the flags to the hardware bridge */ 1261169327d5SPetr Machata ret = br_switchdev_port_vlan_add(port->dev, vid, flags, extack); 12627fbac984SIdo Schimmel if (ret && ret != -EOPNOTSUPP) 12637fbac984SIdo Schimmel return ret; 1264f418af63SNikolay Aleksandrov *changed = __vlan_add_flags(vlan, flags); 1265f418af63SNikolay Aleksandrov 12662594e906SNikolay Aleksandrov return 0; 1267243a2e63SVlad Yasevich } 1268243a2e63SVlad Yasevich 12692594e906SNikolay Aleksandrov vlan = kzalloc(sizeof(*vlan), GFP_KERNEL); 12702594e906SNikolay Aleksandrov if (!vlan) 12712594e906SNikolay Aleksandrov return -ENOMEM; 1272243a2e63SVlad Yasevich 12732594e906SNikolay Aleksandrov vlan->vid = vid; 12742594e906SNikolay Aleksandrov vlan->port = port; 1275169327d5SPetr Machata ret = __vlan_add(vlan, flags, extack); 12762594e906SNikolay Aleksandrov if (ret) 12772594e906SNikolay Aleksandrov kfree(vlan); 1278f418af63SNikolay Aleksandrov else 1279f418af63SNikolay Aleksandrov *changed = true; 1280243a2e63SVlad Yasevich 12812594e906SNikolay Aleksandrov return ret; 1282243a2e63SVlad Yasevich } 1283243a2e63SVlad Yasevich 12848adff41cSToshiaki Makita /* Must be protected by RTNL. 12858adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 12868adff41cSToshiaki Makita */ 1287243a2e63SVlad Yasevich int nbp_vlan_delete(struct net_bridge_port *port, u16 vid) 1288243a2e63SVlad Yasevich { 12892594e906SNikolay Aleksandrov struct net_bridge_vlan *v; 1290243a2e63SVlad Yasevich 1291243a2e63SVlad Yasevich ASSERT_RTNL(); 1292243a2e63SVlad Yasevich 1293907b1e6eSNikolay Aleksandrov v = br_vlan_find(nbp_vlan_group(port), vid); 12942594e906SNikolay Aleksandrov if (!v) 12952594e906SNikolay Aleksandrov return -ENOENT; 1296424bb9c9SToshiaki Makita br_fdb_find_delete_local(port->br, port, port->dev->dev_addr, vid); 12971ea2d020SNikolay Aleksandrov br_fdb_delete_by_port(port->br, port, vid, 0); 1298bc9a25d2SVlad Yasevich 12992594e906SNikolay Aleksandrov return __vlan_del(v); 1300243a2e63SVlad Yasevich } 1301243a2e63SVlad Yasevich 1302243a2e63SVlad Yasevich void nbp_vlan_flush(struct net_bridge_port *port) 1303243a2e63SVlad Yasevich { 1304f409d0edSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 1305f409d0edSNikolay Aleksandrov 1306243a2e63SVlad Yasevich ASSERT_RTNL(); 1307243a2e63SVlad Yasevich 1308f409d0edSNikolay Aleksandrov vg = nbp_vlan_group(port); 1309f545923bSNikolay Aleksandrov __vlan_flush(port->br, port, vg); 1310f409d0edSNikolay Aleksandrov RCU_INIT_POINTER(port->vlgrp, NULL); 1311f409d0edSNikolay Aleksandrov synchronize_rcu(); 1312f409d0edSNikolay Aleksandrov __vlan_group_free(vg); 13135be5a2dfSVlad Yasevich } 1314a60c0903SNikolay Aleksandrov 1315a60c0903SNikolay Aleksandrov void br_vlan_get_stats(const struct net_bridge_vlan *v, 1316281cc284SHeiner Kallweit struct pcpu_sw_netstats *stats) 1317a60c0903SNikolay Aleksandrov { 1318a60c0903SNikolay Aleksandrov int i; 1319a60c0903SNikolay Aleksandrov 1320a60c0903SNikolay Aleksandrov memset(stats, 0, sizeof(*stats)); 1321a60c0903SNikolay Aleksandrov for_each_possible_cpu(i) { 1322a60c0903SNikolay Aleksandrov u64 rxpackets, rxbytes, txpackets, txbytes; 1323281cc284SHeiner Kallweit struct pcpu_sw_netstats *cpu_stats; 1324a60c0903SNikolay Aleksandrov unsigned int start; 1325a60c0903SNikolay Aleksandrov 1326a60c0903SNikolay Aleksandrov cpu_stats = per_cpu_ptr(v->stats, i); 1327a60c0903SNikolay Aleksandrov do { 1328a60c0903SNikolay Aleksandrov start = u64_stats_fetch_begin_irq(&cpu_stats->syncp); 1329a60c0903SNikolay Aleksandrov rxpackets = cpu_stats->rx_packets; 1330a60c0903SNikolay Aleksandrov rxbytes = cpu_stats->rx_bytes; 1331a60c0903SNikolay Aleksandrov txbytes = cpu_stats->tx_bytes; 1332a60c0903SNikolay Aleksandrov txpackets = cpu_stats->tx_packets; 1333a60c0903SNikolay Aleksandrov } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start)); 1334a60c0903SNikolay Aleksandrov 1335a60c0903SNikolay Aleksandrov stats->rx_packets += rxpackets; 1336a60c0903SNikolay Aleksandrov stats->rx_bytes += rxbytes; 1337a60c0903SNikolay Aleksandrov stats->tx_bytes += txbytes; 1338a60c0903SNikolay Aleksandrov stats->tx_packets += txpackets; 1339a60c0903SNikolay Aleksandrov } 1340a60c0903SNikolay Aleksandrov } 13414d4fd361SPetr Machata 134299f62a74SVladimir Oltean int br_vlan_get_pvid(const struct net_device *dev, u16 *p_pvid) 13434d4fd361SPetr Machata { 13444d4fd361SPetr Machata struct net_bridge_vlan_group *vg; 134599f62a74SVladimir Oltean struct net_bridge_port *p; 13464d4fd361SPetr Machata 134799f62a74SVladimir Oltean ASSERT_RTNL(); 134899f62a74SVladimir Oltean p = br_port_get_check_rtnl(dev); 13495a6db04cSIdo Schimmel if (p) 13505a6db04cSIdo Schimmel vg = nbp_vlan_group(p); 13515a6db04cSIdo Schimmel else if (netif_is_bridge_master(dev)) 13524d4fd361SPetr Machata vg = br_vlan_group(netdev_priv(dev)); 13534d4fd361SPetr Machata else 13544d4fd361SPetr Machata return -EINVAL; 13554d4fd361SPetr Machata 13564d4fd361SPetr Machata *p_pvid = br_get_pvid(vg); 13574d4fd361SPetr Machata return 0; 13584d4fd361SPetr Machata } 13594d4fd361SPetr Machata EXPORT_SYMBOL_GPL(br_vlan_get_pvid); 13604d4fd361SPetr Machata 13617582f5b7SPablo Neira Ayuso int br_vlan_get_pvid_rcu(const struct net_device *dev, u16 *p_pvid) 13627582f5b7SPablo Neira Ayuso { 136399f62a74SVladimir Oltean struct net_bridge_vlan_group *vg; 136499f62a74SVladimir Oltean struct net_bridge_port *p; 136599f62a74SVladimir Oltean 136699f62a74SVladimir Oltean p = br_port_get_check_rcu(dev); 136799f62a74SVladimir Oltean if (p) 136899f62a74SVladimir Oltean vg = nbp_vlan_group_rcu(p); 136999f62a74SVladimir Oltean else if (netif_is_bridge_master(dev)) 137099f62a74SVladimir Oltean vg = br_vlan_group_rcu(netdev_priv(dev)); 137199f62a74SVladimir Oltean else 137299f62a74SVladimir Oltean return -EINVAL; 137399f62a74SVladimir Oltean 137499f62a74SVladimir Oltean *p_pvid = br_get_pvid(vg); 137599f62a74SVladimir Oltean return 0; 13767582f5b7SPablo Neira Ayuso } 13777582f5b7SPablo Neira Ayuso EXPORT_SYMBOL_GPL(br_vlan_get_pvid_rcu); 13787582f5b7SPablo Neira Ayuso 1379bcf2766bSFelix Fietkau void br_vlan_fill_forward_path_pvid(struct net_bridge *br, 1380bcf2766bSFelix Fietkau struct net_device_path_ctx *ctx, 1381bcf2766bSFelix Fietkau struct net_device_path *path) 1382bcf2766bSFelix Fietkau { 1383bcf2766bSFelix Fietkau struct net_bridge_vlan_group *vg; 1384bcf2766bSFelix Fietkau int idx = ctx->num_vlans - 1; 1385bcf2766bSFelix Fietkau u16 vid; 1386bcf2766bSFelix Fietkau 1387bcf2766bSFelix Fietkau path->bridge.vlan_mode = DEV_PATH_BR_VLAN_KEEP; 1388bcf2766bSFelix Fietkau 1389bcf2766bSFelix Fietkau if (!br_opt_get(br, BROPT_VLAN_ENABLED)) 1390bcf2766bSFelix Fietkau return; 1391bcf2766bSFelix Fietkau 1392bcf2766bSFelix Fietkau vg = br_vlan_group(br); 1393bcf2766bSFelix Fietkau 1394bcf2766bSFelix Fietkau if (idx >= 0 && 1395bcf2766bSFelix Fietkau ctx->vlan[idx].proto == br->vlan_proto) { 1396bcf2766bSFelix Fietkau vid = ctx->vlan[idx].id; 1397bcf2766bSFelix Fietkau } else { 1398bcf2766bSFelix Fietkau path->bridge.vlan_mode = DEV_PATH_BR_VLAN_TAG; 1399bcf2766bSFelix Fietkau vid = br_get_pvid(vg); 1400bcf2766bSFelix Fietkau } 1401bcf2766bSFelix Fietkau 1402bcf2766bSFelix Fietkau path->bridge.vlan_id = vid; 1403bcf2766bSFelix Fietkau path->bridge.vlan_proto = br->vlan_proto; 1404bcf2766bSFelix Fietkau } 1405bcf2766bSFelix Fietkau 1406bcf2766bSFelix Fietkau int br_vlan_fill_forward_path_mode(struct net_bridge *br, 1407bcf2766bSFelix Fietkau struct net_bridge_port *dst, 1408bcf2766bSFelix Fietkau struct net_device_path *path) 1409bcf2766bSFelix Fietkau { 1410bcf2766bSFelix Fietkau struct net_bridge_vlan_group *vg; 1411bcf2766bSFelix Fietkau struct net_bridge_vlan *v; 1412bcf2766bSFelix Fietkau 1413bcf2766bSFelix Fietkau if (!br_opt_get(br, BROPT_VLAN_ENABLED)) 1414bcf2766bSFelix Fietkau return 0; 1415bcf2766bSFelix Fietkau 1416bcf2766bSFelix Fietkau vg = nbp_vlan_group_rcu(dst); 1417bcf2766bSFelix Fietkau v = br_vlan_find(vg, path->bridge.vlan_id); 1418bcf2766bSFelix Fietkau if (!v || !br_vlan_should_use(v)) 1419bcf2766bSFelix Fietkau return -EINVAL; 1420bcf2766bSFelix Fietkau 1421bcf2766bSFelix Fietkau if (!(v->flags & BRIDGE_VLAN_INFO_UNTAGGED)) 1422bcf2766bSFelix Fietkau return 0; 1423bcf2766bSFelix Fietkau 1424bcf2766bSFelix Fietkau if (path->bridge.vlan_mode == DEV_PATH_BR_VLAN_TAG) 1425bcf2766bSFelix Fietkau path->bridge.vlan_mode = DEV_PATH_BR_VLAN_KEEP; 142626267bf9SFelix Fietkau else if (v->priv_flags & BR_VLFLAG_ADDED_BY_SWITCHDEV) 142726267bf9SFelix Fietkau path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG_HW; 1428bcf2766bSFelix Fietkau else 1429bcf2766bSFelix Fietkau path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG; 1430bcf2766bSFelix Fietkau 1431bcf2766bSFelix Fietkau return 0; 1432bcf2766bSFelix Fietkau } 1433bcf2766bSFelix Fietkau 14344d4fd361SPetr Machata int br_vlan_get_info(const struct net_device *dev, u16 vid, 14354d4fd361SPetr Machata struct bridge_vlan_info *p_vinfo) 14364d4fd361SPetr Machata { 14374d4fd361SPetr Machata struct net_bridge_vlan_group *vg; 14384d4fd361SPetr Machata struct net_bridge_vlan *v; 14394d4fd361SPetr Machata struct net_bridge_port *p; 14404d4fd361SPetr Machata 14414d4fd361SPetr Machata ASSERT_RTNL(); 14424d4fd361SPetr Machata p = br_port_get_check_rtnl(dev); 14434d4fd361SPetr Machata if (p) 14444d4fd361SPetr Machata vg = nbp_vlan_group(p); 14452b18d79eSPetr Machata else if (netif_is_bridge_master(dev)) 14462b18d79eSPetr Machata vg = br_vlan_group(netdev_priv(dev)); 14474d4fd361SPetr Machata else 14484d4fd361SPetr Machata return -EINVAL; 14494d4fd361SPetr Machata 14504d4fd361SPetr Machata v = br_vlan_find(vg, vid); 14514d4fd361SPetr Machata if (!v) 14524d4fd361SPetr Machata return -ENOENT; 14534d4fd361SPetr Machata 14544d4fd361SPetr Machata p_vinfo->vid = vid; 14554d4fd361SPetr Machata p_vinfo->flags = v->flags; 1456f40d9b20SVladimir Oltean if (vid == br_get_pvid(vg)) 1457f40d9b20SVladimir Oltean p_vinfo->flags |= BRIDGE_VLAN_INFO_PVID; 14584d4fd361SPetr Machata return 0; 14594d4fd361SPetr Machata } 14604d4fd361SPetr Machata EXPORT_SYMBOL_GPL(br_vlan_get_info); 14619c0ec2e7SMike Manning 1462ee80dd2eSVladimir Oltean int br_vlan_get_info_rcu(const struct net_device *dev, u16 vid, 1463ee80dd2eSVladimir Oltean struct bridge_vlan_info *p_vinfo) 1464ee80dd2eSVladimir Oltean { 1465ee80dd2eSVladimir Oltean struct net_bridge_vlan_group *vg; 1466ee80dd2eSVladimir Oltean struct net_bridge_vlan *v; 1467ee80dd2eSVladimir Oltean struct net_bridge_port *p; 1468ee80dd2eSVladimir Oltean 1469ee80dd2eSVladimir Oltean p = br_port_get_check_rcu(dev); 1470ee80dd2eSVladimir Oltean if (p) 1471ee80dd2eSVladimir Oltean vg = nbp_vlan_group_rcu(p); 1472ee80dd2eSVladimir Oltean else if (netif_is_bridge_master(dev)) 1473ee80dd2eSVladimir Oltean vg = br_vlan_group_rcu(netdev_priv(dev)); 1474ee80dd2eSVladimir Oltean else 1475ee80dd2eSVladimir Oltean return -EINVAL; 1476ee80dd2eSVladimir Oltean 1477ee80dd2eSVladimir Oltean v = br_vlan_find(vg, vid); 1478ee80dd2eSVladimir Oltean if (!v) 1479ee80dd2eSVladimir Oltean return -ENOENT; 1480ee80dd2eSVladimir Oltean 1481ee80dd2eSVladimir Oltean p_vinfo->vid = vid; 1482ee80dd2eSVladimir Oltean p_vinfo->flags = v->flags; 1483ee80dd2eSVladimir Oltean if (vid == br_get_pvid(vg)) 1484ee80dd2eSVladimir Oltean p_vinfo->flags |= BRIDGE_VLAN_INFO_PVID; 1485ee80dd2eSVladimir Oltean return 0; 1486ee80dd2eSVladimir Oltean } 1487ee80dd2eSVladimir Oltean EXPORT_SYMBOL_GPL(br_vlan_get_info_rcu); 1488ee80dd2eSVladimir Oltean 14899c0ec2e7SMike Manning static int br_vlan_is_bind_vlan_dev(const struct net_device *dev) 14909c0ec2e7SMike Manning { 14919c0ec2e7SMike Manning return is_vlan_dev(dev) && 14929c0ec2e7SMike Manning !!(vlan_dev_priv(dev)->flags & VLAN_FLAG_BRIDGE_BINDING); 14939c0ec2e7SMike Manning } 14949c0ec2e7SMike Manning 14959c0ec2e7SMike Manning static int br_vlan_is_bind_vlan_dev_fn(struct net_device *dev, 1496eff74233STaehee Yoo __always_unused struct netdev_nested_priv *priv) 14979c0ec2e7SMike Manning { 14989c0ec2e7SMike Manning return br_vlan_is_bind_vlan_dev(dev); 14999c0ec2e7SMike Manning } 15009c0ec2e7SMike Manning 15019c0ec2e7SMike Manning static bool br_vlan_has_upper_bind_vlan_dev(struct net_device *dev) 15029c0ec2e7SMike Manning { 15039c0ec2e7SMike Manning int found; 15049c0ec2e7SMike Manning 15059c0ec2e7SMike Manning rcu_read_lock(); 15069c0ec2e7SMike Manning found = netdev_walk_all_upper_dev_rcu(dev, br_vlan_is_bind_vlan_dev_fn, 15079c0ec2e7SMike Manning NULL); 15089c0ec2e7SMike Manning rcu_read_unlock(); 15099c0ec2e7SMike Manning 15109c0ec2e7SMike Manning return !!found; 15119c0ec2e7SMike Manning } 15129c0ec2e7SMike Manning 15139c0ec2e7SMike Manning struct br_vlan_bind_walk_data { 15149c0ec2e7SMike Manning u16 vid; 15159c0ec2e7SMike Manning struct net_device *result; 15169c0ec2e7SMike Manning }; 15179c0ec2e7SMike Manning 15189c0ec2e7SMike Manning static int br_vlan_match_bind_vlan_dev_fn(struct net_device *dev, 1519eff74233STaehee Yoo struct netdev_nested_priv *priv) 15209c0ec2e7SMike Manning { 1521eff74233STaehee Yoo struct br_vlan_bind_walk_data *data = priv->data; 15229c0ec2e7SMike Manning int found = 0; 15239c0ec2e7SMike Manning 15249c0ec2e7SMike Manning if (br_vlan_is_bind_vlan_dev(dev) && 15259c0ec2e7SMike Manning vlan_dev_priv(dev)->vlan_id == data->vid) { 15269c0ec2e7SMike Manning data->result = dev; 15279c0ec2e7SMike Manning found = 1; 15289c0ec2e7SMike Manning } 15299c0ec2e7SMike Manning 15309c0ec2e7SMike Manning return found; 15319c0ec2e7SMike Manning } 15329c0ec2e7SMike Manning 15339c0ec2e7SMike Manning static struct net_device * 15349c0ec2e7SMike Manning br_vlan_get_upper_bind_vlan_dev(struct net_device *dev, u16 vid) 15359c0ec2e7SMike Manning { 15369c0ec2e7SMike Manning struct br_vlan_bind_walk_data data = { 15379c0ec2e7SMike Manning .vid = vid, 15389c0ec2e7SMike Manning }; 1539eff74233STaehee Yoo struct netdev_nested_priv priv = { 1540eff74233STaehee Yoo .data = (void *)&data, 1541eff74233STaehee Yoo }; 15429c0ec2e7SMike Manning 15439c0ec2e7SMike Manning rcu_read_lock(); 15449c0ec2e7SMike Manning netdev_walk_all_upper_dev_rcu(dev, br_vlan_match_bind_vlan_dev_fn, 1545eff74233STaehee Yoo &priv); 15469c0ec2e7SMike Manning rcu_read_unlock(); 15479c0ec2e7SMike Manning 15489c0ec2e7SMike Manning return data.result; 15499c0ec2e7SMike Manning } 15509c0ec2e7SMike Manning 15519c0ec2e7SMike Manning static bool br_vlan_is_dev_up(const struct net_device *dev) 15529c0ec2e7SMike Manning { 15539c0ec2e7SMike Manning return !!(dev->flags & IFF_UP) && netif_oper_up(dev); 15549c0ec2e7SMike Manning } 15559c0ec2e7SMike Manning 15569c0ec2e7SMike Manning static void br_vlan_set_vlan_dev_state(const struct net_bridge *br, 15579c0ec2e7SMike Manning struct net_device *vlan_dev) 15589c0ec2e7SMike Manning { 15599c0ec2e7SMike Manning u16 vid = vlan_dev_priv(vlan_dev)->vlan_id; 15609c0ec2e7SMike Manning struct net_bridge_vlan_group *vg; 15619c0ec2e7SMike Manning struct net_bridge_port *p; 15629c0ec2e7SMike Manning bool has_carrier = false; 15639c0ec2e7SMike Manning 15648e1acd4fSMike Manning if (!netif_carrier_ok(br->dev)) { 15658e1acd4fSMike Manning netif_carrier_off(vlan_dev); 15668e1acd4fSMike Manning return; 15678e1acd4fSMike Manning } 15688e1acd4fSMike Manning 15699c0ec2e7SMike Manning list_for_each_entry(p, &br->port_list, list) { 15709c0ec2e7SMike Manning vg = nbp_vlan_group(p); 15719c0ec2e7SMike Manning if (br_vlan_find(vg, vid) && br_vlan_is_dev_up(p->dev)) { 15729c0ec2e7SMike Manning has_carrier = true; 15739c0ec2e7SMike Manning break; 15749c0ec2e7SMike Manning } 15759c0ec2e7SMike Manning } 15769c0ec2e7SMike Manning 15779c0ec2e7SMike Manning if (has_carrier) 15789c0ec2e7SMike Manning netif_carrier_on(vlan_dev); 15799c0ec2e7SMike Manning else 15809c0ec2e7SMike Manning netif_carrier_off(vlan_dev); 15819c0ec2e7SMike Manning } 15829c0ec2e7SMike Manning 15839c0ec2e7SMike Manning static void br_vlan_set_all_vlan_dev_state(struct net_bridge_port *p) 15849c0ec2e7SMike Manning { 15859c0ec2e7SMike Manning struct net_bridge_vlan_group *vg = nbp_vlan_group(p); 15869c0ec2e7SMike Manning struct net_bridge_vlan *vlan; 15879c0ec2e7SMike Manning struct net_device *vlan_dev; 15889c0ec2e7SMike Manning 15899c0ec2e7SMike Manning list_for_each_entry(vlan, &vg->vlan_list, vlist) { 15909c0ec2e7SMike Manning vlan_dev = br_vlan_get_upper_bind_vlan_dev(p->br->dev, 15919c0ec2e7SMike Manning vlan->vid); 15929c0ec2e7SMike Manning if (vlan_dev) { 15938e1acd4fSMike Manning if (br_vlan_is_dev_up(p->dev)) { 15948e1acd4fSMike Manning if (netif_carrier_ok(p->br->dev)) 15959c0ec2e7SMike Manning netif_carrier_on(vlan_dev); 15968e1acd4fSMike Manning } else { 15979c0ec2e7SMike Manning br_vlan_set_vlan_dev_state(p->br, vlan_dev); 15989c0ec2e7SMike Manning } 15999c0ec2e7SMike Manning } 16009c0ec2e7SMike Manning } 16018e1acd4fSMike Manning } 16029c0ec2e7SMike Manning 16039c0ec2e7SMike Manning static void br_vlan_upper_change(struct net_device *dev, 16049c0ec2e7SMike Manning struct net_device *upper_dev, 16059c0ec2e7SMike Manning bool linking) 16069c0ec2e7SMike Manning { 16079c0ec2e7SMike Manning struct net_bridge *br = netdev_priv(dev); 16089c0ec2e7SMike Manning 16099c0ec2e7SMike Manning if (!br_vlan_is_bind_vlan_dev(upper_dev)) 16109c0ec2e7SMike Manning return; 16119c0ec2e7SMike Manning 16129c0ec2e7SMike Manning if (linking) { 16139c0ec2e7SMike Manning br_vlan_set_vlan_dev_state(br, upper_dev); 16149c0ec2e7SMike Manning br_opt_toggle(br, BROPT_VLAN_BRIDGE_BINDING, true); 16159c0ec2e7SMike Manning } else { 16169c0ec2e7SMike Manning br_opt_toggle(br, BROPT_VLAN_BRIDGE_BINDING, 16179c0ec2e7SMike Manning br_vlan_has_upper_bind_vlan_dev(dev)); 16189c0ec2e7SMike Manning } 16199c0ec2e7SMike Manning } 16209c0ec2e7SMike Manning 16218e1acd4fSMike Manning struct br_vlan_link_state_walk_data { 16228e1acd4fSMike Manning struct net_bridge *br; 16238e1acd4fSMike Manning }; 16248e1acd4fSMike Manning 16258e1acd4fSMike Manning static int br_vlan_link_state_change_fn(struct net_device *vlan_dev, 1626eff74233STaehee Yoo struct netdev_nested_priv *priv) 16278e1acd4fSMike Manning { 1628eff74233STaehee Yoo struct br_vlan_link_state_walk_data *data = priv->data; 16298e1acd4fSMike Manning 16308e1acd4fSMike Manning if (br_vlan_is_bind_vlan_dev(vlan_dev)) 16318e1acd4fSMike Manning br_vlan_set_vlan_dev_state(data->br, vlan_dev); 16328e1acd4fSMike Manning 16338e1acd4fSMike Manning return 0; 16348e1acd4fSMike Manning } 16358e1acd4fSMike Manning 16368e1acd4fSMike Manning static void br_vlan_link_state_change(struct net_device *dev, 16378e1acd4fSMike Manning struct net_bridge *br) 16388e1acd4fSMike Manning { 16398e1acd4fSMike Manning struct br_vlan_link_state_walk_data data = { 16408e1acd4fSMike Manning .br = br 16418e1acd4fSMike Manning }; 1642eff74233STaehee Yoo struct netdev_nested_priv priv = { 1643eff74233STaehee Yoo .data = (void *)&data, 1644eff74233STaehee Yoo }; 16458e1acd4fSMike Manning 16468e1acd4fSMike Manning rcu_read_lock(); 16478e1acd4fSMike Manning netdev_walk_all_upper_dev_rcu(dev, br_vlan_link_state_change_fn, 1648eff74233STaehee Yoo &priv); 16498e1acd4fSMike Manning rcu_read_unlock(); 16508e1acd4fSMike Manning } 16518e1acd4fSMike Manning 16529c0ec2e7SMike Manning /* Must be protected by RTNL. */ 165380900acdSMike Manning static void nbp_vlan_set_vlan_dev_state(struct net_bridge_port *p, u16 vid) 165480900acdSMike Manning { 165580900acdSMike Manning struct net_device *vlan_dev; 165680900acdSMike Manning 165780900acdSMike Manning if (!br_opt_get(p->br, BROPT_VLAN_BRIDGE_BINDING)) 165880900acdSMike Manning return; 165980900acdSMike Manning 166080900acdSMike Manning vlan_dev = br_vlan_get_upper_bind_vlan_dev(p->br->dev, vid); 166180900acdSMike Manning if (vlan_dev) 166280900acdSMike Manning br_vlan_set_vlan_dev_state(p->br, vlan_dev); 166380900acdSMike Manning } 166480900acdSMike Manning 166580900acdSMike Manning /* Must be protected by RTNL. */ 1666091adf9bSNikolay Aleksandrov int br_vlan_bridge_event(struct net_device *dev, unsigned long event, void *ptr) 16679c0ec2e7SMike Manning { 16689c0ec2e7SMike Manning struct netdev_notifier_changeupper_info *info; 1669091adf9bSNikolay Aleksandrov struct net_bridge *br = netdev_priv(dev); 1670f545923bSNikolay Aleksandrov int vlcmd = 0, ret = 0; 1671f545923bSNikolay Aleksandrov bool changed = false; 16729c0ec2e7SMike Manning 16739c0ec2e7SMike Manning switch (event) { 1674091adf9bSNikolay Aleksandrov case NETDEV_REGISTER: 1675091adf9bSNikolay Aleksandrov ret = br_vlan_add(br, br->default_pvid, 1676091adf9bSNikolay Aleksandrov BRIDGE_VLAN_INFO_PVID | 1677091adf9bSNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED | 1678091adf9bSNikolay Aleksandrov BRIDGE_VLAN_INFO_BRENTRY, &changed, NULL); 1679f545923bSNikolay Aleksandrov vlcmd = RTM_NEWVLAN; 1680091adf9bSNikolay Aleksandrov break; 1681091adf9bSNikolay Aleksandrov case NETDEV_UNREGISTER: 1682f545923bSNikolay Aleksandrov changed = !br_vlan_delete(br, br->default_pvid); 1683f545923bSNikolay Aleksandrov vlcmd = RTM_DELVLAN; 1684091adf9bSNikolay Aleksandrov break; 16859c0ec2e7SMike Manning case NETDEV_CHANGEUPPER: 16869c0ec2e7SMike Manning info = ptr; 16879c0ec2e7SMike Manning br_vlan_upper_change(dev, info->upper_dev, info->linking); 16889c0ec2e7SMike Manning break; 16898e1acd4fSMike Manning 16908e1acd4fSMike Manning case NETDEV_CHANGE: 16918e1acd4fSMike Manning case NETDEV_UP: 16928e1acd4fSMike Manning if (!br_opt_get(br, BROPT_VLAN_BRIDGE_BINDING)) 1693091adf9bSNikolay Aleksandrov break; 16948e1acd4fSMike Manning br_vlan_link_state_change(dev, br); 16958e1acd4fSMike Manning break; 16969c0ec2e7SMike Manning } 1697f545923bSNikolay Aleksandrov if (changed) 1698f545923bSNikolay Aleksandrov br_vlan_notify(br, NULL, br->default_pvid, 0, vlcmd); 1699091adf9bSNikolay Aleksandrov 1700091adf9bSNikolay Aleksandrov return ret; 17019c0ec2e7SMike Manning } 17029c0ec2e7SMike Manning 17039c0ec2e7SMike Manning /* Must be protected by RTNL. */ 17049c0ec2e7SMike Manning void br_vlan_port_event(struct net_bridge_port *p, unsigned long event) 17059c0ec2e7SMike Manning { 17069c0ec2e7SMike Manning if (!br_opt_get(p->br, BROPT_VLAN_BRIDGE_BINDING)) 17079c0ec2e7SMike Manning return; 17089c0ec2e7SMike Manning 17099c0ec2e7SMike Manning switch (event) { 17109c0ec2e7SMike Manning case NETDEV_CHANGE: 17119c0ec2e7SMike Manning case NETDEV_DOWN: 17129c0ec2e7SMike Manning case NETDEV_UP: 17139c0ec2e7SMike Manning br_vlan_set_all_vlan_dev_state(p); 17149c0ec2e7SMike Manning break; 17159c0ec2e7SMike Manning } 17169c0ec2e7SMike Manning } 17178dcea187SNikolay Aleksandrov 171856d09976SNikolay Aleksandrov static bool br_vlan_stats_fill(struct sk_buff *skb, 171956d09976SNikolay Aleksandrov const struct net_bridge_vlan *v) 172056d09976SNikolay Aleksandrov { 1721281cc284SHeiner Kallweit struct pcpu_sw_netstats stats; 172256d09976SNikolay Aleksandrov struct nlattr *nest; 172356d09976SNikolay Aleksandrov 172456d09976SNikolay Aleksandrov nest = nla_nest_start(skb, BRIDGE_VLANDB_ENTRY_STATS); 172556d09976SNikolay Aleksandrov if (!nest) 172656d09976SNikolay Aleksandrov return false; 172756d09976SNikolay Aleksandrov 172856d09976SNikolay Aleksandrov br_vlan_get_stats(v, &stats); 172956d09976SNikolay Aleksandrov if (nla_put_u64_64bit(skb, BRIDGE_VLANDB_STATS_RX_BYTES, stats.rx_bytes, 173056d09976SNikolay Aleksandrov BRIDGE_VLANDB_STATS_PAD) || 173156d09976SNikolay Aleksandrov nla_put_u64_64bit(skb, BRIDGE_VLANDB_STATS_RX_PACKETS, 173256d09976SNikolay Aleksandrov stats.rx_packets, BRIDGE_VLANDB_STATS_PAD) || 173356d09976SNikolay Aleksandrov nla_put_u64_64bit(skb, BRIDGE_VLANDB_STATS_TX_BYTES, stats.tx_bytes, 173456d09976SNikolay Aleksandrov BRIDGE_VLANDB_STATS_PAD) || 173556d09976SNikolay Aleksandrov nla_put_u64_64bit(skb, BRIDGE_VLANDB_STATS_TX_PACKETS, 173656d09976SNikolay Aleksandrov stats.tx_packets, BRIDGE_VLANDB_STATS_PAD)) 173756d09976SNikolay Aleksandrov goto out_err; 173856d09976SNikolay Aleksandrov 173956d09976SNikolay Aleksandrov nla_nest_end(skb, nest); 174056d09976SNikolay Aleksandrov 174156d09976SNikolay Aleksandrov return true; 174256d09976SNikolay Aleksandrov 174356d09976SNikolay Aleksandrov out_err: 174456d09976SNikolay Aleksandrov nla_nest_cancel(skb, nest); 174556d09976SNikolay Aleksandrov return false; 174656d09976SNikolay Aleksandrov } 174756d09976SNikolay Aleksandrov 17487a53e718SNikolay Aleksandrov /* v_opts is used to dump the options which must be equal in the whole range */ 17490ab55879SNikolay Aleksandrov static bool br_vlan_fill_vids(struct sk_buff *skb, u16 vid, u16 vid_range, 17507a53e718SNikolay Aleksandrov const struct net_bridge_vlan *v_opts, 175156d09976SNikolay Aleksandrov u16 flags, 175256d09976SNikolay Aleksandrov bool dump_stats) 17538dcea187SNikolay Aleksandrov { 17548dcea187SNikolay Aleksandrov struct bridge_vlan_info info; 17558dcea187SNikolay Aleksandrov struct nlattr *nest; 17568dcea187SNikolay Aleksandrov 17578dcea187SNikolay Aleksandrov nest = nla_nest_start(skb, BRIDGE_VLANDB_ENTRY); 17588dcea187SNikolay Aleksandrov if (!nest) 17598dcea187SNikolay Aleksandrov return false; 17608dcea187SNikolay Aleksandrov 17618dcea187SNikolay Aleksandrov memset(&info, 0, sizeof(info)); 17628dcea187SNikolay Aleksandrov info.vid = vid; 17638dcea187SNikolay Aleksandrov if (flags & BRIDGE_VLAN_INFO_UNTAGGED) 17648dcea187SNikolay Aleksandrov info.flags |= BRIDGE_VLAN_INFO_UNTAGGED; 17658dcea187SNikolay Aleksandrov if (flags & BRIDGE_VLAN_INFO_PVID) 17668dcea187SNikolay Aleksandrov info.flags |= BRIDGE_VLAN_INFO_PVID; 17678dcea187SNikolay Aleksandrov 17688dcea187SNikolay Aleksandrov if (nla_put(skb, BRIDGE_VLANDB_ENTRY_INFO, sizeof(info), &info)) 17698dcea187SNikolay Aleksandrov goto out_err; 17708dcea187SNikolay Aleksandrov 17710ab55879SNikolay Aleksandrov if (vid_range && vid < vid_range && 17720ab55879SNikolay Aleksandrov !(flags & BRIDGE_VLAN_INFO_PVID) && 17730ab55879SNikolay Aleksandrov nla_put_u16(skb, BRIDGE_VLANDB_ENTRY_RANGE, vid_range)) 17740ab55879SNikolay Aleksandrov goto out_err; 17750ab55879SNikolay Aleksandrov 177656d09976SNikolay Aleksandrov if (v_opts) { 177756d09976SNikolay Aleksandrov if (!br_vlan_opts_fill(skb, v_opts)) 17787a53e718SNikolay Aleksandrov goto out_err; 17797a53e718SNikolay Aleksandrov 178056d09976SNikolay Aleksandrov if (dump_stats && !br_vlan_stats_fill(skb, v_opts)) 178156d09976SNikolay Aleksandrov goto out_err; 178256d09976SNikolay Aleksandrov } 178356d09976SNikolay Aleksandrov 17848dcea187SNikolay Aleksandrov nla_nest_end(skb, nest); 17858dcea187SNikolay Aleksandrov 17868dcea187SNikolay Aleksandrov return true; 17878dcea187SNikolay Aleksandrov 17888dcea187SNikolay Aleksandrov out_err: 17898dcea187SNikolay Aleksandrov nla_nest_cancel(skb, nest); 17908dcea187SNikolay Aleksandrov return false; 17918dcea187SNikolay Aleksandrov } 17928dcea187SNikolay Aleksandrov 1793cf5bddb9SNikolay Aleksandrov static size_t rtnl_vlan_nlmsg_size(void) 1794cf5bddb9SNikolay Aleksandrov { 1795cf5bddb9SNikolay Aleksandrov return NLMSG_ALIGN(sizeof(struct br_vlan_msg)) 1796cf5bddb9SNikolay Aleksandrov + nla_total_size(0) /* BRIDGE_VLANDB_ENTRY */ 1797cf5bddb9SNikolay Aleksandrov + nla_total_size(sizeof(u16)) /* BRIDGE_VLANDB_ENTRY_RANGE */ 17987a53e718SNikolay Aleksandrov + nla_total_size(sizeof(struct bridge_vlan_info)) /* BRIDGE_VLANDB_ENTRY_INFO */ 17997a53e718SNikolay Aleksandrov + br_vlan_opts_nl_size(); /* bridge vlan options */ 1800cf5bddb9SNikolay Aleksandrov } 1801cf5bddb9SNikolay Aleksandrov 1802cf5bddb9SNikolay Aleksandrov void br_vlan_notify(const struct net_bridge *br, 1803cf5bddb9SNikolay Aleksandrov const struct net_bridge_port *p, 1804cf5bddb9SNikolay Aleksandrov u16 vid, u16 vid_range, 1805cf5bddb9SNikolay Aleksandrov int cmd) 1806cf5bddb9SNikolay Aleksandrov { 1807cf5bddb9SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 18087a53e718SNikolay Aleksandrov struct net_bridge_vlan *v = NULL; 1809cf5bddb9SNikolay Aleksandrov struct br_vlan_msg *bvm; 1810cf5bddb9SNikolay Aleksandrov struct nlmsghdr *nlh; 1811cf5bddb9SNikolay Aleksandrov struct sk_buff *skb; 1812cf5bddb9SNikolay Aleksandrov int err = -ENOBUFS; 1813cf5bddb9SNikolay Aleksandrov struct net *net; 1814cf5bddb9SNikolay Aleksandrov u16 flags = 0; 1815cf5bddb9SNikolay Aleksandrov int ifindex; 1816cf5bddb9SNikolay Aleksandrov 1817cf5bddb9SNikolay Aleksandrov /* right now notifications are done only with rtnl held */ 1818cf5bddb9SNikolay Aleksandrov ASSERT_RTNL(); 1819cf5bddb9SNikolay Aleksandrov 1820cf5bddb9SNikolay Aleksandrov if (p) { 1821cf5bddb9SNikolay Aleksandrov ifindex = p->dev->ifindex; 1822cf5bddb9SNikolay Aleksandrov vg = nbp_vlan_group(p); 1823cf5bddb9SNikolay Aleksandrov net = dev_net(p->dev); 1824cf5bddb9SNikolay Aleksandrov } else { 1825cf5bddb9SNikolay Aleksandrov ifindex = br->dev->ifindex; 1826cf5bddb9SNikolay Aleksandrov vg = br_vlan_group(br); 1827cf5bddb9SNikolay Aleksandrov net = dev_net(br->dev); 1828cf5bddb9SNikolay Aleksandrov } 1829cf5bddb9SNikolay Aleksandrov 1830cf5bddb9SNikolay Aleksandrov skb = nlmsg_new(rtnl_vlan_nlmsg_size(), GFP_KERNEL); 1831cf5bddb9SNikolay Aleksandrov if (!skb) 1832cf5bddb9SNikolay Aleksandrov goto out_err; 1833cf5bddb9SNikolay Aleksandrov 1834cf5bddb9SNikolay Aleksandrov err = -EMSGSIZE; 1835cf5bddb9SNikolay Aleksandrov nlh = nlmsg_put(skb, 0, 0, cmd, sizeof(*bvm), 0); 1836cf5bddb9SNikolay Aleksandrov if (!nlh) 1837cf5bddb9SNikolay Aleksandrov goto out_err; 1838cf5bddb9SNikolay Aleksandrov bvm = nlmsg_data(nlh); 1839cf5bddb9SNikolay Aleksandrov memset(bvm, 0, sizeof(*bvm)); 1840cf5bddb9SNikolay Aleksandrov bvm->family = AF_BRIDGE; 1841cf5bddb9SNikolay Aleksandrov bvm->ifindex = ifindex; 1842cf5bddb9SNikolay Aleksandrov 1843cf5bddb9SNikolay Aleksandrov switch (cmd) { 1844cf5bddb9SNikolay Aleksandrov case RTM_NEWVLAN: 1845cf5bddb9SNikolay Aleksandrov /* need to find the vlan due to flags/options */ 1846cf5bddb9SNikolay Aleksandrov v = br_vlan_find(vg, vid); 1847cf5bddb9SNikolay Aleksandrov if (!v || !br_vlan_should_use(v)) 1848cf5bddb9SNikolay Aleksandrov goto out_kfree; 1849cf5bddb9SNikolay Aleksandrov 1850cf5bddb9SNikolay Aleksandrov flags = v->flags; 1851cf5bddb9SNikolay Aleksandrov if (br_get_pvid(vg) == v->vid) 1852cf5bddb9SNikolay Aleksandrov flags |= BRIDGE_VLAN_INFO_PVID; 1853cf5bddb9SNikolay Aleksandrov break; 1854cf5bddb9SNikolay Aleksandrov case RTM_DELVLAN: 1855cf5bddb9SNikolay Aleksandrov break; 1856cf5bddb9SNikolay Aleksandrov default: 1857cf5bddb9SNikolay Aleksandrov goto out_kfree; 1858cf5bddb9SNikolay Aleksandrov } 1859cf5bddb9SNikolay Aleksandrov 186056d09976SNikolay Aleksandrov if (!br_vlan_fill_vids(skb, vid, vid_range, v, flags, false)) 1861cf5bddb9SNikolay Aleksandrov goto out_err; 1862cf5bddb9SNikolay Aleksandrov 1863cf5bddb9SNikolay Aleksandrov nlmsg_end(skb, nlh); 1864cf5bddb9SNikolay Aleksandrov rtnl_notify(skb, net, 0, RTNLGRP_BRVLAN, NULL, GFP_KERNEL); 1865cf5bddb9SNikolay Aleksandrov return; 1866cf5bddb9SNikolay Aleksandrov 1867cf5bddb9SNikolay Aleksandrov out_err: 1868cf5bddb9SNikolay Aleksandrov rtnl_set_sk_err(net, RTNLGRP_BRVLAN, err); 1869cf5bddb9SNikolay Aleksandrov out_kfree: 1870cf5bddb9SNikolay Aleksandrov kfree_skb(skb); 1871cf5bddb9SNikolay Aleksandrov } 1872cf5bddb9SNikolay Aleksandrov 18730ab55879SNikolay Aleksandrov /* check if v_curr can enter a range ending in range_end */ 1874a5d29ae2SNikolay Aleksandrov bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, 18750ab55879SNikolay Aleksandrov const struct net_bridge_vlan *range_end) 18760ab55879SNikolay Aleksandrov { 18770ab55879SNikolay Aleksandrov return v_curr->vid - range_end->vid == 1 && 18787a53e718SNikolay Aleksandrov range_end->flags == v_curr->flags && 187999f7c5e0SNikolay Aleksandrov br_vlan_opts_eq_range(v_curr, range_end); 18800ab55879SNikolay Aleksandrov } 18810ab55879SNikolay Aleksandrov 18828dcea187SNikolay Aleksandrov static int br_vlan_dump_dev(const struct net_device *dev, 18838dcea187SNikolay Aleksandrov struct sk_buff *skb, 188456d09976SNikolay Aleksandrov struct netlink_callback *cb, 188556d09976SNikolay Aleksandrov u32 dump_flags) 18868dcea187SNikolay Aleksandrov { 18870ab55879SNikolay Aleksandrov struct net_bridge_vlan *v, *range_start = NULL, *range_end = NULL; 1888743a53d9SNikolay Aleksandrov bool dump_global = !!(dump_flags & BRIDGE_VLANDB_DUMPF_GLOBAL); 188956d09976SNikolay Aleksandrov bool dump_stats = !!(dump_flags & BRIDGE_VLANDB_DUMPF_STATS); 18908dcea187SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 18918dcea187SNikolay Aleksandrov int idx = 0, s_idx = cb->args[1]; 18928dcea187SNikolay Aleksandrov struct nlmsghdr *nlh = NULL; 18938dcea187SNikolay Aleksandrov struct net_bridge_port *p; 18948dcea187SNikolay Aleksandrov struct br_vlan_msg *bvm; 18958dcea187SNikolay Aleksandrov struct net_bridge *br; 18968dcea187SNikolay Aleksandrov int err = 0; 18978dcea187SNikolay Aleksandrov u16 pvid; 18988dcea187SNikolay Aleksandrov 18998dcea187SNikolay Aleksandrov if (!netif_is_bridge_master(dev) && !netif_is_bridge_port(dev)) 19008dcea187SNikolay Aleksandrov return -EINVAL; 19018dcea187SNikolay Aleksandrov 19028dcea187SNikolay Aleksandrov if (netif_is_bridge_master(dev)) { 19038dcea187SNikolay Aleksandrov br = netdev_priv(dev); 19048dcea187SNikolay Aleksandrov vg = br_vlan_group_rcu(br); 19058dcea187SNikolay Aleksandrov p = NULL; 19068dcea187SNikolay Aleksandrov } else { 1907743a53d9SNikolay Aleksandrov /* global options are dumped only for bridge devices */ 1908743a53d9SNikolay Aleksandrov if (dump_global) 1909743a53d9SNikolay Aleksandrov return 0; 1910743a53d9SNikolay Aleksandrov 19118dcea187SNikolay Aleksandrov p = br_port_get_rcu(dev); 19128dcea187SNikolay Aleksandrov if (WARN_ON(!p)) 19138dcea187SNikolay Aleksandrov return -EINVAL; 19148dcea187SNikolay Aleksandrov vg = nbp_vlan_group_rcu(p); 19158dcea187SNikolay Aleksandrov br = p->br; 19168dcea187SNikolay Aleksandrov } 19178dcea187SNikolay Aleksandrov 19188dcea187SNikolay Aleksandrov if (!vg) 19198dcea187SNikolay Aleksandrov return 0; 19208dcea187SNikolay Aleksandrov 19218dcea187SNikolay Aleksandrov nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, 19228dcea187SNikolay Aleksandrov RTM_NEWVLAN, sizeof(*bvm), NLM_F_MULTI); 19238dcea187SNikolay Aleksandrov if (!nlh) 19248dcea187SNikolay Aleksandrov return -EMSGSIZE; 19258dcea187SNikolay Aleksandrov bvm = nlmsg_data(nlh); 19268dcea187SNikolay Aleksandrov memset(bvm, 0, sizeof(*bvm)); 19278dcea187SNikolay Aleksandrov bvm->family = PF_BRIDGE; 19288dcea187SNikolay Aleksandrov bvm->ifindex = dev->ifindex; 19298dcea187SNikolay Aleksandrov pvid = br_get_pvid(vg); 19308dcea187SNikolay Aleksandrov 19310ab55879SNikolay Aleksandrov /* idx must stay at range's beginning until it is filled in */ 19328dcea187SNikolay Aleksandrov list_for_each_entry_rcu(v, &vg->vlan_list, vlist) { 1933743a53d9SNikolay Aleksandrov if (!dump_global && !br_vlan_should_use(v)) 19348dcea187SNikolay Aleksandrov continue; 19350ab55879SNikolay Aleksandrov if (idx < s_idx) { 19360ab55879SNikolay Aleksandrov idx++; 19370ab55879SNikolay Aleksandrov continue; 19380ab55879SNikolay Aleksandrov } 19390ab55879SNikolay Aleksandrov 19400ab55879SNikolay Aleksandrov if (!range_start) { 19410ab55879SNikolay Aleksandrov range_start = v; 19420ab55879SNikolay Aleksandrov range_end = v; 19430ab55879SNikolay Aleksandrov continue; 19440ab55879SNikolay Aleksandrov } 19450ab55879SNikolay Aleksandrov 1946743a53d9SNikolay Aleksandrov if (dump_global) { 1947743a53d9SNikolay Aleksandrov if (br_vlan_global_opts_can_enter_range(v, range_end)) 19486c4110d9SNikolay Aleksandrov goto update_end; 1949743a53d9SNikolay Aleksandrov if (!br_vlan_global_opts_fill(skb, range_start->vid, 1950743a53d9SNikolay Aleksandrov range_end->vid, 1951743a53d9SNikolay Aleksandrov range_start)) { 1952743a53d9SNikolay Aleksandrov err = -EMSGSIZE; 1953743a53d9SNikolay Aleksandrov break; 1954743a53d9SNikolay Aleksandrov } 1955743a53d9SNikolay Aleksandrov /* advance number of filled vlans */ 1956743a53d9SNikolay Aleksandrov idx += range_end->vid - range_start->vid + 1; 1957743a53d9SNikolay Aleksandrov 1958743a53d9SNikolay Aleksandrov range_start = v; 1959743a53d9SNikolay Aleksandrov } else if (dump_stats || v->vid == pvid || 196056d09976SNikolay Aleksandrov !br_vlan_can_enter_range(v, range_end)) { 196156d09976SNikolay Aleksandrov u16 vlan_flags = br_vlan_flags(range_start, pvid); 19620ab55879SNikolay Aleksandrov 19630ab55879SNikolay Aleksandrov if (!br_vlan_fill_vids(skb, range_start->vid, 19647a53e718SNikolay Aleksandrov range_end->vid, range_start, 196556d09976SNikolay Aleksandrov vlan_flags, dump_stats)) { 19668dcea187SNikolay Aleksandrov err = -EMSGSIZE; 19678dcea187SNikolay Aleksandrov break; 19688dcea187SNikolay Aleksandrov } 19690ab55879SNikolay Aleksandrov /* advance number of filled vlans */ 19700ab55879SNikolay Aleksandrov idx += range_end->vid - range_start->vid + 1; 19710ab55879SNikolay Aleksandrov 19720ab55879SNikolay Aleksandrov range_start = v; 19738dcea187SNikolay Aleksandrov } 19746c4110d9SNikolay Aleksandrov update_end: 19750ab55879SNikolay Aleksandrov range_end = v; 19760ab55879SNikolay Aleksandrov } 19770ab55879SNikolay Aleksandrov 19780ab55879SNikolay Aleksandrov /* err will be 0 and range_start will be set in 3 cases here: 19790ab55879SNikolay Aleksandrov * - first vlan (range_start == range_end) 19800ab55879SNikolay Aleksandrov * - last vlan (range_start == range_end, not in range) 19810ab55879SNikolay Aleksandrov * - last vlan range (range_start != range_end, in range) 19820ab55879SNikolay Aleksandrov */ 1983743a53d9SNikolay Aleksandrov if (!err && range_start) { 1984743a53d9SNikolay Aleksandrov if (dump_global && 1985743a53d9SNikolay Aleksandrov !br_vlan_global_opts_fill(skb, range_start->vid, 1986743a53d9SNikolay Aleksandrov range_end->vid, range_start)) 1987743a53d9SNikolay Aleksandrov err = -EMSGSIZE; 1988743a53d9SNikolay Aleksandrov else if (!dump_global && 1989743a53d9SNikolay Aleksandrov !br_vlan_fill_vids(skb, range_start->vid, 1990743a53d9SNikolay Aleksandrov range_end->vid, range_start, 1991743a53d9SNikolay Aleksandrov br_vlan_flags(range_start, pvid), 199256d09976SNikolay Aleksandrov dump_stats)) 19930ab55879SNikolay Aleksandrov err = -EMSGSIZE; 1994743a53d9SNikolay Aleksandrov } 19950ab55879SNikolay Aleksandrov 19960ab55879SNikolay Aleksandrov cb->args[1] = err ? idx : 0; 19970ab55879SNikolay Aleksandrov 19988dcea187SNikolay Aleksandrov nlmsg_end(skb, nlh); 19998dcea187SNikolay Aleksandrov 20008dcea187SNikolay Aleksandrov return err; 20018dcea187SNikolay Aleksandrov } 20028dcea187SNikolay Aleksandrov 200356d09976SNikolay Aleksandrov static const struct nla_policy br_vlan_db_dump_pol[BRIDGE_VLANDB_DUMP_MAX + 1] = { 200456d09976SNikolay Aleksandrov [BRIDGE_VLANDB_DUMP_FLAGS] = { .type = NLA_U32 }, 200556d09976SNikolay Aleksandrov }; 200656d09976SNikolay Aleksandrov 20078dcea187SNikolay Aleksandrov static int br_vlan_rtm_dump(struct sk_buff *skb, struct netlink_callback *cb) 20088dcea187SNikolay Aleksandrov { 200956d09976SNikolay Aleksandrov struct nlattr *dtb[BRIDGE_VLANDB_DUMP_MAX + 1]; 20108dcea187SNikolay Aleksandrov int idx = 0, err = 0, s_idx = cb->args[0]; 20118dcea187SNikolay Aleksandrov struct net *net = sock_net(skb->sk); 20128dcea187SNikolay Aleksandrov struct br_vlan_msg *bvm; 20138dcea187SNikolay Aleksandrov struct net_device *dev; 201456d09976SNikolay Aleksandrov u32 dump_flags = 0; 20158dcea187SNikolay Aleksandrov 201656d09976SNikolay Aleksandrov err = nlmsg_parse(cb->nlh, sizeof(*bvm), dtb, BRIDGE_VLANDB_DUMP_MAX, 201756d09976SNikolay Aleksandrov br_vlan_db_dump_pol, cb->extack); 20188dcea187SNikolay Aleksandrov if (err < 0) 20198dcea187SNikolay Aleksandrov return err; 20208dcea187SNikolay Aleksandrov 20218dcea187SNikolay Aleksandrov bvm = nlmsg_data(cb->nlh); 202256d09976SNikolay Aleksandrov if (dtb[BRIDGE_VLANDB_DUMP_FLAGS]) 202356d09976SNikolay Aleksandrov dump_flags = nla_get_u32(dtb[BRIDGE_VLANDB_DUMP_FLAGS]); 20248dcea187SNikolay Aleksandrov 20258dcea187SNikolay Aleksandrov rcu_read_lock(); 20268dcea187SNikolay Aleksandrov if (bvm->ifindex) { 20278dcea187SNikolay Aleksandrov dev = dev_get_by_index_rcu(net, bvm->ifindex); 20288dcea187SNikolay Aleksandrov if (!dev) { 20298dcea187SNikolay Aleksandrov err = -ENODEV; 20308dcea187SNikolay Aleksandrov goto out_err; 20318dcea187SNikolay Aleksandrov } 203256d09976SNikolay Aleksandrov err = br_vlan_dump_dev(dev, skb, cb, dump_flags); 2033dcb2c5c6SNikolay Aleksandrov /* if the dump completed without an error we return 0 here */ 2034dcb2c5c6SNikolay Aleksandrov if (err != -EMSGSIZE) 20358dcea187SNikolay Aleksandrov goto out_err; 20368dcea187SNikolay Aleksandrov } else { 20378dcea187SNikolay Aleksandrov for_each_netdev_rcu(net, dev) { 20388dcea187SNikolay Aleksandrov if (idx < s_idx) 20398dcea187SNikolay Aleksandrov goto skip; 20408dcea187SNikolay Aleksandrov 204156d09976SNikolay Aleksandrov err = br_vlan_dump_dev(dev, skb, cb, dump_flags); 20428dcea187SNikolay Aleksandrov if (err == -EMSGSIZE) 20438dcea187SNikolay Aleksandrov break; 20448dcea187SNikolay Aleksandrov skip: 20458dcea187SNikolay Aleksandrov idx++; 20468dcea187SNikolay Aleksandrov } 20478dcea187SNikolay Aleksandrov } 20488dcea187SNikolay Aleksandrov cb->args[0] = idx; 20498dcea187SNikolay Aleksandrov rcu_read_unlock(); 20508dcea187SNikolay Aleksandrov 20518dcea187SNikolay Aleksandrov return skb->len; 20528dcea187SNikolay Aleksandrov 20538dcea187SNikolay Aleksandrov out_err: 20548dcea187SNikolay Aleksandrov rcu_read_unlock(); 20558dcea187SNikolay Aleksandrov 20568dcea187SNikolay Aleksandrov return err; 20578dcea187SNikolay Aleksandrov } 20588dcea187SNikolay Aleksandrov 2059f26b2965SNikolay Aleksandrov static const struct nla_policy br_vlan_db_policy[BRIDGE_VLANDB_ENTRY_MAX + 1] = { 20608140860cSJohannes Berg [BRIDGE_VLANDB_ENTRY_INFO] = 20618140860cSJohannes Berg NLA_POLICY_EXACT_LEN(sizeof(struct bridge_vlan_info)), 20620ab55879SNikolay Aleksandrov [BRIDGE_VLANDB_ENTRY_RANGE] = { .type = NLA_U16 }, 2063a580c76dSNikolay Aleksandrov [BRIDGE_VLANDB_ENTRY_STATE] = { .type = NLA_U8 }, 2064fa388f29SNikolay Aleksandrov [BRIDGE_VLANDB_ENTRY_TUNNEL_INFO] = { .type = NLA_NESTED }, 20652796d846SNikolay Aleksandrov [BRIDGE_VLANDB_ENTRY_MCAST_ROUTER] = { .type = NLA_U8 }, 2066f26b2965SNikolay Aleksandrov }; 2067f26b2965SNikolay Aleksandrov 2068f26b2965SNikolay Aleksandrov static int br_vlan_rtm_process_one(struct net_device *dev, 2069f26b2965SNikolay Aleksandrov const struct nlattr *attr, 2070f26b2965SNikolay Aleksandrov int cmd, struct netlink_ext_ack *extack) 2071f26b2965SNikolay Aleksandrov { 20720ab55879SNikolay Aleksandrov struct bridge_vlan_info *vinfo, vrange_end, *vinfo_last = NULL; 2073f26b2965SNikolay Aleksandrov struct nlattr *tb[BRIDGE_VLANDB_ENTRY_MAX + 1]; 2074a5d29ae2SNikolay Aleksandrov bool changed = false, skip_processing = false; 2075f26b2965SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 2076f26b2965SNikolay Aleksandrov struct net_bridge_port *p = NULL; 2077f26b2965SNikolay Aleksandrov int err = 0, cmdmap = 0; 2078f26b2965SNikolay Aleksandrov struct net_bridge *br; 2079f26b2965SNikolay Aleksandrov 2080f26b2965SNikolay Aleksandrov if (netif_is_bridge_master(dev)) { 2081f26b2965SNikolay Aleksandrov br = netdev_priv(dev); 2082f26b2965SNikolay Aleksandrov vg = br_vlan_group(br); 2083f26b2965SNikolay Aleksandrov } else { 2084f26b2965SNikolay Aleksandrov p = br_port_get_rtnl(dev); 2085f26b2965SNikolay Aleksandrov if (WARN_ON(!p)) 2086f26b2965SNikolay Aleksandrov return -ENODEV; 2087f26b2965SNikolay Aleksandrov br = p->br; 2088f26b2965SNikolay Aleksandrov vg = nbp_vlan_group(p); 2089f26b2965SNikolay Aleksandrov } 2090f26b2965SNikolay Aleksandrov 2091f26b2965SNikolay Aleksandrov if (WARN_ON(!vg)) 2092f26b2965SNikolay Aleksandrov return -ENODEV; 2093f26b2965SNikolay Aleksandrov 2094f26b2965SNikolay Aleksandrov err = nla_parse_nested(tb, BRIDGE_VLANDB_ENTRY_MAX, attr, 2095f26b2965SNikolay Aleksandrov br_vlan_db_policy, extack); 2096f26b2965SNikolay Aleksandrov if (err) 2097f26b2965SNikolay Aleksandrov return err; 2098f26b2965SNikolay Aleksandrov 2099f26b2965SNikolay Aleksandrov if (!tb[BRIDGE_VLANDB_ENTRY_INFO]) { 2100f26b2965SNikolay Aleksandrov NL_SET_ERR_MSG_MOD(extack, "Missing vlan entry info"); 2101f26b2965SNikolay Aleksandrov return -EINVAL; 2102f26b2965SNikolay Aleksandrov } 21030ab55879SNikolay Aleksandrov memset(&vrange_end, 0, sizeof(vrange_end)); 2104f26b2965SNikolay Aleksandrov 2105f26b2965SNikolay Aleksandrov vinfo = nla_data(tb[BRIDGE_VLANDB_ENTRY_INFO]); 2106f26b2965SNikolay Aleksandrov if (vinfo->flags & (BRIDGE_VLAN_INFO_RANGE_BEGIN | 2107f26b2965SNikolay Aleksandrov BRIDGE_VLAN_INFO_RANGE_END)) { 2108f26b2965SNikolay Aleksandrov NL_SET_ERR_MSG_MOD(extack, "Old-style vlan ranges are not allowed when using RTM vlan calls"); 2109f26b2965SNikolay Aleksandrov return -EINVAL; 2110f26b2965SNikolay Aleksandrov } 2111f26b2965SNikolay Aleksandrov if (!br_vlan_valid_id(vinfo->vid, extack)) 2112f26b2965SNikolay Aleksandrov return -EINVAL; 2113f26b2965SNikolay Aleksandrov 21140ab55879SNikolay Aleksandrov if (tb[BRIDGE_VLANDB_ENTRY_RANGE]) { 21150ab55879SNikolay Aleksandrov vrange_end.vid = nla_get_u16(tb[BRIDGE_VLANDB_ENTRY_RANGE]); 21160ab55879SNikolay Aleksandrov /* validate user-provided flags without RANGE_BEGIN */ 21170ab55879SNikolay Aleksandrov vrange_end.flags = BRIDGE_VLAN_INFO_RANGE_END | vinfo->flags; 21180ab55879SNikolay Aleksandrov vinfo->flags |= BRIDGE_VLAN_INFO_RANGE_BEGIN; 21190ab55879SNikolay Aleksandrov 21200ab55879SNikolay Aleksandrov /* vinfo_last is the range start, vinfo the range end */ 21210ab55879SNikolay Aleksandrov vinfo_last = vinfo; 21220ab55879SNikolay Aleksandrov vinfo = &vrange_end; 21230ab55879SNikolay Aleksandrov 21240ab55879SNikolay Aleksandrov if (!br_vlan_valid_id(vinfo->vid, extack) || 21250ab55879SNikolay Aleksandrov !br_vlan_valid_range(vinfo, vinfo_last, extack)) 21260ab55879SNikolay Aleksandrov return -EINVAL; 21270ab55879SNikolay Aleksandrov } 21280ab55879SNikolay Aleksandrov 2129f26b2965SNikolay Aleksandrov switch (cmd) { 2130f26b2965SNikolay Aleksandrov case RTM_NEWVLAN: 2131f26b2965SNikolay Aleksandrov cmdmap = RTM_SETLINK; 2132a5d29ae2SNikolay Aleksandrov skip_processing = !!(vinfo->flags & BRIDGE_VLAN_INFO_ONLY_OPTS); 2133f26b2965SNikolay Aleksandrov break; 2134adb3ce9bSNikolay Aleksandrov case RTM_DELVLAN: 2135adb3ce9bSNikolay Aleksandrov cmdmap = RTM_DELLINK; 2136adb3ce9bSNikolay Aleksandrov break; 2137f26b2965SNikolay Aleksandrov } 2138f26b2965SNikolay Aleksandrov 2139a5d29ae2SNikolay Aleksandrov if (!skip_processing) { 2140a5d29ae2SNikolay Aleksandrov struct bridge_vlan_info *tmp_last = vinfo_last; 2141a5d29ae2SNikolay Aleksandrov 2142a5d29ae2SNikolay Aleksandrov /* br_process_vlan_info may overwrite vinfo_last */ 2143a5d29ae2SNikolay Aleksandrov err = br_process_vlan_info(br, p, cmdmap, vinfo, &tmp_last, 2144a5d29ae2SNikolay Aleksandrov &changed, extack); 2145a5d29ae2SNikolay Aleksandrov 2146a5d29ae2SNikolay Aleksandrov /* notify first if anything changed */ 2147f26b2965SNikolay Aleksandrov if (changed) 2148f26b2965SNikolay Aleksandrov br_ifinfo_notify(cmdmap, br, p); 2149f26b2965SNikolay Aleksandrov 2150a5d29ae2SNikolay Aleksandrov if (err) 2151a5d29ae2SNikolay Aleksandrov return err; 2152a5d29ae2SNikolay Aleksandrov } 2153a5d29ae2SNikolay Aleksandrov 2154a5d29ae2SNikolay Aleksandrov /* deal with options */ 2155a5d29ae2SNikolay Aleksandrov if (cmd == RTM_NEWVLAN) { 2156a5d29ae2SNikolay Aleksandrov struct net_bridge_vlan *range_start, *range_end; 2157a5d29ae2SNikolay Aleksandrov 2158a5d29ae2SNikolay Aleksandrov if (vinfo_last) { 2159a5d29ae2SNikolay Aleksandrov range_start = br_vlan_find(vg, vinfo_last->vid); 2160a5d29ae2SNikolay Aleksandrov range_end = br_vlan_find(vg, vinfo->vid); 2161a5d29ae2SNikolay Aleksandrov } else { 2162a5d29ae2SNikolay Aleksandrov range_start = br_vlan_find(vg, vinfo->vid); 2163a5d29ae2SNikolay Aleksandrov range_end = range_start; 2164a5d29ae2SNikolay Aleksandrov } 2165a5d29ae2SNikolay Aleksandrov 2166a5d29ae2SNikolay Aleksandrov err = br_vlan_process_options(br, p, range_start, range_end, 2167a5d29ae2SNikolay Aleksandrov tb, extack); 2168a5d29ae2SNikolay Aleksandrov } 2169a5d29ae2SNikolay Aleksandrov 2170f26b2965SNikolay Aleksandrov return err; 2171f26b2965SNikolay Aleksandrov } 2172f26b2965SNikolay Aleksandrov 2173f26b2965SNikolay Aleksandrov static int br_vlan_rtm_process(struct sk_buff *skb, struct nlmsghdr *nlh, 2174f26b2965SNikolay Aleksandrov struct netlink_ext_ack *extack) 2175f26b2965SNikolay Aleksandrov { 2176f26b2965SNikolay Aleksandrov struct net *net = sock_net(skb->sk); 2177f26b2965SNikolay Aleksandrov struct br_vlan_msg *bvm; 2178f26b2965SNikolay Aleksandrov struct net_device *dev; 2179f26b2965SNikolay Aleksandrov struct nlattr *attr; 2180f26b2965SNikolay Aleksandrov int err, vlans = 0; 2181f26b2965SNikolay Aleksandrov int rem; 2182f26b2965SNikolay Aleksandrov 2183f26b2965SNikolay Aleksandrov /* this should validate the header and check for remaining bytes */ 2184f26b2965SNikolay Aleksandrov err = nlmsg_parse(nlh, sizeof(*bvm), NULL, BRIDGE_VLANDB_MAX, NULL, 2185f26b2965SNikolay Aleksandrov extack); 2186f26b2965SNikolay Aleksandrov if (err < 0) 2187f26b2965SNikolay Aleksandrov return err; 2188f26b2965SNikolay Aleksandrov 2189f26b2965SNikolay Aleksandrov bvm = nlmsg_data(nlh); 2190f26b2965SNikolay Aleksandrov dev = __dev_get_by_index(net, bvm->ifindex); 2191f26b2965SNikolay Aleksandrov if (!dev) 2192f26b2965SNikolay Aleksandrov return -ENODEV; 2193f26b2965SNikolay Aleksandrov 2194f26b2965SNikolay Aleksandrov if (!netif_is_bridge_master(dev) && !netif_is_bridge_port(dev)) { 2195f26b2965SNikolay Aleksandrov NL_SET_ERR_MSG_MOD(extack, "The device is not a valid bridge or bridge port"); 2196f26b2965SNikolay Aleksandrov return -EINVAL; 2197f26b2965SNikolay Aleksandrov } 2198f26b2965SNikolay Aleksandrov 2199f26b2965SNikolay Aleksandrov nlmsg_for_each_attr(attr, nlh, sizeof(*bvm), rem) { 220047ecd2dbSNikolay Aleksandrov switch (nla_type(attr)) { 220147ecd2dbSNikolay Aleksandrov case BRIDGE_VLANDB_ENTRY: 220247ecd2dbSNikolay Aleksandrov err = br_vlan_rtm_process_one(dev, attr, 220347ecd2dbSNikolay Aleksandrov nlh->nlmsg_type, 220447ecd2dbSNikolay Aleksandrov extack); 220547ecd2dbSNikolay Aleksandrov break; 220647ecd2dbSNikolay Aleksandrov case BRIDGE_VLANDB_GLOBAL_OPTIONS: 220747ecd2dbSNikolay Aleksandrov err = br_vlan_rtm_process_global_options(dev, attr, 220847ecd2dbSNikolay Aleksandrov nlh->nlmsg_type, 220947ecd2dbSNikolay Aleksandrov extack); 221047ecd2dbSNikolay Aleksandrov break; 221147ecd2dbSNikolay Aleksandrov default: 2212f26b2965SNikolay Aleksandrov continue; 221347ecd2dbSNikolay Aleksandrov } 2214f26b2965SNikolay Aleksandrov 2215f26b2965SNikolay Aleksandrov vlans++; 2216f26b2965SNikolay Aleksandrov if (err) 2217f26b2965SNikolay Aleksandrov break; 2218f26b2965SNikolay Aleksandrov } 2219f26b2965SNikolay Aleksandrov if (!vlans) { 2220f26b2965SNikolay Aleksandrov NL_SET_ERR_MSG_MOD(extack, "No vlans found to process"); 2221f26b2965SNikolay Aleksandrov err = -EINVAL; 2222f26b2965SNikolay Aleksandrov } 2223f26b2965SNikolay Aleksandrov 2224f26b2965SNikolay Aleksandrov return err; 2225f26b2965SNikolay Aleksandrov } 2226f26b2965SNikolay Aleksandrov 22278dcea187SNikolay Aleksandrov void br_vlan_rtnl_init(void) 22288dcea187SNikolay Aleksandrov { 22298dcea187SNikolay Aleksandrov rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_GETVLAN, NULL, 22308dcea187SNikolay Aleksandrov br_vlan_rtm_dump, 0); 2231f26b2965SNikolay Aleksandrov rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_NEWVLAN, 2232f26b2965SNikolay Aleksandrov br_vlan_rtm_process, NULL, 0); 2233adb3ce9bSNikolay Aleksandrov rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_DELVLAN, 2234adb3ce9bSNikolay Aleksandrov br_vlan_rtm_process, NULL, 0); 22358dcea187SNikolay Aleksandrov } 22368dcea187SNikolay Aleksandrov 22378dcea187SNikolay Aleksandrov void br_vlan_rtnl_uninit(void) 22388dcea187SNikolay Aleksandrov { 22398dcea187SNikolay Aleksandrov rtnl_unregister(PF_BRIDGE, RTM_GETVLAN); 2240f26b2965SNikolay Aleksandrov rtnl_unregister(PF_BRIDGE, RTM_NEWVLAN); 2241adb3ce9bSNikolay Aleksandrov rtnl_unregister(PF_BRIDGE, RTM_DELVLAN); 22428dcea187SNikolay Aleksandrov } 2243