aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/pending-3.18/080-01-fib_trie-Fix-trie-balancing-issue-if-new-node-pushes.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/generic/pending-3.18/080-01-fib_trie-Fix-trie-balancing-issue-if-new-node-pushes.patch')
-rw-r--r--target/linux/generic/pending-3.18/080-01-fib_trie-Fix-trie-balancing-issue-if-new-node-pushes.patch72
1 files changed, 72 insertions, 0 deletions
diff --git a/target/linux/generic/pending-3.18/080-01-fib_trie-Fix-trie-balancing-issue-if-new-node-pushes.patch b/target/linux/generic/pending-3.18/080-01-fib_trie-Fix-trie-balancing-issue-if-new-node-pushes.patch
new file mode 100644
index 0000000000..4e09f8a189
--- /dev/null
+++ b/target/linux/generic/pending-3.18/080-01-fib_trie-Fix-trie-balancing-issue-if-new-node-pushes.patch
@@ -0,0 +1,72 @@
+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)