Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
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 /* my_map, my_hist_map */
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     /* load BPF program */
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     /* start 'ping' in the background to have some kfree_skb events */
0150     f = popen("ping -4 -c5 localhost", "r");
0151     (void) f;
0152 
0153     /* start 'dd' in the background to have plenty of 'write' syscalls */
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 }