mirror of https://gitee.com/openkylin/linux.git
[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: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
82cfbb0085
commit
a88ee22925
|
@ -1908,67 +1908,71 @@ static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah,
|
||||||
return skb->len;
|
return skb->len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fn_trie_dump_plen(struct trie *t, int plen, struct fib_table *tb,
|
|
||||||
struct sk_buff *skb, struct netlink_callback *cb)
|
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 leaf_info *li;
|
||||||
struct list_head *fa_head;
|
struct hlist_node *node;
|
||||||
struct leaf *l = NULL;
|
int i, s_i;
|
||||||
|
|
||||||
s_h = cb->args[3];
|
s_i = cb->args[3];
|
||||||
h = 0;
|
i = 0;
|
||||||
|
|
||||||
for (l = trie_firstleaf(t); l != NULL; h++, l = trie_nextleaf(l)) {
|
/* rcu_read_lock is hold by caller */
|
||||||
if (h < s_h)
|
hlist_for_each_entry_rcu(li, node, &l->list, hlist) {
|
||||||
|
if (i < s_i) {
|
||||||
|
i++;
|
||||||
continue;
|
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 (i > s_i)
|
||||||
|
cb->args[4] = 0;
|
||||||
|
|
||||||
if (!fa_head)
|
if (list_empty(&li->falh))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (list_empty(fa_head))
|
if (fn_trie_dump_fa(l->key, li->plen, &li->falh, tb, skb, cb) < 0) {
|
||||||
continue;
|
cb->args[3] = i;
|
||||||
|
|
||||||
if (fn_trie_dump_fa(l->key, plen, fa_head, tb, skb, cb) < 0) {
|
|
||||||
cb->args[3] = h;
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
cb->args[3] = h;
|
|
||||||
|
cb->args[3] = i;
|
||||||
return skb->len;
|
return skb->len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int fn_trie_dump(struct fib_table *tb, struct sk_buff *skb,
|
static int fn_trie_dump(struct fib_table *tb, struct sk_buff *skb,
|
||||||
struct netlink_callback *cb)
|
struct netlink_callback *cb)
|
||||||
{
|
{
|
||||||
int m, s_m;
|
struct leaf *l;
|
||||||
struct trie *t = (struct trie *) tb->tb_data;
|
struct trie *t = (struct trie *) tb->tb_data;
|
||||||
|
int h = 0;
|
||||||
s_m = cb->args[2];
|
int s_h = cb->args[2];
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
for (m = 0; m <= 32; m++) {
|
for (h = 0, l = trie_firstleaf(t); l != NULL; h++, l = trie_nextleaf(l)) {
|
||||||
if (m < s_m)
|
if (h < s_h)
|
||||||
continue;
|
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) {
|
if (h > s_h) {
|
||||||
cb->args[2] = m;
|
cb->args[3] = 0;
|
||||||
goto out;
|
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();
|
rcu_read_unlock();
|
||||||
cb->args[2] = m;
|
|
||||||
|
cb->args[2] = h;
|
||||||
return skb->len;
|
return skb->len;
|
||||||
out:
|
|
||||||
rcu_read_unlock();
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init fib_hash_init(void)
|
void __init fib_hash_init(void)
|
||||||
|
|
Loading…
Reference in New Issue