1// SPDX-License-Identifier: GPL-2.0
2/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates.*/
3
4#include <test_progs.h>
5#include <network_helpers.h>
6#include "test_ldsx_insn.skel.h"
7
8static void test_map_val_and_probed_memory(void)
9{
10	struct test_ldsx_insn *skel;
11	int err;
12
13	skel = test_ldsx_insn__open();
14	if (!ASSERT_OK_PTR(skel, "test_ldsx_insn__open"))
15		return;
16
17	if (skel->rodata->skip) {
18		test__skip();
19		goto out;
20	}
21
22	bpf_program__set_autoload(skel->progs.rdonly_map_prog, true);
23	bpf_program__set_autoload(skel->progs.map_val_prog, true);
24	bpf_program__set_autoload(skel->progs.test_ptr_struct_arg, true);
25
26	err = test_ldsx_insn__load(skel);
27	if (!ASSERT_OK(err, "test_ldsx_insn__load"))
28		goto out;
29
30	err = test_ldsx_insn__attach(skel);
31	if (!ASSERT_OK(err, "test_ldsx_insn__attach"))
32		goto out;
33
34	ASSERT_OK(trigger_module_test_read(256), "trigger_read");
35
36	ASSERT_EQ(skel->bss->done1, 1, "done1");
37	ASSERT_EQ(skel->bss->ret1, 1, "ret1");
38	ASSERT_EQ(skel->bss->done2, 1, "done2");
39	ASSERT_EQ(skel->bss->ret2, 1, "ret2");
40	ASSERT_EQ(skel->bss->int_member, -1, "int_member");
41
42out:
43	test_ldsx_insn__destroy(skel);
44}
45
46static void test_ctx_member_sign_ext(void)
47{
48	struct test_ldsx_insn *skel;
49	int err, fd, cgroup_fd;
50	char buf[16] = {0};
51	socklen_t optlen;
52
53	cgroup_fd = test__join_cgroup("/ldsx_test");
54	if (!ASSERT_GE(cgroup_fd, 0, "join_cgroup /ldsx_test"))
55		return;
56
57	skel = test_ldsx_insn__open();
58	if (!ASSERT_OK_PTR(skel, "test_ldsx_insn__open"))
59		goto close_cgroup_fd;
60
61	if (skel->rodata->skip) {
62		test__skip();
63		goto destroy_skel;
64	}
65
66	bpf_program__set_autoload(skel->progs._getsockopt, true);
67
68	err = test_ldsx_insn__load(skel);
69	if (!ASSERT_OK(err, "test_ldsx_insn__load"))
70		goto destroy_skel;
71
72	skel->links._getsockopt =
73		bpf_program__attach_cgroup(skel->progs._getsockopt, cgroup_fd);
74	if (!ASSERT_OK_PTR(skel->links._getsockopt, "getsockopt_link"))
75		goto destroy_skel;
76
77	fd = socket(AF_INET, SOCK_STREAM, 0);
78	if (!ASSERT_GE(fd, 0, "socket"))
79		goto destroy_skel;
80
81	optlen = sizeof(buf);
82	(void)getsockopt(fd, SOL_IP, IP_TTL, buf, &optlen);
83
84	ASSERT_EQ(skel->bss->set_optlen, -1, "optlen");
85	ASSERT_EQ(skel->bss->set_retval, -1, "retval");
86
87	close(fd);
88destroy_skel:
89	test_ldsx_insn__destroy(skel);
90close_cgroup_fd:
91	close(cgroup_fd);
92}
93
94static void test_ctx_member_narrow_sign_ext(void)
95{
96	struct test_ldsx_insn *skel;
97	struct __sk_buff skb = {};
98	LIBBPF_OPTS(bpf_test_run_opts, topts,
99		    .data_in = &pkt_v4,
100		    .data_size_in = sizeof(pkt_v4),
101		    .ctx_in = &skb,
102		    .ctx_size_in = sizeof(skb),
103	);
104	int err, prog_fd;
105
106	skel = test_ldsx_insn__open();
107	if (!ASSERT_OK_PTR(skel, "test_ldsx_insn__open"))
108		return;
109
110	if (skel->rodata->skip) {
111		test__skip();
112		goto out;
113	}
114
115	bpf_program__set_autoload(skel->progs._tc, true);
116
117	err = test_ldsx_insn__load(skel);
118	if (!ASSERT_OK(err, "test_ldsx_insn__load"))
119		goto out;
120
121	prog_fd = bpf_program__fd(skel->progs._tc);
122	err = bpf_prog_test_run_opts(prog_fd, &topts);
123	ASSERT_OK(err, "test_run");
124
125	ASSERT_EQ(skel->bss->set_mark, -2, "set_mark");
126
127out:
128	test_ldsx_insn__destroy(skel);
129}
130
131void test_ldsx_insn(void)
132{
133	if (test__start_subtest("map_val and probed_memory"))
134		test_map_val_and_probed_memory();
135	if (test__start_subtest("ctx_member_sign_ext"))
136		test_ctx_member_sign_ext();
137	if (test__start_subtest("ctx_member_narrow_sign_ext"))
138		test_ctx_member_narrow_sign_ext();
139}
140