vxlan fdb can have NDA_IFINDEX, which indicates an out interface. If the interface is removed, that fdb will not work. So, when interface is removed, vxlan's fdb can be removed.
Test commands: ip link add dummy0 type dummy ip link add vxlan0 type vxlan vni 1000 bridge fdb add 11:22:33:44:55:66 dst 1.1.1.1 dev vxlan0 via dummy0 self ip link del dummy0 Before this patch, fdbs will not be removed. Result: bridge fdb show dev vxlan0 11:22:33:44:55:66 dst 1.1.1.1 via if10 self permanent 'if10' indicates 'dummy0' interface index. But the dummy0 interface was removed so this fdb will not work. Signed-off-by: Taehee Yoo <ap420...@gmail.com> --- drivers/net/vxlan.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index a0015cdedfaf..52ca735bd91a 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -4440,6 +4440,39 @@ struct net_device *vxlan_dev_create(struct net *net, const char *name, } EXPORT_SYMBOL_GPL(vxlan_dev_create); +static void vxlan_delete_rdst(struct vxlan_dev *vxlan, unsigned int h, + int ifindex) +{ + struct hlist_node *tmp; + struct vxlan_fdb *f; + + spin_lock_bh(&vxlan->hash_lock[h]); + hlist_for_each_entry_safe(f, tmp, &vxlan->fdb_head[h], hlist) { + struct vxlan_rdst *rd, *rd_next; + + list_for_each_entry_safe(rd, rd_next, &f->remotes, list) { + if (rd->remote_ifindex != ifindex) + continue; + + if (list_is_singular(&f->remotes)) + vxlan_fdb_destroy(vxlan, f, true, true); + else + vxlan_fdb_dst_destroy(vxlan, f, rd, true); + } + } + spin_unlock_bh(&vxlan->hash_lock[h]); +} + +static void vxlan_delete_rdsts(struct vxlan_net *vn, struct net_device *dev) +{ + struct vxlan_dev *vxlan, *next; + unsigned int h; + + list_for_each_entry_safe(vxlan, next, &vn->vxlan_list, next) + for (h = 0; h < FDB_HASH_SIZE; ++h) + vxlan_delete_rdst(vxlan, h, dev->ifindex); +} + static void vxlan_handle_lowerdev_unregister(struct vxlan_net *vn, struct net_device *dev) { @@ -4470,6 +4503,7 @@ static int vxlan_netdevice_event(struct notifier_block *unused, if (event == NETDEV_UNREGISTER) { vxlan_offload_rx_ports(dev, false); + vxlan_delete_rdsts(vn, dev); vxlan_handle_lowerdev_unregister(vn, dev); } else if (event == NETDEV_REGISTER) { vxlan_offload_rx_ports(dev, true); -- 2.17.1