]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/ipv4/fib_trie.c
[NETNS]: Add netns parameter to fib_get_table/fib_new_table.
[linux-2.6-omap-h63xx.git] / net / ipv4 / fib_trie.c
index 81a8285d6d6a4251c7cd166635f7058046078bf6..fc0624e6a649b5dd94d873aefe65a3368d3b95cc 100644 (file)
@@ -54,7 +54,7 @@
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
@@ -164,7 +164,6 @@ static struct tnode *halve(struct trie *t, struct tnode *tn);
 static void tnode_free(struct tnode *tn);
 
 static struct kmem_cache *fn_alias_kmem __read_mostly;
-static struct trie *trie_local = NULL, *trie_main = NULL;
 
 static inline struct tnode *node_parent(struct node *node)
 {
@@ -300,10 +299,10 @@ static inline void check_tnode(const struct tnode *tn)
        WARN_ON(tn && tn->pos+tn->bits > 32);
 }
 
-static int halve_threshold = 25;
-static int inflate_threshold = 50;
-static int halve_threshold_root = 8;
-static int inflate_threshold_root = 15;
+static const int halve_threshold = 25;
+static const int inflate_threshold = 50;
+static const int halve_threshold_root = 8;
+static const int inflate_threshold_root = 15;
 
 
 static void __alias_free_mem(struct rcu_head *head)
@@ -1214,6 +1213,9 @@ static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg)
                        struct fib_info *fi_drop;
                        u8 state;
 
+                       if (fi->fib_treeref > 1)
+                               goto out;
+
                        err = -ENOBUFS;
                        new_fa = kmem_cache_alloc(fn_alias_kmem, GFP_KERNEL);
                        if (new_fa == NULL)
@@ -1780,8 +1782,6 @@ static int fn_trie_flush(struct fib_table *tb)
        return found;
 }
 
-static int trie_last_dflt = -1;
-
 static void
 fn_trie_select_default(struct fib_table *tb, const struct flowi *flp, struct fib_result *res)
 {
@@ -1828,39 +1828,29 @@ fn_trie_select_default(struct fib_table *tb, const struct flowi *flp, struct fib
                        if (next_fi != res->fi)
                                break;
                } else if (!fib_detect_death(fi, order, &last_resort,
-                                            &last_idx, &trie_last_dflt)) {
-                       if (res->fi)
-                               fib_info_put(res->fi);
-                       res->fi = fi;
-                       atomic_inc(&fi->fib_clntref);
-                       trie_last_dflt = order;
+                                            &last_idx, tb->tb_default)) {
+                       fib_result_assign(res, fi);
+                       tb->tb_default = order;
                        goto out;
                }
                fi = next_fi;
                order++;
        }
        if (order <= 0 || fi == NULL) {
-               trie_last_dflt = -1;
+               tb->tb_default = -1;
                goto out;
        }
 
-       if (!fib_detect_death(fi, order, &last_resort, &last_idx, &trie_last_dflt)) {
-               if (res->fi)
-                       fib_info_put(res->fi);
-               res->fi = fi;
-               atomic_inc(&fi->fib_clntref);
-               trie_last_dflt = order;
+       if (!fib_detect_death(fi, order, &last_resort, &last_idx,
+                               tb->tb_default)) {
+               fib_result_assign(res, fi);
+               tb->tb_default = order;
                goto out;
        }
-       if (last_idx >= 0) {
-               if (res->fi)
-                       fib_info_put(res->fi);
-               res->fi = last_resort;
-               if (last_resort)
-                       atomic_inc(&last_resort->fib_clntref);
-       }
-       trie_last_dflt = last_idx;
- out:;
+       if (last_idx >= 0)
+               fib_result_assign(res, last_resort);
+       tb->tb_default = last_idx;
+out:
        rcu_read_unlock();
 }
 
@@ -1966,11 +1956,7 @@ out:
 
 /* Fix more generic FIB names for init later */
 
