1 // SPDX-License-Identifier: GPL-2.0-only 2 #define _GNU_SOURCE 3 4 #include <errno.h> 5 #include <stdbool.h> 6 #include <stdio.h> 7 #include <string.h> 8 #include <unistd.h> 9 #include <sched.h> 10 11 #include <arpa/inet.h> 12 #include <sys/mount.h> 13 #include <sys/stat.h> 14 #include <sys/types.h> 15 #include <sys/un.h> 16 #include <sys/eventfd.h> 17 18 #include <linux/err.h> 19 #include <linux/in.h> 20 #include <linux/in6.h> 21 #include <linux/limits.h> 22 23 #include <linux/ip.h> 24 #include <netinet/udp.h> 25 #include <netinet/tcp.h> 26 #include <net/if.h> 27 28 #include "bpf_util.h" 29 #include "network_helpers.h" 30 #include "test_progs.h" 31 32 #ifdef TRAFFIC_MONITOR 33 /* Prevent pcap.h from including pcap/bpf.h and causing conflicts */ 34 #define PCAP_DONT_INCLUDE_PCAP_BPF_H 1 35 #include <pcap/pcap.h> 36 #include <pcap/dlt.h> 37 #endif 38 39 #ifndef IPPROTO_MPTCP 40 #define IPPROTO_MPTCP 262 41 #endif 42 43 #define clean_errno() (errno == 0 ? "None" : strerror(errno)) 44 #define log_err(MSG, ...) ({ \ 45 int __save = errno; \ 46 fprintf(stderr, "(%s:%d: errno: %s) " MSG "\n", \ 47 __FILE__, __LINE__, clean_errno(), \ 48 ##__VA_ARGS__); \ 49 errno = __save; \ 50 }) 51 52 #define CONNECT_MIN_TIMEOUT_MS 5000 53 54 struct ipv4_packet pkt_v4 = { 55 .eth.h_proto = __bpf_constant_htons(ETH_P_IP), 56 .iph.ihl = 5, 57 .iph.protocol = IPPROTO_TCP, 58 .iph.tot_len = __bpf_constant_htons(MAGIC_BYTES), 59 .tcp.urg_ptr = 123, 60 .tcp.doff = 5, 61 }; 62 63 struct ipv6_packet pkt_v6 = { 64 .eth.h_proto = __bpf_constant_htons(ETH_P_IPV6), 65 .iph.nexthdr = IPPROTO_TCP, 66 .iph.payload_len = __bpf_constant_htons(MAGIC_BYTES), 67 .tcp.urg_ptr = 123, 68 .tcp.doff = 5, 69 }; 70 71 static const struct network_helper_opts default_opts; 72 73 int settimeo(int fd, int timeout_ms) 74 { 75 struct timeval timeout = { .tv_sec = 3 }; 76 77 if (timeout_ms > 0) { 78 timeout.tv_sec = timeout_ms / 1000; 79 timeout.tv_usec = (timeout_ms % 1000) * 1000; 80 } 81 82 if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, 83 sizeof(timeout))) { 84 log_err("Failed to set SO_RCVTIMEO"); 85 return -1; 86 } 87 88 if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, 89 sizeof(timeout))) { 90 log_err("Failed to set SO_SNDTIMEO"); 91 return -1; 92 } 93 94 return 0; 95 } 96 97 #define save_errno_close(fd) ({ int __save = errno; close(fd); errno = __save; }) 98 99 int start_server_addr(int type, const struct sockaddr_storage *addr, socklen_t addrlen, 100 const struct network_helper_opts *opts) 101 { 102 int on = 1, fd; 103 104 if (!opts) 105 opts = &default_opts; 106 107 fd = socket(addr->ss_family, type, opts->proto); 108 if (fd < 0) { 109 log_err("Failed to create server socket"); 110 return -1; 111 } 112 113 if (settimeo(fd, opts->timeout_ms)) 114 goto error_close; 115 116 if ((type & SOCK_TYPE_MASK) == SOCK_STREAM && 117 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) { 118 log_err("Failed to enable SO_REUSEADDR"); 119 goto error_close; 120 } 121 122 if (opts->post_socket_cb && 123 opts->post_socket_cb(fd, opts->cb_opts)) { 124 log_err("Failed to call post_socket_cb"); 125 goto error_close; 126 } 127 128 if (bind(fd, (struct sockaddr *)addr, addrlen) < 0) { 129 log_err("Failed to bind socket"); 130 goto error_close; 131 } 132 133 if ((type & SOCK_TYPE_MASK) == SOCK_STREAM) { 134 if (listen(fd, opts->backlog ? MAX(opts->backlog, 0) : 1) < 0) { 135 log_err("Failed to listed on socket"); 136 goto error_close; 137 } 138 } 139 140 return fd; 141 142 error_close: 143 save_errno_close(fd); 144 return -1; 145 } 146 147 int start_server_str(int family, int type, const char *addr_str, __u16 port, 148 const struct network_helper_opts *opts) 149 { 150 struct sockaddr_storage addr; 151 socklen_t addrlen; 152 153 if (!opts) 154 opts = &default_opts; 155 156 if (make_sockaddr(family, addr_str, port, &addr, &addrlen)) 157 return -1; 158 159 return start_server_addr(type, &addr, addrlen, opts); 160 } 161 162 int start_server(int family, int type, const char *addr_str, __u16 port, 163 int timeout_ms) 164 { 165 struct network_helper_opts opts = { 166 .timeout_ms = timeout_ms, 167 }; 168 169 return start_server_str(family, type, addr_str, port, &opts); 170 } 171 172 static int reuseport_cb(int fd, void *opts) 173 { 174 int on = 1; 175 176 return setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)); 177 } 178 179 int *start_reuseport_server(int family, int type, const char *addr_str, 180 __u16 port, int timeout_ms, unsigned int nr_listens) 181 { 182 struct network_helper_opts opts = { 183 .timeout_ms = timeout_ms, 184 .post_socket_cb = reuseport_cb, 185 }; 186 struct sockaddr_storage addr; 187 unsigned int nr_fds = 0; 188 socklen_t addrlen; 189 int *fds; 190 191 if (!nr_listens) 192 return NULL; 193 194 if (make_sockaddr(family, addr_str, port, &addr, &addrlen)) 195 return NULL; 196 197 fds = malloc(sizeof(*fds) * nr_listens); 198 if (!fds) 199 return NULL; 200 201 fds[0] = start_server_addr(type, &addr, addrlen, &opts); 202 if (fds[0] == -1) 203 goto close_fds; 204 nr_fds = 1; 205 206 if (getsockname(fds[0], (struct sockaddr *)&addr, &addrlen)) 207 goto close_fds; 208 209 for (; nr_fds < nr_listens; nr_fds++) { 210 fds[nr_fds] = start_server_addr(type, &addr, addrlen, &opts); 211 if (fds[nr_fds] == -1) 212 goto close_fds; 213 } 214 215 return fds; 216 217 close_fds: 218 free_fds(fds, nr_fds); 219 return NULL; 220 } 221 222 void free_fds(int *fds, unsigned int nr_close_fds) 223 { 224 if (fds) { 225 while (nr_close_fds) 226 close(fds[--nr_close_fds]); 227 free(fds); 228 } 229 } 230 231 int fastopen_connect(int server_fd, const char *data, unsigned int data_len, 232 int timeout_ms) 233 { 234 struct sockaddr_storage addr; 235 socklen_t addrlen = sizeof(addr); 236 struct sockaddr_in *addr_in; 237 int fd, ret; 238 239 if (getsockname(server_fd, (struct sockaddr *)&addr, &addrlen)) { 240 log_err("Failed to get server addr"); 241 return -1; 242 } 243 244 addr_in = (struct sockaddr_in *)&addr; 245 fd = socket(addr_in->sin_family, SOCK_STREAM, 0); 246 if (fd < 0) { 247 log_err("Failed to create client socket"); 248 return -1; 249 } 250 251 if (settimeo(fd, timeout_ms)) 252 goto error_close; 253 254 ret = sendto(fd, data, data_len, MSG_FASTOPEN, (struct sockaddr *)&addr, 255 addrlen); 256 if (ret != data_len) { 257 log_err("sendto(data, %u) != %d\n", data_len, ret); 258 goto error_close; 259 } 260 261 return fd; 262 263 error_close: 264 save_errno_close(fd); 265 return -1; 266 } 267 268 int client_socket(int family, int type, 269 const struct network_helper_opts *opts) 270 { 271 int fd; 272 273 if (!opts) 274 opts = &default_opts; 275 276 fd = socket(family, type, opts->proto); 277 if (fd < 0) { 278 log_err("Failed to create client socket"); 279 return -1; 280 } 281 282 if (settimeo(fd, opts->timeout_ms)) 283 goto error_close; 284 285 if (opts->post_socket_cb && 286 opts->post_socket_cb(fd, opts->cb_opts)) 287 goto error_close; 288 289 return fd; 290 291 error_close: 292 save_errno_close(fd); 293 return -1; 294 } 295 296 static int connect_with_timeout(int fd, const struct sockaddr_storage *addr, 297 socklen_t addrlen, int timeout_ms) 298 { 299 int connect_timeout_ms = MAX(timeout_ms, CONNECT_MIN_TIMEOUT_MS); 300 301 /* 302 * Override timeout configuration with a larger value for the 303 * connection 304 */ 305 if (settimeo(fd, connect_timeout_ms)) { 306 log_err("Failed to set connect timeout"); 307 return -1; 308 } 309 310 if (connect(fd, (const struct sockaddr *)addr, addrlen)) { 311 log_err("Failed to connect"); 312 return -1; 313 } 314 315 /* 316 * If the timeout configured by the test is different from the 317 * connect timeout, restore it 318 */ 319 if (timeout_ms != connect_timeout_ms && settimeo(fd, timeout_ms)) { 320 log_err("Failed to set timeout for connected socket"); 321 return -1; 322 } 323 324 return 0; 325 } 326 327 int connect_to_addr(int type, const struct sockaddr_storage *addr, socklen_t addrlen, 328 const struct network_helper_opts *opts) 329 { 330 int fd; 331 332 if (!opts) 333 opts = &default_opts; 334 335 fd = client_socket(addr->ss_family, type, opts); 336 if (fd < 0) { 337 log_err("Failed to create client socket"); 338 return -1; 339 } 340 341 if (connect_with_timeout(fd, addr, addrlen, opts->timeout_ms)) { 342 save_errno_close(fd); 343 return -1; 344 } 345 346 return fd; 347 } 348 349 int connect_to_addr_str(int family, int type, const char *addr_str, __u16 port, 350 const struct network_helper_opts *opts) 351 { 352 struct sockaddr_storage addr; 353 socklen_t addrlen; 354 355 if (!opts) 356 opts = &default_opts; 357 358 if (make_sockaddr(family, addr_str, port, &addr, &addrlen)) 359 return -1; 360 361 return connect_to_addr(type, &addr, addrlen, opts); 362 } 363 364 int connect_to_fd_opts(int server_fd, const struct network_helper_opts *opts) 365 { 366 struct sockaddr_storage addr; 367 socklen_t addrlen, optlen; 368 int type; 369 370 if (!opts) 371 opts = &default_opts; 372 373 optlen = sizeof(type); 374 if (getsockopt(server_fd, SOL_SOCKET, SO_TYPE, &type, &optlen)) { 375 log_err("getsockopt(SOL_TYPE)"); 376 return -1; 377 } 378 379 addrlen = sizeof(addr); 380 if (getsockname(server_fd, (struct sockaddr *)&addr, &addrlen)) { 381 log_err("Failed to get server addr"); 382 return -1; 383 } 384 385 return connect_to_addr(type, &addr, addrlen, opts); 386 } 387 388 int connect_to_fd(int server_fd, int timeout_ms) 389 { 390 struct network_helper_opts opts = { 391 .timeout_ms = timeout_ms, 392 }; 393 socklen_t optlen; 394 int protocol; 395 396 optlen = sizeof(protocol); 397 if (getsockopt(server_fd, SOL_SOCKET, SO_PROTOCOL, &protocol, &optlen)) { 398 log_err("getsockopt(SOL_PROTOCOL)"); 399 return -1; 400 } 401 opts.proto = protocol; 402 403 return connect_to_fd_opts(server_fd, &opts); 404 } 405 406 int connect_fd_to_fd(int client_fd, int server_fd, int timeout_ms) 407 { 408 struct sockaddr_storage addr; 409 socklen_t len = sizeof(addr); 410 411 if (getsockname(server_fd, (struct sockaddr *)&addr, &len)) { 412 log_err("Failed to get server addr"); 413 return -1; 414 } 415 416 return connect_with_timeout(client_fd, &addr, len, timeout_ms); 417 } 418 419 int make_sockaddr(int family, const char *addr_str, __u16 port, 420 struct sockaddr_storage *addr, socklen_t *len) 421 { 422 if (family == AF_INET) { 423 struct sockaddr_in *sin = (void *)addr; 424 425 memset(addr, 0, sizeof(*sin)); 426 sin->sin_family = AF_INET; 427 sin->sin_port = htons(port); 428 if (addr_str && 429 inet_pton(AF_INET, addr_str, &sin->sin_addr) != 1) { 430 log_err("inet_pton(AF_INET, %s)", addr_str); 431 return -1; 432 } 433 if (len) 434 *len = sizeof(*sin); 435 return 0; 436 } else if (family == AF_INET6) { 437 struct sockaddr_in6 *sin6 = (void *)addr; 438 439 memset(addr, 0, sizeof(*sin6)); 440 sin6->sin6_family = AF_INET6; 441 sin6->sin6_port = htons(port); 442 if (addr_str && 443 inet_pton(AF_INET6, addr_str, &sin6->sin6_addr) != 1) { 444 log_err("inet_pton(AF_INET6, %s)", addr_str); 445 return -1; 446 } 447 if (len) 448 *len = sizeof(*sin6); 449 return 0; 450 } else if (family == AF_UNIX) { 451 /* 452 * Note that we always use abstract unix sockets to avoid having 453 * to clean up leftover files. 454 */ 455 struct sockaddr_un *sun = (void *)addr; 456 457 memset(addr, 0, sizeof(*sun)); 458 sun->sun_family = family; 459 sun->sun_path[0] = 0; 460 strscpy(sun->sun_path + 1, addr_str, sizeof(sun->sun_path) - 1); 461 if (len) 462 *len = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(addr_str); 463 return 0; 464 } 465 return -1; 466 } 467 468 char *ping_command(int family) 469 { 470 if (family == AF_INET6) { 471 /* On some systems 'ping' doesn't support IPv6, so use ping6 if it is present. */ 472 if (!system("which ping6 >/dev/null 2>&1")) 473 return "ping6"; 474 else 475 return "ping -6"; 476 } 477 return "ping"; 478 } 479 480 int append_tid(char *str, size_t sz) 481 { 482 size_t end; 483 484 if (!str) 485 return -1; 486 487 end = strlen(str); 488 if (end + 8 > sz) 489 return -1; 490 491 sprintf(&str[end], "%07ld", sys_gettid()); 492 str[end + 7] = '\0'; 493 494 return 0; 495 } 496 497 int remove_netns(const char *name) 498 { 499 char *cmd; 500 int r; 501 502 r = asprintf(&cmd, "ip netns del %s >/dev/null 2>&1", name); 503 if (r < 0) { 504 log_err("Failed to malloc cmd"); 505 return -1; 506 } 507 508 r = system(cmd); 509 free(cmd); 510 return r; 511 } 512 513 int make_netns(const char *name) 514 { 515 char *cmd; 516 int r; 517 518 r = asprintf(&cmd, "ip netns add %s", name); 519 if (r < 0) { 520 log_err("Failed to malloc cmd"); 521 return -1; 522 } 523 524 r = system(cmd); 525 free(cmd); 526 527 if (r) 528 return r; 529 530 r = asprintf(&cmd, "ip -n %s link set lo up", name); 531 if (r < 0) { 532 log_err("Failed to malloc cmd for setting up lo"); 533 remove_netns(name); 534 return -1; 535 } 536 537 r = system(cmd); 538 free(cmd); 539 540 return r; 541 } 542 543 struct nstoken { 544 int orig_netns_fd; 545 }; 546 547 struct nstoken *open_netns(const char *name) 548 { 549 int nsfd; 550 char nspath[PATH_MAX]; 551 int err; 552 struct nstoken *token; 553 554 token = calloc(1, sizeof(struct nstoken)); 555 if (!token) { 556 log_err("Failed to malloc token"); 557 return NULL; 558 } 559 560 token->orig_netns_fd = open("/proc/self/ns/net", O_RDONLY); 561 if (token->orig_netns_fd == -1) { 562 log_err("Failed to open(/proc/self/ns/net)"); 563 goto fail; 564 } 565 566 snprintf(nspath, sizeof(nspath), "%s/%s", "/var/run/netns", name); 567 nsfd = open(nspath, O_RDONLY | O_CLOEXEC); 568 if (nsfd == -1) { 569 log_err("Failed to open(%s)", nspath); 570 goto fail; 571 } 572 573 err = setns(nsfd, CLONE_NEWNET); 574 close(nsfd); 575 if (err) { 576 log_err("Failed to setns(nsfd)"); 577 goto fail; 578 } 579 580 return token; 581 fail: 582 if (token->orig_netns_fd != -1) 583 close(token->orig_netns_fd); 584 free(token); 585 return NULL; 586 } 587 588 void close_netns(struct nstoken *token) 589 { 590 if (!token) 591 return; 592 593 if (setns(token->orig_netns_fd, CLONE_NEWNET)) 594 log_err("Failed to setns(orig_netns_fd)"); 595 close(token->orig_netns_fd); 596 free(token); 597 } 598 599 int open_tuntap(const char *dev_name, bool need_mac) 600 { 601 int err = 0; 602 struct ifreq ifr; 603 int fd = open("/dev/net/tun", O_RDWR); 604 605 if (!ASSERT_GE(fd, 0, "open(/dev/net/tun)")) 606 return -1; 607 608 ifr.ifr_flags = IFF_NO_PI | (need_mac ? IFF_TAP : IFF_TUN); 609 strscpy(ifr.ifr_name, dev_name); 610 611 err = ioctl(fd, TUNSETIFF, &ifr); 612 if (!ASSERT_OK(err, "ioctl(TUNSETIFF)")) { 613 close(fd); 614 return -1; 615 } 616 617 err = fcntl(fd, F_SETFL, O_NONBLOCK); 618 if (!ASSERT_OK(err, "fcntl(O_NONBLOCK)")) { 619 close(fd); 620 return -1; 621 } 622 623 return fd; 624 } 625 626 int get_socket_local_port(int sock_fd) 627 { 628 struct sockaddr_storage addr; 629 socklen_t addrlen = sizeof(addr); 630 int err; 631 632 err = getsockname(sock_fd, (struct sockaddr *)&addr, &addrlen); 633 if (err < 0) 634 return err; 635 636 if (addr.ss_family == AF_INET) { 637 struct sockaddr_in *sin = (struct sockaddr_in *)&addr; 638 639 return sin->sin_port; 640 } else if (addr.ss_family == AF_INET6) { 641 struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&addr; 642 643 return sin->sin6_port; 644 } 645 646 return -1; 647 } 648 649 int get_hw_ring_size(char *ifname, struct ethtool_ringparam *ring_param) 650 { 651 struct ifreq ifr = {0}; 652 int sockfd, err; 653 654 sockfd = socket(AF_INET, SOCK_DGRAM, 0); 655 if (sockfd < 0) 656 return -errno; 657 658 memcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 659 660 ring_param->cmd = ETHTOOL_GRINGPARAM; 661 ifr.ifr_data = (char *)ring_param; 662 663 if (ioctl(sockfd, SIOCETHTOOL, &ifr) < 0) { 664 err = errno; 665 close(sockfd); 666 return -err; 667 } 668 669 close(sockfd); 670 return 0; 671 } 672 673 int set_hw_ring_size(char *ifname, struct ethtool_ringparam *ring_param) 674 { 675 struct ifreq ifr = {0}; 676 int sockfd, err; 677 678 sockfd = socket(AF_INET, SOCK_DGRAM, 0); 679 if (sockfd < 0) 680 return -errno; 681 682 memcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 683 684 ring_param->cmd = ETHTOOL_SRINGPARAM; 685 ifr.ifr_data = (char *)ring_param; 686 687 if (ioctl(sockfd, SIOCETHTOOL, &ifr) < 0) { 688 err = errno; 689 close(sockfd); 690 return -err; 691 } 692 693 close(sockfd); 694 return 0; 695 } 696 697 struct send_recv_arg { 698 int fd; 699 uint32_t bytes; 700 int stop; 701 }; 702 703 static void *send_recv_server(void *arg) 704 { 705 struct send_recv_arg *a = (struct send_recv_arg *)arg; 706 ssize_t nr_sent = 0, bytes = 0; 707 char batch[1500]; 708 int err = 0, fd; 709 710 fd = accept(a->fd, NULL, NULL); 711 while (fd == -1) { 712 if (errno == EINTR) 713 continue; 714 err = -errno; 715 goto done; 716 } 717 718 if (settimeo(fd, 0)) { 719 err = -errno; 720 goto done; 721 } 722 723 while (bytes < a->bytes && !READ_ONCE(a->stop)) { 724 nr_sent = send(fd, &batch, 725 MIN(a->bytes - bytes, sizeof(batch)), 0); 726 if (nr_sent == -1 && errno == EINTR) 727 continue; 728 if (nr_sent == -1) { 729 err = -errno; 730 break; 731 } 732 bytes += nr_sent; 733 } 734 735 if (bytes != a->bytes) { 736 log_err("send %zd expected %u", bytes, a->bytes); 737 if (!err) 738 err = bytes > a->bytes ? -E2BIG : -EINTR; 739 } 740 741 done: 742 if (fd >= 0) 743 close(fd); 744 if (err) { 745 WRITE_ONCE(a->stop, 1); 746 return ERR_PTR(err); 747 } 748 return NULL; 749 } 750 751 int send_recv_data(int lfd, int fd, uint32_t total_bytes) 752 { 753 ssize_t nr_recv = 0, bytes = 0; 754 struct send_recv_arg arg = { 755 .fd = lfd, 756 .bytes = total_bytes, 757 .stop = 0, 758 }; 759 pthread_t srv_thread; 760 void *thread_ret; 761 char batch[1500]; 762 int err = 0; 763 764 err = pthread_create(&srv_thread, NULL, send_recv_server, (void *)&arg); 765 if (err) { 766 log_err("Failed to pthread_create"); 767 return err; 768 } 769 770 /* recv total_bytes */ 771 while (bytes < total_bytes && !READ_ONCE(arg.stop)) { 772 nr_recv = recv(fd, &batch, 773 MIN(total_bytes - bytes, sizeof(batch)), 0); 774 if (nr_recv == -1 && errno == EINTR) 775 continue; 776 if (nr_recv == -1) { 777 err = -errno; 778 break; 779 } 780 bytes += nr_recv; 781 } 782 783 if (bytes != total_bytes) { 784 log_err("recv %zd expected %u", bytes, total_bytes); 785 if (!err) 786 err = bytes > total_bytes ? -E2BIG : -EINTR; 787 } 788 789 WRITE_ONCE(arg.stop, 1); 790 pthread_join(srv_thread, &thread_ret); 791 if (IS_ERR(thread_ret)) { 792 log_err("Failed in thread_ret %ld", PTR_ERR(thread_ret)); 793 err = err ? : PTR_ERR(thread_ret); 794 } 795 796 return err; 797 } 798 799 int tc_prog_attach(const char *dev, int ingress_fd, int egress_fd) 800 { 801 int ifindex, ret; 802 803 if (!ASSERT_TRUE(ingress_fd >= 0 || egress_fd >= 0, 804 "at least one program fd is valid")) 805 return -1; 806 807 ifindex = if_nametoindex(dev); 808 if (!ASSERT_NEQ(ifindex, 0, "get ifindex")) 809 return -1; 810 811 DECLARE_LIBBPF_OPTS(bpf_tc_hook, hook, .ifindex = ifindex, 812 .attach_point = BPF_TC_INGRESS | BPF_TC_EGRESS); 813 DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts1, .handle = 1, 814 .priority = 1, .prog_fd = ingress_fd); 815 DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts2, .handle = 1, 816 .priority = 1, .prog_fd = egress_fd); 817 818 ret = bpf_tc_hook_create(&hook); 819 if (!ASSERT_OK(ret, "create tc hook")) 820 return ret; 821 822 if (ingress_fd >= 0) { 823 hook.attach_point = BPF_TC_INGRESS; 824 ret = bpf_tc_attach(&hook, &opts1); 825 if (!ASSERT_OK(ret, "bpf_tc_attach")) { 826 bpf_tc_hook_destroy(&hook); 827 return ret; 828 } 829 } 830 831 if (egress_fd >= 0) { 832 hook.attach_point = BPF_TC_EGRESS; 833 ret = bpf_tc_attach(&hook, &opts2); 834 if (!ASSERT_OK(ret, "bpf_tc_attach")) { 835 bpf_tc_hook_destroy(&hook); 836 return ret; 837 } 838 } 839 840 return 0; 841 } 842 843 #ifdef TRAFFIC_MONITOR 844 struct tmonitor_ctx { 845 pcap_t *pcap; 846 pcap_dumper_t *dumper; 847 pthread_t thread; 848 int wake_fd; 849 850 volatile bool done; 851 char pkt_fname[PATH_MAX]; 852 int pcap_fd; 853 }; 854 855 static int __base_pr(const char *format, va_list args) 856 { 857 return vfprintf(stdout, format, args); 858 } 859 860 static tm_print_fn_t __tm_pr = __base_pr; 861 862 tm_print_fn_t traffic_monitor_set_print(tm_print_fn_t fn) 863 { 864 tm_print_fn_t old_print_fn; 865 866 old_print_fn = __atomic_exchange_n(&__tm_pr, fn, __ATOMIC_RELAXED); 867 868 return old_print_fn; 869 } 870 871 void tm_print(const char *format, ...) 872 { 873 tm_print_fn_t print_fn; 874 va_list args; 875 876 print_fn = __atomic_load_n(&__tm_pr, __ATOMIC_RELAXED); 877 if (!print_fn) 878 return; 879 880 va_start(args, format); 881 print_fn(format, args); 882 va_end(args); 883 } 884 885 /* Is this packet captured with a Ethernet protocol type? */ 886 static bool is_ethernet(const u_char *packet) 887 { 888 u16 arphdr_type; 889 890 memcpy(&arphdr_type, packet + 8, 2); 891 arphdr_type = ntohs(arphdr_type); 892 893 /* 894 * Except the following cases, the protocol type contains the 895 * Ethernet protocol type for the packet. 896 * 897 * https://www.tcpdump.org/linktypes/LINKTYPE_LINUX_SLL2.html 898 */ 899 switch (arphdr_type) { 900 case 770: /* ARPHRD_FRAD */ 901 case 778: /* ARPHDR_IPGRE */ 902 case 803: /* ARPHRD_IEEE80211_RADIOTAP */ 903 tm_print("Packet captured: arphdr_type=%d\n", arphdr_type); 904 return false; 905 } 906 return true; 907 } 908 909 static const char * const pkt_types[] = { 910 "In", 911 "B", /* Broadcast */ 912 "M", /* Multicast */ 913 "C", /* Captured with the promiscuous mode */ 914 "Out", 915 }; 916 917 static const char *pkt_type_str(u16 pkt_type) 918 { 919 if (pkt_type < ARRAY_SIZE(pkt_types)) 920 return pkt_types[pkt_type]; 921 return "Unknown"; 922 } 923 924 #define MAX_FLAGS_STRLEN 21 925 /* Show the information of the transport layer in the packet */ 926 static void show_transport(const u_char *packet, u16 len, u32 ifindex, 927 const char *src_addr, const char *dst_addr, 928 u16 proto, bool ipv6, u8 pkt_type) 929 { 930 char *ifname, _ifname[IF_NAMESIZE], flags[MAX_FLAGS_STRLEN] = ""; 931 const char *transport_str; 932 u16 src_port, dst_port; 933 struct udphdr *udp; 934 struct tcphdr *tcp; 935 936 ifname = if_indextoname(ifindex, _ifname); 937 if (!ifname) { 938 snprintf(_ifname, sizeof(_ifname), "unknown(%d)", ifindex); 939 ifname = _ifname; 940 } 941 942 if (proto == IPPROTO_UDP) { 943 udp = (struct udphdr *)packet; 944 src_port = ntohs(udp->source); 945 dst_port = ntohs(udp->dest); 946 transport_str = "UDP"; 947 } else if (proto == IPPROTO_TCP) { 948 tcp = (struct tcphdr *)packet; 949 src_port = ntohs(tcp->source); 950 dst_port = ntohs(tcp->dest); 951 transport_str = "TCP"; 952 } else if (proto == IPPROTO_ICMP) { 953 tm_print("%-7s %-3s IPv4 %s > %s: ICMP, length %d, type %d, code %d\n", 954 ifname, pkt_type_str(pkt_type), src_addr, dst_addr, len, 955 packet[0], packet[1]); 956 return; 957 } else if (proto == IPPROTO_ICMPV6) { 958 tm_print("%-7s %-3s IPv6 %s > %s: ICMPv6, length %d, type %d, code %d\n", 959 ifname, pkt_type_str(pkt_type), src_addr, dst_addr, len, 960 packet[0], packet[1]); 961 return; 962 } else { 963 tm_print("%-7s %-3s %s %s > %s: protocol %d\n", 964 ifname, pkt_type_str(pkt_type), ipv6 ? "IPv6" : "IPv4", 965 src_addr, dst_addr, proto); 966 return; 967 } 968 969 /* TCP or UDP*/ 970 971 if (proto == IPPROTO_TCP) 972 snprintf(flags, MAX_FLAGS_STRLEN, "%s%s%s%s", 973 tcp->fin ? ", FIN" : "", 974 tcp->syn ? ", SYN" : "", 975 tcp->rst ? ", RST" : "", 976 tcp->ack ? ", ACK" : ""); 977 978 if (ipv6) 979 tm_print("%-7s %-3s IPv6 %s.%d > %s.%d: %s, length %d%s\n", 980 ifname, pkt_type_str(pkt_type), src_addr, src_port, 981 dst_addr, dst_port, transport_str, len, flags); 982 else 983 tm_print("%-7s %-3s IPv4 %s:%d > %s:%d: %s, length %d%s\n", 984 ifname, pkt_type_str(pkt_type), src_addr, src_port, 985 dst_addr, dst_port, transport_str, len, flags); 986 } 987 988 static void show_ipv6_packet(const u_char *packet, u32 ifindex, u8 pkt_type) 989 { 990 char src_buf[INET6_ADDRSTRLEN], dst_buf[INET6_ADDRSTRLEN]; 991 struct ipv6hdr *pkt = (struct ipv6hdr *)packet; 992 const char *src, *dst; 993 u_char proto; 994 995 src = inet_ntop(AF_INET6, &pkt->saddr, src_buf, sizeof(src_buf)); 996 if (!src) 997 src = "<invalid>"; 998 dst = inet_ntop(AF_INET6, &pkt->daddr, dst_buf, sizeof(dst_buf)); 999 if (!dst) 1000 dst = "<invalid>"; 1001 proto = pkt->nexthdr; 1002 show_transport(packet + sizeof(struct ipv6hdr), 1003 ntohs(pkt->payload_len), 1004 ifindex, src, dst, proto, true, pkt_type); 1005 } 1006 1007 static void show_ipv4_packet(const u_char *packet, u32 ifindex, u8 pkt_type) 1008 { 1009 char src_buf[INET_ADDRSTRLEN], dst_buf[INET_ADDRSTRLEN]; 1010 struct iphdr *pkt = (struct iphdr *)packet; 1011 const char *src, *dst; 1012 u_char proto; 1013 1014 src = inet_ntop(AF_INET, &pkt->saddr, src_buf, sizeof(src_buf)); 1015 if (!src) 1016 src = "<invalid>"; 1017 dst = inet_ntop(AF_INET, &pkt->daddr, dst_buf, sizeof(dst_buf)); 1018 if (!dst) 1019 dst = "<invalid>"; 1020 proto = pkt->protocol; 1021 show_transport(packet + sizeof(struct iphdr), 1022 ntohs(pkt->tot_len), 1023 ifindex, src, dst, proto, false, pkt_type); 1024 } 1025 1026 static void *traffic_monitor_thread(void *arg) 1027 { 1028 char *ifname, _ifname[IF_NAMESIZE]; 1029 const u_char *packet, *payload; 1030 struct tmonitor_ctx *ctx = arg; 1031 pcap_dumper_t *dumper = ctx->dumper; 1032 int fd = ctx->pcap_fd, nfds, r; 1033 int wake_fd = ctx->wake_fd; 1034 struct pcap_pkthdr header; 1035 pcap_t *pcap = ctx->pcap; 1036 u32 ifindex; 1037 fd_set fds; 1038 u16 proto; 1039 u8 ptype; 1040 1041 nfds = (fd > wake_fd ? fd : wake_fd) + 1; 1042 FD_ZERO(&fds); 1043 1044 while (!ctx->done) { 1045 FD_SET(fd, &fds); 1046 FD_SET(wake_fd, &fds); 1047 r = select(nfds, &fds, NULL, NULL, NULL); 1048 if (!r) 1049 continue; 1050 if (r < 0) { 1051 if (errno == EINTR) 1052 continue; 1053 log_err("Fail to select on pcap fd and wake fd"); 1054 break; 1055 } 1056 1057 /* This instance of pcap is non-blocking */ 1058 packet = pcap_next(pcap, &header); 1059 if (!packet) 1060 continue; 1061 1062 /* 1063 * According to the man page of pcap_dump(), first argument 1064 * is the pcap_dumper_t pointer even it's argument type is 1065 * u_char *. 1066 */ 1067 pcap_dump((u_char *)dumper, &header, packet); 1068 1069 /* 1070 * Not sure what other types of packets look like. Here, we 1071 * parse only Ethernet and compatible packets. 1072 */ 1073 if (!is_ethernet(packet)) 1074 continue; 1075 1076 /* 1077 * Skip SLL2 header 1078 * https://www.tcpdump.org/linktypes/LINKTYPE_LINUX_SLL2.html 1079 * 1080 * Although the document doesn't mention that, the payload 1081 * doesn't include the Ethernet header. The payload starts 1082 * from the first byte of the network layer header. 1083 */ 1084 payload = packet + 20; 1085 1086 memcpy(&proto, packet, 2); 1087 proto = ntohs(proto); 1088 memcpy(&ifindex, packet + 4, 4); 1089 ifindex = ntohl(ifindex); 1090 ptype = packet[10]; 1091 1092 if (proto == ETH_P_IPV6) { 1093 show_ipv6_packet(payload, ifindex, ptype); 1094 } else if (proto == ETH_P_IP) { 1095 show_ipv4_packet(payload, ifindex, ptype); 1096 } else { 1097 ifname = if_indextoname(ifindex, _ifname); 1098 if (!ifname) { 1099 snprintf(_ifname, sizeof(_ifname), "unknown(%d)", ifindex); 1100 ifname = _ifname; 1101 } 1102 1103 tm_print("%-7s %-3s Unknown network protocol type 0x%x\n", 1104 ifname, pkt_type_str(ptype), proto); 1105 } 1106 } 1107 1108 return NULL; 1109 } 1110 1111 /* 1112 * Prepare the pcap handle to capture packets. 1113 * 1114 * This pcap is non-blocking and immediate mode is enabled to receive 1115 * captured packets as soon as possible. The snaplen is set to 1024 bytes 1116 * to limit the size of captured content. The format of the link-layer 1117 * header is set to DLT_LINUX_SLL2 to enable handling various link-layer 1118 * technologies. 1119 */ 1120 static pcap_t *traffic_monitor_prepare_pcap(void) 1121 { 1122 char errbuf[PCAP_ERRBUF_SIZE]; 1123 pcap_t *pcap; 1124 int r; 1125 1126 /* Listen on all NICs in the namespace */ 1127 pcap = pcap_create("any", errbuf); 1128 if (!pcap) { 1129 log_err("Failed to open pcap: %s", errbuf); 1130 return NULL; 1131 } 1132 /* Limit the size of the packet (first N bytes) */ 1133 r = pcap_set_snaplen(pcap, 1024); 1134 if (r) { 1135 log_err("Failed to set snaplen: %s", pcap_geterr(pcap)); 1136 goto error; 1137 } 1138 /* To receive packets as fast as possible */ 1139 r = pcap_set_immediate_mode(pcap, 1); 1140 if (r) { 1141 log_err("Failed to set immediate mode: %s", pcap_geterr(pcap)); 1142 goto error; 1143 } 1144 r = pcap_setnonblock(pcap, 1, errbuf); 1145 if (r) { 1146 log_err("Failed to set nonblock: %s", errbuf); 1147 goto error; 1148 } 1149 r = pcap_activate(pcap); 1150 if (r) { 1151 log_err("Failed to activate pcap: %s", pcap_geterr(pcap)); 1152 goto error; 1153 } 1154 /* Determine the format of the link-layer header */ 1155 r = pcap_set_datalink(pcap, DLT_LINUX_SLL2); 1156 if (r) { 1157 log_err("Failed to set datalink: %s", pcap_geterr(pcap)); 1158 goto error; 1159 } 1160 1161 return pcap; 1162 error: 1163 pcap_close(pcap); 1164 return NULL; 1165 } 1166 1167 static void encode_test_name(char *buf, size_t len, const char *test_name, const char *subtest_name) 1168 { 1169 char *p; 1170 1171 if (subtest_name) 1172 snprintf(buf, len, "%s__%s", test_name, subtest_name); 1173 else 1174 snprintf(buf, len, "%s", test_name); 1175 while ((p = strchr(buf, '/'))) 1176 *p = '_'; 1177 while ((p = strchr(buf, ' '))) 1178 *p = '_'; 1179 } 1180 1181 #define PCAP_DIR "/tmp/tmon_pcap" 1182 1183 /* 1184 * Start to monitor the network traffic in the given network namespace. 1185 * 1186 * netns: the name of the network namespace to monitor. If NULL, the 1187 * current network namespace is monitored. 1188 * test_name: the name of the running test. 1189 * subtest_name: the name of the running subtest if there is. It should be 1190 * NULL if it is not a subtest. 1191 * 1192 * This function will start a thread to capture packets going through NICs 1193 * in the give network namespace. 1194 */ 1195 struct tmonitor_ctx *traffic_monitor_start(const char *netns, const char *test_name, 1196 const char *subtest_name) 1197 { 1198 struct nstoken *nstoken = NULL; 1199 struct tmonitor_ctx *ctx; 1200 char test_name_buf[64]; 1201 static int tmon_seq; 1202 int r; 1203 1204 if (netns) { 1205 nstoken = open_netns(netns); 1206 if (!nstoken) 1207 return NULL; 1208 } 1209 ctx = malloc(sizeof(*ctx)); 1210 if (!ctx) { 1211 log_err("Failed to malloc ctx"); 1212 goto fail_ctx; 1213 } 1214 memset(ctx, 0, sizeof(*ctx)); 1215 1216 encode_test_name(test_name_buf, sizeof(test_name_buf), test_name, subtest_name); 1217 snprintf(ctx->pkt_fname, sizeof(ctx->pkt_fname), 1218 PCAP_DIR "/packets-%d-%d-%s-%s.log", getpid(), tmon_seq++, 1219 test_name_buf, netns ? netns : "unknown"); 1220 1221 r = mkdir(PCAP_DIR, 0755); 1222 if (r && errno != EEXIST) { 1223 log_err("Failed to create " PCAP_DIR); 1224 goto fail_pcap; 1225 } 1226 1227 ctx->pcap = traffic_monitor_prepare_pcap(); 1228 if (!ctx->pcap) 1229 goto fail_pcap; 1230 ctx->pcap_fd = pcap_get_selectable_fd(ctx->pcap); 1231 if (ctx->pcap_fd < 0) { 1232 log_err("Failed to get pcap fd"); 1233 goto fail_dumper; 1234 } 1235 1236 /* Create a packet file */ 1237 ctx->dumper = pcap_dump_open(ctx->pcap, ctx->pkt_fname); 1238 if (!ctx->dumper) { 1239 log_err("Failed to open pcap dump: %s", ctx->pkt_fname); 1240 goto fail_dumper; 1241 } 1242 1243 /* Create an eventfd to wake up the monitor thread */ 1244 ctx->wake_fd = eventfd(0, 0); 1245 if (ctx->wake_fd < 0) { 1246 log_err("Failed to create eventfd"); 1247 goto fail_eventfd; 1248 } 1249 1250 r = pthread_create(&ctx->thread, NULL, traffic_monitor_thread, ctx); 1251 if (r) { 1252 log_err("Failed to create thread"); 1253 goto fail; 1254 } 1255 1256 close_netns(nstoken); 1257 1258 return ctx; 1259 1260 fail: 1261 close(ctx->wake_fd); 1262 1263 fail_eventfd: 1264 pcap_dump_close(ctx->dumper); 1265 unlink(ctx->pkt_fname); 1266 1267 fail_dumper: 1268 pcap_close(ctx->pcap); 1269 1270 fail_pcap: 1271 free(ctx); 1272 1273 fail_ctx: 1274 close_netns(nstoken); 1275 1276 return NULL; 1277 } 1278 1279 static void traffic_monitor_release(struct tmonitor_ctx *ctx) 1280 { 1281 pcap_close(ctx->pcap); 1282 pcap_dump_close(ctx->dumper); 1283 1284 close(ctx->wake_fd); 1285 1286 free(ctx); 1287 } 1288 1289 /* 1290 * Stop the network traffic monitor. 1291 * 1292 * ctx: the context returned by traffic_monitor_start() 1293 */ 1294 void traffic_monitor_stop(struct tmonitor_ctx *ctx) 1295 { 1296 __u64 w = 1; 1297 1298 if (!ctx) 1299 return; 1300 1301 /* Stop the monitor thread */ 1302 ctx->done = true; 1303 /* Wake up the background thread. */ 1304 write(ctx->wake_fd, &w, sizeof(w)); 1305 pthread_join(ctx->thread, NULL); 1306 1307 tm_print("Packet file: %s\n", strrchr(ctx->pkt_fname, '/') + 1); 1308 1309 traffic_monitor_release(ctx); 1310 } 1311 1312 #endif /* TRAFFIC_MONITOR */ 1313