diff options
Diffstat (limited to 'samples/bpf/tracex2_kern.c')
-rw-r--r-- | samples/bpf/tracex2_kern.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/samples/bpf/tracex2_kern.c b/samples/bpf/tracex2_kern.c new file mode 100644 index 000000000000..19ec1cfc45db --- /dev/null +++ b/samples/bpf/tracex2_kern.c | |||
@@ -0,0 +1,86 @@ | |||
1 | /* Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com | ||
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 | |||
20 | /* kprobe is NOT a stable ABI. If kernel internals change this bpf+kprobe | ||
21 | * example will no longer be meaningful | ||
22 | */ | ||
23 | SEC("kprobe/kfree_skb") | ||
24 | int bpf_prog2(struct pt_regs *ctx) | ||
25 | { | ||
26 | long loc = 0; | ||
27 | long init_val = 1; | ||
28 | long *value; | ||
29 | |||
30 | /* x64 specific: read ip of kfree_skb caller. | ||
31 | * non-portable version of __builtin_return_address(0) | ||
32 | */ | ||
33 | bpf_probe_read(&loc, sizeof(loc), (void *)ctx->sp); | ||
34 | |||
35 | value = bpf_map_lookup_elem(&my_map, &loc); | ||
36 | if (value) | ||
37 | *value += 1; | ||
38 | else | ||
39 | bpf_map_update_elem(&my_map, &loc, &init_val, BPF_ANY); | ||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | static unsigned int log2(unsigned int v) | ||
44 | { | ||
45 | unsigned int r; | ||
46 | unsigned int shift; | ||
47 | |||
48 | r = (v > 0xFFFF) << 4; v >>= r; | ||
49 | shift = (v > 0xFF) << 3; v >>= shift; r |= shift; | ||
50 | shift = (v > 0xF) << 2; v >>= shift; r |= shift; | ||
51 | shift = (v > 0x3) << 1; v >>= shift; r |= shift; | ||
52 | r |= (v >> 1); | ||
53 | return r; | ||
54 | } | ||
55 | |||
56 | static unsigned int log2l(unsigned long v) | ||
57 | { | ||
58 | unsigned int hi = v >> 32; | ||
59 | if (hi) | ||
60 | return log2(hi) + 32; | ||
61 | else | ||
62 | return log2(v); | ||
63 | } | ||
64 | |||
65 | struct bpf_map_def SEC("maps") my_hist_map = { | ||
66 | .type = BPF_MAP_TYPE_ARRAY, | ||
67 | .key_size = sizeof(u32), | ||
68 | .value_size = sizeof(long), | ||
69 | .max_entries = 64, | ||
70 | }; | ||
71 | |||
72 | SEC("kprobe/sys_write") | ||
73 | int bpf_prog3(struct pt_regs *ctx) | ||
74 | { | ||
75 | long write_size = ctx->dx; /* arg3 */ | ||
76 | long init_val = 1; | ||
77 | long *value; | ||
78 | u32 index = log2l(write_size); | ||
79 | |||
80 | value = bpf_map_lookup_elem(&my_hist_map, &index); | ||
81 | if (value) | ||
82 | __sync_fetch_and_add(value, 1); | ||
83 | return 0; | ||
84 | } | ||
85 | char _license[] SEC("license") = "GPL"; | ||
86 | u32 _version SEC("version") = LINUX_VERSION_CODE; | ||