|
@@ -24,6 +24,23 @@
|
|
|
|
|
|
static void nodelist_drop_node(node_t *node, int remove_from_ht);
|
|
|
static void node_free(node_t *node);
|
|
|
+
|
|
|
+/** count_usable_descriptors counts descriptors with these flag(s)
|
|
|
+ */
|
|
|
+typedef enum {
|
|
|
+ /* All descriptors regardless of flags */
|
|
|
+ USABLE_DESCRIPTOR_ALL = 0,
|
|
|
+ /* Only descriptors with the Exit flag */
|
|
|
+ USABLE_DESCRIPTOR_EXIT_ONLY = 1
|
|
|
+} usable_descriptor_t;
|
|
|
+static void count_usable_descriptors(int *num_present,
|
|
|
+ int *num_usable,
|
|
|
+ smartlist_t *descs_out,
|
|
|
+ const networkstatus_t *consensus,
|
|
|
+ const or_options_t *options,
|
|
|
+ time_t now,
|
|
|
+ routerset_t *in_set,
|
|
|
+ usable_descriptor_t exit_only);
|
|
|
static void update_router_have_minimum_dir_info(void);
|
|
|
static double get_frac_paths_needed_for_circs(const or_options_t *options,
|
|
|
const networkstatus_t *ns);
|
|
@@ -1313,20 +1330,23 @@ get_dir_info_status_string(void)
|
|
|
/** Iterate over the servers listed in <b>consensus</b>, and count how many of
|
|
|
* them seem like ones we'd use, and how many of <em>those</em> we have
|
|
|
* descriptors for. Store the former in *<b>num_usable</b> and the latter in
|
|
|
- * *<b>num_present</b>. If <b>in_set</b> is non-NULL, only consider those
|
|
|
- * routers in <b>in_set</b>. If <b>exit_only</b> is true, only consider nodes
|
|
|
- * with the Exit flag. If *descs_out is present, add a node_t for each
|
|
|
- * usable descriptor to it.
|
|
|
+ * *<b>num_present</b>.
|
|
|
+ * If <b>in_set</b> is non-NULL, only consider those routers in <b>in_set</b>.
|
|
|
+ * If <b>exit_only</b> is USABLE_DESCRIPTOR_EXIT_ONLY, only consider nodes
|
|
|
+ * with the Exit flag.
|
|
|
+ * If *<b>descs_out</b> is present, add a node_t for each usable descriptor
|
|
|
+ * to it.
|
|
|
*/
|
|
|
static void
|
|
|
count_usable_descriptors(int *num_present, int *num_usable,
|
|
|
smartlist_t *descs_out,
|
|
|
const networkstatus_t *consensus,
|
|
|
const or_options_t *options, time_t now,
|
|
|
- routerset_t *in_set, int exit_only)
|
|
|
+ routerset_t *in_set,
|
|
|
+ usable_descriptor_t exit_only)
|
|
|
{
|
|
|
const int md = (consensus->flavor == FLAV_MICRODESC);
|
|
|
- *num_present = 0, *num_usable=0;
|
|
|
+ *num_present = 0, *num_usable = 0;
|
|
|
|
|
|
SMARTLIST_FOREACH_BEGIN(consensus->routerstatus_list, routerstatus_t *, rs)
|
|
|
{
|
|
@@ -1334,7 +1354,7 @@ count_usable_descriptors(int *num_present, int *num_usable,
|
|
|
if (!node)
|
|
|
continue; /* This would be a bug: every entry in the consensus is
|
|
|
* supposed to have a node. */
|
|
|
- if (exit_only && ! rs->is_exit)
|
|
|
+ if (exit_only == USABLE_DESCRIPTOR_EXIT_ONLY && ! rs->is_exit)
|
|
|
continue;
|
|
|
if (in_set && ! routerset_contains_routerstatus(in_set, rs, -1))
|
|
|
continue;
|
|
@@ -1358,7 +1378,8 @@ count_usable_descriptors(int *num_present, int *num_usable,
|
|
|
|
|
|
log_debug(LD_DIR, "%d usable, %d present (%s%s).",
|
|
|
*num_usable, *num_present,
|
|
|
- md ? "microdesc" : "desc", exit_only ? " exits" : "s");
|
|
|
+ md ? "microdesc" : "desc",
|
|
|
+ exit_only == USABLE_DESCRIPTOR_EXIT_ONLY ? " exits" : "s");
|
|
|
}
|
|
|
|
|
|
/** Return an estimate of which fraction of usable paths through the Tor
|
|
@@ -1379,10 +1400,11 @@ compute_frac_paths_available(const networkstatus_t *consensus,
|
|
|
const int authdir = authdir_mode_v3(options);
|
|
|
|
|
|
count_usable_descriptors(num_present_out, num_usable_out,
|
|
|
- mid, consensus, options, now, NULL, 0);
|
|
|
+ mid, consensus, options, now, NULL,
|
|
|
+ USABLE_DESCRIPTOR_ALL);
|
|
|
if (options->EntryNodes) {
|
|
|
count_usable_descriptors(&np, &nu, guards, consensus, options, now,
|
|
|
- options->EntryNodes, 0);
|
|
|
+ options->EntryNodes, USABLE_DESCRIPTOR_ALL);
|
|
|
} else {
|
|
|
SMARTLIST_FOREACH(mid, const node_t *, node, {
|
|
|
if (authdir) {
|
|
@@ -1397,20 +1419,49 @@ compute_frac_paths_available(const networkstatus_t *consensus,
|
|
|
|
|
|
/* All nodes with exit flag */
|
|
|
count_usable_descriptors(&np, &nu, exits, consensus, options, now,
|
|
|
- NULL, 1);
|
|
|
+ NULL, USABLE_DESCRIPTOR_EXIT_ONLY);
|
|
|
+ log_debug(LD_NET,
|
|
|
+ "%s: %d present, %d usable",
|
|
|
+ "exits",
|
|
|
+ np,
|
|
|
+ nu);
|
|
|
+
|
|
|
/* All nodes with exit flag in ExitNodes option */
|
|
|
count_usable_descriptors(&np, &nu, myexits, consensus, options, now,
|
|
|
- options->ExitNodes, 1);
|
|
|
+ options->ExitNodes, USABLE_DESCRIPTOR_EXIT_ONLY);
|
|
|
+ log_debug(LD_NET,
|
|
|
+ "%s: %d present, %d usable",
|
|
|
+ "myexits",
|
|
|
+ np,
|
|
|
+ nu);
|
|
|
+
|
|
|
/* Now compute the nodes in the ExitNodes option where which we don't know
|
|
|
* what their exit policy is, or we know it permits something. */
|
|
|
count_usable_descriptors(&np, &nu, myexits_unflagged,
|
|
|
consensus, options, now,
|
|
|
- options->ExitNodes, 0);
|
|
|
+ options->ExitNodes, USABLE_DESCRIPTOR_ALL);
|
|
|
+ log_debug(LD_NET,
|
|
|
+ "%s: %d present, %d usable",
|
|
|
+ "myexits_unflagged (initial)",
|
|
|
+ np,
|
|
|
+ nu);
|
|
|
+
|
|
|
SMARTLIST_FOREACH_BEGIN(myexits_unflagged, const node_t *, node) {
|
|
|
- if (node_has_descriptor(node) && node_exit_policy_rejects_all(node))
|
|
|
+ if (node_has_descriptor(node) && node_exit_policy_rejects_all(node)) {
|
|
|
SMARTLIST_DEL_CURRENT(myexits_unflagged, node);
|
|
|
+ /* this node is not actually an exit */
|
|
|
+ np--;
|
|
|
+ /* this node is unusable as an exit */
|
|
|
+ nu--;
|
|
|
+ }
|
|
|
} SMARTLIST_FOREACH_END(node);
|
|
|
|
|
|
+ log_debug(LD_NET,
|
|
|
+ "%s: %d present, %d usable",
|
|
|
+ "myexits_unflagged (final)",
|
|
|
+ np,
|
|
|
+ nu);
|
|
|
+
|
|
|
f_guard = frac_nodes_with_descriptors(guards, WEIGHT_FOR_GUARD);
|
|
|
f_mid = frac_nodes_with_descriptors(mid, WEIGHT_FOR_MID);
|
|
|
f_exit = frac_nodes_with_descriptors(exits, WEIGHT_FOR_EXIT);
|
|
@@ -1418,6 +1469,12 @@ compute_frac_paths_available(const networkstatus_t *consensus,
|
|
|
f_myexit_unflagged=
|
|
|
frac_nodes_with_descriptors(myexits_unflagged,WEIGHT_FOR_EXIT);
|
|
|
|
|
|
+ log_debug(LD_NET,
|
|
|
+ "f_exit: %.2f, f_myexit: %.2f, f_myexit_unflagged: %.2f",
|
|
|
+ f_exit,
|
|
|
+ f_myexit,
|
|
|
+ f_myexit_unflagged);
|
|
|
+
|
|
|
/* If our ExitNodes list has eliminated every possible Exit node, and there
|
|
|
* were some possible Exit nodes, then instead consider nodes that permit
|
|
|
* exiting to some ports. */
|