aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_vlan.c
diff options
context:
space:
mode:
authorVlad Yasevich <vyasevic@redhat.com>2013-02-13 07:00:19 -0500
committerDavid S. Miller <davem@davemloft.net>2013-02-13 19:42:16 -0500
commitbc9a25d21ef8bad30e259af5114ccfb845c066db (patch)
tree70b44a0a84ecf60c227af9bb35c43c2f7c718d5e /net/bridge/br_vlan.c
parent1690be63a27b20ae65c792729a44f5970561ffa4 (diff)
bridge: Add vlan support for local fdb entries
When VLAN is added to the port, a local fdb entry for that port (the entry with the mac address of the port) is added for that VLAN. This way we can correctly determine if the traffic is for the bridge itself. If the address of the port changes, we try to change all the local fdb entries we have for that port. Signed-off-by: Vlad Yasevich <vyasevic@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge/br_vlan.c')
-rw-r--r--net/bridge/br_vlan.c77
1 files changed, 69 insertions, 8 deletions
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index c79940cff3a1..9ea358fbbf78 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -25,6 +25,9 @@ static void __vlan_delete_pvid(struct net_port_vlans *v, u16 vid)
25 25
26static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags) 26static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags)
27{ 27{
28 struct net_bridge_port *p = NULL;
29 struct net_bridge *br;
30 struct net_device *dev;
28 int err; 31 int err;
29 32
30 if (test_bit(vid, v->vlan_bitmap)) { 33 if (test_bit(vid, v->vlan_bitmap)) {
@@ -33,19 +36,35 @@ static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags)
33 return 0; 36 return 0;
34 } 37 }
35 38
36 if (v->port_idx && vid) { 39 if (vid) {
37 struct net_device *dev = v->parent.port->dev; 40 if (v->port_idx) {
41 p = v->parent.port;
42 br = p->br;
43 dev = p->dev;
44 } else {
45 br = v->parent.br;
46 dev = br->dev;
47 }
38 48
39 /* Add VLAN to the device filter if it is supported. 49 if (p && (dev->features & NETIF_F_HW_VLAN_FILTER)) {
40 * Stricly speaking, this is not necessary now, since devices 50 /* Add VLAN to the device filter if it is supported.
41 * are made promiscuous by the bridge, but if that ever changes 51 * Stricly speaking, this is not necessary now, since
42 * this code will allow tagged traffic to enter the bridge. 52 * devices are made promiscuous by the bridge, but if
43 */ 53 * that ever changes this code will allow tagged
44 if (dev->features & NETIF_F_HW_VLAN_FILTER) { 54 * traffic to enter the bridge.
55 */
45 err = dev->netdev_ops->ndo_vlan_rx_add_vid(dev, vid); 56 err = dev->netdev_ops->ndo_vlan_rx_add_vid(dev, vid);
46 if (err) 57 if (err)
47 return err; 58 return err;
48 } 59 }
60
61 err = br_fdb_insert(br, p, dev->dev_addr, vid);
62 if (err) {
63 br_err(br, "failed insert local address into bridge "
64 "forwarding table\n");
65 goto out_filt;
66 }
67
49 } 68 }
50 69
51 set_bit(vid, v->vlan_bitmap); 70 set_bit(vid, v->vlan_bitmap);
@@ -54,6 +73,11 @@ static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags)
54 __vlan_add_pvid(v, vid); 73 __vlan_add_pvid(v, vid);
55 74
56 return 0; 75 return 0;
76
77out_filt:
78 if (p && (dev->features & NETIF_F_HW_VLAN_FILTER))
79 dev->netdev_ops->ndo_vlan_rx_kill_vid(dev, vid);
80 return err;
57} 81}
58 82
59static int __vlan_del(struct net_port_vlans *v, u16 vid) 83static int __vlan_del(struct net_port_vlans *v, u16 vid)
@@ -253,6 +277,15 @@ int br_vlan_delete(struct net_bridge *br, u16 vid)
253 if (!pv) 277 if (!pv)
254 return -EINVAL; 278 return -EINVAL;
255 279
280 if (vid) {
281 /* If the VID !=0 remove fdb for this vid. VID 0 is special
282 * in that it's the default and is always there in the fdb.
283 */
284 spin_lock_bh(&br->hash_lock);
285 fdb_delete_by_addr(br, br->dev->dev_addr, vid);
286 spin_unlock_bh(&br->hash_lock);
287 }
288
256 __vlan_del(pv, vid); 289 __vlan_del(pv, vid);
257 return 0; 290 return 0;
258} 291}
@@ -329,6 +362,15 @@ int nbp_vlan_delete(struct net_bridge_port *port, u16 vid)
329 if (!pv) 362 if (!pv)
330 return -EINVAL; 363 return -EINVAL;
331 364
365 if (vid) {
366 /* If the VID !=0 remove fdb for this vid. VID 0 is special
367 * in that it's the default and is always there in the fdb.
368 */
369 spin_lock_bh(&port->br->hash_lock);
370 fdb_delete_by_addr(port->br, port->dev->dev_addr, vid);
371 spin_unlock_bh(&port->br->hash_lock);
372 }
373
332 return __vlan_del(pv, vid); 374 return __vlan_del(pv, vid);
333} 375}
334 376
@@ -344,3 +386,22 @@ void nbp_vlan_flush(struct net_bridge_port *port)
344 386
345 __vlan_flush(pv); 387 __vlan_flush(pv);
346} 388}
389
390bool nbp_vlan_find(struct net_bridge_port *port, u16 vid)
391{
392 struct net_port_vlans *pv;
393 bool found = false;
394
395 rcu_read_lock();
396 pv = rcu_dereference(port->vlan_info);
397
398 if (!pv)
399 goto out;
400
401 if (test_bit(vid, pv->vlan_bitmap))
402 found = true;
403
404out:
405 rcu_read_unlock();
406 return found;
407}