GNU Linux-libre 6.6.15-gnu
[releases.git] / samples / bpf / tracex3_user.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com
3  */
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <signal.h>
7 #include <unistd.h>
8 #include <stdbool.h>
9 #include <string.h>
10
11 #include <bpf/bpf.h>
12 #include <bpf/libbpf.h>
13 #include "bpf_util.h"
14
15 #define SLOTS 100
16
17 static void clear_stats(int fd)
18 {
19         unsigned int nr_cpus = bpf_num_possible_cpus();
20         __u64 values[nr_cpus];
21         __u32 key;
22
23         memset(values, 0, sizeof(values));
24         for (key = 0; key < SLOTS; key++)
25                 bpf_map_update_elem(fd, &key, values, BPF_ANY);
26 }
27
28 const char *color[] = {
29         "\033[48;5;255m",
30         "\033[48;5;252m",
31         "\033[48;5;250m",
32         "\033[48;5;248m",
33         "\033[48;5;246m",
34         "\033[48;5;244m",
35         "\033[48;5;242m",
36         "\033[48;5;240m",
37         "\033[48;5;238m",
38         "\033[48;5;236m",
39         "\033[48;5;234m",
40         "\033[48;5;232m",
41 };
42 const int num_colors = ARRAY_SIZE(color);
43
44 const char nocolor[] = "\033[00m";
45
46 const char *sym[] = {
47         " ",
48         " ",
49         ".",
50         ".",
51         "*",
52         "*",
53         "o",
54         "o",
55         "O",
56         "O",
57         "#",
58         "#",
59 };
60
61 bool full_range = false;
62 bool text_only = false;
63
64 static void print_banner(void)
65 {
66         if (full_range)
67                 printf("|1ns     |10ns     |100ns    |1us      |10us     |100us"
68                        "    |1ms      |10ms     |100ms    |1s       |10s\n");
69         else
70                 printf("|1us      |10us     |100us    |1ms      |10ms     "
71                        "|100ms    |1s       |10s\n");
72 }
73
74 static void print_hist(int fd)
75 {
76         unsigned int nr_cpus = bpf_num_possible_cpus();
77         __u64 total_events = 0;
78         long values[nr_cpus];
79         __u64 max_cnt = 0;
80         __u64 cnt[SLOTS];
81         __u64 value;
82         __u32 key;
83         int i;
84
85         for (key = 0; key < SLOTS; key++) {
86                 bpf_map_lookup_elem(fd, &key, values);
87                 value = 0;
88                 for (i = 0; i < nr_cpus; i++)
89                         value += values[i];
90                 cnt[key] = value;
91                 total_events += value;
92                 if (value > max_cnt)
93                         max_cnt = value;
94         }
95         clear_stats(fd);
96         for (key = full_range ? 0 : 29; key < SLOTS; key++) {
97                 int c = num_colors * cnt[key] / (max_cnt + 1);
98
99                 if (text_only)
100                         printf("%s", sym[c]);
101                 else
102                         printf("%s %s", color[c], nocolor);
103         }
104         printf(" # %lld\n", total_events);
105 }
106
107 int main(int ac, char **argv)
108 {
109         struct bpf_link *links[2];
110         struct bpf_program *prog;
111         struct bpf_object *obj;
112         char filename[256];
113         int map_fd, i, j = 0;
114
115         for (i = 1; i < ac; i++) {
116                 if (strcmp(argv[i], "-a") == 0) {
117                         full_range = true;
118                 } else if (strcmp(argv[i], "-t") == 0) {
119                         text_only = true;
120                 } else if (strcmp(argv[i], "-h") == 0) {
121                         printf("Usage:\n"
122                                "  -a display wider latency range\n"
123                                "  -t text only\n");
124                         return 1;
125                 }
126         }
127
128         snprintf(filename, sizeof(filename), "%s.bpf.o", argv[0]);
129         obj = bpf_object__open_file(filename, NULL);
130         if (libbpf_get_error(obj)) {
131                 fprintf(stderr, "ERROR: opening BPF object file failed\n");
132                 return 0;
133         }
134
135         /* load BPF program */
136         if (bpf_object__load(obj)) {
137                 fprintf(stderr, "ERROR: loading BPF object file failed\n");
138                 goto cleanup;
139         }
140
141         map_fd = bpf_object__find_map_fd_by_name(obj, "lat_map");
142         if (map_fd < 0) {
143                 fprintf(stderr, "ERROR: finding a map in obj file failed\n");
144                 goto cleanup;
145         }
146
147         bpf_object__for_each_program(prog, obj) {
148                 links[j] = bpf_program__attach(prog);
149                 if (libbpf_get_error(links[j])) {
150                         fprintf(stderr, "ERROR: bpf_program__attach failed\n");
151                         links[j] = NULL;
152                         goto cleanup;
153                 }
154                 j++;
155         }
156
157         printf("  heatmap of IO latency\n");
158         if (text_only)
159                 printf("  %s", sym[num_colors - 1]);
160         else
161                 printf("  %s %s", color[num_colors - 1], nocolor);
162         printf(" - many events with this latency\n");
163
164         if (text_only)
165                 printf("  %s", sym[0]);
166         else
167                 printf("  %s %s", color[0], nocolor);
168         printf(" - few events\n");
169
170         for (i = 0; ; i++) {
171                 if (i % 20 == 0)
172                         print_banner();
173                 print_hist(map_fd);
174                 sleep(2);
175         }
176
177 cleanup:
178         for (j--; j >= 0; j--)
179                 bpf_link__destroy(links[j]);
180
181         bpf_object__close(obj);
182         return 0;
183 }