ipn/ipnlocal: log traffic steering scores and suggested exit nodes (#18681)

When traffic steering is enabled, some users are suggested an exit
node that is inappropriately far from their location. This seems to
happen right when the client connects to the control plane and the
client eventually fixes itself. But whenever an affected client
reconnects, its suggested exit node flaps, and this happens often
enough to be noticeable because connections drop whenever the exit
node is switched. This should not happen, since the map response that
contains the list of suggested exit nodes that the client picks from,
also contains the scores for those nodes.

Since our current logging and diagnostic tools don’t give us enough
insight into what is happening, this PR adds additional logging when:
- traffic steering scores are used to suggest an exit node
- an exit node is suggested, no matter how it was determined

Updates: tailscale/corp#29964
Updates: tailscale/corp#36446

Signed-off-by: Simon Law <sfllaw@tailscale.com>
main
Simon Law 2 months ago committed by GitHub
parent 1172b2febd
commit 12188c0ade
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 23
      ipn/ipnlocal/local.go

@ -6,6 +6,7 @@
package ipnlocal
import (
"bufio"
"cmp"
"context"
"crypto/sha256"
@ -7484,13 +7485,16 @@ func suggestExitNode(report *netcheck.Report, nb *nodeBackend, prevSuggestion ta
switch {
case nb.SelfHasCap(tailcfg.NodeAttrTrafficSteering):
// The traffic-steering feature flag is enabled on this tailnet.
return suggestExitNodeUsingTrafficSteering(nb, allowList)
res, err = suggestExitNodeUsingTrafficSteering(nb, allowList)
default:
// The control plane will always strip the `traffic-steering`
// node attribute if it isn’t enabled for this tailnet, even if
// it is set in the policy file: tailscale/corp#34401
return suggestExitNodeUsingDERP(report, nb, prevSuggestion, selectRegion, selectNode, allowList)
res, err = suggestExitNodeUsingDERP(report, nb, prevSuggestion, selectRegion, selectNode, allowList)
}
name, _, _ := strings.Cut(res.Name, ".")
nb.logf("netmap: suggested exit node: %s (%s)", name, res.ID)
return res, err
}
// suggestExitNodeUsingDERP is the classic algorithm used to suggest exit nodes,
@ -7723,6 +7727,21 @@ func suggestExitNodeUsingTrafficSteering(nb *nodeBackend, allowed set.Set[tailcf
pick = nodes[0]
}
nb.logf("netmap: traffic steering: exit node scores: %v", logger.ArgWriter(func(bw *bufio.Writer) {
const max = 10
for i, n := range nodes {
if i == max {
fmt.Fprintf(bw, "... +%d", len(nodes)-max)
return
}
if i > 0 {
bw.WriteString(", ")
}
name, _, _ := strings.Cut(n.Name(), ".")
fmt.Fprintf(bw, "%d:%s", score(n), name)
}
}))
if !pick.Valid() {
return apitype.ExitNodeSuggestionResponse{}, nil
}

Loading…
Cancel
Save