net/ipset: return all closures from named wrappers

So profiles show more useful names than just func1, func2, func3, etc.
There will still be func1 on them all, but the symbol before will say
what the lookup type is.

Updates #12486

Change-Id: I910b024a7861394eb83d07f5a899eae338cb1f22
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
pull/12502/head
Brad Fitzpatrick 3 months ago committed by Brad Fitzpatrick
parent 86e0f9b912
commit bf2d13cfa0

@ -10,11 +10,47 @@ import (
"github.com/gaissmai/bart"
"tailscale.com/types/views"
"tailscale.com/util/set"
)
// FalseContainsIPFunc is shorthand for NewContainsIPFunc(views.Slice[netip.Prefix]{}).
func FalseContainsIPFunc() func(ip netip.Addr) bool {
return func(ip netip.Addr) bool { return false }
return emptySet
}
func emptySet(ip netip.Addr) bool { return false }
func bartLookup(t *bart.Table[struct{}]) func(netip.Addr) bool {
return func(ip netip.Addr) bool {
_, ok := t.Get(ip)
return ok
}
}
func prefixContainsLoop(addrs []netip.Prefix) func(netip.Addr) bool {
return func(ip netip.Addr) bool {
for _, p := range addrs {
if p.Contains(ip) {
return true
}
}
return false
}
}
func oneIP(ip1 netip.Addr) func(netip.Addr) bool {
return func(ip netip.Addr) bool { return ip == ip1 }
}
func twoIP(ip1, ip2 netip.Addr) func(netip.Addr) bool {
return func(ip netip.Addr) bool { return ip == ip1 || ip == ip2 }
}
func ipInMap(m set.Set[netip.Addr]) func(netip.Addr) bool {
return func(ip netip.Addr) bool {
_, ok := m[ip]
return ok
}
}
// pathForTest is a test hook for NewContainsIPFunc, to test that it took the
@ -29,7 +65,7 @@ func NewContainsIPFunc(addrs views.Slice[netip.Prefix]) func(ip netip.Addr) bool
// (or just IPv6), and both IPv4 and IPv6.
if addrs.Len() == 0 {
pathForTest("empty")
return func(netip.Addr) bool { return false }
return emptySet
}
// If any addr is a prefix with more than a single IP, then do either a
// linear scan or a bart table, depending on the number of addrs.
@ -41,40 +77,27 @@ func NewContainsIPFunc(addrs views.Slice[netip.Prefix]) func(ip netip.Addr) bool
for i := range addrs.Len() {
t.Insert(addrs.At(i), struct{}{})
}
return func(ip netip.Addr) bool {
_, ok := t.Get(ip)
return ok
}
return bartLookup(t)
} else {
pathForTest("linear-contains")
// Small enough to do a linear search.
acopy := addrs.AsSlice()
return func(ip netip.Addr) bool {
for _, a := range acopy {
if a.Contains(ip) {
return true
}
}
return false
}
return prefixContainsLoop(addrs.AsSlice())
}
}
// Fast paths for 1 and 2 IPs:
if addrs.Len() == 1 {
pathForTest("one-ip")
a := addrs.At(0)
return func(ip netip.Addr) bool { return ip == a.Addr() }
return oneIP(addrs.At(0).Addr())
}
if addrs.Len() == 2 {
pathForTest("two-ip")
a, b := addrs.At(0), addrs.At(1)
return func(ip netip.Addr) bool { return ip == a.Addr() || ip == b.Addr() }
return twoIP(addrs.At(0).Addr(), addrs.At(1).Addr())
}
// General case:
pathForTest("ip-map")
m := map[netip.Addr]bool{}
m := set.Set[netip.Addr]{}
for i := range addrs.Len() {
m[addrs.At(i).Addr()] = true
m.Add(addrs.At(i).Addr())
}
return func(ip netip.Addr) bool { return m[ip] }
return ipInMap(m)
}

Loading…
Cancel
Save