| 252 | } |
| 253 | |
| 254 | static int test_connect_timeout(struct io_uring *ring) |
| 255 | { |
| 256 | int connect_fd[2] = {-1, -1}; |
| 257 | int accept_fd = -1; |
| 258 | int ret, code; |
| 259 | struct sockaddr_in addr; |
| 260 | struct io_uring_sqe *sqe; |
| 261 | struct __kernel_timespec ts = {.tv_sec = 0, .tv_nsec = 100000}; |
| 262 | struct stat sb; |
| 263 | |
| 264 | /* |
| 265 | * Test reliably fails if syncookies isn't enabled |
| 266 | */ |
| 267 | if (stat("/proc/sys/net/ipv4/tcp_syncookies", &sb) < 0) |
| 268 | return T_EXIT_SKIP; |
| 269 | |
| 270 | connect_fd[0] = create_socket(); |
| 271 | if (connect_fd[0] == -1) |
| 272 | return -1; |
| 273 | |
| 274 | connect_fd[1] = create_socket(); |
| 275 | if (connect_fd[1] == -1) |
| 276 | goto err; |
| 277 | |
| 278 | accept_fd = create_socket(); |
| 279 | if (accept_fd == -1) |
| 280 | goto err; |
| 281 | |
| 282 | if (configure_connect(connect_fd[0], &addr) == -1) |
| 283 | goto err; |
| 284 | |
| 285 | if (configure_connect(connect_fd[1], &addr) == -1) |
| 286 | goto err; |
| 287 | |
| 288 | ret = bind(accept_fd, (struct sockaddr*)&addr, sizeof(addr)); |
| 289 | if (ret == -1) { |
| 290 | perror("bind()"); |
| 291 | goto err; |
| 292 | } |
| 293 | |
| 294 | ret = listen(accept_fd, 0); // no backlog in order to block connect_fd[1] |
| 295 | if (ret == -1) { |
| 296 | perror("listen()"); |
| 297 | goto err; |
| 298 | } |
| 299 | |
| 300 | // We first connect with one client socket in order to fill the accept queue. |
| 301 | ret = connect_socket(ring, connect_fd[0], &code, 0); |
| 302 | if (ret == -1 || code != 0) { |
| 303 | fprintf(stderr, "unable to connect\n"); |
| 304 | goto err; |
| 305 | } |
| 306 | |
| 307 | // We do not offload completion events from listening socket on purpose. |
| 308 | // This way we create a state where the second connect request being stalled by OS. |
| 309 | sqe = io_uring_get_sqe(ring); |
| 310 | if (!sqe) { |
| 311 | fprintf(stderr, "unable to get sqe\n"); |
no test coverage detected