ipn/localapi,net/captivedetection,net/netcheck: track DERPRegion.Active

In PR #15245, we deprecated the tailscale.com/tailcfg.DERPRegion.Avoid
field because its implementation had drifted from its documented
meaning. Yet it is still being used in some specific cases.

This patch adds metrics to track when the Avoid flag is set so we can
burn down any lingering uses and eliminate them.

Updates tailscale/corp#24697
Fixes #19793

Signed-off-by: Simon Law <sfllaw@tailscale.com>
This commit is contained in:
Simon Law 2026-05-18 14:07:07 -07:00
parent 5d1bf80597
commit 5f42489e00
No known key found for this signature in database
GPG Key ID: B83D1EE07548341D
3 changed files with 28 additions and 3 deletions

View File

@ -25,8 +25,13 @@
"tailscale.com/tailcfg"
"tailscale.com/types/key"
"tailscale.com/types/nettype"
"tailscale.com/util/clientmetric"
)
// MetricDERPRegionAvoidTrue tracks the usage of DERPRegion.Avoid in the DERPMap
// as it gets replaced with better alternatives. See tailscale/corp#24697.
var metricDERPRegionAvoidTrue = clientmetric.NewCounter("localapi_derpregion_avoid_true")
func (h *Handler) serveDebugDERPRegion(w http.ResponseWriter, r *http.Request) {
if !h.PermitWrite {
http.Error(w, "debug access denied", http.StatusForbidden)
@ -70,6 +75,7 @@ func (h *Handler) serveDebugDERPRegion(w http.ResponseWriter, r *http.Request) {
}
if reg.Avoid {
metricDERPRegionAvoidTrue.Add(1)
st.Warnings = append(st.Warnings, "Region is marked with Avoid bit")
}
if len(reg.Nodes) == 0 {

View File

@ -15,8 +15,13 @@
"tailscale.com/net/dnsfallback"
"tailscale.com/tailcfg"
"tailscale.com/types/logger"
"tailscale.com/util/clientmetric"
)
// MetricDERPRegionAvoidTrue tracks the usage of DERPRegion.Avoid in the DERPMap
// as it gets replaced with better alternatives. See tailscale/corp#24697.
var metricDERPRegionAvoidTrue = clientmetric.NewCounter("captivedetection_derpregion_avoid_true")
// EndpointProvider is an enum that represents the source of an Endpoint.
type EndpointProvider int
@ -89,7 +94,11 @@ func availableEndpoints(derpMap *tailcfg.DERPMap, preferredDERPRegionID int, log
// Use the DERP IPs as captive portal detection endpoints. Using IPs is better than hostnames
// because they do not depend on DNS resolution.
for _, region := range derpMap.Regions {
if region.Avoid || region.NoMeasureNoHome {
if region.Avoid {
metricDERPRegionAvoidTrue.Add(1)
continue
}
if region.NoMeasureNoHome {
continue
}
for _, node := range region.Nodes {

View File

@ -394,8 +394,11 @@ func sortRegions(dm *tailcfg.DERPMap, last *Report, preferredDERP int) (prev []*
continue
}
// include an otherwise avoid region if it is the current preferred region
if reg.Avoid && reg.RegionID != preferredDERP {
continue
if reg.Avoid {
metricDERPRegionAvoidTrue.Add(1)
if reg.RegionID != preferredDERP {
continue
}
}
prev = append(prev, reg)
}
@ -964,6 +967,9 @@ func (c *Client) GetReport(ctx context.Context, dm *tailcfg.DERPMap, opts *GetRe
var wg sync.WaitGroup
var need []*tailcfg.DERPRegion
for rid, reg := range dm.Regions {
if reg.Avoid {
metricDERPRegionAvoidTrue.Add(1)
}
if !rs.haveRegionLatency(rid) && regionHasDERPNode(reg) && !reg.Avoid && !reg.NoMeasureNoHome {
need = append(need, reg)
}
@ -1713,4 +1719,8 @@ func conciseOptBool(b opt.Bool, trueVal string) string {
metricSTUNRecv4 = clientmetric.NewCounter("netcheck_stun_recv_ipv4")
metricSTUNRecv6 = clientmetric.NewCounter("netcheck_stun_recv_ipv6")
metricHTTPSend = clientmetric.NewCounter("netcheck_https_measure")
// MetricDERPRegionAvoidTrue tracks the usage of DERPRegion.Avoid in the DERPMap
// as it gets replaced with better alternatives. See tailscale/corp#24697.
metricDERPRegionAvoidTrue = clientmetric.NewCounter("netcheck_derpregion_avoid_true")
)