mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-31 05:54:26 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			65 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			65 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From: Alexander Duyck <alexander.h.duyck@redhat.com>
 | |
| Date: Wed, 31 Dec 2014 10:56:00 -0800
 | |
| Subject: [PATCH] fib_trie: Optimize fib_find_node
 | |
| 
 | |
| This patch makes use of the same features I made use of for
 | |
| fib_table_lookup to streamline fib_find_node.  The resultant code should be
 | |
| smaller and run faster than the original.
 | |
| 
 | |
| Signed-off-by: Alexander Duyck <alexander.h.duyck@redhat.com>
 | |
| Signed-off-by: David S. Miller <davem@davemloft.net>
 | |
| ---
 | |
| 
 | |
| --- a/net/ipv4/fib_trie.c
 | |
| +++ b/net/ipv4/fib_trie.c
 | |
| @@ -892,28 +892,34 @@ static void insert_leaf_info(struct hlis
 | |
|  }
 | |
|  
 | |
|  /* rcu_read_lock needs to be hold by caller from readside */
 | |
| -
 | |
|  static struct tnode *fib_find_node(struct trie *t, u32 key)
 | |
|  {
 | |
|  	struct tnode *n = rcu_dereference_rtnl(t->trie);
 | |
| -	int pos = 0;
 | |
|  
 | |
| -	while (n && IS_TNODE(n)) {
 | |
| -		if (tkey_sub_equals(n->key, pos, n->pos-pos, key)) {
 | |
| -			pos = n->pos + n->bits;
 | |
| -			n = tnode_get_child_rcu(n,
 | |
| -						tkey_extract_bits(key,
 | |
| -								  n->pos,
 | |
| -								  n->bits));
 | |
| -		} else
 | |
| +	while (n) {
 | |
| +		unsigned long index = get_index(key, n);
 | |
| +
 | |
| +		/* This bit of code is a bit tricky but it combines multiple
 | |
| +		 * checks into a single check.  The prefix consists of the
 | |
| +		 * prefix plus zeros for the bits in the cindex. The index
 | |
| +		 * is the difference between the key and this value.  From
 | |
| +		 * this we can actually derive several pieces of data.
 | |
| +		 *   if !(index >> bits)
 | |
| +		 *     we know the value is cindex
 | |
| +		 *   else
 | |
| +		 *     we have a mismatch in skip bits and failed
 | |
| +		 */
 | |
| +		if (index >> n->bits)
 | |
| +			return NULL;
 | |
| +
 | |
| +		/* we have found a leaf. Prefixes have already been compared */
 | |
| +		if (IS_LEAF(n))
 | |
|  			break;
 | |
| -	}
 | |
| -	/* Case we have found a leaf. Compare prefixes */
 | |
|  
 | |
| -	if (n != NULL && IS_LEAF(n) && tkey_equals(key, n->key))
 | |
| -		return n;
 | |
| +		n = rcu_dereference_rtnl(n->child[index]);
 | |
| +	}
 | |
|  
 | |
| -	return NULL;
 | |
| +	return n;
 | |
|  }
 | |
|  
 | |
|  static void trie_rebalance(struct trie *t, struct tnode *tn)
 |