mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 12:43:29 +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:
committed by
David S. Miller
parent
5df5661a13
commit
1b6687e31a
@@ -260,52 +260,6 @@ static void vrf_map_unlock(struct vrf_map *vmap) __releases(&vmap->vmap_lock)
|
|||||||
spin_unlock(&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 */
|
/* called with rtnl lock held */
|
||||||
static int
|
static int
|
||||||
vrf_map_register_dev(struct net_device *dev, struct netlink_ext_ack *extack)
|
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;
|
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,
|
static int vrf_shared_table_handler(struct ctl_table *table, int write,
|
||||||
void *buffer, size_t *lenp, loff_t *ppos)
|
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 vrf_netns_init_sysctl(struct net *net, struct netns_vrf *nn_vrf)
|
||||||
static int __net_init vrf_netns_init(struct net *net)
|
|
||||||
{
|
{
|
||||||
struct netns_vrf *nn_vrf = net_generic(net, vrf_net_id);
|
|
||||||
struct ctl_table *table;
|
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);
|
table = kmemdup(vrf_table, sizeof(vrf_table), GFP_KERNEL);
|
||||||
if (!table)
|
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);
|
nn_vrf->ctl_hdr = register_net_sysctl(net, "net/vrf", table);
|
||||||
if (!nn_vrf->ctl_hdr) {
|
if (!nn_vrf->ctl_hdr) {
|
||||||
res = -ENOMEM;
|
kfree(table);
|
||||||
goto free_table;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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 netns_vrf *nn_vrf = net_generic(net, vrf_net_id);
|
||||||
struct ctl_table *table;
|
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);
|
unregister_net_sysctl_table(nn_vrf->ctl_hdr);
|
||||||
kfree(table);
|
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 = {
|
static struct pernet_operations vrf_net_ops __net_initdata = {
|
||||||
.init = vrf_netns_init,
|
.init = vrf_netns_init,
|
||||||
|
@@ -379,6 +379,12 @@ if [ ! -x "$(command -v ip)" ]; then
|
|||||||
exit 0
|
exit 0
|
||||||
fi
|
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
|
cleanup &> /dev/null
|
||||||
|
|
||||||
setup
|
setup
|
||||||
|
Reference in New Issue
Block a user