linux/samples/bpf/xdp_fwd_user.c
<<
>>
Prefs
   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
  31static int do_attach(int idx, int fd, const char *name)
  32{
  33        int err;
  34
  35        err = bpf_set_link_xdp_fd(idx, fd, 0);
  36        if (err < 0)
  37                printf("ERROR: failed to attach program to %s\n", name);
  38
  39        return err;
  40}
  41
  42static int do_detach(int idx, const char *name)
  43{
  44        int err;
  45
  46        err = bpf_set_link_xdp_fd(idx, -1, 0);
  47        if (err < 0)
  48                printf("ERROR: failed to detach program from %s\n", name);
  49
  50        return err;
  51}
  52
  53static void usage(const char *prog)
  54{
  55        fprintf(stderr,
  56                "usage: %s [OPTS] interface-list\n"
  57                "\nOPTS:\n"
  58                "    -d    detach program\n"
  59                "    -D    direct table lookups (skip fib rules)\n",
  60                prog);
  61}
  62
  63int main(int argc, char **argv)
  64{
  65        struct bpf_prog_load_attr prog_load_attr = {
  66                .prog_type      = BPF_PROG_TYPE_XDP,
  67        };
  68        const char *prog_name = "xdp_fwd";
  69        struct bpf_program *prog;
  70        char filename[PATH_MAX];
  71        struct bpf_object *obj;
  72        int opt, i, idx, err;
  73        int prog_fd, map_fd;
  74        int attach = 1;
  75        int ret = 0;
  76
  77        while ((opt = getopt(argc, argv, ":dD")) != -1) {
  78                switch (opt) {
  79                case 'd':
  80                        attach = 0;
  81                        break;
  82                case 'D':
  83                        prog_name = "xdp_fwd_direct";
  84                        break;
  85                default:
  86                        usage(basename(argv[0]));
  87                        return 1;
  88                }
  89        }
  90
  91        if (optind == argc) {
  92                usage(basename(argv[0]));
  93                return 1;
  94        }
  95
  96        if (attach) {
  97                snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
  98                prog_load_attr.file = filename;
  99
 100                if (access(filename, O_RDONLY) < 0) {
 101                        printf("error accessing file %s: %s\n",
 102                                filename, strerror(errno));
 103                        return 1;
 104                }
 105
 106                if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd))
 107                        return 1;
 108
 109                prog = bpf_object__find_program_by_title(obj, prog_name);
 110                prog_fd = bpf_program__fd(prog);
 111                if (prog_fd < 0) {
 112                        printf("program not found: %s\n", strerror(prog_fd));
 113                        return 1;
 114                }
 115                map_fd = bpf_map__fd(bpf_object__find_map_by_name(obj,
 116                                                                  "tx_port"));
 117                if (map_fd < 0) {
 118                        printf("map not found: %s\n", strerror(map_fd));
 119                        return 1;
 120                }
 121        }
 122        if (attach) {
 123                for (i = 1; i < 64; ++i)
 124                        bpf_map_update_elem(map_fd, &i, &i, 0);
 125        }
 126
 127        for (i = optind; i < argc; ++i) {
 128                idx = if_nametoindex(argv[i]);
 129                if (!idx)
 130                        idx = strtoul(argv[i], NULL, 0);
 131
 132                if (!idx) {
 133                        fprintf(stderr, "Invalid arg\n");
 134                        return 1;
 135                }
 136                if (!attach) {
 137                        err = do_detach(idx, argv[i]);
 138                        if (err)
 139                                ret = err;
 140                } else {
 141                        err = do_attach(idx, prog_fd, argv[i]);
 142                        if (err)
 143                                ret = err;
 144                }
 145        }
 146
 147        return ret;
 148}
 149