Browse Source

token: Fix uint32_t to uint64_t conversion

Unfortunately, the units passed to
monotime_coarse_stamp_units_to_approx_msec() was always 0 due to a type
conversion.

Signed-off-by: David Goulet <dgoulet@torproject.org>
David Goulet 6 years ago
parent
commit
ae4e5b9824
3 changed files with 29 additions and 2 deletions
  1. 3 2
      src/common/token_bucket.c
  2. 3 0
      src/common/token_bucket.h
  3. 23 0
      src/test/test_bwmgt.c

+ 3 - 2
src/common/token_bucket.c

@@ -108,7 +108,7 @@ token_bucket_raw_dec(token_bucket_raw_t *bucket,
 }
 
 /** Convert a rate in bytes per second to a rate in bytes per step */
-static uint32_t
+STATIC uint32_t
 rate_per_sec_to_rate_per_step(uint32_t rate)
 {
   /*
@@ -117,8 +117,9 @@ rate_per_sec_to_rate_per_step(uint32_t rate)
     (rate / 1000) * to_approximate_msec(TICKS_PER_STEP).  But to minimize
     rounding error, we do it this way instead, and divide last.
   */
+  uint64_t units = (uint64_t) rate * TICKS_PER_STEP;
   uint32_t val = (uint32_t)
-    monotime_coarse_stamp_units_to_approx_msec(rate*TICKS_PER_STEP)/1000;
+    monotime_coarse_stamp_units_to_approx_msec(units) / 1000;
   return val ? val : 1;
 }
 

+ 3 - 0
src/common/token_bucket.h

@@ -10,6 +10,7 @@
 #define TOR_TOKEN_BUCKET_H
 
 #include "torint.h"
+#include "testsupport.h"
 
 /** Largest allowable burst value for a token buffer. */
 #define TOKEN_BUCKET_MAX_BURST INT32_MAX
@@ -109,6 +110,8 @@ token_bucket_rw_get_write(const token_bucket_rw_t *bucket)
  * a power of two if you can. */
 #define TICKS_PER_STEP 16
 
+STATIC uint32_t rate_per_sec_to_rate_per_step(uint32_t rate);
+
 #endif
 
 #endif /* TOR_TOKEN_BUCKET_H */

+ 23 - 0
src/test/test_bwmgt.c

@@ -16,6 +16,7 @@
 // an imaginary time, in timestamp units. Chosen so it will roll over.
 static const uint32_t START_TS = UINT32_MAX-10;
 static const int32_t KB = 1024;
+static const uint32_t GB = (U64_LITERAL(1) << 30);
 
 static void
 test_bwmgt_token_buf_init(void *arg)
@@ -192,6 +193,27 @@ test_bwmgt_token_buf_refill(void *arg)
   ;
 }
 
+/* Test some helper functions we use within the token bucket interface. */
+static void
+test_bwmgt_token_buf_helpers(void *arg)
+{
+  uint32_t ret;
+
+  (void) arg;
+
+  /* The returned value will be OS specific but in any case, it should be
+   * greater than 1 since we are passing 1GB/sec rate. */
+  ret = rate_per_sec_to_rate_per_step(1 * GB);
+  tt_u64_op(ret, OP_GT, 1);
+
+  /* We default to 1 in case rate is 0. */
+  ret = rate_per_sec_to_rate_per_step(0);
+  tt_u64_op(ret, OP_EQ, 1);
+
+ done:
+  ;
+}
+
 #define BWMGT(name)                                          \
   { #name, test_bwmgt_ ## name , 0, NULL, NULL }
 
@@ -200,6 +222,7 @@ struct testcase_t bwmgt_tests[] = {
   BWMGT(token_buf_adjust),
   BWMGT(token_buf_dec),
   BWMGT(token_buf_refill),
+  BWMGT(token_buf_helpers),
   END_OF_TESTCASES
 };