From 5b815da25a16f31928842d38dc2c5e16906e288b Mon Sep 17 00:00:00 2001 From: Masahide NAKAMURA Date: Tue, 24 Jul 2007 12:48:21 +0900 Subject: [PATCH] [PATCH] [IPV6] FIB: Show fib6 tree as a proc interface. Signed-off-by: Masahide NAKAMURA --- include/net/ip6_fib.h | 1 + net/ipv6/ip6_fib.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 92 insertions(+), 1 deletions(-) diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h index 85d6d9f..27ad37c 100644 --- a/include/net/ip6_fib.h +++ b/include/net/ip6_fib.h @@ -121,6 +121,7 @@ struct fib6_walker_t struct rt6_info *leaf; unsigned char state; unsigned char prune; + unsigned char im_node; int (*func)(struct fib6_walker_t *); void *args; }; diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 6a612a7..bd4f3a1 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -31,6 +31,7 @@ #include #ifdef CONFIG_PROC_FS #include +#include #endif #include @@ -1260,7 +1261,8 @@ #endif w->state = FWS_C; w->leaf = fn->leaf; case FWS_C: - if (w->leaf && fn->fn_flags&RTN_RTINFO) { + if (w->leaf && + (fn->fn_flags&RTN_RTINFO || w->im_node)) { int err = w->func(w); if (err) return err; @@ -1354,6 +1356,7 @@ static void fib6_clean_tree(struct fib6_ c.w.root = root; c.w.func = fib6_clean_node; c.w.prune = prune; + c.w.im_node = 0; c.func = func; c.arg = arg; @@ -1469,6 +1472,87 @@ void fib6_run_gc(unsigned long dummy) spin_unlock_bh(&fib6_gc_lock); } +#ifdef CONFIG_PROC_FS +struct fib6_tree_args +{ + struct seq_file *seq; +}; + +static int __fib6_tree_seq_show_node(struct fib6_walker_t *w) +{ + struct fib6_tree_args *args = (struct fib6_tree_args *)w->args; + struct seq_file *seq = args->seq; + struct fib6_node *fn = w->node; + + BUG_TRAP(fn); + + seq_printf(seq, " %p %p %p %p", fn, fn->left, fn->right, + FIB6_SUBTREE(fn)); + seq_printf(seq, " %04x %04x %08x", fn->fn_bit, fn->fn_flags, + fn->fn_sernum); + + if (fn->fn_flags & RTN_RTINFO) { + struct rt6_info *rt6i = w->leaf; + seq_printf(seq, " " NIP6_SEQFMT " %02x " NIP6_SEQFMT " %02x", + NIP6(rt6i->rt6i_dst.addr), rt6i->rt6i_dst.plen, + NIP6(rt6i->rt6i_src.addr), rt6i->rt6i_src.plen); + } + + seq_printf(seq, "\n"); + + w->leaf = NULL; + + return 0; +} + +static int fib6_tree_seq_show(struct seq_file *seq, void *v) +{ + struct fib6_tree_args args; + struct fib6_walker_t w; + struct fib6_table *table; + struct hlist_node *node; + unsigned int h; + + args.seq = seq; + + memset(&w, 0, sizeof(w)); + w.func = __fib6_tree_seq_show_node; + w.prune = 0; + w.im_node = 1; + w.args = &args; + + rcu_read_lock(); + for (h = 0; h < FIB_TABLE_HASHSZ; h++) { + hlist_for_each_entry_rcu(table, node, &fib_table_hash[h], + tb6_hlist) { + read_lock_bh(&table->tb6_lock); + + w.root = &table->tb6_root; + seq_printf(seq, "%08x\n", table->tb6_id); + fib6_walk(&w); + + read_unlock_bh(&table->tb6_lock); + } + } + rcu_read_unlock(); + + return 0; +} + +static int fib6_tree_seq_open(struct inode *inode, struct file *file) +{ + return single_open(file, fib6_tree_seq_show, NULL); +} + +static struct file_operations fib6_tree_seq_fops = { + .owner = THIS_MODULE, + .open = fib6_tree_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +#endif /* CONFIG_PROC_FS */ + void __init fib6_init(void) { fib6_node_kmem = kmem_cache_create("fib6_nodes", @@ -1477,12 +1561,18 @@ void __init fib6_init(void) NULL); fib6_tables_init(); +#ifdef CONFIG_PROC_FS + proc_net_fops_create("fib6_tree", S_IRUGO, &fib6_tree_seq_fops); +#endif __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib); } void fib6_gc_cleanup(void) { +#ifdef CONFIG_PROC_FS + proc_net_remove("fib6_tree"); +#endif del_timer(&ip6_fib_timer); kmem_cache_destroy(fib6_node_kmem); } -- 1.4.3.GIT