Skip to content

Commit

Permalink
samples, bpf: Refactor kprobe tracing user progs with libbpf
Browse files Browse the repository at this point in the history
Currently, the kprobe BPF program attachment method for bpf_load is
quite old. The implementation of bpf_load "directly" controls and
manages(create, delete) the kprobe events of DEBUGFS. On the other hand,
using using the libbpf automatically manages the kprobe event.
(under bpf_link interface)

By calling bpf_program__attach(_kprobe) in libbpf, the corresponding
kprobe is created and the BPF program will be attached to this kprobe.
To remove this, by simply invoking bpf_link__destroy will clean up the
event.

This commit refactors kprobe tracing programs (tracex{1~7}_user.c) with
libbpf using bpf_link interface and bpf_program__attach.

tracex2_kern.c, which tracks system calls (sys_*), has been modified to
append prefix depending on architecture.

Signed-off-by: Daniel T. Lee <[email protected]>
Signed-off-by: Daniel Borkmann <[email protected]>
Acked-by: Yonghong Song <[email protected]>
Link: https://lore.kernel.org/bpf/[email protected]
  • Loading branch information
DanielTimLee authored and borkmann committed May 19, 2020
1 parent 0efdcef commit 63841bc
Show file tree
Hide file tree
Showing 9 changed files with 252 additions and 64 deletions.
12 changes: 6 additions & 6 deletions samples/bpf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,13 @@ fds_example-objs := fds_example.o
sockex1-objs := sockex1_user.o
sockex2-objs := sockex2_user.o
sockex3-objs := bpf_load.o sockex3_user.o
tracex1-objs := bpf_load.o tracex1_user.o $(TRACE_HELPERS)
tracex2-objs := bpf_load.o tracex2_user.o
tracex3-objs := bpf_load.o tracex3_user.o
tracex4-objs := bpf_load.o tracex4_user.o
tracex1-objs := tracex1_user.o $(TRACE_HELPERS)
tracex2-objs := tracex2_user.o
tracex3-objs := tracex3_user.o
tracex4-objs := tracex4_user.o
tracex5-objs := bpf_load.o tracex5_user.o $(TRACE_HELPERS)
tracex6-objs := bpf_load.o tracex6_user.o
tracex7-objs := bpf_load.o tracex7_user.o
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
Expand Down
13 changes: 13 additions & 0 deletions samples/bpf/trace_common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: GPL-2.0
#ifndef __TRACE_COMMON_H
#define __TRACE_COMMON_H

#ifdef __x86_64__
#define SYSCALL(SYS) "__x64_" __stringify(SYS)
#elif defined(__s390x__)
#define SYSCALL(SYS) "__s390x_" __stringify(SYS)
#else
#define SYSCALL(SYS) __stringify(SYS)
#endif

#endif
37 changes: 30 additions & 7 deletions samples/bpf/tracex1_user.c
Original file line number Diff line number Diff line change
@@ -1,27 +1,50 @@
// SPDX-License-Identifier: GPL-2.0
#include <stdio.h>
#include <linux/bpf.h>
#include <unistd.h>
#include <bpf/bpf.h>
#include "bpf_load.h"
#include <bpf/libbpf.h>
#include "trace_helpers.h"

int main(int ac, char **argv)
{
FILE *f;
struct bpf_link *link = NULL;
struct bpf_program *prog;
struct bpf_object *obj;
char filename[256];
FILE *f;

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;
}

