Files
tailscale/feature/routecheck/routecheck.go
T
Simon LawandGitHub 2fbd30824b tailcfg,net/routecheck: add NodeAttrClientSideReachabilityRouteCheck (#20169)
This patch adds a new `client-side-reachability-routecheck` node
attribute to allow admins to selectively enable background routecheck
probing on trial nodes. The current implementation is still
experimental.

It adds the routecheck.IsEnabled helper to check for the new
`client-side-reachability-routecheck` node attribute alongside the
existing `client-side-reachability` node attribute in this node’s self
capabilities. This allows administrators to turn on and off this
feature by editing the policy file.

It adds the `TS_DEBUG_FORCE_CLIENT_SIDE_REACHABILITY_ROUTECHECK`
environment variable which can be set to override the policy file.
When set to `true`, it forcibly enables this feature. And when set to
`false`, it forcibly disables it.

Updates #17366
Updates tailscale/corp#33033

Signed-off-by: Simon Law <sfllaw@tailscale.com>
2026-06-25 18:22:15 -07:00

93 lines
2.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Copyright (c) Tailscale Inc & contributors
// SPDX-License-Identifier: BSD-3-Clause
// Package routecheck registers support for RouteCheck,
// which checks the reachability of overlapping routers.
//
// When there are multiple network paths to an IP address, it is being routed by
// overlapping routers. The client uses reachability to pick between those
// paths: either sticking with an active WireGuard session or choosing from the
// peers that it has determined it can reach. It doesnt need reachability for
// IP addresses that have only one network path, since it can naively attempt to
// establish a WireGuard session.
package routecheck
import (
"fmt"
"tailscale.com/ipn/ipnext"
"tailscale.com/net/routecheck"
"tailscale.com/types/logger"
"tailscale.com/types/netmap"
)
// FeatureName is the name of the feature implemented by this package.
// It is also the [extension] name and the log prefix.
const featureName = "routecheck"
func init() {
ipnext.RegisterExtension(featureName, func(logf logger.Logf, b ipnext.SafeBackend) (ipnext.Extension, error) {
return &Extension{
logf: logger.WithPrefix(logf, featureName+": "),
backend: b,
}, nil
})
}
// Extension implements the [ipnext.Extension] interface.
type Extension struct {
Client *routecheck.Client
logf logger.Logf
backend ipnext.SafeBackend
nb nodeBackender
nm routecheck.NetMapper
}
var _ ipnext.Extension = new(Extension)
// Name implements the [ipnext.Extension.Name] interface method.
func (e *Extension) Name() string {
return featureName
}
// Init implements the [ipnext.Extension.Init] interface method.
func (e *Extension) Init(h ipnext.Host) error {
if routecheck.DebugForceClientSideReachabilityRoutecheck().EqualBool(false) {
return ipnext.SkipExtension
}
e.nb = nodeBackender{h}
nm, ok := e.backend.(routecheck.NetMapper)
if !ok {
return fmt.Errorf("backend %T does not implement routecheck.NetMapper", e.backend)
}
e.nm = nm
pinger := e.backend.Sys().Engine.Get()
c, err := routecheck.NewClient(e.logf, e.nb, e.nm, pinger)
if err != nil {
return err
}
e.Client = c
h.Hooks().OnNetMapToggle.Add(e.onNetMapToggle)
return nil
}
// Shutdown implements the [ipnext.Extension.Shutdown] interface method.
func (e *Extension) Shutdown() error {
err := e.Client.Close()
return err
}
func (e *Extension) onNetMapToggle(nm *netmap.NetworkMap) {
if nm == nil {
return
}
e.Client.NotifyNetMapAvailable(nm)
}