aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2016-12-01 07:27:57 -0500
committerDavid S. Miller <davem@davemloft.net>2016-12-05 13:15:58 -0500
commita52ca62c4a6771028da9c1de934cdbcd93d54bb4 (patch)
treead093923aaace74a845880a5707e997a4aa64647 /net
parent1a239173cccff726b60ac6a9c79ae4a1e26cfa49 (diff)
ipv4: Drop suffix update from resize code
It has been reported that update_suffix can be expensive when it is called on a large node in which most of the suffix lengths are the same. The time required to add 200K entries had increased from around 3 seconds to almost 49 seconds. In order to address this we need to move the code for updating the suffix out of resize and instead just have it handled in the cases where we are pushing a node that increases the suffix length, or will decrease the suffix length. Fixes: 5405afd1a306 ("fib_trie: Add tracking value for suffix length") Reported-by: Robert Shearman <rshearma@brocade.com> Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Reviewed-by: Robert Shearman <rshearma@brocade.com> Tested-by: Robert Shearman <rshearma@brocade.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/fib_trie.c42
1 files changed, 21 insertions, 21 deletions
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index eec90d72dd52..e3665bf7a7f3 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -719,6 +719,13 @@ static unsigned char update_suffix(struct key_vector *tn)
719{ 719{
720 unsigned char slen = tn->pos; 720 unsigned char slen = tn->pos;
721 unsigned long stride, i; 721 unsigned long stride, i;
722 unsigned char slen_max;
723
724 /* only vector 0 can have a suffix length greater than or equal to
725 * tn->pos + tn->bits, the second highest node will have a suffix
726 * length at most of tn->pos + tn->bits - 1
727 */
728 slen_max = min_t(unsigned char, tn->pos + tn->bits - 1, tn->slen);
722 729
723 /* search though the list of children looking for nodes that might 730 /* search though the list of children looking for nodes that might
724 * have a suffix greater than the one we currently have. This is 731 * have a suffix greater than the one we currently have. This is
@@ -736,12 +743,8 @@ static unsigned char update_suffix(struct key_vector *tn)
736 slen = n->slen; 743 slen = n->slen;
737 i &= ~(stride - 1); 744 i &= ~(stride - 1);
738 745
739 /* if slen covers all but the last bit we can stop here 746 /* stop searching if we have hit the maximum possible value */
740 * there will be nothing longer than that since only node 747 if (slen >= slen_max)
741 * 0 and 1 << (bits - 1) could have that as their suffix
742 * length.
743 */
744 if ((slen + 1) >= (tn->pos + tn->bits))
745 break; 748 break;
746 } 749 }
747 750
@@ -913,21 +916,7 @@ static struct key_vector *resize(struct trie *t, struct key_vector *tn)
913 return collapse(t, tn); 916 return collapse(t, tn);
914 917
915 /* update parent in case halve failed */ 918 /* update parent in case halve failed */
916 tp = node_parent(tn); 919 return node_parent(tn);
917
918 /* Return if at least one deflate was run */
919 if (max_work != MAX_WORK)
920 return tp;
921
922 /* push the suffix length to the parent node */
923 if (tn->slen > tn->pos) {
924 unsigned char slen = update_suffix(tn);
925
926 if (slen > tp->slen)
927 tp->slen = slen;
928 }
929
930 return tp;
931} 920}
932 921
933static void node_pull_suffix(struct key_vector *tn, unsigned char slen) 922static void node_pull_suffix(struct key_vector *tn, unsigned char slen)
@@ -1068,6 +1057,7 @@ static int fib_insert_node(struct trie *t, struct key_vector *tp,
1068 } 1057 }
1069 1058
1070 /* Case 3: n is NULL, and will just insert a new leaf */ 1059 /* Case 3: n is NULL, and will just insert a new leaf */
1060 node_push_suffix(tp, new->fa_slen);
1071 NODE_INIT_PARENT(l, tp); 1061 NODE_INIT_PARENT(l, tp);
1072 put_child_root(tp, key, l); 1062 put_child_root(tp, key, l);
1073 trie_rebalance(t, tp); 1063 trie_rebalance(t, tp);
@@ -1501,6 +1491,8 @@ static void fib_remove_alias(struct trie *t, struct key_vector *tp,
1501 * out parent suffix lengths as a part of trie_rebalance 1491 * out parent suffix lengths as a part of trie_rebalance
1502 */ 1492 */
1503 if (hlist_empty(&l->leaf)) { 1493 if (hlist_empty(&l->leaf)) {
1494 if (tp->slen == l->slen)
1495 node_pull_suffix(tp, tp->pos);
1504 put_child_root(tp, l->key, NULL); 1496 put_child_root(tp, l->key, NULL);
1505 node_free(l); 1497 node_free(l);
1506 trie_rebalance(t, tp); 1498 trie_rebalance(t, tp);
@@ -1785,6 +1777,10 @@ void fib_table_flush_external(struct fib_table *tb)
1785 if (IS_TRIE(pn)) 1777 if (IS_TRIE(pn))
1786 break; 1778 break;
1787 1779
1780 /* update the suffix to address pulled leaves */
1781 if (pn->slen > pn->pos)
1782 update_suffix(pn);
1783
1788 /* resize completed node */ 1784 /* resize completed node */
1789 pn = resize(t, pn); 1785 pn = resize(t, pn);
1790 cindex = get_index(pkey, pn); 1786 cindex = get_index(pkey, pn);
@@ -1851,6 +1847,10 @@ int fib_table_flush(struct net *net, struct fib_table *tb)
1851 if (IS_TRIE(pn)) 1847 if (IS_TRIE(pn))
1852 break; 1848 break;
1853 1849
1850 /* update the suffix to address pulled leaves */
1851 if (pn->slen > pn->pos)
1852 update_suffix(pn);
1853
1854 /* resize completed node */ 1854 /* resize completed node */
1855 pn = resize(t, pn); 1855 pn = resize(t, pn);
1856 cindex = get_index(pkey, pn); 1856 cindex = get_index(pkey, pn);