1
0

080-13-fib_trie-Add-functions-should_inflate-and-should_hal.patch 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. From: Alexander Duyck <alexander.h.duyck@redhat.com>
  2. Date: Wed, 31 Dec 2014 10:56:37 -0800
  3. Subject: [PATCH] fib_trie: Add functions should_inflate and should_halve
  4. This change pulls the logic for if we should inflate/halve the nodes out
  5. into separate functions. It also addresses what I believe is a bug where 1
  6. full node is all that is needed to keep a node from ever being halved.
  7. Simple script to reproduce the issue:
  8. modprobe dummy; ifconfig dummy0 up
  9. for i in `seq 0 255`; do ifconfig dummy0:$i 10.0.${i}.1/24 up; done
  10. ifconfig dummy0:256 10.0.255.33/16 up
  11. for i in `seq 0 254`; do ifconfig dummy0:$i down; done
  12. Results from /proc/net/fib_triestat
  13. Before:
  14. Local:
  15. Aver depth: 3.00
  16. Max depth: 4
  17. Leaves: 17
  18. Prefixes: 18
  19. Internal nodes: 11
  20. 1: 8 2: 2 10: 1
  21. Pointers: 1048
  22. Null ptrs: 1021
  23. Total size: 11 kB
  24. After:
  25. Local:
  26. Aver depth: 3.41
  27. Max depth: 5
  28. Leaves: 17
  29. Prefixes: 18
  30. Internal nodes: 12
  31. 1: 8 2: 3 3: 1
  32. Pointers: 36
  33. Null ptrs: 8
  34. Total size: 3 kB
  35. Signed-off-by: Alexander Duyck <alexander.h.duyck@redhat.com>
  36. Signed-off-by: David S. Miller <davem@davemloft.net>
  37. ---
  38. --- a/net/ipv4/fib_trie.c
  39. +++ b/net/ipv4/fib_trie.c
  40. @@ -647,12 +647,94 @@ nomem:
  41. return ERR_PTR(-ENOMEM);
  42. }
  43. +/* From "Implementing a dynamic compressed trie" by Stefan Nilsson of
  44. + * the Helsinki University of Technology and Matti Tikkanen of Nokia
  45. + * Telecommunications, page 6:
  46. + * "A node is doubled if the ratio of non-empty children to all
  47. + * children in the *doubled* node is at least 'high'."
  48. + *
  49. + * 'high' in this instance is the variable 'inflate_threshold'. It
  50. + * is expressed as a percentage, so we multiply it with
  51. + * tnode_child_length() and instead of multiplying by 2 (since the
  52. + * child array will be doubled by inflate()) and multiplying
  53. + * the left-hand side by 100 (to handle the percentage thing) we
  54. + * multiply the left-hand side by 50.
  55. + *
  56. + * The left-hand side may look a bit weird: tnode_child_length(tn)
  57. + * - tn->empty_children is of course the number of non-null children
  58. + * in the current node. tn->full_children is the number of "full"
  59. + * children, that is non-null tnodes with a skip value of 0.
  60. + * All of those will be doubled in the resulting inflated tnode, so
  61. + * we just count them one extra time here.
  62. + *
  63. + * A clearer way to write this would be:
  64. + *
  65. + * to_be_doubled = tn->full_children;
  66. + * not_to_be_doubled = tnode_child_length(tn) - tn->empty_children -
  67. + * tn->full_children;
  68. + *
  69. + * new_child_length = tnode_child_length(tn) * 2;
  70. + *
  71. + * new_fill_factor = 100 * (not_to_be_doubled + 2*to_be_doubled) /
  72. + * new_child_length;
  73. + * if (new_fill_factor >= inflate_threshold)
  74. + *
  75. + * ...and so on, tho it would mess up the while () loop.
  76. + *
  77. + * anyway,
  78. + * 100 * (not_to_be_doubled + 2*to_be_doubled) / new_child_length >=
  79. + * inflate_threshold
  80. + *
  81. + * avoid a division:
  82. + * 100 * (not_to_be_doubled + 2*to_be_doubled) >=
  83. + * inflate_threshold * new_child_length
  84. + *
  85. + * expand not_to_be_doubled and to_be_doubled, and shorten:
  86. + * 100 * (tnode_child_length(tn) - tn->empty_children +
  87. + * tn->full_children) >= inflate_threshold * new_child_length
  88. + *
  89. + * expand new_child_length:
  90. + * 100 * (tnode_child_length(tn) - tn->empty_children +
  91. + * tn->full_children) >=
  92. + * inflate_threshold * tnode_child_length(tn) * 2
  93. + *
  94. + * shorten again:
  95. + * 50 * (tn->full_children + tnode_child_length(tn) -
  96. + * tn->empty_children) >= inflate_threshold *
  97. + * tnode_child_length(tn)
  98. + *
  99. + */
  100. +static bool should_inflate(const struct tnode *tn)
  101. +{
  102. + unsigned long used = tnode_child_length(tn);
  103. + unsigned long threshold = used;
  104. +
  105. + /* Keep root node larger */
  106. + threshold *= node_parent(tn) ? inflate_threshold :
  107. + inflate_threshold_root;
  108. + used += tn->full_children;
  109. + used -= tn->empty_children;
  110. +
  111. + return tn->pos && ((50 * used) >= threshold);
  112. +}
  113. +
  114. +static bool should_halve(const struct tnode *tn)
  115. +{
  116. + unsigned long used = tnode_child_length(tn);
  117. + unsigned long threshold = used;
  118. +
  119. + /* Keep root node larger */
  120. + threshold *= node_parent(tn) ? halve_threshold :
  121. + halve_threshold_root;
  122. + used -= tn->empty_children;
  123. +
  124. + return (tn->bits > 1) && ((100 * used) < threshold);
  125. +}
  126. +
  127. #define MAX_WORK 10
  128. static struct tnode *resize(struct trie *t, struct tnode *tn)
  129. {
  130. struct tnode *old_tn, *n = NULL;
  131. - int inflate_threshold_use;
  132. - int halve_threshold_use;
  133. int max_work;
  134. if (!tn)
  135. @@ -668,86 +750,12 @@ static struct tnode *resize(struct trie
  136. /* One child */
  137. if (tn->empty_children == (tnode_child_length(tn) - 1))
  138. goto one_child;
  139. - /*
  140. - * Double as long as the resulting node has a number of
  141. - * nonempty nodes that are above the threshold.
  142. - */
  143. - /*
  144. - * From "Implementing a dynamic compressed trie" by Stefan Nilsson of
  145. - * the Helsinki University of Technology and Matti Tikkanen of Nokia
  146. - * Telecommunications, page 6:
  147. - * "A node is doubled if the ratio of non-empty children to all
  148. - * children in the *doubled* node is at least 'high'."
  149. - *
  150. - * 'high' in this instance is the variable 'inflate_threshold'. It
  151. - * is expressed as a percentage, so we multiply it with
  152. - * tnode_child_length() and instead of multiplying by 2 (since the
  153. - * child array will be doubled by inflate()) and multiplying
  154. - * the left-hand side by 100 (to handle the percentage thing) we
  155. - * multiply the left-hand side by 50.
  156. - *
  157. - * The left-hand side may look a bit weird: tnode_child_length(tn)
  158. - * - tn->empty_children is of course the number of non-null children
  159. - * in the current node. tn->full_children is the number of "full"
  160. - * children, that is non-null tnodes with a skip value of 0.
  161. - * All of those will be doubled in the resulting inflated tnode, so
  162. - * we just count them one extra time here.
  163. - *
  164. - * A clearer way to write this would be:
  165. - *
  166. - * to_be_doubled = tn->full_children;
  167. - * not_to_be_doubled = tnode_child_length(tn) - tn->empty_children -
  168. - * tn->full_children;
  169. - *
  170. - * new_child_length = tnode_child_length(tn) * 2;
  171. - *
  172. - * new_fill_factor = 100 * (not_to_be_doubled + 2*to_be_doubled) /
  173. - * new_child_length;
  174. - * if (new_fill_factor >= inflate_threshold)
  175. - *
  176. - * ...and so on, tho it would mess up the while () loop.
  177. - *
  178. - * anyway,
  179. - * 100 * (not_to_be_doubled + 2*to_be_doubled) / new_child_length >=
  180. - * inflate_threshold
  181. - *
  182. - * avoid a division:
  183. - * 100 * (not_to_be_doubled + 2*to_be_doubled) >=
  184. - * inflate_threshold * new_child_length
  185. - *
  186. - * expand not_to_be_doubled and to_be_doubled, and shorten:
  187. - * 100 * (tnode_child_length(tn) - tn->empty_children +
  188. - * tn->full_children) >= inflate_threshold * new_child_length
  189. - *
  190. - * expand new_child_length:
  191. - * 100 * (tnode_child_length(tn) - tn->empty_children +
  192. - * tn->full_children) >=
  193. - * inflate_threshold * tnode_child_length(tn) * 2
  194. - *
  195. - * shorten again:
  196. - * 50 * (tn->full_children + tnode_child_length(tn) -
  197. - * tn->empty_children) >= inflate_threshold *
  198. - * tnode_child_length(tn)
  199. - *
  200. + /* Double as long as the resulting node has a number of
  201. + * nonempty nodes that are above the threshold.
  202. */
  203. -
  204. - /* Keep root node larger */
  205. -
  206. - if (!node_parent(tn)) {
  207. - inflate_threshold_use = inflate_threshold_root;
  208. - halve_threshold_use = halve_threshold_root;
  209. - } else {
  210. - inflate_threshold_use = inflate_threshold;
  211. - halve_threshold_use = halve_threshold;
  212. - }
  213. -
  214. max_work = MAX_WORK;
  215. - while ((tn->full_children > 0 && max_work-- &&
  216. - 50 * (tn->full_children + tnode_child_length(tn)
  217. - - tn->empty_children)
  218. - >= inflate_threshold_use * tnode_child_length(tn))) {
  219. -
  220. + while (should_inflate(tn) && max_work--) {
  221. old_tn = tn;
  222. tn = inflate(t, tn);
  223. @@ -764,16 +772,11 @@ static struct tnode *resize(struct trie
  224. if (max_work != MAX_WORK)
  225. return tn;
  226. - /*
  227. - * Halve as long as the number of empty children in this
  228. + /* Halve as long as the number of empty children in this
  229. * node is above threshold.
  230. */
  231. -
  232. max_work = MAX_WORK;
  233. - while (tn->bits > 1 && max_work-- &&
  234. - 100 * (tnode_child_length(tn) - tn->empty_children) <
  235. - halve_threshold_use * tnode_child_length(tn)) {
  236. -
  237. + while (should_halve(tn) && max_work--) {
  238. old_tn = tn;
  239. tn = halve(t, tn);
  240. if (IS_ERR(tn)) {