1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | #include <stdio.h> |
3 | #include <fcntl.h> |
4 | #include <poll.h> |
5 | #include <time.h> |
6 | #include <signal.h> |
7 | #include <bpf/libbpf.h> |
8 | |
9 | static __u64 time_get_ns(void) |
10 | { |
11 | struct timespec ts; |
12 | |
13 | clock_gettime(CLOCK_MONOTONIC, tp: &ts); |
14 | return ts.tv_sec * 1000000000ull + ts.tv_nsec; |
15 | } |
16 | |
17 | static __u64 start_time; |
18 | static __u64 cnt; |
19 | |
20 | #define MAX_CNT 100000ll |
21 | |
22 | static void print_bpf_output(void *ctx, int cpu, void *data, __u32 size) |
23 | { |
24 | struct { |
25 | __u64 pid; |
26 | __u64 cookie; |
27 | } *e = data; |
28 | |
29 | if (e->cookie != 0x12345678) { |
30 | printf(format: "BUG pid %llx cookie %llx sized %d\n" , |
31 | e->pid, e->cookie, size); |
32 | return; |
33 | } |
34 | |
35 | cnt++; |
36 | |
37 | if (cnt == MAX_CNT) { |
38 | printf(format: "recv %lld events per sec\n" , |
39 | MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); |
40 | return; |
41 | } |
42 | } |
43 | |
44 | int main(int argc, char **argv) |
45 | { |
46 | struct bpf_link *link = NULL; |
47 | struct bpf_program *prog; |
48 | struct perf_buffer *pb; |
49 | struct bpf_object *obj; |
50 | int map_fd, ret = 0; |
51 | char filename[256]; |
52 | FILE *f; |
53 | |
54 | snprintf(s: filename, maxlen: sizeof(filename), format: "%s.bpf.o" , argv[0]); |
55 | obj = bpf_object__open_file(filename, NULL); |
56 | if (libbpf_get_error(obj)) { |
57 | fprintf(stderr, format: "ERROR: opening BPF object file failed\n" ); |
58 | return 0; |
59 | } |
60 | |
61 | /* load BPF program */ |
62 | if (bpf_object__load(obj)) { |
63 | fprintf(stderr, format: "ERROR: loading BPF object file failed\n" ); |
64 | goto cleanup; |
65 | } |
66 | |
67 | map_fd = bpf_object__find_map_fd_by_name(obj, "my_map" ); |
68 | if (map_fd < 0) { |
69 | fprintf(stderr, format: "ERROR: finding a map in obj file failed\n" ); |
70 | goto cleanup; |
71 | } |
72 | |
73 | prog = bpf_object__find_program_by_name(obj, "bpf_prog1" ); |
74 | if (libbpf_get_error(prog)) { |
75 | fprintf(stderr, format: "ERROR: finding a prog in obj file failed\n" ); |
76 | goto cleanup; |
77 | } |
78 | |
79 | link = bpf_program__attach(prog); |
80 | if (libbpf_get_error(link)) { |
81 | fprintf(stderr, format: "ERROR: bpf_program__attach failed\n" ); |
82 | link = NULL; |
83 | goto cleanup; |
84 | } |
85 | |
86 | pb = perf_buffer__new(map_fd, 8, print_bpf_output, NULL, NULL, NULL); |
87 | ret = libbpf_get_error(pb); |
88 | if (ret) { |
89 | printf(format: "failed to setup perf_buffer: %d\n" , ret); |
90 | return 1; |
91 | } |
92 | |
93 | f = popen(command: "taskset 1 dd if=/dev/zero of=/dev/null" , modes: "r" ); |
94 | (void) f; |
95 | |
96 | start_time = time_get_ns(); |
97 | while ((ret = perf_buffer__poll(pb, 1000)) >= 0 && cnt < MAX_CNT) { |
98 | } |
99 | kill(pid: 0, SIGINT); |
100 | |
101 | cleanup: |
102 | bpf_link__destroy(link); |
103 | bpf_object__close(obj); |
104 | return ret; |
105 | } |
106 | |