Skip to main content

Module exit_node_suggest

Module exit_node_suggest 

Source
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:

  1. the lowest-latency region wins, with the lowest region id as the tiebreak (min_latency_derp_region); and
  2. prev_suggestion stickiness — if the previously-suggested node is still among the region’s candidates it is kept (see random_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§

ExitNodeCandidate
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 domain Node; 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’s build_file_targets factors out the file-target rules).
ExitNodeSuggestion
The result of an exit-node suggestion — the Rust analog of Go apitype.ExitNodeSuggestionResponse.

Enums§

SuggestExitNodeError
Why an exit-node suggestion could not be produced — the Rust analog of Go’s ErrNoPreferredDERP.

Type Aliases§

RegionLatencies
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 input suggest_exit_node ranks candidate regions on. A region absent from the map has no recent measurement (Go’s missing map key), which min_latency_derp_region sorts as the largest possible latency.
SelectNode
A node-selection closure: given a region’s candidates and the previous suggestion, return the chosen one. Port of Go’s selectNodeFunc. Encapsulates the prev_suggestion stickiness plus the uniform-random fallback; production passes random_node, tests pass a deterministic stub. The slice is always non-empty when invoked.
SelectRegion
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_region returns None); production passes the uniform random_region, tests pass a deterministic stub.