Skip to content

Commit

Permalink
new(driver/modern_bpf,userspace/libpman): support multiple programs f…
Browse files Browse the repository at this point in the history
…or each event.

Try to inject each of them until success.
This allows us to inject `bpf_loop` sendmmsg and recvmmsg programs where supported,
and fallback at just sending first message where it isn't.

Signed-off-by: Federico Di Pierro <[email protected]>
  • Loading branch information
FedeDP committed Jan 24, 2025
1 parent 6c46ed3 commit aa354b6
Show file tree
Hide file tree
Showing 10 changed files with 526 additions and 363 deletions.
3 changes: 0 additions & 3 deletions driver/modern_bpf/helpers/base/shared_size.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@
/* Maximum number of `iovec` structures that we can analyze. */
#define MAX_IOVCNT 32

/* Maximum number of supported sendmmsg/recvmmsg messages */
#define MAX_SENDMMSG_RECVMMSG_SIZE 8

/* Maximum number of `pollfd` structures that we can analyze. */
#define MAX_POLLFD 16

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,17 +159,60 @@ int BPF_PROG(recvmmsg_x, struct pt_regs *regs, long ret) {
.ctx = ctx,
};

// We can't use bpf_loop() helper since the below check triggers a verifier failure:
// see
// https://lore.kernel.org/bpf/CAGQdkDt9zyQwr5JyftXqL=OLKscNcqUtEteY4hvOkx2S4GdEkQ@mail.gmail.com/T/#u
/*if(bpf_core_enum_value_exists(enum bpf_func_id, BPF_FUNC_loop)) {
uint32_t nr_loops = ret < 1024 ? ret : 1024;
bpf_loop(nr_loops, handle_exit, &data, 0);
} else {*/
for(int i = 0; i < ret && i < MAX_SENDMMSG_RECVMMSG_SIZE; i++) {
handle_exit(i, &data);
uint32_t nr_loops = ret < 1024 ? ret : 1024;
bpf_loop(nr_loops, handle_exit, &data, 0);

return 0;
}

SEC("tp_btf/sys_exit")
int BPF_PROG(recvmmsg_old_x, struct pt_regs *regs, long ret) {
if(ret <= 0) {
unsigned long fd = 0;
struct auxiliary_map *auxmap = auxmap__get();
if(!auxmap) {
return 0;
}

auxmap__preload_event_header(auxmap, PPME_SOCKET_RECVMMSG_X);

/* Parameter 1: res (type: PT_ERRNO) */
auxmap__store_s64_param(auxmap, ret);

/* Parameter 2: fd (type: PT_FD) */
extract__network_args(&fd, 1, regs);
auxmap__store_s64_param(auxmap, (int64_t)(int32_t)fd);

/* Parameter 3: size (type: PT_UINT32) */
auxmap__store_u32_param(auxmap, 0);

/* Parameter 4: data (type: PT_BYTEBUF) */
auxmap__store_empty_param(auxmap);

/* Parameter 5: tuple (type: PT_SOCKTUPLE) */
auxmap__store_empty_param(auxmap);

/* Parameter 6: msg_control (type: PT_BYTEBUF) */
auxmap__store_empty_param(auxmap);

auxmap__finalize_event_header(auxmap);

auxmap__submit_event(auxmap);
return 0;
}
//}

/* Collect parameters at the beginning to manage socketcalls */
unsigned long args[2];
extract__network_args(args, 2, regs);
recvmmsg_data_t data = {
.fd = args[0],
.mmh = (struct mmsghdr *)args[1],
.regs = regs,
.ctx = ctx,
};

// Send only first message
handle_exit(0, &data);

return 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,17 +152,57 @@ int BPF_PROG(sendmmsg_x, struct pt_regs *regs, long ret) {
.ctx = ctx,
};

// We can't use bpf_loop() helper since the below check triggers a verifier failure:
// see
// https://lore.kernel.org/bpf/CAGQdkDt9zyQwr5JyftXqL=OLKscNcqUtEteY4hvOkx2S4GdEkQ@mail.gmail.com/T/#u
/*if(bpf_core_enum_value_exists(enum bpf_func_id, BPF_FUNC_loop)) {
uint32_t nr_loops = ret < 1024 ? ret : 1024;
bpf_loop(nr_loops, handle_exit, &data, 0);
} else {*/
for(int i = 0; i < ret && i < MAX_SENDMMSG_RECVMMSG_SIZE; i++) {
handle_exit(i, &data);
uint32_t nr_loops = ret < 1024 ? ret : 1024;
bpf_loop(nr_loops, handle_exit, &data, 0);

return 0;
}

SEC("tp_btf/sys_exit")
int BPF_PROG(sendmmsg_old_x, struct pt_regs *regs, long ret) {
if(ret <= 0) {
unsigned long fd = 0;
struct auxiliary_map *auxmap = auxmap__get();
if(!auxmap) {
return 0;
}

auxmap__preload_event_header(auxmap, PPME_SOCKET_SENDMMSG_X);

/* Parameter 1: res (type: PT_ERRNO) */
auxmap__store_s64_param(auxmap, ret);

/* Parameter 2: fd (type: PT_FD) */
extract__network_args(&fd, 1, regs);
auxmap__store_s64_param(auxmap, (int64_t)(int32_t)fd);

/* Parameter 3: size (type: PT_UINT32) */
auxmap__store_u32_param(auxmap, 0);

/* Parameter 4: data (type: PT_BYTEBUF) */
auxmap__store_empty_param(auxmap);

/* Parameter 5: tuple (type: PT_SOCKTUPLE) */
auxmap__store_empty_param(auxmap);

auxmap__finalize_event_header(auxmap);

auxmap__submit_event(auxmap);
return 0;
}
//}

/* Collect parameters at the beginning to manage socketcalls */
unsigned long args[2];
extract__network_args(args, 2, regs);
sendmmsg_exit_t data = {
.fd = args[0],
.mmh = (struct mmsghdr *)args[1],
.regs = regs,
.ctx = ctx,
};

// Only first message
handle_exit(0, &data);

return 0;
}
Expand Down
1 change: 1 addition & 0 deletions userspace/libpman/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ add_library(
src/configuration.c
src/state.c
src/sc_set.c
src/events_prog_names.c
)

target_include_directories(
Expand Down
8 changes: 8 additions & 0 deletions userspace/libpman/include/libpman.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,14 @@ bool pman_check_support();
*/
int pman_open_probe(void);

/**
* @brief Prepares the bpf skeleton object checking if
* it satisfies each events_prog_name feature requirements for each prog.
*
* @return `0` on success, `errno` in case of error.
*/
int pman_prepare_progs_before_loading(void);

/**
* @brief Load into the kernel all the programs and maps
* contained into the skeleton.
Expand Down
Loading

0 comments on commit aa354b6

Please sign in to comment.