brintos

brintos / linux-shallow public Read only

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