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: Andrea Mayer <andrea.mayer@uniroma2.it>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Andrea Mayer 2020-06-20 00:54:46 +02:00 committed by David S. Miller
parent 33306f1aaf
commit a59a8ffd4a
1 changed files with 55 additions and 4 deletions

View File

@ -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;