165ffd797SStanislav Fomichev // SPDX-License-Identifier: GPL-2.0-only
265ffd797SStanislav Fomichev
365ffd797SStanislav Fomichev #include <sys/socket.h>
465ffd797SStanislav Fomichev #include <linux/bpf.h>
565ffd797SStanislav Fomichev #include <bpf/bpf_helpers.h>
665ffd797SStanislav Fomichev
765ffd797SStanislav Fomichev int invocations = 0, in_use = 0;
865ffd797SStanislav Fomichev
9*4fb5f949SStanislav Fomichev struct {
10*4fb5f949SStanislav Fomichev __uint(type, BPF_MAP_TYPE_SK_STORAGE);
11*4fb5f949SStanislav Fomichev __uint(map_flags, BPF_F_NO_PREALLOC);
12*4fb5f949SStanislav Fomichev __type(key, int);
13*4fb5f949SStanislav Fomichev __type(value, int);
14*4fb5f949SStanislav Fomichev } sk_map SEC(".maps");
15*4fb5f949SStanislav Fomichev
1665ffd797SStanislav Fomichev SEC("cgroup/sock_create")
sock(struct bpf_sock * ctx)1765ffd797SStanislav Fomichev int sock(struct bpf_sock *ctx)
1865ffd797SStanislav Fomichev {
19*4fb5f949SStanislav Fomichev int *sk_storage;
2065ffd797SStanislav Fomichev
2165ffd797SStanislav Fomichev if (ctx->type != SOCK_DGRAM)
2265ffd797SStanislav Fomichev return 1;
2365ffd797SStanislav Fomichev
24*4fb5f949SStanislav Fomichev sk_storage = bpf_sk_storage_get(&sk_map, ctx, 0,
25*4fb5f949SStanislav Fomichev BPF_SK_STORAGE_GET_F_CREATE);
26*4fb5f949SStanislav Fomichev if (!sk_storage)
27*4fb5f949SStanislav Fomichev return 0;
28*4fb5f949SStanislav Fomichev *sk_storage = 0xdeadbeef;
29*4fb5f949SStanislav Fomichev
3065ffd797SStanislav Fomichev __sync_fetch_and_add(&invocations, 1);
3165ffd797SStanislav Fomichev
3265ffd797SStanislav Fomichev if (in_use > 0) {
3365ffd797SStanislav Fomichev /* BPF_CGROUP_INET_SOCK_RELEASE is _not_ called
3465ffd797SStanislav Fomichev * when we return an error from the BPF
3565ffd797SStanislav Fomichev * program!
3665ffd797SStanislav Fomichev */
3765ffd797SStanislav Fomichev return 0;
3865ffd797SStanislav Fomichev }
3965ffd797SStanislav Fomichev
4065ffd797SStanislav Fomichev __sync_fetch_and_add(&in_use, 1);
4165ffd797SStanislav Fomichev return 1;
4265ffd797SStanislav Fomichev }
4365ffd797SStanislav Fomichev
4465ffd797SStanislav Fomichev SEC("cgroup/sock_release")
sock_release(struct bpf_sock * ctx)4565ffd797SStanislav Fomichev int sock_release(struct bpf_sock *ctx)
4665ffd797SStanislav Fomichev {
47*4fb5f949SStanislav Fomichev int *sk_storage;
4865ffd797SStanislav Fomichev
4965ffd797SStanislav Fomichev if (ctx->type != SOCK_DGRAM)
5065ffd797SStanislav Fomichev return 1;
5165ffd797SStanislav Fomichev
52*4fb5f949SStanislav Fomichev sk_storage = bpf_sk_storage_get(&sk_map, ctx, 0, 0);
53*4fb5f949SStanislav Fomichev if (!sk_storage || *sk_storage != 0xdeadbeef)
54*4fb5f949SStanislav Fomichev return 0;
55*4fb5f949SStanislav Fomichev
5665ffd797SStanislav Fomichev __sync_fetch_and_add(&invocations, 1);
5765ffd797SStanislav Fomichev __sync_fetch_and_add(&in_use, -1);
5865ffd797SStanislav Fomichev return 1;
5965ffd797SStanislav Fomichev }
60