token_bucket.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. /* Copyright (c) 2018-2018, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. /**
  4. * \file token_bucket.c
  5. * \brief Functions to use and manipulate token buckets, used for
  6. * rate-limiting on connections and globally.
  7. *
  8. * Tor uses these token buckets to keep track of bandwidth usage, and
  9. * sometimes other things too.
  10. *
  11. * There are two layers of abstraction here: "raw" token buckets, in which all
  12. * the pieces are decoupled, and "read-write" token buckets, which combine all
  13. * the moving parts into one.
  14. *
  15. * Token buckets may become negative.
  16. **/
  17. #define TOKEN_BUCKET_PRIVATE
  18. #include "lib/evloop/token_bucket.h"
  19. #include "lib/log/util_bug.h"
  20. #include "lib/intmath/cmp.h"
  21. #include "lib/time/compat_time.h"
  22. #include <string.h>
  23. /**
  24. * Set the <b>rate</b> and <b>burst</b> value in a token_bucket_cfg.
  25. *
  26. * Note that the <b>rate</b> value is in arbitrary units, but those units will
  27. * determine the units of token_bucket_raw_dec(), token_bucket_raw_refill, and
  28. * so on.
  29. */
  30. void
  31. token_bucket_cfg_init(token_bucket_cfg_t *cfg,
  32. uint32_t rate,
  33. uint32_t burst)
  34. {
  35. tor_assert_nonfatal(rate > 0);
  36. tor_assert_nonfatal(burst > 0);
  37. if (burst > TOKEN_BUCKET_MAX_BURST)
  38. burst = TOKEN_BUCKET_MAX_BURST;
  39. cfg->rate = rate;
  40. cfg->burst = burst;
  41. }
  42. /**
  43. * Initialize a raw token bucket and its associated timestamp to the "full"
  44. * state, according to <b>cfg</b>.
  45. */
  46. void
  47. token_bucket_raw_reset(token_bucket_raw_t *bucket,
  48. const token_bucket_cfg_t *cfg)
  49. {
  50. bucket->bucket = cfg->burst;
  51. }
  52. /**
  53. * Adust a preexisting token bucket to respect the new configuration
  54. * <b>cfg</b>, by decreasing its current level if needed. */
  55. void
  56. token_bucket_raw_adjust(token_bucket_raw_t *bucket,
  57. const token_bucket_cfg_t *cfg)
  58. {
  59. bucket->bucket = MIN(bucket->bucket, cfg->burst);
  60. }
  61. /**
  62. * Given an amount of <b>elapsed</b> time units, and a bucket configuration
  63. * <b>cfg</b>, refill the level of <b>bucket</b> accordingly. Note that the
  64. * units of time in <b>elapsed</b> must correspond to those used to set the
  65. * rate in <b>cfg</b>, or the result will be illogical.
  66. */
  67. int
  68. token_bucket_raw_refill_steps(token_bucket_raw_t *bucket,
  69. const token_bucket_cfg_t *cfg,
  70. const uint32_t elapsed)
  71. {
  72. const int was_empty = (bucket->bucket <= 0);
  73. /* The casts here prevent an underflow.
  74. *
  75. * Note that even if the bucket value is negative, subtracting it from
  76. * "burst" will still produce a correct result. If this result is
  77. * ridiculously high, then the "elapsed > gap / rate" check below
  78. * should catch it. */
  79. const size_t gap = ((size_t)cfg->burst) - ((size_t)bucket->bucket);
  80. if (elapsed > gap / cfg->rate) {
  81. bucket->bucket = cfg->burst;
  82. } else {
  83. bucket->bucket += cfg->rate * elapsed;
  84. }
  85. return was_empty && bucket->bucket > 0;
  86. }
  87. /**
  88. * Decrement a provided bucket by <b>n</b> units. Note that <b>n</b>
  89. * must be nonnegative.
  90. */
  91. int
  92. token_bucket_raw_dec(token_bucket_raw_t *bucket,
  93. ssize_t n)
  94. {
  95. if (BUG(n < 0))
  96. return 0;
  97. const int becomes_empty = bucket->bucket > 0 && n >= bucket->bucket;
  98. bucket->bucket -= n;
  99. return becomes_empty;
  100. }
  101. /** Convert a rate in bytes per second to a rate in bytes per step */
  102. STATIC uint32_t
  103. rate_per_sec_to_rate_per_step(uint32_t rate)
  104. {
  105. /*
  106. The precise calculation we'd want to do is
  107. (rate / 1000) * to_approximate_msec(TICKS_PER_STEP). But to minimize
  108. rounding error, we do it this way instead, and divide last.
  109. */
  110. uint64_t units = (uint64_t) rate * TICKS_PER_STEP;
  111. uint32_t val = (uint32_t)
  112. (monotime_coarse_stamp_units_to_approx_msec(units) / 1000);
  113. return val ? val : 1;
  114. }
  115. /**
  116. * Initialize a token bucket in *<b>bucket</b>, set up to allow <b>rate</b>
  117. * bytes per second, with a maximum burst of <b>burst</b> bytes. The bucket
  118. * is created such that <b>now_ts</b> is the current timestamp. The bucket
  119. * starts out full.
  120. */
  121. void
  122. token_bucket_rw_init(token_bucket_rw_t *bucket,
  123. uint32_t rate,
  124. uint32_t burst,
  125. uint32_t now_ts)
  126. {
  127. memset(bucket, 0, sizeof(token_bucket_rw_t));
  128. token_bucket_rw_adjust(bucket, rate, burst);
  129. token_bucket_rw_reset(bucket, now_ts);
  130. }
  131. /**
  132. * Change the configured rate (in bytes per second) and burst (in bytes)
  133. * for the token bucket in *<b>bucket</b>.
  134. */
  135. void
  136. token_bucket_rw_adjust(token_bucket_rw_t *bucket,
  137. uint32_t rate,
  138. uint32_t burst)
  139. {
  140. token_bucket_cfg_init(&bucket->cfg,
  141. rate_per_sec_to_rate_per_step(rate),
  142. burst);
  143. token_bucket_raw_adjust(&bucket->read_bucket, &bucket->cfg);
  144. token_bucket_raw_adjust(&bucket->write_bucket, &bucket->cfg);
  145. }
  146. /**
  147. * Reset <b>bucket</b> to be full, as of timestamp <b>now_ts</b>.
  148. */
  149. void
  150. token_bucket_rw_reset(token_bucket_rw_t *bucket,
  151. uint32_t now_ts)
  152. {
  153. token_bucket_raw_reset(&bucket->read_bucket, &bucket->cfg);
  154. token_bucket_raw_reset(&bucket->write_bucket, &bucket->cfg);
  155. bucket->last_refilled_at_timestamp = now_ts;
  156. }
  157. /**
  158. * Refill <b>bucket</b> as appropriate, given that the current timestamp
  159. * is <b>now_ts</b>.
  160. *
  161. * Return a bitmask containing TB_READ iff read bucket was empty and became
  162. * nonempty, and TB_WRITE iff the write bucket was empty and became nonempty.
  163. */
  164. int
  165. token_bucket_rw_refill(token_bucket_rw_t *bucket,
  166. uint32_t now_ts)
  167. {
  168. const uint32_t elapsed_ticks =
  169. (now_ts - bucket->last_refilled_at_timestamp);
  170. if (elapsed_ticks > UINT32_MAX-(300*1000)) {
  171. /* Either about 48 days have passed since the last refill, or the
  172. * monotonic clock has somehow moved backwards. (We're looking at you,
  173. * Windows.). We accept up to a 5 minute jump backwards as
  174. * "unremarkable".
  175. */
  176. return 0;
  177. }
  178. const uint32_t elapsed_steps = elapsed_ticks / TICKS_PER_STEP;
  179. if (!elapsed_steps) {
  180. /* Note that if less than one whole step elapsed, we don't advance the
  181. * time in last_refilled_at. That's intentional: we want to make sure
  182. * that we add some bytes to it eventually. */
  183. return 0;
  184. }
  185. int flags = 0;
  186. if (token_bucket_raw_refill_steps(&bucket->read_bucket,
  187. &bucket->cfg, elapsed_steps))
  188. flags |= TB_READ;
  189. if (token_bucket_raw_refill_steps(&bucket->write_bucket,
  190. &bucket->cfg, elapsed_steps))
  191. flags |= TB_WRITE;
  192. bucket->last_refilled_at_timestamp = now_ts;
  193. return flags;
  194. }
  195. /**
  196. * Decrement the read token bucket in <b>bucket</b> by <b>n</b> bytes.
  197. *
  198. * Return true if the bucket was nonempty and became empty; return false
  199. * otherwise.
  200. */
  201. int
  202. token_bucket_rw_dec_read(token_bucket_rw_t *bucket,
  203. ssize_t n)
  204. {
  205. return token_bucket_raw_dec(&bucket->read_bucket, n);
  206. }
  207. /**
  208. * Decrement the write token bucket in <b>bucket</b> by <b>n</b> bytes.
  209. *
  210. * Return true if the bucket was nonempty and became empty; return false
  211. * otherwise.
  212. */
  213. int
  214. token_bucket_rw_dec_write(token_bucket_rw_t *bucket,
  215. ssize_t n)
  216. {
  217. return token_bucket_raw_dec(&bucket->write_bucket, n);
  218. }
  219. /**
  220. * As token_bucket_rw_dec_read and token_bucket_rw_dec_write, in a single
  221. * operation. Return a bitmask of TB_READ and TB_WRITE to indicate
  222. * which buckets became empty.
  223. */
  224. int
  225. token_bucket_rw_dec(token_bucket_rw_t *bucket,
  226. ssize_t n_read, ssize_t n_written)
  227. {
  228. int flags = 0;
  229. if (token_bucket_rw_dec_read(bucket, n_read))
  230. flags |= TB_READ;
  231. if (token_bucket_rw_dec_write(bucket, n_written))
  232. flags |= TB_WRITE;
  233. return flags;
  234. }