0001
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 1,
0122 0,
0123 1,
0124 0,
0125 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 2,
0136 0,
0137 2,
0138 0,
0139 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 }