diff options
Diffstat (limited to 'net/ipv4/fib_trie.c')
-rw-r--r-- | net/ipv4/fib_trie.c | 388 |
1 files changed, 179 insertions, 209 deletions
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 0f280348e0fd..c779ce96e5b5 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -12,7 +12,7 @@ | |||
12 | * | 12 | * |
13 | * Hans Liss <hans.liss@its.uu.se> Uppsala Universitet | 13 | * Hans Liss <hans.liss@its.uu.se> Uppsala Universitet |
14 | * | 14 | * |
15 | * This work is based on the LPC-trie which is originally descibed in: | 15 | * This work is based on the LPC-trie which is originally described in: |
16 | * | 16 | * |
17 | * An experimental study of compression methods for dynamic tries | 17 | * An experimental study of compression methods for dynamic tries |
18 | * Stefan Nilsson and Matti Tikkanen. Algorithmica, 33(1):19-33, 2002. | 18 | * Stefan Nilsson and Matti Tikkanen. Algorithmica, 33(1):19-33, 2002. |
@@ -95,7 +95,7 @@ typedef unsigned int t_key; | |||
95 | #define IS_TNODE(n) (!(n->parent & T_LEAF)) | 95 | #define IS_TNODE(n) (!(n->parent & T_LEAF)) |
96 | #define IS_LEAF(n) (n->parent & T_LEAF) | 96 | #define IS_LEAF(n) (n->parent & T_LEAF) |
97 | 97 | ||
98 | struct node { | 98 | struct rt_trie_node { |
99 | unsigned long parent; | 99 | unsigned long parent; |
100 | t_key key; | 100 | t_key key; |
101 | }; | 101 | }; |
@@ -126,7 +126,7 @@ struct tnode { | |||
126 | struct work_struct work; | 126 | struct work_struct work; |
127 | struct tnode *tnode_free; | 127 | struct tnode *tnode_free; |
128 | }; | 128 | }; |
129 | struct node *child[0]; | 129 | struct rt_trie_node __rcu *child[0]; |
130 | }; | 130 | }; |
131 | 131 | ||
132 | #ifdef CONFIG_IP_FIB_TRIE_STATS | 132 | #ifdef CONFIG_IP_FIB_TRIE_STATS |
@@ -151,16 +151,16 @@ struct trie_stat { | |||
151 | }; | 151 | }; |
152 | 152 | ||
153 | struct trie { | 153 | struct trie { |
154 | struct node *trie; | 154 | struct rt_trie_node __rcu *trie; |
155 | #ifdef CONFIG_IP_FIB_TRIE_STATS | 155 | #ifdef CONFIG_IP_FIB_TRIE_STATS |
156 | struct trie_use_stats stats; | 156 | struct trie_use_stats stats; |
157 | #endif | 157 | #endif |
158 | }; | 158 | }; |
159 | 159 | ||
160 | static void put_child(struct trie *t, struct tnode *tn, int i, struct node *n); | 160 | static void put_child(struct trie *t, struct tnode *tn, int i, struct rt_trie_node *n); |
161 | static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n, | 161 | static void tnode_put_child_reorg(struct tnode *tn, int i, struct rt_trie_node *n, |
162 | int wasfull); | 162 | int wasfull); |
163 | static struct node *resize(struct trie *t, struct tnode *tn); | 163 | static struct rt_trie_node *resize(struct trie *t, struct tnode *tn); |
164 | static struct tnode *inflate(struct trie *t, struct tnode *tn); | 164 | static struct tnode *inflate(struct trie *t, struct tnode *tn); |
165 | static struct tnode *halve(struct trie *t, struct tnode *tn); | 165 | static struct tnode *halve(struct trie *t, struct tnode *tn); |
166 | /* tnodes to free after resize(); protected by RTNL */ | 166 | /* tnodes to free after resize(); protected by RTNL */ |
@@ -177,39 +177,58 @@ static const int sync_pages = 128; | |||
177 | static struct kmem_cache *fn_alias_kmem __read_mostly; | 177 | static struct kmem_cache *fn_alias_kmem __read_mostly; |
178 | static struct kmem_cache *trie_leaf_kmem __read_mostly; | 178 | static struct kmem_cache *trie_leaf_kmem __read_mostly; |
179 | 179 | ||
180 | static inline struct tnode *node_parent(struct node *node) | 180 | /* |
181 | * caller must hold RTNL | ||
182 | */ | ||
183 | static inline struct tnode *node_parent(const struct rt_trie_node *node) | ||
181 | { | 184 | { |
182 | return (struct tnode *)(node->parent & ~NODE_TYPE_MASK); | 185 | unsigned long parent; |
186 | |||
187 | parent = rcu_dereference_index_check(node->parent, lockdep_rtnl_is_held()); | ||
188 | |||
189 | return (struct tnode *)(parent & ~NODE_TYPE_MASK); | ||
183 | } | 190 | } |
184 | 191 | ||
185 | static inline struct tnode *node_parent_rcu(struct node *node) | 192 | /* |
193 | * caller must hold RCU read lock or RTNL | ||
194 | */ | ||
195 | static inline struct tnode *node_parent_rcu(const struct rt_trie_node *node) | ||
186 | { | 196 | { |
187 | struct tnode *ret = node_parent(node); | 197 | unsigned long parent; |
198 | |||
199 | parent = rcu_dereference_index_check(node->parent, rcu_read_lock_held() || | ||
200 | lockdep_rtnl_is_held()); | ||
188 | 201 | ||
189 | return rcu_dereference_rtnl(ret); | 202 | return (struct tnode *)(parent & ~NODE_TYPE_MASK); |
190 | } | 203 | } |
191 | 204 | ||
192 | /* Same as rcu_assign_pointer | 205 | /* Same as rcu_assign_pointer |
193 | * but that macro() assumes that value is a pointer. | 206 | * but that macro() assumes that value is a pointer. |
194 | */ | 207 | */ |
195 | static inline void node_set_parent(struct node *node, struct tnode *ptr) | 208 | static inline void node_set_parent(struct rt_trie_node *node, struct tnode *ptr) |
196 | { | 209 | { |
197 | smp_wmb(); | 210 | smp_wmb(); |
198 | node->parent = (unsigned long)ptr | NODE_TYPE(node); | 211 | node->parent = (unsigned long)ptr | NODE_TYPE(node); |
199 | } | 212 | } |
200 | 213 | ||
201 | static inline struct node *tnode_get_child(struct tnode *tn, unsigned int i) | 214 | /* |
215 | * caller must hold RTNL | ||
216 | */ | ||
217 | static inline struct rt_trie_node *tnode_get_child(const struct tnode *tn, unsigned int i) | ||
202 | { | 218 | { |
203 | BUG_ON(i >= 1U << tn->bits); | 219 | BUG_ON(i >= 1U << tn->bits); |
204 | 220 | ||
205 | return tn->child[i]; | 221 | return rtnl_dereference(tn->child[i]); |
206 | } | 222 | } |
207 | 223 | ||
208 | static inline struct node *tnode_get_child_rcu(struct tnode *tn, unsigned int i) | 224 | /* |
225 | * caller must hold RCU read lock or RTNL | ||
226 | */ | ||
227 | static inline struct rt_trie_node *tnode_get_child_rcu(const struct tnode *tn, unsigned int i) | ||
209 | { | 228 | { |
210 | struct node *ret = tnode_get_child(tn, i); | 229 | BUG_ON(i >= 1U << tn->bits); |
211 | 230 | ||
212 | return rcu_dereference_rtnl(ret); | 231 | return rcu_dereference_rtnl(tn->child[i]); |
213 | } | 232 | } |
214 | 233 | ||
215 | static inline int tnode_child_length(const struct tnode *tn) | 234 | static inline int tnode_child_length(const struct tnode *tn) |
@@ -217,12 +236,12 @@ static inline int tnode_child_length(const struct tnode *tn) | |||
217 | return 1 << tn->bits; | 236 | return 1 << tn->bits; |
218 | } | 237 | } |
219 | 238 | ||
220 | static inline t_key mask_pfx(t_key k, unsigned short l) | 239 | static inline t_key mask_pfx(t_key k, unsigned int l) |
221 | { | 240 | { |
222 | return (l == 0) ? 0 : k >> (KEYLENGTH-l) << (KEYLENGTH-l); | 241 | return (l == 0) ? 0 : k >> (KEYLENGTH-l) << (KEYLENGTH-l); |
223 | } | 242 | } |
224 | 243 | ||
225 | static inline t_key tkey_extract_bits(t_key a, int offset, int bits) | 244 | static inline t_key tkey_extract_bits(t_key a, unsigned int offset, unsigned int bits) |
226 | { | 245 | { |
227 | if (offset < KEYLENGTH) | 246 | if (offset < KEYLENGTH) |
228 | return ((t_key)(a << offset)) >> (KEYLENGTH - bits); | 247 | return ((t_key)(a << offset)) >> (KEYLENGTH - bits); |
@@ -350,14 +369,9 @@ static inline void free_leaf(struct leaf *l) | |||
350 | call_rcu_bh(&l->rcu, __leaf_free_rcu); | 369 | call_rcu_bh(&l->rcu, __leaf_free_rcu); |
351 | } | 370 | } |
352 | 371 | ||
353 | static void __leaf_info_free_rcu(struct rcu_head *head) | ||
354 | { | ||
355 | kfree(container_of(head, struct leaf_info, rcu)); | ||
356 | } | ||
357 | |||
358 | static inline void free_leaf_info(struct leaf_info *leaf) | 372 | static inline void free_leaf_info(struct leaf_info *leaf) |
359 | { | 373 | { |
360 | call_rcu(&leaf->rcu, __leaf_info_free_rcu); | 374 | kfree_rcu(leaf, rcu); |
361 | } | 375 | } |
362 | 376 | ||
363 | static struct tnode *tnode_alloc(size_t size) | 377 | static struct tnode *tnode_alloc(size_t size) |
@@ -378,7 +392,7 @@ static void __tnode_free_rcu(struct rcu_head *head) | |||
378 | { | 392 | { |
379 | struct tnode *tn = container_of(head, struct tnode, rcu); | 393 | struct tnode *tn = container_of(head, struct tnode, rcu); |
380 | size_t size = sizeof(struct tnode) + | 394 | size_t size = sizeof(struct tnode) + |
381 | (sizeof(struct node *) << tn->bits); | 395 | (sizeof(struct rt_trie_node *) << tn->bits); |
382 | 396 | ||
383 | if (size <= PAGE_SIZE) | 397 | if (size <= PAGE_SIZE) |
384 | kfree(tn); | 398 | kfree(tn); |
@@ -402,7 +416,7 @@ static void tnode_free_safe(struct tnode *tn) | |||
402 | tn->tnode_free = tnode_free_head; | 416 | tn->tnode_free = tnode_free_head; |
403 | tnode_free_head = tn; | 417 | tnode_free_head = tn; |
404 | tnode_free_size += sizeof(struct tnode) + | 418 | tnode_free_size += sizeof(struct tnode) + |
405 | (sizeof(struct node *) << tn->bits); | 419 | (sizeof(struct rt_trie_node *) << tn->bits); |
406 | } | 420 | } |
407 | 421 | ||
408 | static void tnode_free_flush(void) | 422 | static void tnode_free_flush(void) |
@@ -443,7 +457,7 @@ static struct leaf_info *leaf_info_new(int plen) | |||
443 | 457 | ||
444 | static struct tnode *tnode_new(t_key key, int pos, int bits) | 458 | static struct tnode *tnode_new(t_key key, int pos, int bits) |
445 | { | 459 | { |
446 | size_t sz = sizeof(struct tnode) + (sizeof(struct node *) << bits); | 460 | size_t sz = sizeof(struct tnode) + (sizeof(struct rt_trie_node *) << bits); |
447 | struct tnode *tn = tnode_alloc(sz); | 461 | struct tnode *tn = tnode_alloc(sz); |
448 | 462 | ||
449 | if (tn) { | 463 | if (tn) { |
@@ -456,7 +470,7 @@ static struct tnode *tnode_new(t_key key, int pos, int bits) | |||
456 | } | 470 | } |
457 | 471 | ||
458 | pr_debug("AT %p s=%zu %zu\n", tn, sizeof(struct tnode), | 472 | pr_debug("AT %p s=%zu %zu\n", tn, sizeof(struct tnode), |
459 | sizeof(struct node) << bits); | 473 | sizeof(struct rt_trie_node) << bits); |
460 | return tn; | 474 | return tn; |
461 | } | 475 | } |
462 | 476 | ||
@@ -465,7 +479,7 @@ static struct tnode *tnode_new(t_key key, int pos, int bits) | |||
465 | * and no bits are skipped. See discussion in dyntree paper p. 6 | 479 | * and no bits are skipped. See discussion in dyntree paper p. 6 |
466 | */ | 480 | */ |
467 | 481 | ||
468 | static inline int tnode_full(const struct tnode *tn, const struct node *n) | 482 | static inline int tnode_full(const struct tnode *tn, const struct rt_trie_node *n) |
469 | { | 483 | { |
470 | if (n == NULL || IS_LEAF(n)) | 484 | if (n == NULL || IS_LEAF(n)) |
471 | return 0; | 485 | return 0; |
@@ -474,7 +488,7 @@ static inline int tnode_full(const struct tnode *tn, const struct node *n) | |||
474 | } | 488 | } |
475 | 489 | ||
476 | static inline void put_child(struct trie *t, struct tnode *tn, int i, | 490 | static inline void put_child(struct trie *t, struct tnode *tn, int i, |
477 | struct node *n) | 491 | struct rt_trie_node *n) |
478 | { | 492 | { |
479 | tnode_put_child_reorg(tn, i, n, -1); | 493 | tnode_put_child_reorg(tn, i, n, -1); |
480 | } | 494 | } |
@@ -484,10 +498,10 @@ static inline void put_child(struct trie *t, struct tnode *tn, int i, | |||
484 | * Update the value of full_children and empty_children. | 498 | * Update the value of full_children and empty_children. |
485 | */ | 499 | */ |
486 | 500 | ||
487 | static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n, | 501 | static void tnode_put_child_reorg(struct tnode *tn, int i, struct rt_trie_node *n, |
488 | int wasfull) | 502 | int wasfull) |
489 | { | 503 | { |
490 | struct node *chi = tn->child[i]; | 504 | struct rt_trie_node *chi = rtnl_dereference(tn->child[i]); |
491 | int isfull; | 505 | int isfull; |
492 | 506 | ||
493 | BUG_ON(i >= 1<<tn->bits); | 507 | BUG_ON(i >= 1<<tn->bits); |
@@ -515,7 +529,7 @@ static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n, | |||
515 | } | 529 | } |
516 | 530 | ||
517 | #define MAX_WORK 10 | 531 | #define MAX_WORK 10 |
518 | static struct node *resize(struct trie *t, struct tnode *tn) | 532 | static struct rt_trie_node *resize(struct trie *t, struct tnode *tn) |
519 | { | 533 | { |
520 | int i; | 534 | int i; |
521 | struct tnode *old_tn; | 535 | struct tnode *old_tn; |
@@ -605,7 +619,7 @@ static struct node *resize(struct trie *t, struct tnode *tn) | |||
605 | 619 | ||
606 | /* Keep root node larger */ | 620 | /* Keep root node larger */ |
607 | 621 | ||
608 | if (!node_parent((struct node *)tn)) { | 622 | if (!node_parent((struct rt_trie_node *)tn)) { |
609 | inflate_threshold_use = inflate_threshold_root; | 623 | inflate_threshold_use = inflate_threshold_root; |
610 | halve_threshold_use = halve_threshold_root; | 624 | halve_threshold_use = halve_threshold_root; |
611 | } else { | 625 | } else { |
@@ -635,7 +649,7 @@ static struct node *resize(struct trie *t, struct tnode *tn) | |||
635 | 649 | ||
636 | /* Return if at least one inflate is run */ | 650 | /* Return if at least one inflate is run */ |
637 | if (max_work != MAX_WORK) | 651 | if (max_work != MAX_WORK) |
638 | return (struct node *) tn; | 652 | return (struct rt_trie_node *) tn; |
639 | 653 | ||
640 | /* | 654 | /* |
641 | * Halve as long as the number of empty children in this | 655 | * Halve as long as the number of empty children in this |
@@ -663,9 +677,9 @@ static struct node *resize(struct trie *t, struct tnode *tn) | |||
663 | if (tn->empty_children == tnode_child_length(tn) - 1) { | 677 | if (tn->empty_children == tnode_child_length(tn) - 1) { |
664 | one_child: | 678 | one_child: |
665 | for (i = 0; i < tnode_child_length(tn); i++) { | 679 | for (i = 0; i < tnode_child_length(tn); i++) { |
666 | struct node *n; | 680 | struct rt_trie_node *n; |
667 | 681 | ||
668 | n = tn->child[i]; | 682 | n = rtnl_dereference(tn->child[i]); |
669 | if (!n) | 683 | if (!n) |
670 | continue; | 684 | continue; |
671 | 685 | ||
@@ -676,7 +690,21 @@ one_child: | |||
676 | return n; | 690 | return n; |
677 | } | 691 | } |
678 | } | 692 | } |
679 | return (struct node *) tn; | 693 | return (struct rt_trie_node *) tn; |
694 | } | ||
695 | |||
696 | |||
697 | static void tnode_clean_free(struct tnode *tn) | ||
698 | { | ||
699 | int i; | ||
700 | struct tnode *tofree; | ||
701 | |||
702 | for (i = 0; i < tnode_child_length(tn); i++) { | ||
703 | tofree = (struct tnode *)rtnl_dereference(tn->child[i]); | ||
704 | if (tofree) | ||
705 | tnode_free(tofree); | ||
706 | } | ||
707 | tnode_free(tn); | ||
680 | } | 708 | } |
681 | 709 | ||
682 | static struct tnode *inflate(struct trie *t, struct tnode *tn) | 710 | static struct tnode *inflate(struct trie *t, struct tnode *tn) |
@@ -723,14 +751,14 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn) | |||
723 | goto nomem; | 751 | goto nomem; |
724 | } | 752 | } |
725 | 753 | ||
726 | put_child(t, tn, 2*i, (struct node *) left); | 754 | put_child(t, tn, 2*i, (struct rt_trie_node *) left); |
727 | put_child(t, tn, 2*i+1, (struct node *) right); | 755 | put_child(t, tn, 2*i+1, (struct rt_trie_node *) right); |
728 | } | 756 | } |
729 | } | 757 | } |
730 | 758 | ||
731 | for (i = 0; i < olen; i++) { | 759 | for (i = 0; i < olen; i++) { |
732 | struct tnode *inode; | 760 | struct tnode *inode; |
733 | struct node *node = tnode_get_child(oldtnode, i); | 761 | struct rt_trie_node *node = tnode_get_child(oldtnode, i); |
734 | struct tnode *left, *right; | 762 | struct tnode *left, *right; |
735 | int size, j; | 763 | int size, j; |
736 | 764 | ||
@@ -755,8 +783,8 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn) | |||
755 | inode = (struct tnode *) node; | 783 | inode = (struct tnode *) node; |
756 | 784 | ||
757 | if (inode->bits == 1) { | 785 | if (inode->bits == 1) { |
758 | put_child(t, tn, 2*i, inode->child[0]); | 786 | put_child(t, tn, 2*i, rtnl_dereference(inode->child[0])); |
759 | put_child(t, tn, 2*i+1, inode->child[1]); | 787 | put_child(t, tn, 2*i+1, rtnl_dereference(inode->child[1])); |
760 | 788 | ||
761 | tnode_free_safe(inode); | 789 | tnode_free_safe(inode); |
762 | continue; | 790 | continue; |
@@ -797,8 +825,8 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn) | |||
797 | 825 | ||
798 | size = tnode_child_length(left); | 826 | size = tnode_child_length(left); |
799 | for (j = 0; j < size; j++) { | 827 | for (j = 0; j < size; j++) { |
800 | put_child(t, left, j, inode->child[j]); | 828 | put_child(t, left, j, rtnl_dereference(inode->child[j])); |
801 | put_child(t, right, j, inode->child[j + size]); | 829 | put_child(t, right, j, rtnl_dereference(inode->child[j + size])); |
802 | } | 830 | } |
803 | put_child(t, tn, 2*i, resize(t, left)); | 831 | put_child(t, tn, 2*i, resize(t, left)); |
804 | put_child(t, tn, 2*i+1, resize(t, right)); | 832 | put_child(t, tn, 2*i+1, resize(t, right)); |
@@ -808,24 +836,14 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn) | |||
808 | tnode_free_safe(oldtnode); | 836 | tnode_free_safe(oldtnode); |
809 | return tn; | 837 | return tn; |
810 | nomem: | 838 | nomem: |
811 | { | 839 | tnode_clean_free(tn); |
812 | int size = tnode_child_length(tn); | 840 | return ERR_PTR(-ENOMEM); |
813 | int j; | ||
814 | |||
815 | for (j = 0; j < size; j++) | ||
816 | if (tn->child[j]) | ||
817 | tnode_free((struct tnode *)tn->child[j]); | ||
818 | |||
819 | tnode_free(tn); | ||
820 | |||
821 | return ERR_PTR(-ENOMEM); | ||
822 | } | ||
823 | } | 841 | } |
824 | 842 | ||
825 | static struct tnode *halve(struct trie *t, struct tnode *tn) | 843 | static struct tnode *halve(struct trie *t, struct tnode *tn) |
826 | { | 844 | { |
827 | struct tnode *oldtnode = tn; | 845 | struct tnode *oldtnode = tn; |
828 | struct node *left, *right; | 846 | struct rt_trie_node *left, *right; |
829 | int i; | 847 | int i; |
830 | int olen = tnode_child_length(tn); | 848 | int olen = tnode_child_length(tn); |
831 | 849 | ||
@@ -856,7 +874,7 @@ static struct tnode *halve(struct trie *t, struct tnode *tn) | |||
856 | if (!newn) | 874 | if (!newn) |
857 | goto nomem; | 875 | goto nomem; |
858 | 876 | ||
859 | put_child(t, tn, i/2, (struct node *)newn); | 877 | put_child(t, tn, i/2, (struct rt_trie_node *)newn); |
860 | } | 878 | } |
861 | 879 | ||
862 | } | 880 | } |
@@ -890,18 +908,8 @@ static struct tnode *halve(struct trie *t, struct tnode *tn) | |||
890 | tnode_free_safe(oldtnode); | 908 | tnode_free_safe(oldtnode); |
891 | return tn; | 909 | return tn; |
892 | nomem: | 910 | nomem: |
893 | { | 911 | tnode_clean_free(tn); |
894 | int size = tnode_child_length(tn); | 912 | return ERR_PTR(-ENOMEM); |
895 | int j; | ||
896 | |||
897 | for (j = 0; j < size; j++) | ||
898 | if (tn->child[j]) | ||
899 | tnode_free((struct tnode *)tn->child[j]); | ||
900 | |||
901 | tnode_free(tn); | ||
902 | |||
903 | return ERR_PTR(-ENOMEM); | ||
904 | } | ||
905 | } | 913 | } |
906 | 914 | ||
907 | /* readside must use rcu_read_lock currently dump routines | 915 | /* readside must use rcu_read_lock currently dump routines |
@@ -958,7 +966,7 @@ fib_find_node(struct trie *t, u32 key) | |||
958 | { | 966 | { |
959 | int pos; | 967 | int pos; |
960 | struct tnode *tn; | 968 | struct tnode *tn; |
961 | struct node *n; | 969 | struct rt_trie_node *n; |
962 | 970 | ||
963 | pos = 0; | 971 | pos = 0; |
964 | n = rcu_dereference_rtnl(t->trie); | 972 | n = rcu_dereference_rtnl(t->trie); |
@@ -993,17 +1001,17 @@ static void trie_rebalance(struct trie *t, struct tnode *tn) | |||
993 | 1001 | ||
994 | key = tn->key; | 1002 | key = tn->key; |
995 | 1003 | ||
996 | while (tn != NULL && (tp = node_parent((struct node *)tn)) != NULL) { | 1004 | while (tn != NULL && (tp = node_parent((struct rt_trie_node *)tn)) != NULL) { |
997 | cindex = tkey_extract_bits(key, tp->pos, tp->bits); | 1005 | cindex = tkey_extract_bits(key, tp->pos, tp->bits); |
998 | wasfull = tnode_full(tp, tnode_get_child(tp, cindex)); | 1006 | wasfull = tnode_full(tp, tnode_get_child(tp, cindex)); |
999 | tn = (struct tnode *) resize(t, (struct tnode *)tn); | 1007 | tn = (struct tnode *) resize(t, (struct tnode *)tn); |
1000 | 1008 | ||
1001 | tnode_put_child_reorg((struct tnode *)tp, cindex, | 1009 | tnode_put_child_reorg((struct tnode *)tp, cindex, |
1002 | (struct node *)tn, wasfull); | 1010 | (struct rt_trie_node *)tn, wasfull); |
1003 | 1011 | ||
1004 | tp = node_parent((struct node *) tn); | 1012 | tp = node_parent((struct rt_trie_node *) tn); |
1005 | if (!tp) | 1013 | if (!tp) |
1006 | rcu_assign_pointer(t->trie, (struct node *)tn); | 1014 | rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn); |
1007 | 1015 | ||
1008 | tnode_free_flush(); | 1016 | tnode_free_flush(); |
1009 | if (!tp) | 1017 | if (!tp) |
@@ -1015,7 +1023,7 @@ static void trie_rebalance(struct trie *t, struct tnode *tn) | |||
1015 | if (IS_TNODE(tn)) | 1023 | if (IS_TNODE(tn)) |
1016 | tn = (struct tnode *)resize(t, (struct tnode *)tn); | 1024 | tn = (struct tnode *)resize(t, (struct tnode *)tn); |
1017 | 1025 | ||
1018 | rcu_assign_pointer(t->trie, (struct node *)tn); | 1026 | rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn); |
1019 | tnode_free_flush(); | 1027 | tnode_free_flush(); |
1020 | } | 1028 | } |
1021 | 1029 | ||
@@ -1025,7 +1033,7 @@ static struct list_head *fib_insert_node(struct trie *t, u32 key, int plen) | |||
1025 | { | 1033 | { |
1026 | int pos, newpos; | 1034 | int pos, newpos; |
1027 | struct tnode *tp = NULL, *tn = NULL; | 1035 | struct tnode *tp = NULL, *tn = NULL; |
1028 | struct node *n; | 1036 | struct rt_trie_node *n; |
1029 | struct leaf *l; | 1037 | struct leaf *l; |
1030 | int missbit; | 1038 | int missbit; |
1031 | struct list_head *fa_head = NULL; | 1039 | struct list_head *fa_head = NULL; |
@@ -1033,7 +1041,7 @@ static struct list_head *fib_insert_node(struct trie *t, u32 key, int plen) | |||
1033 | t_key cindex; | 1041 | t_key cindex; |
1034 | 1042 | ||
1035 | pos = 0; | 1043 | pos = 0; |
1036 | n = t->trie; | 1044 | n = rtnl_dereference(t->trie); |
1037 | 1045 | ||
1038 | /* If we point to NULL, stop. Either the tree is empty and we should | 1046 | /* If we point to NULL, stop. Either the tree is empty and we should |
1039 | * just put a new leaf in if, or we have reached an empty child slot, | 1047 | * just put a new leaf in if, or we have reached an empty child slot, |
@@ -1111,10 +1119,10 @@ static struct list_head *fib_insert_node(struct trie *t, u32 key, int plen) | |||
1111 | if (t->trie && n == NULL) { | 1119 | if (t->trie && n == NULL) { |
1112 | /* Case 2: n is NULL, and will just insert a new leaf */ | 1120 | /* Case 2: n is NULL, and will just insert a new leaf */ |
1113 | 1121 | ||
1114 | node_set_parent((struct node *)l, tp); | 1122 | node_set_parent((struct rt_trie_node *)l, tp); |
1115 | 1123 | ||
1116 | cindex = tkey_extract_bits(key, tp->pos, tp->bits); | 1124 | cindex = tkey_extract_bits(key, tp->pos, tp->bits); |
1117 | put_child(t, (struct tnode *)tp, cindex, (struct node *)l); | 1125 | put_child(t, (struct tnode *)tp, cindex, (struct rt_trie_node *)l); |
1118 | } else { | 1126 | } else { |
1119 | /* Case 3: n is a LEAF or a TNODE and the key doesn't match. */ | 1127 | /* Case 3: n is a LEAF or a TNODE and the key doesn't match. */ |
1120 | /* | 1128 | /* |
@@ -1141,18 +1149,18 @@ static struct list_head *fib_insert_node(struct trie *t, u32 key, int plen) | |||
1141 | return NULL; | 1149 | return NULL; |
1142 | } | 1150 | } |
1143 | 1151 | ||
1144 | node_set_parent((struct node *)tn, tp); | 1152 | node_set_parent((struct rt_trie_node *)tn, tp); |
1145 | 1153 | ||
1146 | missbit = tkey_extract_bits(key, newpos, 1); | 1154 | missbit = tkey_extract_bits(key, newpos, 1); |
1147 | put_child(t, tn, missbit, (struct node *)l); | 1155 | put_child(t, tn, missbit, (struct rt_trie_node *)l); |
1148 | put_child(t, tn, 1-missbit, n); | 1156 | put_child(t, tn, 1-missbit, n); |
1149 | 1157 | ||
1150 | if (tp) { | 1158 | if (tp) { |
1151 | cindex = tkey_extract_bits(key, tp->pos, tp->bits); | 1159 | cindex = tkey_extract_bits(key, tp->pos, tp->bits); |
1152 | put_child(t, (struct tnode *)tp, cindex, | 1160 | put_child(t, (struct tnode *)tp, cindex, |
1153 | (struct node *)tn); | 1161 | (struct rt_trie_node *)tn); |
1154 | } else { | 1162 | } else { |
1155 | rcu_assign_pointer(t->trie, (struct node *)tn); | 1163 | rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn); |
1156 | tp = tn; | 1164 | tp = tn; |
1157 | } | 1165 | } |
1158 | } | 1166 | } |
@@ -1245,7 +1253,6 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) | |||
1245 | if (fa->fa_info->fib_priority != fi->fib_priority) | 1253 | if (fa->fa_info->fib_priority != fi->fib_priority) |
1246 | break; | 1254 | break; |
1247 | if (fa->fa_type == cfg->fc_type && | 1255 | if (fa->fa_type == cfg->fc_type && |
1248 | fa->fa_scope == cfg->fc_scope && | ||
1249 | fa->fa_info == fi) { | 1256 | fa->fa_info == fi) { |
1250 | fa_match = fa; | 1257 | fa_match = fa; |
1251 | break; | 1258 | break; |
@@ -1271,7 +1278,6 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) | |||
1271 | new_fa->fa_tos = fa->fa_tos; | 1278 | new_fa->fa_tos = fa->fa_tos; |
1272 | new_fa->fa_info = fi; | 1279 | new_fa->fa_info = fi; |
1273 | new_fa->fa_type = cfg->fc_type; | 1280 | new_fa->fa_type = cfg->fc_type; |
1274 | new_fa->fa_scope = cfg->fc_scope; | ||
1275 | state = fa->fa_state; | 1281 | state = fa->fa_state; |
1276 | new_fa->fa_state = state & ~FA_S_ACCESSED; | 1282 | new_fa->fa_state = state & ~FA_S_ACCESSED; |
1277 | 1283 | ||
@@ -1308,7 +1314,6 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) | |||
1308 | new_fa->fa_info = fi; | 1314 | new_fa->fa_info = fi; |
1309 | new_fa->fa_tos = tos; | 1315 | new_fa->fa_tos = tos; |
1310 | new_fa->fa_type = cfg->fc_type; | 1316 | new_fa->fa_type = cfg->fc_type; |
1311 | new_fa->fa_scope = cfg->fc_scope; | ||
1312 | new_fa->fa_state = 0; | 1317 | new_fa->fa_state = 0; |
1313 | /* | 1318 | /* |
1314 | * Insert new entry to the list. | 1319 | * Insert new entry to the list. |
@@ -1322,6 +1327,9 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) | |||
1322 | } | 1327 | } |
1323 | } | 1328 | } |
1324 | 1329 | ||
1330 | if (!plen) | ||
1331 | tb->tb_num_default++; | ||
1332 | |||
1325 | list_add_tail_rcu(&new_fa->fa_list, | 1333 | list_add_tail_rcu(&new_fa->fa_list, |
1326 | (fa ? &fa->fa_list : fa_head)); | 1334 | (fa ? &fa->fa_list : fa_head)); |
1327 | 1335 | ||
@@ -1340,8 +1348,8 @@ err: | |||
1340 | } | 1348 | } |
1341 | 1349 | ||
1342 | /* should be called with rcu_read_lock */ | 1350 | /* should be called with rcu_read_lock */ |
1343 | static int check_leaf(struct trie *t, struct leaf *l, | 1351 | static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l, |
1344 | t_key key, const struct flowi *flp, | 1352 | t_key key, const struct flowi4 *flp, |
1345 | struct fib_result *res, int fib_flags) | 1353 | struct fib_result *res, int fib_flags) |
1346 | { | 1354 | { |
1347 | struct leaf_info *li; | 1355 | struct leaf_info *li; |
@@ -1349,40 +1357,75 @@ static int check_leaf(struct trie *t, struct leaf *l, | |||
1349 | struct hlist_node *node; | 1357 | struct hlist_node *node; |
1350 | 1358 | ||
1351 | hlist_for_each_entry_rcu(li, node, hhead, hlist) { | 1359 | hlist_for_each_entry_rcu(li, node, hhead, hlist) { |
1352 | int err; | 1360 | struct fib_alias *fa; |
1353 | int plen = li->plen; | 1361 | int plen = li->plen; |
1354 | __be32 mask = inet_make_mask(plen); | 1362 | __be32 mask = inet_make_mask(plen); |
1355 | 1363 | ||
1356 | if (l->key != (key & ntohl(mask))) | 1364 | if (l->key != (key & ntohl(mask))) |
1357 | continue; | 1365 | continue; |
1358 | 1366 | ||
1359 | err = fib_semantic_match(&li->falh, flp, res, plen, fib_flags); | 1367 | list_for_each_entry_rcu(fa, &li->falh, fa_list) { |
1368 | struct fib_info *fi = fa->fa_info; | ||
1369 | int nhsel, err; | ||
1360 | 1370 | ||
1371 | if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos) | ||
1372 | continue; | ||
1373 | if (fa->fa_info->fib_scope < flp->flowi4_scope) | ||
1374 | continue; | ||
1375 | fib_alias_accessed(fa); | ||
1376 | err = fib_props[fa->fa_type].error; | ||
1377 | if (err) { | ||
1361 | #ifdef CONFIG_IP_FIB_TRIE_STATS | 1378 | #ifdef CONFIG_IP_FIB_TRIE_STATS |
1362 | if (err <= 0) | 1379 | t->stats.semantic_match_passed++; |
1363 | t->stats.semantic_match_passed++; | 1380 | #endif |
1364 | else | 1381 | return err; |
1365 | t->stats.semantic_match_miss++; | 1382 | } |
1383 | if (fi->fib_flags & RTNH_F_DEAD) | ||
1384 | continue; | ||
1385 | for (nhsel = 0; nhsel < fi->fib_nhs; nhsel++) { | ||
1386 | const struct fib_nh *nh = &fi->fib_nh[nhsel]; | ||
1387 | |||
1388 | if (nh->nh_flags & RTNH_F_DEAD) | ||
1389 | continue; | ||
1390 | if (flp->flowi4_oif && flp->flowi4_oif != nh->nh_oif) | ||
1391 | continue; | ||
1392 | |||
1393 | #ifdef CONFIG_IP_FIB_TRIE_STATS | ||
1394 | t->stats.semantic_match_passed++; | ||
1395 | #endif | ||
1396 | res->prefixlen = plen; | ||
1397 | res->nh_sel = nhsel; | ||
1398 | res->type = fa->fa_type; | ||
1399 | res->scope = fa->fa_info->fib_scope; | ||
1400 | res->fi = fi; | ||
1401 | res->table = tb; | ||
1402 | res->fa_head = &li->falh; | ||
1403 | if (!(fib_flags & FIB_LOOKUP_NOREF)) | ||
1404 | atomic_inc(&res->fi->fib_clntref); | ||
1405 | return 0; | ||
1406 | } | ||
1407 | } | ||
1408 | |||
1409 | #ifdef CONFIG_IP_FIB_TRIE_STATS | ||
1410 | t->stats.semantic_match_miss++; | ||
1366 | #endif | 1411 | #endif |
1367 | if (err <= 0) | ||
1368 | return err; | ||
1369 | } | 1412 | } |
1370 | 1413 | ||
1371 | return 1; | 1414 | return 1; |
1372 | } | 1415 | } |
1373 | 1416 | ||
1374 | int fib_table_lookup(struct fib_table *tb, const struct flowi *flp, | 1417 | int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp, |
1375 | struct fib_result *res, int fib_flags) | 1418 | struct fib_result *res, int fib_flags) |
1376 | { | 1419 | { |
1377 | struct trie *t = (struct trie *) tb->tb_data; | 1420 | struct trie *t = (struct trie *) tb->tb_data; |
1378 | int ret; | 1421 | int ret; |
1379 | struct node *n; | 1422 | struct rt_trie_node *n; |
1380 | struct tnode *pn; | 1423 | struct tnode *pn; |
1381 | int pos, bits; | 1424 | unsigned int pos, bits; |
1382 | t_key key = ntohl(flp->fl4_dst); | 1425 | t_key key = ntohl(flp->daddr); |
1383 | int chopped_off; | 1426 | unsigned int chopped_off; |
1384 | t_key cindex = 0; | 1427 | t_key cindex = 0; |
1385 | int current_prefix_length = KEYLENGTH; | 1428 | unsigned int current_prefix_length = KEYLENGTH; |
1386 | struct tnode *cn; | 1429 | struct tnode *cn; |
1387 | t_key pref_mismatch; | 1430 | t_key pref_mismatch; |
1388 | 1431 | ||
@@ -1398,7 +1441,7 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi *flp, | |||
1398 | 1441 | ||
1399 | /* Just a leaf? */ | 1442 | /* Just a leaf? */ |
1400 | if (IS_LEAF(n)) { | 1443 | if (IS_LEAF(n)) { |
1401 | ret = check_leaf(t, (struct leaf *)n, key, flp, res, fib_flags); | 1444 | ret = check_leaf(tb, t, (struct leaf *)n, key, flp, res, fib_flags); |
1402 | goto found; | 1445 | goto found; |
1403 | } | 1446 | } |
1404 | 1447 | ||
@@ -1423,7 +1466,7 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi *flp, | |||
1423 | } | 1466 | } |
1424 | 1467 | ||
1425 | if (IS_LEAF(n)) { | 1468 | if (IS_LEAF(n)) { |
1426 | ret = check_leaf(t, (struct leaf *)n, key, flp, res, fib_flags); | 1469 | ret = check_leaf(tb, t, (struct leaf *)n, key, flp, res, fib_flags); |
1427 | if (ret > 0) | 1470 | if (ret > 0) |
1428 | goto backtrace; | 1471 | goto backtrace; |
1429 | goto found; | 1472 | goto found; |
@@ -1541,7 +1584,7 @@ backtrace: | |||
1541 | if (chopped_off <= pn->bits) { | 1584 | if (chopped_off <= pn->bits) { |
1542 | cindex &= ~(1 << (chopped_off-1)); | 1585 | cindex &= ~(1 << (chopped_off-1)); |
1543 | } else { | 1586 | } else { |
1544 | struct tnode *parent = node_parent_rcu((struct node *) pn); | 1587 | struct tnode *parent = node_parent_rcu((struct rt_trie_node *) pn); |
1545 | if (!parent) | 1588 | if (!parent) |
1546 | goto failed; | 1589 | goto failed; |
1547 | 1590 | ||
@@ -1568,7 +1611,7 @@ found: | |||
1568 | */ | 1611 | */ |
1569 | static void trie_leaf_remove(struct trie *t, struct leaf *l) | 1612 | static void trie_leaf_remove(struct trie *t, struct leaf *l) |
1570 | { | 1613 | { |
1571 | struct tnode *tp = node_parent((struct node *) l); | 1614 | struct tnode *tp = node_parent((struct rt_trie_node *) l); |
1572 | 1615 | ||
1573 | pr_debug("entering trie_leaf_remove(%p)\n", l); | 1616 | pr_debug("entering trie_leaf_remove(%p)\n", l); |
1574 | 1617 | ||
@@ -1629,7 +1672,9 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg) | |||
1629 | 1672 | ||
1630 | if ((!cfg->fc_type || fa->fa_type == cfg->fc_type) && | 1673 | if ((!cfg->fc_type || fa->fa_type == cfg->fc_type) && |
1631 | (cfg->fc_scope == RT_SCOPE_NOWHERE || | 1674 | (cfg->fc_scope == RT_SCOPE_NOWHERE || |
1632 | fa->fa_scope == cfg->fc_scope) && | 1675 | fa->fa_info->fib_scope == cfg->fc_scope) && |
1676 | (!cfg->fc_prefsrc || | ||
1677 | fi->fib_prefsrc == cfg->fc_prefsrc) && | ||
1633 | (!cfg->fc_protocol || | 1678 | (!cfg->fc_protocol || |
1634 | fi->fib_protocol == cfg->fc_protocol) && | 1679 | fi->fib_protocol == cfg->fc_protocol) && |
1635 | fib_nh_match(cfg, fi) == 0) { | 1680 | fib_nh_match(cfg, fi) == 0) { |
@@ -1650,6 +1695,9 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg) | |||
1650 | 1695 | ||
1651 | list_del_rcu(&fa->fa_list); | 1696 | list_del_rcu(&fa->fa_list); |
1652 | 1697 | ||
1698 | if (!plen) | ||
1699 | tb->tb_num_default--; | ||
1700 | |||
1653 | if (list_empty(fa_head)) { | 1701 | if (list_empty(fa_head)) { |
1654 | hlist_del_rcu(&li->hlist); | 1702 | hlist_del_rcu(&li->hlist); |
1655 | free_leaf_info(li); | 1703 | free_leaf_info(li); |
@@ -1706,7 +1754,7 @@ static int trie_flush_leaf(struct leaf *l) | |||
1706 | * Scan for the next right leaf starting at node p->child[idx] | 1754 | * Scan for the next right leaf starting at node p->child[idx] |
1707 | * Since we have back pointer, no recursion necessary. | 1755 | * Since we have back pointer, no recursion necessary. |
1708 | */ | 1756 | */ |
1709 | static struct leaf *leaf_walk_rcu(struct tnode *p, struct node *c) | 1757 | static struct leaf *leaf_walk_rcu(struct tnode *p, struct rt_trie_node *c) |
1710 | { | 1758 | { |
1711 | do { | 1759 | do { |
1712 | t_key idx; | 1760 | t_key idx; |
@@ -1722,7 +1770,7 @@ static struct leaf *leaf_walk_rcu(struct tnode *p, struct node *c) | |||
1722 | continue; | 1770 | continue; |
1723 | 1771 | ||
1724 | if (IS_LEAF(c)) { | 1772 | if (IS_LEAF(c)) { |
1725 | prefetch(p->child[idx]); | 1773 | prefetch(rcu_dereference_rtnl(p->child[idx])); |
1726 | return (struct leaf *) c; | 1774 | return (struct leaf *) c; |
1727 | } | 1775 | } |
1728 | 1776 | ||
@@ -1732,7 +1780,7 @@ static struct leaf *leaf_walk_rcu(struct tnode *p, struct node *c) | |||
1732 | } | 1780 | } |
1733 | 1781 | ||
1734 | /* Node empty, walk back up to parent */ | 1782 | /* Node empty, walk back up to parent */ |
1735 | c = (struct node *) p; | 1783 | c = (struct rt_trie_node *) p; |
1736 | } while ((p = node_parent_rcu(c)) != NULL); | 1784 | } while ((p = node_parent_rcu(c)) != NULL); |
1737 | 1785 | ||
1738 | return NULL; /* Root of trie */ | 1786 | return NULL; /* Root of trie */ |
@@ -1753,7 +1801,7 @@ static struct leaf *trie_firstleaf(struct trie *t) | |||
1753 | 1801 | ||
1754 | static struct leaf *trie_nextleaf(struct leaf *l) | 1802 | static struct leaf *trie_nextleaf(struct leaf *l) |
1755 | { | 1803 | { |
1756 | struct node *c = (struct node *) l; | 1804 | struct rt_trie_node *c = (struct rt_trie_node *) l; |
1757 | struct tnode *p = node_parent_rcu(c); | 1805 | struct tnode *p = node_parent_rcu(c); |
1758 | 1806 | ||
1759 | if (!p) | 1807 | if (!p) |
@@ -1802,80 +1850,6 @@ void fib_free_table(struct fib_table *tb) | |||
1802 | kfree(tb); | 1850 | kfree(tb); |
1803 | } | 1851 | } |
1804 | 1852 | ||
1805 | void fib_table_select_default(struct fib_table *tb, | ||
1806 | const struct flowi *flp, | ||
1807 | struct fib_result *res) | ||
1808 | { | ||
1809 | struct trie *t = (struct trie *) tb->tb_data; | ||
1810 | int order, last_idx; | ||
1811 | struct fib_info *fi = NULL; | ||
1812 | struct fib_info *last_resort; | ||
1813 | struct fib_alias *fa = NULL; | ||
1814 | struct list_head *fa_head; | ||
1815 | struct leaf *l; | ||
1816 | |||
1817 | last_idx = -1; | ||
1818 | last_resort = NULL; | ||
1819 | order = -1; | ||
1820 | |||
1821 | rcu_read_lock(); | ||
1822 | |||
1823 | l = fib_find_node(t, 0); | ||
1824 | if (!l) | ||
1825 | goto out; | ||
1826 | |||
1827 | fa_head = get_fa_head(l, 0); | ||
1828 | if (!fa_head) | ||
1829 | goto out; | ||
1830 | |||
1831 | if (list_empty(fa_head)) | ||
1832 | goto out; | ||
1833 | |||
1834 | list_for_each_entry_rcu(fa, fa_head, fa_list) { | ||
1835 | struct fib_info *next_fi = fa->fa_info; | ||
1836 | |||
1837 | if (fa->fa_scope != res->scope || | ||
1838 | fa->fa_type != RTN_UNICAST) | ||
1839 | continue; | ||
1840 | |||
1841 | if (next_fi->fib_priority > res->fi->fib_priority) | ||
1842 | break; | ||
1843 | if (!next_fi->fib_nh[0].nh_gw || | ||
1844 | next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK) | ||
1845 | continue; | ||
1846 | |||
1847 | fib_alias_accessed(fa); | ||
1848 | |||
1849 | if (fi == NULL) { | ||
1850 | if (next_fi != res->fi) | ||
1851 | break; | ||
1852 | } else if (!fib_detect_death(fi, order, &last_resort, | ||
1853 | &last_idx, tb->tb_default)) { | ||
1854 | fib_result_assign(res, fi); | ||
1855 | tb->tb_default = order; | ||
1856 | goto out; | ||
1857 | } | ||
1858 | fi = next_fi; | ||
1859 | order++; | ||
1860 | } | ||
1861 | if (order <= 0 || fi == NULL) { | ||
1862 | tb->tb_default = -1; | ||
1863 | goto out; | ||
1864 | } | ||
1865 | |||
1866 | if (!fib_detect_death(fi, order, &last_resort, &last_idx, | ||
1867 | tb->tb_default)) { | ||
1868 | fib_result_assign(res, fi); | ||
1869 | tb->tb_default = order; | ||
1870 | goto out; | ||
1871 | } | ||
1872 | if (last_idx >= 0) | ||
1873 | fib_result_assign(res, last_resort); | ||
1874 | tb->tb_default = last_idx; | ||
1875 | out: | ||
1876 | rcu_read_unlock(); | ||
1877 | } | ||
1878 | |||
1879 | static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah, | 1853 | static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah, |
1880 | struct fib_table *tb, | 1854 | struct fib_table *tb, |
1881 | struct sk_buff *skb, struct netlink_callback *cb) | 1855 | struct sk_buff *skb, struct netlink_callback *cb) |
@@ -1900,7 +1874,6 @@ static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah, | |||
1900 | RTM_NEWROUTE, | 1874 | RTM_NEWROUTE, |
1901 | tb->tb_id, | 1875 | tb->tb_id, |
1902 | fa->fa_type, | 1876 | fa->fa_type, |
1903 | fa->fa_scope, | ||
1904 | xkey, | 1877 | xkey, |
1905 | plen, | 1878 | plen, |
1906 | fa->fa_tos, | 1879 | fa->fa_tos, |
@@ -1990,7 +1963,7 @@ int fib_table_dump(struct fib_table *tb, struct sk_buff *skb, | |||
1990 | return skb->len; | 1963 | return skb->len; |
1991 | } | 1964 | } |
1992 | 1965 | ||
1993 | void __init fib_hash_init(void) | 1966 | void __init fib_trie_init(void) |
1994 | { | 1967 | { |
1995 | fn_alias_kmem = kmem_cache_create("ip_fib_alias", | 1968 | fn_alias_kmem = kmem_cache_create("ip_fib_alias", |
1996 | sizeof(struct fib_alias), | 1969 | sizeof(struct fib_alias), |
@@ -2003,8 +1976,7 @@ void __init fib_hash_init(void) | |||
2003 | } | 1976 | } |
2004 | 1977 | ||
2005 | 1978 | ||
2006 | /* Fix more generic FIB names for init later */ | 1979 | struct fib_table *fib_trie_table(u32 id) |
2007 | struct fib_table *fib_hash_table(u32 id) | ||
2008 | { | 1980 | { |
2009 | struct fib_table *tb; | 1981 | struct fib_table *tb; |
2010 | struct trie *t; | 1982 | struct trie *t; |
@@ -2016,13 +1988,11 @@ struct fib_table *fib_hash_table(u32 id) | |||
2016 | 1988 | ||
2017 | tb->tb_id = id; | 1989 | tb->tb_id = id; |
2018 | tb->tb_default = -1; | 1990 | tb->tb_default = -1; |
1991 | tb->tb_num_default = 0; | ||
2019 | 1992 | ||
2020 | t = (struct trie *) tb->tb_data; | 1993 | t = (struct trie *) tb->tb_data; |
2021 | memset(t, 0, sizeof(*t)); | 1994 | memset(t, 0, sizeof(*t)); |
2022 | 1995 | ||
2023 | if (id == RT_TABLE_LOCAL) | ||
2024 | pr_info("IPv4 FIB: Using LC-trie version %s\n", VERSION); | ||
2025 | |||
2026 | return tb; | 1996 | return tb; |
2027 | } | 1997 | } |
2028 | 1998 | ||
@@ -2036,7 +2006,7 @@ struct fib_trie_iter { | |||
2036 | unsigned int depth; | 2006 | unsigned int depth; |
2037 | }; | 2007 | }; |
2038 | 2008 | ||
2039 | static struct node *fib_trie_get_next(struct fib_trie_iter *iter) | 2009 | static struct rt_trie_node *fib_trie_get_next(struct fib_trie_iter *iter) |
2040 | { | 2010 | { |
2041 | struct tnode *tn = iter->tnode; | 2011 | struct tnode *tn = iter->tnode; |
2042 | unsigned int cindex = iter->index; | 2012 | unsigned int cindex = iter->index; |
@@ -2050,7 +2020,7 @@ static struct node *fib_trie_get_next(struct fib_trie_iter *iter) | |||
2050 | iter->tnode, iter->index, iter->depth); | 2020 | iter->tnode, iter->index, iter->depth); |
2051 | rescan: | 2021 | rescan: |
2052 | while (cindex < (1<<tn->bits)) { | 2022 | while (cindex < (1<<tn->bits)) { |
2053 | struct node *n = tnode_get_child_rcu(tn, cindex); | 2023 | struct rt_trie_node *n = tnode_get_child_rcu(tn, cindex); |
2054 | 2024 | ||
2055 | if (n) { | 2025 | if (n) { |
2056 | if (IS_LEAF(n)) { | 2026 | if (IS_LEAF(n)) { |
@@ -2069,7 +2039,7 @@ rescan: | |||
2069 | } | 2039 | } |
2070 | 2040 | ||
2071 | /* Current node exhausted, pop back up */ | 2041 | /* Current node exhausted, pop back up */ |
2072 | p = node_parent_rcu((struct node *)tn); | 2042 | p = node_parent_rcu((struct rt_trie_node *)tn); |
2073 | if (p) { | 2043 | if (p) { |
2074 | cindex = tkey_extract_bits(tn->key, p->pos, p->bits)+1; | 2044 | cindex = tkey_extract_bits(tn->key, p->pos, p->bits)+1; |
2075 | tn = p; | 2045 | tn = p; |
@@ -2081,10 +2051,10 @@ rescan: | |||
2081 | return NULL; | 2051 | return NULL; |
2082 | } | 2052 | } |
2083 | 2053 | ||
2084 | static struct node *fib_trie_get_first(struct fib_trie_iter *iter, | 2054 | static struct rt_trie_node *fib_trie_get_first(struct fib_trie_iter *iter, |
2085 | struct trie *t) | 2055 | struct trie *t) |
2086 | { | 2056 | { |
2087 | struct node *n; | 2057 | struct rt_trie_node *n; |
2088 | 2058 | ||
2089 | if (!t) | 2059 | if (!t) |
2090 | return NULL; | 2060 | return NULL; |
@@ -2108,7 +2078,7 @@ static struct node *fib_trie_get_first(struct fib_trie_iter *iter, | |||
2108 | 2078 | ||
2109 | static void trie_collect_stats(struct trie *t, struct trie_stat *s) | 2079 | static void trie_collect_stats(struct trie *t, struct trie_stat *s) |
2110 | { | 2080 | { |
2111 | struct node *n; | 2081 | struct rt_trie_node *n; |
2112 | struct fib_trie_iter iter; | 2082 | struct fib_trie_iter iter; |
2113 | 2083 | ||
2114 | memset(s, 0, sizeof(*s)); | 2084 | memset(s, 0, sizeof(*s)); |
@@ -2181,7 +2151,7 @@ static void trie_show_stats(struct seq_file *seq, struct trie_stat *stat) | |||
2181 | seq_putc(seq, '\n'); | 2151 | seq_putc(seq, '\n'); |
2182 | seq_printf(seq, "\tPointers: %u\n", pointers); | 2152 | seq_printf(seq, "\tPointers: %u\n", pointers); |
2183 | 2153 | ||
2184 | bytes += sizeof(struct node *) * pointers; | 2154 | bytes += sizeof(struct rt_trie_node *) * pointers; |
2185 | seq_printf(seq, "Null ptrs: %u\n", stat->nullpointers); | 2155 | seq_printf(seq, "Null ptrs: %u\n", stat->nullpointers); |
2186 | seq_printf(seq, "Total size: %u kB\n", (bytes + 1023) / 1024); | 2156 | seq_printf(seq, "Total size: %u kB\n", (bytes + 1023) / 1024); |
2187 | } | 2157 | } |
@@ -2262,7 +2232,7 @@ static const struct file_operations fib_triestat_fops = { | |||
2262 | .release = single_release_net, | 2232 | .release = single_release_net, |
2263 | }; | 2233 | }; |
2264 | 2234 | ||
2265 | static struct node *fib_trie_get_idx(struct seq_file *seq, loff_t pos) | 2235 | static struct rt_trie_node *fib_trie_get_idx(struct seq_file *seq, loff_t pos) |
2266 | { | 2236 | { |
2267 | struct fib_trie_iter *iter = seq->private; | 2237 | struct fib_trie_iter *iter = seq->private; |
2268 | struct net *net = seq_file_net(seq); | 2238 | struct net *net = seq_file_net(seq); |
@@ -2275,7 +2245,7 @@ static struct node *fib_trie_get_idx(struct seq_file *seq, loff_t pos) | |||
2275 | struct fib_table *tb; | 2245 | struct fib_table *tb; |
2276 | 2246 | ||
2277 | hlist_for_each_entry_rcu(tb, node, head, tb_hlist) { | 2247 | hlist_for_each_entry_rcu(tb, node, head, tb_hlist) { |
2278 | struct node *n; | 2248 | struct rt_trie_node *n; |
2279 | 2249 | ||
2280 | for (n = fib_trie_get_first(iter, | 2250 | for (n = fib_trie_get_first(iter, |
2281 | (struct trie *) tb->tb_data); | 2251 | (struct trie *) tb->tb_data); |
@@ -2304,7 +2274,7 @@ static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
2304 | struct fib_table *tb = iter->tb; | 2274 | struct fib_table *tb = iter->tb; |
2305 | struct hlist_node *tb_node; | 2275 | struct hlist_node *tb_node; |
2306 | unsigned int h; | 2276 | unsigned int h; |
2307 | struct node *n; | 2277 | struct rt_trie_node *n; |
2308 | 2278 | ||
2309 | ++*pos; | 2279 | ++*pos; |
2310 | /* next node in same table */ | 2280 | /* next node in same table */ |
@@ -2314,7 +2284,7 @@ static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
2314 | 2284 | ||
2315 | /* walk rest of this hash chain */ | 2285 | /* walk rest of this hash chain */ |
2316 | h = tb->tb_id & (FIB_TABLE_HASHSZ - 1); | 2286 | h = tb->tb_id & (FIB_TABLE_HASHSZ - 1); |
2317 | while ( (tb_node = rcu_dereference(tb->tb_hlist.next)) ) { | 2287 | while ((tb_node = rcu_dereference(hlist_next_rcu(&tb->tb_hlist)))) { |
2318 | tb = hlist_entry(tb_node, struct fib_table, tb_hlist); | 2288 | tb = hlist_entry(tb_node, struct fib_table, tb_hlist); |
2319 | n = fib_trie_get_first(iter, (struct trie *) tb->tb_data); | 2289 | n = fib_trie_get_first(iter, (struct trie *) tb->tb_data); |
2320 | if (n) | 2290 | if (n) |
@@ -2390,7 +2360,7 @@ static inline const char *rtn_type(char *buf, size_t len, unsigned int t) | |||
2390 | static int fib_trie_seq_show(struct seq_file *seq, void *v) | 2360 | static int fib_trie_seq_show(struct seq_file *seq, void *v) |
2391 | { | 2361 | { |
2392 | const struct fib_trie_iter *iter = seq->private; | 2362 | const struct fib_trie_iter *iter = seq->private; |
2393 | struct node *n = v; | 2363 | struct rt_trie_node *n = v; |
2394 | 2364 | ||
2395 | if (!node_parent_rcu(n)) | 2365 | if (!node_parent_rcu(n)) |
2396 | fib_table_print(seq, iter->tb); | 2366 | fib_table_print(seq, iter->tb); |
@@ -2422,7 +2392,7 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v) | |||
2422 | seq_indent(seq, iter->depth+1); | 2392 | seq_indent(seq, iter->depth+1); |
2423 | seq_printf(seq, " /%d %s %s", li->plen, | 2393 | seq_printf(seq, " /%d %s %s", li->plen, |
2424 | rtn_scope(buf1, sizeof(buf1), | 2394 | rtn_scope(buf1, sizeof(buf1), |
2425 | fa->fa_scope), | 2395 | fa->fa_info->fib_scope), |
2426 | rtn_type(buf2, sizeof(buf2), | 2396 | rtn_type(buf2, sizeof(buf2), |
2427 | fa->fa_type)); | 2397 | fa->fa_type)); |
2428 | if (fa->fa_tos) | 2398 | if (fa->fa_tos) |