1243a2e63SVlad Yasevich #include <linux/kernel.h> 2243a2e63SVlad Yasevich #include <linux/netdevice.h> 3243a2e63SVlad Yasevich #include <linux/rtnetlink.h> 4243a2e63SVlad Yasevich #include <linux/slab.h> 57f109539SScott Feldman #include <net/switchdev.h> 6243a2e63SVlad Yasevich 7243a2e63SVlad Yasevich #include "br_private.h" 8243a2e63SVlad Yasevich 92594e906SNikolay Aleksandrov static inline int br_vlan_cmp(struct rhashtable_compare_arg *arg, 102594e906SNikolay Aleksandrov const void *ptr) 11552406c4SVlad Yasevich { 122594e906SNikolay Aleksandrov const struct net_bridge_vlan *vle = ptr; 132594e906SNikolay Aleksandrov u16 vid = *(u16 *)arg->key; 142594e906SNikolay Aleksandrov 152594e906SNikolay Aleksandrov return vle->vid != vid; 162594e906SNikolay Aleksandrov } 172594e906SNikolay Aleksandrov 182594e906SNikolay Aleksandrov static const struct rhashtable_params br_vlan_rht_params = { 192594e906SNikolay Aleksandrov .head_offset = offsetof(struct net_bridge_vlan, vnode), 202594e906SNikolay Aleksandrov .key_offset = offsetof(struct net_bridge_vlan, vid), 212594e906SNikolay Aleksandrov .key_len = sizeof(u16), 228af78b64SNikolay Aleksandrov .nelem_hint = 3, 238af78b64SNikolay Aleksandrov .locks_mul = 1, 242594e906SNikolay Aleksandrov .max_size = VLAN_N_VID, 252594e906SNikolay Aleksandrov .obj_cmpfn = br_vlan_cmp, 262594e906SNikolay Aleksandrov .automatic_shrinking = true, 272594e906SNikolay Aleksandrov }; 282594e906SNikolay Aleksandrov 292594e906SNikolay Aleksandrov static struct net_bridge_vlan *br_vlan_lookup(struct rhashtable *tbl, u16 vid) 302594e906SNikolay Aleksandrov { 312594e906SNikolay Aleksandrov return rhashtable_lookup_fast(tbl, &vid, br_vlan_rht_params); 322594e906SNikolay Aleksandrov } 332594e906SNikolay Aleksandrov 3477751ee8SNikolay Aleksandrov static void __vlan_add_pvid(struct net_bridge_vlan_group *vg, u16 vid) 352594e906SNikolay Aleksandrov { 3677751ee8SNikolay Aleksandrov if (vg->pvid == vid) 37552406c4SVlad Yasevich return; 38552406c4SVlad Yasevich 39552406c4SVlad Yasevich smp_wmb(); 4077751ee8SNikolay Aleksandrov vg->pvid = vid; 41552406c4SVlad Yasevich } 42552406c4SVlad Yasevich 4377751ee8SNikolay Aleksandrov static void __vlan_delete_pvid(struct net_bridge_vlan_group *vg, u16 vid) 44552406c4SVlad Yasevich { 4577751ee8SNikolay Aleksandrov if (vg->pvid != vid) 46552406c4SVlad Yasevich return; 47552406c4SVlad Yasevich 48552406c4SVlad Yasevich smp_wmb(); 4977751ee8SNikolay Aleksandrov vg->pvid = 0; 50552406c4SVlad Yasevich } 51552406c4SVlad Yasevich 522594e906SNikolay Aleksandrov static void __vlan_add_flags(struct net_bridge_vlan *v, u16 flags) 5335e03f3aSVlad Yasevich { 5477751ee8SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 5577751ee8SNikolay Aleksandrov 562594e906SNikolay Aleksandrov if (br_vlan_is_master(v)) 57907b1e6eSNikolay Aleksandrov vg = br_vlan_group(v->br); 58635126b7SVlad Yasevich else 59907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(v->port); 6077751ee8SNikolay Aleksandrov 6177751ee8SNikolay Aleksandrov if (flags & BRIDGE_VLAN_INFO_PVID) 6277751ee8SNikolay Aleksandrov __vlan_add_pvid(vg, v->vid); 632594e906SNikolay Aleksandrov else 6477751ee8SNikolay Aleksandrov __vlan_delete_pvid(vg, v->vid); 6535e03f3aSVlad Yasevich 6635e03f3aSVlad Yasevich if (flags & BRIDGE_VLAN_INFO_UNTAGGED) 672594e906SNikolay Aleksandrov v->flags |= BRIDGE_VLAN_INFO_UNTAGGED; 68635126b7SVlad Yasevich else 692594e906SNikolay Aleksandrov v->flags &= ~BRIDGE_VLAN_INFO_UNTAGGED; 7035e03f3aSVlad Yasevich } 7135e03f3aSVlad Yasevich 727f109539SScott Feldman static int __vlan_vid_add(struct net_device *dev, struct net_bridge *br, 737f109539SScott Feldman u16 vid, u16 flags) 747f109539SScott Feldman { 758f24f309SJiri Pirko struct switchdev_obj_port_vlan v = { 766ff64f6fSIdo Schimmel .obj.orig_dev = dev, 779e8f4a54SJiri Pirko .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN, 787f109539SScott Feldman .flags = flags, 793e3a78b4SScott Feldman .vid_begin = vid, 807f109539SScott Feldman .vid_end = vid, 817f109539SScott Feldman }; 820944d6b5SJiri Pirko int err; 837f109539SScott Feldman 840944d6b5SJiri Pirko /* Try switchdev op first. In case it is not supported, fallback to 850944d6b5SJiri Pirko * 8021q add. 860944d6b5SJiri Pirko */ 879e8f4a54SJiri Pirko err = switchdev_port_obj_add(dev, &v.obj); 887f109539SScott Feldman if (err == -EOPNOTSUPP) 890944d6b5SJiri Pirko return vlan_vid_add(dev, br->vlan_proto, vid); 907f109539SScott Feldman return err; 917f109539SScott Feldman } 927f109539SScott Feldman 932594e906SNikolay Aleksandrov static void __vlan_add_list(struct net_bridge_vlan *v) 94243a2e63SVlad Yasevich { 95907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 962594e906SNikolay Aleksandrov struct list_head *headp, *hpos; 972594e906SNikolay Aleksandrov struct net_bridge_vlan *vent; 98243a2e63SVlad Yasevich 99907b1e6eSNikolay Aleksandrov if (br_vlan_is_master(v)) 100907b1e6eSNikolay Aleksandrov vg = br_vlan_group(v->br); 101907b1e6eSNikolay Aleksandrov else 102907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(v->port); 103907b1e6eSNikolay Aleksandrov 104907b1e6eSNikolay Aleksandrov headp = &vg->vlan_list; 1052594e906SNikolay Aleksandrov list_for_each_prev(hpos, headp) { 1062594e906SNikolay Aleksandrov vent = list_entry(hpos, struct net_bridge_vlan, vlist); 1072594e906SNikolay Aleksandrov if (v->vid < vent->vid) 1082594e906SNikolay Aleksandrov continue; 1092594e906SNikolay Aleksandrov else 1102594e906SNikolay Aleksandrov break; 1112594e906SNikolay Aleksandrov } 112586c2b57SNikolay Aleksandrov list_add_rcu(&v->vlist, hpos); 113552406c4SVlad Yasevich } 114243a2e63SVlad Yasevich 1152594e906SNikolay Aleksandrov static void __vlan_del_list(struct net_bridge_vlan *v) 1162594e906SNikolay Aleksandrov { 117586c2b57SNikolay Aleksandrov list_del_rcu(&v->vlist); 118243a2e63SVlad Yasevich } 119243a2e63SVlad Yasevich 120bf361ad3SVivien Didelot static int __vlan_vid_del(struct net_device *dev, struct net_bridge *br, 1217f109539SScott Feldman u16 vid) 1227f109539SScott Feldman { 1238f24f309SJiri Pirko struct switchdev_obj_port_vlan v = { 1246ff64f6fSIdo Schimmel .obj.orig_dev = dev, 1259e8f4a54SJiri Pirko .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN, 1263e3a78b4SScott Feldman .vid_begin = vid, 1277f109539SScott Feldman .vid_end = vid, 1287f109539SScott Feldman }; 1290944d6b5SJiri Pirko int err; 1307f109539SScott Feldman 1310944d6b5SJiri Pirko /* Try switchdev op first. In case it is not supported, fallback to 1320944d6b5SJiri Pirko * 8021q del. 1330944d6b5SJiri Pirko */ 1349e8f4a54SJiri Pirko err = switchdev_port_obj_del(dev, &v.obj); 1350944d6b5SJiri Pirko if (err == -EOPNOTSUPP) { 1360944d6b5SJiri Pirko vlan_vid_del(dev, br->vlan_proto, vid); 1370944d6b5SJiri Pirko return 0; 1387f109539SScott Feldman } 139bf361ad3SVivien Didelot return err; 1407f109539SScott Feldman } 1417f109539SScott Feldman 142f8ed289fSNikolay Aleksandrov /* Returns a master vlan, if it didn't exist it gets created. In all cases a 143f8ed289fSNikolay Aleksandrov * a reference is taken to the master vlan before returning. 144f8ed289fSNikolay Aleksandrov */ 145f8ed289fSNikolay Aleksandrov static struct net_bridge_vlan *br_vlan_get_master(struct net_bridge *br, u16 vid) 146f8ed289fSNikolay Aleksandrov { 147907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 148f8ed289fSNikolay Aleksandrov struct net_bridge_vlan *masterv; 149f8ed289fSNikolay Aleksandrov 150907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 151907b1e6eSNikolay Aleksandrov masterv = br_vlan_find(vg, vid); 152f8ed289fSNikolay Aleksandrov if (!masterv) { 153f8ed289fSNikolay Aleksandrov /* missing global ctx, create it now */ 154f8ed289fSNikolay Aleksandrov if (br_vlan_add(br, vid, 0)) 155f8ed289fSNikolay Aleksandrov return NULL; 156907b1e6eSNikolay Aleksandrov masterv = br_vlan_find(vg, vid); 157f8ed289fSNikolay Aleksandrov if (WARN_ON(!masterv)) 158f8ed289fSNikolay Aleksandrov return NULL; 159f8ed289fSNikolay Aleksandrov } 160f8ed289fSNikolay Aleksandrov atomic_inc(&masterv->refcnt); 161f8ed289fSNikolay Aleksandrov 162f8ed289fSNikolay Aleksandrov return masterv; 163f8ed289fSNikolay Aleksandrov } 164f8ed289fSNikolay Aleksandrov 165f8ed289fSNikolay Aleksandrov static void br_vlan_put_master(struct net_bridge_vlan *masterv) 166f8ed289fSNikolay Aleksandrov { 167907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 168907b1e6eSNikolay Aleksandrov 169f8ed289fSNikolay Aleksandrov if (!br_vlan_is_master(masterv)) 170f8ed289fSNikolay Aleksandrov return; 171f8ed289fSNikolay Aleksandrov 172907b1e6eSNikolay Aleksandrov vg = br_vlan_group(masterv->br); 173f8ed289fSNikolay Aleksandrov if (atomic_dec_and_test(&masterv->refcnt)) { 174907b1e6eSNikolay Aleksandrov rhashtable_remove_fast(&vg->vlan_hash, 175f8ed289fSNikolay Aleksandrov &masterv->vnode, br_vlan_rht_params); 176f8ed289fSNikolay Aleksandrov __vlan_del_list(masterv); 177f8ed289fSNikolay Aleksandrov kfree_rcu(masterv, rcu); 178f8ed289fSNikolay Aleksandrov } 179f8ed289fSNikolay Aleksandrov } 180f8ed289fSNikolay Aleksandrov 1812594e906SNikolay Aleksandrov /* This is the shared VLAN add function which works for both ports and bridge 1822594e906SNikolay Aleksandrov * devices. There are four possible calls to this function in terms of the 1832594e906SNikolay Aleksandrov * vlan entry type: 1842594e906SNikolay Aleksandrov * 1. vlan is being added on a port (no master flags, global entry exists) 185ddd611d3SIdo Schimmel * 2. vlan is being added on a bridge (both master and brentry flags) 1862594e906SNikolay Aleksandrov * 3. vlan is being added on a port, but a global entry didn't exist which 187ddd611d3SIdo Schimmel * is being created right now (master flag set, brentry flag unset), the 1882594e906SNikolay Aleksandrov * global entry is used for global per-vlan features, but not for filtering 189ddd611d3SIdo Schimmel * 4. same as 3 but with both master and brentry flags set so the entry 1902594e906SNikolay Aleksandrov * will be used for filtering in both the port and the bridge 1912594e906SNikolay Aleksandrov */ 1922594e906SNikolay Aleksandrov static int __vlan_add(struct net_bridge_vlan *v, u16 flags) 193243a2e63SVlad Yasevich { 1942594e906SNikolay Aleksandrov struct net_bridge_vlan *masterv = NULL; 1952594e906SNikolay Aleksandrov struct net_bridge_port *p = NULL; 1966be144f6SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 1972594e906SNikolay Aleksandrov struct net_device *dev; 1982594e906SNikolay Aleksandrov struct net_bridge *br; 199bf361ad3SVivien Didelot int err; 200bf361ad3SVivien Didelot 2012594e906SNikolay Aleksandrov if (br_vlan_is_master(v)) { 2022594e906SNikolay Aleksandrov br = v->br; 2032594e906SNikolay Aleksandrov dev = br->dev; 204907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 2052594e906SNikolay Aleksandrov } else { 2062594e906SNikolay Aleksandrov p = v->port; 2072594e906SNikolay Aleksandrov br = p->br; 2082594e906SNikolay Aleksandrov dev = p->dev; 209907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 2102594e906SNikolay Aleksandrov } 2112594e906SNikolay Aleksandrov 2122594e906SNikolay Aleksandrov if (p) { 2132594e906SNikolay Aleksandrov /* Add VLAN to the device filter if it is supported. 2142594e906SNikolay Aleksandrov * This ensures tagged traffic enters the bridge when 2152594e906SNikolay Aleksandrov * promiscuous mode is disabled by br_manage_promisc(). 2162594e906SNikolay Aleksandrov */ 2172594e906SNikolay Aleksandrov err = __vlan_vid_add(dev, br, v->vid, flags); 218bf361ad3SVivien Didelot if (err) 2192594e906SNikolay Aleksandrov goto out; 2202594e906SNikolay Aleksandrov 2212594e906SNikolay Aleksandrov /* need to work on the master vlan too */ 2222594e906SNikolay Aleksandrov if (flags & BRIDGE_VLAN_INFO_MASTER) { 2232ffdf508SNikolay Aleksandrov err = br_vlan_add(br, v->vid, flags | 2242ffdf508SNikolay Aleksandrov BRIDGE_VLAN_INFO_BRENTRY); 2252594e906SNikolay Aleksandrov if (err) 2262594e906SNikolay Aleksandrov goto out_filt; 2272594e906SNikolay Aleksandrov } 2282594e906SNikolay Aleksandrov 229f8ed289fSNikolay Aleksandrov masterv = br_vlan_get_master(br, v->vid); 230f8ed289fSNikolay Aleksandrov if (!masterv) 2312594e906SNikolay Aleksandrov goto out_filt; 2322594e906SNikolay Aleksandrov v->brvlan = masterv; 2332594e906SNikolay Aleksandrov } 2342594e906SNikolay Aleksandrov 2356be144f6SNikolay Aleksandrov /* Add the dev mac and count the vlan only if it's usable */ 2362594e906SNikolay Aleksandrov if (br_vlan_should_use(v)) { 2372594e906SNikolay Aleksandrov err = br_fdb_insert(br, p, dev->dev_addr, v->vid); 2382594e906SNikolay Aleksandrov if (err) { 2392594e906SNikolay Aleksandrov br_err(br, "failed insert local address into bridge forwarding table\n"); 2402594e906SNikolay Aleksandrov goto out_filt; 2412594e906SNikolay Aleksandrov } 2426be144f6SNikolay Aleksandrov vg->num_vlans++; 2432594e906SNikolay Aleksandrov } 2442594e906SNikolay Aleksandrov 2456be144f6SNikolay Aleksandrov err = rhashtable_lookup_insert_fast(&vg->vlan_hash, &v->vnode, 2466be144f6SNikolay Aleksandrov br_vlan_rht_params); 2472594e906SNikolay Aleksandrov if (err) 2482594e906SNikolay Aleksandrov goto out_fdb_insert; 2492594e906SNikolay Aleksandrov 2502594e906SNikolay Aleksandrov __vlan_add_list(v); 2512594e906SNikolay Aleksandrov __vlan_add_flags(v, flags); 2522594e906SNikolay Aleksandrov out: 2532594e906SNikolay Aleksandrov return err; 2542594e906SNikolay Aleksandrov 2552594e906SNikolay Aleksandrov out_fdb_insert: 2566be144f6SNikolay Aleksandrov if (br_vlan_should_use(v)) { 2576be144f6SNikolay Aleksandrov br_fdb_find_delete_local(br, p, dev->dev_addr, v->vid); 2586be144f6SNikolay Aleksandrov vg->num_vlans--; 2596be144f6SNikolay Aleksandrov } 2602594e906SNikolay Aleksandrov 2612594e906SNikolay Aleksandrov out_filt: 2622594e906SNikolay Aleksandrov if (p) { 2632594e906SNikolay Aleksandrov __vlan_vid_del(dev, br, v->vid); 2642594e906SNikolay Aleksandrov if (masterv) { 265f8ed289fSNikolay Aleksandrov br_vlan_put_master(masterv); 2662594e906SNikolay Aleksandrov v->brvlan = NULL; 2672594e906SNikolay Aleksandrov } 2682594e906SNikolay Aleksandrov } 2692594e906SNikolay Aleksandrov 2702594e906SNikolay Aleksandrov goto out; 2712594e906SNikolay Aleksandrov } 2722594e906SNikolay Aleksandrov 2732594e906SNikolay Aleksandrov static int __vlan_del(struct net_bridge_vlan *v) 2742594e906SNikolay Aleksandrov { 2752594e906SNikolay Aleksandrov struct net_bridge_vlan *masterv = v; 27677751ee8SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 2772594e906SNikolay Aleksandrov struct net_bridge_port *p = NULL; 2782594e906SNikolay Aleksandrov int err = 0; 2792594e906SNikolay Aleksandrov 2802594e906SNikolay Aleksandrov if (br_vlan_is_master(v)) { 281907b1e6eSNikolay Aleksandrov vg = br_vlan_group(v->br); 2822594e906SNikolay Aleksandrov } else { 2832594e906SNikolay Aleksandrov p = v->port; 284907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(v->port); 2852594e906SNikolay Aleksandrov masterv = v->brvlan; 2862594e906SNikolay Aleksandrov } 2872594e906SNikolay Aleksandrov 28877751ee8SNikolay Aleksandrov __vlan_delete_pvid(vg, v->vid); 2892594e906SNikolay Aleksandrov if (p) { 2902594e906SNikolay Aleksandrov err = __vlan_vid_del(p->dev, p->br, v->vid); 2912594e906SNikolay Aleksandrov if (err) 2922594e906SNikolay Aleksandrov goto out; 2932594e906SNikolay Aleksandrov } 2942594e906SNikolay Aleksandrov 2956be144f6SNikolay Aleksandrov if (br_vlan_should_use(v)) { 2962594e906SNikolay Aleksandrov v->flags &= ~BRIDGE_VLAN_INFO_BRENTRY; 2976be144f6SNikolay Aleksandrov vg->num_vlans--; 2982594e906SNikolay Aleksandrov } 2992594e906SNikolay Aleksandrov 3002594e906SNikolay Aleksandrov if (masterv != v) { 30177751ee8SNikolay Aleksandrov rhashtable_remove_fast(&vg->vlan_hash, &v->vnode, 30277751ee8SNikolay Aleksandrov br_vlan_rht_params); 3032594e906SNikolay Aleksandrov __vlan_del_list(v); 3042594e906SNikolay Aleksandrov kfree_rcu(v, rcu); 3052594e906SNikolay Aleksandrov } 3062594e906SNikolay Aleksandrov 307f8ed289fSNikolay Aleksandrov br_vlan_put_master(masterv); 3082594e906SNikolay Aleksandrov out: 309bf361ad3SVivien Didelot return err; 3108580e211SToshiaki Makita } 311243a2e63SVlad Yasevich 312f409d0edSNikolay Aleksandrov static void __vlan_group_free(struct net_bridge_vlan_group *vg) 313f409d0edSNikolay Aleksandrov { 314f409d0edSNikolay Aleksandrov WARN_ON(!list_empty(&vg->vlan_list)); 315f409d0edSNikolay Aleksandrov rhashtable_destroy(&vg->vlan_hash); 316f409d0edSNikolay Aleksandrov kfree(vg); 317f409d0edSNikolay Aleksandrov } 318f409d0edSNikolay Aleksandrov 319f409d0edSNikolay Aleksandrov static void __vlan_flush(struct net_bridge_vlan_group *vg) 320243a2e63SVlad Yasevich { 3212594e906SNikolay Aleksandrov struct net_bridge_vlan *vlan, *tmp; 3222594e906SNikolay Aleksandrov 323f409d0edSNikolay Aleksandrov __vlan_delete_pvid(vg, vg->pvid); 324f409d0edSNikolay Aleksandrov list_for_each_entry_safe(vlan, tmp, &vg->vlan_list, vlist) 3252594e906SNikolay Aleksandrov __vlan_del(vlan); 326243a2e63SVlad Yasevich } 327243a2e63SVlad Yasevich 32878851988SVlad Yasevich struct sk_buff *br_handle_vlan(struct net_bridge *br, 3292594e906SNikolay Aleksandrov struct net_bridge_vlan_group *vg, 330a37b85c9SVlad Yasevich struct sk_buff *skb) 331a37b85c9SVlad Yasevich { 3322594e906SNikolay Aleksandrov struct net_bridge_vlan *v; 333a37b85c9SVlad Yasevich u16 vid; 334a37b85c9SVlad Yasevich 33520adfa1aSVlad Yasevich /* If this packet was not filtered at input, let it pass */ 33620adfa1aSVlad Yasevich if (!BR_INPUT_SKB_CB(skb)->vlan_filtered) 33778851988SVlad Yasevich goto out; 33878851988SVlad Yasevich 3392594e906SNikolay Aleksandrov /* At this point, we know that the frame was filtered and contains 3402594e906SNikolay Aleksandrov * a valid vlan id. If the vlan id has untagged flag set, 3412594e906SNikolay Aleksandrov * send untagged; otherwise, send tagged. 3422594e906SNikolay Aleksandrov */ 3432594e906SNikolay Aleksandrov br_vlan_get_tag(skb, &vid); 3442594e906SNikolay Aleksandrov v = br_vlan_find(vg, vid); 3452594e906SNikolay Aleksandrov /* Vlan entry must be configured at this point. The 346fc92f745SVlad Yasevich * only exception is the bridge is set in promisc mode and the 347fc92f745SVlad Yasevich * packet is destined for the bridge device. In this case 348fc92f745SVlad Yasevich * pass the packet as is. 349fc92f745SVlad Yasevich */ 3502594e906SNikolay Aleksandrov if (!v || !br_vlan_should_use(v)) { 351fc92f745SVlad Yasevich if ((br->dev->flags & IFF_PROMISC) && skb->dev == br->dev) { 352fc92f745SVlad Yasevich goto out; 353fc92f745SVlad Yasevich } else { 354fc92f745SVlad Yasevich kfree_skb(skb); 355fc92f745SVlad Yasevich return NULL; 356fc92f745SVlad Yasevich } 357fc92f745SVlad Yasevich } 3582594e906SNikolay Aleksandrov if (v->flags & BRIDGE_VLAN_INFO_UNTAGGED) 35999b192daSToshiaki Makita skb->vlan_tci = 0; 36078851988SVlad Yasevich 36178851988SVlad Yasevich out: 36278851988SVlad Yasevich return skb; 36378851988SVlad Yasevich } 36478851988SVlad Yasevich 36578851988SVlad Yasevich /* Called under RCU */ 36677751ee8SNikolay Aleksandrov static bool __allowed_ingress(struct net_bridge_vlan_group *vg, __be16 proto, 36778851988SVlad Yasevich struct sk_buff *skb, u16 *vid) 36878851988SVlad Yasevich { 3692594e906SNikolay Aleksandrov const struct net_bridge_vlan *v; 3708580e211SToshiaki Makita bool tagged; 371a37b85c9SVlad Yasevich 37220adfa1aSVlad Yasevich BR_INPUT_SKB_CB(skb)->vlan_filtered = true; 37312464bb8SToshiaki Makita /* If vlan tx offload is disabled on bridge device and frame was 37412464bb8SToshiaki Makita * sent from vlan device on the bridge device, it does not have 37512464bb8SToshiaki Makita * HW accelerated vlan tag. 37612464bb8SToshiaki Makita */ 377df8a39deSJiri Pirko if (unlikely(!skb_vlan_tag_present(skb) && 3788580e211SToshiaki Makita skb->protocol == proto)) { 3790d5501c1SVlad Yasevich skb = skb_vlan_untag(skb); 38012464bb8SToshiaki Makita if (unlikely(!skb)) 38112464bb8SToshiaki Makita return false; 38212464bb8SToshiaki Makita } 38312464bb8SToshiaki Makita 3848580e211SToshiaki Makita if (!br_vlan_get_tag(skb, vid)) { 3858580e211SToshiaki Makita /* Tagged frame */ 3868580e211SToshiaki Makita if (skb->vlan_proto != proto) { 3878580e211SToshiaki Makita /* Protocol-mismatch, empty out vlan_tci for new tag */ 3888580e211SToshiaki Makita skb_push(skb, ETH_HLEN); 38962749e2cSJiri Pirko skb = vlan_insert_tag_set_proto(skb, skb->vlan_proto, 390df8a39deSJiri Pirko skb_vlan_tag_get(skb)); 3918580e211SToshiaki Makita if (unlikely(!skb)) 3928580e211SToshiaki Makita return false; 3938580e211SToshiaki Makita 3948580e211SToshiaki Makita skb_pull(skb, ETH_HLEN); 3958580e211SToshiaki Makita skb_reset_mac_len(skb); 3968580e211SToshiaki Makita *vid = 0; 3978580e211SToshiaki Makita tagged = false; 3988580e211SToshiaki Makita } else { 3998580e211SToshiaki Makita tagged = true; 4008580e211SToshiaki Makita } 4018580e211SToshiaki Makita } else { 4028580e211SToshiaki Makita /* Untagged frame */ 4038580e211SToshiaki Makita tagged = false; 4048580e211SToshiaki Makita } 4058580e211SToshiaki Makita 406b90356ceSToshiaki Makita if (!*vid) { 40777751ee8SNikolay Aleksandrov u16 pvid = br_get_pvid(vg); 40877751ee8SNikolay Aleksandrov 409b90356ceSToshiaki Makita /* Frame had a tag with VID 0 or did not have a tag. 410b90356ceSToshiaki Makita * See if pvid is set on this port. That tells us which 411b90356ceSToshiaki Makita * vlan untagged or priority-tagged traffic belongs to. 41278851988SVlad Yasevich */ 4133df6bf45SVlad Yasevich if (!pvid) 414eb707618SToshiaki Makita goto drop; 41578851988SVlad Yasevich 416b90356ceSToshiaki Makita /* PVID is set on this port. Any untagged or priority-tagged 417b90356ceSToshiaki Makita * ingress frame is considered to belong to this vlan. 41878851988SVlad Yasevich */ 419dfb5fa32SToshiaki Makita *vid = pvid; 4208580e211SToshiaki Makita if (likely(!tagged)) 421b90356ceSToshiaki Makita /* Untagged Frame. */ 4228580e211SToshiaki Makita __vlan_hwaccel_put_tag(skb, proto, pvid); 423b90356ceSToshiaki Makita else 424b90356ceSToshiaki Makita /* Priority-tagged Frame. 425b90356ceSToshiaki Makita * At this point, We know that skb->vlan_tci had 426b90356ceSToshiaki Makita * VLAN_TAG_PRESENT bit and its VID field was 0x000. 427b90356ceSToshiaki Makita * We update only VID field and preserve PCP field. 428b90356ceSToshiaki Makita */ 429b90356ceSToshiaki Makita skb->vlan_tci |= pvid; 430b90356ceSToshiaki Makita 43178851988SVlad Yasevich return true; 43278851988SVlad Yasevich } 43378851988SVlad Yasevich 43478851988SVlad Yasevich /* Frame had a valid vlan tag. See if vlan is allowed */ 43577751ee8SNikolay Aleksandrov v = br_vlan_find(vg, *vid); 4362594e906SNikolay Aleksandrov if (v && br_vlan_should_use(v)) 437a37b85c9SVlad Yasevich return true; 438eb707618SToshiaki Makita drop: 439eb707618SToshiaki Makita kfree_skb(skb); 440a37b85c9SVlad Yasevich return false; 441a37b85c9SVlad Yasevich } 442a37b85c9SVlad Yasevich 44377751ee8SNikolay Aleksandrov bool br_allowed_ingress(const struct net_bridge *br, 44477751ee8SNikolay Aleksandrov struct net_bridge_vlan_group *vg, struct sk_buff *skb, 4452594e906SNikolay Aleksandrov u16 *vid) 4462594e906SNikolay Aleksandrov { 4472594e906SNikolay Aleksandrov /* If VLAN filtering is disabled on the bridge, all packets are 4482594e906SNikolay Aleksandrov * permitted. 4492594e906SNikolay Aleksandrov */ 4502594e906SNikolay Aleksandrov if (!br->vlan_enabled) { 4512594e906SNikolay Aleksandrov BR_INPUT_SKB_CB(skb)->vlan_filtered = false; 4522594e906SNikolay Aleksandrov return true; 4532594e906SNikolay Aleksandrov } 4542594e906SNikolay Aleksandrov 45577751ee8SNikolay Aleksandrov return __allowed_ingress(vg, br->vlan_proto, skb, vid); 4562594e906SNikolay Aleksandrov } 4572594e906SNikolay Aleksandrov 45885f46c6bSVlad Yasevich /* Called under RCU. */ 4592594e906SNikolay Aleksandrov bool br_allowed_egress(struct net_bridge_vlan_group *vg, 46085f46c6bSVlad Yasevich const struct sk_buff *skb) 46185f46c6bSVlad Yasevich { 4622594e906SNikolay Aleksandrov const struct net_bridge_vlan *v; 46385f46c6bSVlad Yasevich u16 vid; 46485f46c6bSVlad Yasevich 46520adfa1aSVlad Yasevich /* If this packet was not filtered at input, let it pass */ 46620adfa1aSVlad Yasevich if (!BR_INPUT_SKB_CB(skb)->vlan_filtered) 46785f46c6bSVlad Yasevich return true; 46885f46c6bSVlad Yasevich 46985f46c6bSVlad Yasevich br_vlan_get_tag(skb, &vid); 4702594e906SNikolay Aleksandrov v = br_vlan_find(vg, vid); 4712594e906SNikolay Aleksandrov if (v && br_vlan_should_use(v)) 47285f46c6bSVlad Yasevich return true; 47385f46c6bSVlad Yasevich 47485f46c6bSVlad Yasevich return false; 47585f46c6bSVlad Yasevich } 47685f46c6bSVlad Yasevich 477e0d7968aSToshiaki Makita /* Called under RCU */ 478e0d7968aSToshiaki Makita bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid) 479e0d7968aSToshiaki Makita { 480468e7944SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 481e0d7968aSToshiaki Makita struct net_bridge *br = p->br; 482e0d7968aSToshiaki Makita 48320adfa1aSVlad Yasevich /* If filtering was disabled at input, let it pass. */ 484c095f248SVlad Yasevich if (!br->vlan_enabled) 485e0d7968aSToshiaki Makita return true; 486e0d7968aSToshiaki Makita 487eca1e006SIdo Schimmel vg = nbp_vlan_group_rcu(p); 488468e7944SNikolay Aleksandrov if (!vg || !vg->num_vlans) 489e0d7968aSToshiaki Makita return false; 490e0d7968aSToshiaki Makita 4918580e211SToshiaki Makita if (!br_vlan_get_tag(skb, vid) && skb->vlan_proto != br->vlan_proto) 4928580e211SToshiaki Makita *vid = 0; 4938580e211SToshiaki Makita 494e0d7968aSToshiaki Makita if (!*vid) { 49577751ee8SNikolay Aleksandrov *vid = br_get_pvid(vg); 4963df6bf45SVlad Yasevich if (!*vid) 497e0d7968aSToshiaki Makita return false; 498e0d7968aSToshiaki Makita 499e0d7968aSToshiaki Makita return true; 500e0d7968aSToshiaki Makita } 501e0d7968aSToshiaki Makita 50277751ee8SNikolay Aleksandrov if (br_vlan_find(vg, *vid)) 503e0d7968aSToshiaki Makita return true; 504e0d7968aSToshiaki Makita 505e0d7968aSToshiaki Makita return false; 506e0d7968aSToshiaki Makita } 507e0d7968aSToshiaki Makita 5088adff41cSToshiaki Makita /* Must be protected by RTNL. 5098adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 5108adff41cSToshiaki Makita */ 511552406c4SVlad Yasevich int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags) 512243a2e63SVlad Yasevich { 513907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 5142594e906SNikolay Aleksandrov struct net_bridge_vlan *vlan; 5152594e906SNikolay Aleksandrov int ret; 516243a2e63SVlad Yasevich 517243a2e63SVlad Yasevich ASSERT_RTNL(); 518243a2e63SVlad Yasevich 519907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 520907b1e6eSNikolay Aleksandrov vlan = br_vlan_find(vg, vid); 5212594e906SNikolay Aleksandrov if (vlan) { 5222594e906SNikolay Aleksandrov if (!br_vlan_is_brentry(vlan)) { 5232594e906SNikolay Aleksandrov /* Trying to change flags of non-existent bridge vlan */ 5242594e906SNikolay Aleksandrov if (!(flags & BRIDGE_VLAN_INFO_BRENTRY)) 5252594e906SNikolay Aleksandrov return -EINVAL; 5262594e906SNikolay Aleksandrov /* It was only kept for port vlans, now make it real */ 5272594e906SNikolay Aleksandrov ret = br_fdb_insert(br, NULL, br->dev->dev_addr, 5282594e906SNikolay Aleksandrov vlan->vid); 5292594e906SNikolay Aleksandrov if (ret) { 5302594e906SNikolay Aleksandrov br_err(br, "failed insert local address into bridge forwarding table\n"); 5312594e906SNikolay Aleksandrov return ret; 5322594e906SNikolay Aleksandrov } 5332594e906SNikolay Aleksandrov atomic_inc(&vlan->refcnt); 5342594e906SNikolay Aleksandrov vlan->flags |= BRIDGE_VLAN_INFO_BRENTRY; 535907b1e6eSNikolay Aleksandrov vg->num_vlans++; 5362594e906SNikolay Aleksandrov } 5372594e906SNikolay Aleksandrov __vlan_add_flags(vlan, flags); 5382594e906SNikolay Aleksandrov return 0; 5392594e906SNikolay Aleksandrov } 540243a2e63SVlad Yasevich 5412594e906SNikolay Aleksandrov vlan = kzalloc(sizeof(*vlan), GFP_KERNEL); 5422594e906SNikolay Aleksandrov if (!vlan) 543243a2e63SVlad Yasevich return -ENOMEM; 544243a2e63SVlad Yasevich 5452594e906SNikolay Aleksandrov vlan->vid = vid; 5462594e906SNikolay Aleksandrov vlan->flags = flags | BRIDGE_VLAN_INFO_MASTER; 5472594e906SNikolay Aleksandrov vlan->flags &= ~BRIDGE_VLAN_INFO_PVID; 5482594e906SNikolay Aleksandrov vlan->br = br; 5492594e906SNikolay Aleksandrov if (flags & BRIDGE_VLAN_INFO_BRENTRY) 5502594e906SNikolay Aleksandrov atomic_set(&vlan->refcnt, 1); 5512594e906SNikolay Aleksandrov ret = __vlan_add(vlan, flags); 5522594e906SNikolay Aleksandrov if (ret) 5532594e906SNikolay Aleksandrov kfree(vlan); 554243a2e63SVlad Yasevich 5552594e906SNikolay Aleksandrov return ret; 556243a2e63SVlad Yasevich } 557243a2e63SVlad Yasevich 5588adff41cSToshiaki Makita /* Must be protected by RTNL. 5598adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 5608adff41cSToshiaki Makita */ 561243a2e63SVlad Yasevich int br_vlan_delete(struct net_bridge *br, u16 vid) 562243a2e63SVlad Yasevich { 563907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 5642594e906SNikolay Aleksandrov struct net_bridge_vlan *v; 565243a2e63SVlad Yasevich 566243a2e63SVlad Yasevich ASSERT_RTNL(); 567243a2e63SVlad Yasevich 568907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 569907b1e6eSNikolay Aleksandrov v = br_vlan_find(vg, vid); 5702594e906SNikolay Aleksandrov if (!v || !br_vlan_is_brentry(v)) 5712594e906SNikolay Aleksandrov return -ENOENT; 572243a2e63SVlad Yasevich 573424bb9c9SToshiaki Makita br_fdb_find_delete_local(br, NULL, br->dev->dev_addr, vid); 5743741873bSRoopa Prabhu br_fdb_delete_by_port(br, NULL, vid, 0); 575bc9a25d2SVlad Yasevich 5762594e906SNikolay Aleksandrov return __vlan_del(v); 577243a2e63SVlad Yasevich } 578243a2e63SVlad Yasevich 579243a2e63SVlad Yasevich void br_vlan_flush(struct net_bridge *br) 580243a2e63SVlad Yasevich { 581f409d0edSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 582f409d0edSNikolay Aleksandrov 583243a2e63SVlad Yasevich ASSERT_RTNL(); 584243a2e63SVlad Yasevich 585f409d0edSNikolay Aleksandrov vg = br_vlan_group(br); 586f409d0edSNikolay Aleksandrov __vlan_flush(vg); 587f409d0edSNikolay Aleksandrov RCU_INIT_POINTER(br->vlgrp, NULL); 588f409d0edSNikolay Aleksandrov synchronize_rcu(); 589f409d0edSNikolay Aleksandrov __vlan_group_free(vg); 590243a2e63SVlad Yasevich } 591243a2e63SVlad Yasevich 5922594e906SNikolay Aleksandrov struct net_bridge_vlan *br_vlan_find(struct net_bridge_vlan_group *vg, u16 vid) 5932b292fb4SToshiaki Makita { 5942594e906SNikolay Aleksandrov if (!vg) 5952594e906SNikolay Aleksandrov return NULL; 5962b292fb4SToshiaki Makita 5972594e906SNikolay Aleksandrov return br_vlan_lookup(&vg->vlan_hash, vid); 5982b292fb4SToshiaki Makita } 5992b292fb4SToshiaki Makita 600204177f3SToshiaki Makita /* Must be protected by RTNL. */ 601204177f3SToshiaki Makita static void recalculate_group_addr(struct net_bridge *br) 602204177f3SToshiaki Makita { 603204177f3SToshiaki Makita if (br->group_addr_set) 604204177f3SToshiaki Makita return; 605204177f3SToshiaki Makita 606204177f3SToshiaki Makita spin_lock_bh(&br->lock); 607204177f3SToshiaki Makita if (!br->vlan_enabled || br->vlan_proto == htons(ETH_P_8021Q)) { 608204177f3SToshiaki Makita /* Bridge Group Address */ 609204177f3SToshiaki Makita br->group_addr[5] = 0x00; 610204177f3SToshiaki Makita } else { /* vlan_enabled && ETH_P_8021AD */ 611204177f3SToshiaki Makita /* Provider Bridge Group Address */ 612204177f3SToshiaki Makita br->group_addr[5] = 0x08; 613204177f3SToshiaki Makita } 614204177f3SToshiaki Makita spin_unlock_bh(&br->lock); 615204177f3SToshiaki Makita } 616204177f3SToshiaki Makita 617204177f3SToshiaki Makita /* Must be protected by RTNL. */ 618204177f3SToshiaki Makita void br_recalculate_fwd_mask(struct net_bridge *br) 619204177f3SToshiaki Makita { 620204177f3SToshiaki Makita if (!br->vlan_enabled || br->vlan_proto == htons(ETH_P_8021Q)) 621204177f3SToshiaki Makita br->group_fwd_mask_required = BR_GROUPFWD_DEFAULT; 622204177f3SToshiaki Makita else /* vlan_enabled && ETH_P_8021AD */ 623204177f3SToshiaki Makita br->group_fwd_mask_required = BR_GROUPFWD_8021AD & 624204177f3SToshiaki Makita ~(1u << br->group_addr[5]); 625204177f3SToshiaki Makita } 626204177f3SToshiaki Makita 627a7854037SNikolay Aleksandrov int __br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) 628243a2e63SVlad Yasevich { 6296b72a770SElad Raz struct switchdev_attr attr = { 6306b72a770SElad Raz .orig_dev = br->dev, 6316b72a770SElad Raz .id = SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING, 6326b72a770SElad Raz .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP, 6336b72a770SElad Raz .u.vlan_filtering = val, 6346b72a770SElad Raz }; 6356b72a770SElad Raz int err; 6366b72a770SElad Raz 637243a2e63SVlad Yasevich if (br->vlan_enabled == val) 638a7854037SNikolay Aleksandrov return 0; 639243a2e63SVlad Yasevich 6406b72a770SElad Raz err = switchdev_port_attr_set(br->dev, &attr); 6416b72a770SElad Raz if (err && err != -EOPNOTSUPP) 6426b72a770SElad Raz return err; 6436b72a770SElad Raz 644243a2e63SVlad Yasevich br->vlan_enabled = val; 6452796d0c6SVlad Yasevich br_manage_promisc(br); 646204177f3SToshiaki Makita recalculate_group_addr(br); 647204177f3SToshiaki Makita br_recalculate_fwd_mask(br); 648243a2e63SVlad Yasevich 649a7854037SNikolay Aleksandrov return 0; 650a7854037SNikolay Aleksandrov } 651a7854037SNikolay Aleksandrov 652a7854037SNikolay Aleksandrov int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) 653a7854037SNikolay Aleksandrov { 6546b72a770SElad Raz int err; 6556b72a770SElad Raz 656a7854037SNikolay Aleksandrov if (!rtnl_trylock()) 657a7854037SNikolay Aleksandrov return restart_syscall(); 658a7854037SNikolay Aleksandrov 6596b72a770SElad Raz err = __br_vlan_filter_toggle(br, val); 660243a2e63SVlad Yasevich rtnl_unlock(); 661a7854037SNikolay Aleksandrov 6626b72a770SElad Raz return err; 663243a2e63SVlad Yasevich } 664243a2e63SVlad Yasevich 665d2d427b3SToshiaki Makita int __br_vlan_set_proto(struct net_bridge *br, __be16 proto) 666204177f3SToshiaki Makita { 667204177f3SToshiaki Makita int err = 0; 668204177f3SToshiaki Makita struct net_bridge_port *p; 6692594e906SNikolay Aleksandrov struct net_bridge_vlan *vlan; 670907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 671d2d427b3SToshiaki Makita __be16 oldproto; 672204177f3SToshiaki Makita 673204177f3SToshiaki Makita if (br->vlan_proto == proto) 674d2d427b3SToshiaki Makita return 0; 675204177f3SToshiaki Makita 676204177f3SToshiaki Makita /* Add VLANs for the new proto to the device filter. */ 677204177f3SToshiaki Makita list_for_each_entry(p, &br->port_list, list) { 678907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 679907b1e6eSNikolay Aleksandrov list_for_each_entry(vlan, &vg->vlan_list, vlist) { 6802594e906SNikolay Aleksandrov err = vlan_vid_add(p->dev, proto, vlan->vid); 681204177f3SToshiaki Makita if (err) 682204177f3SToshiaki Makita goto err_filt; 683204177f3SToshiaki Makita } 684204177f3SToshiaki Makita } 685204177f3SToshiaki Makita 686204177f3SToshiaki Makita oldproto = br->vlan_proto; 687204177f3SToshiaki Makita br->vlan_proto = proto; 688204177f3SToshiaki Makita 689204177f3SToshiaki Makita recalculate_group_addr(br); 690204177f3SToshiaki Makita br_recalculate_fwd_mask(br); 691204177f3SToshiaki Makita 692204177f3SToshiaki Makita /* Delete VLANs for the old proto from the device filter. */ 693907b1e6eSNikolay Aleksandrov list_for_each_entry(p, &br->port_list, list) { 694907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 695907b1e6eSNikolay Aleksandrov list_for_each_entry(vlan, &vg->vlan_list, vlist) 6962594e906SNikolay Aleksandrov vlan_vid_del(p->dev, oldproto, vlan->vid); 697907b1e6eSNikolay Aleksandrov } 698204177f3SToshiaki Makita 699d2d427b3SToshiaki Makita return 0; 700204177f3SToshiaki Makita 701204177f3SToshiaki Makita err_filt: 702907b1e6eSNikolay Aleksandrov list_for_each_entry_continue_reverse(vlan, &vg->vlan_list, vlist) 7032594e906SNikolay Aleksandrov vlan_vid_del(p->dev, proto, vlan->vid); 704204177f3SToshiaki Makita 705907b1e6eSNikolay Aleksandrov list_for_each_entry_continue_reverse(p, &br->port_list, list) { 706907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 707907b1e6eSNikolay Aleksandrov list_for_each_entry(vlan, &vg->vlan_list, vlist) 7082594e906SNikolay Aleksandrov vlan_vid_del(p->dev, proto, vlan->vid); 709907b1e6eSNikolay Aleksandrov } 710204177f3SToshiaki Makita 711d2d427b3SToshiaki Makita return err; 712d2d427b3SToshiaki Makita } 713d2d427b3SToshiaki Makita 714d2d427b3SToshiaki Makita int br_vlan_set_proto(struct net_bridge *br, unsigned long val) 715d2d427b3SToshiaki Makita { 716d2d427b3SToshiaki Makita int err; 717d2d427b3SToshiaki Makita 718d2d427b3SToshiaki Makita if (val != ETH_P_8021Q && val != ETH_P_8021AD) 719d2d427b3SToshiaki Makita return -EPROTONOSUPPORT; 720d2d427b3SToshiaki Makita 721d2d427b3SToshiaki Makita if (!rtnl_trylock()) 722d2d427b3SToshiaki Makita return restart_syscall(); 723d2d427b3SToshiaki Makita 724d2d427b3SToshiaki Makita err = __br_vlan_set_proto(br, htons(val)); 725d2d427b3SToshiaki Makita rtnl_unlock(); 726d2d427b3SToshiaki Makita 727d2d427b3SToshiaki Makita return err; 728204177f3SToshiaki Makita } 729204177f3SToshiaki Makita 73077751ee8SNikolay Aleksandrov static bool vlan_default_pvid(struct net_bridge_vlan_group *vg, u16 vid) 7315be5a2dfSVlad Yasevich { 7322594e906SNikolay Aleksandrov struct net_bridge_vlan *v; 7332594e906SNikolay Aleksandrov 73477751ee8SNikolay Aleksandrov if (vid != vg->pvid) 7352594e906SNikolay Aleksandrov return false; 7362594e906SNikolay Aleksandrov 7372594e906SNikolay Aleksandrov v = br_vlan_lookup(&vg->vlan_hash, vid); 7382594e906SNikolay Aleksandrov if (v && br_vlan_should_use(v) && 7392594e906SNikolay Aleksandrov (v->flags & BRIDGE_VLAN_INFO_UNTAGGED)) 7402594e906SNikolay Aleksandrov return true; 7412594e906SNikolay Aleksandrov 7422594e906SNikolay Aleksandrov return false; 7435be5a2dfSVlad Yasevich } 7445be5a2dfSVlad Yasevich 7455be5a2dfSVlad Yasevich static void br_vlan_disable_default_pvid(struct net_bridge *br) 7465be5a2dfSVlad Yasevich { 7475be5a2dfSVlad Yasevich struct net_bridge_port *p; 7485be5a2dfSVlad Yasevich u16 pvid = br->default_pvid; 7495be5a2dfSVlad Yasevich 7505be5a2dfSVlad Yasevich /* Disable default_pvid on all ports where it is still 7515be5a2dfSVlad Yasevich * configured. 7525be5a2dfSVlad Yasevich */ 753907b1e6eSNikolay Aleksandrov if (vlan_default_pvid(br_vlan_group(br), pvid)) 7545be5a2dfSVlad Yasevich br_vlan_delete(br, pvid); 7555be5a2dfSVlad Yasevich 7565be5a2dfSVlad Yasevich list_for_each_entry(p, &br->port_list, list) { 757907b1e6eSNikolay Aleksandrov if (vlan_default_pvid(nbp_vlan_group(p), pvid)) 7585be5a2dfSVlad Yasevich nbp_vlan_delete(p, pvid); 7595be5a2dfSVlad Yasevich } 7605be5a2dfSVlad Yasevich 7615be5a2dfSVlad Yasevich br->default_pvid = 0; 7625be5a2dfSVlad Yasevich } 7635be5a2dfSVlad Yasevich 7640f963b75SNikolay Aleksandrov int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid) 7655be5a2dfSVlad Yasevich { 7662594e906SNikolay Aleksandrov const struct net_bridge_vlan *pvent; 767907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 7685be5a2dfSVlad Yasevich struct net_bridge_port *p; 7695be5a2dfSVlad Yasevich u16 old_pvid; 7705be5a2dfSVlad Yasevich int err = 0; 7715be5a2dfSVlad Yasevich unsigned long *changed; 7725be5a2dfSVlad Yasevich 7730f963b75SNikolay Aleksandrov if (!pvid) { 7740f963b75SNikolay Aleksandrov br_vlan_disable_default_pvid(br); 7750f963b75SNikolay Aleksandrov return 0; 7760f963b75SNikolay Aleksandrov } 7770f963b75SNikolay Aleksandrov 7785be5a2dfSVlad Yasevich changed = kcalloc(BITS_TO_LONGS(BR_MAX_PORTS), sizeof(unsigned long), 7795be5a2dfSVlad Yasevich GFP_KERNEL); 7805be5a2dfSVlad Yasevich if (!changed) 7815be5a2dfSVlad Yasevich return -ENOMEM; 7825be5a2dfSVlad Yasevich 7835be5a2dfSVlad Yasevich old_pvid = br->default_pvid; 7845be5a2dfSVlad Yasevich 7855be5a2dfSVlad Yasevich /* Update default_pvid config only if we do not conflict with 7865be5a2dfSVlad Yasevich * user configuration. 7875be5a2dfSVlad Yasevich */ 788907b1e6eSNikolay Aleksandrov vg = br_vlan_group(br); 789907b1e6eSNikolay Aleksandrov pvent = br_vlan_find(vg, pvid); 790907b1e6eSNikolay Aleksandrov if ((!old_pvid || vlan_default_pvid(vg, old_pvid)) && 7912594e906SNikolay Aleksandrov (!pvent || !br_vlan_should_use(pvent))) { 7925be5a2dfSVlad Yasevich err = br_vlan_add(br, pvid, 7935be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_PVID | 7942594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED | 7952594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_BRENTRY); 7965be5a2dfSVlad Yasevich if (err) 7975be5a2dfSVlad Yasevich goto out; 7985be5a2dfSVlad Yasevich br_vlan_delete(br, old_pvid); 7995be5a2dfSVlad Yasevich set_bit(0, changed); 8005be5a2dfSVlad Yasevich } 8015be5a2dfSVlad Yasevich 8025be5a2dfSVlad Yasevich list_for_each_entry(p, &br->port_list, list) { 8035be5a2dfSVlad Yasevich /* Update default_pvid config only if we do not conflict with 8045be5a2dfSVlad Yasevich * user configuration. 8055be5a2dfSVlad Yasevich */ 806907b1e6eSNikolay Aleksandrov vg = nbp_vlan_group(p); 8075be5a2dfSVlad Yasevich if ((old_pvid && 808907b1e6eSNikolay Aleksandrov !vlan_default_pvid(vg, old_pvid)) || 809907b1e6eSNikolay Aleksandrov br_vlan_find(vg, pvid)) 8105be5a2dfSVlad Yasevich continue; 8115be5a2dfSVlad Yasevich 8125be5a2dfSVlad Yasevich err = nbp_vlan_add(p, pvid, 8135be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_PVID | 8145be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_UNTAGGED); 8155be5a2dfSVlad Yasevich if (err) 8165be5a2dfSVlad Yasevich goto err_port; 8175be5a2dfSVlad Yasevich nbp_vlan_delete(p, old_pvid); 8185be5a2dfSVlad Yasevich set_bit(p->port_no, changed); 8195be5a2dfSVlad Yasevich } 8205be5a2dfSVlad Yasevich 8215be5a2dfSVlad Yasevich br->default_pvid = pvid; 8225be5a2dfSVlad Yasevich 8235be5a2dfSVlad Yasevich out: 8245be5a2dfSVlad Yasevich kfree(changed); 8255be5a2dfSVlad Yasevich return err; 8265be5a2dfSVlad Yasevich 8275be5a2dfSVlad Yasevich err_port: 8285be5a2dfSVlad Yasevich list_for_each_entry_continue_reverse(p, &br->port_list, list) { 8295be5a2dfSVlad Yasevich if (!test_bit(p->port_no, changed)) 8305be5a2dfSVlad Yasevich continue; 8315be5a2dfSVlad Yasevich 8325be5a2dfSVlad Yasevich if (old_pvid) 8335be5a2dfSVlad Yasevich nbp_vlan_add(p, old_pvid, 8345be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_PVID | 8355be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_UNTAGGED); 8365be5a2dfSVlad Yasevich nbp_vlan_delete(p, pvid); 8375be5a2dfSVlad Yasevich } 8385be5a2dfSVlad Yasevich 8395be5a2dfSVlad Yasevich if (test_bit(0, changed)) { 8405be5a2dfSVlad Yasevich if (old_pvid) 8415be5a2dfSVlad Yasevich br_vlan_add(br, old_pvid, 8425be5a2dfSVlad Yasevich BRIDGE_VLAN_INFO_PVID | 8432594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED | 8442594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_BRENTRY); 8455be5a2dfSVlad Yasevich br_vlan_delete(br, pvid); 8465be5a2dfSVlad Yasevich } 8475be5a2dfSVlad Yasevich goto out; 8485be5a2dfSVlad Yasevich } 8495be5a2dfSVlad Yasevich 85096a20d9dSVlad Yasevich int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val) 85196a20d9dSVlad Yasevich { 85296a20d9dSVlad Yasevich u16 pvid = val; 85396a20d9dSVlad Yasevich int err = 0; 85496a20d9dSVlad Yasevich 8555be5a2dfSVlad Yasevich if (val >= VLAN_VID_MASK) 85696a20d9dSVlad Yasevich return -EINVAL; 85796a20d9dSVlad Yasevich 85896a20d9dSVlad Yasevich if (!rtnl_trylock()) 85996a20d9dSVlad Yasevich return restart_syscall(); 86096a20d9dSVlad Yasevich 86196a20d9dSVlad Yasevich if (pvid == br->default_pvid) 86296a20d9dSVlad Yasevich goto unlock; 86396a20d9dSVlad Yasevich 86496a20d9dSVlad Yasevich /* Only allow default pvid change when filtering is disabled */ 86596a20d9dSVlad Yasevich if (br->vlan_enabled) { 86696a20d9dSVlad Yasevich pr_info_once("Please disable vlan filtering to change default_pvid\n"); 86796a20d9dSVlad Yasevich err = -EPERM; 86896a20d9dSVlad Yasevich goto unlock; 86996a20d9dSVlad Yasevich } 8705be5a2dfSVlad Yasevich err = __br_vlan_set_default_pvid(br, pvid); 87196a20d9dSVlad Yasevich unlock: 87296a20d9dSVlad Yasevich rtnl_unlock(); 87396a20d9dSVlad Yasevich return err; 87496a20d9dSVlad Yasevich } 87596a20d9dSVlad Yasevich 8765be5a2dfSVlad Yasevich int br_vlan_init(struct net_bridge *br) 8778580e211SToshiaki Makita { 878907b1e6eSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 8792594e906SNikolay Aleksandrov int ret = -ENOMEM; 8802594e906SNikolay Aleksandrov 881907b1e6eSNikolay Aleksandrov vg = kzalloc(sizeof(*vg), GFP_KERNEL); 882907b1e6eSNikolay Aleksandrov if (!vg) 8832594e906SNikolay Aleksandrov goto out; 884907b1e6eSNikolay Aleksandrov ret = rhashtable_init(&vg->vlan_hash, &br_vlan_rht_params); 8852594e906SNikolay Aleksandrov if (ret) 8862594e906SNikolay Aleksandrov goto err_rhtbl; 887907b1e6eSNikolay Aleksandrov INIT_LIST_HEAD(&vg->vlan_list); 8888580e211SToshiaki Makita br->vlan_proto = htons(ETH_P_8021Q); 88996a20d9dSVlad Yasevich br->default_pvid = 1; 890907b1e6eSNikolay Aleksandrov rcu_assign_pointer(br->vlgrp, vg); 8912594e906SNikolay Aleksandrov ret = br_vlan_add(br, 1, 8922594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_PVID | BRIDGE_VLAN_INFO_UNTAGGED | 8932594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_BRENTRY); 8942594e906SNikolay Aleksandrov if (ret) 8952594e906SNikolay Aleksandrov goto err_vlan_add; 8962594e906SNikolay Aleksandrov 8972594e906SNikolay Aleksandrov out: 8982594e906SNikolay Aleksandrov return ret; 8992594e906SNikolay Aleksandrov 9002594e906SNikolay Aleksandrov err_vlan_add: 901907b1e6eSNikolay Aleksandrov rhashtable_destroy(&vg->vlan_hash); 9022594e906SNikolay Aleksandrov err_rhtbl: 903907b1e6eSNikolay Aleksandrov kfree(vg); 9042594e906SNikolay Aleksandrov 9052594e906SNikolay Aleksandrov goto out; 9062594e906SNikolay Aleksandrov } 9072594e906SNikolay Aleksandrov 9082594e906SNikolay Aleksandrov int nbp_vlan_init(struct net_bridge_port *p) 9092594e906SNikolay Aleksandrov { 910404cdbf0SElad Raz struct switchdev_attr attr = { 911404cdbf0SElad Raz .orig_dev = p->br->dev, 912404cdbf0SElad Raz .id = SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING, 913404cdbf0SElad Raz .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP, 914404cdbf0SElad Raz .u.vlan_filtering = p->br->vlan_enabled, 915404cdbf0SElad Raz }; 916263344e6SNikolay Aleksandrov struct net_bridge_vlan_group *vg; 9172594e906SNikolay Aleksandrov int ret = -ENOMEM; 9182594e906SNikolay Aleksandrov 919263344e6SNikolay Aleksandrov vg = kzalloc(sizeof(struct net_bridge_vlan_group), GFP_KERNEL); 920263344e6SNikolay Aleksandrov if (!vg) 9212594e906SNikolay Aleksandrov goto out; 9222594e906SNikolay Aleksandrov 923404cdbf0SElad Raz ret = switchdev_port_attr_set(p->dev, &attr); 924404cdbf0SElad Raz if (ret && ret != -EOPNOTSUPP) 925404cdbf0SElad Raz goto err_vlan_enabled; 926404cdbf0SElad Raz 927263344e6SNikolay Aleksandrov ret = rhashtable_init(&vg->vlan_hash, &br_vlan_rht_params); 9282594e906SNikolay Aleksandrov if (ret) 9292594e906SNikolay Aleksandrov goto err_rhtbl; 930263344e6SNikolay Aleksandrov INIT_LIST_HEAD(&vg->vlan_list); 931907b1e6eSNikolay Aleksandrov rcu_assign_pointer(p->vlgrp, vg); 9322594e906SNikolay Aleksandrov if (p->br->default_pvid) { 9332594e906SNikolay Aleksandrov ret = nbp_vlan_add(p, p->br->default_pvid, 9342594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_PVID | 9352594e906SNikolay Aleksandrov BRIDGE_VLAN_INFO_UNTAGGED); 9362594e906SNikolay Aleksandrov if (ret) 9372594e906SNikolay Aleksandrov goto err_vlan_add; 9382594e906SNikolay Aleksandrov } 9392594e906SNikolay Aleksandrov out: 9402594e906SNikolay Aleksandrov return ret; 9412594e906SNikolay Aleksandrov 9422594e906SNikolay Aleksandrov err_vlan_add: 94307bc588fSIdo Schimmel RCU_INIT_POINTER(p->vlgrp, NULL); 94407bc588fSIdo Schimmel synchronize_rcu(); 945263344e6SNikolay Aleksandrov rhashtable_destroy(&vg->vlan_hash); 946404cdbf0SElad Raz err_vlan_enabled: 9472594e906SNikolay Aleksandrov err_rhtbl: 948263344e6SNikolay Aleksandrov kfree(vg); 9492594e906SNikolay Aleksandrov 9502594e906SNikolay Aleksandrov goto out; 9518580e211SToshiaki Makita } 9528580e211SToshiaki Makita 9538adff41cSToshiaki Makita /* Must be protected by RTNL. 9548adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 9558adff41cSToshiaki Makita */ 956552406c4SVlad Yasevich int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags) 957243a2e63SVlad Yasevich { 9587fbac984SIdo Schimmel struct switchdev_obj_port_vlan v = { 9597fbac984SIdo Schimmel .obj.orig_dev = port->dev, 9607fbac984SIdo Schimmel .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN, 9617fbac984SIdo Schimmel .flags = flags, 9627fbac984SIdo Schimmel .vid_begin = vid, 9637fbac984SIdo Schimmel .vid_end = vid, 9647fbac984SIdo Schimmel }; 9652594e906SNikolay Aleksandrov struct net_bridge_vlan *vlan; 9662594e906SNikolay Aleksandrov int ret; 967243a2e63SVlad Yasevich 968243a2e63SVlad Yasevich ASSERT_RTNL(); 969243a2e63SVlad Yasevich 970907b1e6eSNikolay Aleksandrov vlan = br_vlan_find(nbp_vlan_group(port), vid); 9712594e906SNikolay Aleksandrov if (vlan) { 9727fbac984SIdo Schimmel /* Pass the flags to the hardware bridge */ 9737fbac984SIdo Schimmel ret = switchdev_port_obj_add(port->dev, &v.obj); 9747fbac984SIdo Schimmel if (ret && ret != -EOPNOTSUPP) 9757fbac984SIdo Schimmel return ret; 9762594e906SNikolay Aleksandrov __vlan_add_flags(vlan, flags); 9772594e906SNikolay Aleksandrov return 0; 978243a2e63SVlad Yasevich } 979243a2e63SVlad Yasevich 9802594e906SNikolay Aleksandrov vlan = kzalloc(sizeof(*vlan), GFP_KERNEL); 9812594e906SNikolay Aleksandrov if (!vlan) 9822594e906SNikolay Aleksandrov return -ENOMEM; 983243a2e63SVlad Yasevich 9842594e906SNikolay Aleksandrov vlan->vid = vid; 9852594e906SNikolay Aleksandrov vlan->port = port; 9862594e906SNikolay Aleksandrov ret = __vlan_add(vlan, flags); 9872594e906SNikolay Aleksandrov if (ret) 9882594e906SNikolay Aleksandrov kfree(vlan); 989243a2e63SVlad Yasevich 9902594e906SNikolay Aleksandrov return ret; 991243a2e63SVlad Yasevich } 992243a2e63SVlad Yasevich 9938adff41cSToshiaki Makita /* Must be protected by RTNL. 9948adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 9958adff41cSToshiaki Makita */ 996243a2e63SVlad Yasevich int nbp_vlan_delete(struct net_bridge_port *port, u16 vid) 997243a2e63SVlad Yasevich { 9982594e906SNikolay Aleksandrov struct net_bridge_vlan *v; 999243a2e63SVlad Yasevich 1000243a2e63SVlad Yasevich ASSERT_RTNL(); 1001243a2e63SVlad Yasevich 1002907b1e6eSNikolay Aleksandrov v = br_vlan_find(nbp_vlan_group(port), vid); 10032594e906SNikolay Aleksandrov if (!v) 10042594e906SNikolay Aleksandrov return -ENOENT; 1005424bb9c9SToshiaki Makita br_fdb_find_delete_local(port->br, port, port->dev->dev_addr, vid); 10061ea2d020SNikolay Aleksandrov br_fdb_delete_by_port(port->br, port, vid, 0); 1007bc9a25d2SVlad Yasevich 10082594e906SNikolay Aleksandrov return __vlan_del(v); 1009243a2e63SVlad Yasevich } 1010243a2e63SVlad Yasevich 1011243a2e63SVlad Yasevich void nbp_vlan_flush(struct net_bridge_port *port) 1012243a2e63SVlad Yasevich { 1013f409d0edSNikolay Aleksandrov struct net_bridge_vlan_group *vg; 1014f409d0edSNikolay Aleksandrov 1015243a2e63SVlad Yasevich ASSERT_RTNL(); 1016243a2e63SVlad Yasevich 1017f409d0edSNikolay Aleksandrov vg = nbp_vlan_group(port); 1018f409d0edSNikolay Aleksandrov __vlan_flush(vg); 1019f409d0edSNikolay Aleksandrov RCU_INIT_POINTER(port->vlgrp, NULL); 1020f409d0edSNikolay Aleksandrov synchronize_rcu(); 1021f409d0edSNikolay Aleksandrov __vlan_group_free(vg); 10225be5a2dfSVlad Yasevich } 1023