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

Merge branch 'export send_recv_data'

Geliang Tang says:

====================
v5:
- address Martin's comments for v4 (thanks).
- update patch 2, use 'return err' instead of 'return -1/0'.
- drop patch 3 in v4.

v4:
- fix a bug in v3, it should be 'if (err)', not 'if (!err)'.
- move "selftests/bpf: Use log_err in network_helpers" out of this
series.

v3:
- add two more patches.
- use log_err instead of ASSERT in v3.
- let send_recv_data return int as Martin suggested.

v2:

Address Martin's comments for v1 (thanks.)
- drop patch 1, "export send_byte helper".
- drop "WRITE_ONCE(arg.stop, 0)".
- rebased.

send_recv_data will be re-used in MPTCP bpf tests, but not included
in this set because it depends on other patches that have not been
in the bpf-next yet. It will be sent as another set soon.
====================

Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>

+104 -70
+102
tools/testing/selftests/bpf/network_helpers.c
··· 545 545 close(sockfd); 546 546 return 0; 547 547 } 548 + 549 + struct send_recv_arg { 550 + int fd; 551 + uint32_t bytes; 552 + int stop; 553 + }; 554 + 555 + static void *send_recv_server(void *arg) 556 + { 557 + struct send_recv_arg *a = (struct send_recv_arg *)arg; 558 + ssize_t nr_sent = 0, bytes = 0; 559 + char batch[1500]; 560 + int err = 0, fd; 561 + 562 + fd = accept(a->fd, NULL, NULL); 563 + while (fd == -1) { 564 + if (errno == EINTR) 565 + continue; 566 + err = -errno; 567 + goto done; 568 + } 569 + 570 + if (settimeo(fd, 0)) { 571 + err = -errno; 572 + goto done; 573 + } 574 + 575 + while (bytes < a->bytes && !READ_ONCE(a->stop)) { 576 + nr_sent = send(fd, &batch, 577 + MIN(a->bytes - bytes, sizeof(batch)), 0); 578 + if (nr_sent == -1 && errno == EINTR) 579 + continue; 580 + if (nr_sent == -1) { 581 + err = -errno; 582 + break; 583 + } 584 + bytes += nr_sent; 585 + } 586 + 587 + if (bytes != a->bytes) { 588 + log_err("send %zd expected %u", bytes, a->bytes); 589 + if (!err) 590 + err = bytes > a->bytes ? -E2BIG : -EINTR; 591 + } 592 + 593 + done: 594 + if (fd >= 0) 595 + close(fd); 596 + if (err) { 597 + WRITE_ONCE(a->stop, 1); 598 + return ERR_PTR(err); 599 + } 600 + return NULL; 601 + } 602 + 603 + int send_recv_data(int lfd, int fd, uint32_t total_bytes) 604 + { 605 + ssize_t nr_recv = 0, bytes = 0; 606 + struct send_recv_arg arg = { 607 + .fd = lfd, 608 + .bytes = total_bytes, 609 + .stop = 0, 610 + }; 611 + pthread_t srv_thread; 612 + void *thread_ret; 613 + char batch[1500]; 614 + int err = 0; 615 + 616 + err = pthread_create(&srv_thread, NULL, send_recv_server, (void *)&arg); 617 + if (err) { 618 + log_err("Failed to pthread_create"); 619 + return err; 620 + } 621 + 622 + /* recv total_bytes */ 623 + while (bytes < total_bytes && !READ_ONCE(arg.stop)) { 624 + nr_recv = recv(fd, &batch, 625 + MIN(total_bytes - bytes, sizeof(batch)), 0); 626 + if (nr_recv == -1 && errno == EINTR) 627 + continue; 628 + if (nr_recv == -1) { 629 + err = -errno; 630 + break; 631 + } 632 + bytes += nr_recv; 633 + } 634 + 635 + if (bytes != total_bytes) { 636 + log_err("recv %zd expected %u", bytes, total_bytes); 637 + if (!err) 638 + err = bytes > total_bytes ? -E2BIG : -EINTR; 639 + } 640 + 641 + WRITE_ONCE(arg.stop, 1); 642 + pthread_join(srv_thread, &thread_ret); 643 + if (IS_ERR(thread_ret)) { 644 + log_err("Failed in thread_ret %ld", PTR_ERR(thread_ret)); 645 + err = err ? : PTR_ERR(thread_ret); 646 + } 647 + 648 + return err; 649 + }
+1
tools/testing/selftests/bpf/network_helpers.h
··· 76 76 */ 77 77 struct nstoken *open_netns(const char *name); 78 78 void close_netns(struct nstoken *token); 79 + int send_recv_data(int lfd, int fd, uint32_t total_bytes); 79 80 80 81 static __u16 csum_fold(__u32 csum) 81 82 {
+1 -70
tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c
··· 21 21 22 22 static const unsigned int total_bytes = 10 * 1024 * 1024; 23 23 static int expected_stg = 0xeB9F; 24 - static int stop; 25 24 26 25 static int settcpca(int fd, const char *tcp_ca) 27 26 { ··· 33 34 return 0; 34 35 } 35 36 36 - static void *server(void *arg) 37 - { 38 - int lfd = (int)(long)arg, err = 0, fd; 39 - ssize_t nr_sent = 0, bytes = 0; 40 - char batch[1500]; 41 - 42 - fd = accept(lfd, NULL, NULL); 43 - while (fd == -1) { 44 - if (errno == EINTR) 45 - continue; 46 - err = -errno; 47 - goto done; 48 - } 49 - 50 - if (settimeo(fd, 0)) { 51 - err = -errno; 52 - goto done; 53 - } 54 - 55 - while (bytes < total_bytes && !READ_ONCE(stop)) { 56 - nr_sent = send(fd, &batch, 57 - MIN(total_bytes - bytes, sizeof(batch)), 0); 58 - if (nr_sent == -1 && errno == EINTR) 59 - continue; 60 - if (nr_sent == -1) { 61 - err = -errno; 62 - break; 63 - } 64 - bytes += nr_sent; 65 - } 66 - 67 - ASSERT_EQ(bytes, total_bytes, "send"); 68 - 69 - done: 70 - if (fd >= 0) 71 - close(fd); 72 - if (err) { 73 - WRITE_ONCE(stop, 1); 74 - return ERR_PTR(err); 75 - } 76 - return NULL; 77 - } 78 - 79 37 static void do_test(const char *tcp_ca, const struct bpf_map *sk_stg_map) 80 38 { 81 - ssize_t nr_recv = 0, bytes = 0; 82 39 int lfd = -1, fd = -1; 83 - pthread_t srv_thread; 84 - void *thread_ret; 85 - char batch[1500]; 86 40 int err; 87 - 88 - WRITE_ONCE(stop, 0); 89 41 90 42 lfd = start_server(AF_INET6, SOCK_STREAM, NULL, 0, 0); 91 43 if (!ASSERT_NEQ(lfd, -1, "socket")) ··· 73 123 goto done; 74 124 } 75 125 76 - err = pthread_create(&srv_thread, NULL, server, (void *)(long)lfd); 77 - if (!ASSERT_OK(err, "pthread_create")) 78 - goto done; 79 - 80 - /* recv total_bytes */ 81 - while (bytes < total_bytes && !READ_ONCE(stop)) { 82 - nr_recv = recv(fd, &batch, 83 - MIN(total_bytes - bytes, sizeof(batch)), 0); 84 - if (nr_recv == -1 && errno == EINTR) 85 - continue; 86 - if (nr_recv == -1) 87 - break; 88 - bytes += nr_recv; 89 - } 90 - 91 - ASSERT_EQ(bytes, total_bytes, "recv"); 92 - 93 - WRITE_ONCE(stop, 1); 94 - pthread_join(srv_thread, &thread_ret); 95 - ASSERT_OK(IS_ERR(thread_ret), "thread_ret"); 126 + ASSERT_OK(send_recv_data(lfd, fd, total_bytes), "send_recv_data"); 96 127 97 128 done: 98 129 close(lfd);