This is an automated email from the git hooks/post-receive script.
ahf pushed a commit to branch main in repository tor.
commit eac2bad86b6491b73b0086528b2b2cffe6c0d862 Author: Mike Perry mikeperry-git@torproject.org AuthorDate: Tue Mar 7 19:11:38 2023 +0000
Prop#329 params: Consensus parameter and torrc handling
Signed-off-by: David Goulet dgoulet@torproject.org --- doc/man/tor.1.txt | 6 + src/app/config/config.c | 1 + src/app/config/or_options_st.h | 4 + src/core/or/conflux_params.c | 281 +++++++++++++++++++++++++++++++++++ src/core/or/conflux_params.h | 29 ++++ src/feature/nodelist/networkstatus.c | 2 + 6 files changed, 323 insertions(+)
diff --git a/doc/man/tor.1.txt b/doc/man/tor.1.txt index e81b290b55..57992cd8d2 100644 --- a/doc/man/tor.1.txt +++ b/doc/man/tor.1.txt @@ -348,6 +348,12 @@ forward slash (/) in the configuration file and on the command line. forwards its traffic to it. It's the duty of that proxy to properly forward the traffic to the bridge. (Default: none)
+[[ConfluxEnabled]] **ConfluxEnabled** **0**|**1**|**auto**:: + If this option is set to 1, general purpose traffic will use Conflux which + is traffic splitting among multiple legs (circuits). Onion services are not + supported at the moment. Default value is set to "auto" meaning the + consensus is used to decide unless set. (Default: auto) + [[ConnLimit]] **ConnLimit** __NUM__:: The minimum number of file descriptors that must be available to the Tor process before it will start. Tor will ask the OS for as many file diff --git a/src/app/config/config.c b/src/app/config/config.c index 6b07d58240..66a8fe5853 100644 --- a/src/app/config/config.c +++ b/src/app/config/config.c @@ -377,6 +377,7 @@ static const config_var_t option_vars_[] = { V(ClientTransportPlugin, LINELIST, NULL), V(ClientUseIPv6, BOOL, "0"), V(ClientUseIPv4, BOOL, "1"), + V(ConfluxEnabled, AUTOBOOL, "auto"), V(ConnLimit, POSINT, "1000"), V(ConnDirectionStatistics, BOOL, "0"), V(ConstrainedSockets, BOOL, "0"), diff --git a/src/app/config/or_options_st.h b/src/app/config/or_options_st.h index 0811af1388..056aa3b776 100644 --- a/src/app/config/or_options_st.h +++ b/src/app/config/or_options_st.h @@ -723,6 +723,10 @@ struct or_options_t { * accessing this value directly. */ int ClientPreferIPv6DirPort;
+ /** If true, the tor client will use conflux for its general purpose + * circuits which excludes onion service traffic. */ + int ConfluxEnabled; + /** The length of time that we think a consensus should be fresh. */ int V3AuthVotingInterval; /** The length of time we think it will take to distribute votes. */ diff --git a/src/core/or/conflux_params.c b/src/core/or/conflux_params.c new file mode 100644 index 0000000000..f149e3356c --- /dev/null +++ b/src/core/or/conflux_params.c @@ -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); +} diff --git a/src/core/or/conflux_params.h b/src/core/or/conflux_params.h new file mode 100644 index 0000000000..22c3e4ad1f --- /dev/null +++ b/src/core/or/conflux_params.h @@ -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 */ + diff --git a/src/feature/nodelist/networkstatus.c b/src/feature/nodelist/networkstatus.c index b994cfabc4..f14034c2b7 100644 --- a/src/feature/nodelist/networkstatus.c +++ b/src/feature/nodelist/networkstatus.c @@ -51,6 +51,7 @@ #include "core/or/circuitmux.h" #include "core/or/circuitmux_ewma.h" #include "core/or/circuitstats.h" +#include "core/or/conflux_params.h" #include "core/or/connection_edge.h" #include "core/or/connection_or.h" #include "core/or/dos.h" @@ -1711,6 +1712,7 @@ notify_after_networkstatus_changes(void) flow_control_new_consensus_params(c); hs_service_new_consensus_params(c); dns_new_consensus_params(c); + conflux_params_new_consensus(c);
/* Maintenance of our L2 guard list */ maintain_layer2_guards();