linux/samples/bpf/xdp1_user.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/* Copyright (c) 2016 PLUMgrid
   3 */
   4#include <linux/bpf.h>
   5#include <linux/if_link.h>
   6#include <assert.h>
   7#include <errno.h>
   8#include <signal.h>
   9#include <stdio.h>
  10#include <stdlib.h>
  11#include <string.h>
  12#include <unistd.h>
  13#include <libgen.h>
  14#include <sys/resource.h>
  15#include <net/if.h>
  16
  17#include "bpf_util.h"
  18#include "bpf.h"
  19#include "libbpf.h"
  20
  21static int ifindex;
  22static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
  23static __u32 prog_id;
  24
  25static void int_exit(int sig)
  26{
  27        __u32 curr_prog_id = 0;
  28
  29        if (bpf_get_link_xdp_id(ifindex, &curr_prog_id, xdp_flags)) {
  30                printf("bpf_get_link_xdp_id failed\n");
  31                exit(1);
  32        }
  33        if (prog_id == curr_prog_id)
  34                bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
  35        else if (!curr_prog_id)
  36                printf("couldn't find a prog id on a given interface\n");
  37        else
  38                printf("program on interface changed, not removing\n");
  39        exit(0);
  40}
  41
  42/* simple per-protocol drop counter
  43 */
  44static void poll_stats(int map_fd, int interval)
  45{
  46        unsigned int nr_cpus = bpf_num_possible_cpus();
  47        __u64 values[nr_cpus], prev[UINT8_MAX] = { 0 };
  48        int i;
  49
  50        while (1) {
  51                __u32 key = UINT32_MAX;
  52
  53                sleep(interval);
  54
  55                while (bpf_map_get_next_key(map_fd, &key, &key) != -1) {
  56                        __u64 sum = 0;
  57
  58                        assert(bpf_map_lookup_elem(map_fd, &key, values) == 0);
  59                        for (i = 0; i < nr_cpus; i++)
  60                                sum += values[i];
  61                        if (sum > prev[key])
  62                                printf("proto %u: %10llu pkt/s\n",
  63                                       key, (sum - prev[key]) / interval);
  64                        prev[key] = sum;
  65                }
  66        }
  67}
  68
  69static void usage(const char *prog)
  70{
  71        fprintf(stderr,
  72                "usage: %s [OPTS] IFACE\n\n"
  73                "OPTS:\n"
  74                "    -S    use skb-mode\n"
  75                "    -N    enforce native mode\n"
  76                "    -F    force loading prog\n",
  77                prog);
  78}
  79
  80int main(int argc, char **argv)
  81{
  82        struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
  83        struct bpf_prog_load_attr prog_load_attr = {
  84                .prog_type      = BPF_PROG_TYPE_XDP,
  85        };
  86        struct bpf_prog_info info = {};
  87        __u32 info_len = sizeof(info);
  88        const char *optstr = "FSN";
  89        int prog_fd, map_fd, opt;
  90        struct bpf_object *obj;
  91        struct bpf_map *map;
  92        char filename[256];
  93        int err;
  94
  95        while ((opt = getopt(argc, argv, optstr)) != -1) {
  96                switch (opt) {
  97                case 'S':
  98                        xdp_flags |= XDP_FLAGS_SKB_MODE;
  99                        break;
 100                case 'N':
 101                        xdp_flags |= XDP_FLAGS_DRV_MODE;
 102                        break;
 103                case 'F':
 104                        xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
 105                        break;
 106                default:
 107                        usage(basename(argv[0]));
 108                        return 1;
 109                }
 110        }
 111
 112        if (optind == argc) {
 113                usage(basename(argv[0]));
 114                return 1;
 115        }
 116
 117        if (setrlimit(RLIMIT_MEMLOCK, &r)) {
 118                perror("setrlimit(RLIMIT_MEMLOCK)");
 119                return 1;
 120        }
 121
 122        ifindex = if_nametoindex(argv[optind]);
 123        if (!ifindex) {
 124                perror("if_nametoindex");
 125                return 1;
 126        }
 127
 128        snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
 129        prog_load_attr.file = filename;
 130
 131        if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
 132                return 1;
 133
 134        map = bpf_map__next(NULL, obj);
 135        if (!map) {
 136                printf("finding a map in obj file failed\n");
 137                return 1;
 138        }
 139        map_fd = bpf_map__fd(map);
 140
 141        if (!prog_fd) {
 142                printf("load_bpf_file: %s\n", strerror(errno));
 143                return 1;
 144        }
 145
 146        signal(SIGINT, int_exit);
 147        signal(SIGTERM, int_exit);
 148
 149        if (bpf_set_link_xdp_fd(ifindex, prog_fd, xdp_flags) < 0) {
 150                printf("link set xdp fd failed\n");
 151                return 1;
 152        }
 153
 154        err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
 155        if (err) {
 156                printf("can't get prog info - %s\n", strerror(errno));
 157                return err;
 158        }
 159        prog_id = info.id;
 160
 161        poll_stats(map_fd, 2);
 162
 163        return 0;
 164}
 165