18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci
38c2ecf20Sopenharmony_ci#include <sys/socket.h>
48c2ecf20Sopenharmony_ci#include <linux/bpf.h>
58c2ecf20Sopenharmony_ci#include <bpf/bpf_helpers.h>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ciint invocations = 0, in_use = 0;
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_cistruct {
108c2ecf20Sopenharmony_ci	__uint(type, BPF_MAP_TYPE_SK_STORAGE);
118c2ecf20Sopenharmony_ci	__uint(map_flags, BPF_F_NO_PREALLOC);
128c2ecf20Sopenharmony_ci	__type(key, int);
138c2ecf20Sopenharmony_ci	__type(value, int);
148c2ecf20Sopenharmony_ci} sk_map SEC(".maps");
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ciSEC("cgroup/sock_create")
178c2ecf20Sopenharmony_ciint sock(struct bpf_sock *ctx)
188c2ecf20Sopenharmony_ci{
198c2ecf20Sopenharmony_ci	int *sk_storage;
208c2ecf20Sopenharmony_ci	__u32 key;
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci	if (ctx->type != SOCK_DGRAM)
238c2ecf20Sopenharmony_ci		return 1;
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci	sk_storage = bpf_sk_storage_get(&sk_map, ctx, 0,
268c2ecf20Sopenharmony_ci					BPF_SK_STORAGE_GET_F_CREATE);
278c2ecf20Sopenharmony_ci	if (!sk_storage)
288c2ecf20Sopenharmony_ci		return 0;
298c2ecf20Sopenharmony_ci	*sk_storage = 0xdeadbeef;
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci	__sync_fetch_and_add(&invocations, 1);
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	if (in_use > 0) {
348c2ecf20Sopenharmony_ci		/* BPF_CGROUP_INET_SOCK_RELEASE is _not_ called
358c2ecf20Sopenharmony_ci		 * when we return an error from the BPF
368c2ecf20Sopenharmony_ci		 * program!
378c2ecf20Sopenharmony_ci		 */
388c2ecf20Sopenharmony_ci		return 0;
398c2ecf20Sopenharmony_ci	}
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	__sync_fetch_and_add(&in_use, 1);
428c2ecf20Sopenharmony_ci	return 1;
438c2ecf20Sopenharmony_ci}
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ciSEC("cgroup/sock_release")
468c2ecf20Sopenharmony_ciint sock_release(struct bpf_sock *ctx)
478c2ecf20Sopenharmony_ci{
488c2ecf20Sopenharmony_ci	int *sk_storage;
498c2ecf20Sopenharmony_ci	__u32 key;
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	if (ctx->type != SOCK_DGRAM)
528c2ecf20Sopenharmony_ci		return 1;
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	sk_storage = bpf_sk_storage_get(&sk_map, ctx, 0, 0);
558c2ecf20Sopenharmony_ci	if (!sk_storage || *sk_storage != 0xdeadbeef)
568c2ecf20Sopenharmony_ci		return 0;
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	__sync_fetch_and_add(&invocations, 1);
598c2ecf20Sopenharmony_ci	__sync_fetch_and_add(&in_use, -1);
608c2ecf20Sopenharmony_ci	return 1;
618c2ecf20Sopenharmony_ci}
62