Commit a59a8ffd authored by Andrea Mayer's avatar Andrea Mayer Committed by David S. Miller
Browse files

vrf: add l3mdev registration for table to VRF device lookup



During the initialization phase of the VRF module, the callback for table
to VRF device lookup is registered in l3mdev.

Signed-off-by: default avatarAndrea Mayer <andrea.mayer@uniroma2.it>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 33306f1a
Loading
Loading
Loading
Loading
+55 −4
Original line number Diff line number Diff line
@@ -183,6 +183,19 @@ static struct vrf_map *netns_vrf_map_by_dev(struct net_device *dev)
	return netns_vrf_map(dev_net(dev));
}

static int vrf_map_elem_get_vrf_ifindex(struct vrf_map_elem *me)
{
	struct list_head *me_head = &me->vrf_list;
	struct net_vrf *vrf;

	if (list_empty(me_head))
		return -ENODEV;

	vrf = list_first_entry(me_head, struct net_vrf, me_list);

	return vrf->ifindex;
}

static struct vrf_map_elem *vrf_map_elem_alloc(gfp_t flags)
{
	struct vrf_map_elem *me;
@@ -384,6 +397,34 @@ unlock:
	vrf_map_unlock(vmap);
}

/* return the vrf device index associated with the table_id */
static int vrf_ifindex_lookup_by_table_id(struct net *net, u32 table_id)
{
	struct vrf_map *vmap = netns_vrf_map(net);
	struct vrf_map_elem *me;
	int ifindex;

	vrf_map_lock(vmap);

	if (!vmap->strict_mode) {
		ifindex = -EPERM;
		goto unlock;
	}

	me = vrf_map_lookup_elem(vmap, table_id);
	if (!me) {
		ifindex = -ENODEV;
		goto unlock;
	}

	ifindex = vrf_map_elem_get_vrf_ifindex(me);

unlock:
	vrf_map_unlock(vmap);

	return ifindex;
}

/* by default VRF devices do not have a qdisc and are expected
 * to be created with only a single queue.
 */
@@ -1847,14 +1888,24 @@ static int __init vrf_init_module(void)
	if (rc < 0)
		goto error;

	rc = l3mdev_table_lookup_register(L3MDEV_TYPE_VRF,
					  vrf_ifindex_lookup_by_table_id);
	if (rc < 0)
		goto unreg_pernet;

	rc = rtnl_link_register(&vrf_link_ops);
	if (rc < 0) {
		unregister_pernet_subsys(&vrf_net_ops);
		goto error;
	}
	if (rc < 0)
		goto table_lookup_unreg;

	return 0;

table_lookup_unreg:
	l3mdev_table_lookup_unregister(L3MDEV_TYPE_VRF,
				       vrf_ifindex_lookup_by_table_id);

unreg_pernet:
	unregister_pernet_subsys(&vrf_net_ops);

error:
	unregister_netdevice_notifier(&vrf_notifier_block);
	return rc;