wgengine,ipn/ipnlocal: remove Engine.PeerKeyForIP and the engine's peer route table

The engine kept its own longest-prefix-match table (peerByIPRoute),
rebuilt from the full peer list on every reconfig, to route outbound
packets and answer PeerKeyForIP. That's now the route manager's job:
LocalBackend already installs a PeerByIPPacketFunc backed by the
RouteManager's incrementally-maintained outbound table, so the
engine's copy was redundant state with redundant O(n peers) rebuild
work.

Delete the table, the PeerKeyForIP interface method, and the BART-only
default callback. LocalBackend's peerForIP now queries the
RouteManager's outbound table directly for the subnet-route and
exit-node fallback. Engines running without a LocalBackend (such as
wgengine/bench) must install their own outbound peer lookup, since the
device's standard AllowedIPs trie only covers peers that already
exist and can't lazily create them.

Updates #12542

Change-Id: I25100399e273ed6c2bb1f6136b7cd81bc83e7313
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2026-07-13 14:38:55 -07:00
committed by Brad Fitzpatrick
parent 3c800dcd71
commit 2506ede862
6 changed files with 37 additions and 89 deletions
+8 -6
View File
@@ -9489,6 +9489,7 @@ 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) {
@@ -9515,19 +9516,19 @@ func TestEnginePeerForIPAdjustsForPrefs(t *testing.T) {
wantKey := func(ip string, n tailcfg.NodeView) {
t := curT
t.Helper()
pk, _, ok := eng.PeerKeyForIP(netip.MustParseAddr(ip))
pr, ok := curLB.currentNode().routeMgr.Outbound().Lookup(netip.MustParseAddr(ip))
if !ok {
t.Fatalf("PeerKeyForIP(%s): ok=false, want true", ip)
t.Fatalf("routeMgr.Outbound().Lookup(%s): ok=false, want true", ip)
}
if pk != n.Key() {
t.Fatalf("PeerKeyForIP(%s): key=%v, want %v", ip, pk, n.Key())
if pr.Key != n.Key() {
t.Fatalf("routeMgr.Outbound().Lookup(%s): key=%v, want %v", ip, pr.Key, n.Key())
}
}
wantNotKey := func(ip string) {
t := curT
t.Helper()
if _, _, ok := eng.PeerKeyForIP(netip.MustParseAddr(ip)); ok {
t.Fatalf("PeerKeyForIP(%s): ok=true, want false", ip)
if _, ok := curLB.currentNode().routeMgr.Outbound().Lookup(netip.MustParseAddr(ip)); ok {
t.Fatalf("routeMgr.Outbound().Lookup(%s): ok=true, want false", ip)
}
}
wantSelf := func(ip string) {
@@ -9663,6 +9664,7 @@ func TestEnginePeerForIPAdjustsForPrefs(t *testing.T) {
})
eng = lb.sys.Engine.Get()
curLB = lb
curT = t
tt.check()
})
+2 -2
View File
@@ -143,11 +143,11 @@ func (b *LocalBackend) peerForIP(ip netip.Addr) (_ wgengine.PeerForIP, ok bool)
}
}
pk, route, ok := b.e.PeerKeyForIP(ip)
route, pr, ok := nb.routeMgr.Outbound().LookupPrefixLPM(netip.PrefixFrom(ip, ip.BitLen()))
if !ok {
return wgengine.PeerForIP{}, false
}
nid, ok := nb.NodeByKey(pk)
nid, ok := nb.NodeByKey(pr.Key)
if !ok {
return wgengine.PeerForIP{}, false
}
-3
View File
@@ -2019,9 +2019,6 @@ func (e *mockEngine) SetPeerForIPFunc(func(netip.Addr) (_ wgengine.PeerForIP, ok
func (e *mockEngine) SetPeerConfigFunc(func(key.NodePublic) (allowedIPs []netip.Prefix, ok bool)) {
}
func (e *mockEngine) SyncDevicePeer(key.NodePublic) {}
func (e *mockEngine) PeerKeyForIP(netip.Addr) (_ key.NodePublic, _ netip.Prefix, ok bool) {
return key.NodePublic{}, netip.Prefix{}, false
}
func (e *mockEngine) SetPeerSessionStateFunc(func(key.NodePublic, wgengine.PeerWireGuardState)) {
}
func (e *mockEngine) SetNetLogSource(wgengine.NetLogSource) {}