iovisor / iovisor/bcc

Accessing BPF Maps Dynamically

Open
#1,075 1 comment 0 reactions 0 assignees View on GitHub
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.