mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	vrf: Handle CONFIG_SYSCTL not set
Randy reported compile failure when CONFIG_SYSCTL is not set/enabled:
ERROR: modpost: "sysctl_vals" [drivers/net/vrf.ko] undefined!
Fix by splitting out the sysctl init and cleanup into helpers that
can be set to do nothing when CONFIG_SYSCTL is disabled. In addition,
move vrf_strict_mode and vrf_strict_mode_change to above
vrf_shared_table_handler (code move only) and wrap all of it
in the ifdef CONFIG_SYSCTL.
Update the strict mode tests to check for the existence of the
/proc/sys entry.
Fixes: 33306f1aaf ("vrf: add sysctl parameter for strict mode")
Cc: Andrea Mayer <andrea.mayer@uniroma2.it>
Reported-by: Randy Dunlap <rdunlap@infradead.org>
Signed-off-by: David Ahern <dsahern@kernel.org>
Acked-by: Randy Dunlap <rdunlap@infradead.org> # build-tested
Signed-off-by: David S. Miller <davem@davemloft.net>
			
			
This commit is contained in:
		
							parent
							
								
									5df5661a13
								
							
						
					
					
						commit
						1b6687e31a
					
				
					 2 changed files with 83 additions and 61 deletions
				
			
		| 
						 | 
				
			
			@ -260,52 +260,6 @@ static void vrf_map_unlock(struct vrf_map *vmap) __releases(&vmap->vmap_lock)
 | 
			
		|||
	spin_unlock(&vmap->vmap_lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool vrf_strict_mode(struct vrf_map *vmap)
 | 
			
		||||
{
 | 
			
		||||
	bool strict_mode;
 | 
			
		||||
 | 
			
		||||
	vrf_map_lock(vmap);
 | 
			
		||||
	strict_mode = vmap->strict_mode;
 | 
			
		||||
	vrf_map_unlock(vmap);
 | 
			
		||||
 | 
			
		||||
	return strict_mode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int vrf_strict_mode_change(struct vrf_map *vmap, bool new_mode)
 | 
			
		||||
{
 | 
			
		||||
	bool *cur_mode;
 | 
			
		||||
	int res = 0;
 | 
			
		||||
 | 
			
		||||
	vrf_map_lock(vmap);
 | 
			
		||||
 | 
			
		||||
	cur_mode = &vmap->strict_mode;
 | 
			
		||||
	if (*cur_mode == new_mode)
 | 
			
		||||
		goto unlock;
 | 
			
		||||
 | 
			
		||||
	if (*cur_mode) {
 | 
			
		||||
		/* disable strict mode */
 | 
			
		||||
		*cur_mode = false;
 | 
			
		||||
	} else {
 | 
			
		||||
		if (vmap->shared_tables) {
 | 
			
		||||
			/* we cannot allow strict_mode because there are some
 | 
			
		||||
			 * vrfs that share one or more tables.
 | 
			
		||||
			 */
 | 
			
		||||
			res = -EBUSY;
 | 
			
		||||
			goto unlock;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* no tables are shared among vrfs, so we can go back
 | 
			
		||||
		 * to 1:1 association between a vrf with its table.
 | 
			
		||||
		 */
 | 
			
		||||
		*cur_mode = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
unlock:
 | 
			
		||||
	vrf_map_unlock(vmap);
 | 
			
		||||
 | 
			
		||||
	return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* called with rtnl lock held */
 | 
			
		||||
static int
 | 
			
		||||
vrf_map_register_dev(struct net_device *dev, struct netlink_ext_ack *extack)
 | 
			
		||||
| 
						 | 
				
			
			@ -1790,6 +1744,53 @@ static int vrf_map_init(struct vrf_map *vmap)
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_SYSCTL
 | 
			
		||||
static bool vrf_strict_mode(struct vrf_map *vmap)
 | 
			
		||||
{
 | 
			
		||||
	bool strict_mode;
 | 
			
		||||
 | 
			
		||||
	vrf_map_lock(vmap);
 | 
			
		||||
	strict_mode = vmap->strict_mode;
 | 
			
		||||
	vrf_map_unlock(vmap);
 | 
			
		||||
 | 
			
		||||
	return strict_mode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int vrf_strict_mode_change(struct vrf_map *vmap, bool new_mode)
 | 
			
		||||
{
 | 
			
		||||
	bool *cur_mode;
 | 
			
		||||
	int res = 0;
 | 
			
		||||
 | 
			
		||||
	vrf_map_lock(vmap);
 | 
			
		||||
 | 
			
		||||
	cur_mode = &vmap->strict_mode;
 | 
			
		||||
	if (*cur_mode == new_mode)
 | 
			
		||||
		goto unlock;
 | 
			
		||||
 | 
			
		||||
	if (*cur_mode) {
 | 
			
		||||
		/* disable strict mode */
 | 
			
		||||
		*cur_mode = false;
 | 
			
		||||
	} else {
 | 
			
		||||
		if (vmap->shared_tables) {
 | 
			
		||||
			/* we cannot allow strict_mode because there are some
 | 
			
		||||
			 * vrfs that share one or more tables.
 | 
			
		||||
			 */
 | 
			
		||||
			res = -EBUSY;
 | 
			
		||||
			goto unlock;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* no tables are shared among vrfs, so we can go back
 | 
			
		||||
		 * to 1:1 association between a vrf with its table.
 | 
			
		||||
		 */
 | 
			
		||||
		*cur_mode = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
unlock:
 | 
			
		||||
	vrf_map_unlock(vmap);
 | 
			
		||||
 | 
			
		||||
	return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int vrf_shared_table_handler(struct ctl_table *table, int write,
 | 
			
		||||
				    void *buffer, size_t *lenp, loff_t *ppos)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -1830,15 +1831,9 @@ static const struct ctl_table vrf_table[] = {
 | 
			
		|||
	{ },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Initialize per network namespace state */
 | 
			
		||||
static int __net_init vrf_netns_init(struct net *net)
 | 
			
		||||
static int vrf_netns_init_sysctl(struct net *net, struct netns_vrf *nn_vrf)
 | 
			
		||||
{
 | 
			
		||||
	struct netns_vrf *nn_vrf = net_generic(net, vrf_net_id);
 | 
			
		||||
	struct ctl_table *table;
 | 
			
		||||
	int res;
 | 
			
		||||
 | 
			
		||||
	nn_vrf->add_fib_rules = true;
 | 
			
		||||
	vrf_map_init(&nn_vrf->vmap);
 | 
			
		||||
 | 
			
		||||
	table = kmemdup(vrf_table, sizeof(vrf_table), GFP_KERNEL);
 | 
			
		||||
	if (!table)
 | 
			
		||||
| 
						 | 
				
			
			@ -1849,19 +1844,14 @@ static int __net_init vrf_netns_init(struct net *net)
 | 
			
		|||
 | 
			
		||||
	nn_vrf->ctl_hdr = register_net_sysctl(net, "net/vrf", table);
 | 
			
		||||
	if (!nn_vrf->ctl_hdr) {
 | 
			
		||||
		res = -ENOMEM;
 | 
			
		||||
		goto free_table;
 | 
			
		||||
		kfree(table);
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
free_table:
 | 
			
		||||
	kfree(table);
 | 
			
		||||
 | 
			
		||||
	return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void __net_exit vrf_netns_exit(struct net *net)
 | 
			
		||||
static void vrf_netns_exit_sysctl(struct net *net)
 | 
			
		||||
{
 | 
			
		||||
	struct netns_vrf *nn_vrf = net_generic(net, vrf_net_id);
 | 
			
		||||
	struct ctl_table *table;
 | 
			
		||||
| 
						 | 
				
			
			@ -1870,6 +1860,32 @@ static void __net_exit vrf_netns_exit(struct net *net)
 | 
			
		|||
	unregister_net_sysctl_table(nn_vrf->ctl_hdr);
 | 
			
		||||
	kfree(table);
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
static int vrf_netns_init_sysctl(struct net *net, struct netns_vrf *nn_vrf)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void vrf_netns_exit_sysctl(struct net *net)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Initialize per network namespace state */
 | 
			
		||||
static int __net_init vrf_netns_init(struct net *net)
 | 
			
		||||
{
 | 
			
		||||
	struct netns_vrf *nn_vrf = net_generic(net, vrf_net_id);
 | 
			
		||||
 | 
			
		||||
	nn_vrf->add_fib_rules = true;
 | 
			
		||||
	vrf_map_init(&nn_vrf->vmap);
 | 
			
		||||
 | 
			
		||||
	return vrf_netns_init_sysctl(net, nn_vrf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void __net_exit vrf_netns_exit(struct net *net)
 | 
			
		||||
{
 | 
			
		||||
	vrf_netns_exit_sysctl(net);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct pernet_operations vrf_net_ops __net_initdata = {
 | 
			
		||||
	.init = vrf_netns_init,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -379,6 +379,12 @@ if [ ! -x "$(command -v ip)" ]; then
 | 
			
		|||
	exit 0
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
modprobe vrf &>/dev/null
 | 
			
		||||
if [ ! -e /proc/sys/net/vrf/strict_mode ]; then
 | 
			
		||||
	echo "SKIP: vrf sysctl does not exist"
 | 
			
		||||
	exit 0
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
cleanup &> /dev/null
 | 
			
		||||
 | 
			
		||||
setup
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue