1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (c) 2020 Cloudflare 3 /* 4 * Test suite for SOCKMAP/SOCKHASH holding listening sockets. 5 * Covers: 6 * 1. BPF map operations - bpf_map_{update,lookup delete}_elem 7 * 2. BPF redirect helpers - bpf_{sk,msg}_redirect_map 8 * 3. BPF reuseport helper - bpf_sk_select_reuseport 9 */ 10 11 #include <linux/compiler.h> 12 #include <errno.h> 13 #include <error.h> 14 #include <limits.h> 15 #include <netinet/in.h> 16 #include <pthread.h> 17 #include <stdlib.h> 18 #include <string.h> 19 #include <sys/select.h> 20 #include <unistd.h> 21 #include <linux/vm_sockets.h> 22 23 /* workaround for older vm_sockets.h */ 24 #ifndef VMADDR_CID_LOCAL 25 #define VMADDR_CID_LOCAL 1 26 #endif 27 28 #include <bpf/bpf.h> 29 #include <bpf/libbpf.h> 30 31 #include "bpf_util.h" 32 #include "test_progs.h" 33 #include "test_sockmap_listen.skel.h" 34 35 #define IO_TIMEOUT_SEC 30 36 #define MAX_STRERR_LEN 256 37 #define MAX_TEST_NAME 80 38 39 #define __always_unused __attribute__((__unused__)) 40 41 #define _FAIL(errnum, fmt...) \ 42 ({ \ 43 error_at_line(0, (errnum), __func__, __LINE__, fmt); \ 44 CHECK_FAIL(true); \ 45 }) 46 #define FAIL(fmt...) _FAIL(0, fmt) 47 #define FAIL_ERRNO(fmt...) _FAIL(errno, fmt) 48 #define FAIL_LIBBPF(err, msg) \ 49 ({ \ 50 char __buf[MAX_STRERR_LEN]; \ 51 libbpf_strerror((err), __buf, sizeof(__buf)); \ 52 FAIL("%s: %s", (msg), __buf); \ 53 }) 54 55 /* Wrappers that fail the test on error and report it. */ 56 57 #define xaccept_nonblock(fd, addr, len) \ 58 ({ \ 59 int __ret = \ 60 accept_timeout((fd), (addr), (len), IO_TIMEOUT_SEC); \ 61 if (__ret == -1) \ 62 FAIL_ERRNO("accept"); \ 63 __ret; \ 64 }) 65 66 #define xbind(fd, addr, len) \ 67 ({ \ 68 int __ret = bind((fd), (addr), (len)); \ 69 if (__ret == -1) \ 70 FAIL_ERRNO("bind"); \ 71 __ret; \ 72 }) 73 74 #define xclose(fd) \ 75 ({ \ 76 int __ret = close((fd)); \ 77 if (__ret == -1) \ 78 FAIL_ERRNO("close"); \ 79 __ret; \ 80 }) 81 82 #define xconnect(fd, addr, len) \ 83 ({ \ 84 int __ret = connect((fd), (addr), (len)); \ 85 if (__ret == -1) \ 86 FAIL_ERRNO("connect"); \ 87 __ret; \ 88 }) 89 90 #define xgetsockname(fd, addr, len) \ 91 ({ \ 92 int __ret = getsockname((fd), (addr), (len)); \ 93 if (__ret == -1) \ 94 FAIL_ERRNO("getsockname"); \ 95 __ret; \ 96 }) 97 98 #define xgetsockopt(fd, level, name, val, len) \ 99 ({ \ 100 int __ret = getsockopt((fd), (level), (name), (val), (len)); \ 101 if (__ret == -1) \ 102 FAIL_ERRNO("getsockopt(" #name ")"); \ 103 __ret; \ 104 }) 105 106 #define xlisten(fd, backlog) \ 107 ({ \ 108 int __ret = listen((fd), (backlog)); \ 109 if (__ret == -1) \ 110 FAIL_ERRNO("listen"); \ 111 __ret; \ 112 }) 113 114 #define xsetsockopt(fd, level, name, val, len) \ 115 ({ \ 116 int __ret = setsockopt((fd), (level), (name), (val), (len)); \ 117 if (__ret == -1) \ 118 FAIL_ERRNO("setsockopt(" #name ")"); \ 119 __ret; \ 120 }) 121 122 #define xsend(fd, buf, len, flags) \ 123 ({ \ 124 ssize_t __ret = send((fd), (buf), (len), (flags)); \ 125 if (__ret == -1) \ 126 FAIL_ERRNO("send"); \ 127 __ret; \ 128 }) 129 130 #define xrecv_nonblock(fd, buf, len, flags) \ 131 ({ \ 132 ssize_t __ret = recv_timeout((fd), (buf), (len), (flags), \ 133 IO_TIMEOUT_SEC); \ 134 if (__ret == -1) \ 135 FAIL_ERRNO("recv"); \ 136 __ret; \ 137 }) 138 139 #define xsocket(family, sotype, flags) \ 140 ({ \ 141 int __ret = socket(family, sotype, flags); \ 142 if (__ret == -1) \ 143 FAIL_ERRNO("socket"); \ 144 __ret; \ 145 }) 146 147 #define xbpf_map_delete_elem(fd, key) \ 148 ({ \ 149 int __ret = bpf_map_delete_elem((fd), (key)); \ 150 if (__ret < 0) \ 151 FAIL_ERRNO("map_delete"); \ 152 __ret; \ 153 }) 154 155 #define xbpf_map_lookup_elem(fd, key, val) \ 156 ({ \ 157 int __ret = bpf_map_lookup_elem((fd), (key), (val)); \ 158 if (__ret < 0) \ 159 FAIL_ERRNO("map_lookup"); \ 160 __ret; \ 161 }) 162 163 #define xbpf_map_update_elem(fd, key, val, flags) \ 164 ({ \ 165 int __ret = bpf_map_update_elem((fd), (key), (val), (flags)); \ 166 if (__ret < 0) \ 167 FAIL_ERRNO("map_update"); \ 168 __ret; \ 169 }) 170 171 #define xbpf_prog_attach(prog, target, type, flags) \ 172 ({ \ 173 int __ret = \ 174 bpf_prog_attach((prog), (target), (type), (flags)); \ 175 if (__ret < 0) \ 176 FAIL_ERRNO("prog_attach(" #type ")"); \ 177 __ret; \ 178 }) 179 180 #define xbpf_prog_detach2(prog, target, type) \ 181 ({ \ 182 int __ret = bpf_prog_detach2((prog), (target), (type)); \ 183 if (__ret < 0) \ 184 FAIL_ERRNO("prog_detach2(" #type ")"); \ 185 __ret; \ 186 }) 187 188 #define xpthread_create(thread, attr, func, arg) \ 189 ({ \ 190 int __ret = pthread_create((thread), (attr), (func), (arg)); \ 191 errno = __ret; \ 192 if (__ret) \ 193 FAIL_ERRNO("pthread_create"); \ 194 __ret; \ 195 }) 196 197 #define xpthread_join(thread, retval) \ 198 ({ \ 199 int __ret = pthread_join((thread), (retval)); \ 200 errno = __ret; \ 201 if (__ret) \ 202 FAIL_ERRNO("pthread_join"); \ 203 __ret; \ 204 }) 205 206 static int poll_read(int fd, unsigned int timeout_sec) 207 { 208 struct timeval timeout = { .tv_sec = timeout_sec }; 209 fd_set rfds; 210 int r; 211 212 FD_ZERO(&rfds); 213 FD_SET(fd, &rfds); 214 215 r = select(fd + 1, &rfds, NULL, NULL, &timeout); 216 if (r == 0) 217 errno = ETIME; 218 219 return r == 1 ? 0 : -1; 220 } 221 222 static int accept_timeout(int fd, struct sockaddr *addr, socklen_t *len, 223 unsigned int timeout_sec) 224 { 225 if (poll_read(fd, timeout_sec)) 226 return -1; 227 228 return accept(fd, addr, len); 229 } 230 231 static int recv_timeout(int fd, void *buf, size_t len, int flags, 232 unsigned int timeout_sec) 233 { 234 if (poll_read(fd, timeout_sec)) 235 return -1; 236 237 return recv(fd, buf, len, flags); 238 } 239 240 static void init_addr_loopback4(struct sockaddr_storage *ss, socklen_t *len) 241 { 242 struct sockaddr_in *addr4 = memset(ss, 0, sizeof(*ss)); 243 244 addr4->sin_family = AF_INET; 245 addr4->sin_port = 0; 246 addr4->sin_addr.s_addr = htonl(INADDR_LOOPBACK); 247 *len = sizeof(*addr4); 248 } 249 250 static void init_addr_loopback6(struct sockaddr_storage *ss, socklen_t *len) 251 { 252 struct sockaddr_in6 *addr6 = memset(ss, 0, sizeof(*ss)); 253 254 addr6->sin6_family = AF_INET6; 255 addr6->sin6_port = 0; 256 addr6->sin6_addr = in6addr_loopback; 257 *len = sizeof(*addr6); 258 } 259 260 static void init_addr_loopback_vsock(struct sockaddr_storage *ss, socklen_t *len) 261 { 262 struct sockaddr_vm *addr = memset(ss, 0, sizeof(*ss)); 263 264 addr->svm_family = AF_VSOCK; 265 addr->svm_port = VMADDR_PORT_ANY; 266 addr->svm_cid = VMADDR_CID_LOCAL; 267 *len = sizeof(*addr); 268 } 269 270 static void init_addr_loopback(int family, struct sockaddr_storage *ss, 271 socklen_t *len) 272 { 273 switch (family) { 274 case AF_INET: 275 init_addr_loopback4(ss, len); 276 return; 277 case AF_INET6: 278 init_addr_loopback6(ss, len); 279 return; 280 case AF_VSOCK: 281 init_addr_loopback_vsock(ss, len); 282 return; 283 default: 284 FAIL("unsupported address family %d", family); 285 } 286 } 287 288 static inline struct sockaddr *sockaddr(struct sockaddr_storage *ss) 289 { 290 return (struct sockaddr *)ss; 291 } 292 293 static int enable_reuseport(int s, int progfd) 294 { 295 int err, one = 1; 296 297 err = xsetsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)); 298 if (err) 299 return -1; 300 err = xsetsockopt(s, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, &progfd, 301 sizeof(progfd)); 302 if (err) 303 return -1; 304 305 return 0; 306 } 307 308 static int socket_loopback_reuseport(int family, int sotype, int progfd) 309 { 310 struct sockaddr_storage addr; 311 socklen_t len; 312 int err, s; 313 314 init_addr_loopback(family, &addr, &len); 315 316 s = xsocket(family, sotype, 0); 317 if (s == -1) 318 return -1; 319 320 if (progfd >= 0) 321 enable_reuseport(s, progfd); 322 323 err = xbind(s, sockaddr(&addr), len); 324 if (err) 325 goto close; 326 327 if (sotype & SOCK_DGRAM) 328 return s; 329 330 err = xlisten(s, SOMAXCONN); 331 if (err) 332 goto close; 333 334 return s; 335 close: 336 xclose(s); 337 return -1; 338 } 339 340 static int socket_loopback(int family, int sotype) 341 { 342 return socket_loopback_reuseport(family, sotype, -1); 343 } 344 345 static void test_insert_invalid(struct test_sockmap_listen *skel __always_unused, 346 int family, int sotype, int mapfd) 347 { 348 u32 key = 0; 349 u64 value; 350 int err; 351 352 value = -1; 353 err = bpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST); 354 if (!err || errno != EINVAL) 355 FAIL_ERRNO("map_update: expected EINVAL"); 356 357 value = INT_MAX; 358 err = bpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST); 359 if (!err || errno != EBADF) 360 FAIL_ERRNO("map_update: expected EBADF"); 361 } 362 363 static void test_insert_opened(struct test_sockmap_listen *skel __always_unused, 364 int family, int sotype, int mapfd) 365 { 366 u32 key = 0; 367 u64 value; 368 int err, s; 369 370 s = xsocket(family, sotype, 0); 371 if (s == -1) 372 return; 373 374 errno = 0; 375 value = s; 376 err = bpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST); 377 if (sotype == SOCK_STREAM) { 378 if (!err || errno != EOPNOTSUPP) 379 FAIL_ERRNO("map_update: expected EOPNOTSUPP"); 380 } else if (err) 381 FAIL_ERRNO("map_update: expected success"); 382 xclose(s); 383 } 384 385 static void test_insert_bound(struct test_sockmap_listen *skel __always_unused, 386 int family, int sotype, int mapfd) 387 { 388 struct sockaddr_storage addr; 389 socklen_t len; 390 u32 key = 0; 391 u64 value; 392 int err, s; 393 394 init_addr_loopback(family, &addr, &len); 395 396 s = xsocket(family, sotype, 0); 397 if (s == -1) 398 return; 399 400 err = xbind(s, sockaddr(&addr), len); 401 if (err) 402 goto close; 403 404 errno = 0; 405 value = s; 406 err = bpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST); 407 if (!err || errno != EOPNOTSUPP) 408 FAIL_ERRNO("map_update: expected EOPNOTSUPP"); 409 close: 410 xclose(s); 411 } 412 413 static void test_insert(struct test_sockmap_listen *skel __always_unused, 414 int family, int sotype, int mapfd) 415 { 416 u64 value; 417 u32 key; 418 int s; 419 420 s = socket_loopback(family, sotype); 421 if (s < 0) 422 return; 423 424 key = 0; 425 value = s; 426 xbpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST); 427 xclose(s); 428 } 429 430 static void test_delete_after_insert(struct test_sockmap_listen *skel __always_unused, 431 int family, int sotype, int mapfd) 432 { 433 u64 value; 434 u32 key; 435 int s; 436 437 s = socket_loopback(family, sotype); 438 if (s < 0) 439 return; 440 441 key = 0; 442 value = s; 443 xbpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST); 444 xbpf_map_delete_elem(mapfd, &key); 445 xclose(s); 446 } 447 448 static void test_delete_after_close(struct test_sockmap_listen *skel __always_unused, 449 int family, int sotype, int mapfd) 450 { 451 int err, s; 452 u64 value; 453 u32 key; 454 455 s = socket_loopback(family, sotype); 456 if (s < 0) 457 return; 458 459 key = 0; 460 value = s; 461 xbpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST); 462 463 xclose(s); 464 465 errno = 0; 466 err = bpf_map_delete_elem(mapfd, &key); 467 if (!err || (errno != EINVAL && errno != ENOENT)) 468 /* SOCKMAP and SOCKHASH return different error codes */ 469 FAIL_ERRNO("map_delete: expected EINVAL/EINVAL"); 470 } 471 472 static void test_lookup_after_insert(struct test_sockmap_listen *skel __always_unused, 473 int family, int sotype, int mapfd) 474 { 475 u64 cookie, value; 476 socklen_t len; 477 u32 key; 478 int s; 479 480 s = socket_loopback(family, sotype); 481 if (s < 0) 482 return; 483 484 key = 0; 485 value = s; 486 xbpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST); 487 488 len = sizeof(cookie); 489 xgetsockopt(s, SOL_SOCKET, SO_COOKIE, &cookie, &len); 490 491 xbpf_map_lookup_elem(mapfd, &key, &value); 492 493 if (value != cookie) { 494 FAIL("map_lookup: have %#llx, want %#llx", 495 (unsigned long long)value, (unsigned long long)cookie); 496 } 497 498 xclose(s); 499 } 500 501 static void test_lookup_after_delete(struct test_sockmap_listen *skel __always_unused, 502 int family, int sotype, int mapfd) 503 { 504 int err, s; 505 u64 value; 506 u32 key; 507 508 s = socket_loopback(family, sotype); 509 if (s < 0) 510 return; 511 512 key = 0; 513 value = s; 514 xbpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST); 515 xbpf_map_delete_elem(mapfd, &key); 516 517 errno = 0; 518 err = bpf_map_lookup_elem(mapfd, &key, &value); 519 if (!err || errno != ENOENT) 520 FAIL_ERRNO("map_lookup: expected ENOENT"); 521 522 xclose(s); 523 } 524 525 static void test_lookup_32_bit_value(struct test_sockmap_listen *skel __always_unused, 526 int family, int sotype, int mapfd) 527 { 528 u32 key, value32; 529 int err, s; 530 531 s = socket_loopback(family, sotype); 532 if (s < 0) 533 return; 534 535 mapfd = bpf_map_create(BPF_MAP_TYPE_SOCKMAP, NULL, sizeof(key), 536 sizeof(value32), 1, NULL); 537 if (mapfd < 0) { 538 FAIL_ERRNO("map_create"); 539 goto close; 540 } 541 542 key = 0; 543 value32 = s; 544 xbpf_map_update_elem(mapfd, &key, &value32, BPF_NOEXIST); 545 546 errno = 0; 547 err = bpf_map_lookup_elem(mapfd, &key, &value32); 548 if (!err || errno != ENOSPC) 549 FAIL_ERRNO("map_lookup: expected ENOSPC"); 550 551 xclose(mapfd); 552 close: 553 xclose(s); 554 } 555 556 static void test_update_existing(struct test_sockmap_listen *skel __always_unused, 557 int family, int sotype, int mapfd) 558 { 559 int s1, s2; 560 u64 value; 561 u32 key; 562 563 s1 = socket_loopback(family, sotype); 564 if (s1 < 0) 565 return; 566 567 s2 = socket_loopback(family, sotype); 568 if (s2 < 0) 569 goto close_s1; 570 571 key = 0; 572 value = s1; 573 xbpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST); 574 575 value = s2; 576 xbpf_map_update_elem(mapfd, &key, &value, BPF_EXIST); 577 xclose(s2); 578 close_s1: 579 xclose(s1); 580 } 581 582 /* Exercise the code path where we destroy child sockets that never 583 * got accept()'ed, aka orphans, when parent socket gets closed. 584 */ 585 static void do_destroy_orphan_child(int family, int sotype, int mapfd) 586 { 587 struct sockaddr_storage addr; 588 socklen_t len; 589 int err, s, c; 590 u64 value; 591 u32 key; 592 593 s = socket_loopback(family, sotype); 594 if (s < 0) 595 return; 596 597 len = sizeof(addr); 598 err = xgetsockname(s, sockaddr(&addr), &len); 599 if (err) 600 goto close_srv; 601 602 key = 0; 603 value = s; 604 xbpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST); 605 606 c = xsocket(family, sotype, 0); 607 if (c == -1) 608 goto close_srv; 609 610 xconnect(c, sockaddr(&addr), len); 611 xclose(c); 612 close_srv: 613 xclose(s); 614 } 615 616 static void test_destroy_orphan_child(struct test_sockmap_listen *skel, 617 int family, int sotype, int mapfd) 618 { 619 int msg_verdict = bpf_program__fd(skel->progs.prog_msg_verdict); 620 int skb_verdict = bpf_program__fd(skel->progs.prog_skb_verdict); 621 const struct test { 622 int progfd; 623 enum bpf_attach_type atype; 624 } tests[] = { 625 { -1, -1 }, 626 { msg_verdict, BPF_SK_MSG_VERDICT }, 627 { skb_verdict, BPF_SK_SKB_VERDICT }, 628 }; 629 const struct test *t; 630 631 for (t = tests; t < tests + ARRAY_SIZE(tests); t++) { 632 if (t->progfd != -1 && 633 xbpf_prog_attach(t->progfd, mapfd, t->atype, 0) != 0) 634 return; 635 636 do_destroy_orphan_child(family, sotype, mapfd); 637 638 if (t->progfd != -1) 639 xbpf_prog_detach2(t->progfd, mapfd, t->atype); 640 } 641 } 642 643 /* Perform a passive open after removing listening socket from SOCKMAP 644 * to ensure that callbacks get restored properly. 645 */ 646 static void test_clone_after_delete(struct test_sockmap_listen *skel __always_unused, 647 int family, int sotype, int mapfd) 648 { 649 struct sockaddr_storage addr; 650 socklen_t len; 651 int err, s, c; 652 u64 value; 653 u32 key; 654 655 s = socket_loopback(family, sotype); 656 if (s < 0) 657 return; 658 659 len = sizeof(addr); 660 err = xgetsockname(s, sockaddr(&addr), &len); 661 if (err) 662 goto close_srv; 663 664 key = 0; 665 value = s; 666 xbpf_map_update_elem(mapfd, &key, &value, BPF_NOEXIST); 667 xbpf_map_delete_elem(mapfd, &key); 668 669 c = xsocket(family, sotype, 0); 670 if (c < 0) 671 goto close_srv; 672 673 xconnect(c, sockaddr(&addr), len); 674 xclose(c); 675 close_srv: 676 xclose(s); 677 } 678 679 /* Check that child socket that got created while parent was in a 680 * SOCKMAP, but got accept()'ed only after the parent has been removed 681 * from SOCKMAP, gets cloned without parent psock state or callbacks. 682 */ 683 static void test_accept_after_delete(struct test_sockmap_listen *skel __always_unused, 684 int family, int sotype, int mapfd) 685 { 686 struct sockaddr_storage addr; 687 const u32 zero = 0; 688 int err, s, c, p; 689 socklen_t len; 690 u64 value; 691 692 s = socket_loopback(family, sotype | SOCK_NONBLOCK); 693 if (s == -1) 694 return; 695 696 len = sizeof(addr); 697 err = xgetsockname(s, sockaddr(&addr), &len); 698 if (err) 699 goto close_srv; 700 701 value = s; 702 err = xbpf_map_update_elem(mapfd, &zero, &value, BPF_NOEXIST); 703 if (err) 704 goto close_srv; 705 706 c = xsocket(family, sotype, 0); 707 if (c == -1) 708 goto close_srv; 709 710 /* Create child while parent is in sockmap */ 711 err = xconnect(c, sockaddr(&addr), len); 712 if (err) 713 goto close_cli; 714 715 /* Remove parent from sockmap */ 716 err = xbpf_map_delete_elem(mapfd, &zero); 717 if (err) 718 goto close_cli; 719 720 p = xaccept_nonblock(s, NULL, NULL); 721 if (p == -1) 722 goto close_cli; 723 724 /* Check that child sk_user_data is not set */ 725 value = p; 726 xbpf_map_update_elem(mapfd, &zero, &value, BPF_NOEXIST); 727 728 xclose(p); 729 close_cli: 730 xclose(c); 731 close_srv: 732 xclose(s); 733 } 734 735 /* Check that child socket that got created and accepted while parent 736 * was in a SOCKMAP is cloned without parent psock state or callbacks. 737 */ 738 static void test_accept_before_delete(struct test_sockmap_listen *skel __always_unused, 739 int family, int sotype, int mapfd) 740 { 741 struct sockaddr_storage addr; 742 const u32 zero = 0, one = 1; 743 int err, s, c, p; 744 socklen_t len; 745 u64 value; 746 747 s = socket_loopback(family, sotype | SOCK_NONBLOCK); 748 if (s == -1) 749 return; 750 751 len = sizeof(addr); 752 err = xgetsockname(s, sockaddr(&addr), &len); 753 if (err) 754 goto close_srv; 755 756 value = s; 757 err = xbpf_map_update_elem(mapfd, &zero, &value, BPF_NOEXIST); 758 if (err) 759 goto close_srv; 760 761 c = xsocket(family, sotype, 0); 762 if (c == -1) 763 goto close_srv; 764 765 /* Create & accept child while parent is in sockmap */ 766 err = xconnect(c, sockaddr(&addr), len); 767 if (err) 768 goto close_cli; 769 770 p = xaccept_nonblock(s, NULL, NULL); 771 if (p == -1) 772 goto close_cli; 773 774 /* Check that child sk_user_data is not set */ 775 value = p; 776 xbpf_map_update_elem(mapfd, &one, &value, BPF_NOEXIST); 777 778 xclose(p); 779 close_cli: 780 xclose(c); 781 close_srv: 782 xclose(s); 783 } 784 785 struct connect_accept_ctx { 786 int sockfd; 787 unsigned int done; 788 unsigned int nr_iter; 789 }; 790 791 static bool is_thread_done(struct connect_accept_ctx *ctx) 792 { 793 return READ_ONCE(ctx->done); 794 } 795 796 static void *connect_accept_thread(void *arg) 797 { 798 struct connect_accept_ctx *ctx = arg; 799 struct sockaddr_storage addr; 800 int family, socktype; 801 socklen_t len; 802 int err, i, s; 803 804 s = ctx->sockfd; 805 806 len = sizeof(addr); 807 err = xgetsockname(s, sockaddr(&addr), &len); 808 if (err) 809 goto done; 810 811 len = sizeof(family); 812 err = xgetsockopt(s, SOL_SOCKET, SO_DOMAIN, &family, &len); 813 if (err) 814 goto done; 815 816 len = sizeof(socktype); 817 err = xgetsockopt(s, SOL_SOCKET, SO_TYPE, &socktype, &len); 818 if (err) 819 goto done; 820 821 for (i = 0; i < ctx->nr_iter; i++) { 822 int c, p; 823 824 c = xsocket(family, socktype, 0); 825 if (c < 0) 826 break; 827 828 err = xconnect(c, (struct sockaddr *)&addr, sizeof(addr)); 829 if (err) { 830 xclose(c); 831 break; 832 } 833 834 p = xaccept_nonblock(s, NULL, NULL); 835 if (p < 0) { 836 xclose(c); 837 break; 838 } 839 840 xclose(p); 841 xclose(c); 842 } 843 done: 844 WRITE_ONCE(ctx->done, 1); 845 return NULL; 846 } 847 848 static void test_syn_recv_insert_delete(struct test_sockmap_listen *skel __always_unused, 849 int family, int sotype, int mapfd) 850 { 851 struct connect_accept_ctx ctx = { 0 }; 852 struct sockaddr_storage addr; 853 socklen_t len; 854 u32 zero = 0; 855 pthread_t t; 856 int err, s; 857 u64 value; 858 859 s = socket_loopback(family, sotype | SOCK_NONBLOCK); 860 if (s < 0) 861 return; 862 863 len = sizeof(addr); 864 err = xgetsockname(s, sockaddr(&addr), &len); 865 if (err) 866 goto close; 867 868 ctx.sockfd = s; 869 ctx.nr_iter = 1000; 870 871 err = xpthread_create(&t, NULL, connect_accept_thread, &ctx); 872 if (err) 873 goto close; 874 875 value = s; 876 while (!is_thread_done(&ctx)) { 877 err = xbpf_map_update_elem(mapfd, &zero, &value, BPF_NOEXIST); 878 if (err) 879 break; 880 881 err = xbpf_map_delete_elem(mapfd, &zero); 882 if (err) 883 break; 884 } 885 886 xpthread_join(t, NULL); 887 close: 888 xclose(s); 889 } 890 891 static void *listen_thread(void *arg) 892 { 893 struct sockaddr unspec = { AF_UNSPEC }; 894 struct connect_accept_ctx *ctx = arg; 895 int err, i, s; 896 897 s = ctx->sockfd; 898 899 for (i = 0; i < ctx->nr_iter; i++) { 900 err = xlisten(s, 1); 901 if (err) 902 break; 903 err = xconnect(s, &unspec, sizeof(unspec)); 904 if (err) 905 break; 906 } 907 908 WRITE_ONCE(ctx->done, 1); 909 return NULL; 910 } 911 912 static void test_race_insert_listen(struct test_sockmap_listen *skel __always_unused, 913 int family, int socktype, int mapfd) 914 { 915 struct connect_accept_ctx ctx = { 0 }; 916 const u32 zero = 0; 917 const int one = 1; 918 pthread_t t; 919 int err, s; 920 u64 value; 921 922 s = xsocket(family, socktype, 0); 923 if (s < 0) 924 return; 925 926 err = xsetsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); 927 if (err) 928 goto close; 929 930 ctx.sockfd = s; 931 ctx.nr_iter = 10000; 932 933 err = pthread_create(&t, NULL, listen_thread, &ctx); 934 if (err) 935 goto close; 936 937 value = s; 938 while (!is_thread_done(&ctx)) { 939 err = bpf_map_update_elem(mapfd, &zero, &value, BPF_NOEXIST); 940 /* Expecting EOPNOTSUPP before listen() */ 941 if (err && errno != EOPNOTSUPP) { 942 FAIL_ERRNO("map_update"); 943 break; 944 } 945 946 err = bpf_map_delete_elem(mapfd, &zero); 947 /* Expecting no entry after unhash on connect(AF_UNSPEC) */ 948 if (err && errno != EINVAL && errno != ENOENT) { 949 FAIL_ERRNO("map_delete"); 950 break; 951 } 952 } 953 954 xpthread_join(t, NULL); 955 close: 956 xclose(s); 957 } 958 959 static void zero_verdict_count(int mapfd) 960 { 961 unsigned int zero = 0; 962 int key; 963 964 key = SK_DROP; 965 xbpf_map_update_elem(mapfd, &key, &zero, BPF_ANY); 966 key = SK_PASS; 967 xbpf_map_update_elem(mapfd, &key, &zero, BPF_ANY); 968 } 969 970 enum redir_mode { 971 REDIR_INGRESS, 972 REDIR_EGRESS, 973 }; 974 975 static const char *redir_mode_str(enum redir_mode mode) 976 { 977 switch (mode) { 978 case REDIR_INGRESS: 979 return "ingress"; 980 case REDIR_EGRESS: 981 return "egress"; 982 default: 983 return "unknown"; 984 } 985 } 986 987 static int add_to_sockmap(int sock_mapfd, int fd1, int fd2) 988 { 989 u64 value; 990 u32 key; 991 int err; 992 993 key = 0; 994 value = fd1; 995 err = xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST); 996 if (err) 997 return err; 998 999 key = 1; 1000 value = fd2; 1001 return xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST); 1002 } 1003 1004 static void redir_to_connected(int family, int sotype, int sock_mapfd, 1005 int verd_mapfd, enum redir_mode mode) 1006 { 1007 const char *log_prefix = redir_mode_str(mode); 1008 struct sockaddr_storage addr; 1009 int s, c0, c1, p0, p1; 1010 unsigned int pass; 1011 socklen_t len; 1012 int err, n; 1013 u32 key; 1014 char b; 1015 1016 zero_verdict_count(verd_mapfd); 1017 1018 s = socket_loopback(family, sotype | SOCK_NONBLOCK); 1019 if (s < 0) 1020 return; 1021 1022 len = sizeof(addr); 1023 err = xgetsockname(s, sockaddr(&addr), &len); 1024 if (err) 1025 goto close_srv; 1026 1027 c0 = xsocket(family, sotype, 0); 1028 if (c0 < 0) 1029 goto close_srv; 1030 err = xconnect(c0, sockaddr(&addr), len); 1031 if (err) 1032 goto close_cli0; 1033 1034 p0 = xaccept_nonblock(s, NULL, NULL); 1035 if (p0 < 0) 1036 goto close_cli0; 1037 1038 c1 = xsocket(family, sotype, 0); 1039 if (c1 < 0) 1040 goto close_peer0; 1041 err = xconnect(c1, sockaddr(&addr), len); 1042 if (err) 1043 goto close_cli1; 1044 1045 p1 = xaccept_nonblock(s, NULL, NULL); 1046 if (p1 < 0) 1047 goto close_cli1; 1048 1049 err = add_to_sockmap(sock_mapfd, p0, p1); 1050 if (err) 1051 goto close_peer1; 1052 1053 n = write(mode == REDIR_INGRESS ? c1 : p1, "a", 1); 1054 if (n < 0) 1055 FAIL_ERRNO("%s: write", log_prefix); 1056 if (n == 0) 1057 FAIL("%s: incomplete write", log_prefix); 1058 if (n < 1) 1059 goto close_peer1; 1060 1061 key = SK_PASS; 1062 err = xbpf_map_lookup_elem(verd_mapfd, &key, &pass); 1063 if (err) 1064 goto close_peer1; 1065 if (pass != 1) 1066 FAIL("%s: want pass count 1, have %d", log_prefix, pass); 1067 n = recv_timeout(c0, &b, 1, 0, IO_TIMEOUT_SEC); 1068 if (n < 0) 1069 FAIL_ERRNO("%s: recv_timeout", log_prefix); 1070 if (n == 0) 1071 FAIL("%s: incomplete recv", log_prefix); 1072 1073 close_peer1: 1074 xclose(p1); 1075 close_cli1: 1076 xclose(c1); 1077 close_peer0: 1078 xclose(p0); 1079 close_cli0: 1080 xclose(c0); 1081 close_srv: 1082 xclose(s); 1083 } 1084 1085 static void test_skb_redir_to_connected(struct test_sockmap_listen *skel, 1086 struct bpf_map *inner_map, int family, 1087 int sotype) 1088 { 1089 int verdict = bpf_program__fd(skel->progs.prog_stream_verdict); 1090 int parser = bpf_program__fd(skel->progs.prog_stream_parser); 1091 int verdict_map = bpf_map__fd(skel->maps.verdict_map); 1092 int sock_map = bpf_map__fd(inner_map); 1093 int err; 1094 1095 err = xbpf_prog_attach(parser, sock_map, BPF_SK_SKB_STREAM_PARSER, 0); 1096 if (err) 1097 return; 1098 err = xbpf_prog_attach(verdict, sock_map, BPF_SK_SKB_STREAM_VERDICT, 0); 1099 if (err) 1100 goto detach; 1101 1102 redir_to_connected(family, sotype, sock_map, verdict_map, 1103 REDIR_INGRESS); 1104 1105 xbpf_prog_detach2(verdict, sock_map, BPF_SK_SKB_STREAM_VERDICT); 1106 detach: 1107 xbpf_prog_detach2(parser, sock_map, BPF_SK_SKB_STREAM_PARSER); 1108 } 1109 1110 static void test_msg_redir_to_connected(struct test_sockmap_listen *skel, 1111 struct bpf_map *inner_map, int family, 1112 int sotype) 1113 { 1114 int verdict = bpf_program__fd(skel->progs.prog_msg_verdict); 1115 int verdict_map = bpf_map__fd(skel->maps.verdict_map); 1116 int sock_map = bpf_map__fd(inner_map); 1117 int err; 1118 1119 err = xbpf_prog_attach(verdict, sock_map, BPF_SK_MSG_VERDICT, 0); 1120 if (err) 1121 return; 1122 1123 redir_to_connected(family, sotype, sock_map, verdict_map, REDIR_EGRESS); 1124 1125 xbpf_prog_detach2(verdict, sock_map, BPF_SK_MSG_VERDICT); 1126 } 1127 1128 static void redir_to_listening(int family, int sotype, int sock_mapfd, 1129 int verd_mapfd, enum redir_mode mode) 1130 { 1131 const char *log_prefix = redir_mode_str(mode); 1132 struct sockaddr_storage addr; 1133 int s, c, p, err, n; 1134 unsigned int drop; 1135 socklen_t len; 1136 u32 key; 1137 1138 zero_verdict_count(verd_mapfd); 1139 1140 s = socket_loopback(family, sotype | SOCK_NONBLOCK); 1141 if (s < 0) 1142 return; 1143 1144 len = sizeof(addr); 1145 err = xgetsockname(s, sockaddr(&addr), &len); 1146 if (err) 1147 goto close_srv; 1148 1149 c = xsocket(family, sotype, 0); 1150 if (c < 0) 1151 goto close_srv; 1152 err = xconnect(c, sockaddr(&addr), len); 1153 if (err) 1154 goto close_cli; 1155 1156 p = xaccept_nonblock(s, NULL, NULL); 1157 if (p < 0) 1158 goto close_cli; 1159 1160 err = add_to_sockmap(sock_mapfd, s, p); 1161 if (err) 1162 goto close_peer; 1163 1164 n = write(mode == REDIR_INGRESS ? c : p, "a", 1); 1165 if (n < 0 && errno != EACCES) 1166 FAIL_ERRNO("%s: write", log_prefix); 1167 if (n == 0) 1168 FAIL("%s: incomplete write", log_prefix); 1169 if (n < 1) 1170 goto close_peer; 1171 1172 key = SK_DROP; 1173 err = xbpf_map_lookup_elem(verd_mapfd, &key, &drop); 1174 if (err) 1175 goto close_peer; 1176 if (drop != 1) 1177 FAIL("%s: want drop count 1, have %d", log_prefix, drop); 1178 1179 close_peer: 1180 xclose(p); 1181 close_cli: 1182 xclose(c); 1183 close_srv: 1184 xclose(s); 1185 } 1186 1187 static void test_skb_redir_to_listening(struct test_sockmap_listen *skel, 1188 struct bpf_map *inner_map, int family, 1189 int sotype) 1190 { 1191 int verdict = bpf_program__fd(skel->progs.prog_stream_verdict); 1192 int parser = bpf_program__fd(skel->progs.prog_stream_parser); 1193 int verdict_map = bpf_map__fd(skel->maps.verdict_map); 1194 int sock_map = bpf_map__fd(inner_map); 1195 int err; 1196 1197 err = xbpf_prog_attach(parser, sock_map, BPF_SK_SKB_STREAM_PARSER, 0); 1198 if (err) 1199 return; 1200 err = xbpf_prog_attach(verdict, sock_map, BPF_SK_SKB_STREAM_VERDICT, 0); 1201 if (err) 1202 goto detach; 1203 1204 redir_to_listening(family, sotype, sock_map, verdict_map, 1205 REDIR_INGRESS); 1206 1207 xbpf_prog_detach2(verdict, sock_map, BPF_SK_SKB_STREAM_VERDICT); 1208 detach: 1209 xbpf_prog_detach2(parser, sock_map, BPF_SK_SKB_STREAM_PARSER); 1210 } 1211 1212 static void test_msg_redir_to_listening(struct test_sockmap_listen *skel, 1213 struct bpf_map *inner_map, int family, 1214 int sotype) 1215 { 1216 int verdict = bpf_program__fd(skel->progs.prog_msg_verdict); 1217 int verdict_map = bpf_map__fd(skel->maps.verdict_map); 1218 int sock_map = bpf_map__fd(inner_map); 1219 int err; 1220 1221 err = xbpf_prog_attach(verdict, sock_map, BPF_SK_MSG_VERDICT, 0); 1222 if (err) 1223 return; 1224 1225 redir_to_listening(family, sotype, sock_map, verdict_map, REDIR_EGRESS); 1226 1227 xbpf_prog_detach2(verdict, sock_map, BPF_SK_MSG_VERDICT); 1228 } 1229 1230 static void test_reuseport_select_listening(int family, int sotype, 1231 int sock_map, int verd_map, 1232 int reuseport_prog) 1233 { 1234 struct sockaddr_storage addr; 1235 unsigned int pass; 1236 int s, c, err; 1237 socklen_t len; 1238 u64 value; 1239 u32 key; 1240 1241 zero_verdict_count(verd_map); 1242 1243 s = socket_loopback_reuseport(family, sotype | SOCK_NONBLOCK, 1244 reuseport_prog); 1245 if (s < 0) 1246 return; 1247 1248 len = sizeof(addr); 1249 err = xgetsockname(s, sockaddr(&addr), &len); 1250 if (err) 1251 goto close_srv; 1252 1253 key = 0; 1254 value = s; 1255 err = xbpf_map_update_elem(sock_map, &key, &value, BPF_NOEXIST); 1256 if (err) 1257 goto close_srv; 1258 1259 c = xsocket(family, sotype, 0); 1260 if (c < 0) 1261 goto close_srv; 1262 err = xconnect(c, sockaddr(&addr), len); 1263 if (err) 1264 goto close_cli; 1265 1266 if (sotype == SOCK_STREAM) { 1267 int p; 1268 1269 p = xaccept_nonblock(s, NULL, NULL); 1270 if (p < 0) 1271 goto close_cli; 1272 xclose(p); 1273 } else { 1274 char b = 'a'; 1275 ssize_t n; 1276 1277 n = xsend(c, &b, sizeof(b), 0); 1278 if (n == -1) 1279 goto close_cli; 1280 1281 n = xrecv_nonblock(s, &b, sizeof(b), 0); 1282 if (n == -1) 1283 goto close_cli; 1284 } 1285 1286 key = SK_PASS; 1287 err = xbpf_map_lookup_elem(verd_map, &key, &pass); 1288 if (err) 1289 goto close_cli; 1290 if (pass != 1) 1291 FAIL("want pass count 1, have %d", pass); 1292 1293 close_cli: 1294 xclose(c); 1295 close_srv: 1296 xclose(s); 1297 } 1298 1299 static void test_reuseport_select_connected(int family, int sotype, 1300 int sock_map, int verd_map, 1301 int reuseport_prog) 1302 { 1303 struct sockaddr_storage addr; 1304 int s, c0, c1, p0, err; 1305 unsigned int drop; 1306 socklen_t len; 1307 u64 value; 1308 u32 key; 1309 1310 zero_verdict_count(verd_map); 1311 1312 s = socket_loopback_reuseport(family, sotype, reuseport_prog); 1313 if (s < 0) 1314 return; 1315 1316 /* Populate sock_map[0] to avoid ENOENT on first connection */ 1317 key = 0; 1318 value = s; 1319 err = xbpf_map_update_elem(sock_map, &key, &value, BPF_NOEXIST); 1320 if (err) 1321 goto close_srv; 1322 1323 len = sizeof(addr); 1324 err = xgetsockname(s, sockaddr(&addr), &len); 1325 if (err) 1326 goto close_srv; 1327 1328 c0 = xsocket(family, sotype, 0); 1329 if (c0 < 0) 1330 goto close_srv; 1331 1332 err = xconnect(c0, sockaddr(&addr), len); 1333 if (err) 1334 goto close_cli0; 1335 1336 if (sotype == SOCK_STREAM) { 1337 p0 = xaccept_nonblock(s, NULL, NULL); 1338 if (p0 < 0) 1339 goto close_cli0; 1340 } else { 1341 p0 = xsocket(family, sotype, 0); 1342 if (p0 < 0) 1343 goto close_cli0; 1344 1345 len = sizeof(addr); 1346 err = xgetsockname(c0, sockaddr(&addr), &len); 1347 if (err) 1348 goto close_cli0; 1349 1350 err = xconnect(p0, sockaddr(&addr), len); 1351 if (err) 1352 goto close_cli0; 1353 } 1354 1355 /* Update sock_map[0] to redirect to a connected socket */ 1356 key = 0; 1357 value = p0; 1358 err = xbpf_map_update_elem(sock_map, &key, &value, BPF_EXIST); 1359 if (err) 1360 goto close_peer0; 1361 1362 c1 = xsocket(family, sotype, 0); 1363 if (c1 < 0) 1364 goto close_peer0; 1365 1366 len = sizeof(addr); 1367 err = xgetsockname(s, sockaddr(&addr), &len); 1368 if (err) 1369 goto close_srv; 1370 1371 errno = 0; 1372 err = connect(c1, sockaddr(&addr), len); 1373 if (sotype == SOCK_DGRAM) { 1374 char b = 'a'; 1375 ssize_t n; 1376 1377 n = xsend(c1, &b, sizeof(b), 0); 1378 if (n == -1) 1379 goto close_cli1; 1380 1381 n = recv_timeout(c1, &b, sizeof(b), 0, IO_TIMEOUT_SEC); 1382 err = n == -1; 1383 } 1384 if (!err || errno != ECONNREFUSED) 1385 FAIL_ERRNO("connect: expected ECONNREFUSED"); 1386 1387 key = SK_DROP; 1388 err = xbpf_map_lookup_elem(verd_map, &key, &drop); 1389 if (err) 1390 goto close_cli1; 1391 if (drop != 1) 1392 FAIL("want drop count 1, have %d", drop); 1393 1394 close_cli1: 1395 xclose(c1); 1396 close_peer0: 1397 xclose(p0); 1398 close_cli0: 1399 xclose(c0); 1400 close_srv: 1401 xclose(s); 1402 } 1403 1404 /* Check that redirecting across reuseport groups is not allowed. */ 1405 static void test_reuseport_mixed_groups(int family, int sotype, int sock_map, 1406 int verd_map, int reuseport_prog) 1407 { 1408 struct sockaddr_storage addr; 1409 int s1, s2, c, err; 1410 unsigned int drop; 1411 socklen_t len; 1412 u32 key; 1413 1414 zero_verdict_count(verd_map); 1415 1416 /* Create two listeners, each in its own reuseport group */ 1417 s1 = socket_loopback_reuseport(family, sotype, reuseport_prog); 1418 if (s1 < 0) 1419 return; 1420 1421 s2 = socket_loopback_reuseport(family, sotype, reuseport_prog); 1422 if (s2 < 0) 1423 goto close_srv1; 1424 1425 err = add_to_sockmap(sock_map, s1, s2); 1426 if (err) 1427 goto close_srv2; 1428 1429 /* Connect to s2, reuseport BPF selects s1 via sock_map[0] */ 1430 len = sizeof(addr); 1431 err = xgetsockname(s2, sockaddr(&addr), &len); 1432 if (err) 1433 goto close_srv2; 1434 1435 c = xsocket(family, sotype, 0); 1436 if (c < 0) 1437 goto close_srv2; 1438 1439 err = connect(c, sockaddr(&addr), len); 1440 if (sotype == SOCK_DGRAM) { 1441 char b = 'a'; 1442 ssize_t n; 1443 1444 n = xsend(c, &b, sizeof(b), 0); 1445 if (n == -1) 1446 goto close_cli; 1447 1448 n = recv_timeout(c, &b, sizeof(b), 0, IO_TIMEOUT_SEC); 1449 err = n == -1; 1450 } 1451 if (!err || errno != ECONNREFUSED) { 1452 FAIL_ERRNO("connect: expected ECONNREFUSED"); 1453 goto close_cli; 1454 } 1455 1456 /* Expect drop, can't redirect outside of reuseport group */ 1457 key = SK_DROP; 1458 err = xbpf_map_lookup_elem(verd_map, &key, &drop); 1459 if (err) 1460 goto close_cli; 1461 if (drop != 1) 1462 FAIL("want drop count 1, have %d", drop); 1463 1464 close_cli: 1465 xclose(c); 1466 close_srv2: 1467 xclose(s2); 1468 close_srv1: 1469 xclose(s1); 1470 } 1471 1472 #define TEST(fn, ...) \ 1473 { \ 1474 fn, #fn, __VA_ARGS__ \ 1475 } 1476 1477 static void test_ops_cleanup(const struct bpf_map *map) 1478 { 1479 int err, mapfd; 1480 u32 key; 1481 1482 mapfd = bpf_map__fd(map); 1483 1484 for (key = 0; key < bpf_map__max_entries(map); key++) { 1485 err = bpf_map_delete_elem(mapfd, &key); 1486 if (err && errno != EINVAL && errno != ENOENT) 1487 FAIL_ERRNO("map_delete: expected EINVAL/ENOENT"); 1488 } 1489 } 1490 1491 static const char *family_str(sa_family_t family) 1492 { 1493 switch (family) { 1494 case AF_INET: 1495 return "IPv4"; 1496 case AF_INET6: 1497 return "IPv6"; 1498 case AF_UNIX: 1499 return "Unix"; 1500 case AF_VSOCK: 1501 return "VSOCK"; 1502 default: 1503 return "unknown"; 1504 } 1505 } 1506 1507 static const char *map_type_str(const struct bpf_map *map) 1508 { 1509 int type; 1510 1511 if (!map) 1512 return "invalid"; 1513 type = bpf_map__type(map); 1514 1515 switch (type) { 1516 case BPF_MAP_TYPE_SOCKMAP: 1517 return "sockmap"; 1518 case BPF_MAP_TYPE_SOCKHASH: 1519 return "sockhash"; 1520 default: 1521 return "unknown"; 1522 } 1523 } 1524 1525 static const char *sotype_str(int sotype) 1526 { 1527 switch (sotype) { 1528 case SOCK_DGRAM: 1529 return "UDP"; 1530 case SOCK_STREAM: 1531 return "TCP"; 1532 default: 1533 return "unknown"; 1534 } 1535 } 1536 1537 static void test_ops(struct test_sockmap_listen *skel, struct bpf_map *map, 1538 int family, int sotype) 1539 { 1540 const struct op_test { 1541 void (*fn)(struct test_sockmap_listen *skel, 1542 int family, int sotype, int mapfd); 1543 const char *name; 1544 int sotype; 1545 } tests[] = { 1546 /* insert */ 1547 TEST(test_insert_invalid), 1548 TEST(test_insert_opened), 1549 TEST(test_insert_bound, SOCK_STREAM), 1550 TEST(test_insert), 1551 /* delete */ 1552 TEST(test_delete_after_insert), 1553 TEST(test_delete_after_close), 1554 /* lookup */ 1555 TEST(test_lookup_after_insert), 1556 TEST(test_lookup_after_delete), 1557 TEST(test_lookup_32_bit_value), 1558 /* update */ 1559 TEST(test_update_existing), 1560 /* races with insert/delete */ 1561 TEST(test_destroy_orphan_child, SOCK_STREAM), 1562 TEST(test_syn_recv_insert_delete, SOCK_STREAM), 1563 TEST(test_race_insert_listen, SOCK_STREAM), 1564 /* child clone */ 1565 TEST(test_clone_after_delete, SOCK_STREAM), 1566 TEST(test_accept_after_delete, SOCK_STREAM), 1567 TEST(test_accept_before_delete, SOCK_STREAM), 1568 }; 1569 const char *family_name, *map_name, *sotype_name; 1570 const struct op_test *t; 1571 char s[MAX_TEST_NAME]; 1572 int map_fd; 1573 1574 family_name = family_str(family); 1575 map_name = map_type_str(map); 1576 sotype_name = sotype_str(sotype); 1577 map_fd = bpf_map__fd(map); 1578 1579 for (t = tests; t < tests + ARRAY_SIZE(tests); t++) { 1580 snprintf(s, sizeof(s), "%s %s %s %s", map_name, family_name, 1581 sotype_name, t->name); 1582 1583 if (t->sotype != 0 && t->sotype != sotype) 1584 continue; 1585 1586 if (!test__start_subtest(s)) 1587 continue; 1588 1589 t->fn(skel, family, sotype, map_fd); 1590 test_ops_cleanup(map); 1591 } 1592 } 1593 1594 static void test_redir(struct test_sockmap_listen *skel, struct bpf_map *map, 1595 int family, int sotype) 1596 { 1597 const struct redir_test { 1598 void (*fn)(struct test_sockmap_listen *skel, 1599 struct bpf_map *map, int family, int sotype); 1600 const char *name; 1601 } tests[] = { 1602 TEST(test_skb_redir_to_connected), 1603 TEST(test_skb_redir_to_listening), 1604 TEST(test_msg_redir_to_connected), 1605 TEST(test_msg_redir_to_listening), 1606 }; 1607 const char *family_name, *map_name; 1608 const struct redir_test *t; 1609 char s[MAX_TEST_NAME]; 1610 1611 family_name = family_str(family); 1612 map_name = map_type_str(map); 1613 1614 for (t = tests; t < tests + ARRAY_SIZE(tests); t++) { 1615 snprintf(s, sizeof(s), "%s %s %s", map_name, family_name, 1616 t->name); 1617 1618 if (!test__start_subtest(s)) 1619 continue; 1620 1621 t->fn(skel, map, family, sotype); 1622 } 1623 } 1624 1625 static void unix_redir_to_connected(int sotype, int sock_mapfd, 1626 int verd_mapfd, enum redir_mode mode) 1627 { 1628 const char *log_prefix = redir_mode_str(mode); 1629 int c0, c1, p0, p1; 1630 unsigned int pass; 1631 int err, n; 1632 int sfd[2]; 1633 u32 key; 1634 char b; 1635 1636 zero_verdict_count(verd_mapfd); 1637 1638 if (socketpair(AF_UNIX, sotype | SOCK_NONBLOCK, 0, sfd)) 1639 return; 1640 c0 = sfd[0], p0 = sfd[1]; 1641 1642 if (socketpair(AF_UNIX, sotype | SOCK_NONBLOCK, 0, sfd)) 1643 goto close0; 1644 c1 = sfd[0], p1 = sfd[1]; 1645 1646 err = add_to_sockmap(sock_mapfd, p0, p1); 1647 if (err) 1648 goto close; 1649 1650 n = write(c1, "a", 1); 1651 if (n < 0) 1652 FAIL_ERRNO("%s: write", log_prefix); 1653 if (n == 0) 1654 FAIL("%s: incomplete write", log_prefix); 1655 if (n < 1) 1656 goto close; 1657 1658 key = SK_PASS; 1659 err = xbpf_map_lookup_elem(verd_mapfd, &key, &pass); 1660 if (err) 1661 goto close; 1662 if (pass != 1) 1663 FAIL("%s: want pass count 1, have %d", log_prefix, pass); 1664 1665 n = recv_timeout(mode == REDIR_INGRESS ? p0 : c0, &b, 1, 0, IO_TIMEOUT_SEC); 1666 if (n < 0) 1667 FAIL_ERRNO("%s: recv_timeout", log_prefix); 1668 if (n == 0) 1669 FAIL("%s: incomplete recv", log_prefix); 1670 1671 close: 1672 xclose(c1); 1673 xclose(p1); 1674 close0: 1675 xclose(c0); 1676 xclose(p0); 1677 } 1678 1679 static void unix_skb_redir_to_connected(struct test_sockmap_listen *skel, 1680 struct bpf_map *inner_map, int sotype) 1681 { 1682 int verdict = bpf_program__fd(skel->progs.prog_skb_verdict); 1683 int verdict_map = bpf_map__fd(skel->maps.verdict_map); 1684 int sock_map = bpf_map__fd(inner_map); 1685 int err; 1686 1687 err = xbpf_prog_attach(verdict, sock_map, BPF_SK_SKB_VERDICT, 0); 1688 if (err) 1689 return; 1690 1691 skel->bss->test_ingress = false; 1692 unix_redir_to_connected(sotype, sock_map, verdict_map, REDIR_EGRESS); 1693 skel->bss->test_ingress = true; 1694 unix_redir_to_connected(sotype, sock_map, verdict_map, REDIR_INGRESS); 1695 1696 xbpf_prog_detach2(verdict, sock_map, BPF_SK_SKB_VERDICT); 1697 } 1698 1699 static void test_unix_redir(struct test_sockmap_listen *skel, struct bpf_map *map, 1700 int sotype) 1701 { 1702 const char *family_name, *map_name; 1703 char s[MAX_TEST_NAME]; 1704 1705 family_name = family_str(AF_UNIX); 1706 map_name = map_type_str(map); 1707 snprintf(s, sizeof(s), "%s %s %s", map_name, family_name, __func__); 1708 if (!test__start_subtest(s)) 1709 return; 1710 unix_skb_redir_to_connected(skel, map, sotype); 1711 } 1712 1713 /* Returns two connected loopback vsock sockets */ 1714 static int vsock_socketpair_connectible(int sotype, int *v0, int *v1) 1715 { 1716 struct sockaddr_storage addr; 1717 socklen_t len = sizeof(addr); 1718 int s, p, c; 1719 1720 s = socket_loopback(AF_VSOCK, sotype); 1721 if (s < 0) 1722 return -1; 1723 1724 c = xsocket(AF_VSOCK, sotype | SOCK_NONBLOCK, 0); 1725 if (c == -1) 1726 goto close_srv; 1727 1728 if (getsockname(s, sockaddr(&addr), &len) < 0) 1729 goto close_cli; 1730 1731 if (connect(c, sockaddr(&addr), len) < 0 && errno != EINPROGRESS) { 1732 FAIL_ERRNO("connect"); 1733 goto close_cli; 1734 } 1735 1736 len = sizeof(addr); 1737 p = accept_timeout(s, sockaddr(&addr), &len, IO_TIMEOUT_SEC); 1738 if (p < 0) 1739 goto close_cli; 1740 1741 *v0 = p; 1742 *v1 = c; 1743 1744 return 0; 1745 1746 close_cli: 1747 close(c); 1748 close_srv: 1749 close(s); 1750 1751 return -1; 1752 } 1753 1754 static void vsock_unix_redir_connectible(int sock_mapfd, int verd_mapfd, 1755 enum redir_mode mode, int sotype) 1756 { 1757 const char *log_prefix = redir_mode_str(mode); 1758 char a = 'a', b = 'b'; 1759 int u0, u1, v0, v1; 1760 int sfd[2]; 1761 unsigned int pass; 1762 int err, n; 1763 u32 key; 1764 1765 zero_verdict_count(verd_mapfd); 1766 1767 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, sfd)) 1768 return; 1769 1770 u0 = sfd[0]; 1771 u1 = sfd[1]; 1772 1773 err = vsock_socketpair_connectible(sotype, &v0, &v1); 1774 if (err) { 1775 FAIL("vsock_socketpair_connectible() failed"); 1776 goto close_uds; 1777 } 1778 1779 err = add_to_sockmap(sock_mapfd, u0, v0); 1780 if (err) { 1781 FAIL("add_to_sockmap failed"); 1782 goto close_vsock; 1783 } 1784 1785 n = write(v1, &a, sizeof(a)); 1786 if (n < 0) 1787 FAIL_ERRNO("%s: write", log_prefix); 1788 if (n == 0) 1789 FAIL("%s: incomplete write", log_prefix); 1790 if (n < 1) 1791 goto out; 1792 1793 n = recv(mode == REDIR_INGRESS ? u0 : u1, &b, sizeof(b), MSG_DONTWAIT); 1794 if (n < 0) 1795 FAIL("%s: recv() err, errno=%d", log_prefix, errno); 1796 if (n == 0) 1797 FAIL("%s: incomplete recv", log_prefix); 1798 if (b != a) 1799 FAIL("%s: vsock socket map failed, %c != %c", log_prefix, a, b); 1800 1801 key = SK_PASS; 1802 err = xbpf_map_lookup_elem(verd_mapfd, &key, &pass); 1803 if (err) 1804 goto out; 1805 if (pass != 1) 1806 FAIL("%s: want pass count 1, have %d", log_prefix, pass); 1807 out: 1808 key = 0; 1809 bpf_map_delete_elem(sock_mapfd, &key); 1810 key = 1; 1811 bpf_map_delete_elem(sock_mapfd, &key); 1812 1813 close_vsock: 1814 close(v0); 1815 close(v1); 1816 1817 close_uds: 1818 close(u0); 1819 close(u1); 1820 } 1821 1822 static void vsock_unix_skb_redir_connectible(struct test_sockmap_listen *skel, 1823 struct bpf_map *inner_map, 1824 int sotype) 1825 { 1826 int verdict = bpf_program__fd(skel->progs.prog_skb_verdict); 1827 int verdict_map = bpf_map__fd(skel->maps.verdict_map); 1828 int sock_map = bpf_map__fd(inner_map); 1829 int err; 1830 1831 err = xbpf_prog_attach(verdict, sock_map, BPF_SK_SKB_VERDICT, 0); 1832 if (err) 1833 return; 1834 1835 skel->bss->test_ingress = false; 1836 vsock_unix_redir_connectible(sock_map, verdict_map, REDIR_EGRESS, sotype); 1837 skel->bss->test_ingress = true; 1838 vsock_unix_redir_connectible(sock_map, verdict_map, REDIR_INGRESS, sotype); 1839 1840 xbpf_prog_detach2(verdict, sock_map, BPF_SK_SKB_VERDICT); 1841 } 1842 1843 static void test_vsock_redir(struct test_sockmap_listen *skel, struct bpf_map *map) 1844 { 1845 const char *family_name, *map_name; 1846 char s[MAX_TEST_NAME]; 1847 1848 family_name = family_str(AF_VSOCK); 1849 map_name = map_type_str(map); 1850 snprintf(s, sizeof(s), "%s %s %s", map_name, family_name, __func__); 1851 if (!test__start_subtest(s)) 1852 return; 1853 1854 vsock_unix_skb_redir_connectible(skel, map, SOCK_STREAM); 1855 vsock_unix_skb_redir_connectible(skel, map, SOCK_SEQPACKET); 1856 } 1857 1858 static void test_reuseport(struct test_sockmap_listen *skel, 1859 struct bpf_map *map, int family, int sotype) 1860 { 1861 const struct reuseport_test { 1862 void (*fn)(int family, int sotype, int socket_map, 1863 int verdict_map, int reuseport_prog); 1864 const char *name; 1865 int sotype; 1866 } tests[] = { 1867 TEST(test_reuseport_select_listening), 1868 TEST(test_reuseport_select_connected), 1869 TEST(test_reuseport_mixed_groups), 1870 }; 1871 int socket_map, verdict_map, reuseport_prog; 1872 const char *family_name, *map_name, *sotype_name; 1873 const struct reuseport_test *t; 1874 char s[MAX_TEST_NAME]; 1875 1876 family_name = family_str(family); 1877 map_name = map_type_str(map); 1878 sotype_name = sotype_str(sotype); 1879 1880 socket_map = bpf_map__fd(map); 1881 verdict_map = bpf_map__fd(skel->maps.verdict_map); 1882 reuseport_prog = bpf_program__fd(skel->progs.prog_reuseport); 1883 1884 for (t = tests; t < tests + ARRAY_SIZE(tests); t++) { 1885 snprintf(s, sizeof(s), "%s %s %s %s", map_name, family_name, 1886 sotype_name, t->name); 1887 1888 if (t->sotype != 0 && t->sotype != sotype) 1889 continue; 1890 1891 if (!test__start_subtest(s)) 1892 continue; 1893 1894 t->fn(family, sotype, socket_map, verdict_map, reuseport_prog); 1895 } 1896 } 1897 1898 static int inet_socketpair(int family, int type, int *s, int *c) 1899 { 1900 struct sockaddr_storage addr; 1901 socklen_t len; 1902 int p0, c0; 1903 int err; 1904 1905 p0 = socket_loopback(family, type | SOCK_NONBLOCK); 1906 if (p0 < 0) 1907 return p0; 1908 1909 len = sizeof(addr); 1910 err = xgetsockname(p0, sockaddr(&addr), &len); 1911 if (err) 1912 goto close_peer0; 1913 1914 c0 = xsocket(family, type | SOCK_NONBLOCK, 0); 1915 if (c0 < 0) { 1916 err = c0; 1917 goto close_peer0; 1918 } 1919 err = xconnect(c0, sockaddr(&addr), len); 1920 if (err) 1921 goto close_cli0; 1922 err = xgetsockname(c0, sockaddr(&addr), &len); 1923 if (err) 1924 goto close_cli0; 1925 err = xconnect(p0, sockaddr(&addr), len); 1926 if (err) 1927 goto close_cli0; 1928 1929 *s = p0; 1930 *c = c0; 1931 return 0; 1932 1933 close_cli0: 1934 xclose(c0); 1935 close_peer0: 1936 xclose(p0); 1937 return err; 1938 } 1939 1940 static void udp_redir_to_connected(int family, int sock_mapfd, int verd_mapfd, 1941 enum redir_mode mode) 1942 { 1943 const char *log_prefix = redir_mode_str(mode); 1944 int c0, c1, p0, p1; 1945 unsigned int pass; 1946 int err, n; 1947 u32 key; 1948 char b; 1949 1950 zero_verdict_count(verd_mapfd); 1951 1952 err = inet_socketpair(family, SOCK_DGRAM, &p0, &c0); 1953 if (err) 1954 return; 1955 err = inet_socketpair(family, SOCK_DGRAM, &p1, &c1); 1956 if (err) 1957 goto close_cli0; 1958 1959 err = add_to_sockmap(sock_mapfd, p0, p1); 1960 if (err) 1961 goto close_cli1; 1962 1963 n = write(c1, "a", 1); 1964 if (n < 0) 1965 FAIL_ERRNO("%s: write", log_prefix); 1966 if (n == 0) 1967 FAIL("%s: incomplete write", log_prefix); 1968 if (n < 1) 1969 goto close_cli1; 1970 1971 key = SK_PASS; 1972 err = xbpf_map_lookup_elem(verd_mapfd, &key, &pass); 1973 if (err) 1974 goto close_cli1; 1975 if (pass != 1) 1976 FAIL("%s: want pass count 1, have %d", log_prefix, pass); 1977 1978 n = recv_timeout(mode == REDIR_INGRESS ? p0 : c0, &b, 1, 0, IO_TIMEOUT_SEC); 1979 if (n < 0) 1980 FAIL_ERRNO("%s: recv_timeout", log_prefix); 1981 if (n == 0) 1982 FAIL("%s: incomplete recv", log_prefix); 1983 1984 close_cli1: 1985 xclose(c1); 1986 xclose(p1); 1987 close_cli0: 1988 xclose(c0); 1989 xclose(p0); 1990 } 1991 1992 static void udp_skb_redir_to_connected(struct test_sockmap_listen *skel, 1993 struct bpf_map *inner_map, int family) 1994 { 1995 int verdict = bpf_program__fd(skel->progs.prog_skb_verdict); 1996 int verdict_map = bpf_map__fd(skel->maps.verdict_map); 1997 int sock_map = bpf_map__fd(inner_map); 1998 int err; 1999 2000 err = xbpf_prog_attach(verdict, sock_map, BPF_SK_SKB_VERDICT, 0); 2001 if (err) 2002 return; 2003 2004 skel->bss->test_ingress = false; 2005 udp_redir_to_connected(family, sock_map, verdict_map, REDIR_EGRESS); 2006 skel->bss->test_ingress = true; 2007 udp_redir_to_connected(family, sock_map, verdict_map, REDIR_INGRESS); 2008 2009 xbpf_prog_detach2(verdict, sock_map, BPF_SK_SKB_VERDICT); 2010 } 2011 2012 static void test_udp_redir(struct test_sockmap_listen *skel, struct bpf_map *map, 2013 int family) 2014 { 2015 const char *family_name, *map_name; 2016 char s[MAX_TEST_NAME]; 2017 2018 family_name = family_str(family); 2019 map_name = map_type_str(map); 2020 snprintf(s, sizeof(s), "%s %s %s", map_name, family_name, __func__); 2021 if (!test__start_subtest(s)) 2022 return; 2023 udp_skb_redir_to_connected(skel, map, family); 2024 } 2025 2026 static void inet_unix_redir_to_connected(int family, int type, int sock_mapfd, 2027 int verd_mapfd, enum redir_mode mode) 2028 { 2029 const char *log_prefix = redir_mode_str(mode); 2030 int c0, c1, p0, p1; 2031 unsigned int pass; 2032 int err, n; 2033 int sfd[2]; 2034 u32 key; 2035 char b; 2036 2037 zero_verdict_count(verd_mapfd); 2038 2039 if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0, sfd)) 2040 return; 2041 c0 = sfd[0], p0 = sfd[1]; 2042 2043 err = inet_socketpair(family, SOCK_DGRAM, &p1, &c1); 2044 if (err) 2045 goto close; 2046 2047 err = add_to_sockmap(sock_mapfd, p0, p1); 2048 if (err) 2049 goto close_cli1; 2050 2051 n = write(c1, "a", 1); 2052 if (n < 0) 2053 FAIL_ERRNO("%s: write", log_prefix); 2054 if (n == 0) 2055 FAIL("%s: incomplete write", log_prefix); 2056 if (n < 1) 2057 goto close_cli1; 2058 2059 key = SK_PASS; 2060 err = xbpf_map_lookup_elem(verd_mapfd, &key, &pass); 2061 if (err) 2062 goto close_cli1; 2063 if (pass != 1) 2064 FAIL("%s: want pass count 1, have %d", log_prefix, pass); 2065 2066 n = recv_timeout(mode == REDIR_INGRESS ? p0 : c0, &b, 1, 0, IO_TIMEOUT_SEC); 2067 if (n < 0) 2068 FAIL_ERRNO("%s: recv_timeout", log_prefix); 2069 if (n == 0) 2070 FAIL("%s: incomplete recv", log_prefix); 2071 2072 close_cli1: 2073 xclose(c1); 2074 xclose(p1); 2075 close: 2076 xclose(c0); 2077 xclose(p0); 2078 } 2079 2080 static void inet_unix_skb_redir_to_connected(struct test_sockmap_listen *skel, 2081 struct bpf_map *inner_map, int family) 2082 { 2083 int verdict = bpf_program__fd(skel->progs.prog_skb_verdict); 2084 int verdict_map = bpf_map__fd(skel->maps.verdict_map); 2085 int sock_map = bpf_map__fd(inner_map); 2086 int err; 2087 2088 err = xbpf_prog_attach(verdict, sock_map, BPF_SK_SKB_VERDICT, 0); 2089 if (err) 2090 return; 2091 2092 skel->bss->test_ingress = false; 2093 inet_unix_redir_to_connected(family, SOCK_DGRAM, sock_map, verdict_map, 2094 REDIR_EGRESS); 2095 inet_unix_redir_to_connected(family, SOCK_STREAM, sock_map, verdict_map, 2096 REDIR_EGRESS); 2097 skel->bss->test_ingress = true; 2098 inet_unix_redir_to_connected(family, SOCK_DGRAM, sock_map, verdict_map, 2099 REDIR_INGRESS); 2100 inet_unix_redir_to_connected(family, SOCK_STREAM, sock_map, verdict_map, 2101 REDIR_INGRESS); 2102 2103 xbpf_prog_detach2(verdict, sock_map, BPF_SK_SKB_VERDICT); 2104 } 2105 2106 static void unix_inet_redir_to_connected(int family, int type, int sock_mapfd, 2107 int verd_mapfd, enum redir_mode mode) 2108 { 2109 const char *log_prefix = redir_mode_str(mode); 2110 int c0, c1, p0, p1; 2111 unsigned int pass; 2112 int err, n; 2113 int sfd[2]; 2114 u32 key; 2115 char b; 2116 2117 zero_verdict_count(verd_mapfd); 2118 2119 err = inet_socketpair(family, SOCK_DGRAM, &p0, &c0); 2120 if (err) 2121 return; 2122 2123 if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0, sfd)) 2124 goto close_cli0; 2125 c1 = sfd[0], p1 = sfd[1]; 2126 2127 err = add_to_sockmap(sock_mapfd, p0, p1); 2128 if (err) 2129 goto close; 2130 2131 n = write(c1, "a", 1); 2132 if (n < 0) 2133 FAIL_ERRNO("%s: write", log_prefix); 2134 if (n == 0) 2135 FAIL("%s: incomplete write", log_prefix); 2136 if (n < 1) 2137 goto close; 2138 2139 key = SK_PASS; 2140 err = xbpf_map_lookup_elem(verd_mapfd, &key, &pass); 2141 if (err) 2142 goto close; 2143 if (pass != 1) 2144 FAIL("%s: want pass count 1, have %d", log_prefix, pass); 2145 2146 n = recv_timeout(mode == REDIR_INGRESS ? p0 : c0, &b, 1, 0, IO_TIMEOUT_SEC); 2147 if (n < 0) 2148 FAIL_ERRNO("%s: recv_timeout", log_prefix); 2149 if (n == 0) 2150 FAIL("%s: incomplete recv", log_prefix); 2151 2152 close: 2153 xclose(c1); 2154 xclose(p1); 2155 close_cli0: 2156 xclose(c0); 2157 xclose(p0); 2158 2159 } 2160 2161 static void unix_inet_skb_redir_to_connected(struct test_sockmap_listen *skel, 2162 struct bpf_map *inner_map, int family) 2163 { 2164 int verdict = bpf_program__fd(skel->progs.prog_skb_verdict); 2165 int verdict_map = bpf_map__fd(skel->maps.verdict_map); 2166 int sock_map = bpf_map__fd(inner_map); 2167 int err; 2168 2169 err = xbpf_prog_attach(verdict, sock_map, BPF_SK_SKB_VERDICT, 0); 2170 if (err) 2171 return; 2172 2173 skel->bss->test_ingress = false; 2174 unix_inet_redir_to_connected(family, SOCK_DGRAM, sock_map, verdict_map, 2175 REDIR_EGRESS); 2176 unix_inet_redir_to_connected(family, SOCK_STREAM, sock_map, verdict_map, 2177 REDIR_EGRESS); 2178 skel->bss->test_ingress = true; 2179 unix_inet_redir_to_connected(family, SOCK_DGRAM, sock_map, verdict_map, 2180 REDIR_INGRESS); 2181 unix_inet_redir_to_connected(family, SOCK_STREAM, sock_map, verdict_map, 2182 REDIR_INGRESS); 2183 2184 xbpf_prog_detach2(verdict, sock_map, BPF_SK_SKB_VERDICT); 2185 } 2186 2187 static void test_udp_unix_redir(struct test_sockmap_listen *skel, struct bpf_map *map, 2188 int family) 2189 { 2190 const char *family_name, *map_name; 2191 char s[MAX_TEST_NAME]; 2192 2193 family_name = family_str(family); 2194 map_name = map_type_str(map); 2195 snprintf(s, sizeof(s), "%s %s %s", map_name, family_name, __func__); 2196 if (!test__start_subtest(s)) 2197 return; 2198 inet_unix_skb_redir_to_connected(skel, map, family); 2199 unix_inet_skb_redir_to_connected(skel, map, family); 2200 } 2201 2202 static void run_tests(struct test_sockmap_listen *skel, struct bpf_map *map, 2203 int family) 2204 { 2205 test_ops(skel, map, family, SOCK_STREAM); 2206 test_ops(skel, map, family, SOCK_DGRAM); 2207 test_redir(skel, map, family, SOCK_STREAM); 2208 test_reuseport(skel, map, family, SOCK_STREAM); 2209 test_reuseport(skel, map, family, SOCK_DGRAM); 2210 test_udp_redir(skel, map, family); 2211 test_udp_unix_redir(skel, map, family); 2212 } 2213 2214 void serial_test_sockmap_listen(void) 2215 { 2216 struct test_sockmap_listen *skel; 2217 2218 skel = test_sockmap_listen__open_and_load(); 2219 if (!skel) { 2220 FAIL("skeleton open/load failed"); 2221 return; 2222 } 2223 2224 skel->bss->test_sockmap = true; 2225 run_tests(skel, skel->maps.sock_map, AF_INET); 2226 run_tests(skel, skel->maps.sock_map, AF_INET6); 2227 test_unix_redir(skel, skel->maps.sock_map, SOCK_DGRAM); 2228 test_unix_redir(skel, skel->maps.sock_map, SOCK_STREAM); 2229 test_vsock_redir(skel, skel->maps.sock_map); 2230 2231 skel->bss->test_sockmap = false; 2232 run_tests(skel, skel->maps.sock_hash, AF_INET); 2233 run_tests(skel, skel->maps.sock_hash, AF_INET6); 2234 test_unix_redir(skel, skel->maps.sock_hash, SOCK_DGRAM); 2235 test_unix_redir(skel, skel->maps.sock_hash, SOCK_STREAM); 2236 test_vsock_redir(skel, skel->maps.sock_hash); 2237 2238 test_sockmap_listen__destroy(skel); 2239 } 2240