aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation/networking
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-10-14 18:17:12 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-10-14 18:17:12 -0400
commit5d89d9f502f9c33ed0270d716f238429861e1942 (patch)
tree6a353640e6836ca465f2dcf00323a7f8a793ae59 /Documentation/networking
parent50cff89837a43a7c62ac080de9742a298d6418b3 (diff)
parentfecf861e765b2f9ce1a0487c3940afaed80ef7a8 (diff)
Merge tag 'linux-kselftest-4.9-rc1-update' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest
Pull kselftest updates from Shuah Khan: "This update consists of: - Fixes and improvements to existing tests - Moving code from Documentation to selftests, samples, and tools: * Moves dnotify_test, prctl, ptp, vDSO, ia64, watchdog, and networking tests from Documentation to selftests. * Moves mic/mpssd, misc-devices/mei, timers, watchdog, auxdisplay, and blackfin examples from Documentation to samples. * Moves accounting, laptops/dslm, and pcmcia/crc32hash tools from Documentation to tools. * Deletes BUILD_DOCSRC and its dependencies" * tag 'linux-kselftest-4.9-rc1-update' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: (21 commits) selftests/futex: Check ANSI terminal color support Doc: update 00-INDEX files to reflect the runnable code move samples: move blackfin gptimers-example from Documentation tools: move pcmcia crc32hash tool from Documentation tools: move laptops dslm tool from Documentation tools: move accounting tool from Documentation samples: move auxdisplay example code from Documentation samples: move watchdog example code from Documentation samples: move timers example code from Documentation samples: move misc-devices/mei example code from Documentation samples: move mic/mpssd example code from Documentation selftests: Move networking/timestamping from Documentation selftests: move watchdog tests from Documentation/watchdog selftests: move ia64 tests from Documentation/ia64 selftests: move vDSO tests from Documentation/vDSO selftests: move ptp tests from Documentation/ptp selftests: move prctl tests from Documentation/prctl selftests: move dnotify_test from Documentation/filesystems selftests/timers: Add missing error code assignment before test selftests/zram: replace ZRAM_LZ4_COMPRESS ...
Diffstat (limited to 'Documentation/networking')
-rw-r--r--Documentation/networking/00-INDEX2
-rw-r--r--Documentation/networking/Makefile1
-rw-r--r--Documentation/networking/timestamping/.gitignore3
-rw-r--r--Documentation/networking/timestamping/Makefile14
-rw-r--r--Documentation/networking/timestamping/hwtstamp_config.c134
-rw-r--r--Documentation/networking/timestamping/timestamping.c528
-rw-r--r--Documentation/networking/timestamping/txtimestamp.c549
7 files changed, 0 insertions, 1231 deletions
diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX
index a7697783ac4c..c6beb5f1637f 100644
--- a/Documentation/networking/00-INDEX
+++ b/Documentation/networking/00-INDEX
@@ -10,8 +10,6 @@ LICENSE.qlge
10 - GPLv2 for QLogic Linux qlge NIC Driver 10 - GPLv2 for QLogic Linux qlge NIC Driver
11LICENSE.qlcnic 11LICENSE.qlcnic
12 - GPLv2 for QLogic Linux qlcnic NIC Driver 12 - GPLv2 for QLogic Linux qlcnic NIC Driver
13Makefile
14 - Makefile for docsrc.
15PLIP.txt 13PLIP.txt
16 - PLIP: The Parallel Line Internet Protocol device driver 14 - PLIP: The Parallel Line Internet Protocol device driver
17README.ipw2100 15README.ipw2100
diff --git a/Documentation/networking/Makefile b/Documentation/networking/Makefile
deleted file mode 100644
index 4c5d7c485439..000000000000
--- a/Documentation/networking/Makefile
+++ /dev/null
@@ -1 +0,0 @@
1subdir-y := timestamping
diff --git a/Documentation/networking/timestamping/.gitignore b/Documentation/networking/timestamping/.gitignore
deleted file mode 100644
index 9e69e982fb38..000000000000
--- a/Documentation/networking/timestamping/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
1timestamping
2txtimestamp
3hwtstamp_config
diff --git a/Documentation/networking/timestamping/Makefile b/Documentation/networking/timestamping/Makefile
deleted file mode 100644
index 8c20dfaa4d6e..000000000000
--- a/Documentation/networking/timestamping/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
1# To compile, from the source root
2#
3# make headers_install
4# make M=documentation
5
6# List of programs to build
7hostprogs-y := hwtstamp_config timestamping txtimestamp
8
9# Tell kbuild to always build the programs
10always := $(hostprogs-y)
11
12HOSTCFLAGS_timestamping.o += -I$(objtree)/usr/include
13HOSTCFLAGS_txtimestamp.o += -I$(objtree)/usr/include
14HOSTCFLAGS_hwtstamp_config.o += -I$(objtree)/usr/include
diff --git a/Documentation/networking/timestamping/hwtstamp_config.c b/Documentation/networking/timestamping/hwtstamp_config.c
deleted file mode 100644
index e8b685a7f15f..000000000000
--- a/Documentation/networking/timestamping/hwtstamp_config.c
+++ /dev/null
@@ -1,134 +0,0 @@
1/* Test program for SIOC{G,S}HWTSTAMP
2 * Copyright 2013 Solarflare Communications
3 * Author: Ben Hutchings
4 */
5
6#include <errno.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10
11#include <sys/socket.h>
12#include <sys/ioctl.h>
13
14#include <linux/if.h>
15#include <linux/net_tstamp.h>
16#include <linux/sockios.h>
17
18static int
19lookup_value(const char **names, int size, const char *name)
20{
21 int value;
22
23 for (value = 0; value < size; value++)
24 if (names[value] && strcasecmp(names[value], name) == 0)
25 return value;
26
27 return -1;
28}
29
30static const char *
31lookup_name(const char **names, int size, int value)
32{
33 return (value >= 0 && value < size) ? names[value] : NULL;
34}
35
36static void list_names(FILE *f, const char **names, int size)
37{
38 int value;
39
40 for (value = 0; value < size; value++)
41 if (names[value])
42 fprintf(f, " %s\n", names[value]);
43}
44
45static const char *tx_types[] = {
46#define TX_TYPE(name) [HWTSTAMP_TX_ ## name] = #name
47 TX_TYPE(OFF),
48 TX_TYPE(ON),
49 TX_TYPE(ONESTEP_SYNC)
50#undef TX_TYPE
51};
52#define N_TX_TYPES ((int)(sizeof(tx_types) / sizeof(tx_types[0])))
53
54static const char *rx_filters[] = {
55#define RX_FILTER(name) [HWTSTAMP_FILTER_ ## name] = #name
56 RX_FILTER(NONE),
57 RX_FILTER(ALL),
58 RX_FILTER(SOME),
59 RX_FILTER(PTP_V1_L4_EVENT),
60 RX_FILTER(PTP_V1_L4_SYNC),
61 RX_FILTER(PTP_V1_L4_DELAY_REQ),
62 RX_FILTER(PTP_V2_L4_EVENT),
63 RX_FILTER(PTP_V2_L4_SYNC),
64 RX_FILTER(PTP_V2_L4_DELAY_REQ),
65 RX_FILTER(PTP_V2_L2_EVENT),
66 RX_FILTER(PTP_V2_L2_SYNC),
67 RX_FILTER(PTP_V2_L2_DELAY_REQ),
68 RX_FILTER(PTP_V2_EVENT),
69 RX_FILTER(PTP_V2_SYNC),
70 RX_FILTER(PTP_V2_DELAY_REQ),
71#undef RX_FILTER
72};
73#define N_RX_FILTERS ((int)(sizeof(rx_filters) / sizeof(rx_filters[0])))
74
75static void usage(void)
76{
77 fputs("Usage: hwtstamp_config if_name [tx_type rx_filter]\n"
78 "tx_type is any of (case-insensitive):\n",
79 stderr);
80 list_names(stderr, tx_types, N_TX_TYPES);
81 fputs("rx_filter is any of (case-insensitive):\n", stderr);
82 list_names(stderr, rx_filters, N_RX_FILTERS);
83}
84
85int main(int argc, char **argv)
86{
87 struct ifreq ifr;
88 struct hwtstamp_config config;
89 const char *name;
90 int sock;
91
92 if ((argc != 2 && argc != 4) || (strlen(argv[1]) >= IFNAMSIZ)) {
93 usage();
94 return 2;
95 }
96
97 if (argc == 4) {
98 config.flags = 0;
99 config.tx_type = lookup_value(tx_types, N_TX_TYPES, argv[2]);
100 config.rx_filter = lookup_value(rx_filters, N_RX_FILTERS, argv[3]);
101 if (config.tx_type < 0 || config.rx_filter < 0) {
102 usage();
103 return 2;
104 }
105 }
106
107 sock = socket(AF_INET, SOCK_DGRAM, 0);
108 if (sock < 0) {
109 perror("socket");
110 return 1;
111 }
112
113 strcpy(ifr.ifr_name, argv[1]);
114 ifr.ifr_data = (caddr_t)&config;
115
116 if (ioctl(sock, (argc == 2) ? SIOCGHWTSTAMP : SIOCSHWTSTAMP, &ifr)) {
117 perror("ioctl");
118 return 1;
119 }
120
121 printf("flags = %#x\n", config.flags);
122 name = lookup_name(tx_types, N_TX_TYPES, config.tx_type);
123 if (name)
124 printf("tx_type = %s\n", name);
125 else
126 printf("tx_type = %d\n", config.tx_type);
127 name = lookup_name(rx_filters, N_RX_FILTERS, config.rx_filter);
128 if (name)
129 printf("rx_filter = %s\n", name);
130 else
131 printf("rx_filter = %d\n", config.rx_filter);
132
133 return 0;
134}
diff --git a/Documentation/networking/timestamping/timestamping.c b/Documentation/networking/timestamping/timestamping.c
deleted file mode 100644
index 5cdfd743447b..000000000000
--- a/Documentation/networking/timestamping/timestamping.c
+++ /dev/null
@@ -1,528 +0,0 @@
1/*
2 * This program demonstrates how the various time stamping features in
3 * the Linux kernel work. It emulates the behavior of a PTP
4 * implementation in stand-alone master mode by sending PTPv1 Sync
5 * multicasts once every second. It looks for similar packets, but
6 * beyond that doesn't actually implement PTP.
7 *
8 * Outgoing packets are time stamped with SO_TIMESTAMPING with or
9 * without hardware support.
10 *
11 * Incoming packets are time stamped with SO_TIMESTAMPING with or
12 * without hardware support, SIOCGSTAMP[NS] (per-socket time stamp) and
13 * SO_TIMESTAMP[NS].
14 *
15 * Copyright (C) 2009 Intel Corporation.
16 * Author: Patrick Ohly <patrick.ohly@intel.com>
17 *
18 * This program is free software; you can redistribute it and/or modify it
19 * under the terms and conditions of the GNU General Public License,
20 * version 2, as published by the Free Software Foundation.
21 *
22 * This program is distributed in the hope it will be useful, but WITHOUT
23 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
24 * FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for
25 * more details.
26 *
27 * You should have received a copy of the GNU General Public License along with
28 * this program; if not, write to the Free Software Foundation, Inc.,
29 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
30 */
31
32#include <stdio.h>
33#include <stdlib.h>
34#include <errno.h>
35#include <string.h>
36
37#include <sys/time.h>
38#include <sys/socket.h>
39#include <sys/select.h>
40#include <sys/ioctl.h>
41#include <arpa/inet.h>
42#include <net/if.h>
43
44#include <asm/types.h>
45#include <linux/net_tstamp.h>
46#include <linux/errqueue.h>
47
48#ifndef SO_TIMESTAMPING
49# define SO_TIMESTAMPING 37
50# define SCM_TIMESTAMPING SO_TIMESTAMPING
51#endif
52
53#ifndef SO_TIMESTAMPNS
54# define SO_TIMESTAMPNS 35
55#endif
56
57#ifndef SIOCGSTAMPNS
58# define SIOCGSTAMPNS 0x8907
59#endif
60
61#ifndef SIOCSHWTSTAMP
62# define SIOCSHWTSTAMP 0x89b0
63#endif
64
65static void usage(const char *error)
66{
67 if (error)
68 printf("invalid option: %s\n", error);
69 printf("timestamping interface option*\n\n"
70 "Options:\n"
71 " IP_MULTICAST_LOOP - looping outgoing multicasts\n"
72 " SO_TIMESTAMP - normal software time stamping, ms resolution\n"
73 " SO_TIMESTAMPNS - more accurate software time stamping\n"
74 " SOF_TIMESTAMPING_TX_HARDWARE - hardware time stamping of outgoing packets\n"
75 " SOF_TIMESTAMPING_TX_SOFTWARE - software fallback for outgoing packets\n"
76 " SOF_TIMESTAMPING_RX_HARDWARE - hardware time stamping of incoming packets\n"
77 " SOF_TIMESTAMPING_RX_SOFTWARE - software fallback for incoming packets\n"
78 " SOF_TIMESTAMPING_SOFTWARE - request reporting of software time stamps\n"
79 " SOF_TIMESTAMPING_RAW_HARDWARE - request reporting of raw HW time stamps\n"
80 " SIOCGSTAMP - check last socket time stamp\n"
81 " SIOCGSTAMPNS - more accurate socket time stamp\n");
82 exit(1);
83}
84
85static void bail(const char *error)
86{
87 printf("%s: %s\n", error, strerror(errno));
88 exit(1);
89}
90
91static const unsigned char sync[] = {
92 0x00, 0x01, 0x00, 0x01,
93 0x5f, 0x44, 0x46, 0x4c,
94 0x54, 0x00, 0x00, 0x00,
95 0x00, 0x00, 0x00, 0x00,
96 0x00, 0x00, 0x00, 0x00,
97 0x01, 0x01,
98
99 /* fake uuid */
100 0x00, 0x01,
101 0x02, 0x03, 0x04, 0x05,
102
103 0x00, 0x01, 0x00, 0x37,
104 0x00, 0x00, 0x00, 0x08,
105 0x00, 0x00, 0x00, 0x00,
106 0x49, 0x05, 0xcd, 0x01,
107 0x29, 0xb1, 0x8d, 0xb0,
108 0x00, 0x00, 0x00, 0x00,
109 0x00, 0x01,
110
111 /* fake uuid */
112 0x00, 0x01,
113 0x02, 0x03, 0x04, 0x05,
114
115 0x00, 0x00, 0x00, 0x37,
116 0x00, 0x00, 0x00, 0x04,
117 0x44, 0x46, 0x4c, 0x54,
118 0x00, 0x00, 0xf0, 0x60,
119 0x00, 0x01, 0x00, 0x00,
120 0x00, 0x00, 0x00, 0x01,
121 0x00, 0x00, 0xf0, 0x60,
122 0x00, 0x00, 0x00, 0x00,
123 0x00, 0x00, 0x00, 0x04,
124 0x44, 0x46, 0x4c, 0x54,
125 0x00, 0x01,
126
127 /* fake uuid */
128 0x00, 0x01,
129 0x02, 0x03, 0x04, 0x05,
130
131 0x00, 0x00, 0x00, 0x00,
132 0x00, 0x00, 0x00, 0x00,
133 0x00, 0x00, 0x00, 0x00,
134 0x00, 0x00, 0x00, 0x00
135};
136
137static void sendpacket(int sock, struct sockaddr *addr, socklen_t addr_len)
138{
139 struct timeval now;
140 int res;
141
142 res = sendto(sock, sync, sizeof(sync), 0,
143 addr, addr_len);
144 gettimeofday(&now, 0);
145 if (res < 0)
146 printf("%s: %s\n", "send", strerror(errno));
147 else
148 printf("%ld.%06ld: sent %d bytes\n",
149 (long)now.tv_sec, (long)now.tv_usec,
150 res);
151}
152
153static void printpacket(struct msghdr *msg, int res,
154 char *data,
155 int sock, int recvmsg_flags,
156 int siocgstamp, int siocgstampns)
157{
158 struct sockaddr_in *from_addr = (struct sockaddr_in *)msg->msg_name;
159 struct cmsghdr *cmsg;
160 struct timeval tv;
161 struct timespec ts;
162 struct timeval now;
163
164 gettimeofday(&now, 0);
165
166 printf("%ld.%06ld: received %s data, %d bytes from %s, %zu bytes control messages\n",
167 (long)now.tv_sec, (long)now.tv_usec,
168 (recvmsg_flags & MSG_ERRQUEUE) ? "error" : "regular",
169 res,
170 inet_ntoa(from_addr->sin_addr),
171 msg->msg_controllen);
172 for (cmsg = CMSG_FIRSTHDR(msg);
173 cmsg;
174 cmsg = CMSG_NXTHDR(msg, cmsg)) {
175 printf(" cmsg len %zu: ", cmsg->cmsg_len);
176 switch (cmsg->cmsg_level) {
177 case SOL_SOCKET:
178 printf("SOL_SOCKET ");
179 switch (cmsg->cmsg_type) {
180 case SO_TIMESTAMP: {
181 struct timeval *stamp =
182 (struct timeval *)CMSG_DATA(cmsg);
183 printf("SO_TIMESTAMP %ld.%06ld",
184 (long)stamp->tv_sec,
185 (long)stamp->tv_usec);
186 break;
187 }
188 case SO_TIMESTAMPNS: {
189 struct timespec *stamp =
190 (struct timespec *)CMSG_DATA(cmsg);
191 printf("SO_TIMESTAMPNS %ld.%09ld",
192 (long)stamp->tv_sec,
193 (long)stamp->tv_nsec);
194 break;
195 }
196 case SO_TIMESTAMPING: {
197 struct timespec *stamp =
198 (struct timespec *)CMSG_DATA(cmsg);
199 printf("SO_TIMESTAMPING ");
200 printf("SW %ld.%09ld ",
201 (long)stamp->tv_sec,
202 (long)stamp->tv_nsec);
203 stamp++;
204 /* skip deprecated HW transformed */
205 stamp++;
206 printf("HW raw %ld.%09ld",
207 (long)stamp->tv_sec,
208 (long)stamp->tv_nsec);
209 break;
210 }
211 default:
212 printf("type %d", cmsg->cmsg_type);
213 break;
214 }
215 break;
216 case IPPROTO_IP:
217 printf("IPPROTO_IP ");
218 switch (cmsg->cmsg_type) {
219 case IP_RECVERR: {
220 struct sock_extended_err *err =
221 (struct sock_extended_err *)CMSG_DATA(cmsg);
222 printf("IP_RECVERR ee_errno '%s' ee_origin %d => %s",
223 strerror(err->ee_errno),
224 err->ee_origin,
225#ifdef SO_EE_ORIGIN_TIMESTAMPING
226 err->ee_origin == SO_EE_ORIGIN_TIMESTAMPING ?
227 "bounced packet" : "unexpected origin"
228#else
229 "probably SO_EE_ORIGIN_TIMESTAMPING"
230#endif
231 );
232 if (res < sizeof(sync))
233 printf(" => truncated data?!");
234 else if (!memcmp(sync, data + res - sizeof(sync),
235 sizeof(sync)))
236 printf(" => GOT OUR DATA BACK (HURRAY!)");
237 break;
238 }
239 case IP_PKTINFO: {
240 struct in_pktinfo *pktinfo =
241 (struct in_pktinfo *)CMSG_DATA(cmsg);
242 printf("IP_PKTINFO interface index %u",
243 pktinfo->ipi_ifindex);
244 break;
245 }
246 default:
247 printf("type %d", cmsg->cmsg_type);
248 break;
249 }
250 break;
251 default:
252 printf("level %d type %d",
253 cmsg->cmsg_level,
254 cmsg->cmsg_type);
255 break;
256 }
257 printf("\n");
258 }
259
260 if (siocgstamp) {
261 if (ioctl(sock, SIOCGSTAMP, &tv))
262 printf(" %s: %s\n", "SIOCGSTAMP", strerror(errno));
263 else
264 printf("SIOCGSTAMP %ld.%06ld\n",
265 (long)tv.tv_sec,
266 (long)tv.tv_usec);
267 }
268 if (siocgstampns) {
269 if (ioctl(sock, SIOCGSTAMPNS, &ts))
270 printf(" %s: %s\n", "SIOCGSTAMPNS", strerror(errno));
271 else
272 printf("SIOCGSTAMPNS %ld.%09ld\n",
273 (long)ts.tv_sec,
274 (long)ts.tv_nsec);
275 }
276}
277
278static void recvpacket(int sock, int recvmsg_flags,
279 int siocgstamp, int siocgstampns)
280{
281 char data[256];
282 struct msghdr msg;
283 struct iovec entry;
284 struct sockaddr_in from_addr;
285 struct {
286 struct cmsghdr cm;
287 char control[512];
288 } control;
289 int res;
290
291 memset(&msg, 0, sizeof(msg));
292 msg.msg_iov = &entry;
293 msg.msg_iovlen = 1;
294 entry.iov_base = data;
295 entry.iov_len = sizeof(data);
296 msg.msg_name = (caddr_t)&from_addr;
297 msg.msg_namelen = sizeof(from_addr);
298 msg.msg_control = &control;
299 msg.msg_controllen = sizeof(control);
300
301 res = recvmsg(sock, &msg, recvmsg_flags|MSG_DONTWAIT);
302 if (res < 0) {
303 printf("%s %s: %s\n",
304 "recvmsg",
305 (recvmsg_flags & MSG_ERRQUEUE) ? "error" : "regular",
306 strerror(errno));
307 } else {
308 printpacket(&msg, res, data,
309 sock, recvmsg_flags,
310 siocgstamp, siocgstampns);
311 }
312}
313
314int main(int argc, char **argv)
315{
316 int so_timestamping_flags = 0;
317 int so_timestamp = 0;
318 int so_timestampns = 0;
319 int siocgstamp = 0;
320 int siocgstampns = 0;
321 int ip_multicast_loop = 0;
322 char *interface;
323 int i;
324 int enabled = 1;
325 int sock;
326 struct ifreq device;
327 struct ifreq hwtstamp;
328 struct hwtstamp_config hwconfig, hwconfig_requested;
329 struct sockaddr_in addr;
330 struct ip_mreq imr;
331 struct in_addr iaddr;
332 int val;
333 socklen_t len;
334 struct timeval next;
335
336 if (argc < 2)
337 usage(0);
338 interface = argv[1];
339
340 for (i = 2; i < argc; i++) {
341 if (!strcasecmp(argv[i], "SO_TIMESTAMP"))
342 so_timestamp = 1;
343 else if (!strcasecmp(argv[i], "SO_TIMESTAMPNS"))
344 so_timestampns = 1;
345 else if (!strcasecmp(argv[i], "SIOCGSTAMP"))
346 siocgstamp = 1;
347 else if (!strcasecmp(argv[i], "SIOCGSTAMPNS"))
348 siocgstampns = 1;
349 else if (!strcasecmp(argv[i], "IP_MULTICAST_LOOP"))
350 ip_multicast_loop = 1;
351 else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_TX_HARDWARE"))
352 so_timestamping_flags |= SOF_TIMESTAMPING_TX_HARDWARE;
353 else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_TX_SOFTWARE"))
354 so_timestamping_flags |= SOF_TIMESTAMPING_TX_SOFTWARE;
355 else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RX_HARDWARE"))
356 so_timestamping_flags |= SOF_TIMESTAMPING_RX_HARDWARE;
357 else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RX_SOFTWARE"))
358 so_timestamping_flags |= SOF_TIMESTAMPING_RX_SOFTWARE;
359 else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_SOFTWARE"))
360 so_timestamping_flags |= SOF_TIMESTAMPING_SOFTWARE;
361 else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RAW_HARDWARE"))
362 so_timestamping_flags |= SOF_TIMESTAMPING_RAW_HARDWARE;
363 else
364 usage(argv[i]);
365 }
366
367 sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
368 if (sock < 0)
369 bail("socket");
370
371 memset(&device, 0, sizeof(device));
372 strncpy(device.ifr_name, interface, sizeof(device.ifr_name));
373 if (ioctl(sock, SIOCGIFADDR, &device) < 0)
374 bail("getting interface IP address");
375
376 memset(&hwtstamp, 0, sizeof(hwtstamp));
377 strncpy(hwtstamp.ifr_name, interface, sizeof(hwtstamp.ifr_name));
378 hwtstamp.ifr_data = (void *)&hwconfig;
379 memset(&hwconfig, 0, sizeof(hwconfig));
380 hwconfig.tx_type =
381 (so_timestamping_flags & SOF_TIMESTAMPING_TX_HARDWARE) ?
382 HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
383 hwconfig.rx_filter =
384 (so_timestamping_flags & SOF_TIMESTAMPING_RX_HARDWARE) ?
385 HWTSTAMP_FILTER_PTP_V1_L4_SYNC : HWTSTAMP_FILTER_NONE;
386 hwconfig_requested = hwconfig;
387 if (ioctl(sock, SIOCSHWTSTAMP, &hwtstamp) < 0) {
388 if ((errno == EINVAL || errno == ENOTSUP) &&
389 hwconfig_requested.tx_type == HWTSTAMP_TX_OFF &&
390 hwconfig_requested.rx_filter == HWTSTAMP_FILTER_NONE)
391 printf("SIOCSHWTSTAMP: disabling hardware time stamping not possible\n");
392 else
393 bail("SIOCSHWTSTAMP");
394 }
395 printf("SIOCSHWTSTAMP: tx_type %d requested, got %d; rx_filter %d requested, got %d\n",
396 hwconfig_requested.tx_type, hwconfig.tx_type,
397 hwconfig_requested.rx_filter, hwconfig.rx_filter);
398
399 /* bind to PTP port */
400 addr.sin_family = AF_INET;
401 addr.sin_addr.s_addr = htonl(INADDR_ANY);
402 addr.sin_port = htons(319 /* PTP event port */);
403 if (bind(sock,
404 (struct sockaddr *)&addr,
405 sizeof(struct sockaddr_in)) < 0)
406 bail("bind");
407
408 /* set multicast group for outgoing packets */
409 inet_aton("224.0.1.130", &iaddr); /* alternate PTP domain 1 */
410 addr.sin_addr = iaddr;
411 imr.imr_multiaddr.s_addr = iaddr.s_addr;
412 imr.imr_interface.s_addr =
413 ((struct sockaddr_in *)&device.ifr_addr)->sin_addr.s_addr;
414 if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
415 &imr.imr_interface.s_addr, sizeof(struct in_addr)) < 0)
416 bail("set multicast");
417
418 /* join multicast group, loop our own packet */
419 if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
420 &imr, sizeof(struct ip_mreq)) < 0)
421 bail("join multicast group");
422
423 if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP,
424 &ip_multicast_loop, sizeof(enabled)) < 0) {
425 bail("loop multicast");
426 }
427
428 /* set socket options for time stamping */
429 if (so_timestamp &&
430 setsockopt(sock, SOL_SOCKET, SO_TIMESTAMP,
431 &enabled, sizeof(enabled)) < 0)
432 bail("setsockopt SO_TIMESTAMP");
433
434 if (so_timestampns &&
435 setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPNS,
436 &enabled, sizeof(enabled)) < 0)
437 bail("setsockopt SO_TIMESTAMPNS");
438
439 if (so_timestamping_flags &&
440 setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING,
441 &so_timestamping_flags,
442 sizeof(so_timestamping_flags)) < 0)
443 bail("setsockopt SO_TIMESTAMPING");
444
445 /* request IP_PKTINFO for debugging purposes */
446 if (setsockopt(sock, SOL_IP, IP_PKTINFO,
447 &enabled, sizeof(enabled)) < 0)
448 printf("%s: %s\n", "setsockopt IP_PKTINFO", strerror(errno));
449
450 /* verify socket options */
451 len = sizeof(val);
452 if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMP, &val, &len) < 0)
453 printf("%s: %s\n", "getsockopt SO_TIMESTAMP", strerror(errno));
454 else
455 printf("SO_TIMESTAMP %d\n", val);
456
457 if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMPNS, &val, &len) < 0)
458 printf("%s: %s\n", "getsockopt SO_TIMESTAMPNS",
459 strerror(errno));
460 else
461 printf("SO_TIMESTAMPNS %d\n", val);
462
463 if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING, &val, &len) < 0) {
464 printf("%s: %s\n", "getsockopt SO_TIMESTAMPING",
465 strerror(errno));
466 } else {
467 printf("SO_TIMESTAMPING %d\n", val);
468 if (val != so_timestamping_flags)
469 printf(" not the expected value %d\n",
470 so_timestamping_flags);
471 }
472
473 /* send packets forever every five seconds */
474 gettimeofday(&next, 0);
475 next.tv_sec = (next.tv_sec + 1) / 5 * 5;
476 next.tv_usec = 0;
477 while (1) {
478 struct timeval now;
479 struct timeval delta;
480 long delta_us;
481 int res;
482 fd_set readfs, errorfs;
483
484 gettimeofday(&now, 0);
485 delta_us = (long)(next.tv_sec - now.tv_sec) * 1000000 +
486 (long)(next.tv_usec - now.tv_usec);
487 if (delta_us > 0) {
488 /* continue waiting for timeout or data */
489 delta.tv_sec = delta_us / 1000000;
490 delta.tv_usec = delta_us % 1000000;
491
492 FD_ZERO(&readfs);
493 FD_ZERO(&errorfs);
494 FD_SET(sock, &readfs);
495 FD_SET(sock, &errorfs);
496 printf("%ld.%06ld: select %ldus\n",
497 (long)now.tv_sec, (long)now.tv_usec,
498 delta_us);
499 res = select(sock + 1, &readfs, 0, &errorfs, &delta);
500 gettimeofday(&now, 0);
501 printf("%ld.%06ld: select returned: %d, %s\n",
502 (long)now.tv_sec, (long)now.tv_usec,
503 res,
504 res < 0 ? strerror(errno) : "success");
505 if (res > 0) {
506 if (FD_ISSET(sock, &readfs))
507 printf("ready for reading\n");
508 if (FD_ISSET(sock, &errorfs))
509 printf("has error\n");
510 recvpacket(sock, 0,
511 siocgstamp,
512 siocgstampns);
513 recvpacket(sock, MSG_ERRQUEUE,
514 siocgstamp,
515 siocgstampns);
516 }
517 } else {
518 /* write one packet */
519 sendpacket(sock,
520 (struct sockaddr *)&addr,
521 sizeof(addr));
522 next.tv_sec += 5;
523 continue;
524 }
525 }
526
527 return 0;
528}
diff --git a/Documentation/networking/timestamping/txtimestamp.c b/Documentation/networking/timestamping/txtimestamp.c
deleted file mode 100644
index 5df07047ca86..000000000000
--- a/Documentation/networking/timestamping/txtimestamp.c
+++ /dev/null
@@ -1,549 +0,0 @@
1/*
2 * Copyright 2014 Google Inc.
3 * Author: willemb@google.com (Willem de Bruijn)
4 *
5 * Test software tx timestamping, including
6 *
7 * - SCHED, SND and ACK timestamps
8 * - RAW, UDP and TCP
9 * - IPv4 and IPv6
10 * - various packet sizes (to test GSO and TSO)
11 *
12 * Consult the command line arguments for help on running
13 * the various testcases.
14 *
15 * This test requires a dummy TCP server.
16 * A simple `nc6 [-u] -l -p $DESTPORT` will do
17 *
18 *
19 * This program is free software; you can redistribute it and/or modify it
20 * under the terms and conditions of the GNU General Public License,
21 * version 2, as published by the Free Software Foundation.
22 *
23 * This program is distributed in the hope it will be useful, but WITHOUT
24 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
25 * FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for
26 * more details.
27 *
28 * You should have received a copy of the GNU General Public License along with
29 * this program; if not, write to the Free Software Foundation, Inc.,
30 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
31 */
32
33#define _GNU_SOURCE
34
35#include <arpa/inet.h>
36#include <asm/types.h>
37#include <error.h>
38#include <errno.h>
39#include <inttypes.h>
40#include <linux/errqueue.h>
41#include <linux/if_ether.h>
42#include <linux/net_tstamp.h>
43#include <netdb.h>
44#include <net/if.h>
45#include <netinet/in.h>
46#include <netinet/ip.h>
47#include <netinet/udp.h>
48#include <netinet/tcp.h>
49#include <netpacket/packet.h>
50#include <poll.h>
51#include <stdarg.h>
52#include <stdbool.h>
53#include <stdio.h>
54#include <stdlib.h>
55#include <string.h>
56#include <sys/ioctl.h>
57#include <sys/select.h>
58#include <sys/socket.h>
59#include <sys/time.h>
60#include <sys/types.h>
61#include <time.h>
62#include <unistd.h>
63
64/* command line parameters */
65static int cfg_proto = SOCK_STREAM;
66static int cfg_ipproto = IPPROTO_TCP;
67static int cfg_num_pkts = 4;
68static int do_ipv4 = 1;
69static int do_ipv6 = 1;
70static int cfg_payload_len = 10;
71static bool cfg_show_payload;
72static bool cfg_do_pktinfo;
73static bool cfg_loop_nodata;
74static uint16_t dest_port = 9000;
75
76static struct sockaddr_in daddr;
77static struct sockaddr_in6 daddr6;
78static struct timespec ts_prev;
79
80static void __print_timestamp(const char *name, struct timespec *cur,
81 uint32_t key, int payload_len)
82{
83 if (!(cur->tv_sec | cur->tv_nsec))
84 return;
85
86 fprintf(stderr, " %s: %lu s %lu us (seq=%u, len=%u)",
87 name, cur->tv_sec, cur->tv_nsec / 1000,
88 key, payload_len);
89
90 if ((ts_prev.tv_sec | ts_prev.tv_nsec)) {
91 int64_t cur_ms, prev_ms;
92
93 cur_ms = (long) cur->tv_sec * 1000 * 1000;
94 cur_ms += cur->tv_nsec / 1000;
95
96 prev_ms = (long) ts_prev.tv_sec * 1000 * 1000;
97 prev_ms += ts_prev.tv_nsec / 1000;
98
99 fprintf(stderr, " (%+" PRId64 " us)", cur_ms - prev_ms);
100 }
101
102 ts_prev = *cur;
103 fprintf(stderr, "\n");
104}
105
106static void print_timestamp_usr(void)
107{
108 struct timespec ts;
109 struct timeval tv; /* avoid dependency on -lrt */
110
111 gettimeofday(&tv, NULL);
112 ts.tv_sec = tv.tv_sec;
113 ts.tv_nsec = tv.tv_usec * 1000;
114
115 __print_timestamp(" USR", &ts, 0, 0);
116}
117
118static void print_timestamp(struct scm_timestamping *tss, int tstype,
119 int tskey, int payload_len)
120{
121 const char *tsname;
122
123 switch (tstype) {
124 case SCM_TSTAMP_SCHED:
125 tsname = " ENQ";
126 break;
127 case SCM_TSTAMP_SND:
128 tsname = " SND";
129 break;
130 case SCM_TSTAMP_ACK:
131 tsname = " ACK";
132 break;
133 default:
134 error(1, 0, "unknown timestamp type: %u",
135 tstype);
136 }
137 __print_timestamp(tsname, &tss->ts[0], tskey, payload_len);
138}
139
140/* TODO: convert to check_and_print payload once API is stable */
141static void print_payload(char *data, int len)
142{
143 int i;
144
145 if (!len)
146 return;
147
148 if (len > 70)
149 len = 70;
150
151 fprintf(stderr, "payload: ");
152 for (i = 0; i < len; i++)
153 fprintf(stderr, "%02hhx ", data[i]);
154 fprintf(stderr, "\n");
155}
156
157static void print_pktinfo(int family, int ifindex, void *saddr, void *daddr)
158{
159 char sa[INET6_ADDRSTRLEN], da[INET6_ADDRSTRLEN];
160
161 fprintf(stderr, " pktinfo: ifindex=%u src=%s dst=%s\n",
162 ifindex,
163 saddr ? inet_ntop(family, saddr, sa, sizeof(sa)) : "unknown",
164 daddr ? inet_ntop(family, daddr, da, sizeof(da)) : "unknown");
165}
166
167static void __poll(int fd)
168{
169 struct pollfd pollfd;
170 int ret;
171
172 memset(&pollfd, 0, sizeof(pollfd));
173 pollfd.fd = fd;
174 ret = poll(&pollfd, 1, 100);
175 if (ret != 1)
176 error(1, errno, "poll");
177}
178
179static void __recv_errmsg_cmsg(struct msghdr *msg, int payload_len)
180{
181 struct sock_extended_err *serr = NULL;
182 struct scm_timestamping *tss = NULL;
183 struct cmsghdr *cm;
184 int batch = 0;
185
186 for (cm = CMSG_FIRSTHDR(msg);
187 cm && cm->cmsg_len;
188 cm = CMSG_NXTHDR(msg, cm)) {
189 if (cm->cmsg_level == SOL_SOCKET &&
190 cm->cmsg_type == SCM_TIMESTAMPING) {
191 tss = (void *) CMSG_DATA(cm);
192 } else if ((cm->cmsg_level == SOL_IP &&
193 cm->cmsg_type == IP_RECVERR) ||
194 (cm->cmsg_level == SOL_IPV6 &&
195 cm->cmsg_type == IPV6_RECVERR)) {
196 serr = (void *) CMSG_DATA(cm);
197 if (serr->ee_errno != ENOMSG ||
198 serr->ee_origin != SO_EE_ORIGIN_TIMESTAMPING) {
199 fprintf(stderr, "unknown ip error %d %d\n",
200 serr->ee_errno,
201 serr->ee_origin);
202 serr = NULL;
203 }
204 } else if (cm->cmsg_level == SOL_IP &&
205 cm->cmsg_type == IP_PKTINFO) {
206 struct in_pktinfo *info = (void *) CMSG_DATA(cm);
207 print_pktinfo(AF_INET, info->ipi_ifindex,
208 &info->ipi_spec_dst, &info->ipi_addr);
209 } else if (cm->cmsg_level == SOL_IPV6 &&
210 cm->cmsg_type == IPV6_PKTINFO) {
211 struct in6_pktinfo *info6 = (void *) CMSG_DATA(cm);
212 print_pktinfo(AF_INET6, info6->ipi6_ifindex,
213 NULL, &info6->ipi6_addr);
214 } else
215 fprintf(stderr, "unknown cmsg %d,%d\n",
216 cm->cmsg_level, cm->cmsg_type);
217
218 if (serr && tss) {
219 print_timestamp(tss, serr->ee_info, serr->ee_data,
220 payload_len);
221 serr = NULL;
222 tss = NULL;
223 batch++;
224 }
225 }
226
227 if (batch > 1)
228 fprintf(stderr, "batched %d timestamps\n", batch);
229}
230
231static int recv_errmsg(int fd)
232{
233 static char ctrl[1024 /* overprovision*/];
234 static struct msghdr msg;
235 struct iovec entry;
236 static char *data;
237 int ret = 0;
238
239 data = malloc(cfg_payload_len);
240 if (!data)
241 error(1, 0, "malloc");
242
243 memset(&msg, 0, sizeof(msg));
244 memset(&entry, 0, sizeof(entry));
245 memset(ctrl, 0, sizeof(ctrl));
246
247 entry.iov_base = data;
248 entry.iov_len = cfg_payload_len;
249 msg.msg_iov = &entry;
250 msg.msg_iovlen = 1;
251 msg.msg_name = NULL;
252 msg.msg_namelen = 0;
253 msg.msg_control = ctrl;
254 msg.msg_controllen = sizeof(ctrl);
255
256 ret = recvmsg(fd, &msg, MSG_ERRQUEUE);
257 if (ret == -1 && errno != EAGAIN)
258 error(1, errno, "recvmsg");
259
260 if (ret >= 0) {
261 __recv_errmsg_cmsg(&msg, ret);
262 if (cfg_show_payload)
263 print_payload(data, cfg_payload_len);
264 }
265
266 free(data);
267 return ret == -1;
268}
269
270static void do_test(int family, unsigned int opt)
271{
272 char *buf;
273 int fd, i, val = 1, total_len;
274
275 if (family == AF_INET6 && cfg_proto != SOCK_STREAM) {
276 /* due to lack of checksum generation code */
277 fprintf(stderr, "test: skipping datagram over IPv6\n");
278 return;
279 }
280
281 total_len = cfg_payload_len;
282 if (cfg_proto == SOCK_RAW) {
283 total_len += sizeof(struct udphdr);
284 if (cfg_ipproto == IPPROTO_RAW)
285 total_len += sizeof(struct iphdr);
286 }
287
288 buf = malloc(total_len);
289 if (!buf)
290 error(1, 0, "malloc");
291
292 fd = socket(family, cfg_proto, cfg_ipproto);
293 if (fd < 0)
294 error(1, errno, "socket");
295
296 if (cfg_proto == SOCK_STREAM) {
297 if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
298 (char*) &val, sizeof(val)))
299 error(1, 0, "setsockopt no nagle");
300
301 if (family == PF_INET) {
302 if (connect(fd, (void *) &daddr, sizeof(daddr)))
303 error(1, errno, "connect ipv4");
304 } else {
305 if (connect(fd, (void *) &daddr6, sizeof(daddr6)))
306 error(1, errno, "connect ipv6");
307 }
308 }
309
310 if (cfg_do_pktinfo) {
311 if (family == AF_INET6) {
312 if (setsockopt(fd, SOL_IPV6, IPV6_RECVPKTINFO,
313 &val, sizeof(val)))
314 error(1, errno, "setsockopt pktinfo ipv6");
315 } else {
316 if (setsockopt(fd, SOL_IP, IP_PKTINFO,
317 &val, sizeof(val)))
318 error(1, errno, "setsockopt pktinfo ipv4");
319 }
320 }
321
322 opt |= SOF_TIMESTAMPING_SOFTWARE |
323 SOF_TIMESTAMPING_OPT_CMSG |
324 SOF_TIMESTAMPING_OPT_ID;
325 if (cfg_loop_nodata)
326 opt |= SOF_TIMESTAMPING_OPT_TSONLY;
327
328 if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING,
329 (char *) &opt, sizeof(opt)))
330 error(1, 0, "setsockopt timestamping");
331
332 for (i = 0; i < cfg_num_pkts; i++) {
333 memset(&ts_prev, 0, sizeof(ts_prev));
334 memset(buf, 'a' + i, total_len);
335
336 if (cfg_proto == SOCK_RAW) {
337 struct udphdr *udph;
338 int off = 0;
339
340 if (cfg_ipproto == IPPROTO_RAW) {
341 struct iphdr *iph = (void *) buf;
342
343 memset(iph, 0, sizeof(*iph));
344 iph->ihl = 5;
345 iph->version = 4;
346 iph->ttl = 2;
347 iph->daddr = daddr.sin_addr.s_addr;
348 iph->protocol = IPPROTO_UDP;
349 /* kernel writes saddr, csum, len */
350
351 off = sizeof(*iph);
352 }
353
354 udph = (void *) buf + off;
355 udph->source = ntohs(9000); /* random spoof */
356 udph->dest = ntohs(dest_port);
357 udph->len = ntohs(sizeof(*udph) + cfg_payload_len);
358 udph->check = 0; /* not allowed for IPv6 */
359 }
360
361 print_timestamp_usr();
362 if (cfg_proto != SOCK_STREAM) {
363 if (family == PF_INET)
364 val = sendto(fd, buf, total_len, 0, (void *) &daddr, sizeof(daddr));
365 else
366 val = sendto(fd, buf, total_len, 0, (void *) &daddr6, sizeof(daddr6));
367 } else {
368 val = send(fd, buf, cfg_payload_len, 0);
369 }
370 if (val != total_len)
371 error(1, errno, "send");
372
373 /* wait for all errors to be queued, else ACKs arrive OOO */
374 usleep(50 * 1000);
375
376 __poll(fd);
377
378 while (!recv_errmsg(fd)) {}
379 }
380
381 if (close(fd))
382 error(1, errno, "close");
383
384 free(buf);
385 usleep(400 * 1000);
386}
387
388static void __attribute__((noreturn)) usage(const char *filepath)
389{
390 fprintf(stderr, "\nUsage: %s [options] hostname\n"
391 "\nwhere options are:\n"
392 " -4: only IPv4\n"
393 " -6: only IPv6\n"
394 " -h: show this message\n"
395 " -I: request PKTINFO\n"
396 " -l N: send N bytes at a time\n"
397 " -n: set no-payload option\n"
398 " -r: use raw\n"
399 " -R: use raw (IP_HDRINCL)\n"
400 " -p N: connect to port N\n"
401 " -u: use udp\n"
402 " -x: show payload (up to 70 bytes)\n",
403 filepath);
404 exit(1);
405}
406
407static void parse_opt(int argc, char **argv)
408{
409 int proto_count = 0;
410 char c;
411
412 while ((c = getopt(argc, argv, "46hIl:np:rRux")) != -1) {
413 switch (c) {
414 case '4':
415 do_ipv6 = 0;
416 break;
417 case '6':
418 do_ipv4 = 0;
419 break;
420 case 'I':
421 cfg_do_pktinfo = true;
422 break;
423 case 'n':
424 cfg_loop_nodata = true;
425 break;
426 case 'r':
427 proto_count++;
428 cfg_proto = SOCK_RAW;
429 cfg_ipproto = IPPROTO_UDP;
430 break;
431 case 'R':
432 proto_count++;
433 cfg_proto = SOCK_RAW;
434 cfg_ipproto = IPPROTO_RAW;
435 break;
436 case 'u':
437 proto_count++;
438 cfg_proto = SOCK_DGRAM;
439 cfg_ipproto = IPPROTO_UDP;
440 break;
441 case 'l':
442 cfg_payload_len = strtoul(optarg, NULL, 10);
443 break;
444 case 'p':
445 dest_port = strtoul(optarg, NULL, 10);
446 break;
447 case 'x':
448 cfg_show_payload = true;
449 break;
450 case 'h':
451 default:
452 usage(argv[0]);
453 }
454 }
455
456 if (!cfg_payload_len)
457 error(1, 0, "payload may not be nonzero");
458 if (cfg_proto != SOCK_STREAM && cfg_payload_len > 1472)
459 error(1, 0, "udp packet might exceed expected MTU");
460 if (!do_ipv4 && !do_ipv6)
461 error(1, 0, "pass -4 or -6, not both");
462 if (proto_count > 1)
463 error(1, 0, "pass -r, -R or -u, not multiple");
464
465 if (optind != argc - 1)
466 error(1, 0, "missing required hostname argument");
467}
468
469static void resolve_hostname(const char *hostname)
470{
471 struct addrinfo *addrs, *cur;
472 int have_ipv4 = 0, have_ipv6 = 0;
473
474 if (getaddrinfo(hostname, NULL, NULL, &addrs))
475 error(1, errno, "getaddrinfo");
476
477 cur = addrs;
478 while (cur && !have_ipv4 && !have_ipv6) {
479 if (!have_ipv4 && cur->ai_family == AF_INET) {
480 memcpy(&daddr, cur->ai_addr, sizeof(daddr));
481 daddr.sin_port = htons(dest_port);
482 have_ipv4 = 1;
483 }
484 else if (!have_ipv6 && cur->ai_family == AF_INET6) {
485 memcpy(&daddr6, cur->ai_addr, sizeof(daddr6));
486 daddr6.sin6_port = htons(dest_port);
487 have_ipv6 = 1;
488 }
489 cur = cur->ai_next;
490 }
491 if (addrs)
492 freeaddrinfo(addrs);
493
494 do_ipv4 &= have_ipv4;
495 do_ipv6 &= have_ipv6;
496}
497
498static void do_main(int family)
499{
500 fprintf(stderr, "family: %s\n",
501 family == PF_INET ? "INET" : "INET6");
502
503 fprintf(stderr, "test SND\n");
504 do_test(family, SOF_TIMESTAMPING_TX_SOFTWARE);
505
506 fprintf(stderr, "test ENQ\n");
507 do_test(family, SOF_TIMESTAMPING_TX_SCHED);
508
509 fprintf(stderr, "test ENQ + SND\n");
510 do_test(family, SOF_TIMESTAMPING_TX_SCHED |
511 SOF_TIMESTAMPING_TX_SOFTWARE);
512
513 if (cfg_proto == SOCK_STREAM) {
514 fprintf(stderr, "\ntest ACK\n");
515 do_test(family, SOF_TIMESTAMPING_TX_ACK);
516
517 fprintf(stderr, "\ntest SND + ACK\n");
518 do_test(family, SOF_TIMESTAMPING_TX_SOFTWARE |
519 SOF_TIMESTAMPING_TX_ACK);
520
521 fprintf(stderr, "\ntest ENQ + SND + ACK\n");
522 do_test(family, SOF_TIMESTAMPING_TX_SCHED |
523 SOF_TIMESTAMPING_TX_SOFTWARE |
524 SOF_TIMESTAMPING_TX_ACK);
525 }
526}
527
528const char *sock_names[] = { NULL, "TCP", "UDP", "RAW" };
529
530int main(int argc, char **argv)
531{
532 if (argc == 1)
533 usage(argv[0]);
534
535 parse_opt(argc, argv);
536 resolve_hostname(argv[argc - 1]);
537
538 fprintf(stderr, "protocol: %s\n", sock_names[cfg_proto]);
539 fprintf(stderr, "payload: %u\n", cfg_payload_len);
540 fprintf(stderr, "server port: %u\n", dest_port);
541 fprintf(stderr, "\n");
542
543 if (do_ipv4)
544 do_main(PF_INET);
545 if (do_ipv6)
546 do_main(PF_INET6);
547
548 return 0;
549}