optimize(memory): reuse kernel lpm tries in userspace

This commit is contained in:
mzz2017
2023-02-18 22:18:34 +08:00
parent 23140c1f15
commit 55c68a1676
3 changed files with 25 additions and 27 deletions

View File

@ -26,6 +26,7 @@ import (
"net/netip" "net/netip"
"os" "os"
"path/filepath" "path/filepath"
"runtime"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
@ -322,6 +323,9 @@ func NewControlPlane(
c.dnsUpstream.FinishInitCallback = c.finishInitDnsUpstreamResolve c.dnsUpstream.FinishInitCallback = c.finishInitDnsUpstreamResolve
// Try to invoke once to avoid dns leaking at the very beginning. // Try to invoke once to avoid dns leaking at the very beginning.
_, _ = c.dnsUpstream.GetUpstream() _, _ = c.dnsUpstream.GetUpstream()
// Call GC to release memory.
runtime.GC()
return c, nil return c, nil
} }

View File

@ -8,7 +8,6 @@ package control
import ( import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"github.com/Asphaltt/lpmtrie"
"github.com/cilium/ebpf" "github.com/cilium/ebpf"
"github.com/v2rayA/dae/common" "github.com/v2rayA/dae/common"
"github.com/v2rayA/dae/common/consts" "github.com/v2rayA/dae/common/consts"
@ -26,7 +25,6 @@ type RoutingMatcherBuilder struct {
rules []bpfMatchSet rules []bpfMatchSet
simulatedLpmTries [][]netip.Prefix simulatedLpmTries [][]netip.Prefix
simulatedDomainSet []routing.DomainSet simulatedDomainSet []routing.DomainSet
Fallback string
err error err error
} }
@ -215,7 +213,6 @@ func (b *RoutingMatcherBuilder) AddFallback(outbound string) {
if b.err != nil { if b.err != nil {
return return
} }
b.Fallback = outbound
b.rules = append(b.rules, bpfMatchSet{ b.rules = append(b.rules, bpfMatchSet{
Type: uint8(consts.MatchType_Fallback), Type: uint8(consts.MatchType_Fallback),
Outbound: b.OutboundToId(outbound), Outbound: b.OutboundToId(outbound),
@ -266,18 +263,6 @@ func (b *RoutingMatcherBuilder) BuildUserspace() (matcher *RoutingMatcher, err e
return nil, b.err return nil, b.err
} }
var m RoutingMatcher var m RoutingMatcher
// Update lpms.
m.lpms = make([]lpmtrie.LpmTrie, len(b.simulatedLpmTries))
for i, cidrs := range b.simulatedLpmTries {
lpm, err := lpmtrie.New(128)
if err != nil {
return nil, err
}
for _, cidr := range cidrs {
lpm.Update(cidrToLpmTrieKey(cidr), 1)
}
m.lpms[i] = lpm
}
// Build domainMatcher // Build domainMatcher
m.domainMatcher = domain_matcher.NewAhocorasickSlimtrie(consts.MaxMatchSetLen) m.domainMatcher = domain_matcher.NewAhocorasickSlimtrie(consts.MaxMatchSetLen)
for _, domains := range b.simulatedDomainSet { for _, domains := range b.simulatedDomainSet {

View File

@ -9,6 +9,8 @@ import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"github.com/Asphaltt/lpmtrie" "github.com/Asphaltt/lpmtrie"
"github.com/cilium/ebpf"
"github.com/v2rayA/dae/common"
"github.com/v2rayA/dae/common/consts" "github.com/v2rayA/dae/common/consts"
"github.com/v2rayA/dae/component/routing" "github.com/v2rayA/dae/component/routing"
"net" "net"
@ -16,7 +18,7 @@ import (
) )
type RoutingMatcher struct { type RoutingMatcher struct {
lpms []lpmtrie.LpmTrie lpmArrayMap *ebpf.Map
domainMatcher routing.DomainMatcher // All domain matchSets use one DomainMatcher. domainMatcher routing.DomainMatcher // All domain matchSets use one DomainMatcher.
matches []bpfMatchSet matches []bpfMatchSet
@ -37,18 +39,18 @@ func (m *RoutingMatcher) Match(
if len(sourceAddr) != net.IPv6len || len(destAddr) != net.IPv6len || len(mac) != net.IPv6len { if len(sourceAddr) != net.IPv6len || len(destAddr) != net.IPv6len || len(mac) != net.IPv6len {
return 0, fmt.Errorf("bad address length") return 0, fmt.Errorf("bad address length")
} }
lpmKeys := make([]*lpmtrie.Key, consts.MatchType_Mac+1) lpmKeys := make([]*_bpfLpmKey, consts.MatchType_Mac+1)
lpmKeys[consts.MatchType_IpSet] = &lpmtrie.Key{ lpmKeys[consts.MatchType_IpSet] = &_bpfLpmKey{
PrefixLen: 128, PrefixLen: 128,
Data: destAddr, Data: common.Ipv6ByteSliceToUint32Array(destAddr),
} }
lpmKeys[consts.MatchType_SourceIpSet] = &lpmtrie.Key{ lpmKeys[consts.MatchType_SourceIpSet] = &_bpfLpmKey{
PrefixLen: 128, PrefixLen: 128,
Data: sourceAddr, Data: common.Ipv6ByteSliceToUint32Array(sourceAddr),
} }
lpmKeys[consts.MatchType_Mac] = &lpmtrie.Key{ lpmKeys[consts.MatchType_Mac] = &_bpfLpmKey{
PrefixLen: 128, PrefixLen: 128,
Data: mac, Data: common.Ipv6ByteSliceToUint32Array(mac),
} }
var domainMatchBitmap []uint32 var domainMatchBitmap []uint32
if domain != "" { if domain != "" {
@ -63,11 +65,18 @@ func (m *RoutingMatcher) Match(
} }
switch consts.MatchType(match.Type) { switch consts.MatchType(match.Type) {
case consts.MatchType_IpSet, consts.MatchType_SourceIpSet, consts.MatchType_Mac: case consts.MatchType_IpSet, consts.MatchType_SourceIpSet, consts.MatchType_Mac:
lpmIndex := int(binary.LittleEndian.Uint16(match.Value[:])) lpmIndex := uint32(binary.LittleEndian.Uint16(match.Value[:]))
_, hit := m.lpms[lpmIndex].Lookup(*lpmKeys[int(match.Type)]) var lpm *ebpf.Map
if hit { if err = m.lpmArrayMap.Lookup(lpmIndex, &lpm); err != nil {
goodSubrule = true break
} }
var v uint32
if err = lpm.Lookup(*lpmKeys[int(match.Type)], &v); err != nil {
_ = lpm.Close()
break
}
_ = lpm.Close()
goodSubrule = true
case consts.MatchType_DomainSet: case consts.MatchType_DomainSet:
if domainMatchBitmap != nil && (domainMatchBitmap[i/32]>>(i%32))&1 > 0 { if domainMatchBitmap != nil && (domainMatchBitmap[i/32]>>(i%32))&1 > 0 {
goodSubrule = true goodSubrule = true