Merge tag 'driver-core-6.9-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / tools / testing / selftests / bpf / prog_tests / bloom_filter_map.c
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 static void test_fail_cases(void)
10 {
11         LIBBPF_OPTS(bpf_map_create_opts, opts);
12         __u32 value;
13         int fd, err;
14
15         /* Invalid key size */
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"))
18                 close(fd);
19
20         /* Invalid value size */
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"))
23                 close(fd);
24
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
30         /* Invalid max entries size */
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"))
33                 close(fd);
34
35         /* Bloom filter maps do not support BPF_F_NO_PREALLOC */
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"))
39                 close(fd);
40
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"))
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
64 static void test_success_cases(void)
65 {
66         LIBBPF_OPTS(bpf_map_create_opts, opts);
67         char value[11];
68         int fd, err;
69
70         /* Create a map */
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"))
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
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;
108         struct bpf_link *link;
109
110         /* Create a bloom filter map that will be used as the inner map */
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"))
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 {
202         __u32 *rand_vals = NULL, nr_rand_vals = 0;
203         struct bloom_filter_map *skel = NULL;
204         int err;
205
206         test_fail_cases();
207         test_success_cases();
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 }