aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@redhat.com>2014-12-31 13:56:37 -0500
committerDavid S. Miller <davem@davemloft.net>2014-12-31 18:25:54 -0500
commitf05a48198bf742efd9d36553c51e98a648dbe807 (patch)
treeb507ffa2ec5a895c13733063725d6b6153976138
parentcf3637bb8f07fb3b6791708f1d5118afb5446061 (diff)
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 <alexander.h.duyck@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv4/fib_trie.c175
1 files changed, 89 insertions, 86 deletions
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index d044fa355f69..58e1224786fa 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -647,12 +647,94 @@ nomem:
647 return ERR_PTR(-ENOMEM); 647 return ERR_PTR(-ENOMEM);
648} 648}
649 649
650/* From "Implementing a dynamic compressed trie" by Stefan Nilsson of
651 * the Helsinki University of Technology and Matti Tikkanen of Nokia
652 * Telecommunications, page 6:
653 * "A node is doubled if the ratio of non-empty children to all
654 * children in the *doubled* node is at least 'high'."
655 *
656 * 'high' in this instance is the variable 'inflate_threshold'. It
657 * is expressed as a percentage, so we multiply it with
658 * tnode_child_length() and instead of multiplying by 2 (since the
659 * child array will be doubled by inflate()) and multiplying
660 * the left-hand side by 100 (to handle the percentage thing) we
661 * multiply the left-hand side by 50.
662 *
663 * The left-hand side may look a bit weird: tnode_child_length(tn)
664 * - tn->empty_children is of course the number of non-null children
665 * in the current node. tn->full_children is the number of "full"
666 * children, that is non-null tnodes with a skip value of 0.
667 * All of those will be doubled in the resulting inflated tnode, so
668 * we just count them one extra time here.
669 *
670 * A clearer way to write this would be:
671 *
672 * to_be_doubled = tn->full_children;
673 * not_to_be_doubled = tnode_child_length(tn) - tn->empty_children -
674 * tn->full_children;
675 *
676 * new_child_length = tnode_child_length(tn) * 2;
677 *
678 * new_fill_factor = 100 * (not_to_be_doubled + 2*to_be_doubled) /
679 * new_child_length;
680 * if (new_fill_factor >= inflate_threshold)
681 *
682 * ...and so on, tho it would mess up the while () loop.
683 *
684 * anyway,
685 * 100 * (not_to_be_doubled + 2*to_be_doubled) / new_child_length >=
686 * inflate_threshold
687 *
688 * avoid a division:
689 * 100 * (not_to_be_doubled + 2*to_be_doubled) >=
690 * inflate_threshold * new_child_length
691 *
692 * expand not_to_be_doubled and to_be_doubled, and shorten:
693 * 100 * (tnode_child_length(tn) - tn->empty_children +
694 * tn->full_children) >= inflate_threshold * new_child_length
695 *
696 * expand new_child_length:
697 * 100 * (tnode_child_length(tn) - tn->empty_children +
698 * tn->full_children) >=
699 * inflate_threshold * tnode_child_length(tn) * 2
700 *
701 * shorten again:
702 * 50 * (tn->full_children + tnode_child_length(tn) -
703 * tn->empty_children) >= inflate_threshold *
704 * tnode_child_length(tn)
705 *
706 */
707static bool should_inflate(const struct tnode *tn)
708{
709 unsigned long used = tnode_child_length(tn);
710 unsigned long threshold = used;
711
712 /* Keep root node larger */
713 threshold *= node_parent(tn) ? inflate_threshold :
714 inflate_threshold_root;
715 used += tn->full_children;
716 used -= tn->empty_children;
717
718 return tn->pos && ((50 * used) >= threshold);
719}
720
721static bool should_halve(const struct tnode *tn)
722{
723 unsigned long used = tnode_child_length(tn);
724 unsigned long threshold = used;
725
726 /* Keep root node larger */
727 threshold *= node_parent(tn) ? halve_threshold :
728 halve_threshold_root;
729 used -= tn->empty_children;
730
731 return (tn->bits > 1) && ((100 * used) < threshold);
732}
733
650#define MAX_WORK 10 734#define MAX_WORK 10
651static struct tnode *resize(struct trie *t, struct tnode *tn) 735static struct tnode *resize(struct trie *t, struct tnode *tn)
652{ 736{
653 struct tnode *old_tn, *n = NULL; 737 struct tnode *old_tn, *n = NULL;
654 int inflate_threshold_use;
655 int halve_threshold_use;
656 int max_work; 738 int max_work;
657 739
658 if (!tn) 740 if (!tn)
@@ -668,86 +750,12 @@ static struct tnode *resize(struct trie *t, struct tnode *tn)
668 /* One child */ 750 /* One child */
669 if (tn->empty_children == (tnode_child_length(tn) - 1)) 751 if (tn->empty_children == (tnode_child_length(tn) - 1))
670 goto one_child; 752 goto one_child;
671 /*
672 * Double as long as the resulting node has a number of
673 * nonempty nodes that are above the threshold.
674 */
675 753
676 /* 754 /* Double as long as the resulting node has a number of
677 * From "Implementing a dynamic compressed trie" by Stefan Nilsson of 755 * nonempty nodes that are above the threshold.
678 * the Helsinki University of Technology and Matti Tikkanen of Nokia
679 * Telecommunications, page 6:
680 * "A node is doubled if the ratio of non-empty children to all
681 * children in the *doubled* node is at least 'high'."
682 *
683 * 'high' in this instance is the variable 'inflate_threshold'. It
684 * is expressed as a percentage, so we multiply it with
685 * tnode_child_length() and instead of multiplying by 2 (since the
686 * child array will be doubled by inflate()) and multiplying
687 * the left-hand side by 100 (to handle the percentage thing) we
688 * multiply the left-hand side by 50.
689 *
690 * The left-hand side may look a bit weird: tnode_child_length(tn)
691 * - tn->empty_children is of course the number of non-null children
692 * in the current node. tn->full_children is the number of "full"
693 * children, that is non-null tnodes with a skip value of 0.
694 * All of those will be doubled in the resulting inflated tnode, so
695 * we just count them one extra time here.
696 *
697 * A clearer way to write this would be:
698 *
699 * to_be_doubled = tn->full_children;
700 * not_to_be_doubled = tnode_child_length(tn) - tn->empty_children -
701 * tn->full_children;
702 *
703 * new_child_length = tnode_child_length(tn) * 2;
704 *
705 * new_fill_factor = 100 * (not_to_be_doubled + 2*to_be_doubled) /
706 * new_child_length;
707 * if (new_fill_factor >= inflate_threshold)
708 *
709 * ...and so on, tho it would mess up the while () loop.
710 *
711 * anyway,
712 * 100 * (not_to_be_doubled + 2*to_be_doubled) / new_child_length >=
713 * inflate_threshold
714 *
715 * avoid a division:
716 * 100 * (not_to_be_doubled + 2*to_be_doubled) >=
717 * inflate_threshold * new_child_length
718 *
719 * expand not_to_be_doubled and to_be_doubled, and shorten:
720 * 100 * (tnode_child_length(tn) - tn->empty_children +
721 * tn->full_children) >= inflate_threshold * new_child_length
722 *
723 * expand new_child_length:
724 * 100 * (tnode_child_length(tn) - tn->empty_children +
725 * tn->full_children) >=
726 * inflate_threshold * tnode_child_length(tn) * 2
727 *
728 * shorten again:
729 * 50 * (tn->full_children + tnode_child_length(tn) -
730 * tn->empty_children) >= inflate_threshold *
731 * tnode_child_length(tn)
732 *
733 */ 756 */
734
735 /* Keep root node larger */
736
737 if (!node_parent(tn)) {
738 inflate_threshold_use = inflate_threshold_root;
739 halve_threshold_use = halve_threshold_root;
740 } else {
741 inflate_threshold_use = inflate_threshold;
742 halve_threshold_use = halve_threshold;
743 }
744
745 max_work = MAX_WORK; 757 max_work = MAX_WORK;
746 while ((tn->full_children > 0 && max_work-- && 758 while (should_inflate(tn) && max_work--) {
747 50 * (tn->full_children + tnode_child_length(tn)
748 - tn->empty_children)
749 >= inflate_threshold_use * tnode_child_length(tn))) {
750
751 old_tn = tn; 759 old_tn = tn;
752 tn = inflate(t, tn); 760 tn = inflate(t, tn);
753 761
@@ -764,16 +772,11 @@ static struct tnode *resize(struct trie *t, struct tnode *tn)
764 if (max_work != MAX_WORK) 772 if (max_work != MAX_WORK)
765 return tn; 773 return tn;
766 774
767 /* 775 /* Halve as long as the number of empty children in this
768 * Halve as long as the number of empty children in this
769 * node is above threshold. 776 * node is above threshold.
770 */ 777 */
771
772 max_work = MAX_WORK; 778 max_work = MAX_WORK;
773 while (tn->bits > 1 && max_work-- && 779 while (should_halve(tn) && max_work--) {
774 100 * (tnode_child_length(tn) - tn->empty_children) <
775 halve_threshold_use * tnode_child_length(tn)) {
776
777 old_tn = tn; 780 old_tn = tn;
778 tn = halve(t, tn); 781 tn = halve(t, tn);
779 if (IS_ERR(tn)) { 782 if (IS_ERR(tn)) {