1243a2e63SVlad Yasevich #include <linux/kernel.h> 2243a2e63SVlad Yasevich #include <linux/netdevice.h> 3243a2e63SVlad Yasevich #include <linux/rtnetlink.h> 4243a2e63SVlad Yasevich #include <linux/slab.h> 5243a2e63SVlad Yasevich 6243a2e63SVlad Yasevich #include "br_private.h" 7243a2e63SVlad Yasevich 8552406c4SVlad Yasevich static void __vlan_add_pvid(struct net_port_vlans *v, u16 vid) 9552406c4SVlad Yasevich { 10552406c4SVlad Yasevich if (v->pvid == vid) 11552406c4SVlad Yasevich return; 12552406c4SVlad Yasevich 13552406c4SVlad Yasevich smp_wmb(); 14552406c4SVlad Yasevich v->pvid = vid; 15552406c4SVlad Yasevich } 16552406c4SVlad Yasevich 17552406c4SVlad Yasevich static void __vlan_delete_pvid(struct net_port_vlans *v, u16 vid) 18552406c4SVlad Yasevich { 19552406c4SVlad Yasevich if (v->pvid != vid) 20552406c4SVlad Yasevich return; 21552406c4SVlad Yasevich 22552406c4SVlad Yasevich smp_wmb(); 23552406c4SVlad Yasevich v->pvid = 0; 24552406c4SVlad Yasevich } 25552406c4SVlad Yasevich 2635e03f3aSVlad Yasevich static void __vlan_add_flags(struct net_port_vlans *v, u16 vid, u16 flags) 2735e03f3aSVlad Yasevich { 2835e03f3aSVlad Yasevich if (flags & BRIDGE_VLAN_INFO_PVID) 2935e03f3aSVlad Yasevich __vlan_add_pvid(v, vid); 3035e03f3aSVlad Yasevich 3135e03f3aSVlad Yasevich if (flags & BRIDGE_VLAN_INFO_UNTAGGED) 3235e03f3aSVlad Yasevich set_bit(vid, v->untagged_bitmap); 3335e03f3aSVlad Yasevich } 3435e03f3aSVlad Yasevich 35552406c4SVlad Yasevich static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags) 36243a2e63SVlad Yasevich { 37bc9a25d2SVlad Yasevich struct net_bridge_port *p = NULL; 38bc9a25d2SVlad Yasevich struct net_bridge *br; 39bc9a25d2SVlad Yasevich struct net_device *dev; 40243a2e63SVlad Yasevich int err; 41243a2e63SVlad Yasevich 42552406c4SVlad Yasevich if (test_bit(vid, v->vlan_bitmap)) { 4335e03f3aSVlad Yasevich __vlan_add_flags(v, vid, flags); 44552406c4SVlad Yasevich return 0; 45552406c4SVlad Yasevich } 46243a2e63SVlad Yasevich 47bc9a25d2SVlad Yasevich if (v->port_idx) { 48bc9a25d2SVlad Yasevich p = v->parent.port; 49bc9a25d2SVlad Yasevich br = p->br; 50bc9a25d2SVlad Yasevich dev = p->dev; 51bc9a25d2SVlad Yasevich } else { 52bc9a25d2SVlad Yasevich br = v->parent.br; 53bc9a25d2SVlad Yasevich dev = br->dev; 54bc9a25d2SVlad Yasevich } 55243a2e63SVlad Yasevich 5619236837SToshiaki Makita if (p) { 57243a2e63SVlad Yasevich /* Add VLAN to the device filter if it is supported. 58bc9a25d2SVlad Yasevich * Stricly speaking, this is not necessary now, since 59bc9a25d2SVlad Yasevich * devices are made promiscuous by the bridge, but if 60bc9a25d2SVlad Yasevich * that ever changes this code will allow tagged 61bc9a25d2SVlad Yasevich * traffic to enter the bridge. 62243a2e63SVlad Yasevich */ 6319236837SToshiaki Makita err = vlan_vid_add(dev, htons(ETH_P_8021Q), vid); 64243a2e63SVlad Yasevich if (err) 65243a2e63SVlad Yasevich return err; 66243a2e63SVlad Yasevich } 67bc9a25d2SVlad Yasevich 68bc9a25d2SVlad Yasevich err = br_fdb_insert(br, p, dev->dev_addr, vid); 69bc9a25d2SVlad Yasevich if (err) { 70bc9a25d2SVlad Yasevich br_err(br, "failed insert local address into bridge " 71bc9a25d2SVlad Yasevich "forwarding table\n"); 72bc9a25d2SVlad Yasevich goto out_filt; 73bc9a25d2SVlad Yasevich } 74bc9a25d2SVlad Yasevich 75243a2e63SVlad Yasevich set_bit(vid, v->vlan_bitmap); 766cbdceebSVlad Yasevich v->num_vlans++; 7735e03f3aSVlad Yasevich __vlan_add_flags(v, vid, flags); 78552406c4SVlad Yasevich 79243a2e63SVlad Yasevich return 0; 80bc9a25d2SVlad Yasevich 81bc9a25d2SVlad Yasevich out_filt: 8219236837SToshiaki Makita if (p) 8319236837SToshiaki Makita vlan_vid_del(dev, htons(ETH_P_8021Q), vid); 84bc9a25d2SVlad Yasevich return err; 85243a2e63SVlad Yasevich } 86243a2e63SVlad Yasevich 87243a2e63SVlad Yasevich static int __vlan_del(struct net_port_vlans *v, u16 vid) 88243a2e63SVlad Yasevich { 89243a2e63SVlad Yasevich if (!test_bit(vid, v->vlan_bitmap)) 90243a2e63SVlad Yasevich return -EINVAL; 91243a2e63SVlad Yasevich 92552406c4SVlad Yasevich __vlan_delete_pvid(v, vid); 9335e03f3aSVlad Yasevich clear_bit(vid, v->untagged_bitmap); 94552406c4SVlad Yasevich 9519236837SToshiaki Makita if (v->port_idx) 9619236837SToshiaki Makita vlan_vid_del(v->parent.port->dev, htons(ETH_P_8021Q), vid); 97243a2e63SVlad Yasevich 98243a2e63SVlad Yasevich clear_bit(vid, v->vlan_bitmap); 996cbdceebSVlad Yasevich v->num_vlans--; 100ef40b7efSToshiaki Makita if (bitmap_empty(v->vlan_bitmap, VLAN_N_VID)) { 101243a2e63SVlad Yasevich if (v->port_idx) 102cd18721eSMonam Agarwal RCU_INIT_POINTER(v->parent.port->vlan_info, NULL); 103243a2e63SVlad Yasevich else 104cd18721eSMonam Agarwal RCU_INIT_POINTER(v->parent.br->vlan_info, NULL); 105243a2e63SVlad Yasevich kfree_rcu(v, rcu); 106243a2e63SVlad Yasevich } 107243a2e63SVlad Yasevich return 0; 108243a2e63SVlad Yasevich } 109243a2e63SVlad Yasevich 110243a2e63SVlad Yasevich static void __vlan_flush(struct net_port_vlans *v) 111243a2e63SVlad Yasevich { 112552406c4SVlad Yasevich smp_wmb(); 113552406c4SVlad Yasevich v->pvid = 0; 114ef40b7efSToshiaki Makita bitmap_zero(v->vlan_bitmap, VLAN_N_VID); 115243a2e63SVlad Yasevich if (v->port_idx) 116cd18721eSMonam Agarwal RCU_INIT_POINTER(v->parent.port->vlan_info, NULL); 117243a2e63SVlad Yasevich else 118cd18721eSMonam Agarwal RCU_INIT_POINTER(v->parent.br->vlan_info, NULL); 119243a2e63SVlad Yasevich kfree_rcu(v, rcu); 120243a2e63SVlad Yasevich } 121243a2e63SVlad Yasevich 12278851988SVlad Yasevich struct sk_buff *br_handle_vlan(struct net_bridge *br, 12378851988SVlad Yasevich const struct net_port_vlans *pv, 124a37b85c9SVlad Yasevich struct sk_buff *skb) 125a37b85c9SVlad Yasevich { 126a37b85c9SVlad Yasevich u16 vid; 127a37b85c9SVlad Yasevich 12878851988SVlad Yasevich if (!br->vlan_enabled) 12978851988SVlad Yasevich goto out; 13078851988SVlad Yasevich 131fc92f745SVlad Yasevich /* Vlan filter table must be configured at this point. The 132fc92f745SVlad Yasevich * only exception is the bridge is set in promisc mode and the 133fc92f745SVlad Yasevich * packet is destined for the bridge device. In this case 134fc92f745SVlad Yasevich * pass the packet as is. 135fc92f745SVlad Yasevich */ 136fc92f745SVlad Yasevich if (!pv) { 137fc92f745SVlad Yasevich if ((br->dev->flags & IFF_PROMISC) && skb->dev == br->dev) { 138fc92f745SVlad Yasevich goto out; 139fc92f745SVlad Yasevich } else { 140fc92f745SVlad Yasevich kfree_skb(skb); 141fc92f745SVlad Yasevich return NULL; 142fc92f745SVlad Yasevich } 143fc92f745SVlad Yasevich } 144fc92f745SVlad Yasevich 14578851988SVlad Yasevich /* At this point, we know that the frame was filtered and contains 14635e03f3aSVlad Yasevich * a valid vlan id. If the vlan id is set in the untagged bitmap, 1471a81a2e0Stanxiaojun * send untagged; otherwise, send tagged. 14878851988SVlad Yasevich */ 14978851988SVlad Yasevich br_vlan_get_tag(skb, &vid); 15035e03f3aSVlad Yasevich if (test_bit(vid, pv->untagged_bitmap)) 15199b192daSToshiaki Makita skb->vlan_tci = 0; 15278851988SVlad Yasevich 15378851988SVlad Yasevich out: 15478851988SVlad Yasevich return skb; 15578851988SVlad Yasevich } 15678851988SVlad Yasevich 15778851988SVlad Yasevich /* Called under RCU */ 15878851988SVlad Yasevich bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, 15978851988SVlad Yasevich struct sk_buff *skb, u16 *vid) 16078851988SVlad Yasevich { 161b90356ceSToshiaki Makita int err; 162b90356ceSToshiaki Makita 163a37b85c9SVlad Yasevich /* If VLAN filtering is disabled on the bridge, all packets are 164a37b85c9SVlad Yasevich * permitted. 165a37b85c9SVlad Yasevich */ 166a37b85c9SVlad Yasevich if (!br->vlan_enabled) 167a37b85c9SVlad Yasevich return true; 168a37b85c9SVlad Yasevich 169a37b85c9SVlad Yasevich /* If there are no vlan in the permitted list, all packets are 170a37b85c9SVlad Yasevich * rejected. 171a37b85c9SVlad Yasevich */ 172a37b85c9SVlad Yasevich if (!v) 173eb707618SToshiaki Makita goto drop; 174a37b85c9SVlad Yasevich 17512464bb8SToshiaki Makita /* If vlan tx offload is disabled on bridge device and frame was 17612464bb8SToshiaki Makita * sent from vlan device on the bridge device, it does not have 17712464bb8SToshiaki Makita * HW accelerated vlan tag. 17812464bb8SToshiaki Makita */ 17912464bb8SToshiaki Makita if (unlikely(!vlan_tx_tag_present(skb) && 18012464bb8SToshiaki Makita (skb->protocol == htons(ETH_P_8021Q) || 18112464bb8SToshiaki Makita skb->protocol == htons(ETH_P_8021AD)))) { 18212464bb8SToshiaki Makita skb = vlan_untag(skb); 18312464bb8SToshiaki Makita if (unlikely(!skb)) 18412464bb8SToshiaki Makita return false; 18512464bb8SToshiaki Makita } 18612464bb8SToshiaki Makita 187b90356ceSToshiaki Makita err = br_vlan_get_tag(skb, vid); 188b90356ceSToshiaki Makita if (!*vid) { 18978851988SVlad Yasevich u16 pvid = br_get_pvid(v); 19078851988SVlad Yasevich 191b90356ceSToshiaki Makita /* Frame had a tag with VID 0 or did not have a tag. 192b90356ceSToshiaki Makita * See if pvid is set on this port. That tells us which 193b90356ceSToshiaki Makita * vlan untagged or priority-tagged traffic belongs to. 19478851988SVlad Yasevich */ 19578851988SVlad Yasevich if (pvid == VLAN_N_VID) 196eb707618SToshiaki Makita goto drop; 19778851988SVlad Yasevich 198b90356ceSToshiaki Makita /* PVID is set on this port. Any untagged or priority-tagged 199b90356ceSToshiaki Makita * ingress frame is considered to belong to this vlan. 20078851988SVlad Yasevich */ 201dfb5fa32SToshiaki Makita *vid = pvid; 202b90356ceSToshiaki Makita if (likely(err)) 203b90356ceSToshiaki Makita /* Untagged Frame. */ 20486a9bad3SPatrick McHardy __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), pvid); 205b90356ceSToshiaki Makita else 206b90356ceSToshiaki Makita /* Priority-tagged Frame. 207b90356ceSToshiaki Makita * At this point, We know that skb->vlan_tci had 208b90356ceSToshiaki Makita * VLAN_TAG_PRESENT bit and its VID field was 0x000. 209b90356ceSToshiaki Makita * We update only VID field and preserve PCP field. 210b90356ceSToshiaki Makita */ 211b90356ceSToshiaki Makita skb->vlan_tci |= pvid; 212b90356ceSToshiaki Makita 21378851988SVlad Yasevich return true; 21478851988SVlad Yasevich } 21578851988SVlad Yasevich 21678851988SVlad Yasevich /* Frame had a valid vlan tag. See if vlan is allowed */ 21778851988SVlad Yasevich if (test_bit(*vid, v->vlan_bitmap)) 218a37b85c9SVlad Yasevich return true; 219eb707618SToshiaki Makita drop: 220eb707618SToshiaki Makita kfree_skb(skb); 221a37b85c9SVlad Yasevich return false; 222a37b85c9SVlad Yasevich } 223a37b85c9SVlad Yasevich 22485f46c6bSVlad Yasevich /* Called under RCU. */ 22585f46c6bSVlad Yasevich bool br_allowed_egress(struct net_bridge *br, 22685f46c6bSVlad Yasevich const struct net_port_vlans *v, 22785f46c6bSVlad Yasevich const struct sk_buff *skb) 22885f46c6bSVlad Yasevich { 22985f46c6bSVlad Yasevich u16 vid; 23085f46c6bSVlad Yasevich 23185f46c6bSVlad Yasevich if (!br->vlan_enabled) 23285f46c6bSVlad Yasevich return true; 23385f46c6bSVlad Yasevich 23485f46c6bSVlad Yasevich if (!v) 23585f46c6bSVlad Yasevich return false; 23685f46c6bSVlad Yasevich 23785f46c6bSVlad Yasevich br_vlan_get_tag(skb, &vid); 23885f46c6bSVlad Yasevich if (test_bit(vid, v->vlan_bitmap)) 23985f46c6bSVlad Yasevich return true; 24085f46c6bSVlad Yasevich 24185f46c6bSVlad Yasevich return false; 24285f46c6bSVlad Yasevich } 24385f46c6bSVlad Yasevich 244e0d7968aSToshiaki Makita /* Called under RCU */ 245e0d7968aSToshiaki Makita bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid) 246e0d7968aSToshiaki Makita { 247e0d7968aSToshiaki Makita struct net_bridge *br = p->br; 248e0d7968aSToshiaki Makita struct net_port_vlans *v; 249e0d7968aSToshiaki Makita 250e0d7968aSToshiaki Makita if (!br->vlan_enabled) 251e0d7968aSToshiaki Makita return true; 252e0d7968aSToshiaki Makita 253e0d7968aSToshiaki Makita v = rcu_dereference(p->vlan_info); 254e0d7968aSToshiaki Makita if (!v) 255e0d7968aSToshiaki Makita return false; 256e0d7968aSToshiaki Makita 257e0d7968aSToshiaki Makita br_vlan_get_tag(skb, vid); 258e0d7968aSToshiaki Makita if (!*vid) { 259e0d7968aSToshiaki Makita *vid = br_get_pvid(v); 260e0d7968aSToshiaki Makita if (*vid == VLAN_N_VID) 261e0d7968aSToshiaki Makita return false; 262e0d7968aSToshiaki Makita 263e0d7968aSToshiaki Makita return true; 264e0d7968aSToshiaki Makita } 265e0d7968aSToshiaki Makita 266e0d7968aSToshiaki Makita if (test_bit(*vid, v->vlan_bitmap)) 267e0d7968aSToshiaki Makita return true; 268e0d7968aSToshiaki Makita 269e0d7968aSToshiaki Makita return false; 270e0d7968aSToshiaki Makita } 271e0d7968aSToshiaki Makita 2728adff41cSToshiaki Makita /* Must be protected by RTNL. 2738adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 2748adff41cSToshiaki Makita */ 275552406c4SVlad Yasevich int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags) 276243a2e63SVlad Yasevich { 277243a2e63SVlad Yasevich struct net_port_vlans *pv = NULL; 278243a2e63SVlad Yasevich int err; 279243a2e63SVlad Yasevich 280243a2e63SVlad Yasevich ASSERT_RTNL(); 281243a2e63SVlad Yasevich 282243a2e63SVlad Yasevich pv = rtnl_dereference(br->vlan_info); 283243a2e63SVlad Yasevich if (pv) 284552406c4SVlad Yasevich return __vlan_add(pv, vid, flags); 285243a2e63SVlad Yasevich 286243a2e63SVlad Yasevich /* Create port vlan infomration 287243a2e63SVlad Yasevich */ 288243a2e63SVlad Yasevich pv = kzalloc(sizeof(*pv), GFP_KERNEL); 289243a2e63SVlad Yasevich if (!pv) 290243a2e63SVlad Yasevich return -ENOMEM; 291243a2e63SVlad Yasevich 292243a2e63SVlad Yasevich pv->parent.br = br; 293552406c4SVlad Yasevich err = __vlan_add(pv, vid, flags); 294243a2e63SVlad Yasevich if (err) 295243a2e63SVlad Yasevich goto out; 296243a2e63SVlad Yasevich 297243a2e63SVlad Yasevich rcu_assign_pointer(br->vlan_info, pv); 298243a2e63SVlad Yasevich return 0; 299243a2e63SVlad Yasevich out: 300243a2e63SVlad Yasevich kfree(pv); 301243a2e63SVlad Yasevich return err; 302243a2e63SVlad Yasevich } 303243a2e63SVlad Yasevich 3048adff41cSToshiaki Makita /* Must be protected by RTNL. 3058adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 3068adff41cSToshiaki Makita */ 307243a2e63SVlad Yasevich int br_vlan_delete(struct net_bridge *br, u16 vid) 308243a2e63SVlad Yasevich { 309243a2e63SVlad Yasevich struct net_port_vlans *pv; 310243a2e63SVlad Yasevich 311243a2e63SVlad Yasevich ASSERT_RTNL(); 312243a2e63SVlad Yasevich 313243a2e63SVlad Yasevich pv = rtnl_dereference(br->vlan_info); 314243a2e63SVlad Yasevich if (!pv) 315243a2e63SVlad Yasevich return -EINVAL; 316243a2e63SVlad Yasevich 317424bb9c9SToshiaki Makita br_fdb_find_delete_local(br, NULL, br->dev->dev_addr, vid); 318bc9a25d2SVlad Yasevich 319243a2e63SVlad Yasevich __vlan_del(pv, vid); 320243a2e63SVlad Yasevich return 0; 321243a2e63SVlad Yasevich } 322243a2e63SVlad Yasevich 323243a2e63SVlad Yasevich void br_vlan_flush(struct net_bridge *br) 324243a2e63SVlad Yasevich { 325243a2e63SVlad Yasevich struct net_port_vlans *pv; 326243a2e63SVlad Yasevich 327243a2e63SVlad Yasevich ASSERT_RTNL(); 328243a2e63SVlad Yasevich pv = rtnl_dereference(br->vlan_info); 329243a2e63SVlad Yasevich if (!pv) 330243a2e63SVlad Yasevich return; 331243a2e63SVlad Yasevich 332243a2e63SVlad Yasevich __vlan_flush(pv); 333243a2e63SVlad Yasevich } 334243a2e63SVlad Yasevich 3352b292fb4SToshiaki Makita bool br_vlan_find(struct net_bridge *br, u16 vid) 3362b292fb4SToshiaki Makita { 3372b292fb4SToshiaki Makita struct net_port_vlans *pv; 3382b292fb4SToshiaki Makita bool found = false; 3392b292fb4SToshiaki Makita 3402b292fb4SToshiaki Makita rcu_read_lock(); 3412b292fb4SToshiaki Makita pv = rcu_dereference(br->vlan_info); 3422b292fb4SToshiaki Makita 3432b292fb4SToshiaki Makita if (!pv) 3442b292fb4SToshiaki Makita goto out; 3452b292fb4SToshiaki Makita 3462b292fb4SToshiaki Makita if (test_bit(vid, pv->vlan_bitmap)) 3472b292fb4SToshiaki Makita found = true; 3482b292fb4SToshiaki Makita 3492b292fb4SToshiaki Makita out: 3502b292fb4SToshiaki Makita rcu_read_unlock(); 3512b292fb4SToshiaki Makita return found; 3522b292fb4SToshiaki Makita } 3532b292fb4SToshiaki Makita 354243a2e63SVlad Yasevich int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) 355243a2e63SVlad Yasevich { 356243a2e63SVlad Yasevich if (!rtnl_trylock()) 357243a2e63SVlad Yasevich return restart_syscall(); 358243a2e63SVlad Yasevich 359243a2e63SVlad Yasevich if (br->vlan_enabled == val) 360243a2e63SVlad Yasevich goto unlock; 361243a2e63SVlad Yasevich 362243a2e63SVlad Yasevich br->vlan_enabled = val; 363243a2e63SVlad Yasevich 364243a2e63SVlad Yasevich unlock: 365243a2e63SVlad Yasevich rtnl_unlock(); 366243a2e63SVlad Yasevich return 0; 367243a2e63SVlad Yasevich } 368243a2e63SVlad Yasevich 3698adff41cSToshiaki Makita /* Must be protected by RTNL. 3708adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 3718adff41cSToshiaki Makita */ 372552406c4SVlad Yasevich int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags) 373243a2e63SVlad Yasevich { 374243a2e63SVlad Yasevich struct net_port_vlans *pv = NULL; 375243a2e63SVlad Yasevich int err; 376243a2e63SVlad Yasevich 377243a2e63SVlad Yasevich ASSERT_RTNL(); 378243a2e63SVlad Yasevich 379243a2e63SVlad Yasevich pv = rtnl_dereference(port->vlan_info); 380243a2e63SVlad Yasevich if (pv) 381552406c4SVlad Yasevich return __vlan_add(pv, vid, flags); 382243a2e63SVlad Yasevich 383243a2e63SVlad Yasevich /* Create port vlan infomration 384243a2e63SVlad Yasevich */ 385243a2e63SVlad Yasevich pv = kzalloc(sizeof(*pv), GFP_KERNEL); 386243a2e63SVlad Yasevich if (!pv) { 387243a2e63SVlad Yasevich err = -ENOMEM; 388243a2e63SVlad Yasevich goto clean_up; 389243a2e63SVlad Yasevich } 390243a2e63SVlad Yasevich 391243a2e63SVlad Yasevich pv->port_idx = port->port_no; 392243a2e63SVlad Yasevich pv->parent.port = port; 393552406c4SVlad Yasevich err = __vlan_add(pv, vid, flags); 394243a2e63SVlad Yasevich if (err) 395243a2e63SVlad Yasevich goto clean_up; 396243a2e63SVlad Yasevich 397243a2e63SVlad Yasevich rcu_assign_pointer(port->vlan_info, pv); 398243a2e63SVlad Yasevich return 0; 399243a2e63SVlad Yasevich 400243a2e63SVlad Yasevich clean_up: 401243a2e63SVlad Yasevich kfree(pv); 402243a2e63SVlad Yasevich return err; 403243a2e63SVlad Yasevich } 404243a2e63SVlad Yasevich 4058adff41cSToshiaki Makita /* Must be protected by RTNL. 4068adff41cSToshiaki Makita * Must be called with vid in range from 1 to 4094 inclusive. 4078adff41cSToshiaki Makita */ 408243a2e63SVlad Yasevich int nbp_vlan_delete(struct net_bridge_port *port, u16 vid) 409243a2e63SVlad Yasevich { 410243a2e63SVlad Yasevich struct net_port_vlans *pv; 411243a2e63SVlad Yasevich 412243a2e63SVlad Yasevich ASSERT_RTNL(); 413243a2e63SVlad Yasevich 414243a2e63SVlad Yasevich pv = rtnl_dereference(port->vlan_info); 415243a2e63SVlad Yasevich if (!pv) 416243a2e63SVlad Yasevich return -EINVAL; 417243a2e63SVlad Yasevich 418424bb9c9SToshiaki Makita br_fdb_find_delete_local(port->br, port, port->dev->dev_addr, vid); 419bc9a25d2SVlad Yasevich 420243a2e63SVlad Yasevich return __vlan_del(pv, vid); 421243a2e63SVlad Yasevich } 422243a2e63SVlad Yasevich 423243a2e63SVlad Yasevich void nbp_vlan_flush(struct net_bridge_port *port) 424243a2e63SVlad Yasevich { 425243a2e63SVlad Yasevich struct net_port_vlans *pv; 426dbbaf949SToshiaki Makita u16 vid; 427243a2e63SVlad Yasevich 428243a2e63SVlad Yasevich ASSERT_RTNL(); 429243a2e63SVlad Yasevich 430243a2e63SVlad Yasevich pv = rtnl_dereference(port->vlan_info); 431243a2e63SVlad Yasevich if (!pv) 432243a2e63SVlad Yasevich return; 433243a2e63SVlad Yasevich 434dbbaf949SToshiaki Makita for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID) 435dbbaf949SToshiaki Makita vlan_vid_del(port->dev, htons(ETH_P_8021Q), vid); 436dbbaf949SToshiaki Makita 437243a2e63SVlad Yasevich __vlan_flush(pv); 438243a2e63SVlad Yasevich } 439bc9a25d2SVlad Yasevich 440bc9a25d2SVlad Yasevich bool nbp_vlan_find(struct net_bridge_port *port, u16 vid) 441bc9a25d2SVlad Yasevich { 442bc9a25d2SVlad Yasevich struct net_port_vlans *pv; 443bc9a25d2SVlad Yasevich bool found = false; 444bc9a25d2SVlad Yasevich 445bc9a25d2SVlad Yasevich rcu_read_lock(); 446bc9a25d2SVlad Yasevich pv = rcu_dereference(port->vlan_info); 447bc9a25d2SVlad Yasevich 448bc9a25d2SVlad Yasevich if (!pv) 449bc9a25d2SVlad Yasevich goto out; 450bc9a25d2SVlad Yasevich 451bc9a25d2SVlad Yasevich if (test_bit(vid, pv->vlan_bitmap)) 452bc9a25d2SVlad Yasevich found = true; 453bc9a25d2SVlad Yasevich 454bc9a25d2SVlad Yasevich out: 455bc9a25d2SVlad Yasevich rcu_read_unlock(); 456bc9a25d2SVlad Yasevich return found; 457bc9a25d2SVlad Yasevich } 458