linux/tools/testing/selftests/bpf/prog_tests/check_mtu.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright (c) 2020 Jesper Dangaard Brouer */
   3
   4#include <linux/if_link.h> /* before test_progs.h, avoid bpf_util.h redefines */
   5#include <test_progs.h>
   6#include "test_check_mtu.skel.h"
   7#include "network_helpers.h"
   8
   9#include <stdlib.h>
  10#include <inttypes.h>
  11
  12#define IFINDEX_LO 1
  13
  14static __u32 duration; /* Hint: needed for CHECK macro */
  15
  16static int read_mtu_device_lo(void)
  17{
  18        const char *filename = "/sys/class/net/lo/mtu";
  19        char buf[11] = {};
  20        int value, n, fd;
  21
  22        fd = open(filename, 0, O_RDONLY);
  23        if (fd == -1)
  24                return -1;
  25
  26        n = read(fd, buf, sizeof(buf));
  27        close(fd);
  28
  29        if (n == -1)
  30                return -2;
  31
  32        value = strtoimax(buf, NULL, 10);
  33        if (errno == ERANGE)
  34                return -3;
  35
  36        return value;
  37}
  38
  39static void test_check_mtu_xdp_attach(void)
  40{
  41        struct bpf_link_info link_info;
  42        __u32 link_info_len = sizeof(link_info);
  43        struct test_check_mtu *skel;
  44        struct bpf_program *prog;
  45        struct bpf_link *link;
  46        int err = 0;
  47        int fd;
  48
  49        skel = test_check_mtu__open_and_load();
  50        if (CHECK(!skel, "open and load skel", "failed"))
  51                return; /* Exit if e.g. helper unknown to kernel */
  52
  53        prog = skel->progs.xdp_use_helper_basic;
  54
  55        link = bpf_program__attach_xdp(prog, IFINDEX_LO);
  56        if (CHECK(IS_ERR(link), "link_attach", "failed: %ld\n", PTR_ERR(link)))
  57                goto out;
  58        skel->links.xdp_use_helper_basic = link;
  59
  60        memset(&link_info, 0, sizeof(link_info));
  61        fd = bpf_link__fd(link);
  62        err = bpf_obj_get_info_by_fd(fd, &link_info, &link_info_len);
  63        if (CHECK(err, "link_info", "failed: %d\n", err))
  64                goto out;
  65
  66        CHECK(link_info.type != BPF_LINK_TYPE_XDP, "link_type",
  67              "got %u != exp %u\n", link_info.type, BPF_LINK_TYPE_XDP);
  68        CHECK(link_info.xdp.ifindex != IFINDEX_LO, "link_ifindex",
  69              "got %u != exp %u\n", link_info.xdp.ifindex, IFINDEX_LO);
  70
  71        err = bpf_link__detach(link);
  72        CHECK(err, "link_detach", "failed %d\n", err);
  73
  74out:
  75        test_check_mtu__destroy(skel);
  76}
  77
  78static void test_check_mtu_run_xdp(struct test_check_mtu *skel,
  79                                   struct bpf_program *prog,
  80                                   __u32 mtu_expect)
  81{
  82        const char *prog_name = bpf_program__name(prog);
  83        int retval_expect = XDP_PASS;
  84        __u32 mtu_result = 0;
  85        char buf[256] = {};
  86        int err;
  87        struct bpf_prog_test_run_attr tattr = {
  88                .repeat = 1,
  89                .data_in = &pkt_v4,
  90                .data_size_in = sizeof(pkt_v4),
  91                .data_out = buf,
  92                .data_size_out = sizeof(buf),
  93                .prog_fd = bpf_program__fd(prog),
  94        };
  95
  96        err = bpf_prog_test_run_xattr(&tattr);
  97        CHECK_ATTR(err != 0, "bpf_prog_test_run",
  98                   "prog_name:%s (err %d errno %d retval %d)\n",
  99                   prog_name, err, errno, tattr.retval);
 100
 101        CHECK(tattr.retval != retval_expect, "retval",
 102              "progname:%s unexpected retval=%d expected=%d\n",
 103              prog_name, tattr.retval, retval_expect);
 104
 105        /* Extract MTU that BPF-prog got */
 106        mtu_result = skel->bss->global_bpf_mtu_xdp;
 107        ASSERT_EQ(mtu_result, mtu_expect, "MTU-compare-user");
 108}
 109
 110
 111static void test_check_mtu_xdp(__u32 mtu, __u32 ifindex)
 112{
 113        struct test_check_mtu *skel;
 114        int err;
 115
 116        skel = test_check_mtu__open();
 117        if (CHECK(!skel, "skel_open", "failed"))
 118                return;
 119
 120        /* Update "constants" in BPF-prog *BEFORE* libbpf load */
 121        skel->rodata->GLOBAL_USER_MTU = mtu;
 122        skel->rodata->GLOBAL_USER_IFINDEX = ifindex;
 123
 124        err = test_check_mtu__load(skel);
 125        if (CHECK(err, "skel_load", "failed: %d\n", err))
 126                goto cleanup;
 127
 128        test_check_mtu_run_xdp(skel, skel->progs.xdp_use_helper, mtu);
 129        test_check_mtu_run_xdp(skel, skel->progs.xdp_exceed_mtu, mtu);
 130        test_check_mtu_run_xdp(skel, skel->progs.xdp_minus_delta, mtu);
 131        test_check_mtu_run_xdp(skel, skel->progs.xdp_input_len, mtu);
 132        test_check_mtu_run_xdp(skel, skel->progs.xdp_input_len_exceed, mtu);
 133
 134cleanup:
 135        test_check_mtu__destroy(skel);
 136}
 137
 138static void test_check_mtu_run_tc(struct test_check_mtu *skel,
 139                                  struct bpf_program *prog,
 140                                  __u32 mtu_expect)
 141{
 142        const char *prog_name = bpf_program__name(prog);
 143        int retval_expect = BPF_OK;
 144        __u32 mtu_result = 0;
 145        char buf[256] = {};
 146        int err;
 147        struct bpf_prog_test_run_attr tattr = {
 148                .repeat = 1,
 149                .data_in = &pkt_v4,
 150                .data_size_in = sizeof(pkt_v4),
 151                .data_out = buf,
 152                .data_size_out = sizeof(buf),
 153                .prog_fd = bpf_program__fd(prog),
 154        };
 155
 156        err = bpf_prog_test_run_xattr(&tattr);
 157        CHECK_ATTR(err != 0, "bpf_prog_test_run",
 158                   "prog_name:%s (err %d errno %d retval %d)\n",
 159                   prog_name, err, errno, tattr.retval);
 160
 161        CHECK(tattr.retval != retval_expect, "retval",
 162              "progname:%s unexpected retval=%d expected=%d\n",
 163              prog_name, tattr.retval, retval_expect);
 164
 165        /* Extract MTU that BPF-prog got */
 166        mtu_result = skel->bss->global_bpf_mtu_tc;
 167        ASSERT_EQ(mtu_result, mtu_expect, "MTU-compare-user");
 168}
 169
 170
 171static void test_check_mtu_tc(__u32 mtu, __u32 ifindex)
 172{
 173        struct test_check_mtu *skel;
 174        int err;
 175
 176        skel = test_check_mtu__open();
 177        if (CHECK(!skel, "skel_open", "failed"))
 178                return;
 179
 180        /* Update "constants" in BPF-prog *BEFORE* libbpf load */
 181        skel->rodata->GLOBAL_USER_MTU = mtu;
 182        skel->rodata->GLOBAL_USER_IFINDEX = ifindex;
 183
 184        err = test_check_mtu__load(skel);
 185        if (CHECK(err, "skel_load", "failed: %d\n", err))
 186                goto cleanup;
 187
 188        test_check_mtu_run_tc(skel, skel->progs.tc_use_helper, mtu);
 189        test_check_mtu_run_tc(skel, skel->progs.tc_exceed_mtu, mtu);
 190        test_check_mtu_run_tc(skel, skel->progs.tc_exceed_mtu_da, mtu);
 191        test_check_mtu_run_tc(skel, skel->progs.tc_minus_delta, mtu);
 192        test_check_mtu_run_tc(skel, skel->progs.tc_input_len, mtu);
 193        test_check_mtu_run_tc(skel, skel->progs.tc_input_len_exceed, mtu);
 194cleanup:
 195        test_check_mtu__destroy(skel);
 196}
 197
 198void test_check_mtu(void)
 199{
 200        __u32 mtu_lo;
 201
 202        if (test__start_subtest("bpf_check_mtu XDP-attach"))
 203                test_check_mtu_xdp_attach();
 204
 205        mtu_lo = read_mtu_device_lo();
 206        if (CHECK(mtu_lo < 0, "reading MTU value", "failed (err:%d)", mtu_lo))
 207                return;
 208
 209        if (test__start_subtest("bpf_check_mtu XDP-run"))
 210                test_check_mtu_xdp(mtu_lo, 0);
 211
 212        if (test__start_subtest("bpf_check_mtu XDP-run ifindex-lookup"))
 213                test_check_mtu_xdp(mtu_lo, IFINDEX_LO);
 214
 215        if (test__start_subtest("bpf_check_mtu TC-run"))
 216                test_check_mtu_tc(mtu_lo, 0);
 217
 218        if (test__start_subtest("bpf_check_mtu TC-run ifindex-lookup"))
 219                test_check_mtu_tc(mtu_lo, IFINDEX_LO);
 220}
 221