rxtimestamp.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. #include <errno.h>
  2. #include <error.h>
  3. #include <getopt.h>
  4. #include <stdbool.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <sys/time.h>
  9. #include <sys/socket.h>
  10. #include <sys/select.h>
  11. #include <sys/ioctl.h>
  12. #include <arpa/inet.h>
  13. #include <net/if.h>
  14. #include <asm/types.h>
  15. #include <linux/net_tstamp.h>
  16. #include <linux/errqueue.h>
  17. #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
  18. struct options {
  19. int so_timestamp;
  20. int so_timestampns;
  21. int so_timestamping;
  22. };
  23. struct tstamps {
  24. bool tstamp;
  25. bool tstampns;
  26. bool swtstamp;
  27. bool hwtstamp;
  28. };
  29. struct socket_type {
  30. char *friendly_name;
  31. int type;
  32. int protocol;
  33. bool enabled;
  34. };
  35. struct test_case {
  36. struct options sockopt;
  37. struct tstamps expected;
  38. bool enabled;
  39. };
  40. struct sof_flag {
  41. int mask;
  42. char *name;
  43. };
  44. static struct sof_flag sof_flags[] = {
  45. #define SOF_FLAG(f) { f, #f }
  46. SOF_FLAG(SOF_TIMESTAMPING_SOFTWARE),
  47. SOF_FLAG(SOF_TIMESTAMPING_RX_SOFTWARE),
  48. SOF_FLAG(SOF_TIMESTAMPING_RX_HARDWARE),
  49. };
  50. static struct socket_type socket_types[] = {
  51. { "ip", SOCK_RAW, IPPROTO_EGP },
  52. { "udp", SOCK_DGRAM, IPPROTO_UDP },
  53. { "tcp", SOCK_STREAM, IPPROTO_TCP },
  54. };
  55. static struct test_case test_cases[] = {
  56. { {}, {} },
  57. {
  58. { so_timestamp: 1 },
  59. { tstamp: true }
  60. },
  61. {
  62. { so_timestampns: 1 },
  63. { tstampns: true }
  64. },
  65. {
  66. { so_timestamp: 1, so_timestampns: 1 },
  67. { tstampns: true }
  68. },
  69. {
  70. { so_timestamping: SOF_TIMESTAMPING_RX_SOFTWARE },
  71. {}
  72. },
  73. {
  74. /* Loopback device does not support hw timestamps. */
  75. { so_timestamping: SOF_TIMESTAMPING_RX_HARDWARE },
  76. {}
  77. },
  78. {
  79. { so_timestamping: SOF_TIMESTAMPING_SOFTWARE },
  80. {}
  81. },
  82. {
  83. { so_timestamping: SOF_TIMESTAMPING_RX_SOFTWARE
  84. | SOF_TIMESTAMPING_RX_HARDWARE },
  85. {}
  86. },
  87. {
  88. { so_timestamping: SOF_TIMESTAMPING_SOFTWARE
  89. | SOF_TIMESTAMPING_RX_SOFTWARE },
  90. { swtstamp: true }
  91. },
  92. {
  93. { so_timestamp: 1, so_timestamping: SOF_TIMESTAMPING_SOFTWARE
  94. | SOF_TIMESTAMPING_RX_SOFTWARE },
  95. { tstamp: true, swtstamp: true }
  96. },
  97. };
  98. static struct option long_options[] = {
  99. { "list_tests", no_argument, 0, 'l' },
  100. { "test_num", required_argument, 0, 'n' },
  101. { "op_size", required_argument, 0, 's' },
  102. { "tcp", no_argument, 0, 't' },
  103. { "udp", no_argument, 0, 'u' },
  104. { "ip", no_argument, 0, 'i' },
  105. { NULL, 0, NULL, 0 },
  106. };
  107. static int next_port = 19999;
  108. static int op_size = 10 * 1024;
  109. void print_test_case(struct test_case *t)
  110. {
  111. int f = 0;
  112. printf("sockopts {");
  113. if (t->sockopt.so_timestamp)
  114. printf(" SO_TIMESTAMP ");
  115. if (t->sockopt.so_timestampns)
  116. printf(" SO_TIMESTAMPNS ");
  117. if (t->sockopt.so_timestamping) {
  118. printf(" SO_TIMESTAMPING: {");
  119. for (f = 0; f < ARRAY_SIZE(sof_flags); f++)
  120. if (t->sockopt.so_timestamping & sof_flags[f].mask)
  121. printf(" %s |", sof_flags[f].name);
  122. printf("}");
  123. }
  124. printf("} expected cmsgs: {");
  125. if (t->expected.tstamp)
  126. printf(" SCM_TIMESTAMP ");
  127. if (t->expected.tstampns)
  128. printf(" SCM_TIMESTAMPNS ");
  129. if (t->expected.swtstamp || t->expected.hwtstamp) {
  130. printf(" SCM_TIMESTAMPING {");
  131. if (t->expected.swtstamp)
  132. printf("0");
  133. if (t->expected.swtstamp && t->expected.hwtstamp)
  134. printf(",");
  135. if (t->expected.hwtstamp)
  136. printf("2");
  137. printf("}");
  138. }
  139. printf("}\n");
  140. }
  141. void do_send(int src)
  142. {
  143. int r;
  144. char *buf = malloc(op_size);
  145. memset(buf, 'z', op_size);
  146. r = write(src, buf, op_size);
  147. if (r < 0)
  148. error(1, errno, "Failed to sendmsg");
  149. free(buf);
  150. }
  151. bool do_recv(int rcv, int read_size, struct tstamps expected)
  152. {
  153. const int CMSG_SIZE = 1024;
  154. struct scm_timestamping *ts;
  155. struct tstamps actual = {};
  156. char cmsg_buf[CMSG_SIZE];
  157. struct iovec recv_iov;
  158. struct cmsghdr *cmsg;
  159. bool failed = false;
  160. struct msghdr hdr;
  161. int flags = 0;
  162. int r;
  163. memset(&hdr, 0, sizeof(hdr));
  164. hdr.msg_iov = &recv_iov;
  165. hdr.msg_iovlen = 1;
  166. recv_iov.iov_base = malloc(read_size);
  167. recv_iov.iov_len = read_size;
  168. hdr.msg_control = cmsg_buf;
  169. hdr.msg_controllen = sizeof(cmsg_buf);
  170. r = recvmsg(rcv, &hdr, flags);
  171. if (r < 0)
  172. error(1, errno, "Failed to recvmsg");
  173. if (r != read_size)
  174. error(1, 0, "Only received %d bytes of payload.", r);
  175. if (hdr.msg_flags & (MSG_TRUNC | MSG_CTRUNC))
  176. error(1, 0, "Message was truncated.");
  177. for (cmsg = CMSG_FIRSTHDR(&hdr); cmsg != NULL;
  178. cmsg = CMSG_NXTHDR(&hdr, cmsg)) {
  179. if (cmsg->cmsg_level != SOL_SOCKET)
  180. error(1, 0, "Unexpected cmsg_level %d",
  181. cmsg->cmsg_level);
  182. switch (cmsg->cmsg_type) {
  183. case SCM_TIMESTAMP:
  184. actual.tstamp = true;
  185. break;
  186. case SCM_TIMESTAMPNS:
  187. actual.tstampns = true;
  188. break;
  189. case SCM_TIMESTAMPING:
  190. ts = (struct scm_timestamping *)CMSG_DATA(cmsg);
  191. actual.swtstamp = !!ts->ts[0].tv_sec;
  192. if (ts->ts[1].tv_sec != 0)
  193. error(0, 0, "ts[1] should not be set.");
  194. actual.hwtstamp = !!ts->ts[2].tv_sec;
  195. break;
  196. default:
  197. error(1, 0, "Unexpected cmsg_type %d", cmsg->cmsg_type);
  198. }
  199. }
  200. #define VALIDATE(field) \
  201. do { \
  202. if (expected.field != actual.field) { \
  203. if (expected.field) \
  204. error(0, 0, "Expected " #field " to be set."); \
  205. else \
  206. error(0, 0, \
  207. "Expected " #field " to not be set."); \
  208. failed = true; \
  209. } \
  210. } while (0)
  211. VALIDATE(tstamp);
  212. VALIDATE(tstampns);
  213. VALIDATE(swtstamp);
  214. VALIDATE(hwtstamp);
  215. #undef VALIDATE
  216. free(recv_iov.iov_base);
  217. return failed;
  218. }
  219. void config_so_flags(int rcv, struct options o)
  220. {
  221. int on = 1;
  222. if (setsockopt(rcv, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
  223. error(1, errno, "Failed to enable SO_REUSEADDR");
  224. if (o.so_timestamp &&
  225. setsockopt(rcv, SOL_SOCKET, SO_TIMESTAMP,
  226. &o.so_timestamp, sizeof(o.so_timestamp)) < 0)
  227. error(1, errno, "Failed to enable SO_TIMESTAMP");
  228. if (o.so_timestampns &&
  229. setsockopt(rcv, SOL_SOCKET, SO_TIMESTAMPNS,
  230. &o.so_timestampns, sizeof(o.so_timestampns)) < 0)
  231. error(1, errno, "Failed to enable SO_TIMESTAMPNS");
  232. if (o.so_timestamping &&
  233. setsockopt(rcv, SOL_SOCKET, SO_TIMESTAMPING,
  234. &o.so_timestamping, sizeof(o.so_timestamping)) < 0)
  235. error(1, errno, "Failed to set SO_TIMESTAMPING");
  236. }
  237. bool run_test_case(struct socket_type s, struct test_case t)
  238. {
  239. int port = (s.type == SOCK_RAW) ? 0 : next_port++;
  240. int read_size = op_size;
  241. struct sockaddr_in addr;
  242. bool failed = false;
  243. int src, dst, rcv;
  244. src = socket(AF_INET, s.type, s.protocol);
  245. if (src < 0)
  246. error(1, errno, "Failed to open src socket");
  247. dst = socket(AF_INET, s.type, s.protocol);
  248. if (dst < 0)
  249. error(1, errno, "Failed to open dst socket");
  250. memset(&addr, 0, sizeof(addr));
  251. addr.sin_family = AF_INET;
  252. addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  253. addr.sin_port = htons(port);
  254. if (bind(dst, (struct sockaddr *)&addr, sizeof(addr)) < 0)
  255. error(1, errno, "Failed to bind to port %d", port);
  256. if (s.type == SOCK_STREAM && (listen(dst, 1) < 0))
  257. error(1, errno, "Failed to listen");
  258. if (connect(src, (struct sockaddr *)&addr, sizeof(addr)) < 0)
  259. error(1, errno, "Failed to connect");
  260. if (s.type == SOCK_STREAM) {
  261. rcv = accept(dst, NULL, NULL);
  262. if (rcv < 0)
  263. error(1, errno, "Failed to accept");
  264. close(dst);
  265. } else {
  266. rcv = dst;
  267. }
  268. config_so_flags(rcv, t.sockopt);
  269. usleep(20000); /* setsockopt for SO_TIMESTAMPING is asynchronous */
  270. do_send(src);
  271. if (s.type == SOCK_RAW)
  272. read_size += 20; /* for IP header */
  273. failed = do_recv(rcv, read_size, t.expected);
  274. close(rcv);
  275. close(src);
  276. return failed;
  277. }
  278. int main(int argc, char **argv)
  279. {
  280. bool all_protocols = true;
  281. bool all_tests = true;
  282. int arg_index = 0;
  283. int failures = 0;
  284. int s, t, opt;
  285. while ((opt = getopt_long(argc, argv, "", long_options,
  286. &arg_index)) != -1) {
  287. switch (opt) {
  288. case 'l':
  289. for (t = 0; t < ARRAY_SIZE(test_cases); t++) {
  290. printf("%d\t", t);
  291. print_test_case(&test_cases[t]);
  292. }
  293. return 0;
  294. case 'n':
  295. t = atoi(optarg);
  296. if (t >= ARRAY_SIZE(test_cases))
  297. error(1, 0, "Invalid test case: %d", t);
  298. all_tests = false;
  299. test_cases[t].enabled = true;
  300. break;
  301. case 's':
  302. op_size = atoi(optarg);
  303. break;
  304. case 't':
  305. all_protocols = false;
  306. socket_types[2].enabled = true;
  307. break;
  308. case 'u':
  309. all_protocols = false;
  310. socket_types[1].enabled = true;
  311. break;
  312. case 'i':
  313. all_protocols = false;
  314. socket_types[0].enabled = true;
  315. break;
  316. default:
  317. error(1, 0, "Failed to parse parameters.");
  318. }
  319. }
  320. for (s = 0; s < ARRAY_SIZE(socket_types); s++) {
  321. if (!all_protocols && !socket_types[s].enabled)
  322. continue;
  323. printf("Testing %s...\n", socket_types[s].friendly_name);
  324. for (t = 0; t < ARRAY_SIZE(test_cases); t++) {
  325. if (!all_tests && !test_cases[t].enabled)
  326. continue;
  327. printf("Starting testcase %d...\n", t);
  328. if (run_test_case(socket_types[s], test_cases[t])) {
  329. failures++;
  330. printf("FAILURE in test case ");
  331. print_test_case(&test_cases[t]);
  332. }
  333. }
  334. }
  335. if (!failures)
  336. printf("PASSED.\n");
  337. return failures;
  338. }