如何在内核态XDP与TC BPF程序之间共享BPF映射(Map)
内核态BPF程序共享映射的实现方案
核心原理
BPF_OBJ_GET是用户态调用的BPF系统命令,内核态BPF程序无需通过该接口获取已固定的映射。你只需要在需要访问映射的另一个BPF程序中,声明完全一致的map定义,且pinning属性同样设置为PIN_GLOBAL_NS,内核加载程序时会自动匹配到已固定在全局命名空间的同路径映射,不会创建新实例。
具体实现代码
1. TC侧原有map定义(无需修改)
struct bpf_elf_map cnt_map __section("maps") = { .type = BPF_MAP_TYPE_ARRAY, .size_key = sizeof(uint32_t), .size_value = sizeof(uint32_t), .pinning = PIN_GLOBAL_NS, .max_elem = 2, };
2. XDP侧的map声明(核心逻辑)
在XDP程序代码中添加完全相同的map定义,内核加载时会自动关联到已固定的映射,不需要额外操作:
// XDP程序中添加如下声明,属性必须和TC侧定义完全一致 struct bpf_elf_map cnt_map __section("maps") = { .type = BPF_MAP_TYPE_ARRAY, .size_key = sizeof(uint32_t), .size_value = sizeof(uint32_t), .pinning = PIN_GLOBAL_NS, .max_elem = 2, }; // 之后可直接调用BPF辅助函数正常读写映射,示例如下: SEC("xdp") int xdp_test_func(struct xdp_md *ctx) { uint32_t key = 0; uint32_t *val = bpf_map_lookup_elem(&cnt_map, &key); if (val) { __sync_fetch_and_add(val, 1); } return XDP_PASS; }
注意事项
- 两个程序中map的
type、size_key、size_value、max_elem四个属性必须完全一致,否则加载时会报错 - 全局命名空间固定的映射默认存放在
/sys/fs/bpf/路径下,默认匹配规则为map变量名一致+pinning属性一致,内核就会自动关联到同一个映射 - 如果需要自定义固定路径,可以使用
pin_path属性指定路径,两个程序的pin_path设置为相同值即可,不依赖变量名匹配
其他可选方案
如果不想依赖固定路径,也可以在加载两个BPF程序时,通过用户态加载工具(如iproute2、libbpf)手动将同一个map fd传递给两个程序,不过你的场景无用户态程序,使用全局固定的方案是最适配的。
内容的提问来源于stack exchange,提问作者Zarrar
相关产品推荐
相关产品推荐

