Commit c7cdbe2e authored by Roopa Prabhu's avatar Roopa Prabhu Committed by David S. Miller
Browse files

vxlan: support for nexthop notifiers



vxlan driver registers for nexthop add/del notifiers to
cleanup fdb entries pointing to such nexthops.

Signed-off-by: default avatarRoopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8590ceed
Loading
Loading
Loading
Loading
+29 −4
Original line number Diff line number Diff line
@@ -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)
@@ -4641,6 +4664,8 @@ static void __net_exit vxlan_exit_batch_net(struct list_head *net_list)
	LIST_HEAD(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);