162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com 362306a36Sopenharmony_ci */ 462306a36Sopenharmony_ci#include <stdio.h> 562306a36Sopenharmony_ci#include <stdlib.h> 662306a36Sopenharmony_ci#include <signal.h> 762306a36Sopenharmony_ci#include <unistd.h> 862306a36Sopenharmony_ci#include <stdbool.h> 962306a36Sopenharmony_ci#include <string.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <bpf/bpf.h> 1262306a36Sopenharmony_ci#include <bpf/libbpf.h> 1362306a36Sopenharmony_ci#include "bpf_util.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#define SLOTS 100 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_cistatic void clear_stats(int fd) 1862306a36Sopenharmony_ci{ 1962306a36Sopenharmony_ci unsigned int nr_cpus = bpf_num_possible_cpus(); 2062306a36Sopenharmony_ci __u64 values[nr_cpus]; 2162306a36Sopenharmony_ci __u32 key; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci memset(values, 0, sizeof(values)); 2462306a36Sopenharmony_ci for (key = 0; key < SLOTS; key++) 2562306a36Sopenharmony_ci bpf_map_update_elem(fd, &key, values, BPF_ANY); 2662306a36Sopenharmony_ci} 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ciconst char *color[] = { 2962306a36Sopenharmony_ci "\033[48;5;255m", 3062306a36Sopenharmony_ci "\033[48;5;252m", 3162306a36Sopenharmony_ci "\033[48;5;250m", 3262306a36Sopenharmony_ci "\033[48;5;248m", 3362306a36Sopenharmony_ci "\033[48;5;246m", 3462306a36Sopenharmony_ci "\033[48;5;244m", 3562306a36Sopenharmony_ci "\033[48;5;242m", 3662306a36Sopenharmony_ci "\033[48;5;240m", 3762306a36Sopenharmony_ci "\033[48;5;238m", 3862306a36Sopenharmony_ci "\033[48;5;236m", 3962306a36Sopenharmony_ci "\033[48;5;234m", 4062306a36Sopenharmony_ci "\033[48;5;232m", 4162306a36Sopenharmony_ci}; 4262306a36Sopenharmony_ciconst int num_colors = ARRAY_SIZE(color); 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ciconst char nocolor[] = "\033[00m"; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ciconst char *sym[] = { 4762306a36Sopenharmony_ci " ", 4862306a36Sopenharmony_ci " ", 4962306a36Sopenharmony_ci ".", 5062306a36Sopenharmony_ci ".", 5162306a36Sopenharmony_ci "*", 5262306a36Sopenharmony_ci "*", 5362306a36Sopenharmony_ci "o", 5462306a36Sopenharmony_ci "o", 5562306a36Sopenharmony_ci "O", 5662306a36Sopenharmony_ci "O", 5762306a36Sopenharmony_ci "#", 5862306a36Sopenharmony_ci "#", 5962306a36Sopenharmony_ci}; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cibool full_range = false; 6262306a36Sopenharmony_cibool text_only = false; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic void print_banner(void) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci if (full_range) 6762306a36Sopenharmony_ci printf("|1ns |10ns |100ns |1us |10us |100us" 6862306a36Sopenharmony_ci " |1ms |10ms |100ms |1s |10s\n"); 6962306a36Sopenharmony_ci else 7062306a36Sopenharmony_ci printf("|1us |10us |100us |1ms |10ms " 7162306a36Sopenharmony_ci "|100ms |1s |10s\n"); 7262306a36Sopenharmony_ci} 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_cistatic void print_hist(int fd) 7562306a36Sopenharmony_ci{ 7662306a36Sopenharmony_ci unsigned int nr_cpus = bpf_num_possible_cpus(); 7762306a36Sopenharmony_ci __u64 total_events = 0; 7862306a36Sopenharmony_ci long values[nr_cpus]; 7962306a36Sopenharmony_ci __u64 max_cnt = 0; 8062306a36Sopenharmony_ci __u64 cnt[SLOTS]; 8162306a36Sopenharmony_ci __u64 value; 8262306a36Sopenharmony_ci __u32 key; 8362306a36Sopenharmony_ci int i; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci for (key = 0; key < SLOTS; key++) { 8662306a36Sopenharmony_ci bpf_map_lookup_elem(fd, &key, values); 8762306a36Sopenharmony_ci value = 0; 8862306a36Sopenharmony_ci for (i = 0; i < nr_cpus; i++) 8962306a36Sopenharmony_ci value += values[i]; 9062306a36Sopenharmony_ci cnt[key] = value; 9162306a36Sopenharmony_ci total_events += value; 9262306a36Sopenharmony_ci if (value > max_cnt) 9362306a36Sopenharmony_ci max_cnt = value; 9462306a36Sopenharmony_ci } 9562306a36Sopenharmony_ci clear_stats(fd); 9662306a36Sopenharmony_ci for (key = full_range ? 0 : 29; key < SLOTS; key++) { 9762306a36Sopenharmony_ci int c = num_colors * cnt[key] / (max_cnt + 1); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci if (text_only) 10062306a36Sopenharmony_ci printf("%s", sym[c]); 10162306a36Sopenharmony_ci else 10262306a36Sopenharmony_ci printf("%s %s", color[c], nocolor); 10362306a36Sopenharmony_ci } 10462306a36Sopenharmony_ci printf(" # %lld\n", total_events); 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ciint main(int ac, char **argv) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci struct bpf_link *links[2]; 11062306a36Sopenharmony_ci struct bpf_program *prog; 11162306a36Sopenharmony_ci struct bpf_object *obj; 11262306a36Sopenharmony_ci char filename[256]; 11362306a36Sopenharmony_ci int map_fd, i, j = 0; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci for (i = 1; i < ac; i++) { 11662306a36Sopenharmony_ci if (strcmp(argv[i], "-a") == 0) { 11762306a36Sopenharmony_ci full_range = true; 11862306a36Sopenharmony_ci } else if (strcmp(argv[i], "-t") == 0) { 11962306a36Sopenharmony_ci text_only = true; 12062306a36Sopenharmony_ci } else if (strcmp(argv[i], "-h") == 0) { 12162306a36Sopenharmony_ci printf("Usage:\n" 12262306a36Sopenharmony_ci " -a display wider latency range\n" 12362306a36Sopenharmony_ci " -t text only\n"); 12462306a36Sopenharmony_ci return 1; 12562306a36Sopenharmony_ci } 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci snprintf(filename, sizeof(filename), "%s.bpf.o", argv[0]); 12962306a36Sopenharmony_ci obj = bpf_object__open_file(filename, NULL); 13062306a36Sopenharmony_ci if (libbpf_get_error(obj)) { 13162306a36Sopenharmony_ci fprintf(stderr, "ERROR: opening BPF object file failed\n"); 13262306a36Sopenharmony_ci return 0; 13362306a36Sopenharmony_ci } 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci /* load BPF program */ 13662306a36Sopenharmony_ci if (bpf_object__load(obj)) { 13762306a36Sopenharmony_ci fprintf(stderr, "ERROR: loading BPF object file failed\n"); 13862306a36Sopenharmony_ci goto cleanup; 13962306a36Sopenharmony_ci } 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci map_fd = bpf_object__find_map_fd_by_name(obj, "lat_map"); 14262306a36Sopenharmony_ci if (map_fd < 0) { 14362306a36Sopenharmony_ci fprintf(stderr, "ERROR: finding a map in obj file failed\n"); 14462306a36Sopenharmony_ci goto cleanup; 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci bpf_object__for_each_program(prog, obj) { 14862306a36Sopenharmony_ci links[j] = bpf_program__attach(prog); 14962306a36Sopenharmony_ci if (libbpf_get_error(links[j])) { 15062306a36Sopenharmony_ci fprintf(stderr, "ERROR: bpf_program__attach failed\n"); 15162306a36Sopenharmony_ci links[j] = NULL; 15262306a36Sopenharmony_ci goto cleanup; 15362306a36Sopenharmony_ci } 15462306a36Sopenharmony_ci j++; 15562306a36Sopenharmony_ci } 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci printf(" heatmap of IO latency\n"); 15862306a36Sopenharmony_ci if (text_only) 15962306a36Sopenharmony_ci printf(" %s", sym[num_colors - 1]); 16062306a36Sopenharmony_ci else 16162306a36Sopenharmony_ci printf(" %s %s", color[num_colors - 1], nocolor); 16262306a36Sopenharmony_ci printf(" - many events with this latency\n"); 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci if (text_only) 16562306a36Sopenharmony_ci printf(" %s", sym[0]); 16662306a36Sopenharmony_ci else 16762306a36Sopenharmony_ci printf(" %s %s", color[0], nocolor); 16862306a36Sopenharmony_ci printf(" - few events\n"); 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci for (i = 0; ; i++) { 17162306a36Sopenharmony_ci if (i % 20 == 0) 17262306a36Sopenharmony_ci print_banner(); 17362306a36Sopenharmony_ci print_hist(map_fd); 17462306a36Sopenharmony_ci sleep(2); 17562306a36Sopenharmony_ci } 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_cicleanup: 17862306a36Sopenharmony_ci for (j--; j >= 0; j--) 17962306a36Sopenharmony_ci bpf_link__destroy(links[j]); 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci bpf_object__close(obj); 18262306a36Sopenharmony_ci return 0; 18362306a36Sopenharmony_ci} 184