Skip to content

Commit

Permalink
feat(platform): Add support for OpenWrt 24.10 on x86-64 architecture (#…
Browse files Browse the repository at this point in the history
…214)

* improve load btf spec

* fix(capture): fix compatibility with OpenWrt 24.10

* remove hardcode

* change to check error instead of check release id

* fix typo

* fix comm name
  • Loading branch information
mozillazg authored Dec 20, 2024
1 parent a353f78 commit e3fa2ee
Show file tree
Hide file tree
Showing 16 changed files with 64 additions and 10 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ You can download the statically linked executable for x86_64 and arm64 from the

### Requirements

Linux kernel version >= 5.2.
Linux kernel >= 5.2 (compiled with BPF and BTF support).

<p align="right"><a href="#top">🔝</a></p>

Expand Down
2 changes: 1 addition & 1 deletion README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Table of Contents

### Requirements

`ptcpdump` 只支持 Linux 系统,并且系统的内核版本最好 >= 5.2。
`ptcpdump` 只支持 Linux 系统,并且系统的内核版本最好 >= 5.2 (内核需要启用 BPF 和 BTF 支持)

对于内核版本介于 4.18 ~ 5.2 之间的系统,如果系统中未提供程序依赖的内核 BTF 文件的话,
`ptcpdump` 将自动尝试从 [龙蜥 BTF 目录](https://mirrors.openanolis.cn/coolbpf/btf/)[BTFhub](https://github.com/aquasecurity/btfhub-archive)
Expand Down
22 changes: 18 additions & 4 deletions bpf/bpf.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ func (b *BPF) Load(opts Options) error {
if len(opts.ifindexes) > 0 {
config.FilterIfindexEnable = 1
}
if opts.backend != types.NetHookBackendCgroupSkb {
b.disableCgroupSkb()
}
if !b.isLegacyKernel {
log.Infof("rewrite constants with %+v", config)
err = b.spec.RewriteConstants(map[string]interface{}{
Expand All @@ -128,6 +131,9 @@ func (b *BPF) Load(opts Options) error {
}
}

loadCount := 0
load:
loadCount++
err = b.spec.LoadAndAssign(b.objs, &ebpf.CollectionOptions{
Programs: ebpf.ProgramOptions{
KernelTypes: opts.kernelTypes,
Expand All @@ -138,6 +144,11 @@ func (b *BPF) Load(opts Options) error {
IgnoreNotSupportedProgram: true,
})
if err != nil {
log.Infof("load and assign failed: %+v", err)
if isTracingNotSupportErr(err) && loadCount < 2 {
b.disableTracing()
goto load
}
return fmt.Errorf("bpf load and assign: %w", err)
}

Expand Down Expand Up @@ -221,10 +232,13 @@ func (b *BPF) UpdateFlowPidMapValues(data map[*BpfFlowPidKeyT]BpfProcessMetaT) e
}

func (b *BPF) AttachKprobes() error {
err := b.attachFentryOrKprobe("security_sk_classify_flow",
b.objs.FentrySecuritySkClassifyFlow, b.objs.KprobeSecuritySkClassifyFlow)
if err != nil {
return fmt.Errorf(": %w", err)
if err := b.attachFentryOrKprobe("security_sk_classify_flow",
b.objs.FentrySecuritySkClassifyFlow, b.objs.KprobeSecuritySkClassifyFlow); err != nil {
if isProbeNotSupportErr(err) { // some systems do not support this kprobe, e.g. openwrt
log.Warnf("%+v", err)
} else {
return fmt.Errorf(": %w", err)
}
}

if err := b.attachFentryOrKprobe("tcp_sendmsg", b.objs.FentryTcpSendmsg, b.objs.KprobeTcpSendmsg); err != nil {
Expand Down
Binary file modified bpf/bpf_arm64_bpfel.o
Binary file not shown.
Binary file modified bpf/bpf_legacy_arm64_bpfel.o
Binary file not shown.
Binary file modified bpf/bpf_legacy_x86_bpfel.o
Binary file not shown.
Binary file modified bpf/bpf_no_tracing_arm64_bpfel.o
Binary file not shown.
Binary file modified bpf/bpf_no_tracing_x86_bpfel.o
Binary file not shown.
Binary file modified bpf/bpf_x86_bpfel.o
Binary file not shown.
9 changes: 9 additions & 0 deletions bpf/cgroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ func (b *BPF) AttachCgroups(cgroupPath string) error {
b.skipAttachCgroup = true
}
if b.skipAttachCgroup {
log.Info("skipping cgroup attach")
return nil
}

Expand Down Expand Up @@ -40,6 +41,14 @@ func (b *BPF) AttachCgroups(cgroupPath string) error {
return nil
}

func (b *BPF) disableCgroupSkb() {
for k, v := range b.spec.Programs {
if v.Type == ebpf.CGroupSKB {
delete(b.spec.Programs, k)
}
}
}

func (b *BPF) AttachCgroupSkb(cgroupPath string, egress, ingress bool) error {
if cgroupPath == "" {
b.skipAttachCgroup = true
Expand Down
4 changes: 4 additions & 0 deletions bpf/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@ static __always_inline int parse_skb_l4(struct __sk_buff *skb, u8 protocol, stru
return 0;
}
case IPPROTO_SCTP: {
// some systems do not have struct sctphdr. e.g. openwrt
if (!bpf_core_type_exists(struct sctphdr)) {
return 0;
}
struct sctphdr sctp_hdr;
if (bpf_skb_load_bytes(skb, *offset, &sctp_hdr, sizeof(struct sctphdr)) < 0) {
// debug_log("parse_skb_l4 3 failed:\n");
Expand Down
20 changes: 20 additions & 0 deletions bpf/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,23 @@ func isProbeNotSupportErr(err error) bool {
}
return false
}

func isTracingNotSupportErr(err error) bool {
// TODO: refine
// find target in modules: parse types for module cast_common: can't read type names: string table is empty
// openwrt will raise this error
if strings.Contains(err.Error(), "can't read type names") {
log.Infof("%T", err)
log.Infof("%#v", err)
return true
}
return false
}

func (b *BPF) disableTracing() {
for k, v := range b.spec.Programs {
if v.Type == ebpf.Tracing {
delete(b.spec.Programs, k)
}
}
}
3 changes: 1 addition & 2 deletions cmd/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ func logFatal(err error) {
if errors.As(err, &ve) {
// Using %+v will print the whole verifier error, not just the last
// few lines.
log.Errorf("%+v", err)
log.Fatalf("Verifier error: %+v", ve)
log.Errorf("Verifier error: %+v", ve)
}
log.Fatalf("%+v", err)
}
Expand Down
2 changes: 2 additions & 0 deletions internal/btf/btf.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ func LoadBTFSpec(path string) (*btf.Spec, string, error) {
return spec, DefaultPath, nil
}

log.Warnf("could not load BTF specs from default location (/sys/kernel/btf/vmlinux): %s"+
", try to load from candidate locations", err)
spec, path, err = loadSpecFromCandidateLocations()
if err == nil {
return spec, path, nil
Expand Down
4 changes: 2 additions & 2 deletions internal/host/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ func GetRelease() (*Release, error) {
key = strings.TrimSpace(key)
switch key {
case "ID":
release.Id = strings.TrimSpace(value)
release.Id = strings.Trim(strings.TrimSpace(value), `"'`)
break
case "VERSION_ID":
release.VersionId = strings.TrimSpace(value)
release.VersionId = strings.Trim(strings.TrimSpace(value), `"'`)
break
}
}
Expand Down
6 changes: 6 additions & 0 deletions internal/types/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ func (p ProcessBase) FormatArgs() string {
}

func (p ProcessBase) Comm() string {
// openwrt case: pid 13055, cmd /dev/fd/5, args /usr/sbin/dropbear -F -P /var/run/dropbear.1.pid -p 22 -K 300
if strings.HasPrefix(p.Cmd, "/dev/fd/") {
if len(p.Args) > 0 {
return filepath.Base(p.Args[0])
}
}
return filepath.Base(p.Cmd)
}

Expand Down

0 comments on commit e3fa2ee

Please sign in to comment.