<feed xmlns='http://www.w3.org/2005/Atom'>
<title>tailscale, branch fserb/main</title>
<subtitle>The easiest, most secure way to use WireGuard and 2FA</subtitle>
<id>http://git.waynecole.info/tailscale/atom?h=fserb%2Fmain</id>
<link rel='self' href='http://git.waynecole.info/tailscale/atom?h=fserb%2Fmain'/>
<link rel='alternate' type='text/html' href='http://git.waynecole.info/tailscale/'/>
<updated>2026-04-22T22:13:09Z</updated>
<entry>
<title>misc/genreadme,tempfork/pkgdoc,tsnet: generate README.md files from godoc</title>
<updated>2026-04-22T22:13:09Z</updated>
<author>
<name>Brad Fitzpatrick</name>
<email>bradfitz@tailscale.com</email>
</author>
<published>2026-04-22T21:08:16Z</published>
<link rel='alternate' type='text/html' href='http://git.waynecole.info/tailscale/commit/?id=a7d8aeb8aebc4bb01066eb6ffa69b9d8fe178b81'/>
<id>urn:sha1:a7d8aeb8aebc4bb01066eb6ffa69b9d8fe178b81</id>
<content type='text'>
Adds a CI check to keep opted-in directories' README.md files in sync
with their package godoc. For now tsnet (and its sub-packages under
tsnet/example) is the only opted-in tree. The list of directories
lives in misc/genreadme/genreadme.go as defaultRoots, so CI and humans
both just run `./tool/go run ./misc/genreadme` with no arguments.

The check piggybacks on the existing go_generate job in test.yml and
fails if any README.md is out of date, pointing the user at the same
command.

