18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include <stdio.h> 38c2ecf20Sopenharmony_ci#include <unistd.h> 48c2ecf20Sopenharmony_ci#include <stdlib.h> 58c2ecf20Sopenharmony_ci#include <signal.h> 68c2ecf20Sopenharmony_ci#include <string.h> 78c2ecf20Sopenharmony_ci#include <sys/resource.h> 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <bpf/bpf.h> 108c2ecf20Sopenharmony_ci#include <bpf/libbpf.h> 118c2ecf20Sopenharmony_ci#include "bpf_util.h" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#define MAX_INDEX 64 148c2ecf20Sopenharmony_ci#define MAX_STARS 38 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci/* my_map, my_hist_map */ 178c2ecf20Sopenharmony_cistatic int map_fd[2]; 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cistatic void stars(char *str, long val, long max, int width) 208c2ecf20Sopenharmony_ci{ 218c2ecf20Sopenharmony_ci int i; 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci for (i = 0; i < (width * val / max) - 1 && i < width - 1; i++) 248c2ecf20Sopenharmony_ci str[i] = '*'; 258c2ecf20Sopenharmony_ci if (val > max) 268c2ecf20Sopenharmony_ci str[i - 1] = '+'; 278c2ecf20Sopenharmony_ci str[i] = '\0'; 288c2ecf20Sopenharmony_ci} 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistruct task { 318c2ecf20Sopenharmony_ci char comm[16]; 328c2ecf20Sopenharmony_ci __u64 pid_tgid; 338c2ecf20Sopenharmony_ci __u64 uid_gid; 348c2ecf20Sopenharmony_ci}; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistruct hist_key { 378c2ecf20Sopenharmony_ci struct task t; 388c2ecf20Sopenharmony_ci __u32 index; 398c2ecf20Sopenharmony_ci}; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci#define SIZE sizeof(struct task) 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_cistatic void print_hist_for_pid(int fd, void *task) 448c2ecf20Sopenharmony_ci{ 458c2ecf20Sopenharmony_ci unsigned int nr_cpus = bpf_num_possible_cpus(); 468c2ecf20Sopenharmony_ci struct hist_key key = {}, next_key; 478c2ecf20Sopenharmony_ci long values[nr_cpus]; 488c2ecf20Sopenharmony_ci char starstr[MAX_STARS]; 498c2ecf20Sopenharmony_ci long value; 508c2ecf20Sopenharmony_ci long data[MAX_INDEX] = {}; 518c2ecf20Sopenharmony_ci int max_ind = -1; 528c2ecf20Sopenharmony_ci long max_value = 0; 538c2ecf20Sopenharmony_ci int i, ind; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci while (bpf_map_get_next_key(fd, &key, &next_key) == 0) { 568c2ecf20Sopenharmony_ci if (memcmp(&next_key, task, SIZE)) { 578c2ecf20Sopenharmony_ci key = next_key; 588c2ecf20Sopenharmony_ci continue; 598c2ecf20Sopenharmony_ci } 608c2ecf20Sopenharmony_ci bpf_map_lookup_elem(fd, &next_key, values); 618c2ecf20Sopenharmony_ci value = 0; 628c2ecf20Sopenharmony_ci for (i = 0; i < nr_cpus; i++) 638c2ecf20Sopenharmony_ci value += values[i]; 648c2ecf20Sopenharmony_ci ind = next_key.index; 658c2ecf20Sopenharmony_ci data[ind] = value; 668c2ecf20Sopenharmony_ci if (value && ind > max_ind) 678c2ecf20Sopenharmony_ci max_ind = ind; 688c2ecf20Sopenharmony_ci if (value > max_value) 698c2ecf20Sopenharmony_ci max_value = value; 708c2ecf20Sopenharmony_ci key = next_key; 718c2ecf20Sopenharmony_ci } 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci printf(" syscall write() stats\n"); 748c2ecf20Sopenharmony_ci printf(" byte_size : count distribution\n"); 758c2ecf20Sopenharmony_ci for (i = 1; i <= max_ind + 1; i++) { 768c2ecf20Sopenharmony_ci stars(starstr, data[i - 1], max_value, MAX_STARS); 778c2ecf20Sopenharmony_ci printf("%8ld -> %-8ld : %-8ld |%-*s|\n", 788c2ecf20Sopenharmony_ci (1l << i) >> 1, (1l << i) - 1, data[i - 1], 798c2ecf20Sopenharmony_ci MAX_STARS, starstr); 808c2ecf20Sopenharmony_ci } 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistatic void print_hist(int fd) 848c2ecf20Sopenharmony_ci{ 858c2ecf20Sopenharmony_ci struct hist_key key = {}, next_key; 868c2ecf20Sopenharmony_ci static struct task tasks[1024]; 878c2ecf20Sopenharmony_ci int task_cnt = 0; 888c2ecf20Sopenharmony_ci int i; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci while (bpf_map_get_next_key(fd, &key, &next_key) == 0) { 918c2ecf20Sopenharmony_ci int found = 0; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci for (i = 0; i < task_cnt; i++) 948c2ecf20Sopenharmony_ci if (memcmp(&tasks[i], &next_key, SIZE) == 0) 958c2ecf20Sopenharmony_ci found = 1; 968c2ecf20Sopenharmony_ci if (!found) 978c2ecf20Sopenharmony_ci memcpy(&tasks[task_cnt++], &next_key, SIZE); 988c2ecf20Sopenharmony_ci key = next_key; 998c2ecf20Sopenharmony_ci } 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci for (i = 0; i < task_cnt; i++) { 1028c2ecf20Sopenharmony_ci printf("\npid %d cmd %s uid %d\n", 1038c2ecf20Sopenharmony_ci (__u32) tasks[i].pid_tgid, 1048c2ecf20Sopenharmony_ci tasks[i].comm, 1058c2ecf20Sopenharmony_ci (__u32) tasks[i].uid_gid); 1068c2ecf20Sopenharmony_ci print_hist_for_pid(fd, &tasks[i]); 1078c2ecf20Sopenharmony_ci } 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_cistatic void int_exit(int sig) 1128c2ecf20Sopenharmony_ci{ 1138c2ecf20Sopenharmony_ci print_hist(map_fd[1]); 1148c2ecf20Sopenharmony_ci exit(0); 1158c2ecf20Sopenharmony_ci} 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ciint main(int ac, char **argv) 1188c2ecf20Sopenharmony_ci{ 1198c2ecf20Sopenharmony_ci struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; 1208c2ecf20Sopenharmony_ci long key, next_key, value; 1218c2ecf20Sopenharmony_ci struct bpf_link *links[2]; 1228c2ecf20Sopenharmony_ci struct bpf_program *prog; 1238c2ecf20Sopenharmony_ci struct bpf_object *obj; 1248c2ecf20Sopenharmony_ci char filename[256]; 1258c2ecf20Sopenharmony_ci int i, j = 0; 1268c2ecf20Sopenharmony_ci FILE *f; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci if (setrlimit(RLIMIT_MEMLOCK, &r)) { 1298c2ecf20Sopenharmony_ci perror("setrlimit(RLIMIT_MEMLOCK)"); 1308c2ecf20Sopenharmony_ci return 1; 1318c2ecf20Sopenharmony_ci } 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); 1348c2ecf20Sopenharmony_ci obj = bpf_object__open_file(filename, NULL); 1358c2ecf20Sopenharmony_ci if (libbpf_get_error(obj)) { 1368c2ecf20Sopenharmony_ci fprintf(stderr, "ERROR: opening BPF object file failed\n"); 1378c2ecf20Sopenharmony_ci return 0; 1388c2ecf20Sopenharmony_ci } 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci /* load BPF program */ 1418c2ecf20Sopenharmony_ci if (bpf_object__load(obj)) { 1428c2ecf20Sopenharmony_ci fprintf(stderr, "ERROR: loading BPF object file failed\n"); 1438c2ecf20Sopenharmony_ci goto cleanup; 1448c2ecf20Sopenharmony_ci } 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci map_fd[0] = bpf_object__find_map_fd_by_name(obj, "my_map"); 1478c2ecf20Sopenharmony_ci map_fd[1] = bpf_object__find_map_fd_by_name(obj, "my_hist_map"); 1488c2ecf20Sopenharmony_ci if (map_fd[0] < 0 || map_fd[1] < 0) { 1498c2ecf20Sopenharmony_ci fprintf(stderr, "ERROR: finding a map in obj file failed\n"); 1508c2ecf20Sopenharmony_ci goto cleanup; 1518c2ecf20Sopenharmony_ci } 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci signal(SIGINT, int_exit); 1548c2ecf20Sopenharmony_ci signal(SIGTERM, int_exit); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci /* start 'ping' in the background to have some kfree_skb events */ 1578c2ecf20Sopenharmony_ci f = popen("ping -4 -c5 localhost", "r"); 1588c2ecf20Sopenharmony_ci (void) f; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci /* start 'dd' in the background to have plenty of 'write' syscalls */ 1618c2ecf20Sopenharmony_ci f = popen("dd if=/dev/zero of=/dev/null count=5000000", "r"); 1628c2ecf20Sopenharmony_ci (void) f; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci bpf_object__for_each_program(prog, obj) { 1658c2ecf20Sopenharmony_ci links[j] = bpf_program__attach(prog); 1668c2ecf20Sopenharmony_ci if (libbpf_get_error(links[j])) { 1678c2ecf20Sopenharmony_ci fprintf(stderr, "ERROR: bpf_program__attach failed\n"); 1688c2ecf20Sopenharmony_ci links[j] = NULL; 1698c2ecf20Sopenharmony_ci goto cleanup; 1708c2ecf20Sopenharmony_ci } 1718c2ecf20Sopenharmony_ci j++; 1728c2ecf20Sopenharmony_ci } 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci for (i = 0; i < 5; i++) { 1758c2ecf20Sopenharmony_ci key = 0; 1768c2ecf20Sopenharmony_ci while (bpf_map_get_next_key(map_fd[0], &key, &next_key) == 0) { 1778c2ecf20Sopenharmony_ci bpf_map_lookup_elem(map_fd[0], &next_key, &value); 1788c2ecf20Sopenharmony_ci printf("location 0x%lx count %ld\n", next_key, value); 1798c2ecf20Sopenharmony_ci key = next_key; 1808c2ecf20Sopenharmony_ci } 1818c2ecf20Sopenharmony_ci if (key) 1828c2ecf20Sopenharmony_ci printf("\n"); 1838c2ecf20Sopenharmony_ci sleep(1); 1848c2ecf20Sopenharmony_ci } 1858c2ecf20Sopenharmony_ci print_hist(map_fd[1]); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_cicleanup: 1888c2ecf20Sopenharmony_ci for (j--; j >= 0; j--) 1898c2ecf20Sopenharmony_ci bpf_link__destroy(links[j]); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci bpf_object__close(obj); 1928c2ecf20Sopenharmony_ci return 0; 1938c2ecf20Sopenharmony_ci} 194