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

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

[IPV4] fib_trie: dump table in sorted order



It is easier with TRIE to dump the data traversal rather than
interating over every possible prefix. This saves some time and makes
the dump come out in sorted order.

Signed-off-by: default avatarStephen Hemminger <shemminger@vyatta.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 82cfbb00
Loading
Loading
Loading
Loading
+39 −35
Original line number Diff line number Diff line
@@ -1908,67 +1908,71 @@ static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah,
	return skb->len;
}

static int fn_trie_dump_plen(struct trie *t, int plen, struct fib_table *tb,

static int fn_trie_dump_leaf(struct leaf *l, struct fib_table *tb,
			struct sk_buff *skb, struct netlink_callback *cb)
{
	int h, s_h;
	struct list_head *fa_head;
	struct leaf *l = NULL;
	struct leaf_info *li;
	struct hlist_node *node;
	int i, s_i;

	s_h = cb->args[3];
	h = 0;
	s_i = cb->args[3];
	i = 0;

	for (l = trie_firstleaf(t); l != NULL; h++, l = trie_nextleaf(l)) {
		if (h < s_h)
	/* rcu_read_lock is hold by caller */
	hlist_for_each_entry_rcu(li, node, &l->list, hlist) {
		if (i < s_i) {
			i++;
			continue;
		if (h > s_h)
			memset(&cb->args[4], 0,
			       sizeof(cb->args) - 4*sizeof(cb->args[0]));

		fa_head = get_fa_head(l, plen);
		}

		if (!fa_head)
			continue;
		if (i > s_i)
			cb->args[4] = 0;

		if (list_empty(fa_head))
		if (list_empty(&li->falh))
			continue;

		if (fn_trie_dump_fa(l->key, plen, fa_head, tb, skb, cb) < 0) {
			cb->args[3] = h;
		if (fn_trie_dump_fa(l->key, li->plen, &li->falh, tb, skb, cb) < 0) {
			cb->args[3] = i;
			return -1;
		}
		i++;
	}
	cb->args[3] = h;

	cb->args[3] = i;
	return skb->len;
}



static int fn_trie_dump(struct fib_table *tb, struct sk_buff *skb,
			struct netlink_callback *cb)
{
	int m, s_m;
	struct leaf *l;
	struct trie *t = (struct trie *) tb->tb_data;

	s_m = cb->args[2];
	int h = 0;
	int s_h = cb->args[2];

	rcu_read_lock();
	for (m = 0; m <= 32; m++) {
		if (m < s_m)
	for (h = 0, l = trie_firstleaf(t); l != NULL; h++, l = trie_nextleaf(l)) {
		if (h < s_h)
			continue;
		if (m > s_m)
			memset(&cb->args[3], 0,
				sizeof(cb->args) - 3*sizeof(cb->args[0]));

		if (fn_trie_dump_plen(t, 32-m, tb, skb, cb) < 0) {
			cb->args[2] = m;
			goto out;
		if (h > s_h) {
			cb->args[3] = 0;
			cb->args[4] = 0;
		}

		if (fn_trie_dump_leaf(l, tb, skb, cb) < 0) {
			rcu_read_unlock();
			cb->args[2] = h;
			return -1;
		}
	}
	rcu_read_unlock();
	cb->args[2] = m;

	cb->args[2] = h;
	return skb->len;
out:
	rcu_read_unlock();
	return -1;
}

void __init fib_hash_init(void)