162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com 362306a36Sopenharmony_ci * Copyright (c) 2015 BMW Car IT GmbH 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci#include <stdio.h> 662306a36Sopenharmony_ci#include <unistd.h> 762306a36Sopenharmony_ci#include <stdlib.h> 862306a36Sopenharmony_ci#include <signal.h> 962306a36Sopenharmony_ci#include <bpf/libbpf.h> 1062306a36Sopenharmony_ci#include <bpf/bpf.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#define MAX_ENTRIES 20 1362306a36Sopenharmony_ci#define MAX_CPU 4 1462306a36Sopenharmony_ci#define MAX_STARS 40 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_cistruct cpu_hist { 1762306a36Sopenharmony_ci long data[MAX_ENTRIES]; 1862306a36Sopenharmony_ci long max; 1962306a36Sopenharmony_ci}; 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cistatic struct cpu_hist cpu_hist[MAX_CPU]; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic void stars(char *str, long val, long max, int width) 2462306a36Sopenharmony_ci{ 2562306a36Sopenharmony_ci int i; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci for (i = 0; i < (width * val / max) - 1 && i < width - 1; i++) 2862306a36Sopenharmony_ci str[i] = '*'; 2962306a36Sopenharmony_ci if (val > max) 3062306a36Sopenharmony_ci str[i - 1] = '+'; 3162306a36Sopenharmony_ci str[i] = '\0'; 3262306a36Sopenharmony_ci} 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic void print_hist(void) 3562306a36Sopenharmony_ci{ 3662306a36Sopenharmony_ci char starstr[MAX_STARS]; 3762306a36Sopenharmony_ci struct cpu_hist *hist; 3862306a36Sopenharmony_ci int i, j; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci /* clear screen */ 4162306a36Sopenharmony_ci printf("\033[2J"); 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci for (j = 0; j < MAX_CPU; j++) { 4462306a36Sopenharmony_ci hist = &cpu_hist[j]; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci /* ignore CPUs without data (maybe offline?) */ 4762306a36Sopenharmony_ci if (hist->max == 0) 4862306a36Sopenharmony_ci continue; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci printf("CPU %d\n", j); 5162306a36Sopenharmony_ci printf(" latency : count distribution\n"); 5262306a36Sopenharmony_ci for (i = 1; i <= MAX_ENTRIES; i++) { 5362306a36Sopenharmony_ci stars(starstr, hist->data[i - 1], hist->max, MAX_STARS); 5462306a36Sopenharmony_ci printf("%8ld -> %-8ld : %-8ld |%-*s|\n", 5562306a36Sopenharmony_ci (1l << i) >> 1, (1l << i) - 1, 5662306a36Sopenharmony_ci hist->data[i - 1], MAX_STARS, starstr); 5762306a36Sopenharmony_ci } 5862306a36Sopenharmony_ci } 5962306a36Sopenharmony_ci} 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cistatic void get_data(int fd) 6262306a36Sopenharmony_ci{ 6362306a36Sopenharmony_ci long key, value; 6462306a36Sopenharmony_ci int c, i; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci for (i = 0; i < MAX_CPU; i++) 6762306a36Sopenharmony_ci cpu_hist[i].max = 0; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci for (c = 0; c < MAX_CPU; c++) { 7062306a36Sopenharmony_ci for (i = 0; i < MAX_ENTRIES; i++) { 7162306a36Sopenharmony_ci key = c * MAX_ENTRIES + i; 7262306a36Sopenharmony_ci bpf_map_lookup_elem(fd, &key, &value); 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci cpu_hist[c].data[i] = value; 7562306a36Sopenharmony_ci if (value > cpu_hist[c].max) 7662306a36Sopenharmony_ci cpu_hist[c].max = value; 7762306a36Sopenharmony_ci } 7862306a36Sopenharmony_ci } 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ciint main(int argc, char **argv) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci struct bpf_link *links[2]; 8462306a36Sopenharmony_ci struct bpf_program *prog; 8562306a36Sopenharmony_ci struct bpf_object *obj; 8662306a36Sopenharmony_ci char filename[256]; 8762306a36Sopenharmony_ci int map_fd, i = 0; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); 9062306a36Sopenharmony_ci obj = bpf_object__open_file(filename, NULL); 9162306a36Sopenharmony_ci if (libbpf_get_error(obj)) { 9262306a36Sopenharmony_ci fprintf(stderr, "ERROR: opening BPF object file failed\n"); 9362306a36Sopenharmony_ci return 0; 9462306a36Sopenharmony_ci } 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci /* load BPF program */ 9762306a36Sopenharmony_ci if (bpf_object__load(obj)) { 9862306a36Sopenharmony_ci fprintf(stderr, "ERROR: loading BPF object file failed\n"); 9962306a36Sopenharmony_ci goto cleanup; 10062306a36Sopenharmony_ci } 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci map_fd = bpf_object__find_map_fd_by_name(obj, "my_lat"); 10362306a36Sopenharmony_ci if (map_fd < 0) { 10462306a36Sopenharmony_ci fprintf(stderr, "ERROR: finding a map in obj file failed\n"); 10562306a36Sopenharmony_ci goto cleanup; 10662306a36Sopenharmony_ci } 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci bpf_object__for_each_program(prog, obj) { 10962306a36Sopenharmony_ci links[i] = bpf_program__attach(prog); 11062306a36Sopenharmony_ci if (libbpf_get_error(links[i])) { 11162306a36Sopenharmony_ci fprintf(stderr, "ERROR: bpf_program__attach failed\n"); 11262306a36Sopenharmony_ci links[i] = NULL; 11362306a36Sopenharmony_ci goto cleanup; 11462306a36Sopenharmony_ci } 11562306a36Sopenharmony_ci i++; 11662306a36Sopenharmony_ci } 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci while (1) { 11962306a36Sopenharmony_ci get_data(map_fd); 12062306a36Sopenharmony_ci print_hist(); 12162306a36Sopenharmony_ci sleep(5); 12262306a36Sopenharmony_ci } 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cicleanup: 12562306a36Sopenharmony_ci for (i--; i >= 0; i--) 12662306a36Sopenharmony_ci bpf_link__destroy(links[i]); 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci bpf_object__close(obj); 12962306a36Sopenharmony_ci return 0; 13062306a36Sopenharmony_ci} 131