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 { 3780d5c368SPatrick McHardy const struct net_device_ops *ops; 38bc9a25d2SVlad Yasevich struct net_bridge_port *p = NULL; 39bc9a25d2SVlad Yasevich struct net_bridge *br; 40bc9a25d2SVlad Yasevich struct net_device *dev; 41243a2e63SVlad Yasevich int err; 42243a2e63SVlad Yasevich 43552406c4SVlad Yasevich if (test_bit(vid, v->vlan_bitmap)) { 4435e03f3aSVlad Yasevich __vlan_add_flags(v, vid, flags); 45552406c4SVlad Yasevich return 0; 46552406c4SVlad Yasevich } 47243a2e63SVlad Yasevich 48bc9a25d2SVlad Yasevich if (vid) { 49bc9a25d2SVlad Yasevich if (v->port_idx) { 50bc9a25d2SVlad Yasevich p = v->parent.port; 51bc9a25d2SVlad Yasevich br = p->br; 52bc9a25d2SVlad Yasevich dev = p->dev; 53bc9a25d2SVlad Yasevich } else { 54bc9a25d2SVlad Yasevich br = v->parent.br; 55bc9a25d2SVlad Yasevich dev = br->dev; 56bc9a25d2SVlad Yasevich } 5780d5c368SPatrick McHardy ops = dev->netdev_ops; 58243a2e63SVlad Yasevich 59f646968fSPatrick McHardy if (p && (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) { 60243a2e63SVlad Yasevich /* Add VLAN to the device filter if it is supported. 61bc9a25d2SVlad Yasevich * Stricly speaking, this is not necessary now, since 62bc9a25d2SVlad Yasevich * devices are made promiscuous by the bridge, but if 63bc9a25d2SVlad Yasevich * that ever changes this code will allow tagged 64bc9a25d2SVlad Yasevich * traffic to enter the bridge. 65243a2e63SVlad Yasevich */ 6680d5c368SPatrick McHardy err = ops->ndo_vlan_rx_add_vid(dev, htons(ETH_P_8021Q), 6780d5c368SPatrick McHardy vid); 68243a2e63SVlad Yasevich if (err) 69243a2e63SVlad Yasevich return err; 70243a2e63SVlad Yasevich } 71bc9a25d2SVlad Yasevich 72bc9a25d2SVlad Yasevich err = br_fdb_insert(br, p, dev->dev_addr, vid); 73bc9a25d2SVlad Yasevich if (err) { 74bc9a25d2SVlad Yasevich br_err(br, "failed insert local address into bridge " 75bc9a25d2SVlad Yasevich "forwarding table\n"); 76bc9a25d2SVlad Yasevich goto out_filt; 77bc9a25d2SVlad Yasevich } 78bc9a25d2SVlad Yasevich 79243a2e63SVlad Yasevich } 80243a2e63SVlad Yasevich 81243a2e63SVlad Yasevich set_bit(vid, v->vlan_bitmap); 826cbdceebSVlad Yasevich v->num_vlans++; 8335e03f3aSVlad Yasevich __vlan_add_flags(v, vid, flags); 84552406c4SVlad Yasevich 85243a2e63SVlad Yasevich return 0; 86bc9a25d2SVlad Yasevich 87bc9a25d2SVlad Yasevich out_filt: 88f646968fSPatrick McHardy if (p && (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) 8980d5c368SPatrick McHardy ops->ndo_vlan_rx_kill_vid(dev, htons(ETH_P_8021Q), vid); 90bc9a25d2SVlad Yasevich return err; 91243a2e63SVlad Yasevich } 92243a2e63SVlad Yasevich 93243a2e63SVlad Yasevich static int __vlan_del(struct net_port_vlans *v, u16 vid) 94243a2e63SVlad Yasevich { 95243a2e63SVlad Yasevich if (!test_bit(vid, v->vlan_bitmap)) 96243a2e63SVlad Yasevich return -EINVAL; 97243a2e63SVlad Yasevich 98552406c4SVlad Yasevich __vlan_delete_pvid(v, vid); 9935e03f3aSVlad Yasevich clear_bit(vid, v->untagged_bitmap); 100552406c4SVlad Yasevich 101243a2e63SVlad Yasevich if (v->port_idx && vid) { 102243a2e63SVlad Yasevich struct net_device *dev = v->parent.port->dev; 10380d5c368SPatrick McHardy const struct net_device_ops *ops = dev->netdev_ops; 104243a2e63SVlad Yasevich 105f646968fSPatrick McHardy if (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER) 10680d5c368SPatrick McHardy ops->ndo_vlan_rx_kill_vid(dev, htons(ETH_P_8021Q), vid); 107243a2e63SVlad Yasevich } 108243a2e63SVlad Yasevich 109243a2e63SVlad Yasevich clear_bit(vid, v->vlan_bitmap); 1106cbdceebSVlad Yasevich v->num_vlans--; 111243a2e63SVlad Yasevich if (bitmap_empty(v->vlan_bitmap, BR_VLAN_BITMAP_LEN)) { 112243a2e63SVlad Yasevich if (v->port_idx) 113243a2e63SVlad Yasevich rcu_assign_pointer(v->parent.port->vlan_info, NULL); 114243a2e63SVlad Yasevich else 115243a2e63SVlad Yasevich rcu_assign_pointer(v->parent.br->vlan_info, NULL); 116243a2e63SVlad Yasevich kfree_rcu(v, rcu); 117243a2e63SVlad Yasevich } 118243a2e63SVlad Yasevich return 0; 119243a2e63SVlad Yasevich } 120243a2e63SVlad Yasevich 121243a2e63SVlad Yasevich static void __vlan_flush(struct net_port_vlans *v) 122243a2e63SVlad Yasevich { 123552406c4SVlad Yasevich smp_wmb(); 124552406c4SVlad Yasevich v->pvid = 0; 125243a2e63SVlad Yasevich bitmap_zero(v->vlan_bitmap, BR_VLAN_BITMAP_LEN); 126243a2e63SVlad Yasevich if (v->port_idx) 127243a2e63SVlad Yasevich rcu_assign_pointer(v->parent.port->vlan_info, NULL); 128243a2e63SVlad Yasevich else 129243a2e63SVlad Yasevich rcu_assign_pointer(v->parent.br->vlan_info, NULL); 130243a2e63SVlad Yasevich kfree_rcu(v, rcu); 131243a2e63SVlad Yasevich } 132243a2e63SVlad Yasevich 13378851988SVlad Yasevich /* Strip the tag from the packet. Will return skb with tci set 0. */ 13478851988SVlad Yasevich static struct sk_buff *br_vlan_untag(struct sk_buff *skb) 13578851988SVlad Yasevich { 13678851988SVlad Yasevich if (skb->protocol != htons(ETH_P_8021Q)) { 13778851988SVlad Yasevich skb->vlan_tci = 0; 13878851988SVlad Yasevich return skb; 13978851988SVlad Yasevich } 14078851988SVlad Yasevich 14178851988SVlad Yasevich skb->vlan_tci = 0; 14278851988SVlad Yasevich skb = vlan_untag(skb); 14378851988SVlad Yasevich if (skb) 14478851988SVlad Yasevich skb->vlan_tci = 0; 14578851988SVlad Yasevich 14678851988SVlad Yasevich return skb; 14778851988SVlad Yasevich } 14878851988SVlad Yasevich 14978851988SVlad Yasevich struct sk_buff *br_handle_vlan(struct net_bridge *br, 15078851988SVlad Yasevich const struct net_port_vlans *pv, 151a37b85c9SVlad Yasevich struct sk_buff *skb) 152a37b85c9SVlad Yasevich { 153a37b85c9SVlad Yasevich u16 vid; 154a37b85c9SVlad Yasevich 15578851988SVlad Yasevich if (!br->vlan_enabled) 15678851988SVlad Yasevich goto out; 15778851988SVlad Yasevich 15878851988SVlad Yasevich /* At this point, we know that the frame was filtered and contains 15935e03f3aSVlad Yasevich * a valid vlan id. If the vlan id is set in the untagged bitmap, 16078851988SVlad Yasevich * send untagged; otherwise, send taged. 16178851988SVlad Yasevich */ 16278851988SVlad Yasevich br_vlan_get_tag(skb, &vid); 16335e03f3aSVlad Yasevich if (test_bit(vid, pv->untagged_bitmap)) 16478851988SVlad Yasevich skb = br_vlan_untag(skb); 16578851988SVlad Yasevich else { 16678851988SVlad Yasevich /* Egress policy says "send tagged". If output device 16778851988SVlad Yasevich * is the bridge, we need to add the VLAN header 16878851988SVlad Yasevich * ourselves since we'll be going through the RX path. 16978851988SVlad Yasevich * Sending to ports puts the frame on the TX path and 17078851988SVlad Yasevich * we let dev_hard_start_xmit() add the header. 17178851988SVlad Yasevich */ 17278851988SVlad Yasevich if (skb->protocol != htons(ETH_P_8021Q) && 17378851988SVlad Yasevich pv->port_idx == 0) { 17478851988SVlad Yasevich /* vlan_put_tag expects skb->data to point to 17578851988SVlad Yasevich * mac header. 17678851988SVlad Yasevich */ 17778851988SVlad Yasevich skb_push(skb, ETH_HLEN); 17886a9bad3SPatrick McHardy skb = __vlan_put_tag(skb, skb->vlan_proto, skb->vlan_tci); 17978851988SVlad Yasevich if (!skb) 18078851988SVlad Yasevich goto out; 18178851988SVlad Yasevich /* put skb->data back to where it was */ 18278851988SVlad Yasevich skb_pull(skb, ETH_HLEN); 18378851988SVlad Yasevich skb->vlan_tci = 0; 18478851988SVlad Yasevich } 18578851988SVlad Yasevich } 18678851988SVlad Yasevich 18778851988SVlad Yasevich out: 18878851988SVlad Yasevich return skb; 18978851988SVlad Yasevich } 19078851988SVlad Yasevich 19178851988SVlad Yasevich /* Called under RCU */ 19278851988SVlad Yasevich bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, 19378851988SVlad Yasevich struct sk_buff *skb, u16 *vid) 19478851988SVlad Yasevich { 195a37b85c9SVlad Yasevich /* If VLAN filtering is disabled on the bridge, all packets are 196a37b85c9SVlad Yasevich * permitted. 197a37b85c9SVlad Yasevich */ 198a37b85c9SVlad Yasevich if (!br->vlan_enabled) 199a37b85c9SVlad Yasevich return true; 200a37b85c9SVlad Yasevich 201a37b85c9SVlad Yasevich /* If there are no vlan in the permitted list, all packets are 202a37b85c9SVlad Yasevich * rejected. 203a37b85c9SVlad Yasevich */ 204a37b85c9SVlad Yasevich if (!v) 205a37b85c9SVlad Yasevich return false; 206a37b85c9SVlad Yasevich 20778851988SVlad Yasevich if (br_vlan_get_tag(skb, vid)) { 20878851988SVlad Yasevich u16 pvid = br_get_pvid(v); 20978851988SVlad Yasevich 21078851988SVlad Yasevich /* Frame did not have a tag. See if pvid is set 21178851988SVlad Yasevich * on this port. That tells us which vlan untagged 21278851988SVlad Yasevich * traffic belongs to. 21378851988SVlad Yasevich */ 21478851988SVlad Yasevich if (pvid == VLAN_N_VID) 21578851988SVlad Yasevich return false; 21678851988SVlad Yasevich 21778851988SVlad Yasevich /* PVID is set on this port. Any untagged ingress 21878851988SVlad Yasevich * frame is considered to belong to this vlan. 21978851988SVlad Yasevich */ 22086a9bad3SPatrick McHardy __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), pvid); 22178851988SVlad Yasevich return true; 22278851988SVlad Yasevich } 22378851988SVlad Yasevich 22478851988SVlad Yasevich /* Frame had a valid vlan tag. See if vlan is allowed */ 22578851988SVlad Yasevich if (test_bit(*vid, v->vlan_bitmap)) 226a37b85c9SVlad Yasevich return true; 227a37b85c9SVlad Yasevich 228a37b85c9SVlad Yasevich return false; 229a37b85c9SVlad Yasevich } 230a37b85c9SVlad Yasevich 23185f46c6bSVlad Yasevich /* Called under RCU. */ 23285f46c6bSVlad Yasevich bool br_allowed_egress(struct net_bridge *br, 23385f46c6bSVlad Yasevich const struct net_port_vlans *v, 23485f46c6bSVlad Yasevich const struct sk_buff *skb) 23585f46c6bSVlad Yasevich { 23685f46c6bSVlad Yasevich u16 vid; 23785f46c6bSVlad Yasevich 23885f46c6bSVlad Yasevich if (!br->vlan_enabled) 23985f46c6bSVlad Yasevich return true; 24085f46c6bSVlad Yasevich 24185f46c6bSVlad Yasevich if (!v) 24285f46c6bSVlad Yasevich return false; 24385f46c6bSVlad Yasevich 24485f46c6bSVlad Yasevich br_vlan_get_tag(skb, &vid); 24585f46c6bSVlad Yasevich if (test_bit(vid, v->vlan_bitmap)) 24685f46c6bSVlad Yasevich return true; 24785f46c6bSVlad Yasevich 24885f46c6bSVlad Yasevich return false; 24985f46c6bSVlad Yasevich } 25085f46c6bSVlad Yasevich 251243a2e63SVlad Yasevich /* Must be protected by RTNL */ 252552406c4SVlad Yasevich int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags) 253243a2e63SVlad Yasevich { 254243a2e63SVlad Yasevich struct net_port_vlans *pv = NULL; 255243a2e63SVlad Yasevich int err; 256243a2e63SVlad Yasevich 257243a2e63SVlad Yasevich ASSERT_RTNL(); 258243a2e63SVlad Yasevich 259243a2e63SVlad Yasevich pv = rtnl_dereference(br->vlan_info); 260243a2e63SVlad Yasevich if (pv) 261552406c4SVlad Yasevich return __vlan_add(pv, vid, flags); 262243a2e63SVlad Yasevich 263243a2e63SVlad Yasevich /* Create port vlan infomration 264243a2e63SVlad Yasevich */ 265243a2e63SVlad Yasevich pv = kzalloc(sizeof(*pv), GFP_KERNEL); 266243a2e63SVlad Yasevich if (!pv) 267243a2e63SVlad Yasevich return -ENOMEM; 268243a2e63SVlad Yasevich 269243a2e63SVlad Yasevich pv->parent.br = br; 270552406c4SVlad Yasevich err = __vlan_add(pv, vid, flags); 271243a2e63SVlad Yasevich if (err) 272243a2e63SVlad Yasevich goto out; 273243a2e63SVlad Yasevich 274243a2e63SVlad Yasevich rcu_assign_pointer(br->vlan_info, pv); 275243a2e63SVlad Yasevich return 0; 276243a2e63SVlad Yasevich out: 277243a2e63SVlad Yasevich kfree(pv); 278243a2e63SVlad Yasevich return err; 279243a2e63SVlad Yasevich } 280243a2e63SVlad Yasevich 281243a2e63SVlad Yasevich /* Must be protected by RTNL */ 282243a2e63SVlad Yasevich int br_vlan_delete(struct net_bridge *br, u16 vid) 283243a2e63SVlad Yasevich { 284243a2e63SVlad Yasevich struct net_port_vlans *pv; 285243a2e63SVlad Yasevich 286243a2e63SVlad Yasevich ASSERT_RTNL(); 287243a2e63SVlad Yasevich 288243a2e63SVlad Yasevich pv = rtnl_dereference(br->vlan_info); 289243a2e63SVlad Yasevich if (!pv) 290243a2e63SVlad Yasevich return -EINVAL; 291243a2e63SVlad Yasevich 292bc9a25d2SVlad Yasevich if (vid) { 293bc9a25d2SVlad Yasevich /* If the VID !=0 remove fdb for this vid. VID 0 is special 294bc9a25d2SVlad Yasevich * in that it's the default and is always there in the fdb. 295bc9a25d2SVlad Yasevich */ 296bc9a25d2SVlad Yasevich spin_lock_bh(&br->hash_lock); 297bc9a25d2SVlad Yasevich fdb_delete_by_addr(br, br->dev->dev_addr, vid); 298bc9a25d2SVlad Yasevich spin_unlock_bh(&br->hash_lock); 299bc9a25d2SVlad Yasevich } 300bc9a25d2SVlad Yasevich 301243a2e63SVlad Yasevich __vlan_del(pv, vid); 302243a2e63SVlad Yasevich return 0; 303243a2e63SVlad Yasevich } 304243a2e63SVlad Yasevich 305243a2e63SVlad Yasevich void br_vlan_flush(struct net_bridge *br) 306243a2e63SVlad Yasevich { 307243a2e63SVlad Yasevich struct net_port_vlans *pv; 308243a2e63SVlad Yasevich 309243a2e63SVlad Yasevich ASSERT_RTNL(); 310243a2e63SVlad Yasevich pv = rtnl_dereference(br->vlan_info); 311243a2e63SVlad Yasevich if (!pv) 312243a2e63SVlad Yasevich return; 313243a2e63SVlad Yasevich 314243a2e63SVlad Yasevich __vlan_flush(pv); 315243a2e63SVlad Yasevich } 316243a2e63SVlad Yasevich 317243a2e63SVlad Yasevich int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) 318243a2e63SVlad Yasevich { 319243a2e63SVlad Yasevich if (!rtnl_trylock()) 320243a2e63SVlad Yasevich return restart_syscall(); 321243a2e63SVlad Yasevich 322243a2e63SVlad Yasevich if (br->vlan_enabled == val) 323243a2e63SVlad Yasevich goto unlock; 324243a2e63SVlad Yasevich 325243a2e63SVlad Yasevich br->vlan_enabled = val; 326243a2e63SVlad Yasevich 327243a2e63SVlad Yasevich unlock: 328243a2e63SVlad Yasevich rtnl_unlock(); 329243a2e63SVlad Yasevich return 0; 330243a2e63SVlad Yasevich } 331243a2e63SVlad Yasevich 332243a2e63SVlad Yasevich /* Must be protected by RTNL */ 333552406c4SVlad Yasevich int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags) 334243a2e63SVlad Yasevich { 335243a2e63SVlad Yasevich struct net_port_vlans *pv = NULL; 336243a2e63SVlad Yasevich int err; 337243a2e63SVlad Yasevich 338243a2e63SVlad Yasevich ASSERT_RTNL(); 339243a2e63SVlad Yasevich 340243a2e63SVlad Yasevich pv = rtnl_dereference(port->vlan_info); 341243a2e63SVlad Yasevich if (pv) 342552406c4SVlad Yasevich return __vlan_add(pv, vid, flags); 343243a2e63SVlad Yasevich 344243a2e63SVlad Yasevich /* Create port vlan infomration 345243a2e63SVlad Yasevich */ 346243a2e63SVlad Yasevich pv = kzalloc(sizeof(*pv), GFP_KERNEL); 347243a2e63SVlad Yasevich if (!pv) { 348243a2e63SVlad Yasevich err = -ENOMEM; 349243a2e63SVlad Yasevich goto clean_up; 350243a2e63SVlad Yasevich } 351243a2e63SVlad Yasevich 352243a2e63SVlad Yasevich pv->port_idx = port->port_no; 353243a2e63SVlad Yasevich pv->parent.port = port; 354552406c4SVlad Yasevich err = __vlan_add(pv, vid, flags); 355243a2e63SVlad Yasevich if (err) 356243a2e63SVlad Yasevich goto clean_up; 357243a2e63SVlad Yasevich 358243a2e63SVlad Yasevich rcu_assign_pointer(port->vlan_info, pv); 359243a2e63SVlad Yasevich return 0; 360243a2e63SVlad Yasevich 361243a2e63SVlad Yasevich clean_up: 362243a2e63SVlad Yasevich kfree(pv); 363243a2e63SVlad Yasevich return err; 364243a2e63SVlad Yasevich } 365243a2e63SVlad Yasevich 366243a2e63SVlad Yasevich /* Must be protected by RTNL */ 367243a2e63SVlad Yasevich int nbp_vlan_delete(struct net_bridge_port *port, u16 vid) 368243a2e63SVlad Yasevich { 369243a2e63SVlad Yasevich struct net_port_vlans *pv; 370243a2e63SVlad Yasevich 371243a2e63SVlad Yasevich ASSERT_RTNL(); 372243a2e63SVlad Yasevich 373243a2e63SVlad Yasevich pv = rtnl_dereference(port->vlan_info); 374243a2e63SVlad Yasevich if (!pv) 375243a2e63SVlad Yasevich return -EINVAL; 376243a2e63SVlad Yasevich 377bc9a25d2SVlad Yasevich if (vid) { 378bc9a25d2SVlad Yasevich /* If the VID !=0 remove fdb for this vid. VID 0 is special 379bc9a25d2SVlad Yasevich * in that it's the default and is always there in the fdb. 380bc9a25d2SVlad Yasevich */ 381bc9a25d2SVlad Yasevich spin_lock_bh(&port->br->hash_lock); 382bc9a25d2SVlad Yasevich fdb_delete_by_addr(port->br, port->dev->dev_addr, vid); 383bc9a25d2SVlad Yasevich spin_unlock_bh(&port->br->hash_lock); 384bc9a25d2SVlad Yasevich } 385bc9a25d2SVlad Yasevich 386243a2e63SVlad Yasevich return __vlan_del(pv, vid); 387243a2e63SVlad Yasevich } 388243a2e63SVlad Yasevich 389243a2e63SVlad Yasevich void nbp_vlan_flush(struct net_bridge_port *port) 390243a2e63SVlad Yasevich { 391243a2e63SVlad Yasevich struct net_port_vlans *pv; 392243a2e63SVlad Yasevich 393243a2e63SVlad Yasevich ASSERT_RTNL(); 394243a2e63SVlad Yasevich 395243a2e63SVlad Yasevich pv = rtnl_dereference(port->vlan_info); 396243a2e63SVlad Yasevich if (!pv) 397243a2e63SVlad Yasevich return; 398243a2e63SVlad Yasevich 399243a2e63SVlad Yasevich __vlan_flush(pv); 400243a2e63SVlad Yasevich } 401bc9a25d2SVlad Yasevich 402bc9a25d2SVlad Yasevich bool nbp_vlan_find(struct net_bridge_port *port, u16 vid) 403bc9a25d2SVlad Yasevich { 404bc9a25d2SVlad Yasevich struct net_port_vlans *pv; 405bc9a25d2SVlad Yasevich bool found = false; 406bc9a25d2SVlad Yasevich 407bc9a25d2SVlad Yasevich rcu_read_lock(); 408bc9a25d2SVlad Yasevich pv = rcu_dereference(port->vlan_info); 409bc9a25d2SVlad Yasevich 410bc9a25d2SVlad Yasevich if (!pv) 411bc9a25d2SVlad Yasevich goto out; 412bc9a25d2SVlad Yasevich 413bc9a25d2SVlad Yasevich if (test_bit(vid, pv->vlan_bitmap)) 414bc9a25d2SVlad Yasevich found = true; 415bc9a25d2SVlad Yasevich 416bc9a25d2SVlad Yasevich out: 417bc9a25d2SVlad Yasevich rcu_read_unlock(); 418bc9a25d2SVlad Yasevich return found; 419bc9a25d2SVlad Yasevich } 420