Accessing BPF Maps Dynamically
- Dominant language
- C
- Stars
- 22.7k
- Forks
- 4.1k
- Avg merge
- 10d 4h
- Merged PRs (30d)
- 3
Description
Hi folks,
I'm looking for ways to access BPF Maps in a dynamic way. My understanding so far is that this is not possible with the current implementation. Here is what it could look like in BPF:
```C
#include
#include
BPF_TABLE("array", int, int, t1, 1);
BPF_TABLE("array", int, int, t2, 1);
typedef struct {
void *table;
} stream;
typedef struct {
stream *stream;
} container;
static inline void bpf_read_from_index(void *table, int index, void **object) {
*object = bpf_map_lookup_elem_(bpf_pseudo_fd(1, *(u64*)table), &index);
}
static inline void stream_get(stream *s, int index, void **result) {
bpf_read_from_index(s->table, index, result);
}
int socket_fn(struct __sk_buff *skb) {
int index = 0;
int *x = NULL, *y = NULL;
container c1 = {0};
container c2 = {0};
stream s1 = {0};
stream s2 = {0};
u64 s1_fd = 3; // based on bpf_create_map()
u64 s2_fd = 4;
c1.stream = &s1;
c2.stream = &s2;
c1.stream->table = (void*)&s1_fd;
c2.stream->table = (void*)&s2_fd;
stream_get(c1.stream, index, (void**)&x);
stream_get(c2.stream, index, (void**)&y);
return 0;
}
```
However, this results in the following error:
> LLVM ERROR: Cannot select: intrinsic %llvm.bpf.pseudo
The simplest workaround would be to implement a lookup based on the file descriptors, e.g.:
```C
if (*table == 3) map.lookup(&key);
```
---
BCC and BPF go through the following steps in order to allow access to a map:
map.lookup(&key)
gets rewritten to:
bpf_map_lookup_elem(bpf_pseudo_fd(1, 3), &key)
where `bpf_pseudo_fd()` is a special function call that emits "assembler" code. The first parameter is a flag, `1` means we are trying to access a map given a file descriptor in the second parameter which originates from `bpf_create_map()`.
This BPF pseudo instruction is later picked up by the BPF verifier, where the static file descriptor is turned into a pointer to the actual map.
I see two issues preventing a dynamic access to BPF maps:
1. My interpretation of the above error message is that the pseudo instruction is considered as "load immediate," so the given file descriptor must be a constant. Therefore, passing in a pointer will not work since it is not a constant value.
2. The verifier translates a map file descriptor into a map pointer, but this is still a static translation, which could be considered to be at compile time.
So, if the above code snippet should work, both the pseudo instruction and the verifier would need to be changed.
I would be happy if someone could confirm that this is how the process works, and that my conclusion is correct that accessing a map dynamically is currently not possible. I would also be interested in your opinion about a possible implementation -- or if you think that this should NOT be implemented, for example, because it would not make sense given the constraints of BPF.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by tracing bpf_pseudo_fd(1, fd), bpf_map_lookup_elem_, and the verifier handling described in the issue. No files or tests are named; done would require a confirmed feasibility and scope for dynamic map access, or an agreed implementation path covering the pseudo instruction and verifier.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, linux
- Domain
- compilers, operating-systems
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100