0001 #include <errno.h>
0002 #include <error.h>
0003 #include <getopt.h>
0004 #include <stdbool.h>
0005 #include <stdio.h>
0006 #include <stdlib.h>
0007 #include <string.h>
0008 #include <unistd.h>
0009
0010 #include <sys/time.h>
0011 #include <sys/socket.h>
0012 #include <sys/select.h>
0013 #include <sys/ioctl.h>
0014 #include <arpa/inet.h>
0015 #include <net/if.h>
0016
0017 #include <asm/types.h>
0018 #include <linux/net_tstamp.h>
0019 #include <linux/errqueue.h>
0020
0021 #include "../kselftest.h"
0022
0023 struct options {
0024 int so_timestamp;
0025 int so_timestampns;
0026 int so_timestamping;
0027 };
0028
0029 struct tstamps {
0030 bool tstamp;
0031 bool tstampns;
0032 bool swtstamp;
0033 bool hwtstamp;
0034 };
0035
0036 struct socket_type {
0037 char *friendly_name;
0038 int type;
0039 int protocol;
0040 bool enabled;
0041 };
0042
0043 struct test_case {
0044 struct options sockopt;
0045 struct tstamps expected;
0046 bool enabled;
0047 bool warn_on_fail;
0048 };
0049
0050 struct sof_flag {
0051 int mask;
0052 char *name;
0053 };
0054
0055 static struct sof_flag sof_flags[] = {
0056 #define SOF_FLAG(f) { f, #f }
0057 SOF_FLAG(SOF_TIMESTAMPING_SOFTWARE),
0058 SOF_FLAG(SOF_TIMESTAMPING_RX_SOFTWARE),
0059 SOF_FLAG(SOF_TIMESTAMPING_RX_HARDWARE),
0060 };
0061
0062 static struct socket_type socket_types[] = {
0063 { "ip", SOCK_RAW, IPPROTO_EGP },
0064 { "udp", SOCK_DGRAM, IPPROTO_UDP },
0065 { "tcp", SOCK_STREAM, IPPROTO_TCP },
0066 };
0067
0068 static struct test_case test_cases[] = {
0069 { {}, {} },
0070 {
0071 { .so_timestamp = 1 },
0072 { .tstamp = true }
0073 },
0074 {
0075 { .so_timestampns = 1 },
0076 { .tstampns = true }
0077 },
0078 {
0079 { .so_timestamp = 1, .so_timestampns = 1 },
0080 { .tstampns = true }
0081 },
0082 {
0083 { .so_timestamping = SOF_TIMESTAMPING_RX_SOFTWARE },
0084 {}
0085 },
0086 {
0087
0088 { .so_timestamping = SOF_TIMESTAMPING_RX_HARDWARE },
0089 {}
0090 },
0091 {
0092 { .so_timestamping = SOF_TIMESTAMPING_SOFTWARE },
0093 .warn_on_fail = true
0094 },
0095 {
0096 { .so_timestamping = SOF_TIMESTAMPING_RX_SOFTWARE
0097 | SOF_TIMESTAMPING_RX_HARDWARE },
0098 {}
0099 },
0100 {
0101 { .so_timestamping = SOF_TIMESTAMPING_SOFTWARE
0102 | SOF_TIMESTAMPING_RX_SOFTWARE },
0103 { .swtstamp = true }
0104 },
0105 {
0106 { .so_timestamp = 1, .so_timestamping = SOF_TIMESTAMPING_SOFTWARE
0107 | SOF_TIMESTAMPING_RX_SOFTWARE },
0108 { .tstamp = true, .swtstamp = true }
0109 },
0110 };
0111
0112 static struct option long_options[] = {
0113 { "list_tests", no_argument, 0, 'l' },
0114 { "test_num", required_argument, 0, 'n' },
0115 { "op_size", required_argument, 0, 's' },
0116 { "tcp", no_argument, 0, 't' },
0117 { "udp", no_argument, 0, 'u' },
0118 { "ip", no_argument, 0, 'i' },
0119 { "strict", no_argument, 0, 'S' },
0120 { "ipv4", no_argument, 0, '4' },
0121 { "ipv6", no_argument, 0, '6' },
0122 { NULL, 0, NULL, 0 },
0123 };
0124
0125 static int next_port = 19999;
0126 static int op_size = 10 * 1024;
0127
0128 void print_test_case(struct test_case *t)
0129 {
0130 int f = 0;
0131
0132 printf("sockopts {");
0133 if (t->sockopt.so_timestamp)
0134 printf(" SO_TIMESTAMP ");
0135 if (t->sockopt.so_timestampns)
0136 printf(" SO_TIMESTAMPNS ");
0137 if (t->sockopt.so_timestamping) {
0138 printf(" SO_TIMESTAMPING: {");
0139 for (f = 0; f < ARRAY_SIZE(sof_flags); f++)
0140 if (t->sockopt.so_timestamping & sof_flags[f].mask)
0141 printf(" %s |", sof_flags[f].name);
0142 printf("}");
0143 }
0144 printf("} expected cmsgs: {");
0145 if (t->expected.tstamp)
0146 printf(" SCM_TIMESTAMP ");
0147 if (t->expected.tstampns)
0148 printf(" SCM_TIMESTAMPNS ");
0149 if (t->expected.swtstamp || t->expected.hwtstamp) {
0150 printf(" SCM_TIMESTAMPING {");
0151 if (t->expected.swtstamp)
0152 printf("0");
0153 if (t->expected.swtstamp && t->expected.hwtstamp)
0154 printf(",");
0155 if (t->expected.hwtstamp)
0156 printf("2");
0157 printf("}");
0158 }
0159 printf("}\n");
0160 }
0161
0162 void do_send(int src)
0163 {
0164 int r;
0165 char *buf = malloc(op_size);
0166
0167 memset(buf, 'z', op_size);
0168 r = write(src, buf, op_size);
0169 if (r < 0)
0170 error(1, errno, "Failed to sendmsg");
0171
0172 free(buf);
0173 }
0174
0175 bool do_recv(int rcv, int read_size, struct tstamps expected)
0176 {
0177 const int CMSG_SIZE = 1024;
0178
0179 struct scm_timestamping *ts;
0180 struct tstamps actual = {};
0181 char cmsg_buf[CMSG_SIZE];
0182 struct iovec recv_iov;
0183 struct cmsghdr *cmsg;
0184 bool failed = false;
0185 struct msghdr hdr;
0186 int flags = 0;
0187 int r;
0188
0189 memset(&hdr, 0, sizeof(hdr));
0190 hdr.msg_iov = &recv_iov;
0191 hdr.msg_iovlen = 1;
0192 recv_iov.iov_base = malloc(read_size);
0193 recv_iov.iov_len = read_size;
0194
0195 hdr.msg_control = cmsg_buf;
0196 hdr.msg_controllen = sizeof(cmsg_buf);
0197
0198 r = recvmsg(rcv, &hdr, flags);
0199 if (r < 0)
0200 error(1, errno, "Failed to recvmsg");
0201 if (r != read_size)
0202 error(1, 0, "Only received %d bytes of payload.", r);
0203
0204 if (hdr.msg_flags & (MSG_TRUNC | MSG_CTRUNC))
0205 error(1, 0, "Message was truncated.");
0206
0207 for (cmsg = CMSG_FIRSTHDR(&hdr); cmsg != NULL;
0208 cmsg = CMSG_NXTHDR(&hdr, cmsg)) {
0209 if (cmsg->cmsg_level != SOL_SOCKET)
0210 error(1, 0, "Unexpected cmsg_level %d",
0211 cmsg->cmsg_level);
0212 switch (cmsg->cmsg_type) {
0213 case SCM_TIMESTAMP:
0214 actual.tstamp = true;
0215 break;
0216 case SCM_TIMESTAMPNS:
0217 actual.tstampns = true;
0218 break;
0219 case SCM_TIMESTAMPING:
0220 ts = (struct scm_timestamping *)CMSG_DATA(cmsg);
0221 actual.swtstamp = !!ts->ts[0].tv_sec;
0222 if (ts->ts[1].tv_sec != 0)
0223 error(0, 0, "ts[1] should not be set.");
0224 actual.hwtstamp = !!ts->ts[2].tv_sec;
0225 break;
0226 default:
0227 error(1, 0, "Unexpected cmsg_type %d", cmsg->cmsg_type);
0228 }
0229 }
0230
0231 #define VALIDATE(field) \
0232 do { \
0233 if (expected.field != actual.field) { \
0234 if (expected.field) \
0235 error(0, 0, "Expected " #field " to be set."); \
0236 else \
0237 error(0, 0, \
0238 "Expected " #field " to not be set."); \
0239 failed = true; \
0240 } \
0241 } while (0)
0242
0243 VALIDATE(tstamp);
0244 VALIDATE(tstampns);
0245 VALIDATE(swtstamp);
0246 VALIDATE(hwtstamp);
0247 #undef VALIDATE
0248
0249 free(recv_iov.iov_base);
0250
0251 return failed;
0252 }
0253
0254 void config_so_flags(int rcv, struct options o)
0255 {
0256 int on = 1;
0257
0258 if (setsockopt(rcv, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
0259 error(1, errno, "Failed to enable SO_REUSEADDR");
0260
0261 if (o.so_timestamp &&
0262 setsockopt(rcv, SOL_SOCKET, SO_TIMESTAMP,
0263 &o.so_timestamp, sizeof(o.so_timestamp)) < 0)
0264 error(1, errno, "Failed to enable SO_TIMESTAMP");
0265
0266 if (o.so_timestampns &&
0267 setsockopt(rcv, SOL_SOCKET, SO_TIMESTAMPNS,
0268 &o.so_timestampns, sizeof(o.so_timestampns)) < 0)
0269 error(1, errno, "Failed to enable SO_TIMESTAMPNS");
0270
0271 if (o.so_timestamping &&
0272 setsockopt(rcv, SOL_SOCKET, SO_TIMESTAMPING,
0273 &o.so_timestamping, sizeof(o.so_timestamping)) < 0)
0274 error(1, errno, "Failed to set SO_TIMESTAMPING");
0275 }
0276
0277 bool run_test_case(struct socket_type *s, int test_num, char ip_version,
0278 bool strict)
0279 {
0280 union {
0281 struct sockaddr_in6 addr6;
0282 struct sockaddr_in addr4;
0283 struct sockaddr addr_un;
0284 } addr;
0285 int read_size = op_size;
0286 int src, dst, rcv, port;
0287 socklen_t addr_size;
0288 bool failed = false;
0289
0290 port = (s->type == SOCK_RAW) ? 0 : next_port++;
0291 memset(&addr, 0, sizeof(addr));
0292 if (ip_version == '4') {
0293 addr.addr4.sin_family = AF_INET;
0294 addr.addr4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
0295 addr.addr4.sin_port = htons(port);
0296 addr_size = sizeof(addr.addr4);
0297 if (s->type == SOCK_RAW)
0298 read_size += 20;
0299 } else {
0300 addr.addr6.sin6_family = AF_INET6;
0301 addr.addr6.sin6_addr = in6addr_loopback;
0302 addr.addr6.sin6_port = htons(port);
0303 addr_size = sizeof(addr.addr6);
0304 }
0305 printf("Starting testcase %d over ipv%c...\n", test_num, ip_version);
0306 src = socket(addr.addr_un.sa_family, s->type,
0307 s->protocol);
0308 if (src < 0)
0309 error(1, errno, "Failed to open src socket");
0310
0311 dst = socket(addr.addr_un.sa_family, s->type,
0312 s->protocol);
0313 if (dst < 0)
0314 error(1, errno, "Failed to open dst socket");
0315
0316 if (bind(dst, &addr.addr_un, addr_size) < 0)
0317 error(1, errno, "Failed to bind to port %d", port);
0318
0319 if (s->type == SOCK_STREAM && (listen(dst, 1) < 0))
0320 error(1, errno, "Failed to listen");
0321
0322 if (connect(src, &addr.addr_un, addr_size) < 0)
0323 error(1, errno, "Failed to connect");
0324
0325 if (s->type == SOCK_STREAM) {
0326 rcv = accept(dst, NULL, NULL);
0327 if (rcv < 0)
0328 error(1, errno, "Failed to accept");
0329 close(dst);
0330 } else {
0331 rcv = dst;
0332 }
0333
0334 config_so_flags(rcv, test_cases[test_num].sockopt);
0335 usleep(20000);
0336 do_send(src);
0337
0338 failed = do_recv(rcv, read_size, test_cases[test_num].expected);
0339
0340 close(rcv);
0341 close(src);
0342
0343 if (failed) {
0344 printf("FAILURE in testcase %d over ipv%c ", test_num,
0345 ip_version);
0346 print_test_case(&test_cases[test_num]);
0347 if (!strict && test_cases[test_num].warn_on_fail)
0348 failed = false;
0349 }
0350 return failed;
0351 }
0352
0353 int main(int argc, char **argv)
0354 {
0355 bool all_protocols = true;
0356 bool all_tests = true;
0357 bool cfg_ipv4 = false;
0358 bool cfg_ipv6 = false;
0359 bool strict = false;
0360 int arg_index = 0;
0361 int failures = 0;
0362 int s, t, opt;
0363
0364 while ((opt = getopt_long(argc, argv, "", long_options,
0365 &arg_index)) != -1) {
0366 switch (opt) {
0367 case 'l':
0368 for (t = 0; t < ARRAY_SIZE(test_cases); t++) {
0369 printf("%d\t", t);
0370 print_test_case(&test_cases[t]);
0371 }
0372 return 0;
0373 case 'n':
0374 t = atoi(optarg);
0375 if (t >= ARRAY_SIZE(test_cases))
0376 error(1, 0, "Invalid test case: %d", t);
0377 all_tests = false;
0378 test_cases[t].enabled = true;
0379 break;
0380 case 's':
0381 op_size = atoi(optarg);
0382 break;
0383 case 't':
0384 all_protocols = false;
0385 socket_types[2].enabled = true;
0386 break;
0387 case 'u':
0388 all_protocols = false;
0389 socket_types[1].enabled = true;
0390 break;
0391 case 'i':
0392 all_protocols = false;
0393 socket_types[0].enabled = true;
0394 break;
0395 case 'S':
0396 strict = true;
0397 break;
0398 case '4':
0399 cfg_ipv4 = true;
0400 break;
0401 case '6':
0402 cfg_ipv6 = true;
0403 break;
0404 default:
0405 error(1, 0, "Failed to parse parameters.");
0406 }
0407 }
0408
0409 for (s = 0; s < ARRAY_SIZE(socket_types); s++) {
0410 if (!all_protocols && !socket_types[s].enabled)
0411 continue;
0412
0413 printf("Testing %s...\n", socket_types[s].friendly_name);
0414 for (t = 0; t < ARRAY_SIZE(test_cases); t++) {
0415 if (!all_tests && !test_cases[t].enabled)
0416 continue;
0417 if (cfg_ipv4 || !cfg_ipv6)
0418 if (run_test_case(&socket_types[s], t, '4',
0419 strict))
0420 failures++;
0421 if (cfg_ipv6 || !cfg_ipv4)
0422 if (run_test_case(&socket_types[s], t, '6',
0423 strict))
0424 failures++;
0425 }
0426 }
0427 if (!failures)
0428 printf("PASSED.\n");
0429 return failures;
0430 }