123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172 |
- 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)
|