mirror of
https://github.com/AdguardTeam/AdGuardHome.git
synced 2024-11-25 06:25:44 +03:00
e3cc3b0642
Squashed commit of the following:
commit e5daef40330daf97cfd259006586fcc0196fc8e1
Merge: 7c6e63a39 cd09ba63b
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Tue Oct 24 14:06:13 2023 +0300
Merge branch 'master' into AG-26544-ipset-persistent-entries
commit 7c6e63a393a05ae9e6007af1ae539b3c70b49fda
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Mon Oct 23 16:28:34 2023 +0300
ipset: imp docs
commit cfb5d8a6573e33ed466a3767290da84e6db96167
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Fri Oct 20 18:09:01 2023 +0300
ipset: imp code
commit 4ef03c9e0066ddb10f11c653338699f8001ae0de
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Wed Oct 18 20:17:16 2023 +0300
ipset: imp docs
commit 544982b5d7d333d2575da655ebcf15b941fd74d0
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Mon Oct 16 19:05:43 2023 +0300
ipset: add persistent entries
160 lines
3.4 KiB
Go
160 lines
3.4 KiB
Go
//go:build linux
|
|
|
|
package ipset
|
|
|
|
import (
|
|
"net"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/AdguardTeam/golibs/errors"
|
|
"github.com/digineo/go-ipset/v2"
|
|
"github.com/mdlayher/netlink"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/ti-mo/netfilter"
|
|
)
|
|
|
|
// fakeConn is a fake ipsetConn for tests.
|
|
type fakeConn struct {
|
|
ipv4Header *ipset.HeaderPolicy
|
|
ipv4Entries *[]*ipset.Entry
|
|
ipv6Header *ipset.HeaderPolicy
|
|
ipv6Entries *[]*ipset.Entry
|
|
sets []props
|
|
}
|
|
|
|
// type check
|
|
var _ ipsetConn = (*fakeConn)(nil)
|
|
|
|
// Add implements the [ipsetConn] interface for *fakeConn.
|
|
func (c *fakeConn) Add(name string, entries ...*ipset.Entry) (err error) {
|
|
if strings.Contains(name, "ipv4") {
|
|
*c.ipv4Entries = append(*c.ipv4Entries, entries...)
|
|
|
|
return nil
|
|
} else if strings.Contains(name, "ipv6") {
|
|
*c.ipv6Entries = append(*c.ipv6Entries, entries...)
|
|
|
|
return nil
|
|
}
|
|
|
|
return errors.Error("test: ipset not found")
|
|
}
|
|
|
|
// Close implements the [ipsetConn] interface for *fakeConn.
|
|
func (c *fakeConn) Close() (err error) {
|
|
return nil
|
|
}
|
|
|
|
// listAll implements the [ipsetConn] interface for *fakeConn.
|
|
func (c *fakeConn) listAll() (sets []props, err error) {
|
|
return c.sets, nil
|
|
}
|
|
|
|
func TestManager_Add(t *testing.T) {
|
|
ipsetConf := []string{
|
|
"example.com,example.net/ipv4set",
|
|
"example.org,example.biz/ipv6set",
|
|
}
|
|
|
|
var ipv4Entries []*ipset.Entry
|
|
var ipv6Entries []*ipset.Entry
|
|
|
|
fakeDial := func(
|
|
pf netfilter.ProtoFamily,
|
|
conf *netlink.Config,
|
|
) (conn ipsetConn, err error) {
|
|
return &fakeConn{
|
|
ipv4Header: &ipset.HeaderPolicy{
|
|
Family: ipset.NewUInt8Box(uint8(netfilter.ProtoIPv4)),
|
|
},
|
|
ipv4Entries: &ipv4Entries,
|
|
ipv6Header: &ipset.HeaderPolicy{
|
|
Family: ipset.NewUInt8Box(uint8(netfilter.ProtoIPv6)),
|
|
},
|
|
ipv6Entries: &ipv6Entries,
|
|
sets: []props{{
|
|
name: "ipv4set",
|
|
family: netfilter.ProtoIPv4,
|
|
}, {
|
|
name: "ipv6set",
|
|
family: netfilter.ProtoIPv6,
|
|
}},
|
|
}, nil
|
|
}
|
|
|
|
m, err := newManagerWithDialer(ipsetConf, fakeDial)
|
|
require.NoError(t, err)
|
|
|
|
ip4 := net.IP{1, 2, 3, 4}
|
|
ip6 := net.IP{
|
|
0x12, 0x34, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x56, 0x78,
|
|
}
|
|
|
|
n, err := m.Add("example.net", []net.IP{ip4}, nil)
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, 1, n)
|
|
|
|
require.Len(t, ipv4Entries, 1)
|
|
|
|
gotIP4 := ipv4Entries[0].IP.Value
|
|
assert.Equal(t, ip4, gotIP4)
|
|
|
|
n, err = m.Add("example.biz", nil, []net.IP{ip6})
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, 1, n)
|
|
|
|
require.Len(t, ipv6Entries, 1)
|
|
|
|
gotIP6 := ipv6Entries[0].IP.Value
|
|
assert.Equal(t, ip6, gotIP6)
|
|
|
|
err = m.Close()
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
// ipsetPropsSink is the typed sink for benchmark results.
|
|
var ipsetPropsSink []props
|
|
|
|
func BenchmarkManager_LookupHost(b *testing.B) {
|
|
propsLong := []props{{
|
|
name: "example.com",
|
|
family: netfilter.ProtoIPv4,
|
|
}}
|
|
|
|
propsShort := []props{{
|
|
name: "example.net",
|
|
family: netfilter.ProtoIPv4,
|
|
}}
|
|
|
|
m := &manager{
|
|
domainToIpsets: map[string][]props{
|
|
"": propsLong,
|
|
"example.net": propsShort,
|
|
},
|
|
}
|
|
|
|
b.Run("long", func(b *testing.B) {
|
|
const name = "a.very.long.domain.name.inside.the.domain.example.com"
|
|
for i := 0; i < b.N; i++ {
|
|
ipsetPropsSink = m.lookupHost(name)
|
|
}
|
|
|
|
require.Equal(b, propsLong, ipsetPropsSink)
|
|
})
|
|
|
|
b.Run("short", func(b *testing.B) {
|
|
const name = "example.net"
|
|
for i := 0; i < b.N; i++ {
|
|
ipsetPropsSink = m.lookupHost(name)
|
|
}
|
|
|
|
require.Equal(b, propsShort, ipsetPropsSink)
|
|
})
|
|
}
|