user2233706
user2233706

Reputation: 7225

Loop through all elements in BPF_MAP_TYPE_HASH

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

Answers (2)

Niccolo Giraudo
Niccolo Giraudo

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

pchaigno
pchaigno

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

Related Questions