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/bpf.h>
  19#include <bpf/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 bpf_prog_load_attr prog_load_attr = {
  83                .prog_type      = BPF_PROG_TYPE_XDP,
  84        };
  85        struct bpf_prog_info info = {};
  86        __u32 info_len = sizeof(info);
  87        const char *optstr = "FSN";
  88        int prog_fd, map_fd, opt;
  89        struct bpf_object *obj;
  90        struct bpf_map *map;
  91        char filename[256];
  92        int err;
  93
  94        while ((opt = getopt(argc, argv, optstr)) != -1) {
  95                switch (opt) {
  96                case 'S':
  97                        xdp_flags |= XDP_FLAGS_SKB_MODE;
  98                        break;
  99                case 'N':
 100                        /* default, set below */
 101                        break;
 102                case 'F':
 103                        xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
 104                        break;
 105                default:
 106                        usage(basename(argv[0]));
 107                        return 1;
 108                }
 109        }
 110
 111        if (!(xdp_flags & XDP_FLAGS_SKB_MODE))
 112                xdp_flags |= XDP_FLAGS_DRV_MODE;
 113
 114        if (optind == argc) {
 115                usage(basename(argv[0]));
 116                return 1;
 117        }
 118
 119        ifindex = if_nametoindex(argv[optind]);
 120        if (!ifindex) {
 121                perror("if_nametoindex");
 122                return 1;
 123        }
 124
 125        snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
 126        prog_load_attr.file = filename;
 127
 128        if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
 129                return 1;
 130
 131        map = bpf_map__next(NULL, obj);
 132        if (!map) {
 133                printf("finding a map in obj file failed\n");
 134                return 1;
 135        }
 136        map_fd = bpf_map__fd(map);
 137
 138        if (!prog_fd) {
 139                printf("bpf_prog_load_xattr: %s\n", strerror(errno));
 140                return 1;
 141        }
 142
 143        signal(SIGINT, int_exit);
 144        signal(SIGTERM, int_exit);
 145
 146        if (bpf_set_link_xdp_fd(ifindex, prog_fd, xdp_flags) < 0) {
 147                printf("link set xdp fd failed\n");
 148                return 1;
 149        }
 150
 151        err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
 152        if (err) {
 153                printf("can't get prog info - %s\n", strerror(errno));
 154                return err;
 155        }
 156        prog_id = info.id;
 157
 158        poll_stats(map_fd, 2);
 159
 160        return 0;
 161}
 162