- strace:是一个功能强大的调试、分析、诊断工具,跟踪程序或进程执行时的系统调用和所接收的信号。可将所调用的系统调用的名称、参数和返回值输出到标准输出或者输出到-o指定的文件。
它的实现基础是ptrace系统调用, - ltrace:库文件调用跟踪器,Linux内核内建命令,用法类似strace
- ptrace:进程跟踪器,类似于gdb watch的调试方法
ptrace系统调用提供了一种方法来跟踪和控制进程的执行,它可以读取和修改进程地址空间中的内容,包括寄存器的值。 - ftrace:本质上是一种静态代码插装技术,不需要支持某种变成接口让用户自定义trace行为,这样可以提高系统的稳定性。
- btrace:BTrace-用于Java平台的安全,动态跟踪工具,跟踪适用于Java平台的安全
- perf:perf是Linux的一款性能分析工具,能够进行函数级和指令级的热点查找,可以用来分析程序中热点函数的CPU占用率,从而定位性能瓶颈。
- Oprofile: 我觉得是一个较过时的性能检测工具了,基本被perf取代,命令使用起来也不太方便
- DTrace:全称Dynamic Tracing,也称为动态跟踪;可以对内核(kernel)和用户应用程序(user application)进行动态跟踪并且对系统运行不构成任何危险的技术
DTrace是Solaris下的产物,Linux则水土不服,建议不要用了,使用其替代品:BPF(Berkeley Packet Filter,伯克利包过滤器),用法及语法非常相似,功能也是异常的强大,Linux内核层原生支撑其功能。 - systemtap: 这种技术最先始于dtrace,而dtrace主要使用在unix系统上,自己使用的macbook就是直接可以使用dtrace的。systemtap像是dtrace在linux世界中的重新实现(需要安装和内核版本一致的kernel-devel, kernel-debuginfo, kernel-debuginfo-common)
- blktrace:块I/O 跟踪(Linux)
BPF技术原理
BPF 是 Linux 内核中一个非常灵活与高效的类虚拟机(virtual machine-like)组件,能够在许多内核 hook 点安全地执行字节码(bytecode )。
很多内核子系统都已经使用了 BPF,例如常见的网络(networking)、跟踪( tracing)与安全(security ,例如沙盒)。
eBPF 最早出现在 3.18 内核中,此后原来的 BPF 就被称为“经典”
BPF(classic BPF, cBPF),cBPF 现在基本已经过时了。
很多人知道 cBPF 是因为它是 tcpdump 的包过滤语言。
Cilium 在其数据平面(datapath)中重度使用了 BPF 技术,更多信息可参考其 eBPF datapath 架构文档。
本文的目标是提供一份 BPF 参考指南,这份指南能帮助我们更深入地理解 BPF、BPF 网络相关的使用方式(例如用 tc 加载 BPF 程序,XDP 程序 ),以及更好地开发 Cilium 中的 BPF 模板。
BPF 架构
BPF 不仅仅是一个指令集,它还提供了围绕自身的一些基础设施
- BPF map:高效的 key/value 存储
- 辅助函数(helper function):可以更方便地利用内核功能或与内核交互
- 尾调用(tail call):高效地调用其他 BPF 程序
- 安全加固原语(security hardening primitives)
- 用于 pin/unpin 对象(例如 map、程序)的伪文件系统(bpffs),实现持久存储
- 支持 BPF offload(例如 offload 到网卡)的基础设施
LLVM 提供了一个 BPF 后端(back end),因此使用 clang 这样的工具就可以将 C 代码编译成 BPF 对象文件(object file)然后再加载到内核。
BPF 深度绑定 Linux 内核,可以在不牺牲原生内核性能的前提下,实现对内核的完全可编程 (full programmability)。
另外使用了 BPF 的内核子系统也是 BPF 基础设施的一部分。本文将主要讨论 tc和 XDP 这两个子系统,二者都支持 attach(附着)BPF 程序。
XDP BPF 程序会被 attach 到网络驱动的最早阶段(earliest networking driver stage),驱动收到包之后就会触发 BPF 程序的执行。
从定义上来说,这可以取得最好的包处理性能,因为这已经是软件中最早可以处理包的位置了。但也正因为 这一步的处理在网络栈中是如此之早,协议栈此时还没有从包中提取出元数据(因此 XDP BPF 程序无法利用这些元数据)。
tc BPF 程序在内核栈中稍后面的一些地方执行,因此它们能够访问更多的元数据和一些核心的内核功能。
除了 tc 和 XDP 程序之外,还有很多其他内核子系统也在使用 BPF,例如跟踪子系统( kprobes
、uprobes
、tracepoints
等等)。
指令集
指令集
BPF 是一个通用目的 RISC 指令集,其最初的设计目标是:
- 用 C 语言的一个子集编写程序,
- 然后用一个编译器后端(例如 LLVM)将其编译成 BPF 指令,
- 稍后内核再通过一个位于内核中的(in-kernel)即时编译器(JIT Compiler) 将 BPF 指令映射成处理器的原生指令(opcode ),以获得在内核中的最佳执行性能。
将这些指令下放到内核中可以带来如下好处
- 无需在内核/用户空间切换就可以实现内核的可编程。
例如Cilium 这种和网络相关的 BPF 程序能直接在内核中实现灵活的容器策略、负载均衡等功能,而无需将包送先 到用户空间,处理之后再送回内核。需要在 BPF 程序之间或内核/用户空间之间共享状态时,可以使用 BPF map。
- 可编程 datapath 具有很大的灵活性,因此程序能在编译时将不需要的特性禁用掉, 从而极大地优化程序的性能。
例如如果容器不需要 IPv4,那编写 BPF 程序时就可以只处理 IPv6 的情况,从而节省了快速路径(fast path)中的资源。
- 对于网络场景(例如 tc 和 XDP),BPF 程序可以在无需重启内核、系统服务或容器的 情况下实现原子更新,并且不会导致网络中断。另外更新 BPF map 不会导致程序状态(program state)的丢失。
- BPF 给用户空间提供了一个稳定的 ABI,而且不依赖任何第三方内核模块。
BPF 是 Linux 内核的一个核心组成部分,而 Linux 已经得到了广泛的部署,因此可以保证现 有的 BPF 程序能在新的内核版本上继续运行。这种保证与系统调用(内核提供给用 户态应用的接口)是同一级别的。另外BPF 程序在不同平台上是可移植的。
- BPF 程序与内核协同工作,复用已有的内核基础设施(例如驱动、netdevice、 隧道、协议栈和 socket)和工具(例如 iproute2),以及内核提供的安全保证。和内核模块不同 BPF 程序会被一个位于内核中的校验器(in-kernel verifier)进行校验, 以确保它们不会造成内核崩溃、程序永远会终止等等。
例如XDP 程序会复用已有的内核驱动,能够直接操作存放在 DMA 缓冲区中的数据帧,而不用像某些模型(例如 DPDK) 那样将这些数据帧甚至整个驱动暴露给用户空间。 而且XDP 程序复用内核协议栈而不是绕过它。BPF 程序可以看做是内核设施之间的通用“胶水代码”, 基于 BPF 可以设计巧妙的程序,解决特定的问题。
BPF 程序在内核中的执行总是事件驱动的!例如
- 如果网卡的 ingress 路径上 attach 了 BPF 程序,那当网卡收到包之后就会触发这个 BPF 程序的执行。
- 在某个有 kprobe 探测点的内核地址 attach 一段 BPF 程序后,当 内核执行到这个地址时会发生陷入(trap),进而唤醒 kprobe 的回调函数,后 者又会触发 attach 的 BPF 程序的执行。
BPF 寄存器和调用约定
BPF 由下面几部分组成
- 11 个 64 位寄存器(这些寄存器包含 32 位子寄存器)
- 一个程序计数器(program counter,PC)
- 一个 512 字节大小的 BPF 栈空间(从实现的层面理解为什么有 512 字节的限制, 可参考 (译) Linux Socket Filtering (LSF, aka BPF)(Kernel,2021),译注。)
寄存器的名字从 r0 到 r10。
默认的运行模式是 64 位,32 位子寄存器只能通过特殊的 ALU(arithmetic logic unit)访问。向 32 位子寄存器写入时,会用 0 填充 到 64 位。
r10 是唯一的只读寄存器,其中存放的是访问 BPF 栈空间的栈帧指针(frame pointer) 地址。r0 - r9 是可以被读/写的通用目的寄存器。
BPF 程序可以调用核心内核(而不是内核模块)预定义的一些辅助函数。BPF 调用约定 定义如下:
r0
存放被调用的辅助函数的返回值r1
-r5
存放 BPF 调用内核辅助函数时传递的参数r6
-r9
由被调用方(callee)保存,在函数返回之后调用方(caller)可以读取
每个 BPF 程序的最大指令数限制在 4096 条以内,这意味着从设计上就可以保证每个程序都会很快结束。对于内核 5.1+,这个限制放大到了 100 万条。
BPF 指令格式
BPF 指令格式(instruction format)建模为两操作数指令(two operand instructions)
这种格式可以在 JIT 阶段将 BPF 指令映射(mapping)为原生指令。
指令集是固定长度的,这意味着每条指令都是 64 比特编码的。
目前已经实现了 87 条指令,并且在需要时可以对指令集进行进一步扩展
op:8, dst_reg:4, src_reg:4, off:16, imm:32
off
和imm
都是有符号类型
所有的 op 指令可以分为若干类别。
op 字段分为( 从 MSB 到 LSB):code:4, source:1 和 class:3。class
是指令类型code
指特定类型的指令中的某种特定操作码(operational code)source
可以告诉我们源操作数(source operand)是一个寄存器还是一个立即数
op
定了将要执行的操作dst_reg
和src_reg
都提供了寄存器操作数(register operands,例如 r0 - r9)的额外信息。off
用于表示一个相对偏移量(offset),
可能的指令类别包括
BPF_LDX
:加载操作(load operations)BPF_STX
:存储操作(store operations)BPF_ALU
,BPF_ALU64
:逻辑运算操作(ALU operations)
辅助函数
辅助函数(Helper functions)使得 BPF 能够通过一组内核定义的函数调用(function call)来从内核中查询数据,或者将数据推送到内核。
不同类型的 BPF 程序能够使用的 辅助函数可能是不同的
所有的辅助函数都共享同一个通用的、和系统调用类似的函数签名。1
u64 fn(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)
内核将辅助函数抽象成 BPF_CALL_0() 到 BPF_CALL_5() 几个宏,形式和相应类型的系统调用类似。
下面的例子是从某个辅助函数中抽取出来的,可以看到它通过调用相应 map 的回调函数完成更新 map 元素的操作:
1 | BPF_CALL_4(bpf_map_update_elem, struct bpf_map *, map, void *, key, |
这种方式有很多优点:虽然 cBPF 允许其加载指令(load instructions)进行 超出范围的访问(overload),以便从一个看似不可能的包偏移量(packet offset,负的)位置获取数据以唤醒多功能辅助函数,但每个 cBPF JIT 仍然需要为这个 cBPF extension 实现对应的支持。
Maps
map 是驻留在内核空间中的高效键值仓库(key/value store)。
map 中的数据可以被 BPF 程序访问,如果想在多次 BPF 程序调用(invoke)之间保存状态,可以将状态信息放到 map。
map 还可以从用户空间通过文件描述符访问,可以在任意 BPF 程序以及用户空间应用之间共享。
共享 map 的 BPF 程序不要求是相同的程序类型,例如 tracing 程序可以和网络程序共享 map。
单个 BPF 程序目前最多可直接访问 64 个不同 map。
map 的实现由核心内核(core kernel)提供。
有 per-CPU 及 non-per-CPU 的通用 map,这些 map 可以读/写任意数据,也有一些和辅助函数一起使用的非通用 map。
当前可用的通用 map
BPF_MAP_TYPE_HASH
BPF_MAP_TYPE_ARRAY
BPF_MAP_TYPE_PERCPU_HASH
BPF_MAP_TYPE_PERCPU_ARRAY
BPF_MAP_TYPE_LRU_HASH
BPF_MAP_TYPE_LRU_PERCPU_HASH
BPF_MAP_TYPE_LPM_TRIE
以上 map 都使用相同的一组 BPF 辅助函数来执行查找、更新或删除操作
当前内核中的非通用 map
BPF_MAP_TYPE_PROG_ARRAY
BPF_MAP_TYPE_PERF_EVENT_ARRAY
BPF_MAP_TYPE_CGROUP_ARRAY
BPF_MAP_TYPE_STACK_TRACE
BPF_MAP_TYPE_ARRAY_OF_MAPS
BPF_MAP_TYPE_HASH_OF_MAPS
这些类型的 map 都针对特定的问题,不适合单单通过一个 BPF 辅助函数实现,因为它们需要在各次 BPF 程序调用 (invoke)之间时保持额外的(非数据)状态。
Object Pinning(钉住对象)
BPF map 和程序作为内核资源只能通过文件描述符访问,其背后是内核中的匿名 inode。
这带来了很多优点,例如:
- 用户空间应用能够使用大部分文件描述符相关的 API,
- 在 Unix socket 中传递文件描述符是透明的,等等。
但同时也有很多缺点:文件描述符受限于进程的生命周期,使得 map 共享之类的操作非常笨重。
因此这给某些特定的场景带来了很多复杂性,例如 iproute2,其中的 tc 或 XDP 在准备环境、加载程序到内核之后最终会退出。在这种情况下,从用户空间也无法访问这些 map 了,而本来这些 map 其实是很有用的,例如,在 data path 的 ingress 和 egress 位置共享的 map(可以统计包数、字节数、PPS 等信息)。另外第三方应用可能希望在 BPF 程序运行时监控或更新 map。
为了解决这个问题,内核实现了一个最小内核空间 BPF 文件系统,BPF map 和 BPF 程序 都可以钉到(pin)这个文件系统内,这个过程称为 object pinning(钉住对象)。相应地 BPF 系统调用进行了扩展,添加了两个新命令,分别用于钉住(BPF_OBJ_PIN)一个对象和获取(BPF_OBJ_GET)一个被钉住的对象(pinned objects)。
例如tc 之类的工具可以利用这个基础设施在 ingress 和 egress 之间共享 map。BPF 相关的文件系统不是单例模式(singleton),它支持多挂载实例、硬链接、软连接等等。
尾调用(Tail Calls)
尾调用的机制是:一个 BPF 程序可以调用另一个 BPF 程序,并且调用完成后不用返回到原来的程序。
和普通函数调用相比,这种调用方式开销最小,因为它是用长跳转(long jump)实现的,复用了原来的栈帧 (stack frame)。
类型相同的 BPF 程序才可以尾调用,而且还要与 JIT 编译器相匹配, 因此一个给定的 BPF 程序要么是 JIT编译执行,要么是解释器执行(invoke interpreted programs),而不能同时使用两种方式。
尾调用执行涉及两个步骤
- 设置一个称为“程序数组”(program array)的特殊 map(map 类型 BPF_MAP_TYPE_PROG_ARRAY ),这个 map 可以从用户空间通过 key/value 操作,
- 调用辅助函数 bpf_tail_call()。两个参数:一个对程序数组的引用(a reference to the program array),一个查询 map 所用的 key。内核将这个辅助函数调用内联( inline)到一个特殊的 BPF 指令内。目前这样的程序数组在用户空间侧是只写模式( write-only from user space side)。
内核根据传入的文件描述符查找相关的 BPF 程序,自动替换给定的 map slot(槽) 处的 程序指针。如果没有找到给定的 key 对应的 value,内核会跳过(fall through)这一步 ,继续执行 bpf_tail_call() 后面的指令。
尾调用是一个强大的功能,例如可以通过尾调用结构化地解析网络头(network headers)。
cilium其实也使用到了bpf_tail_call功能比如from-netdev
物理网卡到容器种用了tail_call_dynamic
BPF to BPF Calls
除了 BPF 辅助函数和 BPF 尾调用之外,BPF 核心基础设施最近刚加入了一个新特性:BPF 到 BPF 调用(BPF to BPF calls)。
在这个特性引入内核之前,典型的 BPF C 程序必须 将所有需要复用的代码进行特殊处理,例如在头文件中声明为 always_inline。当 LLVM 编译和生成 BPF 对象文件时,所有这些函数将被内联,因此会在生成的对象文件中重复多次,导致代码尺寸膨胀
从 Linux 4.16 和 LLVM 6.0 开始,这个限制得到了解决,BPF 程序不再需要到处使用 always_inline 声明了。
BPF 到 BPF 调用是一个重要的性能优化,极大减小了生成的 BPF 代码大小,因此对 CPU 指令缓存(instruction cache,i-cache)更友好。
内核 5.9 版本之前,BPF 尾调用和 BPF-to-BPF 调用是互斥的,只能二选一。 尾调用的缺点是生成的程序镜像大、加载时间长。
内核 5.10 最终解决了这一问题,允许同时使用者两种调用类型,充分利用二者各自的优点。
但混合使用者两种调用类型是有限制的,否则会导致内核栈溢出。 来看下面的例子
如上图所示,尾调用在真正跳转到目标程序(func3)之前,只会展开(unwind)它当前所处层级的栈帧(stack frame)。
也就是说如果尾调用是从某个子函数发起的,例如 subfunc1 –tailcall–> func2,那当程序在执行 func2 时, 所有 subfunc1 之前的栈帧(在这里是 func1 的栈帧)都会出现在栈上。
只有当最后一个函数(这里是 func3)执行结束时,所有前面的栈帧才将被展开(unwinded),然后控制返回到 BPF 程序的调用者(BPF program caller)。
内核引入了额外的逻辑来检测这种混用的情况。整个调用链中,每个子程序的栈空间( stack size)不能超过 256 字节(如果校验器检测到 bpf2bpf 调用,那主函数也会被当做子函数)。
有了这个限制,BPF 程序调用链最多能使用 8KB 的栈空间,计算方式:256 byte/stack 乘以尾调用数量上限 33。
如果没有这个限制,BPF 程序将使用 512 字节栈空间,最终消耗最多 16KB 的总栈空间,在某些架构上会导致栈溢出。
另外需要说明,这种混合调用目前只有x86-64
架构支持。
JIT
JIT 编译器可以极大加速 BPF 程序的执行,因为与解释器相比,它们可以降低每个指令的开销(reduce the per instruction cost)。
通常指令可以 1:1 映射到底层架构的原生指令。另外,这也会减少生成的可执行镜像的大小,因此对 CPU 的指令缓存更友好。
开启方式
1 | echo 1 > /proc/sys/net/core/bpf_jit_enable |
Offloads
BPF 网络程序,尤其是 tc 和 XDP BPF 程序在内核中都有一个 offload 到硬件的接口,这样就可以直接在网卡上执行 BPF 程序。
当前,Netronome 公司的 nfp 驱动支持通过 JIT 编译器 offload BPF,它会将 BPF 指令 翻译成网卡实现的指令集。
另外它还支持将 BPF maps offload 到网卡,因此 offloaded BPF 程序可以执行 map 查找、更新和删除操作。
工具链
iproute2
很多前端工具,例如 bcc、perf、iproute2,都可以将 BPF 程序加载到内核
但通常来说,不同前端在实现 BPF 程序时,语法和语义稍有不同。
本节主要关注如何使用 iproute2 提供的 BPF 前端加载 XDP、tc 或 lwt 类型的网络程序,因为 Cilium 的 BPF 程序就是面向这个加载器实现的。
将来 Cilium 会实现自己原生的 BPF 加载器,但为了开发和调试方便,程序仍会保持与 iproute2 套件的兼容性。
加载 XDP BPF 对象文件
给定一个为 XDP 编译的 BPF 对象文件prog.o
,可以用 ip 命令加载到支持 XDP 的 netdeviceem1
:
1 | ip link set dev em1 xdp obj prog.o 等价于 ip link set dev em1 xdp obj prog.o sec prog |
以上命令假设程序代码存储在默认的section
,在 XDP 的场景下就是prog section
。如果是在其他section
,例如 foobar,那就需要用如下命令:
1 | ip link set dev em1 xdp obj prog.o sec foobar |
我们还可以从默认的.text section
加载程序
1 |
|
然后通过如下命令加载
1 | ip link set dev em1 xdp obj prog.o sec .text |
默认情况下,如果 XDP 程序已经 attach 到网络接口,那再次加载会报错,这样设计是为了防止程序被无意中覆盖。
要强制替换当前正在运行的 XDP 程序,必须指定-force
参数:
1 | ip -force link set dev em1 xdp obj prog.o |
今天大部分支持 XDP 的驱动都能够在不会引起流量中断(traffic interrupt)的前提下,原子地替换运行中的程序。
出于性能考虑,支持 XDP 的驱动只允许 attach 一个程序 ,不支持程序链(a chain of programs)。
但正如上一节讨论的,如果有必要,可以通过尾调用来对程序进行拆分,以达到与程序链类似的效果。
如果一个接口上有 XDP 程序 attach,ip link 命令会显示一个 xdp 标记。
- 因此可以用
ip link | grep xdp
列出所有有 XDP 程序在运行的网络接口。 ip -d link
可以查看进一步信息;- 另外bpftool 指定 BPF 程序 ID 可以获取 attached 程序的信息,其中程序 ID 可以通过
ip link
看到。
从接口删除 XDP 程序,执行下面的命令:1
ip link set dev em1 xdp off
XDP 工作模式
XDP 总共支持三种工作模式,这三种模式iproute2
都实现了:
xdpdrv
xdpdrv 表示 native XDP(原生 XDP), 意味着 BPF 程序直接在驱动的接收路 径上运行,理论上这是软件层最早可以处理包的位置(the earliest possible point)。这是常规/传统的 XDP 模式,需要驱动实现对 XDP 的支持,目前 Linux 内核中主流的 10G/40G 网卡都已经支持。xdpgeneric
xdpgeneric 表示 generic XDP(通用 XDP),用于给那些还没有原生支持 XDP 的驱动进行试验性测试。generic XDP hook 位于内核协议栈的主接收路径(main receive path)上,接受的是 skb 格式的包,但由于 这些 hook 位于 ingress 路 径的很后面(a much later point),因此与 native XDP 相比性能有明显下降。因 此,xdpgeneric 大部分情况下只能用于试验目的,很少用于生产环境。xdpoffload
最后一些智能网卡(例如支持 Netronome’s nfp 驱动的网卡)实现了 xdpoffload 模式 ,允许将整个 BPF/XDP 程序 offload 到硬件,因此程序在网卡收到包时就直接在网卡进行处理。
这提供了比 native XDP 更高的性能,虽然在这种模式中某些 BPF map 类型和 BPF 辅助函数是不能用的。
BPF 校验器检测到这种情况时会直接报错,告诉用户哪些东西是不支持的。除了这些不支持的 BPF 特性之外,其他方面与 native XDP 都是一样的。
执行ip link set dev em1 xdp obj [...]
命令时,内核会先尝试以 native XDP 模 式加载程序,如果驱动不支持再自动回退到 generic XDP 模式。
如果显式指定了 xdpdrv 而不是 xdp,那驱动不支持 native XDP 时加载就会直接失败,而不再尝试 generic XDP 模式。
一个例子:以 native XDP 模式强制加载一个 BPF/XDP 程序,打印链路详情,最后再卸载程序:
1 | ip -force link set dev em1 xdpdrv obj prog.o |
还是这个例子,但强制以 generic XDP 模式加载(即使驱动支持 native XDP),另外用 bpftool 打印 attached 的这个 dummy 程序内具体的 BPF 指令:
1 | ip -force link set dev em1 xdpgeneric obj prog.o |
最后卸载 XDP,用 bpftool 打印程序信息,查看其中的一些元数据:
1 | ip -force link set dev em1 xdpoffload obj prog.o |
注意每个程序只能选择用一种 XDP 模式加载,无法同时使用多种模式,例如 xdpdrv 和 xdpgeneric。
无法原子地在不同 XDP 模式之间切换,例如从 generic 模式切换到 native 模式。但重复设置为同一种模式是可以的:
1 | ip -force link set dev em1 xdpgeneric obj prog.o |
在不同模式之间切换时,需要先退出当前的操作模式,然后才能进入新模式
1 | ip -force link set dev em1 xdpgeneric obj prog.o |
加载 tc BPF 对象文件
用 tc 加载 BPF 程序
给定一个为 tc 编译的 BPF 对象文件prog.o
,可以通过 tc 命令将其加载到一个网络设备(netdevice)。
但与 XDP 不同,设备是否支持 attach BPF 程序并不依赖驱动 (即任何网络设备都支持 tc BPF)。
下面的命令可以将程序 attach 到em1
的ingress
网络:
1 | tc qdisc add dev em1 clsact |
第一步创建了一个clsact
qdisc (Linux 排队规则,Linux queueing discipline)。
clsact
是一个 dummy qdisc,和 ingress qdisc 类似,用于 持有(hold)分类器和动作(classifier and actions),但 不执行真正的排队(queueing)。后面 attach bpf 分类器需要用到它。clsact
qdisc 提供了两个特殊的 hook:ingress and egress,分类器可以 attach 到这两个 hook 点。这两个 hook 都位于 datapath 的关键收发路径上,设备 em1 的每个包都会经过这两个点。二者的内核调用路径:ingress hook:__netif_receive_skb_core() -> sch_handle_ingress()
egress hook:__dev_queue_xmit() -> sch_handle_egress()
类似地,将程序 attach 到egress
hook 的命令:tc filter add dev em1 egress bpf da obj prog.o
clsact
qdisc 在 ingress 和 egress 方向以无锁(lockless)方式执行, 而且可以 attach 到虚拟的、无队列的设备
(virtual, queue-less devices),例如连接容器和宿主机的 veth 设备。
第二步命令,tc filter 选择了在 da(direct-action)模式中使用 bpf。
da 是 推荐的模式,并且应该永远指定这个参数。粗略地说,da 模式表示 bpf 分类器不需要调用外部的 tc action 模块。
事实上 bpf 分类器也完全不需要调用外部模块,因为所有的 packet mangling、转发或其他类型的 action 都可以在这单个 BPF 程序内完成 ,因此执行会明显更快。
配置了这两条命令之后,程序就 attach 完成了,接下来只要有包经过这个设备,就会触发这个程序执行。
和 XDP 类似,如果没有使用默认 section 名字,那可以在加载时指定,例如指定 section 为 foobar:
1 | tc filter add dev em1 egress bpf da obj prog.o sec foobar |
查看已经 attach 的程序
1 | tc filter show dev em1 ingress |
输出中的 prog.o:[ingress] 表示section ingress
中的程序是从文件 prog.o 加载的,而且 bpf 工作在 direct-action 模式。
上面还打印了程序的 id 和 tag, 其中 tag 是指令流(instruction stream)的哈希,可以关联到对应的对象文件或用 perf 查看调用栈信息。
id 是一个操作系统层唯一的 BPF 程序标识符,可以用 bpftool 进一步查看或 dump 相关的程序信息。
tc 可以 attach 多个 BPF 程序,并提供了其他的一些分类器,这些分类器可以 chain 到一起使用。
但是attach 单个 BPF 程序已经完全足够了,因为有了 da 模式,所有的包操作都可以放到同一个程序中,这意味着 BPF 程序自身将会返回tc action verdict
例如TC_ACT_OK
、TC_ACT_SHOT
等等。出于最佳性能和灵活性考虑,这(da 模式)是推荐的使用方式。
程序优先级(pref)和句柄(handle)
在上面的 show 命令中,tc 还打印出了 pref 49152 和 handle 0x1。如果之前没有 通过命令行显式指定,这两个数据就会自动生成。
pref
表示优先级,如果指定了多个分类器,它们会按照优先级从高到低依次执行;handle
是一个标识符,在加载了同一分类器的多个实例并且它们的优先级(pref)都一样的情况下会用到这个标识符。
因为在 BPF 的场景下,单个程序就足够了,因此 pref 和 handle 通常情况下都可以忽略。
- 除非打算后面原子地替换 attached BPF 程序,否则不建议在加载时显式指定 pref 和 handle。
- 显式指定这两个参数的好处是,后面执行 replace 操作时,就不需要再去动态地查询这两个值。
显式指定 pref 和 handle 时的加载命令
1 | tc filter add dev em1 ingress pref 1 handle 1 bpf da obj prog.o sec foobar |
对应的原子 replace 命令:将
ingress hook
处的已有程序替换为prog.o
文件中foobar section
中的新 BPF 程序,
1 | tc filter replace dev em1 ingress pref 1 handle 1 bpf da obj prog.o sec foobar |
用 tc 删除 BPF 程序
最后,要分别从ingress
和egress
删除所有 attach 的程序执行:
1 | tc filter del dev em1 ingress |
要从netdevice
删除整个clsact qdisc
(会隐式地删除 attach 到ingress
和egress
hook上面的所有程序)执行:
1 | tc qdisc del dev em1 clsact |
offload 到网卡
和 XDP BPF 程序类似,如果网卡驱动支持 tc BPF 程序,那也可以将它们 offload 到网卡 。
Netronome 的 nfp 网卡对 XDP 和 tc BPF 程序都支持 offload。
1 | tc qdisc add dev em1 clsact |
如果显式以上错误,那需要先启用网卡的 hw-tc-offload 功能:
1 | ethtool -K em1 hw-tc-offload on |
其中的in_hw
标志表示这个程序已经被 offload 到网卡了。
bpftool
bpftool 是查看和调试 BPF 程序的主要工具。它随内核一起开发,在内核中的路径是tools/bpf/bpftool/
。
这个工具可以完成
- dump 当前已经加载到系统中的所有 BPF 程序和 map
- 列出和指定程序相关的所有 BPF map
- dump 整个 map 中的 key/value 对
- 查看、更新、删除特定 key
- 查看给定 key 的相邻 key(neighbor key)
要执行这些操作可以指定 BPF 程序、map ID,或者指定 BPF 文件系统中程序或 map 的位置。
另外这个工具还提供了将 map 或程序钉(pin)到 BPF 文件系统的功能
查看系统当前已经加载的 BPF 程序
1 | bpftool prog |
类似地查看所有的 active maps
1 | bpftool map |
bpftool 的每个命令都提供了以 json 格式打印的功能,在命令末尾指定--json
就行了。
另外--pretty
会使得打印更加美观,看起来更清楚。
1 | bpftool prog --json --pretty |
要dump
特定 BPF 程序的post-verifier
BPF 指令镜像(instruction image)
可以先从查看一个具体程序开始,例如查看 attach 到tc ingress hook
上的程序
1 | tc filter show dev cilium_host egress |
这个程序是从对象文件 bpf_host.o 加载来的,程序位于对象文件的 from-netdev section,程序 ID 为 406。
基于以上信息 bpftool 可以提供一些关于这个程序的上层元数据:
1 | bpftool prog show id 406 |
从上面的输出可以看到:
- 程序 ID 为 406,类型是
sched_cls(BPF_PROG_TYPE_SCHED_CLS)
,有一个 tag 为e0362f5bd9163a0a
(指令序列的 SHA sum) - 这个程序被 root uid 0 在
Apr 09/16:24
加载 - BPF 指令序列有 11,144 bytes 长,JIT 之后的镜像有 7,721 bytes
- 程序自身(不包括 maps)占用了 12,288 bytes,这部分空间使用的是 uid 0 用户 的配额
- BPF 程序使用了 ID 为
18、20 8 5 6
和14
的 BPF map。可以用这些 ID 进一步 dump map 自身或相关信息
另外bpftool 可以 dump 出运行中程序的 BPF 指令:
1 | bpftool prog dump xlated id 406 |
由于程序被 JIT,因此真正执行的是生成的 JIT 镜像(从上面 xlated 中的指令生成的 ),这些指令也可以通过bpftool
查看:
1 | bpftool prog dump jited id 406 |
还可以指定在输出中将反汇编之后的指令关联到opcodes
1 | bpftool prog dump jited id 406 opcodes |
也可以将常规的 BPF 指令关联到opcodes
,有时在内核中进行调试时会比较有用
1 | bpftool prog dump xlated id 406 opcodes |
此外还可以用graphviz
以可视化的方式展示程序的基本组成部分
1 | bpftool prog dump xlated id 406 visual &> output.dot |
map dump
子命令可以 dump 整个 map,它会遍历所有的 map 元素,输出 key/value。
如果 map 中没有可用的 BTF 数据,那key/value
会以十六进制格式输出:
1 | bpftool map dump id 5 |
如果有 BTF 数据,map 就有了关于key/value
结构体的调试信息
1 | bpftool map dump id 386 |
此外还可以用btf show
命令来 dump 系统中已经加载的所有 BTF 对象
1 | bpftool btf show |
还可以用子命令 btf dump 来检查 BTF 中携带了哪些 debug 信息。
format 类型可以是raw
或c
1 | bpftool btf dump id 60 format c |
程序类型
当前一共有 18 种不同的 BPF 程序类型
本节接下来进一步介绍其中两种和网络相关的类型,即 XDP BPF 程序和 tc BPF 程序。
XDP
XDP(eXpress Data Path)提供了一个内核态、高性能、可编程 BPF 包处理框架。
这个框架在软件中最早可以处理包的位置(即网卡驱动收到包的 时刻)运行 BPF 程序。
XDP hook 位于网络驱动的快速路径上,XDP 程序直接从接收缓冲区(receive ring)中将 包拿下来,无需执行任何耗时的操作,例如分配 skb 然后将包推送到网络协议栈,或者将包推送给 GRO 引擎等等。
因此只要有 CPU 资源,XDP BPF 程序就能够在最早的位置执行处理。
XDP 和 Linux 内核及其基础设施协同工作,这意味着 XDP 并不会绕过(bypass)内核 ;
作为对比很多完全运行在用户空间的网络框架(例如 DPDK)是绕过内核的。将包留在内核空间可以带来几方面重要好处
- XDP 可以复用所有上游开发的内核网络驱动、用户空间工具,以及其他一些可用的内核 基础设施,例如 BPF 辅助函数在调用自身时可以使用系统路由表、socket 等等。
- 因为驻留在内核空间,因此 XDP 在访问硬件时与内核其他部分有相同的安全模型。
- 无需跨内核/用户空间边界,因为正在被处理的包已经在内核中,因此可以灵活地将 其转发到内核内的其他实体,例如容器的命名空间或内核网络栈自身。
- 将包从 XDP 送到内核中非常简单,可以复用内核中这个健壮、高效、使用广泛的 TCP/IP 协议栈,而不是像一些用户态框架一样需要自己维护一个独立的 TCP/IP 协 议栈。
- 基于 BPF 可以实现内核的完全可编程,保持 ABI 的稳定,保持内核的系统调用 ABI
“永远不会破坏用户空间的兼容性”
的保证。而且与内核模块(modules)方式相比,它还更加安全,这来源于 BPF 校验器,它能保证内核操作的稳定性。 - XDP 轻松地支持在运行时(runtime)原子地创建(spawn)新程序,而不会导致任何网络流量中断,甚至不需要重启内核/系统。
- XDP 允许对负载进行灵活的结构化(structuring of workloads),然后集成到内核。例如它可以工作在
“不停轮询”(busy polling)
或“中断驱动”(interrupt driven)
模式。不需要显式地将专门 CPU 分配给 XDP。没有特殊的硬件需求,它也不依赖 hugepage(大页)。 - XDP 不需要任何第三方内核模块或许可(licensing)。它是一个长期的架构型解决方案,是 Linux 内核的一个核心组件,而且是由内核社区开发的。
- 主流发行版中,4.8+ 的内核已经内置并启用了 XDP,并支持主流的 10G 及更高速网络驱动。
数据包在 XDP 中的表示形式是
xdp_buff
,这也是传递给 BPF 程序的结构体
1 | struct xdp_buff { |
data
指向页面(page)中包数据的起始位置,从名字可以猜出data_end
执行包数据 的结尾位置。data_hard_start
XDP 支持 headroom,因此 data_hard_start 指向页面中最大可能的 headroom 开始位置,即当对包进行封装(加 header)时,data 会逐渐向 data_hard_start 靠近,这是通过 bpf_xdp_adjust_head() 实现的,该辅助函数还支 持解封装(去 header)。data_meta
开始时指向与 data 相同的位置,bpf_xdp_adjust_meta() 能够将其朝着 data_hard_start 移动,这样可以给自定义元数据提供空间,这个空间对内核网络栈是不可见的,但对 tc BPF 程序可见,因为 tc 需要将它从 XDP 转移到 skb。 反之亦然,这个辅助函数也可以将 data_meta 移动到离 data_hard_start 比较远的位 置,这样就可以达到删除或缩小这个自定义空间的目的。 data_meta 还可以单纯用于在尾调用时传递状态,和 tc BPF 程序中用 skb->cb[] 控 制块(control block)类似。rxq
字段指向某些额外的、和每个接收队列相关的元数据:
1 | struct xdp_rxq_info { |
BPF 程序返回码
XDP BPF 程序执行结束后会返回一个判决结果(verdict),告诉驱动接下来如何处理这个包
1 | enum xdp_action { |
XDP_DROP
表示立即在驱动层将包丢弃。这样可以节省很多资源,对于 DDoS mitigation 或通用目的防火墙程序来说这尤其有用。XDP_PASS
表示允许将这个包送到内核网络栈。同时,当前正在处理这个包的 CPU 会分配一个 skb,做一些初始化,然后将其送到 GRO 引擎。这是没有 XDP 时默认的包处理行为是一样的。XDP_TX
是 BPF 程序的一个高效选项,能够在收到包的网卡上直接将包再发送出去。对 于实现防火墙+负载均衡的程序来说这非常有用,因为这些部署了 BPF 的节点可以作为一个 hairpin (发卡模式,从同一个设备进去再出来)模式的负载均衡器集群,将收到的包在 XDP BPF 程序中重写(rewrite)之后直接发送回去。XDP_REDIRECT
与 XDP_TX 类似,但是通过另一个网卡将包发出去。另外, XDP_REDIRECT 还可以将包重定向到一个 BPF cpumap,即当前执行 XDP 程序的 CPU 可以将这个包交给某个远端 CPU,由后者将这个包送到更上层的内核栈,当前 CPU 则继 续在这个网卡执行接收和处理包的任务。这和 XDP_PASS 类似,但当前 CPU 不用去 做将包送到内核协议栈的准备工作(分配 skb,初始化等等),这部分开销还是很大的。XDP_ABORTED
表示程序产生异常,其行为和 XDP_DROP,但 XDP_ABORTED 会经过 trace_xdp_exception tracepoint,因此可以通过 tracing 工具来监控这种非正常行为。
XDP 工作模式
XDP 有三种工作模式,默认是native(原生)
模式,当讨论 XDP 时通常隐含的都是指这种模式。
Native XDP
默认模式,在这种模式中,XDP BPF 程序直接运行在网络驱动的早期接收路径上( early receive path)。大部分广泛使用的 10G 及更高速的网卡都已经支持这种模式 。Offloaded XDP
在这种模式中,XDP BPF 程序直接 offload 到网卡,而不是在主机的 CPU 上执行。 因此,本来就已经很低的 per-packet 开销完全从主机下放到网卡,能够比运行在 native XDP 模式取得更高的性能。这种 offload 通常由智能网卡实现,这些网卡有多 线程、多核流处理器(flow processors),一个位于内核中的 JIT 编译器( in-kernel JIT compiler)将 BPF 翻译成网卡的原生指令。
支持 offloaded XDP 模式的驱动通常也支持 native XDP 模式,因为 BPF 辅助函数可 能目前还只支持后者。Generic XDP
对于还没有实现 native 或 offloaded XDP 的驱动,内核提供了一个 generic XDP 选 项,这种模式不需要任何驱动改动,因为相应的 XDP 代码运行在网络栈很后面的一个位置。
这种设置主要面向的是用内核的 XDP API 来编写和测试程序的开发者,并且无法达到 前面两种模式能达到的性能。对于在生产环境使用 XDP,推荐要么选择 native 要么选择 offloaded 模式。
驱动支持
支持 native XDP 的驱动
- Broadcom
- bnxt
- Cavium
- thunderx
- Intel
- ixgbe
- ixgbevf
- i40e
- Mellanox
- mlx4
- mlx5
- Netronome
- nfp
- Others
- tun
- virtio_net
- Qlogic
- qede
支持 offloaded XDP 的驱动
- Netronome
- nfp
tc
除了 XDP 等类型的程序之外,BPF 还可以用于内核数据路径的 tc (traffic control,流量控制)层。
tc和XDP的不同
从高层看,tc BPF 程序和 XDP BPF 程序有三点主要不同
输入上下文
BPF 的输入上下文(input context)是一个 sk_buff 而不是 xdp_buff。
当内核协议栈收到一个包时(说明包通过了 XDP 层),它会分配一个缓冲区,解析包,并存储包 的元数据。
表示这个包的结构体就是sk_buff。这个结构体会暴露给 BPF 输入上下文, 因此 tc ingress 层的 BPF 程序就可以利用这些(由协议栈提取的)包的元数据。
这些元数据很有用,但在包达到 tc 的 hook 点之前,协议栈执行的缓冲区分配、元数据提取和 其他处理等过程也是有开销的。
从定义来看xdp_buff 不需要访问这些元数据,因为 XDP hook 在协议栈之前就会被调用。这是 XDP 和 tc hook 性能差距的重要原因之一。
因此attach 到 tc BPF hook 的 BPF 程序可以读取 skb 的mark
、pkt_type
、protocol
、priority
、queue_mapping
、napi_id
、cb[]
、hash
、tc_classid
、tc_index
、vlan
元数据、XDP 层传过来的自定义元数据以及其他信息。
tc BPF 的 BPF 上下文中使用了struct __sk_buff
这个结构体中的所有成员字段都定义在 linux/bpf.h 系统头文件。
通常来说sk_buff 和 xdp_buff 完全不同,二者各有有略。
例如,sk_buff 修改 与其关联的元数据(its associated metadata)非常方便,但它包含了大量协议相关的信息(例如 GSO 相关的状态),这使得无法仅仅通过重写包数据来切换协议。
这是因为协议栈是基于元数据处理包的,而不是每次都去读包的内容。
因此BPF 辅助函数需要额外的转换,并且还要正确处理 sk_buff 内部信息。
xdp_buff 没有这些问题,因为它所处的阶段非常早,此时内核还没有分配 sk_buff,因此很容易实现各种类型的数据包重写(packet rewrite)。
但是,xdp_buff 的缺点是在它这个阶段进行 mangling 的时候,无法利用到 sk_buff 元数据。
解决这个问题的方式是从 XDP BPF 传递自定义的元数据到 tc BPF。
这样根据使用场景的不同,可以同时利用这两者 BPF 程序,以达到互补的效果。
hook 触发点
tc BPF 程序在数据路径上的 ingress 和 egress 点都可以触发;而 XDP BPF 程序 只能在 ingress 点触发。
内核两个 hook 点:
- ingress hook sch_handle_ingress():由
__netif_receive_skb_core()
触发 - egress hook sch_handle_egress():由
__dev_queue_xmit()
触发
__netif_receive_skb_core()
和__dev_queue_xmit()
是 data path 的主要接收和 发送函数,不考虑 XDP 的话(XDP 可能会拦截或修改,导致不经过这两个 hook 点), 每个网络进入或离开系统的网络包都会经过这两个点,从而使得 tc BPF 程序具备完全可观测性。
是否依赖驱动支持
tc BPF 程序不需要驱动做任何改动,因为它们运行在网络栈通用层中的 hook 点。因 此它们可以 attach 到任何类型的网络设备上。
Ingress
这提供了很好的灵活性,但跟运行在原生 XDP 层的程序相比,性能要差一些。
然而tc BPF 程序仍然是内核的通用 data path 做完 GRO 之后、且处理任何协议之前最早的 处理点。
传统的 iptables 防火墙也是在这里处理的,例如iptables PREROUTING
或nftables ingress hook
或其他数据包包处理过程。
Egress
类似的,对于 egress,tc BPF 程序在将包交给驱动之前的最晚的地方(latest point)执 行,这个地方在传统 iptables 防火墙 hook 之后(例如 iptables POSTROUTING), 但在内核 GSO 引擎之前。
唯一需要驱动做改动的场景是:将 tc BPF 程序 offload 到网卡。
形式通常和 XDP offload 类似,只是特性列表不同,因为二者的 BPF 输入上下文、辅助函数和返回码( verdict)不同。
cls_bpf 分类器
运行在 tc 层的 BPF 程序使用的是 cls_bpf
分类器。
在 tc 术语中“BPF 附着点”
被 称为“分类器”
,但这个词其实有点误导,因为它少描述了前者可以做的事情。
attachment point 是一个完全可编程的包处理器,不仅能够读取 skb 元数据 和包数据,还可以任意 mangle 这两者,最后结束 tc 处理过程,返回一个裁定结果。
因此 cls_bpf
可以认为是一个管理和执行 tc BPF 程序的自包含实体。
cls_bpf
可以持有(hold)一个或多个 tc BPF 程序。
Cilium 在部署 cls_bpf
程序时 ,对于一个给定的 hook 点只会附着一个程序,并且用的是 direct-action 模式。
典型情况下,在传统 tc 方案中,分类器(classifier )和动作模块(action modules) 之间是分开的,每个分类器可以 attach 多个 action,当匹配到这个分类器时这些 action 就会执行。
cls_bpf
是 tc 层中唯一支持这种快速路径(fast-path)的一个分类器模块。
cls_bpf
可以附着的 tc ingress 和 egress hook 点都是由一个名为sch_clsact
的伪 qdisc 管理的,它是 ingress qdisc 的一个超集(superset),可以无缝替换后 者,因为它既可以管理 ingress tc hook 又可以管理 egress tc hook。
对于__dev_queue_xmit()
内的 tc egress hook,需要注意的是这个 hook 并不是在内核的 qdisc root lock 下执行的。
因此ingress 和 egress hook 都是在快速路径中以无锁( lockless)方式执行的。
不管是 ingress 还是 egress,抢占(preemption )都被关闭, 执行发生在 RCU 读侧
通常在 egress 的场景下,有很多类型的 qdisc 会 attach 到 netdevice,例如 sch_mq, sch_fq, sch_fq_codel or sch_htb,其中某些是 classful qdiscs,这些 qdisc 包含 subclasses 因此需要一个对包进行分类的机制,决定将包 demux 到哪里。
这个机制是 由调用 tcf_classify() 实现的,这个函数会进一步调用 tc 分类器(如果提供了)。
在这种场景下cls_bpf 也可以被 attach 和使用。
这种操作通常发生在 qdisc root lock 下面,因此会面临锁竞争的问题。
sch_clsact qdisc 的 egress hook 点位于更前面,没有落入这个锁的范围内,因此完全独立于常规 egress qdisc 而执行。
因此对于 sch_htb 这种场景,sch_clsact qdisc 可以将繁重的包分类工作放到 tc BPF 程序,在 qdisc root lock 之外执行,在这些 tc BPF 程序中设置 skb->mark 或 skb->priority ,因此随后 sch_htb 只需要一个简单的映射,没有原来在 root lock 下面昂贵的包分类开销,还减少了锁竞争。
在 sch_clsact in combination with cls_bpf 场景下支持 Offloaded tc BPF 程序, 在这种场景下,原来加载到智能网卡驱动的 BPF 程序被 JIT,在网卡原生执行。
只有工作在 direct-action 模式的 cls_bpf 程序支持 offload。 cls_bpf 只支持 offload 单个程序,不支持同时 offload 多个程序。另外只有 ingress hook 支持 offloading BPF 程序。
一个 cls_bpf 实例内部可以 hold 多个 tc BPF 程序。
如果由多个程序, TC_ACT_UNSPEC
程序返回码就是让继续执行列表中的下一个程序。
但这种方式的缺点是:每个程序都需要解析一遍数据包,性能会下降。
tc BPF 程序返回码
1 |
TC_ACT_REDIRECT
这个返回码加上bpf_redirect()
辅助函数,允许重定向一个 skb 到同一个或另一个设备的 ingress 或 egress 路径。
能够将包注入另一个设备的 ingress 或 egress 路径使得基于 BPF 的包转发具备了完全的灵活性。
TC_ACT_SHOT
和TC_ACT_STOLEN
这两个返回码指示内核将包丢弃。这两个返回码很相似,只有少数几个区别:
TC_ACT_SHOT
提示内核 skb 是通过kfree_skb()
释放的,并返回NET_XMIT_DROP
给调用方,作为立即反馈TC_ACT_STOLEN
通过consume_skb()
释放 skb,返回NET_XMIT_SUCCESS
给上 层假装这个包已经被正确发送了
perf 的丢包监控(drop monitor)是跟踪的kfree_skb()
,因此在TC_ACT_STOLEN
的 场景下它无法看到任何丢包统计,因为从语义上说,此时这些 skb 是被”consumed”
或queued
而不是被dropped
。
TC_ACT_UNSPEC
和TC_ACT_OK
TC_ACT_UNSPEC
表示“未指定的动作”,在三种情况下会用到:
- attach 了一个 offloaded tc BPF 程序,tc ingress hook 正在运行,被 offload 的 程序的 cls_bpf 表示会返回
TC_ACT_UNSPEC
- 为了在 cls_bpf 多程序的情况下,继续下一个 tc BPF 程序。这种情况可以和 第一种情况中提到的 offloaded tc BPF 程序一起使用,此时第一种情况返回的
TC_ACT_UNSPEC
继续执行下一个没有被 offloaded BPF 程序? TC_ACT_UNSPEC
还用于单个程序从场景,只是通知内核继续执行 skb 处理,但不要带 来任何副作用(without additional side-effects)。
TC_ACT_UNSPEC
在某些方面和TC_ACT_OK
非常类似,因为二者都是将 skb 向下一个 处理阶段传递,在 ingress 的情况下是传递给内核协议栈的更上层,在 egress 的情况下 是传递给网络设备驱动。
唯一的不同是TC_ACT_OK
基于 tc BPF 程序设置的 classid 来 设置skb->tc_index
,而TC_ACT_UNSPEC
是通过 tc BPF 程序之外的 BPF 上下文中的skb->tc_classid
设置。
实际函数
- bpf_get_smp_processor_id: 只有在内核线程调度的抢占功能被关闭的情况下,该函数才能够获取到稳定的 CPU ID;因为线程会被调度 eBPF 程序所在的线程会被调度到其它CPU上。
- bpf_perf_event_output:
bpf_ringbuf_output: 相比较bpf_perf_event_output更简单,不需要BPF context参数
bpf_get_current_common: 用当前进程名字填充第一个参数地址
- bpf_get_current_task: 返回指向当前task_struct对象的指针。可用于计算CPU在线时间,内核线程,运行队列和其他相关信息。
- bpf_get_current_pid_tgid: 低32位为当前进程ID,高32位是组ID。
- bpf_get_current_uid_gid: 返回用户ID和组ID.
- bpf_ktime_get_ns: 获取当前时间,以纳秒方式。
- bpf_probe_read_str: 复制NULL结尾的字符串到BPF栈,用于后续使用。
各方向细节函数
bpftool feature probe
Scanning system configuration…
bpf() syscall restricted to privileged users (admin can change)
JIT compiler is enabled
JIT compiler hardening is disabled
JIT compiler kallsyms exports are enabled for root
Global memory limit for JIT compiler for unprivileged users is 264241152 bytes
CONFIG_BPF is set to y
CONFIG_BPF_SYSCALL is set to y
CONFIG_HAVE_EBPF_JIT is set to y
CONFIG_BPF_JIT is set to y
CONFIG_BPF_JIT_ALWAYS_ON is not set
CONFIG_DEBUG_INFO_BTF is set to y
CONFIG_DEBUG_INFO_BTF_MODULES is set to y
CONFIG_CGROUPS is set to y
CONFIG_CGROUP_BPF is set to y
CONFIG_CGROUP_NET_CLASSID is set to y
CONFIG_SOCK_CGROUP_DATA is set to y
CONFIG_BPF_EVENTS is set to y
CONFIG_KPROBE_EVENTS is set to y
CONFIG_UPROBE_EVENTS is set to y
CONFIG_TRACING is set to y
CONFIG_FTRACE_SYSCALLS is set to y
CONFIG_FUNCTION_ERROR_INJECTION is set to y
CONFIG_BPF_KPROBE_OVERRIDE is not set
CONFIG_NET is set to y
CONFIG_XDP_SOCKETS is set to y
CONFIG_LWTUNNEL_BPF is set to y
CONFIG_NET_ACT_BPF is set to m
CONFIG_NET_CLS_BPF is set to m
CONFIG_NET_CLS_ACT is set to y
CONFIG_NET_SCH_INGRESS is set to m
CONFIG_XFRM is set to y
CONFIG_IP_ROUTE_CLASSID is set to y
CONFIG_IPV6_SEG6_BPF is set to y
CONFIG_BPF_LIRC_MODE2 is not set
CONFIG_BPF_STREAM_PARSER is set to y
CONFIG_NETFILTER_XT_MATCH_BPF is set to m
CONFIG_BPFILTER is not set
CONFIG_BPFILTER_UMH is not set
CONFIG_TEST_BPF is set to m
CONFIG_HZ is set to 250
Scanning system call availability…
bpf() syscall is available
Scanning eBPF program types…
eBPF program_type socket_filter is available
eBPF program_type kprobe is available
eBPF program_type sched_cls is available
eBPF program_type sched_act is available
eBPF program_type tracepoint is available
eBPF program_type xdp is available
eBPF program_type perf_event is available
eBPF program_type cgroup_skb is available
eBPF program_type cgroup_sock is available
eBPF program_type lwt_in is available
eBPF program_type lwt_out is available
eBPF program_type lwt_xmit is available
eBPF program_type sock_ops is available
eBPF program_type sk_skb is available
eBPF program_type cgroup_device is available
eBPF program_type sk_msg is available
eBPF program_type raw_tracepoint is available
eBPF program_type cgroup_sock_addr is available
eBPF program_type lwt_seg6local is available
eBPF program_type lirc_mode2 is NOT available
eBPF program_type sk_reuseport is available
eBPF program_type flow_dissector is available
eBPF program_type cgroup_sysctl is available
eBPF program_type raw_tracepoint_writable is available
eBPF program_type cgroup_sockopt is available
eBPF program_type tracing is available
eBPF program_type struct_ops is available
eBPF program_type ext is available
eBPF program_type lsm is available
eBPF program_type sk_lookup is available
eBPF program_type syscall is available
Scanning eBPF map types…
eBPF map_type hash is available
eBPF map_type array is available
eBPF map_type prog_array is available
eBPF map_type perf_event_array is available
eBPF map_type percpu_hash is available
eBPF map_type percpu_array is available
eBPF map_type stack_trace is available
eBPF map_type cgroup_array is available
eBPF map_type lru_hash is available
eBPF map_type lru_percpu_hash is available
eBPF map_type lpm_trie is available
eBPF map_type array_of_maps is available
eBPF map_type hash_of_maps is available
eBPF map_type devmap is available
eBPF map_type sockmap is available
eBPF map_type cpumap is available
eBPF map_type xskmap is available
eBPF map_type sockhash is available
eBPF map_type cgroup_storage is available
eBPF map_type reuseport_sockarray is available
eBPF map_type percpu_cgroup_storage is available
eBPF map_type queue is available
eBPF map_type stack is available
eBPF map_type sk_storage is available
eBPF map_type devmap_hash is available
eBPF map_type struct_ops is available
eBPF map_type ringbuf is available
eBPF map_type inode_storage is available
eBPF map_type task_storage is available
eBPF map_type bloom_filter is available
Scanning eBPF helper functions…
eBPF helpers supported for program type socket_filter:
- bpf_map_lookup_elem
- bpf_map_update_elem
- bpf_map_delete_elem
- bpf_ktime_get_ns
- bpf_get_prandom_u32
- bpf_get_smp_processor_id
- bpf_tail_call
- bpf_perf_event_output
- bpf_skb_load_bytes
- bpf_get_current_task
- bpf_get_numa_node_id
- bpf_get_socket_cookie
- bpf_get_socket_uid
- bpf_skb_load_bytes_relative
- bpf_map_push_elem
- bpf_map_pop_elem
- bpf_map_peek_elem
- bpf_spin_lock
- bpf_spin_unlock
- bpf_probe_read_user
- bpf_probe_read_kernel
- bpf_probe_read_user_str
- bpf_probe_read_kernel_str
- bpf_jiffies64
- bpf_ktime_get_boot_ns
- bpf_ringbuf_output
- bpf_ringbuf_reserve
- bpf_ringbuf_submit
- bpf_ringbuf_discard
- bpf_ringbuf_query
- bpf_skc_to_tcp6_sock
- bpf_skc_to_tcp_sock
- bpf_skc_to_tcp_timewait_sock
- bpf_skc_to_tcp_request_sock
- bpf_skc_to_udp6_sock
- bpf_snprintf_btf
- bpf_per_cpu_ptr
- bpf_this_cpu_ptr
- bpf_get_current_task_btf
- bpf_ktime_get_coarse_ns
- bpf_for_each_map_elem
- bpf_snprintf
- bpf_timer_init
- bpf_timer_set_callback
- bpf_timer_start
- bpf_timer_cancel
- bpf_task_pt_regs
- bpf_skc_to_unix_sock
- bpf_loop
- bpf_strncmp
- bpf_kptr_xchg
- bpf_map_lookup_percpu_elem
- bpf_skc_to_mptcp_sock
- bpf_dynptr_from_mem
- bpf_ringbuf_reserve_dynptr
- bpf_ringbuf_submit_dynptr
- bpf_ringbuf_discard_dynptr
- bpf_dynptr_read
- bpf_dynptr_write
- bpf_dynptr_data
eBPF helpers supported for program type kprobe:
- bpf_map_lookup_elem
- bpf_map_update_elem
- bpf_map_delete_elem
- bpf_probe_read
- bpf_ktime_get_ns
- bpf_get_prandom_u32
- bpf_get_smp_processor_id
- bpf_tail_call
- bpf_get_current_pid_tgid
- bpf_get_current_uid_gid
- bpf_get_current_comm
- bpf_perf_event_read
- bpf_perf_event_output
- bpf_get_stackid
- bpf_get_current_task
- bpf_current_task_under_cgroup
- bpf_get_numa_node_id
- bpf_probe_read_str
- bpf_perf_event_read_value
- bpf_get_stack
- bpf_get_current_cgroup_id
- bpf_map_push_elem
- bpf_map_pop_elem
- bpf_map_peek_elem
- bpf_spin_lock
- bpf_spin_unlock
- bpf_send_signal
- bpf_probe_read_user
- bpf_probe_read_kernel
- bpf_probe_read_user_str
- bpf_probe_read_kernel_str
- bpf_send_signal_thread
- bpf_jiffies64
- bpf_get_ns_current_pid_tgid
- bpf_get_current_ancestor_cgroup_id
- bpf_ktime_get_boot_ns
- bpf_ringbuf_output
- bpf_ringbuf_reserve
- bpf_ringbuf_submit
- bpf_ringbuf_discard
- bpf_ringbuf_query
- bpf_get_task_stack
- bpf_snprintf_btf
- bpf_per_cpu_ptr
- bpf_this_cpu_ptr
- bpf_task_storage_get
- bpf_task_storage_delete
- bpf_get_current_task_btf
- bpf_for_each_map_elem
- bpf_snprintf
- bpf_timer_init
- bpf_timer_set_callback
- bpf_timer_start
- bpf_timer_cancel
- bpf_get_func_ip
- bpf_get_attach_cookie
- bpf_task_pt_regs
- bpf_get_branch_snapshot
- bpf_find_vma
- bpf_loop
- bpf_strncmp
- bpf_kptr_xchg
- bpf_map_lookup_percpu_elem
- bpf_dynptr_from_mem
- bpf_ringbuf_reserve_dynptr
- bpf_ringbuf_submit_dynptr
- bpf_ringbuf_discard_dynptr
- bpf_dynptr_read
- bpf_dynptr_write
- bpf_dynptr_data
eBPF helpers supported for program type sched_cls:
- bpf_map_lookup_elem
- bpf_map_update_elem
- bpf_map_delete_elem
- bpf_ktime_get_ns
- bpf_get_prandom_u32
- bpf_get_smp_processor_id
- bpf_skb_store_bytes
- bpf_l3_csum_replace
- bpf_l4_csum_replace
- bpf_tail_call
- bpf_clone_redirect
- bpf_get_cgroup_classid
- bpf_skb_vlan_push
- bpf_skb_vlan_pop
- bpf_skb_get_tunnel_key
- bpf_skb_set_tunnel_key
- bpf_redirect
- bpf_get_route_realm
- bpf_perf_event_output
- bpf_skb_load_bytes
- bpf_csum_diff
- bpf_skb_get_tunnel_opt
- bpf_skb_set_tunnel_opt
- bpf_skb_change_proto
- bpf_skb_change_type
- bpf_skb_under_cgroup
- bpf_get_hash_recalc
- bpf_get_current_task
- bpf_skb_change_tail
- bpf_skb_pull_data
- bpf_csum_update
- bpf_set_hash_invalid
- bpf_get_numa_node_id
- bpf_skb_change_head
- bpf_get_socket_cookie
- bpf_get_socket_uid
- bpf_set_hash
- bpf_skb_adjust_room
- bpf_skb_get_xfrm_state
- bpf_skb_load_bytes_relative
- bpf_fib_lookup
- bpf_skb_cgroup_id
- bpf_skb_ancestor_cgroup_id
- bpf_sk_lookup_tcp
- bpf_sk_lookup_udp
- bpf_sk_release
- bpf_map_push_elem
- bpf_map_pop_elem
- bpf_map_peek_elem
- bpf_spin_lock
- bpf_spin_unlock
- bpf_sk_fullsock
- bpf_tcp_sock
- bpf_skb_ecn_set_ce
- bpf_get_listener_sock
- bpf_skc_lookup_tcp
- bpf_tcp_check_syncookie
- bpf_sk_storage_get
- bpf_sk_storage_delete
- bpf_tcp_gen_syncookie
- bpf_probe_read_user
- bpf_probe_read_kernel
- bpf_probe_read_user_str
- bpf_probe_read_kernel_str
- bpf_jiffies64
- bpf_sk_assign
- bpf_ktime_get_boot_ns
- bpf_ringbuf_output
- bpf_ringbuf_reserve
- bpf_ringbuf_submit
- bpf_ringbuf_discard
- bpf_ringbuf_query
- bpf_csum_level
- bpf_skc_to_tcp6_sock
- bpf_skc_to_tcp_sock
- bpf_skc_to_tcp_timewait_sock
- bpf_skc_to_tcp_request_sock
- bpf_skc_to_udp6_sock
- bpf_snprintf_btf
- bpf_skb_cgroup_classid
- bpf_redirect_neigh
- bpf_per_cpu_ptr
- bpf_this_cpu_ptr
- bpf_redirect_peer
- bpf_get_current_task_btf
- bpf_ktime_get_coarse_ns
- bpf_check_mtu
- bpf_for_each_map_elem
- bpf_snprintf
- bpf_timer_init
- bpf_timer_set_callback
- bpf_timer_start
- bpf_timer_cancel
- bpf_task_pt_regs
- bpf_skc_to_unix_sock
- bpf_loop
- bpf_strncmp
- bpf_skb_set_tstamp
- bpf_kptr_xchg
- bpf_map_lookup_percpu_elem
- bpf_skc_to_mptcp_sock
- bpf_dynptr_from_mem
- bpf_ringbuf_reserve_dynptr
- bpf_ringbuf_submit_dynptr
- bpf_ringbuf_discard_dynptr
- bpf_dynptr_read
- bpf_dynptr_write
- bpf_dynptr_data
eBPF helpers supported for program type sched_act:
- bpf_map_lookup_elem
- bpf_map_update_elem
- bpf_map_delete_elem
- bpf_ktime_get_ns
- bpf_get_prandom_u32
- bpf_get_smp_processor_id
- bpf_skb_store_bytes
- bpf_l3_csum_replace
- bpf_l4_csum_replace
- bpf_tail_call
- bpf_clone_redirect
- bpf_get_cgroup_classid
- bpf_skb_vlan_push
- bpf_skb_vlan_pop
- bpf_skb_get_tunnel_key
- bpf_skb_set_tunnel_key
- bpf_redirect
- bpf_get_route_realm
- bpf_perf_event_output
- bpf_skb_load_bytes
- bpf_csum_diff
- bpf_skb_get_tunnel_opt
- bpf_skb_set_tunnel_opt
- bpf_skb_change_proto
- bpf_skb_change_type
- bpf_skb_under_cgroup
- bpf_get_hash_recalc
- bpf_get_current_task
- bpf_skb_change_tail
- bpf_skb_pull_data
- bpf_csum_update
- bpf_set_hash_invalid
- bpf_get_numa_node_id
- bpf_skb_change_head
- bpf_get_socket_cookie
- bpf_get_socket_uid
- bpf_set_hash
- bpf_skb_adjust_room
- bpf_skb_get_xfrm_state
- bpf_skb_load_bytes_relative
- bpf_fib_lookup
- bpf_skb_cgroup_id
- bpf_skb_ancestor_cgroup_id
- bpf_sk_lookup_tcp
- bpf_sk_lookup_udp
- bpf_sk_release
- bpf_map_push_elem
- bpf_map_pop_elem
- bpf_map_peek_elem
- bpf_spin_lock
- bpf_spin_unlock
- bpf_sk_fullsock
- bpf_tcp_sock
- bpf_skb_ecn_set_ce
- bpf_get_listener_sock
- bpf_skc_lookup_tcp
- bpf_tcp_check_syncookie
- bpf_sk_storage_get
- bpf_sk_storage_delete
- bpf_tcp_gen_syncookie
- bpf_probe_read_user
- bpf_probe_read_kernel
- bpf_probe_read_user_str
- bpf_probe_read_kernel_str
- bpf_jiffies64
- bpf_sk_assign
- bpf_ktime_get_boot_ns
- bpf_ringbuf_output
- bpf_ringbuf_reserve
- bpf_ringbuf_submit
- bpf_ringbuf_discard
- bpf_ringbuf_query
- bpf_csum_level
- bpf_skc_to_tcp6_sock
- bpf_skc_to_tcp_sock
- bpf_skc_to_tcp_timewait_sock
- bpf_skc_to_tcp_request_sock
- bpf_skc_to_udp6_sock
- bpf_snprintf_btf
- bpf_skb_cgroup_classid
- bpf_redirect_neigh
- bpf_per_cpu_ptr
- bpf_this_cpu_ptr
- bpf_redirect_peer
- bpf_get_current_task_btf
- bpf_ktime_get_coarse_ns
- bpf_check_mtu
- bpf_for_each_map_elem
- bpf_snprintf
- bpf_timer_init
- bpf_timer_set_callback
- bpf_timer_start
- bpf_timer_cancel
- bpf_task_pt_regs
- bpf_skc_to_unix_sock
- bpf_loop
- bpf_strncmp
- bpf_skb_set_tstamp
- bpf_kptr_xchg
- bpf_map_lookup_percpu_elem
- bpf_skc_to_mptcp_sock
- bpf_dynptr_from_mem
- bpf_ringbuf_reserve_dynptr
- bpf_ringbuf_submit_dynptr
- bpf_ringbuf_discard_dynptr
- bpf_dynptr_read
- bpf_dynptr_write
- bpf_dynptr_data
eBPF helpers supported for program type tracepoint:
- bpf_map_lookup_elem
- bpf_map_update_elem
- bpf_map_delete_elem
- bpf_probe_read
- bpf_ktime_get_ns
- bpf_get_prandom_u32
- bpf_get_smp_processor_id
- bpf_tail_call
- bpf_get_current_pid_tgid
- bpf_get_current_uid_gid
- bpf_get_current_comm
- bpf_perf_event_read
- bpf_perf_event_output
- bpf_get_stackid
- bpf_get_current_task
- bpf_current_task_under_cgroup
- bpf_get_numa_node_id
- bpf_probe_read_str
- bpf_perf_event_read_value
- bpf_get_stack
- bpf_get_current_cgroup_id
- bpf_map_push_elem
- bpf_map_pop_elem
- bpf_map_peek_elem
- bpf_spin_lock
- bpf_spin_unlock
- bpf_send_signal
- bpf_probe_read_user
- bpf_probe_read_kernel
- bpf_probe_read_user_str
- bpf_probe_read_kernel_str
- bpf_send_signal_thread
- bpf_jiffies64
- bpf_get_ns_current_pid_tgid
- bpf_get_current_ancestor_cgroup_id
- bpf_ktime_get_boot_ns
- bpf_ringbuf_output
- bpf_ringbuf_reserve
- bpf_ringbuf_submit
- bpf_ringbuf_discard
- bpf_ringbuf_query
- bpf_get_task_stack
- bpf_snprintf_btf
- bpf_per_cpu_ptr
- bpf_this_cpu_ptr
- bpf_task_storage_get
- bpf_task_storage_delete
- bpf_get_current_task_btf
- bpf_for_each_map_elem
- bpf_snprintf
- bpf_timer_init
- bpf_timer_set_callback
- bpf_timer_start
- bpf_timer_cancel
- bpf_get_func_ip
- bpf_get_attach_cookie
- bpf_task_pt_regs
- bpf_get_branch_snapshot
- bpf_find_vma
- bpf_loop
- bpf_strncmp
- bpf_kptr_xchg
- bpf_map_lookup_percpu_elem
- bpf_dynptr_from_mem
- bpf_ringbuf_reserve_dynptr
- bpf_ringbuf_submit_dynptr
- bpf_ringbuf_discard_dynptr
- bpf_dynptr_read
- bpf_dynptr_write
- bpf_dynptr_data
eBPF helpers supported for program type xdp:
- bpf_map_lookup_elem
- bpf_map_update_elem
- bpf_map_delete_elem
- bpf_ktime_get_ns
- bpf_get_prandom_u32
- bpf_get_smp_processor_id
- bpf_tail_call
- bpf_redirect
- bpf_perf_event_output
- bpf_csum_diff
- bpf_get_current_task
- bpf_get_numa_node_id
- bpf_xdp_adjust_head
- bpf_redirect_map
- bpf_xdp_adjust_meta
- bpf_xdp_adjust_tail
- bpf_fib_lookup
- bpf_sk_lookup_tcp
- bpf_sk_lookup_udp
- bpf_sk_release
- bpf_map_push_elem
- bpf_map_pop_elem
- bpf_map_peek_elem
- bpf_spin_lock
- bpf_spin_unlock
- bpf_skc_lookup_tcp
- bpf_tcp_check_syncookie
- bpf_tcp_gen_syncookie
- bpf_probe_read_user
- bpf_probe_read_kernel
- bpf_probe_read_user_str
- bpf_probe_read_kernel_str
- bpf_jiffies64
- bpf_ktime_get_boot_ns
- bpf_ringbuf_output
- bpf_ringbuf_reserve
- bpf_ringbuf_submit
- bpf_ringbuf_discard
- bpf_ringbuf_query
- bpf_skc_to_tcp6_sock
- bpf_skc_to_tcp_sock
- bpf_skc_to_tcp_timewait_sock
- bpf_skc_to_tcp_request_sock
- bpf_skc_to_udp6_sock
- bpf_snprintf_btf
- bpf_per_cpu_ptr
- bpf_this_cpu_ptr
- bpf_get_current_task_btf
- bpf_ktime_get_coarse_ns
- bpf_check_mtu
- bpf_for_each_map_elem
- bpf_snprintf
- bpf_timer_init
- bpf_timer_set_callback
- bpf_timer_start
- bpf_timer_cancel
- bpf_task_pt_regs
- bpf_skc_to_unix_sock
- bpf_loop
- bpf_strncmp
- bpf_xdp_get_buff_len
- bpf_xdp_load_bytes
- bpf_xdp_store_bytes
- bpf_kptr_xchg
- bpf_map_lookup_percpu_elem
- bpf_skc_to_mptcp_sock
- bpf_dynptr_from_mem
- bpf_ringbuf_reserve_dynptr
- bpf_ringbuf_submit_dynptr
- bpf_ringbuf_discard_dynptr
- bpf_dynptr_read
- bpf_dynptr_write
- bpf_dynptr_data
eBPF helpers supported for program type perf_event:
- bpf_map_lookup_elem
- bpf_map_update_elem
- bpf_map_delete_elem
- bpf_probe_read
- bpf_ktime_get_ns
- bpf_get_prandom_u32
- bpf_get_smp_processor_id
- bpf_tail_call
- bpf_get_current_pid_tgid
- bpf_get_current_uid_gid
- bpf_get_current_comm
- bpf_perf_event_read
- bpf_perf_event_output
- bpf_get_stackid
- bpf_get_current_task
- bpf_current_task_under_cgroup
- bpf_get_numa_node_id
- bpf_probe_read_str
- bpf_perf_event_read_value
- bpf_perf_prog_read_value
- bpf_get_stack
- bpf_get_current_cgroup_id
- bpf_map_push_elem
- bpf_map_pop_elem
- bpf_map_peek_elem
- bpf_spin_lock
- bpf_spin_unlock
- bpf_send_signal
- bpf_probe_read_user
- bpf_probe_read_kernel
- bpf_probe_read_user_str
- bpf_probe_read_kernel_str
- bpf_send_signal_thread
- bpf_jiffies64
- bpf_read_branch_records
- bpf_get_ns_current_pid_tgid
- bpf_get_current_ancestor_cgroup_id
- bpf_ktime_get_boot_ns
- bpf_ringbuf_output
- bpf_ringbuf_reserve
- bpf_ringbuf_submit
- bpf_ringbuf_discard
- bpf_ringbuf_query
- bpf_get_task_stack
- bpf_snprintf_btf
- bpf_per_cpu_ptr
- bpf_this_cpu_ptr
- bpf_task_storage_get
- bpf_task_storage_delete
- bpf_get_current_task_btf
- bpf_for_each_map_elem
- bpf_snprintf
- bpf_timer_init
- bpf_timer_set_callback
- bpf_timer_start
- bpf_timer_cancel
- bpf_get_func_ip
- bpf_get_attach_cookie
- bpf_task_pt_regs
- bpf_get_branch_snapshot
- bpf_find_vma
- bpf_loop
- bpf_strncmp
- bpf_kptr_xchg
- bpf_map_lookup_percpu_elem
- bpf_dynptr_from_mem
- bpf_ringbuf_reserve_dynptr
- bpf_ringbuf_submit_dynptr
- bpf_ringbuf_discard_dynptr
- bpf_dynptr_read
- bpf_dynptr_write
- bpf_dynptr_data
eBPF helpers supported for program type cgroup_skb:
- bpf_map_lookup_elem
- bpf_map_update_elem
- bpf_map_delete_elem
- bpf_ktime_get_ns
- bpf_get_prandom_u32
- bpf_get_smp_processor_id
- bpf_tail_call
- bpf_perf_event_output
- bpf_skb_load_bytes
- bpf_get_current_task
- bpf_get_numa_node_id
- bpf_get_socket_cookie
- bpf_get_socket_uid
- bpf_skb_load_bytes_relative
- bpf_skb_cgroup_id
- bpf_get_local_storage
- bpf_skb_ancestor_cgroup_id
- bpf_sk_lookup_tcp
- bpf_sk_lookup_udp
- bpf_sk_release
- bpf_map_push_elem
- bpf_map_pop_elem
- bpf_map_peek_elem
- bpf_spin_lock
- bpf_spin_unlock
- bpf_sk_fullsock
- bpf_tcp_sock
- bpf_skb_ecn_set_ce
- bpf_get_listener_sock
- bpf_skc_lookup_tcp
- bpf_sk_storage_get
- bpf_sk_storage_delete
- bpf_probe_read_user
- bpf_probe_read_kernel
- bpf_probe_read_user_str
- bpf_probe_read_kernel_str
- bpf_jiffies64
- bpf_ktime_get_boot_ns
- bpf_sk_cgroup_id
- bpf_sk_ancestor_cgroup_id
- bpf_ringbuf_output
- bpf_ringbuf_reserve
- bpf_ringbuf_submit
- bpf_ringbuf_discard
- bpf_ringbuf_query
- bpf_skc_to_tcp6_sock
- bpf_skc_to_tcp_sock
- bpf_skc_to_tcp_timewait_sock
- bpf_skc_to_tcp_request_sock
- bpf_skc_to_udp6_sock
- bpf_snprintf_btf
- bpf_per_cpu_ptr
- bpf_this_cpu_ptr
- bpf_get_current_task_btf
- bpf_ktime_get_coarse_ns
- bpf_for_each_map_elem
- bpf_snprintf
- bpf_timer_init
- bpf_timer_set_callback
- bpf_timer_start
- bpf_timer_cancel
- bpf_task_pt_regs
- bpf_skc_to_unix_sock
- bpf_loop
- bpf_strncmp
- bpf_kptr_xchg
- bpf_map_lookup_percpu_elem
- bpf_skc_to_mptcp_sock
- bpf_dynptr_from_mem
- bpf_ringbuf_reserve_dynptr
- bpf_ringbuf_submit_dynptr
- bpf_ringbuf_discard_dynptr
- bpf_dynptr_read
- bpf_dynptr_write
- bpf_dynptr_data
eBPF helpers supported for program type cgroup_sock:
- bpf_map_lookup_elem
- bpf_map_update_elem
- bpf_map_delete_elem
- bpf_ktime_get_ns
- bpf_get_prandom_u32
- bpf_get_smp_processor_id
- bpf_tail_call
- bpf_get_current_pid_tgid
- bpf_get_current_uid_gid
- bpf_get_current_comm
- bpf_get_cgroup_classid
- bpf_perf_event_output
- bpf_get_current_task
- bpf_get_numa_node_id
- bpf_get_socket_cookie
- bpf_get_current_cgroup_id
- bpf_get_local_storage
- bpf_map_push_elem
- bpf_map_pop_elem
- bpf_map_peek_elem
- bpf_spin_lock
- bpf_spin_unlock
- bpf_sk_storage_get
- bpf_probe_read_user
- bpf_probe_read_kernel
- bpf_probe_read_user_str
- bpf_probe_read_kernel_str
- bpf_jiffies64
- bpf_get_netns_cookie
- bpf_get_current_ancestor_cgroup_id
- bpf_ktime_get_boot_ns
- bpf_ringbuf_output
- bpf_ringbuf_reserve
- bpf_ringbuf_submit
- bpf_ringbuf_discard
- bpf_ringbuf_query
- bpf_snprintf_btf
- bpf_per_cpu_ptr
- bpf_this_cpu_ptr
- bpf_get_current_task_btf
- bpf_ktime_get_coarse_ns
- bpf_for_each_map_elem
- bpf_snprintf
- bpf_timer_init
- bpf_timer_set_callback
- bpf_timer_start
- bpf_timer_cancel
- bpf_task_pt_regs
- bpf_loop
- bpf_strncmp
- bpf_kptr_xchg
- bpf_map_lookup_percpu_elem
- bpf_dynptr_from_mem
- bpf_ringbuf_reserve_dynptr
- bpf_ringbuf_submit_dynptr
- bpf_ringbuf_discard_dynptr
- bpf_dynptr_read
- bpf_dynptr_write
- bpf_dynptr_data
eBPF helpers supported for program type lwt_in:
- bpf_map_lookup_elem
- bpf_map_update_elem
- bpf_map_delete_elem
- bpf_ktime_get_ns
- bpf_get_prandom_u32
- bpf_get_smp_processor_id
- bpf_tail_call
- bpf_get_cgroup_classid
- bpf_get_route_realm
- bpf_perf_event_output
- bpf_skb_load_bytes
- bpf_csum_diff
- bpf_skb_under_cgroup
- bpf_get_hash_recalc
- bpf_get_current_task
- bpf_skb_pull_data
- bpf_get_numa_node_id
- bpf_lwt_push_encap
- bpf_map_push_elem
- bpf_map_pop_elem
- bpf_map_peek_elem
- bpf_spin_lock
- bpf_spin_unlock
- bpf_probe_read_user
- bpf_probe_read_kernel
- bpf_probe_read_user_str
- bpf_probe_read_kernel_str
- bpf_jiffies64
- bpf_ktime_get_boot_ns
- bpf_ringbuf_output
- bpf_ringbuf_reserve
- bpf_ringbuf_submit
- bpf_ringbuf_discard
- bpf_ringbuf_query
- bpf_skc_to_tcp6_sock
- bpf_skc_to_tcp_sock
- bpf_skc_to_tcp_timewait_sock
- bpf_skc_to_tcp_request_sock
- bpf_skc_to_udp6_sock
- bpf_snprintf_btf
- bpf_per_cpu_ptr
- bpf_this_cpu_ptr
- bpf_get_current_task_btf
- bpf_ktime_get_coarse_ns
- bpf_for_each_map_elem
- bpf_snprintf
- bpf_timer_init
- bpf_timer_set_callback
- bpf_timer_start
- bpf_timer_cancel
- bpf_task_pt_regs
- bpf_skc_to_unix_sock
- bpf_loop
- bpf_strncmp
- bpf_kptr_xchg
- bpf_map_lookup_percpu_elem
- bpf_skc_to_mptcp_sock
- bpf_dynptr_from_mem
- bpf_ringbuf_reserve_dynptr
- bpf_ringbuf_submit_dynptr
- bpf_ringbuf_discard_dynptr
- bpf_dynptr_read
- bpf_dynptr_write
- bpf_dynptr_data
eBPF helpers supported for program type lwt_out:
- bpf_map_lookup_elem
- bpf_map_update_elem
- bpf_map_delete_elem
- bpf_ktime_get_ns
- bpf_get_prandom_u32
- bpf_get_smp_processor_id
- bpf_tail_call
- bpf_get_cgroup_classid
- bpf_get_route_realm
- bpf_perf_event_output
- bpf_skb_load_bytes
- bpf_csum_diff
- bpf_skb_under_cgroup
- bpf_get_hash_recalc
- bpf_get_current_task
- bpf_skb_pull_data
- bpf_get_numa_node_id
- bpf_map_push_elem
- bpf_map_pop_elem
- bpf_map_peek_elem
- bpf_spin_lock
- bpf_spin_unlock
- bpf_probe_read_user
- bpf_probe_read_kernel
- bpf_probe_read_user_str
- bpf_probe_read_kernel_str
- bpf_jiffies64
- bpf_ktime_get_boot_ns
- bpf_ringbuf_output
- bpf_ringbuf_reserve
- bpf_ringbuf_submit
- bpf_ringbuf_discard
- bpf_ringbuf_query
- bpf_skc_to_tcp6_sock
- bpf_skc_to_tcp_sock
- bpf_skc_to_tcp_timewait_sock
- bpf_skc_to_tcp_request_sock
- bpf_skc_to_udp6_sock
- bpf_snprintf_btf
- bpf_per_cpu_ptr
- bpf_this_cpu_ptr
- bpf_get_current_task_btf
- bpf_ktime_get_coarse_ns
- bpf_for_each_map_elem
- bpf_snprintf
- bpf_timer_init
- bpf_timer_set_callback
- bpf_timer_start
- bpf_timer_cancel
- bpf_task_pt_regs
- bpf_skc_to_unix_sock
- bpf_loop
- bpf_strncmp
- bpf_kptr_xchg
- bpf_map_lookup_percpu_elem
- bpf_skc_to_mptcp_sock
- bpf_dynptr_from_mem
- bpf_ringbuf_reserve_dynptr
- bpf_ringbuf_submit_dynptr
- bpf_ringbuf_discard_dynptr
- bpf_dynptr_read
- bpf_dynptr_write
- bpf_dynptr_data
eBPF helpers supported for program type lwt_xmit:
- bpf_map_lookup_elem
- bpf_map_update_elem
- bpf_map_delete_elem
- bpf_ktime_get_ns
- bpf_get_prandom_u32
- bpf_get_smp_processor_id
- bpf_skb_store_bytes
- bpf_l3_csum_replace
- bpf_l4_csum_replace
- bpf_tail_call
- bpf_clone_redirect
- bpf_get_cgroup_classid
- bpf_skb_get_tunnel_key
- bpf_skb_set_tunnel_key
- bpf_redirect
- bpf_get_route_realm
- bpf_perf_event_output
- bpf_skb_load_bytes
- bpf_csum_diff
- bpf_skb_get_tunnel_opt
- bpf_skb_set_tunnel_opt
- bpf_skb_under_cgroup
- bpf_get_hash_recalc
- bpf_get_current_task
- bpf_skb_change_tail
- bpf_skb_pull_data
- bpf_csum_update
- bpf_set_hash_invalid
- bpf_get_numa_node_id
- bpf_skb_change_head
- bpf_lwt_push_encap
- bpf_map_push_elem
- bpf_map_pop_elem
- bpf_map_peek_elem
- bpf_spin_lock
- bpf_spin_unlock
- bpf_probe_read_user
- bpf_probe_read_kernel
- bpf_probe_read_user_str
- bpf_probe_read_kernel_str
- bpf_jiffies64
- bpf_ktime_get_boot_ns
- bpf_ringbuf_output
- bpf_ringbuf_reserve
- bpf_ringbuf_submit
- bpf_ringbuf_discard
- bpf_ringbuf_query
- bpf_csum_level
- bpf_skc_to_tcp6_sock
- bpf_skc_to_tcp_sock
- bpf_skc_to_tcp_timewait_sock
- bpf_skc_to_tcp_request_sock
- bpf_skc_to_udp6_sock
- bpf_snprintf_btf
- bpf_per_cpu_ptr
- bpf_this_cpu_ptr
- bpf_get_current_task_btf
- bpf_ktime_get_coarse_ns
- bpf_for_each_map_elem
- bpf_snprintf
- bpf_timer_init
- bpf_timer_set_callback
- bpf_timer_start
- bpf_timer_cancel
- bpf_task_pt_regs
- bpf_skc_to_unix_sock
- bpf_loop
- bpf_strncmp
- bpf_kptr_xchg
- bpf_map_lookup_percpu_elem
- bpf_skc_to_mptcp_sock
- bpf_dynptr_from_mem
- bpf_ringbuf_reserve_dynptr
- bpf_ringbuf_submit_dynptr
- bpf_ringbuf_discard_dynptr
- bpf_dynptr_read
- bpf_dynptr_write
- bpf_dynptr_data
eBPF helpers supported for program type sock_ops:
- bpf_map_lookup_elem
- bpf_map_update_elem
- bpf_map_delete_elem
- bpf_ktime_get_ns
- bpf_get_prandom_u32
- bpf_get_smp_processor_id
- bpf_tail_call
- bpf_perf_event_output
- bpf_get_current_task
- bpf_get_numa_node_id
- bpf_get_socket_cookie
- bpf_setsockopt
- bpf_sock_map_update
- bpf_getsockopt
- bpf_sock_ops_cb_flags_set
- bpf_sock_hash_update
- bpf_get_local_storage
- bpf_map_push_elem
- bpf_map_pop_elem
- bpf_map_peek_elem
- bpf_spin_lock
- bpf_spin_unlock
- bpf_tcp_sock
- bpf_sk_storage_get
- bpf_sk_storage_delete
- bpf_probe_read_user
- bpf_probe_read_kernel
- bpf_probe_read_user_str
- bpf_probe_read_kernel_str
- bpf_jiffies64
- bpf_get_netns_cookie
- bpf_ktime_get_boot_ns
- bpf_ringbuf_output
- bpf_ringbuf_reserve
- bpf_ringbuf_submit
- bpf_ringbuf_discard
- bpf_ringbuf_query
- bpf_skc_to_tcp6_sock
- bpf_skc_to_tcp_sock
- bpf_skc_to_tcp_timewait_sock
- bpf_skc_to_tcp_request_sock
- bpf_skc_to_udp6_sock
- bpf_load_hdr_opt
- bpf_store_hdr_opt
- bpf_reserve_hdr_opt
- bpf_snprintf_btf
- bpf_per_cpu_ptr
- bpf_this_cpu_ptr
- bpf_get_current_task_btf
- bpf_ktime_get_coarse_ns
- bpf_for_each_map_elem
- bpf_snprintf
- bpf_timer_init
- bpf_timer_set_callback
- bpf_timer_start
- bpf_timer_cancel
- bpf_task_pt_regs
- bpf_skc_to_unix_sock
- bpf_loop
- bpf_strncmp
- bpf_kptr_xchg
- bpf_map_lookup_percpu_elem
- bpf_skc_to_mptcp_sock
- bpf_dynptr_from_mem
- bpf_ringbuf_reserve_dynptr
- bpf_ringbuf_submit_dynptr
- bpf_ringbuf_discard_dynptr
- bpf_dynptr_read
- bpf_dynptr_write
- bpf_dynptr_data
eBPF helpers supported for program type sk_skb:
- bpf_map_lookup_elem
- bpf_map_update_elem
- bpf_map_delete_elem
- bpf_ktime_get_ns
- bpf_get_prandom_u32
- bpf_get_smp_processor_id
- bpf_skb_store_bytes
- bpf_tail_call
- bpf_perf_event_output
- bpf_skb_load_bytes
- bpf_get_current_task
- bpf_skb_change_tail
- bpf_skb_pull_data
- bpf_get_numa_node_id
- bpf_skb_change_head
- bpf_get_socket_cookie
- bpf_get_socket_uid
- bpf_skb_adjust_room
- bpf_sk_redirect_map
- bpf_sk_redirect_hash
- bpf_sk_lookup_tcp
- bpf_sk_lookup_udp
- bpf_sk_release
- bpf_map_push_elem
- bpf_map_pop_elem
- bpf_map_peek_elem
- bpf_spin_lock
- bpf_spin_unlock
- bpf_skc_lookup_tcp
- bpf_probe_read_user
- bpf_probe_read_kernel
- bpf_probe_read_user_str
- bpf_probe_read_kernel_str
- bpf_jiffies64
- bpf_ktime_get_boot_ns
- bpf_ringbuf_output
- bpf_ringbuf_reserve
- bpf_ringbuf_submit
- bpf_ringbuf_discard
- bpf_ringbuf_query
- bpf_skc_to_tcp6_sock
- bpf_skc_to_tcp_sock
- bpf_skc_to_tcp_timewait_sock
- bpf_skc_to_tcp_request_sock
- bpf_skc_to_udp6_sock
- bpf_snprintf_btf
- bpf_per_cpu_ptr
- bpf_this_cpu_ptr
- bpf_get_current_task_btf
- bpf_ktime_get_coarse_ns
- bpf_for_each_map_elem
- bpf_snprintf
- bpf_timer_init
- bpf_timer_set_callback
- bpf_timer_start
- bpf_timer_cancel
- bpf_task_pt_regs
- bpf_skc_to_unix_sock
- bpf_loop
- bpf_strncmp
- bpf_kptr_xchg
- bpf_map_lookup_percpu_elem
- bpf_skc_to_mptcp_sock
- bpf_dynptr_from_mem
- bpf_ringbuf_reserve_dynptr
- bpf_ringbuf_submit_dynptr
- bpf_ringbuf_discard_dynptr
- bpf_dynptr_read
- bpf_dynptr_write
- bpf_dynptr_data
eBPF helpers supported for program type cgroup_device:
- bpf_map_lookup_elem
- bpf_map_update_elem
- bpf_map_delete_elem
- bpf_ktime_get_ns
- bpf_get_prandom_u32
- bpf_get_smp_processor_id
- bpf_tail_call
- bpf_get_current_uid_gid
- bpf_perf_event_output
- bpf_get_current_task
- bpf_get_numa_node_id
- bpf_get_current_cgroup_id
- bpf_get_local_storage
- bpf_map_push_elem
- bpf_map_pop_elem
- bpf_map_peek_elem
- bpf_spin_lock
- bpf_spin_unlock
- bpf_probe_read_user
- bpf_probe_read_kernel
- bpf_probe_read_user_str
- bpf_probe_read_kernel_str
- bpf_jiffies64
- bpf_ktime_get_boot_ns
- bpf_ringbuf_output
- bpf_ringbuf_reserve
- bpf_ringbuf_submit
- bpf_ringbuf_discard
- bpf_ringbuf_query
- bpf_snprintf_btf
- bpf_per_cpu_ptr
- bpf_this_cpu_ptr
- bpf_get_current_task_btf
- bpf_for_each_map_elem
- bpf_snprintf
- bpf_timer_init
- bpf_timer_set_callback
- bpf_timer_start
- bpf_timer_cancel
- bpf_task_pt_regs
- bpf_loop
- bpf_strncmp
- bpf_get_retval
- bpf_set_retval
- bpf_kptr_xchg
- bpf_map_lookup_percpu_elem
- bpf_dynptr_from_mem
- bpf_ringbuf_reserve_dynptr
- bpf_ringbuf_submit_dynptr
- bpf_ringbuf_discard_dynptr
- bpf_dynptr_read
- bpf_dynptr_write
- bpf_dynptr_data
eBPF helpers supported for program type sk_msg:
- bpf_map_lookup_elem
- bpf_map_update_elem
- bpf_map_delete_elem
- bpf_ktime_get_ns
- bpf_get_prandom_u32
- bpf_get_smp_processor_id
- bpf_tail_call
- bpf_get_current_pid_tgid
- bpf_get_current_uid_gid
- bpf_get_cgroup_classid
- bpf_perf_event_output
- bpf_get_current_task
- bpf_get_numa_node_id
- bpf_msg_redirect_map
- bpf_msg_apply_bytes
- bpf_msg_cork_bytes
- bpf_msg_pull_data
- bpf_msg_redirect_hash
- bpf_get_current_cgroup_id
- bpf_map_push_elem
- bpf_map_pop_elem
- bpf_map_peek_elem
- bpf_msg_push_data
- bpf_msg_pop_data
- bpf_spin_lock
- bpf_spin_unlock
- bpf_sk_storage_get
- bpf_sk_storage_delete
- bpf_probe_read_user
- bpf_probe_read_kernel
- bpf_probe_read_user_str
- bpf_probe_read_kernel_str
- bpf_jiffies64
- bpf_get_netns_cookie
- bpf_get_current_ancestor_cgroup_id
- bpf_ktime_get_boot_ns
- bpf_ringbuf_output
- bpf_ringbuf_reserve
- bpf_ringbuf_submit
- bpf_ringbuf_discard
- bpf_ringbuf_query
- bpf_skc_to_tcp6_sock
- bpf_skc_to_tcp_sock
- bpf_skc_to_tcp_timewait_sock
- bpf_skc_to_tcp_request_sock
- bpf_skc_to_udp6_sock
- bpf_snprintf_btf
- bpf_per_cpu_ptr
- bpf_this_cpu_ptr
- bpf_get_current_task_btf
- bpf_ktime_get_coarse_ns
- bpf_for_each_map_elem
- bpf_snprintf
- bpf_timer_init
- bpf_timer_set_callback
- bpf_timer_start
- bpf_timer_cancel
- bpf_task_pt_regs
- bpf_skc_to_unix_sock
- bpf_loop
- bpf_strncmp
- bpf_kptr_xchg
- bpf_map_lookup_percpu_elem
- bpf_skc_to_mptcp_sock
- bpf_dynptr_from_mem
- bpf_ringbuf_reserve_dynptr
- bpf_ringbuf_submit_dynptr
- bpf_ringbuf_discard_dynptr
- bpf_dynptr_read
- bpf_dynptr_write
- bpf_dynptr_data
eBPF helpers supported for program type raw_tracepoint:
- bpf_map_lookup_elem
- bpf_map_update_elem
- bpf_map_delete_elem
- bpf_probe_read
- bpf_ktime_get_ns
- bpf_get_prandom_u32
- bpf_get_smp_processor_id
- bpf_tail_call
- bpf_get_current_pid_tgid
- bpf_get_current_uid_gid
- bpf_get_current_comm
- bpf_perf_event_read
- bpf_perf_event_output
- bpf_get_stackid
- bpf_get_current_task
- bpf_current_task_under_cgroup
- bpf_get_numa_node_id
- bpf_probe_read_str
- bpf_perf_event_read_value
- bpf_get_stack
- bpf_get_current_cgroup_id
- bpf_map_push_elem
- bpf_map_pop_elem
- bpf_map_peek_elem
- bpf_spin_lock
- bpf_spin_unlock
- bpf_send_signal
- bpf_probe_read_user
- bpf_probe_read_kernel
- bpf_probe_read_user_str
- bpf_probe_read_kernel_str
- bpf_send_signal_thread
- bpf_jiffies64
- bpf_get_ns_current_pid_tgid
- bpf_get_current_ancestor_cgroup_id
- bpf_ktime_get_boot_ns
- bpf_ringbuf_output
- bpf_ringbuf_reserve
- bpf_ringbuf_submit
- bpf_ringbuf_discard
- bpf_ringbuf_query
- bpf_get_task_stack
- bpf_snprintf_btf
- bpf_per_cpu_ptr
- bpf_this_cpu_ptr
- bpf_task_storage_get
- bpf_task_storage_delete
- bpf_get_current_task_btf
- bpf_for_each_map_elem
- bpf_snprintf
- bpf_timer_init
- bpf_timer_set_callback
- bpf_timer_start
- bpf_timer_cancel
- bpf_get_func_ip
- bpf_task_pt_regs
- bpf_get_branch_snapshot
- bpf_find_vma
- bpf_loop
- bpf_strncmp
- bpf_kptr_xchg
- bpf_map_lookup_percpu_elem
- bpf_dynptr_from_mem
- bpf_ringbuf_reserve_dynptr
- bpf_ringbuf_submit_dynptr
- bpf_ringbuf_discard_dynptr
- bpf_dynptr_read
- bpf_dynptr_write
- bpf_dynptr_data
eBPF helpers supported for program type cgroup_sock_addr:
- bpf_map_lookup_elem
- bpf_map_update_elem
- bpf_map_delete_elem
- bpf_ktime_get_ns
- bpf_get_prandom_u32
- bpf_get_smp_processor_id
- bpf_tail_call
- bpf_get_current_pid_tgid
- bpf_get_current_uid_gid
- bpf_get_current_comm
- bpf_get_cgroup_classid
- bpf_perf_event_output
- bpf_get_current_task
- bpf_get_numa_node_id
- bpf_get_socket_cookie
- bpf_setsockopt
- bpf_getsockopt
- bpf_bind
- bpf_get_current_cgroup_id
- bpf_get_local_storage
- bpf_sk_lookup_tcp
- bpf_sk_lookup_udp
- bpf_sk_release
- bpf_map_push_elem
- bpf_map_pop_elem
- bpf_map_peek_elem
- bpf_spin_lock
- bpf_spin_unlock
- bpf_skc_lookup_tcp
- bpf_sk_storage_get
- bpf_sk_storage_delete
- bpf_probe_read_user
- bpf_probe_read_kernel
- bpf_probe_read_user_str
- bpf_probe_read_kernel_str
- bpf_jiffies64
- bpf_get_netns_cookie
- bpf_get_current_ancestor_cgroup_id
- bpf_ktime_get_boot_ns
- bpf_ringbuf_output
- bpf_ringbuf_reserve
- bpf_ringbuf_submit
- bpf_ringbuf_discard
- bpf_ringbuf_query
- bpf_skc_to_tcp6_sock
- bpf_skc_to_tcp_sock
- bpf_skc_to_tcp_timewait_sock
- bpf_skc_to_tcp_request_sock
- bpf_skc_to_udp6_sock
- bpf_snprintf_btf
- bpf_per_cpu_ptr
- bpf_this_cpu_ptr
- bpf_get_current_task_btf
- bpf_ktime_get_coarse_ns
- bpf_for_each_map_elem
- bpf_snprintf
- bpf_timer_init
- bpf_timer_set_callback
- bpf_timer_start
- bpf_timer_cancel
- bpf_task_pt_regs
- bpf_skc_to_unix_sock
- bpf_loop
- bpf_strncmp
- bpf_kptr_xchg
- bpf_map_lookup_percpu_elem
- bpf_skc_to_mptcp_sock
- bpf_dynptr_from_mem
- bpf_ringbuf_reserve_dynptr
- bpf_ringbuf_submit_dynptr
- bpf_ringbuf_discard_dynptr
- bpf_dynptr_read
- bpf_dynptr_write
- bpf_dynptr_data
eBPF helpers supported for program type lwt_seg6local:
- bpf_map_lookup_elem
- bpf_map_update_elem
- bpf_map_delete_elem
- bpf_ktime_get_ns
- bpf_get_prandom_u32
- bpf_get_smp_processor_id
- bpf_tail_call
- bpf_get_cgroup_classid
- bpf_get_route_realm
- bpf_perf_event_output
- bpf_skb_load_bytes
- bpf_csum_diff
- bpf_skb_under_cgroup
- bpf_get_hash_recalc
- bpf_get_current_task
- bpf_skb_pull_data
- bpf_get_numa_node_id
- bpf_lwt_seg6_store_bytes
- bpf_lwt_seg6_adjust_srh
- bpf_lwt_seg6_action
- bpf_map_push_elem
- bpf_map_pop_elem
- bpf_map_peek_elem
- bpf_spin_lock
- bpf_spin_unlock
- bpf_probe_read_user
- bpf_probe_read_kernel
- bpf_probe_read_user_str
- bpf_probe_read_kernel_str
- bpf_jiffies64
- bpf_ktime_get_boot_ns
- bpf_ringbuf_output
- bpf_ringbuf_reserve
- bpf_ringbuf_submit
- bpf_ringbuf_discard
- bpf_ringbuf_query
- bpf_skc_to_tcp6_sock
- bpf_skc_to_tcp_sock
- bpf_skc_to_tcp_timewait_sock
- bpf_skc_to_tcp_request_sock
- bpf_skc_to_udp6_sock
- bpf_snprintf_btf
- bpf_per_cpu_ptr
- bpf_this_cpu_ptr
- bpf_get_current_task_btf
- bpf_ktime_get_coarse_ns
- bpf_for_each_map_elem
- bpf_snprintf
- bpf_timer_init
- bpf_timer_set_callback
- bpf_timer_start
- bpf_timer_cancel
- bpf_task_pt_regs
- bpf_skc_to_unix_sock
- bpf_loop
- bpf_strncmp
- bpf_kptr_xchg
- bpf_map_lookup_percpu_elem
- bpf_skc_to_mptcp_sock
- bpf_dynptr_from_mem
- bpf_ringbuf_reserve_dynptr
- bpf_ringbuf_submit_dynptr
- bpf_ringbuf_discard_dynptr
- bpf_dynptr_read
- bpf_dynptr_write
- bpf_dynptr_data
eBPF helpers supported for program type lirc_mode2:
Program type not supported
eBPF helpers supported for program type sk_reuseport:
- bpf_map_lookup_elem
- bpf_map_update_elem
- bpf_map_delete_elem
- bpf_ktime_get_ns
- bpf_get_prandom_u32
- bpf_get_smp_processor_id
- bpf_tail_call
- bpf_skb_load_bytes
- bpf_get_current_task
- bpf_get_numa_node_id
- bpf_get_socket_cookie
- bpf_skb_load_bytes_relative
- bpf_sk_select_reuseport
- bpf_map_push_elem
- bpf_map_pop_elem
- bpf_map_peek_elem
- bpf_spin_lock
- bpf_spin_unlock
- bpf_probe_read_user
- bpf_probe_read_kernel
- bpf_probe_read_user_str
- bpf_probe_read_kernel_str
- bpf_jiffies64
- bpf_ktime_get_boot_ns
- bpf_ringbuf_output
- bpf_ringbuf_reserve
- bpf_ringbuf_submit
- bpf_ringbuf_discard
- bpf_ringbuf_query
- bpf_snprintf_btf
- bpf_per_cpu_ptr
- bpf_this_cpu_ptr
- bpf_get_current_task_btf
- bpf_ktime_get_coarse_ns
- bpf_for_each_map_elem
- bpf_snprintf
- bpf_timer_init
- bpf_timer_set_callback
- bpf_timer_start
- bpf_timer_cancel
- bpf_task_pt_regs
- bpf_loop
- bpf_strncmp
- bpf_kptr_xchg
- bpf_map_lookup_percpu_elem
- bpf_dynptr_from_mem
- bpf_ringbuf_reserve_dynptr
- bpf_ringbuf_submit_dynptr
- bpf_ringbuf_discard_dynptr
- bpf_dynptr_read
- bpf_dynptr_write
- bpf_dynptr_data
eBPF helpers supported for program type flow_dissector:
- bpf_map_lookup_elem
- bpf_map_update_elem
- bpf_map_delete_elem
- bpf_ktime_get_ns
- bpf_get_prandom_u32
- bpf_get_smp_processor_id
- bpf_tail_call
- bpf_skb_load_bytes
- bpf_get_current_task
- bpf_get_numa_node_id
- bpf_map_push_elem
- bpf_map_pop_elem
- bpf_map_peek_elem
- bpf_spin_lock
- bpf_spin_unlock
- bpf_probe_read_user
- bpf_probe_read_kernel
- bpf_probe_read_user_str
- bpf_probe_read_kernel_str
- bpf_jiffies64
- bpf_ktime_get_boot_ns
- bpf_ringbuf_output
- bpf_ringbuf_reserve
- bpf_ringbuf_submit
- bpf_ringbuf_discard
- bpf_ringbuf_query
- bpf_skc_to_tcp6_sock
- bpf_skc_to_tcp_sock
- bpf_skc_to_tcp_timewait_sock
- bpf_skc_to_tcp_request_sock
- bpf_skc_to_udp6_sock
- bpf_snprintf_btf
- bpf_per_cpu_ptr
- bpf_this_cpu_ptr
- bpf_get_current_task_btf
- bpf_ktime_get_coarse_ns
- bpf_for_each_map_elem
- bpf_snprintf
- bpf_timer_init
- bpf_timer_set_callback
- bpf_timer_start
- bpf_timer_cancel
- bpf_task_pt_regs
- bpf_skc_to_unix_sock
- bpf_loop
- bpf_strncmp
- bpf_kptr_xchg
- bpf_map_lookup_percpu_elem
- bpf_skc_to_mptcp_sock
- bpf_dynptr_from_mem
- bpf_ringbuf_reserve_dynptr
- bpf_ringbuf_submit_dynptr
- bpf_ringbuf_discard_dynptr
- bpf_dynptr_read
- bpf_dynptr_write
- bpf_dynptr_data
eBPF helpers supported for program type cgroup_sysctl:
- bpf_map_lookup_elem
- bpf_map_update_elem
- bpf_map_delete_elem
- bpf_ktime_get_ns
- bpf_get_prandom_u32
- bpf_get_smp_processor_id
- bpf_tail_call
- bpf_get_current_uid_gid
- bpf_perf_event_output
- bpf_get_current_task
- bpf_get_numa_node_id
- bpf_get_current_cgroup_id
- bpf_get_local_storage
- bpf_map_push_elem
- bpf_map_pop_elem
- bpf_map_peek_elem
- bpf_spin_lock
- bpf_spin_unlock
- bpf_sysctl_get_name
- bpf_sysctl_get_current_value
- bpf_sysctl_get_new_value
- bpf_sysctl_set_new_value
- bpf_strtol
- bpf_strtoul
- bpf_probe_read_user
- bpf_probe_read_kernel
- bpf_probe_read_user_str
- bpf_probe_read_kernel_str
- bpf_jiffies64
- bpf_ktime_get_boot_ns
- bpf_ringbuf_output
- bpf_ringbuf_reserve
- bpf_ringbuf_submit
- bpf_ringbuf_discard
- bpf_ringbuf_query
- bpf_snprintf_btf
- bpf_per_cpu_ptr
- bpf_this_cpu_ptr
- bpf_get_current_task_btf
- bpf_ktime_get_coarse_ns
- bpf_for_each_map_elem
- bpf_snprintf
- bpf_timer_init
- bpf_timer_set_callback
- bpf_timer_start
- bpf_timer_cancel
- bpf_task_pt_regs
- bpf_loop
- bpf_strncmp
- bpf_get_retval
- bpf_set_retval
- bpf_kptr_xchg
- bpf_map_lookup_percpu_elem
- bpf_dynptr_from_mem
- bpf_ringbuf_reserve_dynptr
- bpf_ringbuf_submit_dynptr
- bpf_ringbuf_discard_dynptr
- bpf_dynptr_read
- bpf_dynptr_write
- bpf_dynptr_data
eBPF helpers supported for program type raw_tracepoint_writable:
- bpf_map_lookup_elem
- bpf_map_update_elem
- bpf_map_delete_elem
- bpf_probe_read
- bpf_ktime_get_ns
- bpf_get_prandom_u32
- bpf_get_smp_processor_id
- bpf_tail_call
- bpf_get_current_pid_tgid
- bpf_get_current_uid_gid
- bpf_get_current_comm
- bpf_perf_event_read
- bpf_perf_event_output
- bpf_get_stackid
- bpf_get_current_task
- bpf_current_task_under_cgroup
- bpf_get_numa_node_id
- bpf_probe_read_str
- bpf_perf_event_read_value
- bpf_get_stack
- bpf_get_current_cgroup_id
- bpf_map_push_elem
- bpf_map_pop_elem
- bpf_map_peek_elem
- bpf_spin_lock
- bpf_spin_unlock
- bpf_send_signal
- bpf_probe_read_user
- bpf_probe_read_kernel
- bpf_probe_read_user_str
- bpf_probe_read_kernel_str
- bpf_send_signal_thread
- bpf_jiffies64
- bpf_get_ns_current_pid_tgid
- bpf_get_current_ancestor_cgroup_id
- bpf_ktime_get_boot_ns
- bpf_ringbuf_output
- bpf_ringbuf_reserve
- bpf_ringbuf_submit
- bpf_ringbuf_discard
- bpf_ringbuf_query
- bpf_get_task_stack
- bpf_snprintf_btf
- bpf_per_cpu_ptr
- bpf_this_cpu_ptr
- bpf_task_storage_get
- bpf_task_storage_delete
- bpf_get_current_task_btf
- bpf_for_each_map_elem
- bpf_snprintf
- bpf_timer_init
- bpf_timer_set_callback
- bpf_timer_start
- bpf_timer_cancel
- bpf_get_func_ip
- bpf_task_pt_regs
- bpf_get_branch_snapshot
- bpf_find_vma
- bpf_loop
- bpf_strncmp
- bpf_kptr_xchg
- bpf_map_lookup_percpu_elem
- bpf_dynptr_from_mem
- bpf_ringbuf_reserve_dynptr
- bpf_ringbuf_submit_dynptr
- bpf_ringbuf_discard_dynptr
- bpf_dynptr_read
- bpf_dynptr_write
- bpf_dynptr_data
eBPF helpers supported for program type cgroup_sockopt:
- bpf_map_lookup_elem
- bpf_map_update_elem
- bpf_map_delete_elem
- bpf_ktime_get_ns
- bpf_get_prandom_u32
- bpf_get_smp_processor_id
- bpf_tail_call
- bpf_get_current_uid_gid
- bpf_perf_event_output
- bpf_get_current_task
- bpf_get_numa_node_id
- bpf_get_current_cgroup_id
- bpf_get_local_storage
- bpf_map_push_elem
- bpf_map_pop_elem
- bpf_map_peek_elem
- bpf_spin_lock
- bpf_spin_unlock
- bpf_tcp_sock
- bpf_sk_storage_get
- bpf_sk_storage_delete
- bpf_probe_read_user
- bpf_probe_read_kernel
- bpf_probe_read_user_str
- bpf_probe_read_kernel_str
- bpf_jiffies64
- bpf_get_netns_cookie
- bpf_ktime_get_boot_ns
- bpf_ringbuf_output
- bpf_ringbuf_reserve
- bpf_ringbuf_submit
- bpf_ringbuf_discard
- bpf_ringbuf_query
- bpf_snprintf_btf
- bpf_per_cpu_ptr
- bpf_this_cpu_ptr
- bpf_get_current_task_btf
- bpf_for_each_map_elem
- bpf_snprintf
- bpf_timer_init
- bpf_timer_set_callback
- bpf_timer_start
- bpf_timer_cancel
- bpf_task_pt_regs
- bpf_loop
- bpf_strncmp
- bpf_get_retval
- bpf_set_retval
- bpf_kptr_xchg
- bpf_map_lookup_percpu_elem
- bpf_dynptr_from_mem
- bpf_ringbuf_reserve_dynptr
- bpf_ringbuf_submit_dynptr
- bpf_ringbuf_discard_dynptr
- bpf_dynptr_read
- bpf_dynptr_write
- bpf_dynptr_data
eBPF helpers supported for program type tracing:
Could not determine which helpers are available
eBPF helpers supported for program type struct_ops:
Could not determine which helpers are available
eBPF helpers supported for program type ext:
Could not determine which helpers are available
eBPF helpers supported for program type lsm:
Could not determine which helpers are available
eBPF helpers supported for program type sk_lookup:- bpf_map_lookup_elem 查看map的元素
- bpf_map_update_elem
- bpf_map_delete_elem
- bpf_ktime_get_ns
- bpf_get_prandom_u32
- bpf_get_smp_processor_id
- bpf_tail_call
- bpf_perf_event_output
- bpf_get_current_task
- bpf_get_numa_node_id
- bpf_sk_release
- bpf_map_push_elem
- bpf_map_pop_elem
- bpf_map_peek_elem
- bpf_spin_lock
- bpf_spin_unlock
- bpf_probe_read_user
- bpf_probe_read_kernel (dst, size, unsafe_ptr)从内核空间内存指针中读取数据,即从地址unsafe_ptr开始读取size大小的字节存储到dst指向的地址,
- bpf_probe_read_user_str
- bpf_probe_read_kernel_str
- bpf_jiffies64
- bpf_sk_assign
- bpf_ktime_get_boot_ns
- bpf_ringbuf_output
- bpf_ringbuf_reserve
- bpf_ringbuf_submit
- bpf_ringbuf_discard
- bpf_ringbuf_query
- bpf_skc_to_tcp6_sock
- bpf_skc_to_tcp_sock
- bpf_skc_to_tcp_timewait_sock
- bpf_skc_to_tcp_request_sock
- bpf_skc_to_udp6_sock
- bpf_snprintf_btf
- bpf_per_cpu_ptr
- bpf_this_cpu_ptr
- bpf_get_current_task_btf
- bpf_ktime_get_coarse_ns
- bpf_for_each_map_elem
- bpf_snprintf
- bpf_timer_init
- bpf_timer_set_callback
- bpf_timer_start
- bpf_timer_cancel
- bpf_task_pt_regs
- bpf_skc_to_unix_sock
- bpf_loop
- bpf_strncmp
- bpf_kptr_xchg
- bpf_map_lookup_percpu_elem
- bpf_skc_to_mptcp_sock
- bpf_dynptr_from_mem
- bpf_ringbuf_reserve_dynptr
- bpf_ringbuf_submit_dynptr
- bpf_ringbuf_discard_dynptr
- bpf_dynptr_read
- bpf_dynptr_write
- bpf_dynptr_data
eBPF helpers supported for program type syscall:
- bpf_map_lookup_elem
- bpf_map_update_elem
- bpf_map_delete_elem
- bpf_probe_read
- bpf_ktime_get_ns
- bpf_get_prandom_u32
- bpf_get_smp_processor_id
- bpf_tail_call
- bpf_get_current_pid_tgid
- bpf_get_current_uid_gid
- bpf_get_current_comm
- bpf_perf_event_read
- bpf_perf_event_output
- bpf_get_stackid
- bpf_get_current_task
- bpf_current_task_under_cgroup
- bpf_get_numa_node_id
- bpf_probe_read_str
- bpf_get_socket_cookie
- bpf_perf_event_read_value
- bpf_get_stack
- bpf_get_current_cgroup_id
- bpf_map_push_elem
- bpf_map_pop_elem
- bpf_map_peek_elem
- bpf_spin_lock
- bpf_spin_unlock
- bpf_sk_storage_get
- bpf_sk_storage_delete
- bpf_send_signal
- bpf_skb_output
- bpf_probe_read_user
- bpf_probe_read_kernel
- bpf_probe_read_user_str
- bpf_probe_read_kernel_str
- bpf_send_signal_thread
- bpf_jiffies64
- bpf_get_ns_current_pid_tgid
- bpf_xdp_output
- bpf_get_current_ancestor_cgroup_id
- bpf_ktime_get_boot_ns
- bpf_ringbuf_output
- bpf_ringbuf_reserve
- bpf_ringbuf_submit
- bpf_ringbuf_discard
- bpf_ringbuf_query
- bpf_skc_to_tcp6_sock
- bpf_skc_to_tcp_sock
- bpf_skc_to_tcp_timewait_sock
- bpf_skc_to_tcp_request_sock
- bpf_skc_to_udp6_sock
- bpf_get_task_stack
- bpf_d_path
- bpf_copy_from_user
- bpf_snprintf_btf
- bpf_per_cpu_ptr
- bpf_this_cpu_ptr
- bpf_task_storage_get
- bpf_task_storage_delete
- bpf_get_current_task_btf
- bpf_sock_from_file
- bpf_for_each_map_elem
- bpf_snprintf
- bpf_sys_bpf
- bpf_btf_find_by_name_kind
- bpf_sys_close
- bpf_timer_init
- bpf_timer_set_callback
- bpf_timer_start
- bpf_timer_cancel
- bpf_get_func_ip
- bpf_task_pt_regs
- bpf_get_branch_snapshot
- bpf_skc_to_unix_sock
- bpf_kallsyms_lookup_name
- bpf_find_vma
- bpf_loop
- bpf_strncmp
- bpf_xdp_get_buff_len
- bpf_copy_from_user_task
- bpf_kptr_xchg
- bpf_map_lookup_percpu_elem
- bpf_skc_to_mptcp_sock
- bpf_dynptr_from_mem
- bpf_ringbuf_reserve_dynptr
- bpf_ringbuf_submit_dynptr
- bpf_ringbuf_discard_dynptr
- bpf_dynptr_read
- bpf_dynptr_write
- bpf_dynptr_data
国内查看评论需要代理~