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