1 #include <stdio.h> 2 #include <unistd.h> 3 #include <stdlib.h> 4 #include <signal.h> 5 #include <linux/bpf.h> 6 #include <string.h> 7 #include "libbpf.h" 8 #include "bpf_load.h" 9 10 #define MAX_INDEX 64 11 #define MAX_STARS 38 12 13 static void stars(char *str, long val, long max, int width) 14 { 15 int i; 16 17 for (i = 0; i < (width * val / max) - 1 && i < width - 1; i++) 18 str[i] = '*'; 19 if (val > max) 20 str[i - 1] = '+'; 21 str[i] = '\0'; 22 } 23 24 struct task { 25 char comm[16]; 26 __u64 pid_tgid; 27 __u64 uid_gid; 28 }; 29 30 struct hist_key { 31 struct task t; 32 __u32 index; 33 }; 34 35 #define SIZE sizeof(struct task) 36 37 static void print_hist_for_pid(int fd, void *task) 38 { 39 struct hist_key key = {}, next_key; 40 unsigned int nr_cpus = sysconf(_SC_NPROCESSORS_CONF); 41 long values[nr_cpus]; 42 char starstr[MAX_STARS]; 43 long value; 44 long data[MAX_INDEX] = {}; 45 int max_ind = -1; 46 long max_value = 0; 47 int i, ind; 48 49 while (bpf_get_next_key(fd, &key, &next_key) == 0) { 50 if (memcmp(&next_key, task, SIZE)) { 51 key = next_key; 52 continue; 53 } 54 bpf_lookup_elem(fd, &next_key, values); 55 value = 0; 56 for (i = 0; i < nr_cpus; i++) 57 value += values[i]; 58 ind = next_key.index; 59 data[ind] = value; 60 if (value && ind > max_ind) 61 max_ind = ind; 62 if (value > max_value) 63 max_value = value; 64 key = next_key; 65 } 66 67 printf(" syscall write() stats\n"); 68 printf(" byte_size : count distribution\n"); 69 for (i = 1; i <= max_ind + 1; i++) { 70 stars(starstr, data[i - 1], max_value, MAX_STARS); 71 printf("%8ld -> %-8ld : %-8ld |%-*s|\n", 72 (1l << i) >> 1, (1l << i) - 1, data[i - 1], 73 MAX_STARS, starstr); 74 } 75 } 76 77 static void print_hist(int fd) 78 { 79 struct hist_key key = {}, next_key; 80 static struct task tasks[1024]; 81 int task_cnt = 0; 82 int i; 83 84 while (bpf_get_next_key(fd, &key, &next_key) == 0) { 85 int found = 0; 86 87 for (i = 0; i < task_cnt; i++) 88 if (memcmp(&tasks[i], &next_key, SIZE) == 0) 89 found = 1; 90 if (!found) 91 memcpy(&tasks[task_cnt++], &next_key, SIZE); 92 key = next_key; 93 } 94 95 for (i = 0; i < task_cnt; i++) { 96 printf("\npid %d cmd %s uid %d\n", 97 (__u32) tasks[i].pid_tgid, 98 tasks[i].comm, 99 (__u32) tasks[i].uid_gid); 100 print_hist_for_pid(fd, &tasks[i]); 101 } 102 103 } 104 105 static void int_exit(int sig) 106 { 107 print_hist(map_fd[1]); 108 exit(0); 109 } 110 111 int main(int ac, char **argv) 112 { 113 char filename[256]; 114 long key, next_key, value; 115 FILE *f; 116 int i; 117 118 snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); 119 120 signal(SIGINT, int_exit); 121 122 /* start 'ping' in the background to have some kfree_skb events */ 123 f = popen("ping -c5 localhost", "r"); 124 (void) f; 125 126 /* start 'dd' in the background to have plenty of 'write' syscalls */ 127 f = popen("dd if=/dev/zero of=/dev/null count=5000000", "r"); 128 (void) f; 129 130 if (load_bpf_file(filename)) { 131 printf("%s", bpf_log_buf); 132 return 1; 133 } 134 135 for (i = 0; i < 5; i++) { 136 key = 0; 137 while (bpf_get_next_key(map_fd[0], &key, &next_key) == 0) { 138 bpf_lookup_elem(map_fd[0], &next_key, &value); 139 printf("location 0x%lx count %ld\n", next_key, value); 140 key = next_key; 141 } 142 if (key) 143 printf("\n"); 144 sleep(1); 145 } 146 print_hist(map_fd[1]); 147 148 return 0; 149 } 150