token_bucket.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /* Copyright (c) 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. * The time units we use internally are based on "timestamp" units -- see
  12. * monotime_coarse_to_stamp() for a rationale.
  13. *
  14. * Token buckets may become negative.
  15. **/
  16. #define TOKEN_BUCKET_PRIVATE
  17. #include "token_bucket.h"
  18. #include "util_bug.h"
  19. /** Convert a rate in bytes per second to a rate in bytes per step */
  20. static uint32_t
  21. rate_per_sec_to_rate_per_step(uint32_t rate)
  22. {
  23. /*
  24. The precise calculation we'd want to do is
  25. (rate / 1000) * to_approximate_msec(TICKS_PER_STEP). But to minimize
  26. rounding error, we do it this way instead, and divide last.
  27. */
  28. return (uint32_t)
  29. monotime_coarse_stamp_units_to_approx_msec(rate*TICKS_PER_STEP)/1000;
  30. }
  31. /**
  32. * Initialize a token bucket in *<b>bucket</b>, set up to allow <b>rate</b>
  33. * bytes per second, with a maximum burst of <b>burst</b> bytes. The bucket
  34. * is created such that <b>now_ts</b> is the current timestamp. The bucket
  35. * starts out full.
  36. */
  37. void
  38. token_bucket_init(token_bucket_t *bucket,
  39. uint32_t rate,
  40. uint32_t burst,
  41. uint32_t now_ts)
  42. {
  43. memset(bucket, 0, sizeof(token_bucket_t));
  44. token_bucket_adjust(bucket, rate, burst);
  45. token_bucket_reset(bucket, now_ts);
  46. }
  47. /**
  48. * Change the configured rate (in bytes per second) and burst (in bytes)
  49. * for the token bucket in *<b>bucket</b>.
  50. */
  51. void
  52. token_bucket_adjust(token_bucket_t *bucket,
  53. uint32_t rate,
  54. uint32_t burst)
  55. {
  56. tor_assert_nonfatal(rate > 0);
  57. tor_assert_nonfatal(burst > 0);
  58. if (burst > TOKEN_BUCKET_MAX_BURST)
  59. burst = TOKEN_BUCKET_MAX_BURST;
  60. bucket->rate = rate_per_sec_to_rate_per_step(rate);
  61. bucket->burst = burst;
  62. bucket->read_bucket = MIN(bucket->read_bucket, (int32_t)burst);
  63. bucket->write_bucket = MIN(bucket->write_bucket, (int32_t)burst);
  64. }
  65. /**
  66. * Reset <b>bucket</b> to be full, as of timestamp <b>now_ts</b>.
  67. */
  68. void
  69. token_bucket_reset(token_bucket_t *bucket,
  70. uint32_t now_ts)
  71. {
  72. bucket->read_bucket = bucket->burst;
  73. bucket->write_bucket = bucket->burst;
  74. bucket->last_refilled_at_ts = now_ts;
  75. }
  76. /* Helper: see token_bucket_refill */
  77. static int
  78. refill_single_bucket(int32_t *bucketptr,
  79. const uint32_t rate,
  80. const int32_t burst,
  81. const uint32_t elapsed_steps)
  82. {
  83. const int was_empty = (*bucketptr <= 0);
  84. /* The casts here prevent an underflow.
  85. *
  86. * Note that even if the bucket value is negative, subtracting it from
  87. * "burst" will still produce a correct result. If this result is
  88. * ridiculously high, then the "elapsed_steps > gap / rate" check below
  89. * should catch it. */
  90. const size_t gap = ((size_t)burst) - ((size_t)*bucketptr);
  91. if (elapsed_steps > gap / rate) {
  92. *bucketptr = burst;
  93. } else {
  94. *bucketptr += rate * elapsed_steps;
  95. }
  96. return was_empty && *bucketptr > 0;
  97. }
  98. /**
  99. * Refill <b>bucket</b> as appropriate, given that the current timestamp
  100. * is <b>now_ts</b>.
  101. *
  102. * Return a bitmask containing TB_READ iff read bucket was empty and became
  103. * nonempty, and TB_WRITE iff the write bucket was empty and became nonempty.
  104. */
  105. int
  106. token_bucket_refill(token_bucket_t *bucket,
  107. uint32_t now_ts)
  108. {
  109. const uint32_t elapsed_ticks = (now_ts - bucket->last_refilled_at_ts);
  110. if (elapsed_ticks > UINT32_MAX-(300*1000)) {
  111. /* Either about 48 days have passed since the last refill, or the
  112. * monotonic clock has somehow moved backwards. (We're looking at you,
  113. * Windows.). We accept up to a 5 minute jump backwards as
  114. * "unremarkable".
  115. */
  116. return 0;
  117. }
  118. const uint32_t elapsed_steps = elapsed_ticks / TICKS_PER_STEP;
  119. if (!elapsed_steps) {
  120. /* Note that if less than one whole step elapsed, we don't advance the
  121. * time in last_refilled_at_ts. That's intentional: we want to make sure
  122. * that we add some bytes to it eventually. */
  123. return 0;
  124. }
  125. int flags = 0;
  126. if (refill_single_bucket(&bucket->read_bucket,
  127. bucket->rate, bucket->burst, elapsed_steps))
  128. flags |= TB_READ;
  129. if (refill_single_bucket(&bucket->write_bucket,
  130. bucket->rate, bucket->burst, elapsed_steps))
  131. flags |= TB_WRITE;
  132. bucket->last_refilled_at_ts = now_ts;
  133. return flags;
  134. }
  135. static int
  136. decrement_single_bucket(int32_t *bucketptr,
  137. ssize_t n)
  138. {
  139. if (BUG(n < 0))
  140. return 0;
  141. const int becomes_empty = *bucketptr > 0 && n >= *bucketptr;
  142. *bucketptr -= n;
  143. return becomes_empty;
  144. }
  145. /**
  146. * Decrement the read token bucket in <b>bucket</b> by <b>n</b> bytes.
  147. *
  148. * Return true if the bucket was nonempty and became empty; return false
  149. * otherwise.
  150. */
  151. int
  152. token_bucket_dec_read(token_bucket_t *bucket,
  153. ssize_t n)
  154. {
  155. return decrement_single_bucket(&bucket->read_bucket, n);
  156. }
  157. /**
  158. * Decrement the write token bucket in <b>bucket</b> by <b>n</b> bytes.
  159. *
  160. * Return true if the bucket was nonempty and became empty; return false
  161. * otherwise.
  162. */
  163. int
  164. token_bucket_dec_write(token_bucket_t *bucket,
  165. ssize_t n)
  166. {
  167. return decrement_single_bucket(&bucket->write_bucket, n);
  168. }
  169. /**
  170. * As token_bucket_dec_read and token_bucket_dec_write, in a single operation.
  171. */
  172. void
  173. token_bucket_dec(token_bucket_t *bucket,
  174. ssize_t n_read, ssize_t n_written)
  175. {
  176. token_bucket_dec_read(bucket, n_read);
  177. token_bucket_dec_read(bucket, n_written);
  178. }