Skip to content

Commit

Permalink
samples: bpf: Refactor kprobe tracing programs with libbpf
Browse files Browse the repository at this point in the history
For the problem of increasing fragmentation of the bpf loader programs,
instead of using bpf_loader.o, which is used in samples/bpf, this
commit refactors the existing kprobe tracing programs with libbbpf
bpf loader.

    - For kprobe events pointing to system calls, the SYSCALL() macro in
    trace_common.h was used.
    - Adding a kprobe event and attaching a bpf program to it was done
    through bpf_program_attach().
    - Instead of using the existing BPF MAP definition, MAP definition
    has been refactored with the new BTF-defined MAP format.

Signed-off-by: Daniel T. Lee <[email protected]>
Signed-off-by: Alexei Starovoitov <[email protected]>
Link: https://lore.kernel.org/bpf/[email protected]
  • Loading branch information
DanielTimLee authored and Alexei Starovoitov committed Aug 25, 2020
1 parent 35a8b6d commit 3677d0a
Show file tree
Hide file tree
Showing 11 changed files with 272 additions and 118 deletions.
10 changes: 5 additions & 5 deletions samples/bpf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,11 @@ tracex4-objs := tracex4_user.o
tracex5-objs := tracex5_user.o $(TRACE_HELPERS)
tracex6-objs := tracex6_user.o
tracex7-objs := tracex7_user.o
test_probe_write_user-objs := bpf_load.o test_probe_write_user_user.o
trace_output-objs := bpf_load.o trace_output_user.o $(TRACE_HELPERS)
lathist-objs := bpf_load.o lathist_user.o
test_probe_write_user-objs := test_probe_write_user_user.o
trace_output-objs := trace_output_user.o $(TRACE_HELPERS)
lathist-objs := lathist_user.o
offwaketime-objs := bpf_load.o offwaketime_user.o $(TRACE_HELPERS)
spintest-objs := bpf_load.o spintest_user.o $(TRACE_HELPERS)
spintest-objs := spintest_user.o $(TRACE_HELPERS)
map_perf_test-objs := map_perf_test_user.o
test_overhead-objs := bpf_load.o test_overhead_user.o
test_cgrp2_array_pin-objs := test_cgrp2_array_pin.o
Expand All @@ -86,7 +86,7 @@ xdp1-objs := xdp1_user.o
# reuse xdp1 source intentionally
xdp2-objs := xdp1_user.o
xdp_router_ipv4-objs := xdp_router_ipv4_user.o
test_current_task_under_cgroup-objs := bpf_load.o $(CGROUP_HELPERS) \
test_current_task_under_cgroup-objs := $(CGROUP_HELPERS) \
test_current_task_under_cgroup_user.o
trace_event-objs := trace_event_user.o $(TRACE_HELPERS)
sampleip-objs := sampleip_user.o $(TRACE_HELPERS)
Expand Down
24 changes: 12 additions & 12 deletions samples/bpf/lathist_kern.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
* trace_preempt_[on|off] tracepoints hooks is not supported.
*/

struct bpf_map_def SEC("maps") my_map = {
.type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(int),
.value_size = sizeof(u64),
.max_entries = MAX_CPU,
};
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__type(key, int);
__type(value, u64);
__uint(max_entries, MAX_CPU);
} my_map SEC(".maps");

SEC("kprobe/trace_preempt_off")
int bpf_prog1(struct pt_regs *ctx)
Expand Down Expand Up @@ -61,12 +61,12 @@ static unsigned int log2l(unsigned long v)
return log2(v);
}

struct bpf_map_def SEC("maps") my_lat = {
.type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(int),
.value_size = sizeof(long),
.max_entries = MAX_CPU * MAX_ENTRIES,
};
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__type(key, int);
__type(value, long);
__uint(max_entries, MAX_CPU * MAX_ENTRIES);
} my_lat SEC(".maps");

SEC("kprobe/trace_preempt_on")
int bpf_prog2(struct pt_regs *ctx)
Expand Down
42 changes: 36 additions & 6 deletions samples/bpf/lathist_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <linux/bpf.h>
#include <bpf/libbpf.h>
#include <bpf/bpf.h>
#include "bpf_load.h"

#define MAX_ENTRIES 20
#define MAX_CPU 4
Expand Down Expand Up @@ -81,20 +80,51 @@ static void get_data(int fd)

