1 // SPDX-License-Identifier: GPL-2.0
2 #include <test_progs.h>
3 #include "cgroup_helpers.h"
6 #include "sockopt_sk.skel.h"
9 #define SOL_TCP IPPROTO_TCP
12 #define SOL_CUSTOM 0xdeadbeef
14 static int getsetsockopt(void)
20 char cc[16]; /* TCP_CA_NAME_MAX */
21 struct tcp_zerocopy_receive zc;
26 fd = socket(AF_INET, SOCK_STREAM, 0);
28 log_err("Failed to create socket");
32 /* IP_TOS - BPF bypass */
34 optlen = getpagesize() * 2;
35 big_buf = calloc(1, optlen);
37 log_err("Couldn't allocate two pages");
41 *(int *)big_buf = 0x08;
42 err = setsockopt(fd, SOL_IP, IP_TOS, big_buf, optlen);
44 log_err("Failed to call setsockopt(IP_TOS)");
48 memset(big_buf, 0, optlen);
50 err = getsockopt(fd, SOL_IP, IP_TOS, big_buf, &optlen);
52 log_err("Failed to call getsockopt(IP_TOS)");
56 if (*big_buf != 0x08) {
57 log_err("Unexpected getsockopt(IP_TOS) optval 0x%x != 0x08",
65 err = setsockopt(fd, SOL_IP, IP_TTL, &buf, 1);
66 if (!err || errno != EPERM) {
67 log_err("Unexpected success from setsockopt(IP_TTL)");
71 /* SOL_CUSTOM - handled by BPF */
74 err = setsockopt(fd, SOL_CUSTOM, 0, &buf, 1);
76 log_err("Failed to call setsockopt");
82 err = getsockopt(fd, SOL_CUSTOM, 0, &buf, &optlen);
84 log_err("Failed to call getsockopt");
89 log_err("Unexpected optlen %d != 1", optlen);
92 if (buf.u8[0] != 0x01) {
93 log_err("Unexpected buf[0] 0x%02x != 0x01", buf.u8[0]);
97 /* IP_FREEBIND - BPF can't access optval past PAGE_SIZE */
99 optlen = getpagesize() * 2;
100 memset(big_buf, 0, optlen);
102 err = setsockopt(fd, SOL_IP, IP_FREEBIND, big_buf, optlen);
104 log_err("Failed to call setsockopt, ret=%d", err);
108 err = getsockopt(fd, SOL_IP, IP_FREEBIND, big_buf, &optlen);
110 log_err("Failed to call getsockopt, ret=%d", err);
114 if (optlen != 1 || *(__u8 *)big_buf != 0x55) {
115 log_err("Unexpected IP_FREEBIND getsockopt, optlen=%d, optval=0x%x",
116 optlen, *(__u8 *)big_buf);
119 /* SO_SNDBUF is overwritten */
121 buf.u32 = 0x01010101;
122 err = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf, 4);
124 log_err("Failed to call setsockopt(SO_SNDBUF)");
130 err = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf, &optlen);
132 log_err("Failed to call getsockopt(SO_SNDBUF)");
136 if (buf.u32 != 0x55AA*2) {
137 log_err("Unexpected getsockopt(SO_SNDBUF) 0x%x != 0x55AA*2",
142 /* TCP_CONGESTION can extend the string */
144 strcpy(buf.cc, "nv");
145 err = setsockopt(fd, SOL_TCP, TCP_CONGESTION, &buf, strlen("nv"));
147 log_err("Failed to call setsockopt(TCP_CONGESTION)");
152 optlen = sizeof(buf.cc);
153 err = getsockopt(fd, SOL_TCP, TCP_CONGESTION, &buf, &optlen);
155 log_err("Failed to call getsockopt(TCP_CONGESTION)");
159 if (strcmp(buf.cc, "cubic") != 0) {
160 log_err("Unexpected getsockopt(TCP_CONGESTION) %s != %s",
165 /* TCP_ZEROCOPY_RECEIVE triggers */
166 memset(&buf, 0, sizeof(buf));
167 optlen = sizeof(buf.zc);
168 err = getsockopt(fd, SOL_TCP, TCP_ZEROCOPY_RECEIVE, &buf, &optlen);
170 log_err("Unexpected getsockopt(TCP_ZEROCOPY_RECEIVE) err=%d errno=%d",
175 memset(&buf, 0, sizeof(buf));
176 buf.zc.address = 12345; /* Not page aligned. Rejected by tcp_zerocopy_receive() */
177 optlen = sizeof(buf.zc);
179 err = getsockopt(fd, SOL_TCP, TCP_ZEROCOPY_RECEIVE, &buf, &optlen);
180 if (errno != EINVAL) {
181 log_err("Unexpected getsockopt(TCP_ZEROCOPY_RECEIVE) err=%d errno=%d",
195 static void run_test(int cgroup_fd)
197 struct sockopt_sk *skel;
199 skel = sockopt_sk__open_and_load();
200 if (!ASSERT_OK_PTR(skel, "skel_load"))
203 skel->bss->page_size = getpagesize();
205 skel->links._setsockopt =
206 bpf_program__attach_cgroup(skel->progs._setsockopt, cgroup_fd);
207 if (!ASSERT_OK_PTR(skel->links._setsockopt, "setsockopt_link"))
210 skel->links._getsockopt =
211 bpf_program__attach_cgroup(skel->progs._getsockopt, cgroup_fd);
212 if (!ASSERT_OK_PTR(skel->links._getsockopt, "getsockopt_link"))
215 ASSERT_OK(getsetsockopt(), "getsetsockopt");
218 sockopt_sk__destroy(skel);
221 void test_sockopt_sk(void)
225 cgroup_fd = test__join_cgroup("/sockopt_sk");
226 if (!ASSERT_GE(cgroup_fd, 0, "join_cgroup /sockopt_sk"))