diff options
Diffstat (limited to 'net/bridge/br_vlan.c')
-rw-r--r-- | net/bridge/br_vlan.c | 137 |
1 files changed, 71 insertions, 66 deletions
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 9a9ffe7e4019..af5ebd18d705 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c | |||
@@ -34,7 +34,6 @@ static void __vlan_add_flags(struct net_port_vlans *v, u16 vid, u16 flags) | |||
34 | 34 | ||
35 | static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags) | 35 | static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags) |
36 | { | 36 | { |
37 | const struct net_device_ops *ops; | ||
38 | struct net_bridge_port *p = NULL; | 37 | struct net_bridge_port *p = NULL; |
39 | struct net_bridge *br; | 38 | struct net_bridge *br; |
40 | struct net_device *dev; | 39 | struct net_device *dev; |
@@ -45,37 +44,32 @@ static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags) | |||
45 | return 0; | 44 | return 0; |
46 | } | 45 | } |
47 | 46 | ||
48 | if (vid) { | 47 | if (v->port_idx) { |
49 | if (v->port_idx) { | 48 | p = v->parent.port; |
50 | p = v->parent.port; | 49 | br = p->br; |
51 | br = p->br; | 50 | dev = p->dev; |
52 | dev = p->dev; | 51 | } else { |
53 | } else { | 52 | br = v->parent.br; |
54 | br = v->parent.br; | 53 | dev = br->dev; |
55 | dev = br->dev; | 54 | } |
56 | } | ||
57 | ops = dev->netdev_ops; | ||
58 | |||
59 | if (p && (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) { | ||
60 | /* Add VLAN to the device filter if it is supported. | ||
61 | * Stricly speaking, this is not necessary now, since | ||
62 | * devices are made promiscuous by the bridge, but if | ||
63 | * that ever changes this code will allow tagged | ||
64 | * traffic to enter the bridge. | ||
65 | */ | ||
66 | err = ops->ndo_vlan_rx_add_vid(dev, htons(ETH_P_8021Q), | ||
67 | vid); | ||
68 | if (err) | ||
69 | return err; | ||
70 | } | ||
71 | 55 | ||
72 | err = br_fdb_insert(br, p, dev->dev_addr, vid); | 56 | if (p) { |
73 | if (err) { | 57 | /* Add VLAN to the device filter if it is supported. |
74 | br_err(br, "failed insert local address into bridge " | 58 | * Stricly speaking, this is not necessary now, since |
75 | "forwarding table\n"); | 59 | * devices are made promiscuous by the bridge, but if |
76 | goto out_filt; | 60 | * that ever changes this code will allow tagged |
77 | } | 61 | * traffic to enter the bridge. |
62 | */ | ||
63 | err = vlan_vid_add(dev, htons(ETH_P_8021Q), vid); | ||
64 | if (err) | ||
65 | return err; | ||
66 | } | ||
78 | 67 | ||
68 | err = br_fdb_insert(br, p, dev->dev_addr, vid); | ||
69 | if (err) { | ||
70 | br_err(br, "failed insert local address into bridge " | ||
71 | "forwarding table\n"); | ||
72 | goto out_filt; | ||
79 | } | 73 | } |
80 | 74 | ||
81 | set_bit(vid, v->vlan_bitmap); | 75 | set_bit(vid, v->vlan_bitmap); |
@@ -85,8 +79,8 @@ static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags) | |||
85 | return 0; | 79 | return 0; |
86 | 80 | ||
87 | out_filt: | 81 | out_filt: |
88 | if (p && (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) | 82 | if (p) |
89 | ops->ndo_vlan_rx_kill_vid(dev, htons(ETH_P_8021Q), vid); | 83 | vlan_vid_del(dev, htons(ETH_P_8021Q), vid); |
90 | return err; | 84 | return err; |
91 | } | 85 | } |
92 | 86 | ||
@@ -98,13 +92,8 @@ static int __vlan_del(struct net_port_vlans *v, u16 vid) | |||
98 | __vlan_delete_pvid(v, vid); | 92 | __vlan_delete_pvid(v, vid); |
99 | clear_bit(vid, v->untagged_bitmap); | 93 | clear_bit(vid, v->untagged_bitmap); |
100 | 94 | ||
101 | if (v->port_idx && vid) { | 95 | if (v->port_idx) |
102 | struct net_device *dev = v->parent.port->dev; | 96 | vlan_vid_del(v->parent.port->dev, htons(ETH_P_8021Q), vid); |
103 | const struct net_device_ops *ops = dev->netdev_ops; | ||
104 | |||
105 | if (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER) | ||
106 | ops->ndo_vlan_rx_kill_vid(dev, htons(ETH_P_8021Q), vid); | ||
107 | } | ||
108 | 97 | ||
109 | clear_bit(vid, v->vlan_bitmap); | 98 | clear_bit(vid, v->vlan_bitmap); |
110 | v->num_vlans--; | 99 | v->num_vlans--; |
@@ -192,6 +181,8 @@ out: | |||
192 | bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, | 181 | bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, |
193 | struct sk_buff *skb, u16 *vid) | 182 | struct sk_buff *skb, u16 *vid) |
194 | { | 183 | { |
184 | int err; | ||
185 | |||
195 | /* If VLAN filtering is disabled on the bridge, all packets are | 186 | /* If VLAN filtering is disabled on the bridge, all packets are |
196 | * permitted. | 187 | * permitted. |
197 | */ | 188 | */ |
@@ -204,20 +195,32 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, | |||
204 | if (!v) | 195 | if (!v) |
205 | return false; | 196 | return false; |
206 | 197 | ||
207 | if (br_vlan_get_tag(skb, vid)) { | 198 | err = br_vlan_get_tag(skb, vid); |
199 | if (!*vid) { | ||
208 | u16 pvid = br_get_pvid(v); | 200 | u16 pvid = br_get_pvid(v); |
209 | 201 | ||
210 | /* Frame did not have a tag. See if pvid is set | 202 | /* Frame had a tag with VID 0 or did not have a tag. |
211 | * on this port. That tells us which vlan untagged | 203 | * See if pvid is set on this port. That tells us which |
212 | * traffic belongs to. | 204 | * vlan untagged or priority-tagged traffic belongs to. |
213 | */ | 205 | */ |
214 | if (pvid == VLAN_N_VID) | 206 | if (pvid == VLAN_N_VID) |
215 | return false; | 207 | return false; |
216 | 208 | ||
217 | /* PVID is set on this port. Any untagged ingress | 209 | /* PVID is set on this port. Any untagged or priority-tagged |
218 | * frame is considered to belong to this vlan. | 210 | * ingress frame is considered to belong to this vlan. |
219 | */ | 211 | */ |
220 | __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), pvid); | 212 | *vid = pvid; |
213 | if (likely(err)) | ||
214 | /* Untagged Frame. */ | ||
215 | __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), pvid); | ||
216 | else | ||
217 | /* Priority-tagged Frame. | ||
218 | * At this point, We know that skb->vlan_tci had | ||
219 | * VLAN_TAG_PRESENT bit and its VID field was 0x000. | ||
220 | * We update only VID field and preserve PCP field. | ||
221 | */ | ||
222 | skb->vlan_tci |= pvid; | ||
223 | |||
221 | return true; | 224 | return true; |
222 | } | 225 | } |
223 | 226 | ||
@@ -248,7 +251,9 @@ bool br_allowed_egress(struct net_bridge *br, | |||
248 | return false; | 251 | return false; |
249 | } | 252 | } |
250 | 253 | ||
251 | /* Must be protected by RTNL */ | 254 | /* Must be protected by RTNL. |
255 | * Must be called with vid in range from 1 to 4094 inclusive. | ||
256 | */ | ||
252 | int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags) | 257 | int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags) |
253 | { | 258 | { |
254 | struct net_port_vlans *pv = NULL; | 259 | struct net_port_vlans *pv = NULL; |
@@ -278,7 +283,9 @@ out: | |||
278 | return err; | 283 | return err; |
279 | } | 284 | } |
280 | 285 | ||
281 | /* Must be protected by RTNL */ | 286 | /* Must be protected by RTNL. |
287 | * Must be called with vid in range from 1 to 4094 inclusive. | ||
288 | */ | ||
282 | int br_vlan_delete(struct net_bridge *br, u16 vid) | 289 | int br_vlan_delete(struct net_bridge *br, u16 vid) |
283 | { | 290 | { |
284 | struct net_port_vlans *pv; | 291 | struct net_port_vlans *pv; |
@@ -289,14 +296,9 @@ int br_vlan_delete(struct net_bridge *br, u16 vid) | |||
289 | if (!pv) | 296 | if (!pv) |
290 | return -EINVAL; | 297 | return -EINVAL; |
291 | 298 | ||
292 | if (vid) { | 299 | spin_lock_bh(&br->hash_lock); |
293 | /* If the VID !=0 remove fdb for this vid. VID 0 is special | 300 | fdb_delete_by_addr(br, br->dev->dev_addr, vid); |
294 | * in that it's the default and is always there in the fdb. | 301 | spin_unlock_bh(&br->hash_lock); |
295 | */ | ||
296 | spin_lock_bh(&br->hash_lock); | ||
297 | fdb_delete_by_addr(br, br->dev->dev_addr, vid); | ||
298 | spin_unlock_bh(&br->hash_lock); | ||
299 | } | ||
300 | 302 | ||
301 | __vlan_del(pv, vid); | 303 | __vlan_del(pv, vid); |
302 | return 0; | 304 | return 0; |
@@ -329,7 +331,9 @@ unlock: | |||
329 | return 0; | 331 | return 0; |
330 | } | 332 | } |
331 | 333 | ||
332 | /* Must be protected by RTNL */ | 334 | /* Must be protected by RTNL. |
335 | * Must be called with vid in range from 1 to 4094 inclusive. | ||
336 | */ | ||
333 | int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags) | 337 | int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags) |
334 | { | 338 | { |
335 | struct net_port_vlans *pv = NULL; | 339 | struct net_port_vlans *pv = NULL; |
@@ -363,7 +367,9 @@ clean_up: | |||
363 | return err; | 367 | return err; |
364 | } | 368 | } |
365 | 369 | ||
366 | /* Must be protected by RTNL */ | 370 | /* Must be protected by RTNL. |
371 | * Must be called with vid in range from 1 to 4094 inclusive. | ||
372 | */ | ||
367 | int nbp_vlan_delete(struct net_bridge_port *port, u16 vid) | 373 | int nbp_vlan_delete(struct net_bridge_port *port, u16 vid) |
368 | { | 374 | { |
369 | struct net_port_vlans *pv; | 375 | struct net_port_vlans *pv; |
@@ -374,14 +380,9 @@ int nbp_vlan_delete(struct net_bridge_port *port, u16 vid) | |||
374 | if (!pv) | 380 | if (!pv) |
375 | return -EINVAL; | 381 | return -EINVAL; |
376 | 382 | ||
377 | if (vid) { | 383 | spin_lock_bh(&port->br->hash_lock); |
378 | /* If the VID !=0 remove fdb for this vid. VID 0 is special | 384 | fdb_delete_by_addr(port->br, port->dev->dev_addr, vid); |
379 | * in that it's the default and is always there in the fdb. | 385 | spin_unlock_bh(&port->br->hash_lock); |
380 | */ | ||
381 | spin_lock_bh(&port->br->hash_lock); | ||
382 | fdb_delete_by_addr(port->br, port->dev->dev_addr, vid); | ||
383 | spin_unlock_bh(&port->br->hash_lock); | ||
384 | } | ||
385 | 386 | ||
386 | return __vlan_del(pv, vid); | 387 | return __vlan_del(pv, vid); |
387 | } | 388 | } |
@@ -389,6 +390,7 @@ int nbp_vlan_delete(struct net_bridge_port *port, u16 vid) | |||
389 | void nbp_vlan_flush(struct net_bridge_port *port) | 390 | void nbp_vlan_flush(struct net_bridge_port *port) |
390 | { | 391 | { |
391 | struct net_port_vlans *pv; | 392 | struct net_port_vlans *pv; |
393 | u16 vid; | ||
392 | 394 | ||
393 | ASSERT_RTNL(); | 395 | ASSERT_RTNL(); |
394 | 396 | ||
@@ -396,6 +398,9 @@ void nbp_vlan_flush(struct net_bridge_port *port) | |||
396 | if (!pv) | 398 | if (!pv) |
397 | return; | 399 | return; |
398 | 400 | ||
401 | for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID) | ||
402 | vlan_vid_del(port->dev, htons(ETH_P_8021Q), vid); | ||
403 | |||
399 | __vlan_flush(pv); | 404 | __vlan_flush(pv); |
400 | } | 405 | } |
401 | 406 | ||