131 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com3 * Copyright (c) 2015 BMW Car IT GmbH4 */5#include <stdio.h>6#include <unistd.h>7#include <stdlib.h>8#include <signal.h>9#include <bpf/libbpf.h>10#include <bpf/bpf.h>11 12#define MAX_ENTRIES 2013#define MAX_CPU 414#define MAX_STARS 4015 16struct cpu_hist {17 long data[MAX_ENTRIES];18 long max;19};20 21static struct cpu_hist cpu_hist[MAX_CPU];22 23static void stars(char *str, long val, long max, int width)24{25 int i;26 27 for (i = 0; i < (width * val / max) - 1 && i < width - 1; i++)28 str[i] = '*';29 if (val > max)30 str[i - 1] = '+';31 str[i] = '\0';32}33 34static void print_hist(void)35{36 char starstr[MAX_STARS];37 struct cpu_hist *hist;38 int i, j;39 40 /* clear screen */41 printf("\033[2J");42 43 for (j = 0; j < MAX_CPU; j++) {44 hist = &cpu_hist[j];45 46 /* ignore CPUs without data (maybe offline?) */47 if (hist->max == 0)48 continue;49 50 printf("CPU %d\n", j);51 printf(" latency : count distribution\n");52 for (i = 1; i <= MAX_ENTRIES; i++) {53 stars(starstr, hist->data[i - 1], hist->max, MAX_STARS);54 printf("%8ld -> %-8ld : %-8ld |%-*s|\n",55 (1l << i) >> 1, (1l << i) - 1,56 hist->data[i - 1], MAX_STARS, starstr);57 }58 }59}60 61static void get_data(int fd)62{63 long key, value;64 int c, i;65 66 for (i = 0; i < MAX_CPU; i++)67 cpu_hist[i].max = 0;68 69 for (c = 0; c < MAX_CPU; c++) {70 for (i = 0; i < MAX_ENTRIES; i++) {71 key = c * MAX_ENTRIES + i;72 bpf_map_lookup_elem(fd, &key, &value);73 74 cpu_hist[c].data[i] = value;75 if (value > cpu_hist[c].max)76 cpu_hist[c].max = value;77 }78 }79}80 81int main(int argc, char **argv)82{83 struct bpf_link *links[2];84 struct bpf_program *prog;85 struct bpf_object *obj;86 char filename[256];87 int map_fd, i = 0;88 89 snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);90 obj = bpf_object__open_file(filename, NULL);91 if (libbpf_get_error(obj)) {92 fprintf(stderr, "ERROR: opening BPF object file failed\n");93 return 0;94 }95 96 /* load BPF program */97 if (bpf_object__load(obj)) {98 fprintf(stderr, "ERROR: loading BPF object file failed\n");99 goto cleanup;100 }101 102 map_fd = bpf_object__find_map_fd_by_name(obj, "my_lat");103 if (map_fd < 0) {104 fprintf(stderr, "ERROR: finding a map in obj file failed\n");105 goto cleanup;106 }107 108 bpf_object__for_each_program(prog, obj) {109 links[i] = bpf_program__attach(prog);110 if (libbpf_get_error(links[i])) {111 fprintf(stderr, "ERROR: bpf_program__attach failed\n");112 links[i] = NULL;113 goto cleanup;114 }115 i++;116 }117 118 while (1) {119 get_data(map_fd);120 print_hist();121 sleep(5);122 }123 124cleanup:125 for (i--; i >= 0; i--)126 bpf_link__destroy(links[i]);127 128 bpf_object__close(obj);129 return 0;130}131