linux/samples/bpf/ibumad_user.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
   2
   3/*
   4 * ibumad BPF sample user side
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of version 2 of the GNU General Public
   8 * License as published by the Free Software Foundation.
   9 *
  10 * Copyright(c) 2018 Ira Weiny, Intel Corporation
  11 */
  12
  13#include <linux/bpf.h>
  14#include <signal.h>
  15#include <stdio.h>
  16#include <stdlib.h>
  17#include <string.h>
  18#include <unistd.h>
  19#include <sys/types.h>
  20#include <limits.h>
  21
  22#include <sys/resource.h>
  23#include <getopt.h>
  24#include <net/if.h>
  25
  26#include <bpf/bpf.h>
  27#include "bpf_util.h"
  28#include <bpf/libbpf.h>
  29
  30static struct bpf_link *tp_links[3];
  31static struct bpf_object *obj;
  32static int map_fd[2];
  33static int tp_cnt;
  34
  35static void dump_counts(int fd)
  36{
  37        __u32 key;
  38        __u64 value;
  39
  40        for (key = 0; key < 256; key++) {
  41                if (bpf_map_lookup_elem(fd, &key, &value)) {
  42                        printf("failed to read key %u\n", key);
  43                        continue;
  44                }
  45                if (value)
  46                        printf("0x%02x : %llu\n", key, value);
  47        }
  48}
  49
  50static void dump_all_counts(void)
  51{
  52        printf("Read 'Class : count'\n");
  53        dump_counts(map_fd[0]);
  54        printf("Write 'Class : count'\n");
  55        dump_counts(map_fd[1]);
  56}
  57
  58static void dump_exit(int sig)
  59{
  60        dump_all_counts();
  61        /* Detach tracepoints */
  62        while (tp_cnt)
  63                bpf_link__destroy(tp_links[--tp_cnt]);
  64
  65        bpf_object__close(obj);
  66        exit(0);
  67}
  68
  69static const struct option long_options[] = {
  70        {"help",      no_argument,       NULL, 'h'},
  71        {"delay",     required_argument, NULL, 'd'},
  72};
  73
  74static void usage(char *cmd)
  75{
  76        printf("eBPF test program to count packets from various IP addresses\n"
  77                "Usage: %s <options>\n"
  78                "       --help,   -h  this menu\n"
  79                "       --delay,  -d  <delay>  wait <delay> sec between prints [1 - 1000000]\n"
  80                , cmd
  81                );
  82}
  83
  84int main(int argc, char **argv)
  85{
  86        struct bpf_program *prog;
  87        unsigned long delay = 5;
  88        char filename[256];
  89        int longindex = 0;
  90        int opt, err = -1;
  91
  92        while ((opt = getopt_long(argc, argv, "hd:rSw",
  93                                  long_options, &longindex)) != -1) {
  94                switch (opt) {
  95                case 'd':
  96                        delay = strtoul(optarg, NULL, 0);
  97                        if (delay == ULONG_MAX || delay < 0 ||
  98                            delay > 1000000) {
  99                                fprintf(stderr, "ERROR: invalid delay : %s\n",
 100                                        optarg);
 101                                usage(argv[0]);
 102                                return 1;
 103                        }
 104                        break;
 105                default:
 106                case 'h':
 107                        usage(argv[0]);
 108                        return 1;
 109                }
 110        }
 111
 112        /* Do one final dump when exiting */
 113        signal(SIGINT, dump_exit);
 114        signal(SIGTERM, dump_exit);
 115
 116        snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
 117        obj = bpf_object__open_file(filename, NULL);
 118        if (libbpf_get_error(obj)) {
 119                fprintf(stderr, "ERROR: opening BPF object file failed\n");
 120                return err;
 121        }
 122
 123        /* load BPF program */
 124        if (bpf_object__load(obj)) {
 125                fprintf(stderr, "ERROR: loading BPF object file failed\n");
 126                goto cleanup;
 127        }
 128
 129        map_fd[0] = bpf_object__find_map_fd_by_name(obj, "read_count");
 130        map_fd[1] = bpf_object__find_map_fd_by_name(obj, "write_count");
 131        if (map_fd[0] < 0 || map_fd[1] < 0) {
 132                fprintf(stderr, "ERROR: finding a map in obj file failed\n");
 133                goto cleanup;
 134        }
 135
 136        bpf_object__for_each_program(prog, obj) {
 137                tp_links[tp_cnt] = bpf_program__attach(prog);
 138                if (libbpf_get_error(tp_links[tp_cnt])) {
 139                        fprintf(stderr, "ERROR: bpf_program__attach failed\n");
 140                        tp_links[tp_cnt] = NULL;
 141                        goto cleanup;
 142                }
 143                tp_cnt++;
 144        }
 145
 146        while (1) {
 147                sleep(delay);
 148                dump_all_counts();
 149        }
 150        err = 0;
 151
 152cleanup:
 153        /* Detach tracepoints */
 154        while (tp_cnt)
 155                bpf_link__destroy(tp_links[--tp_cnt]);
 156
 157        bpf_object__close(obj);
 158        return err;
 159}
 160