Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <test_progs.h>
0003 #include "cgroup_helpers.h"
0004 #include "network_helpers.h"
0005 #include "tcp_rtt.skel.h"
0006 
0007 struct tcp_rtt_storage {
0008     __u32 invoked;
0009     __u32 dsack_dups;
0010     __u32 delivered;
0011     __u32 delivered_ce;
0012     __u32 icsk_retransmits;
0013 };
0014 
0015 static void send_byte(int fd)
0016 {
0017     char b = 0x55;
0018 
0019     if (CHECK_FAIL(write(fd, &b, sizeof(b)) != 1))
0020         perror("Failed to send single byte");
0021 }
0022 
0023 static int wait_for_ack(int fd, int retries)
0024 {
0025     struct tcp_info info;
0026     socklen_t optlen;
0027     int i, err;
0028 
0029     for (i = 0; i < retries; i++) {
0030         optlen = sizeof(info);
0031         err = getsockopt(fd, SOL_TCP, TCP_INFO, &info, &optlen);
0032         if (err < 0) {
0033             log_err("Failed to lookup TCP stats");
0034             return err;
0035         }
0036 
0037         if (info.tcpi_unacked == 0)
0038             return 0;
0039 
0040         usleep(10);
0041     }
0042 
0043     log_err("Did not receive ACK");
0044     return -1;
0045 }
0046 
0047 static int verify_sk(int map_fd, int client_fd, const char *msg, __u32 invoked,
0048              __u32 dsack_dups, __u32 delivered, __u32 delivered_ce,
0049              __u32 icsk_retransmits)
0050 {
0051     int err = 0;
0052     struct tcp_rtt_storage val;
0053 
0054     if (CHECK_FAIL(bpf_map_lookup_elem(map_fd, &client_fd, &val) < 0)) {
0055         perror("Failed to read socket storage");
0056         return -1;
0057     }
0058 
0059     if (val.invoked != invoked) {
0060         log_err("%s: unexpected bpf_tcp_sock.invoked %d != %d",
0061             msg, val.invoked, invoked);
0062         err++;
0063     }
0064 
0065     if (val.dsack_dups != dsack_dups) {
0066         log_err("%s: unexpected bpf_tcp_sock.dsack_dups %d != %d",
0067             msg, val.dsack_dups, dsack_dups);
0068         err++;
0069     }
0070 
0071     if (val.delivered != delivered) {
0072         log_err("%s: unexpected bpf_tcp_sock.delivered %d != %d",
0073             msg, val.delivered, delivered);
0074         err++;
0075     }
0076 
0077     if (val.delivered_ce != delivered_ce) {
0078         log_err("%s: unexpected bpf_tcp_sock.delivered_ce %d != %d",
0079             msg, val.delivered_ce, delivered_ce);
0080         err++;
0081     }
0082 
0083     if (val.icsk_retransmits != icsk_retransmits) {
0084         log_err("%s: unexpected bpf_tcp_sock.icsk_retransmits %d != %d",
0085             msg, val.icsk_retransmits, icsk_retransmits);
0086         err++;
0087     }
0088 
0089     return err;
0090 }
0091 
0092 
0093 static int run_test(int cgroup_fd, int server_fd)
0094 {
0095     struct tcp_rtt *skel;
0096     int client_fd;
0097     int prog_fd;
0098     int map_fd;
0099     int err;
0100 
0101     skel = tcp_rtt__open_and_load();
0102     if (!ASSERT_OK_PTR(skel, "skel_open_load"))
0103         return -1;
0104 
0105     map_fd = bpf_map__fd(skel->maps.socket_storage_map);
0106     prog_fd = bpf_program__fd(skel->progs._sockops);
0107 
0108     err = bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_SOCK_OPS, 0);
0109     if (err) {
0110         log_err("Failed to attach BPF program");
0111         goto close_bpf_object;
0112     }
0113 
0114     client_fd = connect_to_fd(server_fd, 0);
0115     if (client_fd < 0) {
0116         err = -1;
0117         goto close_bpf_object;
0118     }
0119 
0120     err += verify_sk(map_fd, client_fd, "syn-ack",
0121              /*invoked=*/1,
0122              /*dsack_dups=*/0,
0123              /*delivered=*/1,
0124              /*delivered_ce=*/0,
0125              /*icsk_retransmits=*/0);
0126 
0127     send_byte(client_fd);
0128     if (wait_for_ack(client_fd, 100) < 0) {
0129         err = -1;
0130         goto close_client_fd;
0131     }
0132 
0133 
0134     err += verify_sk(map_fd, client_fd, "first payload byte",
0135              /*invoked=*/2,
0136              /*dsack_dups=*/0,
0137              /*delivered=*/2,
0138              /*delivered_ce=*/0,
0139              /*icsk_retransmits=*/0);
0140 
0141 close_client_fd:
0142     close(client_fd);
0143 
0144 close_bpf_object:
0145     tcp_rtt__destroy(skel);
0146     return err;
0147 }
0148 
0149 void test_tcp_rtt(void)
0150 {
0151     int server_fd, cgroup_fd;
0152 
0153     cgroup_fd = test__join_cgroup("/tcp_rtt");
0154     if (CHECK_FAIL(cgroup_fd < 0))
0155         return;
0156 
0157     server_fd = start_server(AF_INET, SOCK_STREAM, NULL, 0, 0);
0158     if (CHECK_FAIL(server_fd < 0))
0159         goto close_cgroup_fd;
0160 
0161     CHECK_FAIL(run_test(cgroup_fd, server_fd));
0162 
0163     close(server_fd);
0164 
0165 close_cgroup_fd:
0166     close(cgroup_fd);
0167 }