From dea9b71dad887f2125dae4df1c447041d24fea23 Mon Sep 17 00:00:00 2001 From: Jan Sondhauss Date: Mon, 4 Mar 2024 07:25:53 +0100 Subject: [PATCH] net: bridge: flush switchdev port fdb When a switchdev's port is assinged to a bridge, there is a sysfs file /sys/..//brport/flush that flushes the fdb entries of that port. The bridge code notifies the switchdev for each entry individually via SWITCHDEV_FDB_DEL_TO_DEVICE. The flush only affects dynamic fdb entries. Local and user created entries will remain in the fdb. Most switch hw has special operations to flush all dynamically learned neighbours. In contrast its not common that a switch allows for individual dynamic fdb entries to get flushed and its also prevented by the DSA framework. This commit introduces a new swichtdev_notifier_type SWITCHDEV_FDB_FLUSH_TO_DEVICE that is called in br_fdb_delete_by_port Signed-off-by: Jan Sondhauss --- include/net/switchdev.h | 1 + net/bridge/br_fdb.c | 1 + net/bridge/br_private.h | 2 ++ net/bridge/br_switchdev.c | 17 +++++++++++++++++ 4 files changed, 21 insertions(+) diff --git a/include/net/switchdev.h b/include/net/switchdev.h index a43062d4c734..f9c0bc36d2bf 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -216,6 +216,7 @@ enum switchdev_notifier_type { SWITCHDEV_FDB_DEL_TO_DEVICE, SWITCHDEV_FDB_OFFLOADED, SWITCHDEV_FDB_FLUSH_TO_BRIDGE, + SWITCHDEV_FDB_FLUSH_TO_DEVICE, SWITCHDEV_PORT_OBJ_ADD, /* Blocking. */ SWITCHDEV_PORT_OBJ_DEL, /* Blocking. */ diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index e69a872bfc1d..c9016fdd3226 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -734,6 +734,7 @@ void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_fdb_entry *f; struct hlist_node *tmp; + br_switchdev_fdb_flush_notify(p->br, p); spin_lock_bh(&br->hash_lock); hlist_for_each_entry_safe(f, tmp, &br->fdb_list, fdb_node) { if (f->dst != p) diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index a1f4acfa6994..4e34a0b094b8 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -2141,6 +2141,8 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p, struct netlink_ext_ack *extack); void br_switchdev_fdb_notify(struct net_bridge *br, const struct net_bridge_fdb_entry *fdb, int type); +int br_switchdev_fdb_flush_notify(struct net_bridge *br, + const struct net_bridge_port *port); void br_switchdev_mdb_notify(struct net_device *dev, struct net_bridge_mdb_entry *mp, struct net_bridge_port_group *pg, diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c index ee84e783e1df..7b8005c4c069 100644 --- a/net/bridge/br_switchdev.c +++ b/net/bridge/br_switchdev.c @@ -173,6 +173,23 @@ br_switchdev_fdb_notify(struct net_bridge *br, } } +int br_switchdev_fdb_flush_notify(struct net_bridge *br, + const struct net_bridge_port *port) +{ + static const u8 addr[ETH_ALEN] = {0}; + struct net_device *ndev = port ? port->dev : br->dev; + struct switchdev_notifier_fdb_info info = { + .vid = 0, + .is_local = 0, + .offloaded = 0, + .addr = &addr[0], + .added_by_user = 0, + }; + + return call_switchdev_notifiers(SWITCHDEV_FDB_FLUSH_TO_DEVICE, ndev, + &info.info, NULL); +} + int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags, bool changed, struct netlink_ext_ack *extack) {