0001
0002 #include <stdio.h>
0003 #include <unistd.h>
0004 #include <stdlib.h>
0005 #include <signal.h>
0006 #include <string.h>
0007
0008 #include <bpf/bpf.h>
0009 #include <bpf/libbpf.h>
0010 #include "bpf_util.h"
0011
0012 #define MAX_INDEX 64
0013 #define MAX_STARS 38
0014
0015
0016 static int map_fd[2];
0017
0018 static void stars(char *str, long val, long max, int width)
0019 {
0020 int i;
0021
0022 for (i = 0; i < (width * val / max) - 1 && i < width - 1; i++)
0023 str[i] = '*';
0024 if (val > max)
0025 str[i - 1] = '+';
0026 str[i] = '\0';
0027 }
0028
0029 struct task {
0030 char comm[16];
0031 __u64 pid_tgid;
0032 __u64 uid_gid;
0033 };
0034
0035 struct hist_key {
0036 struct task t;
0037 __u32 index;
0038 };
0039
0040 #define SIZE sizeof(struct task)
0041
0042 static void print_hist_for_pid(int fd, void *task)
0043 {
0044 unsigned int nr_cpus = bpf_num_possible_cpus();
0045 struct hist_key key = {}, next_key;
0046 long values[nr_cpus];
0047 char starstr[MAX_STARS];
0048 long value;
0049 long data[MAX_INDEX] = {};
0050 int max_ind = -1;
0051 long max_value = 0;
0052 int i, ind;
0053
0054 while (bpf_map_get_next_key(fd, &key, &next_key) == 0) {
0055 if (memcmp(&next_key, task, SIZE)) {
0056 key = next_key;
0057 continue;
0058 }
0059 bpf_map_lookup_elem(fd, &next_key, values);
0060 value = 0;
0061 for (i = 0; i < nr_cpus; i++)
0062 value += values[i];
0063 ind = next_key.index;
0064 data[ind] = value;
0065 if (value && ind > max_ind)
0066 max_ind = ind;
0067 if (value > max_value)
0068 max_value = value;
0069 key = next_key;
0070 }
0071
0072 printf(" syscall write() stats\n");
0073 printf(" byte_size : count distribution\n");
0074 for (i = 1; i <= max_ind + 1; i++) {
0075 stars(starstr, data[i - 1], max_value, MAX_STARS);
0076 printf("%8ld -> %-8ld : %-8ld |%-*s|\n",
0077 (1l << i) >> 1, (1l << i) - 1, data[i - 1],
0078 MAX_STARS, starstr);
0079 }
0080 }
0081
0082 static void print_hist(int fd)
0083 {
0084 struct hist_key key = {}, next_key;
0085 static struct task tasks[1024];
0086 int task_cnt = 0;
0087 int i;
0088
0089 while (bpf_map_get_next_key(fd, &key, &next_key) == 0) {
0090 int found = 0;
0091
0092 for (i = 0; i < task_cnt; i++)
0093 if (memcmp(&tasks[i], &next_key, SIZE) == 0)
0094 found = 1;
0095 if (!found)
0096 memcpy(&tasks[task_cnt++], &next_key, SIZE);
0097 key = next_key;
0098 }
0099
0100 for (i = 0; i < task_cnt; i++) {
0101 printf("\npid %d cmd %s uid %d\n",
0102 (__u32) tasks[i].pid_tgid,
0103 tasks[i].comm,
0104 (__u32) tasks[i].uid_gid);
0105 print_hist_for_pid(fd, &tasks[i]);
0106 }
0107
0108 }
0109
0110 static void int_exit(int sig)
0111 {
0112 print_hist(map_fd[1]);
0113 exit(0);
0114 }
0115
0116 int main(int ac, char **argv)
0117 {
0118 long key, next_key, value;
0119 struct bpf_link *links[2];
0120 struct bpf_program *prog;
0121 struct bpf_object *obj;
0122 char filename[256];
0123 int i, j = 0;
0124 FILE *f;
0125
0126 snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
0127 obj = bpf_object__open_file(filename, NULL);
0128 if (libbpf_get_error(obj)) {
0129 fprintf(stderr, "ERROR: opening BPF object file failed\n");
0130 return 0;
0131 }
0132
0133
0134 if (bpf_object__load(obj)) {
0135 fprintf(stderr, "ERROR: loading BPF object file failed\n");
0136 goto cleanup;
0137 }
0138
0139 map_fd[0] = bpf_object__find_map_fd_by_name(obj, "my_map");
0140 map_fd[1] = bpf_object__find_map_fd_by_name(obj, "my_hist_map");
0141 if (map_fd[0] < 0 || map_fd[1] < 0) {
0142 fprintf(stderr, "ERROR: finding a map in obj file failed\n");
0143 goto cleanup;
0144 }
0145
0146 signal(SIGINT, int_exit);
0147 signal(SIGTERM, int_exit);
0148
0149
0150 f = popen("ping -4 -c5 localhost", "r");
0151 (void) f;
0152
0153
0154 f = popen("dd if=/dev/zero of=/dev/null count=5000000", "r");
0155 (void) f;
0156
0157 bpf_object__for_each_program(prog, obj) {
0158 links[j] = bpf_program__attach(prog);
0159 if (libbpf_get_error(links[j])) {
0160 fprintf(stderr, "ERROR: bpf_program__attach failed\n");
0161 links[j] = NULL;
0162 goto cleanup;
0163 }
0164 j++;
0165 }
0166
0167 for (i = 0; i < 5; i++) {
0168 key = 0;
0169 while (bpf_map_get_next_key(map_fd[0], &key, &next_key) == 0) {
0170 bpf_map_lookup_elem(map_fd[0], &next_key, &value);
0171 printf("location 0x%lx count %ld\n", next_key, value);
0172 key = next_key;
0173 }
0174 if (key)
0175 printf("\n");
0176 sleep(1);
0177 }
0178 print_hist(map_fd[1]);
0179
0180 cleanup:
0181 for (j--; j >= 0; j--)
0182 bpf_link__destroy(links[j]);
0183
0184 bpf_object__close(obj);
0185 return 0;
0186 }