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>
This commit is contained in:
+21
-2
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user