[PATCH RFC bpf-next 5/5] selftests/bpf: Add functional tests for skb local storage
From: Jakub Sitnicki <jakub@cloudflare.com>
Date: 2026-02-26 21:13:18
Also in:
bpf
Subsystem:
bpf [general] (safe dynamic programs and tools), bpf [selftests] (test runners & infrastructure), kernel selftest framework, the rest · Maintainers:
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi, Shuah Khan, Linus Torvalds
Exercise skb local storage across program types and hook boundaries. 1. skb_storage_ops: Unit test for the kfunc API - create, read, delete, and re-create with an initial value. Runs as a socket filter via BPF_PROG_TEST_RUN. 2. tc_clone_redirect: Store from TC egress on lo, bpf_clone_redirect to a dummy device, read from TC egress on the dummy - verifies storage is not carried over to the clone (BPF_F_CLONE is not supported). 3. tc_ingress_to_cgrp_ingress: Store from TC ingress, read from cgroup/skb ingress - verifies storage survives across hooks on the same skb. 4. tc_ingress_to_sk_filter: Store from TC ingress, read from a socket filter - verifies storage is accessible from SO_ATTACH_BPF. 5. cgrp_egress_to_tp_kfree_skb: Store from cgroup/skb egress, read from tp_btf/kfree_skb after a blackhole qdisc drops the packet - verifies storage survives until skb free. 6. tc_ingress_to_lsm_inet_conn_estab: Store from TC ingress, read from LSM inet_conn_established hook - verifies storage is accessible from LSM programs. 7. tc_ingress_to_skops_passive_estab: Store from TC ingress, read from sock_ops BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB via bpf_sock_ops_kern.skb - verifies the sock_ops access path. Signed-off-by: Jakub Sitnicki <jakub@cloudflare.com> --- .../testing/selftests/bpf/prog_tests/skb_storage.c | 405 +++++++++++++++++++++ tools/testing/selftests/bpf/progs/skb_storage.c | 312 ++++++++++++++++ 2 files changed, 717 insertions(+)
diff --git a/tools/testing/selftests/bpf/prog_tests/skb_storage.c b/tools/testing/selftests/bpf/prog_tests/skb_storage.c
new file mode 100644
index 000000000000..32b5669de9f5
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/skb_storage.c@@ -0,0 +1,405 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2026 Cloudflare, Inc. */ + +#include <test_progs.h> +#include <network_helpers.h> +#include "skb_storage.skel.h" + +#define CGROUP_PATH "/skb_storage" +#define DUMMY_DEV "dum0" +#define IFINDEX_LO 1 +#define MAGIC_VALUE 0xdeadbeef +#define TEST_PORT 4242 + +static int send_udp_packet(__be16 port) +{ + struct sockaddr_in addr = { + .sin_family = AF_INET, + .sin_port = port, + .sin_addr.s_addr = htonl(INADDR_LOOPBACK), + }; + int fd, ret = -1; + + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) + return -1; + + ret = sendto(fd, "x", 1, 0, (struct sockaddr *)&addr, sizeof(addr)); + if (ret < 0) + goto out; + + ret = 0; +out: + close(fd); + return ret; +} + +static int recv_udp_packet(int server_fd) +{ + char buf[64]; + struct sockaddr_in addr; + socklen_t len = sizeof(addr); + + return recvfrom(server_fd, buf, sizeof(buf), 0, + (struct sockaddr *)&addr, &len); +} + +static void test_skb_storage_ops(struct skb_storage *skel) +{ + LIBBPF_OPTS(bpf_test_run_opts, topts, + .data_in = &pkt_v4, + .data_size_in = sizeof(pkt_v4), + ); + int err; + + err = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.skb_storage_ops_test), + &topts); + ASSERT_OK(err, "test_run"); + ASSERT_EQ(skel->bss->test_result, 0, "test_result"); +} + +static void test_tc_clone_redirect(struct skb_storage *skel) +{ + const __be16 test_port = htons(TEST_PORT); + struct bpf_link *dummy_link = NULL; + struct bpf_link *lo_link = NULL; + struct netns_obj *netns; + int dummy_ifindex; + + netns = netns_new(__func__, true); + if (!ASSERT_OK_PTR(netns, "netns_new")) + goto cleanup; + + SYS(cleanup, "ip link add " DUMMY_DEV " type dummy"); + SYS(cleanup, "ip link set " DUMMY_DEV " up"); + + dummy_ifindex = if_nametoindex(DUMMY_DEV); + if (!ASSERT_GT(dummy_ifindex, 0, "dummy_ifindex")) + goto cleanup; + + skel->bss->target_port = test_port; + skel->bss->redirect_ifindex = dummy_ifindex; + + lo_link = bpf_program__attach_tcx(skel->progs.tc_clone_redirect_store, + IFINDEX_LO, NULL); + if (!ASSERT_OK_PTR(lo_link, "attach_ingress")) + goto cleanup; + + dummy_link = bpf_program__attach_tcx(skel->progs.tc_clone_redirect_load, + dummy_ifindex, NULL); + if (!ASSERT_OK_PTR(dummy_link, "attach_egress")) + goto cleanup; + + skel->bss->store_seen = 0; + skel->bss->redir_seen = 0; + skel->bss->load_seen = 0; + skel->bss->load_value = 0; + + if (!ASSERT_OK(send_udp_packet(test_port), "send_udp")) + goto cleanup; + + ASSERT_EQ(skel->bss->store_seen, 1, "store_seen"); + ASSERT_EQ(skel->bss->redir_seen, 1, "redir_seen"); + ASSERT_EQ(skel->bss->load_seen, 0, "load_seen"); + ASSERT_EQ(skel->bss->load_value, 0, "load_value"); + +cleanup: + bpf_link__destroy(dummy_link); + bpf_link__destroy(lo_link); + netns_free(netns); +} + +static void test_tc_ingress_to_cgrp_ingress(struct skb_storage *skel) +{ + struct bpf_link *tc_link = NULL; + struct bpf_link *cg_link = NULL; + int cgroup_fd = -1; + int server_fd = -1; + __be16 port; + + cgroup_fd = test__join_cgroup(CGROUP_PATH); + if (!ASSERT_GE(cgroup_fd, 0, "join_cgroup")) + return; + + server_fd = start_server(AF_INET, SOCK_DGRAM, "127.0.0.1", 0, 0); + if (!ASSERT_GE(server_fd, 0, "start_server")) + goto cleanup; + + port = get_socket_local_port(server_fd); + if (!ASSERT_GE(port, 0, "get_port")) + goto cleanup; + + skel->bss->target_port = port; + + tc_link = bpf_program__attach_tcx(skel->progs.tc_ingress_store, + IFINDEX_LO, NULL); + if (!ASSERT_OK_PTR(tc_link, "attach_tc")) + goto cleanup; + + cg_link = bpf_program__attach_cgroup(skel->progs.cgrp_ingress_load, + cgroup_fd); + if (!ASSERT_OK_PTR(cg_link, "attach_cgroup")) + goto cleanup; + + skel->bss->store_seen = 0; + skel->bss->load_seen = 0; + skel->bss->load_value = 0; + + if (!ASSERT_OK(send_udp_packet(port), "send_udp")) + goto cleanup; + + if (!ASSERT_GE(recv_udp_packet(server_fd), 0, "recv_udp")) + goto cleanup; + + ASSERT_EQ(skel->bss->store_seen, 1, "store_seen"); + ASSERT_EQ(skel->bss->load_seen, 1, "load_seen"); + ASSERT_EQ(skel->bss->load_value, MAGIC_VALUE, "load_value"); + +cleanup: + bpf_link__destroy(cg_link); + bpf_link__destroy(tc_link); + if (server_fd >= 0) + close(server_fd); + if (cgroup_fd >= 0) + close(cgroup_fd); +} + +static void test_tc_ingress_to_sk_filter(struct skb_storage *skel) +{ + struct bpf_link *tc_link = NULL; + int server_fd = -1; + int filter_fd = -1; + __be16 port; + int ret; + + server_fd = start_server(AF_INET, SOCK_DGRAM, "127.0.0.1", 0, 0); + if (!ASSERT_GE(server_fd, 0, "start_server")) + goto cleanup; + + port = get_socket_local_port(server_fd); + if (!ASSERT_GE(port, 0, "get_port")) + goto cleanup; + + skel->bss->target_port = port; + + tc_link = bpf_program__attach_tcx(skel->progs.tc_ingress_store, + IFINDEX_LO, NULL); + if (!ASSERT_OK_PTR(tc_link, "attach_tcx")) + goto cleanup; + + filter_fd = bpf_program__fd(skel->progs.sk_filter_load); + if (!ASSERT_GE(filter_fd, 0, "get_prog_fd")) + goto cleanup; + + ret = setsockopt(server_fd, SOL_SOCKET, SO_ATTACH_BPF, + &filter_fd, sizeof(filter_fd)); + if (!ASSERT_OK(ret, "attach_socket_filter")) + goto cleanup; + + skel->bss->store_seen = 0; + skel->bss->load_seen = 0; + skel->bss->load_value = 0; + + if (!ASSERT_OK(send_udp_packet(port), "send_udp")) + goto cleanup; + + if (!ASSERT_GE(recv_udp_packet(server_fd), 0, "recv_udp")) + goto cleanup; + + ASSERT_EQ(skel->bss->store_seen, 1, "store_seen"); + ASSERT_EQ(skel->bss->load_seen, 1, "load_seen"); + ASSERT_EQ(skel->bss->load_value, MAGIC_VALUE, "load_value"); + +cleanup: + bpf_link__destroy(tc_link); + if (server_fd >= 0) + close(server_fd); +} + +static void test_cgrp_egress_to_tp_kfree_skb(struct skb_storage *skel) +{ + struct bpf_link *cg_link = NULL; + struct bpf_link *tp_link = NULL; + struct netns_obj *netns = NULL; + int cgroup_fd = -1; + __be16 port; + + cgroup_fd = test__join_cgroup(CGROUP_PATH); + if (!ASSERT_GE(cgroup_fd, 0, "join_cgroup")) + return; + + netns = netns_new(__func__, true); + if (!ASSERT_OK_PTR(netns, "netns_new")) + goto cleanup; + + port = htons(TEST_PORT); + skel->bss->target_port = port; + + cg_link = bpf_program__attach_cgroup(skel->progs.cgrp_egress_store, + cgroup_fd); + if (!ASSERT_OK_PTR(cg_link, "attach_cgroup")) + goto cleanup; + + tp_link = bpf_program__attach_trace(skel->progs.tp_kfree_skb_load); + if (!ASSERT_OK_PTR(tp_link, "attach_tp")) + goto cleanup; + + skel->bss->store_seen = 0; + skel->bss->load_seen = 0; + skel->bss->load_value = 0; + + SYS(cleanup, "tc qdisc add dev lo root handle 1:0 blackhole"); + + if (!ASSERT_OK(send_udp_packet(port), "send_udp")) + goto cleanup; + + ASSERT_EQ(skel->bss->store_seen, 1, "store_seen"); + ASSERT_EQ(skel->bss->load_seen, 1, "load_seen"); + ASSERT_EQ(skel->bss->load_value, MAGIC_VALUE, "load_value"); + +cleanup: + bpf_link__destroy(tp_link); + bpf_link__destroy(cg_link); + netns_free(netns); + if (cgroup_fd >= 0) + close(cgroup_fd); +} + +static void test_tc_ingress_to_lsm_inet_conn_estab(struct skb_storage *skel) +{ + struct bpf_link *lsm_link = NULL; + struct bpf_link *tc_link = NULL; + int server_fd = -1; + int client_fd = -1; + int conn_fd = -1; + __be16 port; + + server_fd = start_server(AF_INET, SOCK_STREAM, "127.0.0.1", 0, 0); + if (!ASSERT_GE(server_fd, 0, "start_server")) + goto cleanup; + + port = get_socket_local_port(server_fd); + if (!ASSERT_GE(port, 0, "get_port")) + goto cleanup; + + skel->bss->target_port = port; + + tc_link = bpf_program__attach_tcx(skel->progs.tc_ingress_store, IFINDEX_LO, NULL); + if (!ASSERT_OK_PTR(tc_link, "attach_tcx")) + goto cleanup; + + lsm_link = bpf_program__attach_lsm(skel->progs.lsm_inet_conn_estab_load); + if (!ASSERT_OK_PTR(lsm_link, "attach_lsm")) + goto cleanup; + + skel->bss->store_seen = 0; + skel->bss->load_seen = 0; + skel->bss->load_value = 0; + + client_fd = connect_to_fd(server_fd, 0); + if (!ASSERT_GE(client_fd, 0, "connect")) + goto cleanup; + + conn_fd = accept(server_fd, NULL, NULL); + if (!ASSERT_GE(conn_fd, 0, "accept")) + goto cleanup; + close(conn_fd); + + ASSERT_GT(skel->bss->store_seen, 0, "store_seen"); + ASSERT_GT(skel->bss->load_seen, 0, "load_seen"); + ASSERT_EQ(skel->bss->load_value, MAGIC_VALUE, "load_value"); + +cleanup: + bpf_link__destroy(lsm_link); + bpf_link__destroy(tc_link); + if (client_fd >= 0) + close(client_fd); + if (server_fd >= 0) + close(server_fd); +} + +static void test_tc_ingress_to_skops_passive_estab(struct skb_storage *skel) +{ + struct bpf_link *cg_link = NULL; + struct bpf_link *tc_link = NULL; + int cgroup_fd = -1; + int server_fd = -1; + int client_fd = -1; + int conn_fd = -1; + __be16 port; + + cgroup_fd = test__join_cgroup(CGROUP_PATH); + if (!ASSERT_GE(cgroup_fd, 0, "join_cgroup")) + return; + + server_fd = start_server(AF_INET, SOCK_STREAM, "127.0.0.1", 0, 0); + if (!ASSERT_GE(server_fd, 0, "start_server")) + goto cleanup; + + port = get_socket_local_port(server_fd); + if (!ASSERT_GE(port, 0, "get_port")) + goto cleanup; + + skel->bss->target_port = port; + + tc_link = bpf_program__attach_tcx(skel->progs.tc_ingress_store, IFINDEX_LO, NULL); + if (!ASSERT_OK_PTR(tc_link, "attach_tcx")) + goto cleanup; + + cg_link = bpf_program__attach_cgroup(skel->progs.skops_passive_estab_load, cgroup_fd); + if (!ASSERT_OK_PTR(cg_link, "attach_cgroup")) + goto cleanup; + + skel->bss->store_seen = 0; + skel->bss->load_seen = 0; + skel->bss->load_value = 0; + + client_fd = connect_to_fd(server_fd, 0); + if (!ASSERT_GE(client_fd, 0, "connect")) + goto cleanup; + + conn_fd = accept(server_fd, NULL, NULL); + if (!ASSERT_GE(conn_fd, 0, "accept")) + goto cleanup; + close(conn_fd); + + ASSERT_GT(skel->bss->store_seen, 0, "store_seen"); + ASSERT_GT(skel->bss->load_seen, 0, "load_seen"); + ASSERT_EQ(skel->bss->load_value, MAGIC_VALUE, "load_value"); + +cleanup: + bpf_link__destroy(cg_link); + bpf_link__destroy(tc_link); + if (client_fd >= 0) + close(client_fd); + if (server_fd >= 0) + close(server_fd); + if (cgroup_fd >= 0) + close(cgroup_fd); +} + +void test_skb_storage(void) +{ + struct skb_storage *skel; + + skel = skb_storage__open_and_load(); + if (!ASSERT_OK_PTR(skel, "skel_open_and_load")) + return; + + if (test__start_subtest("skb_storage_ops")) + test_skb_storage_ops(skel); + if (test__start_subtest("tc_clone_redirect")) + test_tc_clone_redirect(skel); + if (test__start_subtest("tc_ingress_to_cgrp_ingress")) + test_tc_ingress_to_cgrp_ingress(skel); + if (test__start_subtest("tc_ingress_to_sk_filter")) + test_tc_ingress_to_sk_filter(skel); + if (test__start_subtest("cgrp_egress_to_tp_kfree_skb")) + test_cgrp_egress_to_tp_kfree_skb(skel); + if (test__start_subtest("tc_ingress_to_lsm_inet_conn_estab")) + test_tc_ingress_to_lsm_inet_conn_estab(skel); + if (test__start_subtest("tc_ingress_to_skops_passive_estab")) + test_tc_ingress_to_skops_passive_estab(skel); + + skb_storage__destroy(skel); +}
diff --git a/tools/testing/selftests/bpf/progs/skb_storage.c b/tools/testing/selftests/bpf/progs/skb_storage.c
new file mode 100644
index 000000000000..57628a6d26ae
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/skb_storage.c@@ -0,0 +1,312 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2026 Cloudflare, Inc. */ + +#include "vmlinux.h" +#include <bpf/bpf_helpers.h> +#include <bpf/bpf_endian.h> +#include <bpf/bpf_tracing.h> +#include <errno.h> + +#define fallthrough __attribute__((__fallthrough__)) + +#define ETH_P_IP 0x0800 +#define ETH_HLEN 14 +#define MAGIC_VALUE 0xdeadbeef + +char _license[] SEC("license") = "GPL"; + +struct { + __uint(type, BPF_MAP_TYPE_SKB_STORAGE); + __uint(map_flags, BPF_F_NO_PREALLOC); + __type(key, int); + __type(value, __u32); +} skb_storage SEC(".maps"); + +volatile __be16 target_port; +volatile __u32 redirect_ifindex; + +volatile int test_result; +volatile int store_seen; +volatile int redir_seen; +volatile int load_seen; +volatile int load_value; + +enum { + CG_DROP = 0, + CG_PASS, +}; + +enum layer { L2, L3, L4 }; + +static bool is_test_packet(struct __sk_buff *skb, enum layer layer) +{ + __u32 off = 0; + __be16 src; + __be16 dst; + __u8 ihl; + + if (skb->protocol != bpf_htons(ETH_P_IP)) + return false; + + switch (layer) { + case L2: + off += ETH_HLEN; + fallthrough; + case L3: + if (bpf_skb_load_bytes(skb, off, &ihl, 1)) + return false; + off += (ihl & 0xf) * 4; + fallthrough; + case L4: + if (bpf_skb_load_bytes(skb, off, &src, 2)) + return false; + if (bpf_skb_load_bytes(skb, off + 2, &dst, 2)) + return false; + } + + return src == target_port || dst == target_port; +} + +SEC("socket") +int skb_storage_ops_test(struct __sk_buff *ctx) +{ + struct bpf_map *map = (typeof(map))&skb_storage; + struct sk_buff *skb = bpf_cast_to_kern_ctx(ctx); + __u32 init_value = MAGIC_VALUE; + __u32 *value; + int ret; + + /* Get non-existent storage */ + test_result = 1; + value = bpf_skb_storage_get(map, skb, NULL, 0, 0); + if (value) + goto out; + + /* Create storage and write to it */ + test_result = 2; + value = bpf_skb_storage_get(map, skb, NULL, 0, + BPF_LOCAL_STORAGE_GET_F_CREATE); + if (!value) + goto out; + if (*value) + goto out; + *value = MAGIC_VALUE; + + /* Get existing storage and read from it */ + test_result = 3; + value = bpf_skb_storage_get(map, skb, NULL, 0, 0); + if (!value) + goto out; + if (*value != MAGIC_VALUE) + goto out; + + /* Delete existing storage */ + test_result = 4; + ret = bpf_skb_storage_delete(map, skb); + if (ret) + goto out; + + /* Delete non-existent storage */ + test_result = 5; + ret = bpf_skb_storage_delete(map, skb); + if (ret != -ENOENT) + goto out; + + /* Re-create storage with initial value */ + test_result = 6; + value = bpf_skb_storage_get(map, skb, &init_value, sizeof(init_value), + BPF_LOCAL_STORAGE_GET_F_CREATE); + if (!value) + goto out; + if (*value != MAGIC_VALUE) + goto out; + + test_result = 0; +out: + return ctx->len; +} + +SEC("tcx/egress") +int tc_clone_redirect_store(struct __sk_buff *ctx) +{ + struct bpf_map *map = (typeof(map))&skb_storage; + struct sk_buff *skb = bpf_cast_to_kern_ctx(ctx); + __u32 *value; + + if (!redirect_ifindex) + goto out; + if (!is_test_packet(ctx, L2)) + goto out; + + value = bpf_skb_storage_get(map, skb, NULL, 0, + BPF_LOCAL_STORAGE_GET_F_CREATE); + if (!value) + goto out; + + *value = MAGIC_VALUE; + store_seen++; + + bpf_clone_redirect(ctx, redirect_ifindex, 0); +out: + return TCX_DROP; +} + +SEC("tcx/egress") +int tc_clone_redirect_load(struct __sk_buff *ctx) +{ + struct bpf_map *map = (typeof(map))&skb_storage; + struct sk_buff *skb = bpf_cast_to_kern_ctx(ctx); + __u32 *value; + + if (!is_test_packet(ctx, L2)) + goto out; + + redir_seen++; + + value = bpf_skb_storage_get(map, skb, NULL, 0, 0); + if (!value) + goto out; + + load_value = *value; + load_seen++; +out: + return TCX_DROP; +} + +SEC("tcx/ingress") +int tc_ingress_store(struct __sk_buff *ctx) +{ + struct bpf_map *map = (typeof(map))&skb_storage; + struct sk_buff *skb = bpf_cast_to_kern_ctx(ctx); + __u32 *value; + + if (!is_test_packet(ctx, L2)) + goto out; + + value = bpf_skb_storage_get(map, skb, NULL, 0, + BPF_LOCAL_STORAGE_GET_F_CREATE); + if (!value) + goto out; + + *value = MAGIC_VALUE; + store_seen++; +out: + return TCX_PASS; +} + +SEC("cgroup_skb/ingress") +int cgrp_ingress_load(struct __sk_buff *ctx) +{ + struct bpf_map *map = (typeof(map))&skb_storage; + struct sk_buff *skb = bpf_cast_to_kern_ctx(ctx); + __u32 *value; + + if (!is_test_packet(ctx, L3)) + goto out; + + value = bpf_skb_storage_get(map, skb, NULL, 0, 0); + if (!value) + goto out; + + load_value = *value; + load_seen++; +out: + return CG_PASS; +} + +SEC("cgroup_skb/egress") +int cgrp_egress_store(struct __sk_buff *ctx) +{ + struct bpf_map *map = (typeof(map))&skb_storage; + struct sk_buff *skb = bpf_cast_to_kern_ctx(ctx); + __u32 *value; + + if (!is_test_packet(ctx, L3)) + goto out; + + value = bpf_skb_storage_get(map, skb, NULL, 0, + BPF_LOCAL_STORAGE_GET_F_CREATE); + if (!value) + goto out; + + *value = MAGIC_VALUE; + store_seen++; +out: + return CG_PASS; +} + +SEC("socket") +int sk_filter_load(struct __sk_buff *ctx) +{ + struct bpf_map *map = (typeof(map))&skb_storage; + struct sk_buff *skb = bpf_cast_to_kern_ctx(ctx); + __u32 *value; + + if (!is_test_packet(ctx, L4)) + goto out; + + value = bpf_skb_storage_get(map, skb, NULL, 0, 0); + if (!value) + goto out; + + load_value = *value; + load_seen++; +out: + return skb->len; +} + +SEC("tp_btf/kfree_skb") +int BPF_PROG(tp_kfree_skb_load, struct sk_buff *skb, void *location, + enum skb_drop_reason reason) +{ + struct bpf_map *map = (typeof(map))&skb_storage; + __u32 *value; + + value = bpf_skb_storage_get(map, skb, NULL, 0, 0); + if (!value) + goto out; + + load_value = *value; + load_seen++; +out: + return 0; +} + +SEC("lsm/inet_conn_established") +int BPF_PROG(lsm_inet_conn_estab_load, struct sock *sk, struct sk_buff *skb) +{ + struct bpf_map *map = (typeof(map))&skb_storage; + __u32 *value; + + value = bpf_skb_storage_get(map, skb, NULL, 0, 0); + if (!value) + goto out; + + load_value = *value; + load_seen++; +out: + return 0; +} + +SEC("sockops") +int skops_passive_estab_load(struct bpf_sock_ops *ctx) +{ + struct bpf_sock_ops_kern *kctx = bpf_cast_to_kern_ctx(ctx); + struct bpf_map *map = (typeof(map))&skb_storage; + struct sk_buff *skb = kctx->skb; + __u32 *value; + + if (ctx->op != BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB) + goto out; + if (!skb) + goto out; + + value = bpf_skb_storage_get(map, skb, NULL, 0, 0); + if (!value) + goto out; + + load_value = *value; + load_seen++; +out: + return CG_PASS; +}
--
2.43.0