aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/fib_trie.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/fib_trie.c')
-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)