root/samples/bpf/xdp_fwd_user.c

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

DEFINITIONS

This source file includes following definitions.
  1. do_attach
  2. do_detach
  3. usage
  4. main

   1 // SPDX-License-Identifier: GPL-2.0
   2 /* Copyright (c) 2017-18 David Ahern <dsahern@gmail.com>
   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  * This program is distributed in the hope that it will be useful, but
   9  * WITHOUT ANY WARRANTY; without even the implied warranty of
  10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11  * General Public License for more details.
  12  */
  13 
  14 #include <linux/bpf.h>
  15 #include <linux/if_link.h>
  16 #include <linux/limits.h>
  17 #include <net/if.h>
  18 #include <errno.h>
  19 #include <stdio.h>
  20 #include <stdlib.h>
  21 #include <stdbool.h>
  22 #include <string.h>
  23 #include <unistd.h>
  24 #include <fcntl.h>
  25 #include <libgen.h>
  26 
  27 #include "libbpf.h"
  28 #include <bpf/bpf.h>
  29 
  30 static int do_attach(int idx, int prog_fd, int map_fd, const char *name)
  31 {
  32         int err;
  33 
  34         err = bpf_set_link_xdp_fd(idx, prog_fd, 0);
  35         if (err < 0) {
  36                 printf("ERROR: failed to attach program to %s\n", name);
  37                 return err;
  38         }
  39 
  40         /* Adding ifindex as a possible egress TX port */
  41         err = bpf_map_update_elem(map_fd, &idx, &idx, 0);
  42         if (err)
  43                 printf("ERROR: failed using device %s as TX-port\n", name);
  44 
  45         return err;
  46 }
  47 
  48 static int do_detach(int idx, const char *name)
  49 {
  50         int err;
  51 
  52         err = bpf_set_link_xdp_fd(idx, -1, 0);
  53         if (err < 0)
  54                 printf("ERROR: failed to detach program from %s\n", name);
  55 
  56         /* TODO: Remember to cleanup map, when adding use of shared map
  57          *  bpf_map_delete_elem((map_fd, &idx);
  58          */
  59         return err;
  60 }
  61 
  62 static void usage(const char *prog)
  63 {
  64         fprintf(stderr,
  65                 "usage: %s [OPTS] interface-list\n"
  66                 "\nOPTS:\n"
  67                 "    -d    detach program\n"
  68                 "    -D    direct table lookups (skip fib rules)\n",
  69                 prog);
  70 }
  71 
  72 int main(int argc, char **argv)
  73 {
  74         struct bpf_prog_load_attr prog_load_attr = {
  75                 .prog_type      = BPF_PROG_TYPE_XDP,
  76         };
  77         const char *prog_name = "xdp_fwd";
  78         struct bpf_program *prog;
  79         int prog_fd, map_fd = -1;
  80         char filename[PATH_MAX];
  81         struct bpf_object *obj;
  82         int opt, i, idx, err;
  83         int attach = 1;
  84         int ret = 0;
  85 
  86         while ((opt = getopt(argc, argv, ":dD")) != -1) {
  87                 switch (opt) {
  88                 case 'd':
  89                         attach = 0;
  90                         break;
  91                 case 'D':
  92                         prog_name = "xdp_fwd_direct";
  93                         break;
  94                 default:
  95                         usage(basename(argv[0]));
  96                         return 1;
  97                 }
  98         }
  99 
 100         if (optind == argc) {
 101                 usage(basename(argv[0]));
 102                 return 1;
 103         }
 104 
 105         if (attach) {
 106                 snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
 107                 prog_load_attr.file = filename;
 108 
 109                 if (access(filename, O_RDONLY) < 0) {
 110                         printf("error accessing file %s: %s\n",
 111                                 filename, strerror(errno));
 112                         return 1;
 113                 }
 114 
 115                 err = bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd);
 116                 if (err) {
 117                         printf("Does kernel support devmap lookup?\n");
 118                         /* If not, the error message will be:
 119                          *  "cannot pass map_type 14 into func bpf_map_lookup_elem#1"
 120                          */
 121                         return 1;
 122                 }
 123 
 124                 prog = bpf_object__find_program_by_title(obj, prog_name);
 125                 prog_fd = bpf_program__fd(prog);
 126                 if (prog_fd < 0) {
 127                         printf("program not found: %s\n", strerror(prog_fd));
 128                         return 1;
 129                 }
 130                 map_fd = bpf_map__fd(bpf_object__find_map_by_name(obj,
 131                                                         "xdp_tx_ports"));
 132                 if (map_fd < 0) {
 133                         printf("map not found: %s\n", strerror(map_fd));
 134                         return 1;
 135                 }
 136         }
 137 
 138         for (i = optind; i < argc; ++i) {
 139                 idx = if_nametoindex(argv[i]);
 140                 if (!idx)
 141                         idx = strtoul(argv[i], NULL, 0);
 142 
 143                 if (!idx) {
 144                         fprintf(stderr, "Invalid arg\n");
 145                         return 1;
 146                 }
 147                 if (!attach) {
 148                         err = do_detach(idx, argv[i]);
 149                         if (err)
 150                                 ret = err;
 151                 } else {
 152                         err = do_attach(idx, prog_fd, map_fd, argv[i]);
 153                         if (err)
 154                                 ret = err;
 155                 }
 156         }
 157 
 158         return ret;
 159 }

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