selftests: txtimestamp: add SCM_TS_OPT_ID test
authorVadim Fedorenko <vadfed@meta.com>
Tue, 1 Oct 2024 12:57:16 +0000 (05:57 -0700)
committerJakub Kicinski <kuba@kernel.org>
Fri, 4 Oct 2024 18:52:20 +0000 (11:52 -0700)
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>
tools/include/uapi/asm-generic/socket.h
tools/testing/selftests/net/txtimestamp.c
tools/testing/selftests/net/txtimestamp.sh

index 54d9c8bf7c55f0bbb81ab642f0fa0a4b2cdd5d1d..281df9139d2b906efcf67c55ed75af1dec8028e2 100644 (file)
 #define SO_PASSPIDFD           76
 #define SO_PEERPIDFD           77
 
+#define SCM_TS_OPT_ID          78
+
 #if !defined(__KERNEL__)
 
 #if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__))
index d626f22f955090f889defeb836d853fae15a0b4f..dae91eb97d6992fdfebe1879aa0e7224ac5a772f 100644 (file)
@@ -77,6 +77,8 @@ static bool cfg_epollet;
 static bool cfg_do_listen;
 static uint16_t dest_port = 9000;
 static bool cfg_print_nsec;
+static uint32_t ts_opt_id;
+static bool cfg_use_cmsg_opt_id;
 
 static struct sockaddr_in daddr;
 static struct sockaddr_in6 daddr6;
@@ -136,12 +138,13 @@ static void validate_key(int tskey, int tstype)
        /* compare key for each subsequent request
         * must only test for one type, the first one requested
         */
-       if (saved_tskey == -1)
+       if (saved_tskey == -1 || cfg_use_cmsg_opt_id)
                saved_tskey_type = tstype;
        else if (saved_tskey_type != tstype)
                return;
 
        stepsize = cfg_proto == SOCK_STREAM ? cfg_payload_len : 1;
