Add a minimal ndo_fdb_flush implementation which flushes all entries. Support for more fine-grained filtering will be added in the following patches. Signed-off-by: Nikolay Aleksandrov <razor@xxxxxxxxxxxxx> --- net/bridge/br_device.c | 1 + net/bridge/br_fdb.c | 25 ++++++++++++++++++++++++- net/bridge/br_netlink.c | 2 +- net/bridge/br_private.h | 6 +++++- net/bridge/br_sysfs_br.c | 2 +- 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 8d6bab244c4a..76ee2675457a 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -466,6 +466,7 @@ static const struct net_device_ops br_netdev_ops = { .ndo_fdb_add = br_fdb_add, .ndo_fdb_del = br_fdb_delete, .ndo_fdb_dump = br_fdb_dump, + .ndo_fdb_flush = br_fdb_flush, .ndo_fdb_get = br_fdb_get, .ndo_bridge_getlink = br_getlink, .ndo_bridge_setlink = br_setlink, diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 6ccda68bd473..64a549acdac8 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -559,7 +559,7 @@ void br_fdb_cleanup(struct work_struct *work) } /* Completely flush all dynamic entries in forwarding database.*/ -void br_fdb_flush(struct net_bridge *br) +void __br_fdb_flush(struct net_bridge *br) { struct net_bridge_fdb_entry *f; struct hlist_node *tmp; @@ -572,6 +572,29 @@ void br_fdb_flush(struct net_bridge *br) spin_unlock_bh(&br->hash_lock); } +int br_fdb_flush(struct ndmsg *ndm, struct nlattr *tb[], + struct net_device *dev, u16 vid, + struct netlink_ext_ack *extack) +{ + struct net_bridge *br; + + if (netif_is_bridge_master(dev)) { + br = netdev_priv(dev); + } else { + struct net_bridge_port *p = br_port_get_rtnl(dev); + + if (!p) { + NL_SET_ERR_MSG_MOD(extack, "Device is not a bridge port"); + return -EINVAL; + } + br = p->br; + } + + __br_fdb_flush(br); + + return 0; +} + /* Flush all entries referring to a specific port. * if do_all is set also flush static entries * if vid is set delete all entries that match the vlan_id diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 200ad05b296f..c59c775730bb 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -1327,7 +1327,7 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[], } if (data[IFLA_BR_FDB_FLUSH]) - br_fdb_flush(br); + __br_fdb_flush(br); #ifdef CONFIG_BRIDGE_IGMP_SNOOPING if (data[IFLA_BR_MCAST_ROUTER]) { diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 6e62af2e07e9..23ef2982d1bc 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -759,7 +759,11 @@ int br_fdb_init(void); void br_fdb_fini(void); int br_fdb_hash_init(struct net_bridge *br); void br_fdb_hash_fini(struct net_bridge *br); -void br_fdb_flush(struct net_bridge *br); +void __br_fdb_flush(struct net_bridge *br); +int br_fdb_flush(struct ndmsg *ndm, struct nlattr *tb[], + struct net_device *dev, u16 vid, + struct netlink_ext_ack *extack); + void br_fdb_find_delete_local(struct net_bridge *br, const struct net_bridge_port *p, const unsigned char *addr, u16 vid); diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index 3f7ca88c2aa3..7a2cf3aebc84 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c @@ -344,7 +344,7 @@ static DEVICE_ATTR_RW(group_addr); static int set_flush(struct net_bridge *br, unsigned long val, struct netlink_ext_ack *extack) { - br_fdb_flush(br); + __br_fdb_flush(br); return 0; } -- 2.35.1