2023-01-23 18:54:21 +07:00
|
|
|
/*
|
|
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
2023-03-14 14:01:55 +07:00
|
|
|
* Copyright (c) 2022-2023, daeuniverse Organization <dae@v2raya.org>
|
2023-01-23 18:54:21 +07:00
|
|
|
*/
|
|
|
|
|
|
|
|
package control
|
|
|
|
|
|
|
|
import (
|
2023-02-04 10:24:03 +07:00
|
|
|
"encoding/binary"
|
2023-01-23 18:54:21 +07:00
|
|
|
"fmt"
|
2023-04-23 12:27:29 +07:00
|
|
|
"net/netip"
|
|
|
|
"strconv"
|
|
|
|
|
2023-08-20 00:55:42 +07:00
|
|
|
"github.com/daeuniverse/dae/pkg/trie"
|
|
|
|
|
2023-01-24 15:27:19 +07:00
|
|
|
"github.com/cilium/ebpf"
|
2023-03-14 14:01:55 +07:00
|
|
|
"github.com/daeuniverse/dae/common"
|
|
|
|
"github.com/daeuniverse/dae/common/consts"
|
|
|
|
"github.com/daeuniverse/dae/component/routing"
|
|
|
|
"github.com/daeuniverse/dae/component/routing/domain_matcher"
|
|
|
|
"github.com/daeuniverse/dae/config"
|
|
|
|
"github.com/daeuniverse/dae/pkg/config_parser"
|
2023-03-23 14:46:58 +07:00
|
|
|
"github.com/sirupsen/logrus"
|
2023-01-23 18:54:21 +07:00
|
|
|
)
|
|
|
|
|
|
|
|
type RoutingMatcherBuilder struct {
|
2023-03-24 23:35:45 +07:00
|
|
|
log *logrus.Logger
|
2023-01-23 18:54:21 +07:00
|
|
|
outboundName2Id map[string]uint8
|
|
|
|
bpf *bpfObjects
|
2023-02-04 10:38:01 +07:00
|
|
|
rules []bpfMatchSet
|
2023-02-18 17:27:28 +07:00
|
|
|
simulatedLpmTries [][]netip.Prefix
|
|
|
|
simulatedDomainSet []routing.DomainSet
|
2023-02-25 01:38:21 +07:00
|
|
|
fallback *routing.Outbound
|
2023-01-23 18:54:21 +07:00
|
|
|
}
|
|
|
|
|
2023-02-25 01:38:21 +07:00
|
|
|
func NewRoutingMatcherBuilder(log *logrus.Logger, rules []*config_parser.RoutingRule, outboundName2Id map[string]uint8, bpf *bpfObjects, fallback config.FunctionOrString) (b *RoutingMatcherBuilder, err error) {
|
2023-03-24 23:35:45 +07:00
|
|
|
b = &RoutingMatcherBuilder{log: log, outboundName2Id: outboundName2Id, bpf: bpf}
|
2023-02-25 01:38:21 +07:00
|
|
|
rulesBuilder := routing.NewRulesBuilder(log)
|
|
|
|
rulesBuilder.RegisterFunctionParser(consts.Function_Domain, routing.PlainParserFactory(b.addDomain))
|
|
|
|
rulesBuilder.RegisterFunctionParser(consts.Function_Ip, routing.IpParserFactory(b.addIp))
|
|
|
|
rulesBuilder.RegisterFunctionParser(consts.Function_SourceIp, routing.IpParserFactory(b.addSourceIp))
|
|
|
|
rulesBuilder.RegisterFunctionParser(consts.Function_Port, routing.PortRangeParserFactory(b.addPort))
|
|
|
|
rulesBuilder.RegisterFunctionParser(consts.Function_SourcePort, routing.PortRangeParserFactory(b.addSourcePort))
|
|
|
|
rulesBuilder.RegisterFunctionParser(consts.Function_L4Proto, routing.L4ProtoParserFactory(b.addL4Proto))
|
|
|
|
rulesBuilder.RegisterFunctionParser(consts.Function_Mac, routing.MacParserFactory(b.addSourceMac))
|
|
|
|
rulesBuilder.RegisterFunctionParser(consts.Function_ProcessName, routing.ProcessNameParserFactory(b.addProcessName))
|
2023-08-20 22:43:33 +07:00
|
|
|
rulesBuilder.RegisterFunctionParser(consts.Function_Dscp, routing.UintParserFactory(b.addDscp))
|
2023-02-25 01:38:21 +07:00
|
|
|
rulesBuilder.RegisterFunctionParser(consts.Function_IpVersion, routing.IpVersionParserFactory(b.addIpVersion))
|
|
|
|
if err = rulesBuilder.Apply(rules); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = b.addFallback(fallback); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return b, nil
|
2023-01-23 18:54:21 +07:00
|
|
|
}
|
|
|
|
|
2023-02-25 01:38:21 +07:00
|
|
|
func (b *RoutingMatcherBuilder) outboundToId(outbound string) (uint8, error) {
|
2023-01-23 18:54:21 +07:00
|
|
|
var outboundId uint8
|
2023-01-29 06:31:52 +07:00
|
|
|
switch outbound {
|
2023-02-25 01:38:21 +07:00
|
|
|
case consts.OutboundLogicalOr.String():
|
2023-01-29 06:31:52 +07:00
|
|
|
outboundId = uint8(consts.OutboundLogicalOr)
|
2023-02-25 01:38:21 +07:00
|
|
|
case consts.OutboundLogicalAnd.String():
|
|
|
|
outboundId = uint8(consts.OutboundLogicalAnd)
|
2023-04-02 11:02:57 +07:00
|
|
|
case consts.OutboundMustRules.String():
|
|
|
|
outboundId = uint8(consts.OutboundMustRules)
|
2023-01-29 06:31:52 +07:00
|
|
|
default:
|
2023-01-23 18:54:21 +07:00
|
|
|
var ok bool
|
|
|
|
outboundId, ok = b.outboundName2Id[outbound]
|
|
|
|
if !ok {
|
2023-02-25 01:38:21 +07:00
|
|
|
return 0, fmt.Errorf("outbound (group) %v not found; please define it in section \"group\"", strconv.Quote(outbound))
|
2023-01-23 18:54:21 +07:00
|
|
|
}
|
|
|
|
}
|
2023-02-25 01:38:21 +07:00
|
|
|
return outboundId, nil
|
2023-01-23 18:54:21 +07:00
|
|
|
}
|
|
|
|
|
2023-02-25 01:38:21 +07:00
|
|
|
func (b *RoutingMatcherBuilder) addDomain(f *config_parser.Function, key string, values []string, outbound *routing.Outbound) (err error) {
|
2023-02-18 17:27:28 +07:00
|
|
|
switch consts.RoutingDomainKey(key) {
|
|
|
|
case consts.RoutingDomainKey_Regex,
|
|
|
|
consts.RoutingDomainKey_Full,
|
|
|
|
consts.RoutingDomainKey_Keyword,
|
|
|
|
consts.RoutingDomainKey_Suffix:
|
2023-01-23 18:54:21 +07:00
|
|
|
default:
|
2023-02-25 01:38:21 +07:00
|
|
|
return fmt.Errorf("addDomain: unsupported key: %v", key)
|
2023-01-23 18:54:21 +07:00
|
|
|
}
|
2023-02-18 17:27:28 +07:00
|
|
|
b.simulatedDomainSet = append(b.simulatedDomainSet, routing.DomainSet{
|
|
|
|
Key: consts.RoutingDomainKey(key),
|
2023-01-23 18:54:21 +07:00
|
|
|
RuleIndex: len(b.rules),
|
|
|
|
Domains: values,
|
|
|
|
})
|
2023-02-25 01:38:21 +07:00
|
|
|
outboundId, err := b.outboundToId(outbound.Name)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2023-02-04 10:38:01 +07:00
|
|
|
b.rules = append(b.rules, bpfMatchSet{
|
2023-01-31 18:33:53 +07:00
|
|
|
Type: uint8(consts.MatchType_DomainSet),
|
2023-01-29 06:31:52 +07:00
|
|
|
Not: f.Not,
|
2023-02-25 01:38:21 +07:00
|
|
|
Outbound: outboundId,
|
2023-02-20 17:06:54 +07:00
|
|
|
Mark: outbound.Mark,
|
2023-04-02 10:07:53 +07:00
|
|
|
Must: outbound.Must,
|
2023-01-23 18:54:21 +07:00
|
|
|
})
|
2023-02-25 01:38:21 +07:00
|
|
|
return nil
|
2023-01-23 18:54:21 +07:00
|
|
|
}
|
|
|
|
|
2023-02-25 01:38:21 +07:00
|
|
|
func (b *RoutingMatcherBuilder) addSourceMac(f *config_parser.Function, macAddrs [][6]byte, outbound *routing.Outbound) (err error) {
|
2023-01-24 23:31:20 +07:00
|
|
|
var addr16 [16]byte
|
|
|
|
values := make([]netip.Prefix, 0, len(macAddrs))
|
|
|
|
for _, mac := range macAddrs {
|
|
|
|
copy(addr16[10:], mac[:])
|
|
|
|
prefix := netip.PrefixFrom(netip.AddrFrom16(addr16), 128)
|
|
|
|
values = append(values, prefix)
|
|
|
|
}
|
2023-02-18 17:27:28 +07:00
|
|
|
lpmTrieIndex := len(b.simulatedLpmTries)
|
|
|
|
b.simulatedLpmTries = append(b.simulatedLpmTries, values)
|
2023-02-25 01:38:21 +07:00
|
|
|
outboundId, err := b.outboundToId(outbound.Name)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2023-02-04 10:38:01 +07:00
|
|
|
set := bpfMatchSet{
|
2023-02-04 10:24:03 +07:00
|
|
|
Value: [16]byte{},
|
2023-01-31 18:33:53 +07:00
|
|
|
Type: uint8(consts.MatchType_Mac),
|
2023-01-29 06:31:52 +07:00
|
|
|
Not: f.Not,
|
2023-02-25 01:38:21 +07:00
|
|
|
Outbound: outboundId,
|
2023-02-20 17:06:54 +07:00
|
|
|
Mark: outbound.Mark,
|
2023-04-02 10:07:53 +07:00
|
|
|
Must: outbound.Must,
|
2023-02-04 10:24:03 +07:00
|
|
|
}
|
|
|
|
binary.LittleEndian.PutUint32(set.Value[:], uint32(lpmTrieIndex))
|
|
|
|
b.rules = append(b.rules, set)
|
2023-02-25 01:38:21 +07:00
|
|
|
return nil
|
2023-01-24 23:31:20 +07:00
|
|
|
}
|
|
|
|
|
2023-02-25 01:38:21 +07:00
|
|
|
func (b *RoutingMatcherBuilder) addIp(f *config_parser.Function, values []netip.Prefix, outbound *routing.Outbound) (err error) {
|
2023-02-18 17:27:28 +07:00
|
|
|
lpmTrieIndex := len(b.simulatedLpmTries)
|
|
|
|
b.simulatedLpmTries = append(b.simulatedLpmTries, values)
|
2023-02-25 01:38:21 +07:00
|
|
|
outboundId, err := b.outboundToId(outbound.Name)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2023-02-04 10:38:01 +07:00
|
|
|
set := bpfMatchSet{
|
2023-02-04 10:24:03 +07:00
|
|
|
Value: [16]byte{},
|
2023-01-31 18:33:53 +07:00
|
|
|
Type: uint8(consts.MatchType_IpSet),
|
2023-01-29 06:31:52 +07:00
|
|
|
Not: f.Not,
|
2023-02-25 01:38:21 +07:00
|
|
|
Outbound: outboundId,
|
2023-02-20 17:06:54 +07:00
|
|
|
Mark: outbound.Mark,
|
2023-04-02 10:07:53 +07:00
|
|
|
Must: outbound.Must,
|
2023-02-04 10:24:03 +07:00
|
|
|
}
|
|
|
|
binary.LittleEndian.PutUint32(set.Value[:], uint32(lpmTrieIndex))
|
|
|
|
b.rules = append(b.rules, set)
|
2023-02-25 01:38:21 +07:00
|
|
|
return nil
|
2023-01-23 18:54:21 +07:00
|
|
|
}
|
|
|
|
|
2023-02-25 01:38:21 +07:00
|
|
|
func (b *RoutingMatcherBuilder) addPort(f *config_parser.Function, values [][2]uint16, outbound *routing.Outbound) (err error) {
|
2023-01-29 10:19:58 +07:00
|
|
|
for i, value := range values {
|
2023-02-25 01:38:21 +07:00
|
|
|
outboundName := consts.OutboundLogicalOr.String()
|
2023-01-29 10:19:58 +07:00
|
|
|
if i == len(values)-1 {
|
2023-02-20 17:06:54 +07:00
|
|
|
outboundName = outbound.Name
|
2023-01-29 10:19:58 +07:00
|
|
|
}
|
2023-02-25 01:38:21 +07:00
|
|
|
outboundId, err := b.outboundToId(outboundName)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2023-02-04 10:38:01 +07:00
|
|
|
b.rules = append(b.rules, bpfMatchSet{
|
2023-01-31 18:33:53 +07:00
|
|
|
Type: uint8(consts.MatchType_Port),
|
2023-01-29 06:31:52 +07:00
|
|
|
Value: _bpfPortRange{
|
|
|
|
PortStart: value[0],
|
|
|
|
PortEnd: value[1],
|
|
|
|
}.Encode(),
|
|
|
|
Not: f.Not,
|
2023-02-25 01:38:21 +07:00
|
|
|
Outbound: outboundId,
|
2023-02-20 17:06:54 +07:00
|
|
|
Mark: outbound.Mark,
|
2023-04-02 10:07:53 +07:00
|
|
|
Must: outbound.Must,
|
2023-01-29 06:31:52 +07:00
|
|
|
})
|
|
|
|
}
|
2023-02-25 01:38:21 +07:00
|
|
|
return nil
|
2023-01-29 06:31:52 +07:00
|
|
|
}
|
|
|
|
|
2023-02-25 01:38:21 +07:00
|
|
|
func (b *RoutingMatcherBuilder) addSourceIp(f *config_parser.Function, values []netip.Prefix, outbound *routing.Outbound) (err error) {
|
2023-02-18 17:27:28 +07:00
|
|
|
lpmTrieIndex := len(b.simulatedLpmTries)
|
|
|
|
b.simulatedLpmTries = append(b.simulatedLpmTries, values)
|
2023-02-25 01:38:21 +07:00
|
|
|
outboundId, err := b.outboundToId(outbound.Name)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2023-02-04 10:38:01 +07:00
|
|
|
set := bpfMatchSet{
|
2023-02-04 10:24:03 +07:00
|
|
|
Value: [16]byte{},
|
2023-01-31 18:33:53 +07:00
|
|
|
Type: uint8(consts.MatchType_SourceIpSet),
|
2023-01-29 06:31:52 +07:00
|
|
|
Not: f.Not,
|
2023-02-25 01:38:21 +07:00
|
|
|
Outbound: outboundId,
|
2023-02-20 17:06:54 +07:00
|
|
|
Mark: outbound.Mark,
|
2023-04-02 10:07:53 +07:00
|
|
|
Must: outbound.Must,
|
2023-02-04 10:24:03 +07:00
|
|
|
}
|
|
|
|
binary.LittleEndian.PutUint32(set.Value[:], uint32(lpmTrieIndex))
|
|
|
|
b.rules = append(b.rules, set)
|
2023-02-25 01:38:21 +07:00
|
|
|
return nil
|
2023-01-24 23:31:20 +07:00
|
|
|
}
|
|
|
|
|
2023-02-25 01:38:21 +07:00
|
|
|
func (b *RoutingMatcherBuilder) addSourcePort(f *config_parser.Function, values [][2]uint16, outbound *routing.Outbound) (err error) {
|
2023-01-29 10:19:58 +07:00
|
|
|
for i, value := range values {
|
2023-02-25 01:38:21 +07:00
|
|
|
outboundName := consts.OutboundLogicalOr.String()
|
2023-01-29 10:19:58 +07:00
|
|
|
if i == len(values)-1 {
|
2023-02-20 17:06:54 +07:00
|
|
|
outboundName = outbound.Name
|
2023-01-29 10:19:58 +07:00
|
|
|
}
|
2023-02-25 01:38:21 +07:00
|
|
|
outboundId, err := b.outboundToId(outboundName)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2023-02-04 10:38:01 +07:00
|
|
|
b.rules = append(b.rules, bpfMatchSet{
|
2023-01-31 18:33:53 +07:00
|
|
|
Type: uint8(consts.MatchType_SourcePort),
|
2023-01-29 06:31:52 +07:00
|
|
|
Value: _bpfPortRange{
|
|
|
|
PortStart: value[0],
|
|
|
|
PortEnd: value[1],
|
|
|
|
}.Encode(),
|
|
|
|
Not: f.Not,
|
2023-02-25 01:38:21 +07:00
|
|
|
Outbound: outboundId,
|
2023-02-20 17:06:54 +07:00
|
|
|
Mark: outbound.Mark,
|
2023-04-02 10:07:53 +07:00
|
|
|
Must: outbound.Must,
|
2023-01-29 06:31:52 +07:00
|
|
|
})
|
|
|
|
}
|
2023-02-25 01:38:21 +07:00
|
|
|
return nil
|
2023-01-29 06:31:52 +07:00
|
|
|
}
|
|
|
|
|
2023-02-25 01:38:21 +07:00
|
|
|
func (b *RoutingMatcherBuilder) addL4Proto(f *config_parser.Function, values consts.L4ProtoType, outbound *routing.Outbound) (err error) {
|
|
|
|
outboundId, err := b.outboundToId(outbound.Name)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
2023-01-24 23:31:20 +07:00
|
|
|
}
|
2023-02-04 10:38:01 +07:00
|
|
|
b.rules = append(b.rules, bpfMatchSet{
|
2023-02-04 10:24:03 +07:00
|
|
|
Value: [16]byte{byte(values)},
|
2023-01-31 18:33:53 +07:00
|
|
|
Type: uint8(consts.MatchType_L4Proto),
|
2023-01-29 06:31:52 +07:00
|
|
|
Not: f.Not,
|
2023-02-25 01:38:21 +07:00
|
|
|
Outbound: outboundId,
|
2023-02-20 17:06:54 +07:00
|
|
|
Mark: outbound.Mark,
|
2023-04-02 10:07:53 +07:00
|
|
|
Must: outbound.Must,
|
2023-01-24 23:31:20 +07:00
|
|
|
})
|
2023-02-25 01:38:21 +07:00
|
|
|
return nil
|
2023-01-24 23:31:20 +07:00
|
|
|
}
|
|
|
|
|
2023-02-25 01:38:21 +07:00
|
|
|
func (b *RoutingMatcherBuilder) addIpVersion(f *config_parser.Function, values consts.IpVersionType, outbound *routing.Outbound) (err error) {
|
|
|
|
outboundId, err := b.outboundToId(outbound.Name)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
2023-01-24 23:31:20 +07:00
|
|
|
}
|
2023-02-04 10:38:01 +07:00
|
|
|
b.rules = append(b.rules, bpfMatchSet{
|
2023-02-04 10:24:03 +07:00
|
|
|
Value: [16]byte{byte(values)},
|
2023-01-31 18:33:53 +07:00
|
|
|
Type: uint8(consts.MatchType_IpVersion),
|
2023-01-29 06:31:52 +07:00
|
|
|
Not: f.Not,
|
2023-02-25 01:38:21 +07:00
|
|
|
Outbound: outboundId,
|
2023-02-20 17:06:54 +07:00
|
|
|
Mark: outbound.Mark,
|
2023-04-02 10:07:53 +07:00
|
|
|
Must: outbound.Must,
|
2023-01-24 23:31:20 +07:00
|
|
|
})
|
2023-02-25 01:38:21 +07:00
|
|
|
return nil
|
2023-01-24 23:31:20 +07:00
|
|
|
}
|
|
|
|
|
2023-02-25 01:38:21 +07:00
|
|
|
func (b *RoutingMatcherBuilder) addProcessName(f *config_parser.Function, values [][consts.TaskCommLen]byte, outbound *routing.Outbound) (err error) {
|
2023-01-31 18:33:53 +07:00
|
|
|
for i, value := range values {
|
2023-02-25 01:38:21 +07:00
|
|
|
outboundName := consts.OutboundLogicalOr.String()
|
2023-01-31 18:33:53 +07:00
|
|
|
if i == len(values)-1 {
|
2023-02-20 17:06:54 +07:00
|
|
|
outboundName = outbound.Name
|
2023-01-31 18:33:53 +07:00
|
|
|
}
|
2023-02-25 01:38:21 +07:00
|
|
|
outboundId, err := b.outboundToId(outboundName)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2023-02-04 10:38:01 +07:00
|
|
|
matchSet := bpfMatchSet{
|
2023-01-31 18:33:53 +07:00
|
|
|
Type: uint8(consts.MatchType_ProcessName),
|
|
|
|
Not: f.Not,
|
2023-02-25 01:38:21 +07:00
|
|
|
Outbound: outboundId,
|
2023-02-20 17:06:54 +07:00
|
|
|
Mark: outbound.Mark,
|
2023-04-02 10:07:53 +07:00
|
|
|
Must: outbound.Must,
|
2023-01-31 18:33:53 +07:00
|
|
|
}
|
2023-02-04 10:24:03 +07:00
|
|
|
copy(matchSet.Value[:], value[:])
|
2023-01-31 18:33:53 +07:00
|
|
|
b.rules = append(b.rules, matchSet)
|
|
|
|
}
|
2023-02-25 01:38:21 +07:00
|
|
|
return nil
|
2023-01-31 18:33:53 +07:00
|
|
|
}
|
|
|
|
|
2023-08-20 22:43:33 +07:00
|
|
|
func (b *RoutingMatcherBuilder) addDscp(f *config_parser.Function, values []uint8, outbound *routing.Outbound) (err error) {
|
2023-08-20 00:55:42 +07:00
|
|
|
for i, value := range values {
|
|
|
|
outboundName := consts.OutboundLogicalOr.String()
|
|
|
|
if i == len(values)-1 {
|
|
|
|
outboundName = outbound.Name
|
|
|
|
}
|
|
|
|
outboundId, err := b.outboundToId(outboundName)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
matchSet := bpfMatchSet{
|
2023-08-20 22:43:33 +07:00
|
|
|
Type: uint8(consts.MatchType_Dscp),
|
2023-08-20 00:55:42 +07:00
|
|
|
Not: f.Not,
|
|
|
|
Outbound: outboundId,
|
|
|
|
Mark: outbound.Mark,
|
|
|
|
Must: outbound.Must,
|
|
|
|
}
|
|
|
|
matchSet.Value[0] = value
|
|
|
|
b.rules = append(b.rules, matchSet)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-02-25 01:38:21 +07:00
|
|
|
func (b *RoutingMatcherBuilder) addFallback(fallbackOutbound config.FunctionOrString) (err error) {
|
|
|
|
outbound, err := routing.ParseOutbound(config.FunctionOrStringToFunction(fallbackOutbound))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
outboundId, err := b.outboundToId(outbound.Name)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
2023-01-24 15:27:19 +07:00
|
|
|
}
|
2023-02-04 10:38:01 +07:00
|
|
|
b.rules = append(b.rules, bpfMatchSet{
|
2023-02-18 02:01:51 +07:00
|
|
|
Type: uint8(consts.MatchType_Fallback),
|
2023-02-25 01:38:21 +07:00
|
|
|
Outbound: outboundId,
|
2023-02-20 17:06:54 +07:00
|
|
|
Mark: outbound.Mark,
|
2023-04-02 10:07:53 +07:00
|
|
|
Must: outbound.Must,
|
2023-01-23 18:54:21 +07:00
|
|
|
})
|
2023-02-25 01:38:21 +07:00
|
|
|
return nil
|
2023-01-23 18:54:21 +07:00
|
|
|
}
|
|
|
|
|
2023-03-14 12:54:43 +07:00
|
|
|
func (b *RoutingMatcherBuilder) BuildKernspace(log *logrus.Logger) (err error) {
|
2023-01-23 18:54:21 +07:00
|
|
|
// Update lpm_array_map.
|
2023-02-18 17:27:28 +07:00
|
|
|
for i, cidrs := range b.simulatedLpmTries {
|
2023-01-28 10:47:02 +07:00
|
|
|
var keys []_bpfLpmKey
|
2023-01-23 18:54:21 +07:00
|
|
|
var values []uint32
|
|
|
|
for _, cidr := range cidrs {
|
|
|
|
keys = append(keys, cidrToBpfLpmKey(cidr))
|
|
|
|
values = append(values, 1)
|
|
|
|
}
|
2023-01-27 01:10:27 +07:00
|
|
|
m, err := b.bpf.newLpmMap(keys, values)
|
2023-01-23 18:54:21 +07:00
|
|
|
if err != nil {
|
2023-01-27 01:10:27 +07:00
|
|
|
return fmt.Errorf("newLpmMap: %w", err)
|
2023-01-23 18:54:21 +07:00
|
|
|
}
|
2023-02-09 11:26:44 +07:00
|
|
|
// We cannot invoke BpfMapBatchUpdate when value is ebpf.Map.
|
2023-01-23 18:54:21 +07:00
|
|
|
if err = b.bpf.LpmArrayMap.Update(uint32(i), m, ebpf.UpdateAny); err != nil {
|
|
|
|
m.Close()
|
|
|
|
return fmt.Errorf("Update: %w", err)
|
|
|
|
}
|
|
|
|
m.Close()
|
|
|
|
}
|
2023-01-27 01:10:27 +07:00
|
|
|
// Write routings.
|
2023-02-18 02:01:51 +07:00
|
|
|
// Fallback rule MUST be the last.
|
|
|
|
if b.rules[len(b.rules)-1].Type != uint8(consts.MatchType_Fallback) {
|
2023-02-25 01:38:21 +07:00
|
|
|
return fmt.Errorf("fallback rule MUST be the last")
|
2023-01-27 01:10:27 +07:00
|
|
|
}
|
2023-01-23 18:54:21 +07:00
|
|
|
routingsLen := uint32(len(b.rules))
|
|
|
|
routingsKeys := common.ARangeU32(routingsLen)
|
2023-02-09 11:26:44 +07:00
|
|
|
if _, err = BpfMapBatchUpdate(b.bpf.RoutingMap, routingsKeys, b.rules, &ebpf.BatchOptions{
|
2023-01-23 18:54:21 +07:00
|
|
|
ElemFlags: uint64(ebpf.UpdateAny),
|
|
|
|
}); err != nil {
|
2023-02-09 11:26:44 +07:00
|
|
|
return fmt.Errorf("BpfMapBatchUpdate: %w", err)
|
2023-01-23 18:54:21 +07:00
|
|
|
}
|
2023-03-14 12:54:43 +07:00
|
|
|
log.Infof("Routing match set len: %v/%v", len(b.rules), consts.MaxMatchSetLen)
|
2023-02-18 22:09:06 +07:00
|
|
|
|
2023-01-23 18:54:21 +07:00
|
|
|
return nil
|
|
|
|
}
|
2023-02-18 17:27:28 +07:00
|
|
|
|
2023-06-11 11:48:52 +07:00
|
|
|
func (b *RoutingMatcherBuilder) BuildUserspace() (matcher *RoutingMatcher, err error) {
|
2023-02-18 17:27:28 +07:00
|
|
|
// Build domainMatcher
|
2023-03-24 23:35:45 +07:00
|
|
|
domainMatcher := domain_matcher.NewAhocorasickSlimtrie(b.log, consts.MaxMatchSetLen)
|
2023-02-18 17:27:28 +07:00
|
|
|
for _, domains := range b.simulatedDomainSet {
|
2023-02-25 01:38:21 +07:00
|
|
|
domainMatcher.AddSet(domains.RuleIndex, domains.Domains, domains.Key)
|
2023-02-18 17:27:28 +07:00
|
|
|
}
|
2023-06-11 11:48:52 +07:00
|
|
|
// Build Ip matcher.
|
|
|
|
var lpmMatcher []*trie.Trie
|
|
|
|
for _, prefixes := range b.simulatedLpmTries {
|
|
|
|
t, err := trie.NewTrieFromPrefixes(prefixes)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
lpmMatcher = append(lpmMatcher, t)
|
|
|
|
}
|
2023-02-25 01:38:21 +07:00
|
|
|
if err = domainMatcher.Build(); err != nil {
|
2023-02-18 17:27:28 +07:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write routings.
|
|
|
|
// Fallback rule MUST be the last.
|
|
|
|
if b.rules[len(b.rules)-1].Type != uint8(consts.MatchType_Fallback) {
|
2023-02-25 01:38:21 +07:00
|
|
|
return nil, fmt.Errorf("fallback rule MUST be the last")
|
2023-02-18 17:27:28 +07:00
|
|
|
}
|
|
|
|
|
2023-02-25 01:38:21 +07:00
|
|
|
return &RoutingMatcher{
|
2023-06-11 11:48:52 +07:00
|
|
|
lpmMatcher: lpmMatcher,
|
2023-02-25 01:38:21 +07:00
|
|
|
domainMatcher: domainMatcher,
|
|
|
|
matches: b.rules,
|
|
|
|
}, nil
|
2023-02-18 17:27:28 +07:00
|
|
|
}
|