Add a selftest for the newly added bpf_skb_rx_checksum() kfunc.
The test consists of a TC BPF program that calls the kfunc and
records which checksum type each packet has in a per-type counter
map, and a userspace test runner that exercises two scenarios:

- csum_none: runs with bpf_prog_test_run_opts (no special flags),
  verifies all packets are reported as CHECKSUM_NONE.
- csum_complete: runs with BPF_F_TEST_SKB_CHECKSUM_COMPLETE flag,
  verifies all packets are reported as CHECKSUM_COMPLETE.

Signed-off-by: Lorenzo Bianconi <[email protected]>
---
 tools/testing/selftests/bpf/bpf_kfuncs.h           |  8 ++++
 .../selftests/bpf/prog_tests/skb_rx_checksum.c     | 50 ++++++++++++++++++++++
 .../testing/selftests/bpf/progs/skb_rx_checksum.c  | 33 ++++++++++++++
 tools/testing/selftests/bpf/skb_rx_checksum.h      |  8 ++++
 4 files changed, 99 insertions(+)

diff --git a/tools/testing/selftests/bpf/bpf_kfuncs.h 
b/tools/testing/selftests/bpf/bpf_kfuncs.h
index ae71e9b69051..d03572e26df2 100644
--- a/tools/testing/selftests/bpf/bpf_kfuncs.h
+++ b/tools/testing/selftests/bpf/bpf_kfuncs.h
@@ -64,6 +64,14 @@ struct bpf_tcp_req_attrs;
 extern int bpf_sk_assign_tcp_reqsk(struct __sk_buff *skb, struct sock *sk,
                                   struct bpf_tcp_req_attrs *attrs, int 
attrs__sz) __ksym;
 
+/* Description
+ *  Read skb RX checksum info (ip_summed and csum_meta).
+ * Returns
+ *  0 on success
+ */
+extern int bpf_skb_rx_checksum(struct __sk_buff *skb, __u32 *ip_summed,
+                              __u32 *csum_meta) __ksym;
+
 void *bpf_cast_to_kern_ctx(void *) __ksym;
 
 extern void *bpf_rdonly_cast(const void *obj, __u32 btf_id) __ksym __weak;
diff --git a/tools/testing/selftests/bpf/prog_tests/skb_rx_checksum.c 
b/tools/testing/selftests/bpf/prog_tests/skb_rx_checksum.c
new file mode 100644
index 000000000000..d71ab7c70b68
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/skb_rx_checksum.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <test_progs.h>
+#include <network_helpers.h>
+#include "skb_rx_checksum.skel.h"
+#include "skb_rx_checksum.h"
+
+#define TX_PACKETS 3
+
+static int run_test(__u32 flags, enum skb_csum expected_csum)
+{
+       LIBBPF_OPTS(bpf_test_run_opts, topts,
+               .data_in = &pkt_v4,
+               .data_size_in = sizeof(pkt_v4),
+               .repeat = TX_PACKETS,
+               .flags = flags,
+       );
+       int prog_fd, err, key = expected_csum;
+       struct skb_rx_checksum *skel;
+       __u64 cnt;
+
+       skel = skb_rx_checksum__open_and_load();
+       if (!ASSERT_OK_PTR(skel, "skel_open_and_load"))
+               return -1;
+
+       prog_fd = bpf_program__fd(skel->progs.tc_rx_csum);
+       err = bpf_prog_test_run_opts(prog_fd, &topts);
+       if (!ASSERT_OK(err, "test_run"))
+               goto cleanup;
+
+       if (!ASSERT_EQ(topts.retval, 0, "retval"))
+               goto cleanup;
+
+       err = bpf_map_lookup_elem(bpf_map__fd(skel->maps.csum_cnt), &key, &cnt);
+       if (!ASSERT_OK(err, "map_lookup"))
+               goto cleanup;
+
+       ASSERT_EQ(cnt, TX_PACKETS, "csum_cnt");
+cleanup:
+       skb_rx_checksum__destroy(skel);
+       return 0;
+}
+
+void test_skb_rx_checksum(void)
+{
+       if (test__start_subtest("csum_none"))
+               run_test(0, SKB_CSUM_NONE);
+
+       if (test__start_subtest("csum_complete"))
+               run_test(BPF_F_TEST_SKB_CHECKSUM_COMPLETE, SKB_CSUM_COMPLETE);
+}
diff --git a/tools/testing/selftests/bpf/progs/skb_rx_checksum.c 
b/tools/testing/selftests/bpf/progs/skb_rx_checksum.c
new file mode 100644
index 000000000000..dc4e192905d5
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/skb_rx_checksum.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/bpf.h>
+#include <linux/pkt_cls.h>
+#include <bpf/bpf_helpers.h>
+#include "bpf_kfuncs.h"
+#include "skb_rx_checksum.h"
+
+struct {
+       __uint(type, BPF_MAP_TYPE_ARRAY);
+       __uint(max_entries, SKB_CSUM_PARTIAL);
+       __type(key, __u32);
+       __type(value, __u64);
+} csum_cnt SEC(".maps");
+
+SEC("tc")
+int tc_rx_csum(struct __sk_buff *skb)
+{
+       enum skb_csum ip_summed;
+       __u32 csum_meta;
+       __u64 *cnt;
+
+       bpf_skb_rx_checksum(skb, &ip_summed, &csum_meta);
+       if (ip_summed < SKB_CSUM_PARTIAL) {
+               cnt = bpf_map_lookup_elem(&csum_cnt, &ip_summed);
+               if (cnt)
+                       __sync_fetch_and_add(cnt, 1);
+       }
+
+       return TC_ACT_OK;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/skb_rx_checksum.h 
b/tools/testing/selftests/bpf/skb_rx_checksum.h
new file mode 100644
index 000000000000..60aad3561843
--- /dev/null
+++ b/tools/testing/selftests/bpf/skb_rx_checksum.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+enum skb_csum {
+       SKB_CSUM_NONE           = 0,
+       SKB_CSUM_UNNECESSARY    = 1,
+       SKB_CSUM_COMPLETE       = 2,
+       SKB_CSUM_PARTIAL        = 3,
+};

-- 
2.55.0


Reply via email to