diff --git a/client/firewall/uspfilter/localip.go b/client/firewall/uspfilter/localip.go index e9295dbf1..49c07ab53 100644 --- a/client/firewall/uspfilter/localip.go +++ b/client/firewall/uspfilter/localip.go @@ -11,12 +11,10 @@ import ( "github.com/netbirdio/netbird/client/firewall/uspfilter/common" ) -// localIPSnapshot is an immutable snapshot of local IP addresses. -// The entire snapshot is swapped atomically so reads are lock-free. +// localIPSnapshot is an immutable snapshot of local IP addresses, swapped +// atomically so reads are lock-free. type localIPSnapshot struct { ips map[netip.Addr]struct{} - // loopbackV4 is pre-checked to avoid map lookups for 127.0.0.0/8 - loopbackV4 bool } type localIPManager struct { @@ -95,10 +93,7 @@ func (m *localIPManager) UpdateLocalIPs(iface common.IFaceMapper) (err error) { } } - m.snapshot.Store(&localIPSnapshot{ - ips: ips, - loopbackV4: true, - }) + m.snapshot.Store(&localIPSnapshot{ips: ips}) log.Debugf("Local IP addresses: %v", addresses) return nil @@ -108,11 +103,8 @@ func (m *localIPManager) UpdateLocalIPs(iface common.IFaceMapper) (err error) { func (m *localIPManager) IsLocalIP(ip netip.Addr) bool { s := m.snapshot.Load() - // Fast path for 127.x.x.x without map lookup - if s.loopbackV4 && ip.Is4() { - if ip.As4()[0] == 127 { - return true - } + if ip.Is4() && ip.As4()[0] == 127 { + return true } _, found := s.ips[ip] diff --git a/client/firewall/uspfilter/localip_bench_test.go b/client/firewall/uspfilter/localip_bench_test.go new file mode 100644 index 000000000..11bdee7ab --- /dev/null +++ b/client/firewall/uspfilter/localip_bench_test.go @@ -0,0 +1,70 @@ +package uspfilter + +import ( + "net/netip" + "testing" + + "github.com/netbirdio/netbird/client/iface/wgaddr" +) + +func setupManager(b *testing.B) *localIPManager { + b.Helper() + m := newLocalIPManager() + mock := &IFaceMock{ + AddressFunc: func() wgaddr.Address { + return wgaddr.Address{ + IP: netip.MustParseAddr("100.64.0.1"), + Network: netip.MustParsePrefix("100.64.0.0/16"), + IPv6: netip.MustParseAddr("fd00::1"), + IPv6Net: netip.MustParsePrefix("fd00::/64"), + } + }, + } + _ = m.UpdateLocalIPs(mock) + return m +} + +func BenchmarkIsLocalIP_v4_hit(b *testing.B) { + m := setupManager(b) + ip := netip.MustParseAddr("100.64.0.1") + b.ResetTimer() + for i := 0; i < b.N; i++ { + m.IsLocalIP(ip) + } +} + +func BenchmarkIsLocalIP_v4_miss(b *testing.B) { + m := setupManager(b) + ip := netip.MustParseAddr("8.8.8.8") + b.ResetTimer() + for i := 0; i < b.N; i++ { + m.IsLocalIP(ip) + } +} + +func BenchmarkIsLocalIP_v6_hit(b *testing.B) { + m := setupManager(b) + ip := netip.MustParseAddr("fd00::1") + b.ResetTimer() + for i := 0; i < b.N; i++ { + m.IsLocalIP(ip) + } +} + +func BenchmarkIsLocalIP_v6_miss(b *testing.B) { + m := setupManager(b) + ip := netip.MustParseAddr("2001:db8::1") + b.ResetTimer() + for i := 0; i < b.N; i++ { + m.IsLocalIP(ip) + } +} + +func BenchmarkIsLocalIP_loopback(b *testing.B) { + m := setupManager(b) + ip := netip.MustParseAddr("127.0.0.1") + b.ResetTimer() + for i := 0; i < b.N; i++ { + m.IsLocalIP(ip) + } +} diff --git a/client/internal/connect.go b/client/internal/connect.go index f0836aa0a..4b1448e21 100644 --- a/client/internal/connect.go +++ b/client/internal/connect.go @@ -40,7 +40,6 @@ import ( "github.com/netbirdio/netbird/client/system" mgm "github.com/netbirdio/netbird/shared/management/client" mgmProto "github.com/netbirdio/netbird/shared/management/proto" - "github.com/netbirdio/netbird/shared/netiputil" "github.com/netbirdio/netbird/shared/relay/auth/hmac" relayClient "github.com/netbirdio/netbird/shared/relay/client" signal "github.com/netbirdio/netbird/shared/signal/client" @@ -530,16 +529,8 @@ func createEngineConfig(key wgtypes.Key, config *profilemanager.Config, peerConf } if !config.DisableIPv6 { - if raw := peerConfig.GetAddressV6(); len(raw) > 0 { - prefix, err := netiputil.DecodePrefix(raw) - if err != nil { - log.Warnf("decode v6 overlay address: %v", err) - } else if !prefix.Addr().Is6() { - log.Warnf("expected IPv6 overlay address, got %s", prefix.Addr()) - } else { - wgAddr.IPv6 = prefix.Addr() - wgAddr.IPv6Net = prefix.Masked() - } + if err := wgAddr.SetIPv6FromCompact(peerConfig.GetAddressV6()); err != nil { + log.Warn(err) } }