aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/fib_trie.c177
1 files changed, 145 insertions, 32 deletions
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 9038b914b4b1..4be234c7d8c3 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -43,7 +43,7 @@
43 * 2 of the License, or (at your option) any later version. 43 * 2 of the License, or (at your option) any later version.
44 */ 44 */
45 45
46#define VERSION "0.324" 46#define VERSION "0.325"
47 47
48#include <linux/config.h> 48#include <linux/config.h>
49#include <asm/uaccess.h> 49#include <asm/uaccess.h>
@@ -136,6 +136,7 @@ struct trie_use_stats {
136 unsigned int semantic_match_passed; 136 unsigned int semantic_match_passed;
137 unsigned int semantic_match_miss; 137 unsigned int semantic_match_miss;
138 unsigned int null_node_hit; 138 unsigned int null_node_hit;
139 unsigned int resize_node_skipped;
139}; 140};
140#endif 141#endif
141 142
@@ -164,8 +165,8 @@ static void put_child(struct trie *t, struct tnode *tn, int i, struct node *n);
164static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n, int wasfull); 165static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n, int wasfull);
165static int tnode_child_length(struct tnode *tn); 166static int tnode_child_length(struct tnode *tn);
166static struct node *resize(struct trie *t, struct tnode *tn); 167static struct node *resize(struct trie *t, struct tnode *tn);
167static struct tnode *inflate(struct trie *t, struct tnode *tn); 168static struct tnode *inflate(struct trie *t, struct tnode *tn, int *err);
168static struct tnode *halve(struct trie *t, struct tnode *tn); 169static struct tnode *halve(struct trie *t, struct tnode *tn, int *err);
169static void tnode_free(struct tnode *tn); 170static void tnode_free(struct tnode *tn);
170static void trie_dump_seq(struct seq_file *seq, struct trie *t); 171static void trie_dump_seq(struct seq_file *seq, struct trie *t);
171extern struct fib_alias *fib_find_alias(struct list_head *fah, u8 tos, u32 prio); 172extern struct fib_alias *fib_find_alias(struct list_head *fah, u8 tos, u32 prio);
@@ -481,6 +482,7 @@ static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n, int w
481static struct node *resize(struct trie *t, struct tnode *tn) 482static struct node *resize(struct trie *t, struct tnode *tn)
482{ 483{
483 int i; 484 int i;
485 int err = 0;
484 486
485 if (!tn) 487 if (!tn)
486 return NULL; 488 return NULL;
@@ -577,12 +579,20 @@ static struct node *resize(struct trie *t, struct tnode *tn)
577 */ 579 */
578 580
579 check_tnode(tn); 581 check_tnode(tn);
580 582
583 err = 0;
581 while ((tn->full_children > 0 && 584 while ((tn->full_children > 0 &&
582 50 * (tn->full_children + tnode_child_length(tn) - tn->empty_children) >= 585 50 * (tn->full_children + tnode_child_length(tn) - tn->empty_children) >=
583 inflate_threshold * tnode_child_length(tn))) { 586 inflate_threshold * tnode_child_length(tn))) {
584 587
585 tn = inflate(t, tn); 588 tn = inflate(t, tn, &err);
589
590 if(err) {
591#ifdef CONFIG_IP_FIB_TRIE_STATS
592 t->stats.resize_node_skipped++;
593#endif
594 break;
595 }
586 } 596 }
587 597
588 check_tnode(tn); 598 check_tnode(tn);
@@ -591,11 +601,22 @@ static struct node *resize(struct trie *t, struct tnode *tn)
591 * Halve as long as the number of empty children in this 601 * Halve as long as the number of empty children in this
592 * node is above threshold. 602 * node is above threshold.
593 */ 603 */
604
605 err = 0;
594 while (tn->bits > 1 && 606 while (tn->bits > 1 &&
595 100 * (tnode_child_length(tn) - tn->empty_children) < 607 100 * (tnode_child_length(tn) - tn->empty_children) <
596 halve_threshold * tnode_child_length(tn)) 608 halve_threshold * tnode_child_length(tn)) {
609
610 tn = halve(t, tn, &err);
611
612 if(err) {
613#ifdef CONFIG_IP_FIB_TRIE_STATS
614 t->stats.resize_node_skipped++;
615#endif
616 break;
617 }
618 }
597 619
598 tn = halve(t, tn);
599 620
600 /* Only one child remains */ 621 /* Only one child remains */
601 622
@@ -620,7 +641,7 @@ static struct node *resize(struct trie *t, struct tnode *tn)
620 return (struct node *) tn; 641 return (struct node *) tn;
621} 642}
622 643
623static struct tnode *inflate(struct trie *t, struct tnode *tn) 644static struct tnode *inflate(struct trie *t, struct tnode *tn, int *err)
624{ 645{
625 struct tnode *inode; 646 struct tnode *inode;
626 struct tnode *oldtnode = tn; 647 struct tnode *oldtnode = tn;
@@ -632,8 +653,63 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn)
632 653
633 tn = tnode_new(oldtnode->key, oldtnode->pos, oldtnode->bits + 1); 654 tn = tnode_new(oldtnode->key, oldtnode->pos, oldtnode->bits + 1);
634 655
635 if (!tn) 656 if (!tn) {
636 trie_bug("tnode_new failed"); 657 *err = -ENOMEM;
658 return oldtnode;
659 }
660
661 /*
662 * Preallocate and store tnodes before the actual work so we
663 * don't get into an inconsistent state if memory allocation
664 * fails. In case of failure we return the oldnode and inflate
665 * of tnode is ignored.
666 */
667
668 for(i = 0; i < olen; i++) {
669 struct tnode *inode = (struct tnode *) tnode_get_child(oldtnode, i);
670
671 if (inode &&
672 IS_TNODE(inode) &&
673 inode->pos == oldtnode->pos + oldtnode->bits &&
674 inode->bits > 1) {
675 struct tnode *left, *right;
676
677 t_key m = TKEY_GET_MASK(inode->pos, 1);
678
679 left = tnode_new(inode->key&(~m), inode->pos + 1,
680 inode->bits - 1);
681
682 if(!left) {
683 *err = -ENOMEM;
684 break;
685 }
686
687 right = tnode_new(inode->key|m, inode->pos + 1,
688 inode->bits - 1);
689
690 if(!right) {
691 *err = -ENOMEM;
692 break;
693 }
694
695 put_child(t, tn, 2*i, (struct node *) left);
696 put_child(t, tn, 2*i+1, (struct node *) right);
697 }
698 }
699
700 if(*err) {
701 int size = tnode_child_length(tn);
702 int j;
703
704 for(j = 0; j < size; j++)
705 if( tn->child[j])
706 tnode_free((struct tnode *)tn->child[j]);
707
708 tnode_free(tn);
709
710 *err = -ENOMEM;
711 return oldtnode;
712 }
637 713
638 for(i = 0; i < olen; i++) { 714 for(i = 0; i < olen; i++) {
639 struct node *node = tnode_get_child(oldtnode, i); 715 struct node *node = tnode_get_child(oldtnode, i);
@@ -646,7 +722,7 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn)
646 722
647 if(IS_LEAF(node) || ((struct tnode *) node)->pos > 723 if(IS_LEAF(node) || ((struct tnode *) node)->pos >
648 tn->pos + tn->bits - 1) { 724 tn->pos + tn->bits - 1) {
649 if(tkey_extract_bits(node->key, tn->pos + tn->bits - 1, 725 if(tkey_extract_bits(node->key, oldtnode->pos + oldtnode->bits,
650 1) == 0) 726 1) == 0)
651 put_child(t, tn, 2*i, node); 727 put_child(t, tn, 2*i, node);
652 else 728 else
@@ -686,27 +762,22 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn)
686 * the position (inode->pos) 762 * the position (inode->pos)
687 */ 763 */
688 764
689 t_key m = TKEY_GET_MASK(inode->pos, 1);
690
691 /* Use the old key, but set the new significant 765 /* Use the old key, but set the new significant
692 * bit to zero. 766 * bit to zero.
693 */ 767 */
694 left = tnode_new(inode->key&(~m), inode->pos + 1,
695 inode->bits - 1);
696 768
697 if(!left) 769 left = (struct tnode *) tnode_get_child(tn, 2*i);
698 trie_bug("tnode_new failed"); 770 put_child(t, tn, 2*i, NULL);
699 771
700 772 if(!left)
701 /* Use the old key, but set the new significant 773 BUG();
702 * bit to one. 774
703 */ 775 right = (struct tnode *) tnode_get_child(tn, 2*i+1);
704 right = tnode_new(inode->key|m, inode->pos + 1, 776 put_child(t, tn, 2*i+1, NULL);
705 inode->bits - 1); 777
778 if(!right)
779 BUG();
706 780
707 if(!right)
708 trie_bug("tnode_new failed");
709
710 size = tnode_child_length(left); 781 size = tnode_child_length(left);
711 for(j = 0; j < size; j++) { 782 for(j = 0; j < size; j++) {
712 put_child(t, left, j, inode->child[j]); 783 put_child(t, left, j, inode->child[j]);
@@ -722,7 +793,7 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn)
722 return tn; 793 return tn;
723} 794}
724 795
725static struct tnode *halve(struct trie *t, struct tnode *tn) 796static struct tnode *halve(struct trie *t, struct tnode *tn, int *err)
726{ 797{
727 struct tnode *oldtnode = tn; 798 struct tnode *oldtnode = tn;
728 struct node *left, *right; 799 struct node *left, *right;
@@ -733,8 +804,48 @@ static struct tnode *halve(struct trie *t, struct tnode *tn)
733 804
734 tn=tnode_new(oldtnode->key, oldtnode->pos, oldtnode->bits - 1); 805 tn=tnode_new(oldtnode->key, oldtnode->pos, oldtnode->bits - 1);
735 806
736 if(!tn) 807 if (!tn) {
737 trie_bug("tnode_new failed"); 808 *err = -ENOMEM;
809 return oldtnode;
810 }
811
812 /*
813 * Preallocate and store tnodes before the actual work so we
814 * don't get into an inconsistent state if memory allocation
815 * fails. In case of failure we return the oldnode and halve
816 * of tnode is ignored.
817 */
818
819 for(i = 0; i < olen; i += 2) {
820 left = tnode_get_child(oldtnode, i);
821 right = tnode_get_child(oldtnode, i+1);
822
823 /* Two nonempty children */
824 if( left && right) {
825 struct tnode *newBinNode =
826 tnode_new(left->key, tn->pos + tn->bits, 1);
827
828 if(!newBinNode) {
829 *err = -ENOMEM;
830 break;
831 }
832 put_child(t, tn, i/2, (struct node *)newBinNode);
833 }
834 }
835
836 if(*err) {
837 int size = tnode_child_length(tn);
838 int j;
839
840 for(j = 0; j < size; j++)
841 if( tn->child[j])
842 tnode_free((struct tnode *)tn->child[j]);
843
844 tnode_free(tn);
845
846 *err = -ENOMEM;
847 return oldtnode;
848 }
738 849
739 for(i = 0; i < olen; i += 2) { 850 for(i = 0; i < olen; i += 2) {
740 left = tnode_get_child(oldtnode, i); 851 left = tnode_get_child(oldtnode, i);
@@ -751,10 +862,11 @@ static struct tnode *halve(struct trie *t, struct tnode *tn)
751 /* Two nonempty children */ 862 /* Two nonempty children */
752 else { 863 else {
753 struct tnode *newBinNode = 864 struct tnode *newBinNode =
754 tnode_new(left->key, tn->pos + tn->bits, 1); 865 (struct tnode *) tnode_get_child(tn, i/2);
866 put_child(t, tn, i/2, NULL);
755 867
756 if(!newBinNode) 868 if(!newBinNode)
757 trie_bug("tnode_new failed"); 869 BUG();
758 870
759 put_child(t, newBinNode, 0, left); 871 put_child(t, newBinNode, 0, left);
760 put_child(t, newBinNode, 1, right); 872 put_child(t, newBinNode, 1, right);
@@ -2322,6 +2434,7 @@ static void collect_and_show(struct trie *t, struct seq_file *seq)
2322 seq_printf(seq,"semantic match passed = %d\n", t->stats.semantic_match_passed); 2434 seq_printf(seq,"semantic match passed = %d\n", t->stats.semantic_match_passed);
2323 seq_printf(seq,"semantic match miss = %d\n", t->stats.semantic_match_miss); 2435 seq_printf(seq,"semantic match miss = %d\n", t->stats.semantic_match_miss);
2324 seq_printf(seq,"null node hit= %d\n", t->stats.null_node_hit); 2436 seq_printf(seq,"null node hit= %d\n", t->stats.null_node_hit);
2437 seq_printf(seq,"skipped node resize = %d\n", t->stats.resize_node_skipped);
2325#ifdef CLEAR_STATS 2438#ifdef CLEAR_STATS
2326 memset(&(t->stats), 0, sizeof(t->stats)); 2439 memset(&(t->stats), 0, sizeof(t->stats));
2327#endif 2440#endif