1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2021 Facebook */ 3 #define _GNU_SOURCE 4 #include <linux/compiler.h> 5 #include <test_progs.h> 6 #include "testing_helpers.h" 7 #include "test_perf_link.skel.h" 8 9 #define BURN_TIMEOUT_MS 100 10 #define BURN_TIMEOUT_NS BURN_TIMEOUT_MS * 1000000 11 12 static void burn_cpu(void) 13 { 14 int i; 15 16 /* spin the loop for a while (random high number) */ 17 for (i = 0; i < 1000000; ++i) 18 barrier(); 19 } 20 21 void test_perf_link(void) 22 { 23 struct test_perf_link *skel = NULL; 24 struct perf_event_attr attr; 25 int pfd = -1, link_fd = -1, err; 26 int run_cnt_before, run_cnt_after; 27 struct bpf_link_info info; 28 __u32 info_len = sizeof(info); 29 __u64 timeout_time_ns; 30 31 /* create perf event */ 32 memset(&attr, 0, sizeof(attr)); 33 attr.size = sizeof(attr); 34 attr.type = PERF_TYPE_SOFTWARE; 35 attr.config = PERF_COUNT_SW_CPU_CLOCK; 36 attr.freq = 1; 37 attr.sample_freq = 1000; 38 pfd = syscall(__NR_perf_event_open, &attr, 0, -1, -1, PERF_FLAG_FD_CLOEXEC); 39 if (!ASSERT_GE(pfd, 0, "perf_fd")) 40 goto cleanup; 41 42 skel = test_perf_link__open_and_load(); 43 if (!ASSERT_OK_PTR(skel, "skel_load")) 44 goto cleanup; 45 46 link_fd = bpf_link_create(bpf_program__fd(skel->progs.handler), pfd, 47 BPF_PERF_EVENT, NULL); 48 if (!ASSERT_GE(link_fd, 0, "link_fd")) 49 goto cleanup; 50 51 memset(&info, 0, sizeof(info)); 52 err = bpf_link_get_info_by_fd(link_fd, &info, &info_len); 53 if (!ASSERT_OK(err, "link_get_info")) 54 goto cleanup; 55 56 ASSERT_EQ(info.type, BPF_LINK_TYPE_PERF_EVENT, "link_type"); 57 ASSERT_GT(info.id, 0, "link_id"); 58 ASSERT_GT(info.prog_id, 0, "link_prog_id"); 59 60 /* ensure we get at least one perf_event prog execution */ 61 timeout_time_ns = get_time_ns() + BURN_TIMEOUT_NS; 62 while (true) { 63 burn_cpu(); 64 if (skel->bss->run_cnt > 0) 65 break; 66 if (!ASSERT_LT(get_time_ns(), timeout_time_ns, "run_cnt_timeout")) 67 break; 68 } 69 70 /* perf_event is still active, but we close link and BPF program 71 * shouldn't be executed anymore 72 */ 73 close(link_fd); 74 link_fd = -1; 75 76 /* make sure there are no stragglers */ 77 kern_sync_rcu(); 78 79 run_cnt_before = skel->bss->run_cnt; 80 burn_cpu(); 81 run_cnt_after = skel->bss->run_cnt; 82 83 ASSERT_EQ(run_cnt_before, run_cnt_after, "run_cnt_before_after"); 84 85 cleanup: 86 if (link_fd >= 0) 87 close(link_fd); 88 if (pfd >= 0) 89 close(pfd); 90 test_perf_link__destroy(skel); 91 } 92