0001
0002
0003
0004
0005 #include <stdio.h>
0006 #include <unistd.h>
0007 #include <stdlib.h>
0008 #include <signal.h>
0009 #include <bpf/libbpf.h>
0010 #include <bpf/bpf.h>
0011
0012 #define MAX_ENTRIES 20
0013 #define MAX_CPU 4
0014 #define MAX_STARS 40
0015
0016 struct cpu_hist {
0017 long data[MAX_ENTRIES];
0018 long max;
0019 };
0020
0021 static struct cpu_hist cpu_hist[MAX_CPU];
0022
0023 static void stars(char *str, long val, long max, int width)
0024 {
0025 int i;
0026
0027 for (i = 0; i < (width * val / max) - 1 && i < width - 1; i++)
0028 str[i] = '*';
0029 if (val > max)
0030 str[i - 1] = '+';
0031 str[i] = '\0';
0032 }
0033
0034 static void print_hist(void)
0035 {
0036 char starstr[MAX_STARS];
0037 struct cpu_hist *hist;
0038 int i, j;
0039
0040
0041 printf("\033[2J");
0042
0043 for (j = 0; j < MAX_CPU; j++) {
0044 hist = &cpu_hist[j];
0045
0046
0047 if (hist->max == 0)
0048 continue;
0049
0050 printf("CPU %d\n", j);
0051 printf(" latency : count distribution\n");
0052 for (i = 1; i <= MAX_ENTRIES; i++) {
0053 stars(starstr, hist->data[i - 1], hist->max, MAX_STARS);
0054 printf("%8ld -> %-8ld : %-8ld |%-*s|\n",
0055 (1l << i) >> 1, (1l << i) - 1,
0056 hist->data[i - 1], MAX_STARS, starstr);
0057 }
0058 }
0059 }
0060
0061 static void get_data(int fd)
0062 {
0063 long key, value;
0064 int c, i;
0065
0066 for (i = 0; i < MAX_CPU; i++)
0067 cpu_hist[i].max = 0;
0068
0069 for (c = 0; c < MAX_CPU; c++) {
0070 for (i = 0; i < MAX_ENTRIES; i++) {
0071 key = c * MAX_ENTRIES + i;
0072 bpf_map_lookup_elem(fd, &key, &value);
0073
0074 cpu_hist[c].data[i] = value;
0075 if (value > cpu_hist[c].max)
0076 cpu_hist[c].max = value;
0077 }
0078 }
0079 }
0080
0081 int main(int argc, char **argv)
0082 {
0083 struct bpf_link *links[2];
0084 struct bpf_program *prog;
0085 struct bpf_object *obj;
0086 char filename[256];
0087 int map_fd, i = 0;
0088
0089 snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
0090 obj = bpf_object__open_file(filename, NULL);
0091 if (libbpf_get_error(obj)) {
0092 fprintf(stderr, "ERROR: opening BPF object file failed\n");
0093 return 0;
0094 }
0095
0096
0097 if (bpf_object__load(obj)) {
0098 fprintf(stderr, "ERROR: loading BPF object file failed\n");
0099 goto cleanup;
0100 }
0101
0102 map_fd = bpf_object__find_map_fd_by_name(obj, "my_lat");
0103 if (map_fd < 0) {
0104 fprintf(stderr, "ERROR: finding a map in obj file failed\n");
0105 goto cleanup;
0106 }
0107
0108 bpf_object__for_each_program(prog, obj) {
0109 links[i] = bpf_program__attach(prog);
0110 if (libbpf_get_error(links[i])) {
0111 fprintf(stderr, "ERROR: bpf_program__attach failed\n");
0112 links[i] = NULL;
0113 goto cleanup;
0114 }
0115 i++;
0116 }
0117
0118 while (1) {
0119 get_data(map_fd);
0120 print_hist();
0121 sleep(5);
0122 }
0123
0124 cleanup:
0125 for (i--; i >= 0; i--)
0126 bpf_link__destroy(links[i]);
0127
0128 bpf_object__close(obj);
0129 return 0;
0130 }