prog = bpf_object__find_program_by_name(obj, "bpf_prog1");
if (!prog) {
fprintf(stderr, "ERROR: 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;
}

if (load_bpf_file(filename)) {
printf("%s", bpf_log_buf);
return 1;
link = bpf_program__attach(prog);
if (libbpf_get_error(link)) {
fprintf(stderr, "ERROR: bpf_program__attach failed\n");
link = NULL;
goto cleanup;
}

f = popen("taskset 1 ping -c5 localhost", "r");
(void) f;

read_trace_pipe();

cleanup:
bpf_link__destroy(link);
bpf_object__close(obj);
return 0;
}
3 changes: 2 additions & 1 deletion samples/bpf/tracex2_kern.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <uapi/linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include "trace_common.h"

struct bpf_map_def SEC("maps") my_map = {
.type = BPF_MAP_TYPE_HASH,
Expand Down Expand Up @@ -77,7 +78,7 @@ struct bpf_map_def SEC("maps") my_hist_map = {
.max_entries = 1024,
};

SEC("kprobe/sys_write")
SEC("kprobe/" SYSCALL(sys_write))
int bpf_prog3(struct pt_regs *ctx)
{
long write_size = PT_REGS_PARM3(ctx);
Expand Down
51 changes: 42 additions & 9 deletions samples/bpf/tracex2_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,19 @@
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <linux/bpf.h>
#include <string.h>
#include <sys/resource.h>

#include <bpf/bpf.h>
#include "bpf_load.h"
#include <bpf/libbpf.h>
#include "bpf_util.h"

#define MAX_INDEX 64
#define MAX_STARS 38

/* my_map, my_hist_map */
static int map_fd[2];

static void stars(char *str, long val, long max, int width)
{
int i;
Expand Down Expand Up @@ -115,18 +117,39 @@ static void int_exit(int sig)
int main(int ac, char **argv)
{
struct rlimit r = {1024*1024, RLIM_INFINITY};
char filename[256];
long key, next_key, value;
struct bpf_link *links[2];
struct bpf_program *prog;
struct bpf_object *obj;
char filename[256];
int i, j = 0;
FILE *f;
int i;

snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);

if (setrlimit(RLIMIT_MEMLOCK, &r)) {
perror("setrlimit(RLIMIT_MEMLOCK)");
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");
return 0;
}

/* 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, "my_map");
map_fd[1] = bpf_object__find_map_fd_by_name(obj, "my_hist_map");
if (map_fd[0] < 0 || map_fd[1] < 0) {
fprintf(stderr, "ERROR: finding a map in obj file failed\n");
goto cleanup;
}

signal(SIGINT, int_exit);
signal(SIGTERM, int_exit);

Expand All @@ -138,9 +161,14 @@ int main(int ac, char **argv)
f = popen("dd if=/dev/zero of=/dev/null count=5000000", "r");
(void) f;

if (load_bpf_file(filename)) {
printf("%s", bpf_log_buf);
return 1;
bpf_object__for_each_program(prog, obj) {
links[j] = bpf_program__attach(prog);
if (libbpf_get_error(links[j])) {
fprintf(stderr, "ERROR: bpf_program__attach failed\n");
links[j] = NULL;
goto cleanup;
}
j++;
}

for (i = 0; i < 5; i++) {
Expand All @@ -156,5 +184,10 @@ int main(int ac, char **argv)
}
print_hist(map_fd[1]);

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

bpf_object__close(obj);
return 0;
}
61 changes: 45 additions & 16 deletions samples/bpf/tracex3_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@
#include <unistd.h>
#include <stdbool.h>
#include <string.h>
#include <linux/bpf.h>
#include <sys/resource.h>

#include <bpf/bpf.h>
#include "bpf_load.h"
#include <bpf/libbpf.h>
#include "bpf_util.h"

#define SLOTS 100
Expand Down Expand Up @@ -109,20 +108,11 @@ static void print_hist(int fd)
int main(int ac, char **argv)
{
struct rlimit r = {1024*1024, RLIM_INFINITY};
struct bpf_link *links[2];
struct bpf_program *prog;
struct bpf_object *obj;
char filename[256];
int i;

snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);

if (setrlimit(RLIMIT_MEMLOCK, &r)) {
perror("setrlimit(RLIMIT_MEMLOCK)");
return 1;
}

if (load_bpf_file(filename)) {
printf("%s", bpf_log_buf);
return 1;
}
int map_fd, i, j = 0;

for (i = 1; i < ac; i++) {
if (strcmp(argv[i], "-a") == 0) {
Expand All @@ -137,6 +127,40 @@ int main(int ac, char **argv)
}
}

if (setrlimit(RLIMIT_MEMLOCK, &r)) {
perror("setrlimit(RLIMIT_MEMLOCK)");
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");
return 0;
}

/* 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, "lat_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) {
links[j] = bpf_program__attach(prog);
if (libbpf_get_error(links[j])) {
fprintf(stderr, "ERROR: bpf_program__attach failed\n");
links[j] = NULL;
goto cleanup;
}
j++;
}

printf(" heatmap of IO latency\n");
if (text_only)
printf(" %s", sym[num_colors - 1]);
Expand All @@ -153,9 +177,14 @@ int main(int ac, char **argv)
for (i = 0; ; i++) {
if (i % 20 == 0)
print_banner();
print_hist(map_fd[1]);
print_hist(map_fd);
sleep(2);
}

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

bpf_object__close(obj);
return 0;
}
51 changes: 40 additions & 11 deletions samples/bpf/tracex4_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@
#include <stdbool.h>
#include <string.h>
#include <time.h>
#include <linux/bpf.h>
#include <sys/resource.h>

#include <bpf/bpf.h>
#include "bpf_load.h"
#include <bpf/libbpf.h>

struct pair {
long long val;
Expand All @@ -36,8 +35,8 @@ static void print_old_objects(int fd)
key = write(1, "\e[1;1H\e[2J", 12); /* clear screen */

key = -1;
while (bpf_map_get_next_key(map_fd[0], &key, &next_key) == 0) {
bpf_map_lookup_elem(map_fd[0], &next_key, &v);
while (bpf_map_get_next_key(fd, &key, &next_key) == 0) {
bpf_map_lookup_elem(fd, &next_key, &v);
key = next_key;
if (val - v.val < 1000000000ll)
/* object was allocated more then 1 sec ago */
Expand All @@ -50,25 +49,55 @@ static void print_old_objects(int fd)
int main(int ac, char **argv)
{
struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
struct bpf_link *links[2];
struct bpf_program *prog;
struct bpf_object *obj;
char filename[256];
int i;

snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
int map_fd, i, j = 0;

if (setrlimit(RLIMIT_MEMLOCK, &r)) {
perror("setrlimit(RLIMIT_MEMLOCK, RLIM_INFINITY)");
return 1;
}

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");
return 0;
}

/* 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) {
links[j] = bpf_program__attach(prog);
if (libbpf_get_error(links[j])) {
fprintf(stderr, "ERROR: bpf_program__attach failed\n");
links[j] = NULL;
goto cleanup;
}
j++;
}

for (i = 0; ; i++) {
print_old_objects(map_fd[1]);
print_old_objects(map_fd);
sleep(1);
}

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

bpf_object__close(obj);
return 0;
}
Loading

0 comments on commit 63841bc

Please sign in to comment.