fix: eliminate stale verdict poisoning, memory leaks, data races, and per-packet allocations in engine
This commit is contained in:
@@ -1,20 +1,16 @@
|
||||
package engine
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"git.difuse.io/Difuse/Mellaris/analyzer"
|
||||
"git.difuse.io/Difuse/Mellaris/ruleset"
|
||||
|
||||
"github.com/bwmarrin/snowflake"
|
||||
"github.com/google/gopacket"
|
||||
"github.com/google/gopacket/layers"
|
||||
)
|
||||
|
||||
type legacyUDPStreamValue struct {
|
||||
IPFlow gopacket.Flow
|
||||
UDPFlow gopacket.Flow
|
||||
Tuple udpTupleKey
|
||||
}
|
||||
|
||||
type emptyRuleset struct{}
|
||||
@@ -36,17 +32,20 @@ func benchmarkUDPManager(b *testing.B, churn bool) {
|
||||
}
|
||||
|
||||
const flowCount = 20000
|
||||
flows := make([]gopacket.Flow, flowCount)
|
||||
udps := make([]*layers.UDP, flowCount)
|
||||
tuples := make([]udpTupleKey, flowCount)
|
||||
payloads := make([][]byte, flowCount)
|
||||
for i := 0; i < flowCount; i++ {
|
||||
a := byte(i >> 8)
|
||||
c := byte(i)
|
||||
flows[i] = gopacket.NewFlow(layers.EndpointIPv4, net.IPv4(10, a, 0, c).To4(), net.IPv4(172, 16, a, c).To4())
|
||||
udps[i] = &layers.UDP{
|
||||
SrcPort: layers.UDPPort(1024 + i%20000),
|
||||
DstPort: layers.UDPPort(20000 + (i*7)%20000),
|
||||
BaseLayer: layers.BaseLayer{Payload: []byte{0x01, 0x00, 0x00, 0x00}},
|
||||
}
|
||||
var t udpTupleKey
|
||||
t.AIP = [16]byte{10, a, 0, c}
|
||||
t.ALen = 4
|
||||
t.BIP = [16]byte{172, 16, a, c}
|
||||
t.BLen = 4
|
||||
t.APort = 1024 + uint16(i%20000)
|
||||
t.BPort = 20000 + uint16((i*7)%20000)
|
||||
tuples[i] = t
|
||||
payloads[i] = []byte{0x01, 0x00, 0x00, 0x00}
|
||||
}
|
||||
|
||||
ctx := &udpContext{Verdict: udpVerdictAccept}
|
||||
@@ -59,7 +58,7 @@ func benchmarkUDPManager(b *testing.B, churn bool) {
|
||||
}
|
||||
ctx.Verdict = udpVerdictAccept
|
||||
ctx.Packet = nil
|
||||
mgr.MatchWithContext(streamID, flows[idx], udps[idx], ctx)
|
||||
mgr.MatchWithContext(streamID, tuples[idx], false, payloads[idx], ctx)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,27 +72,25 @@ func BenchmarkUDPManagerMatchStreamIDChurn(b *testing.B) {
|
||||
|
||||
func BenchmarkLegacyUDPFallbackScanChurn(b *testing.B) {
|
||||
const flowCount = 5000
|
||||
flows := make([]gopacket.Flow, flowCount)
|
||||
udps := make([]*layers.UDP, flowCount)
|
||||
tuples := make([]udpTupleKey, flowCount)
|
||||
for i := 0; i < flowCount; i++ {
|
||||
a := byte(i >> 8)
|
||||
c := byte(i)
|
||||
flows[i] = gopacket.NewFlow(layers.EndpointIPv4, net.IPv4(10, a, 0, c).To4(), net.IPv4(172, 16, a, c).To4())
|
||||
udps[i] = &layers.UDP{
|
||||
SrcPort: layers.UDPPort(1024 + i%20000),
|
||||
DstPort: layers.UDPPort(20000 + (i*7)%20000),
|
||||
BaseLayer: layers.BaseLayer{Payload: []byte{0x01, 0x00, 0x00, 0x00}},
|
||||
}
|
||||
var t udpTupleKey
|
||||
t.AIP = [16]byte{10, a, 0, c}
|
||||
t.ALen = 4
|
||||
t.BIP = [16]byte{172, 16, a, c}
|
||||
t.BLen = 4
|
||||
t.APort = 1024 + uint16(i%20000)
|
||||
t.BPort = 20000 + uint16((i*7)%20000)
|
||||
tuples[i] = t
|
||||
}
|
||||
|
||||
streams := make(map[uint32]*legacyUDPStreamValue, flowCount)
|
||||
keys := make([]uint32, 0, flowCount)
|
||||
for i := 0; i < flowCount; i++ {
|
||||
streamID := uint32(i + 1)
|
||||
streams[streamID] = &legacyUDPStreamValue{
|
||||
IPFlow: flows[i],
|
||||
UDPFlow: udps[i].TransportFlow(),
|
||||
}
|
||||
streams[streamID] = &legacyUDPStreamValue{Tuple: tuples[i]}
|
||||
keys = append(keys, streamID)
|
||||
}
|
||||
|
||||
@@ -104,15 +101,14 @@ func BenchmarkLegacyUDPFallbackScanChurn(b *testing.B) {
|
||||
if _, ok := streams[streamID]; ok {
|
||||
continue
|
||||
}
|
||||
ipFlow := flows[idx]
|
||||
udpFlow := udps[idx].TransportFlow()
|
||||
tuple := tuples[idx]
|
||||
revTuple := reverseTuple(tuple)
|
||||
for _, k := range keys {
|
||||
v, ok := streams[k]
|
||||
if !ok || v == nil {
|
||||
continue
|
||||
}
|
||||
if (v.IPFlow == ipFlow && v.UDPFlow == udpFlow) ||
|
||||
(v.IPFlow == ipFlow.Reverse() && v.UDPFlow == udpFlow.Reverse()) {
|
||||
if v.Tuple == tuple || v.Tuple == revTuple {
|
||||
delete(streams, k)
|
||||
streams[streamID] = v
|
||||
break
|
||||
|
||||
Reference in New Issue
Block a user