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

View File

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

View File

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