最近在项目中使用bpf更改udp头部信息,出现一个比较怪异问题。相同的代码分别在x86平台(ubuntu18.04 linux-5.4.0-150-generic)和 aarch64(linux-4.19.90)都出现相同现象。
先抛问题:在使用tc指令加载bpf程序时,出现如下错误:
发现在代码里注释掉一条赋值语句,加载就成功,赋值语句如下:
但是把这语句注释掉不是我预期,只能另外想办法解决。
在x86平台的解决方案:
在函数前面__always_inline宏,宏定义如下:
#ifndef __always_inline
#define __always_inline inline __attribute__((always_inline)
#endif
在aarch64平台的解决方案:
因为bpf代码里实现ingress和egress两个方向改udp头部信息,因此在一个c文件里定义了两个SEC,代码如下:
SEC("tc_ingress")
int tc_ingress_func(struct __sk_buff *skb)
{
return do_change_udp_port((u8 *)(long)skb->data, (u8 *)(long)skb->data_end, enINGRESS);
}
SEC("tc_egress")
int tc_egress_func(struct __sk_buff *skb)
{
return do_change_udp_port((u8 *)(long)skb->data, (u8 *)(long)skb->data_end, enEGRESS);
}
使用llvm-objdump -d bpf_port.o查看发现tc_ingress_func和tc_egress_func两个函数的汇编代码并不一样,因此将两个SEC拆开,放在两个C文件里,再用llvm-objdump命令查看两个o文件汇编代码,两个函数的汇编代码相近。使用tc指令也能加载成功。