+       stepsize = cfg_use_cmsg_opt_id ? 0 : stepsize;
        if (tskey != saved_tskey + stepsize) {
                fprintf(stderr, "ERROR: key %d, expected %d\n",
                                tskey, saved_tskey + stepsize);
@@ -484,7 +487,7 @@ static void fill_header_udp(void *p, bool is_ipv4)
 
 static void do_test(int family, unsigned int report_opt)
 {
-       char control[CMSG_SPACE(sizeof(uint32_t))];
+       char control[2 * CMSG_SPACE(sizeof(uint32_t))];
        struct sockaddr_ll laddr;
        unsigned int sock_opt;
        struct cmsghdr *cmsg;
@@ -624,18 +627,32 @@ static void do_test(int family, unsigned int report_opt)
                msg.msg_iov = &iov;
                msg.msg_iovlen = 1;
 
-               if (cfg_use_cmsg) {
+               if (cfg_use_cmsg || cfg_use_cmsg_opt_id) {
                        memset(control, 0, sizeof(control));
 
                        msg.msg_control = control;
-                       msg.msg_controllen = sizeof(control);
+                       msg.msg_controllen = cfg_use_cmsg * CMSG_SPACE(sizeof(uint32_t));
+                       msg.msg_controllen += cfg_use_cmsg_opt_id * CMSG_SPACE(sizeof(uint32_t));
 
-                       cmsg = CMSG_FIRSTHDR(&msg);
-                       cmsg->cmsg_level = SOL_SOCKET;
-                       cmsg->cmsg_type = SO_TIMESTAMPING;
-                       cmsg->cmsg_len = CMSG_LEN(sizeof(uint32_t));
+                       cmsg = NULL;
+                       if (cfg_use_cmsg) {
+                               cmsg = CMSG_FIRSTHDR(&msg);
+                               cmsg->cmsg_level = SOL_SOCKET;
+                               cmsg->cmsg_type = SO_TIMESTAMPING;
+                               cmsg->cmsg_len = CMSG_LEN(sizeof(uint32_t));
+
+                               *((uint32_t *)CMSG_DATA(cmsg)) = report_opt;
+                       }
+                       if (cfg_use_cmsg_opt_id) {
+                               cmsg = cmsg ? CMSG_NXTHDR(&msg, cmsg) : CMSG_FIRSTHDR(&msg);
+                               cmsg->cmsg_level = SOL_SOCKET;
+                               cmsg->cmsg_type = SCM_TS_OPT_ID;
+                               cmsg->cmsg_len = CMSG_LEN(sizeof(uint32_t));
+
+                               *((uint32_t *)CMSG_DATA(cmsg)) = ts_opt_id;
+                               saved_tskey = ts_opt_id;
+                       }
 
-                       *((uint32_t *) CMSG_DATA(cmsg)) = report_opt;
                }
 
                val = sendmsg(fd, &msg, 0);
@@ -685,6 +702,7 @@ static void __attribute__((noreturn)) usage(const char *filepath)
                        "  -L    listen on hostname and port\n"
                        "  -n:   set no-payload option\n"
                        "  -N:   print timestamps and durations in nsec (instead of usec)\n"
+                       "  -o N: use SCM_TS_OPT_ID control message to provide N as tskey\n"
                        "  -p N: connect to port N\n"
                        "  -P:   use PF_PACKET\n"
                        "  -r:   use raw\n"
@@ -705,7 +723,7 @@ static void parse_opt(int argc, char **argv)
        int c;
 
        while ((c = getopt(argc, argv,
-                               "46bc:CeEFhIl:LnNp:PrRS:t:uv:V:x")) != -1) {
+                               "46bc:CeEFhIl:LnNo:p:PrRS:t:uv:V:x")) != -1) {
                switch (c) {
                case '4':
                        do_ipv6 = 0;
@@ -746,6 +764,10 @@ static void parse_opt(int argc, char **argv)
                case 'N':
                        cfg_print_nsec = true;
                        break;
+               case 'o':
+                       ts_opt_id = strtoul(optarg, NULL, 10);
+                       cfg_use_cmsg_opt_id = true;
+                       break;
                case 'p':
                        dest_port = strtoul(optarg, NULL, 10);
                        break;
@@ -803,6 +825,8 @@ static void parse_opt(int argc, char **argv)
                error(1, 0, "cannot ask for pktinfo over pf_packet");
        if (cfg_busy_poll && cfg_use_epoll)
                error(1, 0, "pass epoll or busy_poll, not both");
+       if (cfg_proto == SOCK_STREAM && cfg_use_cmsg_opt_id)
+               error(1, 0, "TCP sockets don't support SCM_TS_OPT_ID");
 
        if (optind != argc - 1)
                error(1, 0, "missing required hostname argument");
index 25baca4b148ecb1f6cb0bccde1f611905c73303f..fe4649bb87868820bc922b61946dae744c45e74b 100755 (executable)
@@ -37,11 +37,13 @@ run_test_v4v6() {
 run_test_tcpudpraw() {
        local -r args=$@
 
-       run_test_v4v6 ${args}           # tcp
-       run_test_v4v6 ${args} -u        # udp
-       run_test_v4v6 ${args} -r        # raw
-       run_test_v4v6 ${args} -R        # raw (IPPROTO_RAW)
-       run_test_v4v6 ${args} -P        # pf_packet
+       run_test_v4v6 ${args}             # tcp
+       run_test_v4v6 ${args} -u          # udp
+       run_test_v4v6 ${args} -u -o 42    # udp with fixed tskey
+       run_test_v4v6 ${args} -r          # raw
+       run_test_v4v6 ${args} -r -o 42    # raw
+       run_test_v4v6 ${args} -R          # raw (IPPROTO_RAW)
+       run_test_v4v6 ${args} -P          # pf_packet
 }
 
 run_test_all() {