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: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
2a706ec188
commit
3d3b2d25a4
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -2087,26 +2086,21 @@ static struct node *fib_trie_get_first(struct fib_trie_iter *iter,
|
||||||
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->trie = t;
|
|
||||||
iter->index = 0;
|
iter->index = 0;
|
||||||
iter->depth = 1;
|
iter->depth = 1;
|
||||||
} else {
|
} else {
|
||||||
iter->tnode = NULL;
|
iter->tnode = NULL;
|
||||||
iter->trie = t;
|
|
||||||
iter->index = 0;
|
iter->index = 0;
|
||||||
iter->depth = 0;
|
iter->depth = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
||||||
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,
|
||||||
}
|
}
|
||||||
#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;
|
||||||
|
|
||||||
tb = fib_get_table(net, RT_TABLE_MAIN);
|
hlist_for_each_entry_rcu(tb, node, head, tb_hlist) {
|
||||||
if (tb)
|
struct trie *t = (struct trie *) tb->tb_data;
|
||||||
fib_trie_show(seq, "Main", (struct trie *) tb->tb_data);
|
struct trie_stat stat;
|
||||||
|
|
||||||
|
if (!t)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
fib_table_print(seq, tb);
|
||||||
|
|
||||||
|
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 = {
|
||||||
.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;
|
||||||
|
unsigned int h;
|
||||||
|
|
||||||
|
for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
|
||||||
|
struct hlist_head *head = &net->ipv4.fib_table_hash[h];
|
||||||
|
struct hlist_node *node;
|
||||||
|
struct fib_table *tb;
|
||||||
|
|
||||||
|
hlist_for_each_entry_rcu(tb, node, head, tb_hlist) {
|
||||||
struct node *n;
|
struct node *n;
|
||||||
|
|
||||||
for (n = fib_trie_get_first(iter, iter->trie_local);
|
for (n = fib_trie_get_first(iter,
|
||||||
n; ++idx, n = fib_trie_get_next(iter)) {
|
(struct trie *) tb->tb_data);
|
||||||
if (pos == idx)
|
n; n = fib_trie_get_next(iter))
|
||||||
|
if (pos == idx++) {
|
||||||
|
iter->tb = tb;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (n = fib_trie_get_first(iter, iter->trie_main);
|
|
||||||
n; ++idx, n = fib_trie_get_next(iter)) {
|
|
||||||
if (pos == idx)
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
return n;
|
||||||
|
|
||||||
v = fib_trie_get_next(iter);
|
/* walk rest of this hash chain */
|
||||||
BUG_ON(v == l);
|
h = tb->tb_id & (FIB_TABLE_HASHSZ - 1);
|
||||||
if (v)
|
while ( (tb_node = rcu_dereference(tb->tb_hlist.next)) ) {
|
||||||
return v;
|
tb = hlist_entry(tb_node, struct fib_table, tb_hlist);
|
||||||
|
n = fib_trie_get_first(iter, (struct trie *) tb->tb_data);
|
||||||
/* continue scan in next trie */
|
if (n)
|
||||||
if (iter->trie == iter->trie_local)
|
goto found;
|
||||||
return fib_trie_get_first(iter, iter->trie_main);
|
}
|
||||||
|
|
||||||
|
/* 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)
|
||||||
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;
|
||||||
|
|
Loading…
Reference in New Issue