Tor 0.4.9.3-alpha-dev
Loading...
Searching...
No Matches
conflux_params.c
1/* Copyright (c) 2023, The Tor Project, Inc. */
2/* See LICENSE for licensing information */
3
4/**
5 * \file conflux_params.h
6 * \brief Header file for conflux_params.c.
7 **/
8
9#include "core/or/or.h"
10
11#include "app/config/config.h"
12
15#include "core/or/circuitlist.h"
16
21
23
24/**
25 * Consensus parameters defaults, minimums and maximums.
26 */
27
28/* For "cfx_enabled". */
29#define CONFLUX_ENABLED_MIN (0)
30#define CONFLUX_ENABLED_MAX (1)
31#define CONFLUX_ENABLED_DEFAULT (1)
32
33/* For "cfx_low_exit_threshold". This is a percentage scaled to 10000 so we can
34 * support two decimal points. For example, 65.78% would be 6578. */
35#define LOW_EXIT_THRESHOLD_MIN (0)
36#define LOW_EXIT_THRESHOLD_MAX (10000)
37#define LOW_EXIT_THRESHOLD_DEFAULT (6000)
38
39/* For "cfx_max_linked_set". */
40#define MAX_LINKED_SET_MIN (0)
41#define MAX_LINKED_SET_MAX (UINT8_MAX)
42#define MAX_LINKED_SET_DEFAULT (10)
43
44/* For "cfx_max_prebuilt_set". */
45#define MAX_PREBUILT_SET_MIN (0)
46#define MAX_PREBUILT_SET_MAX (UINT8_MAX)
47#define MAX_PREBUILT_SET_DEFAULT (3)
48
49/* For "cfx_max_leg_retry". */
50#define MAX_UNLINKED_LEG_RETRY_DEFAULT (3)
51#define MAX_UNLINKED_LEG_RETRY_MIN (0)
52#define MAX_UNLINKED_LEG_RETRY_MAX (UINT8_MAX)
53
54/* For "cfx_num_legs_set". */
55#define NUM_LEGS_SET_MIN (0)
56#define NUM_LEGS_SET_MAX (UINT8_MAX)
57#define NUM_LEGS_SET_DEFAULT (2)
58
59/* For "cfx_max_legs_set" */
60#define MAX_LEGS_SET_MIN (3)
61#define MAX_LEGS_SET_MAX (UINT8_MAX)
62#define MAX_LEGS_SET_DEFAULT (8)
63
64/* For "cfx_send_pct". */
65#define CFX_SEND_PCT_MIN (0)
66#define CFX_SEND_PCT_MAX (255)
67#define CFX_SEND_PCT_DFLT 100
68
69/* For "cfx_drain_pct". */
70#define CFX_DRAIN_PCT_MIN (0)
71#define CFX_DRAIN_PCT_MAX (255)
72#define CFX_DRAIN_PCT_DFLT 0
73
74/* For "max_ooo_queue_bytes". */
75#define MAX_OOO_QUEUE_BYTES_MIN (0)
76#define MAX_OOO_QUEUE_BYTES_MAX (INT32_MAX)
77#define MAX_OOO_QUEUE_BYTES_DEFAULT MAX_OOO_QUEUE_BYTES_MAX
78
79/*
80 * Cached consensus parameters.
81 */
82
83/* Indicate if conflux is enabled or disabled. */
84static bool conflux_enabled = CONFLUX_ENABLED_DEFAULT;
85/* Maximum number of linked set we are allowed to have (even if in use). */
86static uint8_t max_linked_set = MAX_LINKED_SET_DEFAULT;
87/* Maximum number of pre built set. */
88static uint8_t max_prebuilt_set = MAX_PREBUILT_SET_DEFAULT;
89/* Maximum number of unlinked leg retry that is how many times are we allowed
90 * to retry a leg until it successfully links. */
91STATIC uint32_t max_unlinked_leg_retry = MAX_UNLINKED_LEG_RETRY_DEFAULT;
92/* Number of legs per set. */
93static uint8_t num_legs_set = NUM_LEGS_SET_DEFAULT;
94/* Maximum number of legs per set allowed at exits */
95static uint8_t max_legs_set = MAX_LEGS_SET_DEFAULT;
96/* The low Exit relay threshold, as a ratio between 0 and 1, used as a limit to
97 * decide the amount of pre-built set we build depending on how many Exit relay
98 * supports conflux in our current consensus. */
99static double low_exit_threshold_ratio =
100 LOW_EXIT_THRESHOLD_DEFAULT / (double)LOW_EXIT_THRESHOLD_MAX;
101
102static uint8_t cfx_drain_pct = CFX_DRAIN_PCT_DFLT;
103static uint8_t cfx_send_pct = CFX_SEND_PCT_DFLT;
104
105/* The maximum number of bytes allowed in a single OOO queue. Above this value,
106 * the conflux set is closed. */
107static uint32_t max_ooo_queue_bytes = MAX_OOO_QUEUE_BYTES_DEFAULT;
108
109/* Ratio of Exit relays in our consensus supporting conflux. This is computed
110 * at every consensus and it is between 0 and 1. */
111static double exit_conflux_ratio = 0.0;
112
113/** Sets num_conflux_exit with the latest count of Exits in the given consensus
114 * that supports Conflux. */
115static void
116count_exit_with_conflux_support(const networkstatus_t *ns)
117{
118 double supported = 0.0;
119 int total_exits = 0;
120
121 if (!ns || smartlist_len(ns->routerstatus_list) == 0) {
122 return;
123 }
124
126 if (!rs->is_exit || rs->is_bad_exit) {
127 continue;
128 }
129 if (rs->pv.supports_conflux) {
130 supported++;
131 }
132 total_exits++;
133 } SMARTLIST_FOREACH_END(rs);
134
135 if (total_exits > 0) {
136 exit_conflux_ratio =
137 supported / total_exits;
138 } else {
139 exit_conflux_ratio = 0.0;
140 }
141
142 log_info(LD_GENERAL, "Consensus has %.2f %% Exit relays supporting Conflux",
143 exit_conflux_ratio * 100.0);
144}
145
146/**
147 * Return true iff conflux feature is enabled and usable for a given circuit.
148 *
149 * Circ may be NULL, in which case we only check the consensus and torrc. */
150bool
151conflux_is_enabled(const circuit_t *circ)
152{
153 const or_options_t *opts = get_options();
154
155 /* Conflux CAN NOT operate properly without congestion control and so
156 * automatically disabled conflux if we don't have CC enabled. */
158 return false;
159 }
160
161 if (circ) {
162 /* If circuit is non-null, we need to check to see if congestion
163 * control was successfully negotiated. Conflux depends upon congestion
164 * control, and consensus checks are not enough because there can be a
165 * race between those checks and the consensus update to enable
166 * congestion control. This happens in Shadow, and at relay restart. */
167 if (CIRCUIT_IS_ORIGIN(circ)) {
168 tor_assert(CONST_TO_ORIGIN_CIRCUIT(circ)->cpath);
169 tor_assert(CONST_TO_ORIGIN_CIRCUIT(circ)->cpath->prev);
170 if (!CONST_TO_ORIGIN_CIRCUIT(circ)->cpath->prev->ccontrol)
171 return false;
172 } else {
173 if (!circ->ccontrol)
174 return false;
175 }
176 }
177
178 /* For clients, this is mostly for sbws. For relays, this is an emergency
179 * emergency override, in case a bug is discovered by a relay operator
180 * and we can't set a consensus param fast enough. Basically gives them
181 * an option other than downgrading. */
182 if (opts->ConfluxEnabled != -1) {
183 if (server_mode(opts)) {
184 char *msg;
185 static ratelim_t rlimit = RATELIM_INIT(60 * 60); /* Hourly */
186 if ((msg = rate_limit_log(&rlimit, time(NULL)))) {
187 log_warn(LD_GENERAL,
188 "This tor is a relay and ConfluxEnabled is set to 0. "
189 "We would ask you to please write to us on "
190 "tor-relays@lists.torproject.org or file a bug explaining "
191 "why you have disabled this option. Without news from you, "
192 "we might end up marking your relay as a BadExit.");
193 tor_free(msg);
194 }
195 }
196 return opts->ConfluxEnabled;
197 }
198
199 return conflux_enabled;
200}
201
202/** Return the maximum number of linked set we are allowed to have. */
203uint8_t
204conflux_params_get_max_linked_set(void)
205{
206 return max_linked_set;
207}
208
209/** Return the number of maximum pre built sets that is allowed to have. */
210uint8_t
211conflux_params_get_max_prebuilt(void)
212{
213 /* Without any Exit supporting conflux, we won't be able to build a set. The
214 * float problem here is minimal because exit_conflux_ratio is either a flat
215 * 0 or else it means we do have at least an exit. */
216 if (exit_conflux_ratio <= 0.0) {
217 return 0;
218 }
219
220 /* Allow only 1 pre built set if we are lower than the low exit threshold
221 * parameter from the consensus. */
222 if (exit_conflux_ratio < low_exit_threshold_ratio) {
223 return 1;
224 }
225 return max_prebuilt_set;
226}
227
228/** Return the maximum number of retry we can do until a leg links. */
229uint8_t
230conflux_params_get_max_unlinked_leg_retry(void)
231{
232 return max_unlinked_leg_retry;
233}
234
235/** Return the number of legs per set. */
236uint8_t
237conflux_params_get_num_legs_set(void)
238{
239 return num_legs_set;
240}
241
242/** Return the maximum number of legs per set. */
243uint8_t
244conflux_params_get_max_legs_set(void)
245{
246 return max_legs_set;
247}
248
249/** Return the drain percent we must hit before switching */
250uint8_t
251conflux_params_get_drain_pct(void)
252{
253 return cfx_drain_pct;
254}
255
256/** Return the percent of the congestion window to send before switching. */
257uint8_t
258conflux_params_get_send_pct(void)
259{
260 return cfx_send_pct;
261}
262
263/** Return maximum allowed bytes in a single OOO queue. */
264uint32_t
265conflux_params_get_max_oooq(void)
266{
267 return max_ooo_queue_bytes;
268}
269
270/** Update global conflux related consensus parameter values, every consensus
271 * update. */
272void
273conflux_params_new_consensus(const networkstatus_t *ns)
274{
275 /* Params used by conflux_pool.c */
276 conflux_enabled =
277 networkstatus_get_param(ns, "cfx_enabled",
278 CONFLUX_ENABLED_DEFAULT,
279 CONFLUX_ENABLED_MIN, CONFLUX_ENABLED_MAX);
280
281 low_exit_threshold_ratio =
282 networkstatus_get_param(ns, "cfx_low_exit_threshold",
283 LOW_EXIT_THRESHOLD_DEFAULT,
284 LOW_EXIT_THRESHOLD_MIN, LOW_EXIT_THRESHOLD_MAX) /
285 (double)LOW_EXIT_THRESHOLD_MAX;
286
287 max_linked_set =
288 networkstatus_get_param(ns, "cfx_max_linked_set",
289 MAX_LINKED_SET_DEFAULT,
290 MAX_LINKED_SET_MIN, MAX_LINKED_SET_MAX);
291
292 max_prebuilt_set =
293 networkstatus_get_param(ns, "cfx_max_prebuilt_set",
294 MAX_PREBUILT_SET_DEFAULT,
295 MAX_PREBUILT_SET_MIN, MAX_PREBUILT_SET_MAX);
296
297 max_unlinked_leg_retry =
298 networkstatus_get_param(ns, "cfx_max_unlinked_leg_retry",
299 MAX_UNLINKED_LEG_RETRY_DEFAULT,
300 MAX_UNLINKED_LEG_RETRY_MIN,
301 MAX_UNLINKED_LEG_RETRY_MAX);
302
303 num_legs_set =
304 networkstatus_get_param(ns, "cfx_num_legs_set",
305 NUM_LEGS_SET_DEFAULT,
306 NUM_LEGS_SET_MIN, NUM_LEGS_SET_MAX);
307
308 max_legs_set =
309 networkstatus_get_param(ns, "cfx_max_legs_set",
310 MAX_LEGS_SET_DEFAULT,
311 MAX_LEGS_SET_MIN, MAX_LEGS_SET_MAX);
312
313 /* Params used by conflux.c */
314 cfx_send_pct = networkstatus_get_param(ns, "cfx_send_pct",
315 CFX_SEND_PCT_DFLT,
316 CFX_SEND_PCT_MIN,
317 CFX_SEND_PCT_MAX);
318
319 cfx_drain_pct = networkstatus_get_param(ns, "cfx_drain_pct",
320 CFX_DRAIN_PCT_DFLT,
321 CFX_DRAIN_PCT_MIN,
322 CFX_DRAIN_PCT_MAX);
323
324 max_ooo_queue_bytes = networkstatus_get_param(ns, "cfx_max_oooq_bytes",
325 MAX_OOO_QUEUE_BYTES_DEFAULT,
326 MAX_OOO_QUEUE_BYTES_MIN,
327 MAX_OOO_QUEUE_BYTES_MAX);
328
329 count_exit_with_conflux_support(ns);
330}
Header file for circuitlist.c.
#define CIRCUIT_IS_ORIGIN(c)
const or_options_t * get_options(void)
Definition config.c:948
Header file for config.c.
Header file for conflux_params.c.
bool congestion_control_enabled(void)
Public APIs for congestion control.
#define LD_GENERAL
Definition log.h:62
#define tor_free(p)
Definition malloc.h:56
int32_t networkstatus_get_param(const networkstatus_t *ns, const char *param_name, int32_t default_val, int32_t min_val, int32_t max_val)
Header file for networkstatus.c.
Networkstatus consensus/vote structure.
Master header file for Tor-specific functionality.
Origin circuit structure.
char * rate_limit_log(ratelim_t *lim, time_t now)
Definition ratelim.c:42
Header file for routermode.c.
Routerstatus (consensus entry) structure.
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
struct congestion_control_t * ccontrol
Definition circuit_st.h:260
smartlist_t * routerstatus_list
#define STATIC
Definition testsupport.h:32
#define tor_assert(expr)
Definition util_bug.h:103