ipv6: introduce a new function fib6_update_sernum()
[linux-2.6-microblaze.git] / net / ipv6 / ip6_fib.c
index a3b5c16..0ba4fbb 100644 (file)
@@ -110,6 +110,20 @@ enum {
        FIB6_NO_SERNUM_CHANGE = 0,
 };
 
+void fib6_update_sernum(struct rt6_info *rt)
+{
+       struct fib6_table *table = rt->rt6i_table;
+       struct net *net = dev_net(rt->dst.dev);
+       struct fib6_node *fn;
+
+       write_lock_bh(&table->tb6_lock);
+       fn = rcu_dereference_protected(rt->rt6i_node,
+                       lockdep_is_held(&table->tb6_lock));
+       if (fn)
+               fn->fn_sernum = fib6_new_sernum(net);
+       write_unlock_bh(&table->tb6_lock);
+}
+
 /*
  *     Auxiliary address test functions for the radix tree.
  *
@@ -191,6 +205,12 @@ void rt6_free_pcpu(struct rt6_info *non_pcpu_rt)
 }
 EXPORT_SYMBOL_GPL(rt6_free_pcpu);
 
+static void fib6_free_table(struct fib6_table *table)
+{
+       inetpeer_invalidate_tree(&table->tb6_peers);
+       kfree(table);
+}
+
 static void fib6_link_table(struct net *net, struct fib6_table *tb)
 {
        unsigned int h;
@@ -2022,15 +2042,22 @@ out_timer:
 
 static void fib6_net_exit(struct net *net)
 {
+       unsigned int i;
+
        rt6_ifdown(net, NULL);
        del_timer_sync(&net->ipv6.ip6_fib_timer);
 
-#ifdef CONFIG_IPV6_MULTIPLE_TABLES
-       inetpeer_invalidate_tree(&net->ipv6.fib6_local_tbl->tb6_peers);
-       kfree(net->ipv6.fib6_local_tbl);
-#endif
-       inetpeer_invalidate_tree(&net->ipv6.fib6_main_tbl->tb6_peers);
-       kfree(net->ipv6.fib6_main_tbl);
+       for (i = 0; i < FIB6_TABLE_HASHSZ; i++) {
+               struct hlist_head *head = &net->ipv6.fib_table_hash[i];
+               struct hlist_node *tmp;
+               struct fib6_table *tb;
+
+               hlist_for_each_entry_safe(tb, tmp, head, tb6_hlist) {
+                       hlist_del(&tb->tb6_hlist);
+                       fib6_free_table(tb);
+               }
+       }
+
        kfree(net->ipv6.fib_table_hash);
        kfree(net->ipv6.rt6_stats);
        fib6_notifier_exit(net);