diff --git a/hostmap.go b/hostmap.go index 45515fc3..fb518552 100644 --- a/hostmap.go +++ b/hostmap.go @@ -543,6 +543,17 @@ func (hm *HostMap) unlockedDeleteHostInfo(hostinfo *HostInfo) bool { return final } +func (hm *HostMap) QueryIndexCached(index uint32, cache map[uint32]*HostInfo) *HostInfo { + if out, ok := cache[index]; ok { + return out + } + out := hm.QueryIndex(index) + if out != nil { + cache[index] = out + } + return out +} + func (hm *HostMap) QueryIndex(index uint32) *HostInfo { hm.RLock() if h, ok := hm.Indexes[index]; ok { diff --git a/interface.go b/interface.go index f384565a..2a980044 100644 --- a/interface.go +++ b/interface.go @@ -363,15 +363,17 @@ func (f *Interface) listenOut(i int) { fwPacket := &firewall.ParsedPacket{} nb := make([]byte, 12, 12) scratch := make([]byte, mtu) + hostmapCache := map[uint32]*HostInfo{} //todo is this stupid listener := func(fromUdpAddr netip.AddrPort, payload []byte) { - f.readOutsidePackets(ViaSender{UdpAddr: fromUdpAddr}, scratch, payload, h, fwPacket, lhh, nb, i, ctCache.Get()) + f.readOutsidePackets(ViaSender{UdpAddr: fromUdpAddr}, scratch, payload, h, fwPacket, lhh, nb, i, ctCache.Get(), hostmapCache) } flusher := func() { if err := f.batchers[i].Flush(); err != nil { f.l.Error("Failed to flush tun coalescer", "error", err) } + clear(hostmapCache) } err := li.ListenOut(listener, flusher) diff --git a/outside.go b/outside.go index 442e4ecd..77239ce7 100644 --- a/outside.go +++ b/outside.go @@ -26,7 +26,7 @@ var ErrOutOfWindow = errors.New("out of window packet") // readOutsidePackets processes one received underlay packet. // Message payloads are decrypted IN PLACE, so packet must stay untouched // by the caller until the batcher for queue q has been flushed -func (f *Interface) readOutsidePackets(via ViaSender, scratch []byte, packet []byte, h *header.H, fwPacket *firewall.ParsedPacket, lhf *LightHouseHandler, nb []byte, q int, localCache firewall.ConntrackCache) { +func (f *Interface) readOutsidePackets(via ViaSender, scratch []byte, packet []byte, h *header.H, fwPacket *firewall.ParsedPacket, lhf *LightHouseHandler, nb []byte, q int, localCache firewall.ConntrackCache, hmCache map[uint32]*HostInfo) { err := h.Parse(packet) if err != nil { // Hole punch packets are 0 or 1 byte big, so lets ignore printing those errors @@ -94,7 +94,7 @@ func (f *Interface) readOutsidePackets(via ViaSender, scratch []byte, packet []b if isMessageRelay { hostinfo = f.hostMap.QueryRelayIndex(h.RemoteIndex) } else { - hostinfo = f.hostMap.QueryIndex(h.RemoteIndex) + hostinfo = f.hostMap.QueryIndexCached(h.RemoteIndex, hmCache) } // At this point we should have a valid existing tunnel, verify and send @@ -124,7 +124,7 @@ func (f *Interface) readOutsidePackets(via ViaSender, scratch []byte, packet []b } return } - f.handleOutsideRelayPacket(hostinfo, via, scratch, packet, h, fwPacket, lhf, nb, q, localCache) + f.handleOutsideRelayPacket(hostinfo, via, scratch, packet, h, fwPacket, lhf, nb, q, localCache, hmCache) return } @@ -186,7 +186,7 @@ func (f *Interface) readOutsidePackets(via ViaSender, scratch []byte, packet []b } } -func (f *Interface) handleOutsideRelayPacket(hostinfo *HostInfo, via ViaSender, scratch []byte, packet []byte, h *header.H, fwPacket *firewall.ParsedPacket, lhf *LightHouseHandler, nb []byte, q int, localCache firewall.ConntrackCache) { +func (f *Interface) handleOutsideRelayPacket(hostinfo *HostInfo, via ViaSender, scratch []byte, packet []byte, h *header.H, fwPacket *firewall.ParsedPacket, lhf *LightHouseHandler, nb []byte, q int, localCache firewall.ConntrackCache, hmCache map[uint32]*HostInfo) { // Successfully validated the thing. Get rid of the Relay header and the AEAD tag signedPayload := packet[header.Len : len(packet)-hostinfo.ConnectionState.dKey.Overhead()] // Pull the Roaming parts up here, and return in all call paths. @@ -213,7 +213,7 @@ func (f *Interface) handleOutsideRelayPacket(hostinfo *HostInfo, via ViaSender, relay: relay, IsRelayed: true, } - f.readOutsidePackets(via, scratch, signedPayload, h, fwPacket, lhf, nb, q, localCache) + f.readOutsidePackets(via, scratch, signedPayload, h, fwPacket, lhf, nb, q, localCache, hmCache) case ForwardingType: // Find the target HostInfo relay object targetHI, targetRelay, err := f.hostMap.QueryVpnAddrsRelayFor(hostinfo.vpnAddrs, relay.PeerAddr)