File Index
Files and directories
Sign in
FILE

fd_htab_lookup.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/bpf/prog_tests/fd_htab_lookup.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (C) 2025. Huawei Technologies Co., Ltd */
  3#define _GNU_SOURCE
  4#include <stdbool.h>
  5#include <test_progs.h>
  6#include "fd_htab_lookup.skel.h"
  7
  8struct htab_op_ctx {
  9	int fd;
 10	int loop;
 11	unsigned int entries;
 12	bool stop;
 13};
 14
 15#define ERR_TO_RETVAL(where, err) ((void *)(long)(((where) << 12) | (-err)))
 16
 17static void *htab_lookup_fn(void *arg)
 18{
 19	struct htab_op_ctx *ctx = arg;
 20	int i = 0;
 21
 22	while (i++ < ctx->loop && !ctx->stop) {
 23		unsigned int j;
 24
 25		for (j = 0; j < ctx->entries; j++) {
 26			unsigned int key = j, zero = 0, value;
 27			int inner_fd, err;
 28
 29			err = bpf_map_lookup_elem(ctx->fd, &key, &value);
 30			if (err) {
 31				ctx->stop = true;
 32				return ERR_TO_RETVAL(1, err);
 33			}
 34
 35			inner_fd = bpf_map_get_fd_by_id(value);
 36			if (inner_fd < 0) {
 37				/* The old map has been freed */
 38				if (inner_fd == -ENOENT)
 39					continue;
 40				ctx->stop = true;
 41				return ERR_TO_RETVAL(2, inner_fd);
 42			}
 43
 44			err = bpf_map_lookup_elem(inner_fd, &zero, &value);
 45			if (err) {
 46				close(inner_fd);
 47				ctx->stop = true;
 48				return ERR_TO_RETVAL(3, err);
 49			}
 50			close(inner_fd);
 51
 52			if (value != key) {
 53				ctx->stop = true;
 54				return ERR_TO_RETVAL(4, -EINVAL);
 55			}
 56		}
 57	}
 58
 59	return NULL;
 60}
 61
 62static void *htab_update_fn(void *arg)
 63{
 64	struct htab_op_ctx *ctx = arg;
 65	int i = 0;
 66
 67	while (i++ < ctx->loop && !ctx->stop) {
 68		unsigned int j;
 69
 70		for (j = 0; j < ctx->entries; j++) {
 71			unsigned int key = j, zero = 0;
 72			int inner_fd, err;
 73
 74			inner_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, NULL, 4, 4, 1, NULL);
 75			if (inner_fd < 0) {
 76				ctx->stop = true;
 77				return ERR_TO_RETVAL(1, inner_fd);
 78			}
 79
 80			err = bpf_map_update_elem(inner_fd, &zero, &key, 0);
 81			if (err) {
 82				close(inner_fd);
 83				ctx->stop = true;
 84				return ERR_TO_RETVAL(2, err);
 85			}
 86
 87			err = bpf_map_update_elem(ctx->fd, &key, &inner_fd, BPF_EXIST);
 88			if (err) {
 89				close(inner_fd);
 90				ctx->stop = true;
 91				return ERR_TO_RETVAL(3, err);
 92			}
 93			close(inner_fd);
 94		}
 95	}
 96
 97	return NULL;
 98}
 99
100static int setup_htab(int fd, unsigned int entries)
101{
102	unsigned int i;
103
104	for (i = 0; i < entries; i++) {
105		unsigned int key = i, zero = 0;
106		int inner_fd, err;
107
108		inner_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, NULL, 4, 4, 1, NULL);
109		if (!ASSERT_OK_FD(inner_fd, "new array"))
110			return -1;
111
112		err = bpf_map_update_elem(inner_fd, &zero, &key, 0);
113		if (!ASSERT_OK(err, "init array")) {
114			close(inner_fd);
115			return -1;
116		}
117
118		err = bpf_map_update_elem(fd, &key, &inner_fd, 0);
119		if (!ASSERT_OK(err, "init outer")) {
120			close(inner_fd);
121			return -1;
122		}
123		close(inner_fd);
124	}
125
126	return 0;
127}
128
129static int get_int_from_env(const char *name, int dft)
130{
131	const char *value;
132
133	value = getenv(name);
134	if (!value)
135		return dft;
136
137	return atoi(value);
138}
139
140void test_fd_htab_lookup(void)
141{
142	unsigned int i, wr_nr = 8, rd_nr = 16;
143	pthread_t tids[wr_nr + rd_nr];
144	struct fd_htab_lookup *skel;
145	struct htab_op_ctx ctx;
146	int err;
147
148	skel = fd_htab_lookup__open_and_load();
149	if (!ASSERT_OK_PTR(skel, "fd_htab_lookup__open_and_load"))
150		return;
151
152	ctx.fd = bpf_map__fd(skel->maps.outer_map);
153	ctx.loop = get_int_from_env("FD_HTAB_LOOP_NR", 5);
154	ctx.stop = false;
155	ctx.entries = 8;
156
157	err = setup_htab(ctx.fd, ctx.entries);
158	if (err)
159		goto destroy;
160
161	memset(tids, 0, sizeof(tids));
162	for (i = 0; i < wr_nr; i++) {
163		err = pthread_create(&tids[i], NULL, htab_update_fn, &ctx);
164		if (!ASSERT_OK(err, "pthread_create")) {
165			ctx.stop = true;
166			goto reap;
167		}
168	}
169	for (i = 0; i < rd_nr; i++) {
170		err = pthread_create(&tids[i + wr_nr], NULL, htab_lookup_fn, &ctx);
171		if (!ASSERT_OK(err, "pthread_create")) {
172			ctx.stop = true;
173			goto reap;
174		}
175	}
176
177reap:
178	for (i = 0; i < wr_nr + rd_nr; i++) {
179		void *ret = NULL;
180		char desc[32];
181
182		if (!tids[i])
183			continue;
184
185		snprintf(desc, sizeof(desc), "thread %u", i + 1);
186		err = pthread_join(tids[i], &ret);
187		ASSERT_OK(err, desc);
188		ASSERT_EQ(ret, NULL, desc);
189	}
190destroy:
191	fd_htab_lookup__destroy(skel);
192}
~/ Read-only file preview.