1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (c) 2017-2018 Covalent IO, Inc. http://covalent.io 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <sys/socket.h> 6 #include <sys/ioctl.h> 7 #include <sys/select.h> 8 #include <netinet/in.h> 9 #include <arpa/inet.h> 10 #include <unistd.h> 11 #include <string.h> 12 #include <errno.h> 13 #include <stdbool.h> 14 #include <signal.h> 15 #include <fcntl.h> 16 #include <sys/wait.h> 17 #include <time.h> 18 #include <sched.h> 19 20 #include <sys/time.h> 21 #include <sys/resource.h> 22 #include <sys/types.h> 23 #include <sys/sendfile.h> 24 25 #include <linux/netlink.h> 26 #include <linux/socket.h> 27 #include <linux/sock_diag.h> 28 #include <linux/bpf.h> 29 #include <linux/if_link.h> 30 #include <linux/tls.h> 31 #include <assert.h> 32 #include <libgen.h> 33 34 #include <getopt.h> 35 36 #include <bpf/bpf.h> 37 #include <bpf/libbpf.h> 38 39 #include "bpf_util.h" 40 #include "bpf_rlimit.h" 41 #include "cgroup_helpers.h" 42 43 int running; 44 static void running_handler(int a); 45 46 #ifndef TCP_ULP 47 # define TCP_ULP 31 48 #endif 49 #ifndef SOL_TLS 50 # define SOL_TLS 282 51 #endif 52 53 /* randomly selected ports for testing on lo */ 54 #define S1_PORT 10000 55 #define S2_PORT 10001 56 57 #define BPF_SOCKMAP_FILENAME "test_sockmap_kern.o" 58 #define BPF_SOCKHASH_FILENAME "test_sockhash_kern.o" 59 #define CG_PATH "/sockmap" 60 61 /* global sockets */ 62 int s1, s2, c1, c2, p1, p2; 63 int test_cnt; 64 int passed; 65 int failed; 66 int map_fd[9]; 67 struct bpf_map *maps[9]; 68 int prog_fd[11]; 69 70 int txmsg_pass; 71 int txmsg_redir; 72 int txmsg_drop; 73 int txmsg_apply; 74 int txmsg_cork; 75 int txmsg_start; 76 int txmsg_end; 77 int txmsg_start_push; 78 int txmsg_end_push; 79 int txmsg_start_pop; 80 int txmsg_pop; 81 int txmsg_ingress; 82 int txmsg_redir_skb; 83 int txmsg_ktls_skb; 84 int txmsg_ktls_skb_drop; 85 int txmsg_ktls_skb_redir; 86 int ktls; 87 int peek_flag; 88 int skb_use_parser; 89 int txmsg_omit_skb_parser; 90 91 static const struct option long_options[] = { 92 {"help", no_argument, NULL, 'h' }, 93 {"cgroup", required_argument, NULL, 'c' }, 94 {"rate", required_argument, NULL, 'r' }, 95 {"verbose", optional_argument, NULL, 'v' }, 96 {"iov_count", required_argument, NULL, 'i' }, 97 {"length", required_argument, NULL, 'l' }, 98 {"test", required_argument, NULL, 't' }, 99 {"data_test", no_argument, NULL, 'd' }, 100 {"txmsg", no_argument, &txmsg_pass, 1 }, 101 {"txmsg_redir", no_argument, &txmsg_redir, 1 }, 102 {"txmsg_drop", no_argument, &txmsg_drop, 1 }, 103 {"txmsg_apply", required_argument, NULL, 'a'}, 104 {"txmsg_cork", required_argument, NULL, 'k'}, 105 {"txmsg_start", required_argument, NULL, 's'}, 106 {"txmsg_end", required_argument, NULL, 'e'}, 107 {"txmsg_start_push", required_argument, NULL, 'p'}, 108 {"txmsg_end_push", required_argument, NULL, 'q'}, 109 {"txmsg_start_pop", required_argument, NULL, 'w'}, 110 {"txmsg_pop", required_argument, NULL, 'x'}, 111 {"txmsg_ingress", no_argument, &txmsg_ingress, 1 }, 112 {"txmsg_redir_skb", no_argument, &txmsg_redir_skb, 1 }, 113 {"ktls", no_argument, &ktls, 1 }, 114 {"peek", no_argument, &peek_flag, 1 }, 115 {"txmsg_omit_skb_parser", no_argument, &txmsg_omit_skb_parser, 1}, 116 {"whitelist", required_argument, NULL, 'n' }, 117 {"blacklist", required_argument, NULL, 'b' }, 118 {0, 0, NULL, 0 } 119 }; 120 121 struct test_env { 122 const char *type; 123 const char *subtest; 124 const char *prepend; 125 126 int test_num; 127 int subtest_num; 128 129 int succ_cnt; 130 int fail_cnt; 131 int fail_last; 132 }; 133 134 struct test_env env; 135 136 struct sockmap_options { 137 int verbose; 138 bool base; 139 bool sendpage; 140 bool data_test; 141 bool drop_expected; 142 int iov_count; 143 int iov_length; 144 int rate; 145 char *map; 146 char *whitelist; 147 char *blacklist; 148 char *prepend; 149 }; 150 151 struct _test { 152 char *title; 153 void (*tester)(int cg_fd, struct sockmap_options *opt); 154 }; 155 156 static void test_start(void) 157 { 158 env.subtest_num++; 159 } 160 161 static void test_fail(void) 162 { 163 env.fail_cnt++; 164 } 165 166 static void test_pass(void) 167 { 168 env.succ_cnt++; 169 } 170 171 static void test_reset(void) 172 { 173 txmsg_start = txmsg_end = 0; 174 txmsg_start_pop = txmsg_pop = 0; 175 txmsg_start_push = txmsg_end_push = 0; 176 txmsg_pass = txmsg_drop = txmsg_redir = 0; 177 txmsg_apply = txmsg_cork = 0; 178 txmsg_ingress = txmsg_redir_skb = 0; 179 txmsg_ktls_skb = txmsg_ktls_skb_drop = txmsg_ktls_skb_redir = 0; 180 txmsg_omit_skb_parser = 0; 181 skb_use_parser = 0; 182 } 183 184 static int test_start_subtest(const struct _test *t, struct sockmap_options *o) 185 { 186 env.type = o->map; 187 env.subtest = t->title; 188 env.prepend = o->prepend; 189 env.test_num++; 190 env.subtest_num = 0; 191 env.fail_last = env.fail_cnt; 192 test_reset(); 193 return 0; 194 } 195 196 static void test_end_subtest(void) 197 { 198 int error = env.fail_cnt - env.fail_last; 199 int type = strcmp(env.type, BPF_SOCKMAP_FILENAME); 200 201 if (!error) 202 test_pass(); 203 204 fprintf(stdout, "#%2d/%2d %8s:%s:%s:%s\n", 205 env.test_num, env.subtest_num, 206 !type ? "sockmap" : "sockhash", 207 env.prepend ? : "", 208 env.subtest, error ? "FAIL" : "OK"); 209 } 210 211 static void test_print_results(void) 212 { 213 fprintf(stdout, "Pass: %d Fail: %d\n", 214 env.succ_cnt, env.fail_cnt); 215 } 216 217 static void usage(char *argv[]) 218 { 219 int i; 220 221 printf(" Usage: %s --cgroup <cgroup_path>\n", argv[0]); 222 printf(" options:\n"); 223 for (i = 0; long_options[i].name != 0; i++) { 224 printf(" --%-12s", long_options[i].name); 225 if (long_options[i].flag != NULL) 226 printf(" flag (internal value:%d)\n", 227 *long_options[i].flag); 228 else 229 printf(" -%c\n", long_options[i].val); 230 } 231 printf("\n"); 232 } 233 234 char *sock_to_string(int s) 235 { 236 if (s == c1) 237 return "client1"; 238 else if (s == c2) 239 return "client2"; 240 else if (s == s1) 241 return "server1"; 242 else if (s == s2) 243 return "server2"; 244 else if (s == p1) 245 return "peer1"; 246 else if (s == p2) 247 return "peer2"; 248 else 249 return "unknown"; 250 } 251 252 static int sockmap_init_ktls(int verbose, int s) 253 { 254 struct tls12_crypto_info_aes_gcm_128 tls_tx = { 255 .info = { 256 .version = TLS_1_2_VERSION, 257 .cipher_type = TLS_CIPHER_AES_GCM_128, 258 }, 259 }; 260 struct tls12_crypto_info_aes_gcm_128 tls_rx = { 261 .info = { 262 .version = TLS_1_2_VERSION, 263 .cipher_type = TLS_CIPHER_AES_GCM_128, 264 }, 265 }; 266 int so_buf = 6553500; 267 int err; 268 269 err = setsockopt(s, 6, TCP_ULP, "tls", sizeof("tls")); 270 if (err) { 271 fprintf(stderr, "setsockopt: TCP_ULP(%s) failed with error %i\n", sock_to_string(s), err); 272 return -EINVAL; 273 } 274 err = setsockopt(s, SOL_TLS, TLS_TX, (void *)&tls_tx, sizeof(tls_tx)); 275 if (err) { 276 fprintf(stderr, "setsockopt: TLS_TX(%s) failed with error %i\n", sock_to_string(s), err); 277 return -EINVAL; 278 } 279 err = setsockopt(s, SOL_TLS, TLS_RX, (void *)&tls_rx, sizeof(tls_rx)); 280 if (err) { 281 fprintf(stderr, "setsockopt: TLS_RX(%s) failed with error %i\n", sock_to_string(s), err); 282 return -EINVAL; 283 } 284 err = setsockopt(s, SOL_SOCKET, SO_SNDBUF, &so_buf, sizeof(so_buf)); 285 if (err) { 286 fprintf(stderr, "setsockopt: (%s) failed sndbuf with error %i\n", sock_to_string(s), err); 287 return -EINVAL; 288 } 289 err = setsockopt(s, SOL_SOCKET, SO_RCVBUF, &so_buf, sizeof(so_buf)); 290 if (err) { 291 fprintf(stderr, "setsockopt: (%s) failed rcvbuf with error %i\n", sock_to_string(s), err); 292 return -EINVAL; 293 } 294 295 if (verbose) 296 fprintf(stdout, "socket(%s) kTLS enabled\n", sock_to_string(s)); 297 return 0; 298 } 299 static int sockmap_init_sockets(int verbose) 300 { 301 int i, err, one = 1; 302 struct sockaddr_in addr; 303 int *fds[4] = {&s1, &s2, &c1, &c2}; 304 305 s1 = s2 = p1 = p2 = c1 = c2 = 0; 306 307 /* Init sockets */ 308 for (i = 0; i < 4; i++) { 309 *fds[i] = socket(AF_INET, SOCK_STREAM, 0); 310 if (*fds[i] < 0) { 311 perror("socket s1 failed()"); 312 return errno; 313 } 314 } 315 316 /* Allow reuse */ 317 for (i = 0; i < 2; i++) { 318 err = setsockopt(*fds[i], SOL_SOCKET, SO_REUSEADDR, 319 (char *)&one, sizeof(one)); 320 if (err) { 321 perror("setsockopt failed()"); 322 return errno; 323 } 324 } 325 326 /* Non-blocking sockets */ 327 for (i = 0; i < 2; i++) { 328 err = ioctl(*fds[i], FIONBIO, (char *)&one); 329 if (err < 0) { 330 perror("ioctl s1 failed()"); 331 return errno; 332 } 333 } 334 335 /* Bind server sockets */ 336 memset(&addr, 0, sizeof(struct sockaddr_in)); 337 addr.sin_family = AF_INET; 338 addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 339 340 addr.sin_port = htons(S1_PORT); 341 err = bind(s1, (struct sockaddr *)&addr, sizeof(addr)); 342 if (err < 0) { 343 perror("bind s1 failed()"); 344 return errno; 345 } 346 347 addr.sin_port = htons(S2_PORT); 348 err = bind(s2, (struct sockaddr *)&addr, sizeof(addr)); 349 if (err < 0) { 350 perror("bind s2 failed()"); 351 return errno; 352 } 353 354 /* Listen server sockets */ 355 addr.sin_port = htons(S1_PORT); 356 err = listen(s1, 32); 357 if (err < 0) { 358 perror("listen s1 failed()"); 359 return errno; 360 } 361 362 addr.sin_port = htons(S2_PORT); 363 err = listen(s2, 32); 364 if (err < 0) { 365 perror("listen s1 failed()"); 366 return errno; 367 } 368 369 /* Initiate Connect */ 370 addr.sin_port = htons(S1_PORT); 371 err = connect(c1, (struct sockaddr *)&addr, sizeof(addr)); 372 if (err < 0 && errno != EINPROGRESS) { 373 perror("connect c1 failed()"); 374 return errno; 375 } 376 377 addr.sin_port = htons(S2_PORT); 378 err = connect(c2, (struct sockaddr *)&addr, sizeof(addr)); 379 if (err < 0 && errno != EINPROGRESS) { 380 perror("connect c2 failed()"); 381 return errno; 382 } else if (err < 0) { 383 err = 0; 384 } 385 386 /* Accept Connecrtions */ 387 p1 = accept(s1, NULL, NULL); 388 if (p1 < 0) { 389 perror("accept s1 failed()"); 390 return errno; 391 } 392 393 p2 = accept(s2, NULL, NULL); 394 if (p2 < 0) { 395 perror("accept s1 failed()"); 396 return errno; 397 } 398 399 if (verbose > 1) { 400 printf("connected sockets: c1 <-> p1, c2 <-> p2\n"); 401 printf("cgroups binding: c1(%i) <-> s1(%i) - - - c2(%i) <-> s2(%i)\n", 402 c1, s1, c2, s2); 403 } 404 return 0; 405 } 406 407 struct msg_stats { 408 size_t bytes_sent; 409 size_t bytes_recvd; 410 struct timespec start; 411 struct timespec end; 412 }; 413 414 static int msg_loop_sendpage(int fd, int iov_length, int cnt, 415 struct msg_stats *s, 416 struct sockmap_options *opt) 417 { 418 bool drop = opt->drop_expected; 419 unsigned char k = 0; 420 FILE *file; 421 int i, fp; 422 423 file = tmpfile(); 424 if (!file) { 425 perror("create file for sendpage"); 426 return 1; 427 } 428 for (i = 0; i < iov_length * cnt; i++, k++) 429 fwrite(&k, sizeof(char), 1, file); 430 fflush(file); 431 fseek(file, 0, SEEK_SET); 432 433 fp = fileno(file); 434 435 clock_gettime(CLOCK_MONOTONIC, &s->start); 436 for (i = 0; i < cnt; i++) { 437 int sent; 438 439 errno = 0; 440 sent = sendfile(fd, fp, NULL, iov_length); 441 442 if (!drop && sent < 0) { 443 perror("sendpage loop error"); 444 fclose(file); 445 return sent; 446 } else if (drop && sent >= 0) { 447 printf("sendpage loop error expected: %i errno %i\n", 448 sent, errno); 449 fclose(file); 450 return -EIO; 451 } 452 453 if (sent > 0) 454 s->bytes_sent += sent; 455 } 456 clock_gettime(CLOCK_MONOTONIC, &s->end); 457 fclose(file); 458 return 0; 459 } 460 461 static void msg_free_iov(struct msghdr *msg) 462 { 463 int i; 464 465 for (i = 0; i < msg->msg_iovlen; i++) 466 free(msg->msg_iov[i].iov_base); 467 free(msg->msg_iov); 468 msg->msg_iov = NULL; 469 msg->msg_iovlen = 0; 470 } 471 472 static int msg_alloc_iov(struct msghdr *msg, 473 int iov_count, int iov_length, 474 bool data, bool xmit) 475 { 476 unsigned char k = 0; 477 struct iovec *iov; 478 int i; 479 480 iov = calloc(iov_count, sizeof(struct iovec)); 481 if (!iov) 482 return errno; 483 484 for (i = 0; i < iov_count; i++) { 485 unsigned char *d = calloc(iov_length, sizeof(char)); 486 487 if (!d) { 488 fprintf(stderr, "iov_count %i/%i OOM\n", i, iov_count); 489 goto unwind_iov; 490 } 491 iov[i].iov_base = d; 492 iov[i].iov_len = iov_length; 493 494 if (data && xmit) { 495 int j; 496 497 for (j = 0; j < iov_length; j++) 498 d[j] = k++; 499 } 500 } 501 502 msg->msg_iov = iov; 503 msg->msg_iovlen = iov_count; 504 505 return 0; 506 unwind_iov: 507 for (i--; i >= 0 ; i--) 508 free(msg->msg_iov[i].iov_base); 509 return -ENOMEM; 510 } 511 512 static int msg_verify_data(struct msghdr *msg, int size, int chunk_sz) 513 { 514 int i, j = 0, bytes_cnt = 0; 515 unsigned char k = 0; 516 517 for (i = 0; i < msg->msg_iovlen; i++) { 518 unsigned char *d = msg->msg_iov[i].iov_base; 519 520 /* Special case test for skb ingress + ktls */ 521 if (i == 0 && txmsg_ktls_skb) { 522 if (msg->msg_iov[i].iov_len < 4) 523 return -EIO; 524 if (memcmp(d, "PASS", 4) != 0) { 525 fprintf(stderr, 526 "detected skb data error with skb ingress update @iov[%i]:%i \"%02x %02x %02x %02x\" != \"PASS\"\n", 527 i, 0, d[0], d[1], d[2], d[3]); 528 return -EIO; 529 } 530 j = 4; /* advance index past PASS header */ 531 } 532 533 for (; j < msg->msg_iov[i].iov_len && size; j++) { 534 if (d[j] != k++) { 535 fprintf(stderr, 536 "detected data corruption @iov[%i]:%i %02x != %02x, %02x ?= %02x\n", 537 i, j, d[j], k - 1, d[j+1], k); 538 return -EIO; 539 } 540 bytes_cnt++; 541 if (bytes_cnt == chunk_sz) { 542 k = 0; 543 bytes_cnt = 0; 544 } 545 size--; 546 } 547 } 548 return 0; 549 } 550 551 static int msg_loop(int fd, int iov_count, int iov_length, int cnt, 552 struct msg_stats *s, bool tx, 553 struct sockmap_options *opt) 554 { 555 struct msghdr msg = {0}, msg_peek = {0}; 556 int err, i, flags = MSG_NOSIGNAL; 557 bool drop = opt->drop_expected; 558 bool data = opt->data_test; 559 560 err = msg_alloc_iov(&msg, iov_count, iov_length, data, tx); 561 if (err) 562 goto out_errno; 563 if (peek_flag) { 564 err = msg_alloc_iov(&msg_peek, iov_count, iov_length, data, tx); 565 if (err) 566 goto out_errno; 567 } 568 569 if (tx) { 570 clock_gettime(CLOCK_MONOTONIC, &s->start); 571 for (i = 0; i < cnt; i++) { 572 int sent; 573 574 errno = 0; 575 sent = sendmsg(fd, &msg, flags); 576 577 if (!drop && sent < 0) { 578 perror("sendmsg loop error"); 579 goto out_errno; 580 } else if (drop && sent >= 0) { 581 fprintf(stderr, 582 "sendmsg loop error expected: %i errno %i\n", 583 sent, errno); 584 errno = -EIO; 585 goto out_errno; 586 } 587 if (sent > 0) 588 s->bytes_sent += sent; 589 } 590 clock_gettime(CLOCK_MONOTONIC, &s->end); 591 } else { 592 int slct, recvp = 0, recv, max_fd = fd; 593 float total_bytes, txmsg_pop_total; 594 int fd_flags = O_NONBLOCK; 595 struct timeval timeout; 596 fd_set w; 597 598 fcntl(fd, fd_flags); 599 /* Account for pop bytes noting each iteration of apply will 600 * call msg_pop_data helper so we need to account for this 601 * by calculating the number of apply iterations. Note user 602 * of the tool can create cases where no data is sent by 603 * manipulating pop/push/pull/etc. For example txmsg_apply 1 604 * with txmsg_pop 1 will try to apply 1B at a time but each 605 * iteration will then pop 1B so no data will ever be sent. 606 * This is really only useful for testing edge cases in code 607 * paths. 608 */ 609 total_bytes = (float)iov_count * (float)iov_length * (float)cnt; 610 if (txmsg_apply) 611 txmsg_pop_total = txmsg_pop * (total_bytes / txmsg_apply); 612 else 613 txmsg_pop_total = txmsg_pop * cnt; 614 total_bytes -= txmsg_pop_total; 615 err = clock_gettime(CLOCK_MONOTONIC, &s->start); 616 if (err < 0) 617 perror("recv start time"); 618 while (s->bytes_recvd < total_bytes) { 619 if (txmsg_cork) { 620 timeout.tv_sec = 0; 621 timeout.tv_usec = 300000; 622 } else { 623 timeout.tv_sec = 3; 624 timeout.tv_usec = 0; 625 } 626 627 /* FD sets */ 628 FD_ZERO(&w); 629 FD_SET(fd, &w); 630 631 slct = select(max_fd + 1, &w, NULL, NULL, &timeout); 632 if (slct == -1) { 633 perror("select()"); 634 clock_gettime(CLOCK_MONOTONIC, &s->end); 635 goto out_errno; 636 } else if (!slct) { 637 if (opt->verbose) 638 fprintf(stderr, "unexpected timeout: recved %zu/%f pop_total %f\n", s->bytes_recvd, total_bytes, txmsg_pop_total); 639 errno = -EIO; 640 clock_gettime(CLOCK_MONOTONIC, &s->end); 641 goto out_errno; 642 } 643 644 errno = 0; 645 if (peek_flag) { 646 flags |= MSG_PEEK; 647 recvp = recvmsg(fd, &msg_peek, flags); 648 if (recvp < 0) { 649 if (errno != EWOULDBLOCK) { 650 clock_gettime(CLOCK_MONOTONIC, &s->end); 651 goto out_errno; 652 } 653 } 654 flags = 0; 655 } 656 657 recv = recvmsg(fd, &msg, flags); 658 if (recv < 0) { 659 if (errno != EWOULDBLOCK) { 660 clock_gettime(CLOCK_MONOTONIC, &s->end); 661 perror("recv failed()"); 662 goto out_errno; 663 } 664 } 665 666 s->bytes_recvd += recv; 667 668 if (data) { 669 int chunk_sz = opt->sendpage ? 670 iov_length * cnt : 671 iov_length * iov_count; 672 673 errno = msg_verify_data(&msg, recv, chunk_sz); 674 if (errno) { 675 perror("data verify msg failed"); 676 goto out_errno; 677 } 678 if (recvp) { 679 errno = msg_verify_data(&msg_peek, 680 recvp, 681 chunk_sz); 682 if (errno) { 683 perror("data verify msg_peek failed"); 684 goto out_errno; 685 } 686 } 687 } 688 } 689 clock_gettime(CLOCK_MONOTONIC, &s->end); 690 } 691 692 msg_free_iov(&msg); 693 msg_free_iov(&msg_peek); 694 return err; 695 out_errno: 696 msg_free_iov(&msg); 697 msg_free_iov(&msg_peek); 698 return errno; 699 } 700 701 static float giga = 1000000000; 702 703 static inline float sentBps(struct msg_stats s) 704 { 705 return s.bytes_sent / (s.end.tv_sec - s.start.tv_sec); 706 } 707 708 static inline float recvdBps(struct msg_stats s) 709 { 710 return s.bytes_recvd / (s.end.tv_sec - s.start.tv_sec); 711 } 712 713 static int sendmsg_test(struct sockmap_options *opt) 714 { 715 float sent_Bps = 0, recvd_Bps = 0; 716 int rx_fd, txpid, rxpid, err = 0; 717 struct msg_stats s = {0}; 718 int iov_count = opt->iov_count; 719 int iov_buf = opt->iov_length; 720 int rx_status, tx_status; 721 int cnt = opt->rate; 722 723 errno = 0; 724 725 if (opt->base) 726 rx_fd = p1; 727 else 728 rx_fd = p2; 729 730 if (ktls) { 731 /* Redirecting into non-TLS socket which sends into a TLS 732 * socket is not a valid test. So in this case lets not 733 * enable kTLS but still run the test. 734 */ 735 if (!txmsg_redir || (txmsg_redir && txmsg_ingress)) { 736 err = sockmap_init_ktls(opt->verbose, rx_fd); 737 if (err) 738 return err; 739 } 740 err = sockmap_init_ktls(opt->verbose, c1); 741 if (err) 742 return err; 743 } 744 745 rxpid = fork(); 746 if (rxpid == 0) { 747 iov_buf -= (txmsg_pop - txmsg_start_pop + 1); 748 if (opt->drop_expected || txmsg_ktls_skb_drop) 749 _exit(0); 750 751 if (!iov_buf) /* zero bytes sent case */ 752 _exit(0); 753 754 if (opt->sendpage) 755 iov_count = 1; 756 err = msg_loop(rx_fd, iov_count, iov_buf, 757 cnt, &s, false, opt); 758 if (opt->verbose > 1) 759 fprintf(stderr, 760 "msg_loop_rx: iov_count %i iov_buf %i cnt %i err %i\n", 761 iov_count, iov_buf, cnt, err); 762 if (s.end.tv_sec - s.start.tv_sec) { 763 sent_Bps = sentBps(s); 764 recvd_Bps = recvdBps(s); 765 } 766 if (opt->verbose > 1) 767 fprintf(stdout, 768 "rx_sendmsg: TX: %zuB %fB/s %fGB/s RX: %zuB %fB/s %fGB/s %s\n", 769 s.bytes_sent, sent_Bps, sent_Bps/giga, 770 s.bytes_recvd, recvd_Bps, recvd_Bps/giga, 771 peek_flag ? "(peek_msg)" : ""); 772 if (err && txmsg_cork) 773 err = 0; 774 exit(err ? 1 : 0); 775 } else if (rxpid == -1) { 776 perror("msg_loop_rx"); 777 return errno; 778 } 779 780 txpid = fork(); 781 if (txpid == 0) { 782 if (opt->sendpage) 783 err = msg_loop_sendpage(c1, iov_buf, cnt, &s, opt); 784 else 785 err = msg_loop(c1, iov_count, iov_buf, 786 cnt, &s, true, opt); 787 788 if (err) 789 fprintf(stderr, 790 "msg_loop_tx: iov_count %i iov_buf %i cnt %i err %i\n", 791 iov_count, iov_buf, cnt, err); 792 if (s.end.tv_sec - s.start.tv_sec) { 793 sent_Bps = sentBps(s); 794 recvd_Bps = recvdBps(s); 795 } 796 if (opt->verbose > 1) 797 fprintf(stdout, 798 "tx_sendmsg: TX: %zuB %fB/s %f GB/s RX: %zuB %fB/s %fGB/s\n", 799 s.bytes_sent, sent_Bps, sent_Bps/giga, 800 s.bytes_recvd, recvd_Bps, recvd_Bps/giga); 801 exit(err ? 1 : 0); 802 } else if (txpid == -1) { 803 perror("msg_loop_tx"); 804 return errno; 805 } 806 807 assert(waitpid(rxpid, &rx_status, 0) == rxpid); 808 assert(waitpid(txpid, &tx_status, 0) == txpid); 809 if (WIFEXITED(rx_status)) { 810 err = WEXITSTATUS(rx_status); 811 if (err) { 812 fprintf(stderr, "rx thread exited with err %d.\n", err); 813 goto out; 814 } 815 } 816 if (WIFEXITED(tx_status)) { 817 err = WEXITSTATUS(tx_status); 818 if (err) 819 fprintf(stderr, "tx thread exited with err %d.\n", err); 820 } 821 out: 822 return err; 823 } 824 825 static int forever_ping_pong(int rate, struct sockmap_options *opt) 826 { 827 struct timeval timeout; 828 char buf[1024] = {0}; 829 int sc; 830 831 timeout.tv_sec = 10; 832 timeout.tv_usec = 0; 833 834 /* Ping/Pong data from client to server */ 835 sc = send(c1, buf, sizeof(buf), 0); 836 if (sc < 0) { 837 perror("send failed()"); 838 return sc; 839 } 840 841 do { 842 int s, rc, i, max_fd = p2; 843 fd_set w; 844 845 /* FD sets */ 846 FD_ZERO(&w); 847 FD_SET(c1, &w); 848 FD_SET(c2, &w); 849 FD_SET(p1, &w); 850 FD_SET(p2, &w); 851 852 s = select(max_fd + 1, &w, NULL, NULL, &timeout); 853 if (s == -1) { 854 perror("select()"); 855 break; 856 } else if (!s) { 857 fprintf(stderr, "unexpected timeout\n"); 858 break; 859 } 860 861 for (i = 0; i <= max_fd && s > 0; ++i) { 862 if (!FD_ISSET(i, &w)) 863 continue; 864 865 s--; 866 867 rc = recv(i, buf, sizeof(buf), 0); 868 if (rc < 0) { 869 if (errno != EWOULDBLOCK) { 870 perror("recv failed()"); 871 return rc; 872 } 873 } 874 875 if (rc == 0) { 876 close(i); 877 break; 878 } 879 880 sc = send(i, buf, rc, 0); 881 if (sc < 0) { 882 perror("send failed()"); 883 return sc; 884 } 885 } 886 887 if (rate) 888 sleep(rate); 889 890 if (opt->verbose) { 891 printf("."); 892 fflush(stdout); 893 894 } 895 } while (running); 896 897 return 0; 898 } 899 900 enum { 901 SELFTESTS, 902 PING_PONG, 903 SENDMSG, 904 BASE, 905 BASE_SENDPAGE, 906 SENDPAGE, 907 }; 908 909 static int run_options(struct sockmap_options *options, int cg_fd, int test) 910 { 911 int i, key, next_key, err, tx_prog_fd = -1, zero = 0; 912 913 /* If base test skip BPF setup */ 914 if (test == BASE || test == BASE_SENDPAGE) 915 goto run; 916 917 /* Attach programs to sockmap */ 918 if (!txmsg_omit_skb_parser) { 919 err = bpf_prog_attach(prog_fd[0], map_fd[0], 920 BPF_SK_SKB_STREAM_PARSER, 0); 921 if (err) { 922 fprintf(stderr, 923 "ERROR: bpf_prog_attach (sockmap %i->%i): %d (%s)\n", 924 prog_fd[0], map_fd[0], err, strerror(errno)); 925 return err; 926 } 927 } 928 929 err = bpf_prog_attach(prog_fd[1], map_fd[0], 930 BPF_SK_SKB_STREAM_VERDICT, 0); 931 if (err) { 932 fprintf(stderr, "ERROR: bpf_prog_attach (sockmap): %d (%s)\n", 933 err, strerror(errno)); 934 return err; 935 } 936 937 /* Attach programs to TLS sockmap */ 938 if (txmsg_ktls_skb) { 939 if (!txmsg_omit_skb_parser) { 940 err = bpf_prog_attach(prog_fd[0], map_fd[8], 941 BPF_SK_SKB_STREAM_PARSER, 0); 942 if (err) { 943 fprintf(stderr, 944 "ERROR: bpf_prog_attach (TLS sockmap %i->%i): %d (%s)\n", 945 prog_fd[0], map_fd[8], err, strerror(errno)); 946 return err; 947 } 948 } 949 950 err = bpf_prog_attach(prog_fd[2], map_fd[8], 951 BPF_SK_SKB_STREAM_VERDICT, 0); 952 if (err) { 953 fprintf(stderr, "ERROR: bpf_prog_attach (TLS sockmap): %d (%s)\n", 954 err, strerror(errno)); 955 return err; 956 } 957 } 958 959 /* Attach to cgroups */ 960 err = bpf_prog_attach(prog_fd[3], cg_fd, BPF_CGROUP_SOCK_OPS, 0); 961 if (err) { 962 fprintf(stderr, "ERROR: bpf_prog_attach (groups): %d (%s)\n", 963 err, strerror(errno)); 964 return err; 965 } 966 967 run: 968 err = sockmap_init_sockets(options->verbose); 969 if (err) { 970 fprintf(stderr, "ERROR: test socket failed: %d\n", err); 971 goto out; 972 } 973 974 /* Attach txmsg program to sockmap */ 975 if (txmsg_pass) 976 tx_prog_fd = prog_fd[4]; 977 else if (txmsg_redir) 978 tx_prog_fd = prog_fd[5]; 979 else if (txmsg_apply) 980 tx_prog_fd = prog_fd[6]; 981 else if (txmsg_cork) 982 tx_prog_fd = prog_fd[7]; 983 else if (txmsg_drop) 984 tx_prog_fd = prog_fd[8]; 985 else 986 tx_prog_fd = 0; 987 988 if (tx_prog_fd) { 989 int redir_fd, i = 0; 990 991 err = bpf_prog_attach(tx_prog_fd, 992 map_fd[1], BPF_SK_MSG_VERDICT, 0); 993 if (err) { 994 fprintf(stderr, 995 "ERROR: bpf_prog_attach (txmsg): %d (%s)\n", 996 err, strerror(errno)); 997 goto out; 998 } 999 1000 err = bpf_map_update_elem(map_fd[1], &i, &c1, BPF_ANY); 1001 if (err) { 1002 fprintf(stderr, 1003 "ERROR: bpf_map_update_elem (txmsg): %d (%s\n", 1004 err, strerror(errno)); 1005 goto out; 1006 } 1007 1008 if (txmsg_redir) 1009 redir_fd = c2; 1010 else 1011 redir_fd = c1; 1012 1013 err = bpf_map_update_elem(map_fd[2], &i, &redir_fd, BPF_ANY); 1014 if (err) { 1015 fprintf(stderr, 1016 "ERROR: bpf_map_update_elem (txmsg): %d (%s\n", 1017 err, strerror(errno)); 1018 goto out; 1019 } 1020 1021 if (txmsg_apply) { 1022 err = bpf_map_update_elem(map_fd[3], 1023 &i, &txmsg_apply, BPF_ANY); 1024 if (err) { 1025 fprintf(stderr, 1026 "ERROR: bpf_map_update_elem (apply_bytes): %d (%s\n", 1027 err, strerror(errno)); 1028 goto out; 1029 } 1030 } 1031 1032 if (txmsg_cork) { 1033 err = bpf_map_update_elem(map_fd[4], 1034 &i, &txmsg_cork, BPF_ANY); 1035 if (err) { 1036 fprintf(stderr, 1037 "ERROR: bpf_map_update_elem (cork_bytes): %d (%s\n", 1038 err, strerror(errno)); 1039 goto out; 1040 } 1041 } 1042 1043 if (txmsg_start) { 1044 err = bpf_map_update_elem(map_fd[5], 1045 &i, &txmsg_start, BPF_ANY); 1046 if (err) { 1047 fprintf(stderr, 1048 "ERROR: bpf_map_update_elem (txmsg_start): %d (%s)\n", 1049 err, strerror(errno)); 1050 goto out; 1051 } 1052 } 1053 1054 if (txmsg_end) { 1055 i = 1; 1056 err = bpf_map_update_elem(map_fd[5], 1057 &i, &txmsg_end, BPF_ANY); 1058 if (err) { 1059 fprintf(stderr, 1060 "ERROR: bpf_map_update_elem (txmsg_end): %d (%s)\n", 1061 err, strerror(errno)); 1062 goto out; 1063 } 1064 } 1065 1066 if (txmsg_start_push) { 1067 i = 2; 1068 err = bpf_map_update_elem(map_fd[5], 1069 &i, &txmsg_start_push, BPF_ANY); 1070 if (err) { 1071 fprintf(stderr, 1072 "ERROR: bpf_map_update_elem (txmsg_start_push): %d (%s)\n", 1073 err, strerror(errno)); 1074 goto out; 1075 } 1076 } 1077 1078 if (txmsg_end_push) { 1079 i = 3; 1080 err = bpf_map_update_elem(map_fd[5], 1081 &i, &txmsg_end_push, BPF_ANY); 1082 if (err) { 1083 fprintf(stderr, 1084 "ERROR: bpf_map_update_elem %i@%i (txmsg_end_push): %d (%s)\n", 1085 txmsg_end_push, i, err, strerror(errno)); 1086 goto out; 1087 } 1088 } 1089 1090 if (txmsg_start_pop) { 1091 i = 4; 1092 err = bpf_map_update_elem(map_fd[5], 1093 &i, &txmsg_start_pop, BPF_ANY); 1094 if (err) { 1095 fprintf(stderr, 1096 "ERROR: bpf_map_update_elem %i@%i (txmsg_start_pop): %d (%s)\n", 1097 txmsg_start_pop, i, err, strerror(errno)); 1098 goto out; 1099 } 1100 } else { 1101 i = 4; 1102 bpf_map_update_elem(map_fd[5], 1103 &i, &txmsg_start_pop, BPF_ANY); 1104 } 1105 1106 if (txmsg_pop) { 1107 i = 5; 1108 err = bpf_map_update_elem(map_fd[5], 1109 &i, &txmsg_pop, BPF_ANY); 1110 if (err) { 1111 fprintf(stderr, 1112 "ERROR: bpf_map_update_elem %i@%i (txmsg_pop): %d (%s)\n", 1113 txmsg_pop, i, err, strerror(errno)); 1114 goto out; 1115 } 1116 } else { 1117 i = 5; 1118 bpf_map_update_elem(map_fd[5], 1119 &i, &txmsg_pop, BPF_ANY); 1120 1121 } 1122 1123 if (txmsg_ingress) { 1124 int in = BPF_F_INGRESS; 1125 1126 i = 0; 1127 err = bpf_map_update_elem(map_fd[6], &i, &in, BPF_ANY); 1128 if (err) { 1129 fprintf(stderr, 1130 "ERROR: bpf_map_update_elem (txmsg_ingress): %d (%s)\n", 1131 err, strerror(errno)); 1132 } 1133 i = 1; 1134 err = bpf_map_update_elem(map_fd[1], &i, &p1, BPF_ANY); 1135 if (err) { 1136 fprintf(stderr, 1137 "ERROR: bpf_map_update_elem (p1 txmsg): %d (%s)\n", 1138 err, strerror(errno)); 1139 } 1140 err = bpf_map_update_elem(map_fd[2], &i, &p1, BPF_ANY); 1141 if (err) { 1142 fprintf(stderr, 1143 "ERROR: bpf_map_update_elem (p1 redir): %d (%s)\n", 1144 err, strerror(errno)); 1145 } 1146 1147 i = 2; 1148 err = bpf_map_update_elem(map_fd[2], &i, &p2, BPF_ANY); 1149 if (err) { 1150 fprintf(stderr, 1151 "ERROR: bpf_map_update_elem (p2 txmsg): %d (%s)\n", 1152 err, strerror(errno)); 1153 } 1154 } 1155 1156 if (txmsg_ktls_skb) { 1157 int ingress = BPF_F_INGRESS; 1158 1159 i = 0; 1160 err = bpf_map_update_elem(map_fd[8], &i, &p2, BPF_ANY); 1161 if (err) { 1162 fprintf(stderr, 1163 "ERROR: bpf_map_update_elem (c1 sockmap): %d (%s)\n", 1164 err, strerror(errno)); 1165 } 1166 1167 if (txmsg_ktls_skb_redir) { 1168 i = 1; 1169 err = bpf_map_update_elem(map_fd[7], 1170 &i, &ingress, BPF_ANY); 1171 if (err) { 1172 fprintf(stderr, 1173 "ERROR: bpf_map_update_elem (txmsg_ingress): %d (%s)\n", 1174 err, strerror(errno)); 1175 } 1176 } 1177 1178 if (txmsg_ktls_skb_drop) { 1179 i = 1; 1180 err = bpf_map_update_elem(map_fd[7], &i, &i, BPF_ANY); 1181 } 1182 } 1183 1184 if (txmsg_redir_skb) { 1185 int skb_fd = (test == SENDMSG || test == SENDPAGE) ? 1186 p2 : p1; 1187 int ingress = BPF_F_INGRESS; 1188 1189 i = 0; 1190 err = bpf_map_update_elem(map_fd[7], 1191 &i, &ingress, BPF_ANY); 1192 if (err) { 1193 fprintf(stderr, 1194 "ERROR: bpf_map_update_elem (txmsg_ingress): %d (%s)\n", 1195 err, strerror(errno)); 1196 } 1197 1198 i = 3; 1199 err = bpf_map_update_elem(map_fd[0], &i, &skb_fd, BPF_ANY); 1200 if (err) { 1201 fprintf(stderr, 1202 "ERROR: bpf_map_update_elem (c1 sockmap): %d (%s)\n", 1203 err, strerror(errno)); 1204 } 1205 } 1206 } 1207 1208 if (skb_use_parser) { 1209 i = 2; 1210 err = bpf_map_update_elem(map_fd[7], &i, &skb_use_parser, BPF_ANY); 1211 } 1212 1213 if (txmsg_drop) 1214 options->drop_expected = true; 1215 1216 if (test == PING_PONG) 1217 err = forever_ping_pong(options->rate, options); 1218 else if (test == SENDMSG) { 1219 options->base = false; 1220 options->sendpage = false; 1221 err = sendmsg_test(options); 1222 } else if (test == SENDPAGE) { 1223 options->base = false; 1224 options->sendpage = true; 1225 err = sendmsg_test(options); 1226 } else if (test == BASE) { 1227 options->base = true; 1228 options->sendpage = false; 1229 err = sendmsg_test(options); 1230 } else if (test == BASE_SENDPAGE) { 1231 options->base = true; 1232 options->sendpage = true; 1233 err = sendmsg_test(options); 1234 } else 1235 fprintf(stderr, "unknown test\n"); 1236 out: 1237 /* Detatch and zero all the maps */ 1238 bpf_prog_detach2(prog_fd[3], cg_fd, BPF_CGROUP_SOCK_OPS); 1239 bpf_prog_detach2(prog_fd[0], map_fd[0], BPF_SK_SKB_STREAM_PARSER); 1240 bpf_prog_detach2(prog_fd[1], map_fd[0], BPF_SK_SKB_STREAM_VERDICT); 1241 bpf_prog_detach2(prog_fd[0], map_fd[8], BPF_SK_SKB_STREAM_PARSER); 1242 bpf_prog_detach2(prog_fd[2], map_fd[8], BPF_SK_SKB_STREAM_VERDICT); 1243 1244 if (tx_prog_fd >= 0) 1245 bpf_prog_detach2(tx_prog_fd, map_fd[1], BPF_SK_MSG_VERDICT); 1246 1247 for (i = 0; i < 8; i++) { 1248 key = next_key = 0; 1249 bpf_map_update_elem(map_fd[i], &key, &zero, BPF_ANY); 1250 while (bpf_map_get_next_key(map_fd[i], &key, &next_key) == 0) { 1251 bpf_map_update_elem(map_fd[i], &key, &zero, BPF_ANY); 1252 key = next_key; 1253 } 1254 } 1255 1256 close(s1); 1257 close(s2); 1258 close(p1); 1259 close(p2); 1260 close(c1); 1261 close(c2); 1262 return err; 1263 } 1264 1265 static char *test_to_str(int test) 1266 { 1267 switch (test) { 1268 case SENDMSG: 1269 return "sendmsg"; 1270 case SENDPAGE: 1271 return "sendpage"; 1272 } 1273 return "unknown"; 1274 } 1275 1276 static void append_str(char *dst, const char *src, size_t dst_cap) 1277 { 1278 size_t avail = dst_cap - strlen(dst); 1279 1280 if (avail <= 1) /* just zero byte could be written */ 1281 return; 1282 1283 strncat(dst, src, avail - 1); /* strncat() adds + 1 for zero byte */ 1284 } 1285 1286 #define OPTSTRING 60 1287 static void test_options(char *options) 1288 { 1289 char tstr[OPTSTRING]; 1290 1291 memset(options, 0, OPTSTRING); 1292 1293 if (txmsg_pass) 1294 append_str(options, "pass,", OPTSTRING); 1295 if (txmsg_redir) 1296 append_str(options, "redir,", OPTSTRING); 1297 if (txmsg_drop) 1298 append_str(options, "drop,", OPTSTRING); 1299 if (txmsg_apply) { 1300 snprintf(tstr, OPTSTRING, "apply %d,", txmsg_apply); 1301 append_str(options, tstr, OPTSTRING); 1302 } 1303 if (txmsg_cork) { 1304 snprintf(tstr, OPTSTRING, "cork %d,", txmsg_cork); 1305 append_str(options, tstr, OPTSTRING); 1306 } 1307 if (txmsg_start) { 1308 snprintf(tstr, OPTSTRING, "start %d,", txmsg_start); 1309 append_str(options, tstr, OPTSTRING); 1310 } 1311 if (txmsg_end) { 1312 snprintf(tstr, OPTSTRING, "end %d,", txmsg_end); 1313 append_str(options, tstr, OPTSTRING); 1314 } 1315 if (txmsg_start_pop) { 1316 snprintf(tstr, OPTSTRING, "pop (%d,%d),", 1317 txmsg_start_pop, txmsg_start_pop + txmsg_pop); 1318 append_str(options, tstr, OPTSTRING); 1319 } 1320 if (txmsg_ingress) 1321 append_str(options, "ingress,", OPTSTRING); 1322 if (txmsg_redir_skb) 1323 append_str(options, "redir_skb,", OPTSTRING); 1324 if (txmsg_ktls_skb) 1325 append_str(options, "ktls_skb,", OPTSTRING); 1326 if (ktls) 1327 append_str(options, "ktls,", OPTSTRING); 1328 if (peek_flag) 1329 append_str(options, "peek,", OPTSTRING); 1330 } 1331 1332 static int __test_exec(int cgrp, int test, struct sockmap_options *opt) 1333 { 1334 char *options = calloc(OPTSTRING, sizeof(char)); 1335 int err; 1336 1337 if (test == SENDPAGE) 1338 opt->sendpage = true; 1339 else 1340 opt->sendpage = false; 1341 1342 if (txmsg_drop) 1343 opt->drop_expected = true; 1344 else 1345 opt->drop_expected = false; 1346 1347 test_options(options); 1348 1349 if (opt->verbose) { 1350 fprintf(stdout, 1351 " [TEST %i]: (%i, %i, %i, %s, %s): ", 1352 test_cnt, opt->rate, opt->iov_count, opt->iov_length, 1353 test_to_str(test), options); 1354 fflush(stdout); 1355 } 1356 err = run_options(opt, cgrp, test); 1357 if (opt->verbose) 1358 fprintf(stdout, " %s\n", !err ? "PASS" : "FAILED"); 1359 test_cnt++; 1360 !err ? passed++ : failed++; 1361 free(options); 1362 return err; 1363 } 1364 1365 static void test_exec(int cgrp, struct sockmap_options *opt) 1366 { 1367 int type = strcmp(opt->map, BPF_SOCKMAP_FILENAME); 1368 int err; 1369 1370 if (type == 0) { 1371 test_start(); 1372 err = __test_exec(cgrp, SENDMSG, opt); 1373 if (err) 1374 test_fail(); 1375 } else { 1376 test_start(); 1377 err = __test_exec(cgrp, SENDPAGE, opt); 1378 if (err) 1379 test_fail(); 1380 } 1381 } 1382 1383 static void test_send_one(struct sockmap_options *opt, int cgrp) 1384 { 1385 opt->iov_length = 1; 1386 opt->iov_count = 1; 1387 opt->rate = 1; 1388 test_exec(cgrp, opt); 1389 1390 opt->iov_length = 1; 1391 opt->iov_count = 1024; 1392 opt->rate = 1; 1393 test_exec(cgrp, opt); 1394 1395 opt->iov_length = 1024; 1396 opt->iov_count = 1; 1397 opt->rate = 1; 1398 test_exec(cgrp, opt); 1399 1400 } 1401 1402 static void test_send_many(struct sockmap_options *opt, int cgrp) 1403 { 1404 opt->iov_length = 3; 1405 opt->iov_count = 1; 1406 opt->rate = 512; 1407 test_exec(cgrp, opt); 1408 1409 opt->rate = 100; 1410 opt->iov_count = 1; 1411 opt->iov_length = 5; 1412 test_exec(cgrp, opt); 1413 } 1414 1415 static void test_send_large(struct sockmap_options *opt, int cgrp) 1416 { 1417 opt->iov_length = 256; 1418 opt->iov_count = 1024; 1419 opt->rate = 2; 1420 test_exec(cgrp, opt); 1421 } 1422 1423 static void test_send(struct sockmap_options *opt, int cgrp) 1424 { 1425 test_send_one(opt, cgrp); 1426 test_send_many(opt, cgrp); 1427 test_send_large(opt, cgrp); 1428 sched_yield(); 1429 } 1430 1431 static void test_txmsg_pass(int cgrp, struct sockmap_options *opt) 1432 { 1433 /* Test small and large iov_count values with pass/redir/apply/cork */ 1434 txmsg_pass = 1; 1435 test_send(opt, cgrp); 1436 } 1437 1438 static void test_txmsg_redir(int cgrp, struct sockmap_options *opt) 1439 { 1440 txmsg_redir = 1; 1441 test_send(opt, cgrp); 1442 } 1443 1444 static void test_txmsg_drop(int cgrp, struct sockmap_options *opt) 1445 { 1446 txmsg_drop = 1; 1447 test_send(opt, cgrp); 1448 } 1449 1450 static void test_txmsg_ingress_redir(int cgrp, struct sockmap_options *opt) 1451 { 1452 txmsg_pass = txmsg_drop = 0; 1453 txmsg_ingress = txmsg_redir = 1; 1454 test_send(opt, cgrp); 1455 } 1456 1457 static void test_txmsg_skb(int cgrp, struct sockmap_options *opt) 1458 { 1459 bool data = opt->data_test; 1460 int k = ktls; 1461 1462 opt->data_test = true; 1463 ktls = 1; 1464 1465 txmsg_pass = txmsg_drop = 0; 1466 txmsg_ingress = txmsg_redir = 0; 1467 txmsg_ktls_skb = 1; 1468 txmsg_pass = 1; 1469 1470 /* Using data verification so ensure iov layout is 1471 * expected from test receiver side. e.g. has enough 1472 * bytes to write test code. 1473 */ 1474 opt->iov_length = 100; 1475 opt->iov_count = 1; 1476 opt->rate = 1; 1477 test_exec(cgrp, opt); 1478 1479 txmsg_ktls_skb_drop = 1; 1480 test_exec(cgrp, opt); 1481 1482 txmsg_ktls_skb_drop = 0; 1483 txmsg_ktls_skb_redir = 1; 1484 test_exec(cgrp, opt); 1485 txmsg_ktls_skb_redir = 0; 1486 1487 /* Tests that omit skb_parser */ 1488 txmsg_omit_skb_parser = 1; 1489 ktls = 0; 1490 txmsg_ktls_skb = 0; 1491 test_exec(cgrp, opt); 1492 1493 txmsg_ktls_skb_drop = 1; 1494 test_exec(cgrp, opt); 1495 txmsg_ktls_skb_drop = 0; 1496 1497 txmsg_ktls_skb_redir = 1; 1498 test_exec(cgrp, opt); 1499 1500 ktls = 1; 1501 test_exec(cgrp, opt); 1502 txmsg_omit_skb_parser = 0; 1503 1504 opt->data_test = data; 1505 ktls = k; 1506 } 1507 1508 /* Test cork with hung data. This tests poor usage patterns where 1509 * cork can leave data on the ring if user program is buggy and 1510 * doesn't flush them somehow. They do take some time however 1511 * because they wait for a timeout. Test pass, redir and cork with 1512 * apply logic. Use cork size of 4097 with send_large to avoid 1513 * aligning cork size with send size. 1514 */ 1515 static void test_txmsg_cork_hangs(int cgrp, struct sockmap_options *opt) 1516 { 1517 txmsg_pass = 1; 1518 txmsg_redir = 0; 1519 txmsg_cork = 4097; 1520 txmsg_apply = 4097; 1521 test_send_large(opt, cgrp); 1522 1523 txmsg_pass = 0; 1524 txmsg_redir = 1; 1525 txmsg_apply = 0; 1526 txmsg_cork = 4097; 1527 test_send_large(opt, cgrp); 1528 1529 txmsg_pass = 0; 1530 txmsg_redir = 1; 1531 txmsg_apply = 4097; 1532 txmsg_cork = 4097; 1533 test_send_large(opt, cgrp); 1534 } 1535 1536 static void test_txmsg_pull(int cgrp, struct sockmap_options *opt) 1537 { 1538 /* Test basic start/end */ 1539 txmsg_start = 1; 1540 txmsg_end = 2; 1541 test_send(opt, cgrp); 1542 1543 /* Test >4k pull */ 1544 txmsg_start = 4096; 1545 txmsg_end = 9182; 1546 test_send_large(opt, cgrp); 1547 1548 /* Test pull + redirect */ 1549 txmsg_redir = 0; 1550 txmsg_start = 1; 1551 txmsg_end = 2; 1552 test_send(opt, cgrp); 1553 1554 /* Test pull + cork */ 1555 txmsg_redir = 0; 1556 txmsg_cork = 512; 1557 txmsg_start = 1; 1558 txmsg_end = 2; 1559 test_send_many(opt, cgrp); 1560 1561 /* Test pull + cork + redirect */ 1562 txmsg_redir = 1; 1563 txmsg_cork = 512; 1564 txmsg_start = 1; 1565 txmsg_end = 2; 1566 test_send_many(opt, cgrp); 1567 } 1568 1569 static void test_txmsg_pop(int cgrp, struct sockmap_options *opt) 1570 { 1571 /* Test basic pop */ 1572 txmsg_start_pop = 1; 1573 txmsg_pop = 2; 1574 test_send_many(opt, cgrp); 1575 1576 /* Test pop with >4k */ 1577 txmsg_start_pop = 4096; 1578 txmsg_pop = 4096; 1579 test_send_large(opt, cgrp); 1580 1581 /* Test pop + redirect */ 1582 txmsg_redir = 1; 1583 txmsg_start_pop = 1; 1584 txmsg_pop = 2; 1585 test_send_many(opt, cgrp); 1586 1587 /* Test pop + cork */ 1588 txmsg_redir = 0; 1589 txmsg_cork = 512; 1590 txmsg_start_pop = 1; 1591 txmsg_pop = 2; 1592 test_send_many(opt, cgrp); 1593 1594 /* Test pop + redirect + cork */ 1595 txmsg_redir = 1; 1596 txmsg_cork = 4; 1597 txmsg_start_pop = 1; 1598 txmsg_pop = 2; 1599 test_send_many(opt, cgrp); 1600 } 1601 1602 static void test_txmsg_push(int cgrp, struct sockmap_options *opt) 1603 { 1604 /* Test basic push */ 1605 txmsg_start_push = 1; 1606 txmsg_end_push = 1; 1607 test_send(opt, cgrp); 1608 1609 /* Test push 4kB >4k */ 1610 txmsg_start_push = 4096; 1611 txmsg_end_push = 4096; 1612 test_send_large(opt, cgrp); 1613 1614 /* Test push + redirect */ 1615 txmsg_redir = 1; 1616 txmsg_start_push = 1; 1617 txmsg_end_push = 2; 1618 test_send_many(opt, cgrp); 1619 1620 /* Test push + cork */ 1621 txmsg_redir = 0; 1622 txmsg_cork = 512; 1623 txmsg_start_push = 1; 1624 txmsg_end_push = 2; 1625 test_send_many(opt, cgrp); 1626 } 1627 1628 static void test_txmsg_push_pop(int cgrp, struct sockmap_options *opt) 1629 { 1630 txmsg_start_push = 1; 1631 txmsg_end_push = 10; 1632 txmsg_start_pop = 5; 1633 txmsg_pop = 4; 1634 test_send_large(opt, cgrp); 1635 } 1636 1637 static void test_txmsg_apply(int cgrp, struct sockmap_options *opt) 1638 { 1639 txmsg_pass = 1; 1640 txmsg_redir = 0; 1641 txmsg_apply = 1; 1642 txmsg_cork = 0; 1643 test_send_one(opt, cgrp); 1644 1645 txmsg_pass = 0; 1646 txmsg_redir = 1; 1647 txmsg_apply = 1; 1648 txmsg_cork = 0; 1649 test_send_one(opt, cgrp); 1650 1651 txmsg_pass = 1; 1652 txmsg_redir = 0; 1653 txmsg_apply = 1024; 1654 txmsg_cork = 0; 1655 test_send_large(opt, cgrp); 1656 1657 txmsg_pass = 0; 1658 txmsg_redir = 1; 1659 txmsg_apply = 1024; 1660 txmsg_cork = 0; 1661 test_send_large(opt, cgrp); 1662 } 1663 1664 static void test_txmsg_cork(int cgrp, struct sockmap_options *opt) 1665 { 1666 txmsg_pass = 1; 1667 txmsg_redir = 0; 1668 txmsg_apply = 0; 1669 txmsg_cork = 1; 1670 test_send(opt, cgrp); 1671 1672 txmsg_pass = 1; 1673 txmsg_redir = 0; 1674 txmsg_apply = 1; 1675 txmsg_cork = 1; 1676 test_send(opt, cgrp); 1677 } 1678 1679 static void test_txmsg_ingress_parser(int cgrp, struct sockmap_options *opt) 1680 { 1681 txmsg_pass = 1; 1682 skb_use_parser = 512; 1683 opt->iov_length = 256; 1684 opt->iov_count = 1; 1685 opt->rate = 2; 1686 test_exec(cgrp, opt); 1687 } 1688 1689 char *map_names[] = { 1690 "sock_map", 1691 "sock_map_txmsg", 1692 "sock_map_redir", 1693 "sock_apply_bytes", 1694 "sock_cork_bytes", 1695 "sock_bytes", 1696 "sock_redir_flags", 1697 "sock_skb_opts", 1698 "tls_sock_map", 1699 }; 1700 1701 int prog_attach_type[] = { 1702 BPF_SK_SKB_STREAM_PARSER, 1703 BPF_SK_SKB_STREAM_VERDICT, 1704 BPF_SK_SKB_STREAM_VERDICT, 1705 BPF_CGROUP_SOCK_OPS, 1706 BPF_SK_MSG_VERDICT, 1707 BPF_SK_MSG_VERDICT, 1708 BPF_SK_MSG_VERDICT, 1709 BPF_SK_MSG_VERDICT, 1710 BPF_SK_MSG_VERDICT, 1711 BPF_SK_MSG_VERDICT, 1712 BPF_SK_MSG_VERDICT, 1713 }; 1714 1715 int prog_type[] = { 1716 BPF_PROG_TYPE_SK_SKB, 1717 BPF_PROG_TYPE_SK_SKB, 1718 BPF_PROG_TYPE_SK_SKB, 1719 BPF_PROG_TYPE_SOCK_OPS, 1720 BPF_PROG_TYPE_SK_MSG, 1721 BPF_PROG_TYPE_SK_MSG, 1722 BPF_PROG_TYPE_SK_MSG, 1723 BPF_PROG_TYPE_SK_MSG, 1724 BPF_PROG_TYPE_SK_MSG, 1725 BPF_PROG_TYPE_SK_MSG, 1726 BPF_PROG_TYPE_SK_MSG, 1727 }; 1728 1729 static int populate_progs(char *bpf_file) 1730 { 1731 struct bpf_program *prog; 1732 struct bpf_object *obj; 1733 int i = 0; 1734 long err; 1735 1736 obj = bpf_object__open(bpf_file); 1737 err = libbpf_get_error(obj); 1738 if (err) { 1739 char err_buf[256]; 1740 1741 libbpf_strerror(err, err_buf, sizeof(err_buf)); 1742 printf("Unable to load eBPF objects in file '%s' : %s\n", 1743 bpf_file, err_buf); 1744 return -1; 1745 } 1746 1747 bpf_object__for_each_program(prog, obj) { 1748 bpf_program__set_type(prog, prog_type[i]); 1749 bpf_program__set_expected_attach_type(prog, 1750 prog_attach_type[i]); 1751 i++; 1752 } 1753 1754 i = bpf_object__load(obj); 1755 i = 0; 1756 bpf_object__for_each_program(prog, obj) { 1757 prog_fd[i] = bpf_program__fd(prog); 1758 i++; 1759 } 1760 1761 for (i = 0; i < sizeof(map_fd)/sizeof(int); i++) { 1762 maps[i] = bpf_object__find_map_by_name(obj, map_names[i]); 1763 map_fd[i] = bpf_map__fd(maps[i]); 1764 if (map_fd[i] < 0) { 1765 fprintf(stderr, "load_bpf_file: (%i) %s\n", 1766 map_fd[i], strerror(errno)); 1767 return -1; 1768 } 1769 } 1770 1771 return 0; 1772 } 1773 1774 struct _test test[] = { 1775 {"txmsg test passthrough", test_txmsg_pass}, 1776 {"txmsg test redirect", test_txmsg_redir}, 1777 {"txmsg test drop", test_txmsg_drop}, 1778 {"txmsg test ingress redirect", test_txmsg_ingress_redir}, 1779 {"txmsg test skb", test_txmsg_skb}, 1780 {"txmsg test apply", test_txmsg_apply}, 1781 {"txmsg test cork", test_txmsg_cork}, 1782 {"txmsg test hanging corks", test_txmsg_cork_hangs}, 1783 {"txmsg test push_data", test_txmsg_push}, 1784 {"txmsg test pull-data", test_txmsg_pull}, 1785 {"txmsg test pop-data", test_txmsg_pop}, 1786 {"txmsg test push/pop data", test_txmsg_push_pop}, 1787 {"txmsg text ingress parser", test_txmsg_ingress_parser}, 1788 }; 1789 1790 static int check_whitelist(struct _test *t, struct sockmap_options *opt) 1791 { 1792 char *entry, *ptr; 1793 1794 if (!opt->whitelist) 1795 return 0; 1796 ptr = strdup(opt->whitelist); 1797 if (!ptr) 1798 return -ENOMEM; 1799 entry = strtok(ptr, ","); 1800 while (entry) { 1801 if ((opt->prepend && strstr(opt->prepend, entry) != 0) || 1802 strstr(opt->map, entry) != 0 || 1803 strstr(t->title, entry) != 0) 1804 return 0; 1805 entry = strtok(NULL, ","); 1806 } 1807 return -EINVAL; 1808 } 1809 1810 static int check_blacklist(struct _test *t, struct sockmap_options *opt) 1811 { 1812 char *entry, *ptr; 1813 1814 if (!opt->blacklist) 1815 return -EINVAL; 1816 ptr = strdup(opt->blacklist); 1817 if (!ptr) 1818 return -ENOMEM; 1819 entry = strtok(ptr, ","); 1820 while (entry) { 1821 if ((opt->prepend && strstr(opt->prepend, entry) != 0) || 1822 strstr(opt->map, entry) != 0 || 1823 strstr(t->title, entry) != 0) 1824 return 0; 1825 entry = strtok(NULL, ","); 1826 } 1827 return -EINVAL; 1828 } 1829 1830 static int __test_selftests(int cg_fd, struct sockmap_options *opt) 1831 { 1832 int i, err; 1833 1834 err = populate_progs(opt->map); 1835 if (err < 0) { 1836 fprintf(stderr, "ERROR: (%i) load bpf failed\n", err); 1837 return err; 1838 } 1839 1840 /* Tests basic commands and APIs */ 1841 for (i = 0; i < sizeof(test)/sizeof(struct _test); i++) { 1842 struct _test t = test[i]; 1843 1844 if (check_whitelist(&t, opt) != 0) 1845 continue; 1846 if (check_blacklist(&t, opt) == 0) 1847 continue; 1848 1849 test_start_subtest(&t, opt); 1850 t.tester(cg_fd, opt); 1851 test_end_subtest(); 1852 } 1853 1854 return err; 1855 } 1856 1857 static void test_selftests_sockmap(int cg_fd, struct sockmap_options *opt) 1858 { 1859 opt->map = BPF_SOCKMAP_FILENAME; 1860 __test_selftests(cg_fd, opt); 1861 } 1862 1863 static void test_selftests_sockhash(int cg_fd, struct sockmap_options *opt) 1864 { 1865 opt->map = BPF_SOCKHASH_FILENAME; 1866 __test_selftests(cg_fd, opt); 1867 } 1868 1869 static void test_selftests_ktls(int cg_fd, struct sockmap_options *opt) 1870 { 1871 opt->map = BPF_SOCKHASH_FILENAME; 1872 opt->prepend = "ktls"; 1873 ktls = 1; 1874 __test_selftests(cg_fd, opt); 1875 ktls = 0; 1876 } 1877 1878 static int test_selftest(int cg_fd, struct sockmap_options *opt) 1879 { 1880 1881 test_selftests_sockmap(cg_fd, opt); 1882 test_selftests_sockhash(cg_fd, opt); 1883 test_selftests_ktls(cg_fd, opt); 1884 test_print_results(); 1885 return 0; 1886 } 1887 1888 int main(int argc, char **argv) 1889 { 1890 int iov_count = 1, length = 1024, rate = 1; 1891 struct sockmap_options options = {0}; 1892 int opt, longindex, err, cg_fd = 0; 1893 char *bpf_file = BPF_SOCKMAP_FILENAME; 1894 int test = SELFTESTS; 1895 bool cg_created = 0; 1896 1897 while ((opt = getopt_long(argc, argv, ":dhv:c:r:i:l:t:p:q:n:b:", 1898 long_options, &longindex)) != -1) { 1899 switch (opt) { 1900 case 's': 1901 txmsg_start = atoi(optarg); 1902 break; 1903 case 'e': 1904 txmsg_end = atoi(optarg); 1905 break; 1906 case 'p': 1907 txmsg_start_push = atoi(optarg); 1908 break; 1909 case 'q': 1910 txmsg_end_push = atoi(optarg); 1911 break; 1912 case 'w': 1913 txmsg_start_pop = atoi(optarg); 1914 break; 1915 case 'x': 1916 txmsg_pop = atoi(optarg); 1917 break; 1918 case 'a': 1919 txmsg_apply = atoi(optarg); 1920 break; 1921 case 'k': 1922 txmsg_cork = atoi(optarg); 1923 break; 1924 case 'c': 1925 cg_fd = open(optarg, O_DIRECTORY, O_RDONLY); 1926 if (cg_fd < 0) { 1927 fprintf(stderr, 1928 "ERROR: (%i) open cg path failed: %s\n", 1929 cg_fd, optarg); 1930 return cg_fd; 1931 } 1932 break; 1933 case 'r': 1934 rate = atoi(optarg); 1935 break; 1936 case 'v': 1937 options.verbose = 1; 1938 if (optarg) 1939 options.verbose = atoi(optarg); 1940 break; 1941 case 'i': 1942 iov_count = atoi(optarg); 1943 break; 1944 case 'l': 1945 length = atoi(optarg); 1946 break; 1947 case 'd': 1948 options.data_test = true; 1949 break; 1950 case 't': 1951 if (strcmp(optarg, "ping") == 0) { 1952 test = PING_PONG; 1953 } else if (strcmp(optarg, "sendmsg") == 0) { 1954 test = SENDMSG; 1955 } else if (strcmp(optarg, "base") == 0) { 1956 test = BASE; 1957 } else if (strcmp(optarg, "base_sendpage") == 0) { 1958 test = BASE_SENDPAGE; 1959 } else if (strcmp(optarg, "sendpage") == 0) { 1960 test = SENDPAGE; 1961 } else { 1962 usage(argv); 1963 return -1; 1964 } 1965 break; 1966 case 'n': 1967 options.whitelist = strdup(optarg); 1968 if (!options.whitelist) 1969 return -ENOMEM; 1970 break; 1971 case 'b': 1972 options.blacklist = strdup(optarg); 1973 if (!options.blacklist) 1974 return -ENOMEM; 1975 case 0: 1976 break; 1977 case 'h': 1978 default: 1979 usage(argv); 1980 return -1; 1981 } 1982 } 1983 1984 if (!cg_fd) { 1985 cg_fd = cgroup_setup_and_join(CG_PATH); 1986 if (cg_fd < 0) 1987 return cg_fd; 1988 cg_created = 1; 1989 } 1990 1991 if (test == SELFTESTS) { 1992 err = test_selftest(cg_fd, &options); 1993 goto out; 1994 } 1995 1996 err = populate_progs(bpf_file); 1997 if (err) { 1998 fprintf(stderr, "populate program: (%s) %s\n", 1999 bpf_file, strerror(errno)); 2000 return 1; 2001 } 2002 running = 1; 2003 2004 /* catch SIGINT */ 2005 signal(SIGINT, running_handler); 2006 2007 options.iov_count = iov_count; 2008 options.iov_length = length; 2009 options.rate = rate; 2010 2011 err = run_options(&options, cg_fd, test); 2012 out: 2013 if (options.whitelist) 2014 free(options.whitelist); 2015 if (options.blacklist) 2016 free(options.blacklist); 2017 if (cg_created) 2018 cleanup_cgroup_environment(); 2019 close(cg_fd); 2020 return err; 2021 } 2022 2023 void running_handler(int a) 2024 { 2025 running = 0; 2026 } 2027