From 944612680d9382720671f1fb731a24eccbbf118c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 12 Mar 2015 15:27:44 +0000 Subject: kernel: backport fib_trie improvements/fixes from 4.0-rc Signed-off-by: Felix Fietkau SVN-Revision: 44695 --- ...d-functions-should_inflate-and-should_hal.patch | 250 +++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 target/linux/generic/patches-3.18/080-13-fib_trie-Add-functions-should_inflate-and-should_hal.patch (limited to 'target/linux/generic/patches-3.18/080-13-fib_trie-Add-functions-should_inflate-and-should_hal.patch') diff --git a/target/linux/generic/patches-3.18/080-13-fib_trie-Add-functions-should_inflate-and-should_hal.patch b/target/linux/generic/patches-3.18/080-13-fib_trie-Add-functions-should_inflate-and-should_hal.patch new file mode 100644 index 0000000000..42c0394689 --- /dev/null +++ b/target/linux/generic/patches-3.18/080-13-fib_trie-Add-functions-should_inflate-and-should_hal.patch @@ -0,0 +1,250 @@ +From: Alexander Duyck +Date: Wed, 31 Dec 2014 10:56:37 -0800 +Subject: [PATCH] fib_trie: Add functions should_inflate and should_halve + +This change pulls the logic for if we should inflate/halve the nodes out +into separate functions. It also addresses what I believe is a bug where 1 +full node is all that is needed to keep a node from ever being halved. + +Simple script to reproduce the issue: + modprobe dummy; ifconfig dummy0 up + for i in `seq 0 255`; do ifconfig dummy0:$i 10.0.${i}.1/24 up; done + ifconfig dummy0:256 10.0.255.33/16 up + for i in `seq 0 254`; do ifconfig dummy0:$i down; done + +Results from /proc/net/fib_triestat +Before: + Local: + Aver depth: 3.00 + Max depth: 4 + Leaves: 17 + Prefixes: 18 + Internal nodes: 11 + 1: 8 2: 2 10: 1 + Pointers: 1048 + Null ptrs: 1021 + Total size: 11 kB +After: + Local: + Aver depth: 3.41 + Max depth: 5 + Leaves: 17 + Prefixes: 18 + Internal nodes: 12 + 1: 8 2: 3 3: 1 + Pointers: 36 + Null ptrs: 8 + Total size: 3 kB + +Signed-off-by: Alexander Duyck +Signed-off-by: David S. Miller +--- + +--- a/net/ipv4/fib_trie.c ++++ b/net/ipv4/fib_trie.c +@@ -647,12 +647,94 @@ nomem: + return ERR_PTR(-ENOMEM); + } + ++/* From "Implementing a dynamic compressed trie" by Stefan Nilsson of ++ * the Helsinki University of Technology and Matti Tikkanen of Nokia ++ * Telecommunications, page 6: ++ * "A node is doubled if the ratio of non-empty children to all ++ * children in the *doubled* node is at least 'high'." ++ * ++ * 'high' in this instance is the variable 'inflate_threshold'. It ++ * is expressed as a percentage, so we multiply it with ++ * tnode_child_length() and instead of multiplying by 2 (since the ++ * child array will be doubled by inflate()) and multiplying ++ * the left-hand side by 100 (to handle the percentage thing) we ++ * multiply the left-hand side by 50. ++ * ++ * The left-hand side may look a bit weird: tnode_child_length(tn) ++ * - tn->empty_children is of course the number of non-null children ++ * in the current node. tn->full_children is the number of "full" ++ * children, that is non-null tnodes with a skip value of 0. ++ * All of those will be doubled in the resulting inflated tnode, so ++ * we just count them one extra time here. ++ * ++ * A clearer way to write this would be: ++ * ++ * to_be_doubled = tn->full_children; ++ * not_to_be_doubled = tnode_child_length(tn) - tn->empty_children - ++ * tn->full_children; ++ * ++ * new_child_length = tnode_child_length(tn) * 2; ++ * ++ * new_fill_factor = 100 * (not_to_be_doubled + 2*to_be_doubled) / ++ * new_child_length; ++ * if (new_fill_factor >= inflate_threshold) ++ * ++ * ...and so on, tho it would mess up the while () loop. ++ * ++ * anyway, ++ * 100 * (not_to_be_doubled + 2*to_be_doubled) / new_child_length >= ++ * inflate_threshold ++ * ++ * avoid a division: ++ * 100 * (not_to_be_doubled + 2*to_be_doubled) >= ++ * inflate_threshold * new_child_length ++ * ++ * expand not_to_be_doubled and to_be_doubled, and shorten: ++ * 100 * (tnode_child_length(tn) - tn->empty_children + ++ * tn->full_children) >= inflate_threshold * new_child_length ++ * ++ * expand new_child_length: ++ * 100 * (tnode_child_length(tn) - tn->empty_children + ++ * tn->full_children) >= ++ * inflate_threshold * tnode_child_length(tn) * 2 ++ * ++ * shorten again: ++ * 50 * (tn->full_children + tnode_child_length(tn) - ++ * tn->empty_children) >= inflate_threshold * ++ * tnode_child_length(tn) ++ * ++ */ ++static bool should_inflate(const struct tnode *tn) ++{ ++ unsigned long used = tnode_child_length(tn); ++ unsigned long threshold = used; ++ ++ /* Keep root node larger */ ++ threshold *= node_parent(tn) ? inflate_threshold : ++ inflate_threshold_root; ++ used += tn->full_children; ++ used -= tn->empty_children; ++ ++ return tn->pos && ((50 * used) >= threshold); ++} ++ ++static bool should_halve(const struct tnode *tn) ++{ ++ unsigned long used = tnode_child_length(tn); ++ unsigned long threshold = used; ++ ++ /* Keep root node larger */ ++ threshold *= node_parent(tn) ? halve_threshold : ++ halve_threshold_root; ++ used -= tn->empty_children; ++ ++ return (tn->bits > 1) && ((100 * used) < threshold); ++} ++ + #define MAX_WORK 10 + static struct tnode *resize(struct trie *t, struct tnode *tn) + { + struct tnode *old_tn, *n = NULL; +- int inflate_threshold_use; +- int halve_threshold_use; + int max_work; + + if (!tn) +@@ -668,86 +750,12 @@ static struct tnode *resize(struct trie + /* One child */ + if (tn->empty_children == (tnode_child_length(tn) - 1)) + goto one_child; +- /* +- * Double as long as the resulting node has a number of +- * nonempty nodes that are above the threshold. +- */ + +- /* +- * From "Implementing a dynamic compressed trie" by Stefan Nilsson of +- * the Helsinki University of Technology and Matti Tikkanen of Nokia +- * Telecommunications, page 6: +- * "A node is doubled if the ratio of non-empty children to all +- * children in the *doubled* node is at least 'high'." +- * +- * 'high' in this instance is the variable 'inflate_threshold'. It +- * is expressed as a percentage, so we multiply it with +- * tnode_child_length() and instead of multiplying by 2 (since the +- * child array will be doubled by inflate()) and multiplying +- * the left-hand side by 100 (to handle the percentage thing) we +- * multiply the left-hand side by 50. +- * +- * The left-hand side may look a bit weird: tnode_child_length(tn) +- * - tn->empty_children is of course the number of non-null children +- * in the current node. tn->full_children is the number of "full" +- * children, that is non-null tnodes with a skip value of 0. +- * All of those will be doubled in the resulting inflated tnode, so +- * we just count them one extra time here. +- * +- * A clearer way to write this would be: +- * +- * to_be_doubled = tn->full_children; +- * not_to_be_doubled = tnode_child_length(tn) - tn->empty_children - +- * tn->full_children; +- * +- * new_child_length = tnode_child_length(tn) * 2; +- * +- * new_fill_factor = 100 * (not_to_be_doubled + 2*to_be_doubled) / +- * new_child_length; +- * if (new_fill_factor >= inflate_threshold) +- * +- * ...and so on, tho it would mess up the while () loop. +- * +- * anyway, +- * 100 * (not_to_be_doubled + 2*to_be_doubled) / new_child_length >= +- * inflate_threshold +- * +- * avoid a division: +- * 100 * (not_to_be_doubled + 2*to_be_doubled) >= +- * inflate_threshold * new_child_length +- * +- * expand not_to_be_doubled and to_be_doubled, and shorten: +- * 100 * (tnode_child_length(tn) - tn->empty_children + +- * tn->full_children) >= inflate_threshold * new_child_length +- * +- * expand new_child_length: +- * 100 * (tnode_child_length(tn) - tn->empty_children + +- * tn->full_children) >= +- * inflate_threshold * tnode_child_length(tn) * 2 +- * +- * shorten again: +- * 50 * (tn->full_children + tnode_child_length(tn) - +- * tn->empty_children) >= inflate_threshold * +- * tnode_child_length(tn) +- * ++ /* Double as long as the resulting node has a number of ++ * nonempty nodes that are above the threshold. + */ +- +- /* Keep root node larger */ +- +- if (!node_parent(tn)) { +- inflate_threshold_use = inflate_threshold_root; +- halve_threshold_use = halve_threshold_root; +- } else { +- inflate_threshold_use = inflate_threshold; +- halve_threshold_use = halve_threshold; +- } +- + max_work = MAX_WORK; +- while ((tn->full_children > 0 && max_work-- && +- 50 * (tn->full_children + tnode_child_length(tn) +- - tn->empty_children) +- >= inflate_threshold_use * tnode_child_length(tn))) { +- ++ while (should_inflate(tn) && max_work--) { + old_tn = tn; + tn = inflate(t, tn); + +@@ -764,16 +772,11 @@ static struct tnode *resize(struct trie + if (max_work != MAX_WORK) + return tn; + +- /* +- * Halve as long as the number of empty children in this ++ /* Halve as long as the number of empty children in this + * node is above threshold. + */ +- + max_work = MAX_WORK; +- while (tn->bits > 1 && max_work-- && +- 100 * (tnode_child_length(tn) - tn->empty_children) < +- halve_threshold_use * tnode_child_length(tn)) { +- ++ while (should_halve(tn) && max_work--) { + old_tn = tn; + tn = halve(t, tn); + if (IS_ERR(tn)) { -- cgit v1.2.3