xref: /openbmc/linux/tools/testing/selftests/bpf/prog_tests/tcp_rtt.c (revision 34d6f206a88c2651d216bd3487ac956a40b2ba8e)
11f4f80feSStanislav Fomichev // SPDX-License-Identifier: GPL-2.0
2*227b50feSTony Ambardar #define _GNU_SOURCE
31f4f80feSStanislav Fomichev #include <test_progs.h>
41f4f80feSStanislav Fomichev #include "cgroup_helpers.h"
533181bb8SStanislav Fomichev #include "network_helpers.h"
6186d1a86SAndrii Nakryiko #include "tcp_rtt.skel.h"
71f4f80feSStanislav Fomichev 
81f4f80feSStanislav Fomichev struct tcp_rtt_storage {
91f4f80feSStanislav Fomichev 	__u32 invoked;
101f4f80feSStanislav Fomichev 	__u32 dsack_dups;
111f4f80feSStanislav Fomichev 	__u32 delivered;
121f4f80feSStanislav Fomichev 	__u32 delivered_ce;
131f4f80feSStanislav Fomichev 	__u32 icsk_retransmits;
141f4f80feSStanislav Fomichev };
151f4f80feSStanislav Fomichev 
send_byte(int fd)161f4f80feSStanislav Fomichev static void send_byte(int fd)
171f4f80feSStanislav Fomichev {
181f4f80feSStanislav Fomichev 	char b = 0x55;
191f4f80feSStanislav Fomichev 
208dda32acSWang Yufen 	ASSERT_EQ(write(fd, &b, sizeof(b)), 1, "send single byte");
211f4f80feSStanislav Fomichev }
221f4f80feSStanislav Fomichev 
wait_for_ack(int fd,int retries)231f4f80feSStanislav Fomichev static int wait_for_ack(int fd, int retries)
241f4f80feSStanislav Fomichev {
251f4f80feSStanislav Fomichev 	struct tcp_info info;
261f4f80feSStanislav Fomichev 	socklen_t optlen;
271f4f80feSStanislav Fomichev 	int i, err;
281f4f80feSStanislav Fomichev 
291f4f80feSStanislav Fomichev 	for (i = 0; i < retries; i++) {
301f4f80feSStanislav Fomichev 		optlen = sizeof(info);
311f4f80feSStanislav Fomichev 		err = getsockopt(fd, SOL_TCP, TCP_INFO, &info, &optlen);
321f4f80feSStanislav Fomichev 		if (err < 0) {
331f4f80feSStanislav Fomichev 			log_err("Failed to lookup TCP stats");
341f4f80feSStanislav Fomichev 			return err;
351f4f80feSStanislav Fomichev 		}
361f4f80feSStanislav Fomichev 
371f4f80feSStanislav Fomichev 		if (info.tcpi_unacked == 0)
381f4f80feSStanislav Fomichev 			return 0;
391f4f80feSStanislav Fomichev 
401f4f80feSStanislav Fomichev 		usleep(10);
411f4f80feSStanislav Fomichev 	}
421f4f80feSStanislav Fomichev 
431f4f80feSStanislav Fomichev 	log_err("Did not receive ACK");
441f4f80feSStanislav Fomichev 	return -1;
451f4f80feSStanislav Fomichev }
461f4f80feSStanislav Fomichev 
verify_sk(int map_fd,int client_fd,const char * msg,__u32 invoked,__u32 dsack_dups,__u32 delivered,__u32 delivered_ce,__u32 icsk_retransmits)471f4f80feSStanislav Fomichev static int verify_sk(int map_fd, int client_fd, const char *msg, __u32 invoked,
481f4f80feSStanislav Fomichev 		     __u32 dsack_dups, __u32 delivered, __u32 delivered_ce,
491f4f80feSStanislav Fomichev 		     __u32 icsk_retransmits)
501f4f80feSStanislav Fomichev {
511f4f80feSStanislav Fomichev 	int err = 0;
521f4f80feSStanislav Fomichev 	struct tcp_rtt_storage val;
531f4f80feSStanislav Fomichev 
548dda32acSWang Yufen 	if (!ASSERT_GE(bpf_map_lookup_elem(map_fd, &client_fd, &val), 0, "read socket storage"))
551f4f80feSStanislav Fomichev 		return -1;
561f4f80feSStanislav Fomichev 
571f4f80feSStanislav Fomichev 	if (val.invoked != invoked) {
581f4f80feSStanislav Fomichev 		log_err("%s: unexpected bpf_tcp_sock.invoked %d != %d",
591f4f80feSStanislav Fomichev 			msg, val.invoked, invoked);
601f4f80feSStanislav Fomichev 		err++;
611f4f80feSStanislav Fomichev 	}
621f4f80feSStanislav Fomichev 
631f4f80feSStanislav Fomichev 	if (val.dsack_dups != dsack_dups) {
641f4f80feSStanislav Fomichev 		log_err("%s: unexpected bpf_tcp_sock.dsack_dups %d != %d",
651f4f80feSStanislav Fomichev 			msg, val.dsack_dups, dsack_dups);
661f4f80feSStanislav Fomichev 		err++;
671f4f80feSStanislav Fomichev 	}
681f4f80feSStanislav Fomichev 
691f4f80feSStanislav Fomichev 	if (val.delivered != delivered) {
701f4f80feSStanislav Fomichev 		log_err("%s: unexpected bpf_tcp_sock.delivered %d != %d",
711f4f80feSStanislav Fomichev 			msg, val.delivered, delivered);
721f4f80feSStanislav Fomichev 		err++;
731f4f80feSStanislav Fomichev 	}
741f4f80feSStanislav Fomichev 
751f4f80feSStanislav Fomichev 	if (val.delivered_ce != delivered_ce) {
761f4f80feSStanislav Fomichev 		log_err("%s: unexpected bpf_tcp_sock.delivered_ce %d != %d",
771f4f80feSStanislav Fomichev 			msg, val.delivered_ce, delivered_ce);
781f4f80feSStanislav Fomichev 		err++;
791f4f80feSStanislav Fomichev 	}
801f4f80feSStanislav Fomichev 
811f4f80feSStanislav Fomichev 	if (val.icsk_retransmits != icsk_retransmits) {
821f4f80feSStanislav Fomichev 		log_err("%s: unexpected bpf_tcp_sock.icsk_retransmits %d != %d",
831f4f80feSStanislav Fomichev 			msg, val.icsk_retransmits, icsk_retransmits);
841f4f80feSStanislav Fomichev 		err++;
851f4f80feSStanislav Fomichev 	}
861f4f80feSStanislav Fomichev 
871f4f80feSStanislav Fomichev 	return err;
881f4f80feSStanislav Fomichev }
891f4f80feSStanislav Fomichev 
901f4f80feSStanislav Fomichev 
run_test(int cgroup_fd,int server_fd)911f4f80feSStanislav Fomichev static int run_test(int cgroup_fd, int server_fd)
921f4f80feSStanislav Fomichev {
93186d1a86SAndrii Nakryiko 	struct tcp_rtt *skel;
941f4f80feSStanislav Fomichev 	int client_fd;
951f4f80feSStanislav Fomichev 	int prog_fd;
961f4f80feSStanislav Fomichev 	int map_fd;
971f4f80feSStanislav Fomichev 	int err;
981f4f80feSStanislav Fomichev 
99186d1a86SAndrii Nakryiko 	skel = tcp_rtt__open_and_load();
100186d1a86SAndrii Nakryiko 	if (!ASSERT_OK_PTR(skel, "skel_open_load"))
1011f4f80feSStanislav Fomichev 		return -1;
1021f4f80feSStanislav Fomichev 
103186d1a86SAndrii Nakryiko 	map_fd = bpf_map__fd(skel->maps.socket_storage_map);
104186d1a86SAndrii Nakryiko 	prog_fd = bpf_program__fd(skel->progs._sockops);
1051f4f80feSStanislav Fomichev 
1061f4f80feSStanislav Fomichev 	err = bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_SOCK_OPS, 0);
1071f4f80feSStanislav Fomichev 	if (err) {
1081f4f80feSStanislav Fomichev 		log_err("Failed to attach BPF program");
1091f4f80feSStanislav Fomichev 		goto close_bpf_object;
1101f4f80feSStanislav Fomichev 	}
1111f4f80feSStanislav Fomichev 
11299126abeSMartin KaFai Lau 	client_fd = connect_to_fd(server_fd, 0);
1131f4f80feSStanislav Fomichev 	if (client_fd < 0) {
1141f4f80feSStanislav Fomichev 		err = -1;
1151f4f80feSStanislav Fomichev 		goto close_bpf_object;
1161f4f80feSStanislav Fomichev 	}
1171f4f80feSStanislav Fomichev 
1181f4f80feSStanislav Fomichev 	err += verify_sk(map_fd, client_fd, "syn-ack",
1191f4f80feSStanislav Fomichev 			 /*invoked=*/1,
1201f4f80feSStanislav Fomichev 			 /*dsack_dups=*/0,
1211f4f80feSStanislav Fomichev 			 /*delivered=*/1,
1221f4f80feSStanislav Fomichev 			 /*delivered_ce=*/0,
1231f4f80feSStanislav Fomichev 			 /*icsk_retransmits=*/0);
1241f4f80feSStanislav Fomichev 
1251f4f80feSStanislav Fomichev 	send_byte(client_fd);
1261f4f80feSStanislav Fomichev 	if (wait_for_ack(client_fd, 100) < 0) {
1271f4f80feSStanislav Fomichev 		err = -1;
1281f4f80feSStanislav Fomichev 		goto close_client_fd;
1291f4f80feSStanislav Fomichev 	}
1301f4f80feSStanislav Fomichev 
1311f4f80feSStanislav Fomichev 
1321f4f80feSStanislav Fomichev 	err += verify_sk(map_fd, client_fd, "first payload byte",
1331f4f80feSStanislav Fomichev 			 /*invoked=*/2,
1341f4f80feSStanislav Fomichev 			 /*dsack_dups=*/0,
1351f4f80feSStanislav Fomichev 			 /*delivered=*/2,
1361f4f80feSStanislav Fomichev 			 /*delivered_ce=*/0,
1371f4f80feSStanislav Fomichev 			 /*icsk_retransmits=*/0);
1381f4f80feSStanislav Fomichev 
1391f4f80feSStanislav Fomichev close_client_fd:
1401f4f80feSStanislav Fomichev 	close(client_fd);
1411f4f80feSStanislav Fomichev 
1421f4f80feSStanislav Fomichev close_bpf_object:
143186d1a86SAndrii Nakryiko 	tcp_rtt__destroy(skel);
1441f4f80feSStanislav Fomichev 	return err;
1451f4f80feSStanislav Fomichev }
1461f4f80feSStanislav Fomichev 
test_tcp_rtt(void)1471f4f80feSStanislav Fomichev void test_tcp_rtt(void)
1481f4f80feSStanislav Fomichev {
1491f4f80feSStanislav Fomichev 	int server_fd, cgroup_fd;
1501f4f80feSStanislav Fomichev 
1511f4f80feSStanislav Fomichev 	cgroup_fd = test__join_cgroup("/tcp_rtt");
1528dda32acSWang Yufen 	if (!ASSERT_GE(cgroup_fd, 0, "join_cgroup /tcp_rtt"))
1531f4f80feSStanislav Fomichev 		return;
1541f4f80feSStanislav Fomichev 
15599126abeSMartin KaFai Lau 	server_fd = start_server(AF_INET, SOCK_STREAM, NULL, 0, 0);
1568dda32acSWang Yufen 	if (!ASSERT_GE(server_fd, 0, "start_server"))
1571f4f80feSStanislav Fomichev 		goto close_cgroup_fd;
1581f4f80feSStanislav Fomichev 
1598dda32acSWang Yufen 	ASSERT_OK(run_test(cgroup_fd, server_fd), "run_test");
1604cd729faSAndrii Nakryiko 
1611f4f80feSStanislav Fomichev 	close(server_fd);
16233181bb8SStanislav Fomichev 
1631f4f80feSStanislav Fomichev close_cgroup_fd:
1641f4f80feSStanislav Fomichev 	close(cgroup_fd);
1651f4f80feSStanislav Fomichev }
166