hc
2024-01-05 071106ecf68c401173c58808b1cf5f68cc50d390
kernel/samples/bpf/trace_output_user.c
....@@ -1,29 +1,10 @@
1
-/* This program is free software; you can redistribute it and/or
2
- * modify it under the terms of version 2 of the GNU General Public
3
- * License as published by the Free Software Foundation.
4
- */
1
+// SPDX-License-Identifier: GPL-2.0-only
52 #include <stdio.h>
6
-#include <unistd.h>
7
-#include <stdlib.h>
8
-#include <stdbool.h>
9
-#include <string.h>
103 #include <fcntl.h>
114 #include <poll.h>
12
-#include <linux/perf_event.h>
13
-#include <linux/bpf.h>
14
-#include <errno.h>
15
-#include <assert.h>
16
-#include <sys/syscall.h>
17
-#include <sys/ioctl.h>
18
-#include <sys/mman.h>
195 #include <time.h>
206 #include <signal.h>
21
-#include <libbpf.h>
22
-#include "bpf_load.h"
23
-#include "perf-sys.h"
24
-#include "trace_helpers.h"
25
-
26
-static int pmu_fd;
7
+#include <bpf/libbpf.h>
278
289 static __u64 time_get_ns(void)
2910 {
....@@ -34,12 +15,12 @@
3415 }
3516
3617 static __u64 start_time;
18
+static __u64 cnt;
3719
3820 #define MAX_CNT 100000ll
3921
40
-static int print_bpf_output(void *data, int size)
22
+static void print_bpf_output(void *ctx, int cpu, void *data, __u32 size)
4123 {
42
- static __u64 cnt;
4324 struct {
4425 __u64 pid;
4526 __u64 cookie;
....@@ -48,7 +29,7 @@
4829 if (e->cookie != 0x12345678) {
4930 printf("BUG pid %llx cookie %llx sized %d\n",
5031 e->pid, e->cookie, size);
51
- return LIBBPF_PERF_EVENT_ERROR;
32
+ return;
5233 }
5334
5435 cnt++;
....@@ -56,51 +37,71 @@
5637 if (cnt == MAX_CNT) {
5738 printf("recv %lld events per sec\n",
5839 MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
59
- return LIBBPF_PERF_EVENT_DONE;
40
+ return;
6041 }
61
-
62
- return LIBBPF_PERF_EVENT_CONT;
63
-}
64
-
65
-static void test_bpf_perf_event(void)
66
-{
67
- struct perf_event_attr attr = {
68
- .sample_type = PERF_SAMPLE_RAW,
69
- .type = PERF_TYPE_SOFTWARE,
70
- .config = PERF_COUNT_SW_BPF_OUTPUT,
71
- };
72
- int key = 0;
73
-
74
- pmu_fd = sys_perf_event_open(&attr, -1/*pid*/, 0/*cpu*/, -1/*group_fd*/, 0);
75
-
76
- assert(pmu_fd >= 0);
77
- assert(bpf_map_update_elem(map_fd[0], &key, &pmu_fd, BPF_ANY) == 0);
78
- ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0);
7942 }
8043
8144 int main(int argc, char **argv)
8245 {
46
+ struct perf_buffer_opts pb_opts = {};
47
+ struct bpf_link *link = NULL;
48
+ struct bpf_program *prog;
49
+ struct perf_buffer *pb;
50
+ struct bpf_object *obj;
51
+ int map_fd, ret = 0;
8352 char filename[256];
8453 FILE *f;
85
- int ret;
8654
8755 snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
88
-
89
- if (load_bpf_file(filename)) {
90
- printf("%s", bpf_log_buf);
91
- return 1;
56
+ obj = bpf_object__open_file(filename, NULL);
57
+ if (libbpf_get_error(obj)) {
58
+ fprintf(stderr, "ERROR: opening BPF object file failed\n");
59
+ return 0;
9260 }
9361
94
- test_bpf_perf_event();
62
+ /* load BPF program */
63
+ if (bpf_object__load(obj)) {
64
+ fprintf(stderr, "ERROR: loading BPF object file failed\n");
65
+ goto cleanup;
66
+ }
9567
96
- if (perf_event_mmap(pmu_fd) < 0)
68
+ map_fd = bpf_object__find_map_fd_by_name(obj, "my_map");
69
+ if (map_fd < 0) {
70
+ fprintf(stderr, "ERROR: finding a map in obj file failed\n");
71
+ goto cleanup;
72
+ }
73
+
74
+ prog = bpf_object__find_program_by_name(obj, "bpf_prog1");
75
+ if (libbpf_get_error(prog)) {
76
+ fprintf(stderr, "ERROR: finding a prog in obj file failed\n");
77
+ goto cleanup;
78
+ }
79
+
80
+ link = bpf_program__attach(prog);
81
+ if (libbpf_get_error(link)) {
82
+ fprintf(stderr, "ERROR: bpf_program__attach failed\n");
83
+ link = NULL;
84
+ goto cleanup;
85
+ }
86
+
87
+ pb_opts.sample_cb = print_bpf_output;
88
+ pb = perf_buffer__new(map_fd, 8, &pb_opts);
89
+ ret = libbpf_get_error(pb);
90
+ if (ret) {
91
+ printf("failed to setup perf_buffer: %d\n", ret);
9792 return 1;
93
+ }
9894
9995 f = popen("taskset 1 dd if=/dev/zero of=/dev/null", "r");
10096 (void) f;
10197
10298 start_time = time_get_ns();
103
- ret = perf_event_poller(pmu_fd, print_bpf_output);
99
+ while ((ret = perf_buffer__poll(pb, 1000)) >= 0 && cnt < MAX_CNT) {
100
+ }
104101 kill(0, SIGINT);
102
+
103
+cleanup:
104
+ bpf_link__destroy(link);
105
+ bpf_object__close(obj);
105106 return ret;
106107 }