Repository navigation
tagpeers, lansport, rendezvous: add LAN peering among tagged tailnet nodes - #1
Conversation
tomhjp
left a comment
There was a problem hiding this comment.
Just the rendevous package reviewed so far. I'll probably split my review for the other 2 packages too to break it into manageable chunks.
| } | ||
|
|
||
| type member struct { | ||
| key string |
There was a problem hiding this comment.
Tiny type for key? Reading this file, I'm getting a bit confused between member and key, because I think this key is referenced as a member in Score, and key is another thing altogether in that function signature?
| // the given name and weight: -weight / ln(u) for u uniform in (0, 1) derived | ||
| // from hashing member and key together. The member with the highest score |
There was a problem hiding this comment.
nit: the exact implementation doesn't mean much to the casual reader, and the non-casual reader can read the code. Maybe here or elsewhere we should add a reference for details of where the equations came from though?
| // the given name and weight: -weight / ln(u) for u uniform in (0, 1) derived | |
| // from hashing member and key together. The member with the highest score | |
| // the given name and weight. The member with the highest score |
| r.table.mu.RLock() | ||
| defer r.table.mu.RUnlock() |
There was a problem hiding this comment.
I don't think we should reach in and use table's mutex here - let's make a method for it
| r.table.Set(members) | ||
| r.peers.Store(&peers) |
There was a problem hiding this comment.
This looks racy, and maybe it should be protected by a Router mutex?
| t.mu.Unlock() | ||
| if changed { | ||
| t.signal() | ||
| } |
There was a problem hiding this comment.
defer this chunk higher up? The big gap after lock makes it kinda vulnerable to future bugs or panics
| t.mu.Unlock() | ||
| if changed { | ||
| t.signal() | ||
| } |
| type Tracker struct { | ||
| cfg Config | ||
| lc *local.Client | ||
| logf logger.Logf |
| cancel context.CancelFunc | ||
| done chan struct{} | ||
|
|
||
| mu sync.Mutex |
There was a problem hiding this comment.
Looks like this never composes with the subsMu lock, maybe document that?
| "github.com/tailscale/tb/tagpeers/tagpeerstest" | ||
| ) | ||
|
|
||
| func waitFor(t testing.TB, what string, f func() bool) { |
There was a problem hiding this comment.
I haven't looked in detail, but does this exist because of needing to use real network? Go 1.27 had this nifty looking release note I've been meaning to check out, which might be relevant:
The new NewTestServer function creates a Server configured to use an in-memory fake network suitable for use with the testing/synctest package.
| TrustedAddr(ip netip.Addr) bool | ||
|
|
||
| // SelfKey returns this node's own routing key, if known. | ||
| SelfKey() (string, bool) |
There was a problem hiding this comment.
Tiny type or more documentation on key?
|
|
||
| // probe fetches p's advert over the source's trusted path, rebuilds its | ||
| // transport if the pin or address changed, and checks the LAN path. | ||
| func (s *Server) probe(ctx context.Context, p *peerState) { |
There was a problem hiding this comment.
This function signature could be clearer if it took a value peerState and returned another value with all the mutations it made. As it is, it's not clear whose state we're mutating when we update this pointer in-place in the function, and it looks like it complicates the locking semantics too.
…nodes
These are the reusable layers under gocached's upcoming cache pooling for
the colo Macs, moved here so anything with the same shape can use them:
a set of tailnet nodes on one LAN that want to exchange bulk traffic
directly, without pushing every byte through magicsock/wireguard, while
still getting their trust from the tailnet.
tagpeers watches tailscaled's IPN bus and keeps the set of nodes
carrying a tag, as the control plane sees it; no
reachability analysis.
lansport turns those nodes into working connections: each process
serves a plain-HTTP advert over the tailnet naming its LAN
TLS address and per-process certificate hash, fetches its
peers' adverts, pins their certificates, and maintains a
pinned *http.Transport to each reachable peer. Requests
from peers arrive on a TLS listener that admits only
pinned certificates.
rendezvous weighted rendezvous hashing over a changing member set,
and a router that picks which lansport peer, if any,
should handle a key.
tagpeerstest has a fake tailscaled serving the IPN bus watch endpoint
for testing code built on these.
Updates tailscale/corp#48514
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Change-Id: I7b2f9c41d8e3a65f0c2d4b8e1a9f3c7d5e6b0a12
dba52ea to
ddca591
Compare
|
All done. |
These are the reusable layers under gocached's upcoming cache pooling for
the colo Macs, moved here so anything with the same shape can use them:
a set of tailnet nodes on one LAN that want to exchange bulk traffic
directly, without pushing every byte through magicsock/wireguard, while
still getting their trust from the tailnet.
tagpeers watches tailscaled's IPN bus and keeps the set of nodes
carrying a tag, as the control plane sees it; no
reachability analysis.
lansport turns those nodes into working connections: each process
serves a plain-HTTP advert over the tailnet naming its LAN
TLS address and per-process certificate hash, fetches its
peers' adverts, pins their certificates, and maintains a
pinned *http.Transport to each reachable peer. Requests
from peers arrive on a TLS listener that admits only
pinned certificates.
rendezvous weighted rendezvous hashing over a changing member set,
and a router that picks which lansport peer, if any,
should handle a key.
tagpeerstest has a fake tailscaled serving the IPN bus watch endpoint
for testing code built on these.
Updates tailscale/corp#48514