eBPF中const char*作为bpf_map键无法取值的原因咨询
eBPF哈希嵌套映射查找问题:const char* vs char[192] key的差异分析
问题现象
在使用bpf_map_lookup_elem从BPF_MAP_TYPE_HASH_OF_MAPS类型的outer_of_maglev映射中取值时:
- 传入
const char*类型的key(内容与char[192]的key完全一致),返回NULL,无法获取映射值; - 传入
char[192]类型的key,能正确获取目标值。
相关eBPF代码
struct { __uint(type, BPF_MAP_TYPE_HASH_OF_MAPS); __uint(key_size, CLUSTER_NAME_MAX_LEN); // CLUSTER_NAME_MAX_LEN = 192 __uint(value_size, sizeof(__u32)); __uint(max_entries, MAP_SIZE_OF_CLUSTER); __uint(map_flags, BPF_F_NO_PREALLOC); __array(values, struct inner_of_maglev); }outer_of_maglev SEC(".maps"); static inline void *loadbalance(struct cluster_endpoints *eps, const char* name,ctx_buff_t *ctx) { if (!eps || eps->ep_num == 0) return NULL; __u32 *res1; __u32 *res2; char c_name[192] = "outbound|5000||helloworld.default.svc.cluster.local"; res1 = (__u32 *)bpf_map_lookup_elem(&outer_of_maglev,name); res2 = (__u32 *)bpf_map_lookup_elem(&outer_of_maglev,c_name); if (res1) { BPF_LOG(INFO, CLUSTER, "loadbalance_maglev test res %u\n",res); } return NULL; }
核心差异与问题原因
两种key类型的本质差异
char[192]固定长度数组:内存中是连续的192字节空间,初始化时如果字符串长度不足192,剩余字节会被自动填充为\0(空字符),整个key的内存内容是确定且完整的192字节。const char*指针:仅指向字符串的起始地址,eBPF程序无法确定指针指向的内存后续内容。当bpf_map_lookup_elem按照key_size=192读取key时,会从指针指向的地址开始读取192字节——如果原字符串长度小于192,超出字符串末尾的部分是栈上的未初始化垃圾数据,而非预期的\0。
现象产生的根本原因
eBPF哈希映射(包括哈希嵌套映射)的查找逻辑是基于key_size指定的全部字节计算哈希值,只有当传入的key与映射中存储的key的每一个字节都完全匹配时,才能找到对应的值:
- 存入映射时的key大概率是用
char[192]类型写入的,整个192字节中,字符串部分是业务内容,剩余部分补\0; - 传入
const char*类型的key时,读取的192字节中,字符串末尾之后的部分是不确定的垃圾数据,与存入时的key字节内容不匹配,导致哈希值计算错误,最终返回NULL; - 而
char[192]类型的key,内存内容与存入时的key完全一致,哈希匹配成功,因此能正确查到值。
解决方案
如果必须使用const char*类型的key,需要先将其内容复制到一个固定192字节的数组中,确保剩余字节补\0,再用这个数组作为key传入bpf_map_lookup_elem,示例代码如下:
char fixed_key[192] = {0}; __builtin_memcpy(fixed_key, name, sizeof(fixed_key)-1); // 避免溢出,留一个字节补\0 res1 = (__u32 *)bpf_map_lookup_elem(&outer_of_maglev, fixed_key);
内容的提问来源于stack exchange,提问作者bfforever
相关产品推荐
相关产品推荐

