Skip to content

Commit 2fe0619

Browse files
lmbkernel-patches-bot
authored andcommitted
Add a test that exercises a basic sockmap / sockhash iteration. For
now we simply count the number of elements seen. Once sockmap update from iterators works we can extend this to perform a full copy. Signed-off-by: Lorenz Bauer <[email protected]> --- .../selftests/bpf/prog_tests/sockmap_basic.c | 89 +++++++++++++++++++ tools/testing/selftests/bpf/progs/bpf_iter.h | 9 ++ .../selftests/bpf/progs/bpf_iter_sockmap.c | 43 +++++++++ .../selftests/bpf/progs/bpf_iter_sockmap.h | 3 + 4 files changed, 144 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/bpf_iter_sockmap.c create mode 100644 tools/testing/selftests/bpf/progs/bpf_iter_sockmap.h
1 parent 31a304c commit 2fe0619

File tree

4 files changed

+144
-0
lines changed

4 files changed

+144
-0
lines changed

tools/testing/selftests/bpf/prog_tests/sockmap_basic.c

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
#include "test_skmsg_load_helpers.skel.h"
77
#include "test_sockmap_update.skel.h"
88
#include "test_sockmap_invalid_update.skel.h"
9+
#include "bpf_iter_sockmap.skel.h"
10+
11+
#include "progs/bpf_iter_sockmap.h"
912

1013
#define TCP_REPAIR 19 /* TCP sock is under repair right now */
1114

@@ -171,6 +174,88 @@ static void test_sockmap_invalid_update(void)
171174
test_sockmap_invalid_update__destroy(skel);
172175
}
173176

177+
static void test_sockmap_iter(enum bpf_map_type map_type)
178+
{
179+
DECLARE_LIBBPF_OPTS(bpf_iter_attach_opts, opts);
180+
int err, len, src_fd, iter_fd, duration;
181+
union bpf_iter_link_info linfo = {0};
182+
__s64 sock_fd[SOCKMAP_MAX_ENTRIES];
183+
__u32 i, num_sockets, max_elems;
184+
struct bpf_iter_sockmap *skel;
185+
struct bpf_link *link;
186+
struct bpf_map *src;
187+
char buf[64];
188+
189+
skel = bpf_iter_sockmap__open_and_load();
190+
if (CHECK(!skel, "bpf_iter_sockmap__open_and_load", "skeleton open_and_load failed\n"))
191+
return;
192+
193+
for (i = 0; i < ARRAY_SIZE(sock_fd); i++)
194+
sock_fd[i] = -1;
195+
196+
/* Make sure we have at least one "empty" entry to test iteration of
197+
* an empty slot.
198+
*/
199+
num_sockets = ARRAY_SIZE(sock_fd) - 1;
200+
201+
if (map_type == BPF_MAP_TYPE_SOCKMAP) {
202+
src = skel->maps.sockmap;
203+
max_elems = bpf_map__max_entries(src);
204+
} else {
205+
src = skel->maps.sockhash;
206+
max_elems = num_sockets;
207+
}
208+
209+
src_fd = bpf_map__fd(src);
210+
211+
for (i = 0; i < num_sockets; i++) {
212+
sock_fd[i] = connected_socket_v4();
213+
if (CHECK(sock_fd[i] == -1, "connected_socket_v4", "cannot connect\n"))
214+
goto out;
215+
216+
err = bpf_map_update_elem(src_fd, &i, &sock_fd[i], BPF_NOEXIST);
217+
if (CHECK(err, "map_update", "failed: %s\n", strerror(errno)))
218+
goto out;
219+
}
220+
221+
linfo.map.map_fd = src_fd;
222+
opts.link_info = &linfo;
223+
opts.link_info_len = sizeof(linfo);
224+
link = bpf_program__attach_iter(skel->progs.count_elems, &opts);
225+
if (CHECK(IS_ERR(link), "attach_iter", "attach_iter failed\n"))
226+
goto out;
227+
228+
iter_fd = bpf_iter_create(bpf_link__fd(link));
229+
if (CHECK(iter_fd < 0, "create_iter", "create_iter failed\n"))
230+
goto free_link;
231+
232+
/* do some tests */
233+
while ((len = read(iter_fd, buf, sizeof(buf))) > 0)
234+
;
235+
if (CHECK(len < 0, "read", "failed: %s\n", strerror(errno)))
236+
goto close_iter;
237+
238+
/* test results */
239+
if (CHECK(skel->bss->elems != max_elems, "elems", "got %u expected %u\n",
240+
skel->bss->elems, max_elems))
241+
goto close_iter;
242+
243+
if (CHECK(skel->bss->socks != num_sockets, "socks", "got %u expected %u\n",
244+
skel->bss->socks, num_sockets))
245+
goto close_iter;
246+
247+
close_iter:
248+
close(iter_fd);
249+
free_link:
250+
bpf_link__destroy(link);
251+
out:
252+
for (i = 0; i < num_sockets; i++) {
253+
if (sock_fd[i] >= 0)
254+
close(sock_fd[i]);
255+
}
256+
bpf_iter_sockmap__destroy(skel);
257+
}
258+
174259
void test_sockmap_basic(void)
175260
{
176261
if (test__start_subtest("sockmap create_update_free"))
@@ -187,4 +272,8 @@ void test_sockmap_basic(void)
187272
test_sockmap_update(BPF_MAP_TYPE_SOCKHASH);
188273
if (test__start_subtest("sockmap update in unsafe context"))
189274
test_sockmap_invalid_update();
275+
if (test__start_subtest("sockmap iter"))
276+
test_sockmap_iter(BPF_MAP_TYPE_SOCKMAP);
277+
if (test__start_subtest("sockhash iter"))
278+
test_sockmap_iter(BPF_MAP_TYPE_SOCKHASH);
190279
}

