Use the new probability distribution code in WTF-PAD.

Co-authored-by: Mike Perry <mikeperry-git@torproject.org>
Co-authored-by: Taylor R Campbell <campbell+tor@mumble.net>
This commit is contained in:
George Kadianakis 2018-11-27 01:54:10 +02:00
parent 2ccf326837
commit dd04917851

View File

@ -1,8 +1,11 @@
/* Copyright (c) 2017 The Tor Project, Inc. */ /* Copyright (c) 2017 The Tor Project, Inc. */
/* See LICENSE for licensing information */ /* See LICENSE for licensing information */
#define CIRCUITPADDING_PRIVATE
#include <math.h> #include <math.h>
#include "lib/math/fp.h" #include "lib/math/fp.h"
#include "lib/math/prob_distr.h"
#include "core/or/or.h" #include "core/or/or.h"
#include "core/or/circuitpadding.h" #include "core/or/circuitpadding.h"
#include "core/or/circuitlist.h" #include "core/or/circuitlist.h"
@ -374,7 +377,7 @@ circpad_distribution_sample_iat_delay(const circpad_state_t *state,
* of tokens in each bin, and then a time value is chosen uniformly from * of tokens in each bin, and then a time value is chosen uniformly from
* that bin's [start,end) time range. * that bin's [start,end) time range.
*/ */
static circpad_delay_t STATIC circpad_delay_t
circpad_machine_sample_delay(circpad_machineinfo_t *mi) circpad_machine_sample_delay(circpad_machineinfo_t *mi)
{ {
const circpad_state_t *state = circpad_machine_current_state(mi); const circpad_state_t *state = circpad_machine_current_state(mi);
@ -487,57 +490,75 @@ circpad_machine_sample_delay(circpad_machineinfo_t *mi)
static double static double
circpad_distribution_sample(circpad_distribution_t dist) circpad_distribution_sample(circpad_distribution_t dist)
{ {
double p = 0; log_fn(LOG_DEBUG,LD_CIRC, "Sampling delay with distribution %d",
dist.type);
switch (dist.type) { switch (dist.type) {
case CIRCPAD_DIST_NONE: case CIRCPAD_DIST_NONE:
return 0; {
case CIRCPAD_DIST_UNIFORM: /* We should not get in here like this */
p = crypto_rand_double(); tor_assert_nonfatal_unreached();
// param2 is upper bound, param1 is lower
/* The subtraction is exact as long as param2 and param1 are less than
* 2**53. The multiplication is accurate as long as (param2 - param1)
* is less than 2**52. (And when they are large, the low bits aren't
* important.) The result covers the full range of outputs, as long as
* p has a resolution of 1/2**32 or greater. */
p *= (dist.param2 - dist.param1);
p += dist.param1;
return p;
case CIRCPAD_DIST_LOGISTIC:
p = crypto_rand_double();
/* https://en.wikipedia.org/wiki/Logistic_distribution#Quantile_function
* param1 is Mu, param2 is s. */
if (p <= 0.0) // Avoid log(0)
return 0; return 0;
return dist.param1 + dist.param2*tor_mathlog(p/(1.0-p)); }
case CIRCPAD_DIST_UNIFORM:
{
// param2 is upper bound, param1 is lower
const struct uniform my_uniform = {
.base = DIST_BASE(&uniform_ops),
.a = dist.param1,
.b = dist.param2,
};
return uniform_sample(&my_uniform.base);
}
case CIRCPAD_DIST_LOGISTIC:
{
/* param1 is Mu, param2 is sigma. */
const struct logistic my_logistic = {
.base = DIST_BASE(&uniform_ops),
.mu = dist.param1,
.sigma = dist.param2,
};
return logistic_sample(&my_logistic.base);
}
case CIRCPAD_DIST_LOG_LOGISTIC: case CIRCPAD_DIST_LOG_LOGISTIC:
p = crypto_rand_double(); {
/* https://en.wikipedia.org/wiki/Log-logistic_distribution#Quantiles /* param1 is Alpha, param2 is 1.0/Beta */
* param1 is Alpha, param2 is Beta */ const struct log_logistic my_log_logistic = {
return dist.param1 * pow(p/(1.0-p), 1.0/dist.param2); .base = DIST_BASE(&log_logistic_ops),
.alpha = dist.param1,
.beta = dist.param2,
};
return log_logistic_sample(&my_log_logistic.base);
}
case CIRCPAD_DIST_GEOMETRIC: case CIRCPAD_DIST_GEOMETRIC:
{ {
/* param1 is 'p' (success probability) */ /* param1 is 'p' (success probability) */
return geometric_sample(dist.param1); return geometric_sample(dist.param1);
} }
case CIRCPAD_DIST_WEIBULL: case CIRCPAD_DIST_WEIBULL:
p = crypto_rand_double(); {
/* https://en.wikipedia.org/wiki/Weibull_distribution \ /* param1 is k, param2 is Lambda */
* #Cumulative_distribution_function const struct weibull my_weibull = {
* param1 is k, param2 is Lambda */ .base = DIST_BASE(&weibull_ops),
return dist.param2*pow(-tor_mathlog(1.0-p), 1.0/dist.param1); .k = dist.param1,
.lambda = dist.param2,
};
return weibull_sample(&my_weibull.base);
}
case CIRCPAD_DIST_PARETO: case CIRCPAD_DIST_PARETO:
p = 1.0-crypto_rand_double(); // Pareto quantile needs (0,1] {
/* param1 is sigma, param2 is xi, no more params for mu so we use 0 */
/* https://en.wikipedia.org/wiki/Generalized_Pareto_distribution \ const struct genpareto my_genpareto = {
* #Generating_generalized_Pareto_random_variables .base = DIST_BASE(&weibull_ops),
* param1 is Sigma, param2 is Xi .mu = 0,
* Since it's piecewise, we must define it for 0 (or close to 0) */ .sigma = dist.param1,
if (fabs(dist.param2) <= 1e-22) .xi = dist.param2,
return -dist.param1*tor_mathlog(p); };
else return genpareto_sample(&my_genpareto.base);
return dist.param1*(pow(p, -dist.param2) - 1.0)/dist.param2; }
} }
tor_assert_nonfatal_unreached();
return 0; return 0;
} }
@ -1086,8 +1107,8 @@ circpad_machine_reached_padding_limit(circpad_machineinfo_t *mi)
* Returns 1 if we decide to transition states (due to infinity bin), * Returns 1 if we decide to transition states (due to infinity bin),
* 0 otherwise. * 0 otherwise.
*/ */
circpad_decision_t MOCK_IMPL(circpad_decision_t,
circpad_machine_schedule_padding(circpad_machineinfo_t *mi) circpad_machine_schedule_padding,(circpad_machineinfo_t *mi))
{ {
circpad_delay_t in_usec = 0; circpad_delay_t in_usec = 0;
struct timeval timeout; struct timeval timeout;