root/samples/bpf/xdp1_user.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. int_exit
  2. poll_stats
  3. usage
  4. main

   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 
  21 static int ifindex;
  22 static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
  23 static __u32 prog_id;
  24 
  25 static 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  */
  44 static 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 
  69 static 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 
  80 int 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 }

/* [<][>][^][v][top][bottom][index][help] */