11 #include <sys/socket.h>
12 #include <sys/select.h>
13 #include <sys/ioctl.h>
14 #include <arpa/inet.h>
17 #include <asm/types.h>
18 #include <linux/net_tstamp.h>
19 #include <linux/errqueue.h>
21 #include "../kselftest.h"
44 struct options sockopt
;
45 struct tstamps expected
;
55 static struct sof_flag sof_flags
[] = {
56 #define SOF_FLAG(f) { f, #f }
57 SOF_FLAG(SOF_TIMESTAMPING_SOFTWARE
),
58 SOF_FLAG(SOF_TIMESTAMPING_RX_SOFTWARE
),
59 SOF_FLAG(SOF_TIMESTAMPING_RX_HARDWARE
),
60 SOF_FLAG(SOF_TIMESTAMPING_OPT_RX_FILTER
),
61 SOF_FLAG(SOF_TIMESTAMPING_RAW_HARDWARE
),
64 static struct socket_type socket_types
[] = {
65 { "ip", SOCK_RAW
, IPPROTO_EGP
},
66 { "udp", SOCK_DGRAM
, IPPROTO_UDP
},
67 { "tcp", SOCK_STREAM
, IPPROTO_TCP
},
70 static struct test_case test_cases
[] = {
73 { .so_timestamp
= 1 },
77 { .so_timestampns
= 1 },
81 { .so_timestamp
= 1, .so_timestampns
= 1 },
85 { .so_timestamping
= SOF_TIMESTAMPING_RX_SOFTWARE
},
89 /* Loopback device does not support hw timestamps. */
90 { .so_timestamping
= SOF_TIMESTAMPING_RX_HARDWARE
},
94 { .so_timestamping
= SOF_TIMESTAMPING_SOFTWARE
},
98 { .so_timestamping
= SOF_TIMESTAMPING_RX_SOFTWARE
99 | SOF_TIMESTAMPING_RX_HARDWARE
},
103 { .so_timestamping
= SOF_TIMESTAMPING_RAW_HARDWARE
104 | SOF_TIMESTAMPING_OPT_RX_FILTER
},
108 { .so_timestamping
= SOF_TIMESTAMPING_SOFTWARE
109 | SOF_TIMESTAMPING_OPT_RX_FILTER
},
113 { .so_timestamping
= SOF_TIMESTAMPING_SOFTWARE
114 | SOF_TIMESTAMPING_RX_SOFTWARE
115 | SOF_TIMESTAMPING_OPT_RX_FILTER
},
119 { .so_timestamping
= SOF_TIMESTAMPING_SOFTWARE
120 | SOF_TIMESTAMPING_RX_SOFTWARE
},
124 { .so_timestamp
= 1, .so_timestamping
= SOF_TIMESTAMPING_SOFTWARE
125 | SOF_TIMESTAMPING_RX_SOFTWARE
},
126 { .tstamp
= true, .swtstamp
= true }
130 static struct option long_options
[] = {
131 { "list_tests", no_argument
, 0, 'l' },
132 { "test_num", required_argument
, 0, 'n' },
133 { "op_size", required_argument
, 0, 's' },
134 { "tcp", no_argument
, 0, 't' },
135 { "udp", no_argument
, 0, 'u' },
136 { "ip", no_argument
, 0, 'i' },
137 { "strict", no_argument
, 0, 'S' },
138 { "ipv4", no_argument
, 0, '4' },
139 { "ipv6", no_argument
, 0, '6' },
140 { NULL
, 0, NULL
, 0 },
143 static int next_port
= 19999;
144 static int op_size
= 10 * 1024;
146 void print_test_case(struct test_case
*t
)
150 printf("sockopts {");
151 if (t
->sockopt
.so_timestamp
)
152 printf(" SO_TIMESTAMP ");
153 if (t
->sockopt
.so_timestampns
)
154 printf(" SO_TIMESTAMPNS ");
155 if (t
->sockopt
.so_timestamping
) {
156 printf(" SO_TIMESTAMPING: {");
157 for (f
= 0; f
< ARRAY_SIZE(sof_flags
); f
++)
158 if (t
->sockopt
.so_timestamping
& sof_flags
[f
].mask
)
159 printf(" %s |", sof_flags
[f
].name
);
162 printf("} expected cmsgs: {");
163 if (t
->expected
.tstamp
)
164 printf(" SCM_TIMESTAMP ");
165 if (t
->expected
.tstampns
)
166 printf(" SCM_TIMESTAMPNS ");
167 if (t
->expected
.swtstamp
|| t
->expected
.hwtstamp
) {
168 printf(" SCM_TIMESTAMPING {");
169 if (t
->expected
.swtstamp
)
171 if (t
->expected
.swtstamp
&& t
->expected
.hwtstamp
)
173 if (t
->expected
.hwtstamp
)
180 void do_send(int src
)
183 char *buf
= malloc(op_size
);
185 memset(buf
, 'z', op_size
);
186 r
= write(src
, buf
, op_size
);
188 error(1, errno
, "Failed to sendmsg");
193 bool do_recv(int rcv
, int read_size
, struct tstamps expected
)
195 const int CMSG_SIZE
= 1024;
197 struct scm_timestamping
*ts
;
198 struct tstamps actual
= {};
199 char cmsg_buf
[CMSG_SIZE
];
200 struct iovec recv_iov
;
201 struct cmsghdr
*cmsg
;
207 memset(&hdr
, 0, sizeof(hdr
));
208 hdr
.msg_iov
= &recv_iov
;
210 recv_iov
.iov_base
= malloc(read_size
);
211 recv_iov
.iov_len
= read_size
;
213 hdr
.msg_control
= cmsg_buf
;
214 hdr
.msg_controllen
= sizeof(cmsg_buf
);
216 r
= recvmsg(rcv
, &hdr
, flags
);
218 error(1, errno
, "Failed to recvmsg");
220 error(1, 0, "Only received %d bytes of payload.", r
);
222 if (hdr
.msg_flags
& (MSG_TRUNC
| MSG_CTRUNC
))
223 error(1, 0, "Message was truncated.");
225 for (cmsg
= CMSG_FIRSTHDR(&hdr
); cmsg
!= NULL
;
226 cmsg
= CMSG_NXTHDR(&hdr
, cmsg
)) {
227 if (cmsg
->cmsg_level
!= SOL_SOCKET
)
228 error(1, 0, "Unexpected cmsg_level %d",
230 switch (cmsg
->cmsg_type
) {
232 actual
.tstamp
= true;
234 case SCM_TIMESTAMPNS
:
235 actual
.tstampns
= true;
237 case SCM_TIMESTAMPING
:
238 ts
= (struct scm_timestamping
*)CMSG_DATA(cmsg
);
239 actual
.swtstamp
= !!ts
->ts
[0].tv_sec
;
240 if (ts
->ts
[1].tv_sec
!= 0)
241 error(0, 0, "ts[1] should not be set.");
242 actual
.hwtstamp
= !!ts
->ts
[2].tv_sec
;
245 error(1, 0, "Unexpected cmsg_type %d", cmsg
->cmsg_type
);
249 #define VALIDATE(field) \
251 if (expected.field != actual.field) { \
252 if (expected.field) \
253 error(0, 0, "Expected " #field " to be set."); \
256 "Expected " #field " to not be set."); \
267 free(recv_iov
.iov_base
);
272 void config_so_flags(int rcv
, struct options o
)
276 if (setsockopt(rcv
, SOL_SOCKET
, SO_REUSEADDR
, &on
, sizeof(on
)) < 0)
277 error(1, errno
, "Failed to enable SO_REUSEADDR");
279 if (o
.so_timestamp
&&
280 setsockopt(rcv
, SOL_SOCKET
, SO_TIMESTAMP
,
281 &o
.so_timestamp
, sizeof(o
.so_timestamp
)) < 0)
282 error(1, errno
, "Failed to enable SO_TIMESTAMP");
284 if (o
.so_timestampns
&&
285 setsockopt(rcv
, SOL_SOCKET
, SO_TIMESTAMPNS
,
286 &o
.so_timestampns
, sizeof(o
.so_timestampns
)) < 0)
287 error(1, errno
, "Failed to enable SO_TIMESTAMPNS");
289 if (o
.so_timestamping
&&
290 setsockopt(rcv
, SOL_SOCKET
, SO_TIMESTAMPING
,
291 &o
.so_timestamping
, sizeof(o
.so_timestamping
)) < 0)
292 error(1, errno
, "Failed to set SO_TIMESTAMPING");
295 bool run_test_case(struct socket_type
*s
, int test_num
, char ip_version
,
299 struct sockaddr_in6 addr6
;
300 struct sockaddr_in addr4
;
301 struct sockaddr addr_un
;
303 int read_size
= op_size
;
304 int src
, dst
, rcv
, port
;
308 port
= (s
->type
== SOCK_RAW
) ? 0 : next_port
++;
309 memset(&addr
, 0, sizeof(addr
));
310 if (ip_version
== '4') {
311 addr
.addr4
.sin_family
= AF_INET
;
312 addr
.addr4
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
313 addr
.addr4
.sin_port
= htons(port
);
314 addr_size
= sizeof(addr
.addr4
);
315 if (s
->type
== SOCK_RAW
)
316 read_size
+= 20; /* for IPv4 header */
318 addr
.addr6
.sin6_family
= AF_INET6
;
319 addr
.addr6
.sin6_addr
= in6addr_loopback
;
320 addr
.addr6
.sin6_port
= htons(port
);
321 addr_size
= sizeof(addr
.addr6
);
323 printf("Starting testcase %d over ipv%c...\n", test_num
, ip_version
);
324 src
= socket(addr
.addr_un
.sa_family
, s
->type
,
327 error(1, errno
, "Failed to open src socket");
329 dst
= socket(addr
.addr_un
.sa_family
, s
->type
,
332 error(1, errno
, "Failed to open dst socket");
334 if (bind(dst
, &addr
.addr_un
, addr_size
) < 0)
335 error(1, errno
, "Failed to bind to port %d", port
);
337 if (s
->type
== SOCK_STREAM
&& (listen(dst
, 1) < 0))
338 error(1, errno
, "Failed to listen");
340 if (connect(src
, &addr
.addr_un
, addr_size
) < 0)
341 error(1, errno
, "Failed to connect");
343 if (s
->type
== SOCK_STREAM
) {
344 rcv
= accept(dst
, NULL
, NULL
);
346 error(1, errno
, "Failed to accept");
352 config_so_flags(rcv
, test_cases
[test_num
].sockopt
);
353 usleep(20000); /* setsockopt for SO_TIMESTAMPING is asynchronous */
356 failed
= do_recv(rcv
, read_size
, test_cases
[test_num
].expected
);
362 printf("FAILURE in testcase %d over ipv%c ", test_num
,
364 print_test_case(&test_cases
[test_num
]);
365 if (!strict
&& test_cases
[test_num
].warn_on_fail
)
371 int main(int argc
, char **argv
)
373 bool all_protocols
= true;
374 bool all_tests
= true;
375 bool cfg_ipv4
= false;
376 bool cfg_ipv6
= false;
382 while ((opt
= getopt_long(argc
, argv
, "", long_options
,
383 &arg_index
)) != -1) {
386 for (t
= 0; t
< ARRAY_SIZE(test_cases
); t
++) {
388 print_test_case(&test_cases
[t
]);
393 if (t
>= ARRAY_SIZE(test_cases
))
394 error(1, 0, "Invalid test case: %d", t
);
396 test_cases
[t
].enabled
= true;
399 op_size
= atoi(optarg
);
402 all_protocols
= false;
403 socket_types
[2].enabled
= true;
406 all_protocols
= false;
407 socket_types
[1].enabled
= true;
410 all_protocols
= false;
411 socket_types
[0].enabled
= true;
423 error(1, 0, "Failed to parse parameters.");
427 for (s
= 0; s
< ARRAY_SIZE(socket_types
); s
++) {
428 if (!all_protocols
&& !socket_types
[s
].enabled
)
431 printf("Testing %s...\n", socket_types
[s
].friendly_name
);
432 for (t
= 0; t
< ARRAY_SIZE(test_cases
); t
++) {
433 if (!all_tests
&& !test_cases
[t
].enabled
)
435 if (cfg_ipv4
|| !cfg_ipv6
)
436 if (run_test_case(&socket_types
[s
], t
, '4',
439 if (cfg_ipv6
|| !cfg_ipv4
)
440 if (run_test_case(&socket_types
[s
], t
, '6',