1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright 2014 Google Inc. 4 * Author: willemb@google.com (Willem de Bruijn) 5 * 6 * Test software tx timestamping, including 7 * 8 * - SCHED, SND and ACK timestamps 9 * - RAW, UDP and TCP 10 * - IPv4 and IPv6 11 * - various packet sizes (to test GSO and TSO) 12 * 13 * Consult the command line arguments for help on running 14 * the various testcases. 15 * 16 * This test requires a dummy TCP server. 17 * A simple `nc6 [-u] -l -p $DESTPORT` will do 18 */ 19 20 #define _GNU_SOURCE 21 22 #include <arpa/inet.h> 23 #include <asm/types.h> 24 #include <error.h> 25 #include <errno.h> 26 #include <inttypes.h> 27 #include <linux/errqueue.h> 28 #include <linux/if_ether.h> 29 #include <linux/if_packet.h> 30 #include <linux/ipv6.h> 31 #include <linux/net_tstamp.h> 32 #include <netdb.h> 33 #include <net/if.h> 34 #include <netinet/in.h> 35 #include <netinet/ip.h> 36 #include <netinet/udp.h> 37 #include <netinet/tcp.h> 38 #include <poll.h> 39 #include <stdarg.h> 40 #include <stdbool.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <sys/epoll.h> 45 #include <sys/ioctl.h> 46 #include <sys/select.h> 47 #include <sys/socket.h> 48 #include <sys/time.h> 49 #include <sys/types.h> 50 #include <time.h> 51 #include <unistd.h> 52 53 #define NSEC_PER_USEC 1000L 54 #define USEC_PER_SEC 1000000L 55 #define NSEC_PER_SEC 1000000000LL 56 57 /* command line parameters */ 58 static int cfg_proto = SOCK_STREAM; 59 static int cfg_ipproto = IPPROTO_TCP; 60 static int cfg_num_pkts = 4; 61 static int do_ipv4 = 1; 62 static int do_ipv6 = 1; 63 static int cfg_payload_len = 10; 64 static int cfg_poll_timeout = 100; 65 static int cfg_delay_snd; 66 static int cfg_delay_ack; 67 static int cfg_delay_tolerance_usec = 500; 68 static bool cfg_show_payload; 69 static bool cfg_do_pktinfo; 70 static bool cfg_busy_poll; 71 static int cfg_sleep_usec = 50 * 1000; 72 static bool cfg_loop_nodata; 73 static bool cfg_use_cmsg; 74 static bool cfg_use_pf_packet; 75 static bool cfg_use_epoll; 76 static bool cfg_epollet; 77 static bool cfg_do_listen; 78 static uint16_t dest_port = 9000; 79 static bool cfg_print_nsec; 80 static uint32_t ts_opt_id; 81 static bool cfg_use_cmsg_opt_id; 82 83 static struct sockaddr_in daddr; 84 static struct sockaddr_in6 daddr6; 85 static struct timespec ts_usr; 86 87 static int saved_tskey = -1; 88 static int saved_tskey_type = -1; 89 90 struct timing_event { 91 int64_t min; 92 int64_t max; 93 int64_t total; 94 int count; 95 }; 96 97 static struct timing_event usr_enq; 98 static struct timing_event usr_snd; 99 static struct timing_event usr_ack; 100 101 static bool test_failed; 102 103 static int64_t timespec_to_ns64(struct timespec *ts) 104 { 105 return ts->tv_sec * NSEC_PER_SEC + ts->tv_nsec; 106 } 107 108 static int64_t timespec_to_us64(struct timespec *ts) 109 { 110 return ts->tv_sec * USEC_PER_SEC + ts->tv_nsec / NSEC_PER_USEC; 111 } 112 113 static void init_timing_event(struct timing_event *te) 114 { 115 te->min = INT64_MAX; 116 te->max = 0; 117 te->total = 0; 118 te->count = 0; 119 } 120 121 static void add_timing_event(struct timing_event *te, 122 struct timespec *t_start, struct timespec *t_end) 123 { 124 int64_t ts_delta = timespec_to_ns64(t_end) - timespec_to_ns64(t_start); 125 126 te->count++; 127 if (ts_delta < te->min) 128 te->min = ts_delta; 129 if (ts_delta > te->max) 130 te->max = ts_delta; 131 te->total += ts_delta; 132 } 133 134 static void validate_key(int tskey, int tstype) 135 { 136 int stepsize; 137 138 /* compare key for each subsequent request 139 * must only test for one type, the first one requested 140 */ 141 if (saved_tskey == -1 || cfg_use_cmsg_opt_id) 142 saved_tskey_type = tstype; 143 else if (saved_tskey_type != tstype) 144 return; 145 146 stepsize = cfg_proto == SOCK_STREAM ? cfg_payload_len : 1; 147 stepsize = cfg_use_cmsg_opt_id ? 0 : stepsize; 148 if (tskey != saved_tskey + stepsize) { 149 fprintf(stderr, "ERROR: key %d, expected %d\n", 150 tskey, saved_tskey + stepsize); 151 test_failed = true; 152 } 153 154 saved_tskey = tskey; 155 } 156 157 static void validate_timestamp(struct timespec *cur, int min_delay) 158 { 159 int64_t cur64, start64; 160 int max_delay; 161 162 cur64 = timespec_to_us64(cur); 163 start64 = timespec_to_us64(&ts_usr); 164 max_delay = min_delay + cfg_delay_tolerance_usec; 165 166 if (cur64 < start64 + min_delay || cur64 > start64 + max_delay) { 167 fprintf(stderr, "ERROR: %" PRId64 " us expected between %d and %d\n", 168 cur64 - start64, min_delay, max_delay); 169 if (!getenv("KSFT_MACHINE_SLOW")) 170 test_failed = true; 171 } 172 } 173 174 static void __print_ts_delta_formatted(int64_t ts_delta) 175 { 176 if (cfg_print_nsec) 177 fprintf(stderr, "%" PRId64 " ns", ts_delta); 178 else 179 fprintf(stderr, "%" PRId64 " us", ts_delta / NSEC_PER_USEC); 180 } 181 182 static void __print_timestamp(const char *name, struct timespec *cur, 183 uint32_t key, int payload_len) 184 { 185 int64_t ts_delta; 186 187 if (!(cur->tv_sec | cur->tv_nsec)) 188 return; 189 190 if (cfg_print_nsec) 191 fprintf(stderr, " %s: %lu s %lu ns (seq=%u, len=%u)", 192 name, cur->tv_sec, cur->tv_nsec, 193 key, payload_len); 194 else 195 fprintf(stderr, " %s: %lu s %lu us (seq=%u, len=%u)", 196 name, cur->tv_sec, cur->tv_nsec / NSEC_PER_USEC, 197 key, payload_len); 198 199 if (cur != &ts_usr) { 200 ts_delta = timespec_to_ns64(cur) - timespec_to_ns64(&ts_usr); 201 fprintf(stderr, " (USR +"); 202 __print_ts_delta_formatted(ts_delta); 203 fprintf(stderr, ")"); 204 } 205 206 fprintf(stderr, "\n"); 207 } 208 209 static void print_timestamp_usr(void) 210 { 211 if (clock_gettime(CLOCK_REALTIME, &ts_usr)) 212 error(1, errno, "clock_gettime"); 213 214 __print_timestamp(" USR", &ts_usr, 0, 0); 215 } 216 217 static void print_timestamp(struct scm_timestamping *tss, int tstype, 218 int tskey, int payload_len) 219 { 220 const char *tsname; 221 222 validate_key(tskey, tstype); 223 224 switch (tstype) { 225 case SCM_TSTAMP_SCHED: 226 tsname = " ENQ"; 227 validate_timestamp(&tss->ts[0], 0); 228 add_timing_event(&usr_enq, &ts_usr, &tss->ts[0]); 229 break; 230 case SCM_TSTAMP_SND: 231 tsname = " SND"; 232 validate_timestamp(&tss->ts[0], cfg_delay_snd); 233 add_timing_event(&usr_snd, &ts_usr, &tss->ts[0]); 234 break; 235 case SCM_TSTAMP_ACK: 236 tsname = " ACK"; 237 validate_timestamp(&tss->ts[0], cfg_delay_ack); 238 add_timing_event(&usr_ack, &ts_usr, &tss->ts[0]); 239 break; 240 default: 241 error(1, 0, "unknown timestamp type: %u", 242 tstype); 243 } 244 __print_timestamp(tsname, &tss->ts[0], tskey, payload_len); 245 } 246 247 static void print_timing_event(char *name, struct timing_event *te) 248 { 249 if (!te->count) 250 return; 251 252 fprintf(stderr, " %s: count=%d", name, te->count); 253 fprintf(stderr, ", avg="); 254 __print_ts_delta_formatted((int64_t)(te->total / te->count)); 255 fprintf(stderr, ", min="); 256 __print_ts_delta_formatted(te->min); 257 fprintf(stderr, ", max="); 258 __print_ts_delta_formatted(te->max); 259 fprintf(stderr, "\n"); 260 } 261 262 /* TODO: convert to check_and_print payload once API is stable */ 263 static void print_payload(char *data, int len) 264 { 265 int i; 266 267 if (!len) 268 return; 269 270 if (len > 70) 271 len = 70; 272 273 fprintf(stderr, "payload: "); 274 for (i = 0; i < len; i++) 275 fprintf(stderr, "%02hhx ", data[i]); 276 fprintf(stderr, "\n"); 277 } 278 279 static void print_pktinfo(int family, int ifindex, void *saddr, void *daddr) 280 { 281 char sa[INET6_ADDRSTRLEN], da[INET6_ADDRSTRLEN]; 282 283 fprintf(stderr, " pktinfo: ifindex=%u src=%s dst=%s\n", 284 ifindex, 285 saddr ? inet_ntop(family, saddr, sa, sizeof(sa)) : "unknown", 286 daddr ? inet_ntop(family, daddr, da, sizeof(da)) : "unknown"); 287 } 288 289 static void __epoll(int epfd) 290 { 291 struct epoll_event events; 292 int ret; 293 294 memset(&events, 0, sizeof(events)); 295 ret = epoll_wait(epfd, &events, 1, cfg_poll_timeout); 296 if (ret != 1) 297 error(1, errno, "epoll_wait"); 298 } 299 300 static void __poll(int fd) 301 { 302 struct pollfd pollfd; 303 int ret; 304 305 memset(&pollfd, 0, sizeof(pollfd)); 306 pollfd.fd = fd; 307 ret = poll(&pollfd, 1, cfg_poll_timeout); 308 if (ret != 1) 309 error(1, errno, "poll"); 310 } 311 312 static void __recv_errmsg_cmsg(struct msghdr *msg, int payload_len) 313 { 314 struct sock_extended_err *serr = NULL; 315 struct scm_timestamping *tss = NULL; 316 struct cmsghdr *cm; 317 int batch = 0; 318 319 for (cm = CMSG_FIRSTHDR(msg); 320 cm && cm->cmsg_len; 321 cm = CMSG_NXTHDR(msg, cm)) { 322 if (cm->cmsg_level == SOL_SOCKET && 323 cm->cmsg_type == SCM_TIMESTAMPING) { 324 tss = (void *) CMSG_DATA(cm); 325 } else if ((cm->cmsg_level == SOL_IP && 326 cm->cmsg_type == IP_RECVERR) || 327 (cm->cmsg_level == SOL_IPV6 && 328 cm->cmsg_type == IPV6_RECVERR) || 329 (cm->cmsg_level == SOL_PACKET && 330 cm->cmsg_type == PACKET_TX_TIMESTAMP)) { 331 serr = (void *) CMSG_DATA(cm); 332 if (serr->ee_errno != ENOMSG || 333 serr->ee_origin != SO_EE_ORIGIN_TIMESTAMPING) { 334 fprintf(stderr, "unknown ip error %d %d\n", 335 serr->ee_errno, 336 serr->ee_origin); 337 serr = NULL; 338 } 339 } else if (cm->cmsg_level == SOL_IP && 340 cm->cmsg_type == IP_PKTINFO) { 341 struct in_pktinfo *info = (void *) CMSG_DATA(cm); 342 print_pktinfo(AF_INET, info->ipi_ifindex, 343 &info->ipi_spec_dst, &info->ipi_addr); 344 } else if (cm->cmsg_level == SOL_IPV6 && 345 cm->cmsg_type == IPV6_PKTINFO) { 346 struct in6_pktinfo *info6 = (void *) CMSG_DATA(cm); 347 print_pktinfo(AF_INET6, info6->ipi6_ifindex, 348 NULL, &info6->ipi6_addr); 349 } else 350 fprintf(stderr, "unknown cmsg %d,%d\n", 351 cm->cmsg_level, cm->cmsg_type); 352 353 if (serr && tss) { 354 print_timestamp(tss, serr->ee_info, serr->ee_data, 355 payload_len); 356 serr = NULL; 357 tss = NULL; 358 batch++; 359 } 360 } 361 362 if (batch > 1) { 363 fprintf(stderr, "batched %d timestamps\n", batch); 364 } else if (!batch) { 365 fprintf(stderr, "Failed to report timestamps\n"); 366 test_failed = true; 367 } 368 } 369 370 static int recv_errmsg(int fd) 371 { 372 static char ctrl[1024 /* overprovision*/]; 373 static struct msghdr msg; 374 struct iovec entry; 375 static char *data; 376 int ret = 0; 377 378 data = malloc(cfg_payload_len); 379 if (!data) 380 error(1, 0, "malloc"); 381 382 memset(&msg, 0, sizeof(msg)); 383 memset(&entry, 0, sizeof(entry)); 384 memset(ctrl, 0, sizeof(ctrl)); 385 386 entry.iov_base = data; 387 entry.iov_len = cfg_payload_len; 388 msg.msg_iov = &entry; 389 msg.msg_iovlen = 1; 390 msg.msg_name = NULL; 391 msg.msg_namelen = 0; 392 msg.msg_control = ctrl; 393 msg.msg_controllen = sizeof(ctrl); 394 395 ret = recvmsg(fd, &msg, MSG_ERRQUEUE); 396 if (ret == -1 && errno != EAGAIN) 397 error(1, errno, "recvmsg"); 398 399 if (ret >= 0) { 400 __recv_errmsg_cmsg(&msg, ret); 401 if (cfg_show_payload) 402 print_payload(data, cfg_payload_len); 403 } 404 405 free(data); 406 return ret == -1; 407 } 408 409 static uint16_t get_ip_csum(const uint16_t *start, int num_words, 410 unsigned long sum) 411 { 412 int i; 413 414 for (i = 0; i < num_words; i++) 415 sum += start[i]; 416 417 while (sum >> 16) 418 sum = (sum & 0xFFFF) + (sum >> 16); 419 420 return ~sum; 421 } 422 423 static uint16_t get_udp_csum(const struct udphdr *udph, int alen) 424 { 425 unsigned long pseudo_sum, csum_len; 426 const void *csum_start = udph; 427 428 pseudo_sum = htons(IPPROTO_UDP); 429 pseudo_sum += udph->len; 430 431 /* checksum ip(v6) addresses + udp header + payload */ 432 csum_start -= alen * 2; 433 csum_len = ntohs(udph->len) + alen * 2; 434 435 return get_ip_csum(csum_start, csum_len >> 1, pseudo_sum); 436 } 437 438 static int fill_header_ipv4(void *p) 439 { 440 struct iphdr *iph = p; 441 442 memset(iph, 0, sizeof(*iph)); 443 444 iph->ihl = 5; 445 iph->version = 4; 446 iph->ttl = 2; 447 iph->saddr = daddr.sin_addr.s_addr; /* set for udp csum calc */ 448 iph->daddr = daddr.sin_addr.s_addr; 449 iph->protocol = IPPROTO_UDP; 450 451 /* kernel writes saddr, csum, len */ 452 453 return sizeof(*iph); 454 } 455 456 static int fill_header_ipv6(void *p) 457 { 458 struct ipv6hdr *ip6h = p; 459 460 memset(ip6h, 0, sizeof(*ip6h)); 461 462 ip6h->version = 6; 463 ip6h->payload_len = htons(sizeof(struct udphdr) + cfg_payload_len); 464 ip6h->nexthdr = IPPROTO_UDP; 465 ip6h->hop_limit = 64; 466 467 ip6h->saddr = daddr6.sin6_addr; 468 ip6h->daddr = daddr6.sin6_addr; 469 470 /* kernel does not write saddr in case of ipv6 */ 471 472 return sizeof(*ip6h); 473 } 474 475 static void fill_header_udp(void *p, bool is_ipv4) 476 { 477 struct udphdr *udph = p; 478 479 udph->source = ntohs(dest_port + 1); /* spoof */ 480 udph->dest = ntohs(dest_port); 481 udph->len = ntohs(sizeof(*udph) + cfg_payload_len); 482 udph->check = 0; 483 484 udph->check = get_udp_csum(udph, is_ipv4 ? sizeof(struct in_addr) : 485 sizeof(struct in6_addr)); 486 } 487 488 static void do_test(int family, unsigned int report_opt) 489 { 490 char control[2 * CMSG_SPACE(sizeof(uint32_t))]; 491 struct sockaddr_ll laddr; 492 unsigned int sock_opt; 493 struct cmsghdr *cmsg; 494 struct msghdr msg; 495 struct iovec iov; 496 char *buf; 497 int fd, i, val = 1, total_len, epfd = 0; 498 499 init_timing_event(&usr_enq); 500 init_timing_event(&usr_snd); 501 init_timing_event(&usr_ack); 502 503 total_len = cfg_payload_len; 504 if (cfg_use_pf_packet || cfg_proto == SOCK_RAW) { 505 total_len += sizeof(struct udphdr); 506 if (cfg_use_pf_packet || cfg_ipproto == IPPROTO_RAW) { 507 if (family == PF_INET) 508 total_len += sizeof(struct iphdr); 509 else 510 total_len += sizeof(struct ipv6hdr); 511 } 512 /* special case, only rawv6_sendmsg: 513 * pass proto in sin6_port if not connected 514 * also see ANK comment in net/ipv4/raw.c 515 */ 516 daddr6.sin6_port = htons(cfg_ipproto); 517 } 518 519 buf = malloc(total_len); 520 if (!buf) 521 error(1, 0, "malloc"); 522 523 fd = socket(cfg_use_pf_packet ? PF_PACKET : family, 524 cfg_proto, cfg_ipproto); 525 if (fd < 0) 526 error(1, errno, "socket"); 527 528 if (cfg_use_epoll) { 529 struct epoll_event ev; 530 531 memset(&ev, 0, sizeof(ev)); 532 ev.data.fd = fd; 533 if (cfg_epollet) 534 ev.events |= EPOLLET; 535 epfd = epoll_create(1); 536 if (epfd <= 0) 537 error(1, errno, "epoll_create"); 538 if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev)) 539 error(1, errno, "epoll_ctl"); 540 } 541 542 /* reset expected key on each new socket */ 543 saved_tskey = -1; 544 545 if (cfg_proto == SOCK_STREAM) { 546 if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, 547 (char*) &val, sizeof(val))) 548 error(1, 0, "setsockopt no nagle"); 549 550 if (family == PF_INET) { 551 if (connect(fd, (void *) &daddr, sizeof(daddr))) 552 error(1, errno, "connect ipv4"); 553 } else { 554 if (connect(fd, (void *) &daddr6, sizeof(daddr6))) 555 error(1, errno, "connect ipv6"); 556 } 557 } 558 559 if (cfg_do_pktinfo) { 560 if (family == AF_INET6) { 561 if (setsockopt(fd, SOL_IPV6, IPV6_RECVPKTINFO, 562 &val, sizeof(val))) 563 error(1, errno, "setsockopt pktinfo ipv6"); 564 } else { 565 if (setsockopt(fd, SOL_IP, IP_PKTINFO, 566 &val, sizeof(val))) 567 error(1, errno, "setsockopt pktinfo ipv4"); 568 } 569 } 570 571 sock_opt = SOF_TIMESTAMPING_SOFTWARE | 572 SOF_TIMESTAMPING_OPT_CMSG | 573 SOF_TIMESTAMPING_OPT_ID; 574 575 if (!cfg_use_cmsg) 576 sock_opt |= report_opt; 577 578 if (cfg_loop_nodata) 579 sock_opt |= SOF_TIMESTAMPING_OPT_TSONLY; 580 581 if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING, 582 (char *) &sock_opt, sizeof(sock_opt))) 583 error(1, 0, "setsockopt timestamping"); 584 585 for (i = 0; i < cfg_num_pkts; i++) { 586 memset(&msg, 0, sizeof(msg)); 587 memset(buf, 'a' + i, total_len); 588 589 if (cfg_use_pf_packet || cfg_proto == SOCK_RAW) { 590 int off = 0; 591 592 if (cfg_use_pf_packet || cfg_ipproto == IPPROTO_RAW) { 593 if (family == PF_INET) 594 off = fill_header_ipv4(buf); 595 else 596 off = fill_header_ipv6(buf); 597 } 598 599 fill_header_udp(buf + off, family == PF_INET); 600 } 601 602 print_timestamp_usr(); 603 604 iov.iov_base = buf; 605 iov.iov_len = total_len; 606 607 if (cfg_proto != SOCK_STREAM) { 608 if (cfg_use_pf_packet) { 609 memset(&laddr, 0, sizeof(laddr)); 610 611 laddr.sll_family = AF_PACKET; 612 laddr.sll_ifindex = 1; 613 laddr.sll_protocol = htons(family == AF_INET ? ETH_P_IP : ETH_P_IPV6); 614 laddr.sll_halen = ETH_ALEN; 615 616 msg.msg_name = (void *)&laddr; 617 msg.msg_namelen = sizeof(laddr); 618 } else if (family == PF_INET) { 619 msg.msg_name = (void *)&daddr; 620 msg.msg_namelen = sizeof(daddr); 621 } else { 622 msg.msg_name = (void *)&daddr6; 623 msg.msg_namelen = sizeof(daddr6); 624 } 625 } 626 627 msg.msg_iov = &iov; 628 msg.msg_iovlen = 1; 629 630 if (cfg_use_cmsg || cfg_use_cmsg_opt_id) { 631 memset(control, 0, sizeof(control)); 632 633 msg.msg_control = control; 634 msg.msg_controllen = cfg_use_cmsg * CMSG_SPACE(sizeof(uint32_t)); 635 msg.msg_controllen += cfg_use_cmsg_opt_id * CMSG_SPACE(sizeof(uint32_t)); 636 637 cmsg = NULL; 638 if (cfg_use_cmsg) { 639 cmsg = CMSG_FIRSTHDR(&msg); 640 cmsg->cmsg_level = SOL_SOCKET; 641 cmsg->cmsg_type = SO_TIMESTAMPING; 642 cmsg->cmsg_len = CMSG_LEN(sizeof(uint32_t)); 643 644 *((uint32_t *)CMSG_DATA(cmsg)) = report_opt; 645 } 646 if (cfg_use_cmsg_opt_id) { 647 cmsg = cmsg ? CMSG_NXTHDR(&msg, cmsg) : CMSG_FIRSTHDR(&msg); 648 cmsg->cmsg_level = SOL_SOCKET; 649 cmsg->cmsg_type = SCM_TS_OPT_ID; 650 cmsg->cmsg_len = CMSG_LEN(sizeof(uint32_t)); 651 652 *((uint32_t *)CMSG_DATA(cmsg)) = ts_opt_id; 653 saved_tskey = ts_opt_id; 654 } 655 656 } 657 658 val = sendmsg(fd, &msg, 0); 659 if (val != total_len) 660 error(1, errno, "send"); 661 662 /* wait for all errors to be queued, else ACKs arrive OOO */ 663 if (cfg_sleep_usec) 664 usleep(cfg_sleep_usec); 665 666 if (!cfg_busy_poll) { 667 if (cfg_use_epoll) 668 __epoll(epfd); 669 else 670 __poll(fd); 671 } 672 673 while (!recv_errmsg(fd)) {} 674 } 675 676 print_timing_event("USR-ENQ", &usr_enq); 677 print_timing_event("USR-SND", &usr_snd); 678 print_timing_event("USR-ACK", &usr_ack); 679 680 if (close(fd)) 681 error(1, errno, "close"); 682 683 free(buf); 684 usleep(100 * NSEC_PER_USEC); 685 } 686 687 static void __attribute__((noreturn)) usage(const char *filepath) 688 { 689 fprintf(stderr, "\nUsage: %s [options] hostname\n" 690 "\nwhere options are:\n" 691 " -4: only IPv4\n" 692 " -6: only IPv6\n" 693 " -h: show this message\n" 694 " -b: busy poll to read from error queue\n" 695 " -c N: number of packets for each test\n" 696 " -C: use cmsg to set tstamp recording options\n" 697 " -e: use level-triggered epoll() instead of poll()\n" 698 " -E: use event-triggered epoll() instead of poll()\n" 699 " -F: poll()/epoll() waits forever for an event\n" 700 " -I: request PKTINFO\n" 701 " -l N: send N bytes at a time\n" 702 " -L listen on hostname and port\n" 703 " -n: set no-payload option\n" 704 " -N: print timestamps and durations in nsec (instead of usec)\n" 705 " -o N: use SCM_TS_OPT_ID control message to provide N as tskey\n" 706 " -p N: connect to port N\n" 707 " -P: use PF_PACKET\n" 708 " -r: use raw\n" 709 " -R: use raw (IP_HDRINCL)\n" 710 " -S N: usec to sleep before reading error queue\n" 711 " -t N: tolerance (usec) for timestamp validation\n" 712 " -u: use udp\n" 713 " -v: validate SND delay (usec)\n" 714 " -V: validate ACK delay (usec)\n" 715 " -x: show payload (up to 70 bytes)\n", 716 filepath); 717 exit(1); 718 } 719 720 static void parse_opt(int argc, char **argv) 721 { 722 int proto_count = 0; 723 int c; 724 725 while ((c = getopt(argc, argv, 726 "46bc:CeEFhIl:LnNo:p:PrRS:t:uv:V:x")) != -1) { 727 switch (c) { 728 case '4': 729 do_ipv6 = 0; 730 break; 731 case '6': 732 do_ipv4 = 0; 733 break; 734 case 'b': 735 cfg_busy_poll = true; 736 break; 737 case 'c': 738 cfg_num_pkts = strtoul(optarg, NULL, 10); 739 break; 740 case 'C': 741 cfg_use_cmsg = true; 742 break; 743 case 'e': 744 cfg_use_epoll = true; 745 break; 746 case 'E': 747 cfg_use_epoll = true; 748 cfg_epollet = true; 749 case 'F': 750 cfg_poll_timeout = -1; 751 break; 752 case 'I': 753 cfg_do_pktinfo = true; 754 break; 755 case 'l': 756 cfg_payload_len = strtoul(optarg, NULL, 10); 757 break; 758 case 'L': 759 cfg_do_listen = true; 760 break; 761 case 'n': 762 cfg_loop_nodata = true; 763 break; 764 case 'N': 765 cfg_print_nsec = true; 766 break; 767 case 'o': 768 ts_opt_id = strtoul(optarg, NULL, 10); 769 cfg_use_cmsg_opt_id = true; 770 break; 771 case 'p': 772 dest_port = strtoul(optarg, NULL, 10); 773 break; 774 case 'P': 775 proto_count++; 776 cfg_use_pf_packet = true; 777 cfg_proto = SOCK_DGRAM; 778 cfg_ipproto = 0; 779 break; 780 case 'r': 781 proto_count++; 782 cfg_proto = SOCK_RAW; 783 cfg_ipproto = IPPROTO_UDP; 784 break; 785 case 'R': 786 proto_count++; 787 cfg_proto = SOCK_RAW; 788 cfg_ipproto = IPPROTO_RAW; 789 break; 790 case 'S': 791 cfg_sleep_usec = strtoul(optarg, NULL, 10); 792 break; 793 case 't': 794 cfg_delay_tolerance_usec = strtoul(optarg, NULL, 10); 795 break; 796 case 'u': 797 proto_count++; 798 cfg_proto = SOCK_DGRAM; 799 cfg_ipproto = IPPROTO_UDP; 800 break; 801 case 'v': 802 cfg_delay_snd = strtoul(optarg, NULL, 10); 803 break; 804 case 'V': 805 cfg_delay_ack = strtoul(optarg, NULL, 10); 806 break; 807 case 'x': 808 cfg_show_payload = true; 809 break; 810 case 'h': 811 default: 812 usage(argv[0]); 813 } 814 } 815 816 if (!cfg_payload_len) 817 error(1, 0, "payload may not be nonzero"); 818 if (cfg_proto != SOCK_STREAM && cfg_payload_len > 1472) 819 error(1, 0, "udp packet might exceed expected MTU"); 820 if (!do_ipv4 && !do_ipv6) 821 error(1, 0, "pass -4 or -6, not both"); 822 if (proto_count > 1) 823 error(1, 0, "pass -P, -r, -R or -u, not multiple"); 824 if (cfg_do_pktinfo && cfg_use_pf_packet) 825 error(1, 0, "cannot ask for pktinfo over pf_packet"); 826 if (cfg_busy_poll && cfg_use_epoll) 827 error(1, 0, "pass epoll or busy_poll, not both"); 828 if (cfg_proto == SOCK_STREAM && cfg_use_cmsg_opt_id) 829 error(1, 0, "TCP sockets don't support SCM_TS_OPT_ID"); 830 831 if (optind != argc - 1) 832 error(1, 0, "missing required hostname argument"); 833 } 834 835 static void resolve_hostname(const char *hostname) 836 { 837 struct addrinfo hints = { .ai_family = do_ipv4 ? AF_INET : AF_INET6 }; 838 struct addrinfo *addrs, *cur; 839 int have_ipv4 = 0, have_ipv6 = 0; 840 841 retry: 842 if (getaddrinfo(hostname, NULL, &hints, &addrs)) 843 error(1, errno, "getaddrinfo"); 844 845 cur = addrs; 846 while (cur && !have_ipv4 && !have_ipv6) { 847 if (!have_ipv4 && cur->ai_family == AF_INET) { 848 memcpy(&daddr, cur->ai_addr, sizeof(daddr)); 849 daddr.sin_port = htons(dest_port); 850 have_ipv4 = 1; 851 } 852 else if (!have_ipv6 && cur->ai_family == AF_INET6) { 853 memcpy(&daddr6, cur->ai_addr, sizeof(daddr6)); 854 daddr6.sin6_port = htons(dest_port); 855 have_ipv6 = 1; 856 } 857 cur = cur->ai_next; 858 } 859 if (addrs) 860 freeaddrinfo(addrs); 861 862 if (do_ipv6 && hints.ai_family != AF_INET6) { 863 hints.ai_family = AF_INET6; 864 goto retry; 865 } 866 867 do_ipv4 &= have_ipv4; 868 do_ipv6 &= have_ipv6; 869 } 870 871 static void do_listen(int family, void *addr, int alen) 872 { 873 int fd, type; 874 875 type = cfg_proto == SOCK_RAW ? SOCK_DGRAM : cfg_proto; 876 877 fd = socket(family, type, 0); 878 if (fd == -1) 879 error(1, errno, "socket rx"); 880 881 if (bind(fd, addr, alen)) 882 error(1, errno, "bind rx"); 883 884 if (type == SOCK_STREAM && listen(fd, 10)) 885 error(1, errno, "listen rx"); 886 887 /* leave fd open, will be closed on process exit. 888 * this enables connect() to succeed and avoids icmp replies 889 */ 890 } 891 892 static void do_main(int family) 893 { 894 fprintf(stderr, "family: %s %s\n", 895 family == PF_INET ? "INET" : "INET6", 896 cfg_use_pf_packet ? "(PF_PACKET)" : ""); 897 898 fprintf(stderr, "test SND\n"); 899 do_test(family, SOF_TIMESTAMPING_TX_SOFTWARE); 900 901 fprintf(stderr, "test ENQ\n"); 902 do_test(family, SOF_TIMESTAMPING_TX_SCHED); 903 904 fprintf(stderr, "test ENQ + SND\n"); 905 do_test(family, SOF_TIMESTAMPING_TX_SCHED | 906 SOF_TIMESTAMPING_TX_SOFTWARE); 907 908 if (cfg_proto == SOCK_STREAM) { 909 fprintf(stderr, "\ntest ACK\n"); 910 do_test(family, SOF_TIMESTAMPING_TX_ACK); 911 912 fprintf(stderr, "\ntest SND + ACK\n"); 913 do_test(family, SOF_TIMESTAMPING_TX_SOFTWARE | 914 SOF_TIMESTAMPING_TX_ACK); 915 916 fprintf(stderr, "\ntest ENQ + SND + ACK\n"); 917 do_test(family, SOF_TIMESTAMPING_TX_SCHED | 918 SOF_TIMESTAMPING_TX_SOFTWARE | 919 SOF_TIMESTAMPING_TX_ACK); 920 } 921 } 922 923 const char *sock_names[] = { NULL, "TCP", "UDP", "RAW" }; 924 925 int main(int argc, char **argv) 926 { 927 if (argc == 1) 928 usage(argv[0]); 929 930 parse_opt(argc, argv); 931 resolve_hostname(argv[argc - 1]); 932 933 fprintf(stderr, "protocol: %s\n", sock_names[cfg_proto]); 934 fprintf(stderr, "payload: %u\n", cfg_payload_len); 935 fprintf(stderr, "server port: %u\n", dest_port); 936 fprintf(stderr, "\n"); 937 938 if (do_ipv4) { 939 if (cfg_do_listen) 940 do_listen(PF_INET, &daddr, sizeof(daddr)); 941 do_main(PF_INET); 942 } 943 944 if (do_ipv6) { 945 if (cfg_do_listen) 946 do_listen(PF_INET6, &daddr6, sizeof(daddr6)); 947 do_main(PF_INET6); 948 } 949 950 return test_failed; 951 } 952