conflux_params.c (10372B)
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 13 #include "core/or/conflux_params.h" 14 #include "core/or/congestion_control_common.h" 15 #include "core/or/circuitlist.h" 16 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" 21 22 #include "core/or/origin_circuit_st.h" 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. */ 84 static bool conflux_enabled = CONFLUX_ENABLED_DEFAULT; 85 /* Maximum number of linked set we are allowed to have (even if in use). */ 86 static uint8_t max_linked_set = MAX_LINKED_SET_DEFAULT; 87 /* Maximum number of pre built set. */ 88 static 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. */ 91 STATIC uint32_t max_unlinked_leg_retry = MAX_UNLINKED_LEG_RETRY_DEFAULT; 92 /* Number of legs per set. */ 93 static uint8_t num_legs_set = NUM_LEGS_SET_DEFAULT; 94 /* Maximum number of legs per set allowed at exits */ 95 static 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. */ 99 static double low_exit_threshold_ratio = 100 LOW_EXIT_THRESHOLD_DEFAULT / (double)LOW_EXIT_THRESHOLD_MAX; 101 102 static uint8_t cfx_drain_pct = CFX_DRAIN_PCT_DFLT; 103 static 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. */ 107 static 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. */ 111 static 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. */ 115 static void 116 count_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 125 SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, const routerstatus_t *, rs) { 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. */ 150 bool 151 conflux_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. */ 157 if (!congestion_control_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. */ 203 uint8_t 204 conflux_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. */ 210 uint8_t 211 conflux_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. */ 229 uint8_t 230 conflux_params_get_max_unlinked_leg_retry(void) 231 { 232 return max_unlinked_leg_retry; 233 } 234 235 /** Return the number of legs per set. */ 236 uint8_t 237 conflux_params_get_num_legs_set(void) 238 { 239 return num_legs_set; 240 } 241 242 /** Return the maximum number of legs per set. */ 243 uint8_t 244 conflux_params_get_max_legs_set(void) 245 { 246 return max_legs_set; 247 } 248 249 /** Return the drain percent we must hit before switching */ 250 uint8_t 251 conflux_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. */ 257 uint8_t 258 conflux_params_get_send_pct(void) 259 { 260 return cfx_send_pct; 261 } 262 263 /** Return maximum allowed bytes in a single OOO queue. */ 264 uint32_t 265 conflux_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. */ 272 void 273 conflux_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 }