wgengine/filter: use NewContainsIPFunc for Srcs matches

NewContainsIPFunc returns a contains matcher optimized for its
input. Use that instead of what this did before, always doing a test
over each of a list of netip.Prefixes.

    goos: darwin
    goarch: arm64
    pkg: tailscale.com/wgengine/filter
                        │   before    │                after                │
                        │   sec/op    │   sec/op     vs base                │
    FilterMatch/file1-8   32.60n ± 1%   18.87n ± 1%  -42.12% (p=0.000 n=10)

Updates #12486

Change-Id: I8f902bc064effb431e5b46751115942104ff6531
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2024-06-15 18:20:17 -07:00
committed by Brad Fitzpatrick
parent e2c0d69c9c
commit 21ed31e33a
5 changed files with 55 additions and 42 deletions

View File

@@ -66,10 +66,11 @@ type CapMatch struct {
// Match matches packets from any IP address in Srcs to any ip:port in
// Dsts.
type Match struct {
IPProto []ipproto.Proto // required set (no default value at this layer)
Srcs []netip.Prefix
Dsts []NetPortRange // optional, if Srcs match
Caps []CapMatch // optional, if Srcs match
IPProto []ipproto.Proto // required set (no default value at this layer)
Srcs []netip.Prefix
SrcsContains func(netip.Addr) bool `json:"-"` // report whether Addr is in Srcs
Dsts []NetPortRange // optional, if Srcs match
Caps []CapMatch // optional, if Srcs match
}
func (m Match) String() string {
@@ -104,7 +105,7 @@ func (ms matches) match(q *packet.Parsed) bool {
if !slices.Contains(m.IPProto, q.IPProto) {
continue
}
if !ipInList(q.Src.Addr(), m.Srcs) {
if !m.SrcsContains(q.Src.Addr()) {
continue
}
for _, dst := range m.Dsts {
@@ -122,7 +123,7 @@ func (ms matches) match(q *packet.Parsed) bool {
func (ms matches) matchIPsOnly(q *packet.Parsed) bool {
for _, m := range ms {
if !ipInList(q.Src.Addr(), m.Srcs) {
if !m.SrcsContains(q.Src.Addr()) {
continue
}
for _, dst := range m.Dsts {
@@ -142,7 +143,7 @@ func (ms matches) matchProtoAndIPsOnlyIfAllPorts(q *packet.Parsed) bool {
if !slices.Contains(m.IPProto, q.IPProto) {
continue
}
if !ipInList(q.Src.Addr(), m.Srcs) {
if !m.SrcsContains(q.Src.Addr()) {
continue
}
for _, dst := range m.Dsts {
@@ -156,12 +157,3 @@ func (ms matches) matchProtoAndIPsOnlyIfAllPorts(q *packet.Parsed) bool {
}
return false
}
func ipInList(ip netip.Addr, netlist []netip.Prefix) bool {
for _, net := range netlist {
if net.Contains(ip) {
return true
}
}
return false
}