Linux Audio

Check our new training course

Loading...
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (C) 2023. Huawei Technologies Co., Ltd */
  3#define _GNU_SOURCE
  4#include <unistd.h>
  5#include <sys/syscall.h>
  6#include <test_progs.h>
  7#include <bpf/btf.h>
  8
  9#include "access_map_in_map.skel.h"
 10#include "update_map_in_htab.skel.h"
 11
 12struct thread_ctx {
 13	pthread_barrier_t barrier;
 14	int outer_map_fd;
 15	int start, abort;
 16	int loop, err;
 17};
 18
 19static int wait_for_start_or_abort(struct thread_ctx *ctx)
 20{
 21	while (!ctx->start && !ctx->abort)
 22		usleep(1);
 23	return ctx->abort ? -1 : 0;
 24}
 25
 26static void *update_map_fn(void *data)
 27{
 28	struct thread_ctx *ctx = data;
 29	int loop = ctx->loop, err = 0;
 30
 31	if (wait_for_start_or_abort(ctx) < 0)
 32		return NULL;
 33	pthread_barrier_wait(&ctx->barrier);
 34
 35	while (loop-- > 0) {
 36		int fd, zero = 0;
 37
 38		fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, NULL, 4, 4, 1, NULL);
 39		if (fd < 0) {
 40			err |= 1;
 41			pthread_barrier_wait(&ctx->barrier);
 42			continue;
 43		}
 44
 45		/* Remove the old inner map */
 46		if (bpf_map_update_elem(ctx->outer_map_fd, &zero, &fd, 0) < 0)
 47			err |= 2;
 48		close(fd);
 49		pthread_barrier_wait(&ctx->barrier);
 50	}
 51
 52	ctx->err = err;
 53
 54	return NULL;
 55}
 56
 57static void *access_map_fn(void *data)
 58{
 59	struct thread_ctx *ctx = data;
 60	int loop = ctx->loop;
 61
 62	if (wait_for_start_or_abort(ctx) < 0)
 63		return NULL;
 64	pthread_barrier_wait(&ctx->barrier);
 65
 66	while (loop-- > 0) {
 67		/* Access the old inner map */
 68		syscall(SYS_getpgid);
 69		pthread_barrier_wait(&ctx->barrier);
 70	}
 71
 72	return NULL;
 73}
 74
 75static void test_map_in_map_access(const char *prog_name, const char *map_name)
 76{
 77	struct access_map_in_map *skel;
 78	struct bpf_map *outer_map;
 79	struct bpf_program *prog;
 80	struct thread_ctx ctx;
 81	pthread_t tid[2];
 82	int err;
 83
 84	skel = access_map_in_map__open();
 85	if (!ASSERT_OK_PTR(skel, "access_map_in_map open"))
 86		return;
 87
 88	prog = bpf_object__find_program_by_name(skel->obj, prog_name);
 89	if (!ASSERT_OK_PTR(prog, "find program"))
 90		goto out;
 91	bpf_program__set_autoload(prog, true);
 92
 93	outer_map = bpf_object__find_map_by_name(skel->obj, map_name);
 94	if (!ASSERT_OK_PTR(outer_map, "find map"))
 95		goto out;
 96
 97	err = access_map_in_map__load(skel);
 98	if (!ASSERT_OK(err, "access_map_in_map load"))
 99		goto out;
100
101	err = access_map_in_map__attach(skel);
102	if (!ASSERT_OK(err, "access_map_in_map attach"))
103		goto out;
104
105	skel->bss->tgid = getpid();
106
107	memset(&ctx, 0, sizeof(ctx));
108	pthread_barrier_init(&ctx.barrier, NULL, 2);
109	ctx.outer_map_fd = bpf_map__fd(outer_map);
110	ctx.loop = 4;
111
112	err = pthread_create(&tid[0], NULL, update_map_fn, &ctx);
113	if (!ASSERT_OK(err, "close_thread"))
114		goto out;
115
116	err = pthread_create(&tid[1], NULL, access_map_fn, &ctx);
117	if (!ASSERT_OK(err, "read_thread")) {
118		ctx.abort = 1;
119		pthread_join(tid[0], NULL);
120		goto out;
121	}
122
123	ctx.start = 1;
124	pthread_join(tid[0], NULL);
125	pthread_join(tid[1], NULL);
126
127	ASSERT_OK(ctx.err, "err");
128out:
129	access_map_in_map__destroy(skel);
130}
131
132static void add_del_fd_htab(int outer_fd)
133{
134	int inner_fd, err;
135	int key = 1;
136
137	inner_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, "arr1", 4, 4, 1, NULL);
138	if (!ASSERT_OK_FD(inner_fd, "inner1"))
139		return;
140	err = bpf_map_update_elem(outer_fd, &key, &inner_fd, BPF_NOEXIST);
141	close(inner_fd);
142	if (!ASSERT_OK(err, "add"))
143		return;
144
145	/* Delete */
146	err = bpf_map_delete_elem(outer_fd, &key);
147	ASSERT_OK(err, "del");
148}
149
150static void overwrite_fd_htab(int outer_fd)
151{
152	int inner_fd, err;
153	int key = 1;
154
155	inner_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, "arr1", 4, 4, 1, NULL);
156	if (!ASSERT_OK_FD(inner_fd, "inner1"))
157		return;
158	err = bpf_map_update_elem(outer_fd, &key, &inner_fd, BPF_NOEXIST);
159	close(inner_fd);
160	if (!ASSERT_OK(err, "add"))
161		return;
162
163	/* Overwrite */
164	inner_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, "arr2", 4, 4, 1, NULL);
165	if (!ASSERT_OK_FD(inner_fd, "inner2"))
166		goto out;
167	err = bpf_map_update_elem(outer_fd, &key, &inner_fd, BPF_EXIST);
168	close(inner_fd);
169	if (!ASSERT_OK(err, "overwrite"))
170		goto out;
171
172	err = bpf_map_delete_elem(outer_fd, &key);
173	ASSERT_OK(err, "del");
174	return;
175out:
176	bpf_map_delete_elem(outer_fd, &key);
177}
178
179static void lookup_delete_fd_htab(int outer_fd)
180{
181	int key = 1, value;
182	int inner_fd, err;
183
184	inner_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, "arr1", 4, 4, 1, NULL);
185	if (!ASSERT_OK_FD(inner_fd, "inner1"))
186		return;
187	err = bpf_map_update_elem(outer_fd, &key, &inner_fd, BPF_NOEXIST);
188	close(inner_fd);
189	if (!ASSERT_OK(err, "add"))
190		return;
191
192	/* lookup_and_delete is not supported for htab of maps */
193	err = bpf_map_lookup_and_delete_elem(outer_fd, &key, &value);
194	ASSERT_EQ(err, -ENOTSUPP, "lookup_del");
195
196	err = bpf_map_delete_elem(outer_fd, &key);
197	ASSERT_OK(err, "del");
198}
199
200static void batched_lookup_delete_fd_htab(int outer_fd)
201{
202	int keys[2] = {1, 2}, values[2];
203	unsigned int cnt, batch;
204	int inner_fd, err;
205
206	inner_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, "arr1", 4, 4, 1, NULL);
207	if (!ASSERT_OK_FD(inner_fd, "inner1"))
208		return;
209
210	err = bpf_map_update_elem(outer_fd, &keys[0], &inner_fd, BPF_NOEXIST);
211	close(inner_fd);
212	if (!ASSERT_OK(err, "add1"))
213		return;
214
215	inner_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, "arr2", 4, 4, 1, NULL);
216	if (!ASSERT_OK_FD(inner_fd, "inner2"))
217		goto out;
218	err = bpf_map_update_elem(outer_fd, &keys[1], &inner_fd, BPF_NOEXIST);
219	close(inner_fd);
220	if (!ASSERT_OK(err, "add2"))
221		goto out;
222
223	/* batched lookup_and_delete */
224	cnt = ARRAY_SIZE(keys);
225	err = bpf_map_lookup_and_delete_batch(outer_fd, NULL, &batch, keys, values, &cnt, NULL);
226	ASSERT_TRUE((!err || err == -ENOENT), "delete_batch ret");
227	ASSERT_EQ(cnt, ARRAY_SIZE(keys), "delete_batch cnt");
228
229out:
230	bpf_map_delete_elem(outer_fd, &keys[0]);
231}
232
233static void test_update_map_in_htab(bool preallocate)
234{
235	struct update_map_in_htab *skel;
236	int err, fd;
237
238	skel = update_map_in_htab__open();
239	if (!ASSERT_OK_PTR(skel, "open"))
240		return;
241
242	err = update_map_in_htab__load(skel);
243	if (!ASSERT_OK(err, "load"))
244		goto out;
245
246	fd = preallocate ? bpf_map__fd(skel->maps.outer_htab_map) :
247			   bpf_map__fd(skel->maps.outer_alloc_htab_map);
248
249	add_del_fd_htab(fd);
250	overwrite_fd_htab(fd);
251	lookup_delete_fd_htab(fd);
252	batched_lookup_delete_fd_htab(fd);
253out:
254	update_map_in_htab__destroy(skel);
255}
256
257void test_map_in_map(void)
258{
259	if (test__start_subtest("acc_map_in_array"))
260		test_map_in_map_access("access_map_in_array", "outer_array_map");
261	if (test__start_subtest("sleepable_acc_map_in_array"))
262		test_map_in_map_access("sleepable_access_map_in_array", "outer_array_map");
263	if (test__start_subtest("acc_map_in_htab"))
264		test_map_in_map_access("access_map_in_htab", "outer_htab_map");
265	if (test__start_subtest("sleepable_acc_map_in_htab"))
266		test_map_in_map_access("sleepable_access_map_in_htab", "outer_htab_map");
267	if (test__start_subtest("update_map_in_htab"))
268		test_update_map_in_htab(true);
269	if (test__start_subtest("update_map_in_alloc_htab"))
270		test_update_map_in_htab(false);
271}
v6.8
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (C) 2023. Huawei Technologies Co., Ltd */
  3#define _GNU_SOURCE
  4#include <unistd.h>
  5#include <sys/syscall.h>
  6#include <test_progs.h>
  7#include <bpf/btf.h>
 
  8#include "access_map_in_map.skel.h"
 
  9
 10struct thread_ctx {
 11	pthread_barrier_t barrier;
 12	int outer_map_fd;
 13	int start, abort;
 14	int loop, err;
 15};
 16
 17static int wait_for_start_or_abort(struct thread_ctx *ctx)
 18{
 19	while (!ctx->start && !ctx->abort)
 20		usleep(1);
 21	return ctx->abort ? -1 : 0;
 22}
 23
 24static void *update_map_fn(void *data)
 25{
 26	struct thread_ctx *ctx = data;
 27	int loop = ctx->loop, err = 0;
 28
 29	if (wait_for_start_or_abort(ctx) < 0)
 30		return NULL;
 31	pthread_barrier_wait(&ctx->barrier);
 32
 33	while (loop-- > 0) {
 34		int fd, zero = 0;
 35
 36		fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, NULL, 4, 4, 1, NULL);
 37		if (fd < 0) {
 38			err |= 1;
 39			pthread_barrier_wait(&ctx->barrier);
 40			continue;
 41		}
 42
 43		/* Remove the old inner map */
 44		if (bpf_map_update_elem(ctx->outer_map_fd, &zero, &fd, 0) < 0)
 45			err |= 2;
 46		close(fd);
 47		pthread_barrier_wait(&ctx->barrier);
 48	}
 49
 50	ctx->err = err;
 51
 52	return NULL;
 53}
 54
 55static void *access_map_fn(void *data)
 56{
 57	struct thread_ctx *ctx = data;
 58	int loop = ctx->loop;
 59
 60	if (wait_for_start_or_abort(ctx) < 0)
 61		return NULL;
 62	pthread_barrier_wait(&ctx->barrier);
 63
 64	while (loop-- > 0) {
 65		/* Access the old inner map */
 66		syscall(SYS_getpgid);
 67		pthread_barrier_wait(&ctx->barrier);
 68	}
 69
 70	return NULL;
 71}
 72
 73static void test_map_in_map_access(const char *prog_name, const char *map_name)
 74{
 75	struct access_map_in_map *skel;
 76	struct bpf_map *outer_map;
 77	struct bpf_program *prog;
 78	struct thread_ctx ctx;
 79	pthread_t tid[2];
 80	int err;
 81
 82	skel = access_map_in_map__open();
 83	if (!ASSERT_OK_PTR(skel, "access_map_in_map open"))
 84		return;
 85
 86	prog = bpf_object__find_program_by_name(skel->obj, prog_name);
 87	if (!ASSERT_OK_PTR(prog, "find program"))
 88		goto out;
 89	bpf_program__set_autoload(prog, true);
 90
 91	outer_map = bpf_object__find_map_by_name(skel->obj, map_name);
 92	if (!ASSERT_OK_PTR(outer_map, "find map"))
 93		goto out;
 94
 95	err = access_map_in_map__load(skel);
 96	if (!ASSERT_OK(err, "access_map_in_map load"))
 97		goto out;
 98
 99	err = access_map_in_map__attach(skel);
100	if (!ASSERT_OK(err, "access_map_in_map attach"))
101		goto out;
102
103	skel->bss->tgid = getpid();
104
105	memset(&ctx, 0, sizeof(ctx));
106	pthread_barrier_init(&ctx.barrier, NULL, 2);
107	ctx.outer_map_fd = bpf_map__fd(outer_map);
108	ctx.loop = 4;
109
110	err = pthread_create(&tid[0], NULL, update_map_fn, &ctx);
111	if (!ASSERT_OK(err, "close_thread"))
112		goto out;
113
114	err = pthread_create(&tid[1], NULL, access_map_fn, &ctx);
115	if (!ASSERT_OK(err, "read_thread")) {
116		ctx.abort = 1;
117		pthread_join(tid[0], NULL);
118		goto out;
119	}
120
121	ctx.start = 1;
122	pthread_join(tid[0], NULL);
123	pthread_join(tid[1], NULL);
124
125	ASSERT_OK(ctx.err, "err");
126out:
127	access_map_in_map__destroy(skel);
128}
129
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130void test_map_in_map(void)
131{
132	if (test__start_subtest("acc_map_in_array"))
133		test_map_in_map_access("access_map_in_array", "outer_array_map");
134	if (test__start_subtest("sleepable_acc_map_in_array"))
135		test_map_in_map_access("sleepable_access_map_in_array", "outer_array_map");
136	if (test__start_subtest("acc_map_in_htab"))
137		test_map_in_map_access("access_map_in_htab", "outer_htab_map");
138	if (test__start_subtest("sleepable_acc_map_in_htab"))
139		test_map_in_map_access("sleepable_access_map_in_htab", "outer_htab_map");
 
 
 
 
140}
141