ebpf尾调用无法正常工作,即使bpf代码已成功加载。

huangapple go评论68阅读模式
英文:

ebpf tail call didn't work even bpf code is loaded successfully

问题

#include "bpf/bpf_helpers.h"
#include <linux/bpf.h>

char _license[] SEC("license") = "GPL";

struct bpf_map_def SEC("maps") jump_table = {
    .type = BPF_MAP_TYPE_PROG_ARRAY,
    .key_size = sizeof(__u32),
    .value_size = sizeof(__u32),
    .max_entries = 100,
};

SEC("xdp_1")
int test_func(struct xdp_md *ctx) {
    bpf_printk("tail call\n");
    return XDP_PASS;
}

SEC("xdp")
int xdp_pass_func(struct xdp_md *ctx) {
    __u32 zero = 0;
    bpf_tail_call(ctx, &jump_table, zero);
    bpf_printk("tail call failed\n");
    return XDP_PASS;
}

当我查看 cat /sys/kernel/debug/tracing/trace_pipe 时,显示 tail call failed,但我不知道出了什么问题,这是我的加载代码:

func main() {
    if err := rlimit.RemoveMemlock(); err != nil {
        log.Fatal(err)
        return
    }
    var obj aclObjects
    err := loadAclObjects(&obj, nil)
    if err != nil {
        log.Fatal(err)
        return
    }
    err = obj.JumpTable.Put(uint32(0), uint32(obj.TestFunc.FD()))
    if err != nil {
        log.Fatal(err)
        return
    }
    link, err := netlink.LinkByName("ens33")
    if err != nil {
        log.Fatal(err)
        return
    }
    err = netlink.LinkSetXdpFd(link, obj.XdpPassFunc.FD())
    if err != nil {
        log.Fatal(err)
        return
    }
}

BPF代码可以加载,但似乎tail_call有些问题,我根据Linux源代码编写的,有人可以帮助我吗?

英文:
#include &quot;bpf/bpf_helpers.h&quot;
#include &lt;linux/bpf.h&gt;
char _license[] SEC(&quot;license&quot;) = &quot;GPL&quot;;
struct bpf_map_def SEC(&quot;maps&quot;) jump_table = {
    .type = BPF_MAP_TYPE_PROG_ARRAY,
    .key_size = sizeof(__u32),
    .value_size = sizeof(__u32),
    .max_entries = 100,
};

SEC(&quot;xdp_1&quot;)
int test_func(struct xdp_md *ctx) {
  bpf_printk(&quot;tail call\n&quot;);
  return XDP_PASS;
}

SEC(&quot;xdp&quot;)
int xdp_pass_func(struct xdp_md *ctx) {
  __u32 zero = 0;
  bpf_tail_call(ctx, &amp;jump_table, zero);
  bpf_printk(&quot;tail call failed\n&quot;);
  return XDP_PASS;
}

when i look cat /sys/kernel/debug/tracing/trace_pipe, it shows tail call failed,but i don't know whats wrong,here is my load code

func main() {
	if err := rlimit.RemoveMemlock(); err != nil {
		log.Fatal(err)
		return
	}
	var obj aclObjects
	err := loadAclObjects(&amp;obj, nil)
	if err != nil {
		log.Fatal(err)
		return
	}
	err = obj.JumpTable.Put(uint32(0), uint32(obj.TestFunc.FD()))
	if err != nil {
		log.Fatal(err)
		return
	}
	link, err := netlink.LinkByName(&quot;ens33&quot;)
	if err != nil {
		log.Fatal(err)
		return
	}
	err = netlink.LinkSetXdpFd(link, obj.XdpPassFunc.FD())
	if err != nil {
		log.Fatal(err)
		return
	}
}

the bpf code can be loaded, but it seems some thing wrong with tail_call,i wrote it according to linux source code,someone can help me?

答案1

得分: 1

正如你在回答中意识到并提到的那样,当加载器退出时,引用程序的文件描述符确实会关闭。

如果没有其他引用该程序的内容,它将被卸载。什么可以保持这样的引用?

  • 上述文件描述符,只要加载器保持打开状态。
  • 如果程序连接到某些钩子(例如:网络钩子),即使加载过程结束后,它仍然保持在原地。
  • 如果程序被固定,它也会被保留。这正是将程序固定到虚拟BPF文件系统的目的。有关将程序固定到bpffs的详细信息,请参阅此参考资料,或者更一般地,参阅关于eBPF对象生命周期的文章

你想要在加载器退出之前将程序固定(看起来你使用的是goebpf?显然该库有一个Pin()函数,应该会有所帮助)。

英文:

As you realised and mentioned in your answer, the file descriptor referencing the program will indeed be closed when the loader exits.

If nothing else references the program, it is unloaded. What can hold such a reference?

What you want is to pin your program before your loader exits (It seems you use goebpf? Apparently the library has a Pin() function, which should probably help).

答案2

得分: 0

我发现了一个问题,当加载程序退出时,程序fd会被关闭,所以我将程序阻塞住,尾调用正常工作,我不知道为什么fd关闭会成为一个问题,希望有人可以回答。

英文:

i find the problem that prog fd will be closed when loader program exit, so i keep the program blocked and tail call works fine, i don't know why fd closed is a problem, hoping someone can answer

huangapple
  • 本文由 发表于 2022年5月9日 17:54:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/72170112.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定