1 #include <errno.h> 2 #include <error.h> 3 #include <getopt.h> 4 #include <stdbool.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <unistd.h> 9 10 #include <sys/time.h> 11 #include <sys/socket.h> 12 #include <sys/select.h> 13 #include <sys/ioctl.h> 14 #include <arpa/inet.h> 15 #include <net/if.h> 16 17 #include <asm/types.h> 18 #include <linux/net_tstamp.h> 19 #include <linux/errqueue.h> 20 21 #include "../kselftest.h" 22 23 struct options { 24 int so_timestamp; 25 int so_timestampns; 26 int so_timestamping; 27 }; 28 29 struct tstamps { 30 bool tstamp; 31 bool tstampns; 32 bool swtstamp; 33 bool hwtstamp; 34 }; 35 36 struct socket_type { 37 char *friendly_name; 38 int type; 39 int protocol; 40 bool enabled; 41 }; 42 43 struct test_case { 44 struct options sockopt; 45 struct tstamps expected; 46 bool enabled; 47 bool warn_on_fail; 48 }; 49 50 struct sof_flag { 51 int mask; 52 char *name; 53 }; 54 55 static struct sof_flag sof_flags[] = { 56 #define SOF_FLAG(f) { f, #f } 57 SOF_FLAG(SOF_TIMESTAMPING_SOFTWARE), 58 SOF_FLAG(SOF_TIMESTAMPING_RX_SOFTWARE), 59 SOF_FLAG(SOF_TIMESTAMPING_RX_HARDWARE), 60 SOF_FLAG(SOF_TIMESTAMPING_OPT_RX_FILTER), 61 SOF_FLAG(SOF_TIMESTAMPING_RAW_HARDWARE), 62 }; 63 64 static struct socket_type socket_types[] = { 65 { "ip", SOCK_RAW, IPPROTO_EGP }, 66 { "udp", SOCK_DGRAM, IPPROTO_UDP }, 67 { "tcp", SOCK_STREAM, IPPROTO_TCP }, 68 }; 69 70 static struct test_case test_cases[] = { 71 { {}, {} }, 72 { 73 { .so_timestamp = 1 }, 74 { .tstamp = true } 75 }, 76 { 77 { .so_timestampns = 1 }, 78 { .tstampns = true } 79 }, 80 { 81 { .so_timestamp = 1, .so_timestampns = 1 }, 82 { .tstampns = true } 83 }, 84 { 85 { .so_timestamping = SOF_TIMESTAMPING_RX_SOFTWARE }, 86 {} 87 }, 88 { 89 /* Loopback device does not support hw timestamps. */ 90 { .so_timestamping = SOF_TIMESTAMPING_RX_HARDWARE }, 91 {} 92 }, 93 { 94 { .so_timestamping = SOF_TIMESTAMPING_SOFTWARE }, 95 .warn_on_fail = true 96 }, 97 { 98 { .so_timestamping = SOF_TIMESTAMPING_RX_SOFTWARE 99 | SOF_TIMESTAMPING_RX_HARDWARE }, 100 {} 101 }, 102 { 103 { .so_timestamping = SOF_TIMESTAMPING_RAW_HARDWARE 104 | SOF_TIMESTAMPING_OPT_RX_FILTER }, 105 {} 106 }, 107 { 108 { .so_timestamping = SOF_TIMESTAMPING_SOFTWARE 109 | SOF_TIMESTAMPING_OPT_RX_FILTER }, 110 {} 111 }, 112 { 113 { .so_timestamping = SOF_TIMESTAMPING_SOFTWARE 114 | SOF_TIMESTAMPING_RX_SOFTWARE 115 | SOF_TIMESTAMPING_OPT_RX_FILTER }, 116 { .swtstamp = true } 117 }, 118 { 119 { .so_timestamping = SOF_TIMESTAMPING_SOFTWARE 120 | SOF_TIMESTAMPING_RX_SOFTWARE }, 121 { .swtstamp = true } 122 }, 123 { 124 { .so_timestamp = 1, .so_timestamping = SOF_TIMESTAMPING_SOFTWARE 125 | SOF_TIMESTAMPING_RX_SOFTWARE }, 126 { .tstamp = true, .swtstamp = true } 127 }, 128 }; 129 130 static struct option long_options[] = { 131 { "list_tests", no_argument, 0, 'l' }, 132 { "test_num", required_argument, 0, 'n' }, 133 { "op_size", required_argument, 0, 's' }, 134 { "tcp", no_argument, 0, 't' }, 135 { "udp", no_argument, 0, 'u' }, 136 { "ip", no_argument, 0, 'i' }, 137 { "strict", no_argument, 0, 'S' }, 138 { "ipv4", no_argument, 0, '4' }, 139 { "ipv6", no_argument, 0, '6' }, 140 { NULL, 0, NULL, 0 }, 141 }; 142 143 static int next_port = 19999; 144 static int op_size = 10 * 1024; 145 146 void print_test_case(struct test_case *t) 147 { 148 int f = 0; 149 150 printf("sockopts {"); 151 if (t->sockopt.so_timestamp) 152 printf(" SO_TIMESTAMP "); 153 if (t->sockopt.so_timestampns) 154 printf(" SO_TIMESTAMPNS "); 155 if (t->sockopt.so_timestamping) { 156 printf(" SO_TIMESTAMPING: {"); 157 for (f = 0; f < ARRAY_SIZE(sof_flags); f++) 158 if (t->sockopt.so_timestamping & sof_flags[f].mask) 159 printf(" %s |", sof_flags[f].name); 160 printf("}"); 161 } 162 printf("} expected cmsgs: {"); 163 if (t->expected.tstamp) 164 printf(" SCM_TIMESTAMP "); 165 if (t->expected.tstampns) 166 printf(" SCM_TIMESTAMPNS "); 167 if (t->expected.swtstamp || t->expected.hwtstamp) { 168 printf(" SCM_TIMESTAMPING {"); 169 if (t->expected.swtstamp) 170 printf("0"); 171 if (t->expected.swtstamp && t->expected.hwtstamp) 172 printf(","); 173 if (t->expected.hwtstamp) 174 printf("2"); 175 printf("}"); 176 } 177 printf("}\n"); 178 } 179 180 void do_send(int src) 181 { 182 int r; 183 char *buf = malloc(op_size); 184 185 memset(buf, 'z', op_size); 186 r = write(src, buf, op_size); 187 if (r < 0) 188 error(1, errno, "Failed to sendmsg"); 189 190 free(buf); 191 } 192 193 bool do_recv(int rcv, int read_size, struct tstamps expected) 194 { 195 const int CMSG_SIZE = 1024; 196 197 struct scm_timestamping *ts; 198 struct tstamps actual = {}; 199 char cmsg_buf[CMSG_SIZE]; 200 struct iovec recv_iov; 201 struct cmsghdr *cmsg; 202 bool failed = false; 203 struct msghdr hdr; 204 int flags = 0; 205 int r; 206 207 memset(&hdr, 0, sizeof(hdr)); 208 hdr.msg_iov = &recv_iov; 209 hdr.msg_iovlen = 1; 210 recv_iov.iov_base = malloc(read_size); 211 recv_iov.iov_len = read_size; 212 213 hdr.msg_control = cmsg_buf; 214 hdr.msg_controllen = sizeof(cmsg_buf); 215 216 r = recvmsg(rcv, &hdr, flags); 217 if (r < 0) 218 error(1, errno, "Failed to recvmsg"); 219 if (r != read_size) 220 error(1, 0, "Only received %d bytes of payload.", r); 221 222 if (hdr.msg_flags & (MSG_TRUNC | MSG_CTRUNC)) 223 error(1, 0, "Message was truncated."); 224 225 for (cmsg = CMSG_FIRSTHDR(&hdr); cmsg != NULL; 226 cmsg = CMSG_NXTHDR(&hdr, cmsg)) { 227 if (cmsg->cmsg_level != SOL_SOCKET) 228 error(1, 0, "Unexpected cmsg_level %d", 229 cmsg->cmsg_level); 230 switch (cmsg->cmsg_type) { 231 case SCM_TIMESTAMP: 232 actual.tstamp = true; 233 break; 234 case SCM_TIMESTAMPNS: 235 actual.tstampns = true; 236 break; 237 case SCM_TIMESTAMPING: 238 ts = (struct scm_timestamping *)CMSG_DATA(cmsg); 239 actual.swtstamp = !!ts->ts[0].tv_sec; 240 if (ts->ts[1].tv_sec != 0) 241 error(0, 0, "ts[1] should not be set."); 242 actual.hwtstamp = !!ts->ts[2].tv_sec; 243 break; 244 default: 245 error(1, 0, "Unexpected cmsg_type %d", cmsg->cmsg_type); 246 } 247 } 248 249 #define VALIDATE(field) \ 250 do { \ 251 if (expected.field != actual.field) { \ 252 if (expected.field) \ 253 error(0, 0, "Expected " #field " to be set."); \ 254 else \ 255 error(0, 0, \ 256 "Expected " #field " to not be set."); \ 257 failed = true; \ 258 } \ 259 } while (0) 260 261 VALIDATE(tstamp); 262 VALIDATE(tstampns); 263 VALIDATE(swtstamp); 264 VALIDATE(hwtstamp); 265 #undef VALIDATE 266 267 free(recv_iov.iov_base); 268 269 return failed; 270 } 271 272 void config_so_flags(int rcv, struct options o) 273 { 274 int on = 1; 275 276 if (setsockopt(rcv, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) 277 error(1, errno, "Failed to enable SO_REUSEADDR"); 278 279 if (o.so_timestamp && 280 setsockopt(rcv, SOL_SOCKET, SO_TIMESTAMP, 281 &o.so_timestamp, sizeof(o.so_timestamp)) < 0) 282 error(1, errno, "Failed to enable SO_TIMESTAMP"); 283 284 if (o.so_timestampns && 285 setsockopt(rcv, SOL_SOCKET, SO_TIMESTAMPNS, 286 &o.so_timestampns, sizeof(o.so_timestampns)) < 0) 287 error(1, errno, "Failed to enable SO_TIMESTAMPNS"); 288 289 if (o.so_timestamping && 290 setsockopt(rcv, SOL_SOCKET, SO_TIMESTAMPING, 291 &o.so_timestamping, sizeof(o.so_timestamping)) < 0) 292 error(1, errno, "Failed to set SO_TIMESTAMPING"); 293 } 294 295 bool run_test_case(struct socket_type *s, int test_num, char ip_version, 296 bool strict) 297 { 298 union { 299 struct sockaddr_in6 addr6; 300 struct sockaddr_in addr4; 301 struct sockaddr addr_un; 302 } addr; 303 int read_size = op_size; 304 int src, dst, rcv, port; 305 socklen_t addr_size; 306 bool failed = false; 307 308 port = (s->type == SOCK_RAW) ? 0 : next_port++; 309 memset(&addr, 0, sizeof(addr)); 310 if (ip_version == '4') { 311 addr.addr4.sin_family = AF_INET; 312 addr.addr4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 313 addr.addr4.sin_port = htons(port); 314 addr_size = sizeof(addr.addr4); 315 if (s->type == SOCK_RAW) 316 read_size += 20; /* for IPv4 header */ 317 } else { 318 addr.addr6.sin6_family = AF_INET6; 319 addr.addr6.sin6_addr = in6addr_loopback; 320 addr.addr6.sin6_port = htons(port); 321 addr_size = sizeof(addr.addr6); 322 } 323 printf("Starting testcase %d over ipv%c...\n", test_num, ip_version); 324 src = socket(addr.addr_un.sa_family, s->type, 325 s->protocol); 326 if (src < 0) 327 error(1, errno, "Failed to open src socket"); 328 329 dst = socket(addr.addr_un.sa_family, s->type, 330 s->protocol); 331 if (dst < 0) 332 error(1, errno, "Failed to open dst socket"); 333 334 if (bind(dst, &addr.addr_un, addr_size) < 0) 335 error(1, errno, "Failed to bind to port %d", port); 336 337 if (s->type == SOCK_STREAM && (listen(dst, 1) < 0)) 338 error(1, errno, "Failed to listen"); 339 340 if (connect(src, &addr.addr_un, addr_size) < 0) 341 error(1, errno, "Failed to connect"); 342 343 if (s->type == SOCK_STREAM) { 344 rcv = accept(dst, NULL, NULL); 345 if (rcv < 0) 346 error(1, errno, "Failed to accept"); 347 close(dst); 348 } else { 349 rcv = dst; 350 } 351 352 config_so_flags(rcv, test_cases[test_num].sockopt); 353 usleep(20000); /* setsockopt for SO_TIMESTAMPING is asynchronous */ 354 do_send(src); 355 356 failed = do_recv(rcv, read_size, test_cases[test_num].expected); 357 358 close(rcv); 359 close(src); 360 361 if (failed) { 362 printf("FAILURE in testcase %d over ipv%c ", test_num, 363 ip_version); 364 print_test_case(&test_cases[test_num]); 365 if (!strict && test_cases[test_num].warn_on_fail) 366 failed = false; 367 } 368 return failed; 369 } 370 371 int main(int argc, char **argv) 372 { 373 bool all_protocols = true; 374 bool all_tests = true; 375 bool cfg_ipv4 = false; 376 bool cfg_ipv6 = false; 377 bool strict = false; 378 int arg_index = 0; 379 int failures = 0; 380 int s, t, opt; 381 382 while ((opt = getopt_long(argc, argv, "", long_options, 383 &arg_index)) != -1) { 384 switch (opt) { 385 case 'l': 386 for (t = 0; t < ARRAY_SIZE(test_cases); t++) { 387 printf("%d\t", t); 388 print_test_case(&test_cases[t]); 389 } 390 return 0; 391 case 'n': 392 t = atoi(optarg); 393 if (t >= ARRAY_SIZE(test_cases)) 394 error(1, 0, "Invalid test case: %d", t); 395 all_tests = false; 396 test_cases[t].enabled = true; 397 break; 398 case 's': 399 op_size = atoi(optarg); 400 break; 401 case 't': 402 all_protocols = false; 403 socket_types[2].enabled = true; 404 break; 405 case 'u': 406 all_protocols = false; 407 socket_types[1].enabled = true; 408 break; 409 case 'i': 410 all_protocols = false; 411 socket_types[0].enabled = true; 412 break; 413 case 'S': 414 strict = true; 415 break; 416 case '4': 417 cfg_ipv4 = true; 418 break; 419 case '6': 420 cfg_ipv6 = true; 421 break; 422 default: 423 error(1, 0, "Failed to parse parameters."); 424 } 425 } 426 427 for (s = 0; s < ARRAY_SIZE(socket_types); s++) { 428 if (!all_protocols && !socket_types[s].enabled) 429 continue; 430 431 printf("Testing %s...\n", socket_types[s].friendly_name); 432 for (t = 0; t < ARRAY_SIZE(test_cases); t++) { 433 if (!all_tests && !test_cases[t].enabled) 434 continue; 435 if (cfg_ipv4 || !cfg_ipv6) 436 if (run_test_case(&socket_types[s], t, '4', 437 strict)) 438 failures++; 439 if (cfg_ipv6 || !cfg_ipv4) 440 if (run_test_case(&socket_types[s], t, '6', 441 strict)) 442 failures++; 443 } 444 } 445 if (!failures) 446 printf("PASSED.\n"); 447 return failures; 448 } 449