mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
Move exponential-random backoff computation out of download_status_schedule_get_delay() into separate function, per code review
This commit is contained in:
+50
-29
@@ -3784,6 +3784,52 @@ find_dl_min_and_max_delay(download_status_t *dls, const or_options_t *options,
|
||||
*max = *((int *)((smartlist_get(schedule, smartlist_len(schedule) - 1))));
|
||||
}
|
||||
|
||||
/** Advance one delay step. The algorithm is to use the previous delay to
|
||||
* compute an increment. Consuming one byte of entropy per step, we use 7
|
||||
* bits to construct an increment between 0 and (127/128)*delay by adding
|
||||
* right-shifted copies of delay, controlled by each bit. Then, to prevent
|
||||
* getting stuck at zero if we start from zero, we use one last bit to add
|
||||
* 1 with probability 50%. Finally, we add the increment to the original
|
||||
* delay, clamp the value <= max_delay, and return it.
|
||||
*/
|
||||
STATIC int
|
||||
next_random_exponential_delay(int delay, int max_delay)
|
||||
{
|
||||
int delay_increment, i;
|
||||
uint8_t entropy;
|
||||
|
||||
/*
|
||||
* Backoff step: we want to multiply by something ~1.5, and then add
|
||||
* 1 with non-zero probability so we can't get stuck at zero even if
|
||||
* we start out with zero delay. To do this, pick a uint8_t of
|
||||
* entropy in the range [0,255], and use it to construct an
|
||||
* increment.
|
||||
*/
|
||||
delay_increment = 0;
|
||||
/* Get a byte of entropy */
|
||||
crypto_rand((char *)(&entropy), sizeof(entropy));
|
||||
/* Clamp it just to be sure */
|
||||
entropy &= 0xff;
|
||||
/* If we have non-zero delay; otherwise this is a no-op */
|
||||
if (delay > 0) {
|
||||
/* Use the low 7 bits for the increment */
|
||||
for (i = 0; i < 7; ++i) {
|
||||
if (entropy & (0x1 << i)) delay_increment += (delay >> (i + 1));
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Using the remaining bit of entropy, add 1 with probability 50% so
|
||||
* we can't get stuck at 0
|
||||
*/
|
||||
if (entropy & 0x80) delay_increment += 1;
|
||||
/* Increment delay, make sure to saturate if we would wrap around */
|
||||
if (delay_increment < max_delay - delay) delay += delay_increment;
|
||||
else delay = max_delay;
|
||||
|
||||
/* Return the updated delay */
|
||||
return delay;
|
||||
}
|
||||
|
||||
/** Find the current delay for dls based on schedule or min_delay/
|
||||
* max_delay if we're using exponential backoff. If dls->backoff is
|
||||
* DL_SCHED_RANDOM_EXPONENTIAL, we must have 0 <= min_delay <= max_delay <=
|
||||
@@ -3807,12 +3853,10 @@ download_status_schedule_get_delay(download_status_t *dls,
|
||||
max_delay <= INT_MAX));
|
||||
|
||||
int delay = INT_MAX;
|
||||
int delay_increment, i;
|
||||
uint8_t dls_schedule_position = (dls->increment_on
|
||||
== DL_SCHED_INCREMENT_ATTEMPT
|
||||
? dls->n_download_attempts
|
||||
: dls->n_download_failures);
|
||||
uint8_t entropy;
|
||||
|
||||
if (dls->backoff == DL_SCHED_DETERMINISTIC) {
|
||||
if (dls_schedule_position < smartlist_len(schedule))
|
||||
@@ -3832,36 +3876,13 @@ download_status_schedule_get_delay(download_status_t *dls,
|
||||
delay = dls->last_delay_used;
|
||||
|
||||
while (dls->last_backoff_position < dls_schedule_position) {
|
||||
/*
|
||||
* Backoff step: we want to multiply by something ~1.5, and then add
|
||||
* 1 with non-zero probability so we can't get stuck at zero even if
|
||||
* we start out with zero delay. To do this, pick a uint8_t of
|
||||
* entropy in the range [0,255], and use it to construct an
|
||||
* increment.
|
||||
*/
|
||||
delay_increment = 0;
|
||||
/* Get a byte of entropy */
|
||||
crypto_rand((char *)(&entropy), sizeof(entropy));
|
||||
/* Clamp it just to be sure */
|
||||
entropy &= 0xff;
|
||||
/* If we have non-zero delay; otherwise this is a no-op */
|
||||
if (delay > 0) {
|
||||
/* Use the low 7 bits for the increment */
|
||||
for (i = 0; i < 7; ++i) {
|
||||
if (entropy & (0x1 << i)) delay_increment += (delay >> (i + 1));
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Using the remaining bit of entropy, add 1 with probability 50% so
|
||||
* we can't get stuck at 0
|
||||
*/
|
||||
if (entropy & 0x80) delay_increment += 1;
|
||||
/* Increment delay, make sure to saturate if we would wrap around */
|
||||
if (delay_increment < max_delay - delay) delay += delay_increment;
|
||||
else delay = max_delay;
|
||||
/* Do one increment step */
|
||||
delay = next_random_exponential_delay(delay, max_delay);
|
||||
/* Update our position */
|
||||
++(dls->last_backoff_position);
|
||||
}
|
||||
} else {
|
||||
/* If we're just starting out, use the minimum delay */
|
||||
delay = min_delay;
|
||||
}
|
||||
|
||||
|
||||
@@ -158,6 +158,8 @@ STATIC const smartlist_t *find_dl_schedule(download_status_t *dls,
|
||||
STATIC void find_dl_min_and_max_delay(download_status_t *dls,
|
||||
const or_options_t *options,
|
||||
int *min, int *max);
|
||||
STATIC int next_random_exponential_delay(int delay, int max_delay);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user