diff options
author | Alexei Starovoitov <ast@fb.com> | 2016-03-08 18:07:52 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-03-08 23:22:02 -0500 |
commit | 9d8b612d88e81c2cf7dbc0d4a827da6ca0d848e0 (patch) | |
tree | 224ffcb5af7fa6d63fc1e25abd718e59667b14f8 /samples | |
parent | e28e87ed474c5a0b378c66fb85efc8e487f4f63f (diff) |
samples/bpf: add bpf map stress test
this test calls bpf programs from different contexts:
from inside of slub, from rcu, from pretty much everywhere,
since it kprobes all spin_lock functions.
It stresses the bpf hash and percpu map pre-allocation,
deallocation logic and call_rcu mechanisms.
User space part adding more stress by walking and deleting map elements.
Note that due to nature bpf_load.c the earlier kprobe+bpf programs are
already active while loader loads new programs, creates new kprobes and
attaches them.
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'samples')
-rw-r--r-- | samples/bpf/Makefile | 4 | ||||
-rw-r--r-- | samples/bpf/spintest_kern.c | 59 | ||||
-rw-r--r-- | samples/bpf/spintest_user.c | 50 |
3 files changed, 113 insertions, 0 deletions
diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile index c4f8ae0c8afe..75a13e742ab4 100644 --- a/samples/bpf/Makefile +++ b/samples/bpf/Makefile | |||
@@ -17,6 +17,7 @@ hostprogs-y += tracex6 | |||
17 | hostprogs-y += trace_output | 17 | hostprogs-y += trace_output |
18 | hostprogs-y += lathist | 18 | hostprogs-y += lathist |
19 | hostprogs-y += offwaketime | 19 | hostprogs-y += offwaketime |
20 | hostprogs-y += spintest | ||
20 | 21 | ||
21 | test_verifier-objs := test_verifier.o libbpf.o | 22 | test_verifier-objs := test_verifier.o libbpf.o |
22 | test_maps-objs := test_maps.o libbpf.o | 23 | test_maps-objs := test_maps.o libbpf.o |
@@ -34,6 +35,7 @@ tracex6-objs := bpf_load.o libbpf.o tracex6_user.o | |||
34 | trace_output-objs := bpf_load.o libbpf.o trace_output_user.o | 35 | trace_output-objs := bpf_load.o libbpf.o trace_output_user.o |
35 | lathist-objs := bpf_load.o libbpf.o lathist_user.o | 36 | lathist-objs := bpf_load.o libbpf.o lathist_user.o |
36 | offwaketime-objs := bpf_load.o libbpf.o offwaketime_user.o | 37 | offwaketime-objs := bpf_load.o libbpf.o offwaketime_user.o |
38 | spintest-objs := bpf_load.o libbpf.o spintest_user.o | ||
37 | 39 | ||
38 | # Tell kbuild to always build the programs | 40 | # Tell kbuild to always build the programs |
39 | always := $(hostprogs-y) | 41 | always := $(hostprogs-y) |
@@ -50,6 +52,7 @@ always += trace_output_kern.o | |||
50 | always += tcbpf1_kern.o | 52 | always += tcbpf1_kern.o |
51 | always += lathist_kern.o | 53 | always += lathist_kern.o |
52 | always += offwaketime_kern.o | 54 | always += offwaketime_kern.o |
55 | always += spintest_kern.o | ||
53 | 56 | ||
54 | HOSTCFLAGS += -I$(objtree)/usr/include | 57 | HOSTCFLAGS += -I$(objtree)/usr/include |
55 | 58 | ||
@@ -67,6 +70,7 @@ HOSTLOADLIBES_tracex6 += -lelf | |||
67 | HOSTLOADLIBES_trace_output += -lelf -lrt | 70 | HOSTLOADLIBES_trace_output += -lelf -lrt |
68 | HOSTLOADLIBES_lathist += -lelf | 71 | HOSTLOADLIBES_lathist += -lelf |
69 | HOSTLOADLIBES_offwaketime += -lelf | 72 | HOSTLOADLIBES_offwaketime += -lelf |
73 | HOSTLOADLIBES_spintest += -lelf | ||
70 | 74 | ||
71 | # point this to your LLVM backend with bpf support | 75 | # point this to your LLVM backend with bpf support |
72 | LLC=$(srctree)/tools/bpf/llvm/bld/Debug+Asserts/bin/llc | 76 | LLC=$(srctree)/tools/bpf/llvm/bld/Debug+Asserts/bin/llc |
diff --git a/samples/bpf/spintest_kern.c b/samples/bpf/spintest_kern.c new file mode 100644 index 000000000000..ef8ac33bb2e9 --- /dev/null +++ b/samples/bpf/spintest_kern.c | |||
@@ -0,0 +1,59 @@ | |||
1 | /* Copyright (c) 2016, Facebook | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or | ||
4 | * modify it under the terms of version 2 of the GNU General Public | ||
5 | * License as published by the Free Software Foundation. | ||
6 | */ | ||
7 | #include <linux/skbuff.h> | ||
8 | #include <linux/netdevice.h> | ||
9 | #include <linux/version.h> | ||
10 | #include <uapi/linux/bpf.h> | ||
11 | #include "bpf_helpers.h" | ||
12 | |||
13 | struct bpf_map_def SEC("maps") my_map = { | ||
14 | .type = BPF_MAP_TYPE_HASH, | ||
15 | .key_size = sizeof(long), | ||
16 | .value_size = sizeof(long), | ||
17 | .max_entries = 1024, | ||
18 | }; | ||
19 | struct bpf_map_def SEC("maps") my_map2 = { | ||
20 | .type = BPF_MAP_TYPE_PERCPU_HASH, | ||
21 | .key_size = sizeof(long), | ||
22 | .value_size = sizeof(long), | ||
23 | .max_entries = 1024, | ||
24 | }; | ||
25 | |||
26 | #define PROG(foo) \ | ||
27 | int foo(struct pt_regs *ctx) \ | ||
28 | { \ | ||
29 | long v = ctx->ip, *val; \ | ||
30 | \ | ||
31 | val = bpf_map_lookup_elem(&my_map, &v); \ | ||
32 | bpf_map_update_elem(&my_map, &v, &v, BPF_ANY); \ | ||
33 | bpf_map_update_elem(&my_map2, &v, &v, BPF_ANY); \ | ||
34 | bpf_map_delete_elem(&my_map2, &v); \ | ||
35 | return 0; \ | ||
36 | } | ||
37 | |||
38 | /* add kprobes to all possible *spin* functions */ | ||
39 | SEC("kprobe/spin_unlock")PROG(p1) | ||
40 | SEC("kprobe/spin_lock")PROG(p2) | ||
41 | SEC("kprobe/mutex_spin_on_owner")PROG(p3) | ||
42 | SEC("kprobe/rwsem_spin_on_owner")PROG(p4) | ||
43 | SEC("kprobe/spin_unlock_irqrestore")PROG(p5) | ||
44 | SEC("kprobe/_raw_spin_unlock_irqrestore")PROG(p6) | ||
45 | SEC("kprobe/_raw_spin_unlock_bh")PROG(p7) | ||
46 | SEC("kprobe/_raw_spin_unlock")PROG(p8) | ||
47 | SEC("kprobe/_raw_spin_lock_irqsave")PROG(p9) | ||
48 | SEC("kprobe/_raw_spin_trylock_bh")PROG(p10) | ||
49 | SEC("kprobe/_raw_spin_lock_irq")PROG(p11) | ||
50 | SEC("kprobe/_raw_spin_trylock")PROG(p12) | ||
51 | SEC("kprobe/_raw_spin_lock")PROG(p13) | ||
52 | SEC("kprobe/_raw_spin_lock_bh")PROG(p14) | ||
53 | /* and to inner bpf helpers */ | ||
54 | SEC("kprobe/htab_map_update_elem")PROG(p15) | ||
55 | SEC("kprobe/__htab_percpu_map_update_elem")PROG(p16) | ||
56 | SEC("kprobe/htab_map_alloc")PROG(p17) | ||
57 | |||
58 | char _license[] SEC("license") = "GPL"; | ||
59 | u32 _version SEC("version") = LINUX_VERSION_CODE; | ||
diff --git a/samples/bpf/spintest_user.c b/samples/bpf/spintest_user.c new file mode 100644 index 000000000000..311ede532230 --- /dev/null +++ b/samples/bpf/spintest_user.c | |||
@@ -0,0 +1,50 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <unistd.h> | ||
3 | #include <linux/bpf.h> | ||
4 | #include <string.h> | ||
5 | #include <assert.h> | ||
6 | #include <sys/resource.h> | ||
7 | #include "libbpf.h" | ||
8 | #include "bpf_load.h" | ||
9 | |||
10 | int main(int ac, char **argv) | ||
11 | { | ||
12 | struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; | ||
13 | long key, next_key, value; | ||
14 | char filename[256]; | ||
15 | struct ksym *sym; | ||
16 | int i; | ||
17 | |||
18 | snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); | ||
19 | setrlimit(RLIMIT_MEMLOCK, &r); | ||
20 | |||
21 | if (load_kallsyms()) { | ||
22 | printf("failed to process /proc/kallsyms\n"); | ||
23 | return 2; | ||
24 | } | ||
25 | |||
26 | if (load_bpf_file(filename)) { | ||
27 | printf("%s", bpf_log_buf); | ||
28 | return 1; | ||
29 | } | ||
30 | |||
31 | for (i = 0; i < 5; i++) { | ||
32 | key = 0; | ||
33 | printf("kprobing funcs:"); | ||
34 | while (bpf_get_next_key(map_fd[0], &key, &next_key) == 0) { | ||
35 | bpf_lookup_elem(map_fd[0], &next_key, &value); | ||
36 | assert(next_key == value); | ||
37 | sym = ksym_search(value); | ||
38 | printf(" %s", sym->name); | ||
39 | key = next_key; | ||
40 | } | ||
41 | if (key) | ||
42 | printf("\n"); | ||
43 | key = 0; | ||
44 | while (bpf_get_next_key(map_fd[0], &key, &next_key) == 0) | ||
45 | bpf_delete_elem(map_fd[0], &next_key); | ||
46 | sleep(1); | ||
47 | } | ||
48 | |||
49 | return 0; | ||
50 | } | ||