linux/samples/bpf/xdp1_user.c
<<
>>
Prefs
   1/* Copyright (c) 2016 PLUMgrid
   2 *
   3 * This program is free software; you can redistribute it and/or
   4 * modify it under the terms of version 2 of the GNU General Public
   5 * License as published by the Free Software Foundation.
   6 */
   7#include <linux/bpf.h>
   8#include <linux/if_link.h>
   9#include <assert.h>
  10#include <errno.h>
  11#include <signal.h>
  12#include <stdio.h>
  13#include <stdlib.h>
  14#include <string.h>
  15#include <unistd.h>
  16#include <libgen.h>
  17#include <sys/resource.h>
  18
  19#include "bpf_load.h"
  20#include "bpf_util.h"
  21#include "libbpf.h"
  22
  23static int ifindex;
  24static __u32 xdp_flags;
  25
  26static void int_exit(int sig)
  27{
  28        bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
  29        exit(0);
  30}
  31
  32/* simple per-protocol drop counter
  33 */
  34static void poll_stats(int interval)
  35{
  36        unsigned int nr_cpus = bpf_num_possible_cpus();
  37        const unsigned int nr_keys = 256;
  38        __u64 values[nr_cpus], prev[nr_keys][nr_cpus];
  39        __u32 key;
  40        int i;
  41
  42        memset(prev, 0, sizeof(prev));
  43
  44        while (1) {
  45                sleep(interval);
  46
  47                for (key = 0; key < nr_keys; key++) {
  48                        __u64 sum = 0;
  49
  50                        assert(bpf_map_lookup_elem(map_fd[0], &key, values) == 0);
  51                        for (i = 0; i < nr_cpus; i++)
  52                                sum += (values[i] - prev[key][i]);
  53                        if (sum)
  54                                printf("proto %u: %10llu pkt/s\n",
  55                                       key, sum / interval);
  56                        memcpy(prev[key], values, sizeof(values));
  57                }
  58        }
  59}
  60
  61static void usage(const char *prog)
  62{
  63        fprintf(stderr,
  64                "usage: %s [OPTS] IFINDEX\n\n"
  65                "OPTS:\n"
  66                "    -S    use skb-mode\n"
  67                "    -N    enforce native mode\n",
  68                prog);
  69}
  70
  71int main(int argc, char **argv)
  72{
  73        struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
  74        const char *optstr = "SN";
  75        char filename[256];
  76        int opt;
  77
  78        while ((opt = getopt(argc, argv, optstr)) != -1) {
  79                switch (opt) {
  80                case 'S':
  81                        xdp_flags |= XDP_FLAGS_SKB_MODE;
  82                        break;
  83                case 'N':
  84                        xdp_flags |= XDP_FLAGS_DRV_MODE;
  85                        break;
  86                default:
  87                        usage(basename(argv[0]));
  88                        return 1;
  89                }
  90        }
  91
  92        if (optind == argc) {
  93                usage(basename(argv[0]));
  94                return 1;
  95        }
  96
  97        if (setrlimit(RLIMIT_MEMLOCK, &r)) {
  98                perror("setrlimit(RLIMIT_MEMLOCK)");
  99                return 1;
 100        }
 101
 102        ifindex = strtoul(argv[optind], NULL, 0);
 103
 104        snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
 105
 106        if (load_bpf_file(filename)) {
 107                printf("%s", bpf_log_buf);
 108                return 1;
 109        }
 110
 111        if (!prog_fd[0]) {
 112                printf("load_bpf_file: %s\n", strerror(errno));
 113                return 1;
 114        }
 115
 116        signal(SIGINT, int_exit);
 117        signal(SIGTERM, int_exit);
 118
 119        if (bpf_set_link_xdp_fd(ifindex, prog_fd[0], xdp_flags) < 0) {
 120                printf("link set xdp fd failed\n");
 121                return 1;
 122        }
 123
 124        poll_stats(2);
 125
 126        return 0;
 127}
 128