139444Smsmith// SPDX-License-Identifier: GPL-2.0
239444Smsmith/* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */
339444Smsmith
439444Smsmith#include "vmlinux.h"
539444Smsmith#include <bpf/bpf_helpers.h>
639444Smsmith#include "bpf_misc.h"
739444Smsmith
839444Smsmith#define HASHMAP_SZ 4194304
939444Smsmith
1039444Smsmithstruct {
1139444Smsmith	__uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
1239444Smsmith	__uint(max_entries, 1000);
1339444Smsmith	__type(key, int);
1439444Smsmith	__type(value, int);
1539444Smsmith	__array(values, struct {
1639444Smsmith		__uint(type, BPF_MAP_TYPE_TASK_STORAGE);
1739444Smsmith		__uint(map_flags, BPF_F_NO_PREALLOC);
1839444Smsmith		__type(key, int);
1939444Smsmith		__type(value, int);
2039444Smsmith	});
2139444Smsmith} array_of_local_storage_maps SEC(".maps");
2239444Smsmith
2339444Smsmithstruct {
2439444Smsmith	__uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
2539444Smsmith	__uint(max_entries, 1000);
2639444Smsmith	__type(key, int);
2740597Smsmith	__type(value, int);
2839444Smsmith	__array(values, struct {
2939444Smsmith		__uint(type, BPF_MAP_TYPE_HASH);
3039444Smsmith		__uint(max_entries, HASHMAP_SZ);
3139444Smsmith		__type(key, int);
3239444Smsmith		__type(value, int);
3339444Smsmith	});
3439444Smsmith} array_of_hash_maps SEC(".maps");
3539444Smsmith
3639444Smsmithlong important_hits;
3739444Smsmithlong hits;
3839444Smsmith
3939444Smsmith/* set from user-space */
4039444Smsmithconst volatile unsigned int use_hashmap;
4139444Smsmithconst volatile unsigned int hashmap_num_keys;
4239444Smsmithconst volatile unsigned int num_maps;
4339444Smsmithconst volatile unsigned int interleave;
4439444Smsmith
4539444Smsmithstruct loop_ctx {
4640553Smsmith	struct task_struct *task;
4740553Smsmith	long loop_hits;
4839444Smsmith	long loop_important_hits;
4939444Smsmith};
5040597Smsmith
5139444Smsmithstatic int do_lookup(unsigned int elem, struct loop_ctx *lctx)
5239444Smsmith{
5339444Smsmith	void *map, *inner_map;
5439444Smsmith	int idx = 0;
5539444Smsmith
5640553Smsmith	if (use_hashmap)
5739444Smsmith		map = &array_of_hash_maps;
5839444Smsmith	else
5939444Smsmith		map = &array_of_local_storage_maps;
6039444Smsmith
6139444Smsmith	inner_map = bpf_map_lookup_elem(map, &elem);
6239444Smsmith	if (!inner_map)
6339444Smsmith		return -1;
6439444Smsmith
6539444Smsmith	if (use_hashmap) {
6639444Smsmith		idx = bpf_get_prandom_u32() % hashmap_num_keys;
6739444Smsmith		bpf_map_lookup_elem(inner_map, &idx);
6839444Smsmith	} else {
6939444Smsmith		bpf_task_storage_get(inner_map, lctx->task, &idx,
7039444Smsmith				     BPF_LOCAL_STORAGE_GET_F_CREATE);
7140597Smsmith	}
7239444Smsmith
7339444Smsmith	lctx->loop_hits++;
7439444Smsmith	if (!elem)
7539444Smsmith		lctx->loop_important_hits++;
7639444Smsmith	return 0;
7739444Smsmith}
7839444Smsmith
7939444Smsmithstatic long loop(u32 index, void *ctx)
8039444Smsmith{
8139444Smsmith	struct loop_ctx *lctx = (struct loop_ctx *)ctx;
8239444Smsmith	unsigned int map_idx = index % num_maps;
8339444Smsmith
8439444Smsmith	do_lookup(map_idx, lctx);
8539444Smsmith	if (interleave && map_idx % 3 == 0)
8639444Smsmith		do_lookup(0, lctx);
8739444Smsmith	return 0;
8839444Smsmith}
8939444Smsmith
9039444SmsmithSEC("fentry/" SYS_PREFIX "sys_getpgid")
9139444Smsmithint get_local(void *ctx)
9239444Smsmith{
9339444Smsmith	struct loop_ctx lctx;
9439444Smsmith
9539444Smsmith	lctx.task = bpf_get_current_task_btf();
9639444Smsmith	lctx.loop_hits = 0;
9739444Smsmith	lctx.loop_important_hits = 0;
9839444Smsmith	bpf_loop(10000, &loop, &lctx, 0);
9939444Smsmith	__sync_add_and_fetch(&hits, lctx.loop_hits);
10039444Smsmith	__sync_add_and_fetch(&important_hits, lctx.loop_important_hits);
10139444Smsmith	return 0;
10239444Smsmith}
10339444Smsmith
10439444Smsmithchar _license[] SEC("license") = "GPL";
10539444Smsmith