Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.3-rc6 254 lines 5.3 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2#include <error.h> 3#include <errno.h> 4#include <stdio.h> 5#include <unistd.h> 6#include <sys/types.h> 7#include <sys/socket.h> 8#include <netinet/in.h> 9#include <pthread.h> 10 11#include <linux/filter.h> 12#include <bpf/bpf.h> 13#include <bpf/libbpf.h> 14 15#include "bpf_rlimit.h" 16#include "bpf_util.h" 17#include "cgroup_helpers.h" 18 19#define CG_PATH "/tcp_rtt" 20 21struct tcp_rtt_storage { 22 __u32 invoked; 23 __u32 dsack_dups; 24 __u32 delivered; 25 __u32 delivered_ce; 26 __u32 icsk_retransmits; 27}; 28 29static void send_byte(int fd) 30{ 31 char b = 0x55; 32 33 if (write(fd, &b, sizeof(b)) != 1) 34 error(1, errno, "Failed to send single byte"); 35} 36 37static int verify_sk(int map_fd, int client_fd, const char *msg, __u32 invoked, 38 __u32 dsack_dups, __u32 delivered, __u32 delivered_ce, 39 __u32 icsk_retransmits) 40{ 41 int err = 0; 42 struct tcp_rtt_storage val; 43 44 if (bpf_map_lookup_elem(map_fd, &client_fd, &val) < 0) 45 error(1, errno, "Failed to read socket storage"); 46 47 if (val.invoked != invoked) { 48 log_err("%s: unexpected bpf_tcp_sock.invoked %d != %d", 49 msg, val.invoked, invoked); 50 err++; 51 } 52 53 if (val.dsack_dups != dsack_dups) { 54 log_err("%s: unexpected bpf_tcp_sock.dsack_dups %d != %d", 55 msg, val.dsack_dups, dsack_dups); 56 err++; 57 } 58 59 if (val.delivered != delivered) { 60 log_err("%s: unexpected bpf_tcp_sock.delivered %d != %d", 61 msg, val.delivered, delivered); 62 err++; 63 } 64 65 if (val.delivered_ce != delivered_ce) { 66 log_err("%s: unexpected bpf_tcp_sock.delivered_ce %d != %d", 67 msg, val.delivered_ce, delivered_ce); 68 err++; 69 } 70 71 if (val.icsk_retransmits != icsk_retransmits) { 72 log_err("%s: unexpected bpf_tcp_sock.icsk_retransmits %d != %d", 73 msg, val.icsk_retransmits, icsk_retransmits); 74 err++; 75 } 76 77 return err; 78} 79 80static int connect_to_server(int server_fd) 81{ 82 struct sockaddr_storage addr; 83 socklen_t len = sizeof(addr); 84 int fd; 85 86 fd = socket(AF_INET, SOCK_STREAM, 0); 87 if (fd < 0) { 88 log_err("Failed to create client socket"); 89 return -1; 90 } 91 92 if (getsockname(server_fd, (struct sockaddr *)&addr, &len)) { 93 log_err("Failed to get server addr"); 94 goto out; 95 } 96 97 if (connect(fd, (const struct sockaddr *)&addr, len) < 0) { 98 log_err("Fail to connect to server"); 99 goto out; 100 } 101 102 return fd; 103 104out: 105 close(fd); 106 return -1; 107} 108 109static int run_test(int cgroup_fd, int server_fd) 110{ 111 struct bpf_prog_load_attr attr = { 112 .prog_type = BPF_PROG_TYPE_SOCK_OPS, 113 .file = "./tcp_rtt.o", 114 .expected_attach_type = BPF_CGROUP_SOCK_OPS, 115 }; 116 struct bpf_object *obj; 117 struct bpf_map *map; 118 int client_fd; 119 int prog_fd; 120 int map_fd; 121 int err; 122 123 err = bpf_prog_load_xattr(&attr, &obj, &prog_fd); 124 if (err) { 125 log_err("Failed to load BPF object"); 126 return -1; 127 } 128 129 map = bpf_map__next(NULL, obj); 130 map_fd = bpf_map__fd(map); 131 132 err = bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_SOCK_OPS, 0); 133 if (err) { 134 log_err("Failed to attach BPF program"); 135 goto close_bpf_object; 136 } 137 138 client_fd = connect_to_server(server_fd); 139 if (client_fd < 0) { 140 err = -1; 141 goto close_bpf_object; 142 } 143 144 err += verify_sk(map_fd, client_fd, "syn-ack", 145 /*invoked=*/1, 146 /*dsack_dups=*/0, 147 /*delivered=*/1, 148 /*delivered_ce=*/0, 149 /*icsk_retransmits=*/0); 150 151 send_byte(client_fd); 152 153 err += verify_sk(map_fd, client_fd, "first payload byte", 154 /*invoked=*/2, 155 /*dsack_dups=*/0, 156 /*delivered=*/2, 157 /*delivered_ce=*/0, 158 /*icsk_retransmits=*/0); 159 160 close(client_fd); 161 162close_bpf_object: 163 bpf_object__close(obj); 164 return err; 165} 166 167static int start_server(void) 168{ 169 struct sockaddr_in addr = { 170 .sin_family = AF_INET, 171 .sin_addr.s_addr = htonl(INADDR_LOOPBACK), 172 }; 173 int fd; 174 175 fd = socket(AF_INET, SOCK_STREAM, 0); 176 if (fd < 0) { 177 log_err("Failed to create server socket"); 178 return -1; 179 } 180 181 if (bind(fd, (const struct sockaddr *)&addr, sizeof(addr)) < 0) { 182 log_err("Failed to bind socket"); 183 close(fd); 184 return -1; 185 } 186 187 return fd; 188} 189 190static void *server_thread(void *arg) 191{ 192 struct sockaddr_storage addr; 193 socklen_t len = sizeof(addr); 194 int fd = *(int *)arg; 195 int client_fd; 196 197 if (listen(fd, 1) < 0) 198 error(1, errno, "Failed to listed on socket"); 199 200 client_fd = accept(fd, (struct sockaddr *)&addr, &len); 201 if (client_fd < 0) 202 error(1, errno, "Failed to accept client"); 203 204 /* Wait for the next connection (that never arrives) 205 * to keep this thread alive to prevent calling 206 * close() on client_fd. 207 */ 208 if (accept(fd, (struct sockaddr *)&addr, &len) >= 0) 209 error(1, errno, "Unexpected success in second accept"); 210 211 close(client_fd); 212 213 return NULL; 214} 215 216int main(int args, char **argv) 217{ 218 int server_fd, cgroup_fd; 219 int err = EXIT_SUCCESS; 220 pthread_t tid; 221 222 if (setup_cgroup_environment()) 223 goto cleanup_obj; 224 225 cgroup_fd = create_and_get_cgroup(CG_PATH); 226 if (cgroup_fd < 0) 227 goto cleanup_cgroup_env; 228 229 if (join_cgroup(CG_PATH)) 230 goto cleanup_cgroup; 231 232 server_fd = start_server(); 233 if (server_fd < 0) { 234 err = EXIT_FAILURE; 235 goto cleanup_cgroup; 236 } 237 238 pthread_create(&tid, NULL, server_thread, (void *)&server_fd); 239 240 if (run_test(cgroup_fd, server_fd)) 241 err = EXIT_FAILURE; 242 243 close(server_fd); 244 245 printf("test_sockopt_sk: %s\n", 246 err == EXIT_SUCCESS ? "PASSED" : "FAILED"); 247 248cleanup_cgroup: 249 close(cgroup_fd); 250cleanup_cgroup_env: 251 cleanup_cgroup_environment(); 252cleanup_obj: 253 return err; 254}