wgengine,ipn/ipnlocal,tsnet,cmd/tailscaled: remove PeerForIP from the Engine interface

Engine.PeerForIP was pure delegation to the callback that LocalBackend
installs via SetPeerForIPFunc, so external callers going through the
engine were taking a pointless round trip: LocalBackend called
b.e.PeerForIP, which called right back into LocalBackend, and the
netstack UseNetstackForIP hooks in tsnet and tailscaled did the same
dance one layer removed.

Export LocalBackend.PeerForIP and make those callers use it directly.
The engine-internal cold paths (Ping, TSMP disco advertisements,
pendopen diagnostics) still need the lookup and have no netmap of
their own, so SetPeerForIPFunc stays on the interface, but the lookup
method itself is now unexported and gone from the Engine interface.
In tailscaled the UseNetstackForIP hook moves from netstack setup to
just after the LocalBackend is created, since the backend doesn't
exist yet when netstack is wired up.

Updates #12542

Change-Id: Ib1e1a4fa5c84ee0dcb9ce5d1910047f2bab9453c
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2026-07-13 15:15:16 -07:00
committed by Brad Fitzpatrick
parent c436dec43c
commit 9cb1147805
10 changed files with 43 additions and 62 deletions
+2 -2
View File
@@ -634,7 +634,7 @@ func NewLocalBackend(logf logger.Logf, logID logid.PublicID, sys *tsd.System, lo
e.SetPeerByIPPacketFunc(b.lookupPeerByIP)
e.SetPeerConfigFunc(b.peerAllowedIPs)
e.SetPeerForIPFunc(b.peerForIP)
e.SetPeerForIPFunc(b.PeerForIP)
e.SetPeerSessionStateFunc(b.onPeerWireGuardState)
e.SetNetLogSource(netLogNodeSource{b})
e.SetWGPeerLookup(b.lookupPeerWireGuardString)
@@ -8492,7 +8492,7 @@ func (b *LocalBackend) ResetAuth() error {
}
func (b *LocalBackend) GetPeerEndpointChanges(ctx context.Context, ip netip.Addr) ([]magicsock.EndpointChange, error) {
pip, ok := b.e.PeerForIP(ip)
pip, ok := b.PeerForIP(ip)
if !ok {
return nil, fmt.Errorf("no matching peer")
}
+3 -5
View File
@@ -9488,14 +9488,13 @@ func TestEnginePeerForIPAdjustsForPrefs(t *testing.T) {
nm := buildNetmapWithPeers(selfNode, exitA, exitB, subnetBig, subnetSmall)
var eng wgengine.Engine
var curLB *LocalBackend
var curT *testing.T // active subtest, for test helpers
wantPeer := func(ip string, n tailcfg.NodeView) {
t := curT
t.Helper()
pip, ok := eng.PeerForIP(netip.MustParseAddr(ip))
pip, ok := curLB.PeerForIP(netip.MustParseAddr(ip))
if !ok {
t.Fatalf("PeerForIP(%s): ok=false, want true", ip)
}
@@ -9509,7 +9508,7 @@ func TestEnginePeerForIPAdjustsForPrefs(t *testing.T) {
wantNotPeer := func(ip string) {
t := curT
t.Helper()
if _, ok := eng.PeerForIP(netip.MustParseAddr(ip)); ok {
if _, ok := curLB.PeerForIP(netip.MustParseAddr(ip)); ok {
t.Fatalf("PeerForIP(%s): ok=true, want false", ip)
}
}
@@ -9534,7 +9533,7 @@ func TestEnginePeerForIPAdjustsForPrefs(t *testing.T) {
wantSelf := func(ip string) {
t := curT
t.Helper()
pip, ok := eng.PeerForIP(netip.MustParseAddr(ip))
pip, ok := curLB.PeerForIP(netip.MustParseAddr(ip))
if !ok {
t.Fatalf("PeerForIP(%s): ok=false, want true", ip)
}
@@ -9663,7 +9662,6 @@ func TestEnginePeerForIPAdjustsForPrefs(t *testing.T) {
LoggedIn: true,
})
eng = lb.sys.Engine.Get()
curLB = lb
curT = t
tt.check()
+5 -3
View File
@@ -118,13 +118,15 @@ func addrFamilyMatch(ip netip.Addr, network string) bool {
return true
}
// peerForIP returns which peer is responsible for a given IP address.
// PeerForIP returns which peer is responsible for a given IP address.
// Despite the name, it can also return the self node (with IsSelf set).
// It handles both Tailscale IPs (returning the owning peer or self) and
// non-Tailscale addresses like subnet-routed IPs or exit-node global
// internet IPs (returning whichever peer would route that traffic).
// It is installed as the [wgengine.Engine.SetPeerForIPFunc] callback.
func (b *LocalBackend) peerForIP(ip netip.Addr) (_ wgengine.PeerForIP, ok bool) {
// It is installed as the [wgengine.Engine.SetPeerForIPFunc] callback,
// serving the engine's internal cold-path lookups (Ping, TSMP, pendopen
// diagnostics).
func (b *LocalBackend) PeerForIP(ip netip.Addr) (_ wgengine.PeerForIP, ok bool) {
nb := b.currentNode()
if tsaddr.IsTailscaleIP(ip) {
-4
View File
@@ -1949,10 +1949,6 @@ func (e *mockEngine) DNSConfig() *dns.Config {
return e.dnsCfg
}
func (e *mockEngine) PeerForIP(netip.Addr) (_ wgengine.PeerForIP, ok bool) {
return wgengine.PeerForIP{}, false
}
func (e *mockEngine) GetFilter() *filter.Filter {
e.mu.Lock()
defer e.mu.Unlock()