Expand description
Exit-node suggestion algorithm (the classic DERP-region-latency path, Go
suggestExitNodeUsingDERP) and its result/error types.
Exit-node suggestion: pick a reasonably good exit node from the netmap + recent DERP latency.
This is the Rust port of Go ipnlocal’s suggestExitNodeUsingDERP (the classic DERP-region
-latency path; tailscale ipn/ipnlocal/local.go @ 3945b82f8a9550b54c33e61d4ed2227862d53e8a),
surfaced as Runtime::suggest_exit_node and consumed by
the daemon’s tnet exit-node suggest. The traffic-steering path (NodeAttrTrafficSteering) and
the Mullvad geo-distance path are Phase 2 and deliberately not ported here (see
suggest_exit_node).
§Determinism contract (this corrects a common misconception)
There is no seed/hash tiebreak. Determinism comes from exactly two places, mirroring Go:
- the lowest-latency region wins, with the lowest region id as the tiebreak
(
min_latency_derp_region); and prev_suggestionstickiness — if the previously-suggested node is still among the region’s candidates it is kept (seerandom_node).
The final pick among equally-good ties is uniform random and varies run-to-run (Go’s own doc
says “the result is not stable”). So that the algorithm stays unit-testable, the region pick and
the node pick are taken as injected closures (SelectRegion
/ SelectNode); production passes the uniform-random
random_region / random_node, and tests pass deterministic stubs. This is a direct port of
Go’s selectRegionFunc / selectNodeFunc parameters.
§Ranking input: recent per-region latency, not one report
The ranking reads a RegionLatencies map — the
lowest latency seen per region over the retained measurement history (Go
netcheck.Client.RecentRegionLatency(), here
ControlRunner::recent_region_latency) — not the newest
netcheck report. Upstream made that change because netcheck alternates full reports with
incremental ones and “when the most recent report is incremental, the suggestion fell back to a
random for exit nodes that are far away”. It bites harder here: ts_netcheck::Config ends a
measurement as soon as complete_threshold (3) regions have answered, so every report this
fork produces names a handful of regions. Ranked against a single report, a candidate homed
anywhere else has no latency at all, min_latency_derp_region returns None, and the
suggestion degrades to the uniform select_region pick — the nearest exit node loses to a coin
flip. Ranked against the history’s union, it does not.
Structs§
- Exit
Node Candidate - A peer being considered as an exit-node suggestion, carrying exactly the inputs the suggestion
algorithm reads. Built (in
Runtime::suggest_exit_node) from a domainNode; kept as a small standalone struct so the algorithm is a pure function over its inputs (unit-testable without the actor graph, mirroring how the runtime’sbuild_file_targetsfactors out the file-target rules). - Exit
Node Suggestion - The result of an exit-node suggestion — the Rust analog of Go
apitype.ExitNodeSuggestionResponse.
Enums§
- Suggest
Exit Node Error - Why an exit-node suggestion could not be produced — the Rust analog of Go’s
ErrNoPreferredDERP.
Type Aliases§
- Region
Latencies - The lowest latency seen for each DERP region across the retained measurement history — the Rust
analog of the map Go’s
netcheck.Client.RecentRegionLatency()returns, and the inputsuggest_exit_noderanks candidate regions on. A region absent from the map has no recent measurement (Go’s missing map key), whichmin_latency_derp_regionsorts as the largest possible latency. - Select
Node - A node-selection closure: given a region’s candidates and the previous suggestion, return the
chosen one. Port of Go’s
selectNodeFunc. Encapsulates theprev_suggestionstickiness plus the uniform-random fallback; production passesrandom_node, tests pass a deterministic stub. The slice is always non-empty when invoked. - Select
Region - A region-selection closure: given the candidate regions (those with at least one DERP-homed
candidate), return one to draw the suggestion from. Port of Go’s
selectRegionFunc. Only invoked as the fallback when no region has a usable measured latency (min_latency_derp_regionreturnsNone); production passes the uniformrandom_region, tests pass a deterministic stub.