Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: add number iterator tests

Add number iterator (bpf_iter_num_{new,next,destroy}()) tests,
validating the correct handling of various corner and common cases
*at runtime*.

Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20230308184121.1165081-8-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Andrii Nakryiko and committed by
Alexei Starovoitov
f59b1460 57400dcc

+291
+49
tools/testing/selftests/bpf/prog_tests/iters.c
··· 6 6 #include "iters.skel.h" 7 7 #include "iters_state_safety.skel.h" 8 8 #include "iters_looping.skel.h" 9 + #include "iters_num.skel.h" 10 + 11 + static void subtest_num_iters(void) 12 + { 13 + struct iters_num *skel; 14 + int err; 15 + 16 + skel = iters_num__open_and_load(); 17 + if (!ASSERT_OK_PTR(skel, "skel_open_and_load")) 18 + return; 19 + 20 + err = iters_num__attach(skel); 21 + if (!ASSERT_OK(err, "skel_attach")) 22 + goto cleanup; 23 + 24 + usleep(1); 25 + iters_num__detach(skel); 26 + 27 + #define VALIDATE_CASE(case_name) \ 28 + ASSERT_EQ(skel->bss->res_##case_name, \ 29 + skel->rodata->exp_##case_name, \ 30 + #case_name) 31 + 32 + VALIDATE_CASE(empty_zero); 33 + VALIDATE_CASE(empty_int_min); 34 + VALIDATE_CASE(empty_int_max); 35 + VALIDATE_CASE(empty_minus_one); 36 + 37 + VALIDATE_CASE(simple_sum); 38 + VALIDATE_CASE(neg_sum); 39 + VALIDATE_CASE(very_neg_sum); 40 + VALIDATE_CASE(neg_pos_sum); 41 + 42 + VALIDATE_CASE(invalid_range); 43 + VALIDATE_CASE(max_range); 44 + VALIDATE_CASE(e2big_range); 45 + 46 + VALIDATE_CASE(succ_elem_cnt); 47 + VALIDATE_CASE(overfetched_elem_cnt); 48 + VALIDATE_CASE(fail_elem_cnt); 49 + 50 + #undef VALIDATE_CASE 51 + 52 + cleanup: 53 + iters_num__destroy(skel); 54 + } 9 55 10 56 void test_iters(void) 11 57 { 12 58 RUN_TESTS(iters_state_safety); 13 59 RUN_TESTS(iters_looping); 14 60 RUN_TESTS(iters); 61 + 62 + if (test__start_subtest("num")) 63 + subtest_num_iters(); 15 64 }
+242
tools/testing/selftests/bpf/progs/iters_num.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */ 3 + 4 + #include <limits.h> 5 + #include <linux/errno.h> 6 + #include "vmlinux.h" 7 + #include <bpf/bpf_helpers.h> 8 + #include "bpf_misc.h" 9 + 10 + const volatile __s64 exp_empty_zero = 0 + 1; 11 + __s64 res_empty_zero; 12 + 13 + SEC("raw_tp/sys_enter") 14 + int num_empty_zero(const void *ctx) 15 + { 16 + __s64 sum = 0, i; 17 + 18 + bpf_for(i, 0, 0) sum += i; 19 + res_empty_zero = 1 + sum; 20 + 21 + return 0; 22 + } 23 + 24 + const volatile __s64 exp_empty_int_min = 0 + 2; 25 + __s64 res_empty_int_min; 26 + 27 + SEC("raw_tp/sys_enter") 28 + int num_empty_int_min(const void *ctx) 29 + { 30 + __s64 sum = 0, i; 31 + 32 + bpf_for(i, INT_MIN, INT_MIN) sum += i; 33 + res_empty_int_min = 2 + sum; 34 + 35 + return 0; 36 + } 37 + 38 + const volatile __s64 exp_empty_int_max = 0 + 3; 39 + __s64 res_empty_int_max; 40 + 41 + SEC("raw_tp/sys_enter") 42 + int num_empty_int_max(const void *ctx) 43 + { 44 + __s64 sum = 0, i; 45 + 46 + bpf_for(i, INT_MAX, INT_MAX) sum += i; 47 + res_empty_int_max = 3 + sum; 48 + 49 + return 0; 50 + } 51 + 52 + const volatile __s64 exp_empty_minus_one = 0 + 4; 53 + __s64 res_empty_minus_one; 54 + 55 + SEC("raw_tp/sys_enter") 56 + int num_empty_minus_one(const void *ctx) 57 + { 58 + __s64 sum = 0, i; 59 + 60 + bpf_for(i, -1, -1) sum += i; 61 + res_empty_minus_one = 4 + sum; 62 + 63 + return 0; 64 + } 65 + 66 + const volatile __s64 exp_simple_sum = 9 * 10 / 2; 67 + __s64 res_simple_sum; 68 + 69 + SEC("raw_tp/sys_enter") 70 + int num_simple_sum(const void *ctx) 71 + { 72 + __s64 sum = 0, i; 73 + 74 + bpf_for(i, 0, 10) sum += i; 75 + res_simple_sum = sum; 76 + 77 + return 0; 78 + } 79 + 80 + const volatile __s64 exp_neg_sum = -11 * 10 / 2; 81 + __s64 res_neg_sum; 82 + 83 + SEC("raw_tp/sys_enter") 84 + int num_neg_sum(const void *ctx) 85 + { 86 + __s64 sum = 0, i; 87 + 88 + bpf_for(i, -10, 0) sum += i; 89 + res_neg_sum = sum; 90 + 91 + return 0; 92 + } 93 + 94 + const volatile __s64 exp_very_neg_sum = INT_MIN + (__s64)(INT_MIN + 1); 95 + __s64 res_very_neg_sum; 96 + 97 + SEC("raw_tp/sys_enter") 98 + int num_very_neg_sum(const void *ctx) 99 + { 100 + __s64 sum = 0, i; 101 + 102 + bpf_for(i, INT_MIN, INT_MIN + 2) sum += i; 103 + res_very_neg_sum = sum; 104 + 105 + return 0; 106 + } 107 + 108 + const volatile __s64 exp_very_big_sum = (__s64)(INT_MAX - 1) + (__s64)(INT_MAX - 2); 109 + __s64 res_very_big_sum; 110 + 111 + SEC("raw_tp/sys_enter") 112 + int num_very_big_sum(const void *ctx) 113 + { 114 + __s64 sum = 0, i; 115 + 116 + bpf_for(i, INT_MAX - 2, INT_MAX) sum += i; 117 + res_very_big_sum = sum; 118 + 119 + return 0; 120 + } 121 + 122 + const volatile __s64 exp_neg_pos_sum = -3; 123 + __s64 res_neg_pos_sum; 124 + 125 + SEC("raw_tp/sys_enter") 126 + int num_neg_pos_sum(const void *ctx) 127 + { 128 + __s64 sum = 0, i; 129 + 130 + bpf_for(i, -3, 3) sum += i; 131 + res_neg_pos_sum = sum; 132 + 133 + return 0; 134 + } 135 + 136 + const volatile __s64 exp_invalid_range = -EINVAL; 137 + __s64 res_invalid_range; 138 + 139 + SEC("raw_tp/sys_enter") 140 + int num_invalid_range(const void *ctx) 141 + { 142 + struct bpf_iter_num it; 143 + 144 + res_invalid_range = bpf_iter_num_new(&it, 1, 0); 145 + bpf_iter_num_destroy(&it); 146 + 147 + return 0; 148 + } 149 + 150 + const volatile __s64 exp_max_range = 0 + 10; 151 + __s64 res_max_range; 152 + 153 + SEC("raw_tp/sys_enter") 154 + int num_max_range(const void *ctx) 155 + { 156 + struct bpf_iter_num it; 157 + 158 + res_max_range = 10 + bpf_iter_num_new(&it, 0, BPF_MAX_LOOPS); 159 + bpf_iter_num_destroy(&it); 160 + 161 + return 0; 162 + } 163 + 164 + const volatile __s64 exp_e2big_range = -E2BIG; 165 + __s64 res_e2big_range; 166 + 167 + SEC("raw_tp/sys_enter") 168 + int num_e2big_range(const void *ctx) 169 + { 170 + struct bpf_iter_num it; 171 + 172 + res_e2big_range = bpf_iter_num_new(&it, -1, BPF_MAX_LOOPS); 173 + bpf_iter_num_destroy(&it); 174 + 175 + return 0; 176 + } 177 + 178 + const volatile __s64 exp_succ_elem_cnt = 10; 179 + __s64 res_succ_elem_cnt; 180 + 181 + SEC("raw_tp/sys_enter") 182 + int num_succ_elem_cnt(const void *ctx) 183 + { 184 + struct bpf_iter_num it; 185 + int cnt = 0, *v; 186 + 187 + bpf_iter_num_new(&it, 0, 10); 188 + while ((v = bpf_iter_num_next(&it))) { 189 + cnt++; 190 + } 191 + bpf_iter_num_destroy(&it); 192 + 193 + res_succ_elem_cnt = cnt; 194 + 195 + return 0; 196 + } 197 + 198 + const volatile __s64 exp_overfetched_elem_cnt = 5; 199 + __s64 res_overfetched_elem_cnt; 200 + 201 + SEC("raw_tp/sys_enter") 202 + int num_overfetched_elem_cnt(const void *ctx) 203 + { 204 + struct bpf_iter_num it; 205 + int cnt = 0, *v, i; 206 + 207 + bpf_iter_num_new(&it, 0, 5); 208 + for (i = 0; i < 10; i++) { 209 + v = bpf_iter_num_next(&it); 210 + if (v) 211 + cnt++; 212 + } 213 + bpf_iter_num_destroy(&it); 214 + 215 + res_overfetched_elem_cnt = cnt; 216 + 217 + return 0; 218 + } 219 + 220 + const volatile __s64 exp_fail_elem_cnt = 20 + 0; 221 + __s64 res_fail_elem_cnt; 222 + 223 + SEC("raw_tp/sys_enter") 224 + int num_fail_elem_cnt(const void *ctx) 225 + { 226 + struct bpf_iter_num it; 227 + int cnt = 0, *v, i; 228 + 229 + bpf_iter_num_new(&it, 100, 10); 230 + for (i = 0; i < 10; i++) { 231 + v = bpf_iter_num_next(&it); 232 + if (v) 233 + cnt++; 234 + } 235 + bpf_iter_num_destroy(&it); 236 + 237 + res_fail_elem_cnt = 20 + cnt; 238 + 239 + return 0; 240 + } 241 + 242 + char _license[] SEC("license") = "GPL";