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

selftests: txtimestamp: add SCM_TS_OPT_ID test

Extend txtimestamp test to run with fixed tskey using
SCM_TS_OPT_ID control message for all types of sockets.

Reviewed-by: Jason Xing <kerneljasonxing@gmail.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Vadim Fedorenko <vadfed@meta.com>
Link: https://patch.msgid.link/20241001125716.2832769-4-vadfed@meta.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Vadim Fedorenko and committed by
Jakub Kicinski
a89568e9 822b5bc6

+43 -15
+2
tools/include/uapi/asm-generic/socket.h
··· 124 124 #define SO_PASSPIDFD 76 125 125 #define SO_PEERPIDFD 77 126 126 127 + #define SCM_TS_OPT_ID 78 128 + 127 129 #if !defined(__KERNEL__) 128 130 129 131 #if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__))
+34 -10
tools/testing/selftests/net/txtimestamp.c
··· 77 77 static bool cfg_do_listen; 78 78 static uint16_t dest_port = 9000; 79 79 static bool cfg_print_nsec; 80 + static uint32_t ts_opt_id; 81 + static bool cfg_use_cmsg_opt_id; 80 82 81 83 static struct sockaddr_in daddr; 82 84 static struct sockaddr_in6 daddr6; ··· 138 136 /* compare key for each subsequent request 139 137 * must only test for one type, the first one requested 140 138 */ 141 - if (saved_tskey == -1) 139 + if (saved_tskey == -1 || cfg_use_cmsg_opt_id) 142 140 saved_tskey_type = tstype; 143 141 else if (saved_tskey_type != tstype) 144 142 return; 145 143 146 144 stepsize = cfg_proto == SOCK_STREAM ? cfg_payload_len : 1; 145 + stepsize = cfg_use_cmsg_opt_id ? 0 : stepsize; 147 146 if (tskey != saved_tskey + stepsize) { 148 147 fprintf(stderr, "ERROR: key %d, expected %d\n", 149 148 tskey, saved_tskey + stepsize); ··· 487 484 488 485 static void do_test(int family, unsigned int report_opt) 489 486 { 490 - char control[CMSG_SPACE(sizeof(uint32_t))]; 487 + char control[2 * CMSG_SPACE(sizeof(uint32_t))]; 491 488 struct sockaddr_ll laddr; 492 489 unsigned int sock_opt; 493 490 struct cmsghdr *cmsg; ··· 627 624 msg.msg_iov = &iov; 628 625 msg.msg_iovlen = 1; 629 626 630 - if (cfg_use_cmsg) { 627 + if (cfg_use_cmsg || cfg_use_cmsg_opt_id) { 631 628 memset(control, 0, sizeof(control)); 632 629 633 630 msg.msg_control = control; 634 - msg.msg_controllen = sizeof(control); 631 + msg.msg_controllen = cfg_use_cmsg * CMSG_SPACE(sizeof(uint32_t)); 632 + msg.msg_controllen += cfg_use_cmsg_opt_id * CMSG_SPACE(sizeof(uint32_t)); 635 633 636 - cmsg = CMSG_FIRSTHDR(&msg); 637 - cmsg->cmsg_level = SOL_SOCKET; 638 - cmsg->cmsg_type = SO_TIMESTAMPING; 639 - cmsg->cmsg_len = CMSG_LEN(sizeof(uint32_t)); 634 + cmsg = NULL; 635 + if (cfg_use_cmsg) { 636 + cmsg = CMSG_FIRSTHDR(&msg); 637 + cmsg->cmsg_level = SOL_SOCKET; 638 + cmsg->cmsg_type = SO_TIMESTAMPING; 639 + cmsg->cmsg_len = CMSG_LEN(sizeof(uint32_t)); 640 640 641 - *((uint32_t *) CMSG_DATA(cmsg)) = report_opt; 641 + *((uint32_t *)CMSG_DATA(cmsg)) = report_opt; 642 + } 643 + if (cfg_use_cmsg_opt_id) { 644 + cmsg = cmsg ? CMSG_NXTHDR(&msg, cmsg) : CMSG_FIRSTHDR(&msg); 645 + cmsg->cmsg_level = SOL_SOCKET; 646 + cmsg->cmsg_type = SCM_TS_OPT_ID; 647 + cmsg->cmsg_len = CMSG_LEN(sizeof(uint32_t)); 648 + 649 + *((uint32_t *)CMSG_DATA(cmsg)) = ts_opt_id; 650 + saved_tskey = ts_opt_id; 651 + } 652 + 642 653 } 643 654 644 655 val = sendmsg(fd, &msg, 0); ··· 702 685 " -L listen on hostname and port\n" 703 686 " -n: set no-payload option\n" 704 687 " -N: print timestamps and durations in nsec (instead of usec)\n" 688 + " -o N: use SCM_TS_OPT_ID control message to provide N as tskey\n" 705 689 " -p N: connect to port N\n" 706 690 " -P: use PF_PACKET\n" 707 691 " -r: use raw\n" ··· 723 705 int c; 724 706 725 707 while ((c = getopt(argc, argv, 726 - "46bc:CeEFhIl:LnNp:PrRS:t:uv:V:x")) != -1) { 708 + "46bc:CeEFhIl:LnNo:p:PrRS:t:uv:V:x")) != -1) { 727 709 switch (c) { 728 710 case '4': 729 711 do_ipv6 = 0; ··· 763 745 break; 764 746 case 'N': 765 747 cfg_print_nsec = true; 748 + break; 749 + case 'o': 750 + ts_opt_id = strtoul(optarg, NULL, 10); 751 + cfg_use_cmsg_opt_id = true; 766 752 break; 767 753 case 'p': 768 754 dest_port = strtoul(optarg, NULL, 10); ··· 825 803 error(1, 0, "cannot ask for pktinfo over pf_packet"); 826 804 if (cfg_busy_poll && cfg_use_epoll) 827 805 error(1, 0, "pass epoll or busy_poll, not both"); 806 + if (cfg_proto == SOCK_STREAM && cfg_use_cmsg_opt_id) 807 + error(1, 0, "TCP sockets don't support SCM_TS_OPT_ID"); 828 808 829 809 if (optind != argc - 1) 830 810 error(1, 0, "missing required hostname argument");
+7 -5
tools/testing/selftests/net/txtimestamp.sh
··· 37 37 run_test_tcpudpraw() { 38 38 local -r args=$@ 39 39 40 - run_test_v4v6 ${args} # tcp 41 - run_test_v4v6 ${args} -u # udp 42 - run_test_v4v6 ${args} -r # raw 43 - run_test_v4v6 ${args} -R # raw (IPPROTO_RAW) 44 - run_test_v4v6 ${args} -P # pf_packet 40 + run_test_v4v6 ${args} # tcp 41 + run_test_v4v6 ${args} -u # udp 42 + run_test_v4v6 ${args} -u -o 42 # udp with fixed tskey 43 + run_test_v4v6 ${args} -r # raw 44 + run_test_v4v6 ${args} -r -o 42 # raw 45 + run_test_v4v6 ${args} -R # raw (IPPROTO_RAW) 46 + run_test_v4v6 ${args} -P # pf_packet 45 47 } 46 48 47 49 run_test_all() {