diff options
-rw-r--r-- | net/ipv4/fib_trie.c | 100 |
1 files changed, 65 insertions, 35 deletions
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 80892f565030..f874e1811eab 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -83,7 +83,8 @@ | |||
83 | 83 | ||
84 | #define MAX_STAT_DEPTH 32 | 84 | #define MAX_STAT_DEPTH 32 |
85 | 85 | ||
86 | #define KEYLENGTH (8*sizeof(t_key)) | 86 | #define KEYLENGTH (8*sizeof(t_key)) |
87 | #define KEY_MAX ((t_key)~0) | ||
87 | 88 | ||
88 | typedef unsigned int t_key; | 89 | typedef unsigned int t_key; |
89 | 90 | ||
@@ -102,8 +103,8 @@ struct tnode { | |||
102 | union { | 103 | union { |
103 | /* The fields in this struct are valid if bits > 0 (TNODE) */ | 104 | /* The fields in this struct are valid if bits > 0 (TNODE) */ |
104 | struct { | 105 | struct { |
105 | unsigned int full_children; /* KEYLENGTH bits needed */ | 106 | t_key empty_children; /* KEYLENGTH bits needed */ |
106 | unsigned int empty_children; /* KEYLENGTH bits needed */ | 107 | t_key full_children; /* KEYLENGTH bits needed */ |
107 | struct tnode __rcu *child[0]; | 108 | struct tnode __rcu *child[0]; |
108 | }; | 109 | }; |
109 | /* This list pointer if valid if bits == 0 (LEAF) */ | 110 | /* This list pointer if valid if bits == 0 (LEAF) */ |
@@ -302,6 +303,16 @@ static struct tnode *tnode_alloc(size_t size) | |||
302 | return vzalloc(size); | 303 | return vzalloc(size); |
303 | } | 304 | } |
304 | 305 | ||
306 | static inline void empty_child_inc(struct tnode *n) | ||
307 | { | ||
308 | ++n->empty_children ? : ++n->full_children; | ||
309 | } | ||
310 | |||
311 | static inline void empty_child_dec(struct tnode *n) | ||
312 | { | ||
313 | n->empty_children-- ? : n->full_children--; | ||
314 | } | ||
315 | |||
305 | static struct tnode *leaf_new(t_key key) | 316 | static struct tnode *leaf_new(t_key key) |
306 | { | 317 | { |
307 | struct tnode *l = kmem_cache_alloc(trie_leaf_kmem, GFP_KERNEL); | 318 | struct tnode *l = kmem_cache_alloc(trie_leaf_kmem, GFP_KERNEL); |
@@ -335,7 +346,7 @@ static struct leaf_info *leaf_info_new(int plen) | |||
335 | 346 | ||
336 | static struct tnode *tnode_new(t_key key, int pos, int bits) | 347 | static struct tnode *tnode_new(t_key key, int pos, int bits) |
337 | { | 348 | { |
338 | size_t sz = offsetof(struct tnode, child[1 << bits]); | 349 | size_t sz = offsetof(struct tnode, child[1ul << bits]); |
339 | struct tnode *tn = tnode_alloc(sz); | 350 | struct tnode *tn = tnode_alloc(sz); |
340 | unsigned int shift = pos + bits; | 351 | unsigned int shift = pos + bits; |
341 | 352 | ||
@@ -348,8 +359,10 @@ static struct tnode *tnode_new(t_key key, int pos, int bits) | |||
348 | tn->pos = pos; | 359 | tn->pos = pos; |
349 | tn->bits = bits; | 360 | tn->bits = bits; |
350 | tn->key = (shift < KEYLENGTH) ? (key >> shift) << shift : 0; | 361 | tn->key = (shift < KEYLENGTH) ? (key >> shift) << shift : 0; |
351 | tn->full_children = 0; | 362 | if (bits == KEYLENGTH) |
352 | tn->empty_children = 1<<bits; | 363 | tn->full_children = 1; |
364 | else | ||
365 | tn->empty_children = 1ul << bits; | ||
353 | } | 366 | } |
354 | 367 | ||
355 | pr_debug("AT %p s=%zu %zu\n", tn, sizeof(struct tnode), | 368 | pr_debug("AT %p s=%zu %zu\n", tn, sizeof(struct tnode), |
@@ -375,11 +388,11 @@ static void put_child(struct tnode *tn, unsigned long i, struct tnode *n) | |||
375 | 388 | ||
376 | BUG_ON(i >= tnode_child_length(tn)); | 389 | BUG_ON(i >= tnode_child_length(tn)); |
377 | 390 | ||
378 | /* update emptyChildren */ | 391 | /* update emptyChildren, overflow into fullChildren */ |
379 | if (n == NULL && chi != NULL) | 392 | if (n == NULL && chi != NULL) |
380 | tn->empty_children++; | 393 | empty_child_inc(tn); |
381 | else if (n != NULL && chi == NULL) | 394 | if (n != NULL && chi == NULL) |
382 | tn->empty_children--; | 395 | empty_child_dec(tn); |
383 | 396 | ||
384 | /* update fullChildren */ | 397 | /* update fullChildren */ |
385 | wasfull = tnode_full(tn, chi); | 398 | wasfull = tnode_full(tn, chi); |
@@ -630,6 +643,24 @@ static int halve(struct trie *t, struct tnode *oldtnode) | |||
630 | return 0; | 643 | return 0; |
631 | } | 644 | } |
632 | 645 | ||
646 | static void collapse(struct trie *t, struct tnode *oldtnode) | ||
647 | { | ||
648 | struct tnode *n, *tp; | ||
649 | unsigned long i; | ||
650 | |||
651 | /* scan the tnode looking for that one child that might still exist */ | ||
652 | for (n = NULL, i = tnode_child_length(oldtnode); !n && i;) | ||
653 | n = tnode_get_child(oldtnode, --i); | ||
654 | |||
655 | /* compress one level */ | ||
656 | tp = node_parent(oldtnode); | ||
657 | put_child_root(tp, t, oldtnode->key, n); | ||
658 | node_set_parent(n, tp); | ||
659 | |||
660 | /* drop dead node */ | ||
661 | node_free(oldtnode); | ||
662 | } | ||
663 | |||
633 | static unsigned char update_suffix(struct tnode *tn) | 664 | static unsigned char update_suffix(struct tnode *tn) |
634 | { | 665 | { |
635 | unsigned char slen = tn->pos; | 666 | unsigned char slen = tn->pos; |
@@ -729,10 +760,12 @@ static bool should_inflate(const struct tnode *tp, const struct tnode *tn) | |||
729 | 760 | ||
730 | /* Keep root node larger */ | 761 | /* Keep root node larger */ |
731 | threshold *= tp ? inflate_threshold : inflate_threshold_root; | 762 | threshold *= tp ? inflate_threshold : inflate_threshold_root; |
732 | used += tn->full_children; | ||
733 | used -= tn->empty_children; | 763 | used -= tn->empty_children; |
764 | used += tn->full_children; | ||
734 | 765 | ||
735 | return tn->pos && ((50 * used) >= threshold); | 766 | /* if bits == KEYLENGTH then pos = 0, and will fail below */ |
767 | |||
768 | return (used > 1) && tn->pos && ((50 * used) >= threshold); | ||
736 | } | 769 | } |
737 | 770 | ||
738 | static bool should_halve(const struct tnode *tp, const struct tnode *tn) | 771 | static bool should_halve(const struct tnode *tp, const struct tnode *tn) |
@@ -744,13 +777,29 @@ static bool should_halve(const struct tnode *tp, const struct tnode *tn) | |||
744 | threshold *= tp ? halve_threshold : halve_threshold_root; | 777 | threshold *= tp ? halve_threshold : halve_threshold_root; |
745 | used -= tn->empty_children; | 778 | used -= tn->empty_children; |
746 | 779 | ||
747 | return (tn->bits > 1) && ((100 * used) < threshold); | 780 | /* if bits == KEYLENGTH then used = 100% on wrap, and will fail below */ |
781 | |||
782 | return (used > 1) && (tn->bits > 1) && ((100 * used) < threshold); | ||
783 | } | ||
784 | |||
785 | static bool should_collapse(const struct tnode *tn) | ||
786 | { | ||
787 | unsigned long used = tnode_child_length(tn); | ||
788 | |||
789 | used -= tn->empty_children; | ||
790 | |||
791 | /* account for bits == KEYLENGTH case */ | ||
792 | if ((tn->bits == KEYLENGTH) && tn->full_children) | ||
793 | used -= KEY_MAX; | ||
794 | |||
795 | /* One child or none, time to drop us from the trie */ | ||
796 | return used < 2; | ||
748 | } | 797 | } |
749 | 798 | ||
750 | #define MAX_WORK 10 | 799 | #define MAX_WORK 10 |
751 | static void resize(struct trie *t, struct tnode *tn) | 800 | static void resize(struct trie *t, struct tnode *tn) |
752 | { | 801 | { |
753 | struct tnode *tp = node_parent(tn), *n = NULL; | 802 | struct tnode *tp = node_parent(tn); |
754 | struct tnode __rcu **cptr; | 803 | struct tnode __rcu **cptr; |
755 | int max_work = MAX_WORK; | 804 | int max_work = MAX_WORK; |
756 | 805 | ||
@@ -764,14 +813,6 @@ static void resize(struct trie *t, struct tnode *tn) | |||
764 | cptr = tp ? &tp->child[get_index(tn->key, tp)] : &t->trie; | 813 | cptr = tp ? &tp->child[get_index(tn->key, tp)] : &t->trie; |
765 | BUG_ON(tn != rtnl_dereference(*cptr)); | 814 | BUG_ON(tn != rtnl_dereference(*cptr)); |
766 | 815 | ||
767 | /* No children */ | ||
768 | if (tn->empty_children > (tnode_child_length(tn) - 1)) | ||
769 | goto no_children; | ||
770 | |||
771 | /* One child */ | ||
772 | if (tn->empty_children == (tnode_child_length(tn) - 1)) | ||
773 | goto one_child; | ||
774 | |||
775 | /* Double as long as the resulting node has a number of | 816 | /* Double as long as the resulting node has a number of |
776 | * nonempty nodes that are above the threshold. | 817 | * nonempty nodes that are above the threshold. |
777 | */ | 818 | */ |
@@ -807,19 +848,8 @@ static void resize(struct trie *t, struct tnode *tn) | |||
807 | } | 848 | } |
808 | 849 | ||
809 | /* Only one child remains */ | 850 | /* Only one child remains */ |
810 | if (tn->empty_children == (tnode_child_length(tn) - 1)) { | 851 | if (should_collapse(tn)) { |
811 | unsigned long i; | 852 | collapse(t, tn); |
812 | one_child: | ||
813 | for (i = tnode_child_length(tn); !n && i;) | ||
814 | n = tnode_get_child(tn, --i); | ||
815 | no_children: | ||
816 | /* compress one level */ | ||
817 | put_child_root(tp, t, tn->key, n); | ||
818 | node_set_parent(n, tp); | ||
819 | |||
820 | /* drop dead node */ | ||
821 | tnode_free_init(tn); | ||
822 | tnode_free(tn); | ||
823 | return; | 853 | return; |
824 | } | 854 | } |
825 | 855 | ||