int main(int argc, char **argv)
{
struct bpf_link *links[2];
struct bpf_program *prog;
struct bpf_object *obj;
char filename[256];
int map_fd, i = 0;

snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
obj = bpf_object__open_file(filename, NULL);
if (libbpf_get_error(obj)) {
fprintf(stderr, "ERROR: opening BPF object file failed\n");
return 0;
}

/* load BPF program */
if (bpf_object__load(obj)) {
fprintf(stderr, "ERROR: loading BPF object file failed\n");
goto cleanup;
}

if (load_bpf_file(filename)) {
printf("%s", bpf_log_buf);
return 1;
map_fd = bpf_object__find_map_fd_by_name(obj, "my_lat");
if (map_fd < 0) {
fprintf(stderr, "ERROR: finding a map in obj file failed\n");
goto cleanup;
}

bpf_object__for_each_program(prog, obj) {
links[i] = bpf_program__attach(prog);
if (libbpf_get_error(links[i])) {
fprintf(stderr, "ERROR: bpf_program__attach failed\n");
links[i] = NULL;
goto cleanup;
}
i++;
}

while (1) {
get_data(map_fd[1]);
get_data(map_fd);
print_hist();
sleep(5);
}

cleanup:
for (i--; i >= 0; i--)
bpf_link__destroy(links[i]);

bpf_object__close(obj);
return 0;
}
36 changes: 18 additions & 18 deletions samples/bpf/spintest_kern.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,25 @@
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>

struct bpf_map_def SEC("maps") my_map = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(long),
.value_size = sizeof(long),
.max_entries = 1024,
};
struct bpf_map_def SEC("maps") my_map2 = {
.type = BPF_MAP_TYPE_PERCPU_HASH,
.key_size = sizeof(long),
.value_size = sizeof(long),
.max_entries = 1024,
};
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, long);
__type(value, long);
__uint(max_entries, 1024);
} my_map SEC(".maps");
struct {
__uint(type, BPF_MAP_TYPE_PERCPU_HASH);
__uint(key_size, sizeof(long));
__uint(value_size, sizeof(long));
__uint(max_entries, 1024);
} my_map2 SEC(".maps");

struct bpf_map_def SEC("maps") stackmap = {
.type = BPF_MAP_TYPE_STACK_TRACE,
.key_size = sizeof(u32),
.value_size = PERF_MAX_STACK_DEPTH * sizeof(u64),
.max_entries = 10000,
};
struct {
__uint(type, BPF_MAP_TYPE_STACK_TRACE);
__uint(key_size, sizeof(u32));
__uint(value_size, PERF_MAX_STACK_DEPTH * sizeof(u64));
__uint(max_entries, 10000);
} stackmap SEC(".maps");

#define PROG(foo) \
int foo(struct pt_regs *ctx) \
Expand Down
68 changes: 55 additions & 13 deletions samples/bpf/spintest_user.c
Original file line number Diff line number Diff line change
@@ -1,40 +1,77 @@
// SPDX-License-Identifier: GPL-2.0
#include <stdio.h>
#include <unistd.h>
#include <linux/bpf.h>
#include <string.h>
#include <assert.h>
#include <sys/resource.h>
#include <bpf/libbpf.h>
#include "bpf_load.h"
#include <bpf/bpf.h>
#include "trace_helpers.h"

