080-18-fib_trie-Add-tracking-value-for-suffix-length.patch 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. From: Alexander Duyck <alexander.h.duyck@redhat.com>
  2. Date: Wed, 31 Dec 2014 10:57:08 -0800
  3. Subject: [PATCH] fib_trie: Add tracking value for suffix length
  4. This change adds a tracking value for the maximum suffix length of all
  5. prefixes stored in any given tnode. With this value we can determine if we
  6. need to backtrace or not based on if the suffix is greater than the pos
  7. value.
  8. By doing this we can reduce the CPU overhead for lookups in the local table
  9. as many of the prefixes there are 32b long and have a suffix length of 0
  10. meaning we can immediately backtrace to the root node without needing to
  11. test any of the nodes between it and where we ended up.
  12. Signed-off-by: Alexander Duyck <alexander.h.duyck@redhat.com>
  13. Signed-off-by: David S. Miller <davem@davemloft.net>
  14. ---
  15. --- a/net/ipv4/fib_trie.c
  16. +++ b/net/ipv4/fib_trie.c
  17. @@ -96,6 +96,7 @@ struct tnode {
  18. t_key key;
  19. unsigned char bits; /* 2log(KEYLENGTH) bits needed */
  20. unsigned char pos; /* 2log(KEYLENGTH) bits needed */
  21. + unsigned char slen;
  22. struct tnode __rcu *parent;
  23. struct rcu_head rcu;
  24. union {
  25. @@ -311,6 +312,7 @@ static struct tnode *leaf_new(t_key key)
  26. * as the nodes are searched
  27. */
  28. l->key = key;
  29. + l->slen = 0;
  30. l->pos = 0;
  31. /* set bits to 0 indicating we are not a tnode */
  32. l->bits = 0;
  33. @@ -342,6 +344,7 @@ static struct tnode *tnode_new(t_key key
  34. if (tn) {
  35. tn->parent = NULL;
  36. + tn->slen = pos;
  37. tn->pos = pos;
  38. tn->bits = bits;
  39. tn->key = (shift < KEYLENGTH) ? (key >> shift) << shift : 0;
  40. @@ -387,6 +390,9 @@ static void put_child(struct tnode *tn,
  41. else if (!wasfull && isfull)
  42. tn->full_children++;
  43. + if (n && (tn->slen < n->slen))
  44. + tn->slen = n->slen;
  45. +
  46. rcu_assign_pointer(tn->child[i], n);
  47. }
  48. @@ -635,6 +641,41 @@ static int halve(struct trie *t, struct
  49. return 0;
  50. }
  51. +static unsigned char update_suffix(struct tnode *tn)
  52. +{
  53. + unsigned char slen = tn->pos;
  54. + unsigned long stride, i;
  55. +
  56. + /* search though the list of children looking for nodes that might
  57. + * have a suffix greater than the one we currently have. This is
  58. + * why we start with a stride of 2 since a stride of 1 would
  59. + * represent the nodes with suffix length equal to tn->pos
  60. + */
  61. + for (i = 0, stride = 0x2ul ; i < tnode_child_length(tn); i += stride) {
  62. + struct tnode *n = tnode_get_child(tn, i);
  63. +
  64. + if (!n || (n->slen <= slen))
  65. + continue;
  66. +
  67. + /* update stride and slen based on new value */
  68. + stride <<= (n->slen - slen);
  69. + slen = n->slen;
  70. + i &= ~(stride - 1);
  71. +
  72. + /* if slen covers all but the last bit we can stop here
  73. + * there will be nothing longer than that since only node
  74. + * 0 and 1 << (bits - 1) could have that as their suffix
  75. + * length.
  76. + */
  77. + if ((slen + 1) >= (tn->pos + tn->bits))
  78. + break;
  79. + }
  80. +
  81. + tn->slen = slen;
  82. +
  83. + return slen;
  84. +}
  85. +
  86. /* From "Implementing a dynamic compressed trie" by Stefan Nilsson of
  87. * the Helsinki University of Technology and Matti Tikkanen of Nokia
  88. * Telecommunications, page 6:
  89. @@ -790,6 +831,19 @@ no_children:
  90. /* drop dead node */
  91. tnode_free_init(tn);
  92. tnode_free(tn);
  93. + return;
  94. + }
  95. +
  96. + /* Return if at least one deflate was run */
  97. + if (max_work != MAX_WORK)
  98. + return;
  99. +
  100. + /* push the suffix length to the parent node */
  101. + if (tn->slen > tn->pos) {
  102. + unsigned char slen = update_suffix(tn);
  103. +
  104. + if (tp && (slen > tp->slen))
  105. + tp->slen = slen;
  106. }
  107. }
  108. @@ -818,8 +872,58 @@ static inline struct list_head *get_fa_h
  109. return &li->falh;
  110. }
  111. -static void insert_leaf_info(struct hlist_head *head, struct leaf_info *new)
  112. +static void leaf_pull_suffix(struct tnode *l)
  113. +{
  114. + struct tnode *tp = node_parent(l);
  115. +
  116. + while (tp && (tp->slen > tp->pos) && (tp->slen > l->slen)) {
  117. + if (update_suffix(tp) > l->slen)
  118. + break;
  119. + tp = node_parent(tp);
  120. + }
  121. +}
  122. +
  123. +static void leaf_push_suffix(struct tnode *l)
  124. +{
  125. + struct tnode *tn = node_parent(l);
  126. +
  127. + /* if this is a new leaf then tn will be NULL and we can sort
  128. + * out parent suffix lengths as a part of trie_rebalance
  129. + */
  130. + while (tn && (tn->slen < l->slen)) {
  131. + tn->slen = l->slen;
  132. + tn = node_parent(tn);
  133. + }
  134. +}
  135. +
  136. +static void remove_leaf_info(struct tnode *l, struct leaf_info *old)
  137. +{
  138. + struct hlist_node *prev;
  139. +
  140. + /* record the location of the pointer to this object */
  141. + prev = rtnl_dereference(hlist_pprev_rcu(&old->hlist));
  142. +
  143. + /* remove the leaf info from the list */
  144. + hlist_del_rcu(&old->hlist);
  145. +
  146. + /* if we emptied the list this leaf will be freed and we can sort
  147. + * out parent suffix lengths as a part of trie_rebalance
  148. + */
  149. + if (hlist_empty(&l->list))
  150. + return;
  151. +
  152. + /* if we removed the tail then we need to update slen */
  153. + if (!rcu_access_pointer(hlist_next_rcu(prev))) {
  154. + struct leaf_info *li = hlist_entry(prev, typeof(*li), hlist);
  155. +
  156. + l->slen = KEYLENGTH - li->plen;
  157. + leaf_pull_suffix(l);
  158. + }
  159. +}
  160. +
  161. +static void insert_leaf_info(struct tnode *l, struct leaf_info *new)
  162. {
  163. + struct hlist_head *head = &l->list;
  164. struct leaf_info *li = NULL, *last = NULL;
  165. if (hlist_empty(head)) {
  166. @@ -836,6 +940,12 @@ static void insert_leaf_info(struct hlis
  167. else
  168. hlist_add_before_rcu(&new->hlist, &li->hlist);
  169. }
  170. +
  171. + /* if we added to the tail node then we need to update slen */
  172. + if (!rcu_access_pointer(hlist_next_rcu(&new->hlist))) {
  173. + l->slen = KEYLENGTH - new->plen;
  174. + leaf_push_suffix(l);
  175. + }
  176. }
  177. /* rcu_read_lock needs to be hold by caller from readside */
  178. @@ -925,7 +1035,7 @@ static struct list_head *fib_insert_node
  179. /* we have found a leaf. Prefixes have already been compared */
  180. if (IS_LEAF(n)) {
  181. /* Case 1: n is a leaf, and prefixes match*/
  182. - insert_leaf_info(&n->list, li);
  183. + insert_leaf_info(n, li);
  184. return fa_head;
  185. }
  186. @@ -939,7 +1049,7 @@ static struct list_head *fib_insert_node
  187. return NULL;
  188. }
  189. - insert_leaf_info(&l->list, li);
  190. + insert_leaf_info(l, li);
  191. /* Case 2: n is a LEAF or a TNODE and the key doesn't match.
  192. *
  193. @@ -1206,7 +1316,7 @@ int fib_table_lookup(struct fib_table *t
  194. /* only record pn and cindex if we are going to be chopping
  195. * bits later. Otherwise we are just wasting cycles.
  196. */
  197. - if (index) {
  198. + if (n->slen > n->pos) {
  199. pn = n;
  200. cindex = index;
  201. }
  202. @@ -1225,7 +1335,7 @@ int fib_table_lookup(struct fib_table *t
  203. * between the key and the prefix exist in the region of
  204. * the lsb and higher in the prefix.
  205. */
  206. - if (unlikely(prefix_mismatch(key, n)))
  207. + if (unlikely(prefix_mismatch(key, n)) || (n->slen == n->pos))
  208. goto backtrace;
  209. /* exit out and process leaf */
  210. @@ -1425,7 +1535,7 @@ int fib_table_delete(struct fib_table *t
  211. tb->tb_num_default--;
  212. if (list_empty(fa_head)) {
  213. - hlist_del_rcu(&li->hlist);
  214. + remove_leaf_info(l, li);
  215. free_leaf_info(li);
  216. }