From c7cdbe2efc40b366be748cd5786279ac395de181 Mon Sep 17 00:00:00 2001 From: Roopa Prabhu Date: Thu, 21 May 2020 22:26:16 -0700 Subject: [PATCH] vxlan: support for nexthop notifiers vxlan driver registers for nexthop add/del notifiers to cleanup fdb entries pointing to such nexthops. Signed-off-by: Roopa Prabhu Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 754e00240eea..3e88fbef2d4a 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -81,6 +81,7 @@ struct vxlan_fdb { u16 flags; /* see ndm_flags and below */ struct list_head nh_list; struct nexthop __rcu *nh; + struct vxlan_dev *vdev; }; #define NTF_VXLAN_ADDED_BY_USER 0x100 @@ -813,8 +814,9 @@ static int vxlan_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff) return eth_gro_complete(skb, nhoff + sizeof(struct vxlanhdr)); } -static struct vxlan_fdb *vxlan_fdb_alloc(const u8 *mac, __u16 state, - __be32 src_vni, __u16 ndm_flags) +static struct vxlan_fdb *vxlan_fdb_alloc(struct vxlan_dev *vxlan, const u8 *mac, + __u16 state, __be32 src_vni, + __u16 ndm_flags) { struct vxlan_fdb *f; @@ -826,6 +828,7 @@ static struct vxlan_fdb *vxlan_fdb_alloc(const u8 *mac, __u16 state, f->updated = f->used = jiffies; f->vni = src_vni; f->nh = NULL; + f->vdev = vxlan; INIT_LIST_HEAD(&f->nh_list); INIT_LIST_HEAD(&f->remotes); memcpy(f->eth_addr, mac, ETH_ALEN); @@ -923,7 +926,7 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan, return -ENOSPC; netdev_dbg(vxlan->dev, "add %pM -> %pIS\n", mac, ip); - f = vxlan_fdb_alloc(mac, state, src_vni, ndm_flags); + f = vxlan_fdb_alloc(vxlan, mac, state, src_vni, ndm_flags); if (!f) return -ENOMEM; @@ -988,6 +991,7 @@ static void vxlan_fdb_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f, } hlist_del_rcu(&f->hlist); + f->vdev = NULL; call_rcu(&f->rcu, vxlan_fdb_free); } @@ -4598,6 +4602,25 @@ static struct notifier_block vxlan_switchdev_notifier_block __read_mostly = { .notifier_call = vxlan_switchdev_event, }; +static int vxlan_nexthop_event(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct nexthop *nh = ptr; + struct vxlan_fdb *fdb, *tmp; + + if (!nh || event != NEXTHOP_EVENT_DEL) + return NOTIFY_DONE; + + list_for_each_entry_safe(fdb, tmp, &nh->fdb_list, nh_list) + vxlan_fdb_destroy(fdb->vdev, fdb, false, false); + + return NOTIFY_DONE; +} + +static struct notifier_block vxlan_nexthop_notifier_block __read_mostly = { + .notifier_call = vxlan_nexthop_event, +}; + static __net_init int vxlan_init_net(struct net *net) { struct vxlan_net *vn = net_generic(net, vxlan_net_id); @@ -4609,7 +4632,7 @@ static __net_init int vxlan_init_net(struct net *net) for (h = 0; h < PORT_HASH_SIZE; ++h) INIT_HLIST_HEAD(&vn->sock_list[h]); - return 0; + return register_nexthop_notifier(net, &vxlan_nexthop_notifier_block); } static void vxlan_destroy_tunnels(struct net *net, struct list_head *head) @@ -4642,6 +4665,8 @@ static void __net_exit vxlan_exit_batch_net(struct list_head *net_list) rtnl_lock(); list_for_each_entry(net, net_list, exit_list) + unregister_nexthop_notifier(net, &vxlan_nexthop_notifier_block); + list_for_each_entry(net, net_list, exit_list) vxlan_destroy_tunnels(net, &list); unregister_netdevice_many(&list); -- 2.11.0