mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
Prop#329 params: Consensus parameter and torrc handling
Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
@@ -0,0 +1,281 @@
|
||||
/* Copyright (c) 2023, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file conflux_params.h
|
||||
* \brief Header file for conflux_params.c.
|
||||
**/
|
||||
|
||||
#include "core/or/or.h"
|
||||
|
||||
#include "app/config/config.h"
|
||||
|
||||
#include "core/or/conflux_params.h"
|
||||
#include "core/or/congestion_control_common.h"
|
||||
#include "core/or/circuitlist.h"
|
||||
|
||||
#include "feature/nodelist/networkstatus.h"
|
||||
#include "feature/nodelist/networkstatus_st.h"
|
||||
#include "feature/nodelist/routerstatus_st.h"
|
||||
#include "feature/relay/routermode.h"
|
||||
|
||||
#include "core/or/origin_circuit_st.h"
|
||||
|
||||
/**
|
||||
* Consensus parameters defaults, minimums and maximums.
|
||||
*/
|
||||
|
||||
/* For "cfx_enabled". */
|
||||
#define CONFLUX_ENABLED_MIN (0)
|
||||
#define CONFLUX_ENABLED_MAX (1)
|
||||
#define CONFLUX_ENABLED_DEFAULT (1)
|
||||
|
||||
/* For "cfx_low_exit_threshold". This is a percentage scaled to 10000 so we can
|
||||
* support two decimal points. For example, 65.78% would be 6578. */
|
||||
#define LOW_EXIT_THRESHOLD_MIN (0)
|
||||
#define LOW_EXIT_THRESHOLD_MAX (10000)
|
||||
#define LOW_EXIT_THRESHOLD_DEFAULT (6000)
|
||||
|
||||
/* For "cfx_max_linked_set". */
|
||||
#define MAX_LINKED_SET_MIN (0)
|
||||
#define MAX_LINKED_SET_MAX (UINT8_MAX)
|
||||
#define MAX_LINKED_SET_DEFAULT (10)
|
||||
|
||||
/* For "cfx_max_prebuilt_set". */
|
||||
#define MAX_PREBUILT_SET_MIN (0)
|
||||
#define MAX_PREBUILT_SET_MAX (UINT8_MAX)
|
||||
#define MAX_PREBUILT_SET_DEFAULT (3)
|
||||
|
||||
/* For "cfx_max_leg_retry". */
|
||||
#define MAX_UNLINKED_LEG_RETRY_DEFAULT (3)
|
||||
#define MAX_UNLINKED_LEG_RETRY_MIN (0)
|
||||
#define MAX_UNLINKED_LEG_RETRY_MAX (UINT8_MAX)
|
||||
|
||||
/* For "cfx_num_legs_set". */
|
||||
#define NUM_LEGS_SET_MIN (0)
|
||||
#define NUM_LEGS_SET_MAX (UINT8_MAX)
|
||||
#define NUM_LEGS_SET_DEFAULT (2)
|
||||
|
||||
/* For "cfx_send_pct". */
|
||||
#define CFX_SEND_PCT_MIN (0)
|
||||
#define CFX_SEND_PCT_MAX (255)
|
||||
#define CFX_SEND_PCT_DFLT 100
|
||||
|
||||
/* For "cfx_drain_pct". */
|
||||
#define CFX_DRAIN_PCT_MIN (0)
|
||||
#define CFX_DRAIN_PCT_MAX (255)
|
||||
#define CFX_DRAIN_PCT_DFLT 0
|
||||
|
||||
/*
|
||||
* Cached consensus parameters.
|
||||
*/
|
||||
|
||||
/* Indicate if conflux is enabled or disabled. */
|
||||
static bool conflux_enabled = CONFLUX_ENABLED_DEFAULT;
|
||||
/* Maximum number of linked set we are allowed to have (even if in use). */
|
||||
static uint8_t max_linked_set = MAX_LINKED_SET_DEFAULT;
|
||||
/* Maximum number of pre built set. */
|
||||
static uint8_t max_prebuilt_set = MAX_PREBUILT_SET_DEFAULT;
|
||||
/* Maximum number of unlinked leg retry that is how many times are we allowed
|
||||
* to retry a leg until it successfully links. */
|
||||
STATIC uint32_t max_unlinked_leg_retry = MAX_UNLINKED_LEG_RETRY_DEFAULT;
|
||||
/* Number of legs per set. */
|
||||
static uint8_t num_legs_set = NUM_LEGS_SET_DEFAULT;
|
||||
/* The low Exit relay threshold, as a ratio between 0 and 1, used as a limit to
|
||||
* decide the amount of pre-built set we build depending on how many Exit relay
|
||||
* supports conflux in our current consensus. */
|
||||
static double low_exit_threshold_ratio =
|
||||
LOW_EXIT_THRESHOLD_DEFAULT / (double)LOW_EXIT_THRESHOLD_MAX;
|
||||
|
||||
static uint8_t cfx_drain_pct = CFX_DRAIN_PCT_DFLT;
|
||||
static uint8_t cfx_send_pct = CFX_SEND_PCT_DFLT;
|
||||
|
||||
/* Ratio of Exit relays in our consensus supporting conflux. This is computed
|
||||
* at every consensus and it is between 0 and 1. */
|
||||
static double exit_conflux_ratio = 0.0;
|
||||
|
||||
/** Sets num_conflux_exit with the latest count of Exits in the given consensus
|
||||
* that supports Conflux. */
|
||||
static void
|
||||
count_exit_with_conflux_support(const networkstatus_t *ns)
|
||||
{
|
||||
double supported = 0.0;
|
||||
|
||||
if (!ns || smartlist_len(ns->routerstatus_list) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, const routerstatus_t *, rs) {
|
||||
if (rs->pv.supports_conflux) {
|
||||
supported++;
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(rs);
|
||||
|
||||
exit_conflux_ratio =
|
||||
supported / smartlist_len(ns->routerstatus_list);
|
||||
|
||||
log_info(LD_GENERAL, "Consensus has %.2f %% Exit relays supporting Conflux",
|
||||
exit_conflux_ratio * 100.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true iff conflux feature is enabled and usable for a given circuit.
|
||||
*
|
||||
* Circ may be NULL, in which case we only check the consensus and torrc. */
|
||||
bool
|
||||
conflux_is_enabled(const circuit_t *circ)
|
||||
{
|
||||
const or_options_t *opts = get_options();
|
||||
|
||||
/* Conflux CAN NOT operate properly without congestion control and so
|
||||
* automatically disabled conflux if we don't have CC enabled. */
|
||||
if (!congestion_control_enabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (circ) {
|
||||
/* If circuit is non-null, we need to check to see if congestion
|
||||
* control was successfully negotiated. Conflux depends upon congestion
|
||||
* control, and consensus checks are not enough because there can be a
|
||||
* race between those checks and the consensus update to enable
|
||||
* congestion control. This happens in Shadow, and at relay restart. */
|
||||
if (CIRCUIT_IS_ORIGIN(circ)) {
|
||||
tor_assert(CONST_TO_ORIGIN_CIRCUIT(circ)->cpath);
|
||||
tor_assert(CONST_TO_ORIGIN_CIRCUIT(circ)->cpath->prev);
|
||||
if (!CONST_TO_ORIGIN_CIRCUIT(circ)->cpath->prev->ccontrol)
|
||||
return false;
|
||||
} else {
|
||||
if (!circ->ccontrol)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* For clients, this is mostly for sbws. For relays, this is an emergency
|
||||
* emergency override, in case a bug is discovered by a relay operator
|
||||
* and we can't set a consensus param fast enough. Basically gives them
|
||||
* an option other than downgrading. */
|
||||
if (opts->ConfluxEnabled != -1) {
|
||||
if (server_mode(opts)) {
|
||||
char *msg;
|
||||
static ratelim_t rlimit = RATELIM_INIT(60 * 60); /* Hourly */
|
||||
if ((msg = rate_limit_log(&rlimit, time(NULL)))) {
|
||||
log_warn(LD_GENERAL,
|
||||
"This tor is a relay and ConfluxEnabled is set to 0. "
|
||||
"We would ask you to please write to us on "
|
||||
"tor-relay@lists.torproject.org or file a bug explaining "
|
||||
"why you have disabled this option. Without news from you, "
|
||||
"we might end up marking your relay as a BadExit.");
|
||||
tor_free(msg);
|
||||
}
|
||||
}
|
||||
return opts->ConfluxEnabled;
|
||||
}
|
||||
|
||||
return conflux_enabled;
|
||||
}
|
||||
|
||||
/** Return the maximum number of linked set we are allowed to have. */
|
||||
uint8_t
|
||||
conflux_params_get_max_linked_set(void)
|
||||
{
|
||||
return max_linked_set;
|
||||
}
|
||||
|
||||
/** Return the number of maximum pre built sets that is allowed to have. */
|
||||
uint8_t
|
||||
conflux_params_get_max_prebuilt(void)
|
||||
{
|
||||
/* Without any Exit supporting conflux, we won't be able to build a set. The
|
||||
* float problem here is minimal because exit_conflux_ratio is either a flat
|
||||
* 0 or else it means we do have at least an exit. */
|
||||
if (exit_conflux_ratio <= 0.0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Allow only 1 pre built set if we are lower than the low exit threshold
|
||||
* parameter from the consensus. */
|
||||
if (exit_conflux_ratio < low_exit_threshold_ratio) {
|
||||
return 1;
|
||||
}
|
||||
return max_prebuilt_set;
|
||||
}
|
||||
|
||||
/** Return the maximum number of retry we can do until a leg links. */
|
||||
uint8_t
|
||||
conflux_params_get_max_unlinked_leg_retry(void)
|
||||
{
|
||||
return max_unlinked_leg_retry;
|
||||
}
|
||||
|
||||
/** Return the number of legs per set. */
|
||||
uint8_t
|
||||
conflux_params_get_num_legs_set(void)
|
||||
{
|
||||
return num_legs_set;
|
||||
}
|
||||
|
||||
/** Return the drain percent we must hit before switching */
|
||||
uint8_t
|
||||
conflux_params_get_drain_pct(void)
|
||||
{
|
||||
return cfx_drain_pct;
|
||||
}
|
||||
|
||||
/** Return the percent of the congestion window to send before switching. */
|
||||
uint8_t
|
||||
conflux_params_get_send_pct(void)
|
||||
{
|
||||
return cfx_send_pct;
|
||||
}
|
||||
|
||||
/** Update global conflux related consensus parameter values, every consensus
|
||||
* update. */
|
||||
void
|
||||
conflux_params_new_consensus(const networkstatus_t *ns)
|
||||
{
|
||||
/* Params used by conflux_pool.c */
|
||||
conflux_enabled =
|
||||
networkstatus_get_param(ns, "cfx_enabled",
|
||||
CONFLUX_ENABLED_DEFAULT,
|
||||
CONFLUX_ENABLED_MIN, CONFLUX_ENABLED_MAX);
|
||||
|
||||
low_exit_threshold_ratio =
|
||||
networkstatus_get_param(ns, "cfx_low_exit_threshold",
|
||||
LOW_EXIT_THRESHOLD_DEFAULT,
|
||||
LOW_EXIT_THRESHOLD_MIN, LOW_EXIT_THRESHOLD_MAX) /
|
||||
(double)LOW_EXIT_THRESHOLD_MAX;
|
||||
|
||||
max_linked_set =
|
||||
networkstatus_get_param(ns, "cfx_max_linked_set",
|
||||
MAX_LINKED_SET_DEFAULT,
|
||||
MAX_LINKED_SET_MIN, MAX_LINKED_SET_MAX);
|
||||
|
||||
max_prebuilt_set =
|
||||
networkstatus_get_param(ns, "cfx_max_prebuilt_set",
|
||||
MAX_PREBUILT_SET_DEFAULT,
|
||||
MAX_PREBUILT_SET_MIN, MAX_PREBUILT_SET_MAX);
|
||||
|
||||
max_unlinked_leg_retry =
|
||||
networkstatus_get_param(ns, "cfx_max_unlinked_leg_retry",
|
||||
MAX_UNLINKED_LEG_RETRY_DEFAULT,
|
||||
MAX_UNLINKED_LEG_RETRY_MIN,
|
||||
MAX_UNLINKED_LEG_RETRY_MAX);
|
||||
|
||||
num_legs_set =
|
||||
networkstatus_get_param(ns, "cfx_num_legs_set",
|
||||
NUM_LEGS_SET_DEFAULT,
|
||||
NUM_LEGS_SET_MIN, NUM_LEGS_SET_MAX);
|
||||
|
||||
/* Params used by conflux.c */
|
||||
cfx_send_pct = networkstatus_get_param(ns, "cfx_send_pct",
|
||||
CFX_SEND_PCT_DFLT,
|
||||
CFX_SEND_PCT_MIN,
|
||||
CFX_SEND_PCT_MAX);
|
||||
|
||||
cfx_drain_pct = networkstatus_get_param(ns, "cfx_drain_pct",
|
||||
CFX_DRAIN_PCT_DFLT,
|
||||
CFX_DRAIN_PCT_MIN,
|
||||
CFX_DRAIN_PCT_MAX);
|
||||
|
||||
count_exit_with_conflux_support(ns);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/* Copyright (c) 2023, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file conflux_params.h
|
||||
* \brief Header file for conflux_params.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_CONFLUX_PARAMS_H
|
||||
#define TOR_CONFLUX_PARAMS_H
|
||||
|
||||
#include "core/or/or.h"
|
||||
|
||||
bool conflux_is_enabled(const struct circuit_t *circ);
|
||||
uint8_t conflux_params_get_max_linked_set(void);
|
||||
uint8_t conflux_params_get_max_prebuilt(void);
|
||||
uint8_t conflux_params_get_max_unlinked_leg_retry(void);
|
||||
uint8_t conflux_params_get_num_legs_set(void);
|
||||
uint8_t conflux_params_get_drain_pct(void);
|
||||
uint8_t conflux_params_get_send_pct(void);
|
||||
|
||||
void conflux_params_new_consensus(const networkstatus_t *ns);
|
||||
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
extern uint32_t max_unlinked_leg_retry;
|
||||
#endif
|
||||
|
||||
#endif /* TOR_CONFLUX_PARAMS_H */
|
||||
|
||||
Reference in New Issue
Block a user