关于bpf:eBPF-HashMap-与-padding-的坑
前言上一篇文章《ebpf-go 初体验》中,咱们提到了一个小插曲,就是当 map 的 key 这样写的时候 struct tuple key = {ip, bpf_ntohs(sport)},map 的 key 看起来会反复,有些令人惊讶,于是我用另外一台机器 B 测了下(内核 6.6,clang 14.0.0)。发现了报错:"invalid indirect read from stack R2 off",顺藤摸瓜找到了这篇文档1 ,才反馈过去:咱们的 struct tuple 是不规整的,须要 padding,而不同的架构/编译器对 padding 的解决又是一样的,从而导致了不同的后果。 那么这个 padding 到底是怎么导致看起来反复的 key 的呢?这就得看看 ebpf 的 hashmap 的实现原理了。 ebpf hashmap 外围原理bpf 的 map 的操作都在 syscall2 中,从其中的 map_update_elem 下手,找到 bpf_map_update_value,而后是 map->ops->map_update_elem,找到 hashmap 对应的实现就在此3(per cpu4 的咱们先不看),外围如下: static long htab_map_update_elem(struct bpf_map *map, void *key, void *value, u64 map_flags){ hash = htab_map_hash(key, key_size, htab->hashrnd); b = __select_bucket(htab, hash); head = &b->head; l_old = lookup_elem_raw(head, hash, key, key_size); l_new = alloc_htab_elem(htab, key, value, key_size, hash, false, false, l_old); /* add new element to the head of the list, so that * concurrent search will find it before old elem */ hlist_nulls_add_head_rcu(&l_new->hash_node, head);}如果你学过 Java 就晓得:一个 Objec 要能成为 hashmap 的 key,必须得有 hashcode 和 equals 办法。这也是hashmap 的外围,与语言无关。那么下面的代码如何体现的呢? ...