Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+95 −84
Original line number Original line Diff line number Diff line
@@ -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;

		hlist_for_each_entry_rcu(tb, node, head, tb_hlist) {
			struct trie *t = (struct trie *) tb->tb_data;
			struct trie_stat stat;


	tb = fib_get_table(net, RT_TABLE_MAIN);
			if (!t)
	if (tb)
				continue;
		fib_trie_show(seq, "Main", (struct trie *) tb->tb_data);

			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)
	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)
	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;