Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add macro to control the bpf read method #27

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions bpf/kprobe_pwru.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

#define PRINT_SKB_STR_SIZE 2048

extern u32 LINUX_KERNEL_VERSION __kconfig;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think LINUX_KERNEL_VERSION is set only when loading with libbpf (we are using github.com/cilium/ebpf to load the prog).

We could ask / contribute to cilium/ebpf to add the support for it (should be relatively trivial, see https://github.com/libbpf/libbpf/blob/v0.5.0/src/libbpf.c#L6804). /cc @ti-mo @lmb

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LINUX_KERNEL_VERSION is just to extract a running kernel version or a name that matches one of Kconfig’s keys. I do not think it has something with libbpf.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The version is set during the loadtime. Check https://github.com/libbpf/libbpf/blob/v0.5.0/src/libbpf.c#L6804 to see how it's set in libbpf. Currently, cilium/ebpf doesn't support it.

Also, you can check it by adding into the code:

#if (LINUX_KERNEL_VERSION >= KERNEL_VERSION(5,5,0))
	char fmt[] = "foo\n";
	bpf_trace_printk(foo, sizeof(foo));
#endif

and then

cat /sys/kernel/debug/tracing/trace_pipe

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@brb thanks for you explanation. I got the point.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Please let me know if you are going to work on adding LINUX_KERNEL_VERSION support to cilium/ebpf.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, apparenly this depends on parsing /proc/config.gz: https://nakryiko.com/posts/bpf-core-reference-guide/#linux-kernel-version. I don't think cilium/ebpf has support for Kconfig externs yet.

We have kernel version detection, though: https://github.com/cilium/ebpf/blob/1eb0e981058a2d5335965c6dc450a6442ad0377e/internal/version.go#L90-L99. I would prefer to use this for LINUX_KERNEL_VERSION over parsing kconfig.gz in the mean time.

@lmb any thoughts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

apparenly this depends on parsing /proc/config.gz

It depends on config.gz for CONFIG_ parsing. While LINUX_KERNEL_VERSION - on the uname syscall.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, we're open to implementing the LINUX_KERNEL_VERSION extern using the existing kernel version detection we have in the lib. @zhangbo1882 would you be willing to contribute this as a feature?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ti-mo , I am very pleased to do that. Let me check cilium/ebpf code first.


struct skb_meta {
u32 mark;
u32 ifindex;
Expand Down Expand Up @@ -109,7 +111,11 @@ filter_mark(struct sk_buff *skb, struct config *cfg) {
u32 mark;

if (cfg->mark) {
#if (LINUX_KERNEL_VERSION >= KERNEL_VERSION(5, 5, 0))
mark = BPF_CORE_READ(skb, mark);
#else
bpf_probe_read(&mark, sizeof(mark), &skb->mark);
zhangbo1882 marked this conversation as resolved.
Show resolved Hide resolved
#endif
return mark == cfg->mark;
}

Expand All @@ -135,9 +141,15 @@ filter_l3_and_l4(struct sk_buff *skb, struct config *cfg) {
!cfg->sport && !cfg->dport)
return true;

#if (LINUX_KERNEL_VERSION >= KERNEL_VERSION(5, 5, 0))
skb_head = BPF_CORE_READ(skb, head);
l3_off = BPF_CORE_READ(skb, network_header);
l4_off = BPF_CORE_READ(skb, transport_header);
#else
bpf_probe_read(&skb_head, sizeof(skb_head), &skb->head);
bpf_probe_read(&l3_off, sizeof(l3_off), &skb->network_header);
bpf_probe_read(&l4_off, sizeof(l4_off), &skb->transport_header);
#endif

struct iphdr *tmp = (struct iphdr *) (skb_head + l3_off);
bpf_probe_read(&iphdr_first_byte, 1, tmp);
Expand Down Expand Up @@ -196,11 +208,25 @@ filter(struct sk_buff *skb, struct config *cfg) {

static __always_inline void
set_meta(struct sk_buff *skb, struct skb_meta *meta) {
#if (LINUX_KERNEL_VERSION >= KERNEL_VERSION(5, 5, 0))
meta->mark = BPF_CORE_READ(skb, mark);
meta->len = BPF_CORE_READ(skb, len);
meta->protocol = BPF_CORE_READ(skb, protocol);
meta->ifindex = BPF_CORE_READ(skb, dev, ifindex);
meta->mtu = BPF_CORE_READ(skb, dev, mtu);
#else
struct net_device *dev = 0;

bpf_probe_read(&meta->mark, sizeof(meta->mark), &skb->mark);
bpf_probe_read(&meta->len, sizeof(meta->len), &skb->len);
bpf_probe_read(&meta->protocol, sizeof(meta->protocol), &skb->protocol);

if (!bpf_probe_read(&dev, sizeof(dev), &skb->dev)) {
bpf_probe_read(&meta->ifindex, sizeof(dev->ifindex),
&dev->ifindex);
bpf_probe_read(&meta->mtu, sizeof(dev->mtu), &dev->mtu);
}
#endif
}

static __always_inline void
Expand All @@ -212,10 +238,16 @@ set_tuple(struct sk_buff *skb, struct tuple *tpl) {
u8 iphdr_first_byte;
u8 ip_vsn;

#if (LINUX_KERNEL_VERSION >= KERNEL_VERSION(5, 5, 0))
skb_head = BPF_CORE_READ(skb, head);
l3_off = BPF_CORE_READ(skb, network_header);
l4_off = BPF_CORE_READ(skb, transport_header);
#else
bpf_probe_read(&skb_head, sizeof(skb_head), &skb->head);
bpf_probe_read(&l3_off, sizeof(l3_off), &skb->network_header);
bpf_probe_read(&l4_off, sizeof(l4_off), &skb->transport_header);

#endif
ip = (struct iphdr *) (skb_head + l3_off);
bpf_probe_read(&tpl->proto, 1, &ip->protocol);

Expand Down