Commit 9264e4ad authored by Vladimir Oltean's avatar Vladimir Oltean Committed by David S. Miller

net: dsa: flush the dynamic FDB of the software bridge when fast ageing a port

Currently, when DSA performs fast ageing on a port, 'bridge fdb' shows
us that the 'self' entries (corresponding to the hardware bridge, as
printed by dsa_slave_fdb_dump) are deleted, but the 'master' entries
(corresponding to the software bridge) aren't.

Indeed, searching through the bridge driver, neither the
brport_attr_learning handler nor the IFLA_BRPORT_LEARNING handler call
br_fdb_delete_by_port. However, br_stp_disable_port does, which is one
of the paths which DSA uses to trigger a fast ageing process anyway.

There is, however, one other very promising caller of
br_fdb_delete_by_port, and that is the bridge driver's handler of the
SWITCHDEV_FDB_FLUSH_TO_BRIDGE atomic notifier. Currently the s390/qeth
HiperSockets card driver is the only user of this.

I can't say I understand that driver's architecture or interaction with
the bridge, but it appears to not be a switchdev driver in the traditional
sense of the word. Nonetheless, the mechanism it provides is a useful
way for DSA to express the fact that it performs fast ageing too, in a
way that does not change the existing behavior for other drivers.

Cc: Alexandra Winter <wintera@linux.ibm.com>
Cc: Julian Wiedmann <jwi@linux.ibm.com>
Cc: Roopa Prabhu <roopa@nvidia.com>
Cc: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4eab90d9
...@@ -30,6 +30,24 @@ static int dsa_port_notify(const struct dsa_port *dp, unsigned long e, void *v) ...@@ -30,6 +30,24 @@ static int dsa_port_notify(const struct dsa_port *dp, unsigned long e, void *v)
return dsa_tree_notify(dp->ds->dst, e, v); return dsa_tree_notify(dp->ds->dst, e, v);
} }
static void dsa_port_notify_bridge_fdb_flush(const struct dsa_port *dp)
{
struct net_device *brport_dev = dsa_port_to_bridge_port(dp);
struct switchdev_notifier_fdb_info info = {
/* flush all VLANs */
.vid = 0,
};
/* When the port becomes standalone it has already left the bridge.
* Don't notify the bridge in that case.
*/
if (!brport_dev)
return;
call_switchdev_notifiers(SWITCHDEV_FDB_FLUSH_TO_BRIDGE,
brport_dev, &info.info, NULL);
}
static void dsa_port_fast_age(const struct dsa_port *dp) static void dsa_port_fast_age(const struct dsa_port *dp)
{ {
struct dsa_switch *ds = dp->ds; struct dsa_switch *ds = dp->ds;
...@@ -38,6 +56,8 @@ static void dsa_port_fast_age(const struct dsa_port *dp) ...@@ -38,6 +56,8 @@ static void dsa_port_fast_age(const struct dsa_port *dp)
return; return;
ds->ops->port_fast_age(ds, dp->index); ds->ops->port_fast_age(ds, dp->index);
dsa_port_notify_bridge_fdb_flush(dp);
} }
int dsa_port_set_state(struct dsa_port *dp, u8 state, bool do_fast_age) int dsa_port_set_state(struct dsa_port *dp, u8 state, bool do_fast_age)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment