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