feature/routecheck,ipn/routecheck: probe reachability in the background
Previously, refreshing the routecheck.Client would probe to generate a new routecheck.Report, but this method was only wired up to the LocalAPI and the `tailscale routecheck` command. However, waiting for a probe to finish before choosing a router would take too long, so we must keep a regularly updated report to be consulted as necessary. This patch adds a Start and Close method to the routecheck.Client and starts it in the background from features/routecheck. To enable this feature for a given node, set both of the following node attributes: `client-side-reachability` and `client-side-reachability-routecheck`. This patch also wires up the RouterTracker.OnRoutersChange hook, which fires a callback whenever a new network map includes information about a router node, This signals to the routecheck.Client that it might need to schedule another probe, if the shape of the routing table has changed materially. Updates #17366 Updates tailscale/corp#33033 Signed-off-by: Simon Law <sfllaw@tailscale.com>
This commit is contained in:
@@ -37,18 +37,16 @@ func serveRouteCheck(h *localapi.Handler, w http.ResponseWriter, r *http.Request
|
||||
return
|
||||
}
|
||||
|
||||
var err error
|
||||
var report *routecheck.Report
|
||||
report := rc.Report()
|
||||
if def.Bool(r.FormValue("probe"), false) {
|
||||
timeout := def.Duration(r.FormValue("timeout"), routecheck.DefaultTimeout)
|
||||
timeout = min(max(0, timeout), 60*time.Second) // clamp to [0s, 60s]
|
||||
report, err = rc.Refresh(r.Context(), timeout)
|
||||
} else {
|
||||
report = rc.Report()
|
||||
}
|
||||
if err != nil {
|
||||
localapi.WriteErrorJSON(w, err)
|
||||
return
|
||||
timeout = clampRouteCheckTimeout(timeout)
|
||||
rp, err := rc.Refresh(r.Context(), timeout)
|
||||
if err != nil {
|
||||
localapi.WriteErrorJSON(w, err)
|
||||
return
|
||||
}
|
||||
report = rp
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
@@ -61,3 +59,10 @@ func serveRouteCheck(h *localapi.Handler, w http.ResponseWriter, r *http.Request
|
||||
// with its default options, marshal with DefaultOptionsV1.
|
||||
jsonv2.MarshalWrite(w, report, jsonv1.DefaultOptionsV1())
|
||||
}
|
||||
|
||||
func clampRouteCheckTimeout(timeout time.Duration) time.Duration {
|
||||
if timeout < 0 {
|
||||
timeout = routecheck.DefaultTimeout
|
||||
}
|
||||
return min(max(0, timeout), 60*time.Second) // clamp to [0s, 60s]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user