Reputation: 7225
How can I loop through all the elements in a BPF_MAP_TYPE_HASH? Here is what my map looks like:
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(key_size, sizeof(__u32));
__uint(value_size, sizeof(__u64));
__uint(max_entries, 64);
} field_comb_table SEC(".maps");
I am using the map as a linked list, and hash map was the most convenient data structure available for this. Element ordering is not important. The map contains filters which I will used to determine whether to drop a packet using XDP_DROP
. The keys are between 0 and 63 (max_entries - 1
).
The issue with bpf_for_each_map_elem()
that you can return either 0 or 1 to either continue or stop looping through the map. You can't return XDP_DROP
because it has no meaning within the context of the callback function.
I can go through the entire map starting from key index = 0 and call bpf_map_lookup_elem()
to check if it exists in the map. I would prefer not to go through every possible key, but only through the keys that have been inserted into the map.
Upvotes: 1
Views: 2443
Reputation: 31
You can use the bpf_map_get_next_key
helper. It takes the first available key and return the key of the next element, 0 if your element is the last of the map. With a simple while you can navigate through the map
Upvotes: 1
Reputation: 13133
You can use the third argument of bpf_for_each_map_elem
to pass data back to the caller.
For example:
struct callback_ctx data = {
.ctx = &ctx,
.output = XDP_PASS,
};
bpf_for_each_map_elem(&field_comb_table, check_filter, &data, 0);
return data.output;
with:
struct callback_ctx {
struct xdp_md *ctx;
int output;
};
and:
static __u64
check_filter(struct bpf_map *map, __u32 *key, __u64 *val,
struct callback_ctx *data)
{
struct xdp_md *ctx = data->ctx;
if (run_filter(ctx, key, val))
data->output = XDP_DROP;
return 0;
}
Upvotes: 4