root/samples/bpf/xdp_adjust_tail_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
   2  * Copyright (c) 2018 Facebook
   3  *
   4  * This program is free software; you can redistribute it and/or
   5  * modify it under the terms of version 2 of the GNU General Public
   6  * License as published by the Free Software Foundation.
   7  */
   8 #include <linux/bpf.h>
   9 #include <linux/if_link.h>
  10 #include <assert.h>
  11 #include <errno.h>
  12 #include <signal.h>
  13 #include <stdio.h>
  14 #include <stdlib.h>
  15 #include <string.h>
  16 #include <net/if.h>
  17 #include <sys/resource.h>
  18 #include <arpa/inet.h>
  19 #include <netinet/ether.h>
  20 #include <unistd.h>
  21 #include <time.h>
  22 #include "bpf.h"
  23 #include "libbpf.h"
  24 
  25 #define STATS_INTERVAL_S 2U
  26 
  27 static int ifindex = -1;
  28 static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
  29 static __u32 prog_id;
  30 
  31 static void int_exit(int sig)
  32 {
  33         __u32 curr_prog_id = 0;
  34 
  35         if (ifindex > -1) {
  36                 if (bpf_get_link_xdp_id(ifindex, &curr_prog_id, xdp_flags)) {
  37                         printf("bpf_get_link_xdp_id failed\n");
  38                         exit(1);
  39                 }
  40                 if (prog_id == curr_prog_id)
  41                         bpf_set_link_xdp_fd(ifindex, -1, xdp_flags);
  42                 else if (!curr_prog_id)
  43                         printf("couldn't find a prog id on a given iface\n");
  44                 else
  45                         printf("program on interface changed, not removing\n");
  46         }
  47         exit(0);
  48 }
  49 
  50 /* simple "icmp packet too big sent" counter
  51  */
  52 static void poll_stats(unsigned int map_fd, unsigned int kill_after_s)
  53 {
  54         time_t started_at = time(NULL);
  55         __u64 value = 0;
  56         int key = 0;
  57 
  58 
  59         while (!kill_after_s || time(NULL) - started_at <= kill_after_s) {
  60                 sleep(STATS_INTERVAL_S);
  61 
  62                 assert(bpf_map_lookup_elem(map_fd, &key, &value) == 0);
  63 
  64                 printf("icmp \"packet too big\" sent: %10llu pkts\n", value);
  65         }
  66 }
  67 
  68 static void usage(const char *cmd)
  69 {
  70         printf("Start a XDP prog which send ICMP \"packet too big\" \n"
  71                 "messages if ingress packet is bigger then MAX_SIZE bytes\n");
  72         printf("Usage: %s [...]\n", cmd);
  73         printf("    -i <ifname|ifindex> Interface\n");
  74         printf("    -T <stop-after-X-seconds> Default: 0 (forever)\n");
  75         printf("    -S use skb-mode\n");
  76         printf("    -N enforce native mode\n");
  77         printf("    -F force loading prog\n");
  78         printf("    -h Display this help\n");
  79 }
  80 
  81 int main(int argc, char **argv)
  82 {
  83         struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
  84         struct bpf_prog_load_attr prog_load_attr = {
  85                 .prog_type      = BPF_PROG_TYPE_XDP,
  86         };
  87         unsigned char opt_flags[256] = {};
  88         const char *optstr = "i:T:SNFh";
  89         struct bpf_prog_info info = {};
  90         __u32 info_len = sizeof(info);
  91         unsigned int kill_after_s = 0;
  92         int i, prog_fd, map_fd, opt;
  93         struct bpf_object *obj;
  94         struct bpf_map *map;
  95         char filename[256];
  96         int err;
  97 
  98         for (i = 0; i < strlen(optstr); i++)
  99                 if (optstr[i] != 'h' && 'a' <= optstr[i] && optstr[i] <= 'z')
 100                         opt_flags[(unsigned char)optstr[i]] = 1;
 101 
 102         while ((opt = getopt(argc, argv, optstr)) != -1) {
 103 
 104                 switch (opt) {
 105                 case 'i':
 106                         ifindex = if_nametoindex(optarg);
 107                         if (!ifindex)
 108                                 ifindex = atoi(optarg);
 109                         break;
 110                 case 'T':
 111                         kill_after_s = atoi(optarg);
 112                         break;
 113                 case 'S':
 114                         xdp_flags |= XDP_FLAGS_SKB_MODE;
 115                         break;
 116                 case 'N':
 117                         xdp_flags |= XDP_FLAGS_DRV_MODE;
 118                         break;
 119                 case 'F':
 120                         xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST;
 121                         break;
 122                 default:
 123                         usage(argv[0]);
 124                         return 1;
 125                 }
 126                 opt_flags[opt] = 0;
 127         }
 128 
 129         for (i = 0; i < strlen(optstr); i++) {
 130                 if (opt_flags[(unsigned int)optstr[i]]) {
 131                         fprintf(stderr, "Missing argument -%c\n", optstr[i]);
 132                         usage(argv[0]);
 133                         return 1;
 134                 }
 135         }
 136 
 137         if (setrlimit(RLIMIT_MEMLOCK, &r)) {
 138                 perror("setrlimit(RLIMIT_MEMLOCK, RLIM_INFINITY)");
 139                 return 1;
 140         }
 141 
 142         if (!ifindex) {
 143                 fprintf(stderr, "Invalid ifname\n");
 144                 return 1;
 145         }
 146 
 147         snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
 148         prog_load_attr.file = filename;
 149 
 150         if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
 151                 return 1;
 152 
 153         map = bpf_map__next(NULL, obj);
 154         if (!map) {
 155                 printf("finding a map in obj file failed\n");
 156                 return 1;
 157         }
 158         map_fd = bpf_map__fd(map);
 159 
 160         if (!prog_fd) {
 161                 printf("load_bpf_file: %s\n", strerror(errno));
 162                 return 1;
 163         }
 164 
 165         signal(SIGINT, int_exit);
 166         signal(SIGTERM, int_exit);
 167 
 168         if (bpf_set_link_xdp_fd(ifindex, prog_fd, xdp_flags) < 0) {
 169                 printf("link set xdp fd failed\n");
 170                 return 1;
 171         }
 172 
 173         err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
 174         if (err) {
 175                 printf("can't get prog info - %s\n", strerror(errno));
 176                 return 1;
 177         }
 178         prog_id = info.id;
 179 
 180         poll_stats(map_fd, kill_after_s);
 181         int_exit(0);
 182 
 183         return 0;
 184 }

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