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