Commit 8ed677896752fff056f6cf3d7ce462adc6c464f0
Committed by
David S. Miller
1 parent
bdb3289f73
Exists in
master
and in
4 other branches
[NETNS][IPV6] rt6_info - move rt6_info structure inside the namespace
The rt6_info structures are moved inside the network namespace structure. All references to these structures are now relative to the initial network namespace. 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>
Showing 6 changed files with 171 additions and 108 deletions Side-by-side Diff
include/net/ip6_fib.h
... | ... | @@ -174,7 +174,8 @@ |
174 | 174 | #define RT6_TABLE_LOCAL RT6_TABLE_MAIN |
175 | 175 | #endif |
176 | 176 | |
177 | -typedef struct rt6_info *(*pol_lookup_t)(struct fib6_table *, | |
177 | +typedef struct rt6_info *(*pol_lookup_t)(struct net *, | |
178 | + struct fib6_table *, | |
178 | 179 | struct flowi *, int); |
179 | 180 | |
180 | 181 | /* |
include/net/netns/ipv6.h
... | ... | @@ -36,11 +36,14 @@ |
36 | 36 | struct xt_table *ip6table_mangle; |
37 | 37 | struct xt_table *ip6table_raw; |
38 | 38 | #endif |
39 | + struct rt6_info *ip6_null_entry; | |
39 | 40 | struct rt6_statistics *rt6_stats; |
40 | 41 | struct timer_list *ip6_fib_timer; |
41 | 42 | struct hlist_head *fib_table_hash; |
42 | 43 | struct fib6_table *fib6_main_tbl; |
43 | 44 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
45 | + struct rt6_info *ip6_prohibit_entry; | |
46 | + struct rt6_info *ip6_blk_hole_entry; | |
44 | 47 | struct fib6_table *fib6_local_tbl; |
45 | 48 | struct fib_rules_ops *fib6_rules_ops; |
46 | 49 | #endif |
net/ipv6/addrconf.c
... | ... | @@ -4301,15 +4301,6 @@ |
4301 | 4301 | if (err) |
4302 | 4302 | goto errlo; |
4303 | 4303 | |
4304 | - ip6_null_entry->u.dst.dev = init_net.loopback_dev; | |
4305 | - ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | |
4306 | -#ifdef CONFIG_IPV6_MULTIPLE_TABLES | |
4307 | - ip6_prohibit_entry->u.dst.dev = init_net.loopback_dev; | |
4308 | - ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | |
4309 | - ip6_blk_hole_entry->u.dst.dev = init_net.loopback_dev; | |
4310 | - ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | |
4311 | -#endif | |
4312 | - | |
4313 | 4304 | register_netdevice_notifier(&ipv6_dev_notf); |
4314 | 4305 | |
4315 | 4306 | addrconf_verify(0); |
net/ipv6/fib6_rules.c
... | ... | @@ -43,8 +43,8 @@ |
43 | 43 | if (arg.result) |
44 | 44 | return arg.result; |
45 | 45 | |
46 | - dst_hold(&ip6_null_entry->u.dst); | |
47 | - return &ip6_null_entry->u.dst; | |
46 | + dst_hold(&net->ipv6.ip6_null_entry->u.dst); | |
47 | + return &net->ipv6.ip6_null_entry->u.dst; | |
48 | 48 | } |
49 | 49 | |
50 | 50 | static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, |
51 | 51 | |
52 | 52 | |
53 | 53 | |
54 | 54 | |
55 | 55 | |
56 | 56 | |
... | ... | @@ -52,28 +52,29 @@ |
52 | 52 | { |
53 | 53 | struct rt6_info *rt = NULL; |
54 | 54 | struct fib6_table *table; |
55 | + struct net *net = rule->fr_net; | |
55 | 56 | pol_lookup_t lookup = arg->lookup_ptr; |
56 | 57 | |
57 | 58 | switch (rule->action) { |
58 | 59 | case FR_ACT_TO_TBL: |
59 | 60 | break; |
60 | 61 | case FR_ACT_UNREACHABLE: |
61 | - rt = ip6_null_entry; | |
62 | + rt = net->ipv6.ip6_null_entry; | |
62 | 63 | goto discard_pkt; |
63 | 64 | default: |
64 | 65 | case FR_ACT_BLACKHOLE: |
65 | - rt = ip6_blk_hole_entry; | |
66 | + rt = net->ipv6.ip6_blk_hole_entry; | |
66 | 67 | goto discard_pkt; |
67 | 68 | case FR_ACT_PROHIBIT: |
68 | - rt = ip6_prohibit_entry; | |
69 | + rt = net->ipv6.ip6_prohibit_entry; | |
69 | 70 | goto discard_pkt; |
70 | 71 | } |
71 | 72 | |
72 | - table = fib6_get_table(rule->fr_net, rule->table); | |
73 | + table = fib6_get_table(net, rule->table); | |
73 | 74 | if (table) |
74 | - rt = lookup(table, flp, flags); | |
75 | + rt = lookup(net, table, flp, flags); | |
75 | 76 | |
76 | - if (rt != ip6_null_entry) { | |
77 | + if (rt != net->ipv6.ip6_null_entry) { | |
77 | 78 | struct fib6_rule *r = (struct fib6_rule *)rule; |
78 | 79 | |
79 | 80 | /* |
net/ipv6/ip6_fib.c
... | ... | @@ -79,8 +79,8 @@ |
79 | 79 | |
80 | 80 | static void fib6_prune_clones(struct net *net, struct fib6_node *fn, |
81 | 81 | struct rt6_info *rt); |
82 | -static struct rt6_info * fib6_find_prefix(struct fib6_node *fn); | |
83 | -static struct fib6_node * fib6_repair_tree(struct fib6_node *fn); | |
82 | +static struct rt6_info *fib6_find_prefix(struct net *net, struct fib6_node *fn); | |
83 | +static struct fib6_node *fib6_repair_tree(struct net *net, struct fib6_node *fn); | |
84 | 84 | static int fib6_walk(struct fib6_walker_t *w); |
85 | 85 | static int fib6_walk_continue(struct fib6_walker_t *w); |
86 | 86 | |
87 | 87 | |
... | ... | @@ -193,14 +193,14 @@ |
193 | 193 | |
194 | 194 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
195 | 195 | |
196 | -static struct fib6_table *fib6_alloc_table(u32 id) | |
196 | +static struct fib6_table *fib6_alloc_table(struct net *net, u32 id) | |
197 | 197 | { |
198 | 198 | struct fib6_table *table; |
199 | 199 | |
200 | 200 | table = kzalloc(sizeof(*table), GFP_ATOMIC); |
201 | 201 | if (table != NULL) { |
202 | 202 | table->tb6_id = id; |
203 | - table->tb6_root.leaf = ip6_null_entry; | |
203 | + table->tb6_root.leaf = net->ipv6.ip6_null_entry; | |
204 | 204 | table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; |
205 | 205 | } |
206 | 206 | |
... | ... | @@ -217,7 +217,7 @@ |
217 | 217 | if (tb) |
218 | 218 | return tb; |
219 | 219 | |
220 | - tb = fib6_alloc_table(id); | |
220 | + tb = fib6_alloc_table(net, id); | |
221 | 221 | if (tb != NULL) |
222 | 222 | fib6_link_table(net, tb); |
223 | 223 | |
... | ... | @@ -267,7 +267,7 @@ |
267 | 267 | struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl, |
268 | 268 | int flags, pol_lookup_t lookup) |
269 | 269 | { |
270 | - return (struct dst_entry *) lookup(net->ipv6.fib6_main_tbl, fl, flags); | |
270 | + return (struct dst_entry *) lookup(net, net->ipv6.fib6_main_tbl, fl, flags); | |
271 | 271 | } |
272 | 272 | |
273 | 273 | static void fib6_tables_init(struct net *net) |
... | ... | @@ -717,8 +717,8 @@ |
717 | 717 | if (sfn == NULL) |
718 | 718 | goto st_failure; |
719 | 719 | |
720 | - sfn->leaf = ip6_null_entry; | |
721 | - atomic_inc(&ip6_null_entry->rt6i_ref); | |
720 | + sfn->leaf = info->nl_net->ipv6.ip6_null_entry; | |
721 | + atomic_inc(&info->nl_net->ipv6.ip6_null_entry->rt6i_ref); | |
722 | 722 | sfn->fn_flags = RTN_ROOT; |
723 | 723 | sfn->fn_sernum = fib6_new_sernum(); |
724 | 724 | |
725 | 725 | |
... | ... | @@ -773,11 +773,11 @@ |
773 | 773 | * super-tree leaf node we have to find a new one for it. |
774 | 774 | */ |
775 | 775 | if (pn != fn && !pn->leaf && !(pn->fn_flags & RTN_RTINFO)) { |
776 | - pn->leaf = fib6_find_prefix(pn); | |
776 | + pn->leaf = fib6_find_prefix(info->nl_net, pn); | |
777 | 777 | #if RT6_DEBUG >= 2 |
778 | 778 | if (!pn->leaf) { |
779 | 779 | BUG_TRAP(pn->leaf != NULL); |
780 | - pn->leaf = ip6_null_entry; | |
780 | + pn->leaf = info->nl_net->ipv6.ip6_null_entry; | |
781 | 781 | } |
782 | 782 | #endif |
783 | 783 | atomic_inc(&pn->leaf->rt6i_ref); |
... | ... | @@ -793,7 +793,7 @@ |
793 | 793 | */ |
794 | 794 | st_failure: |
795 | 795 | if (fn && !(fn->fn_flags & (RTN_RTINFO|RTN_ROOT))) |
796 | - fib6_repair_tree(fn); | |
796 | + fib6_repair_tree(info->nl_net, fn); | |
797 | 797 | dst_free(&rt->u.dst); |
798 | 798 | return err; |
799 | 799 | #endif |
800 | 800 | |
... | ... | @@ -959,10 +959,10 @@ |
959 | 959 | * |
960 | 960 | */ |
961 | 961 | |
962 | -static struct rt6_info * fib6_find_prefix(struct fib6_node *fn) | |
962 | +static struct rt6_info *fib6_find_prefix(struct net *net, struct fib6_node *fn) | |
963 | 963 | { |
964 | 964 | if (fn->fn_flags&RTN_ROOT) |
965 | - return ip6_null_entry; | |
965 | + return net->ipv6.ip6_null_entry; | |
966 | 966 | |
967 | 967 | while(fn) { |
968 | 968 | if(fn->left) |
... | ... | @@ -981,7 +981,8 @@ |
981 | 981 | * is the node we want to try and remove. |
982 | 982 | */ |
983 | 983 | |
984 | -static struct fib6_node * fib6_repair_tree(struct fib6_node *fn) | |
984 | +static struct fib6_node *fib6_repair_tree(struct net *net, | |
985 | + struct fib6_node *fn) | |
985 | 986 | { |
986 | 987 | int children; |
987 | 988 | int nstate; |
988 | 989 | |
... | ... | @@ -1008,11 +1009,11 @@ |
1008 | 1009 | || (children && fn->fn_flags&RTN_ROOT) |
1009 | 1010 | #endif |
1010 | 1011 | ) { |
1011 | - fn->leaf = fib6_find_prefix(fn); | |
1012 | + fn->leaf = fib6_find_prefix(net, fn); | |
1012 | 1013 | #if RT6_DEBUG >= 2 |
1013 | 1014 | if (fn->leaf==NULL) { |
1014 | 1015 | BUG_TRAP(fn->leaf); |
1015 | - fn->leaf = ip6_null_entry; | |
1016 | + fn->leaf = net->ipv6.ip6_null_entry; | |
1016 | 1017 | } |
1017 | 1018 | #endif |
1018 | 1019 | atomic_inc(&fn->leaf->rt6i_ref); |
... | ... | @@ -1117,7 +1118,7 @@ |
1117 | 1118 | if (fn->leaf == NULL) { |
1118 | 1119 | fn->fn_flags &= ~RTN_RTINFO; |
1119 | 1120 | net->ipv6.rt6_stats->fib_route_nodes--; |
1120 | - fn = fib6_repair_tree(fn); | |
1121 | + fn = fib6_repair_tree(net, fn); | |
1121 | 1122 | } |
1122 | 1123 | |
1123 | 1124 | if (atomic_read(&rt->rt6i_ref) != 1) { |
... | ... | @@ -1129,7 +1130,7 @@ |
1129 | 1130 | */ |
1130 | 1131 | while (fn) { |
1131 | 1132 | if (!(fn->fn_flags&RTN_RTINFO) && fn->leaf == rt) { |
1132 | - fn->leaf = fib6_find_prefix(fn); | |
1133 | + fn->leaf = fib6_find_prefix(net, fn); | |
1133 | 1134 | atomic_inc(&fn->leaf->rt6i_ref); |
1134 | 1135 | rt6_release(rt); |
1135 | 1136 | } |
... | ... | @@ -1145,6 +1146,7 @@ |
1145 | 1146 | |
1146 | 1147 | int fib6_del(struct rt6_info *rt, struct nl_info *info) |
1147 | 1148 | { |
1149 | + struct net *net = info->nl_net; | |
1148 | 1150 | struct fib6_node *fn = rt->rt6i_node; |
1149 | 1151 | struct rt6_info **rtp; |
1150 | 1152 | |
... | ... | @@ -1154,7 +1156,7 @@ |
1154 | 1156 | return -ENOENT; |
1155 | 1157 | } |
1156 | 1158 | #endif |
1157 | - if (fn == NULL || rt == ip6_null_entry) | |
1159 | + if (fn == NULL || rt == net->ipv6.ip6_null_entry) | |
1158 | 1160 | return -ENOENT; |
1159 | 1161 | |
1160 | 1162 | BUG_TRAP(fn->fn_flags&RTN_RTINFO); |
... | ... | @@ -1501,7 +1503,7 @@ |
1501 | 1503 | goto out_fib_table_hash; |
1502 | 1504 | |
1503 | 1505 | net->ipv6.fib6_main_tbl->tb6_id = RT6_TABLE_MAIN; |
1504 | - net->ipv6.fib6_main_tbl->tb6_root.leaf = ip6_null_entry; | |
1506 | + net->ipv6.fib6_main_tbl->tb6_root.leaf = net->ipv6.ip6_null_entry; | |
1505 | 1507 | net->ipv6.fib6_main_tbl->tb6_root.fn_flags = |
1506 | 1508 | RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; |
1507 | 1509 | |
... | ... | @@ -1511,7 +1513,7 @@ |
1511 | 1513 | if (!net->ipv6.fib6_local_tbl) |
1512 | 1514 | goto out_fib6_main_tbl; |
1513 | 1515 | net->ipv6.fib6_local_tbl->tb6_id = RT6_TABLE_LOCAL; |
1514 | - net->ipv6.fib6_local_tbl->tb6_root.leaf = ip6_null_entry; | |
1516 | + net->ipv6.fib6_local_tbl->tb6_root.leaf = net->ipv6.ip6_null_entry; | |
1515 | 1517 | net->ipv6.fib6_local_tbl->tb6_root.fn_flags = |
1516 | 1518 | RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; |
1517 | 1519 | #endif |
... | ... | @@ -1536,6 +1538,7 @@ |
1536 | 1538 | |
1537 | 1539 | static void fib6_net_exit(struct net *net) |
1538 | 1540 | { |
1541 | + rt6_ifdown(net, NULL); | |
1539 | 1542 | del_timer(net->ipv6.ip6_fib_timer); |
1540 | 1543 | kfree(net->ipv6.ip6_fib_timer); |
1541 | 1544 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
net/ipv6/route.c
... | ... | @@ -145,8 +145,6 @@ |
145 | 145 | .rt6i_ref = ATOMIC_INIT(1), |
146 | 146 | }; |
147 | 147 | |
148 | -struct rt6_info *ip6_null_entry; | |
149 | - | |
150 | 148 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
151 | 149 | |
152 | 150 | static int ip6_pkt_prohibit(struct sk_buff *skb); |
... | ... | @@ -170,8 +168,6 @@ |
170 | 168 | .rt6i_ref = ATOMIC_INIT(1), |
171 | 169 | }; |
172 | 170 | |
173 | -struct rt6_info *ip6_prohibit_entry; | |
174 | - | |
175 | 171 | static struct rt6_info ip6_blk_hole_entry_template = { |
176 | 172 | .u = { |
177 | 173 | .dst = { |
... | ... | @@ -190,8 +186,6 @@ |
190 | 186 | .rt6i_ref = ATOMIC_INIT(1), |
191 | 187 | }; |
192 | 188 | |
193 | -struct rt6_info *ip6_blk_hole_entry; | |
194 | - | |
195 | 189 | #endif |
196 | 190 | |
197 | 191 | /* allocate dst with ip6_dst_ops */ |
... | ... | @@ -245,7 +239,8 @@ |
245 | 239 | * Route lookup. Any table->tb6_lock is implied. |
246 | 240 | */ |
247 | 241 | |
248 | -static __inline__ struct rt6_info *rt6_device_match(struct rt6_info *rt, | |
242 | +static inline struct rt6_info *rt6_device_match(struct net *net, | |
243 | + struct rt6_info *rt, | |
249 | 244 | int oif, |
250 | 245 | int strict) |
251 | 246 | { |
... | ... | @@ -274,7 +269,7 @@ |
274 | 269 | return local; |
275 | 270 | |
276 | 271 | if (strict) |
277 | - return ip6_null_entry; | |
272 | + return net->ipv6.ip6_null_entry; | |
278 | 273 | } |
279 | 274 | return rt; |
280 | 275 | } |
... | ... | @@ -415,6 +410,7 @@ |
415 | 410 | static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict) |
416 | 411 | { |
417 | 412 | struct rt6_info *match, *rt0; |
413 | + struct net *net; | |
418 | 414 | |
419 | 415 | RT6_TRACE("%s(fn->leaf=%p, oif=%d)\n", |
420 | 416 | __FUNCTION__, fn->leaf, oif); |
... | ... | @@ -440,7 +436,8 @@ |
440 | 436 | RT6_TRACE("%s() => %p\n", |
441 | 437 | __FUNCTION__, match); |
442 | 438 | |
443 | - return (match ? match : ip6_null_entry); | |
439 | + net = rt0->rt6i_dev->nd_net; | |
440 | + return (match ? match : net->ipv6.ip6_null_entry); | |
444 | 441 | } |
445 | 442 | |
446 | 443 | #ifdef CONFIG_IPV6_ROUTE_INFO |
447 | 444 | |
... | ... | @@ -523,9 +520,9 @@ |
523 | 520 | } |
524 | 521 | #endif |
525 | 522 | |
526 | -#define BACKTRACK(saddr) \ | |
523 | +#define BACKTRACK(__net, saddr) \ | |
527 | 524 | do { \ |
528 | - if (rt == ip6_null_entry) { \ | |
525 | + if (rt == __net->ipv6.ip6_null_entry) { \ | |
529 | 526 | struct fib6_node *pn; \ |
530 | 527 | while (1) { \ |
531 | 528 | if (fn->fn_flags & RTN_TL_ROOT) \ |
... | ... | @@ -541,7 +538,8 @@ |
541 | 538 | } \ |
542 | 539 | } while(0) |
543 | 540 | |
544 | -static struct rt6_info *ip6_pol_route_lookup(struct fib6_table *table, | |
541 | +static struct rt6_info *ip6_pol_route_lookup(struct net *net, | |
542 | + struct fib6_table *table, | |
545 | 543 | struct flowi *fl, int flags) |
546 | 544 | { |
547 | 545 | struct fib6_node *fn; |
... | ... | @@ -551,8 +549,8 @@ |
551 | 549 | fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); |
552 | 550 | restart: |
553 | 551 | rt = fn->leaf; |
554 | - rt = rt6_device_match(rt, fl->oif, flags); | |
555 | - BACKTRACK(&fl->fl6_src); | |
552 | + rt = rt6_device_match(net, rt, fl->oif, flags); | |
553 | + BACKTRACK(net, &fl->fl6_src); | |
556 | 554 | out: |
557 | 555 | dst_use(&rt->u.dst, jiffies); |
558 | 556 | read_unlock_bh(&table->tb6_lock); |
... | ... | @@ -668,8 +666,8 @@ |
668 | 666 | return rt; |
669 | 667 | } |
670 | 668 | |
671 | -static struct rt6_info *ip6_pol_route(struct fib6_table *table, int oif, | |
672 | - struct flowi *fl, int flags) | |
669 | +static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, int oif, | |
670 | + struct flowi *fl, int flags) | |
673 | 671 | { |
674 | 672 | struct fib6_node *fn; |
675 | 673 | struct rt6_info *rt, *nrt; |
... | ... | @@ -688,8 +686,9 @@ |
688 | 686 | |
689 | 687 | restart: |
690 | 688 | rt = rt6_select(fn, oif, strict | reachable); |
691 | - BACKTRACK(&fl->fl6_src); | |
692 | - if (rt == ip6_null_entry || | |
689 | + | |
690 | + BACKTRACK(net, &fl->fl6_src); | |
691 | + if (rt == net->ipv6.ip6_null_entry || | |
693 | 692 | rt->rt6i_flags & RTF_CACHE) |
694 | 693 | goto out; |
695 | 694 | |
... | ... | @@ -707,7 +706,7 @@ |
707 | 706 | } |
708 | 707 | |
709 | 708 | dst_release(&rt->u.dst); |
710 | - rt = nrt ? : ip6_null_entry; | |
709 | + rt = nrt ? : net->ipv6.ip6_null_entry; | |
711 | 710 | |
712 | 711 | dst_hold(&rt->u.dst); |
713 | 712 | if (nrt) { |
714 | 713 | |
... | ... | @@ -740,10 +739,10 @@ |
740 | 739 | return rt; |
741 | 740 | } |
742 | 741 | |
743 | -static struct rt6_info *ip6_pol_route_input(struct fib6_table *table, | |
742 | +static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table *table, | |
744 | 743 | struct flowi *fl, int flags) |
745 | 744 | { |
746 | - return ip6_pol_route(table, fl->iif, fl, flags); | |
745 | + return ip6_pol_route(net, table, fl->iif, fl, flags); | |
747 | 746 | } |
748 | 747 | |
749 | 748 | void ip6_route_input(struct sk_buff *skb) |
750 | 749 | |
... | ... | @@ -770,10 +769,10 @@ |
770 | 769 | skb->dst = fib6_rule_lookup(net, &fl, flags, ip6_pol_route_input); |
771 | 770 | } |
772 | 771 | |
773 | -static struct rt6_info *ip6_pol_route_output(struct fib6_table *table, | |
772 | +static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table, | |
774 | 773 | struct flowi *fl, int flags) |
775 | 774 | { |
776 | - return ip6_pol_route(table, fl->oif, fl, flags); | |
775 | + return ip6_pol_route(net, table, fl->oif, fl, flags); | |
777 | 776 | } |
778 | 777 | |
779 | 778 | struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) |
780 | 779 | |
... | ... | @@ -1259,8 +1258,9 @@ |
1259 | 1258 | { |
1260 | 1259 | int err; |
1261 | 1260 | struct fib6_table *table; |
1261 | + struct net *net = rt->rt6i_dev->nd_net; | |
1262 | 1262 | |
1263 | - if (rt == ip6_null_entry) | |
1263 | + if (rt == net->ipv6.ip6_null_entry) | |
1264 | 1264 | return -ENOENT; |
1265 | 1265 | |
1266 | 1266 | table = rt->rt6i_table; |
... | ... | @@ -1329,7 +1329,8 @@ |
1329 | 1329 | struct in6_addr gateway; |
1330 | 1330 | }; |
1331 | 1331 | |
1332 | -static struct rt6_info *__ip6_route_redirect(struct fib6_table *table, | |
1332 | +static struct rt6_info *__ip6_route_redirect(struct net *net, | |
1333 | + struct fib6_table *table, | |
1333 | 1334 | struct flowi *fl, |
1334 | 1335 | int flags) |
1335 | 1336 | { |
... | ... | @@ -1372,8 +1373,8 @@ |
1372 | 1373 | } |
1373 | 1374 | |
1374 | 1375 | if (!rt) |
1375 | - rt = ip6_null_entry; | |
1376 | - BACKTRACK(&fl->fl6_src); | |
1376 | + rt = net->ipv6.ip6_null_entry; | |
1377 | + BACKTRACK(net, &fl->fl6_src); | |
1377 | 1378 | out: |
1378 | 1379 | dst_hold(&rt->u.dst); |
1379 | 1380 | |
1380 | 1381 | |
... | ... | @@ -1415,10 +1416,11 @@ |
1415 | 1416 | { |
1416 | 1417 | struct rt6_info *rt, *nrt = NULL; |
1417 | 1418 | struct netevent_redirect netevent; |
1419 | + struct net *net = neigh->dev->nd_net; | |
1418 | 1420 | |
1419 | 1421 | rt = ip6_route_redirect(dest, src, saddr, neigh->dev); |
1420 | 1422 | |
1421 | - if (rt == ip6_null_entry) { | |
1423 | + if (rt == net->ipv6.ip6_null_entry) { | |
1422 | 1424 | if (net_ratelimit()) |
1423 | 1425 | printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop " |
1424 | 1426 | "for redirect target\n"); |
1425 | 1427 | |
... | ... | @@ -1886,10 +1888,18 @@ |
1886 | 1888 | return rt; |
1887 | 1889 | } |
1888 | 1890 | |
1891 | +struct arg_dev_net { | |
1892 | + struct net_device *dev; | |
1893 | + struct net *net; | |
1894 | +}; | |
1895 | + | |
1889 | 1896 | static int fib6_ifdown(struct rt6_info *rt, void *arg) |
1890 | 1897 | { |
1891 | - if (((void*)rt->rt6i_dev == arg || arg == NULL) && | |
1892 | - rt != ip6_null_entry) { | |
1898 | + struct net_device *dev = ((struct arg_dev_net *)arg)->dev; | |
1899 | + struct net *net = ((struct arg_dev_net *)arg)->net; | |
1900 | + | |
1901 | + if (((void *)rt->rt6i_dev == dev || dev == NULL) && | |
1902 | + rt != net->ipv6.ip6_null_entry) { | |
1893 | 1903 | RT6_TRACE("deleted by ifdown %p\n", rt); |
1894 | 1904 | return -1; |
1895 | 1905 | } |
... | ... | @@ -1898,7 +1908,12 @@ |
1898 | 1908 | |
1899 | 1909 | void rt6_ifdown(struct net *net, struct net_device *dev) |
1900 | 1910 | { |
1901 | - fib6_clean_all(net, fib6_ifdown, 0, dev); | |
1911 | + struct arg_dev_net adn = { | |
1912 | + .dev = dev, | |
1913 | + .net = net, | |
1914 | + }; | |
1915 | + | |
1916 | + fib6_clean_all(net, fib6_ifdown, 0, &adn); | |
1902 | 1917 | } |
1903 | 1918 | |
1904 | 1919 | struct rt6_mtu_change_arg |
... | ... | @@ -2289,6 +2304,26 @@ |
2289 | 2304 | rtnl_set_sk_err(net, RTNLGRP_IPV6_ROUTE, err); |
2290 | 2305 | } |
2291 | 2306 | |
2307 | +static int ip6_route_dev_notify(struct notifier_block *this, | |
2308 | + unsigned long event, void *data) | |
2309 | +{ | |
2310 | + struct net_device *dev = (struct net_device *)data; | |
2311 | + struct net *net = dev->nd_net; | |
2312 | + | |
2313 | + if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) { | |
2314 | + net->ipv6.ip6_null_entry->u.dst.dev = dev; | |
2315 | + net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev); | |
2316 | +#ifdef CONFIG_IPV6_MULTIPLE_TABLES | |
2317 | + net->ipv6.ip6_prohibit_entry->u.dst.dev = dev; | |
2318 | + net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); | |
2319 | + net->ipv6.ip6_blk_hole_entry->u.dst.dev = dev; | |
2320 | + net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); | |
2321 | +#endif | |
2322 | + } | |
2323 | + | |
2324 | + return NOTIFY_OK; | |
2325 | +} | |
2326 | + | |
2292 | 2327 | /* |
2293 | 2328 | * /proc |
2294 | 2329 | */ |
2295 | 2330 | |
... | ... | @@ -2535,11 +2570,47 @@ |
2535 | 2570 | |
2536 | 2571 | static int ip6_route_net_init(struct net *net) |
2537 | 2572 | { |
2573 | + int ret = 0; | |
2574 | + | |
2575 | + ret = -ENOMEM; | |
2576 | + net->ipv6.ip6_null_entry = kmemdup(&ip6_null_entry_template, | |
2577 | + sizeof(*net->ipv6.ip6_null_entry), | |
2578 | + GFP_KERNEL); | |
2579 | + if (!net->ipv6.ip6_null_entry) | |
2580 | + goto out; | |
2581 | + net->ipv6.ip6_null_entry->u.dst.path = | |
2582 | + (struct dst_entry *)net->ipv6.ip6_null_entry; | |
2583 | + | |
2584 | +#ifdef CONFIG_IPV6_MULTIPLE_TABLES | |
2585 | + net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, | |
2586 | + sizeof(*net->ipv6.ip6_prohibit_entry), | |
2587 | + GFP_KERNEL); | |
2588 | + if (!net->ipv6.ip6_prohibit_entry) { | |
2589 | + kfree(net->ipv6.ip6_null_entry); | |
2590 | + goto out; | |
2591 | + } | |
2592 | + net->ipv6.ip6_prohibit_entry->u.dst.path = | |
2593 | + (struct dst_entry *)net->ipv6.ip6_prohibit_entry; | |
2594 | + | |
2595 | + net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, | |
2596 | + sizeof(*net->ipv6.ip6_blk_hole_entry), | |
2597 | + GFP_KERNEL); | |
2598 | + if (!net->ipv6.ip6_blk_hole_entry) { | |
2599 | + kfree(net->ipv6.ip6_null_entry); | |
2600 | + kfree(net->ipv6.ip6_prohibit_entry); | |
2601 | + goto out; | |
2602 | + } | |
2603 | + net->ipv6.ip6_blk_hole_entry->u.dst.path = | |
2604 | + (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; | |
2605 | +#endif | |
2606 | + | |
2538 | 2607 | #ifdef CONFIG_PROC_FS |
2539 | 2608 | proc_net_fops_create(net, "ipv6_route", 0, &ipv6_route_proc_fops); |
2540 | 2609 | proc_net_fops_create(net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops); |
2541 | 2610 | #endif |
2542 | - return 0; | |
2611 | + ret = 0; | |
2612 | +out: | |
2613 | + return ret; | |
2543 | 2614 | } |
2544 | 2615 | |
2545 | 2616 | static void ip6_route_net_exit(struct net *net) |
... | ... | @@ -2548,7 +2619,11 @@ |
2548 | 2619 | proc_net_remove(net, "ipv6_route"); |
2549 | 2620 | proc_net_remove(net, "rt6_stats"); |
2550 | 2621 | #endif |
2551 | - rt6_ifdown(net, NULL); | |
2622 | + kfree(net->ipv6.ip6_null_entry); | |
2623 | +#ifdef CONFIG_IPV6_MULTIPLE_TABLES | |
2624 | + kfree(net->ipv6.ip6_prohibit_entry); | |
2625 | + kfree(net->ipv6.ip6_blk_hole_entry); | |
2626 | +#endif | |
2552 | 2627 | } |
2553 | 2628 | |
2554 | 2629 | static struct pernet_operations ip6_route_net_ops = { |
... | ... | @@ -2556,6 +2631,11 @@ |
2556 | 2631 | .exit = ip6_route_net_exit, |
2557 | 2632 | }; |
2558 | 2633 | |
2634 | +static struct notifier_block ip6_route_dev_notifier = { | |
2635 | + .notifier_call = ip6_route_dev_notify, | |
2636 | + .priority = 0, | |
2637 | +}; | |
2638 | + | |
2559 | 2639 | int __init ip6_route_init(void) |
2560 | 2640 | { |
2561 | 2641 | int ret; |
2562 | 2642 | |
2563 | 2643 | |
2564 | 2644 | |
... | ... | @@ -2568,30 +2648,24 @@ |
2568 | 2648 | |
2569 | 2649 | ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops.kmem_cachep; |
2570 | 2650 | |
2571 | - ret = -ENOMEM; | |
2572 | - ip6_null_entry = kmemdup(&ip6_null_entry_template, | |
2573 | - sizeof(*ip6_null_entry), GFP_KERNEL); | |
2574 | - if (!ip6_null_entry) | |
2651 | + ret = register_pernet_subsys(&ip6_route_net_ops); | |
2652 | + if (ret) | |
2575 | 2653 | goto out_kmem_cache; |
2576 | - ip6_null_entry->u.dst.path = (struct dst_entry *)ip6_null_entry; | |
2577 | 2654 | |
2578 | -#ifdef CONFIG_IPV6_MULTIPLE_TABLES | |
2579 | - ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, | |
2580 | - sizeof(*ip6_prohibit_entry), GFP_KERNEL); | |
2581 | - if (!ip6_prohibit_entry) | |
2582 | - goto out_ip6_null_entry; | |
2583 | - ip6_prohibit_entry->u.dst.path = (struct dst_entry *)ip6_prohibit_entry; | |
2584 | - | |
2585 | - ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, | |
2586 | - sizeof(*ip6_blk_hole_entry), GFP_KERNEL); | |
2587 | - if (!ip6_blk_hole_entry) | |
2588 | - goto out_ip6_prohibit_entry; | |
2589 | - ip6_blk_hole_entry->u.dst.path = (struct dst_entry *)ip6_blk_hole_entry; | |
2590 | -#endif | |
2591 | - | |
2655 | + /* Registering of the loopback is done before this portion of code, | |
2656 | + * the loopback reference in rt6_info will not be taken, do it | |
2657 | + * manually for init_net */ | |
2658 | + init_net.ipv6.ip6_null_entry->u.dst.dev = init_net.loopback_dev; | |
2659 | + init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | |
2660 | + #ifdef CONFIG_IPV6_MULTIPLE_TABLES | |
2661 | + init_net.ipv6.ip6_prohibit_entry->u.dst.dev = init_net.loopback_dev; | |
2662 | + init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | |
2663 | + init_net.ipv6.ip6_blk_hole_entry->u.dst.dev = init_net.loopback_dev; | |
2664 | + init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); | |
2665 | + #endif | |
2592 | 2666 | ret = fib6_init(); |
2593 | 2667 | if (ret) |
2594 | - goto out_ip6_blk_hole_entry; | |
2668 | + goto out_register_subsys; | |
2595 | 2669 | |
2596 | 2670 | ret = xfrm6_init(); |
2597 | 2671 | if (ret) |
2598 | 2672 | |
... | ... | @@ -2607,9 +2681,10 @@ |
2607 | 2681 | __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL)) |
2608 | 2682 | goto fib6_rules_init; |
2609 | 2683 | |
2610 | - ret = register_pernet_subsys(&ip6_route_net_ops); | |
2684 | + ret = register_netdevice_notifier(&ip6_route_dev_notifier); | |
2611 | 2685 | if (ret) |
2612 | 2686 | goto fib6_rules_init; |
2687 | + | |
2613 | 2688 | out: |
2614 | 2689 | return ret; |
2615 | 2690 | |
... | ... | @@ -2619,14 +2694,8 @@ |
2619 | 2694 | xfrm6_fini(); |
2620 | 2695 | out_fib6_init: |
2621 | 2696 | fib6_gc_cleanup(); |
2622 | -out_ip6_blk_hole_entry: | |
2623 | -#ifdef CONFIG_IPV6_MULTIPLE_TABLES | |
2624 | - kfree(ip6_blk_hole_entry); | |
2625 | -out_ip6_prohibit_entry: | |
2626 | - kfree(ip6_prohibit_entry); | |
2627 | -out_ip6_null_entry: | |
2628 | -#endif | |
2629 | - kfree(ip6_null_entry); | |
2697 | +out_register_subsys: | |
2698 | + unregister_pernet_subsys(&ip6_route_net_ops); | |
2630 | 2699 | out_kmem_cache: |
2631 | 2700 | kmem_cache_destroy(ip6_dst_ops.kmem_cachep); |
2632 | 2701 | goto out; |
2633 | 2702 | |
2634 | 2703 | |
... | ... | @@ -2634,16 +2703,11 @@ |
2634 | 2703 | |
2635 | 2704 | void ip6_route_cleanup(void) |
2636 | 2705 | { |
2637 | - unregister_pernet_subsys(&ip6_route_net_ops); | |
2706 | + unregister_netdevice_notifier(&ip6_route_dev_notifier); | |
2638 | 2707 | fib6_rules_cleanup(); |
2639 | 2708 | xfrm6_fini(); |
2640 | 2709 | fib6_gc_cleanup(); |
2710 | + unregister_pernet_subsys(&ip6_route_net_ops); | |
2641 | 2711 | kmem_cache_destroy(ip6_dst_ops.kmem_cachep); |
2642 | - | |
2643 | - kfree(ip6_null_entry); | |
2644 | -#ifdef CONFIG_IPV6_MULTIPLE_TABLES | |
2645 | - kfree(ip6_prohibit_entry); | |
2646 | - kfree(ip6_blk_hole_entry); | |
2647 | -#endif | |
2648 | 2712 | } |