summaryrefslogtreecommitdiffhomepage
path: root/control/controlclient/map.go
AgeCommit message (Collapse)AuthorFilesLines
2026-04-15control/controlclient: add patchify miss statsBrad Fitzpatrick1-4/+41
Add an opt-in metrics.LabelMap tracking why patchifyPeer fails to convert a PeersChanged entry into a PeersChangedPatch. The stats are gated behind the TS_DEBUG_PATCHIFY_PEER_MISS envknob so there is zero overhead in normal operation. peerChangeDiff now takes an optional onFalse callback that is called with the field name on every non-patchable return path. When the envknob is off, nil is passed and replaced with a no-op at the top of peerChangeDiff. The resulting metric renders as: counter_patchify_miss{why="Hostinfo"} 2 counter_patchify_miss{why="peer_not_found"} 1170 Updates tailscale/corp#40088 Change-Id: I2d4b9074bf42ec03ab296c0629a54106bafa873e Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2026-04-15control/controlclient: accept key if last seen on exist node is absent (#19402)Claus Lensbøl1-2/+3
On some nodes (found via natlab), the existing nodes last seen could be unset. For these cases, we would want to accept the key and write a last seen. This was breaking the cached netmap natlab tests. Updates #12639 Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-04-14control/controlclient: improve filter on netmap updates (#19308)Claus Lensbøl1-8/+30
The previous filters would allow for a handful of subtle issues such as updating the last seen date when the key or online status had not changed, and making online keys unconditionally make an engine update. These have been fixed along side making no change updates from TSMP into a no-op for the engine so we don't have to reconfigure. A bunch of additional testing has been added as well. Updates #12639 Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-04-08control/controlclient: avoid calls to ms.netmap() (#19281)Claus Lensbøl1-14/+10
Instead of generating the full netmap, just fetch the peers out the the existing peers map. The extra usage was introduced with netmap caching, but there is no need to call the netmap to get this information, rather the existing peermap can be used. Updates #12639 Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-04-07control/controlclient: add rwlock to peers in mapsession (#19261)Claus Lensbøl1-1/+32
After moving around locks in 4334dfa7d5ccbee1daf5acf30b33557bbca66525, a data race were made possible. Introduce an RWlock to the mapSession itself for fetching peers. Fixes #19260 Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-04-02control/controlclient: filter out disco updates from full map (#19220)Claus Lensbøl1-0/+60
When getting a full map from control, disco keys for the nodes will also be delivered. When communicating with a peer that is running without being connected to control, and having that connection running based on a TSMP learned disco key, we need to avoid overwriting the disco key for that peer with the stale one control knows about. Add a filter that filteres out keys from control, and replace them with the TSMP learned disco keys. Updates #12639 Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-03-30control/controlclient,ipn/ipnlocal,wgengine: avoid restarting wireguard when ↵Claus Lensbøl1-14/+50
key is learned via tsmp (#19142) When disco keys are learned on a node that is connected to control and has a mapSession, wgengine will see the key as having changed, and assume that any existing connections will need to be reset. For keys learned via TSMP, the connection should not be reset as that key is learned via an active wireguard connection. If wgengine resets that connetion, a 15s timeout will occur. This change adds a map to track new keys coming in via TSMP, and removes them from the list of keys that needs to trigger wireguard resets. This is done with an interface chain from controlclient down via localBackend to userspaceEngine via the watchdog. Once a key has been actively used for preventing a wireguard reset, the key is removed from the map. If mapSession becomes a long lived process instead of being dependent on having a connection to control. This interface chain can be removed, and the event sequence from wrap->controlClient->userspaceEngine, can be changed to wrap->userspaceEngine->controlClient as we know the map will not be gunked up with stale TSMP entries. Updates #12639 Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-03-20wgengine/magicsock,control/controlclient: do not overwrite discokey with old ↵Claus Lensbøl1-2/+127
key (#18606) When a client starts up without being able to connect to control, it sends its discoKey to other nodes it wants to communicate with over TSMP. This disco key will be a newer key than the one control knows about. If the client that can connect to control gets a full netmap, ensure that the disco key for the node not connected to control is not overwritten with the stale key control knows about. This is implemented through keeping track of mapSession and use that for the discokey injection if it is available. This ensures that we are not constantly resetting the wireguard connection when getting the wrong keys from control. This is implemented as: - If the key is received via TSMP: - Set lastSeen for the peer to now() - Set online for the peer to false - When processing new keys, only accept keys where either: - Peer is online - lastSeen is newer than existing last seen If mapSession is not available, as in we are not yet connected to control, punt down the disco key injection to magicsock. Ideally, we will want to have mapSession be long lived at some point in the near future so we only need to inject keys in one location and then also use that for testing and loading the cache, but that is a yak for another PR. Updates #12639 Signed-off-by: Claus Lensbøl <claus@tailscale.com>
2026-03-06all: use Go 1.26 things, run most gofix modernizersBrad Fitzpatrick1-4/+4
I omitted a lot of the min/max modernizers because they didn't result in more clear code. Some of it's older "for x := range 123". Also: errors.AsType, any, fmt.Appendf, etc. Updates #18682 Change-Id: I83a451577f33877f962766a5b65ce86f7696471c Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2026-03-05types/ptr: deprecate ptr.To, use Go 1.26 newBrad Fitzpatrick1-10/+9
Updates #18682 Change-Id: I62f6aa0de2a15ef8c1435032c6aa74a181c25f8f Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2026-01-23all: remove AUTHORS file and references to itWill Norris1-1/+1
This file was never truly necessary and has never actually been used in the history of Tailscale's open source releases. A Brief History of AUTHORS files --- The AUTHORS file was a pattern developed at Google, originally for Chromium, then adopted by Go and a bunch of other projects. The problem was that Chromium originally had a copyright line only recognizing Google as the copyright holder. Because Google (and most open source projects) do not require copyright assignemnt for contributions, each contributor maintains their copyright. Some large corporate contributors then tried to add their own name to the copyright line in the LICENSE file or in file headers. This quickly becomes unwieldy, and puts a tremendous burden on anyone building on top of Chromium, since the license requires that they keep all copyright lines intact. The compromise was to create an AUTHORS file that would list all of the copyright holders. The LICENSE file and source file headers would then include that list by reference, listing the copyright holder as "The Chromium Authors". This also become cumbersome to simply keep the file up to date with a high rate of new contributors. Plus it's not always obvious who the copyright holder is. Sometimes it is the individual making the contribution, but many times it may be their employer. There is no way for the proejct maintainer to know. Eventually, Google changed their policy to no longer recommend trying to keep the AUTHORS file up to date proactively, and instead to only add to it when requested: https://opensource.google/docs/releasing/authors. They are also clear that: > Adding contributors to the AUTHORS file is entirely within the > project's discretion and has no implications for copyright ownership. It was primarily added to appease a small number of large contributors that insisted that they be recognized as copyright holders (which was entirely their right to do). But it's not truly necessary, and not even the most accurate way of identifying contributors and/or copyright holders. In practice, we've never added anyone to our AUTHORS file. It only lists Tailscale, so it's not really serving any purpose. It also causes confusion because Tailscalars put the "Tailscale Inc & AUTHORS" header in other open source repos which don't actually have an AUTHORS file, so it's ambiguous what that means. Instead, we just acknowledge that the contributors to Tailscale (whoever they are) are copyright holders for their individual contributions. We also have the benefit of using the DCO (developercertificate.org) which provides some additional certification of their right to make the contribution. The source file changes were purely mechanical with: git ls-files | xargs sed -i -e 's/\(Tailscale Inc &\) AUTHORS/\1 contributors/g' Updates #cleanup Change-Id: Ia101a4a3005adb9118051b3416f5a64a4a45987d Signed-off-by: Will Norris <will@tailscale.com>
2025-11-18types/netmap,*: remove some redundant fields from NetMapBrad Fitzpatrick1-2/+0
Updates #12639 Change-Id: Ia50b15529bd1c002cdd2c937cdfbe69c06fa2dc8 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-11-16types/netmap: remove PrivateKey from NetworkMapBrad Fitzpatrick1-1/+0
It's an unnecessary nuisance having it. We go out of our way to redact it in so many places when we don't even need it there anyway. Updates #12639 Change-Id: I5fc72e19e9cf36caeb42cf80ba430873f67167c3 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-10-02control/controlclient: optimize zstd decode of KeepAlive messagesBrad Fitzpatrick1-0/+3
Maybe it matters? At least globally across all nodes? Fixes #17343 Change-Id: I3f61758ea37de527e16602ec1a6e453d913b3195 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-06-09health: prefix Warnables received from the control planeJames Sanderson1-1/+1
Updates tailscale/corp#27759 Signed-off-by: James Sanderson <jsanderson@tailscale.com>
2025-05-30controlclient,health,ipnlocal,tailcfg: add DisplayMessage supportJames Sanderson1-7/+28
Updates tailscale/corp#27759 Signed-off-by: James Sanderson <jsanderson@tailscale.com>
2025-05-22control/controlclient,health,tailcfg: refactor control health messages (#15839)James 'zofrex' Sanderson1-1/+21
* control/controlclient,health,tailcfg: refactor control health messages Updates tailscale/corp#27759 Signed-off-by: James Sanderson <jsanderson@tailscale.com> Signed-off-by: Paul Scott <408401+icio@users.noreply.github.com> Co-authored-by: Paul Scott <408401+icio@users.noreply.github.com>
2025-04-02all: use network less when running in v86 emulatorBrad Fitzpatrick1-0/+26
Updates #5794 Change-Id: I1d8b005a1696835c9062545f87b7bab643cfc44d Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-03-07wgengine/magicsock: use learned DERP route as send path of last resortBrad Fitzpatrick1-0/+3
If we get a packet in over some DERP and don't otherwise know how to reply (no known DERP home or UDP endpoint), this makes us use the DERP connection on which we received the packet to reply. This will almost always be our own home DERP region. This is particularly useful for large one-way nodes (such as hello.ts.net) that don't actively reach out to other nodes, so don't need to be told the DERP home of peers. They can instead learn the DERP home upon getting the first connection. This can also help nodes from a slow or misbehaving control plane. Updates tailscale/corp#26438 Change-Id: I6241ec92828bf45982e0eb83ad5c7404df5968bc Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-02-14control/controlclient,tailcfg:types: remove MaxKeyduration from NetMapJames Sanderson1-5/+0
This reverts most of 124dc10261ea (#10401). Removing in favour of adding this in CapMaps instead (#14829). Updates tailscale/corp#16016 Signed-off-by: James Sanderson <jsanderson@tailscale.com>
2025-02-11Revert "control/controlclient: delete unreferenced mapSession UserProfiles"Brad Fitzpatrick1-30/+1
This reverts commit 413fb5b93311972e3a8d724bb696607ef3afe6f2. See long story in #14992 Updates #14992 Updates tailscale/corp#26058 Change-Id: I3de7d080443efe47cbf281ea20887a3caf202488 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-02-11types/netmap,*: pass around UserProfiles as views (pointers) insteadBrad Fitzpatrick1-4/+4
Smaller. Updates tailscale/corp#26058 (@andrew-d noticed during this) Change-Id: Id33cddd171aaf8f042073b6d3c183b0a746e9931 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-01-24control/controlclient: sanitize invalid DERPMap nil Region from controlBrad Fitzpatrick1-0/+9
Fixes #14752 Change-Id: If364603eefb9ac6dc5ec6df84a0d5e16c94dda8d Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-01-23control/controlclient: delete unreferenced mapSession UserProfilesBrad Fitzpatrick1-1/+30
This was a slow memory leak on busy tailnets with lots of tagged ephemeral nodes. Updates tailscale/corp#26058 Change-Id: I298e7d438e3ffbb3cde795640e344671d244c632 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-01-15tailcfg,control/controlclient: treat nil AllowedIPs as Addresses [capver 112]Brad Fitzpatrick1-0/+4
Updates #14635 Change-Id: I21e2bd1ec4eb384eb7a3fc8379f0788a684893f3 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-01-14all: add Node.HomeDERP int, phase out "127.3.3.40:$region" hack [capver 111]Brad Fitzpatrick1-13/+36
This deprecates the old "DERP string" packing a DERP region ID into an IP:port of 127.3.3.40:$REGION_ID and just uses an integer, like PeerChange.DERPRegion does. We still support servers sending the old form; they're converted to the new form internally right when they're read off the network. Updates #14636 Change-Id: I9427ec071f02a2c6d75ccb0fcbf0ecff9f19f26f Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-01-14cmd/viewer,types/views,various: avoid allocations in pointer field getters ↵Nick Khyl1-8/+6
whenever possible In this PR, we add a generic views.ValuePointer type that can be used as a view for pointers to basic types and struct types that do not require deep cloning and do not have corresponding view types. Its Get/GetOk methods return stack-allocated shallow copies of the underlying value. We then update the cmd/viewer codegen to produce getters that return either concrete views when available or ValuePointer views when not, for pointer fields in generated view types. This allows us to avoid unnecessary allocations compared to returning pointers to newly allocated shallow copies. Updates #14570 Signed-off-by: Nick Khyl <nickk@tailscale.com>
2025-01-04all: use iterators in more places instead of Range funcsBrad Fitzpatrick1-9/+11
And misc cleanup along the way. Updates #12912 Change-Id: I0cab148b49efc668c6f5cdf09c740b84a713e388 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-01-03control/controlclient: remove optimization that was more convoluted than usefulBrad Fitzpatrick1-44/+24
While working on #13390, I ran across this non-idiomatic pointer-to-view and parallel-sorted-map accounting code that was all just to avoid a sort later. But the sort later when building a new netmap.NetworkMap is already a drop in the bucket of CPU compared to how much work & allocs mapSession.netmap and LocalBackend's spamming of the full netmap (potentially tens of thousands of peers, MBs of JSON) out to IPNBus clients for any tiny little change (node changing online status, etc). Removing the parallel sorted slice let everything be simpler to reason about, so this does that. The sort might take a bit more CPU time now in theory, but in practice for any netmap size for which it'd matter, the quadratic netmap IPN bus spam (which we need to fix soon) will overshadow that little sort. Updates #13390 Updates #1909 Change-Id: I3092d7c67dc10b2a0f141496fe0e7e98ccc07712 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-09-04all: use new Go 1.23 slices.Sorted moreBrad Fitzpatrick1-4/+1
Updates #12912 Change-Id: If1294e5bc7b5d3cf0067535ae10db75e8b988d8b Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-05-06tailcfg,all: add/plumb Node.IsJailedMaisem Ali1-0/+4
This adds a new bool that can be sent down from control to do jailing on the client side. Previously this would only be done from control by modifying the packet filter we sent down to clients. This would result in a lot of additional work/CPU on control, we could instead just do this on the client. This has always been a TODO which we keep putting off, might as well do it now. Updates tailscale/corp#19623 Signed-off-by: Maisem Ali <maisem@tailscale.com>
2024-04-16all: use Go 1.22 range-over-intBrad Fitzpatrick1-1/+1
Updates #11058 Change-Id: I35e7ef9b90e83cac04ca93fd964ad00ed5b48430 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-03-24all: deprecate Node.Capabilities (more), remove PeerChange.Capabilities ↵Brad Fitzpatrick1-10/+12
[capver 89] First we had Capabilities []string. Then https://tailscale.com/blog/acl-grants (#4217) brought CapMap, a superset of Capabilities. Except we never really finished the transition inside the codebase to go all-in on CapMap. This does so. Notably, this coverts Capabilities on the wire early to CapMap internally so the code can only deal in CapMap, even against an old control server. In the process, this removes PeerChange.Capabilities support, which no known control plane sent anyway. They can and should use PeerChange.CapMap instead. Updates #11508 Updates #4217 Change-Id: I872074e226b873f9a578d9603897b831d50b25d9 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-03-22ipn/ipnlocal, types/netmap: replace hasCapability with set lookup on NetworkMapBrad Fitzpatrick1-0/+12
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>
2024-03-22control/controlclient: free memory on iOS before full netmap workBrad Fitzpatrick1-0/+8
Updates tailscale/corp#18514 Change-Id: I8d0330334b030ed8692b25549a0ee887ac6d7188 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-03-20control/controlclient: do not alias peer CapMapAdrian Dewhurst1-2/+3
Updates #cleanup Change-Id: I10fd5e04310cdd7894a3caa3045b86eb0a06b6a0 Signed-off-by: Adrian Dewhurst <adrian@tailscale.com>
2024-03-19control/controlclient: fix sending peer capmap changes (#11457)Claire Wang1-2/+15
Instead of just checking if a peer capmap is nil, compare the previous state peer capmap with the new peer capmap. Updates tailscale/corp#17516 Signed-off-by: Claire Wang <claire@tailscale.com>
2024-02-25all: remove LenIter, use Go 1.22 range-over-int insteadBrad Fitzpatrick1-1/+1
Updates #11058 Updates golang/go#65685 Change-Id: Ibb216b346e511d486271ab3d84e4546c521e4e22 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-02-08all: use reflect.TypeFor now available in Go 1.22 (#11078)Joe Tsai1-1/+1
Updates #cleanup Signed-off-by: Joe Tsai <joetsai@digital-static.net>
2024-02-07util/cmpx: delete now that we're using Go 1.22Brad Fitzpatrick1-3/+3
Updates #11058 Change-Id: I09dea8e86f03ec148b715efca339eab8b1f0f644 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-01-05controlclient,tailcfg,types: expose MaxKeyDuration via localapi (#10401)James 'zofrex' Sanderson1-0/+5
Updates tailscale/corp#16016 Signed-off-by: James Sanderson <jsanderson@tailscale.com>
2023-12-21all: cleanup unused code, part 2 (#10670)Andrew Lytvynov1-42/+0
And enable U1000 check in staticcheck. Updates #cleanup Signed-off-by: Andrew Lytvynov <awly@tailscale.com>
2023-11-17control/controlclient: support incremental packet filter updates [capver 81]Brad Fitzpatrick1-3/+35
Updates #10299 Change-Id: I87e4235c668a1db7de7ef1abc743f0beecb86d3d Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2023-11-05control/controlclient: move watchdog out of mapSessionBrad Fitzpatrick1-40/+6
In prep for making mapSession's lifetime not be 1:1 with a single HTTP response's lifetime, this moves the inactivity timer watchdog out of mapSession and into the caller that owns the streaming HTTP response. (This is admittedly closer to how it was prior to the mapSession type existing, but that was before we connected some dots which were impossible to even see before the mapSession type broke the code up.) Updates #7175 Change-Id: Ia108dac84a4953db41cbd30e73b1de4a2a676c11 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2023-11-05control/controlclient: move lastPrintMap field from Direct to mapSessionBrad Fitzpatrick1-12/+22
It was a really a mutable field owned by mapSession that we didn't move in earlier commits. Once moved, it's then possible to de-func-ify the code and turn it into a regular method rather than an installed optional hook. Noticed while working to move map session lifetimes out of Direct.sendMapRequest's single-HTTP-connection scope. Updates #7175 Updates #cleanup Change-Id: I6446b15793953d88d1cabf94b5943bb3ccac3ad9 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2023-09-18all: declare & plumb IPv6 masquerade address for peerTom DNetto1-0/+8
This PR plumbs through awareness of an IPv6 SNAT/masquerade address from the wire protocol through to the low-level (tstun / wgengine). This PR is the first in two PRs for implementing IPv6 NAT support to/from peers. A subsequent PR will implement the data-plane changes to implement IPv6 NAT - this is just plumbing. Signed-off-by: Tom DNetto <tom@tailscale.com> Updates ENG-991
2023-09-18tailcfg: add NodeCapMapMaisem Ali1-1/+11
Like PeerCapMap, add a field to `tailcfg.Node` which provides a map of Capability to raw JSON messages which are deferred to be parsed later by the application code which cares about the specific capabilities. This effectively allows us to prototype new behavior without having to commit to a schema in tailcfg, and it also opens up the possibilities to develop custom behavior in tsnet applications w/o having to plumb through application specific data in the MapResponse. Updates #4217 Signed-off-by: Maisem Ali <maisem@tailscale.com>
2023-09-18types/netmap: remove NetworkMap.{Addresses,MachineStatus}Brad Fitzpatrick1-6/+0
And convert all callers over to the methods that check SelfNode. Now we don't have multiple ways to express things in tests (setting fields on SelfNode vs NetworkMap, sometimes inconsistently) and don't have multiple ways to check those two fields (often only checking one or the other). Updates #9443 Change-Id: I2d7ba1cf6556142d219fae2be6f484f528756e3c Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2023-09-15tailcfg: add DNS address list for IsWireGuardOnly nodesJames Tucker1-0/+13
Tailscale exit nodes provide DNS service over the peer API, however IsWireGuardOnly nodes do not have a peer API, and instead need client DNS parameters passed in their node description. For Mullvad nodes this will contain the in network 10.64.0.1 address. Updates #9377 Signed-off-by: James Tucker <james@tailscale.com>
2023-09-12control/controlknobs: move more controlknobs code from controlclientBrad Fitzpatrick1-1/+1
Updates #cleanup Change-Id: I2b8b6ac97589270f307bfb20e33674894ce873b5 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>