@@ -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
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: 33306f1aaf82 ("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> --- drivers/net/vrf.c | 138 ++++++++++-------- .../selftests/net/vrf_strict_mode_test.sh | 6 + 2 files changed, 83 insertions(+), 61 deletions(-)