如何从内核树构建 BPF 程序
how to build BPF program out of the kernel tree
内核在samples/bpf
中提供了大量示例。我有兴趣在树之外构建一个示例,就像我们构建内核模块一样,其中 Makefile
可以足够简单。 bpf 也可以这样做吗?我通过从 samples/bpf/Makefile
中删除不必要的部分并保持对 libbpf
和其他人的依赖来尝试它,但事实证明它并不那么容易。
例如,尝试在内核树之外构建 samples/bpf/bpf_tcp_kern.c
,使用以下命令行(我查看了 samples/bpf/Makefile,以及 make samples/bpf V=1
的输出):
clang -nostdinc -isystem /usr/lib/gcc/x86_64-linux-gnu/5/include \
-I/home/mark/work/net-next.git/arch/x86/include -I/home/mark/work/net-next.git/arch/x86/include/generated -I./include -I/home/mark/work/net-next.git/arch/x86/include/uapi -I/home/mark/work/net-next.git/arch/x86/include/generated/uapi -I/home/mark/work/net-next.git/include -I/home/mark/work/net-next.git/generated/uapi -I./ \
-D__KERNEL__ -Wno-unused-value -Wno-pointer-sign \
-D__TARGET_ARCH_x86 -Wno-compare-distinct-pointer-types \
-Wno-gnu-variable-sized-type-not-at-end \
-Wno-address-of-packed-member -Wno-tautological-compare \
-Wno-unknown-warning-option \
-O2 -emit-llvm -c bpf_tcp_kern.c -o -| llc -march=bpf -filetype=obj -o bpf_tcp_kern.o
In file included from bpf_tcp_kern.c:15:
In file included from /home/mark/work/net-next.git/include/uapi/linux/bpf.h:11:
In file included from /home/mark/work/net-next.git/include/linux/types.h:6:
In file included from /home/mark/work/net-next.git/include/uapi/linux/types.h:5:
/home/mark/work/net-next.git/arch/x86/include/uapi/asm/types.h:5:10: fatal error: 'asm-generic/types.h' file not found
#include <asm-generic/types.h>
^
1 error generated
这是 clang-llvm 3.8.0
我需要 libbpf
来构建用户端 bpf 应用程序。这部分工作构建得很好。
我错过了什么吗?我相信这个任务应该相当容易 ;-)
假设这是“eBPF”。是的,这应该是可能的。基本上,你应该能够用这样的东西编译最简单的 eBPF 程序:
clang -O2 -emit-llvm -c bpf.c -o - | llc -march=bpf -filetype=obj -o bpf.o
(摘自 tc-bpf(8)
的手册页)
当然,如果您的程序使用本地 header 文件中的定义,您必须找到一种方法来包含它们(即保留足够的 header 文件来编译您的文件,即使你 "rip out" 其他一切)。
一些注意事项:
- clang 和 llvm (llc) 应该是 3.7 或更高版本(越高越好)。
- 根据您尝试编译的 eBPF 功能,您需要内核 headers(特别是
<linux/bpf.h>
)足够新以支持您的程序(另请参阅 this page).
- 不确定您打算使用
libbpf
做什么。如果我没记错的话,它是用来从外部程序加载和管理eBPF程序的,而不是包含在eBPF程序本身中?
- [编辑] 此外,
samples/bpf
下的 eBPF 程序似乎是使用内核模块基础架构构建的。它们本身 不是 模块,但以某种方式编译就好像它们是模块一样,可以访问内核 headers。因此,如果您尝试在树之外编译它们并且没有内核 makefile,您可能会失去对 <linux/*.h>
header 的访问权限,并且必须将 <uapi/linux/*.h>
替换为 <linux/*.h>
相反..
作为一般建议,尝试简化您的程序直到它编译,然后再次添加功能:)。如果没有源代码或错误消息,我恐怕无法为您提供更多帮助。祝你好运!
[在问题本身更新后编辑]
我能够通过向命令添加以下三行来编译一个示例(通过 运行 make samples/bpf/tcp_bufs_kern.o V=1
获得它们,不确定您是否将它们修剪掉或者是否有不同的东西):
…
-I/home/mark/work/net-next.git/include/generated/uapi \
-I/home/mark/work/net-next.git/tools/testing/selftests/bpf/ \
-include /home/mark/work/net-next.git/include/linux/kconfig.h \
…
您的命令抱怨的 asm-generic.h
header 的第一行;第二行是 "bpf-helpers.h"
,您可以轻松地将其复制到您的工作目录。最后一行可能更难删除,我没有详细搜索为什么需要kconfig.h
,你必须调查一下。
内核在samples/bpf
中提供了大量示例。我有兴趣在树之外构建一个示例,就像我们构建内核模块一样,其中 Makefile
可以足够简单。 bpf 也可以这样做吗?我通过从 samples/bpf/Makefile
中删除不必要的部分并保持对 libbpf
和其他人的依赖来尝试它,但事实证明它并不那么容易。
例如,尝试在内核树之外构建 samples/bpf/bpf_tcp_kern.c
,使用以下命令行(我查看了 samples/bpf/Makefile,以及 make samples/bpf V=1
的输出):
clang -nostdinc -isystem /usr/lib/gcc/x86_64-linux-gnu/5/include \
-I/home/mark/work/net-next.git/arch/x86/include -I/home/mark/work/net-next.git/arch/x86/include/generated -I./include -I/home/mark/work/net-next.git/arch/x86/include/uapi -I/home/mark/work/net-next.git/arch/x86/include/generated/uapi -I/home/mark/work/net-next.git/include -I/home/mark/work/net-next.git/generated/uapi -I./ \
-D__KERNEL__ -Wno-unused-value -Wno-pointer-sign \
-D__TARGET_ARCH_x86 -Wno-compare-distinct-pointer-types \
-Wno-gnu-variable-sized-type-not-at-end \
-Wno-address-of-packed-member -Wno-tautological-compare \
-Wno-unknown-warning-option \
-O2 -emit-llvm -c bpf_tcp_kern.c -o -| llc -march=bpf -filetype=obj -o bpf_tcp_kern.o
In file included from bpf_tcp_kern.c:15:
In file included from /home/mark/work/net-next.git/include/uapi/linux/bpf.h:11:
In file included from /home/mark/work/net-next.git/include/linux/types.h:6:
In file included from /home/mark/work/net-next.git/include/uapi/linux/types.h:5:
/home/mark/work/net-next.git/arch/x86/include/uapi/asm/types.h:5:10: fatal error: 'asm-generic/types.h' file not found
#include <asm-generic/types.h>
^
1 error generated
这是 clang-llvm 3.8.0
我需要 libbpf
来构建用户端 bpf 应用程序。这部分工作构建得很好。
我错过了什么吗?我相信这个任务应该相当容易 ;-)
假设这是“eBPF”。是的,这应该是可能的。基本上,你应该能够用这样的东西编译最简单的 eBPF 程序:
clang -O2 -emit-llvm -c bpf.c -o - | llc -march=bpf -filetype=obj -o bpf.o
(摘自 tc-bpf(8)
的手册页)
当然,如果您的程序使用本地 header 文件中的定义,您必须找到一种方法来包含它们(即保留足够的 header 文件来编译您的文件,即使你 "rip out" 其他一切)。
一些注意事项:
- clang 和 llvm (llc) 应该是 3.7 或更高版本(越高越好)。
- 根据您尝试编译的 eBPF 功能,您需要内核 headers(特别是
<linux/bpf.h>
)足够新以支持您的程序(另请参阅 this page). - 不确定您打算使用
libbpf
做什么。如果我没记错的话,它是用来从外部程序加载和管理eBPF程序的,而不是包含在eBPF程序本身中? - [编辑] 此外,
samples/bpf
下的 eBPF 程序似乎是使用内核模块基础架构构建的。它们本身 不是 模块,但以某种方式编译就好像它们是模块一样,可以访问内核 headers。因此,如果您尝试在树之外编译它们并且没有内核 makefile,您可能会失去对<linux/*.h>
header 的访问权限,并且必须将<uapi/linux/*.h>
替换为<linux/*.h>
相反..
作为一般建议,尝试简化您的程序直到它编译,然后再次添加功能:)。如果没有源代码或错误消息,我恐怕无法为您提供更多帮助。祝你好运!
[在问题本身更新后编辑]
我能够通过向命令添加以下三行来编译一个示例(通过 运行 make samples/bpf/tcp_bufs_kern.o V=1
获得它们,不确定您是否将它们修剪掉或者是否有不同的东西):
…
-I/home/mark/work/net-next.git/include/generated/uapi \
-I/home/mark/work/net-next.git/tools/testing/selftests/bpf/ \
-include /home/mark/work/net-next.git/include/linux/kconfig.h \
…
您的命令抱怨的 asm-generic.h
header 的第一行;第二行是 "bpf-helpers.h"
,您可以轻松地将其复制到您的工作目录。最后一行可能更难删除,我没有详细搜索为什么需要kconfig.h
,你必须调查一下。