blob: 6f7bd55bb2e56f2c185a95a9e46442e0b9fca0c6 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package filter
import (
"math"
"math/rand"
"testing"
"time"
"github.com/google/netstack/tcpip"
"github.com/google/netstack/tcpip/buffer"
"github.com/google/netstack/tcpip/header"
)
var srcSubnet = func() tcpip.Subnet {
srcSubnet, err := tcpip.NewSubnet("\x0a\x00\x00\x00", "\xff\x00\x00\x00")
if err != nil {
panic(err)
}
return srcSubnet
}()
var ruleset1 = []Rule{
{
action: Drop,
direction: Incoming,
transProto: header.TCPProtocolNumber,
srcSubnet: &srcSubnet,
srcPort: 100,
log: testing.Verbose(),
},
}
var ruleset2 = []Rule{
{
action: Drop,
direction: Incoming,
transProto: header.UDPProtocolNumber,
log: testing.Verbose(),
},
{
action: Pass,
direction: Incoming,
transProto: header.UDPProtocolNumber,
srcSubnet: &srcSubnet,
srcPort: 100,
log: testing.Verbose(),
},
}
func TestRun(t *testing.T) {
var tests = []struct {
ruleset []Rule
dir Direction
netProto tcpip.NetworkProtocolNumber
packet func() (buffer.Prependable, buffer.VectorisedView)
want Action
}{
{
ruleset1,
Incoming,
header.IPv4ProtocolNumber,
func() (buffer.Prependable, buffer.VectorisedView) {
return tcpV4Packet([]byte("payload"), &tcpParams{
srcAddr: "\x0a\x00\x00\x00",
srcPort: 100,
dstAddr: "\x0a\x00\x00\x02",
dstPort: 200,
})
},
Drop,
},
{
ruleset2,
Incoming,
header.IPv4ProtocolNumber,
func() (buffer.Prependable, buffer.VectorisedView) {
return udpV4Packet([]byte("payload"), &udpParams{
srcAddr: "\x0a\x00\x00\x00",
srcPort: 100,
dstAddr: "\x0a\x00\x00\x02",
dstPort: 200,
})
},
Pass,
},
}
f := New(nil)
for _, test := range tests {
f.rulesetMain.Lock()
f.rulesetMain.v = test.ruleset
f.rulesetMain.Unlock()
hdr, payload := test.packet()
if got := f.Run(test.dir, test.netProto, hdr, payload); got != test.want {
t.Fatalf("wrong action, want %v, got %v", test.want, got)
}
}
}
type Packet struct {
hdr buffer.Prependable
payload buffer.VectorisedView
}
func generateRandomUdp4Packet() Packet {
buf := make([]byte, 4)
rand.Read(buf)
srcAddr := tcpip.Address(buf)
rand.Read(buf)
dstAddr := tcpip.Address(buf)
p := udpParams{
srcAddr: srcAddr,
srcPort: uint16(rand.Int31n(math.MaxUint16)),
dstAddr: dstAddr,
dstPort: uint16(rand.Int31n(math.MaxUint16)),
}
hdr, payload := udpV4Packet([]byte("payload"), &p)
return Packet{hdr, payload}
}
func BenchmarkFilterConcurrency(b *testing.B) {
b.StopTimer()
f := New(nil)
f.rulesetMain.Lock()
f.rulesetMain.v = ruleset1
f.rulesetMain.Unlock()
// Unique number of src+dst combinations
uniques := int(math.Ceil(float64(b.N) / 500.0))
packets := make([]Packet, uniques)
for n := range packets {
packets[n] = generateRandomUdp4Packet()
}
b.SetParallelism(5)
b.StartTimer()
b.RunParallel(func(pb *testing.PB) {
rng := rand.New(rand.NewSource(rand.Int63() + time.Now().UnixNano()))
for pb.Next() {
// x2 for incoming vs outgoing
r := rng.Intn(uniques * 2)
var dir Direction
if r&1 == 0 {
dir = Incoming
} else {
dir = Outgoing
}
r = r >> 1
p := packets[r]
hdr := p.hdr
payload := p.payload
f.Run(dir, header.IPv4ProtocolNumber, hdr, payload)
}
})
}