我在BPF中有一个XDP的实现,其中我指定了五个要创建的映射,如下所示:
struct bpf_map_def SEC("maps") servers = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(struct ip_key),
.value_size = sizeof(struct dest_info),
.max_entries = MAX_SERVERS,
};
struct bpf_map_def SEC("maps") server_ips = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(struct ip_key),
.value_size = sizeof(struct server_ip_key),
.max_entries = MAX_SERVERS,
};
struct bpf_map_def SEC("maps") client_addrs = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(struct port_key),
.value_size = sizeof(struct client_port_addr),
.max_entries = MAX_CLIENTS,
};
struct bpf_map_def SEC("maps") stoc_port_maps = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(struct port_key),
.value_size = sizeof(struct port_map),
.max_entries = MAX_FLOWS,
};
struct bpf_map_def SEC("maps") ctos_port_maps = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(struct port_key),
.value_size = sizeof(struct port_map),
.max_entries = MAX_FLOWS,
};
但是,无论我做什么,都不会创建servers
映射。当我运行bpftool map show
时,我只得到如下输出:
root@balancer:/xdp# bpftool map list
68: hash name client_addrs flags 0x0
key 8B value 16B max_entries 4096 memlock 98304B
69: hash name ctos_port_maps flags 0x0
key 8B value 20B max_entries 4096 memlock 131072B
70: hash name server_ips flags 0x0
key 8B value 8B max_entries 512 memlock 8192B
73: hash name stoc_port_maps flags 0x0
key 8B value 20B max_entries 4096 memlock 131072B
74: array name xdp_lb_k.rodata flags 0x480
key 4B value 50B max_entries 1 memlock 4096B
frozen
root@balancer:/xdp#
值得注意的是,每个键或值结构都被填充到了八个字节的最接近倍数,并且没有编译或验证错误。我还在docker容器上运行该程序。到目前为止,我已经尝试在代码中移动servers
映射定义,注释掉其他映射定义,只保留servers
定义处于活动状态,将名称更改为其他组合,以及其他一些小更改,但到目前为止都没有效果。
如果您需要我的代码或信息的任何其他部分来更好地分析情况,请告诉我。
附录1:我正在使用Makefile规则编译对象文件:
xdp_lb_kern.o: xdp_lb_kern.c
clang -S
-target bpf
-D __BPF_TRACING__
-I../../libbpf/src
-I../../custom-headers
-Wall
-Wno-unused-value
-Wno-pointer-sign
-Wno-compare-distinct-pointer-types
-O2 -emit-llvm -c -o ${@:.o=.ll} $<
llc -march=bpf -filetype=obj -o $@ ${@:.o=.ll}
然后,在容器的环境中,我使用以下规则加载程序:
load_balancer:
bpftool net detach xdpgeneric dev eth0
rm -f /sys/fs/bpf/xdp_lb
bpftool prog load xdp_lb_kern.o /sys/fs/bpf/xdp_lb
bpftool net attach xdpgeneric pinned /sys/fs/bpf/xdp_lb dev eth0
编译过程生成.o
和.ll
输出文件。.ll
输出文件的开头几行显示了映射定义,如下所示:
; ModuleID = 'xdp_lb_kern.c'
source_filename = "xdp_lb_kern.c"
target datalayout = "e-m:e-p:64:64-i64:64-n32:64-S128"
target triple = "bpf"
%struct.bpf_map_def = type { i32, i32, i32, i32, i32 }
%struct.xdp_md = type { i32, i32, i32, i32, i32 }
%struct.ip_key = type { i32, i32 }
%struct.port_key = type { i16, [3 x i16] }
%struct.ethhdr = type { [6 x i8], [6 x i8], i16 }
%struct.iphdr = type { i8, i8, i16, i16, i16, i8, i8, i16, i32, i32 }
@servers = dso_local global %struct.bpf_map_def { i32 1, i32 8, i32 32, i32 512, i32 0 }, section "maps", align 4
@server_ips = dso_local global %struct.bpf_map_def { i32 1, i32 8, i32 8, i32 512, i32 0 }, section "maps", align 4
@client_addrs = dso_local global %struct.bpf_map_def { i32 1, i32 8, i32 16, i32 4096, i32 0 }, section "maps", align 4
@stoc_port_maps = dso_local global %struct.bpf_map_def { i32 1, i32 8, i32 20, i32 4096, i32 0 }, section "maps", align 4
@ctos_port_maps = dso_local global %struct.bpf_map_def { i32 1, i32 8, i32 20, i32 4096, i32 0 }, section "maps", align 4
@loadbal.____fmt = internal constant [24 x i8] c"balancer got something! 0", align 1
@_license = dso_local global [4 x i8] c"GPL 0", section "license", align 1
@process_packet.____fmt = internal constant [26 x i8] c"it's an ip packet from %x 0", align 1
@llvm.used = appending global [7 x i8*] [i8* getelementptr inbounds ([4 x i8], [4 x i8]* @_license, i32 0, i32 0), i8* bitcast (%struct.bpf_map_def* @client_addrs to i8*), i8* bitcast (%struct.bpf_map_def* @ctos_port_maps to i8*), i8* bitcast (i32 (%struct.xdp_md*)* @loadbal to i8*), i8* bitcast (%struct.bpf_map_def* @server_ips to i8*), i8* bitcast (%struct.bpf_map_def* @servers to i8*), i8* bitcast (%struct.bpf_map_def* @stoc_port_maps to i8*)], section "llvm.metadata"
; Function Attrs: nounwind
define dso_local i32 @loadbal(%struct.xdp_md* nocapture readonly %0) #0 section "xdp" {
%2 = alloca %struct.ip_key, align 4
%3 = alloca %struct.port_key, align 2
%4 = alloca %struct.port_key, align 2
%5 = getelementptr inbounds %struct.xdp_md, %struct.xdp_md* %0, i64 0, i32 1
%6 = load i32, i32* %5, align 4, !tbaa !2
%7 = zext i32 %6 to i64
%8 = inttoptr i64 %7 to i8*
%9 = getelementptr inbounds %struct.xdp_md, %struct.xdp_md* %0, i64 0, i32 0
%10 = load i32, i32* %9, align 4, !tbaa !7
根据评论中的讨论,没有创建映射,因为它实际上没有在eBPF代码中使用(问题中没有提供(。
正如您自己意识到的那样,代码中调用映射的分支实际上是无法访问的。基于此,clang很可能编译出了这部分代码,并且在生成的eBPF字节码中没有使用映射。在准备加载程序时,bpftool(libbpf(会查看哪些映射是必要的,并且只创建程序所需的映射。如果没有程序使用ELF文件中定义的映射,它可能会跳过这些映射。
这里的一个提示是,如果程序有效地使用了映射,那么如果映射丢失,它就无法成功加载:考虑到程序加载,如果需要映射,映射就必须存在。请注意,bpftool prog show
将向您显示程序使用的映射的ID。