xref: /linux/tools/testing/selftests/bpf/prog_tests/bloom_filter_map.c (revision d9104cec3e8fe4b458b74709853231385779001f)
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