aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/fib_trie.c
diff options
context:
space:
mode:
authorJens Låås <jens.laas@its.uu.se>2009-08-29 02:57:15 -0400
committerDavid S. Miller <davem@davemloft.net>2009-08-29 02:57:15 -0400
commit80b71b80df14d885f7e50e115c1348398f418759 (patch)
treef5b58c73d1b2ca7639a8e0513b6c68a992b05484 /net/ipv4/fib_trie.c
parent8945a808f7d5efd21fa9fb6055d2dd7887bdd9d8 (diff)
fib_trie: resize rework
Here is rework and cleanup of the resize function. Some bugs we had. We were using ->parent when we should use node_parent(). Also we used ->parent which is not assigned by inflate in inflate loop. Also a fix to set thresholds to power 2 to fit halve and double strategy. max_resize is renamed to max_work which better indicates it's function. Reaching max_work is not an error, so warning is removed. max_work only limits amount of work done per resize. (limits CPU-usage, outstanding memory etc). The clean-up makes it relatively easy to add fixed sized root-nodes if we would like to decrease the memory pressure on routers with large routing tables and dynamic routing. If we'll need that... Its been tested with 280k routes. Work done together with Robert Olsson. Signed-off-by: Jens Låås <jens.laas@its.uu.se> Signed-off-by: Robert Olsson <robert.olsson@its.uu.se> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/fib_trie.c')
-rw-r--r--net/ipv4/fib_trie.c95
1 files changed, 23 insertions, 72 deletions
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index fe3c846b99a6..291bdf50a21f 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -48,7 +48,7 @@
48 * Patrick McHardy <kaber@trash.net> 48 * Patrick McHardy <kaber@trash.net>
49 */ 49 */
50 50
51#define VERSION "0.408" 51#define VERSION "0.409"
52 52
53#include <asm/uaccess.h> 53#include <asm/uaccess.h>
54#include <asm/system.h> 54#include <asm/system.h>
@@ -325,10 +325,7 @@ static inline void check_tnode(const struct tnode *tn)
325static const int halve_threshold = 25; 325static const int halve_threshold = 25;
326static const int inflate_threshold = 50; 326static const int inflate_threshold = 50;
327static const int halve_threshold_root = 15; 327static const int halve_threshold_root = 15;
328static const int inflate_threshold_root = 25; 328static const int inflate_threshold_root = 30;
329
330static int inflate_threshold_root_fix;
331#define INFLATE_FIX_MAX 10 /* a comment in resize() */
332 329
333static void __alias_free_mem(struct rcu_head *head) 330static void __alias_free_mem(struct rcu_head *head)
334{ 331{
@@ -516,14 +513,14 @@ static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n,
516 rcu_assign_pointer(tn->child[i], n); 513 rcu_assign_pointer(tn->child[i], n);
517} 514}
518 515
516#define MAX_WORK 10
519static struct node *resize(struct trie *t, struct tnode *tn) 517static struct node *resize(struct trie *t, struct tnode *tn)
520{ 518{
521 int i; 519 int i;
522 int err = 0;
523 struct tnode *old_tn; 520 struct tnode *old_tn;
524 int inflate_threshold_use; 521 int inflate_threshold_use;
525 int halve_threshold_use; 522 int halve_threshold_use;
526 int max_resize; 523 int max_work;
527 524
528 if (!tn) 525 if (!tn)
529 return NULL; 526 return NULL;
@@ -538,18 +535,7 @@ static struct node *resize(struct trie *t, struct tnode *tn)
538 } 535 }
539 /* One child */ 536 /* One child */
540 if (tn->empty_children == tnode_child_length(tn) - 1) 537 if (tn->empty_children == tnode_child_length(tn) - 1)
541 for (i = 0; i < tnode_child_length(tn); i++) { 538 goto one_child;
542 struct node *n;
543
544 n = tn->child[i];
545 if (!n)
546 continue;
547
548 /* compress one level */
549 node_set_parent(n, NULL);
550 tnode_free_safe(tn);
551 return n;
552 }
553 /* 539 /*
554 * Double as long as the resulting node has a number of 540 * Double as long as the resulting node has a number of
555 * nonempty nodes that are above the threshold. 541 * nonempty nodes that are above the threshold.
@@ -618,15 +604,17 @@ static struct node *resize(struct trie *t, struct tnode *tn)
618 604
619 /* Keep root node larger */ 605 /* Keep root node larger */
620 606
621 if (!tn->parent) 607 if (!node_parent((struct node*) tn)) {
622 inflate_threshold_use = inflate_threshold_root + 608 inflate_threshold_use = inflate_threshold_root;
623 inflate_threshold_root_fix; 609 halve_threshold_use = halve_threshold_root;
624 else 610 }
611 else {
625 inflate_threshold_use = inflate_threshold; 612 inflate_threshold_use = inflate_threshold;
613 halve_threshold_use = halve_threshold;
614 }
626 615
627 err = 0; 616 max_work = MAX_WORK;
628 max_resize = 10; 617 while ((tn->full_children > 0 && max_work-- &&
629 while ((tn->full_children > 0 && max_resize-- &&
630 50 * (tn->full_children + tnode_child_length(tn) 618 50 * (tn->full_children + tnode_child_length(tn)
631 - tn->empty_children) 619 - tn->empty_children)
632 >= inflate_threshold_use * tnode_child_length(tn))) { 620 >= inflate_threshold_use * tnode_child_length(tn))) {
@@ -643,47 +631,19 @@ static struct node *resize(struct trie *t, struct tnode *tn)
643 } 631 }
644 } 632 }
645 633
646 if (max_resize < 0) {
647 if (!tn->parent) {
648 /*
649 * It was observed that during large updates even
650 * inflate_threshold_root = 35 might be needed to avoid
651 * this warning; but it should be temporary, so let's
652 * try to handle this automatically.
653 */
654 if (inflate_threshold_root_fix < INFLATE_FIX_MAX)
655 inflate_threshold_root_fix++;
656 else
657 pr_warning("Fix inflate_threshold_root."
658 " Now=%d size=%d bits fix=%d\n",
659 inflate_threshold_root, tn->bits,
660 inflate_threshold_root_fix);
661 } else {
662 pr_warning("Fix inflate_threshold."
663 " Now=%d size=%d bits\n",
664 inflate_threshold, tn->bits);
665 }
666 } else if (max_resize > 3 && !tn->parent && inflate_threshold_root_fix)
667 inflate_threshold_root_fix--;
668
669 check_tnode(tn); 634 check_tnode(tn);
670 635
636 /* Return if at least one inflate is run */
637 if( max_work != MAX_WORK)
638 return (struct node *) tn;
639
671 /* 640 /*
672 * Halve as long as the number of empty children in this 641 * Halve as long as the number of empty children in this
673 * node is above threshold. 642 * node is above threshold.
674 */ 643 */
675 644
676 645 max_work = MAX_WORK;
677 /* Keep root node larger */ 646 while (tn->bits > 1 && max_work-- &&
678
679 if (!tn->parent)
680 halve_threshold_use = halve_threshold_root;
681 else
682 halve_threshold_use = halve_threshold;
683
684 err = 0;
685 max_resize = 10;
686 while (tn->bits > 1 && max_resize-- &&
687 100 * (tnode_child_length(tn) - tn->empty_children) < 647 100 * (tnode_child_length(tn) - tn->empty_children) <
688 halve_threshold_use * tnode_child_length(tn)) { 648 halve_threshold_use * tnode_child_length(tn)) {
689 649
@@ -698,19 +658,10 @@ static struct node *resize(struct trie *t, struct tnode *tn)
698 } 658 }
699 } 659 }
700 660
701 if (max_resize < 0) {
702 if (!tn->parent)
703 pr_warning("Fix halve_threshold_root."
704 " Now=%d size=%d bits\n",
705 halve_threshold_root, tn->bits);
706 else
707 pr_warning("Fix halve_threshold."
708 " Now=%d size=%d bits\n",
709 halve_threshold, tn->bits);
710 }
711 661
712 /* Only one child remains */ 662 /* Only one child remains */
713 if (tn->empty_children == tnode_child_length(tn) - 1) 663 if (tn->empty_children == tnode_child_length(tn) - 1) {
664one_child:
714 for (i = 0; i < tnode_child_length(tn); i++) { 665 for (i = 0; i < tnode_child_length(tn); i++) {
715 struct node *n; 666 struct node *n;
716 667
@@ -724,7 +675,7 @@ static struct node *resize(struct trie *t, struct tnode *tn)
724 tnode_free_safe(tn); 675 tnode_free_safe(tn);
725 return n; 676 return n;
726 } 677 }
727 678 }
728 return (struct node *) tn; 679 return (struct node *) tn;
729} 680}
730 681