tools/testing/selftests/bpf/progs/bpf_iter.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#define udp6_sock udp6_sock___not_used
1414
#define bpf_iter__bpf_map_elem bpf_iter__bpf_map_elem___not_used
1515
#define bpf_iter__bpf_sk_storage_map bpf_iter__bpf_sk_storage_map___not_used
16+
#define bpf_iter__sockmap bpf_iter__sockmap___not_used
1617
#include "vmlinux.h"
1718
#undef bpf_iter_meta
1819
#undef bpf_iter__bpf_map
@@ -26,6 +27,7 @@
2627
#undef udp6_sock
2728
#undef bpf_iter__bpf_map_elem
2829
#undef bpf_iter__bpf_sk_storage_map
30+
#undef bpf_iter__sockmap
2931

3032
struct bpf_iter_meta {
3133
struct seq_file *seq;
@@ -96,3 +98,10 @@ struct bpf_iter__bpf_sk_storage_map {
9698
struct sock *sk;
9799
void *value;
98100
};
101+
102+
struct bpf_iter__sockmap {
103+
struct bpf_iter_meta *meta;
104+
struct bpf_map *map;
105+
void *key;
106+
struct sock *sk;
107+
};
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2020 Cloudflare */
3+
#include "bpf_iter.h"
4+
#include "bpf_tracing_net.h"
5+
#include "bpf_iter_sockmap.h"
6+
#include <bpf/bpf_helpers.h>
7+
#include <bpf/bpf_tracing.h>
8+
#include <errno.h>
9+
10+
char _license[] SEC("license") = "GPL";
11+
12+
struct {
13+
__uint(type, BPF_MAP_TYPE_SOCKMAP);
14+
__uint(max_entries, SOCKMAP_MAX_ENTRIES);
15+
__type(key, __u32);
16+
__type(value, __u64);
17+
} sockmap SEC(".maps");
18+
19+
struct {
20+
__uint(type, BPF_MAP_TYPE_SOCKHASH);
21+
__uint(max_entries, SOCKMAP_MAX_ENTRIES);
22+
__type(key, __u32);
23+
__type(value, __u64);
24+
} sockhash SEC(".maps");
25+
26+
__u32 elems = 0;
27+
__u32 socks = 0;
28+
29+
SEC("iter/sockmap")
30+
int count_elems(struct bpf_iter__sockmap *ctx)
31+
{
32+
struct sock *sk = ctx->sk;
33+
__u32 tmp, *key = ctx->key;
34+
int ret;
35+
36+
if (key)
37+
elems++;
38+
39+
if (sk)
40+
socks++;
41+
42+
return 0;
43+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
3+
#define SOCKMAP_MAX_ENTRIES (64)

0 commit comments

Comments
 (0)