aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorStephen Hemminger <stephen.hemminger@vyatta.com>2008-01-23 00:56:11 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 18:11:00 -0500
commita88ee229253b31e3a844b30525ff77fbfe3111d3 (patch)
tree853ed090854a81baec257b41a09bead66e2bd391 /net/ipv4
parent82cfbb008572b1a953091ef78f767aa3ca213092 (diff)
[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>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/fib_trie.c74
1 files changed, 39 insertions, 35 deletions
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index dab439b52672..2ea94ebe19f8 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1908,67 +1908,71 @@ static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah,
1908 return skb->len; 1908 return skb->len;
1909} 1909}
1910 1910
1911static int fn_trie_dump_plen(struct trie *t, int plen, struct fib_table *tb, 1911
1912 struct sk_buff *skb, struct netlink_callback *cb) 1912static int fn_trie_dump_leaf(struct leaf *l, struct fib_table *tb,
1913 struct sk_buff *skb, struct netlink_callback *cb)
1913{ 1914{
1914 int h, s_h; 1915 struct leaf_info *li;
1915 struct list_head *fa_head; 1916 struct hlist_node *node;
1916 struct leaf *l = NULL; 1917 int i, s_i;
1917 1918
1918 s_h = cb->args[3]; 1919 s_i = cb->args[3];
1919 h = 0; 1920 i = 0;
1920 1921
1921 for (l = trie_firstleaf(t); l != NULL; h++, l = trie_nextleaf(l)) { 1922 /* rcu_read_lock is hold by caller */
1922 if (h < s_h) 1923 hlist_for_each_entry_rcu(li, node, &l->list, hlist) {
1924 if (i < s_i) {
1925 i++;
1923 continue; 1926 continue;
1924 if (h > s_h) 1927 }
1925 memset(&cb->args[4], 0,
1926 sizeof(cb->args) - 4*sizeof(cb->args[0]));
1927
1928 fa_head = get_fa_head(l, plen);
1929 1928
1930 if (!fa_head) 1929 if (i > s_i)
1931 continue; 1930 cb->args[4] = 0;
1932 1931
1933 if (list_empty(fa_head)) 1932 if (list_empty(&li->falh))
1934 continue; 1933 continue;
1935 1934
1936 if (fn_trie_dump_fa(l->key, plen, fa_head, tb, skb, cb) < 0) { 1935 if (fn_trie_dump_fa(l->key, li->plen, &li->falh, tb, skb, cb) < 0) {
1937 cb->args[3] = h; 1936 cb->args[3] = i;
1938 return -1; 1937 return -1;
1939 } 1938 }
1939 i++;
1940 } 1940 }
1941 cb->args[3] = h; 1941
1942 cb->args[3] = i;
1942 return skb->len; 1943 return skb->len;
1943} 1944}
1944 1945
1946
1947
1945static int fn_trie_dump(struct fib_table *tb, struct sk_buff *skb, 1948static int fn_trie_dump(struct fib_table *tb, struct sk_buff *skb,
1946 struct netlink_callback *cb) 1949 struct netlink_callback *cb)
1947{ 1950{
1948 int m, s_m; 1951 struct leaf *l;
1949 struct trie *t = (struct trie *) tb->tb_data; 1952 struct trie *t = (struct trie *) tb->tb_data;
1950 1953 int h = 0;
1951 s_m = cb->args[2]; 1954 int s_h = cb->args[2];
1952 1955
1953 rcu_read_lock(); 1956 rcu_read_lock();
1954 for (m = 0; m <= 32; m++) { 1957 for (h = 0, l = trie_firstleaf(t); l != NULL; h++, l = trie_nextleaf(l)) {
1955 if (m < s_m) 1958 if (h < s_h)
1956 continue; 1959 continue;
1957 if (m > s_m)
1958 memset(&cb->args[3], 0,
1959 sizeof(cb->args) - 3*sizeof(cb->args[0]));
1960 1960
1961 if (fn_trie_dump_plen(t, 32-m, tb, skb, cb) < 0) { 1961 if (h > s_h) {
1962 cb->args[2] = m; 1962 cb->args[3] = 0;
1963 goto out; 1963 cb->args[4] = 0;
1964 }
1965
1966 if (fn_trie_dump_leaf(l, tb, skb, cb) < 0) {
1967 rcu_read_unlock();
1968 cb->args[2] = h;
1969 return -1;
1964 } 1970 }
1965 } 1971 }
1966 rcu_read_unlock(); 1972 rcu_read_unlock();
1967 cb->args[2] = m; 1973
1974 cb->args[2] = h;
1968 return skb->len; 1975 return skb->len;
1969out:
1970 rcu_read_unlock();
1971 return -1;
1972} 1976}
1973 1977
1974void __init fib_hash_init(void) 1978void __init fib_hash_init(void)