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 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                        /* default, set below */
 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 (!(xdp_flags & XDP_FLAGS_SKB_MODE))
 113                xdp_flags |= XDP_FLAGS_DRV_MODE;
 114
 115        if (optind == argc) {
 116                usage(basename(argv[0]));
 117                return 1;
 118        }
 119
 120        if (setrlimit(RLIMIT_MEMLOCK, &r)) {
 121                perror("setrlimit(RLIMIT_MEMLOCK)");
 122                return 1;
 123        }
 124
 125        ifindex = if_nametoindex(argv[optind]);
 126        if (!ifindex) {
 127                perror("if_nametoindex");
 128                return 1;
 129        }
 130
 131        snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
 132        prog_load_attr.file = filename;
 133
 134        if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
 135                return 1;
 136
 137        map = bpf_map__next(NULL, obj);
 138        if (!map) {
 139                printf("finding a map in obj file failed\n");
 140                return 1;
 141        }
 142        map_fd = bpf_map__fd(map);
 143
 144        if (!prog_fd) {
 145                printf("bpf_prog_load_xattr: %s\n", strerror(errno));
 146                return 1;
 147        }
 148
 149        signal(SIGINT, int_exit);
 150        signal(SIGTERM, int_exit);
 151
 152        if (bpf_set_link_xdp_fd(ifindex, prog_fd, xdp_flags) < 0) {
 153                printf("link set xdp fd failed\n");
 154                return 1;
 155        }
 156
 157        err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
 158        if (err) {
 159                printf("can't get prog info - %s\n", strerror(errno));
 160                return err;
 161        }
 162        prog_id = info.id;
 163
 164        poll_stats(map_fd, 2);
 165
 166        return 0;
 167}
 168