Blame view
samples/bpf/sampleip_user.c
4.83 KB
25763b3c8 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
72874418e samples/bpf: add ... |
2 3 4 5 |
/* * sampleip: sample instruction pointer and frequency count in a BPF map. * * Copyright 2016 Netflix, Inc. |
72874418e samples/bpf: add ... |
6 7 8 |
*/ #include <stdio.h> #include <stdlib.h> |
72874418e samples/bpf: add ... |
9 10 11 12 |
#include <unistd.h> #include <errno.h> #include <signal.h> #include <string.h> |
72874418e samples/bpf: add ... |
13 14 15 |
#include <linux/perf_event.h> #include <linux/ptrace.h> #include <linux/bpf.h> |
aa5e2af66 samples, bpf: Ref... |
16 |
#include <bpf/bpf.h> |
7cf245a37 samples/bpf: Use ... |
17 |
#include <bpf/libbpf.h> |
205c8ada3 samples/bpf: Remo... |
18 |
#include "perf-sys.h" |
28dbf861d samples/bpf: move... |
19 |
#include "trace_helpers.h" |
72874418e samples/bpf: add ... |
20 21 22 23 24 |
#define DEFAULT_FREQ 99 #define DEFAULT_SECS 5 #define MAX_IPS 8192 #define PAGE_OFFSET 0xffff880000000000 |
aa5e2af66 samples, bpf: Ref... |
25 |
static int map_fd; |
72874418e samples/bpf: add ... |
26 27 28 29 30 31 32 33 34 35 36 |
static int nr_cpus; static void usage(void) { printf("USAGE: sampleip [-F freq] [duration] "); printf(" -F freq # sample frequency (Hertz), default 99 "); printf(" duration # sampling duration (seconds), default 5 "); } |
aa5e2af66 samples, bpf: Ref... |
37 38 |
static int sampling_start(int freq, struct bpf_program *prog, struct bpf_link *links[]) |
72874418e samples/bpf: add ... |
39 |
{ |
aa5e2af66 samples, bpf: Ref... |
40 |
int i, pmu_fd; |
72874418e samples/bpf: add ... |
41 42 43 44 45 46 47 48 49 50 |
struct perf_event_attr pe_sample_attr = { .type = PERF_TYPE_SOFTWARE, .freq = 1, .sample_period = freq, .config = PERF_COUNT_SW_CPU_CLOCK, .inherit = 1, }; for (i = 0; i < nr_cpus; i++) { |
aa5e2af66 samples, bpf: Ref... |
51 |
pmu_fd = sys_perf_event_open(&pe_sample_attr, -1 /* pid */, i, |
72874418e samples/bpf: add ... |
52 |
-1 /* group_fd */, 0 /* flags */); |
aa5e2af66 samples, bpf: Ref... |
53 |
if (pmu_fd < 0) { |
72874418e samples/bpf: add ... |
54 55 56 57 |
fprintf(stderr, "ERROR: Initializing perf sampling "); return 1; } |
aa5e2af66 samples, bpf: Ref... |
58 |
links[i] = bpf_program__attach_perf_event(prog, pmu_fd); |
0efdcefb0 samples, bpf: Ref... |
59 |
if (libbpf_get_error(links[i])) { |
aa5e2af66 samples, bpf: Ref... |
60 61 62 63 64 65 |
fprintf(stderr, "ERROR: Attach perf event "); links[i] = NULL; close(pmu_fd); return 1; } |
72874418e samples/bpf: add ... |
66 67 68 69 |
} return 0; } |
aa5e2af66 samples, bpf: Ref... |
70 |
static void sampling_end(struct bpf_link *links[]) |
72874418e samples/bpf: add ... |
71 72 73 74 |
{ int i; for (i = 0; i < nr_cpus; i++) |
aa5e2af66 samples, bpf: Ref... |
75 |
bpf_link__destroy(links[i]); |
72874418e samples/bpf: add ... |
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
} struct ipcount { __u64 ip; __u32 count; }; /* used for sorting */ struct ipcount counts[MAX_IPS]; static int count_cmp(const void *p1, const void *p2) { return ((struct ipcount *)p1)->count - ((struct ipcount *)p2)->count; } static void print_ip_map(int fd) { struct ksym *sym; __u64 key, next_key; __u32 value; int i, max; printf("%-19s %-32s %s ", "ADDR", "KSYM", "COUNT"); /* fetch IPs and counts */ key = 0, i = 0; |
d40fc181e samples/bpf: Make... |
103 104 |
while (bpf_map_get_next_key(fd, &key, &next_key) == 0) { bpf_map_lookup_elem(fd, &next_key, &value); |
72874418e samples/bpf: add ... |
105 106 107 108 109 110 111 112 113 114 115 |
counts[i].ip = next_key; counts[i++].count = value; key = next_key; } max = i; /* sort and print */ qsort(counts, max, sizeof(struct ipcount), count_cmp); for (i = 0; i < max; i++) { if (counts[i].ip > PAGE_OFFSET) { sym = ksym_search(counts[i].ip); |
e67b2c715 samples, selftest... |
116 117 118 119 120 |
if (!sym) { printf("ksym not found. Is kallsyms loaded? "); continue; } |
72874418e samples/bpf: add ... |
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
printf("0x%-17llx %-32s %u ", counts[i].ip, sym->name, counts[i].count); } else { printf("0x%-17llx %-32s %u ", counts[i].ip, "(user)", counts[i].count); } } if (max == MAX_IPS) { printf("WARNING: IP hash was full (max %d entries); ", max); printf("may have dropped samples "); } } static void int_exit(int sig) { printf(" "); |
aa5e2af66 samples, bpf: Ref... |
142 |
print_ip_map(map_fd); |
72874418e samples/bpf: add ... |
143 144 145 146 147 |
exit(0); } int main(int argc, char **argv) { |
aa5e2af66 samples, bpf: Ref... |
148 149 150 151 |
int opt, freq = DEFAULT_FREQ, secs = DEFAULT_SECS, error = 1; struct bpf_object *obj = NULL; struct bpf_program *prog; struct bpf_link **links; |
72874418e samples/bpf: add ... |
152 |
char filename[256]; |
72874418e samples/bpf: add ... |
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
/* process arguments */ while ((opt = getopt(argc, argv, "F:h")) != -1) { switch (opt) { case 'F': freq = atoi(optarg); break; case 'h': default: usage(); return 0; } } if (argc - optind == 1) secs = atoi(argv[optind]); if (freq == 0 || secs == 0) { usage(); return 1; } /* initialize kernel symbol translation */ if (load_kallsyms()) { fprintf(stderr, "ERROR: loading /proc/kallsyms "); return 2; } /* create perf FDs for each CPU */ |
aa5e2af66 samples, bpf: Ref... |
181 182 183 184 185 186 |
nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); links = calloc(nr_cpus, sizeof(struct bpf_link *)); if (!links) { fprintf(stderr, "ERROR: malloc of links "); goto cleanup; |
72874418e samples/bpf: add ... |
187 |
} |
72874418e samples/bpf: add ... |
188 |
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); |
aa5e2af66 samples, bpf: Ref... |
189 |
obj = bpf_object__open_file(filename, NULL); |
0efdcefb0 samples, bpf: Ref... |
190 |
if (libbpf_get_error(obj)) { |
aa5e2af66 samples, bpf: Ref... |
191 192 193 194 195 196 197 198 199 200 201 |
fprintf(stderr, "ERROR: opening BPF object file failed "); obj = NULL; goto cleanup; } prog = bpf_object__find_program_by_name(obj, "do_sample"); if (!prog) { fprintf(stderr, "ERROR: finding a prog in obj file failed "); goto cleanup; |
72874418e samples/bpf: add ... |
202 |
} |
aa5e2af66 samples, bpf: Ref... |
203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
/* load BPF program */ if (bpf_object__load(obj)) { fprintf(stderr, "ERROR: loading BPF object file failed "); goto cleanup; } map_fd = bpf_object__find_map_fd_by_name(obj, "ip_map"); if (map_fd < 0) { fprintf(stderr, "ERROR: finding a map in obj file failed "); goto cleanup; } |
72874418e samples/bpf: add ... |
217 |
signal(SIGINT, int_exit); |
ad990dbe6 samples/bpf: run ... |
218 |
signal(SIGTERM, int_exit); |
72874418e samples/bpf: add ... |
219 220 221 222 223 |
/* do sampling */ printf("Sampling at %d Hertz for %d seconds. Ctrl-C also ends. ", freq, secs); |
aa5e2af66 samples, bpf: Ref... |
224 225 |
if (sampling_start(freq, prog, links) != 0) goto cleanup; |
72874418e samples/bpf: add ... |
226 |
sleep(secs); |
aa5e2af66 samples, bpf: Ref... |
227 |
error = 0; |
72874418e samples/bpf: add ... |
228 |
|
aa5e2af66 samples, bpf: Ref... |
229 230 |
cleanup: sampling_end(links); |
72874418e samples/bpf: add ... |
231 |
/* output sample counts */ |
aa5e2af66 samples, bpf: Ref... |
232 233 |
if (!error) print_ip_map(map_fd); |
72874418e samples/bpf: add ... |
234 |
|
aa5e2af66 samples, bpf: Ref... |
235 236 237 |
free(links); bpf_object__close(obj); return error; |
72874418e samples/bpf: add ... |
238 |
} |