Skip to content

Commit

Permalink
bridge: del external_learned fdbs from device on flush or ageout
Browse files Browse the repository at this point in the history
We need to delete from offload the device externally learnded fdbs when any
one of these events happen:

1) Bridge ages out fdb.  (When bridge is doing ageing vs. device doing
ageing.  If device is doing ageing, it would send SWITCHDEV_FDB_DEL
directly).

2) STP state change flushes fdbs on port.

3) User uses sysfs interface to flush fdbs from bridge or bridge port:

	echo 1 >/sys/class/net/BR_DEV/bridge/flush
	echo 1 >/sys/class/net/BR_PORT/brport/flush

4) Offload driver send event SWITCHDEV_FDB_DEL to delete fdb entry.

For rocker, we can now get called to delete fdb entry in wait and nowait
contexts, so set NOWAIT flag when deleting fdb entry.

Signed-off-by: Scott Feldman <sfeldma@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Scott Feldman authored and David S. Miller committed Jun 16, 2015
1 parent 023033b commit b4ad7ba
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 10 deletions.
11 changes: 2 additions & 9 deletions Documentation/networking/switchdev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -251,15 +251,8 @@ out stale FDB entries. To keep an FDB entry "alive", the driver should refresh
the FDB entry by calling call_switchdev_notifiers(SWITCHDEV_FDB_ADD, ...). The
notification will reset the FDB entry's last-used time to now. The driver
should rate limit refresh notifications, for example, no more than once a
second. If the FDB entry expires, ndo_fdb_del is called to remove entry from
the device. XXX: this last part isn't currently correct: ndo_fdb_del isn't
called, so the stale entry remains in device...this need to get fixed.

FDB Flush
^^^^^^^^^

XXX: Unimplemented. Need to support FDB flush by bridge driver for port and
remove both static and learned FDB entries.
second. If the FDB entry expires, fdb_delete is called to remove entry from
the device.

STP State Change on Port
^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/rocker/rocker.c
Original file line number Diff line number Diff line change
Expand Up @@ -4392,7 +4392,7 @@ static int rocker_port_fdb_del(struct rocker_port *rocker_port,
const struct switchdev_obj_fdb *fdb)
{
__be16 vlan_id = rocker_port_vid_to_vlan(rocker_port, fdb->vid, NULL);
int flags = ROCKER_OP_FLAG_REMOVE;
int flags = ROCKER_OP_FLAG_NOWAIT | ROCKER_OP_FLAG_REMOVE;

if (!rocker_port_is_bridged(rocker_port))
return -EINVAL;
Expand Down
17 changes: 17 additions & 0 deletions net/bridge/br_fdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <linux/atomic.h>
#include <asm/unaligned.h>
#include <linux/if_vlan.h>
#include <net/switchdev.h>
#include "br_private.h"

static struct kmem_cache *br_fdb_cache __read_mostly;
Expand Down Expand Up @@ -130,11 +131,27 @@ static void fdb_del_hw_addr(struct net_bridge *br, const unsigned char *addr)
}
}

static void fdb_del_external_learn(struct net_bridge_fdb_entry *f)
{
struct switchdev_obj obj = {
.id = SWITCHDEV_OBJ_PORT_FDB,
.u.fdb = {
.addr = f->addr.addr,
.vid = f->vlan_id,
},
};

switchdev_port_obj_del(f->dst->dev, &obj);
}

static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f)
{
if (f->is_static)
fdb_del_hw_addr(br, f->addr.addr);

if (f->added_by_external_learn)
fdb_del_external_learn(f);

hlist_del_rcu(&f->hlist);
fdb_notify(br, f, RTM_DELNEIGH);
call_rcu(&f->rcu, fdb_rcu_free);
Expand Down

0 comments on commit b4ad7ba

Please sign in to comment.