linux/tools/testing/selftests/bpf/prog_tests/link_pinning.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright (c) 2020 Facebook */
   3
   4#include <test_progs.h>
   5#include <sys/stat.h>
   6
   7#include "test_link_pinning.skel.h"
   8
   9static int duration = 0;
  10
  11void test_link_pinning_subtest(struct bpf_program *prog,
  12                               struct test_link_pinning__bss *bss)
  13{
  14        const char *link_pin_path = "/sys/fs/bpf/pinned_link_test";
  15        struct stat statbuf = {};
  16        struct bpf_link *link;
  17        int err, i;
  18
  19        link = bpf_program__attach(prog);
  20        if (!ASSERT_OK_PTR(link, "link_attach"))
  21                goto cleanup;
  22
  23        bss->in = 1;
  24        usleep(1);
  25        CHECK(bss->out != 1, "res_check1", "exp %d, got %d\n", 1, bss->out);
  26
  27        /* pin link */
  28        err = bpf_link__pin(link, link_pin_path);
  29        if (CHECK(err, "link_pin", "err: %d\n", err))
  30                goto cleanup;
  31
  32        CHECK(strcmp(link_pin_path, bpf_link__pin_path(link)), "pin_path1",
  33              "exp %s, got %s\n", link_pin_path, bpf_link__pin_path(link));
  34
  35        /* check that link was pinned */
  36        err = stat(link_pin_path, &statbuf);
  37        if (CHECK(err, "stat_link", "err %d errno %d\n", err, errno))
  38                goto cleanup;
  39
  40        bss->in = 2;
  41        usleep(1);
  42        CHECK(bss->out != 2, "res_check2", "exp %d, got %d\n", 2, bss->out);
  43
  44        /* destroy link, pinned link should keep program attached */
  45        bpf_link__destroy(link);
  46        link = NULL;
  47
  48        bss->in = 3;
  49        usleep(1);
  50        CHECK(bss->out != 3, "res_check3", "exp %d, got %d\n", 3, bss->out);
  51
  52        /* re-open link from BPFFS */
  53        link = bpf_link__open(link_pin_path);
  54        if (!ASSERT_OK_PTR(link, "link_open"))
  55                goto cleanup;
  56
  57        CHECK(strcmp(link_pin_path, bpf_link__pin_path(link)), "pin_path2",
  58              "exp %s, got %s\n", link_pin_path, bpf_link__pin_path(link));
  59
  60        /* unpin link from BPFFS, program still attached */
  61        err = bpf_link__unpin(link);
  62        if (CHECK(err, "link_unpin", "err: %d\n", err))
  63                goto cleanup;
  64
  65        /* still active, as we have FD open now */
  66        bss->in = 4;
  67        usleep(1);
  68        CHECK(bss->out != 4, "res_check4", "exp %d, got %d\n", 4, bss->out);
  69
  70        bpf_link__destroy(link);
  71        link = NULL;
  72
  73        /* Validate it's finally detached.
  74         * Actual detachment might get delayed a bit, so there is no reliable
  75         * way to validate it immediately here, let's count up for long enough
  76         * and see if eventually output stops being updated
  77         */
  78        for (i = 5; i < 10000; i++) {
  79                bss->in = i;
  80                usleep(1);
  81                if (bss->out == i - 1)
  82                        break;
  83        }
  84        CHECK(i == 10000, "link_attached", "got to iteration #%d\n", i);
  85
  86cleanup:
  87        bpf_link__destroy(link);
  88}
  89
  90void test_link_pinning(void)
  91{
  92        struct test_link_pinning* skel;
  93
  94        skel = test_link_pinning__open_and_load();
  95        if (CHECK(!skel, "skel_open", "failed to open skeleton\n"))
  96                return;
  97
  98        if (test__start_subtest("pin_raw_tp"))
  99                test_link_pinning_subtest(skel->progs.raw_tp_prog, skel->bss);
 100        if (test__start_subtest("pin_tp_btf"))
 101                test_link_pinning_subtest(skel->progs.tp_btf_prog, skel->bss);
 102
 103        test_link_pinning__destroy(skel);
 104}
 105