162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Copyright (c) 2021 Facebook */
362306a36Sopenharmony_ci#include <linux/bpf.h>
462306a36Sopenharmony_ci#include <time.h>
562306a36Sopenharmony_ci#include <errno.h>
662306a36Sopenharmony_ci#include <bpf/bpf_helpers.h>
762306a36Sopenharmony_ci#include "bpf_tcp_helpers.h"
862306a36Sopenharmony_ci
962306a36Sopenharmony_cichar _license[] SEC("license") = "GPL";
1062306a36Sopenharmony_cistruct hmap_elem {
1162306a36Sopenharmony_ci	int pad; /* unused */
1262306a36Sopenharmony_ci	struct bpf_timer timer;
1362306a36Sopenharmony_ci};
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_cistruct inner_map {
1662306a36Sopenharmony_ci	__uint(type, BPF_MAP_TYPE_HASH);
1762306a36Sopenharmony_ci	__uint(max_entries, 1024);
1862306a36Sopenharmony_ci	__type(key, int);
1962306a36Sopenharmony_ci	__type(value, struct hmap_elem);
2062306a36Sopenharmony_ci} inner_htab SEC(".maps");
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#define ARRAY_KEY 1
2362306a36Sopenharmony_ci#define HASH_KEY 1234
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistruct outer_arr {
2662306a36Sopenharmony_ci	__uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
2762306a36Sopenharmony_ci	__uint(max_entries, 2);
2862306a36Sopenharmony_ci	__uint(key_size, sizeof(int));
2962306a36Sopenharmony_ci	__uint(value_size, sizeof(int));
3062306a36Sopenharmony_ci	__array(values, struct inner_map);
3162306a36Sopenharmony_ci} outer_arr SEC(".maps") = {
3262306a36Sopenharmony_ci	.values = { [ARRAY_KEY] = &inner_htab },
3362306a36Sopenharmony_ci};
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci__u64 err;
3662306a36Sopenharmony_ci__u64 ok;
3762306a36Sopenharmony_ci__u64 cnt;
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_cistatic int timer_cb1(void *map, int *key, struct hmap_elem *val);
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cistatic int timer_cb2(void *map, int *key, struct hmap_elem *val)
4262306a36Sopenharmony_ci{
4362306a36Sopenharmony_ci	cnt++;
4462306a36Sopenharmony_ci	bpf_timer_set_callback(&val->timer, timer_cb1);
4562306a36Sopenharmony_ci	if (bpf_timer_start(&val->timer, 1000, 0))
4662306a36Sopenharmony_ci		err |= 1;
4762306a36Sopenharmony_ci	ok |= 1;
4862306a36Sopenharmony_ci	return 0;
4962306a36Sopenharmony_ci}
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci/* callback for inner hash map */
5262306a36Sopenharmony_cistatic int timer_cb1(void *map, int *key, struct hmap_elem *val)
5362306a36Sopenharmony_ci{
5462306a36Sopenharmony_ci	cnt++;
5562306a36Sopenharmony_ci	bpf_timer_set_callback(&val->timer, timer_cb2);
5662306a36Sopenharmony_ci	if (bpf_timer_start(&val->timer, 1000, 0))
5762306a36Sopenharmony_ci		err |= 2;
5862306a36Sopenharmony_ci	/* Do a lookup to make sure 'map' and 'key' pointers are correct */
5962306a36Sopenharmony_ci	bpf_map_lookup_elem(map, key);
6062306a36Sopenharmony_ci	ok |= 2;
6162306a36Sopenharmony_ci	return 0;
6262306a36Sopenharmony_ci}
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ciSEC("fentry/bpf_fentry_test1")
6562306a36Sopenharmony_ciint BPF_PROG(test1, int a)
6662306a36Sopenharmony_ci{
6762306a36Sopenharmony_ci	struct hmap_elem init = {};
6862306a36Sopenharmony_ci	struct bpf_map *inner_map;
6962306a36Sopenharmony_ci	struct hmap_elem *val;
7062306a36Sopenharmony_ci	int array_key = ARRAY_KEY;
7162306a36Sopenharmony_ci	int hash_key = HASH_KEY;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	inner_map = bpf_map_lookup_elem(&outer_arr, &array_key);
7462306a36Sopenharmony_ci	if (!inner_map)
7562306a36Sopenharmony_ci		return 0;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	bpf_map_update_elem(inner_map, &hash_key, &init, 0);
7862306a36Sopenharmony_ci	val = bpf_map_lookup_elem(inner_map, &hash_key);
7962306a36Sopenharmony_ci	if (!val)
8062306a36Sopenharmony_ci		return 0;
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	bpf_timer_init(&val->timer, inner_map, CLOCK_MONOTONIC);
8362306a36Sopenharmony_ci	if (bpf_timer_set_callback(&val->timer, timer_cb1))
8462306a36Sopenharmony_ci		err |= 4;
8562306a36Sopenharmony_ci	if (bpf_timer_start(&val->timer, 0, 0))
8662306a36Sopenharmony_ci		err |= 8;
8762306a36Sopenharmony_ci	return 0;
8862306a36Sopenharmony_ci}
89