函数调用栈
以xdp SKB模式为例,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| --> bpf_prog_run_generic_xdp --> --> bpf_prog_run_xdp --> --> --> u32 act = __bpf_prog_run(prog, xdp, BPF_DISPATCHER_FUNC(xdp)); 展开BPF_DISPATCHER_FUNC(xdp), 相当于 u32 act = __bpf_prog_run(prog, xdp, bpf_dispatcher_xdp_func)); --> --> --> --> ret = dfunc(ctx, prog->insnsi, prog->bpf_func); 这里的dfun是`__bpf_prog_run`的第三个参数,因此相当于 ret = bpf_dispatcher_xdp_func(ctx, prog->insnsi, prog->bpf_func); <== 这里的第三个函数就是我们之前提到的,当bpf程序被加载时候,在bpf_prog结构体保存的bpf_func。 --> --> --> --> --> return __BPF_DISPATCHER_CALL(name); <== 根据bpf_dispatcher_xdp_func的定义 展开__BPF_DISPATCHER_CALL,相当于 bpf_func(ctx, insnsi) <=== **这里很有意思**,bpf_fun, ctx, insnsi分别代表bpf_dispatcher_xdp_func的三个函数入口参数, 根据顺序依次为 第三个,第一个,第二个,按照这个顺序展开 prog->bpf_func(ctx, prog->insnsi); <== 至此,就把我们上面一节里总结的`prog->bpf_func`这个函数指针用上了。 最终这个函数根据不同stacksize入口函数的包装,调用到 --> --> --> --> --> --> ___bpf_prog_run(ctx, prog->insnsi)
|
BPF_DISPATCHER_FUNC
BPF_DISPATCHER_FUNC(xdp)相当于:bpf_dispatcher_xdp_func
1
| 1270 #define BPF_DISPATCHER_FUNC(name) bpf_dispatcher_##name##_func
|
bpf_dispatcher_xdp_func
的定义
bpf_dispatcher_xdp_func
这个函数直接用grep命令是找不到函数定义的。
这个函数的定义是通过宏DEFINE_BPF_DISPATCHER
实现的。
1 2 3 4 5 6 7 8 9 10 11 12 13
| 1519 DEFINE_BPF_DISPATCHER(xdp) 1250 #define DEFINE_BPF_DISPATCHER(name) \ 1251 __BPF_DISPATCHER_SC(name); \ 1252 noinline __nocfi unsigned int bpf_dispatcher_##name##_func( \ <== 此函数相当于bpf_dispatcher_xdp(ctx, prog->insnsi, prog->bpf_func) 1253 const void *ctx, \ 1254 const struct bpf_insn *insnsi, \ 1255 bpf_func_t bpf_func) \ 1256 { \ 1257 return __BPF_DISPATCHER_CALL(name); \ <== 此处相当于 prog->bpf_func, 参数只在static call场景下有用(ctx, prog->insnsi) 1258 } \ 1259 EXPORT_SYMBOL(bpf_dispatcher_##name##_func); \ 1260 struct bpf_dispatcher bpf_dispatcher_##name = \ 1261 BPF_DISPATCHER_INIT(bpf_dispatcher_##name);
|
__BPF_DISPATCHER_CALL
为了便于理解,我们使用非static call的场景
1
| 1232 #define __BPF_DISPATCHER_CALL(name) bpf_func(ctx, insnsi)
|
至于static call场景,目前没有遇到,看起来跟xdp管理不大,暂时先不分析了 :(
1 2
| 1223 #define __BPF_DISPATCHER_CALL(name) \ 1224 static_call(bpf_dispatcher_##name##_call)(ctx, insnsi, bpf_func)
|