xref: /openbmc/linux/samples/bpf/tracex2_user.c (revision a8fe58ce)
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 	char starstr[MAX_STARS];
41 	long value;
42 	long data[MAX_INDEX] = {};
43 	int max_ind = -1;
44 	long max_value = 0;
45 	int i, ind;
46 
47 	while (bpf_get_next_key(fd, &key, &next_key) == 0) {
48 		if (memcmp(&next_key, task, SIZE)) {
49 			key = next_key;
50 			continue;
51 		}
52 		bpf_lookup_elem(fd, &next_key, &value);
53 		ind = next_key.index;
54 		data[ind] = value;
55 		if (value && ind > max_ind)
56 			max_ind = ind;
57 		if (value > max_value)
58 			max_value = value;
59 		key = next_key;
60 	}
61 
62 	printf("           syscall write() stats\n");
63 	printf("     byte_size       : count     distribution\n");
64 	for (i = 1; i <= max_ind + 1; i++) {
65 		stars(starstr, data[i - 1], max_value, MAX_STARS);
66 		printf("%8ld -> %-8ld : %-8ld |%-*s|\n",
67 		       (1l << i) >> 1, (1l << i) - 1, data[i - 1],
68 		       MAX_STARS, starstr);
69 	}
70 }
71 
72 static void print_hist(int fd)
73 {
74 	struct hist_key key = {}, next_key;
75 	static struct task tasks[1024];
76 	int task_cnt = 0;
77 	int i;
78 
79 	while (bpf_get_next_key(fd, &key, &next_key) == 0) {
80 		int found = 0;
81 
82 		for (i = 0; i < task_cnt; i++)
83 			if (memcmp(&tasks[i], &next_key, SIZE) == 0)
84 				found = 1;
85 		if (!found)
86 			memcpy(&tasks[task_cnt++], &next_key, SIZE);
87 		key = next_key;
88 	}
89 
90 	for (i = 0; i < task_cnt; i++) {
91 		printf("\npid %d cmd %s uid %d\n",
92 		       (__u32) tasks[i].pid_tgid,
93 		       tasks[i].comm,
94 		       (__u32) tasks[i].uid_gid);
95 		print_hist_for_pid(fd, &tasks[i]);
96 	}
97 
98 }
99 
100 static void int_exit(int sig)
101 {
102 	print_hist(map_fd[1]);
103 	exit(0);
104 }
105 
106 int main(int ac, char **argv)
107 {
108 	char filename[256];
109 	long key, next_key, value;
110 	FILE *f;
111 	int i;
112 
113 	snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
114 
115 	signal(SIGINT, int_exit);
116 
117 	/* start 'ping' in the background to have some kfree_skb events */
118 	f = popen("ping -c5 localhost", "r");
119 	(void) f;
120 
121 	/* start 'dd' in the background to have plenty of 'write' syscalls */
122 	f = popen("dd if=/dev/zero of=/dev/null count=5000000", "r");
123 	(void) f;
124 
125 	if (load_bpf_file(filename)) {
126 		printf("%s", bpf_log_buf);
127 		return 1;
128 	}
129 
130 	for (i = 0; i < 5; i++) {
131 		key = 0;
132 		while (bpf_get_next_key(map_fd[0], &key, &next_key) == 0) {
133 			bpf_lookup_elem(map_fd[0], &next_key, &value);
134 			printf("location 0x%lx count %ld\n", next_key, value);
135 			key = next_key;
136 		}
137 		if (key)
138 			printf("\n");
139 		sleep(1);
140 	}
141 	print_hist(map_fd[1]);
142 
143 	return 0;
144 }
145