summaryrefslogtreecommitdiffstats
path: root/net/ipv6/ip6_fib.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2019-10-04 11:10:57 -0700
committerDavid S. Miller <davem@davemloft.net>2019-10-04 11:10:57 -0700
commit97bfe0e05ceb8ff91a331765bff384876ebd5f5e (patch)
tree11b86c4b4089b0fe46de77348727678d5eb9be8c /net/ipv6/ip6_fib.c
parent9077f052abd5391a866dd99e27212213648becef (diff)
parentb74c37fd35a28ddcfcdfbf559e16e380e7ba25aa (diff)
downloadlinux-97bfe0e05ceb8ff91a331765bff384876ebd5f5e.tar.gz
linux-97bfe0e05ceb8ff91a331765bff384876ebd5f5e.tar.bz2
linux-97bfe0e05ceb8ff91a331765bff384876ebd5f5e.zip
Merge branch 'devlink-allow-devlink-instances-to-change-network-namespace'
Jiri Pirko says: ==================== devlink: allow devlink instances to change network namespace Devlink from the beginning counts with network namespaces, but the instances has been fixed to init_net. Implement change of network namespace as part of "devlink reload" procedure like this: $ ip netns add testns1 $ devlink/devlink dev reload netdevsim/netdevsim10 netns testns1 This command reloads device "netdevsim10" into network namespace "testns1". Note that "devlink reload" reinstantiates driver objects, effectively it reloads the driver instance, including possible hw reset etc. Newly created netdevices respect the network namespace of the parent devlink instance and according to that, they are created in target network namespace. Driver is able to refuse to be reloaded into different namespace. That is the case of mlx4 right now. FIB entries and rules are replayed during FIB notifier registration which is triggered during reload (driver instance init). FIB notifier is also registered to the target network namespace, that allows user to use netdevsim devlink resources to setup per-namespace limits of FIB entries and FIB rules. In fact, with multiple netdevsim instances in each network namespace, user might setup different limits. This maintains and extends current netdevsim resources behaviour. Patch 1 prepares netdevsim code for the follow-up changes in the patchset. It does not change the behaviour, only moves pet-init_netns accounting to netdevsim instance, which is also in init_netns. Patches 2-5 prepare the FIB notifier making it per-netns and to behave correctly upon error conditions. Patch 6 just exports a devlink_net helper so it can be used in drivers. Patches 7-9 do preparations in mlxsw driver. Patches 10-13 do preparations in netdevsim driver, namely patch 12 implements proper devlink reload where the driver instance objects are actually re-created as they should be. Patch 14 actually implements the possibility to reload into a different network namespace. Patch 15 adds needed selftests for devlink reload into namespace for netdevsim driver. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/ip6_fib.c')
-rw-r--r--net/ipv6/ip6_fib.c50
1 files changed, 34 insertions, 16 deletions
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 6e2af411cd9c..f66bc2af4e9d 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -357,15 +357,17 @@ unsigned int fib6_tables_seq_read(struct net *net)
return fib_seq;
}
-static int call_fib6_entry_notifier(struct notifier_block *nb, struct net *net,
+static int call_fib6_entry_notifier(struct notifier_block *nb,
enum fib_event_type event_type,
- struct fib6_info *rt)
+ struct fib6_info *rt,
+ struct netlink_ext_ack *extack)
{
struct fib6_entry_notifier_info info = {
+ .info.extack = extack,
.rt = rt,
};
- return call_fib6_notifier(nb, net, event_type, &info.info);
+ return call_fib6_notifier(nb, event_type, &info.info);
}
int call_fib6_entry_notifiers(struct net *net,
@@ -401,40 +403,51 @@ int call_fib6_multipath_entry_notifiers(struct net *net,
struct fib6_dump_arg {
struct net *net;
struct notifier_block *nb;
+ struct netlink_ext_ack *extack;
};
-static void fib6_rt_dump(struct fib6_info *rt, struct fib6_dump_arg *arg)
+static int fib6_rt_dump(struct fib6_info *rt, struct fib6_dump_arg *arg)
{
if (rt == arg->net->ipv6.fib6_null_entry)
- return;
- call_fib6_entry_notifier(arg->nb, arg->net, FIB_EVENT_ENTRY_ADD, rt);
+ return 0;
+ return call_fib6_entry_notifier(arg->nb, FIB_EVENT_ENTRY_ADD,
+ rt, arg->extack);
}
static int fib6_node_dump(struct fib6_walker *w)
{
struct fib6_info *rt;
+ int err = 0;
- for_each_fib6_walker_rt(w)
- fib6_rt_dump(rt, w->args);
+ for_each_fib6_walker_rt(w) {
+ err = fib6_rt_dump(rt, w->args);
+ if (err)
+ break;
+ }
w->leaf = NULL;
- return 0;
+ return err;
}
-static void fib6_table_dump(struct net *net, struct fib6_table *tb,
- struct fib6_walker *w)
+static int fib6_table_dump(struct net *net, struct fib6_table *tb,
+ struct fib6_walker *w)
{
+ int err;
+
w->root = &tb->tb6_root;
spin_lock_bh(&tb->tb6_lock);
- fib6_walk(net, w);
+ err = fib6_walk(net, w);
spin_unlock_bh(&tb->tb6_lock);
+ return err;
}
/* Called with rcu_read_lock() */
-int fib6_tables_dump(struct net *net, struct notifier_block *nb)
+int fib6_tables_dump(struct net *net, struct notifier_block *nb,
+ struct netlink_ext_ack *extack)
{
struct fib6_dump_arg arg;
struct fib6_walker *w;
unsigned int h;
+ int err = 0;
w = kzalloc(sizeof(*w), GFP_ATOMIC);
if (!w)
@@ -443,19 +456,24 @@ int fib6_tables_dump(struct net *net, struct notifier_block *nb)
w->func = fib6_node_dump;
arg.net = net;
arg.nb = nb;
+ arg.extack = extack;
w->args = &arg;
for (h = 0; h < FIB6_TABLE_HASHSZ; h++) {
struct hlist_head *head = &net->ipv6.fib_table_hash[h];
struct fib6_table *tb;
- hlist_for_each_entry_rcu(tb, head, tb6_hlist)
- fib6_table_dump(net, tb, w);
+ hlist_for_each_entry_rcu(tb, head, tb6_hlist) {
+ err = fib6_table_dump(net, tb, w);
+ if (err < 0)
+ goto out;
+ }
}
+out:
kfree(w);
- return 0;
+ return err;
}
static int fib6_dump_node(struct fib6_walker *w)