int main(int ac, char **argv)
{
struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
char filename[256], symbol[256];
struct bpf_object *obj = NULL;
struct bpf_link *links[20];
long key, next_key, value;
char filename[256];
struct bpf_program *prog;
int map_fd, i, j = 0;
const char *title;
struct ksym *sym;
int i;

snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
setrlimit(RLIMIT_MEMLOCK, &r);
if (setrlimit(RLIMIT_MEMLOCK, &r)) {
perror("setrlimit(RLIMIT_MEMLOCK)");
return 1;
}

if (load_kallsyms()) {
printf("failed to process /proc/kallsyms\n");
return 2;
}

if (load_bpf_file(filename)) {
printf("%s", bpf_log_buf);
return 1;
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
obj = bpf_object__open_file(filename, NULL);
if (libbpf_get_error(obj)) {
fprintf(stderr, "ERROR: opening BPF object file failed\n");
obj = NULL;
goto cleanup;
}

/* load BPF program */
if (bpf_object__load(obj)) {
fprintf(stderr, "ERROR: loading BPF object file failed\n");
goto cleanup;
}

map_fd = bpf_object__find_map_fd_by_name(obj, "my_map");
if (map_fd < 0) {
fprintf(stderr, "ERROR: finding a map in obj file failed\n");
goto cleanup;
}

bpf_object__for_each_program(prog, obj) {
title = bpf_program__title(prog, false);
if (sscanf(title, "kprobe/%s", symbol) != 1)
continue;

/* Attach prog only when symbol exists */
if (ksym_get_addr(symbol)) {
links[j] = bpf_program__attach(prog);
if (libbpf_get_error(links[j])) {
fprintf(stderr, "bpf_program__attach failed\n");
links[j] = NULL;
goto cleanup;
}
j++;
}
}

for (i = 0; i < 5; i++) {
key = 0;
printf("kprobing funcs:");
while (bpf_map_get_next_key(map_fd[0], &key, &next_key) == 0) {
bpf_map_lookup_elem(map_fd[0], &next_key, &value);
while (bpf_map_get_next_key(map_fd, &key, &next_key) == 0) {
bpf_map_lookup_elem(map_fd, &next_key, &value);
assert(next_key == value);
sym = ksym_search(value);
key = next_key;
Expand All @@ -48,10 +85,15 @@ int main(int ac, char **argv)
if (key)
printf("\n");
key = 0;
while (bpf_map_get_next_key(map_fd[0], &key, &next_key) == 0)
bpf_map_delete_elem(map_fd[0], &next_key);
while (bpf_map_get_next_key(map_fd, &key, &next_key) == 0)
bpf_map_delete_elem(map_fd, &next_key);
sleep(1);
}

cleanup:
for (j--; j >= 0; j--)
bpf_link__destroy(links[j]);

bpf_object__close(obj);
return 0;
}
27 changes: 14 additions & 13 deletions samples/bpf/test_current_task_under_cgroup_kern.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,24 @@
#include <linux/version.h>
#include <bpf/bpf_helpers.h>
#include <uapi/linux/utsname.h>
#include "trace_common.h"

struct bpf_map_def SEC("maps") cgroup_map = {
.type = BPF_MAP_TYPE_CGROUP_ARRAY,
.key_size = sizeof(u32),
.value_size = sizeof(u32),
.max_entries = 1,
};
struct {
__uint(type, BPF_MAP_TYPE_CGROUP_ARRAY);
__uint(key_size, sizeof(u32));
__uint(value_size, sizeof(u32));
__uint(max_entries, 1);
} cgroup_map SEC(".maps");

struct bpf_map_def SEC("maps") perf_map = {
.type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(u32),
.value_size = sizeof(u64),
.max_entries = 1,
};
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__type(key, u32);
__type(value, u64);
__uint(max_entries, 1);
} perf_map SEC(".maps");

/* Writes the last PID that called sync to a map at index 0 */
SEC("kprobe/sys_sync")
SEC("kprobe/" SYSCALL(sys_sync))
int bpf_prog1(struct pt_regs *ctx)
{
u64 pid = bpf_get_current_pid_tgid();
Expand Down
52 changes: 42 additions & 10 deletions samples/bpf/test_current_task_under_cgroup_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,54 @@

#define _GNU_SOURCE
#include <stdio.h>
#include <linux/bpf.h>
#include <unistd.h>
#include <bpf/bpf.h>
#include "bpf_load.h"
#include <bpf/libbpf.h>
#include "cgroup_helpers.h"

#define CGROUP_PATH "/my-cgroup"

int main(int argc, char **argv)
{
pid_t remote_pid, local_pid = getpid();
int cg2, idx = 0, rc = 0;
struct bpf_link *link = NULL;
struct bpf_program *prog;
int cg2, idx = 0, rc = 1;
struct bpf_object *obj;
char filename[256];
int map_fd[2];

snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
if (load_bpf_file(filename)) {
printf("%s", bpf_log_buf);
return 1;
obj = bpf_object__open_file(filename, NULL);
if (libbpf_get_error(obj)) {
fprintf(stderr, "ERROR: opening BPF object file failed\n");
return 0;
}

prog = bpf_object__find_program_by_name(obj, "bpf_prog1");
if (!prog) {
printf("finding a prog in obj file failed\n");
goto cleanup;
}

/* load BPF program */
if (bpf_object__load(obj)) {
fprintf(stderr, "ERROR: loading BPF object file failed\n");
goto cleanup;
}

map_fd[0] = bpf_object__find_map_fd_by_name(obj, "cgroup_map");
map_fd[1] = bpf_object__find_map_fd_by_name(obj, "perf_map");
if (map_fd[0] < 0 || map_fd[1] < 0) {
fprintf(stderr, "ERROR: finding a map in obj file failed\n");
goto cleanup;
}

link = bpf_program__attach(prog);
if (libbpf_get_error(link)) {
fprintf(stderr, "ERROR: bpf_program__attach failed\n");
link = NULL;
goto cleanup;
}

if (setup_cgroup_environment())
Expand Down Expand Up @@ -70,12 +100,14 @@ int main(int argc, char **argv)
goto err;
}

goto out;
err:
rc = 1;
rc = 0;

out:
err:
close(cg2);
cleanup_cgroup_environment();

cleanup:
bpf_link__destroy(link);
bpf_object__close(obj);
return rc;
}
Loading

0 comments on commit 3677d0a

Please sign in to comment.