linux/samples/bpf/tracex2_user.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#include <stdio.h>
   3#include <unistd.h>
   4#include <stdlib.h>
   5#include <signal.h>
   6#include <string.h>
   7#include <sys/resource.h>
   8
   9#include <bpf/bpf.h>
  10#include <bpf/libbpf.h>
  11#include "bpf_util.h"
  12
  13#define MAX_INDEX       64
  14#define MAX_STARS       38
  15
  16/* my_map, my_hist_map */
  17static int map_fd[2];
  18
  19static void stars(char *str, long val, long max, int width)
  20{
  21        int i;
  22
  23        for (i = 0; i < (width * val / max) - 1 && i < width - 1; i++)
  24                str[i] = '*';
  25        if (val > max)
  26                str[i - 1] = '+';
  27        str[i] = '\0';
  28}
  29
  30struct task {
  31        char comm[16];
  32        __u64 pid_tgid;
  33        __u64 uid_gid;
  34};
  35
  36struct hist_key {
  37        struct task t;
  38        __u32 index;
  39};
  40
  41#define SIZE sizeof(struct task)
  42
  43static void print_hist_for_pid(int fd, void *task)
  44{
  45        unsigned int nr_cpus = bpf_num_possible_cpus();
  46        struct hist_key key = {}, next_key;
  47        long values[nr_cpus];
  48        char starstr[MAX_STARS];
  49        long value;
  50        long data[MAX_INDEX] = {};
  51        int max_ind = -1;
  52        long max_value = 0;
  53        int i, ind;
  54
  55        while (bpf_map_get_next_key(fd, &key, &next_key) == 0) {
  56                if (memcmp(&next_key, task, SIZE)) {
  57                        key = next_key;
  58                        continue;
  59                }
  60                bpf_map_lookup_elem(fd, &next_key, values);
  61                value = 0;
  62                for (i = 0; i < nr_cpus; i++)
  63                        value += values[i];
  64                ind = next_key.index;
  65                data[ind] = value;
  66                if (value && ind > max_ind)
  67                        max_ind = ind;
  68                if (value > max_value)
  69                        max_value = value;
  70                key = next_key;
  71        }
  72
  73        printf("           syscall write() stats\n");
  74        printf("     byte_size       : count     distribution\n");
  75        for (i = 1; i <= max_ind + 1; i++) {
  76                stars(starstr, data[i - 1], max_value, MAX_STARS);
  77                printf("%8ld -> %-8ld : %-8ld |%-*s|\n",
  78                       (1l << i) >> 1, (1l << i) - 1, data[i - 1],
  79                       MAX_STARS, starstr);
  80        }
  81}
  82
  83static void print_hist(int fd)
  84{
  85        struct hist_key key = {}, next_key;
  86        static struct task tasks[1024];
  87        int task_cnt = 0;
  88        int i;
  89
  90        while (bpf_map_get_next_key(fd, &key, &next_key) == 0) {
  91                int found = 0;
  92
  93                for (i = 0; i < task_cnt; i++)
  94                        if (memcmp(&tasks[i], &next_key, SIZE) == 0)
  95                                found = 1;
  96                if (!found)
  97                        memcpy(&tasks[task_cnt++], &next_key, SIZE);
  98                key = next_key;
  99        }
 100
 101        for (i = 0; i < task_cnt; i++) {
 102                printf("\npid %d cmd %s uid %d\n",
 103                       (__u32) tasks[i].pid_tgid,
 104                       tasks[i].comm,
 105                       (__u32) tasks[i].uid_gid);
 106                print_hist_for_pid(fd, &tasks[i]);
 107        }
 108
 109}
 110
 111static void int_exit(int sig)
 112{
 113        print_hist(map_fd[1]);
 114        exit(0);
 115}
 116
 117int main(int ac, char **argv)
 118{
 119        long key, next_key, value;
 120        struct bpf_link *links[2];
 121        struct bpf_program *prog;
 122        struct bpf_object *obj;
 123        char filename[256];
 124        int i, j = 0;
 125        FILE *f;
 126
 127        snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
 128        obj = bpf_object__open_file(filename, NULL);
 129        if (libbpf_get_error(obj)) {
 130                fprintf(stderr, "ERROR: opening BPF object file failed\n");
 131                return 0;
 132        }
 133
 134        /* load BPF program */
 135        if (bpf_object__load(obj)) {
 136                fprintf(stderr, "ERROR: loading BPF object file failed\n");
 137                goto cleanup;
 138        }
 139
 140        map_fd[0] = bpf_object__find_map_fd_by_name(obj, "my_map");
 141        map_fd[1] = bpf_object__find_map_fd_by_name(obj, "my_hist_map");
 142        if (map_fd[0] < 0 || map_fd[1] < 0) {
 143                fprintf(stderr, "ERROR: finding a map in obj file failed\n");
 144                goto cleanup;
 145        }
 146
 147        signal(SIGINT, int_exit);
 148        signal(SIGTERM, int_exit);
 149
 150        /* start 'ping' in the background to have some kfree_skb events */
 151        f = popen("ping -4 -c5 localhost", "r");
 152        (void) f;
 153
 154        /* start 'dd' in the background to have plenty of 'write' syscalls */
 155        f = popen("dd if=/dev/zero of=/dev/null count=5000000", "r");
 156        (void) f;
 157
 158        bpf_object__for_each_program(prog, obj) {
 159                links[j] = bpf_program__attach(prog);
 160                if (libbpf_get_error(links[j])) {
 161                        fprintf(stderr, "ERROR: bpf_program__attach failed\n");
 162                        links[j] = NULL;
 163                        goto cleanup;
 164                }
 165                j++;
 166        }
 167
 168        for (i = 0; i < 5; i++) {
 169                key = 0;
 170                while (bpf_map_get_next_key(map_fd[0], &key, &next_key) == 0) {
 171                        bpf_map_lookup_elem(map_fd[0], &next_key, &value);
 172                        printf("location 0x%lx count %ld\n", next_key, value);
 173                        key = next_key;
 174                }
 175                if (key)
 176                        printf("\n");
 177                sleep(1);
 178        }
 179        print_hist(map_fd[1]);
 180
 181cleanup:
 182        for (j--; j >= 0; j--)
 183                bpf_link__destroy(links[j]);
 184
 185        bpf_object__close(obj);
 186        return 0;
 187}
 188