diff options
Diffstat (limited to 'net/ipv6/ip6_fib.c')
-rw-r--r-- | net/ipv6/ip6_fib.c | 45 |
1 files changed, 24 insertions, 21 deletions
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index f028f7a1a446..b0814b0082e7 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -79,8 +79,8 @@ static DEFINE_RWLOCK(fib6_walker_lock); | |||
79 | 79 | ||
80 | static void fib6_prune_clones(struct net *net, struct fib6_node *fn, | 80 | static void fib6_prune_clones(struct net *net, struct fib6_node *fn, |
81 | struct rt6_info *rt); | 81 | struct rt6_info *rt); |
82 | static struct rt6_info * fib6_find_prefix(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 fib6_node *fn); | 83 | static struct fib6_node *fib6_repair_tree(struct net *net, struct fib6_node *fn); |
84 | static int fib6_walk(struct fib6_walker_t *w); | 84 | static int fib6_walk(struct fib6_walker_t *w); |
85 | static int fib6_walk_continue(struct fib6_walker_t *w); | 85 | static int fib6_walk_continue(struct fib6_walker_t *w); |
86 | 86 | ||
@@ -193,14 +193,14 @@ static void fib6_link_table(struct net *net, struct fib6_table *tb) | |||
193 | 193 | ||
194 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 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 | struct fib6_table *table; | 198 | struct fib6_table *table; |
199 | 199 | ||
200 | table = kzalloc(sizeof(*table), GFP_ATOMIC); | 200 | table = kzalloc(sizeof(*table), GFP_ATOMIC); |
201 | if (table != NULL) { | 201 | if (table != NULL) { |
202 | table->tb6_id = id; | 202 | table->tb6_id = id; |
203 | table->tb6_root.leaf = ip6_null_entry; | 203 | table->tb6_root.leaf = net->ipv6.ip6_null_entry; |
204 | table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; | 204 | table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; |
205 | } | 205 | } |
206 | 206 | ||
@@ -217,7 +217,7 @@ struct fib6_table *fib6_new_table(struct net *net, u32 id) | |||
217 | if (tb) | 217 | if (tb) |
218 | return tb; | 218 | return tb; |
219 | 219 | ||
220 | tb = fib6_alloc_table(id); | 220 | tb = fib6_alloc_table(net, id); |
221 | if (tb != NULL) | 221 | if (tb != NULL) |
222 | fib6_link_table(net, tb); | 222 | fib6_link_table(net, tb); |
223 | 223 | ||
@@ -267,7 +267,7 @@ struct fib6_table *fib6_get_table(struct net *net, u32 id) | |||
267 | struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl, | 267 | struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl, |
268 | int flags, pol_lookup_t lookup) | 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 | static void fib6_tables_init(struct net *net) | 273 | static void fib6_tables_init(struct net *net) |
@@ -717,8 +717,8 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info) | |||
717 | if (sfn == NULL) | 717 | if (sfn == NULL) |
718 | goto st_failure; | 718 | goto st_failure; |
719 | 719 | ||
720 | sfn->leaf = ip6_null_entry; | 720 | sfn->leaf = info->nl_net->ipv6.ip6_null_entry; |
721 | atomic_inc(&ip6_null_entry->rt6i_ref); | 721 | atomic_inc(&info->nl_net->ipv6.ip6_null_entry->rt6i_ref); |
722 | sfn->fn_flags = RTN_ROOT; | 722 | sfn->fn_flags = RTN_ROOT; |
723 | sfn->fn_sernum = fib6_new_sernum(); | 723 | sfn->fn_sernum = fib6_new_sernum(); |
724 | 724 | ||
@@ -773,11 +773,11 @@ out: | |||
773 | * super-tree leaf node we have to find a new one for it. | 773 | * super-tree leaf node we have to find a new one for it. |
774 | */ | 774 | */ |
775 | if (pn != fn && !pn->leaf && !(pn->fn_flags & RTN_RTINFO)) { | 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 | #if RT6_DEBUG >= 2 | 777 | #if RT6_DEBUG >= 2 |
778 | if (!pn->leaf) { | 778 | if (!pn->leaf) { |
779 | BUG_TRAP(pn->leaf != NULL); | 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 | #endif | 782 | #endif |
783 | atomic_inc(&pn->leaf->rt6i_ref); | 783 | atomic_inc(&pn->leaf->rt6i_ref); |
@@ -793,7 +793,7 @@ out: | |||
793 | */ | 793 | */ |
794 | st_failure: | 794 | st_failure: |
795 | if (fn && !(fn->fn_flags & (RTN_RTINFO|RTN_ROOT))) | 795 | if (fn && !(fn->fn_flags & (RTN_RTINFO|RTN_ROOT))) |
796 | fib6_repair_tree(fn); | 796 | fib6_repair_tree(info->nl_net, fn); |
797 | dst_free(&rt->u.dst); | 797 | dst_free(&rt->u.dst); |
798 | return err; | 798 | return err; |
799 | #endif | 799 | #endif |
@@ -959,10 +959,10 @@ struct fib6_node * fib6_locate(struct fib6_node *root, | |||
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 | if (fn->fn_flags&RTN_ROOT) | 964 | if (fn->fn_flags&RTN_ROOT) |
965 | return ip6_null_entry; | 965 | return net->ipv6.ip6_null_entry; |
966 | 966 | ||
967 | while(fn) { | 967 | while(fn) { |
968 | if(fn->left) | 968 | if(fn->left) |
@@ -981,7 +981,8 @@ static struct rt6_info * fib6_find_prefix(struct fib6_node *fn) | |||
981 | * is the node we want to try and remove. | 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 | int children; | 987 | int children; |
987 | int nstate; | 988 | int nstate; |
@@ -1008,11 +1009,11 @@ static struct fib6_node * fib6_repair_tree(struct fib6_node *fn) | |||
1008 | || (children && fn->fn_flags&RTN_ROOT) | 1009 | || (children && fn->fn_flags&RTN_ROOT) |
1009 | #endif | 1010 | #endif |
1010 | ) { | 1011 | ) { |
1011 | fn->leaf = fib6_find_prefix(fn); | 1012 | fn->leaf = fib6_find_prefix(net, fn); |
1012 | #if RT6_DEBUG >= 2 | 1013 | #if RT6_DEBUG >= 2 |
1013 | if (fn->leaf==NULL) { | 1014 | if (fn->leaf==NULL) { |
1014 | BUG_TRAP(fn->leaf); | 1015 | BUG_TRAP(fn->leaf); |
1015 | fn->leaf = ip6_null_entry; | 1016 | fn->leaf = net->ipv6.ip6_null_entry; |
1016 | } | 1017 | } |
1017 | #endif | 1018 | #endif |
1018 | atomic_inc(&fn->leaf->rt6i_ref); | 1019 | atomic_inc(&fn->leaf->rt6i_ref); |
@@ -1117,7 +1118,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, | |||
1117 | if (fn->leaf == NULL) { | 1118 | if (fn->leaf == NULL) { |
1118 | fn->fn_flags &= ~RTN_RTINFO; | 1119 | fn->fn_flags &= ~RTN_RTINFO; |
1119 | net->ipv6.rt6_stats->fib_route_nodes--; | 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 | if (atomic_read(&rt->rt6i_ref) != 1) { | 1124 | if (atomic_read(&rt->rt6i_ref) != 1) { |
@@ -1129,7 +1130,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, | |||
1129 | */ | 1130 | */ |
1130 | while (fn) { | 1131 | while (fn) { |
1131 | if (!(fn->fn_flags&RTN_RTINFO) && fn->leaf == rt) { | 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 | atomic_inc(&fn->leaf->rt6i_ref); | 1134 | atomic_inc(&fn->leaf->rt6i_ref); |
1134 | rt6_release(rt); | 1135 | rt6_release(rt); |
1135 | } | 1136 | } |
@@ -1145,6 +1146,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, | |||
1145 | 1146 | ||
1146 | int fib6_del(struct rt6_info *rt, struct nl_info *info) | 1147 | int fib6_del(struct rt6_info *rt, struct nl_info *info) |
1147 | { | 1148 | { |
1149 | struct net *net = info->nl_net; | ||
1148 | struct fib6_node *fn = rt->rt6i_node; | 1150 | struct fib6_node *fn = rt->rt6i_node; |
1149 | struct rt6_info **rtp; | 1151 | struct rt6_info **rtp; |
1150 | 1152 | ||
@@ -1154,7 +1156,7 @@ int fib6_del(struct rt6_info *rt, struct nl_info *info) | |||
1154 | return -ENOENT; | 1156 | return -ENOENT; |
1155 | } | 1157 | } |
1156 | #endif | 1158 | #endif |
1157 | if (fn == NULL || rt == ip6_null_entry) | 1159 | if (fn == NULL || rt == net->ipv6.ip6_null_entry) |
1158 | return -ENOENT; | 1160 | return -ENOENT; |
1159 | 1161 | ||
1160 | BUG_TRAP(fn->fn_flags&RTN_RTINFO); | 1162 | BUG_TRAP(fn->fn_flags&RTN_RTINFO); |
@@ -1501,7 +1503,7 @@ static int fib6_net_init(struct net *net) | |||
1501 | goto out_fib_table_hash; | 1503 | goto out_fib_table_hash; |
1502 | 1504 | ||
1503 | net->ipv6.fib6_main_tbl->tb6_id = RT6_TABLE_MAIN; | 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 | net->ipv6.fib6_main_tbl->tb6_root.fn_flags = | 1507 | net->ipv6.fib6_main_tbl->tb6_root.fn_flags = |
1506 | RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; | 1508 | RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; |
1507 | 1509 | ||
@@ -1511,7 +1513,7 @@ static int fib6_net_init(struct net *net) | |||
1511 | if (!net->ipv6.fib6_local_tbl) | 1513 | if (!net->ipv6.fib6_local_tbl) |
1512 | goto out_fib6_main_tbl; | 1514 | goto out_fib6_main_tbl; |
1513 | net->ipv6.fib6_local_tbl->tb6_id = RT6_TABLE_LOCAL; | 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 | net->ipv6.fib6_local_tbl->tb6_root.fn_flags = | 1517 | net->ipv6.fib6_local_tbl->tb6_root.fn_flags = |
1516 | RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; | 1518 | RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; |
1517 | #endif | 1519 | #endif |
@@ -1536,6 +1538,7 @@ out_timer: | |||
1536 | 1538 | ||
1537 | static void fib6_net_exit(struct net *net) | 1539 | static void fib6_net_exit(struct net *net) |
1538 | { | 1540 | { |
1541 | rt6_ifdown(net, NULL); | ||
1539 | del_timer(net->ipv6.ip6_fib_timer); | 1542 | del_timer(net->ipv6.ip6_fib_timer); |
1540 | kfree(net->ipv6.ip6_fib_timer); | 1543 | kfree(net->ipv6.ip6_fib_timer); |
1541 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 1544 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |