1ad2f8eb0SMartin KaFai Lau // SPDX-License-Identifier: GPL-2.0
2ad2f8eb0SMartin KaFai Lau /* Copyright (c) 2020 Facebook */
3ad2f8eb0SMartin KaFai Lau 
4ad2f8eb0SMartin KaFai Lau #define _GNU_SOURCE
5ad2f8eb0SMartin KaFai Lau #include <sched.h>
6ad2f8eb0SMartin KaFai Lau #include <stdio.h>
7ad2f8eb0SMartin KaFai Lau #include <stdlib.h>
8ad2f8eb0SMartin KaFai Lau #include <sys/socket.h>
9ad2f8eb0SMartin KaFai Lau #include <linux/compiler.h>
10ad2f8eb0SMartin KaFai Lau 
11ad2f8eb0SMartin KaFai Lau #include "test_progs.h"
12ad2f8eb0SMartin KaFai Lau #include "cgroup_helpers.h"
13ad2f8eb0SMartin KaFai Lau #include "network_helpers.h"
14ad2f8eb0SMartin KaFai Lau #include "test_tcp_hdr_options.h"
15ad2f8eb0SMartin KaFai Lau #include "test_tcp_hdr_options.skel.h"
16ad2f8eb0SMartin KaFai Lau #include "test_misc_tcp_hdr_options.skel.h"
17ad2f8eb0SMartin KaFai Lau 
188a3feed9SMartin KaFai Lau #define LO_ADDR6 "::1"
19ad2f8eb0SMartin KaFai Lau #define CG_NAME "/tcpbpf-hdr-opt-test"
20ad2f8eb0SMartin KaFai Lau 
21f52b8fd3SMartin KaFai Lau static struct bpf_test_option exp_passive_estab_in;
22f52b8fd3SMartin KaFai Lau static struct bpf_test_option exp_active_estab_in;
23f52b8fd3SMartin KaFai Lau static struct bpf_test_option exp_passive_fin_in;
24f52b8fd3SMartin KaFai Lau static struct bpf_test_option exp_active_fin_in;
25f52b8fd3SMartin KaFai Lau static struct hdr_stg exp_passive_hdr_stg;
26f52b8fd3SMartin KaFai Lau static struct hdr_stg exp_active_hdr_stg = { .active = true, };
27ad2f8eb0SMartin KaFai Lau 
28ad2f8eb0SMartin KaFai Lau static struct test_misc_tcp_hdr_options *misc_skel;
29ad2f8eb0SMartin KaFai Lau static struct test_tcp_hdr_options *skel;
30ad2f8eb0SMartin KaFai Lau static int lport_linum_map_fd;
31ad2f8eb0SMartin KaFai Lau static int hdr_stg_map_fd;
32ad2f8eb0SMartin KaFai Lau static __u32 duration;
33ad2f8eb0SMartin KaFai Lau static int cg_fd;
34ad2f8eb0SMartin KaFai Lau 
35ad2f8eb0SMartin KaFai Lau struct sk_fds {
36ad2f8eb0SMartin KaFai Lau 	int srv_fd;
37ad2f8eb0SMartin KaFai Lau 	int passive_fd;
38ad2f8eb0SMartin KaFai Lau 	int active_fd;
39ad2f8eb0SMartin KaFai Lau 	int passive_lport;
40ad2f8eb0SMartin KaFai Lau 	int active_lport;
41ad2f8eb0SMartin KaFai Lau };
42ad2f8eb0SMartin KaFai Lau 
create_netns(void)43ad2f8eb0SMartin KaFai Lau static int create_netns(void)
44ad2f8eb0SMartin KaFai Lau {
453082f8cdSWang Yufen 	if (!ASSERT_OK(unshare(CLONE_NEWNET), "create netns"))
46ad2f8eb0SMartin KaFai Lau 		return -1;
47ad2f8eb0SMartin KaFai Lau 
483082f8cdSWang Yufen 	if (!ASSERT_OK(system("ip link set dev lo up"), "run ip cmd"))
49ad2f8eb0SMartin KaFai Lau 		return -1;
50ad2f8eb0SMartin KaFai Lau 
51ad2f8eb0SMartin KaFai Lau 	return 0;
52ad2f8eb0SMartin KaFai Lau }
53ad2f8eb0SMartin KaFai Lau 
print_hdr_stg(const struct hdr_stg * hdr_stg,const char * prefix)54ad2f8eb0SMartin KaFai Lau static void print_hdr_stg(const struct hdr_stg *hdr_stg, const char *prefix)
55ad2f8eb0SMartin KaFai Lau {
56ad2f8eb0SMartin KaFai Lau 	fprintf(stderr, "%s{active:%u, resend_syn:%u, syncookie:%u, fastopen:%u}\n",
57ad2f8eb0SMartin KaFai Lau 		prefix ? : "", hdr_stg->active, hdr_stg->resend_syn,
58ad2f8eb0SMartin KaFai Lau 		hdr_stg->syncookie, hdr_stg->fastopen);
59ad2f8eb0SMartin KaFai Lau }
60ad2f8eb0SMartin KaFai Lau 
print_option(const struct bpf_test_option * opt,const char * prefix)61ad2f8eb0SMartin KaFai Lau static void print_option(const struct bpf_test_option *opt, const char *prefix)
62ad2f8eb0SMartin KaFai Lau {
63ad2f8eb0SMartin KaFai Lau 	fprintf(stderr, "%s{flags:0x%x, max_delack_ms:%u, rand:0x%x}\n",
64ad2f8eb0SMartin KaFai Lau 		prefix ? : "", opt->flags, opt->max_delack_ms, opt->rand);
65ad2f8eb0SMartin KaFai Lau }
66ad2f8eb0SMartin KaFai Lau 
sk_fds_close(struct sk_fds * sk_fds)67ad2f8eb0SMartin KaFai Lau static void sk_fds_close(struct sk_fds *sk_fds)
68ad2f8eb0SMartin KaFai Lau {
69ad2f8eb0SMartin KaFai Lau 	close(sk_fds->srv_fd);
70ad2f8eb0SMartin KaFai Lau 	close(sk_fds->passive_fd);
71ad2f8eb0SMartin KaFai Lau 	close(sk_fds->active_fd);
72ad2f8eb0SMartin KaFai Lau }
73ad2f8eb0SMartin KaFai Lau 
sk_fds_shutdown(struct sk_fds * sk_fds)74ad2f8eb0SMartin KaFai Lau static int sk_fds_shutdown(struct sk_fds *sk_fds)
75ad2f8eb0SMartin KaFai Lau {
76ad2f8eb0SMartin KaFai Lau 	int ret, abyte;
77ad2f8eb0SMartin KaFai Lau 
78ad2f8eb0SMartin KaFai Lau 	shutdown(sk_fds->active_fd, SHUT_WR);
79ad2f8eb0SMartin KaFai Lau 	ret = read(sk_fds->passive_fd, &abyte, sizeof(abyte));
803082f8cdSWang Yufen 	if (!ASSERT_EQ(ret, 0, "read-after-shutdown(passive_fd):"))
81ad2f8eb0SMartin KaFai Lau 		return -1;
82ad2f8eb0SMartin KaFai Lau 
83ad2f8eb0SMartin KaFai Lau 	shutdown(sk_fds->passive_fd, SHUT_WR);
84ad2f8eb0SMartin KaFai Lau 	ret = read(sk_fds->active_fd, &abyte, sizeof(abyte));
853082f8cdSWang Yufen 	if (!ASSERT_EQ(ret, 0, "read-after-shutdown(active_fd):"))
86ad2f8eb0SMartin KaFai Lau 		return -1;
87ad2f8eb0SMartin KaFai Lau 
88ad2f8eb0SMartin KaFai Lau 	return 0;
89ad2f8eb0SMartin KaFai Lau }
90ad2f8eb0SMartin KaFai Lau 
sk_fds_connect(struct sk_fds * sk_fds,bool fast_open)91ad2f8eb0SMartin KaFai Lau static int sk_fds_connect(struct sk_fds *sk_fds, bool fast_open)
92ad2f8eb0SMartin KaFai Lau {
93ad2f8eb0SMartin KaFai Lau 	const char fast[] = "FAST!!!";
94ad2f8eb0SMartin KaFai Lau 	struct sockaddr_in6 addr6;
95ad2f8eb0SMartin KaFai Lau 	socklen_t len;
96ad2f8eb0SMartin KaFai Lau 
97ad2f8eb0SMartin KaFai Lau 	sk_fds->srv_fd = start_server(AF_INET6, SOCK_STREAM, LO_ADDR6, 0, 0);
983082f8cdSWang Yufen 	if (!ASSERT_NEQ(sk_fds->srv_fd, -1, "start_server"))
99ad2f8eb0SMartin KaFai Lau 		goto error;
100ad2f8eb0SMartin KaFai Lau 
101ad2f8eb0SMartin KaFai Lau 	if (fast_open)
102ad2f8eb0SMartin KaFai Lau 		sk_fds->active_fd = fastopen_connect(sk_fds->srv_fd, fast,
103ad2f8eb0SMartin KaFai Lau 						     sizeof(fast), 0);
104ad2f8eb0SMartin KaFai Lau 	else
105ad2f8eb0SMartin KaFai Lau 		sk_fds->active_fd = connect_to_fd(sk_fds->srv_fd, 0);
106ad2f8eb0SMartin KaFai Lau 
1073082f8cdSWang Yufen 	if (!ASSERT_NEQ(sk_fds->active_fd, -1, "")) {
108ad2f8eb0SMartin KaFai Lau 		close(sk_fds->srv_fd);
109ad2f8eb0SMartin KaFai Lau 		goto error;
110ad2f8eb0SMartin KaFai Lau 	}
111ad2f8eb0SMartin KaFai Lau 
112ad2f8eb0SMartin KaFai Lau 	len = sizeof(addr6);
1133082f8cdSWang Yufen 	if (!ASSERT_OK(getsockname(sk_fds->srv_fd, (struct sockaddr *)&addr6,
1143082f8cdSWang Yufen 				   &len), "getsockname(srv_fd)"))
115ad2f8eb0SMartin KaFai Lau 		goto error_close;
116ad2f8eb0SMartin KaFai Lau 	sk_fds->passive_lport = ntohs(addr6.sin6_port);
117ad2f8eb0SMartin KaFai Lau 
118ad2f8eb0SMartin KaFai Lau 	len = sizeof(addr6);
1193082f8cdSWang Yufen 	if (!ASSERT_OK(getsockname(sk_fds->active_fd, (struct sockaddr *)&addr6,
1203082f8cdSWang Yufen 				   &len), "getsockname(active_fd)"))
121ad2f8eb0SMartin KaFai Lau 		goto error_close;
122ad2f8eb0SMartin KaFai Lau 	sk_fds->active_lport = ntohs(addr6.sin6_port);
123ad2f8eb0SMartin KaFai Lau 
124ad2f8eb0SMartin KaFai Lau 	sk_fds->passive_fd = accept(sk_fds->srv_fd, NULL, 0);
1253082f8cdSWang Yufen 	if (!ASSERT_NEQ(sk_fds->passive_fd, -1, "accept(srv_fd)"))
126ad2f8eb0SMartin KaFai Lau 		goto error_close;
127ad2f8eb0SMartin KaFai Lau 
128ad2f8eb0SMartin KaFai Lau 	if (fast_open) {
129ad2f8eb0SMartin KaFai Lau 		char bytes_in[sizeof(fast)];
130ad2f8eb0SMartin KaFai Lau 		int ret;
131ad2f8eb0SMartin KaFai Lau 
132ad2f8eb0SMartin KaFai Lau 		ret = read(sk_fds->passive_fd, bytes_in, sizeof(bytes_in));
1333082f8cdSWang Yufen 		if (!ASSERT_EQ(ret, sizeof(fast), "read fastopen syn data")) {
134ad2f8eb0SMartin KaFai Lau 			close(sk_fds->passive_fd);
135ad2f8eb0SMartin KaFai Lau 			goto error_close;
136ad2f8eb0SMartin KaFai Lau 		}
137ad2f8eb0SMartin KaFai Lau 	}
138ad2f8eb0SMartin KaFai Lau 
139ad2f8eb0SMartin KaFai Lau 	return 0;
140ad2f8eb0SMartin KaFai Lau 
141ad2f8eb0SMartin KaFai Lau error_close:
142ad2f8eb0SMartin KaFai Lau 	close(sk_fds->active_fd);
143ad2f8eb0SMartin KaFai Lau 	close(sk_fds->srv_fd);
144ad2f8eb0SMartin KaFai Lau 
145ad2f8eb0SMartin KaFai Lau error:
146ad2f8eb0SMartin KaFai Lau 	memset(sk_fds, -1, sizeof(*sk_fds));
147ad2f8eb0SMartin KaFai Lau 	return -1;
148ad2f8eb0SMartin KaFai Lau }
149ad2f8eb0SMartin KaFai Lau 
check_hdr_opt(const struct bpf_test_option * exp,const struct bpf_test_option * act,const char * hdr_desc)150ad2f8eb0SMartin KaFai Lau static int check_hdr_opt(const struct bpf_test_option *exp,
151ad2f8eb0SMartin KaFai Lau 			 const struct bpf_test_option *act,
152ad2f8eb0SMartin KaFai Lau 			 const char *hdr_desc)
153ad2f8eb0SMartin KaFai Lau {
154ed01385cSMartin KaFai Lau 	if (!ASSERT_EQ(memcmp(exp, act, sizeof(*exp)), 0, hdr_desc)) {
155ad2f8eb0SMartin KaFai Lau 		print_option(exp, "expected: ");
156ad2f8eb0SMartin KaFai Lau 		print_option(act, "  actual: ");
157ad2f8eb0SMartin KaFai Lau 		return -1;
158ad2f8eb0SMartin KaFai Lau 	}
159ad2f8eb0SMartin KaFai Lau 
160ad2f8eb0SMartin KaFai Lau 	return 0;
161ad2f8eb0SMartin KaFai Lau }
162ad2f8eb0SMartin KaFai Lau 
check_hdr_stg(const struct hdr_stg * exp,int fd,const char * stg_desc)163ad2f8eb0SMartin KaFai Lau static int check_hdr_stg(const struct hdr_stg *exp, int fd,
164ad2f8eb0SMartin KaFai Lau 			 const char *stg_desc)
165ad2f8eb0SMartin KaFai Lau {
166ad2f8eb0SMartin KaFai Lau 	struct hdr_stg act;
167ad2f8eb0SMartin KaFai Lau 
1683082f8cdSWang Yufen 	if (!ASSERT_OK(bpf_map_lookup_elem(hdr_stg_map_fd, &fd, &act),
1693082f8cdSWang Yufen 		  "map_lookup(hdr_stg_map_fd)"))
170ad2f8eb0SMartin KaFai Lau 		return -1;
171ad2f8eb0SMartin KaFai Lau 
172ed01385cSMartin KaFai Lau 	if (!ASSERT_EQ(memcmp(exp, &act, sizeof(*exp)), 0, stg_desc)) {
173ad2f8eb0SMartin KaFai Lau 		print_hdr_stg(exp, "expected: ");
174ad2f8eb0SMartin KaFai Lau 		print_hdr_stg(&act, "  actual: ");
175ad2f8eb0SMartin KaFai Lau 		return -1;
176ad2f8eb0SMartin KaFai Lau 	}
177ad2f8eb0SMartin KaFai Lau 
178ad2f8eb0SMartin KaFai Lau 	return 0;
179ad2f8eb0SMartin KaFai Lau }
180ad2f8eb0SMartin KaFai Lau 
check_error_linum(const struct sk_fds * sk_fds)181ad2f8eb0SMartin KaFai Lau static int check_error_linum(const struct sk_fds *sk_fds)
182ad2f8eb0SMartin KaFai Lau {
183ad2f8eb0SMartin KaFai Lau 	unsigned int nr_errors = 0;
184ad2f8eb0SMartin KaFai Lau 	struct linum_err linum_err;
185ad2f8eb0SMartin KaFai Lau 	int lport;
186ad2f8eb0SMartin KaFai Lau 
187ad2f8eb0SMartin KaFai Lau 	lport = sk_fds->passive_lport;
188ad2f8eb0SMartin KaFai Lau 	if (!bpf_map_lookup_elem(lport_linum_map_fd, &lport, &linum_err)) {
189ad2f8eb0SMartin KaFai Lau 		fprintf(stderr,
190ad2f8eb0SMartin KaFai Lau 			"bpf prog error out at lport:passive(%d), linum:%u err:%d\n",
191ad2f8eb0SMartin KaFai Lau 			lport, linum_err.linum, linum_err.err);
192ad2f8eb0SMartin KaFai Lau 		nr_errors++;
193ad2f8eb0SMartin KaFai Lau 	}
194ad2f8eb0SMartin KaFai Lau 
195ad2f8eb0SMartin KaFai Lau 	lport = sk_fds->active_lport;
196ad2f8eb0SMartin KaFai Lau 	if (!bpf_map_lookup_elem(lport_linum_map_fd, &lport, &linum_err)) {
197ad2f8eb0SMartin KaFai Lau 		fprintf(stderr,
198ad2f8eb0SMartin KaFai Lau 			"bpf prog error out at lport:active(%d), linum:%u err:%d\n",
199ad2f8eb0SMartin KaFai Lau 			lport, linum_err.linum, linum_err.err);
200ad2f8eb0SMartin KaFai Lau 		nr_errors++;
201ad2f8eb0SMartin KaFai Lau 	}
202ad2f8eb0SMartin KaFai Lau 
203ad2f8eb0SMartin KaFai Lau 	return nr_errors;
204ad2f8eb0SMartin KaFai Lau }
205ad2f8eb0SMartin KaFai Lau 
check_hdr_and_close_fds(struct sk_fds * sk_fds)206ad2f8eb0SMartin KaFai Lau static void check_hdr_and_close_fds(struct sk_fds *sk_fds)
207ad2f8eb0SMartin KaFai Lau {
20896d46c50SMartin KaFai Lau 	const __u32 expected_inherit_cb_flags =
20996d46c50SMartin KaFai Lau 		BPF_SOCK_OPS_PARSE_UNKNOWN_HDR_OPT_CB_FLAG |
21096d46c50SMartin KaFai Lau 		BPF_SOCK_OPS_WRITE_HDR_OPT_CB_FLAG |
21196d46c50SMartin KaFai Lau 		BPF_SOCK_OPS_STATE_CB_FLAG;
21296d46c50SMartin KaFai Lau 
213ad2f8eb0SMartin KaFai Lau 	if (sk_fds_shutdown(sk_fds))
214ad2f8eb0SMartin KaFai Lau 		goto check_linum;
215ad2f8eb0SMartin KaFai Lau 
2163082f8cdSWang Yufen 	if (!ASSERT_EQ(expected_inherit_cb_flags, skel->bss->inherit_cb_flags,
2173082f8cdSWang Yufen 		       "inherit_cb_flags"))
21896d46c50SMartin KaFai Lau 		goto check_linum;
21996d46c50SMartin KaFai Lau 
220ad2f8eb0SMartin KaFai Lau 	if (check_hdr_stg(&exp_passive_hdr_stg, sk_fds->passive_fd,
221ad2f8eb0SMartin KaFai Lau 			  "passive_hdr_stg"))
222ad2f8eb0SMartin KaFai Lau 		goto check_linum;
223ad2f8eb0SMartin KaFai Lau 
224ad2f8eb0SMartin KaFai Lau 	if (check_hdr_stg(&exp_active_hdr_stg, sk_fds->active_fd,
225ad2f8eb0SMartin KaFai Lau 			  "active_hdr_stg"))
226ad2f8eb0SMartin KaFai Lau 		goto check_linum;
227ad2f8eb0SMartin KaFai Lau 
228ad2f8eb0SMartin KaFai Lau 	if (check_hdr_opt(&exp_passive_estab_in, &skel->bss->passive_estab_in,
229ad2f8eb0SMartin KaFai Lau 			  "passive_estab_in"))
230ad2f8eb0SMartin KaFai Lau 		goto check_linum;
231ad2f8eb0SMartin KaFai Lau 
232ad2f8eb0SMartin KaFai Lau 	if (check_hdr_opt(&exp_active_estab_in, &skel->bss->active_estab_in,
233ad2f8eb0SMartin KaFai Lau 			  "active_estab_in"))
234ad2f8eb0SMartin KaFai Lau 		goto check_linum;
235ad2f8eb0SMartin KaFai Lau 
236ad2f8eb0SMartin KaFai Lau 	if (check_hdr_opt(&exp_passive_fin_in, &skel->bss->passive_fin_in,
237ad2f8eb0SMartin KaFai Lau 			  "passive_fin_in"))
238ad2f8eb0SMartin KaFai Lau 		goto check_linum;
239ad2f8eb0SMartin KaFai Lau 
240ad2f8eb0SMartin KaFai Lau 	check_hdr_opt(&exp_active_fin_in, &skel->bss->active_fin_in,
241ad2f8eb0SMartin KaFai Lau 		      "active_fin_in");
242ad2f8eb0SMartin KaFai Lau 
243ad2f8eb0SMartin KaFai Lau check_linum:
2443082f8cdSWang Yufen 	ASSERT_FALSE(check_error_linum(sk_fds), "check_error_linum");
245ad2f8eb0SMartin KaFai Lau 	sk_fds_close(sk_fds);
246ad2f8eb0SMartin KaFai Lau }
247ad2f8eb0SMartin KaFai Lau 
prepare_out(void)248ad2f8eb0SMartin KaFai Lau static void prepare_out(void)
249ad2f8eb0SMartin KaFai Lau {
250ad2f8eb0SMartin KaFai Lau 	skel->bss->active_syn_out = exp_passive_estab_in;
251ad2f8eb0SMartin KaFai Lau 	skel->bss->passive_synack_out = exp_active_estab_in;
252ad2f8eb0SMartin KaFai Lau 
253ad2f8eb0SMartin KaFai Lau 	skel->bss->active_fin_out = exp_passive_fin_in;
254ad2f8eb0SMartin KaFai Lau 	skel->bss->passive_fin_out = exp_active_fin_in;
255ad2f8eb0SMartin KaFai Lau }
256ad2f8eb0SMartin KaFai Lau 
reset_test(void)257ad2f8eb0SMartin KaFai Lau static void reset_test(void)
258ad2f8eb0SMartin KaFai Lau {
259ad2f8eb0SMartin KaFai Lau 	size_t optsize = sizeof(struct bpf_test_option);
260ad2f8eb0SMartin KaFai Lau 	int lport, err;
261ad2f8eb0SMartin KaFai Lau 
262ad2f8eb0SMartin KaFai Lau 	memset(&skel->bss->passive_synack_out, 0, optsize);
263ad2f8eb0SMartin KaFai Lau 	memset(&skel->bss->passive_fin_out, 0, optsize);
264ad2f8eb0SMartin KaFai Lau 
265ad2f8eb0SMartin KaFai Lau 	memset(&skel->bss->passive_estab_in, 0, optsize);
266ad2f8eb0SMartin KaFai Lau 	memset(&skel->bss->passive_fin_in, 0, optsize);
267ad2f8eb0SMartin KaFai Lau 
268ad2f8eb0SMartin KaFai Lau 	memset(&skel->bss->active_syn_out, 0, optsize);
269ad2f8eb0SMartin KaFai Lau 	memset(&skel->bss->active_fin_out, 0, optsize);
270ad2f8eb0SMartin KaFai Lau 
271ad2f8eb0SMartin KaFai Lau 	memset(&skel->bss->active_estab_in, 0, optsize);
272ad2f8eb0SMartin KaFai Lau 	memset(&skel->bss->active_fin_in, 0, optsize);
273ad2f8eb0SMartin KaFai Lau 
27496d46c50SMartin KaFai Lau 	skel->bss->inherit_cb_flags = 0;
27596d46c50SMartin KaFai Lau 
276ad2f8eb0SMartin KaFai Lau 	skel->data->test_kind = TCPOPT_EXP;
277ad2f8eb0SMartin KaFai Lau 	skel->data->test_magic = 0xeB9F;
278ad2f8eb0SMartin KaFai Lau 
279ad2f8eb0SMartin KaFai Lau 	memset(&exp_passive_estab_in, 0, optsize);
280ad2f8eb0SMartin KaFai Lau 	memset(&exp_active_estab_in, 0, optsize);
281ad2f8eb0SMartin KaFai Lau 	memset(&exp_passive_fin_in, 0, optsize);
282ad2f8eb0SMartin KaFai Lau 	memset(&exp_active_fin_in, 0, optsize);
283ad2f8eb0SMartin KaFai Lau 
284ad2f8eb0SMartin KaFai Lau 	memset(&exp_passive_hdr_stg, 0, sizeof(exp_passive_hdr_stg));
285ad2f8eb0SMartin KaFai Lau 	memset(&exp_active_hdr_stg, 0, sizeof(exp_active_hdr_stg));
286ad2f8eb0SMartin KaFai Lau 	exp_active_hdr_stg.active = true;
287ad2f8eb0SMartin KaFai Lau 
288ad2f8eb0SMartin KaFai Lau 	err = bpf_map_get_next_key(lport_linum_map_fd, NULL, &lport);
289ad2f8eb0SMartin KaFai Lau 	while (!err) {
290ad2f8eb0SMartin KaFai Lau 		bpf_map_delete_elem(lport_linum_map_fd, &lport);
291ad2f8eb0SMartin KaFai Lau 		err = bpf_map_get_next_key(lport_linum_map_fd, &lport, &lport);
292ad2f8eb0SMartin KaFai Lau 	}
293ad2f8eb0SMartin KaFai Lau }
294ad2f8eb0SMartin KaFai Lau 
fastopen_estab(void)295ad2f8eb0SMartin KaFai Lau static void fastopen_estab(void)
296ad2f8eb0SMartin KaFai Lau {
297ad2f8eb0SMartin KaFai Lau 	struct bpf_link *link;
298ad2f8eb0SMartin KaFai Lau 	struct sk_fds sk_fds;
299ad2f8eb0SMartin KaFai Lau 
300ad2f8eb0SMartin KaFai Lau 	hdr_stg_map_fd = bpf_map__fd(skel->maps.hdr_stg_map);
301ad2f8eb0SMartin KaFai Lau 	lport_linum_map_fd = bpf_map__fd(skel->maps.lport_linum_map);
302ad2f8eb0SMartin KaFai Lau 
303ad2f8eb0SMartin KaFai Lau 	exp_passive_estab_in.flags = OPTION_F_RAND | OPTION_F_MAX_DELACK_MS;
304ad2f8eb0SMartin KaFai Lau 	exp_passive_estab_in.rand = 0xfa;
305ad2f8eb0SMartin KaFai Lau 	exp_passive_estab_in.max_delack_ms = 11;
306ad2f8eb0SMartin KaFai Lau 
307ad2f8eb0SMartin KaFai Lau 	exp_active_estab_in.flags = OPTION_F_RAND | OPTION_F_MAX_DELACK_MS;
308ad2f8eb0SMartin KaFai Lau 	exp_active_estab_in.rand = 0xce;
309ad2f8eb0SMartin KaFai Lau 	exp_active_estab_in.max_delack_ms = 22;
310ad2f8eb0SMartin KaFai Lau 
311ad2f8eb0SMartin KaFai Lau 	exp_passive_hdr_stg.fastopen = true;
312ad2f8eb0SMartin KaFai Lau 
313ad2f8eb0SMartin KaFai Lau 	prepare_out();
314ad2f8eb0SMartin KaFai Lau 
315ad2f8eb0SMartin KaFai Lau 	/* Allow fastopen without fastopen cookie */
316ad2f8eb0SMartin KaFai Lau 	if (write_sysctl("/proc/sys/net/ipv4/tcp_fastopen", "1543"))
317ad2f8eb0SMartin KaFai Lau 		return;
318ad2f8eb0SMartin KaFai Lau 
319ad2f8eb0SMartin KaFai Lau 	link = bpf_program__attach_cgroup(skel->progs.estab, cg_fd);
320bad2e478SAndrii Nakryiko 	if (!ASSERT_OK_PTR(link, "attach_cgroup(estab)"))
321ad2f8eb0SMartin KaFai Lau 		return;
322ad2f8eb0SMartin KaFai Lau 
323ad2f8eb0SMartin KaFai Lau 	if (sk_fds_connect(&sk_fds, true)) {
324ad2f8eb0SMartin KaFai Lau 		bpf_link__destroy(link);
325ad2f8eb0SMartin KaFai Lau 		return;
326ad2f8eb0SMartin KaFai Lau 	}
327ad2f8eb0SMartin KaFai Lau 
328ad2f8eb0SMartin KaFai Lau 	check_hdr_and_close_fds(&sk_fds);
329ad2f8eb0SMartin KaFai Lau 	bpf_link__destroy(link);
330ad2f8eb0SMartin KaFai Lau }
331ad2f8eb0SMartin KaFai Lau 
syncookie_estab(void)332ad2f8eb0SMartin KaFai Lau static void syncookie_estab(void)
333ad2f8eb0SMartin KaFai Lau {
334ad2f8eb0SMartin KaFai Lau 	struct bpf_link *link;
335ad2f8eb0SMartin KaFai Lau 	struct sk_fds sk_fds;
336ad2f8eb0SMartin KaFai Lau 
337ad2f8eb0SMartin KaFai Lau 	hdr_stg_map_fd = bpf_map__fd(skel->maps.hdr_stg_map);
338ad2f8eb0SMartin KaFai Lau 	lport_linum_map_fd = bpf_map__fd(skel->maps.lport_linum_map);
339ad2f8eb0SMartin KaFai Lau 
340ad2f8eb0SMartin KaFai Lau 	exp_passive_estab_in.flags = OPTION_F_RAND | OPTION_F_MAX_DELACK_MS;
341ad2f8eb0SMartin KaFai Lau 	exp_passive_estab_in.rand = 0xfa;
342ad2f8eb0SMartin KaFai Lau 	exp_passive_estab_in.max_delack_ms = 11;
343ad2f8eb0SMartin KaFai Lau 
344ad2f8eb0SMartin KaFai Lau 	exp_active_estab_in.flags = OPTION_F_RAND | OPTION_F_MAX_DELACK_MS |
345ad2f8eb0SMartin KaFai Lau 					OPTION_F_RESEND;
346ad2f8eb0SMartin KaFai Lau 	exp_active_estab_in.rand = 0xce;
347ad2f8eb0SMartin KaFai Lau 	exp_active_estab_in.max_delack_ms = 22;
348ad2f8eb0SMartin KaFai Lau 
349ad2f8eb0SMartin KaFai Lau 	exp_passive_hdr_stg.syncookie = true;
350*856fe03dSLu Hongfei 	exp_active_hdr_stg.resend_syn = true;
351ad2f8eb0SMartin KaFai Lau 
352ad2f8eb0SMartin KaFai Lau 	prepare_out();
353ad2f8eb0SMartin KaFai Lau 
354ad2f8eb0SMartin KaFai Lau 	/* Clear the RESEND to ensure the bpf prog can learn
355ad2f8eb0SMartin KaFai Lau 	 * want_cookie and set the RESEND by itself.
356ad2f8eb0SMartin KaFai Lau 	 */
357ad2f8eb0SMartin KaFai Lau 	skel->bss->passive_synack_out.flags &= ~OPTION_F_RESEND;
358ad2f8eb0SMartin KaFai Lau 
359ad2f8eb0SMartin KaFai Lau 	/* Enforce syncookie mode */
360ad2f8eb0SMartin KaFai Lau 	if (write_sysctl("/proc/sys/net/ipv4/tcp_syncookies", "2"))
361ad2f8eb0SMartin KaFai Lau 		return;
362ad2f8eb0SMartin KaFai Lau 
363ad2f8eb0SMartin KaFai Lau 	link = bpf_program__attach_cgroup(skel->progs.estab, cg_fd);
364bad2e478SAndrii Nakryiko 	if (!ASSERT_OK_PTR(link, "attach_cgroup(estab)"))
365ad2f8eb0SMartin KaFai Lau 		return;
366ad2f8eb0SMartin KaFai Lau 
367ad2f8eb0SMartin KaFai Lau 	if (sk_fds_connect(&sk_fds, false)) {
368ad2f8eb0SMartin KaFai Lau 		bpf_link__destroy(link);
369ad2f8eb0SMartin KaFai Lau 		return;
370ad2f8eb0SMartin KaFai Lau 	}
371ad2f8eb0SMartin KaFai Lau 
372ad2f8eb0SMartin KaFai Lau 	check_hdr_and_close_fds(&sk_fds);
373ad2f8eb0SMartin KaFai Lau 	bpf_link__destroy(link);
374ad2f8eb0SMartin KaFai Lau }
375ad2f8eb0SMartin KaFai Lau 
fin(void)376ad2f8eb0SMartin KaFai Lau static void fin(void)
377ad2f8eb0SMartin KaFai Lau {
378ad2f8eb0SMartin KaFai Lau 	struct bpf_link *link;
379ad2f8eb0SMartin KaFai Lau 	struct sk_fds sk_fds;
380ad2f8eb0SMartin KaFai Lau 
381ad2f8eb0SMartin KaFai Lau 	hdr_stg_map_fd = bpf_map__fd(skel->maps.hdr_stg_map);
382ad2f8eb0SMartin KaFai Lau 	lport_linum_map_fd = bpf_map__fd(skel->maps.lport_linum_map);
383ad2f8eb0SMartin KaFai Lau 
384ad2f8eb0SMartin KaFai Lau 	exp_passive_fin_in.flags = OPTION_F_RAND;
385ad2f8eb0SMartin KaFai Lau 	exp_passive_fin_in.rand = 0xfa;
386ad2f8eb0SMartin KaFai Lau 
387ad2f8eb0SMartin KaFai Lau 	exp_active_fin_in.flags = OPTION_F_RAND;
388ad2f8eb0SMartin KaFai Lau 	exp_active_fin_in.rand = 0xce;
389ad2f8eb0SMartin KaFai Lau 
390ad2f8eb0SMartin KaFai Lau 	prepare_out();
391ad2f8eb0SMartin KaFai Lau 
392ad2f8eb0SMartin KaFai Lau 	if (write_sysctl("/proc/sys/net/ipv4/tcp_syncookies", "1"))
393ad2f8eb0SMartin KaFai Lau 		return;
394ad2f8eb0SMartin KaFai Lau 
395ad2f8eb0SMartin KaFai Lau 	link = bpf_program__attach_cgroup(skel->progs.estab, cg_fd);
396bad2e478SAndrii Nakryiko 	if (!ASSERT_OK_PTR(link, "attach_cgroup(estab)"))
397ad2f8eb0SMartin KaFai Lau 		return;
398ad2f8eb0SMartin KaFai Lau 
399ad2f8eb0SMartin KaFai Lau 	if (sk_fds_connect(&sk_fds, false)) {
400ad2f8eb0SMartin KaFai Lau 		bpf_link__destroy(link);
401ad2f8eb0SMartin KaFai Lau 		return;
402ad2f8eb0SMartin KaFai Lau 	}
403ad2f8eb0SMartin KaFai Lau 
404ad2f8eb0SMartin KaFai Lau 	check_hdr_and_close_fds(&sk_fds);
405ad2f8eb0SMartin KaFai Lau 	bpf_link__destroy(link);
406ad2f8eb0SMartin KaFai Lau }
407ad2f8eb0SMartin KaFai Lau 
__simple_estab(bool exprm)408ad2f8eb0SMartin KaFai Lau static void __simple_estab(bool exprm)
409ad2f8eb0SMartin KaFai Lau {
410ad2f8eb0SMartin KaFai Lau 	struct bpf_link *link;
411ad2f8eb0SMartin KaFai Lau 	struct sk_fds sk_fds;
412ad2f8eb0SMartin KaFai Lau 
413ad2f8eb0SMartin KaFai Lau 	hdr_stg_map_fd = bpf_map__fd(skel->maps.hdr_stg_map);
414ad2f8eb0SMartin KaFai Lau 	lport_linum_map_fd = bpf_map__fd(skel->maps.lport_linum_map);
415ad2f8eb0SMartin KaFai Lau 
416ad2f8eb0SMartin KaFai Lau 	exp_passive_estab_in.flags = OPTION_F_RAND | OPTION_F_MAX_DELACK_MS;
417ad2f8eb0SMartin KaFai Lau 	exp_passive_estab_in.rand = 0xfa;
418ad2f8eb0SMartin KaFai Lau 	exp_passive_estab_in.max_delack_ms = 11;
419ad2f8eb0SMartin KaFai Lau 
420ad2f8eb0SMartin KaFai Lau 	exp_active_estab_in.flags = OPTION_F_RAND | OPTION_F_MAX_DELACK_MS;
421ad2f8eb0SMartin KaFai Lau 	exp_active_estab_in.rand = 0xce;
422ad2f8eb0SMartin KaFai Lau 	exp_active_estab_in.max_delack_ms = 22;
423ad2f8eb0SMartin KaFai Lau 
424ad2f8eb0SMartin KaFai Lau 	prepare_out();
425ad2f8eb0SMartin KaFai Lau 
426ad2f8eb0SMartin KaFai Lau 	if (!exprm) {
427ad2f8eb0SMartin KaFai Lau 		skel->data->test_kind = 0xB9;
428ad2f8eb0SMartin KaFai Lau 		skel->data->test_magic = 0;
429ad2f8eb0SMartin KaFai Lau 	}
430ad2f8eb0SMartin KaFai Lau 
431ad2f8eb0SMartin KaFai Lau 	if (write_sysctl("/proc/sys/net/ipv4/tcp_syncookies", "1"))
432ad2f8eb0SMartin KaFai Lau 		return;
433ad2f8eb0SMartin KaFai Lau 
434ad2f8eb0SMartin KaFai Lau 	link = bpf_program__attach_cgroup(skel->progs.estab, cg_fd);
435bad2e478SAndrii Nakryiko 	if (!ASSERT_OK_PTR(link, "attach_cgroup(estab)"))
436ad2f8eb0SMartin KaFai Lau 		return;
437ad2f8eb0SMartin KaFai Lau 
438ad2f8eb0SMartin KaFai Lau 	if (sk_fds_connect(&sk_fds, false)) {
439ad2f8eb0SMartin KaFai Lau 		bpf_link__destroy(link);
440ad2f8eb0SMartin KaFai Lau 		return;
441ad2f8eb0SMartin KaFai Lau 	}
442ad2f8eb0SMartin KaFai Lau 
443ad2f8eb0SMartin KaFai Lau 	check_hdr_and_close_fds(&sk_fds);
444ad2f8eb0SMartin KaFai Lau 	bpf_link__destroy(link);
445ad2f8eb0SMartin KaFai Lau }
446ad2f8eb0SMartin KaFai Lau 
no_exprm_estab(void)447ad2f8eb0SMartin KaFai Lau static void no_exprm_estab(void)
448ad2f8eb0SMartin KaFai Lau {
449ad2f8eb0SMartin KaFai Lau 	__simple_estab(false);
450ad2f8eb0SMartin KaFai Lau }
451ad2f8eb0SMartin KaFai Lau 
simple_estab(void)452ad2f8eb0SMartin KaFai Lau static void simple_estab(void)
453ad2f8eb0SMartin KaFai Lau {
454ad2f8eb0SMartin KaFai Lau 	__simple_estab(true);
455ad2f8eb0SMartin KaFai Lau }
456ad2f8eb0SMartin KaFai Lau 
misc(void)457ad2f8eb0SMartin KaFai Lau static void misc(void)
458ad2f8eb0SMartin KaFai Lau {
459ad2f8eb0SMartin KaFai Lau 	const char send_msg[] = "MISC!!!";
460ad2f8eb0SMartin KaFai Lau 	char recv_msg[sizeof(send_msg)];
461ad2f8eb0SMartin KaFai Lau 	const unsigned int nr_data = 2;
462ad2f8eb0SMartin KaFai Lau 	struct bpf_link *link;
463ad2f8eb0SMartin KaFai Lau 	struct sk_fds sk_fds;
464ad2f8eb0SMartin KaFai Lau 	int i, ret;
465ad2f8eb0SMartin KaFai Lau 
466ad2f8eb0SMartin KaFai Lau 	lport_linum_map_fd = bpf_map__fd(misc_skel->maps.lport_linum_map);
467ad2f8eb0SMartin KaFai Lau 
468ad2f8eb0SMartin KaFai Lau 	if (write_sysctl("/proc/sys/net/ipv4/tcp_syncookies", "1"))
469ad2f8eb0SMartin KaFai Lau 		return;
470ad2f8eb0SMartin KaFai Lau 
471ad2f8eb0SMartin KaFai Lau 	link = bpf_program__attach_cgroup(misc_skel->progs.misc_estab, cg_fd);
472bad2e478SAndrii Nakryiko 	if (!ASSERT_OK_PTR(link, "attach_cgroup(misc_estab)"))
473ad2f8eb0SMartin KaFai Lau 		return;
474ad2f8eb0SMartin KaFai Lau 
475ad2f8eb0SMartin KaFai Lau 	if (sk_fds_connect(&sk_fds, false)) {
476ad2f8eb0SMartin KaFai Lau 		bpf_link__destroy(link);
477ad2f8eb0SMartin KaFai Lau 		return;
478ad2f8eb0SMartin KaFai Lau 	}
479ad2f8eb0SMartin KaFai Lau 
480ad2f8eb0SMartin KaFai Lau 	for (i = 0; i < nr_data; i++) {
481ad2f8eb0SMartin KaFai Lau 		/* MSG_EOR to ensure skb will not be combined */
482ad2f8eb0SMartin KaFai Lau 		ret = send(sk_fds.active_fd, send_msg, sizeof(send_msg),
483ad2f8eb0SMartin KaFai Lau 			   MSG_EOR);
4843082f8cdSWang Yufen 		if (!ASSERT_EQ(ret, sizeof(send_msg), "send(msg)"))
485ad2f8eb0SMartin KaFai Lau 			goto check_linum;
486ad2f8eb0SMartin KaFai Lau 
487ad2f8eb0SMartin KaFai Lau 		ret = read(sk_fds.passive_fd, recv_msg, sizeof(recv_msg));
48852929912SMartin KaFai Lau 		if (!ASSERT_EQ(ret, sizeof(send_msg), "read(msg)"))
489ad2f8eb0SMartin KaFai Lau 			goto check_linum;
490ad2f8eb0SMartin KaFai Lau 	}
491ad2f8eb0SMartin KaFai Lau 
492ad2f8eb0SMartin KaFai Lau 	if (sk_fds_shutdown(&sk_fds))
493ad2f8eb0SMartin KaFai Lau 		goto check_linum;
494ad2f8eb0SMartin KaFai Lau 
4953082f8cdSWang Yufen 	ASSERT_EQ(misc_skel->bss->nr_syn, 1, "unexpected nr_syn");
496ad2f8eb0SMartin KaFai Lau 
4973082f8cdSWang Yufen 	ASSERT_EQ(misc_skel->bss->nr_data, nr_data, "unexpected nr_data");
498ad2f8eb0SMartin KaFai Lau 
499ad2f8eb0SMartin KaFai Lau 	/* The last ACK may have been delayed, so it is either 1 or 2. */
500ad2f8eb0SMartin KaFai Lau 	CHECK(misc_skel->bss->nr_pure_ack != 1 &&
501ad2f8eb0SMartin KaFai Lau 	      misc_skel->bss->nr_pure_ack != 2,
502ad2f8eb0SMartin KaFai Lau 	      "unexpected nr_pure_ack",
503ad2f8eb0SMartin KaFai Lau 	      "expected (1 or 2) != actual (%u)\n",
504ad2f8eb0SMartin KaFai Lau 		misc_skel->bss->nr_pure_ack);
505ad2f8eb0SMartin KaFai Lau 
5063082f8cdSWang Yufen 	ASSERT_EQ(misc_skel->bss->nr_fin, 1, "unexpected nr_fin");
507ad2f8eb0SMartin KaFai Lau 
5088cac7a59SMartin KaFai Lau 	ASSERT_EQ(misc_skel->bss->nr_hwtstamp, 0, "nr_hwtstamp");
5098cac7a59SMartin KaFai Lau 
510ad2f8eb0SMartin KaFai Lau check_linum:
5113082f8cdSWang Yufen 	ASSERT_FALSE(check_error_linum(&sk_fds), "check_error_linum");
512ad2f8eb0SMartin KaFai Lau 	sk_fds_close(&sk_fds);
513ad2f8eb0SMartin KaFai Lau 	bpf_link__destroy(link);
514ad2f8eb0SMartin KaFai Lau }
515ad2f8eb0SMartin KaFai Lau 
516ad2f8eb0SMartin KaFai Lau struct test {
517ad2f8eb0SMartin KaFai Lau 	const char *desc;
518ad2f8eb0SMartin KaFai Lau 	void (*run)(void);
519ad2f8eb0SMartin KaFai Lau };
520ad2f8eb0SMartin KaFai Lau 
521ad2f8eb0SMartin KaFai Lau #define DEF_TEST(name) { #name, name }
522ad2f8eb0SMartin KaFai Lau static struct test tests[] = {
523ad2f8eb0SMartin KaFai Lau 	DEF_TEST(simple_estab),
524ad2f8eb0SMartin KaFai Lau 	DEF_TEST(no_exprm_estab),
525ad2f8eb0SMartin KaFai Lau 	DEF_TEST(syncookie_estab),
526ad2f8eb0SMartin KaFai Lau 	DEF_TEST(fastopen_estab),
527ad2f8eb0SMartin KaFai Lau 	DEF_TEST(fin),
528ad2f8eb0SMartin KaFai Lau 	DEF_TEST(misc),
529ad2f8eb0SMartin KaFai Lau };
530ad2f8eb0SMartin KaFai Lau 
test_tcp_hdr_options(void)531ad2f8eb0SMartin KaFai Lau void test_tcp_hdr_options(void)
532ad2f8eb0SMartin KaFai Lau {
533ad2f8eb0SMartin KaFai Lau 	int i;
534ad2f8eb0SMartin KaFai Lau 
535ad2f8eb0SMartin KaFai Lau 	skel = test_tcp_hdr_options__open_and_load();
5363082f8cdSWang Yufen 	if (!ASSERT_OK_PTR(skel, "open and load skel"))
537ad2f8eb0SMartin KaFai Lau 		return;
538ad2f8eb0SMartin KaFai Lau 
539ad2f8eb0SMartin KaFai Lau 	misc_skel = test_misc_tcp_hdr_options__open_and_load();
5403082f8cdSWang Yufen 	if (!ASSERT_OK_PTR(misc_skel, "open and load misc test skel"))
541ad2f8eb0SMartin KaFai Lau 		goto skel_destroy;
542ad2f8eb0SMartin KaFai Lau 
543ad2f8eb0SMartin KaFai Lau 	cg_fd = test__join_cgroup(CG_NAME);
54452929912SMartin KaFai Lau 	if (!ASSERT_GE(cg_fd, 0, "join_cgroup"))
545ad2f8eb0SMartin KaFai Lau 		goto skel_destroy;
546ad2f8eb0SMartin KaFai Lau 
547ad2f8eb0SMartin KaFai Lau 	for (i = 0; i < ARRAY_SIZE(tests); i++) {
548ad2f8eb0SMartin KaFai Lau 		if (!test__start_subtest(tests[i].desc))
549ad2f8eb0SMartin KaFai Lau 			continue;
550ad2f8eb0SMartin KaFai Lau 
551ad2f8eb0SMartin KaFai Lau 		if (create_netns())
552ad2f8eb0SMartin KaFai Lau 			break;
553ad2f8eb0SMartin KaFai Lau 
554ad2f8eb0SMartin KaFai Lau 		tests[i].run();
555ad2f8eb0SMartin KaFai Lau 
556ad2f8eb0SMartin KaFai Lau 		reset_test();
557ad2f8eb0SMartin KaFai Lau 	}
558ad2f8eb0SMartin KaFai Lau 
559ad2f8eb0SMartin KaFai Lau 	close(cg_fd);
560ad2f8eb0SMartin KaFai Lau skel_destroy:
561ad2f8eb0SMartin KaFai Lau 	test_misc_tcp_hdr_options__destroy(misc_skel);
562ad2f8eb0SMartin KaFai Lau 	test_tcp_hdr_options__destroy(skel);
563ad2f8eb0SMartin KaFai Lau }
564