fix: incorrectly throw error when 5.2<=kernel<5.5

This commit is contained in:
mzz2017 2023-02-01 01:34:50 +08:00
parent 9cdee19b57
commit db50c80a96
4 changed files with 65 additions and 13 deletions

View File

@ -5,6 +5,8 @@
package consts
import internal "github.com/v2rayA/dae/pkg/ebpf_internal"
const (
AppName = "dae"
BpfPinRoot = "/sys/fs/bpf"
@ -93,3 +95,5 @@ const (
IpVersion_6 IpVersion = 2
IpVersion_X IpVersion = 3
)
var FtraceFeatureVersion = internal.Version{5, 5, 0}

View File

@ -95,3 +95,37 @@ func BatchUpdate(m *ebpf.Map, keys interface{}, values interface{}, opts *ebpf.B
return vKeys.Len(), nil
}
}
type bpfObjectsLan struct {
// NOTICE: Consider to update me if any program added.
TproxyEgress *ebpf.Program `ebpf:"tproxy_egress"`
TproxyIngress *ebpf.Program `ebpf:"tproxy_ingress"`
bpfMaps
}
func AssignBpfPrograms(to *bpfObjects, from interface{}) {
vTo := reflect.Indirect(reflect.ValueOf(to))
vFrom := reflect.Indirect(reflect.ValueOf(from))
tFrom := vFrom.Type()
// programs
for i := 0; i < vFrom.NumField(); i++ {
fieldFrom := vFrom.Field(i)
structFieldFrom := tFrom.Field(i)
if structFieldFrom.Type != reflect.TypeOf(&ebpf.Program{}) {
continue
}
fieldTo := vTo.FieldByName(structFieldFrom.Name)
fieldTo.Set(fieldFrom)
}
// bpfMaps
vFrom = vFrom.FieldByName("bpfMaps")
tFrom = vFrom.Type()
for i := 0; i < vFrom.NumField(); i++ {
fieldFrom := vFrom.Field(i)
structFieldFrom := tFrom.Field(i)
fieldTo := vTo.FieldByName(structFieldFrom.Name)
fieldTo.Set(fieldFrom)
}
}

View File

@ -38,6 +38,8 @@ import (
type ControlPlane struct {
log *logrus.Logger
kernelVersion *internal.Version
// TODO: add mutex?
outbounds []*outbound.DialerGroup
outboundName2Id map[string]uint8
@ -64,6 +66,11 @@ func NewControlPlane(
checkUrl string,
checkInterval time.Duration,
) (c *ControlPlane, err error) {
kernelVersion, e := internal.KernelVersion()
if e != nil {
return nil, fmt.Errorf("failed to get kernel version: %w", e)
}
// Allow the current process to lock memory for eBPF resources.
if err = rlimit.RemoveMemlock(); err != nil {
return nil, fmt.Errorf("rlimit.RemoveMemlock:%v", err)
@ -73,14 +80,20 @@ func NewControlPlane(
// Load pre-compiled programs and maps into the kernel.
var bpf bpfObjects
var bpfLan bpfObjectsLan
var ProgramOptions ebpf.ProgramOptions
if log.IsLevelEnabled(logrus.TraceLevel) {
ProgramOptions = ebpf.ProgramOptions{
LogLevel: ebpf.LogLevelStats,
}
}
var obj interface{} = &bpf
if kernelVersion.Less(consts.FtraceFeatureVersion) {
// Trick. Replace the beams with rotten timbers.
obj = &bpfLan
}
retryLoadBpf:
if err = loadBpfObjects(&bpf, &ebpf.CollectionOptions{
if err = loadBpfObjects(obj, &ebpf.CollectionOptions{
Maps: ebpf.MapOptions{
PinPath: pinPath,
},
@ -110,6 +123,11 @@ retryLoadBpf:
}
return nil, fmt.Errorf("loading objects: %v", err)
}
if kernelVersion.Less(consts.FtraceFeatureVersion) {
// Reverse takeover.
AssignBpfPrograms(&bpf, &bpfLan)
}
// Write params.
if err = bpf.ParamMap.Update(consts.DisableL4TxChecksumKey, consts.DisableL4ChecksumPolicy_SetZero, ebpf.UpdateAny); err != nil {
return nil, err
@ -235,6 +253,7 @@ retryLoadBpf:
return &ControlPlane{
log: log,
kernelVersion: &kernelVersion,
outbounds: outbounds,
outboundName2Id: outboundName2Id,
bpf: &bpf,
@ -369,22 +388,17 @@ func (c *ControlPlane) BindLan(ifname string) error {
}
func (c *ControlPlane) BindWan(ifname string) error {
if c.kernelVersion.Less(consts.FtraceFeatureVersion) {
// Not support ftrace (fentry/fexit).
// PID bypass needs it.
return fmt.Errorf("your kernel version %v does not support bind to WAN; expect >=%v; remove wan_interface in config file and try again", c.kernelVersion.String(), consts.FtraceFeatureVersion.String())
}
link, err := netlink.LinkByName(ifname)
if err != nil {
return err
}
version, e := internal.KernelVersion()
if e != nil {
return fmt.Errorf("BindWan: failed to get kernel version: %w", e)
}
ftraceFeatureVersion := internal.Version{5, 5, 0}
if version.Less(ftraceFeatureVersion) {
// Not support ftrace (fentry/fexit).
// PID bypass needs it.
return fmt.Errorf("your kernel version %v does not support bind to WAN; expect >=%v", version.String(), ftraceFeatureVersion.String())
}
// Set-up SrcPidMapper.
// Attach programs to support pname routing.

View File

@ -50,7 +50,7 @@ func (b *RoutingMatcherBuilder) OutboundToId(outbound string) uint8 {
var ok bool
outboundId, ok = b.outboundName2Id[outbound]
if !ok {
b.err = fmt.Errorf("%v not in outboundName2Id", strconv.Quote(outbound))
b.err = fmt.Errorf("%v not defined in group", strconv.Quote(outbound))
}
}
return outboundId