Commit | Line | Data |
---|---|---|
ed9109ad JK |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright (c) 2021 Facebook */ | |
3 | ||
4 | #include <sys/syscall.h> | |
a8d89feb | 5 | #include <limits.h> |
ed9109ad JK |
6 | #include <test_progs.h> |
7 | #include "bloom_filter_map.skel.h" | |
8 | ||
9 | static void test_fail_cases(void) | |
10 | { | |
2fe256a4 | 11 | LIBBPF_OPTS(bpf_map_create_opts, opts); |
ed9109ad JK |
12 | __u32 value; |
13 | int fd, err; | |
14 | ||
15 | /* Invalid key size */ | |
2fe256a4 AN |
16 | fd = bpf_map_create(BPF_MAP_TYPE_BLOOM_FILTER, NULL, 4, sizeof(value), 100, NULL); |
17 | if (!ASSERT_LT(fd, 0, "bpf_map_create bloom filter invalid key size")) | |
ed9109ad | 18 | close(fd); |
ed9109ad JK |
19 | |
20 | /* Invalid value size */ | |
2fe256a4 AN |
21 | fd = bpf_map_create(BPF_MAP_TYPE_BLOOM_FILTER, NULL, 0, 0, 100, NULL); |
22 | if (!ASSERT_LT(fd, 0, "bpf_map_create bloom filter invalid value size 0")) | |
ed9109ad | 23 | close(fd); |
ed9109ad | 24 | |
a8d89feb AM |
25 | /* Invalid value size: too big */ |
26 | fd = bpf_map_create(BPF_MAP_TYPE_BLOOM_FILTER, NULL, 0, INT32_MAX, 100, NULL); | |
27 | if (!ASSERT_LT(fd, 0, "bpf_map_create bloom filter invalid value too large")) | |
28 | close(fd); | |
29 | ||
ed9109ad | 30 | /* Invalid max entries size */ |
2fe256a4 AN |
31 | fd = bpf_map_create(BPF_MAP_TYPE_BLOOM_FILTER, NULL, 0, sizeof(value), 0, NULL); |
32 | if (!ASSERT_LT(fd, 0, "bpf_map_create bloom filter invalid max entries size")) | |
ed9109ad | 33 | close(fd); |
ed9109ad JK |
34 | |
35 | /* Bloom filter maps do not support BPF_F_NO_PREALLOC */ | |
2fe256a4 AN |
36 | opts.map_flags = BPF_F_NO_PREALLOC; |
37 | fd = bpf_map_create(BPF_MAP_TYPE_BLOOM_FILTER, NULL, 0, sizeof(value), 100, &opts); | |
38 | if (!ASSERT_LT(fd, 0, "bpf_map_create bloom filter invalid flags")) | |
ed9109ad | 39 | close(fd); |
ed9109ad | 40 | |
2fe256a4 AN |
41 | fd = bpf_map_create(BPF_MAP_TYPE_BLOOM_FILTER, NULL, 0, sizeof(value), 100, NULL); |
42 | if (!ASSERT_GE(fd, 0, "bpf_map_create bloom filter")) | |
ed9109ad JK |
43 | return; |
44 | ||
45 | /* Test invalid flags */ | |
46 | err = bpf_map_update_elem(fd, NULL, &value, -1); | |
47 | ASSERT_EQ(err, -EINVAL, "bpf_map_update_elem bloom filter invalid flags"); | |
48 | ||
49 | err = bpf_map_update_elem(fd, NULL, &value, BPF_EXIST); | |
50 | ASSERT_EQ(err, -EINVAL, "bpf_map_update_elem bloom filter invalid flags"); | |
51 | ||
52 | err = bpf_map_update_elem(fd, NULL, &value, BPF_F_LOCK); | |
53 | ASSERT_EQ(err, -EINVAL, "bpf_map_update_elem bloom filter invalid flags"); | |
54 | ||
55 | err = bpf_map_update_elem(fd, NULL, &value, BPF_NOEXIST); | |
56 | ASSERT_EQ(err, -EINVAL, "bpf_map_update_elem bloom filter invalid flags"); | |
57 | ||
58 | err = bpf_map_update_elem(fd, NULL, &value, 10000); | |
59 | ASSERT_EQ(err, -EINVAL, "bpf_map_update_elem bloom filter invalid flags"); | |
60 | ||
61 | close(fd); | |
62 | } | |
63 | ||
7a670872 JK |
64 | static void test_success_cases(void) |
65 | { | |
2fe256a4 | 66 | LIBBPF_OPTS(bpf_map_create_opts, opts); |
7a670872 JK |
67 | char value[11]; |
68 | int fd, err; | |
69 | ||
70 | /* Create a map */ | |
2fe256a4 AN |
71 | opts.map_flags = BPF_F_ZERO_SEED | BPF_F_NUMA_NODE; |
72 | fd = bpf_map_create(BPF_MAP_TYPE_BLOOM_FILTER, NULL, 0, sizeof(value), 100, &opts); | |
73 | if (!ASSERT_GE(fd, 0, "bpf_map_create bloom filter success case")) | |
7a670872 JK |
74 | return; |
75 | ||
76 | /* Add a value to the bloom filter */ | |
77 | err = bpf_map_update_elem(fd, NULL, &value, 0); | |
78 | if (!ASSERT_OK(err, "bpf_map_update_elem bloom filter success case")) | |
79 | goto done; | |
80 | ||
81 | /* Lookup a value in the bloom filter */ | |
82 | err = bpf_map_lookup_elem(fd, NULL, &value); | |
83 | ASSERT_OK(err, "bpf_map_update_elem bloom filter success case"); | |
84 | ||
85 | done: | |
86 | close(fd); | |
87 | } | |
88 | ||
ed9109ad JK |
89 | static void check_bloom(struct bloom_filter_map *skel) |
90 | { | |
91 | struct bpf_link *link; | |
92 | ||
93 | link = bpf_program__attach(skel->progs.check_bloom); | |
94 | if (!ASSERT_OK_PTR(link, "link")) | |
95 | return; | |
96 | ||
97 | syscall(SYS_getpgid); | |
98 | ||
99 | ASSERT_EQ(skel->bss->error, 0, "error"); | |
100 | ||
101 | bpf_link__destroy(link); | |
102 | } | |
103 | ||
104 | static void test_inner_map(struct bloom_filter_map *skel, const __u32 *rand_vals, | |
105 | __u32 nr_rand_vals) | |
106 | { | |
107 | int outer_map_fd, inner_map_fd, err, i, key = 0; | |
ed9109ad JK |
108 | struct bpf_link *link; |
109 | ||
110 | /* Create a bloom filter map that will be used as the inner map */ | |
2fe256a4 AN |
111 | inner_map_fd = bpf_map_create(BPF_MAP_TYPE_BLOOM_FILTER, NULL, 0, sizeof(*rand_vals), |
112 | nr_rand_vals, NULL); | |
113 | if (!ASSERT_GE(inner_map_fd, 0, "bpf_map_create bloom filter inner map")) | |
ed9109ad JK |
114 | return; |
115 | ||
116 | for (i = 0; i < nr_rand_vals; i++) { | |
117 | err = bpf_map_update_elem(inner_map_fd, NULL, rand_vals + i, BPF_ANY); | |
118 | if (!ASSERT_OK(err, "Add random value to inner_map_fd")) | |
119 | goto done; | |
120 | } | |
121 | ||
122 | /* Add the bloom filter map to the outer map */ | |
123 | outer_map_fd = bpf_map__fd(skel->maps.outer_map); | |
124 | err = bpf_map_update_elem(outer_map_fd, &key, &inner_map_fd, BPF_ANY); | |
125 | if (!ASSERT_OK(err, "Add bloom filter map to outer map")) | |
126 | goto done; | |
127 | ||
128 | /* Attach the bloom_filter_inner_map prog */ | |
129 | link = bpf_program__attach(skel->progs.inner_map); | |
130 | if (!ASSERT_OK_PTR(link, "link")) | |
131 | goto delete_inner_map; | |
132 | ||
133 | syscall(SYS_getpgid); | |
134 | ||
135 | ASSERT_EQ(skel->bss->error, 0, "error"); | |
136 | ||
137 | bpf_link__destroy(link); | |
138 | ||
139 | delete_inner_map: | |
140 | /* Ensure the inner bloom filter map can be deleted */ | |
141 | err = bpf_map_delete_elem(outer_map_fd, &key); | |
142 | ASSERT_OK(err, "Delete inner bloom filter map"); | |
143 | ||
144 | done: | |
145 | close(inner_map_fd); | |
146 | } | |
147 | ||
148 | static int setup_progs(struct bloom_filter_map **out_skel, __u32 **out_rand_vals, | |
149 | __u32 *out_nr_rand_vals) | |
150 | { | |
151 | struct bloom_filter_map *skel; | |
152 | int random_data_fd, bloom_fd; | |
153 | __u32 *rand_vals = NULL; | |
154 | __u32 map_size, val; | |
155 | int err, i; | |
156 | ||
157 | /* Set up a bloom filter map skeleton */ | |
158 | skel = bloom_filter_map__open_and_load(); | |
159 | if (!ASSERT_OK_PTR(skel, "bloom_filter_map__open_and_load")) | |
160 | return -EINVAL; | |
161 | ||
162 | /* Set up rand_vals */ | |
163 | map_size = bpf_map__max_entries(skel->maps.map_random_data); | |
164 | rand_vals = malloc(sizeof(*rand_vals) * map_size); | |
165 | if (!rand_vals) { | |
166 | err = -ENOMEM; | |
167 | goto error; | |
168 | } | |
169 | ||
170 | /* Generate random values and populate both skeletons */ | |
171 | random_data_fd = bpf_map__fd(skel->maps.map_random_data); | |
172 | bloom_fd = bpf_map__fd(skel->maps.map_bloom); | |
173 | for (i = 0; i < map_size; i++) { | |
174 | val = rand(); | |
175 | ||
176 | err = bpf_map_update_elem(random_data_fd, &i, &val, BPF_ANY); | |
177 | if (!ASSERT_OK(err, "Add random value to map_random_data")) | |
178 | goto error; | |
179 | ||
180 | err = bpf_map_update_elem(bloom_fd, NULL, &val, BPF_ANY); | |
181 | if (!ASSERT_OK(err, "Add random value to map_bloom")) | |
182 | goto error; | |
183 | ||
184 | rand_vals[i] = val; | |
185 | } | |
186 | ||
187 | *out_skel = skel; | |
188 | *out_rand_vals = rand_vals; | |
189 | *out_nr_rand_vals = map_size; | |
190 | ||
191 | return 0; | |
192 | ||
193 | error: | |
194 | bloom_filter_map__destroy(skel); | |
195 | if (rand_vals) | |
196 | free(rand_vals); | |
197 | return err; | |
198 | } | |
199 | ||
200 | void test_bloom_filter_map(void) | |
201 | { | |
925a0157 AN |
202 | __u32 *rand_vals = NULL, nr_rand_vals = 0; |
203 | struct bloom_filter_map *skel = NULL; | |
ed9109ad JK |
204 | int err; |
205 | ||
206 | test_fail_cases(); | |
7a670872 | 207 | test_success_cases(); |
ed9109ad JK |
208 | |
209 | err = setup_progs(&skel, &rand_vals, &nr_rand_vals); | |
210 | if (err) | |
211 | return; | |
212 | ||
213 | test_inner_map(skel, rand_vals, nr_rand_vals); | |
214 | free(rand_vals); | |
215 | ||
216 | check_bloom(skel); | |
217 | ||
218 | bloom_filter_map__destroy(skel); | |
219 | } |