hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/samples/bpf/sampleip_user.c
....@@ -1,26 +1,20 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * sampleip: sample instruction pointer and frequency count in a BPF map.
34 *
45 * Copyright 2016 Netflix, Inc.
5
- *
6
- * This program is free software; you can redistribute it and/or
7
- * modify it under the terms of version 2 of the GNU General Public
8
- * License as published by the Free Software Foundation.
96 */
107 #include <stdio.h>
118 #include <stdlib.h>
12
-#include <stdio.h>
139 #include <unistd.h>
1410 #include <errno.h>
1511 #include <signal.h>
1612 #include <string.h>
17
-#include <assert.h>
1813 #include <linux/perf_event.h>
1914 #include <linux/ptrace.h>
2015 #include <linux/bpf.h>
21
-#include <sys/ioctl.h>
22
-#include "libbpf.h"
23
-#include "bpf_load.h"
16
+#include <bpf/bpf.h>
17
+#include <bpf/libbpf.h>
2418 #include "perf-sys.h"
2519 #include "trace_helpers.h"
2620
....@@ -29,6 +23,7 @@
2923 #define MAX_IPS 8192
3024 #define PAGE_OFFSET 0xffff880000000000
3125
26
+static int map_fd;
3227 static int nr_cpus;
3328
3429 static void usage(void)
....@@ -38,9 +33,10 @@
3833 printf(" duration # sampling duration (seconds), default 5\n");
3934 }
4035
41
-static int sampling_start(int *pmu_fd, int freq)
36
+static int sampling_start(int freq, struct bpf_program *prog,
37
+ struct bpf_link *links[])
4238 {
43
- int i;
39
+ int i, pmu_fd;
4440
4541 struct perf_event_attr pe_sample_attr = {
4642 .type = PERF_TYPE_SOFTWARE,
....@@ -51,26 +47,30 @@
5147 };
5248
5349 for (i = 0; i < nr_cpus; i++) {
54
- pmu_fd[i] = sys_perf_event_open(&pe_sample_attr, -1 /* pid */, i,
50
+ pmu_fd = sys_perf_event_open(&pe_sample_attr, -1 /* pid */, i,
5551 -1 /* group_fd */, 0 /* flags */);
56
- if (pmu_fd[i] < 0) {
52
+ if (pmu_fd < 0) {
5753 fprintf(stderr, "ERROR: Initializing perf sampling\n");
5854 return 1;
5955 }
60
- assert(ioctl(pmu_fd[i], PERF_EVENT_IOC_SET_BPF,
61
- prog_fd[0]) == 0);
62
- assert(ioctl(pmu_fd[i], PERF_EVENT_IOC_ENABLE, 0) == 0);
56
+ links[i] = bpf_program__attach_perf_event(prog, pmu_fd);
57
+ if (libbpf_get_error(links[i])) {
58
+ fprintf(stderr, "ERROR: Attach perf event\n");
59
+ links[i] = NULL;
60
+ close(pmu_fd);
61
+ return 1;
62
+ }
6363 }
6464
6565 return 0;
6666 }
6767
68
-static void sampling_end(int *pmu_fd)
68
+static void sampling_end(struct bpf_link *links[])
6969 {
7070 int i;
7171
7272 for (i = 0; i < nr_cpus; i++)
73
- close(pmu_fd[i]);
73
+ bpf_link__destroy(links[i]);
7474 }
7575
7676 struct ipcount {
....@@ -110,6 +110,11 @@
110110 for (i = 0; i < max; i++) {
111111 if (counts[i].ip > PAGE_OFFSET) {
112112 sym = ksym_search(counts[i].ip);
113
+ if (!sym) {
114
+ printf("ksym not found. Is kallsyms loaded?\n");
115
+ continue;
116
+ }
117
+
113118 printf("0x%-17llx %-32s %u\n", counts[i].ip, sym->name,
114119 counts[i].count);
115120 } else {
....@@ -127,14 +132,17 @@
127132 static void int_exit(int sig)
128133 {
129134 printf("\n");
130
- print_ip_map(map_fd[0]);
135
+ print_ip_map(map_fd);
131136 exit(0);
132137 }
133138
134139 int main(int argc, char **argv)
135140 {
141
+ int opt, freq = DEFAULT_FREQ, secs = DEFAULT_SECS, error = 1;
142
+ struct bpf_object *obj = NULL;
143
+ struct bpf_program *prog;
144
+ struct bpf_link **links;
136145 char filename[256];
137
- int *pmu_fd, opt, freq = DEFAULT_FREQ, secs = DEFAULT_SECS;
138146
139147 /* process arguments */
140148 while ((opt = getopt(argc, argv, "F:h")) != -1) {
....@@ -162,38 +170,58 @@
162170 }
163171
164172 /* create perf FDs for each CPU */
165
- nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
166
- pmu_fd = malloc(nr_cpus * sizeof(int));
167
- if (pmu_fd == NULL) {
168
- fprintf(stderr, "ERROR: malloc of pmu_fd\n");
169
- return 1;
173
+ nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
174
+ links = calloc(nr_cpus, sizeof(struct bpf_link *));
175
+ if (!links) {
176
+ fprintf(stderr, "ERROR: malloc of links\n");
177
+ goto cleanup;
178
+ }
179
+
180
+ snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
181
+ obj = bpf_object__open_file(filename, NULL);
182
+ if (libbpf_get_error(obj)) {
183
+ fprintf(stderr, "ERROR: opening BPF object file failed\n");
184
+ obj = NULL;
185
+ goto cleanup;
186
+ }
187
+
188
+ prog = bpf_object__find_program_by_name(obj, "do_sample");
189
+ if (!prog) {
190
+ fprintf(stderr, "ERROR: finding a prog in obj file failed\n");
191
+ goto cleanup;
170192 }
171193
172194 /* load BPF program */
173
- snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
174
- if (load_bpf_file(filename)) {
175
- fprintf(stderr, "ERROR: loading BPF program (errno %d):\n",
176
- errno);
177
- if (strcmp(bpf_log_buf, "") == 0)
178
- fprintf(stderr, "Try: ulimit -l unlimited\n");
179
- else
180
- fprintf(stderr, "%s", bpf_log_buf);
181
- return 1;
195
+ if (bpf_object__load(obj)) {
196
+ fprintf(stderr, "ERROR: loading BPF object file failed\n");
197
+ goto cleanup;
182198 }
199
+
200
+ map_fd = bpf_object__find_map_fd_by_name(obj, "ip_map");
201
+ if (map_fd < 0) {
202
+ fprintf(stderr, "ERROR: finding a map in obj file failed\n");
203
+ goto cleanup;
204
+ }
205
+
183206 signal(SIGINT, int_exit);
184207 signal(SIGTERM, int_exit);
185208
186209 /* do sampling */
187210 printf("Sampling at %d Hertz for %d seconds. Ctrl-C also ends.\n",
188211 freq, secs);
189
- if (sampling_start(pmu_fd, freq) != 0)
190
- return 1;
212
+ if (sampling_start(freq, prog, links) != 0)
213
+ goto cleanup;
214
+
191215 sleep(secs);
192
- sampling_end(pmu_fd);
193
- free(pmu_fd);
216
+ error = 0;
194217
218
+cleanup:
219
+ sampling_end(links);
195220 /* output sample counts */
196
- print_ip_map(map_fd[0]);
221
+ if (!error)
222
+ print_ip_map(map_fd);
197223
198
- return 0;
224
+ free(links);
225
+ bpf_object__close(obj);
226
+ return error;
199227 }