0001
0002
0003
0004 #include <test_progs.h>
0005 #include <network_helpers.h>
0006 #include "bpf_loop.skel.h"
0007
0008 static void check_nr_loops(struct bpf_loop *skel)
0009 {
0010 struct bpf_link *link;
0011
0012 link = bpf_program__attach(skel->progs.test_prog);
0013 if (!ASSERT_OK_PTR(link, "link"))
0014 return;
0015
0016
0017 skel->bss->nr_loops = 0;
0018
0019 usleep(1);
0020
0021 ASSERT_EQ(skel->bss->nr_loops_returned, skel->bss->nr_loops,
0022 "0 loops");
0023
0024
0025 skel->bss->nr_loops = 500;
0026
0027 usleep(1);
0028
0029 ASSERT_EQ(skel->bss->nr_loops_returned, skel->bss->nr_loops,
0030 "500 loops");
0031 ASSERT_EQ(skel->bss->g_output, (500 * 499) / 2, "g_output");
0032
0033
0034 skel->bss->nr_loops = -1;
0035
0036 usleep(1);
0037
0038 ASSERT_EQ(skel->bss->err, -E2BIG, "over max limit");
0039
0040 bpf_link__destroy(link);
0041 }
0042
0043 static void check_callback_fn_stop(struct bpf_loop *skel)
0044 {
0045 struct bpf_link *link;
0046
0047 link = bpf_program__attach(skel->progs.test_prog);
0048 if (!ASSERT_OK_PTR(link, "link"))
0049 return;
0050
0051
0052 skel->bss->nr_loops = 400;
0053 skel->data->stop_index = 50;
0054
0055 usleep(1);
0056
0057 ASSERT_EQ(skel->bss->nr_loops_returned, skel->data->stop_index + 1,
0058 "nr_loops_returned");
0059 ASSERT_EQ(skel->bss->g_output, (50 * 49) / 2,
0060 "g_output");
0061
0062 bpf_link__destroy(link);
0063 }
0064
0065 static void check_null_callback_ctx(struct bpf_loop *skel)
0066 {
0067 struct bpf_link *link;
0068
0069
0070 link = bpf_program__attach(skel->progs.prog_null_ctx);
0071 if (!ASSERT_OK_PTR(link, "link"))
0072 return;
0073
0074 skel->bss->nr_loops = 10;
0075
0076 usleep(1);
0077
0078 ASSERT_EQ(skel->bss->nr_loops_returned, skel->bss->nr_loops,
0079 "nr_loops_returned");
0080
0081 bpf_link__destroy(link);
0082 }
0083
0084 static void check_invalid_flags(struct bpf_loop *skel)
0085 {
0086 struct bpf_link *link;
0087
0088
0089 link = bpf_program__attach(skel->progs.prog_invalid_flags);
0090 if (!ASSERT_OK_PTR(link, "link"))
0091 return;
0092
0093 usleep(1);
0094
0095 ASSERT_EQ(skel->bss->err, -EINVAL, "err");
0096
0097 bpf_link__destroy(link);
0098 }
0099
0100 static void check_nested_calls(struct bpf_loop *skel)
0101 {
0102 __u32 nr_loops = 100, nested_callback_nr_loops = 4;
0103 struct bpf_link *link;
0104
0105
0106 link = bpf_program__attach(skel->progs.prog_nested_calls);
0107 if (!ASSERT_OK_PTR(link, "link"))
0108 return;
0109
0110 skel->bss->nr_loops = nr_loops;
0111 skel->bss->nested_callback_nr_loops = nested_callback_nr_loops;
0112
0113 usleep(1);
0114
0115 ASSERT_EQ(skel->bss->nr_loops_returned, nr_loops * nested_callback_nr_loops
0116 * nested_callback_nr_loops, "nr_loops_returned");
0117 ASSERT_EQ(skel->bss->g_output, (4 * 3) / 2 * nested_callback_nr_loops
0118 * nr_loops, "g_output");
0119
0120 bpf_link__destroy(link);
0121 }
0122
0123 static void check_non_constant_callback(struct bpf_loop *skel)
0124 {
0125 struct bpf_link *link =
0126 bpf_program__attach(skel->progs.prog_non_constant_callback);
0127
0128 if (!ASSERT_OK_PTR(link, "link"))
0129 return;
0130
0131 skel->bss->callback_selector = 0x0F;
0132 usleep(1);
0133 ASSERT_EQ(skel->bss->g_output, 0x0F, "g_output #1");
0134
0135 skel->bss->callback_selector = 0xF0;
0136 usleep(1);
0137 ASSERT_EQ(skel->bss->g_output, 0xF0, "g_output #2");
0138
0139 bpf_link__destroy(link);
0140 }
0141
0142 static void check_stack(struct bpf_loop *skel)
0143 {
0144 struct bpf_link *link = bpf_program__attach(skel->progs.stack_check);
0145 const int max_key = 12;
0146 int key;
0147 int map_fd;
0148
0149 if (!ASSERT_OK_PTR(link, "link"))
0150 return;
0151
0152 map_fd = bpf_map__fd(skel->maps.map1);
0153
0154 if (!ASSERT_GE(map_fd, 0, "bpf_map__fd"))
0155 goto out;
0156
0157 for (key = 1; key <= max_key; ++key) {
0158 int val = key;
0159 int err = bpf_map_update_elem(map_fd, &key, &val, BPF_NOEXIST);
0160
0161 if (!ASSERT_OK(err, "bpf_map_update_elem"))
0162 goto out;
0163 }
0164
0165 usleep(1);
0166
0167 for (key = 1; key <= max_key; ++key) {
0168 int val;
0169 int err = bpf_map_lookup_elem(map_fd, &key, &val);
0170
0171 if (!ASSERT_OK(err, "bpf_map_lookup_elem"))
0172 goto out;
0173 if (!ASSERT_EQ(val, key + 1, "bad value in the map"))
0174 goto out;
0175 }
0176
0177 out:
0178 bpf_link__destroy(link);
0179 }
0180
0181 void test_bpf_loop(void)
0182 {
0183 struct bpf_loop *skel;
0184
0185 skel = bpf_loop__open_and_load();
0186 if (!ASSERT_OK_PTR(skel, "bpf_loop__open_and_load"))
0187 return;
0188
0189 skel->bss->pid = getpid();
0190
0191 if (test__start_subtest("check_nr_loops"))
0192 check_nr_loops(skel);
0193 if (test__start_subtest("check_callback_fn_stop"))
0194 check_callback_fn_stop(skel);
0195 if (test__start_subtest("check_null_callback_ctx"))
0196 check_null_callback_ctx(skel);
0197 if (test__start_subtest("check_invalid_flags"))
0198 check_invalid_flags(skel);
0199 if (test__start_subtest("check_nested_calls"))
0200 check_nested_calls(skel);
0201 if (test__start_subtest("check_non_constant_callback"))
0202 check_non_constant_callback(skel);
0203 if (test__start_subtest("check_stack"))
0204 check_stack(skel);
0205
0206 bpf_loop__destroy(skel);
0207 }