Commit 3d3b2d25 authored by Stephen Hemminger's avatar Stephen Hemminger Committed by David S. Miller

fib_trie: print information on all routing tables

Make /proc/net/fib_trie and /proc/net/fib_triestat display
all routing tables, not just local and main.
Signed-off-by: default avatarStephen Hemminger <shemminger@vyatta.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2a706ec1
...@@ -2026,9 +2026,8 @@ struct fib_table *fib_hash_table(u32 id) ...@@ -2026,9 +2026,8 @@ struct fib_table *fib_hash_table(u32 id)
/* Depth first Trie walk iterator */ /* Depth first Trie walk iterator */
struct fib_trie_iter { struct fib_trie_iter {
struct seq_net_private p; struct seq_net_private p;
struct trie *trie_local, *trie_main; struct fib_table *tb;
struct tnode *tnode; struct tnode *tnode;
struct trie *trie;
unsigned index; unsigned index;
unsigned depth; unsigned depth;
}; };
...@@ -2081,31 +2080,26 @@ rescan: ...@@ -2081,31 +2080,26 @@ rescan:
static struct node *fib_trie_get_first(struct fib_trie_iter *iter, static struct node *fib_trie_get_first(struct fib_trie_iter *iter,
struct trie *t) struct trie *t)
{ {
struct node *n ; struct node *n;
if (!t) if (!t)
return NULL; return NULL;
n = rcu_dereference(t->trie); n = rcu_dereference(t->trie);
if (!n)
if (!iter)
return NULL; return NULL;
if (n) { if (IS_TNODE(n)) {
if (IS_TNODE(n)) { iter->tnode = (struct tnode *) n;
iter->tnode = (struct tnode *) n; iter->index = 0;
iter->trie = t; iter->depth = 1;
iter->index = 0; } else {
iter->depth = 1; iter->tnode = NULL;
} else { iter->index = 0;
iter->tnode = NULL; iter->depth = 0;
iter->trie = t;
iter->index = 0;
iter->depth = 0;
}
return n;
} }
return NULL;
return n;
} }
static void trie_collect_stats(struct trie *t, struct trie_stat *s) static void trie_collect_stats(struct trie *t, struct trie_stat *s)
...@@ -2116,8 +2110,7 @@ static void trie_collect_stats(struct trie *t, struct trie_stat *s) ...@@ -2116,8 +2110,7 @@ static void trie_collect_stats(struct trie *t, struct trie_stat *s)
memset(s, 0, sizeof(*s)); memset(s, 0, sizeof(*s));
rcu_read_lock(); rcu_read_lock();
for (n = fib_trie_get_first(&iter, t); n; for (n = fib_trie_get_first(&iter, t); n; n = fib_trie_get_next(&iter)) {
n = fib_trie_get_next(&iter)) {
if (IS_LEAF(n)) { if (IS_LEAF(n)) {
struct leaf *l = (struct leaf *)n; struct leaf *l = (struct leaf *)n;
struct leaf_info *li; struct leaf_info *li;
...@@ -2206,36 +2199,48 @@ static void trie_show_usage(struct seq_file *seq, ...@@ -2206,36 +2199,48 @@ static void trie_show_usage(struct seq_file *seq,
} }
#endif /* CONFIG_IP_FIB_TRIE_STATS */ #endif /* CONFIG_IP_FIB_TRIE_STATS */
static void fib_trie_show(struct seq_file *seq, const char *name, static void fib_table_print(struct seq_file *seq, struct fib_table *tb)
struct trie *trie)
{ {
struct trie_stat stat; if (tb->tb_id == RT_TABLE_LOCAL)
seq_puts(seq, "Local:\n");
trie_collect_stats(trie, &stat); else if (tb->tb_id == RT_TABLE_MAIN)
seq_printf(seq, "%s:\n", name); seq_puts(seq, "Main:\n");
trie_show_stats(seq, &stat); else
#ifdef CONFIG_IP_FIB_TRIE_STATS seq_printf(seq, "Id %d:\n", tb->tb_id);
trie_show_usage(seq, &trie->stats);
#endif
} }
static int fib_triestat_seq_show(struct seq_file *seq, void *v) static int fib_triestat_seq_show(struct seq_file *seq, void *v)
{ {
struct net *net = (struct net *)seq->private; struct net *net = (struct net *)seq->private;
struct fib_table *tb; unsigned int h;
seq_printf(seq, seq_printf(seq,
"Basic info: size of leaf:" "Basic info: size of leaf:"
" %Zd bytes, size of tnode: %Zd bytes.\n", " %Zd bytes, size of tnode: %Zd bytes.\n",
sizeof(struct leaf), sizeof(struct tnode)); sizeof(struct leaf), sizeof(struct tnode));
tb = fib_get_table(net, RT_TABLE_LOCAL); for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
if (tb) struct hlist_head *head = &net->ipv4.fib_table_hash[h];
fib_trie_show(seq, "Local", (struct trie *) tb->tb_data); struct hlist_node *node;
struct fib_table *tb;
hlist_for_each_entry_rcu(tb, node, head, tb_hlist) {
struct trie *t = (struct trie *) tb->tb_data;
struct trie_stat stat;
if (!t)
continue;
tb = fib_get_table(net, RT_TABLE_MAIN); fib_table_print(seq, tb);
if (tb)
fib_trie_show(seq, "Main", (struct trie *) tb->tb_data); trie_collect_stats(t, &stat);
trie_show_stats(seq, &stat);
#ifdef CONFIG_IP_FIB_TRIE_STATS
trie_show_usage(seq, &t->stats);
#endif
}
}
return 0; return 0;
} }
...@@ -2271,23 +2276,30 @@ static const struct file_operations fib_triestat_fops = { ...@@ -2271,23 +2276,30 @@ static const struct file_operations fib_triestat_fops = {
.release = fib_triestat_seq_release, .release = fib_triestat_seq_release,
}; };
static struct node *fib_trie_get_idx(struct fib_trie_iter *iter, static struct node *fib_trie_get_idx(struct fib_trie_iter *iter, loff_t pos)
loff_t pos)
{ {
struct net *net = iter->p.net;
loff_t idx = 0; loff_t idx = 0;
struct node *n; unsigned int h;
for (n = fib_trie_get_first(iter, iter->trie_local); for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
n; ++idx, n = fib_trie_get_next(iter)) { struct hlist_head *head = &net->ipv4.fib_table_hash[h];
if (pos == idx) struct hlist_node *node;
return n; struct fib_table *tb;
}
for (n = fib_trie_get_first(iter, iter->trie_main); hlist_for_each_entry_rcu(tb, node, head, tb_hlist) {
n; ++idx, n = fib_trie_get_next(iter)) { struct node *n;
if (pos == idx)
return n; for (n = fib_trie_get_first(iter,
(struct trie *) tb->tb_data);
n; n = fib_trie_get_next(iter))
if (pos == idx++) {
iter->tb = tb;
return n;
}
}
} }
return NULL; return NULL;
} }
...@@ -2295,43 +2307,49 @@ static void *fib_trie_seq_start(struct seq_file *seq, loff_t *pos) ...@@ -2295,43 +2307,49 @@ static void *fib_trie_seq_start(struct seq_file *seq, loff_t *pos)
__acquires(RCU) __acquires(RCU)
{ {
struct fib_trie_iter *iter = seq->private; struct fib_trie_iter *iter = seq->private;
struct fib_table *tb;
if (!iter->trie_local) {
tb = fib_get_table(iter->p.net, RT_TABLE_LOCAL);
if (tb)
iter->trie_local = (struct trie *) tb->tb_data;
}
if (!iter->trie_main) {
tb = fib_get_table(iter->p.net, RT_TABLE_MAIN);
if (tb)
iter->trie_main = (struct trie *) tb->tb_data;
}
rcu_read_lock(); rcu_read_lock();
if (*pos == 0) return fib_trie_get_idx(iter, *pos);
return SEQ_START_TOKEN;
return fib_trie_get_idx(iter, *pos - 1);
} }
static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos) static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{ {
struct fib_trie_iter *iter = seq->private; struct fib_trie_iter *iter = seq->private;
void *l = v; struct net *net = iter->p.net;
struct fib_table *tb = iter->tb;
struct hlist_node *tb_node;
unsigned int h;
struct node *n;
++*pos; ++*pos;
if (v == SEQ_START_TOKEN) /* next node in same table */
return fib_trie_get_idx(iter, 0); n = fib_trie_get_next(iter);
if (n)
v = fib_trie_get_next(iter); return n;
BUG_ON(v == l);
if (v)
return v;
/* continue scan in next trie */ /* walk rest of this hash chain */
if (iter->trie == iter->trie_local) h = tb->tb_id & (FIB_TABLE_HASHSZ - 1);
return fib_trie_get_first(iter, iter->trie_main); while ( (tb_node = rcu_dereference(tb->tb_hlist.next)) ) {
tb = hlist_entry(tb_node, struct fib_table, tb_hlist);
n = fib_trie_get_first(iter, (struct trie *) tb->tb_data);
if (n)
goto found;
}
/* new hash chain */
while (++h < FIB_TABLE_HASHSZ) {
struct hlist_head *head = &net->ipv4.fib_table_hash[h];
hlist_for_each_entry_rcu(tb, tb_node, head, tb_hlist) {
n = fib_trie_get_first(iter, (struct trie *) tb->tb_data);
if (n)
goto found;
}
}
return NULL; return NULL;
found:
iter->tb = tb;
return n;
} }
static void fib_trie_seq_stop(struct seq_file *seq, void *v) static void fib_trie_seq_stop(struct seq_file *seq, void *v)
...@@ -2388,15 +2406,8 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v) ...@@ -2388,15 +2406,8 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v)
const struct fib_trie_iter *iter = seq->private; const struct fib_trie_iter *iter = seq->private;
struct node *n = v; struct node *n = v;
if (v == SEQ_START_TOKEN) if (!node_parent_rcu(n))
return 0; fib_table_print(seq, iter->tb);
if (!node_parent_rcu(n)) {
if (iter->trie == iter->trie_local)
seq_puts(seq, "<local>:\n");
else
seq_puts(seq, "<main>:\n");
}
if (IS_TNODE(n)) { if (IS_TNODE(n)) {
struct tnode *tn = (struct tnode *) n; struct tnode *tn = (struct tnode *) n;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment