Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com
0003  */
0004 #include <stdio.h>
0005 #include <stdlib.h>
0006 #include <signal.h>
0007 #include <unistd.h>
0008 #include <stdbool.h>
0009 #include <string.h>
0010 
0011 #include <bpf/bpf.h>
0012 #include <bpf/libbpf.h>
0013 #include "bpf_util.h"
0014 
0015 #define SLOTS 100
0016 
0017 static void clear_stats(int fd)
0018 {
0019     unsigned int nr_cpus = bpf_num_possible_cpus();
0020     __u64 values[nr_cpus];
0021     __u32 key;
0022 
0023     memset(values, 0, sizeof(values));
0024     for (key = 0; key < SLOTS; key++)
0025         bpf_map_update_elem(fd, &key, values, BPF_ANY);
0026 }
0027 
0028 const char *color[] = {
0029     "\033[48;5;255m",
0030     "\033[48;5;252m",
0031     "\033[48;5;250m",
0032     "\033[48;5;248m",
0033     "\033[48;5;246m",
0034     "\033[48;5;244m",
0035     "\033[48;5;242m",
0036     "\033[48;5;240m",
0037     "\033[48;5;238m",
0038     "\033[48;5;236m",
0039     "\033[48;5;234m",
0040     "\033[48;5;232m",
0041 };
0042 const int num_colors = ARRAY_SIZE(color);
0043 
0044 const char nocolor[] = "\033[00m";
0045 
0046 const char *sym[] = {
0047     " ",
0048     " ",
0049     ".",
0050     ".",
0051     "*",
0052     "*",
0053     "o",
0054     "o",
0055     "O",
0056     "O",
0057     "#",
0058     "#",
0059 };
0060 
0061 bool full_range = false;
0062 bool text_only = false;
0063 
0064 static void print_banner(void)
0065 {
0066     if (full_range)
0067         printf("|1ns     |10ns     |100ns    |1us      |10us     |100us"
0068                "    |1ms      |10ms     |100ms    |1s       |10s\n");
0069     else
0070         printf("|1us      |10us     |100us    |1ms      |10ms     "
0071                "|100ms    |1s       |10s\n");
0072 }
0073 
0074 static void print_hist(int fd)
0075 {
0076     unsigned int nr_cpus = bpf_num_possible_cpus();
0077     __u64 total_events = 0;
0078     long values[nr_cpus];
0079     __u64 max_cnt = 0;
0080     __u64 cnt[SLOTS];
0081     __u64 value;
0082     __u32 key;
0083     int i;
0084 
0085     for (key = 0; key < SLOTS; key++) {
0086         bpf_map_lookup_elem(fd, &key, values);
0087         value = 0;
0088         for (i = 0; i < nr_cpus; i++)
0089             value += values[i];
0090         cnt[key] = value;
0091         total_events += value;
0092         if (value > max_cnt)
0093             max_cnt = value;
0094     }
0095     clear_stats(fd);
0096     for (key = full_range ? 0 : 29; key < SLOTS; key++) {
0097         int c = num_colors * cnt[key] / (max_cnt + 1);
0098 
0099         if (text_only)
0100             printf("%s", sym[c]);
0101         else
0102             printf("%s %s", color[c], nocolor);
0103     }
0104     printf(" # %lld\n", total_events);
0105 }
0106 
0107 int main(int ac, char **argv)
0108 {
0109     struct bpf_link *links[2];
0110     struct bpf_program *prog;
0111     struct bpf_object *obj;
0112     char filename[256];
0113     int map_fd, i, j = 0;
0114 
0115     for (i = 1; i < ac; i++) {
0116         if (strcmp(argv[i], "-a") == 0) {
0117             full_range = true;
0118         } else if (strcmp(argv[i], "-t") == 0) {
0119             text_only = true;
0120         } else if (strcmp(argv[i], "-h") == 0) {
0121             printf("Usage:\n"
0122                    "  -a display wider latency range\n"
0123                    "  -t text only\n");
0124             return 1;
0125         }
0126     }
0127 
0128     snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
0129     obj = bpf_object__open_file(filename, NULL);
0130     if (libbpf_get_error(obj)) {
0131         fprintf(stderr, "ERROR: opening BPF object file failed\n");
0132         return 0;
0133     }
0134 
0135     /* load BPF program */
0136     if (bpf_object__load(obj)) {
0137         fprintf(stderr, "ERROR: loading BPF object file failed\n");
0138         goto cleanup;
0139     }
0140 
0141     map_fd = bpf_object__find_map_fd_by_name(obj, "lat_map");
0142     if (map_fd < 0) {
0143         fprintf(stderr, "ERROR: finding a map in obj file failed\n");
0144         goto cleanup;
0145     }
0146 
0147     bpf_object__for_each_program(prog, obj) {
0148         links[j] = bpf_program__attach(prog);
0149         if (libbpf_get_error(links[j])) {
0150             fprintf(stderr, "ERROR: bpf_program__attach failed\n");
0151             links[j] = NULL;
0152             goto cleanup;
0153         }
0154         j++;
0155     }
0156 
0157     printf("  heatmap of IO latency\n");
0158     if (text_only)
0159         printf("  %s", sym[num_colors - 1]);
0160     else
0161         printf("  %s %s", color[num_colors - 1], nocolor);
0162     printf(" - many events with this latency\n");
0163 
0164     if (text_only)
0165         printf("  %s", sym[0]);
0166     else
0167         printf("  %s %s", color[0], nocolor);
0168     printf(" - few events\n");
0169 
0170     for (i = 0; ; i++) {
0171         if (i % 20 == 0)
0172             print_banner();
0173         print_hist(map_fd);
0174         sleep(2);
0175     }
0176 
0177 cleanup:
0178     for (j--; j >= 0; j--)
0179         bpf_link__destroy(links[j]);
0180 
0181     bpf_object__close(obj);
0182     return 0;
0183 }