mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-13 22:47:30 +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()
|
id := n.ID()
|
||||||
s, ok := scores[id]
|
s, ok := scores[id]
|
||||||
if !ok {
|
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 hi := n.Hostinfo(); hi.Valid() {
|
||||||
if loc := hi.Location(); loc.Valid() {
|
if loc := hi.Location(); loc.Valid() {
|
||||||
s = loc.Priority()
|
s = loc.Priority()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SetScore:
|
||||||
scores[id] = s
|
scores[id] = s
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
|
@@ -5076,6 +5076,76 @@ func TestSuggestExitNodeTrafficSteering(t *testing.T) {
|
|||||||
wantID: "stable3",
|
wantID: "stable3",
|
||||||
wantName: "peer3",
|
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",
|
name: "exit-nodes-with-and-without-priority",
|
||||||
netMap: &netmap.NetworkMap{
|
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