mptcp_sockopt.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885
  1. // SPDX-License-Identifier: GPL-2.0
  2. #define _GNU_SOURCE
  3. #include <assert.h>
  4. #include <errno.h>
  5. #include <fcntl.h>
  6. #include <limits.h>
  7. #include <string.h>
  8. #include <stdarg.h>
  9. #include <stdbool.h>
  10. #include <stdint.h>
  11. #include <inttypes.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <strings.h>
  15. #include <time.h>
  16. #include <unistd.h>
  17. #include <sys/socket.h>
  18. #include <sys/types.h>
  19. #include <sys/wait.h>
  20. #include <netdb.h>
  21. #include <netinet/in.h>
  22. #include <linux/tcp.h>
  23. #include <linux/compiler.h>
  24. static int pf = AF_INET;
  25. #ifndef IPPROTO_MPTCP
  26. #define IPPROTO_MPTCP 262
  27. #endif
  28. #ifndef SOL_MPTCP
  29. #define SOL_MPTCP 284
  30. #endif
  31. #ifndef MPTCP_INFO
  32. struct mptcp_info {
  33. __u8 mptcpi_subflows;
  34. __u8 mptcpi_add_addr_signal;
  35. __u8 mptcpi_add_addr_accepted;
  36. __u8 mptcpi_subflows_max;
  37. __u8 mptcpi_add_addr_signal_max;
  38. __u8 mptcpi_add_addr_accepted_max;
  39. __u32 mptcpi_flags;
  40. __u32 mptcpi_token;
  41. __u64 mptcpi_write_seq;
  42. __u64 mptcpi_snd_una;
  43. __u64 mptcpi_rcv_nxt;
  44. __u8 mptcpi_local_addr_used;
  45. __u8 mptcpi_local_addr_max;
  46. __u8 mptcpi_csum_enabled;
  47. __u32 mptcpi_retransmits;
  48. __u64 mptcpi_bytes_retrans;
  49. __u64 mptcpi_bytes_sent;
  50. __u64 mptcpi_bytes_received;
  51. __u64 mptcpi_bytes_acked;
  52. };
  53. struct mptcp_subflow_data {
  54. __u32 size_subflow_data; /* size of this structure in userspace */
  55. __u32 num_subflows; /* must be 0, set by kernel */
  56. __u32 size_kernel; /* must be 0, set by kernel */
  57. __u32 size_user; /* size of one element in data[] */
  58. } __attribute__((aligned(8)));
  59. struct mptcp_subflow_addrs {
  60. union {
  61. __kernel_sa_family_t sa_family;
  62. struct sockaddr sa_local;
  63. struct sockaddr_in sin_local;
  64. struct sockaddr_in6 sin6_local;
  65. struct __kernel_sockaddr_storage ss_local;
  66. };
  67. union {
  68. struct sockaddr sa_remote;
  69. struct sockaddr_in sin_remote;
  70. struct sockaddr_in6 sin6_remote;
  71. struct __kernel_sockaddr_storage ss_remote;
  72. };
  73. };
  74. #define MPTCP_INFO 1
  75. #define MPTCP_TCPINFO 2
  76. #define MPTCP_SUBFLOW_ADDRS 3
  77. #endif
  78. #ifndef MPTCP_FULL_INFO
  79. struct mptcp_subflow_info {
  80. __u32 id;
  81. struct mptcp_subflow_addrs addrs;
  82. };
  83. struct mptcp_full_info {
  84. __u32 size_tcpinfo_kernel; /* must be 0, set by kernel */
  85. __u32 size_tcpinfo_user;
  86. __u32 size_sfinfo_kernel; /* must be 0, set by kernel */
  87. __u32 size_sfinfo_user;
  88. __u32 num_subflows; /* must be 0, set by kernel (real subflow count) */
  89. __u32 size_arrays_user; /* max subflows that userspace is interested in;
  90. * the buffers at subflow_info/tcp_info
  91. * are respectively at least:
  92. * size_arrays * size_sfinfo_user
  93. * size_arrays * size_tcpinfo_user
  94. * bytes wide
  95. */
  96. __aligned_u64 subflow_info;
  97. __aligned_u64 tcp_info;
  98. struct mptcp_info mptcp_info;
  99. };
  100. #define MPTCP_FULL_INFO 4
  101. #endif
  102. struct so_state {
  103. struct mptcp_info mi;
  104. struct mptcp_info last_sample;
  105. struct tcp_info tcp_info;
  106. struct mptcp_subflow_addrs addrs;
  107. uint64_t mptcpi_rcv_delta;
  108. uint64_t tcpi_rcv_delta;
  109. bool pkt_stats_avail;
  110. };
  111. #ifndef MIN
  112. #define MIN(a, b) ((a) < (b) ? (a) : (b))
  113. #endif
  114. static void __noreturn die_perror(const char *msg)
  115. {
  116. perror(msg);
  117. exit(1);
  118. }
  119. static void die_usage(int r)
  120. {
  121. fprintf(stderr, "Usage: mptcp_sockopt [-6]\n");
  122. exit(r);
  123. }
  124. static void __noreturn xerror(const char *fmt, ...)
  125. {
  126. va_list ap;
  127. va_start(ap, fmt);
  128. vfprintf(stderr, fmt, ap);
  129. va_end(ap);
  130. fputc('\n', stderr);
  131. exit(1);
  132. }
  133. static const char *getxinfo_strerr(int err)
  134. {
  135. if (err == EAI_SYSTEM)
  136. return strerror(errno);
  137. return gai_strerror(err);
  138. }
  139. static void xgetaddrinfo(const char *node, const char *service,
  140. struct addrinfo *hints,
  141. struct addrinfo **res)
  142. {
  143. int err;
  144. again:
  145. err = getaddrinfo(node, service, hints, res);
  146. if (err) {
  147. const char *errstr;
  148. if (err == EAI_SOCKTYPE) {
  149. hints->ai_protocol = IPPROTO_TCP;
  150. goto again;
  151. }
  152. errstr = getxinfo_strerr(err);
  153. fprintf(stderr, "Fatal: getaddrinfo(%s:%s): %s\n",
  154. node ? node : "", service ? service : "", errstr);
  155. exit(1);
  156. }
  157. }
  158. static int sock_listen_mptcp(const char * const listenaddr,
  159. const char * const port)
  160. {
  161. int sock = -1;
  162. struct addrinfo hints = {
  163. .ai_protocol = IPPROTO_MPTCP,
  164. .ai_socktype = SOCK_STREAM,
  165. .ai_flags = AI_PASSIVE | AI_NUMERICHOST
  166. };
  167. hints.ai_family = pf;
  168. struct addrinfo *a, *addr;
  169. int one = 1;
  170. xgetaddrinfo(listenaddr, port, &hints, &addr);
  171. hints.ai_family = pf;
  172. for (a = addr; a; a = a->ai_next) {
  173. sock = socket(a->ai_family, a->ai_socktype, IPPROTO_MPTCP);
  174. if (sock < 0)
  175. continue;
  176. if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one,
  177. sizeof(one)))
  178. perror("setsockopt");
  179. if (bind(sock, a->ai_addr, a->ai_addrlen) == 0)
  180. break; /* success */
  181. perror("bind");
  182. close(sock);
  183. sock = -1;
  184. }
  185. freeaddrinfo(addr);
  186. if (sock < 0)
  187. xerror("could not create listen socket");
  188. if (listen(sock, 20))
  189. die_perror("listen");
  190. return sock;
  191. }
  192. static int sock_connect_mptcp(const char * const remoteaddr,
  193. const char * const port, int proto)
  194. {
  195. struct addrinfo hints = {
  196. .ai_protocol = IPPROTO_MPTCP,
  197. .ai_socktype = SOCK_STREAM,
  198. };
  199. struct addrinfo *a, *addr;
  200. int sock = -1;
  201. hints.ai_family = pf;
  202. xgetaddrinfo(remoteaddr, port, &hints, &addr);
  203. for (a = addr; a; a = a->ai_next) {
  204. sock = socket(a->ai_family, a->ai_socktype, proto);
  205. if (sock < 0)
  206. continue;
  207. if (connect(sock, a->ai_addr, a->ai_addrlen) == 0)
  208. break; /* success */
  209. die_perror("connect");
  210. }
  211. if (sock < 0)
  212. xerror("could not create connect socket");
  213. freeaddrinfo(addr);
  214. return sock;
  215. }
  216. static void parse_opts(int argc, char **argv)
  217. {
  218. int c;
  219. while ((c = getopt(argc, argv, "h6")) != -1) {
  220. switch (c) {
  221. case 'h':
  222. die_usage(0);
  223. break;
  224. case '6':
  225. pf = AF_INET6;
  226. break;
  227. default:
  228. die_usage(1);
  229. break;
  230. }
  231. }
  232. }
  233. static void do_getsockopt_bogus_sf_data(int fd, int optname)
  234. {
  235. struct mptcp_subflow_data good_data;
  236. struct bogus_data {
  237. struct mptcp_subflow_data d;
  238. char buf[2];
  239. } bd;
  240. socklen_t olen, _olen;
  241. int ret;
  242. memset(&bd, 0, sizeof(bd));
  243. memset(&good_data, 0, sizeof(good_data));
  244. olen = sizeof(good_data);
  245. good_data.size_subflow_data = olen;
  246. ret = getsockopt(fd, SOL_MPTCP, optname, &bd, &olen);
  247. assert(ret < 0); /* 0 size_subflow_data */
  248. assert(olen == sizeof(good_data));
  249. bd.d = good_data;
  250. ret = getsockopt(fd, SOL_MPTCP, optname, &bd, &olen);
  251. assert(ret == 0);
  252. assert(olen == sizeof(good_data));
  253. assert(bd.d.num_subflows == 1);
  254. assert(bd.d.size_kernel > 0);
  255. assert(bd.d.size_user == 0);
  256. bd.d = good_data;
  257. _olen = rand() % olen;
  258. olen = _olen;
  259. ret = getsockopt(fd, SOL_MPTCP, optname, &bd, &olen);
  260. assert(ret < 0); /* bogus olen */
  261. assert(olen == _olen); /* must be unchanged */
  262. bd.d = good_data;
  263. olen = sizeof(good_data);
  264. bd.d.size_kernel = 1;
  265. ret = getsockopt(fd, SOL_MPTCP, optname, &bd, &olen);
  266. assert(ret < 0); /* size_kernel not 0 */
  267. bd.d = good_data;
  268. olen = sizeof(good_data);
  269. bd.d.num_subflows = 1;
  270. ret = getsockopt(fd, SOL_MPTCP, optname, &bd, &olen);
  271. assert(ret < 0); /* num_subflows not 0 */
  272. /* forward compat check: larger struct mptcp_subflow_data on 'old' kernel */
  273. bd.d = good_data;
  274. olen = sizeof(bd);
  275. bd.d.size_subflow_data = sizeof(bd);
  276. ret = getsockopt(fd, SOL_MPTCP, optname, &bd, &olen);
  277. assert(ret == 0);
  278. /* olen must be truncated to real data size filled by kernel: */
  279. assert(olen == sizeof(good_data));
  280. assert(bd.d.size_subflow_data == sizeof(bd));
  281. bd.d = good_data;
  282. bd.d.size_subflow_data += 1;
  283. bd.d.size_user = 1;
  284. olen = bd.d.size_subflow_data + 1;
  285. _olen = olen;
  286. ret = getsockopt(fd, SOL_MPTCP, optname, &bd, &_olen);
  287. assert(ret == 0);
  288. /* no truncation, kernel should have filled 1 byte of optname payload in buf[1]: */
  289. assert(olen == _olen);
  290. assert(bd.d.size_subflow_data == sizeof(good_data) + 1);
  291. assert(bd.buf[0] == 0);
  292. }
  293. static void do_getsockopt_mptcp_info(struct so_state *s, int fd, size_t w)
  294. {
  295. struct mptcp_info i;
  296. socklen_t olen;
  297. int ret;
  298. olen = sizeof(i);
  299. ret = getsockopt(fd, SOL_MPTCP, MPTCP_INFO, &i, &olen);
  300. if (ret < 0)
  301. die_perror("getsockopt MPTCP_INFO");
  302. s->pkt_stats_avail = olen >= sizeof(i);
  303. s->last_sample = i;
  304. if (s->mi.mptcpi_write_seq == 0)
  305. s->mi = i;
  306. assert(s->mi.mptcpi_write_seq + w == i.mptcpi_write_seq);
  307. s->mptcpi_rcv_delta = i.mptcpi_rcv_nxt - s->mi.mptcpi_rcv_nxt;
  308. }
  309. static void do_getsockopt_tcp_info(struct so_state *s, int fd, size_t r, size_t w)
  310. {
  311. struct my_tcp_info {
  312. struct mptcp_subflow_data d;
  313. struct tcp_info ti[2];
  314. } ti;
  315. int ret, tries = 5;
  316. socklen_t olen;
  317. do {
  318. memset(&ti, 0, sizeof(ti));
  319. ti.d.size_subflow_data = sizeof(struct mptcp_subflow_data);
  320. ti.d.size_user = sizeof(struct tcp_info);
  321. olen = sizeof(ti);
  322. ret = getsockopt(fd, SOL_MPTCP, MPTCP_TCPINFO, &ti, &olen);
  323. if (ret < 0)
  324. xerror("getsockopt MPTCP_TCPINFO (tries %d, %m)");
  325. assert(olen <= sizeof(ti));
  326. assert(ti.d.size_kernel > 0);
  327. assert(ti.d.size_user ==
  328. MIN(ti.d.size_kernel, sizeof(struct tcp_info)));
  329. assert(ti.d.num_subflows == 1);
  330. assert(olen > (socklen_t)sizeof(struct mptcp_subflow_data));
  331. olen -= sizeof(struct mptcp_subflow_data);
  332. assert(olen == ti.d.size_user);
  333. s->tcp_info = ti.ti[0];
  334. if (ti.ti[0].tcpi_bytes_sent == w &&
  335. ti.ti[0].tcpi_bytes_received == r)
  336. goto done;
  337. if (r == 0 && ti.ti[0].tcpi_bytes_sent == w &&
  338. ti.ti[0].tcpi_bytes_received) {
  339. s->tcpi_rcv_delta = ti.ti[0].tcpi_bytes_received;
  340. goto done;
  341. }
  342. /* wait and repeat, might be that tx is still ongoing */
  343. sleep(1);
  344. } while (tries-- > 0);
  345. xerror("tcpi_bytes_sent %" PRIu64 ", want %zu. tcpi_bytes_received %" PRIu64 ", want %zu",
  346. ti.ti[0].tcpi_bytes_sent, w, ti.ti[0].tcpi_bytes_received, r);
  347. done:
  348. do_getsockopt_bogus_sf_data(fd, MPTCP_TCPINFO);
  349. }
  350. static void do_getsockopt_subflow_addrs(struct so_state *s, int fd)
  351. {
  352. struct sockaddr_storage remote, local;
  353. socklen_t olen, rlen, llen;
  354. int ret;
  355. struct my_addrs {
  356. struct mptcp_subflow_data d;
  357. struct mptcp_subflow_addrs addr[2];
  358. } addrs;
  359. memset(&addrs, 0, sizeof(addrs));
  360. memset(&local, 0, sizeof(local));
  361. memset(&remote, 0, sizeof(remote));
  362. addrs.d.size_subflow_data = sizeof(struct mptcp_subflow_data);
  363. addrs.d.size_user = sizeof(struct mptcp_subflow_addrs);
  364. olen = sizeof(addrs);
  365. ret = getsockopt(fd, SOL_MPTCP, MPTCP_SUBFLOW_ADDRS, &addrs, &olen);
  366. if (ret < 0)
  367. die_perror("getsockopt MPTCP_SUBFLOW_ADDRS");
  368. assert(olen <= sizeof(addrs));
  369. assert(addrs.d.size_kernel > 0);
  370. assert(addrs.d.size_user ==
  371. MIN(addrs.d.size_kernel, sizeof(struct mptcp_subflow_addrs)));
  372. assert(addrs.d.num_subflows == 1);
  373. assert(olen > (socklen_t)sizeof(struct mptcp_subflow_data));
  374. olen -= sizeof(struct mptcp_subflow_data);
  375. assert(olen == addrs.d.size_user);
  376. llen = sizeof(local);
  377. ret = getsockname(fd, (struct sockaddr *)&local, &llen);
  378. if (ret < 0)
  379. die_perror("getsockname");
  380. rlen = sizeof(remote);
  381. ret = getpeername(fd, (struct sockaddr *)&remote, &rlen);
  382. if (ret < 0)
  383. die_perror("getpeername");
  384. assert(rlen > 0);
  385. assert(rlen == llen);
  386. assert(remote.ss_family == local.ss_family);
  387. assert(memcmp(&local, &addrs.addr[0].ss_local, sizeof(local)) == 0);
  388. assert(memcmp(&remote, &addrs.addr[0].ss_remote, sizeof(remote)) == 0);
  389. s->addrs = addrs.addr[0];
  390. memset(&addrs, 0, sizeof(addrs));
  391. addrs.d.size_subflow_data = sizeof(struct mptcp_subflow_data);
  392. addrs.d.size_user = sizeof(sa_family_t);
  393. olen = sizeof(addrs.d) + sizeof(sa_family_t);
  394. ret = getsockopt(fd, SOL_MPTCP, MPTCP_SUBFLOW_ADDRS, &addrs, &olen);
  395. assert(ret == 0);
  396. assert(olen == sizeof(addrs.d) + sizeof(sa_family_t));
  397. assert(addrs.addr[0].sa_family == pf);
  398. assert(addrs.addr[0].sa_family == local.ss_family);
  399. assert(memcmp(&local, &addrs.addr[0].ss_local, sizeof(local)) != 0);
  400. assert(memcmp(&remote, &addrs.addr[0].ss_remote, sizeof(remote)) != 0);
  401. do_getsockopt_bogus_sf_data(fd, MPTCP_SUBFLOW_ADDRS);
  402. }
  403. static void do_getsockopt_mptcp_full_info(struct so_state *s, int fd)
  404. {
  405. size_t data_size = sizeof(struct mptcp_full_info);
  406. struct mptcp_subflow_info sfinfo[2];
  407. struct tcp_info tcp_info[2];
  408. struct mptcp_full_info mfi;
  409. socklen_t olen;
  410. int ret;
  411. memset(&mfi, 0, data_size);
  412. memset(tcp_info, 0, sizeof(tcp_info));
  413. memset(sfinfo, 0, sizeof(sfinfo));
  414. mfi.size_tcpinfo_user = sizeof(struct tcp_info);
  415. mfi.size_sfinfo_user = sizeof(struct mptcp_subflow_info);
  416. mfi.size_arrays_user = 2;
  417. mfi.subflow_info = (unsigned long)&sfinfo[0];
  418. mfi.tcp_info = (unsigned long)&tcp_info[0];
  419. olen = data_size;
  420. ret = getsockopt(fd, SOL_MPTCP, MPTCP_FULL_INFO, &mfi, &olen);
  421. if (ret < 0) {
  422. if (errno == EOPNOTSUPP) {
  423. perror("MPTCP_FULL_INFO test skipped");
  424. return;
  425. }
  426. xerror("getsockopt MPTCP_FULL_INFO");
  427. }
  428. assert(olen <= data_size);
  429. assert(mfi.size_tcpinfo_kernel > 0);
  430. assert(mfi.size_tcpinfo_user ==
  431. MIN(mfi.size_tcpinfo_kernel, sizeof(struct tcp_info)));
  432. assert(mfi.size_sfinfo_kernel > 0);
  433. assert(mfi.size_sfinfo_user ==
  434. MIN(mfi.size_sfinfo_kernel, sizeof(struct mptcp_subflow_info)));
  435. assert(mfi.num_subflows == 1);
  436. /* Tolerate future extension to mptcp_info struct and running newer
  437. * test on top of older kernel.
  438. * Anyway any kernel supporting MPTCP_FULL_INFO must at least include
  439. * the following in mptcp_info.
  440. */
  441. assert(olen > (socklen_t)__builtin_offsetof(struct mptcp_full_info, tcp_info));
  442. assert(mfi.mptcp_info.mptcpi_subflows == 0);
  443. assert(mfi.mptcp_info.mptcpi_bytes_sent == s->last_sample.mptcpi_bytes_sent);
  444. assert(mfi.mptcp_info.mptcpi_bytes_received == s->last_sample.mptcpi_bytes_received);
  445. assert(sfinfo[0].id == 1);
  446. assert(tcp_info[0].tcpi_bytes_sent == s->tcp_info.tcpi_bytes_sent);
  447. assert(tcp_info[0].tcpi_bytes_received == s->tcp_info.tcpi_bytes_received);
  448. assert(!memcmp(&sfinfo->addrs, &s->addrs, sizeof(struct mptcp_subflow_addrs)));
  449. }
  450. static void do_getsockopts(struct so_state *s, int fd, size_t r, size_t w)
  451. {
  452. do_getsockopt_mptcp_info(s, fd, w);
  453. do_getsockopt_tcp_info(s, fd, r, w);
  454. do_getsockopt_subflow_addrs(s, fd);
  455. if (r)
  456. do_getsockopt_mptcp_full_info(s, fd);
  457. }
  458. static void connect_one_server(int fd, int pipefd)
  459. {
  460. char buf[4096], buf2[4096];
  461. size_t len, i, total;
  462. struct so_state s;
  463. bool eof = false;
  464. ssize_t ret;
  465. memset(&s, 0, sizeof(s));
  466. len = rand() % (sizeof(buf) - 1);
  467. if (len < 128)
  468. len = 128;
  469. for (i = 0; i < len ; i++) {
  470. buf[i] = rand() % 26;
  471. buf[i] += 'A';
  472. }
  473. buf[i] = '\n';
  474. do_getsockopts(&s, fd, 0, 0);
  475. /* un-block server */
  476. ret = read(pipefd, buf2, 4);
  477. assert(ret == 4);
  478. close(pipefd);
  479. assert(strncmp(buf2, "xmit", 4) == 0);
  480. ret = write(fd, buf, len);
  481. if (ret < 0)
  482. die_perror("write");
  483. if (ret != (ssize_t)len)
  484. xerror("short write");
  485. total = 0;
  486. do {
  487. ret = read(fd, buf2 + total, sizeof(buf2) - total);
  488. if (ret < 0)
  489. die_perror("read");
  490. if (ret == 0) {
  491. eof = true;
  492. break;
  493. }
  494. total += ret;
  495. } while (total < len);
  496. if (total != len)
  497. xerror("total %lu, len %lu eof %d\n", total, len, eof);
  498. if (memcmp(buf, buf2, len))
  499. xerror("data corruption");
  500. if (s.tcpi_rcv_delta)
  501. assert(s.tcpi_rcv_delta <= total);
  502. do_getsockopts(&s, fd, ret, ret);
  503. if (eof)
  504. total += 1; /* sequence advances due to FIN */
  505. assert(s.mptcpi_rcv_delta == (uint64_t)total);
  506. close(fd);
  507. }
  508. static void process_one_client(int fd, int pipefd)
  509. {
  510. ssize_t ret, ret2, ret3;
  511. struct so_state s;
  512. char buf[4096];
  513. memset(&s, 0, sizeof(s));
  514. do_getsockopts(&s, fd, 0, 0);
  515. ret = write(pipefd, "xmit", 4);
  516. assert(ret == 4);
  517. ret = read(fd, buf, sizeof(buf));
  518. if (ret < 0)
  519. die_perror("read");
  520. assert(s.mptcpi_rcv_delta <= (uint64_t)ret);
  521. if (s.tcpi_rcv_delta)
  522. assert(s.tcpi_rcv_delta == (uint64_t)ret);
  523. ret2 = write(fd, buf, ret);
  524. if (ret2 < 0)
  525. die_perror("write");
  526. /* wait for hangup */
  527. ret3 = read(fd, buf, 1);
  528. if (ret3 != 0)
  529. xerror("expected EOF, got %lu", ret3);
  530. do_getsockopts(&s, fd, ret, ret2);
  531. if (s.mptcpi_rcv_delta != (uint64_t)ret + 1)
  532. xerror("mptcpi_rcv_delta %" PRIu64 ", expect %" PRIu64 ", diff %" PRId64,
  533. s.mptcpi_rcv_delta, ret + 1, s.mptcpi_rcv_delta - (ret + 1));
  534. /* be nice when running on top of older kernel */
  535. if (s.pkt_stats_avail) {
  536. if (s.last_sample.mptcpi_bytes_sent != ret2)
  537. xerror("mptcpi_bytes_sent %" PRIu64 ", expect %" PRIu64
  538. ", diff %" PRId64,
  539. s.last_sample.mptcpi_bytes_sent, ret2,
  540. s.last_sample.mptcpi_bytes_sent - ret2);
  541. if (s.last_sample.mptcpi_bytes_received != ret)
  542. xerror("mptcpi_bytes_received %" PRIu64 ", expect %" PRIu64
  543. ", diff %" PRId64,
  544. s.last_sample.mptcpi_bytes_received, ret,
  545. s.last_sample.mptcpi_bytes_received - ret);
  546. if (s.last_sample.mptcpi_bytes_acked != ret)
  547. xerror("mptcpi_bytes_acked %" PRIu64 ", expect %" PRIu64
  548. ", diff %" PRId64,
  549. s.last_sample.mptcpi_bytes_acked, ret,
  550. s.last_sample.mptcpi_bytes_acked - ret);
  551. }
  552. close(fd);
  553. }
  554. static int xaccept(int s)
  555. {
  556. int fd = accept(s, NULL, 0);
  557. if (fd < 0)
  558. die_perror("accept");
  559. return fd;
  560. }
  561. static int server(int pipefd)
  562. {
  563. int fd = -1, r;
  564. switch (pf) {
  565. case AF_INET:
  566. fd = sock_listen_mptcp("127.0.0.1", "15432");
  567. break;
  568. case AF_INET6:
  569. fd = sock_listen_mptcp("::1", "15432");
  570. break;
  571. default:
  572. xerror("Unknown pf %d\n", pf);
  573. break;
  574. }
  575. r = write(pipefd, "conn", 4);
  576. assert(r == 4);
  577. alarm(15);
  578. r = xaccept(fd);
  579. process_one_client(r, pipefd);
  580. close(fd);
  581. return 0;
  582. }
  583. static void test_ip_tos_sockopt(int fd)
  584. {
  585. uint8_t tos_in, tos_out;
  586. socklen_t s;
  587. int r;
  588. tos_in = rand() & 0xfc;
  589. r = setsockopt(fd, SOL_IP, IP_TOS, &tos_in, sizeof(tos_out));
  590. if (r != 0)
  591. die_perror("setsockopt IP_TOS");
  592. tos_out = 0;
  593. s = sizeof(tos_out);
  594. r = getsockopt(fd, SOL_IP, IP_TOS, &tos_out, &s);
  595. if (r != 0)
  596. die_perror("getsockopt IP_TOS");
  597. if (tos_in != tos_out)
  598. xerror("tos %x != %x socklen_t %d\n", tos_in, tos_out, s);
  599. if (s != 1)
  600. xerror("tos should be 1 byte");
  601. s = 0;
  602. r = getsockopt(fd, SOL_IP, IP_TOS, &tos_out, &s);
  603. if (r != 0)
  604. die_perror("getsockopt IP_TOS 0");
  605. if (s != 0)
  606. xerror("expect socklen_t == 0");
  607. s = -1;
  608. r = getsockopt(fd, SOL_IP, IP_TOS, &tos_out, &s);
  609. if (r != -1 && errno != EINVAL)
  610. die_perror("getsockopt IP_TOS did not indicate -EINVAL");
  611. if (s != -1)
  612. xerror("expect socklen_t == -1");
  613. }
  614. static int client(int pipefd)
  615. {
  616. int fd = -1;
  617. alarm(15);
  618. switch (pf) {
  619. case AF_INET:
  620. fd = sock_connect_mptcp("127.0.0.1", "15432", IPPROTO_MPTCP);
  621. break;
  622. case AF_INET6:
  623. fd = sock_connect_mptcp("::1", "15432", IPPROTO_MPTCP);
  624. break;
  625. default:
  626. xerror("Unknown pf %d\n", pf);
  627. }
  628. test_ip_tos_sockopt(fd);
  629. connect_one_server(fd, pipefd);
  630. return 0;
  631. }
  632. static pid_t xfork(void)
  633. {
  634. pid_t p = fork();
  635. if (p < 0)
  636. die_perror("fork");
  637. return p;
  638. }
  639. static int rcheck(int wstatus, const char *what)
  640. {
  641. if (WIFEXITED(wstatus)) {
  642. if (WEXITSTATUS(wstatus) == 0)
  643. return 0;
  644. fprintf(stderr, "%s exited, status=%d\n", what, WEXITSTATUS(wstatus));
  645. return WEXITSTATUS(wstatus);
  646. } else if (WIFSIGNALED(wstatus)) {
  647. xerror("%s killed by signal %d\n", what, WTERMSIG(wstatus));
  648. } else if (WIFSTOPPED(wstatus)) {
  649. xerror("%s stopped by signal %d\n", what, WSTOPSIG(wstatus));
  650. }
  651. return 111;
  652. }
  653. static void init_rng(void)
  654. {
  655. int fd = open("/dev/urandom", O_RDONLY);
  656. if (fd >= 0) {
  657. unsigned int foo;
  658. ssize_t ret;
  659. /* can't fail */
  660. ret = read(fd, &foo, sizeof(foo));
  661. assert(ret == sizeof(foo));
  662. close(fd);
  663. srand(foo);
  664. } else {
  665. srand(time(NULL));
  666. }
  667. }
  668. int main(int argc, char *argv[])
  669. {
  670. int e1, e2, wstatus;
  671. pid_t s, c, ret;
  672. int pipefds[2];
  673. parse_opts(argc, argv);
  674. init_rng();
  675. e1 = pipe(pipefds);
  676. if (e1 < 0)
  677. die_perror("pipe");
  678. s = xfork();
  679. if (s == 0) {
  680. close(pipefds[0]);
  681. ret = server(pipefds[1]);
  682. close(pipefds[1]);
  683. return ret;
  684. }
  685. close(pipefds[1]);
  686. /* wait until server bound a socket */
  687. e1 = read(pipefds[0], &e1, 4);
  688. assert(e1 == 4);
  689. c = xfork();
  690. if (c == 0)
  691. return client(pipefds[0]);
  692. close(pipefds[0]);
  693. ret = waitpid(s, &wstatus, 0);
  694. if (ret == -1)
  695. die_perror("waitpid");
  696. e1 = rcheck(wstatus, "server");
  697. ret = waitpid(c, &wstatus, 0);
  698. if (ret == -1)
  699. die_perror("waitpid");
  700. e2 = rcheck(wstatus, "client");
  701. return e1 ? e1 : e2;
  702. }