xref: /openbmc/linux/net/bridge/br_vlan.c (revision bc9a25d2)
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 
26552406c4SVlad Yasevich static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags)
27243a2e63SVlad Yasevich {
28bc9a25d2SVlad Yasevich 	struct net_bridge_port *p = NULL;
29bc9a25d2SVlad Yasevich 	struct net_bridge *br;
30bc9a25d2SVlad Yasevich 	struct net_device *dev;
31243a2e63SVlad Yasevich 	int err;
32243a2e63SVlad Yasevich 
33552406c4SVlad Yasevich 	if (test_bit(vid, v->vlan_bitmap)) {
34552406c4SVlad Yasevich 		if (flags & BRIDGE_VLAN_INFO_PVID)
35552406c4SVlad Yasevich 			__vlan_add_pvid(v, vid);
36552406c4SVlad Yasevich 		return 0;
37552406c4SVlad Yasevich 	}
38243a2e63SVlad Yasevich 
39bc9a25d2SVlad Yasevich 	if (vid) {
40bc9a25d2SVlad Yasevich 		if (v->port_idx) {
41bc9a25d2SVlad Yasevich 			p = v->parent.port;
42bc9a25d2SVlad Yasevich 			br = p->br;
43bc9a25d2SVlad Yasevich 			dev = p->dev;
44bc9a25d2SVlad Yasevich 		} else {
45bc9a25d2SVlad Yasevich 			br = v->parent.br;
46bc9a25d2SVlad Yasevich 			dev = br->dev;
47bc9a25d2SVlad Yasevich 		}
48243a2e63SVlad Yasevich 
49bc9a25d2SVlad Yasevich 		if (p && (dev->features & NETIF_F_HW_VLAN_FILTER)) {
50243a2e63SVlad Yasevich 			/* Add VLAN to the device filter if it is supported.
51bc9a25d2SVlad Yasevich 			 * Stricly speaking, this is not necessary now, since
52bc9a25d2SVlad Yasevich 			 * devices are made promiscuous by the bridge, but if
53bc9a25d2SVlad Yasevich 			 * that ever changes this code will allow tagged
54bc9a25d2SVlad Yasevich 			 * traffic to enter the bridge.
55243a2e63SVlad Yasevich 			 */
56243a2e63SVlad Yasevich 			err = dev->netdev_ops->ndo_vlan_rx_add_vid(dev, vid);
57243a2e63SVlad Yasevich 			if (err)
58243a2e63SVlad Yasevich 				return err;
59243a2e63SVlad Yasevich 		}
60bc9a25d2SVlad Yasevich 
61bc9a25d2SVlad Yasevich 		err = br_fdb_insert(br, p, dev->dev_addr, vid);
62bc9a25d2SVlad Yasevich 		if (err) {
63bc9a25d2SVlad Yasevich 			br_err(br, "failed insert local address into bridge "
64bc9a25d2SVlad Yasevich 			       "forwarding table\n");
65bc9a25d2SVlad Yasevich 			goto out_filt;
66bc9a25d2SVlad Yasevich 		}
67bc9a25d2SVlad Yasevich 
68243a2e63SVlad Yasevich 	}
69243a2e63SVlad Yasevich 
70243a2e63SVlad Yasevich 	set_bit(vid, v->vlan_bitmap);
716cbdceebSVlad Yasevich 	v->num_vlans++;
72552406c4SVlad Yasevich 	if (flags & BRIDGE_VLAN_INFO_PVID)
73552406c4SVlad Yasevich 		__vlan_add_pvid(v, vid);
74552406c4SVlad Yasevich 
75243a2e63SVlad Yasevich 	return 0;
76bc9a25d2SVlad Yasevich 
77bc9a25d2SVlad Yasevich out_filt:
78bc9a25d2SVlad Yasevich 	if (p && (dev->features & NETIF_F_HW_VLAN_FILTER))
79bc9a25d2SVlad Yasevich 		dev->netdev_ops->ndo_vlan_rx_kill_vid(dev, vid);
80bc9a25d2SVlad Yasevich 	return err;
81243a2e63SVlad Yasevich }
82243a2e63SVlad Yasevich 
83243a2e63SVlad Yasevich static int __vlan_del(struct net_port_vlans *v, u16 vid)
84243a2e63SVlad Yasevich {
85243a2e63SVlad Yasevich 	if (!test_bit(vid, v->vlan_bitmap))
86243a2e63SVlad Yasevich 		return -EINVAL;
87243a2e63SVlad Yasevich 
88552406c4SVlad Yasevich 	__vlan_delete_pvid(v, vid);
89552406c4SVlad Yasevich 
90243a2e63SVlad Yasevich 	if (v->port_idx && vid) {
91243a2e63SVlad Yasevich 		struct net_device *dev = v->parent.port->dev;
92243a2e63SVlad Yasevich 
93243a2e63SVlad Yasevich 		if (dev->features & NETIF_F_HW_VLAN_FILTER)
94243a2e63SVlad Yasevich 			dev->netdev_ops->ndo_vlan_rx_kill_vid(dev, vid);
95243a2e63SVlad Yasevich 	}
96243a2e63SVlad Yasevich 
97243a2e63SVlad Yasevich 	clear_bit(vid, v->vlan_bitmap);
986cbdceebSVlad Yasevich 	v->num_vlans--;
99243a2e63SVlad Yasevich 	if (bitmap_empty(v->vlan_bitmap, BR_VLAN_BITMAP_LEN)) {
100243a2e63SVlad Yasevich 		if (v->port_idx)
101243a2e63SVlad Yasevich 			rcu_assign_pointer(v->parent.port->vlan_info, NULL);
102243a2e63SVlad Yasevich 		else
103243a2e63SVlad Yasevich 			rcu_assign_pointer(v->parent.br->vlan_info, NULL);
104243a2e63SVlad Yasevich 		kfree_rcu(v, rcu);
105243a2e63SVlad Yasevich 	}
106243a2e63SVlad Yasevich 	return 0;
107243a2e63SVlad Yasevich }
108243a2e63SVlad Yasevich 
109243a2e63SVlad Yasevich static void __vlan_flush(struct net_port_vlans *v)
110243a2e63SVlad Yasevich {
111552406c4SVlad Yasevich 	smp_wmb();
112552406c4SVlad Yasevich 	v->pvid = 0;
113243a2e63SVlad Yasevich 	bitmap_zero(v->vlan_bitmap, BR_VLAN_BITMAP_LEN);
114243a2e63SVlad Yasevich 	if (v->port_idx)
115243a2e63SVlad Yasevich 		rcu_assign_pointer(v->parent.port->vlan_info, NULL);
116243a2e63SVlad Yasevich 	else
117243a2e63SVlad Yasevich 		rcu_assign_pointer(v->parent.br->vlan_info, NULL);
118243a2e63SVlad Yasevich 	kfree_rcu(v, rcu);
119243a2e63SVlad Yasevich }
120243a2e63SVlad Yasevich 
12178851988SVlad Yasevich /* Strip the tag from the packet.  Will return skb with tci set 0.  */
12278851988SVlad Yasevich static struct sk_buff *br_vlan_untag(struct sk_buff *skb)
12378851988SVlad Yasevich {
12478851988SVlad Yasevich 	if (skb->protocol != htons(ETH_P_8021Q)) {
12578851988SVlad Yasevich 		skb->vlan_tci = 0;
12678851988SVlad Yasevich 		return skb;
12778851988SVlad Yasevich 	}
12878851988SVlad Yasevich 
12978851988SVlad Yasevich 	skb->vlan_tci = 0;
13078851988SVlad Yasevich 	skb = vlan_untag(skb);
13178851988SVlad Yasevich 	if (skb)
13278851988SVlad Yasevich 		skb->vlan_tci = 0;
13378851988SVlad Yasevich 
13478851988SVlad Yasevich 	return skb;
13578851988SVlad Yasevich }
13678851988SVlad Yasevich 
13778851988SVlad Yasevich struct sk_buff *br_handle_vlan(struct net_bridge *br,
13878851988SVlad Yasevich 			       const struct net_port_vlans *pv,
139a37b85c9SVlad Yasevich 			       struct sk_buff *skb)
140a37b85c9SVlad Yasevich {
141a37b85c9SVlad Yasevich 	u16 vid;
142a37b85c9SVlad Yasevich 
14378851988SVlad Yasevich 	if (!br->vlan_enabled)
14478851988SVlad Yasevich 		goto out;
14578851988SVlad Yasevich 
14678851988SVlad Yasevich 	/* At this point, we know that the frame was filtered and contains
14778851988SVlad Yasevich 	 * a valid vlan id.  If the vlan id matches the pvid of current port
14878851988SVlad Yasevich 	 * send untagged; otherwise, send taged.
14978851988SVlad Yasevich 	 */
15078851988SVlad Yasevich 	br_vlan_get_tag(skb, &vid);
15178851988SVlad Yasevich 	if (vid == br_get_pvid(pv))
15278851988SVlad Yasevich 		skb = br_vlan_untag(skb);
15378851988SVlad Yasevich 	else {
15478851988SVlad Yasevich 		/* Egress policy says "send tagged".  If output device
15578851988SVlad Yasevich 		 * is the  bridge, we need to add the VLAN header
15678851988SVlad Yasevich 		 * ourselves since we'll be going through the RX path.
15778851988SVlad Yasevich 		 * Sending to ports puts the frame on the TX path and
15878851988SVlad Yasevich 		 * we let dev_hard_start_xmit() add the header.
15978851988SVlad Yasevich 		 */
16078851988SVlad Yasevich 		if (skb->protocol != htons(ETH_P_8021Q) &&
16178851988SVlad Yasevich 		    pv->port_idx == 0) {
16278851988SVlad Yasevich 			/* vlan_put_tag expects skb->data to point to
16378851988SVlad Yasevich 			 * mac header.
16478851988SVlad Yasevich 			 */
16578851988SVlad Yasevich 			skb_push(skb, ETH_HLEN);
16678851988SVlad Yasevich 			skb = __vlan_put_tag(skb, skb->vlan_tci);
16778851988SVlad Yasevich 			if (!skb)
16878851988SVlad Yasevich 				goto out;
16978851988SVlad Yasevich 			/* put skb->data back to where it was */
17078851988SVlad Yasevich 			skb_pull(skb, ETH_HLEN);
17178851988SVlad Yasevich 			skb->vlan_tci = 0;
17278851988SVlad Yasevich 		}
17378851988SVlad Yasevich 	}
17478851988SVlad Yasevich 
17578851988SVlad Yasevich out:
17678851988SVlad Yasevich 	return skb;
17778851988SVlad Yasevich }
17878851988SVlad Yasevich 
17978851988SVlad Yasevich /* Called under RCU */
18078851988SVlad Yasevich bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
18178851988SVlad Yasevich 			struct sk_buff *skb, u16 *vid)
18278851988SVlad Yasevich {
183a37b85c9SVlad Yasevich 	/* If VLAN filtering is disabled on the bridge, all packets are
184a37b85c9SVlad Yasevich 	 * permitted.
185a37b85c9SVlad Yasevich 	 */
186a37b85c9SVlad Yasevich 	if (!br->vlan_enabled)
187a37b85c9SVlad Yasevich 		return true;
188a37b85c9SVlad Yasevich 
189a37b85c9SVlad Yasevich 	/* If there are no vlan in the permitted list, all packets are
190a37b85c9SVlad Yasevich 	 * rejected.
191a37b85c9SVlad Yasevich 	 */
192a37b85c9SVlad Yasevich 	if (!v)
193a37b85c9SVlad Yasevich 		return false;
194a37b85c9SVlad Yasevich 
19578851988SVlad Yasevich 	if (br_vlan_get_tag(skb, vid)) {
19678851988SVlad Yasevich 		u16 pvid = br_get_pvid(v);
19778851988SVlad Yasevich 
19878851988SVlad Yasevich 		/* Frame did not have a tag.  See if pvid is set
19978851988SVlad Yasevich 		 * on this port.  That tells us which vlan untagged
20078851988SVlad Yasevich 		 * traffic belongs to.
20178851988SVlad Yasevich 		 */
20278851988SVlad Yasevich 		if (pvid == VLAN_N_VID)
20378851988SVlad Yasevich 			return false;
20478851988SVlad Yasevich 
20578851988SVlad Yasevich 		/* PVID is set on this port.  Any untagged ingress
20678851988SVlad Yasevich 		 * frame is considered to belong to this vlan.
20778851988SVlad Yasevich 		 */
20878851988SVlad Yasevich 		__vlan_hwaccel_put_tag(skb, pvid);
20978851988SVlad Yasevich 		return true;
21078851988SVlad Yasevich 	}
21178851988SVlad Yasevich 
21278851988SVlad Yasevich 	/* Frame had a valid vlan tag.  See if vlan is allowed */
21378851988SVlad Yasevich 	if (test_bit(*vid, v->vlan_bitmap))
214a37b85c9SVlad Yasevich 		return true;
215a37b85c9SVlad Yasevich 
216a37b85c9SVlad Yasevich 	return false;
217a37b85c9SVlad Yasevich }
218a37b85c9SVlad Yasevich 
21985f46c6bSVlad Yasevich /* Called under RCU. */
22085f46c6bSVlad Yasevich bool br_allowed_egress(struct net_bridge *br,
22185f46c6bSVlad Yasevich 		       const struct net_port_vlans *v,
22285f46c6bSVlad Yasevich 		       const struct sk_buff *skb)
22385f46c6bSVlad Yasevich {
22485f46c6bSVlad Yasevich 	u16 vid;
22585f46c6bSVlad Yasevich 
22685f46c6bSVlad Yasevich 	if (!br->vlan_enabled)
22785f46c6bSVlad Yasevich 		return true;
22885f46c6bSVlad Yasevich 
22985f46c6bSVlad Yasevich 	if (!v)
23085f46c6bSVlad Yasevich 		return false;
23185f46c6bSVlad Yasevich 
23285f46c6bSVlad Yasevich 	br_vlan_get_tag(skb, &vid);
23385f46c6bSVlad Yasevich 	if (test_bit(vid, v->vlan_bitmap))
23485f46c6bSVlad Yasevich 		return true;
23585f46c6bSVlad Yasevich 
23685f46c6bSVlad Yasevich 	return false;
23785f46c6bSVlad Yasevich }
23885f46c6bSVlad Yasevich 
239243a2e63SVlad Yasevich /* Must be protected by RTNL */
240552406c4SVlad Yasevich int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags)
241243a2e63SVlad Yasevich {
242243a2e63SVlad Yasevich 	struct net_port_vlans *pv = NULL;
243243a2e63SVlad Yasevich 	int err;
244243a2e63SVlad Yasevich 
245243a2e63SVlad Yasevich 	ASSERT_RTNL();
246243a2e63SVlad Yasevich 
247243a2e63SVlad Yasevich 	pv = rtnl_dereference(br->vlan_info);
248243a2e63SVlad Yasevich 	if (pv)
249552406c4SVlad Yasevich 		return __vlan_add(pv, vid, flags);
250243a2e63SVlad Yasevich 
251243a2e63SVlad Yasevich 	/* Create port vlan infomration
252243a2e63SVlad Yasevich 	 */
253243a2e63SVlad Yasevich 	pv = kzalloc(sizeof(*pv), GFP_KERNEL);
254243a2e63SVlad Yasevich 	if (!pv)
255243a2e63SVlad Yasevich 		return -ENOMEM;
256243a2e63SVlad Yasevich 
257243a2e63SVlad Yasevich 	pv->parent.br = br;
258552406c4SVlad Yasevich 	err = __vlan_add(pv, vid, flags);
259243a2e63SVlad Yasevich 	if (err)
260243a2e63SVlad Yasevich 		goto out;
261243a2e63SVlad Yasevich 
262243a2e63SVlad Yasevich 	rcu_assign_pointer(br->vlan_info, pv);
263243a2e63SVlad Yasevich 	return 0;
264243a2e63SVlad Yasevich out:
265243a2e63SVlad Yasevich 	kfree(pv);
266243a2e63SVlad Yasevich 	return err;
267243a2e63SVlad Yasevich }
268243a2e63SVlad Yasevich 
269243a2e63SVlad Yasevich /* Must be protected by RTNL */
270243a2e63SVlad Yasevich int br_vlan_delete(struct net_bridge *br, u16 vid)
271243a2e63SVlad Yasevich {
272243a2e63SVlad Yasevich 	struct net_port_vlans *pv;
273243a2e63SVlad Yasevich 
274243a2e63SVlad Yasevich 	ASSERT_RTNL();
275243a2e63SVlad Yasevich 
276243a2e63SVlad Yasevich 	pv = rtnl_dereference(br->vlan_info);
277243a2e63SVlad Yasevich 	if (!pv)
278243a2e63SVlad Yasevich 		return -EINVAL;
279243a2e63SVlad Yasevich 
280bc9a25d2SVlad Yasevich 	if (vid) {
281bc9a25d2SVlad Yasevich 		/* If the VID !=0 remove fdb for this vid. VID 0 is special
282bc9a25d2SVlad Yasevich 		 * in that it's the default and is always there in the fdb.
283bc9a25d2SVlad Yasevich 		 */
284bc9a25d2SVlad Yasevich 		spin_lock_bh(&br->hash_lock);
285bc9a25d2SVlad Yasevich 		fdb_delete_by_addr(br, br->dev->dev_addr, vid);
286bc9a25d2SVlad Yasevich 		spin_unlock_bh(&br->hash_lock);
287bc9a25d2SVlad Yasevich 	}
288bc9a25d2SVlad Yasevich 
289243a2e63SVlad Yasevich 	__vlan_del(pv, vid);
290243a2e63SVlad Yasevich 	return 0;
291243a2e63SVlad Yasevich }
292243a2e63SVlad Yasevich 
293243a2e63SVlad Yasevich void br_vlan_flush(struct net_bridge *br)
294243a2e63SVlad Yasevich {
295243a2e63SVlad Yasevich 	struct net_port_vlans *pv;
296243a2e63SVlad Yasevich 
297243a2e63SVlad Yasevich 	ASSERT_RTNL();
298243a2e63SVlad Yasevich 	pv = rtnl_dereference(br->vlan_info);
299243a2e63SVlad Yasevich 	if (!pv)
300243a2e63SVlad Yasevich 		return;
301243a2e63SVlad Yasevich 
302243a2e63SVlad Yasevich 	__vlan_flush(pv);
303243a2e63SVlad Yasevich }
304243a2e63SVlad Yasevich 
305243a2e63SVlad Yasevich int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val)
306243a2e63SVlad Yasevich {
307243a2e63SVlad Yasevich 	if (!rtnl_trylock())
308243a2e63SVlad Yasevich 		return restart_syscall();
309243a2e63SVlad Yasevich 
310243a2e63SVlad Yasevich 	if (br->vlan_enabled == val)
311243a2e63SVlad Yasevich 		goto unlock;
312243a2e63SVlad Yasevich 
313243a2e63SVlad Yasevich 	br->vlan_enabled = val;
314243a2e63SVlad Yasevich 
315243a2e63SVlad Yasevich unlock:
316243a2e63SVlad Yasevich 	rtnl_unlock();
317243a2e63SVlad Yasevich 	return 0;
318243a2e63SVlad Yasevich }
319243a2e63SVlad Yasevich 
320243a2e63SVlad Yasevich /* Must be protected by RTNL */
321552406c4SVlad Yasevich int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags)
322243a2e63SVlad Yasevich {
323243a2e63SVlad Yasevich 	struct net_port_vlans *pv = NULL;
324243a2e63SVlad Yasevich 	int err;
325243a2e63SVlad Yasevich 
326243a2e63SVlad Yasevich 	ASSERT_RTNL();
327243a2e63SVlad Yasevich 
328243a2e63SVlad Yasevich 	pv = rtnl_dereference(port->vlan_info);
329243a2e63SVlad Yasevich 	if (pv)
330552406c4SVlad Yasevich 		return __vlan_add(pv, vid, flags);
331243a2e63SVlad Yasevich 
332243a2e63SVlad Yasevich 	/* Create port vlan infomration
333243a2e63SVlad Yasevich 	 */
334243a2e63SVlad Yasevich 	pv = kzalloc(sizeof(*pv), GFP_KERNEL);
335243a2e63SVlad Yasevich 	if (!pv) {
336243a2e63SVlad Yasevich 		err = -ENOMEM;
337243a2e63SVlad Yasevich 		goto clean_up;
338243a2e63SVlad Yasevich 	}
339243a2e63SVlad Yasevich 
340243a2e63SVlad Yasevich 	pv->port_idx = port->port_no;
341243a2e63SVlad Yasevich 	pv->parent.port = port;
342552406c4SVlad Yasevich 	err = __vlan_add(pv, vid, flags);
343243a2e63SVlad Yasevich 	if (err)
344243a2e63SVlad Yasevich 		goto clean_up;
345243a2e63SVlad Yasevich 
346243a2e63SVlad Yasevich 	rcu_assign_pointer(port->vlan_info, pv);
347243a2e63SVlad Yasevich 	return 0;
348243a2e63SVlad Yasevich 
349243a2e63SVlad Yasevich clean_up:
350243a2e63SVlad Yasevich 	kfree(pv);
351243a2e63SVlad Yasevich 	return err;
352243a2e63SVlad Yasevich }
353243a2e63SVlad Yasevich 
354243a2e63SVlad Yasevich /* Must be protected by RTNL */
355243a2e63SVlad Yasevich int nbp_vlan_delete(struct net_bridge_port *port, u16 vid)
356243a2e63SVlad Yasevich {
357243a2e63SVlad Yasevich 	struct net_port_vlans *pv;
358243a2e63SVlad Yasevich 
359243a2e63SVlad Yasevich 	ASSERT_RTNL();
360243a2e63SVlad Yasevich 
361243a2e63SVlad Yasevich 	pv = rtnl_dereference(port->vlan_info);
362243a2e63SVlad Yasevich 	if (!pv)
363243a2e63SVlad Yasevich 		return -EINVAL;
364243a2e63SVlad Yasevich 
365bc9a25d2SVlad Yasevich 	if (vid) {
366bc9a25d2SVlad Yasevich 		/* If the VID !=0 remove fdb for this vid. VID 0 is special
367bc9a25d2SVlad Yasevich 		 * in that it's the default and is always there in the fdb.
368bc9a25d2SVlad Yasevich 		 */
369bc9a25d2SVlad Yasevich 		spin_lock_bh(&port->br->hash_lock);
370bc9a25d2SVlad Yasevich 		fdb_delete_by_addr(port->br, port->dev->dev_addr, vid);
371bc9a25d2SVlad Yasevich 		spin_unlock_bh(&port->br->hash_lock);
372bc9a25d2SVlad Yasevich 	}
373bc9a25d2SVlad Yasevich 
374243a2e63SVlad Yasevich 	return __vlan_del(pv, vid);
375243a2e63SVlad Yasevich }
376243a2e63SVlad Yasevich 
377243a2e63SVlad Yasevich void nbp_vlan_flush(struct net_bridge_port *port)
378243a2e63SVlad Yasevich {
379243a2e63SVlad Yasevich 	struct net_port_vlans *pv;
380243a2e63SVlad Yasevich 
381243a2e63SVlad Yasevich 	ASSERT_RTNL();
382243a2e63SVlad Yasevich 
383243a2e63SVlad Yasevich 	pv = rtnl_dereference(port->vlan_info);
384243a2e63SVlad Yasevich 	if (!pv)
385243a2e63SVlad Yasevich 		return;
386243a2e63SVlad Yasevich 
387243a2e63SVlad Yasevich 	__vlan_flush(pv);
388243a2e63SVlad Yasevich }
389bc9a25d2SVlad Yasevich 
390bc9a25d2SVlad Yasevich bool nbp_vlan_find(struct net_bridge_port *port, u16 vid)
391bc9a25d2SVlad Yasevich {
392bc9a25d2SVlad Yasevich 	struct net_port_vlans *pv;
393bc9a25d2SVlad Yasevich 	bool found = false;
394bc9a25d2SVlad Yasevich 
395bc9a25d2SVlad Yasevich 	rcu_read_lock();
396bc9a25d2SVlad Yasevich 	pv = rcu_dereference(port->vlan_info);
397bc9a25d2SVlad Yasevich 
398bc9a25d2SVlad Yasevich 	if (!pv)
399bc9a25d2SVlad Yasevich 		goto out;
400bc9a25d2SVlad Yasevich 
401bc9a25d2SVlad Yasevich 	if (test_bit(vid, pv->vlan_bitmap))
402bc9a25d2SVlad Yasevich 		found = true;
403bc9a25d2SVlad Yasevich 
404bc9a25d2SVlad Yasevich out:
405bc9a25d2SVlad Yasevich 	rcu_read_unlock();
406bc9a25d2SVlad Yasevich 	return found;
407bc9a25d2SVlad Yasevich }
408