mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-30 21:44:27 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			73 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			73 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From: Alexander Duyck <alexander.h.duyck@redhat.com>
 | |
| Date: Wed, 10 Dec 2014 21:49:22 -0800
 | |
| Subject: [PATCH] fib_trie: Fix trie balancing issue if new node pushes down
 | |
|  existing node
 | |
| 
 | |
| This patch addresses an issue with the level compression of the fib_trie.
 | |
| Specifically in the case of adding a new leaf that triggers a new node to
 | |
| be added that takes the place of the old node.  The result is a trie where
 | |
| the 1 child tnode is on one side and one leaf is on the other which gives
 | |
| you a very deep trie.  Below is the script I used to generate a trie on
 | |
| dummy0 with a 10.X.X.X family of addresses.
 | |
| 
 | |
|   ip link add type dummy
 | |
|   ipval=184549374
 | |
|   bit=2
 | |
|   for i in `seq 1 23`
 | |
|   do
 | |
|     ifconfig dummy0:$bit $ipval/8
 | |
|     ipval=`expr $ipval - $bit`
 | |
|     bit=`expr $bit \* 2`
 | |
|   done
 | |
|   cat /proc/net/fib_triestat
 | |
| 
 | |
| Running the script before the patch:
 | |
| 
 | |
| 	Local:
 | |
| 		Aver depth:     10.82
 | |
| 		Max depth:      23
 | |
| 		Leaves:         29
 | |
| 		Prefixes:       30
 | |
| 		Internal nodes: 27
 | |
| 		  1: 26  2: 1
 | |
| 		Pointers: 56
 | |
| 	Null ptrs: 1
 | |
| 	Total size: 5  kB
 | |
| 
 | |
| After applying the patch and repeating:
 | |
| 
 | |
| 	Local:
 | |
| 		Aver depth:     4.72
 | |
| 		Max depth:      9
 | |
| 		Leaves:         29
 | |
| 		Prefixes:       30
 | |
| 		Internal nodes: 12
 | |
| 		  1: 3  2: 2  3: 7
 | |
| 		Pointers: 70
 | |
| 	Null ptrs: 30
 | |
| 	Total size: 4  kB
 | |
| 
 | |
| What this fix does is start the rebalance at the newly created tnode
 | |
| instead of at the parent tnode.  This way if there is a gap between the
 | |
| parent and the new node it doesn't prevent the new tnode from being
 | |
| coalesced with any pre-existing nodes that may have been pushed into one
 | |
| of the new nodes child branches.
 | |
| 
 | |
| 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
 | |
| @@ -1143,8 +1143,9 @@ static struct list_head *fib_insert_node
 | |
|  			put_child(tp, cindex, (struct rt_trie_node *)tn);
 | |
|  		} else {
 | |
|  			rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn);
 | |
| -			tp = tn;
 | |
|  		}
 | |
| +
 | |
| +		tp = tn;
 | |
|  	}
 | |
|  
 | |
|  	if (tp && tp->pos + tp->bits > 32)
 |