1 /* Copyright (c) 2023, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
5 * \file conflux_params.h
6 * \brief Header file for conflux_params.c.
9 #include "core/or/or.h"
11 #include "app/config/config.h"
13 #include "core/or/conflux_params.h"
14 #include "core/or/congestion_control_common.h"
15 #include "core/or/circuitlist.h"
17 #include "feature/nodelist/networkstatus.h"
18 #include "feature/nodelist/networkstatus_st.h"
19 #include "feature/nodelist/routerstatus_st.h"
20 #include "feature/relay/routermode.h"
22 #include "core/or/origin_circuit_st.h"
25 * Consensus parameters defaults, minimums and maximums.
28 /* For "cfx_enabled". */
29 #define CONFLUX_ENABLED_MIN (0)
30 #define CONFLUX_ENABLED_MAX (1)
31 #define CONFLUX_ENABLED_DEFAULT (1)
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)
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)
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)
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)
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)
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)
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
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
75 * Cached consensus parameters.
78 /* Indicate if conflux is enabled or disabled. */
79 static bool conflux_enabled
= CONFLUX_ENABLED_DEFAULT
;
80 /* Maximum number of linked set we are allowed to have (even if in use). */
81 static uint8_t max_linked_set
= MAX_LINKED_SET_DEFAULT
;
82 /* Maximum number of pre built set. */
83 static uint8_t max_prebuilt_set
= MAX_PREBUILT_SET_DEFAULT
;
84 /* Maximum number of unlinked leg retry that is how many times are we allowed
85 * to retry a leg until it successfully links. */
86 STATIC
uint32_t max_unlinked_leg_retry
= MAX_UNLINKED_LEG_RETRY_DEFAULT
;
87 /* Number of legs per set. */
88 static uint8_t num_legs_set
= NUM_LEGS_SET_DEFAULT
;
89 /* Maximum number of legs per set allowed at exits */
90 static uint8_t max_legs_set
= MAX_LEGS_SET_DEFAULT
;
91 /* The low Exit relay threshold, as a ratio between 0 and 1, used as a limit to
92 * decide the amount of pre-built set we build depending on how many Exit relay
93 * supports conflux in our current consensus. */
94 static double low_exit_threshold_ratio
=
95 LOW_EXIT_THRESHOLD_DEFAULT
/ (double)LOW_EXIT_THRESHOLD_MAX
;
97 static uint8_t cfx_drain_pct
= CFX_DRAIN_PCT_DFLT
;
98 static uint8_t cfx_send_pct
= CFX_SEND_PCT_DFLT
;
100 /* Ratio of Exit relays in our consensus supporting conflux. This is computed
101 * at every consensus and it is between 0 and 1. */
102 static double exit_conflux_ratio
= 0.0;
104 /** Sets num_conflux_exit with the latest count of Exits in the given consensus
105 * that supports Conflux. */
107 count_exit_with_conflux_support(const networkstatus_t
*ns
)
109 double supported
= 0.0;
112 if (!ns
|| smartlist_len(ns
->routerstatus_list
) == 0) {
116 SMARTLIST_FOREACH_BEGIN(ns
->routerstatus_list
, const routerstatus_t
*, rs
) {
117 if (!rs
->is_exit
|| rs
->is_bad_exit
) {
120 if (rs
->pv
.supports_conflux
) {
124 } SMARTLIST_FOREACH_END(rs
);
126 if (total_exits
> 0) {
128 supported
/ total_exits
;
130 exit_conflux_ratio
= 0.0;
133 log_info(LD_GENERAL
, "Consensus has %.2f %% Exit relays supporting Conflux",
134 exit_conflux_ratio
* 100.0);
138 * Return true iff conflux feature is enabled and usable for a given circuit.
140 * Circ may be NULL, in which case we only check the consensus and torrc. */
142 conflux_is_enabled(const circuit_t
*circ
)
144 const or_options_t
*opts
= get_options();
146 /* Conflux CAN NOT operate properly without congestion control and so
147 * automatically disabled conflux if we don't have CC enabled. */
148 if (!congestion_control_enabled()) {
153 /* If circuit is non-null, we need to check to see if congestion
154 * control was successfully negotiated. Conflux depends upon congestion
155 * control, and consensus checks are not enough because there can be a
156 * race between those checks and the consensus update to enable
157 * congestion control. This happens in Shadow, and at relay restart. */
158 if (CIRCUIT_IS_ORIGIN(circ
)) {
159 tor_assert(CONST_TO_ORIGIN_CIRCUIT(circ
)->cpath
);
160 tor_assert(CONST_TO_ORIGIN_CIRCUIT(circ
)->cpath
->prev
);
161 if (!CONST_TO_ORIGIN_CIRCUIT(circ
)->cpath
->prev
->ccontrol
)
169 /* For clients, this is mostly for sbws. For relays, this is an emergency
170 * emergency override, in case a bug is discovered by a relay operator
171 * and we can't set a consensus param fast enough. Basically gives them
172 * an option other than downgrading. */
173 if (opts
->ConfluxEnabled
!= -1) {
174 if (server_mode(opts
)) {
176 static ratelim_t rlimit
= RATELIM_INIT(60 * 60); /* Hourly */
177 if ((msg
= rate_limit_log(&rlimit
, time(NULL
)))) {
179 "This tor is a relay and ConfluxEnabled is set to 0. "
180 "We would ask you to please write to us on "
181 "tor-relays@lists.torproject.org or file a bug explaining "
182 "why you have disabled this option. Without news from you, "
183 "we might end up marking your relay as a BadExit.");
187 return opts
->ConfluxEnabled
;
190 return conflux_enabled
;
193 /** Return the maximum number of linked set we are allowed to have. */
195 conflux_params_get_max_linked_set(void)
197 return max_linked_set
;
200 /** Return the number of maximum pre built sets that is allowed to have. */
202 conflux_params_get_max_prebuilt(void)
204 /* Without any Exit supporting conflux, we won't be able to build a set. The
205 * float problem here is minimal because exit_conflux_ratio is either a flat
206 * 0 or else it means we do have at least an exit. */
207 if (exit_conflux_ratio
<= 0.0) {
211 /* Allow only 1 pre built set if we are lower than the low exit threshold
212 * parameter from the consensus. */
213 if (exit_conflux_ratio
< low_exit_threshold_ratio
) {
216 return max_prebuilt_set
;
219 /** Return the maximum number of retry we can do until a leg links. */
221 conflux_params_get_max_unlinked_leg_retry(void)
223 return max_unlinked_leg_retry
;
226 /** Return the number of legs per set. */
228 conflux_params_get_num_legs_set(void)
233 /** Return the maximum number of legs per set. */
235 conflux_params_get_max_legs_set(void)
240 /** Return the drain percent we must hit before switching */
242 conflux_params_get_drain_pct(void)
244 return cfx_drain_pct
;
247 /** Return the percent of the congestion window to send before switching. */
249 conflux_params_get_send_pct(void)
254 /** Update global conflux related consensus parameter values, every consensus
257 conflux_params_new_consensus(const networkstatus_t
*ns
)
259 /* Params used by conflux_pool.c */
261 networkstatus_get_param(ns
, "cfx_enabled",
262 CONFLUX_ENABLED_DEFAULT
,
263 CONFLUX_ENABLED_MIN
, CONFLUX_ENABLED_MAX
);
265 low_exit_threshold_ratio
=
266 networkstatus_get_param(ns
, "cfx_low_exit_threshold",
267 LOW_EXIT_THRESHOLD_DEFAULT
,
268 LOW_EXIT_THRESHOLD_MIN
, LOW_EXIT_THRESHOLD_MAX
) /
269 (double)LOW_EXIT_THRESHOLD_MAX
;
272 networkstatus_get_param(ns
, "cfx_max_linked_set",
273 MAX_LINKED_SET_DEFAULT
,
274 MAX_LINKED_SET_MIN
, MAX_LINKED_SET_MAX
);
277 networkstatus_get_param(ns
, "cfx_max_prebuilt_set",
278 MAX_PREBUILT_SET_DEFAULT
,
279 MAX_PREBUILT_SET_MIN
, MAX_PREBUILT_SET_MAX
);
281 max_unlinked_leg_retry
=
282 networkstatus_get_param(ns
, "cfx_max_unlinked_leg_retry",
283 MAX_UNLINKED_LEG_RETRY_DEFAULT
,
284 MAX_UNLINKED_LEG_RETRY_MIN
,
285 MAX_UNLINKED_LEG_RETRY_MAX
);
288 networkstatus_get_param(ns
, "cfx_num_legs_set",
289 NUM_LEGS_SET_DEFAULT
,
290 NUM_LEGS_SET_MIN
, NUM_LEGS_SET_MAX
);
293 networkstatus_get_param(ns
, "cfx_max_legs_set",
294 MAX_LEGS_SET_DEFAULT
,
295 MAX_LEGS_SET_MIN
, MAX_LEGS_SET_MAX
);
297 /* Params used by conflux.c */
298 cfx_send_pct
= networkstatus_get_param(ns
, "cfx_send_pct",
303 cfx_drain_pct
= networkstatus_get_param(ns
, "cfx_drain_pct",
308 count_exit_with_conflux_support(ns
);