-#ifdef CONFIG_IP_MULTIPLE_TABLES
-struct fib_table * fib_hash_init(u32 id)
-#else
-struct fib_table * __init fib_hash_init(u32 id)
-#endif
+struct fib_table *fib_hash_init(u32 id)
 {
        struct fib_table *tb;
        struct trie *t;
@@ -1987,6 +1973,7 @@ struct fib_table * __init fib_hash_init(u32 id)
                return NULL;
 
        tb->tb_id = id;
+       tb->tb_default = -1;
        tb->tb_lookup = fn_trie_lookup;
        tb->tb_insert = fn_trie_insert;
        tb->tb_delete = fn_trie_delete;
@@ -1999,11 +1986,6 @@ struct fib_table * __init fib_hash_init(u32 id)
 
        trie_init(t);
 
-       if (id == RT_TABLE_LOCAL)
-               trie_local = t;
-       else if (id == RT_TABLE_MAIN)
-               trie_main = t;
-
        if (id == RT_TABLE_LOCAL)
                printk(KERN_INFO "IPv4 FIB: Using LC-trie version %s\n", VERSION);
 
@@ -2013,6 +1995,7 @@ struct fib_table * __init fib_hash_init(u32 id)
 #ifdef CONFIG_PROC_FS
 /* Depth first Trie walk iterator */
 struct fib_trie_iter {
+       struct trie *trie_local, *trie_main;
        struct tnode *tnode;
        struct trie *trie;
        unsigned index;
@@ -2179,7 +2162,20 @@ static void trie_show_stats(struct seq_file *seq, struct trie_stat *stat)
 
 static int fib_triestat_seq_show(struct seq_file *seq, void *v)
 {
+       struct trie *trie_local, *trie_main;
        struct trie_stat *stat;
+       struct fib_table *tb;
+
+       trie_local = NULL;
+       tb = fib_get_table(&init_net, RT_TABLE_LOCAL);
+       if (tb)
+               trie_local = (struct trie *) tb->tb_data;
+
+       trie_main = NULL;
+       tb = fib_get_table(&init_net, RT_TABLE_MAIN);
+       if (tb)
+               trie_main = (struct trie *) tb->tb_data;
+
 
        stat = kmalloc(sizeof(*stat), GFP_KERNEL);
        if (!stat)
@@ -2223,13 +2219,13 @@ static struct node *fib_trie_get_idx(struct fib_trie_iter *iter,
        loff_t idx = 0;
        struct node *n;
 
-       for (n = fib_trie_get_first(iter, trie_local);
+       for (n = fib_trie_get_first(iter, iter->trie_local);
             n; ++idx, n = fib_trie_get_next(iter)) {
                if (pos == idx)
                        return n;
        }
 
-       for (n = fib_trie_get_first(iter, trie_main);
+       for (n = fib_trie_get_first(iter, iter->trie_main);
             n; ++idx, n = fib_trie_get_next(iter)) {
                if (pos == idx)
                        return n;
@@ -2239,10 +2235,23 @@ static struct node *fib_trie_get_idx(struct fib_trie_iter *iter,
 
 static void *fib_trie_seq_start(struct seq_file *seq, loff_t *pos)
 {
+       struct fib_trie_iter *iter = seq->private;
+       struct fib_table *tb;
+
+       if (!iter->trie_local) {
+               tb = fib_get_table(&init_net, RT_TABLE_LOCAL);
+               if (tb)
+                       iter->trie_local = (struct trie *) tb->tb_data;
+       }
+       if (!iter->trie_main) {
+               tb = fib_get_table(&init_net, RT_TABLE_MAIN);
+               if (tb)
+                       iter->trie_main = (struct trie *) tb->tb_data;
+       }
        rcu_read_lock();
        if (*pos == 0)
                return SEQ_START_TOKEN;
-       return fib_trie_get_idx(seq->private, *pos - 1);
+       return fib_trie_get_idx(iter, *pos - 1);
 }
 
 static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos)
@@ -2260,8 +2269,8 @@ static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos)
                return v;
 
        /* continue scan in next trie */
-       if (iter->trie == trie_local)
-               return fib_trie_get_first(iter, trie_main);
+       if (iter->trie == iter->trie_local)
+               return fib_trie_get_first(iter, iter->trie_main);
 
        return NULL;
 }
@@ -2327,7 +2336,7 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v)
                return 0;
 
        if (!node_parent(n)) {
-               if (iter->trie == trie_local)
+               if (iter->trie == iter->trie_local)
                        seq_puts(seq, "<local>:\n");
                else
                        seq_puts(seq, "<main>:\n");
@@ -2426,7 +2435,7 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
                return 0;
        }
 
-       if (iter->trie == trie_local)
+       if (iter->trie == iter->trie_local)
                return 0;
        if (IS_TNODE(l))
                return 0;
@@ -2495,32 +2504,33 @@ static const struct file_operations fib_route_fops = {
        .release = seq_release_private,
 };
 
-int __init fib_proc_init(void)
+int __net_init fib_proc_init(struct net *net)
 {
-       if (!proc_net_fops_create(&init_net, "fib_trie", S_IRUGO, &fib_trie_fops))
+       if (!proc_net_fops_create(net, "fib_trie", S_IRUGO, &fib_trie_fops))
                goto out1;
 
-       if (!proc_net_fops_create(&init_net, "fib_triestat", S_IRUGO, &fib_triestat_fops))
+       if (!proc_net_fops_create(net, "fib_triestat", S_IRUGO,
+                                 &fib_triestat_fops))
                goto out2;
 
-       if (!proc_net_fops_create(&init_net, "route", S_IRUGO, &fib_route_fops))
+       if (!proc_net_fops_create(net, "route", S_IRUGO, &fib_route_fops))
                goto out3;
 
        return 0;
 
 out3:
-       proc_net_remove(&init_net, "fib_triestat");
+       proc_net_remove(net, "fib_triestat");
 out2:
-       proc_net_remove(&init_net, "fib_trie");
+       proc_net_remove(net, "fib_trie");
 out1:
        return -ENOMEM;
 }
 
-void __init fib_proc_exit(void)
+void __net_exit fib_proc_exit(struct net *net)
 {
-       proc_net_remove(&init_net, "fib_trie");
-       proc_net_remove(&init_net, "fib_triestat");
-       proc_net_remove(&init_net, "route");
+       proc_net_remove(net, "fib_trie");
+       proc_net_remove(net, "fib_triestat");
+       proc_net_remove(net, "route");
 }
 
 #endif /* CONFIG_PROC_FS */