1*539c7e67SKui-Feng Lee // SPDX-License-Identifier: GPL-2.0
2*539c7e67SKui-Feng Lee /* Copyright (c) 2023 Facebook */
3*539c7e67SKui-Feng Lee #include <test_progs.h>
4*539c7e67SKui-Feng Lee #include <linux/in6.h>
5*539c7e67SKui-Feng Lee #include <sys/socket.h>
6*539c7e67SKui-Feng Lee #include <sched.h>
7*539c7e67SKui-Feng Lee #include <unistd.h>
8*539c7e67SKui-Feng Lee #include "cgroup_helpers.h"
9*539c7e67SKui-Feng Lee #include "testing_helpers.h"
10*539c7e67SKui-Feng Lee #include "cgroup_tcp_skb.skel.h"
11*539c7e67SKui-Feng Lee #include "cgroup_tcp_skb.h"
12*539c7e67SKui-Feng Lee 
13*539c7e67SKui-Feng Lee #define CGROUP_TCP_SKB_PATH "/test_cgroup_tcp_skb"
14*539c7e67SKui-Feng Lee 
15*539c7e67SKui-Feng Lee static int install_filters(int cgroup_fd,
16*539c7e67SKui-Feng Lee 			   struct bpf_link **egress_link,
17*539c7e67SKui-Feng Lee 			   struct bpf_link **ingress_link,
18*539c7e67SKui-Feng Lee 			   struct bpf_program *egress_prog,
19*539c7e67SKui-Feng Lee 			   struct bpf_program *ingress_prog,
20*539c7e67SKui-Feng Lee 			   struct cgroup_tcp_skb *skel)
21*539c7e67SKui-Feng Lee {
22*539c7e67SKui-Feng Lee 	/* Prepare filters */
23*539c7e67SKui-Feng Lee 	skel->bss->g_sock_state = 0;
24*539c7e67SKui-Feng Lee 	skel->bss->g_unexpected = 0;
25*539c7e67SKui-Feng Lee 	*egress_link =
26*539c7e67SKui-Feng Lee 		bpf_program__attach_cgroup(egress_prog,
27*539c7e67SKui-Feng Lee 					   cgroup_fd);
28*539c7e67SKui-Feng Lee 	if (!ASSERT_OK_PTR(egress_link, "egress_link"))
29*539c7e67SKui-Feng Lee 		return -1;
30*539c7e67SKui-Feng Lee 	*ingress_link =
31*539c7e67SKui-Feng Lee 		bpf_program__attach_cgroup(ingress_prog,
32*539c7e67SKui-Feng Lee 					   cgroup_fd);
33*539c7e67SKui-Feng Lee 	if (!ASSERT_OK_PTR(ingress_link, "ingress_link"))
34*539c7e67SKui-Feng Lee 		return -1;
35*539c7e67SKui-Feng Lee 
36*539c7e67SKui-Feng Lee 	return 0;
37*539c7e67SKui-Feng Lee }
38*539c7e67SKui-Feng Lee 
39*539c7e67SKui-Feng Lee static void uninstall_filters(struct bpf_link **egress_link,
40*539c7e67SKui-Feng Lee 			      struct bpf_link **ingress_link)
41*539c7e67SKui-Feng Lee {
42*539c7e67SKui-Feng Lee 	bpf_link__destroy(*egress_link);
43*539c7e67SKui-Feng Lee 	*egress_link = NULL;
44*539c7e67SKui-Feng Lee 	bpf_link__destroy(*ingress_link);
45*539c7e67SKui-Feng Lee 	*ingress_link = NULL;
46*539c7e67SKui-Feng Lee }
47*539c7e67SKui-Feng Lee 
48*539c7e67SKui-Feng Lee static int create_client_sock_v6(void)
49*539c7e67SKui-Feng Lee {
50*539c7e67SKui-Feng Lee 	int fd;
51*539c7e67SKui-Feng Lee 
52*539c7e67SKui-Feng Lee 	fd = socket(AF_INET6, SOCK_STREAM, 0);
53*539c7e67SKui-Feng Lee 	if (fd < 0) {
54*539c7e67SKui-Feng Lee 		perror("socket");
55*539c7e67SKui-Feng Lee 		return -1;
56*539c7e67SKui-Feng Lee 	}
57*539c7e67SKui-Feng Lee 
58*539c7e67SKui-Feng Lee 	return fd;
59*539c7e67SKui-Feng Lee }
60*539c7e67SKui-Feng Lee 
61*539c7e67SKui-Feng Lee static int create_server_sock_v6(void)
62*539c7e67SKui-Feng Lee {
63*539c7e67SKui-Feng Lee 	struct sockaddr_in6 addr = {
64*539c7e67SKui-Feng Lee 		.sin6_family = AF_INET6,
65*539c7e67SKui-Feng Lee 		.sin6_port = htons(0),
66*539c7e67SKui-Feng Lee 		.sin6_addr = IN6ADDR_LOOPBACK_INIT,
67*539c7e67SKui-Feng Lee 	};
68*539c7e67SKui-Feng Lee 	int fd, err;
69*539c7e67SKui-Feng Lee 
70*539c7e67SKui-Feng Lee 	fd = socket(AF_INET6, SOCK_STREAM, 0);
71*539c7e67SKui-Feng Lee 	if (fd < 0) {
72*539c7e67SKui-Feng Lee 		perror("socket");
73*539c7e67SKui-Feng Lee 		return -1;
74*539c7e67SKui-Feng Lee 	}
75*539c7e67SKui-Feng Lee 
76*539c7e67SKui-Feng Lee 	err = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
77*539c7e67SKui-Feng Lee 	if (err < 0) {
78*539c7e67SKui-Feng Lee 		perror("bind");
79*539c7e67SKui-Feng Lee 		return -1;
80*539c7e67SKui-Feng Lee 	}
81*539c7e67SKui-Feng Lee 
82*539c7e67SKui-Feng Lee 	err = listen(fd, 1);
83*539c7e67SKui-Feng Lee 	if (err < 0) {
84*539c7e67SKui-Feng Lee 		perror("listen");
85*539c7e67SKui-Feng Lee 		return -1;
86*539c7e67SKui-Feng Lee 	}
87*539c7e67SKui-Feng Lee 
88*539c7e67SKui-Feng Lee 	return fd;
89*539c7e67SKui-Feng Lee }
90*539c7e67SKui-Feng Lee 
91*539c7e67SKui-Feng Lee static int get_sock_port_v6(int fd)
92*539c7e67SKui-Feng Lee {
93*539c7e67SKui-Feng Lee 	struct sockaddr_in6 addr;
94*539c7e67SKui-Feng Lee 	socklen_t len;
95*539c7e67SKui-Feng Lee 	int err;
96*539c7e67SKui-Feng Lee 
97*539c7e67SKui-Feng Lee 	len = sizeof(addr);
98*539c7e67SKui-Feng Lee 	err = getsockname(fd, (struct sockaddr *)&addr, &len);
99*539c7e67SKui-Feng Lee 	if (err < 0) {
100*539c7e67SKui-Feng Lee 		perror("getsockname");
101*539c7e67SKui-Feng Lee 		return -1;
102*539c7e67SKui-Feng Lee 	}
103*539c7e67SKui-Feng Lee 
104*539c7e67SKui-Feng Lee 	return ntohs(addr.sin6_port);
105*539c7e67SKui-Feng Lee }
106*539c7e67SKui-Feng Lee 
107*539c7e67SKui-Feng Lee static int connect_client_server_v6(int client_fd, int listen_fd)
108*539c7e67SKui-Feng Lee {
109*539c7e67SKui-Feng Lee 	struct sockaddr_in6 addr = {
110*539c7e67SKui-Feng Lee 		.sin6_family = AF_INET6,
111*539c7e67SKui-Feng Lee 		.sin6_addr = IN6ADDR_LOOPBACK_INIT,
112*539c7e67SKui-Feng Lee 	};
113*539c7e67SKui-Feng Lee 	int err;
114*539c7e67SKui-Feng Lee 
115*539c7e67SKui-Feng Lee 	addr.sin6_port = htons(get_sock_port_v6(listen_fd));
116*539c7e67SKui-Feng Lee 	if (addr.sin6_port < 0)
117*539c7e67SKui-Feng Lee 		return -1;
118*539c7e67SKui-Feng Lee 
119*539c7e67SKui-Feng Lee 	err = connect(client_fd, (struct sockaddr *)&addr, sizeof(addr));
120*539c7e67SKui-Feng Lee 	if (err < 0) {
121*539c7e67SKui-Feng Lee 		perror("connect");
122*539c7e67SKui-Feng Lee 		return -1;
123*539c7e67SKui-Feng Lee 	}
124*539c7e67SKui-Feng Lee 
125*539c7e67SKui-Feng Lee 	return 0;
126*539c7e67SKui-Feng Lee }
127*539c7e67SKui-Feng Lee 
128*539c7e67SKui-Feng Lee /* Connect to the server in a cgroup from the outside of the cgroup. */
129*539c7e67SKui-Feng Lee static int talk_to_cgroup(int *client_fd, int *listen_fd, int *service_fd,
130*539c7e67SKui-Feng Lee 			  struct cgroup_tcp_skb *skel)
131*539c7e67SKui-Feng Lee {
132*539c7e67SKui-Feng Lee 	int err, cp;
133*539c7e67SKui-Feng Lee 	char buf[5];
134*539c7e67SKui-Feng Lee 
135*539c7e67SKui-Feng Lee 	/* Create client & server socket */
136*539c7e67SKui-Feng Lee 	err = join_root_cgroup();
137*539c7e67SKui-Feng Lee 	if (!ASSERT_OK(err, "join_root_cgroup"))
138*539c7e67SKui-Feng Lee 		return -1;
139*539c7e67SKui-Feng Lee 	*client_fd = create_client_sock_v6();
140*539c7e67SKui-Feng Lee 	if (!ASSERT_GE(*client_fd, 0, "client_fd"))
141*539c7e67SKui-Feng Lee 		return -1;
142*539c7e67SKui-Feng Lee 	err = join_cgroup(CGROUP_TCP_SKB_PATH);
143*539c7e67SKui-Feng Lee 	if (!ASSERT_OK(err, "join_cgroup"))
144*539c7e67SKui-Feng Lee 		return -1;
145*539c7e67SKui-Feng Lee 	*listen_fd = create_server_sock_v6();
146*539c7e67SKui-Feng Lee 	if (!ASSERT_GE(*listen_fd, 0, "listen_fd"))
147*539c7e67SKui-Feng Lee 		return -1;
148*539c7e67SKui-Feng Lee 	skel->bss->g_sock_port = get_sock_port_v6(*listen_fd);
149*539c7e67SKui-Feng Lee 
150*539c7e67SKui-Feng Lee 	/* Connect client to server */
151*539c7e67SKui-Feng Lee 	err = connect_client_server_v6(*client_fd, *listen_fd);
152*539c7e67SKui-Feng Lee 	if (!ASSERT_OK(err, "connect_client_server_v6"))
153*539c7e67SKui-Feng Lee 		return -1;
154*539c7e67SKui-Feng Lee 	*service_fd = accept(*listen_fd, NULL, NULL);
155*539c7e67SKui-Feng Lee 	if (!ASSERT_GE(*service_fd, 0, "service_fd"))
156*539c7e67SKui-Feng Lee 		return -1;
157*539c7e67SKui-Feng Lee 	err = join_root_cgroup();
158*539c7e67SKui-Feng Lee 	if (!ASSERT_OK(err, "join_root_cgroup"))
159*539c7e67SKui-Feng Lee 		return -1;
160*539c7e67SKui-Feng Lee 	cp = write(*client_fd, "hello", 5);
161*539c7e67SKui-Feng Lee 	if (!ASSERT_EQ(cp, 5, "write"))
162*539c7e67SKui-Feng Lee 		return -1;
163*539c7e67SKui-Feng Lee 	cp = read(*service_fd, buf, 5);
164*539c7e67SKui-Feng Lee 	if (!ASSERT_EQ(cp, 5, "read"))
165*539c7e67SKui-Feng Lee 		return -1;
166*539c7e67SKui-Feng Lee 
167*539c7e67SKui-Feng Lee 	return 0;
168*539c7e67SKui-Feng Lee }
169*539c7e67SKui-Feng Lee 
170*539c7e67SKui-Feng Lee /* Connect to the server out of a cgroup from inside the cgroup. */
171*539c7e67SKui-Feng Lee static int talk_to_outside(int *client_fd, int *listen_fd, int *service_fd,
172*539c7e67SKui-Feng Lee 			   struct cgroup_tcp_skb *skel)
173*539c7e67SKui-Feng Lee 
174*539c7e67SKui-Feng Lee {
175*539c7e67SKui-Feng Lee 	int err, cp;
176*539c7e67SKui-Feng Lee 	char buf[5];
177*539c7e67SKui-Feng Lee 
178*539c7e67SKui-Feng Lee 	/* Create client & server socket */
179*539c7e67SKui-Feng Lee 	err = join_root_cgroup();
180*539c7e67SKui-Feng Lee 	if (!ASSERT_OK(err, "join_root_cgroup"))
181*539c7e67SKui-Feng Lee 		return -1;
182*539c7e67SKui-Feng Lee 	*listen_fd = create_server_sock_v6();
183*539c7e67SKui-Feng Lee 	if (!ASSERT_GE(*listen_fd, 0, "listen_fd"))
184*539c7e67SKui-Feng Lee 		return -1;
185*539c7e67SKui-Feng Lee 	err = join_cgroup(CGROUP_TCP_SKB_PATH);
186*539c7e67SKui-Feng Lee 	if (!ASSERT_OK(err, "join_cgroup"))
187*539c7e67SKui-Feng Lee 		return -1;
188*539c7e67SKui-Feng Lee 	*client_fd = create_client_sock_v6();
189*539c7e67SKui-Feng Lee 	if (!ASSERT_GE(*client_fd, 0, "client_fd"))
190*539c7e67SKui-Feng Lee 		return -1;
191*539c7e67SKui-Feng Lee 	err = join_root_cgroup();
192*539c7e67SKui-Feng Lee 	if (!ASSERT_OK(err, "join_root_cgroup"))
193*539c7e67SKui-Feng Lee 		return -1;
194*539c7e67SKui-Feng Lee 	skel->bss->g_sock_port = get_sock_port_v6(*listen_fd);
195*539c7e67SKui-Feng Lee 
196*539c7e67SKui-Feng Lee 	/* Connect client to server */
197*539c7e67SKui-Feng Lee 	err = connect_client_server_v6(*client_fd, *listen_fd);
198*539c7e67SKui-Feng Lee 	if (!ASSERT_OK(err, "connect_client_server_v6"))
199*539c7e67SKui-Feng Lee 		return -1;
200*539c7e67SKui-Feng Lee 	*service_fd = accept(*listen_fd, NULL, NULL);
201*539c7e67SKui-Feng Lee 	if (!ASSERT_GE(*service_fd, 0, "service_fd"))
202*539c7e67SKui-Feng Lee 		return -1;
203*539c7e67SKui-Feng Lee 	cp = write(*client_fd, "hello", 5);
204*539c7e67SKui-Feng Lee 	if (!ASSERT_EQ(cp, 5, "write"))
205*539c7e67SKui-Feng Lee 		return -1;
206*539c7e67SKui-Feng Lee 	cp = read(*service_fd, buf, 5);
207*539c7e67SKui-Feng Lee 	if (!ASSERT_EQ(cp, 5, "read"))
208*539c7e67SKui-Feng Lee 		return -1;
209*539c7e67SKui-Feng Lee 
210*539c7e67SKui-Feng Lee 	return 0;
211*539c7e67SKui-Feng Lee }
212*539c7e67SKui-Feng Lee 
213*539c7e67SKui-Feng Lee static int close_connection(int *closing_fd, int *peer_fd, int *listen_fd,
214*539c7e67SKui-Feng Lee 			    struct cgroup_tcp_skb *skel)
215*539c7e67SKui-Feng Lee {
216*539c7e67SKui-Feng Lee 	__u32 saved_packet_count = 0;
217*539c7e67SKui-Feng Lee 	int err;
218*539c7e67SKui-Feng Lee 	int i;
219*539c7e67SKui-Feng Lee 
220*539c7e67SKui-Feng Lee 	/* Wait for ACKs to be sent */
221*539c7e67SKui-Feng Lee 	saved_packet_count = skel->bss->g_packet_count;
222*539c7e67SKui-Feng Lee 	usleep(100000);		/* 0.1s */
223*539c7e67SKui-Feng Lee 	for (i = 0;
224*539c7e67SKui-Feng Lee 	     skel->bss->g_packet_count != saved_packet_count && i < 10;
225*539c7e67SKui-Feng Lee 	     i++) {
226*539c7e67SKui-Feng Lee 		saved_packet_count = skel->bss->g_packet_count;
227*539c7e67SKui-Feng Lee 		usleep(100000);	/* 0.1s */
228*539c7e67SKui-Feng Lee 	}
229*539c7e67SKui-Feng Lee 	if (!ASSERT_EQ(skel->bss->g_packet_count, saved_packet_count,
230*539c7e67SKui-Feng Lee 		       "packet_count"))
231*539c7e67SKui-Feng Lee 		return -1;
232*539c7e67SKui-Feng Lee 
233*539c7e67SKui-Feng Lee 	skel->bss->g_packet_count = 0;
234*539c7e67SKui-Feng Lee 	saved_packet_count = 0;
235*539c7e67SKui-Feng Lee 
236*539c7e67SKui-Feng Lee 	/* Half shutdown to make sure the closing socket having a chance to
237*539c7e67SKui-Feng Lee 	 * receive a FIN from the peer.
238*539c7e67SKui-Feng Lee 	 */
239*539c7e67SKui-Feng Lee 	err = shutdown(*closing_fd, SHUT_WR);
240*539c7e67SKui-Feng Lee 	if (!ASSERT_OK(err, "shutdown closing_fd"))
241*539c7e67SKui-Feng Lee 		return -1;
242*539c7e67SKui-Feng Lee 
243*539c7e67SKui-Feng Lee 	/* Wait for FIN and the ACK of the FIN to be observed */
244*539c7e67SKui-Feng Lee 	for (i = 0;
245*539c7e67SKui-Feng Lee 	     skel->bss->g_packet_count < saved_packet_count + 2 && i < 10;
246*539c7e67SKui-Feng Lee 	     i++)
247*539c7e67SKui-Feng Lee 		usleep(100000);	/* 0.1s */
248*539c7e67SKui-Feng Lee 	if (!ASSERT_GE(skel->bss->g_packet_count, saved_packet_count + 2,
249*539c7e67SKui-Feng Lee 		       "packet_count"))
250*539c7e67SKui-Feng Lee 		return -1;
251*539c7e67SKui-Feng Lee 
252*539c7e67SKui-Feng Lee 	saved_packet_count = skel->bss->g_packet_count;
253*539c7e67SKui-Feng Lee 
254*539c7e67SKui-Feng Lee 	/* Fully shutdown the connection */
255*539c7e67SKui-Feng Lee 	err = close(*peer_fd);
256*539c7e67SKui-Feng Lee 	if (!ASSERT_OK(err, "close peer_fd"))
257*539c7e67SKui-Feng Lee 		return -1;
258*539c7e67SKui-Feng Lee 	*peer_fd = -1;
259*539c7e67SKui-Feng Lee 
260*539c7e67SKui-Feng Lee 	/* Wait for FIN and the ACK of the FIN to be observed */
261*539c7e67SKui-Feng Lee 	for (i = 0;
262*539c7e67SKui-Feng Lee 	     skel->bss->g_packet_count < saved_packet_count + 2 && i < 10;
263*539c7e67SKui-Feng Lee 	     i++)
264*539c7e67SKui-Feng Lee 		usleep(100000);	/* 0.1s */
265*539c7e67SKui-Feng Lee 	if (!ASSERT_GE(skel->bss->g_packet_count, saved_packet_count + 2,
266*539c7e67SKui-Feng Lee 		       "packet_count"))
267*539c7e67SKui-Feng Lee 		return -1;
268*539c7e67SKui-Feng Lee 
269*539c7e67SKui-Feng Lee 	err = close(*closing_fd);
270*539c7e67SKui-Feng Lee 	if (!ASSERT_OK(err, "close closing_fd"))
271*539c7e67SKui-Feng Lee 		return -1;
272*539c7e67SKui-Feng Lee 	*closing_fd = -1;
273*539c7e67SKui-Feng Lee 
274*539c7e67SKui-Feng Lee 	close(*listen_fd);
275*539c7e67SKui-Feng Lee 	*listen_fd = -1;
276*539c7e67SKui-Feng Lee 
277*539c7e67SKui-Feng Lee 	return 0;
278*539c7e67SKui-Feng Lee }
279*539c7e67SKui-Feng Lee 
280*539c7e67SKui-Feng Lee /* This test case includes four scenarios:
281*539c7e67SKui-Feng Lee  * 1. Connect to the server from outside the cgroup and close the connection
282*539c7e67SKui-Feng Lee  *    from outside the cgroup.
283*539c7e67SKui-Feng Lee  * 2. Connect to the server from outside the cgroup and close the connection
284*539c7e67SKui-Feng Lee  *    from inside the cgroup.
285*539c7e67SKui-Feng Lee  * 3. Connect to the server from inside the cgroup and close the connection
286*539c7e67SKui-Feng Lee  *    from outside the cgroup.
287*539c7e67SKui-Feng Lee  * 4. Connect to the server from inside the cgroup and close the connection
288*539c7e67SKui-Feng Lee  *    from inside the cgroup.
289*539c7e67SKui-Feng Lee  *
290*539c7e67SKui-Feng Lee  * The test case is to verify that cgroup_skb/{egress,ingress} filters
291*539c7e67SKui-Feng Lee  * receive expected packets including SYN, SYN/ACK, ACK, FIN, and FIN/ACK.
292*539c7e67SKui-Feng Lee  */
293*539c7e67SKui-Feng Lee void test_cgroup_tcp_skb(void)
294*539c7e67SKui-Feng Lee {
295*539c7e67SKui-Feng Lee 	struct bpf_link *ingress_link = NULL;
296*539c7e67SKui-Feng Lee 	struct bpf_link *egress_link = NULL;
297*539c7e67SKui-Feng Lee 	int client_fd = -1, listen_fd = -1;
298*539c7e67SKui-Feng Lee 	struct cgroup_tcp_skb *skel;
299*539c7e67SKui-Feng Lee 	int service_fd = -1;
300*539c7e67SKui-Feng Lee 	int cgroup_fd = -1;
301*539c7e67SKui-Feng Lee 	int err;
302*539c7e67SKui-Feng Lee 
303*539c7e67SKui-Feng Lee 	skel = cgroup_tcp_skb__open_and_load();
304*539c7e67SKui-Feng Lee 	if (!ASSERT_OK(!skel, "skel_open_load"))
305*539c7e67SKui-Feng Lee 		return;
306*539c7e67SKui-Feng Lee 
307*539c7e67SKui-Feng Lee 	err = setup_cgroup_environment();
308*539c7e67SKui-Feng Lee 	if (!ASSERT_OK(err, "setup_cgroup_environment"))
309*539c7e67SKui-Feng Lee 		goto cleanup;
310*539c7e67SKui-Feng Lee 
311*539c7e67SKui-Feng Lee 	cgroup_fd = create_and_get_cgroup(CGROUP_TCP_SKB_PATH);
312*539c7e67SKui-Feng Lee 	if (!ASSERT_GE(cgroup_fd, 0, "cgroup_fd"))
313*539c7e67SKui-Feng Lee 		goto cleanup;
314*539c7e67SKui-Feng Lee 
315*539c7e67SKui-Feng Lee 	/* Scenario 1 */
316*539c7e67SKui-Feng Lee 	err = install_filters(cgroup_fd, &egress_link, &ingress_link,
317*539c7e67SKui-Feng Lee 			      skel->progs.server_egress,
318*539c7e67SKui-Feng Lee 			      skel->progs.server_ingress,
319*539c7e67SKui-Feng Lee 			      skel);
320*539c7e67SKui-Feng Lee 	if (!ASSERT_OK(err, "install_filters"))
321*539c7e67SKui-Feng Lee 		goto cleanup;
322*539c7e67SKui-Feng Lee 
323*539c7e67SKui-Feng Lee 	err = talk_to_cgroup(&client_fd, &listen_fd, &service_fd, skel);
324*539c7e67SKui-Feng Lee 	if (!ASSERT_OK(err, "talk_to_cgroup"))
325*539c7e67SKui-Feng Lee 		goto cleanup;
326*539c7e67SKui-Feng Lee 
327*539c7e67SKui-Feng Lee 	err = close_connection(&client_fd, &service_fd, &listen_fd, skel);
328*539c7e67SKui-Feng Lee 	if (!ASSERT_OK(err, "close_connection"))
329*539c7e67SKui-Feng Lee 		goto cleanup;
330*539c7e67SKui-Feng Lee 
331*539c7e67SKui-Feng Lee 	ASSERT_EQ(skel->bss->g_unexpected, 0, "g_unexpected");
332*539c7e67SKui-Feng Lee 	ASSERT_EQ(skel->bss->g_sock_state, CLOSED, "g_sock_state");
333*539c7e67SKui-Feng Lee 
334*539c7e67SKui-Feng Lee 	uninstall_filters(&egress_link, &ingress_link);
335*539c7e67SKui-Feng Lee 
336*539c7e67SKui-Feng Lee 	/* Scenario 2 */
337*539c7e67SKui-Feng Lee 	err = install_filters(cgroup_fd, &egress_link, &ingress_link,
338*539c7e67SKui-Feng Lee 			      skel->progs.server_egress_srv,
339*539c7e67SKui-Feng Lee 			      skel->progs.server_ingress_srv,
340*539c7e67SKui-Feng Lee 			      skel);
341*539c7e67SKui-Feng Lee 
342*539c7e67SKui-Feng Lee 	err = talk_to_cgroup(&client_fd, &listen_fd, &service_fd, skel);
343*539c7e67SKui-Feng Lee 	if (!ASSERT_OK(err, "talk_to_cgroup"))
344*539c7e67SKui-Feng Lee 		goto cleanup;
345*539c7e67SKui-Feng Lee 
346*539c7e67SKui-Feng Lee 	err = close_connection(&service_fd, &client_fd, &listen_fd, skel);
347*539c7e67SKui-Feng Lee 	if (!ASSERT_OK(err, "close_connection"))
348*539c7e67SKui-Feng Lee 		goto cleanup;
349*539c7e67SKui-Feng Lee 
350*539c7e67SKui-Feng Lee 	ASSERT_EQ(skel->bss->g_unexpected, 0, "g_unexpected");
351*539c7e67SKui-Feng Lee 	ASSERT_EQ(skel->bss->g_sock_state, TIME_WAIT, "g_sock_state");
352*539c7e67SKui-Feng Lee 
353*539c7e67SKui-Feng Lee 	uninstall_filters(&egress_link, &ingress_link);
354*539c7e67SKui-Feng Lee 
355*539c7e67SKui-Feng Lee 	/* Scenario 3 */
356*539c7e67SKui-Feng Lee 	err = install_filters(cgroup_fd, &egress_link, &ingress_link,
357*539c7e67SKui-Feng Lee 			      skel->progs.client_egress_srv,
358*539c7e67SKui-Feng Lee 			      skel->progs.client_ingress_srv,
359*539c7e67SKui-Feng Lee 			      skel);
360*539c7e67SKui-Feng Lee 
361*539c7e67SKui-Feng Lee 	err = talk_to_outside(&client_fd, &listen_fd, &service_fd, skel);
362*539c7e67SKui-Feng Lee 	if (!ASSERT_OK(err, "talk_to_outside"))
363*539c7e67SKui-Feng Lee 		goto cleanup;
364*539c7e67SKui-Feng Lee 
365*539c7e67SKui-Feng Lee 	err = close_connection(&service_fd, &client_fd, &listen_fd, skel);
366*539c7e67SKui-Feng Lee 	if (!ASSERT_OK(err, "close_connection"))
367*539c7e67SKui-Feng Lee 		goto cleanup;
368*539c7e67SKui-Feng Lee 
369*539c7e67SKui-Feng Lee 	ASSERT_EQ(skel->bss->g_unexpected, 0, "g_unexpected");
370*539c7e67SKui-Feng Lee 	ASSERT_EQ(skel->bss->g_sock_state, CLOSED, "g_sock_state");
371*539c7e67SKui-Feng Lee 
372*539c7e67SKui-Feng Lee 	uninstall_filters(&egress_link, &ingress_link);
373*539c7e67SKui-Feng Lee 
374*539c7e67SKui-Feng Lee 	/* Scenario 4 */
375*539c7e67SKui-Feng Lee 	err = install_filters(cgroup_fd, &egress_link, &ingress_link,
376*539c7e67SKui-Feng Lee 			      skel->progs.client_egress,
377*539c7e67SKui-Feng Lee 			      skel->progs.client_ingress,
378*539c7e67SKui-Feng Lee 			      skel);
379*539c7e67SKui-Feng Lee 
380*539c7e67SKui-Feng Lee 	err = talk_to_outside(&client_fd, &listen_fd, &service_fd, skel);
381*539c7e67SKui-Feng Lee 	if (!ASSERT_OK(err, "talk_to_outside"))
382*539c7e67SKui-Feng Lee 		goto cleanup;
383*539c7e67SKui-Feng Lee 
384*539c7e67SKui-Feng Lee 	err = close_connection(&client_fd, &service_fd, &listen_fd, skel);
385*539c7e67SKui-Feng Lee 	if (!ASSERT_OK(err, "close_connection"))
386*539c7e67SKui-Feng Lee 		goto cleanup;
387*539c7e67SKui-Feng Lee 
388*539c7e67SKui-Feng Lee 	ASSERT_EQ(skel->bss->g_unexpected, 0, "g_unexpected");
389*539c7e67SKui-Feng Lee 	ASSERT_EQ(skel->bss->g_sock_state, TIME_WAIT, "g_sock_state");
390*539c7e67SKui-Feng Lee 
391*539c7e67SKui-Feng Lee 	uninstall_filters(&egress_link, &ingress_link);
392*539c7e67SKui-Feng Lee 
393*539c7e67SKui-Feng Lee cleanup:
394*539c7e67SKui-Feng Lee 	close(client_fd);
395*539c7e67SKui-Feng Lee 	close(listen_fd);
396*539c7e67SKui-Feng Lee 	close(service_fd);
397*539c7e67SKui-Feng Lee 	close(cgroup_fd);
398*539c7e67SKui-Feng Lee 	bpf_link__destroy(egress_link);
399*539c7e67SKui-Feng Lee 	bpf_link__destroy(ingress_link);
400*539c7e67SKui-Feng Lee 	cleanup_cgroup_environment();
401*539c7e67SKui-Feng Lee 	cgroup_tcp_skb__destroy(skel);
402*539c7e67SKui-Feng Lee }
403