2
0

080-08-fib_trie-Optimize-fib_table_insert.patch 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. From: Alexander Duyck <alexander.h.duyck@redhat.com>
  2. Date: Wed, 31 Dec 2014 10:56:06 -0800
  3. Subject: [PATCH] fib_trie: Optimize fib_table_insert
  4. This patch updates the fib_table_insert function to take advantage of the
  5. changes made to improve the performance of fib_table_lookup. As a result
  6. the code should be smaller and run faster then the original.
  7. Signed-off-by: Alexander Duyck <alexander.h.duyck@redhat.com>
  8. Signed-off-by: David S. Miller <davem@davemloft.net>
  9. ---
  10. --- a/net/ipv4/fib_trie.c
  11. +++ b/net/ipv4/fib_trie.c
  12. @@ -222,31 +222,6 @@ static inline t_key tkey_extract_bits(t_
  13. return 0;
  14. }
  15. -static inline int tkey_equals(t_key a, t_key b)
  16. -{
  17. - return a == b;
  18. -}
  19. -
  20. -static inline int tkey_sub_equals(t_key a, int offset, int bits, t_key b)
  21. -{
  22. - if (bits == 0 || offset >= KEYLENGTH)
  23. - return 1;
  24. - bits = bits > KEYLENGTH ? KEYLENGTH : bits;
  25. - return ((a ^ b) << offset) >> (KEYLENGTH - bits) == 0;
  26. -}
  27. -
  28. -static inline int tkey_mismatch(t_key a, int offset, t_key b)
  29. -{
  30. - t_key diff = a ^ b;
  31. - int i = offset;
  32. -
  33. - if (!diff)
  34. - return 0;
  35. - while ((diff << i) >> (KEYLENGTH-1) == 0)
  36. - i++;
  37. - return i;
  38. -}
  39. -
  40. /*
  41. To understand this stuff, an understanding of keys and all their bits is
  42. necessary. Every node in the trie has a key associated with it, but not
  43. @@ -485,6 +460,15 @@ static void tnode_put_child_reorg(struct
  44. rcu_assign_pointer(tn->child[i], n);
  45. }
  46. +static void put_child_root(struct tnode *tp, struct trie *t,
  47. + t_key key, struct tnode *n)
  48. +{
  49. + if (tp)
  50. + put_child(tp, get_index(key, tp), n);
  51. + else
  52. + rcu_assign_pointer(t->trie, n);
  53. +}
  54. +
  55. #define MAX_WORK 10
  56. static struct tnode *resize(struct trie *t, struct tnode *tn)
  57. {
  58. @@ -959,138 +943,100 @@ static void trie_rebalance(struct trie *
  59. static struct list_head *fib_insert_node(struct trie *t, u32 key, int plen)
  60. {
  61. - int pos, newpos;
  62. - struct tnode *tp = NULL, *tn = NULL;
  63. - struct tnode *n;
  64. - struct tnode *l;
  65. - int missbit;
  66. struct list_head *fa_head = NULL;
  67. + struct tnode *l, *n, *tp = NULL;
  68. struct leaf_info *li;
  69. - t_key cindex;
  70. - pos = 0;
  71. + li = leaf_info_new(plen);
  72. + if (!li)
  73. + return NULL;
  74. + fa_head = &li->falh;
  75. +
  76. n = rtnl_dereference(t->trie);
  77. /* If we point to NULL, stop. Either the tree is empty and we should
  78. * just put a new leaf in if, or we have reached an empty child slot,
  79. * and we should just put our new leaf in that.
  80. - * If we point to a T_TNODE, check if it matches our key. Note that
  81. - * a T_TNODE might be skipping any number of bits - its 'pos' need
  82. - * not be the parent's 'pos'+'bits'!
  83. - *
  84. - * If it does match the current key, get pos/bits from it, extract
  85. - * the index from our key, push the T_TNODE and walk the tree.
  86. - *
  87. - * If it doesn't, we have to replace it with a new T_TNODE.
  88. *
  89. - * If we point to a T_LEAF, it might or might not have the same key
  90. - * as we do. If it does, just change the value, update the T_LEAF's
  91. - * value, and return it.
  92. - * If it doesn't, we need to replace it with a T_TNODE.
  93. + * If we hit a node with a key that does't match then we should stop
  94. + * and create a new tnode to replace that node and insert ourselves
  95. + * and the other node into the new tnode.
  96. */
  97. + while (n) {
  98. + unsigned long index = get_index(key, n);
  99. - while (n && IS_TNODE(n)) {
  100. - if (tkey_sub_equals(n->key, pos, n->pos-pos, key)) {
  101. - tp = n;
  102. - pos = n->pos + n->bits;
  103. - n = tnode_get_child(n,
  104. - tkey_extract_bits(key,
  105. - n->pos,
  106. - n->bits));
  107. -
  108. - BUG_ON(n && node_parent(n) != tp);
  109. - } else
  110. + /* This bit of code is a bit tricky but it combines multiple
  111. + * checks into a single check. The prefix consists of the
  112. + * prefix plus zeros for the "bits" in the prefix. The index
  113. + * is the difference between the key and this value. From
  114. + * this we can actually derive several pieces of data.
  115. + * if !(index >> bits)
  116. + * we know the value is child index
  117. + * else
  118. + * we have a mismatch in skip bits and failed
  119. + */
  120. + if (index >> n->bits)
  121. break;
  122. - }
  123. -
  124. - /*
  125. - * n ----> NULL, LEAF or TNODE
  126. - *
  127. - * tp is n's (parent) ----> NULL or TNODE
  128. - */
  129. - BUG_ON(tp && IS_LEAF(tp));
  130. -
  131. - /* Case 1: n is a leaf. Compare prefixes */
  132. -
  133. - if (n != NULL && IS_LEAF(n) && tkey_equals(key, n->key)) {
  134. - li = leaf_info_new(plen);
  135. -
  136. - if (!li)
  137. - return NULL;
  138. + /* we have found a leaf. Prefixes have already been compared */
  139. + if (IS_LEAF(n)) {
  140. + /* Case 1: n is a leaf, and prefixes match*/
  141. + insert_leaf_info(&n->list, li);
  142. + return fa_head;
  143. + }
  144. - fa_head = &li->falh;
  145. - insert_leaf_info(&n->list, li);
  146. - goto done;
  147. + tp = n;
  148. + n = rcu_dereference_rtnl(n->child[index]);
  149. }
  150. - l = leaf_new(key);
  151. -
  152. - if (!l)
  153. - return NULL;
  154. - li = leaf_info_new(plen);
  155. -
  156. - if (!li) {
  157. - node_free(l);
  158. + l = leaf_new(key);
  159. + if (!l) {
  160. + free_leaf_info(li);
  161. return NULL;
  162. }
  163. - fa_head = &li->falh;
  164. insert_leaf_info(&l->list, li);
  165. - if (t->trie && n == NULL) {
  166. - /* Case 2: n is NULL, and will just insert a new leaf */
  167. -
  168. - node_set_parent(l, tp);
  169. -
  170. - cindex = tkey_extract_bits(key, tp->pos, tp->bits);
  171. - put_child(tp, cindex, l);
  172. - } else {
  173. - /* Case 3: n is a LEAF or a TNODE and the key doesn't match. */
  174. - /*
  175. - * Add a new tnode here
  176. - * first tnode need some special handling
  177. - */
  178. + /* Case 2: n is a LEAF or a TNODE and the key doesn't match.
  179. + *
  180. + * Add a new tnode here
  181. + * first tnode need some special handling
  182. + * leaves us in position for handling as case 3
  183. + */
  184. + if (n) {
  185. + struct tnode *tn;
  186. + int newpos;
  187. - if (n) {
  188. - pos = tp ? tp->pos+tp->bits : 0;
  189. - newpos = tkey_mismatch(key, pos, n->key);
  190. - tn = tnode_new(n->key, newpos, 1);
  191. - } else {
  192. - newpos = 0;
  193. - tn = tnode_new(key, newpos, 1); /* First tnode */
  194. - }
  195. + newpos = KEYLENGTH - __fls(n->key ^ key) - 1;
  196. + tn = tnode_new(key, newpos, 1);
  197. if (!tn) {
  198. free_leaf_info(li);
  199. node_free(l);
  200. return NULL;
  201. }
  202. - node_set_parent(tn, tp);
  203. -
  204. - missbit = tkey_extract_bits(key, newpos, 1);
  205. - put_child(tn, missbit, l);
  206. - put_child(tn, 1-missbit, n);
  207. -
  208. - if (tp) {
  209. - cindex = tkey_extract_bits(key, tp->pos, tp->bits);
  210. - put_child(tp, cindex, tn);
  211. - } else {
  212. - rcu_assign_pointer(t->trie, tn);
  213. - }
  214. + /* initialize routes out of node */
  215. + NODE_INIT_PARENT(tn, tp);
  216. + put_child(tn, get_index(key, tn) ^ 1, n);
  217. +
  218. + /* start adding routes into the node */
  219. + put_child_root(tp, t, key, tn);
  220. + node_set_parent(n, tn);
  221. + /* parent now has a NULL spot where the leaf can go */
  222. tp = tn;
  223. }
  224. - if (tp && tp->pos + tp->bits > 32)
  225. - pr_warn("fib_trie tp=%p pos=%d, bits=%d, key=%0x plen=%d\n",
  226. - tp, tp->pos, tp->bits, key, plen);
  227. -
  228. - /* Rebalance the trie */
  229. + /* Case 3: n is NULL, and will just insert a new leaf */
  230. + if (tp) {
  231. + NODE_INIT_PARENT(l, tp);
  232. + put_child(tp, get_index(key, tp), l);
  233. + trie_rebalance(t, tp);
  234. + } else {
  235. + rcu_assign_pointer(t->trie, l);
  236. + }
  237. - trie_rebalance(t, tp);
  238. -done:
  239. return fa_head;
  240. }
  241. @@ -1470,11 +1416,11 @@ static void trie_leaf_remove(struct trie
  242. pr_debug("entering trie_leaf_remove(%p)\n", l);
  243. if (tp) {
  244. - t_key cindex = tkey_extract_bits(l->key, tp->pos, tp->bits);
  245. - put_child(tp, cindex, NULL);
  246. + put_child(tp, get_index(l->key, tp), NULL);
  247. trie_rebalance(t, tp);
  248. - } else
  249. + } else {
  250. RCU_INIT_POINTER(t->trie, NULL);
  251. + }
  252. node_free(l);
  253. }