Along the way:

 - tempfork/pkgdoc now emits Markdown instead of plain text: headings
   become level-2 with no {#hdr-...} anchors, and [Symbol] doc links
   resolve to pkg.go.dev URLs, including for symbols in the current
   package (which the default Printer would otherwise emit as bare
   #Name fragments with no backing anchor in a README). Parsing no
   longer uses parser.ImportsOnly, so doc.Package knows the package's
   symbols and can resolve [Symbol] links at all.

 - genreadme also emits a pkg.go.dev Go Reference badge at the top of
   a library package's README; suppressed for package main.

 - tsnet/tsnet.go's package godoc is expanded in idiomatic godoc
   syntax — [Type], [Type.Method], reference-style [link]: URL
   definitions — rather than Markdown-flavored [text](url) or
   backtick-quoted identifiers, so that both pkg.go.dev and the
   generated README.md render cleanly from a single source.

Fixes #19431
Fixes #19483
Fixes #19470

Change-Id: I8ca37e9e7b3bd446b8bfa7a91ac548f142688cb1
Co-authored-by: Brad Fitzpatrick &lt;bradfitz@tailscale.com&gt;
Signed-off-by: Walter Poupore &lt;walterp@tailscale.com&gt;
Signed-off-by: Brad Fitzpatrick &lt;bradfitz@tailscale.com&gt;
</content>
</entry>
<entry>
<title>wgengine/magicsock: replace peers slice with peersByID map; add Upsert/RemovePeer</title>
<updated>2026-04-22T22:07:11Z</updated>
<author>
<name>Brad Fitzpatrick</name>
<email>bradfitz@tailscale.com</email>
</author>
<published>2026-04-21T19:19:35Z</published>
<link rel='alternate' type='text/html' href='http://git.waynecole.info/tailscale/commit/?id=311dd3839da3b41c515eec87d3dc040861e6dea6'/>
<id>urn:sha1:311dd3839da3b41c515eec87d3dc040861e6dea6</id>
<content type='text'>
Replace Conn.peers (sorted views.Slice) with peersByID, a
map[tailcfg.NodeID]tailcfg.NodeView. The only caller that needed
the sorted slice (the disco message receive path's binary search)
becomes a single map lookup. Drop nodesEqual.

Add Conn.UpsertPeer / Conn.RemovePeer for O(1) single-peer endpoint
work. RemovePeer also performs a targeted single-disco-key cleanup
(previously that scan was O(discoInfo)).

Extract the shared per-peer upsert body as upsertPeerLocked; still
used by SetNetworkMap's bulk path. SetNetworkMap is documented as
the bulk / initial / self-change path; UpsertPeer and RemovePeer
are preferred for single-peer changes.

Make the relay server set update O(1) per peer: add serverUpsertCh
/ serverRemoveCh to relayManager with matching run-loop handlers.
UpsertPeer / RemovePeer evaluate the per-peer relay predicate
locally and dispatch upsert or remove. The full-rebuild
updateRelayServersSet stays for the initial netmap, filter
changes, and fallback.

Move the hasPeerRelayServers atomic from Conn onto relayManager,
next to the serversByNodeKey map it summarizes. The run loop is
now the single writer and needs no back-pointer to Conn;
endpoint's two hot-path readers take one extra hop to
de.c.relayManager.hasPeerRelayServers but the cost is the same
atomic load.

No callers use UpsertPeer/RemovePeer yet; a subsequent change will
plumb per-peer add/remove through the incremental map update path.

Updates #12542

Change-Id: If6a3442fe29ccbd77890ea61b754a4d1ad6ef225
Signed-off-by: Brad Fitzpatrick &lt;bradfitz@tailscale.com&gt;
</content>
</entry>
<entry>
<title>tstest/natlab/vmtest,cmd/tta: add TestSiteToSite</title>
<updated>2026-04-22T19:11:30Z</updated>
<author>
<name>Brad Fitzpatrick</name>
<email>bradfitz@tailscale.com</email>
</author>
<published>2026-04-22T03:39:15Z</published>
<link rel='alternate' type='text/html' href='http://git.waynecole.info/tailscale/commit/?id=f289f7e77c66c4870897eb21f1b3a0ba6e83bb14'/>
<id>urn:sha1:f289f7e77c66c4870897eb21f1b3a0ba6e83bb14</id>
<content type='text'>
Verifies that site-to-site Tailscale subnet routing with
--snat-subnet-routes=false preserves the original source IP
end-to-end.

Topology: two sites, each with a Linux subnet router on a NATted WAN
plus an internal LAN, and a non-Tailscale backend on each LAN. Backends
are given static routes pointing to their local subnet router for the
remote site's prefix; an HTTP GET from backend-a to backend-b over
Tailscale returns a body containing backend-a's LAN IP.

Adds the supporting vmtest.SNATSubnetRoutes NodeOption and plumbs
snat-subnet-routes through TTA's /up handler. The webserver started by
vmtest.WebServer now also echoes the remote IP, for the preservation
assertion.

Adds a /add-route TTA endpoint (Linux-only for now) and a vmtest
Env.AddRoute helper so the test can install the backend static routes
through TTA rather than needing a host SSH key and debug NIC.

ensureGokrazy now always rebuilds the natlab qcow2 (once per test
process, via sync.Once) so the test picks up the new TTA and webserver
behavior.

This is pulled out of a larger pending change that adds FreeBSD
site-to-site subnet routing support; figured we should have at least
the Linux test covering what works today.

Updates #5573

Change-Id: I881c55b0f118ac9094546b5fbe68dddf179bb042
Signed-off-by: Brad Fitzpatrick &lt;bradfitz@tailscale.com&gt;
</content>
</entry>
<entry>
<title>cmd/tsnet-proxy: add tsnet-based port proxy tool (#19468)</title>
<updated>2026-04-22T17:34:18Z</updated>
<author>
<name>Fernando Serboncini</name>
<email>fserb@tailscale.com</email>
</author>
<published>2026-04-22T17:34:18Z</published>
<link rel='alternate' type='text/html' href='http://git.waynecole.info/tailscale/commit/?id=81fbcc1ac8c6ba8f2f67e21f9a9a4cfa44d31148'/>
<id>urn:sha1:81fbcc1ac8c6ba8f2f67e21f9a9a4cfa44d31148</id>
<content type='text'>
Exposes a local port on the tailnet under a chosen hostname. Raw TCP by
default; --http or --https reverse-proxy with Tailscale-User-* identity
headers from WhoIs, matching tailscaled's serve header conventions.

Useful as a one-shot to put a dev server on the tailnet.

Fixes #19467

Change-Id: I79f63cfbbedf7e40cf0f1f51cbae8df86ae90cdf

Signed-off-by: Fernando Serboncini &lt;fserb@tailscale.com&gt;</content>
</entry>
<entry>
<title>ipn/ipnlocal: deflake TestStateMachine{,Seamless} (#19475)</title>
<updated>2026-04-22T09:22:47Z</updated>
<author>
<name>James 'zofrex' Sanderson</name>
<email>jsanderson@tailscale.com</email>
</author>
<published>2026-04-22T09:22:47Z</published>
<link rel='alternate' type='text/html' href='http://git.waynecole.info/tailscale/commit/?id=36f094ea3b06e6e87aaab756c3d69c09c60ad3a8'/>
<id>urn:sha1:36f094ea3b06e6e87aaab756c3d69c09c60ad3a8</id>
<content type='text'>
Remove the remaining known sources of flakiness in TestStateMachine and
TestStateMachineSeamless.

Updates tailscale/corp#36230
Updates #19377

Signed-off-by: James Sanderson &lt;jsanderson@tailscale.com&gt;</content>
</entry>
<entry>
<title>tool/listpkgs: add --has-go-generate filter flag too</title>
<updated>2026-04-22T00:51:13Z</updated>
<author>
<name>Brad Fitzpatrick</name>
<email>bradfitz@tailscale.com</email>
</author>
<published>2026-04-22T00:42:20Z</published>
<link rel='alternate' type='text/html' href='http://git.waynecole.info/tailscale/commit/?id=12813dee02a4537f8fd89d562f319d1caef5013b'/>
<id>urn:sha1:12813dee02a4537f8fd89d562f319d1caef5013b</id>
<content type='text'>
For use in parallelizing go:generate up-to-date checks.

Updates tailscale/corp#28679

Change-Id: Ifc31c56de4225ba2e0fc048b0f18974dc2f2fc82
Signed-off-by: Brad Fitzpatrick &lt;bradfitz@tailscale.com&gt;
</content>
</entry>
<entry>
<title>feature/conn25: add expiresAt field to addrs</title>
<updated>2026-04-21T21:22:39Z</updated>
<author>
<name>Fran Bull</name>
<email>fran@tailscale.com</email>
</author>
<published>2026-04-20T16:40:12Z</published>
<link rel='alternate' type='text/html' href='http://git.waynecole.info/tailscale/commit/?id=d7916d4369bd2b880281e38edac2f600d5ab2673'/>
<id>urn:sha1:d7916d4369bd2b880281e38edac2f600d5ab2673</id>
<content type='text'>
And use it to allow overwrites of old address assignments in the conn25 client.

The magic and transit address pools from which the addresses come are limited
resources and we want to reuse them. This commit is a small part of that bigger
need.

We expect to follow soon:
 * Extending expiry if assignments are still in use.
 * Returning expired addresses back to the pools so they can be reallocated.

Updates tailscale/corp#39975

Signed-off-by: Fran Bull &lt;fran@tailscale.com&gt;
</content>
</entry>
<entry>
<title>feature/conn25: move byConnKey from addrAssignments to client</title>
<updated>2026-04-21T21:22:39Z</updated>
<author>
<name>Fran Bull</name>
<email>fran@tailscale.com</email>
</author>
<published>2026-04-16T21:15:52Z</published>
<link rel='alternate' type='text/html' href='http://git.waynecole.info/tailscale/commit/?id=19544b4b8173ae1eecbca3fa0a19514b64250428'/>
<id>urn:sha1:19544b4b8173ae1eecbca3fa0a19514b64250428</id>
<content type='text'>
addrAssignments is a table of addrs with lookup indices, representing
the assignments of magic+destination+transit IP addresses the client has
made dut to the domain being routed because of an app
.
byConnKey is a map of node public key to prefixes of transit IPs, so it
is associated with, but not that data itself, and can be its own thing.

Updates tailscale/corp#39975

Signed-off-by: Fran Bull &lt;fran@tailscale.com&gt;
</content>
</entry>
<entry>
<title>misc/genreadme: port from corp (#19477)</title>
<updated>2026-04-21T19:18:37Z</updated>
<author>
<name>Walter Poupore</name>
<email>walterp@tailscale.com</email>
</author>
<published>2026-04-21T19:18:37Z</published>
<link rel='alternate' type='text/html' href='http://git.waynecole.info/tailscale/commit/?id=04415b81774c117e0fd50112d3bb8389feaba014'/>
<id>urn:sha1:04415b81774c117e0fd50112d3bb8389feaba014</id>
<content type='text'>
also port pkgdoc, into the tempfork folder

git rev from corp at the time this copy was made:

-  e909fc93595414c90ff1339cece7c84500ab3c36

Updates #19470

Change-Id: I3d98d82020a2b336647b795210dcb7065dfa44d7


Change-Id: Ie63141860b76dd2d5ae3ff52f8a4bcdf6106421e

Signed-off-by: Walter Poupore &lt;walterp@tailscale.com&gt;</content>
</entry>
<entry>
<title>misc/git_hook: fix building git_hook in a nested worktree (#19473)</title>
<updated>2026-04-21T15:42:53Z</updated>
<author>
<name>Fernando Serboncini</name>
<email>fserb@tailscale.com</email>
</author>
<published>2026-04-21T15:42:53Z</published>
<link rel='alternate' type='text/html' href='http://git.waynecole.info/tailscale/commit/?id=1669b0d3d48310e970fb55460af34527d7bde602'/>
<id>urn:sha1:1669b0d3d48310e970fb55460af34527d7bde602</id>
<content type='text'>
When the repo is checked out as a nested worktree, a go.work in the
outer tree hijacks module resolution, which makes the rebuild fails
with "main module does not contain package." Set GOWORK=off for the
build since the hook is self-contained.

Bumps HOOK_VERSION so existing installs pick up the fix.

Updates #cleanup

Change-Id: Ibd14849efc26e4e1893c5b8e300caa71573f54bd

Signed-off-by: Fernando Serboncini &lt;fserb@fserb.com.br&gt;</content>
</entry>
</feed>
