Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright 2014 Google Inc.
0004  * Author: willemb@google.com (Willem de Bruijn)
0005  *
0006  * Test software tx timestamping, including
0007  *
0008  * - SCHED, SND and ACK timestamps
0009  * - RAW, UDP and TCP
0010  * - IPv4 and IPv6
0011  * - various packet sizes (to test GSO and TSO)
0012  *
0013  * Consult the command line arguments for help on running
0014  * the various testcases.
0015  *
0016  * This test requires a dummy TCP server.
0017  * A simple `nc6 [-u] -l -p $DESTPORT` will do
0018  */
0019 
0020 #define _GNU_SOURCE
0021 
0022 #include <arpa/inet.h>
0023 #include <asm/types.h>
0024 #include <error.h>
0025 #include <errno.h>
0026 #include <inttypes.h>
0027 #include <linux/errqueue.h>
0028 #include <linux/if_ether.h>
0029 #include <linux/if_packet.h>
0030 #include <linux/ipv6.h>
0031 #include <linux/net_tstamp.h>
0032 #include <netdb.h>
0033 #include <net/if.h>
0034 #include <netinet/in.h>
0035 #include <netinet/ip.h>
0036 #include <netinet/udp.h>
0037 #include <netinet/tcp.h>
0038 #include <poll.h>
0039 #include <stdarg.h>
0040 #include <stdbool.h>
0041 #include <stdio.h>
0042 #include <stdlib.h>
0043 #include <string.h>
0044 #include <sys/epoll.h>
0045 #include <sys/ioctl.h>
0046 #include <sys/select.h>
0047 #include <sys/socket.h>
0048 #include <sys/time.h>
0049 #include <sys/types.h>
0050 #include <time.h>
0051 #include <unistd.h>
0052 
0053 #define NSEC_PER_USEC   1000L
0054 #define USEC_PER_SEC    1000000L
0055 #define NSEC_PER_SEC    1000000000LL
0056 
0057 /* command line parameters */
0058 static int cfg_proto = SOCK_STREAM;
0059 static int cfg_ipproto = IPPROTO_TCP;
0060 static int cfg_num_pkts = 4;
0061 static int do_ipv4 = 1;
0062 static int do_ipv6 = 1;
0063 static int cfg_payload_len = 10;
0064 static int cfg_poll_timeout = 100;
0065 static int cfg_delay_snd;
0066 static int cfg_delay_ack;
0067 static int cfg_delay_tolerance_usec = 500;
0068 static bool cfg_show_payload;
0069 static bool cfg_do_pktinfo;
0070 static bool cfg_busy_poll;
0071 static int cfg_sleep_usec = 50 * 1000;
0072 static bool cfg_loop_nodata;
0073 static bool cfg_use_cmsg;
0074 static bool cfg_use_pf_packet;
0075 static bool cfg_use_epoll;
0076 static bool cfg_epollet;
0077 static bool cfg_do_listen;
0078 static uint16_t dest_port = 9000;
0079 static bool cfg_print_nsec;
0080 
0081 static struct sockaddr_in daddr;
0082 static struct sockaddr_in6 daddr6;
0083 static struct timespec ts_usr;
0084 
0085 static int saved_tskey = -1;
0086 static int saved_tskey_type = -1;
0087 
0088 struct timing_event {
0089     int64_t min;
0090     int64_t max;
0091     int64_t total;
0092     int count;
0093 };
0094 
0095 static struct timing_event usr_enq;
0096 static struct timing_event usr_snd;
0097 static struct timing_event usr_ack;
0098 
0099 static bool test_failed;
0100 
0101 static int64_t timespec_to_ns64(struct timespec *ts)
0102 {
0103     return ts->tv_sec * NSEC_PER_SEC + ts->tv_nsec;
0104 }
0105 
0106 static int64_t timespec_to_us64(struct timespec *ts)
0107 {
0108     return ts->tv_sec * USEC_PER_SEC + ts->tv_nsec / NSEC_PER_USEC;
0109 }
0110 
0111 static void init_timing_event(struct timing_event *te)
0112 {
0113     te->min = INT64_MAX;
0114     te->max = 0;
0115     te->total = 0;
0116     te->count = 0;
0117 }
0118 
0119 static void add_timing_event(struct timing_event *te,
0120         struct timespec *t_start, struct timespec *t_end)
0121 {
0122     int64_t ts_delta = timespec_to_ns64(t_end) - timespec_to_ns64(t_start);
0123 
0124     te->count++;
0125     if (ts_delta < te->min)
0126         te->min = ts_delta;
0127     if (ts_delta > te->max)
0128         te->max = ts_delta;
0129     te->total += ts_delta;
0130 }
0131 
0132 static void validate_key(int tskey, int tstype)
0133 {
0134     int stepsize;
0135 
0136     /* compare key for each subsequent request
0137      * must only test for one type, the first one requested
0138      */
0139     if (saved_tskey == -1)
0140         saved_tskey_type = tstype;
0141     else if (saved_tskey_type != tstype)
0142         return;
0143 
0144     stepsize = cfg_proto == SOCK_STREAM ? cfg_payload_len : 1;
0145     if (tskey != saved_tskey + stepsize) {
0146         fprintf(stderr, "ERROR: key %d, expected %d\n",
0147                 tskey, saved_tskey + stepsize);
0148         test_failed = true;
0149     }
0150 
0151     saved_tskey = tskey;
0152 }
0153 
0154 static void validate_timestamp(struct timespec *cur, int min_delay)
0155 {
0156     int64_t cur64, start64;
0157     int max_delay;
0158 
0159     cur64 = timespec_to_us64(cur);
0160     start64 = timespec_to_us64(&ts_usr);
0161     max_delay = min_delay + cfg_delay_tolerance_usec;
0162 
0163     if (cur64 < start64 + min_delay || cur64 > start64 + max_delay) {
0164         fprintf(stderr, "ERROR: %" PRId64 " us expected between %d and %d\n",
0165                 cur64 - start64, min_delay, max_delay);
0166         test_failed = true;
0167     }
0168 }
0169 
0170 static void __print_ts_delta_formatted(int64_t ts_delta)
0171 {
0172     if (cfg_print_nsec)
0173         fprintf(stderr, "%" PRId64 " ns", ts_delta);
0174     else
0175         fprintf(stderr, "%" PRId64 " us", ts_delta / NSEC_PER_USEC);
0176 }
0177 
0178 static void __print_timestamp(const char *name, struct timespec *cur,
0179                   uint32_t key, int payload_len)
0180 {
0181     int64_t ts_delta;
0182 
0183     if (!(cur->tv_sec | cur->tv_nsec))
0184         return;
0185 
0186     if (cfg_print_nsec)
0187         fprintf(stderr, "  %s: %lu s %lu ns (seq=%u, len=%u)",
0188                 name, cur->tv_sec, cur->tv_nsec,
0189                 key, payload_len);
0190     else
0191         fprintf(stderr, "  %s: %lu s %lu us (seq=%u, len=%u)",
0192                 name, cur->tv_sec, cur->tv_nsec / NSEC_PER_USEC,
0193                 key, payload_len);
0194 
0195     if (cur != &ts_usr) {
0196         ts_delta = timespec_to_ns64(cur) - timespec_to_ns64(&ts_usr);
0197         fprintf(stderr, "  (USR +");
0198         __print_ts_delta_formatted(ts_delta);
0199         fprintf(stderr, ")");
0200     }
0201 
0202     fprintf(stderr, "\n");
0203 }
0204 
0205 static void print_timestamp_usr(void)
0206 {
0207     if (clock_gettime(CLOCK_REALTIME, &ts_usr))
0208         error(1, errno, "clock_gettime");
0209 
0210     __print_timestamp("  USR", &ts_usr, 0, 0);
0211 }
0212 
0213 static void print_timestamp(struct scm_timestamping *tss, int tstype,
0214                 int tskey, int payload_len)
0215 {
0216     const char *tsname;
0217 
0218     validate_key(tskey, tstype);
0219 
0220     switch (tstype) {
0221     case SCM_TSTAMP_SCHED:
0222         tsname = "  ENQ";
0223         validate_timestamp(&tss->ts[0], 0);
0224         add_timing_event(&usr_enq, &ts_usr, &tss->ts[0]);
0225         break;
0226     case SCM_TSTAMP_SND:
0227         tsname = "  SND";
0228         validate_timestamp(&tss->ts[0], cfg_delay_snd);
0229         add_timing_event(&usr_snd, &ts_usr, &tss->ts[0]);
0230         break;
0231     case SCM_TSTAMP_ACK:
0232         tsname = "  ACK";
0233         validate_timestamp(&tss->ts[0], cfg_delay_ack);
0234         add_timing_event(&usr_ack, &ts_usr, &tss->ts[0]);
0235         break;
0236     default:
0237         error(1, 0, "unknown timestamp type: %u",
0238         tstype);
0239     }
0240     __print_timestamp(tsname, &tss->ts[0], tskey, payload_len);
0241 }
0242 
0243 static void print_timing_event(char *name, struct timing_event *te)
0244 {
0245     if (!te->count)
0246         return;
0247 
0248     fprintf(stderr, "    %s: count=%d", name, te->count);
0249     fprintf(stderr, ", avg=");
0250     __print_ts_delta_formatted((int64_t)(te->total / te->count));
0251     fprintf(stderr, ", min=");
0252     __print_ts_delta_formatted(te->min);
0253     fprintf(stderr, ", max=");
0254     __print_ts_delta_formatted(te->max);
0255     fprintf(stderr, "\n");
0256 }
0257 
0258 /* TODO: convert to check_and_print payload once API is stable */
0259 static void print_payload(char *data, int len)
0260 {
0261     int i;
0262 
0263     if (!len)
0264         return;
0265 
0266     if (len > 70)
0267         len = 70;
0268 
0269     fprintf(stderr, "payload: ");
0270     for (i = 0; i < len; i++)
0271         fprintf(stderr, "%02hhx ", data[i]);
0272     fprintf(stderr, "\n");
0273 }
0274 
0275 static void print_pktinfo(int family, int ifindex, void *saddr, void *daddr)
0276 {
0277     char sa[INET6_ADDRSTRLEN], da[INET6_ADDRSTRLEN];
0278 
0279     fprintf(stderr, "         pktinfo: ifindex=%u src=%s dst=%s\n",
0280         ifindex,
0281         saddr ? inet_ntop(family, saddr, sa, sizeof(sa)) : "unknown",
0282         daddr ? inet_ntop(family, daddr, da, sizeof(da)) : "unknown");
0283 }
0284 
0285 static void __epoll(int epfd)
0286 {
0287     struct epoll_event events;
0288     int ret;
0289 
0290     memset(&events, 0, sizeof(events));
0291     ret = epoll_wait(epfd, &events, 1, cfg_poll_timeout);
0292     if (ret != 1)
0293         error(1, errno, "epoll_wait");
0294 }
0295 
0296 static void __poll(int fd)
0297 {
0298     struct pollfd pollfd;
0299     int ret;
0300 
0301     memset(&pollfd, 0, sizeof(pollfd));
0302     pollfd.fd = fd;
0303     ret = poll(&pollfd, 1, cfg_poll_timeout);
0304     if (ret != 1)
0305         error(1, errno, "poll");
0306 }
0307 
0308 static void __recv_errmsg_cmsg(struct msghdr *msg, int payload_len)
0309 {
0310     struct sock_extended_err *serr = NULL;
0311     struct scm_timestamping *tss = NULL;
0312     struct cmsghdr *cm;
0313     int batch = 0;
0314 
0315     for (cm = CMSG_FIRSTHDR(msg);
0316          cm && cm->cmsg_len;
0317          cm = CMSG_NXTHDR(msg, cm)) {
0318         if (cm->cmsg_level == SOL_SOCKET &&
0319             cm->cmsg_type == SCM_TIMESTAMPING) {
0320             tss = (void *) CMSG_DATA(cm);
0321         } else if ((cm->cmsg_level == SOL_IP &&
0322                 cm->cmsg_type == IP_RECVERR) ||
0323                (cm->cmsg_level == SOL_IPV6 &&
0324                 cm->cmsg_type == IPV6_RECVERR) ||
0325                (cm->cmsg_level == SOL_PACKET &&
0326                 cm->cmsg_type == PACKET_TX_TIMESTAMP)) {
0327             serr = (void *) CMSG_DATA(cm);
0328             if (serr->ee_errno != ENOMSG ||
0329                 serr->ee_origin != SO_EE_ORIGIN_TIMESTAMPING) {
0330                 fprintf(stderr, "unknown ip error %d %d\n",
0331                         serr->ee_errno,
0332                         serr->ee_origin);
0333                 serr = NULL;
0334             }
0335         } else if (cm->cmsg_level == SOL_IP &&
0336                cm->cmsg_type == IP_PKTINFO) {
0337             struct in_pktinfo *info = (void *) CMSG_DATA(cm);
0338             print_pktinfo(AF_INET, info->ipi_ifindex,
0339                       &info->ipi_spec_dst, &info->ipi_addr);
0340         } else if (cm->cmsg_level == SOL_IPV6 &&
0341                cm->cmsg_type == IPV6_PKTINFO) {
0342             struct in6_pktinfo *info6 = (void *) CMSG_DATA(cm);
0343             print_pktinfo(AF_INET6, info6->ipi6_ifindex,
0344                       NULL, &info6->ipi6_addr);
0345         } else
0346             fprintf(stderr, "unknown cmsg %d,%d\n",
0347                     cm->cmsg_level, cm->cmsg_type);
0348 
0349         if (serr && tss) {
0350             print_timestamp(tss, serr->ee_info, serr->ee_data,
0351                     payload_len);
0352             serr = NULL;
0353             tss = NULL;
0354             batch++;
0355         }
0356     }
0357 
0358     if (batch > 1)
0359         fprintf(stderr, "batched %d timestamps\n", batch);
0360 }
0361 
0362 static int recv_errmsg(int fd)
0363 {
0364     static char ctrl[1024 /* overprovision*/];
0365     static struct msghdr msg;
0366     struct iovec entry;
0367     static char *data;
0368     int ret = 0;
0369 
0370     data = malloc(cfg_payload_len);
0371     if (!data)
0372         error(1, 0, "malloc");
0373 
0374     memset(&msg, 0, sizeof(msg));
0375     memset(&entry, 0, sizeof(entry));
0376     memset(ctrl, 0, sizeof(ctrl));
0377 
0378     entry.iov_base = data;
0379     entry.iov_len = cfg_payload_len;
0380     msg.msg_iov = &entry;
0381     msg.msg_iovlen = 1;
0382     msg.msg_name = NULL;
0383     msg.msg_namelen = 0;
0384     msg.msg_control = ctrl;
0385     msg.msg_controllen = sizeof(ctrl);
0386 
0387     ret = recvmsg(fd, &msg, MSG_ERRQUEUE);
0388     if (ret == -1 && errno != EAGAIN)
0389         error(1, errno, "recvmsg");
0390 
0391     if (ret >= 0) {
0392         __recv_errmsg_cmsg(&msg, ret);
0393         if (cfg_show_payload)
0394             print_payload(data, cfg_payload_len);
0395     }
0396 
0397     free(data);
0398     return ret == -1;
0399 }
0400 
0401 static uint16_t get_ip_csum(const uint16_t *start, int num_words,
0402                 unsigned long sum)
0403 {
0404     int i;
0405 
0406     for (i = 0; i < num_words; i++)
0407         sum += start[i];
0408 
0409     while (sum >> 16)
0410         sum = (sum & 0xFFFF) + (sum >> 16);
0411 
0412     return ~sum;
0413 }
0414 
0415 static uint16_t get_udp_csum(const struct udphdr *udph, int alen)
0416 {
0417     unsigned long pseudo_sum, csum_len;
0418     const void *csum_start = udph;
0419 
0420     pseudo_sum = htons(IPPROTO_UDP);
0421     pseudo_sum += udph->len;
0422 
0423     /* checksum ip(v6) addresses + udp header + payload */
0424     csum_start -= alen * 2;
0425     csum_len = ntohs(udph->len) + alen * 2;
0426 
0427     return get_ip_csum(csum_start, csum_len >> 1, pseudo_sum);
0428 }
0429 
0430 static int fill_header_ipv4(void *p)
0431 {
0432     struct iphdr *iph = p;
0433 
0434     memset(iph, 0, sizeof(*iph));
0435 
0436     iph->ihl    = 5;
0437     iph->version    = 4;
0438     iph->ttl    = 2;
0439     iph->saddr  = daddr.sin_addr.s_addr;    /* set for udp csum calc */
0440     iph->daddr  = daddr.sin_addr.s_addr;
0441     iph->protocol   = IPPROTO_UDP;
0442 
0443     /* kernel writes saddr, csum, len */
0444 
0445     return sizeof(*iph);
0446 }
0447 
0448 static int fill_header_ipv6(void *p)
0449 {
0450     struct ipv6hdr *ip6h = p;
0451 
0452     memset(ip6h, 0, sizeof(*ip6h));
0453 
0454     ip6h->version       = 6;
0455     ip6h->payload_len   = htons(sizeof(struct udphdr) + cfg_payload_len);
0456     ip6h->nexthdr       = IPPROTO_UDP;
0457     ip6h->hop_limit     = 64;
0458 
0459     ip6h->saddr             = daddr6.sin6_addr;
0460     ip6h->daddr     = daddr6.sin6_addr;
0461 
0462     /* kernel does not write saddr in case of ipv6 */
0463 
0464     return sizeof(*ip6h);
0465 }
0466 
0467 static void fill_header_udp(void *p, bool is_ipv4)
0468 {
0469     struct udphdr *udph = p;
0470 
0471     udph->source = ntohs(dest_port + 1);    /* spoof */
0472     udph->dest   = ntohs(dest_port);
0473     udph->len    = ntohs(sizeof(*udph) + cfg_payload_len);
0474     udph->check  = 0;
0475 
0476     udph->check  = get_udp_csum(udph, is_ipv4 ? sizeof(struct in_addr) :
0477                             sizeof(struct in6_addr));
0478 }
0479 
0480 static void do_test(int family, unsigned int report_opt)
0481 {
0482     char control[CMSG_SPACE(sizeof(uint32_t))];
0483     struct sockaddr_ll laddr;
0484     unsigned int sock_opt;
0485     struct cmsghdr *cmsg;
0486     struct msghdr msg;
0487     struct iovec iov;
0488     char *buf;
0489     int fd, i, val = 1, total_len, epfd = 0;
0490 
0491     init_timing_event(&usr_enq);
0492     init_timing_event(&usr_snd);
0493     init_timing_event(&usr_ack);
0494 
0495     total_len = cfg_payload_len;
0496     if (cfg_use_pf_packet || cfg_proto == SOCK_RAW) {
0497         total_len += sizeof(struct udphdr);
0498         if (cfg_use_pf_packet || cfg_ipproto == IPPROTO_RAW) {
0499             if (family == PF_INET)
0500                 total_len += sizeof(struct iphdr);
0501             else
0502                 total_len += sizeof(struct ipv6hdr);
0503         }
0504         /* special case, only rawv6_sendmsg:
0505          * pass proto in sin6_port if not connected
0506          * also see ANK comment in net/ipv4/raw.c
0507          */
0508         daddr6.sin6_port = htons(cfg_ipproto);
0509     }
0510 
0511     buf = malloc(total_len);
0512     if (!buf)
0513         error(1, 0, "malloc");
0514 
0515     fd = socket(cfg_use_pf_packet ? PF_PACKET : family,
0516             cfg_proto, cfg_ipproto);
0517     if (fd < 0)
0518         error(1, errno, "socket");
0519 
0520     if (cfg_use_epoll) {
0521         struct epoll_event ev;
0522 
0523         memset(&ev, 0, sizeof(ev));
0524         ev.data.fd = fd;
0525         if (cfg_epollet)
0526             ev.events |= EPOLLET;
0527         epfd = epoll_create(1);
0528         if (epfd <= 0)
0529             error(1, errno, "epoll_create");
0530         if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev))
0531             error(1, errno, "epoll_ctl");
0532     }
0533 
0534     /* reset expected key on each new socket */
0535     saved_tskey = -1;
0536 
0537     if (cfg_proto == SOCK_STREAM) {
0538         if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
0539                    (char*) &val, sizeof(val)))
0540             error(1, 0, "setsockopt no nagle");
0541 
0542         if (family == PF_INET) {
0543             if (connect(fd, (void *) &daddr, sizeof(daddr)))
0544                 error(1, errno, "connect ipv4");
0545         } else {
0546             if (connect(fd, (void *) &daddr6, sizeof(daddr6)))
0547                 error(1, errno, "connect ipv6");
0548         }
0549     }
0550 
0551     if (cfg_do_pktinfo) {
0552         if (family == AF_INET6) {
0553             if (setsockopt(fd, SOL_IPV6, IPV6_RECVPKTINFO,
0554                        &val, sizeof(val)))
0555                 error(1, errno, "setsockopt pktinfo ipv6");
0556         } else {
0557             if (setsockopt(fd, SOL_IP, IP_PKTINFO,
0558                        &val, sizeof(val)))
0559                 error(1, errno, "setsockopt pktinfo ipv4");
0560         }
0561     }
0562 
0563     sock_opt = SOF_TIMESTAMPING_SOFTWARE |
0564            SOF_TIMESTAMPING_OPT_CMSG |
0565            SOF_TIMESTAMPING_OPT_ID;
0566 
0567     if (!cfg_use_cmsg)
0568         sock_opt |= report_opt;
0569 
0570     if (cfg_loop_nodata)
0571         sock_opt |= SOF_TIMESTAMPING_OPT_TSONLY;
0572 
0573     if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING,
0574                (char *) &sock_opt, sizeof(sock_opt)))
0575         error(1, 0, "setsockopt timestamping");
0576 
0577     for (i = 0; i < cfg_num_pkts; i++) {
0578         memset(&msg, 0, sizeof(msg));
0579         memset(buf, 'a' + i, total_len);
0580 
0581         if (cfg_use_pf_packet || cfg_proto == SOCK_RAW) {
0582             int off = 0;
0583 
0584             if (cfg_use_pf_packet || cfg_ipproto == IPPROTO_RAW) {
0585                 if (family == PF_INET)
0586                     off = fill_header_ipv4(buf);
0587                 else
0588                     off = fill_header_ipv6(buf);
0589             }
0590 
0591             fill_header_udp(buf + off, family == PF_INET);
0592         }
0593 
0594         print_timestamp_usr();
0595 
0596         iov.iov_base = buf;
0597         iov.iov_len = total_len;
0598 
0599         if (cfg_proto != SOCK_STREAM) {
0600             if (cfg_use_pf_packet) {
0601                 memset(&laddr, 0, sizeof(laddr));
0602 
0603                 laddr.sll_family    = AF_PACKET;
0604                 laddr.sll_ifindex   = 1;
0605                 laddr.sll_protocol  = htons(family == AF_INET ? ETH_P_IP : ETH_P_IPV6);
0606                 laddr.sll_halen     = ETH_ALEN;
0607 
0608                 msg.msg_name = (void *)&laddr;
0609                 msg.msg_namelen = sizeof(laddr);
0610             } else if (family == PF_INET) {
0611                 msg.msg_name = (void *)&daddr;
0612                 msg.msg_namelen = sizeof(daddr);
0613             } else {
0614                 msg.msg_name = (void *)&daddr6;
0615                 msg.msg_namelen = sizeof(daddr6);
0616             }
0617         }
0618 
0619         msg.msg_iov = &iov;
0620         msg.msg_iovlen = 1;
0621 
0622         if (cfg_use_cmsg) {
0623             memset(control, 0, sizeof(control));
0624 
0625             msg.msg_control = control;
0626             msg.msg_controllen = sizeof(control);
0627 
0628             cmsg = CMSG_FIRSTHDR(&msg);
0629             cmsg->cmsg_level = SOL_SOCKET;
0630             cmsg->cmsg_type = SO_TIMESTAMPING;
0631             cmsg->cmsg_len = CMSG_LEN(sizeof(uint32_t));
0632 
0633             *((uint32_t *) CMSG_DATA(cmsg)) = report_opt;
0634         }
0635 
0636         val = sendmsg(fd, &msg, 0);
0637         if (val != total_len)
0638             error(1, errno, "send");
0639 
0640         /* wait for all errors to be queued, else ACKs arrive OOO */
0641         if (cfg_sleep_usec)
0642             usleep(cfg_sleep_usec);
0643 
0644         if (!cfg_busy_poll) {
0645             if (cfg_use_epoll)
0646                 __epoll(epfd);
0647             else
0648                 __poll(fd);
0649         }
0650 
0651         while (!recv_errmsg(fd)) {}
0652     }
0653 
0654     print_timing_event("USR-ENQ", &usr_enq);
0655     print_timing_event("USR-SND", &usr_snd);
0656     print_timing_event("USR-ACK", &usr_ack);
0657 
0658     if (close(fd))
0659         error(1, errno, "close");
0660 
0661     free(buf);
0662     usleep(100 * NSEC_PER_USEC);
0663 }
0664 
0665 static void __attribute__((noreturn)) usage(const char *filepath)
0666 {
0667     fprintf(stderr, "\nUsage: %s [options] hostname\n"
0668             "\nwhere options are:\n"
0669             "  -4:   only IPv4\n"
0670             "  -6:   only IPv6\n"
0671             "  -h:   show this message\n"
0672             "  -b:   busy poll to read from error queue\n"
0673             "  -c N: number of packets for each test\n"
0674             "  -C:   use cmsg to set tstamp recording options\n"
0675             "  -e:   use level-triggered epoll() instead of poll()\n"
0676             "  -E:   use event-triggered epoll() instead of poll()\n"
0677             "  -F:   poll()/epoll() waits forever for an event\n"
0678             "  -I:   request PKTINFO\n"
0679             "  -l N: send N bytes at a time\n"
0680             "  -L    listen on hostname and port\n"
0681             "  -n:   set no-payload option\n"
0682             "  -N:   print timestamps and durations in nsec (instead of usec)\n"
0683             "  -p N: connect to port N\n"
0684             "  -P:   use PF_PACKET\n"
0685             "  -r:   use raw\n"
0686             "  -R:   use raw (IP_HDRINCL)\n"
0687             "  -S N: usec to sleep before reading error queue\n"
0688             "  -t N: tolerance (usec) for timestamp validation\n"
0689             "  -u:   use udp\n"
0690             "  -v:   validate SND delay (usec)\n"
0691             "  -V:   validate ACK delay (usec)\n"
0692             "  -x:   show payload (up to 70 bytes)\n",
0693             filepath);
0694     exit(1);
0695 }
0696 
0697 static void parse_opt(int argc, char **argv)
0698 {
0699     int proto_count = 0;
0700     int c;
0701 
0702     while ((c = getopt(argc, argv,
0703                 "46bc:CeEFhIl:LnNp:PrRS:t:uv:V:x")) != -1) {
0704         switch (c) {
0705         case '4':
0706             do_ipv6 = 0;
0707             break;
0708         case '6':
0709             do_ipv4 = 0;
0710             break;
0711         case 'b':
0712             cfg_busy_poll = true;
0713             break;
0714         case 'c':
0715             cfg_num_pkts = strtoul(optarg, NULL, 10);
0716             break;
0717         case 'C':
0718             cfg_use_cmsg = true;
0719             break;
0720         case 'e':
0721             cfg_use_epoll = true;
0722             break;
0723         case 'E':
0724             cfg_use_epoll = true;
0725             cfg_epollet = true;
0726         case 'F':
0727             cfg_poll_timeout = -1;
0728             break;
0729         case 'I':
0730             cfg_do_pktinfo = true;
0731             break;
0732         case 'l':
0733             cfg_payload_len = strtoul(optarg, NULL, 10);
0734             break;
0735         case 'L':
0736             cfg_do_listen = true;
0737             break;
0738         case 'n':
0739             cfg_loop_nodata = true;
0740             break;
0741         case 'N':
0742             cfg_print_nsec = true;
0743             break;
0744         case 'p':
0745             dest_port = strtoul(optarg, NULL, 10);
0746             break;
0747         case 'P':
0748             proto_count++;
0749             cfg_use_pf_packet = true;
0750             cfg_proto = SOCK_DGRAM;
0751             cfg_ipproto = 0;
0752             break;
0753         case 'r':
0754             proto_count++;
0755             cfg_proto = SOCK_RAW;
0756             cfg_ipproto = IPPROTO_UDP;
0757             break;
0758         case 'R':
0759             proto_count++;
0760             cfg_proto = SOCK_RAW;
0761             cfg_ipproto = IPPROTO_RAW;
0762             break;
0763         case 'S':
0764             cfg_sleep_usec = strtoul(optarg, NULL, 10);
0765             break;
0766         case 't':
0767             cfg_delay_tolerance_usec = strtoul(optarg, NULL, 10);
0768             break;
0769         case 'u':
0770             proto_count++;
0771             cfg_proto = SOCK_DGRAM;
0772             cfg_ipproto = IPPROTO_UDP;
0773             break;
0774         case 'v':
0775             cfg_delay_snd = strtoul(optarg, NULL, 10);
0776             break;
0777         case 'V':
0778             cfg_delay_ack = strtoul(optarg, NULL, 10);
0779             break;
0780         case 'x':
0781             cfg_show_payload = true;
0782             break;
0783         case 'h':
0784         default:
0785             usage(argv[0]);
0786         }
0787     }
0788 
0789     if (!cfg_payload_len)
0790         error(1, 0, "payload may not be nonzero");
0791     if (cfg_proto != SOCK_STREAM && cfg_payload_len > 1472)
0792         error(1, 0, "udp packet might exceed expected MTU");
0793     if (!do_ipv4 && !do_ipv6)
0794         error(1, 0, "pass -4 or -6, not both");
0795     if (proto_count > 1)
0796         error(1, 0, "pass -P, -r, -R or -u, not multiple");
0797     if (cfg_do_pktinfo && cfg_use_pf_packet)
0798         error(1, 0, "cannot ask for pktinfo over pf_packet");
0799     if (cfg_busy_poll && cfg_use_epoll)
0800         error(1, 0, "pass epoll or busy_poll, not both");
0801 
0802     if (optind != argc - 1)
0803         error(1, 0, "missing required hostname argument");
0804 }
0805 
0806 static void resolve_hostname(const char *hostname)
0807 {
0808     struct addrinfo hints = { .ai_family = do_ipv4 ? AF_INET : AF_INET6 };
0809     struct addrinfo *addrs, *cur;
0810     int have_ipv4 = 0, have_ipv6 = 0;
0811 
0812 retry:
0813     if (getaddrinfo(hostname, NULL, &hints, &addrs))
0814         error(1, errno, "getaddrinfo");
0815 
0816     cur = addrs;
0817     while (cur && !have_ipv4 && !have_ipv6) {
0818         if (!have_ipv4 && cur->ai_family == AF_INET) {
0819             memcpy(&daddr, cur->ai_addr, sizeof(daddr));
0820             daddr.sin_port = htons(dest_port);
0821             have_ipv4 = 1;
0822         }
0823         else if (!have_ipv6 && cur->ai_family == AF_INET6) {
0824             memcpy(&daddr6, cur->ai_addr, sizeof(daddr6));
0825             daddr6.sin6_port = htons(dest_port);
0826             have_ipv6 = 1;
0827         }
0828         cur = cur->ai_next;
0829     }
0830     if (addrs)
0831         freeaddrinfo(addrs);
0832 
0833     if (do_ipv6 && hints.ai_family != AF_INET6) {
0834         hints.ai_family = AF_INET6;
0835         goto retry;
0836     }
0837 
0838     do_ipv4 &= have_ipv4;
0839     do_ipv6 &= have_ipv6;
0840 }
0841 
0842 static void do_listen(int family, void *addr, int alen)
0843 {
0844     int fd, type;
0845 
0846     type = cfg_proto == SOCK_RAW ? SOCK_DGRAM : cfg_proto;
0847 
0848     fd = socket(family, type, 0);
0849     if (fd == -1)
0850         error(1, errno, "socket rx");
0851 
0852     if (bind(fd, addr, alen))
0853         error(1, errno, "bind rx");
0854 
0855     if (type == SOCK_STREAM && listen(fd, 10))
0856         error(1, errno, "listen rx");
0857 
0858     /* leave fd open, will be closed on process exit.
0859      * this enables connect() to succeed and avoids icmp replies
0860      */
0861 }
0862 
0863 static void do_main(int family)
0864 {
0865     fprintf(stderr, "family:       %s %s\n",
0866             family == PF_INET ? "INET" : "INET6",
0867             cfg_use_pf_packet ? "(PF_PACKET)" : "");
0868 
0869     fprintf(stderr, "test SND\n");
0870     do_test(family, SOF_TIMESTAMPING_TX_SOFTWARE);
0871 
0872     fprintf(stderr, "test ENQ\n");
0873     do_test(family, SOF_TIMESTAMPING_TX_SCHED);
0874 
0875     fprintf(stderr, "test ENQ + SND\n");
0876     do_test(family, SOF_TIMESTAMPING_TX_SCHED |
0877             SOF_TIMESTAMPING_TX_SOFTWARE);
0878 
0879     if (cfg_proto == SOCK_STREAM) {
0880         fprintf(stderr, "\ntest ACK\n");
0881         do_test(family, SOF_TIMESTAMPING_TX_ACK);
0882 
0883         fprintf(stderr, "\ntest SND + ACK\n");
0884         do_test(family, SOF_TIMESTAMPING_TX_SOFTWARE |
0885                 SOF_TIMESTAMPING_TX_ACK);
0886 
0887         fprintf(stderr, "\ntest ENQ + SND + ACK\n");
0888         do_test(family, SOF_TIMESTAMPING_TX_SCHED |
0889                 SOF_TIMESTAMPING_TX_SOFTWARE |
0890                 SOF_TIMESTAMPING_TX_ACK);
0891     }
0892 }
0893 
0894 const char *sock_names[] = { NULL, "TCP", "UDP", "RAW" };
0895 
0896 int main(int argc, char **argv)
0897 {
0898     if (argc == 1)
0899         usage(argv[0]);
0900 
0901     parse_opt(argc, argv);
0902     resolve_hostname(argv[argc - 1]);
0903 
0904     fprintf(stderr, "protocol:     %s\n", sock_names[cfg_proto]);
0905     fprintf(stderr, "payload:      %u\n", cfg_payload_len);
0906     fprintf(stderr, "server port:  %u\n", dest_port);
0907     fprintf(stderr, "\n");
0908 
0909     if (do_ipv4) {
0910         if (cfg_do_listen)
0911             do_listen(PF_INET, &daddr, sizeof(daddr));
0912         do_main(PF_INET);
0913     }
0914 
0915     if (do_ipv6) {
0916         if (cfg_do_listen)
0917             do_listen(PF_INET6, &daddr6, sizeof(daddr6));
0918         do_main(PF_INET6);
0919     }
0920 
0921     return test_failed;
0922 }