aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Lezcano2008-03-03 23:33:08 -0800
committerDavid S. Miller2008-03-03 23:33:08 -0800
commitdcabb819a6eced95ef531b001e663d0d592c8d9f (patch)
tree1ecd3db4de537c8aad94a43827723668c7e4368c
parenteb5564b8532eec6b49379095df2b979aab85661f (diff)
[NETNS][IPV6] fib6_rules - handle several network namespaces
The fib6_rules_ops is moved to the network namespace structure. All references are changed to have it relatively to it. Each time a network namespace is created a new fib6_rules_ops is allocated, initialized and stored into the network namespace structure. The common part of the fib rules is namespace aware, so it is quite easy to retrieve the network namespace from the rules and use it in the different callbacks. Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com> Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/netns/ipv6.h1
-rw-r--r--net/ipv6/fib6_rules.c82
2 files changed, 47 insertions, 36 deletions
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
index 5279cd6a00ba..66bf9c0f745b 100644
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
@@ -41,6 +41,7 @@ struct netns_ipv6 {
struct fib6_table *fib6_main_tbl;
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
struct fib6_table *fib6_local_tbl;
+ struct fib_rules_ops *fib6_rules_ops;
#endif
struct sock **icmp_sk;
};
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index 60af08f12547..89cb092c9732 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -29,8 +29,6 @@ struct fib6_rule
u8 tclass;
};
-static struct fib_rules_ops *fib6_rules_ops;
-
struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl,
int flags, pol_lookup_t lookup)
{
@@ -38,7 +36,7 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl,
.lookup_ptr = lookup,
};
- fib_rules_lookup(fib6_rules_ops, fl, flags, &arg);
+ fib_rules_lookup(net->ipv6.fib6_rules_ops, fl, flags, &arg);
if (arg.rule)
fib_rule_put(arg.rule);
@@ -71,7 +69,7 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
goto discard_pkt;
}
- table = fib6_get_table(&init_net, rule->table);
+ table = fib6_get_table(rule->fr_net, rule->table);
if (table)
rt = lookup(table, flp, flags);
@@ -145,13 +143,14 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
struct nlattr **tb)
{
int err = -EINVAL;
+ struct net *net = skb->sk->sk_net;
struct fib6_rule *rule6 = (struct fib6_rule *) rule;
if (rule->action == FR_ACT_TO_TBL) {
if (rule->table == RT6_TABLE_UNSPEC)
goto errout;
- if (fib6_new_table(&init_net, rule->table) == NULL) {
+ if (fib6_new_table(net, rule->table) == NULL) {
err = -ENOBUFS;
goto errout;
}
@@ -251,49 +250,60 @@ static struct fib_rules_ops fib6_rules_ops_template = {
.fro_net = &init_net,
};
-static int __init fib6_default_rules_init(void)
+static int fib6_rules_net_init(struct net *net)
{
- int err;
+ int err = -ENOMEM;
- fib6_rules_ops = kmemdup(&fib6_rules_ops_template,
- sizeof(*fib6_rules_ops), GFP_KERNEL);
- if (!fib6_rules_ops)
- return -ENOMEM;
+ net->ipv6.fib6_rules_ops = kmemdup(&fib6_rules_ops_template,
+ sizeof(*net->ipv6.fib6_rules_ops),
+ GFP_KERNEL);
+ if (!net->ipv6.fib6_rules_ops)
+ goto out;
- INIT_LIST_HEAD(&fib6_rules_ops->rules_list);
+ net->ipv6.fib6_rules_ops->fro_net = net;
+ INIT_LIST_HEAD(&net->ipv6.fib6_rules_ops->rules_list);
- err = fib_default_rule_add(fib6_rules_ops, 0,
+ err = fib_default_rule_add(net->ipv6.fib6_rules_ops, 0,
RT6_TABLE_LOCAL, FIB_RULE_PERMANENT);
- if (err < 0)
- return err;
- err = fib_default_rule_add(fib6_rules_ops, 0x7FFE, RT6_TABLE_MAIN, 0);
- if (err < 0)
- return err;
- return 0;
-}
-
-int __init fib6_rules_init(void)
-{
- int ret;
+ if (err)
+ goto out_fib6_rules_ops;
- ret = fib6_default_rules_init();
- if (ret)
- goto out;
+ err = fib_default_rule_add(net->ipv6.fib6_rules_ops,
+ 0x7FFE, RT6_TABLE_MAIN, 0);
+ if (err)
+ goto out_fib6_default_rule_add;
- ret = fib_rules_register(fib6_rules_ops);
- if (ret)
- goto out_default_rules_init;
+ err = fib_rules_register(net->ipv6.fib6_rules_ops);
+ if (err)
+ goto out_fib6_default_rule_add;
out:
- return ret;
+ return err;
-out_default_rules_init:
- fib_rules_cleanup_ops(fib6_rules_ops);
- kfree(fib6_rules_ops);
+out_fib6_default_rule_add:
+ fib_rules_cleanup_ops(net->ipv6.fib6_rules_ops);
+out_fib6_rules_ops:
+ kfree(net->ipv6.fib6_rules_ops);
goto out;
}
+static void fib6_rules_net_exit(struct net *net)
+{
+ fib_rules_unregister(net->ipv6.fib6_rules_ops);
+ kfree(net->ipv6.fib6_rules_ops);
+}
+
+static struct pernet_operations fib6_rules_net_ops = {
+ .init = fib6_rules_net_init,
+ .exit = fib6_rules_net_exit,
+};
+
+int __init fib6_rules_init(void)
+{
+ return register_pernet_subsys(&fib6_rules_net_ops);
+}
+
+
void fib6_rules_cleanup(void)
{
- fib_rules_unregister(fib6_rules_ops);
- kfree(fib6_rules_ops);
+ return unregister_pernet_subsys(&fib6_rules_net_ops);
}