From 8869cf39b6a10ab92a84504efafd48353dbc6707 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 25 Aug 2023 10:47:56 -0400 Subject: Merge 337-simpler-guard-usability.md into guard-spec This proposal gives an alternative formulation of the usability rules of guard-spec, and the relationship between guard status and circuit status. --- guard-spec.txt | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 4 deletions(-) (limited to 'guard-spec.txt') diff --git a/guard-spec.txt b/guard-spec.txt index 9a15eb8..154edae 100644 --- a/guard-spec.txt +++ b/guard-spec.txt @@ -257,6 +257,10 @@ Table of Contents are trying to build an exploratory circuit through the guard, and we don't know whether it will succeed. + - {tvar:pending_since}: A timestamp. Set whenever we set + {tvar:is_pending} to true; cleared whenever we set + {tvar:is_pending} to false. NOTE + We require that {SAMPLED_GUARDS} contain at least {MIN_FILTERED_SAMPLE} guards from the consensus (if possible), but not more than {MAX_SAMPLE_THRESHOLD} of the number of guards @@ -519,13 +523,16 @@ Table of Contents * Otherwise, if the ordered intersection of {CONFIRMED_GUARDS} and {USABLE_FILTERED_GUARDS} is nonempty, return the first entry in that intersection that has {is_pending} set to - false. Set its value of {is_pending} to true. The circuit + false. Set its value of {is_pending} to true, + and set its {pending_since} to the current time. + The circuit is now . (If all entries have {is_pending} true, pick the first one.) * Otherwise, if there is no such entry, select a member from {USABLE_FILTERED_GUARDS} in sample order. Set its {is_pending} field to - true. The circuit is . + true, and set its {pending_since} to the current time. + The circuit is . * Otherwise, if USABLE_FILTERED_GUARDS is empty, we have exhausted all the sampled guards. In this case we proceed by marking all guards @@ -565,7 +572,8 @@ Table of Contents is not reachable, we take the following steps: * Set the guard's {is_reachable} status to . If it had - {is_pending} set to true, we make it non-pending. + {is_pending} set to true, we make it non-pending and clear + {pending_since}. * Close the circuit, of course. (This removes it from consideration by the algorithm in [UPDATE_WAITING].) @@ -588,7 +596,8 @@ Table of Contents * We set its {is_reachable} status to . * We set its {failing_since} to "never". - * If the guard was {is_pending}, we clear the {is_pending} flag. + * If the guard was {is_pending}, we clear the {is_pending} flag + and set {pending_since} to false. * If the guard was not a member of {CONFIRMED_GUARDS}, we add it to the end of {CONFIRMED_GUARDS}. @@ -652,6 +661,48 @@ Table of Contents them after all if the circuit goes down before {NONPRIMARY_GUARD_IDLE_TIMEOUT} seconds. +4.9.1. Without a list of waiting circuits [Section:NO_CIRCLIST] + + As an alternative to the section [SECTION:UPDATE_WAITING] above, + this section presents a new way to maintain guard status + independently of tracking individual circuit status. This + formulation gives a result equivalent or similar to the approach + above, but simplifies the necessary communications between the + guard and circuit subsystems. + + As before, when all primary guards are Unreachable, we need to + try non-primary guards. We select the first such guard (in + preference order) that is neither Unreachable nor Pending. + Whenever we give out such a guard, if the guard's status is + Unknown, then we call that guard "Pending" with its {is_pending} + flag, until the attempt to use it succeeds or fails. We remember + when the guard became Pending with the {pending_since variable}. + + After completing a circuit, the implementation must check whether + its guard is usable. A guard's usability status may be "usable", + "unusable", or "unknown". A guard is usable according to + these rules: + + 1. Primary guards are always usable. + + 2. Non-primary guards are usable _for a given circuit_ if every + guard earlier in the preference list is either unsuitable for + that circuit (e.g. because of family restrictions), or marked as + Unreachable, or has been pending for at least + `{NONPRIMARY_GUARD_CONNECT_TIMEOUT}`. + + Non-primary guards are not usable _for a given circuit_ if some + guard earlier in the preference list is suitable for the circuit + _and_ Reachable. + + Non-primary guards are unusable if they have not become + usable after `{NONPRIMARY_GUARD_IDLE_TIMEOUT}` seconds. + + 3. If a circuit's guard is not usable or unusable immediately, the + circuit is not discarded; instead, it is kept (but not used) until the + guard becomes usable or unusable. + + 4.10. Whenever we get a new consensus. [Section:ON_CONSENSUS] We update {GUARDS}. -- cgit v1.2.3-54-g00ecf