使用 ip 命令安装 XDP 程序时出错
error when install XDP program using ip command
我正在尝试在我的网络驱动程序上安装 XDP 程序,但我收到错误消息 ELF 在指向第 4 节的条目 0 中包含非 {map,call} 相关的 relo 数据!编译器错误?!获取 program/map!
时出错
我正在尝试的代码 运行 :
#define KBUILD_MODNAME "filter"
#include <arpa/inet.h>
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/in.h>
#include <linux/udp.h>
static int (*bpf_trace_printk)(const char *fmt,...) = (void *)BPF_FUNC_trace_printk;
int udpfilter(struct xdp_md *ctx) {
bpf_trace_printk("got a packet\n");
void *data = (void *)(long)ctx->data;
void *data_end = (void *)(long)ctx->data_end;
struct ethhdr *eth = data;
if ((void*)eth + sizeof(*eth) <= data_end) {
struct iphdr *ip = data + sizeof(*eth);
if ((void*)ip + sizeof(*ip) <= data_end) {
if (ip->protocol == IPPROTO_UDP) {
struct udphdr *udp = (void*)ip + sizeof(*ip);
if ((void*)udp + sizeof(*udp) <= data_end) {
if (udp->dest == ntohs(7999)) {
bpf_trace_printk("udp port 7999\n");
udp->dest = ntohs(7998);
}
}
}
}
}
return XDP_PASS;
}
编译命令:clang -O2 -g -Wall -target bpf -c filter.c -o filter.o 就可以了!
和我用来安装的命令:ip link set enp0s3 xdpgeneric obj filter.o 然后我得到上面的错误。
我不确定这条消息是什么意思,我是不是漏掉了什么?
获取错误 program/map!
您不必在编译时包含其他文件中提到的这个目录。此错误是由于 ip
未在 ELF 文件中找到预期的部分。参见 ip-link
man page:
If no section
option is passed, then the default section name ("prog") will be assumed, otherwise the provided section name will be used.
所以你有两个解决方案:
将函数放在 prog
ELF 部分:
__attribute__((section("prog"), used))
int udpfilter(struct xdp_md *ctx) {
[...]
}
加载程序时使用section
选项。默认情况下,clang 将您的代码放入 .text
部分:
# ip link set enp0s3 xdpgeneric obj filter.o sec .text
ELF 在指向第 4 节的条目 0 中包含与{map,call} 无关的 relo 数据!编译器错误?!
如前所述,这是您使用 bpf_trace_prink()
造成的。您不能简单地将格式字符串直接传递给帮助程序,因为 clang 会将其放置在特定的 ELF 部分并将 at 标记为重定位数据,但加载程序(在本例中为 ip
)将不知道如何处理它.当然,您必须至少向它传递第二个参数,以提供格式字符串的大小。有关详细信息,请参阅 its documentation。
请注意,我们经常可以看到像这样为该助手定义的包装器:
#define bpf_printk(fmt, ...) \
({ \
char ____fmt[] = fmt; \
bpf_trace_printk(____fmt, sizeof(____fmt), \
##__VA_ARGS__); \
})
字符串的声明方式不会触发任何重定位,之后使用起来更方便,你可以直接bpf_printk("got a packet\n");
。
我正在尝试在我的网络驱动程序上安装 XDP 程序,但我收到错误消息 ELF 在指向第 4 节的条目 0 中包含非 {map,call} 相关的 relo 数据!编译器错误?!获取 program/map!
时出错我正在尝试的代码 运行 :
#define KBUILD_MODNAME "filter"
#include <arpa/inet.h>
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/in.h>
#include <linux/udp.h>
static int (*bpf_trace_printk)(const char *fmt,...) = (void *)BPF_FUNC_trace_printk;
int udpfilter(struct xdp_md *ctx) {
bpf_trace_printk("got a packet\n");
void *data = (void *)(long)ctx->data;
void *data_end = (void *)(long)ctx->data_end;
struct ethhdr *eth = data;
if ((void*)eth + sizeof(*eth) <= data_end) {
struct iphdr *ip = data + sizeof(*eth);
if ((void*)ip + sizeof(*ip) <= data_end) {
if (ip->protocol == IPPROTO_UDP) {
struct udphdr *udp = (void*)ip + sizeof(*ip);
if ((void*)udp + sizeof(*udp) <= data_end) {
if (udp->dest == ntohs(7999)) {
bpf_trace_printk("udp port 7999\n");
udp->dest = ntohs(7998);
}
}
}
}
}
return XDP_PASS;
}
编译命令:clang -O2 -g -Wall -target bpf -c filter.c -o filter.o 就可以了!
和我用来安装的命令:ip link set enp0s3 xdpgeneric obj filter.o 然后我得到上面的错误。
我不确定这条消息是什么意思,我是不是漏掉了什么?
获取错误 program/map!
您不必在编译时包含其他文件中提到的这个目录。此错误是由于 ip
未在 ELF 文件中找到预期的部分。参见 ip-link
man page:
If no
section
option is passed, then the default section name ("prog") will be assumed, otherwise the provided section name will be used.
所以你有两个解决方案:
将函数放在
prog
ELF 部分:__attribute__((section("prog"), used)) int udpfilter(struct xdp_md *ctx) { [...] }
加载程序时使用
section
选项。默认情况下,clang 将您的代码放入.text
部分:# ip link set enp0s3 xdpgeneric obj filter.o sec .text
ELF 在指向第 4 节的条目 0 中包含与{map,call} 无关的 relo 数据!编译器错误?!
如前所述,这是您使用 bpf_trace_prink()
造成的。您不能简单地将格式字符串直接传递给帮助程序,因为 clang 会将其放置在特定的 ELF 部分并将 at 标记为重定位数据,但加载程序(在本例中为 ip
)将不知道如何处理它.当然,您必须至少向它传递第二个参数,以提供格式字符串的大小。有关详细信息,请参阅 its documentation。
请注意,我们经常可以看到像这样为该助手定义的包装器:
#define bpf_printk(fmt, ...) \
({ \
char ____fmt[] = fmt; \
bpf_trace_printk(____fmt, sizeof(____fmt), \
##__VA_ARGS__); \
})
字符串的声明方式不会触发任何重定位,之后使用起来更方便,你可以直接bpf_printk("got a packet\n");
。