aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_vlan.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge/br_vlan.c')
-rw-r--r--net/bridge/br_vlan.c47
1 files changed, 37 insertions, 10 deletions
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index 20057de56db0..c79940cff3a1 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -5,12 +5,33 @@
5 5
6#include "br_private.h" 6#include "br_private.h"
7 7
8static int __vlan_add(struct net_port_vlans *v, u16 vid) 8static void __vlan_add_pvid(struct net_port_vlans *v, u16 vid)
9{
10 if (v->pvid == vid)
11 return;
12
13 smp_wmb();
14 v->pvid = vid;
15}
16
17static void __vlan_delete_pvid(struct net_port_vlans *v, u16 vid)
18{
19 if (v->pvid != vid)
20 return;
21
22 smp_wmb();
23 v->pvid = 0;
24}
25
26static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags)
9{ 27{
10 int err; 28 int err;
11 29
12 if (test_bit(vid, v->vlan_bitmap)) 30 if (test_bit(vid, v->vlan_bitmap)) {
13 return -EEXIST; 31 if (flags & BRIDGE_VLAN_INFO_PVID)
32 __vlan_add_pvid(v, vid);
33 return 0;
34 }
14 35
15 if (v->port_idx && vid) { 36 if (v->port_idx && vid) {
16 struct net_device *dev = v->parent.port->dev; 37 struct net_device *dev = v->parent.port->dev;
@@ -29,6 +50,9 @@ static int __vlan_add(struct net_port_vlans *v, u16 vid)
29 50
30 set_bit(vid, v->vlan_bitmap); 51 set_bit(vid, v->vlan_bitmap);
31 v->num_vlans++; 52 v->num_vlans++;
53 if (flags & BRIDGE_VLAN_INFO_PVID)
54 __vlan_add_pvid(v, vid);
55
32 return 0; 56 return 0;
33} 57}
34 58
@@ -37,6 +61,8 @@ static int __vlan_del(struct net_port_vlans *v, u16 vid)
37 if (!test_bit(vid, v->vlan_bitmap)) 61 if (!test_bit(vid, v->vlan_bitmap))
38 return -EINVAL; 62 return -EINVAL;
39 63
64 __vlan_delete_pvid(v, vid);
65
40 if (v->port_idx && vid) { 66 if (v->port_idx && vid) {
41 struct net_device *dev = v->parent.port->dev; 67 struct net_device *dev = v->parent.port->dev;
42 68
@@ -58,6 +84,8 @@ static int __vlan_del(struct net_port_vlans *v, u16 vid)
58 84
59static void __vlan_flush(struct net_port_vlans *v) 85static void __vlan_flush(struct net_port_vlans *v)
60{ 86{
87 smp_wmb();
88 v->pvid = 0;
61 bitmap_zero(v->vlan_bitmap, BR_VLAN_BITMAP_LEN); 89 bitmap_zero(v->vlan_bitmap, BR_VLAN_BITMAP_LEN);
62 if (v->port_idx) 90 if (v->port_idx)
63 rcu_assign_pointer(v->parent.port->vlan_info, NULL); 91 rcu_assign_pointer(v->parent.port->vlan_info, NULL);
@@ -185,7 +213,7 @@ bool br_allowed_egress(struct net_bridge *br,
185} 213}
186 214
187/* Must be protected by RTNL */ 215/* Must be protected by RTNL */
188int br_vlan_add(struct net_bridge *br, u16 vid) 216int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags)
189{ 217{
190 struct net_port_vlans *pv = NULL; 218 struct net_port_vlans *pv = NULL;
191 int err; 219 int err;
@@ -194,7 +222,7 @@ int br_vlan_add(struct net_bridge *br, u16 vid)
194 222
195 pv = rtnl_dereference(br->vlan_info); 223 pv = rtnl_dereference(br->vlan_info);
196 if (pv) 224 if (pv)
197 return __vlan_add(pv, vid); 225 return __vlan_add(pv, vid, flags);
198 226
199 /* Create port vlan infomration 227 /* Create port vlan infomration
200 */ 228 */
@@ -203,7 +231,7 @@ int br_vlan_add(struct net_bridge *br, u16 vid)
203 return -ENOMEM; 231 return -ENOMEM;
204 232
205 pv->parent.br = br; 233 pv->parent.br = br;
206 err = __vlan_add(pv, vid); 234 err = __vlan_add(pv, vid, flags);
207 if (err) 235 if (err)
208 goto out; 236 goto out;
209 237
@@ -234,7 +262,6 @@ void br_vlan_flush(struct net_bridge *br)
234 struct net_port_vlans *pv; 262 struct net_port_vlans *pv;
235 263
236 ASSERT_RTNL(); 264 ASSERT_RTNL();
237
238 pv = rtnl_dereference(br->vlan_info); 265 pv = rtnl_dereference(br->vlan_info);
239 if (!pv) 266 if (!pv)
240 return; 267 return;
@@ -258,7 +285,7 @@ unlock:
258} 285}
259 286
260/* Must be protected by RTNL */ 287/* Must be protected by RTNL */
261int nbp_vlan_add(struct net_bridge_port *port, u16 vid) 288int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags)
262{ 289{
263 struct net_port_vlans *pv = NULL; 290 struct net_port_vlans *pv = NULL;
264 int err; 291 int err;
@@ -267,7 +294,7 @@ int nbp_vlan_add(struct net_bridge_port *port, u16 vid)
267 294
268 pv = rtnl_dereference(port->vlan_info); 295 pv = rtnl_dereference(port->vlan_info);
269 if (pv) 296 if (pv)
270 return __vlan_add(pv, vid); 297 return __vlan_add(pv, vid, flags);
271 298
272 /* Create port vlan infomration 299 /* Create port vlan infomration
273 */ 300 */
@@ -279,7 +306,7 @@ int nbp_vlan_add(struct net_bridge_port *port, u16 vid)
279 306
280 pv->port_idx = port->port_no; 307 pv->port_idx = port->port_no;
281 pv->parent.port = port; 308 pv->parent.port = port;
282 err = __vlan_add(pv, vid); 309 err = __vlan_add(pv, vid, flags);
283 if (err) 310 if (err)
284 goto clean_up; 311 goto clean_up;
285 312