mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-25 19:15:34 +00:00
ipn/ipnlocal, types/netmap: replace hasCapability with set lookup on NetworkMap
When node attributes were super rare, the O(n) slice scans looking for node attributes was more acceptable. But now more code and more users are using increasingly more node attributes. Time to make it a map. Noticed while working on tailscale/corp#17879 Updates #cleanup Change-Id: Ic17c80341f418421002fbceb47490729048756d2 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
8c88853db6
commit
b104688e04
@ -31,6 +31,7 @@
|
|||||||
"tailscale.com/types/views"
|
"tailscale.com/types/views"
|
||||||
"tailscale.com/util/clientmetric"
|
"tailscale.com/util/clientmetric"
|
||||||
"tailscale.com/util/mak"
|
"tailscale.com/util/mak"
|
||||||
|
"tailscale.com/util/set"
|
||||||
"tailscale.com/wgengine/filter"
|
"tailscale.com/wgengine/filter"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -74,6 +75,7 @@ type mapSession struct {
|
|||||||
// Fields storing state over the course of multiple MapResponses.
|
// Fields storing state over the course of multiple MapResponses.
|
||||||
lastPrintMap time.Time
|
lastPrintMap time.Time
|
||||||
lastNode tailcfg.NodeView
|
lastNode tailcfg.NodeView
|
||||||
|
lastCapSet set.Set[tailcfg.NodeCapability]
|
||||||
peers map[tailcfg.NodeID]*tailcfg.NodeView // pointer to view (oddly). same pointers as sortedPeers.
|
peers map[tailcfg.NodeID]*tailcfg.NodeView // pointer to view (oddly). same pointers as sortedPeers.
|
||||||
sortedPeers []*tailcfg.NodeView // same pointers as peers, but sorted by Node.ID
|
sortedPeers []*tailcfg.NodeView // same pointers as peers, but sorted by Node.ID
|
||||||
lastDNSConfig *tailcfg.DNSConfig
|
lastDNSConfig *tailcfg.DNSConfig
|
||||||
@ -239,6 +241,15 @@ func (ms *mapSession) updateStateFromResponse(resp *tailcfg.MapResponse) {
|
|||||||
|
|
||||||
if resp.Node != nil {
|
if resp.Node != nil {
|
||||||
ms.lastNode = resp.Node.View()
|
ms.lastNode = resp.Node.View()
|
||||||
|
|
||||||
|
capSet := set.Set[tailcfg.NodeCapability]{}
|
||||||
|
for _, c := range resp.Node.Capabilities {
|
||||||
|
capSet.Add(c)
|
||||||
|
}
|
||||||
|
for c := range resp.Node.CapMap {
|
||||||
|
capSet.Add(c)
|
||||||
|
}
|
||||||
|
ms.lastCapSet = capSet
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, up := range resp.UserProfiles {
|
for _, up := range resp.UserProfiles {
|
||||||
@ -803,6 +814,7 @@ func (ms *mapSession) netmap() *netmap.NetworkMap {
|
|||||||
nm.SelfNode = node
|
nm.SelfNode = node
|
||||||
nm.Expiry = node.KeyExpiry()
|
nm.Expiry = node.KeyExpiry()
|
||||||
nm.Name = node.Name()
|
nm.Name = node.Name()
|
||||||
|
nm.AllCaps = ms.lastCapSet
|
||||||
}
|
}
|
||||||
|
|
||||||
ms.addUserProfile(nm, nm.User())
|
ms.addUserProfile(nm, nm.User())
|
||||||
|
@ -1164,7 +1164,7 @@ func (b *LocalBackend) SetControlClientStatus(c controlclient.Client, st control
|
|||||||
|
|
||||||
// Perform all reconfiguration based on the netmap here.
|
// Perform all reconfiguration based on the netmap here.
|
||||||
if st.NetMap != nil {
|
if st.NetMap != nil {
|
||||||
b.capTailnetLock = hasCapability(st.NetMap, tailcfg.CapabilityTailnetLock)
|
b.capTailnetLock = st.NetMap.HasCap(tailcfg.CapabilityTailnetLock)
|
||||||
b.setWebClientAtomicBoolLocked(st.NetMap)
|
b.setWebClientAtomicBoolLocked(st.NetMap)
|
||||||
|
|
||||||
b.mu.Unlock() // respect locking rules for tkaSyncIfNeeded
|
b.mu.Unlock() // respect locking rules for tkaSyncIfNeeded
|
||||||
@ -1201,7 +1201,7 @@ func (b *LocalBackend) SetControlClientStatus(c controlclient.Client, st control
|
|||||||
}
|
}
|
||||||
|
|
||||||
if st.NetMap != nil {
|
if st.NetMap != nil {
|
||||||
if envknob.NoLogsNoSupport() && hasCapability(st.NetMap, tailcfg.CapabilityDataPlaneAuditLogs) {
|
if envknob.NoLogsNoSupport() && st.NetMap.HasCap(tailcfg.CapabilityDataPlaneAuditLogs) {
|
||||||
msg := "tailnet requires logging to be enabled. Remove --no-logs-no-support from tailscaled command line."
|
msg := "tailnet requires logging to be enabled. Remove --no-logs-no-support from tailscaled command line."
|
||||||
health.SetLocalLogConfigHealth(errors.New(msg))
|
health.SetLocalLogConfigHealth(errors.New(msg))
|
||||||
// Connecting to this tailnet without logging is forbidden; boot us outta here.
|
// Connecting to this tailnet without logging is forbidden; boot us outta here.
|
||||||
@ -3068,7 +3068,7 @@ func (b *LocalBackend) checkSSHPrefsLocked(p *ipn.Prefs) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if b.netMap != nil {
|
if b.netMap != nil {
|
||||||
if !hasCapability(b.netMap, tailcfg.CapabilitySSH) {
|
if !b.netMap.HasCap(tailcfg.CapabilitySSH) {
|
||||||
if b.isDefaultServerLocked() {
|
if b.isDefaultServerLocked() {
|
||||||
return errors.New("Unable to enable local Tailscale SSH server; not enabled on Tailnet. See https://tailscale.com/s/ssh")
|
return errors.New("Unable to enable local Tailscale SSH server; not enabled on Tailnet. See https://tailscale.com/s/ssh")
|
||||||
}
|
}
|
||||||
@ -3093,9 +3093,8 @@ func (b *LocalBackend) sshOnButUnusableHealthCheckMessageLocked() (healthMessage
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
isDefault := b.isDefaultServerLocked()
|
isDefault := b.isDefaultServerLocked()
|
||||||
isAdmin := hasCapability(nm, tailcfg.CapabilityAdmin)
|
|
||||||
|
|
||||||
if !isAdmin {
|
if !nm.HasCap(tailcfg.CapabilityAdmin) {
|
||||||
return healthmsg.TailscaleSSHOnBut + "access controls don't allow anyone to access this device. Ask your admin to update your tailnet's ACLs to allow access."
|
return healthmsg.TailscaleSSHOnBut + "access controls don't allow anyone to access this device. Ask your admin to update your tailnet's ACLs to allow access."
|
||||||
}
|
}
|
||||||
if !isDefault {
|
if !isDefault {
|
||||||
@ -3565,7 +3564,7 @@ func (b *LocalBackend) authReconfig() {
|
|||||||
prefs := b.pm.CurrentPrefs()
|
prefs := b.pm.CurrentPrefs()
|
||||||
nm := b.netMap
|
nm := b.netMap
|
||||||
hasPAC := b.prevIfState.HasPAC()
|
hasPAC := b.prevIfState.HasPAC()
|
||||||
disableSubnetsIfPAC := hasCapability(nm, tailcfg.NodeAttrDisableSubnetsIfPAC)
|
disableSubnetsIfPAC := nm.HasCap(tailcfg.NodeAttrDisableSubnetsIfPAC)
|
||||||
dohURL, dohURLOK := exitNodeCanProxyDNS(nm, b.peers, prefs.ExitNodeID())
|
dohURL, dohURLOK := exitNodeCanProxyDNS(nm, b.peers, prefs.ExitNodeID())
|
||||||
dcfg := dnsConfigForNetmap(nm, b.peers, prefs, b.logf, version.OS())
|
dcfg := dnsConfigForNetmap(nm, b.peers, prefs, b.logf, version.OS())
|
||||||
// If the current node is an app connector, ensure the app connector machine is started
|
// If the current node is an app connector, ensure the app connector machine is started
|
||||||
@ -4533,7 +4532,7 @@ func (b *LocalBackend) ShouldExposeRemoteWebClient() bool {
|
|||||||
//
|
//
|
||||||
// b.mu must be held.
|
// b.mu must be held.
|
||||||
func (b *LocalBackend) setWebClientAtomicBoolLocked(nm *netmap.NetworkMap) {
|
func (b *LocalBackend) setWebClientAtomicBoolLocked(nm *netmap.NetworkMap) {
|
||||||
shouldRun := !hasCapability(nm, tailcfg.NodeAttrDisableWebClient)
|
shouldRun := !nm.HasCap(tailcfg.NodeAttrDisableWebClient)
|
||||||
wasRunning := b.webClientAtomicBool.Swap(shouldRun)
|
wasRunning := b.webClientAtomicBool.Swap(shouldRun)
|
||||||
if wasRunning && !shouldRun {
|
if wasRunning && !shouldRun {
|
||||||
go b.webClientShutdown() // stop web client
|
go b.webClientShutdown() // stop web client
|
||||||
@ -4630,13 +4629,6 @@ func (b *LocalBackend) setNetInfo(ni *tailcfg.NetInfo) {
|
|||||||
cc.SetNetInfo(ni)
|
cc.SetNetInfo(ni)
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasCapability(nm *netmap.NetworkMap, cap tailcfg.NodeCapability) bool {
|
|
||||||
if nm != nil {
|
|
||||||
return nm.SelfNode.HasCap(cap)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// setNetMapLocked updates the LocalBackend state to reflect the newly
|
// setNetMapLocked updates the LocalBackend state to reflect the newly
|
||||||
// received nm. If nm is nil, it resets all configuration as though
|
// received nm. If nm is nil, it resets all configuration as though
|
||||||
// Tailscale is turned off.
|
// Tailscale is turned off.
|
||||||
@ -4665,15 +4657,15 @@ func (b *LocalBackend) setNetMapLocked(nm *netmap.NetworkMap) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Determine if file sharing is enabled
|
// Determine if file sharing is enabled
|
||||||
fs := hasCapability(nm, tailcfg.CapabilityFileSharing)
|
fs := nm.HasCap(tailcfg.CapabilityFileSharing)
|
||||||
if fs != b.capFileSharing {
|
if fs != b.capFileSharing {
|
||||||
osshare.SetFileSharingEnabled(fs, b.logf)
|
osshare.SetFileSharingEnabled(fs, b.logf)
|
||||||
}
|
}
|
||||||
b.capFileSharing = fs
|
b.capFileSharing = fs
|
||||||
|
|
||||||
if hasCapability(nm, tailcfg.NodeAttrLinuxMustUseIPTables) {
|
if nm.HasCap(tailcfg.NodeAttrLinuxMustUseIPTables) {
|
||||||
b.capForcedNetfilter = "iptables"
|
b.capForcedNetfilter = "iptables"
|
||||||
} else if hasCapability(nm, tailcfg.NodeAttrLinuxMustUseNfTables) {
|
} else if nm.HasCap(tailcfg.NodeAttrLinuxMustUseNfTables) {
|
||||||
b.capForcedNetfilter = "nftables"
|
b.capForcedNetfilter = "nftables"
|
||||||
} else {
|
} else {
|
||||||
b.capForcedNetfilter = "" // empty string means client can auto-detect
|
b.capForcedNetfilter = "" // empty string means client can auto-detect
|
||||||
@ -4685,8 +4677,8 @@ func (b *LocalBackend) setNetMapLocked(nm *netmap.NetworkMap) {
|
|||||||
b.setDebugLogsByCapabilityLocked(nm)
|
b.setDebugLogsByCapabilityLocked(nm)
|
||||||
|
|
||||||
// See the netns package for documentation on what this capability does.
|
// See the netns package for documentation on what this capability does.
|
||||||
netns.SetBindToInterfaceByRoute(hasCapability(nm, tailcfg.CapabilityBindToInterfaceByRoute))
|
netns.SetBindToInterfaceByRoute(nm.HasCap(tailcfg.CapabilityBindToInterfaceByRoute))
|
||||||
netns.SetDisableBindConnToInterface(hasCapability(nm, tailcfg.CapabilityDebugDisableBindConnToInterface))
|
netns.SetDisableBindConnToInterface(nm.HasCap(tailcfg.CapabilityDebugDisableBindConnToInterface))
|
||||||
|
|
||||||
b.setTCPPortsInterceptedFromNetmapAndPrefsLocked(b.pm.CurrentPrefs())
|
b.setTCPPortsInterceptedFromNetmapAndPrefsLocked(b.pm.CurrentPrefs())
|
||||||
if nm == nil {
|
if nm == nil {
|
||||||
@ -4777,7 +4769,7 @@ func (t *tailFSTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
|||||||
func (b *LocalBackend) setDebugLogsByCapabilityLocked(nm *netmap.NetworkMap) {
|
func (b *LocalBackend) setDebugLogsByCapabilityLocked(nm *netmap.NetworkMap) {
|
||||||
// These are sufficiently cheap (atomic bools) that we don't need to
|
// These are sufficiently cheap (atomic bools) that we don't need to
|
||||||
// store state and compare.
|
// store state and compare.
|
||||||
if hasCapability(nm, tailcfg.CapabilityDebugTSDNSResolution) {
|
if nm.HasCap(tailcfg.CapabilityDebugTSDNSResolution) {
|
||||||
dnscache.SetDebugLoggingEnabled(true)
|
dnscache.SetDebugLoggingEnabled(true)
|
||||||
} else {
|
} else {
|
||||||
dnscache.SetDebugLoggingEnabled(false)
|
dnscache.SetDebugLoggingEnabled(false)
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
"tailscale.com/tka"
|
"tailscale.com/tka"
|
||||||
"tailscale.com/types/key"
|
"tailscale.com/types/key"
|
||||||
"tailscale.com/types/views"
|
"tailscale.com/types/views"
|
||||||
|
"tailscale.com/util/set"
|
||||||
"tailscale.com/wgengine/filter"
|
"tailscale.com/wgengine/filter"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -26,6 +27,7 @@
|
|||||||
// alias parts of previous NetworkMap values.
|
// alias parts of previous NetworkMap values.
|
||||||
type NetworkMap struct {
|
type NetworkMap struct {
|
||||||
SelfNode tailcfg.NodeView
|
SelfNode tailcfg.NodeView
|
||||||
|
AllCaps set.Set[tailcfg.NodeCapability] // set version of SelfNode.Capabilities + SelfNode.CapMap
|
||||||
NodeKey key.NodePublic
|
NodeKey key.NodePublic
|
||||||
PrivateKey key.NodePrivate
|
PrivateKey key.NodePrivate
|
||||||
Expiry time.Time
|
Expiry time.Time
|
||||||
@ -120,6 +122,11 @@ func (nm *NetworkMap) GetMachineStatus() tailcfg.MachineStatus {
|
|||||||
return tailcfg.MachineUnauthorized
|
return tailcfg.MachineUnauthorized
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HasCap reports whether nm is non-nil and nm.AllCaps contains c.
|
||||||
|
func (nm *NetworkMap) HasCap(c tailcfg.NodeCapability) bool {
|
||||||
|
return nm != nil && nm.AllCaps.Contains(c)
|
||||||
|
}
|
||||||
|
|
||||||
// PeerByTailscaleIP returns a peer's Node based on its Tailscale IP.
|
// PeerByTailscaleIP returns a peer's Node based on its Tailscale IP.
|
||||||
//
|
//
|
||||||
// If nm is nil or no peer is found, ok is false.
|
// If nm is nil or no peer is found, ok is false.
|
||||||
|
Loading…
Reference in New Issue
Block a user