我编写了以下 eBPF 程序来计算数据包:
#include <linux/version.h>
#include <uapi/linux/bpf.h>
#include "include/bpf_map.h"
#include "include/bpf_helpers.h"
struct bpf_map_def SEC("maps/count") count_map = {
.type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(int),
.value_size = sizeof(__u64),
.max_entries = 1024,
};
SEC("cgroup/skb")
int count_packets(struct __sk_buff *skb) {
char debug[] = "count_packets\n";
bpf_trace_printk(debug, sizeof(debug));
int packets_key = 0;
__u64 *packets = 0;
packets = bpf_map_lookup_elem(&count_map, &packets_key);
if (packets == 0)
return 0;
*packets += 1;
// allow access
return 1;
}
char _license[] SEC("license") = "GPL";
u32 _version SEC("version") = LINUX_VERSION_CODE;
我还有一个用户空间组件,它将程序加载为 BPF_PROG_TYPE_CGROUP_SKB
,将其附加到 v2 cgroup (/sys/fs/cgroup/unified/foo
)使用附加类型 BPF_CGROUP_INET_EGRESS
,将自己的 PID 添加到该 cgroup 并开始创建网络流量。
当我在容器外运行这个用户空间组件时,它按预期工作,我看到我的程序通过执行 cat/sys/kernel/debug/tracing/trace_pipe
被调用。
但是,当我在容器中运行我的程序时,我看不到任何输出。
我按如下方式运行容器:
docker run -it \
--privileged \
--pid=host \
--net=host \
-v /sys/fs/cgroup/unified:/sys/fs/cgroup/unified \
${IMAGE}
我正在使用主机网络和 PID namespace 来避免它们可能导致的任何潜在问题。
为什么我的程序似乎无法在容器中运行?
uname -a
:Linux ubuntu-bionic 4.18.0-16-generic#17~18.04.1-Ubuntu SMP Tue Feb 12 13:35:51 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
最佳答案
这是因为 docker 使用 net_prio
和 net_cls
Controller 覆盖了用于 cgroup2 匹配的数据。来自 here
While userland may start using net_prio or net_cls at any time, once either is used, cgroup2 matching no longer works.
我的解决方案是使用引导标志禁用这些 Controller :cgroup_no_v1=net_prio,net_cls
。更好的解决方案是停止 docker 使用它们,但我不知道该怎么做。
关于linux - 为什么我的 BPF_PROG_TYPE_CGROUP_SKB 程序不能在容器中运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55646983/