types/netmap,wgengine/magicsock: propagate CapVer to magicsock.endpoint (#16244)

This enables us to mark nodes as relay capable or not. We don't actually
do that yet, as we haven't established a relay CapVer.

Updates tailscale/corp#27502

Signed-off-by: Jordan Whited <jordan@tailscale.com>
This commit is contained in:
Jordan Whited 2025-06-10 17:31:14 -07:00 committed by GitHub
parent 8114260019
commit 6a93b17c8c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 33 additions and 0 deletions

View File

@ -69,6 +69,17 @@ func (m NodeMutationLastSeen) Apply(n *tailcfg.Node) {
n.LastSeen = ptr.To(m.LastSeen)
}
// NodeMutationCap is a NodeMutation that says a node's
// [tailcfg.CapabilityVersion] value has changed.
type NodeMutationCap struct {
mutatingNodeID
Cap tailcfg.CapabilityVersion
}
func (m NodeMutationCap) Apply(n *tailcfg.Node) {
n.Cap = m.Cap
}
var peerChangeFields = sync.OnceValue(func() []reflect.StructField {
var fields []reflect.StructField
rt := reflect.TypeFor[tailcfg.PeerChange]()
@ -105,6 +116,8 @@ func NodeMutationsFromPatch(p *tailcfg.PeerChange) (_ []NodeMutation, ok bool) {
ret = append(ret, NodeMutationOnline{mutatingNodeID(p.NodeID), *p.Online})
case "LastSeen":
ret = append(ret, NodeMutationLastSeen{mutatingNodeID(p.NodeID), *p.LastSeen})
case "Cap":
ret = append(ret, NodeMutationCap{mutatingNodeID(p.NodeID), p.Cap})
}
}
return ret, true

View File

@ -177,6 +177,14 @@ func TestMutationsFromMapResponse(t *testing.T) {
},
want: nil,
},
{
name: "patch-cap",
mr: fromChanges(&tailcfg.PeerChange{
NodeID: 1,
Cap: 2,
}),
want: muts(NodeMutationCap{1, 2}),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@ -195,6 +203,7 @@ func TestMutationsFromMapResponse(t *testing.T) {
NodeMutationDERPHome{},
NodeMutationOnline{},
NodeMutationLastSeen{},
NodeMutationCap{},
)); diff != "" {
t.Errorf("wrong result (-want +got):\n%s", diff)
}

View File

@ -1423,6 +1423,8 @@ func (de *endpoint) updateFromNode(n tailcfg.NodeView, heartbeatDisabled bool, p
}
de.setEndpointsLocked(n.Endpoints())
de.relayCapable = capVerIsRelayCapable(n.Cap())
}
func (de *endpoint) setEndpointsLocked(eps interface {

View File

@ -2507,6 +2507,11 @@ func (c *Conn) SetProbeUDPLifetime(v bool) {
})
}
func capVerIsRelayCapable(version tailcfg.CapabilityVersion) bool {
// TODO(jwhited): implement once capVer is bumped
return false
}
// SetNetworkMap is called when the control client gets a new network
// map from the control server. It must always be non-nil.
//
@ -3203,6 +3208,10 @@ func (c *Conn) UpdateNetmapDelta(muts []netmap.NodeMutation) (handled bool) {
ep.mu.Lock()
ep.setEndpointsLocked(views.SliceOf(m.Endpoints))
ep.mu.Unlock()
case netmap.NodeMutationCap:
ep.mu.Lock()
ep.relayCapable = capVerIsRelayCapable(m.Cap)
ep.mu.Unlock()
}
}
return true