mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-13 06:07:34 +00:00
ipn/ipnlocal: parse priority out of suggest-exit-node capability
When the `experimental:exit-node-steering` attribute is enabled for a node, it is likely that the priority score for an exit node is different when considering it as a suggested exit node versus considering it for the routers / connectors that it hosts. In order to distinguish between these two, the network map can now contain the priority score for suggesting the exit node in the `suggest-exit-node` capability, in that peer’s CapMap: "CapMap": { "suggest-exit-node": [ { "Priority": 42 } ] } Updates tailscale/corp#31011 Signed-off-by: Simon Law <sfllaw@tailscale.com>
This commit is contained in:
@@ -7952,12 +7952,32 @@ func suggestExitNodeUsingTrafficSteering(nb *nodeBackend, allowed set.Set[tailcf
|
||||
id := n.ID()
|
||||
s, ok := scores[id]
|
||||
if !ok {
|
||||
s = 0 // score of zero means incomparable
|
||||
// score of zero means incomparable
|
||||
s = 0
|
||||
|
||||
// Prefer the priority in the suggest-exit-node peer cap.
|
||||
if caps, ok := n.CapMap().GetOk(tailcfg.NodeAttrSuggestExitNode); ok {
|
||||
for _, cap := range caps.All() {
|
||||
var c tailcfg.SuggestExitNode
|
||||
if err := json.Unmarshal([]byte(cap), &c); err != nil {
|
||||
break
|
||||
}
|
||||
if c.Priority == 0 {
|
||||
break
|
||||
}
|
||||
s = c.Priority
|
||||
goto SetScore
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback on the peer’s location priority.
|
||||
if hi := n.Hostinfo(); hi.Valid() {
|
||||
if loc := hi.Location(); loc.Valid() {
|
||||
s = loc.Priority()
|
||||
}
|
||||
}
|
||||
|
||||
SetScore:
|
||||
scores[id] = s
|
||||
}
|
||||
return s
|
||||
|
@@ -5076,6 +5076,76 @@ func TestSuggestExitNodeTrafficSteering(t *testing.T) {
|
||||
wantID: "stable3",
|
||||
wantName: "peer3",
|
||||
},
|
||||
{
|
||||
name: "exit-node-empty-suggestions",
|
||||
netMap: &netmap.NetworkMap{
|
||||
SelfNode: selfNode.View(),
|
||||
Peers: []tailcfg.NodeView{
|
||||
makePeer(1,
|
||||
withExitRoutes(),
|
||||
withSuggest(nil)),
|
||||
makePeer(2,
|
||||
withExitRoutes(),
|
||||
withSuggest([]tailcfg.RawMessage{})),
|
||||
makePeer(3,
|
||||
withExitRoutes(),
|
||||
withSuggest([]tailcfg.RawMessage{
|
||||
`{}`,
|
||||
})),
|
||||
makePeer(4,
|
||||
withExitRoutes(),
|
||||
withSuggest([]tailcfg.RawMessage{
|
||||
`{"Priority": 0}`,
|
||||
})),
|
||||
},
|
||||
},
|
||||
// Change this, if the hashing function changes.
|
||||
wantID: "stable3",
|
||||
wantName: "peer3",
|
||||
},
|
||||
{
|
||||
name: "exit-node-with-suggestion-and-priority",
|
||||
netMap: &netmap.NetworkMap{
|
||||
SelfNode: selfNode.View(),
|
||||
Peers: []tailcfg.NodeView{
|
||||
makePeer(1,
|
||||
withExitRoutes(),
|
||||
withSuggest([]tailcfg.RawMessage{
|
||||
`{"Priority": 3}`,
|
||||
}),
|
||||
withLocationPriority(1)), // overridden
|
||||
makePeer(2,
|
||||
withExitRoutes(),
|
||||
withLocationPriority(2)),
|
||||
},
|
||||
},
|
||||
wantID: "stable1",
|
||||
wantName: "peer1",
|
||||
wantPri: 1, // Location.Priority
|
||||
},
|
||||
{
|
||||
name: "exit-node-with-priority",
|
||||
netMap: &netmap.NetworkMap{
|
||||
SelfNode: selfNode.View(),
|
||||
Peers: []tailcfg.NodeView{
|
||||
makePeer(1,
|
||||
withExitRoutes(),
|
||||
withSuggest(nil)),
|
||||
makePeer(2,
|
||||
withExitRoutes(),
|
||||
withSuggest(nil)),
|
||||
makePeer(3,
|
||||
withExitRoutes(),
|
||||
withSuggest(nil)),
|
||||
makePeer(4,
|
||||
withExitRoutes(),
|
||||
withSuggest(nil)),
|
||||
},
|
||||
},
|
||||
// Change this, if the hashing function changes.
|
||||
wantID: "stable3",
|
||||
wantName: "peer3",
|
||||
},
|
||||
{
|
||||
name: "exit-nodes-with-and-without-priority",
|
||||
netMap: &netmap.NetworkMap{
|
||||
|
13
tailcfg/traffic.go
Normal file
13
tailcfg/traffic.go
Normal file
@@ -0,0 +1,13 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package tailcfg
|
||||
|
||||
type SuggestExitNode struct {
|
||||
// Priority is the relative priority of this exit node. Nodes with a
|
||||
// higher priority are preferred over nodes with a lower priority, nodes
|
||||
// of equal probability may be selected arbitrarily. A priority of 0
|
||||
// means the exit node has no a priority preference and a negative
|
||||
// priority is not allowed.
|
||||
Priority int `json:",omitempty"`
|
||||
}
|
Reference in New Issue
Block a user