Skip to content

Commit

Permalink
bridge: Fix the way to insert new local fdb entries in br_fdb_changeaddr
Browse files Browse the repository at this point in the history
Since commit bc9a25d ("bridge: Add vlan support for local fdb entries"),
br_fdb_changeaddr() has inserted a new local fdb entry only if it can
find old one. But if we have two ports where they have the same address
or user has deleted a local entry, there will be no entry for one of the
ports.

Example of problematic case:
  ip link set eth0 address aa:bb:cc:dd:ee:ff
  ip link set eth1 address aa:bb:cc:dd:ee:ff
  brctl addif br0 eth0
  brctl addif br0 eth1 # eth1 will not have a local entry due to dup.
  ip link set eth1 address 12:34:56:78:90:ab
Then, the new entry for the address 12:34:56:78:90:ab will not be
created, and the bridge device will not be able to communicate.

Insert new entries regardless of whether we can find old entries or not.

Signed-off-by: Toshiaki Makita <[email protected]>
Acked-by: Vlad Yasevich <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Toshiaki Makita authored and davem330 committed Feb 10, 2014
1 parent a5642ab commit 2836882
Showing 1 changed file with 20 additions and 9 deletions.
29 changes: 20 additions & 9 deletions net/bridge/br_fdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,10 @@ static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f)
void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr)
{
struct net_bridge *br = p->br;
bool no_vlan = (nbp_get_vlan_info(p) == NULL) ? true : false;
struct net_port_vlans *pv = nbp_get_vlan_info(p);
bool no_vlan = !pv;
int i;
u16 vid;

spin_lock_bh(&br->hash_lock);

Expand All @@ -114,28 +116,37 @@ void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr)
f->addr.addr) &&
nbp_vlan_find(op, vid)) {
f->dst = op;
goto insert;
goto skip_delete;
}
}

/* delete old one */
fdb_delete(br, f);
insert:
/* insert new address, may fail if invalid
* address or dup.
*/
fdb_insert(br, p, newaddr, vid);

skip_delete:
/* if this port has no vlan information
* configured, we can safely be done at
* this point.
*/
if (no_vlan)
goto done;
goto insert;
}
}
}

insert:
/* insert new address, may fail if invalid address or dup. */
fdb_insert(br, p, newaddr, 0);

if (no_vlan)
goto done;

/* Now add entries for every VLAN configured on the port.
* This function runs under RTNL so the bitmap will not change
* from under us.
*/
for_each_set_bit(vid, pv->vlan_bitmap, VLAN_N_VID)
fdb_insert(br, p, newaddr, vid);

done:
spin_unlock_bh(&br->hash_lock);
}
Expand Down

0 comments on commit 2836882

Please sign in to comment.