tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

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 }