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.c36
1 files changed, 21 insertions, 15 deletions
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 3fe4dd917ce1..ac04f31a632e 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -892,28 +892,34 @@ static void insert_leaf_info(struct hlist_head *head, struct leaf_info *new)
892} 892}
893 893
894/* rcu_read_lock needs to be hold by caller from readside */ 894/* rcu_read_lock needs to be hold by caller from readside */
895
896static struct tnode *fib_find_node(struct trie *t, u32 key) 895static struct tnode *fib_find_node(struct trie *t, u32 key)
897{ 896{
898 struct tnode *n = rcu_dereference_rtnl(t->trie); 897 struct tnode *n = rcu_dereference_rtnl(t->trie);
899 int pos = 0;
900 898
901 while (n && IS_TNODE(n)) { 899 while (n) {
902 if (tkey_sub_equals(n->key, pos, n->pos-pos, key)) { 900 unsigned long index = get_index(key, n);
903 pos = n->pos + n->bits; 901
904 n = tnode_get_child_rcu(n, 902 /* This bit of code is a bit tricky but it combines multiple
905 tkey_extract_bits(key, 903 * checks into a single check. The prefix consists of the
906 n->pos, 904 * prefix plus zeros for the bits in the cindex. The index
907 n->bits)); 905 * is the difference between the key and this value. From
908 } else 906 * this we can actually derive several pieces of data.
907 * if !(index >> bits)
908 * we know the value is cindex
909 * else
910 * we have a mismatch in skip bits and failed
911 */
912 if (index >> n->bits)
913 return NULL;
914
915 /* we have found a leaf. Prefixes have already been compared */
916 if (IS_LEAF(n))
909 break; 917 break;
910 }
911 /* Case we have found a leaf. Compare prefixes */
912 918
913 if (n != NULL && IS_LEAF(n) && tkey_equals(key, n->key)) 919 n = rcu_dereference_rtnl(n->child[index]);
914 return n; 920 }
915 921
916 return NULL; 922 return n;
917} 923}
918 924
919static void trie_rebalance(struct trie *t, struct tnode *tn) 925static void trie_rebalance(struct trie *t, struct tnode *tn)