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