aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ip6_fib.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/ip6_fib.c')
-rw-r--r--net/ipv6/ip6_fib.c45
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
80static void fib6_prune_clones(struct net *net, struct fib6_node *fn, 80static void fib6_prune_clones(struct net *net, struct fib6_node *fn,
81 struct rt6_info *rt); 81 struct rt6_info *rt);
82static struct rt6_info * fib6_find_prefix(struct fib6_node *fn); 82static struct rt6_info *fib6_find_prefix(struct net *net, struct fib6_node *fn);
83static struct fib6_node * fib6_repair_tree(struct fib6_node *fn); 83static struct fib6_node *fib6_repair_tree(struct net *net, struct fib6_node *fn);
84static int fib6_walk(struct fib6_walker_t *w); 84static int fib6_walk(struct fib6_walker_t *w);
85static int fib6_walk_continue(struct fib6_walker_t *w); 85static 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
196static struct fib6_table *fib6_alloc_table(u32 id) 196static 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)
267struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl, 267struct 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
273static void fib6_tables_init(struct net *net) 273static 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 */
794st_failure: 794st_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
962static struct rt6_info * fib6_find_prefix(struct fib6_node *fn) 962static 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
984static struct fib6_node * fib6_repair_tree(struct fib6_node *fn) 984static 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
1146int fib6_del(struct rt6_info *rt, struct nl_info *info) 1147int 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
1537static void fib6_net_exit(struct net *net) 1539static 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