PageRenderTime 59ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/tools/testing/selftests/bpf/test_sockmap.c

https://gitlab.com/deepcypher/linux
C | 2056 lines | 1739 code | 252 blank | 65 comment | 335 complexity | bfd863781a3dae297d560c7152236d7b MD5 | raw file
  1. // SPDX-License-Identifier: GPL-2.0
  2. // Copyright (c) 2017-2018 Covalent IO, Inc. http://covalent.io
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <sys/socket.h>
  6. #include <sys/ioctl.h>
  7. #include <sys/select.h>
  8. #include <netinet/in.h>
  9. #include <arpa/inet.h>
  10. #include <unistd.h>
  11. #include <string.h>
  12. #include <errno.h>
  13. #include <stdbool.h>
  14. #include <signal.h>
  15. #include <fcntl.h>
  16. #include <sys/wait.h>
  17. #include <time.h>
  18. #include <sched.h>
  19. #include <sys/time.h>
  20. #include <sys/types.h>
  21. #include <sys/sendfile.h>
  22. #include <linux/netlink.h>
  23. #include <linux/socket.h>
  24. #include <linux/sock_diag.h>
  25. #include <linux/bpf.h>
  26. #include <linux/if_link.h>
  27. #include <linux/tls.h>
  28. #include <assert.h>
  29. #include <libgen.h>
  30. #include <getopt.h>
  31. #include <bpf/bpf.h>
  32. #include <bpf/libbpf.h>
  33. #include "bpf_util.h"
  34. #include "cgroup_helpers.h"
  35. int running;
  36. static void running_handler(int a);
  37. #ifndef TCP_ULP
  38. # define TCP_ULP 31
  39. #endif
  40. #ifndef SOL_TLS
  41. # define SOL_TLS 282
  42. #endif
  43. /* randomly selected ports for testing on lo */
  44. #define S1_PORT 10000
  45. #define S2_PORT 10001
  46. #define BPF_SOCKMAP_FILENAME "test_sockmap_kern.o"
  47. #define BPF_SOCKHASH_FILENAME "test_sockhash_kern.o"
  48. #define CG_PATH "/sockmap"
  49. /* global sockets */
  50. int s1, s2, c1, c2, p1, p2;
  51. int test_cnt;
  52. int passed;
  53. int failed;
  54. int map_fd[9];
  55. struct bpf_map *maps[9];
  56. int prog_fd[11];
  57. int txmsg_pass;
  58. int txmsg_redir;
  59. int txmsg_drop;
  60. int txmsg_apply;
  61. int txmsg_cork;
  62. int txmsg_start;
  63. int txmsg_end;
  64. int txmsg_start_push;
  65. int txmsg_end_push;
  66. int txmsg_start_pop;
  67. int txmsg_pop;
  68. int txmsg_ingress;
  69. int txmsg_redir_skb;
  70. int txmsg_ktls_skb;
  71. int txmsg_ktls_skb_drop;
  72. int txmsg_ktls_skb_redir;
  73. int ktls;
  74. int peek_flag;
  75. int skb_use_parser;
  76. int txmsg_omit_skb_parser;
  77. static const struct option long_options[] = {
  78. {"help", no_argument, NULL, 'h' },
  79. {"cgroup", required_argument, NULL, 'c' },
  80. {"rate", required_argument, NULL, 'r' },
  81. {"verbose", optional_argument, NULL, 'v' },
  82. {"iov_count", required_argument, NULL, 'i' },
  83. {"length", required_argument, NULL, 'l' },
  84. {"test", required_argument, NULL, 't' },
  85. {"data_test", no_argument, NULL, 'd' },
  86. {"txmsg", no_argument, &txmsg_pass, 1 },
  87. {"txmsg_redir", no_argument, &txmsg_redir, 1 },
  88. {"txmsg_drop", no_argument, &txmsg_drop, 1 },
  89. {"txmsg_apply", required_argument, NULL, 'a'},
  90. {"txmsg_cork", required_argument, NULL, 'k'},
  91. {"txmsg_start", required_argument, NULL, 's'},
  92. {"txmsg_end", required_argument, NULL, 'e'},
  93. {"txmsg_start_push", required_argument, NULL, 'p'},
  94. {"txmsg_end_push", required_argument, NULL, 'q'},
  95. {"txmsg_start_pop", required_argument, NULL, 'w'},
  96. {"txmsg_pop", required_argument, NULL, 'x'},
  97. {"txmsg_ingress", no_argument, &txmsg_ingress, 1 },
  98. {"txmsg_redir_skb", no_argument, &txmsg_redir_skb, 1 },
  99. {"ktls", no_argument, &ktls, 1 },
  100. {"peek", no_argument, &peek_flag, 1 },
  101. {"txmsg_omit_skb_parser", no_argument, &txmsg_omit_skb_parser, 1},
  102. {"whitelist", required_argument, NULL, 'n' },
  103. {"blacklist", required_argument, NULL, 'b' },
  104. {0, 0, NULL, 0 }
  105. };
  106. struct test_env {
  107. const char *type;
  108. const char *subtest;
  109. const char *prepend;
  110. int test_num;
  111. int subtest_num;
  112. int succ_cnt;
  113. int fail_cnt;
  114. int fail_last;
  115. };
  116. struct test_env env;
  117. struct sockmap_options {
  118. int verbose;
  119. bool base;
  120. bool sendpage;
  121. bool data_test;
  122. bool drop_expected;
  123. bool check_recved_len;
  124. int iov_count;
  125. int iov_length;
  126. int rate;
  127. char *map;
  128. char *whitelist;
  129. char *blacklist;
  130. char *prepend;
  131. };
  132. struct _test {
  133. char *title;
  134. void (*tester)(int cg_fd, struct sockmap_options *opt);
  135. };
  136. static void test_start(void)
  137. {
  138. env.subtest_num++;
  139. }
  140. static void test_fail(void)
  141. {
  142. env.fail_cnt++;
  143. }
  144. static void test_pass(void)
  145. {
  146. env.succ_cnt++;
  147. }
  148. static void test_reset(void)
  149. {
  150. txmsg_start = txmsg_end = 0;
  151. txmsg_start_pop = txmsg_pop = 0;
  152. txmsg_start_push = txmsg_end_push = 0;
  153. txmsg_pass = txmsg_drop = txmsg_redir = 0;
  154. txmsg_apply = txmsg_cork = 0;
  155. txmsg_ingress = txmsg_redir_skb = 0;
  156. txmsg_ktls_skb = txmsg_ktls_skb_drop = txmsg_ktls_skb_redir = 0;
  157. txmsg_omit_skb_parser = 0;
  158. skb_use_parser = 0;
  159. }
  160. static int test_start_subtest(const struct _test *t, struct sockmap_options *o)
  161. {
  162. env.type = o->map;
  163. env.subtest = t->title;
  164. env.prepend = o->prepend;
  165. env.test_num++;
  166. env.subtest_num = 0;
  167. env.fail_last = env.fail_cnt;
  168. test_reset();
  169. return 0;
  170. }
  171. static void test_end_subtest(void)
  172. {
  173. int error = env.fail_cnt - env.fail_last;
  174. int type = strcmp(env.type, BPF_SOCKMAP_FILENAME);
  175. if (!error)
  176. test_pass();
  177. fprintf(stdout, "#%2d/%2d %8s:%s:%s:%s\n",
  178. env.test_num, env.subtest_num,
  179. !type ? "sockmap" : "sockhash",
  180. env.prepend ? : "",
  181. env.subtest, error ? "FAIL" : "OK");
  182. }
  183. static void test_print_results(void)
  184. {
  185. fprintf(stdout, "Pass: %d Fail: %d\n",
  186. env.succ_cnt, env.fail_cnt);
  187. }
  188. static void usage(char *argv[])
  189. {
  190. int i;
  191. printf(" Usage: %s --cgroup <cgroup_path>\n", argv[0]);
  192. printf(" options:\n");
  193. for (i = 0; long_options[i].name != 0; i++) {
  194. printf(" --%-12s", long_options[i].name);
  195. if (long_options[i].flag != NULL)
  196. printf(" flag (internal value:%d)\n",
  197. *long_options[i].flag);
  198. else
  199. printf(" -%c\n", long_options[i].val);
  200. }
  201. printf("\n");
  202. }
  203. char *sock_to_string(int s)
  204. {
  205. if (s == c1)
  206. return "client1";
  207. else if (s == c2)
  208. return "client2";
  209. else if (s == s1)
  210. return "server1";
  211. else if (s == s2)
  212. return "server2";
  213. else if (s == p1)
  214. return "peer1";
  215. else if (s == p2)
  216. return "peer2";
  217. else
  218. return "unknown";
  219. }
  220. static int sockmap_init_ktls(int verbose, int s)
  221. {
  222. struct tls12_crypto_info_aes_gcm_128 tls_tx = {
  223. .info = {
  224. .version = TLS_1_2_VERSION,
  225. .cipher_type = TLS_CIPHER_AES_GCM_128,
  226. },
  227. };
  228. struct tls12_crypto_info_aes_gcm_128 tls_rx = {
  229. .info = {
  230. .version = TLS_1_2_VERSION,
  231. .cipher_type = TLS_CIPHER_AES_GCM_128,
  232. },
  233. };
  234. int so_buf = 6553500;
  235. int err;
  236. err = setsockopt(s, 6, TCP_ULP, "tls", sizeof("tls"));
  237. if (err) {
  238. fprintf(stderr, "setsockopt: TCP_ULP(%s) failed with error %i\n", sock_to_string(s), err);
  239. return -EINVAL;
  240. }
  241. err = setsockopt(s, SOL_TLS, TLS_TX, (void *)&tls_tx, sizeof(tls_tx));
  242. if (err) {
  243. fprintf(stderr, "setsockopt: TLS_TX(%s) failed with error %i\n", sock_to_string(s), err);
  244. return -EINVAL;
  245. }
  246. err = setsockopt(s, SOL_TLS, TLS_RX, (void *)&tls_rx, sizeof(tls_rx));
  247. if (err) {
  248. fprintf(stderr, "setsockopt: TLS_RX(%s) failed with error %i\n", sock_to_string(s), err);
  249. return -EINVAL;
  250. }
  251. err = setsockopt(s, SOL_SOCKET, SO_SNDBUF, &so_buf, sizeof(so_buf));
  252. if (err) {
  253. fprintf(stderr, "setsockopt: (%s) failed sndbuf with error %i\n", sock_to_string(s), err);
  254. return -EINVAL;
  255. }
  256. err = setsockopt(s, SOL_SOCKET, SO_RCVBUF, &so_buf, sizeof(so_buf));
  257. if (err) {
  258. fprintf(stderr, "setsockopt: (%s) failed rcvbuf with error %i\n", sock_to_string(s), err);
  259. return -EINVAL;
  260. }
  261. if (verbose)
  262. fprintf(stdout, "socket(%s) kTLS enabled\n", sock_to_string(s));
  263. return 0;
  264. }
  265. static int sockmap_init_sockets(int verbose)
  266. {
  267. int i, err, one = 1;
  268. struct sockaddr_in addr;
  269. int *fds[4] = {&s1, &s2, &c1, &c2};
  270. s1 = s2 = p1 = p2 = c1 = c2 = 0;
  271. /* Init sockets */
  272. for (i = 0; i < 4; i++) {
  273. *fds[i] = socket(AF_INET, SOCK_STREAM, 0);
  274. if (*fds[i] < 0) {
  275. perror("socket s1 failed()");
  276. return errno;
  277. }
  278. }
  279. /* Allow reuse */
  280. for (i = 0; i < 2; i++) {
  281. err = setsockopt(*fds[i], SOL_SOCKET, SO_REUSEADDR,
  282. (char *)&one, sizeof(one));
  283. if (err) {
  284. perror("setsockopt failed()");
  285. return errno;
  286. }
  287. }
  288. /* Non-blocking sockets */
  289. for (i = 0; i < 2; i++) {
  290. err = ioctl(*fds[i], FIONBIO, (char *)&one);
  291. if (err < 0) {
  292. perror("ioctl s1 failed()");
  293. return errno;
  294. }
  295. }
  296. /* Bind server sockets */
  297. memset(&addr, 0, sizeof(struct sockaddr_in));
  298. addr.sin_family = AF_INET;
  299. addr.sin_addr.s_addr = inet_addr("127.0.0.1");
  300. addr.sin_port = htons(S1_PORT);
  301. err = bind(s1, (struct sockaddr *)&addr, sizeof(addr));
  302. if (err < 0) {
  303. perror("bind s1 failed()");
  304. return errno;
  305. }
  306. addr.sin_port = htons(S2_PORT);
  307. err = bind(s2, (struct sockaddr *)&addr, sizeof(addr));
  308. if (err < 0) {
  309. perror("bind s2 failed()");
  310. return errno;
  311. }
  312. /* Listen server sockets */
  313. addr.sin_port = htons(S1_PORT);
  314. err = listen(s1, 32);
  315. if (err < 0) {
  316. perror("listen s1 failed()");
  317. return errno;
  318. }
  319. addr.sin_port = htons(S2_PORT);
  320. err = listen(s2, 32);
  321. if (err < 0) {
  322. perror("listen s1 failed()");
  323. return errno;
  324. }
  325. /* Initiate Connect */
  326. addr.sin_port = htons(S1_PORT);
  327. err = connect(c1, (struct sockaddr *)&addr, sizeof(addr));
  328. if (err < 0 && errno != EINPROGRESS) {
  329. perror("connect c1 failed()");
  330. return errno;
  331. }
  332. addr.sin_port = htons(S2_PORT);
  333. err = connect(c2, (struct sockaddr *)&addr, sizeof(addr));
  334. if (err < 0 && errno != EINPROGRESS) {
  335. perror("connect c2 failed()");
  336. return errno;
  337. } else if (err < 0) {
  338. err = 0;
  339. }
  340. /* Accept Connecrtions */
  341. p1 = accept(s1, NULL, NULL);
  342. if (p1 < 0) {
  343. perror("accept s1 failed()");
  344. return errno;
  345. }
  346. p2 = accept(s2, NULL, NULL);
  347. if (p2 < 0) {
  348. perror("accept s1 failed()");
  349. return errno;
  350. }
  351. if (verbose > 1) {
  352. printf("connected sockets: c1 <-> p1, c2 <-> p2\n");
  353. printf("cgroups binding: c1(%i) <-> s1(%i) - - - c2(%i) <-> s2(%i)\n",
  354. c1, s1, c2, s2);
  355. }
  356. return 0;
  357. }
  358. struct msg_stats {
  359. size_t bytes_sent;
  360. size_t bytes_recvd;
  361. struct timespec start;
  362. struct timespec end;
  363. };
  364. static int msg_loop_sendpage(int fd, int iov_length, int cnt,
  365. struct msg_stats *s,
  366. struct sockmap_options *opt)
  367. {
  368. bool drop = opt->drop_expected;
  369. unsigned char k = 0;
  370. FILE *file;
  371. int i, fp;
  372. file = tmpfile();
  373. if (!file) {
  374. perror("create file for sendpage");
  375. return 1;
  376. }
  377. for (i = 0; i < iov_length * cnt; i++, k++)
  378. fwrite(&k, sizeof(char), 1, file);
  379. fflush(file);
  380. fseek(file, 0, SEEK_SET);
  381. fp = fileno(file);
  382. clock_gettime(CLOCK_MONOTONIC, &s->start);
  383. for (i = 0; i < cnt; i++) {
  384. int sent;
  385. errno = 0;
  386. sent = sendfile(fd, fp, NULL, iov_length);
  387. if (!drop && sent < 0) {
  388. perror("sendpage loop error");
  389. fclose(file);
  390. return sent;
  391. } else if (drop && sent >= 0) {
  392. printf("sendpage loop error expected: %i errno %i\n",
  393. sent, errno);
  394. fclose(file);
  395. return -EIO;
  396. }
  397. if (sent > 0)
  398. s->bytes_sent += sent;
  399. }
  400. clock_gettime(CLOCK_MONOTONIC, &s->end);
  401. fclose(file);
  402. return 0;
  403. }
  404. static void msg_free_iov(struct msghdr *msg)
  405. {
  406. int i;
  407. for (i = 0; i < msg->msg_iovlen; i++)
  408. free(msg->msg_iov[i].iov_base);
  409. free(msg->msg_iov);
  410. msg->msg_iov = NULL;
  411. msg->msg_iovlen = 0;
  412. }
  413. static int msg_alloc_iov(struct msghdr *msg,
  414. int iov_count, int iov_length,
  415. bool data, bool xmit)
  416. {
  417. unsigned char k = 0;
  418. struct iovec *iov;
  419. int i;
  420. iov = calloc(iov_count, sizeof(struct iovec));
  421. if (!iov)
  422. return errno;
  423. for (i = 0; i < iov_count; i++) {
  424. unsigned char *d = calloc(iov_length, sizeof(char));
  425. if (!d) {
  426. fprintf(stderr, "iov_count %i/%i OOM\n", i, iov_count);
  427. goto unwind_iov;
  428. }
  429. iov[i].iov_base = d;
  430. iov[i].iov_len = iov_length;
  431. if (data && xmit) {
  432. int j;
  433. for (j = 0; j < iov_length; j++)
  434. d[j] = k++;
  435. }
  436. }
  437. msg->msg_iov = iov;
  438. msg->msg_iovlen = iov_count;
  439. return 0;
  440. unwind_iov:
  441. for (i--; i >= 0 ; i--)
  442. free(msg->msg_iov[i].iov_base);
  443. return -ENOMEM;
  444. }
  445. static int msg_verify_data(struct msghdr *msg, int size, int chunk_sz)
  446. {
  447. int i, j = 0, bytes_cnt = 0;
  448. unsigned char k = 0;
  449. for (i = 0; i < msg->msg_iovlen; i++) {
  450. unsigned char *d = msg->msg_iov[i].iov_base;
  451. /* Special case test for skb ingress + ktls */
  452. if (i == 0 && txmsg_ktls_skb) {
  453. if (msg->msg_iov[i].iov_len < 4)
  454. return -EIO;
  455. if (memcmp(d, "PASS", 4) != 0) {
  456. fprintf(stderr,
  457. "detected skb data error with skb ingress update @iov[%i]:%i \"%02x %02x %02x %02x\" != \"PASS\"\n",
  458. i, 0, d[0], d[1], d[2], d[3]);
  459. return -EIO;
  460. }
  461. j = 4; /* advance index past PASS header */
  462. }
  463. for (; j < msg->msg_iov[i].iov_len && size; j++) {
  464. if (d[j] != k++) {
  465. fprintf(stderr,
  466. "detected data corruption @iov[%i]:%i %02x != %02x, %02x ?= %02x\n",
  467. i, j, d[j], k - 1, d[j+1], k);
  468. return -EIO;
  469. }
  470. bytes_cnt++;
  471. if (bytes_cnt == chunk_sz) {
  472. k = 0;
  473. bytes_cnt = 0;
  474. }
  475. size--;
  476. }
  477. }
  478. return 0;
  479. }
  480. static int msg_loop(int fd, int iov_count, int iov_length, int cnt,
  481. struct msg_stats *s, bool tx,
  482. struct sockmap_options *opt)
  483. {
  484. struct msghdr msg = {0}, msg_peek = {0};
  485. int err, i, flags = MSG_NOSIGNAL;
  486. bool drop = opt->drop_expected;
  487. bool data = opt->data_test;
  488. int iov_alloc_length = iov_length;
  489. if (!tx && opt->check_recved_len)
  490. iov_alloc_length *= 2;
  491. err = msg_alloc_iov(&msg, iov_count, iov_alloc_length, data, tx);
  492. if (err)
  493. goto out_errno;
  494. if (peek_flag) {
  495. err = msg_alloc_iov(&msg_peek, iov_count, iov_length, data, tx);
  496. if (err)
  497. goto out_errno;
  498. }
  499. if (tx) {
  500. clock_gettime(CLOCK_MONOTONIC, &s->start);
  501. for (i = 0; i < cnt; i++) {
  502. int sent;
  503. errno = 0;
  504. sent = sendmsg(fd, &msg, flags);
  505. if (!drop && sent < 0) {
  506. perror("sendmsg loop error");
  507. goto out_errno;
  508. } else if (drop && sent >= 0) {
  509. fprintf(stderr,
  510. "sendmsg loop error expected: %i errno %i\n",
  511. sent, errno);
  512. errno = -EIO;
  513. goto out_errno;
  514. }
  515. if (sent > 0)
  516. s->bytes_sent += sent;
  517. }
  518. clock_gettime(CLOCK_MONOTONIC, &s->end);
  519. } else {
  520. int slct, recvp = 0, recv, max_fd = fd;
  521. float total_bytes, txmsg_pop_total;
  522. int fd_flags = O_NONBLOCK;
  523. struct timeval timeout;
  524. fd_set w;
  525. fcntl(fd, fd_flags);
  526. /* Account for pop bytes noting each iteration of apply will
  527. * call msg_pop_data helper so we need to account for this
  528. * by calculating the number of apply iterations. Note user
  529. * of the tool can create cases where no data is sent by
  530. * manipulating pop/push/pull/etc. For example txmsg_apply 1
  531. * with txmsg_pop 1 will try to apply 1B at a time but each
  532. * iteration will then pop 1B so no data will ever be sent.
  533. * This is really only useful for testing edge cases in code
  534. * paths.
  535. */
  536. total_bytes = (float)iov_count * (float)iov_length * (float)cnt;
  537. if (txmsg_apply)
  538. txmsg_pop_total = txmsg_pop * (total_bytes / txmsg_apply);
  539. else
  540. txmsg_pop_total = txmsg_pop * cnt;
  541. total_bytes -= txmsg_pop_total;
  542. err = clock_gettime(CLOCK_MONOTONIC, &s->start);
  543. if (err < 0)
  544. perror("recv start time");
  545. while (s->bytes_recvd < total_bytes) {
  546. if (txmsg_cork) {
  547. timeout.tv_sec = 0;
  548. timeout.tv_usec = 300000;
  549. } else {
  550. timeout.tv_sec = 3;
  551. timeout.tv_usec = 0;
  552. }
  553. /* FD sets */
  554. FD_ZERO(&w);
  555. FD_SET(fd, &w);
  556. slct = select(max_fd + 1, &w, NULL, NULL, &timeout);
  557. if (slct == -1) {
  558. perror("select()");
  559. clock_gettime(CLOCK_MONOTONIC, &s->end);
  560. goto out_errno;
  561. } else if (!slct) {
  562. if (opt->verbose)
  563. fprintf(stderr, "unexpected timeout: recved %zu/%f pop_total %f\n", s->bytes_recvd, total_bytes, txmsg_pop_total);
  564. errno = -EIO;
  565. clock_gettime(CLOCK_MONOTONIC, &s->end);
  566. goto out_errno;
  567. }
  568. errno = 0;
  569. if (peek_flag) {
  570. flags |= MSG_PEEK;
  571. recvp = recvmsg(fd, &msg_peek, flags);
  572. if (recvp < 0) {
  573. if (errno != EWOULDBLOCK) {
  574. clock_gettime(CLOCK_MONOTONIC, &s->end);
  575. goto out_errno;
  576. }
  577. }
  578. flags = 0;
  579. }
  580. recv = recvmsg(fd, &msg, flags);
  581. if (recv < 0) {
  582. if (errno != EWOULDBLOCK) {
  583. clock_gettime(CLOCK_MONOTONIC, &s->end);
  584. perror("recv failed()");
  585. goto out_errno;
  586. }
  587. }
  588. s->bytes_recvd += recv;
  589. if (opt->check_recved_len && s->bytes_recvd > total_bytes) {
  590. errno = EMSGSIZE;
  591. fprintf(stderr, "recv failed(), bytes_recvd:%zd, total_bytes:%f\n",
  592. s->bytes_recvd, total_bytes);
  593. goto out_errno;
  594. }
  595. if (data) {
  596. int chunk_sz = opt->sendpage ?
  597. iov_length * cnt :
  598. iov_length * iov_count;
  599. errno = msg_verify_data(&msg, recv, chunk_sz);
  600. if (errno) {
  601. perror("data verify msg failed");
  602. goto out_errno;
  603. }
  604. if (recvp) {
  605. errno = msg_verify_data(&msg_peek,
  606. recvp,
  607. chunk_sz);
  608. if (errno) {
  609. perror("data verify msg_peek failed");
  610. goto out_errno;
  611. }
  612. }
  613. }
  614. }
  615. clock_gettime(CLOCK_MONOTONIC, &s->end);
  616. }
  617. msg_free_iov(&msg);
  618. msg_free_iov(&msg_peek);
  619. return err;
  620. out_errno:
  621. msg_free_iov(&msg);
  622. msg_free_iov(&msg_peek);
  623. return errno;
  624. }
  625. static float giga = 1000000000;
  626. static inline float sentBps(struct msg_stats s)
  627. {
  628. return s.bytes_sent / (s.end.tv_sec - s.start.tv_sec);
  629. }
  630. static inline float recvdBps(struct msg_stats s)
  631. {
  632. return s.bytes_recvd / (s.end.tv_sec - s.start.tv_sec);
  633. }
  634. static int sendmsg_test(struct sockmap_options *opt)
  635. {
  636. float sent_Bps = 0, recvd_Bps = 0;
  637. int rx_fd, txpid, rxpid, err = 0;
  638. struct msg_stats s = {0};
  639. int iov_count = opt->iov_count;
  640. int iov_buf = opt->iov_length;
  641. int rx_status, tx_status;
  642. int cnt = opt->rate;
  643. errno = 0;
  644. if (opt->base)
  645. rx_fd = p1;
  646. else
  647. rx_fd = p2;
  648. if (ktls) {
  649. /* Redirecting into non-TLS socket which sends into a TLS
  650. * socket is not a valid test. So in this case lets not
  651. * enable kTLS but still run the test.
  652. */
  653. if (!txmsg_redir || txmsg_ingress) {
  654. err = sockmap_init_ktls(opt->verbose, rx_fd);
  655. if (err)
  656. return err;
  657. }
  658. err = sockmap_init_ktls(opt->verbose, c1);
  659. if (err)
  660. return err;
  661. }
  662. rxpid = fork();
  663. if (rxpid == 0) {
  664. if (txmsg_pop || txmsg_start_pop)
  665. iov_buf -= (txmsg_pop - txmsg_start_pop + 1);
  666. if (opt->drop_expected || txmsg_ktls_skb_drop)
  667. _exit(0);
  668. if (!iov_buf) /* zero bytes sent case */
  669. _exit(0);
  670. if (opt->sendpage)
  671. iov_count = 1;
  672. err = msg_loop(rx_fd, iov_count, iov_buf,
  673. cnt, &s, false, opt);
  674. if (opt->verbose > 1)
  675. fprintf(stderr,
  676. "msg_loop_rx: iov_count %i iov_buf %i cnt %i err %i\n",
  677. iov_count, iov_buf, cnt, err);
  678. if (s.end.tv_sec - s.start.tv_sec) {
  679. sent_Bps = sentBps(s);
  680. recvd_Bps = recvdBps(s);
  681. }
  682. if (opt->verbose > 1)
  683. fprintf(stdout,
  684. "rx_sendmsg: TX: %zuB %fB/s %fGB/s RX: %zuB %fB/s %fGB/s %s\n",
  685. s.bytes_sent, sent_Bps, sent_Bps/giga,
  686. s.bytes_recvd, recvd_Bps, recvd_Bps/giga,
  687. peek_flag ? "(peek_msg)" : "");
  688. if (err && txmsg_cork)
  689. err = 0;
  690. exit(err ? 1 : 0);
  691. } else if (rxpid == -1) {
  692. perror("msg_loop_rx");
  693. return errno;
  694. }
  695. txpid = fork();
  696. if (txpid == 0) {
  697. if (opt->sendpage)
  698. err = msg_loop_sendpage(c1, iov_buf, cnt, &s, opt);
  699. else
  700. err = msg_loop(c1, iov_count, iov_buf,
  701. cnt, &s, true, opt);
  702. if (err)
  703. fprintf(stderr,
  704. "msg_loop_tx: iov_count %i iov_buf %i cnt %i err %i\n",
  705. iov_count, iov_buf, cnt, err);
  706. if (s.end.tv_sec - s.start.tv_sec) {
  707. sent_Bps = sentBps(s);
  708. recvd_Bps = recvdBps(s);
  709. }
  710. if (opt->verbose > 1)
  711. fprintf(stdout,
  712. "tx_sendmsg: TX: %zuB %fB/s %f GB/s RX: %zuB %fB/s %fGB/s\n",
  713. s.bytes_sent, sent_Bps, sent_Bps/giga,
  714. s.bytes_recvd, recvd_Bps, recvd_Bps/giga);
  715. exit(err ? 1 : 0);
  716. } else if (txpid == -1) {
  717. perror("msg_loop_tx");
  718. return errno;
  719. }
  720. assert(waitpid(rxpid, &rx_status, 0) == rxpid);
  721. assert(waitpid(txpid, &tx_status, 0) == txpid);
  722. if (WIFEXITED(rx_status)) {
  723. err = WEXITSTATUS(rx_status);
  724. if (err) {
  725. fprintf(stderr, "rx thread exited with err %d.\n", err);
  726. goto out;
  727. }
  728. }
  729. if (WIFEXITED(tx_status)) {
  730. err = WEXITSTATUS(tx_status);
  731. if (err)
  732. fprintf(stderr, "tx thread exited with err %d.\n", err);
  733. }
  734. out:
  735. return err;
  736. }
  737. static int forever_ping_pong(int rate, struct sockmap_options *opt)
  738. {
  739. struct timeval timeout;
  740. char buf[1024] = {0};
  741. int sc;
  742. timeout.tv_sec = 10;
  743. timeout.tv_usec = 0;
  744. /* Ping/Pong data from client to server */
  745. sc = send(c1, buf, sizeof(buf), 0);
  746. if (sc < 0) {
  747. perror("send failed()");
  748. return sc;
  749. }
  750. do {
  751. int s, rc, i, max_fd = p2;
  752. fd_set w;
  753. /* FD sets */
  754. FD_ZERO(&w);
  755. FD_SET(c1, &w);
  756. FD_SET(c2, &w);
  757. FD_SET(p1, &w);
  758. FD_SET(p2, &w);
  759. s = select(max_fd + 1, &w, NULL, NULL, &timeout);
  760. if (s == -1) {
  761. perror("select()");
  762. break;
  763. } else if (!s) {
  764. fprintf(stderr, "unexpected timeout\n");
  765. break;
  766. }
  767. for (i = 0; i <= max_fd && s > 0; ++i) {
  768. if (!FD_ISSET(i, &w))
  769. continue;
  770. s--;
  771. rc = recv(i, buf, sizeof(buf), 0);
  772. if (rc < 0) {
  773. if (errno != EWOULDBLOCK) {
  774. perror("recv failed()");
  775. return rc;
  776. }
  777. }
  778. if (rc == 0) {
  779. close(i);
  780. break;
  781. }
  782. sc = send(i, buf, rc, 0);
  783. if (sc < 0) {
  784. perror("send failed()");
  785. return sc;
  786. }
  787. }
  788. if (rate)
  789. sleep(rate);
  790. if (opt->verbose) {
  791. printf(".");
  792. fflush(stdout);
  793. }
  794. } while (running);
  795. return 0;
  796. }
  797. enum {
  798. SELFTESTS,
  799. PING_PONG,
  800. SENDMSG,
  801. BASE,
  802. BASE_SENDPAGE,
  803. SENDPAGE,
  804. };
  805. static int run_options(struct sockmap_options *options, int cg_fd, int test)
  806. {
  807. int i, key, next_key, err, tx_prog_fd = -1, zero = 0;
  808. /* If base test skip BPF setup */
  809. if (test == BASE || test == BASE_SENDPAGE)
  810. goto run;
  811. /* Attach programs to sockmap */
  812. if (!txmsg_omit_skb_parser) {
  813. err = bpf_prog_attach(prog_fd[0], map_fd[0],
  814. BPF_SK_SKB_STREAM_PARSER, 0);
  815. if (err) {
  816. fprintf(stderr,
  817. "ERROR: bpf_prog_attach (sockmap %i->%i): %d (%s)\n",
  818. prog_fd[0], map_fd[0], err, strerror(errno));
  819. return err;
  820. }
  821. }
  822. err = bpf_prog_attach(prog_fd[1], map_fd[0],
  823. BPF_SK_SKB_STREAM_VERDICT, 0);
  824. if (err) {
  825. fprintf(stderr, "ERROR: bpf_prog_attach (sockmap): %d (%s)\n",
  826. err, strerror(errno));
  827. return err;
  828. }
  829. /* Attach programs to TLS sockmap */
  830. if (txmsg_ktls_skb) {
  831. if (!txmsg_omit_skb_parser) {
  832. err = bpf_prog_attach(prog_fd[0], map_fd[8],
  833. BPF_SK_SKB_STREAM_PARSER, 0);
  834. if (err) {
  835. fprintf(stderr,
  836. "ERROR: bpf_prog_attach (TLS sockmap %i->%i): %d (%s)\n",
  837. prog_fd[0], map_fd[8], err, strerror(errno));
  838. return err;
  839. }
  840. }
  841. err = bpf_prog_attach(prog_fd[2], map_fd[8],
  842. BPF_SK_SKB_STREAM_VERDICT, 0);
  843. if (err) {
  844. fprintf(stderr, "ERROR: bpf_prog_attach (TLS sockmap): %d (%s)\n",
  845. err, strerror(errno));
  846. return err;
  847. }
  848. }
  849. /* Attach to cgroups */
  850. err = bpf_prog_attach(prog_fd[3], cg_fd, BPF_CGROUP_SOCK_OPS, 0);
  851. if (err) {
  852. fprintf(stderr, "ERROR: bpf_prog_attach (groups): %d (%s)\n",
  853. err, strerror(errno));
  854. return err;
  855. }
  856. run:
  857. err = sockmap_init_sockets(options->verbose);
  858. if (err) {
  859. fprintf(stderr, "ERROR: test socket failed: %d\n", err);
  860. goto out;
  861. }
  862. /* Attach txmsg program to sockmap */
  863. if (txmsg_pass)
  864. tx_prog_fd = prog_fd[4];
  865. else if (txmsg_redir)
  866. tx_prog_fd = prog_fd[5];
  867. else if (txmsg_apply)
  868. tx_prog_fd = prog_fd[6];
  869. else if (txmsg_cork)
  870. tx_prog_fd = prog_fd[7];
  871. else if (txmsg_drop)
  872. tx_prog_fd = prog_fd[8];
  873. else
  874. tx_prog_fd = 0;
  875. if (tx_prog_fd) {
  876. int redir_fd, i = 0;
  877. err = bpf_prog_attach(tx_prog_fd,
  878. map_fd[1], BPF_SK_MSG_VERDICT, 0);
  879. if (err) {
  880. fprintf(stderr,
  881. "ERROR: bpf_prog_attach (txmsg): %d (%s)\n",
  882. err, strerror(errno));
  883. goto out;
  884. }
  885. err = bpf_map_update_elem(map_fd[1], &i, &c1, BPF_ANY);
  886. if (err) {
  887. fprintf(stderr,
  888. "ERROR: bpf_map_update_elem (txmsg): %d (%s\n",
  889. err, strerror(errno));
  890. goto out;
  891. }
  892. if (txmsg_redir)
  893. redir_fd = c2;
  894. else
  895. redir_fd = c1;
  896. err = bpf_map_update_elem(map_fd[2], &i, &redir_fd, BPF_ANY);
  897. if (err) {
  898. fprintf(stderr,
  899. "ERROR: bpf_map_update_elem (txmsg): %d (%s\n",
  900. err, strerror(errno));
  901. goto out;
  902. }
  903. if (txmsg_apply) {
  904. err = bpf_map_update_elem(map_fd[3],
  905. &i, &txmsg_apply, BPF_ANY);
  906. if (err) {
  907. fprintf(stderr,
  908. "ERROR: bpf_map_update_elem (apply_bytes): %d (%s\n",
  909. err, strerror(errno));
  910. goto out;
  911. }
  912. }
  913. if (txmsg_cork) {
  914. err = bpf_map_update_elem(map_fd[4],
  915. &i, &txmsg_cork, BPF_ANY);
  916. if (err) {
  917. fprintf(stderr,
  918. "ERROR: bpf_map_update_elem (cork_bytes): %d (%s\n",
  919. err, strerror(errno));
  920. goto out;
  921. }
  922. }
  923. if (txmsg_start) {
  924. err = bpf_map_update_elem(map_fd[5],
  925. &i, &txmsg_start, BPF_ANY);
  926. if (err) {
  927. fprintf(stderr,
  928. "ERROR: bpf_map_update_elem (txmsg_start): %d (%s)\n",
  929. err, strerror(errno));
  930. goto out;
  931. }
  932. }
  933. if (txmsg_end) {
  934. i = 1;
  935. err = bpf_map_update_elem(map_fd[5],
  936. &i, &txmsg_end, BPF_ANY);
  937. if (err) {
  938. fprintf(stderr,
  939. "ERROR: bpf_map_update_elem (txmsg_end): %d (%s)\n",
  940. err, strerror(errno));
  941. goto out;
  942. }
  943. }
  944. if (txmsg_start_push) {
  945. i = 2;
  946. err = bpf_map_update_elem(map_fd[5],
  947. &i, &txmsg_start_push, BPF_ANY);
  948. if (err) {
  949. fprintf(stderr,
  950. "ERROR: bpf_map_update_elem (txmsg_start_push): %d (%s)\n",
  951. err, strerror(errno));
  952. goto out;
  953. }
  954. }
  955. if (txmsg_end_push) {
  956. i = 3;
  957. err = bpf_map_update_elem(map_fd[5],
  958. &i, &txmsg_end_push, BPF_ANY);
  959. if (err) {
  960. fprintf(stderr,
  961. "ERROR: bpf_map_update_elem %i@%i (txmsg_end_push): %d (%s)\n",
  962. txmsg_end_push, i, err, strerror(errno));
  963. goto out;
  964. }
  965. }
  966. if (txmsg_start_pop) {
  967. i = 4;
  968. err = bpf_map_update_elem(map_fd[5],
  969. &i, &txmsg_start_pop, BPF_ANY);
  970. if (err) {
  971. fprintf(stderr,
  972. "ERROR: bpf_map_update_elem %i@%i (txmsg_start_pop): %d (%s)\n",
  973. txmsg_start_pop, i, err, strerror(errno));
  974. goto out;
  975. }
  976. } else {
  977. i = 4;
  978. bpf_map_update_elem(map_fd[5],
  979. &i, &txmsg_start_pop, BPF_ANY);
  980. }
  981. if (txmsg_pop) {
  982. i = 5;
  983. err = bpf_map_update_elem(map_fd[5],
  984. &i, &txmsg_pop, BPF_ANY);
  985. if (err) {
  986. fprintf(stderr,
  987. "ERROR: bpf_map_update_elem %i@%i (txmsg_pop): %d (%s)\n",
  988. txmsg_pop, i, err, strerror(errno));
  989. goto out;
  990. }
  991. } else {
  992. i = 5;
  993. bpf_map_update_elem(map_fd[5],
  994. &i, &txmsg_pop, BPF_ANY);
  995. }
  996. if (txmsg_ingress) {
  997. int in = BPF_F_INGRESS;
  998. i = 0;
  999. err = bpf_map_update_elem(map_fd[6], &i, &in, BPF_ANY);
  1000. if (err) {
  1001. fprintf(stderr,
  1002. "ERROR: bpf_map_update_elem (txmsg_ingress): %d (%s)\n",
  1003. err, strerror(errno));
  1004. }
  1005. i = 1;
  1006. err = bpf_map_update_elem(map_fd[1], &i, &p1, BPF_ANY);
  1007. if (err) {
  1008. fprintf(stderr,
  1009. "ERROR: bpf_map_update_elem (p1 txmsg): %d (%s)\n",
  1010. err, strerror(errno));
  1011. }
  1012. err = bpf_map_update_elem(map_fd[2], &i, &p1, BPF_ANY);
  1013. if (err) {
  1014. fprintf(stderr,
  1015. "ERROR: bpf_map_update_elem (p1 redir): %d (%s)\n",
  1016. err, strerror(errno));
  1017. }
  1018. i = 2;
  1019. err = bpf_map_update_elem(map_fd[2], &i, &p2, BPF_ANY);
  1020. if (err) {
  1021. fprintf(stderr,
  1022. "ERROR: bpf_map_update_elem (p2 txmsg): %d (%s)\n",
  1023. err, strerror(errno));
  1024. }
  1025. }
  1026. if (txmsg_ktls_skb) {
  1027. int ingress = BPF_F_INGRESS;
  1028. i = 0;
  1029. err = bpf_map_update_elem(map_fd[8], &i, &p2, BPF_ANY);
  1030. if (err) {
  1031. fprintf(stderr,
  1032. "ERROR: bpf_map_update_elem (c1 sockmap): %d (%s)\n",
  1033. err, strerror(errno));
  1034. }
  1035. if (txmsg_ktls_skb_redir) {
  1036. i = 1;
  1037. err = bpf_map_update_elem(map_fd[7],
  1038. &i, &ingress, BPF_ANY);
  1039. if (err) {
  1040. fprintf(stderr,
  1041. "ERROR: bpf_map_update_elem (txmsg_ingress): %d (%s)\n",
  1042. err, strerror(errno));
  1043. }
  1044. }
  1045. if (txmsg_ktls_skb_drop) {
  1046. i = 1;
  1047. err = bpf_map_update_elem(map_fd[7], &i, &i, BPF_ANY);
  1048. }
  1049. }
  1050. if (txmsg_redir_skb) {
  1051. int skb_fd = (test == SENDMSG || test == SENDPAGE) ?
  1052. p2 : p1;
  1053. int ingress = BPF_F_INGRESS;
  1054. i = 0;
  1055. err = bpf_map_update_elem(map_fd[7],
  1056. &i, &ingress, BPF_ANY);
  1057. if (err) {
  1058. fprintf(stderr,
  1059. "ERROR: bpf_map_update_elem (txmsg_ingress): %d (%s)\n",
  1060. err, strerror(errno));
  1061. }
  1062. i = 3;
  1063. err = bpf_map_update_elem(map_fd[0], &i, &skb_fd, BPF_ANY);
  1064. if (err) {
  1065. fprintf(stderr,
  1066. "ERROR: bpf_map_update_elem (c1 sockmap): %d (%s)\n",
  1067. err, strerror(errno));
  1068. }
  1069. }
  1070. }
  1071. if (skb_use_parser) {
  1072. i = 2;
  1073. err = bpf_map_update_elem(map_fd[7], &i, &skb_use_parser, BPF_ANY);
  1074. }
  1075. if (txmsg_drop)
  1076. options->drop_expected = true;
  1077. if (test == PING_PONG)
  1078. err = forever_ping_pong(options->rate, options);
  1079. else if (test == SENDMSG) {
  1080. options->base = false;
  1081. options->sendpage = false;
  1082. err = sendmsg_test(options);
  1083. } else if (test == SENDPAGE) {
  1084. options->base = false;
  1085. options->sendpage = true;
  1086. err = sendmsg_test(options);
  1087. } else if (test == BASE) {
  1088. options->base = true;
  1089. options->sendpage = false;
  1090. err = sendmsg_test(options);
  1091. } else if (test == BASE_SENDPAGE) {
  1092. options->base = true;
  1093. options->sendpage = true;
  1094. err = sendmsg_test(options);
  1095. } else
  1096. fprintf(stderr, "unknown test\n");
  1097. out:
  1098. /* Detatch and zero all the maps */
  1099. bpf_prog_detach2(prog_fd[3], cg_fd, BPF_CGROUP_SOCK_OPS);
  1100. bpf_prog_detach2(prog_fd[0], map_fd[0], BPF_SK_SKB_STREAM_PARSER);
  1101. bpf_prog_detach2(prog_fd[1], map_fd[0], BPF_SK_SKB_STREAM_VERDICT);
  1102. bpf_prog_detach2(prog_fd[0], map_fd[8], BPF_SK_SKB_STREAM_PARSER);
  1103. bpf_prog_detach2(prog_fd[2], map_fd[8], BPF_SK_SKB_STREAM_VERDICT);
  1104. if (tx_prog_fd >= 0)
  1105. bpf_prog_detach2(tx_prog_fd, map_fd[1], BPF_SK_MSG_VERDICT);
  1106. for (i = 0; i < 8; i++) {
  1107. key = next_key = 0;
  1108. bpf_map_update_elem(map_fd[i], &key, &zero, BPF_ANY);
  1109. while (bpf_map_get_next_key(map_fd[i], &key, &next_key) == 0) {
  1110. bpf_map_update_elem(map_fd[i], &key, &zero, BPF_ANY);
  1111. key = next_key;
  1112. }
  1113. }
  1114. close(s1);
  1115. close(s2);
  1116. close(p1);
  1117. close(p2);
  1118. close(c1);
  1119. close(c2);
  1120. return err;
  1121. }
  1122. static char *test_to_str(int test)
  1123. {
  1124. switch (test) {
  1125. case SENDMSG:
  1126. return "sendmsg";
  1127. case SENDPAGE:
  1128. return "sendpage";
  1129. }
  1130. return "unknown";
  1131. }
  1132. static void append_str(char *dst, const char *src, size_t dst_cap)
  1133. {
  1134. size_t avail = dst_cap - strlen(dst);
  1135. if (avail <= 1) /* just zero byte could be written */
  1136. return;
  1137. strncat(dst, src, avail - 1); /* strncat() adds + 1 for zero byte */
  1138. }
  1139. #define OPTSTRING 60
  1140. static void test_options(char *options)
  1141. {
  1142. char tstr[OPTSTRING];
  1143. memset(options, 0, OPTSTRING);
  1144. if (txmsg_pass)
  1145. append_str(options, "pass,", OPTSTRING);
  1146. if (txmsg_redir)
  1147. append_str(options, "redir,", OPTSTRING);
  1148. if (txmsg_drop)
  1149. append_str(options, "drop,", OPTSTRING);
  1150. if (txmsg_apply) {
  1151. snprintf(tstr, OPTSTRING, "apply %d,", txmsg_apply);
  1152. append_str(options, tstr, OPTSTRING);
  1153. }
  1154. if (txmsg_cork) {
  1155. snprintf(tstr, OPTSTRING, "cork %d,", txmsg_cork);
  1156. append_str(options, tstr, OPTSTRING);
  1157. }
  1158. if (txmsg_start) {
  1159. snprintf(tstr, OPTSTRING, "start %d,", txmsg_start);
  1160. append_str(options, tstr, OPTSTRING);
  1161. }
  1162. if (txmsg_end) {
  1163. snprintf(tstr, OPTSTRING, "end %d,", txmsg_end);
  1164. append_str(options, tstr, OPTSTRING);
  1165. }
  1166. if (txmsg_start_pop) {
  1167. snprintf(tstr, OPTSTRING, "pop (%d,%d),",
  1168. txmsg_start_pop, txmsg_start_pop + txmsg_pop);
  1169. append_str(options, tstr, OPTSTRING);
  1170. }
  1171. if (txmsg_ingress)
  1172. append_str(options, "ingress,", OPTSTRING);
  1173. if (txmsg_redir_skb)
  1174. append_str(options, "redir_skb,", OPTSTRING);
  1175. if (txmsg_ktls_skb)
  1176. append_str(options, "ktls_skb,", OPTSTRING);
  1177. if (ktls)
  1178. append_str(options, "ktls,", OPTSTRING);
  1179. if (peek_flag)
  1180. append_str(options, "peek,", OPTSTRING);
  1181. }
  1182. static int __test_exec(int cgrp, int test, struct sockmap_options *opt)
  1183. {
  1184. char *options = calloc(OPTSTRING, sizeof(char));
  1185. int err;
  1186. if (test == SENDPAGE)
  1187. opt->sendpage = true;
  1188. else
  1189. opt->sendpage = false;
  1190. if (txmsg_drop)
  1191. opt->drop_expected = true;
  1192. else
  1193. opt->drop_expected = false;
  1194. test_options(options);
  1195. if (opt->verbose) {
  1196. fprintf(stdout,
  1197. " [TEST %i]: (%i, %i, %i, %s, %s): ",
  1198. test_cnt, opt->rate, opt->iov_count, opt->iov_length,
  1199. test_to_str(test), options);
  1200. fflush(stdout);
  1201. }
  1202. err = run_options(opt, cgrp, test);
  1203. if (opt->verbose)
  1204. fprintf(stdout, " %s\n", !err ? "PASS" : "FAILED");
  1205. test_cnt++;
  1206. !err ? passed++ : failed++;
  1207. free(options);
  1208. return err;
  1209. }
  1210. static void test_exec(int cgrp, struct sockmap_options *opt)
  1211. {
  1212. int type = strcmp(opt->map, BPF_SOCKMAP_FILENAME);
  1213. int err;
  1214. if (type == 0) {
  1215. test_start();
  1216. err = __test_exec(cgrp, SENDMSG, opt);
  1217. if (err)
  1218. test_fail();
  1219. } else {
  1220. test_start();
  1221. err = __test_exec(cgrp, SENDPAGE, opt);
  1222. if (err)
  1223. test_fail();
  1224. }
  1225. }
  1226. static void test_send_one(struct sockmap_options *opt, int cgrp)
  1227. {
  1228. opt->iov_length = 1;
  1229. opt->iov_count = 1;
  1230. opt->rate = 1;
  1231. test_exec(cgrp, opt);
  1232. opt->iov_length = 1;
  1233. opt->iov_count = 1024;
  1234. opt->rate = 1;
  1235. test_exec(cgrp, opt);
  1236. opt->iov_length = 1024;
  1237. opt->iov_count = 1;
  1238. opt->rate = 1;
  1239. test_exec(cgrp, opt);
  1240. }
  1241. static void test_send_many(struct sockmap_options *opt, int cgrp)
  1242. {
  1243. opt->iov_length = 3;
  1244. opt->iov_count = 1;
  1245. opt->rate = 512;
  1246. test_exec(cgrp, opt);
  1247. opt->rate = 100;
  1248. opt->iov_count = 1;
  1249. opt->iov_length = 5;
  1250. test_exec(cgrp, opt);
  1251. }
  1252. static void test_send_large(struct sockmap_options *opt, int cgrp)
  1253. {
  1254. opt->iov_length = 256;
  1255. opt->iov_count = 1024;
  1256. opt->rate = 2;
  1257. test_exec(cgrp, opt);
  1258. }
  1259. static void test_send(struct sockmap_options *opt, int cgrp)
  1260. {
  1261. test_send_one(opt, cgrp);
  1262. test_send_many(opt, cgrp);
  1263. test_send_large(opt, cgrp);
  1264. sched_yield();
  1265. }
  1266. static void test_txmsg_pass(int cgrp, struct sockmap_options *opt)
  1267. {
  1268. /* Test small and large iov_count values with pass/redir/apply/cork */
  1269. txmsg_pass = 1;
  1270. test_send(opt, cgrp);
  1271. }
  1272. static void test_txmsg_redir(int cgrp, struct sockmap_options *opt)
  1273. {
  1274. txmsg_redir = 1;
  1275. test_send(opt, cgrp);
  1276. }
  1277. static void test_txmsg_drop(int cgrp, struct sockmap_options *opt)
  1278. {
  1279. txmsg_drop = 1;
  1280. test_send(opt, cgrp);
  1281. }
  1282. static void test_txmsg_ingress_redir(int cgrp, struct sockmap_options *opt)
  1283. {
  1284. txmsg_pass = txmsg_drop = 0;
  1285. txmsg_ingress = txmsg_redir = 1;
  1286. test_send(opt, cgrp);
  1287. }
  1288. static void test_txmsg_skb(int cgrp, struct sockmap_options *opt)
  1289. {
  1290. bool data = opt->data_test;
  1291. int k = ktls;
  1292. opt->data_test = true;
  1293. ktls = 1;
  1294. txmsg_pass = txmsg_drop = 0;
  1295. txmsg_ingress = txmsg_redir = 0;
  1296. txmsg_ktls_skb = 1;
  1297. txmsg_pass = 1;
  1298. /* Using data verification so ensure iov layout is
  1299. * expected from test receiver side. e.g. has enough
  1300. * bytes to write test code.
  1301. */
  1302. opt->iov_length = 100;
  1303. opt->iov_count = 1;
  1304. opt->rate = 1;
  1305. test_exec(cgrp, opt);
  1306. txmsg_ktls_skb_drop = 1;
  1307. test_exec(cgrp, opt);
  1308. txmsg_ktls_skb_drop = 0;
  1309. txmsg_ktls_skb_redir = 1;
  1310. test_exec(cgrp, opt);
  1311. txmsg_ktls_skb_redir = 0;
  1312. /* Tests that omit skb_parser */
  1313. txmsg_omit_skb_parser = 1;
  1314. ktls = 0;
  1315. txmsg_ktls_skb = 0;
  1316. test_exec(cgrp, opt);
  1317. txmsg_ktls_skb_drop = 1;
  1318. test_exec(cgrp, opt);
  1319. txmsg_ktls_skb_drop = 0;
  1320. txmsg_ktls_skb_redir = 1;
  1321. test_exec(cgrp, opt);
  1322. ktls = 1;
  1323. test_exec(cgrp, opt);
  1324. txmsg_omit_skb_parser = 0;
  1325. opt->data_test = data;
  1326. ktls = k;
  1327. }
  1328. /* Test cork with hung data. This tests poor usage patterns where
  1329. * cork can leave data on the ring if user program is buggy and
  1330. * doesn't flush them somehow. They do take some time however
  1331. * because they wait for a timeout. Test pass, redir and cork with
  1332. * apply logic. Use cork size of 4097 with send_large to avoid
  1333. * aligning cork size with send size.
  1334. */
  1335. static void test_txmsg_cork_hangs(int cgrp, struct sockmap_options *opt)
  1336. {
  1337. txmsg_pass = 1;
  1338. txmsg_redir = 0;
  1339. txmsg_cork = 4097;
  1340. txmsg_apply = 4097;
  1341. test_send_large(opt, cgrp);
  1342. txmsg_pass = 0;
  1343. txmsg_redir = 1;
  1344. txmsg_apply = 0;
  1345. txmsg_cork = 4097;
  1346. test_send_large(opt, cgrp);
  1347. txmsg_pass = 0;
  1348. txmsg_redir = 1;
  1349. txmsg_apply = 4097;
  1350. txmsg_cork = 4097;
  1351. test_send_large(opt, cgrp);
  1352. }
  1353. static void test_txmsg_pull(int cgrp, struct sockmap_options *opt)
  1354. {
  1355. /* Test basic start/end */
  1356. txmsg_start = 1;
  1357. txmsg_end = 2;
  1358. test_send(opt, cgrp);
  1359. /* Test >4k pull */
  1360. txmsg_start = 4096;
  1361. txmsg_end = 9182;
  1362. test_send_large(opt, cgrp);
  1363. /* Test pull + redirect */
  1364. txmsg_redir = 0;
  1365. txmsg_start = 1;
  1366. txmsg_end = 2;
  1367. test_send(opt, cgrp);
  1368. /* Test pull + cork */
  1369. txmsg_redir = 0;
  1370. txmsg_cork = 512;
  1371. txmsg_start = 1;
  1372. txmsg_end = 2;
  1373. test_send_many(opt, cgrp);
  1374. /* Test pull + cork + redirect */
  1375. txmsg_redir = 1;
  1376. txmsg_cork = 512;
  1377. txmsg_start = 1;
  1378. txmsg_end = 2;
  1379. test_send_many(opt, cgrp);
  1380. }
  1381. static void test_txmsg_pop(int cgrp, struct sockmap_options *opt)
  1382. {
  1383. /* Test basic pop */
  1384. txmsg_start_pop = 1;
  1385. txmsg_pop = 2;
  1386. test_send_many(opt, cgrp);
  1387. /* Test pop with >4k */
  1388. txmsg_start_pop = 4096;
  1389. txmsg_pop = 4096;
  1390. test_send_large(opt, cgrp);
  1391. /* Test pop + redirect */
  1392. txmsg_redir = 1;
  1393. txmsg_start_pop = 1;
  1394. txmsg_pop = 2;
  1395. test_send_many(opt, cgrp);
  1396. /* Test pop + cork */
  1397. txmsg_redir = 0;
  1398. txmsg_cork = 512;
  1399. txmsg_start_pop = 1;
  1400. txmsg_pop = 2;
  1401. test_send_many(opt, cgrp);
  1402. /* Test pop + redirect + cork */
  1403. txmsg_redir = 1;
  1404. txmsg_cork = 4;
  1405. txmsg_start_pop = 1;
  1406. txmsg_pop = 2;
  1407. test_send_many(opt, cgrp);
  1408. }
  1409. static void test_txmsg_push(int cgrp, struct sockmap_options *opt)
  1410. {
  1411. /* Test basic push */
  1412. txmsg_start_push = 1;
  1413. txmsg_end_push = 1;
  1414. test_send(opt, cgrp);
  1415. /* Test push 4kB >4k */
  1416. txmsg_start_push = 4096;
  1417. txmsg_end_push = 4096;
  1418. test_send_large(opt, cgrp);
  1419. /* Test push + redirect */
  1420. txmsg_redir = 1;
  1421. txmsg_start_push = 1;
  1422. txmsg_end_push = 2;
  1423. test_send_many(opt, cgrp);
  1424. /* Test push + cork */
  1425. txmsg_redir = 0;
  1426. txmsg_cork = 512;
  1427. txmsg_start_push = 1;
  1428. txmsg_end_push = 2;
  1429. test_send_many(opt, cgrp);
  1430. }
  1431. static void test_txmsg_push_pop(int cgrp, struct sockmap_options *opt)
  1432. {
  1433. txmsg_start_push = 1;
  1434. txmsg_end_push = 10;
  1435. txmsg_start_pop = 5;
  1436. txmsg_pop = 4;
  1437. test_send_large(opt, cgrp);
  1438. }
  1439. static void test_txmsg_apply(int cgrp, struct sockmap_options *opt)
  1440. {
  1441. txmsg_pass = 1;
  1442. txmsg_redir = 0;
  1443. txmsg_apply = 1;
  1444. txmsg_cork = 0;
  1445. test_send_one(opt, cgrp);
  1446. txmsg_pass = 0;
  1447. txmsg_redir = 1;
  1448. txmsg_apply = 1;
  1449. txmsg_cork = 0;
  1450. test_send_one(opt, cgrp);
  1451. txmsg_pass = 1;
  1452. txmsg_redir = 0;
  1453. txmsg_apply = 1024;
  1454. txmsg_cork = 0;
  1455. test_send_large(opt, cgrp);
  1456. txmsg_pass = 0;
  1457. txmsg_redir = 1;
  1458. txmsg_apply = 1024;
  1459. txmsg_cork = 0;
  1460. test_send_large(opt, cgrp);
  1461. }
  1462. static void test_txmsg_cork(int cgrp, struct sockmap_options *opt)
  1463. {
  1464. txmsg_pass = 1;
  1465. txmsg_redir = 0;
  1466. txmsg_apply = 0;
  1467. txmsg_cork = 1;
  1468. test_send(opt, cgrp);
  1469. txmsg_pass = 1;
  1470. txmsg_redir = 0;
  1471. txmsg_apply = 1;
  1472. txmsg_cork = 1;
  1473. test_send(opt, cgrp);
  1474. }
  1475. static void test_txmsg_ingress_parser(int cgrp, struct sockmap_options *opt)
  1476. {
  1477. txmsg_pass = 1;
  1478. skb_use_parser = 512;
  1479. if (ktls == 1)
  1480. skb_use_parser = 570;
  1481. opt->iov_length = 256;
  1482. opt->iov_count = 1;
  1483. opt->rate = 2;
  1484. test_exec(cgrp, opt);
  1485. }
  1486. static void test_txmsg_ingress_parser2(int cgrp, struct sockmap_options *opt)
  1487. {
  1488. if (ktls == 1)
  1489. return;
  1490. skb_use_parser = 10;
  1491. opt->iov_length = 20;
  1492. opt->iov_count = 1;
  1493. opt->rate = 1;
  1494. opt->check_recved_len = true;
  1495. test_exec(cgrp, opt);
  1496. opt->check_recved_len = false;
  1497. }
  1498. char *map_names[] = {
  1499. "sock_map",
  1500. "sock_map_txmsg",
  1501. "sock_map_redir",
  1502. "sock_apply_bytes",
  1503. "sock_cork_bytes",
  1504. "sock_bytes",
  1505. "sock_redir_flags",
  1506. "sock_skb_opts",
  1507. "tls_sock_map",
  1508. };
  1509. int prog_attach_type[] = {
  1510. BPF_SK_SKB_STREAM_PARSER,
  1511. BPF_SK_SKB_STREAM_VERDICT,
  1512. BPF_SK_SKB_STREAM_VERDICT,
  1513. BPF_CGROUP_SOCK_OPS,
  1514. BPF_SK_MSG_VERDICT,
  1515. BPF_SK_MSG_VERDICT,
  1516. BPF_SK_MSG_VERDICT,
  1517. BPF_SK_MSG_VERDICT,
  1518. BPF_SK_MSG_VERDICT,
  1519. BPF_SK_MSG_VERDICT,
  1520. BPF_SK_MSG_VERDICT,
  1521. };
  1522. int prog_type[] = {
  1523. BPF_PROG_TYPE_SK_SKB,
  1524. BPF_PROG_TYPE_SK_SKB,
  1525. BPF_PROG_TYPE_SK_SKB,
  1526. BPF_PROG_TYPE_SOCK_OPS,
  1527. BPF_PROG_TYPE_SK_MSG,
  1528. BPF_PROG_TYPE_SK_MSG,
  1529. BPF_PROG_TYPE_SK_MSG,
  1530. BPF_PROG_TYPE_SK_MSG,
  1531. BPF_PROG_TYPE_SK_MSG,
  1532. BPF_PROG_TYPE_SK_MSG,
  1533. BPF_PROG_TYPE_SK_MSG,
  1534. };
  1535. static int populate_progs(char *bpf_file)
  1536. {
  1537. struct bpf_program *prog;
  1538. struct bpf_object *obj;
  1539. int i = 0;
  1540. long err;
  1541. obj = bpf_object__open(bpf_file);
  1542. err = libbpf_get_error(obj);
  1543. if (err) {
  1544. char err_buf[256];
  1545. libbpf_strerror(err, err_buf, sizeof(err_buf));
  1546. printf("Unable to load eBPF objects in file '%s' : %s\n",
  1547. bpf_file, err_buf);
  1548. return -1;
  1549. }
  1550. bpf_object__for_each_program(prog, obj) {
  1551. bpf_program__set_type(prog, prog_type[i]);
  1552. bpf_program__set_expected_attach_type(prog,
  1553. prog_attach_type[i]);
  1554. i++;
  1555. }
  1556. i = bpf_object__load(obj);
  1557. i = 0;
  1558. bpf_object__for_each_program(prog, obj) {
  1559. prog_fd[i] = bpf_program__fd(prog);
  1560. i++;
  1561. }
  1562. for (i = 0; i < ARRAY_SIZE(map_fd); i++) {
  1563. maps[i] = bpf_object__find_map_by_name(obj, map_names[i]);
  1564. map_fd[i] = bpf_map__fd(maps[i]);
  1565. if (map_fd[i] < 0) {
  1566. fprintf(stderr, "load_bpf_file: (%i) %s\n",
  1567. map_fd[i], strerror(errno));
  1568. return -1;
  1569. }
  1570. }
  1571. return 0;
  1572. }
  1573. struct _test test[] = {
  1574. {"txmsg test passthrough", test_txmsg_pass},
  1575. {"txmsg test redirect", test_txmsg_redir},
  1576. {"txmsg test drop", test_txmsg_drop},
  1577. {"txmsg test ingress redirect", test_txmsg_ingress_redir},
  1578. {"txmsg test skb", test_txmsg_skb},
  1579. {"txmsg test apply", test_txmsg_apply},
  1580. {"txmsg test cork", test_txmsg_cork},
  1581. {"txmsg test hanging corks", test_txmsg_cork_hangs},
  1582. {"txmsg test push_data", test_txmsg_push},
  1583. {"txmsg test pull-data", test_txmsg_pull},
  1584. {"txmsg test pop-data", test_txmsg_pop},
  1585. {"txmsg test push/pop data", test_txmsg_push_pop},
  1586. {"txmsg test ingress parser", test_txmsg_ingress_parser},
  1587. {"txmsg test ingress parser2", test_txmsg_ingress_parser2},
  1588. };
  1589. static int check_whitelist(struct _test *t, struct sockmap_options *opt)
  1590. {
  1591. char *entry, *ptr;
  1592. if (!opt->whitelist)
  1593. return 0;
  1594. ptr = strdup(opt->whitelist);
  1595. if (!ptr)
  1596. return -ENOMEM;
  1597. entry = strtok(ptr, ",");
  1598. while (entry) {
  1599. if ((opt->prepend && strstr(opt->prepend, entry) != 0) ||
  1600. strstr(opt->map, entry) != 0 ||
  1601. strstr(t->title, entry) != 0)
  1602. return 0;
  1603. entry = strtok(NULL, ",");
  1604. }
  1605. return -EINVAL;
  1606. }
  1607. static int check_blacklist(struct _test *t, struct sockmap_options *opt)
  1608. {
  1609. char *entry, *ptr;
  1610. if (!opt->blacklist)
  1611. return -EINVAL;
  1612. ptr = strdup(opt->blacklist);
  1613. if (!ptr)
  1614. return -ENOMEM;
  1615. entry = strtok(ptr, ",");
  1616. while (entry) {
  1617. if ((opt->prepend && strstr(opt->prepend, entry) != 0) ||
  1618. strstr(opt->map, entry) != 0 ||
  1619. strstr(t->title, entry) != 0)
  1620. return 0;
  1621. entry = strtok(NULL, ",");
  1622. }
  1623. return -EINVAL;
  1624. }
  1625. static int __test_selftests(int cg_fd, struct sockmap_options *opt)
  1626. {
  1627. int i, err;
  1628. err = populate_progs(opt->map);
  1629. if (err < 0) {
  1630. fprintf(stderr, "ERROR: (%i) load bpf failed\n", err);
  1631. return err;
  1632. }
  1633. /* Tests basic commands and APIs */
  1634. for (i = 0; i < ARRAY_SIZE(test); i++) {
  1635. struct _test t = test[i];
  1636. if (check_whitelist(&t, opt) != 0)
  1637. continue;
  1638. if (check_blacklist(&t, opt) == 0)
  1639. continue;
  1640. test_start_subtest(&t, opt);
  1641. t.tester(cg_fd, opt);
  1642. test_end_subtest();
  1643. }
  1644. return err;
  1645. }
  1646. static void test_selftests_sockmap(int cg_fd, struct sockmap_options *opt)
  1647. {
  1648. opt->map = BPF_SOCKMAP_FILENAME;
  1649. __test_selftests(cg_fd, opt);
  1650. }
  1651. static void test_selftests_sockhash(int cg_fd, struct sockmap_options *opt)
  1652. {
  1653. opt->map = BPF_SOCKHASH_FILENAME;
  1654. __test_selftests(cg_fd, opt);
  1655. }
  1656. static void test_selftests_ktls(int cg_fd, struct sockmap_options *opt)
  1657. {
  1658. opt->map = BPF_SOCKHASH_FILENAME;
  1659. opt->prepend = "ktls";
  1660. ktls = 1;
  1661. __test_selftests(cg_fd, opt);
  1662. ktls = 0;
  1663. }
  1664. static int test_selftest(int cg_fd, struct sockmap_options *opt)
  1665. {
  1666. test_selftests_sockmap(cg_fd, opt);
  1667. test_selftests_sockhash(cg_fd, opt);
  1668. test_selftests_ktls(cg_fd, opt);
  1669. test_print_results();
  1670. return 0;
  1671. }
  1672. int main(int argc, char **argv)
  1673. {
  1674. int iov_count = 1, length = 1024, rate = 1;
  1675. struct sockmap_options options = {0};
  1676. int opt, longindex, err, cg_fd = 0;
  1677. char *bpf_file = BPF_SOCKMAP_FILENAME;
  1678. int test = SELFTESTS;
  1679. bool cg_created = 0;
  1680. while ((opt = getopt_long(argc, argv, ":dhv:c:r:i:l:t:p:q:n:b:",
  1681. long_options, &longindex)) != -1) {
  1682. switch (opt) {
  1683. case 's':
  1684. txmsg_start = atoi(optarg);
  1685. break;
  1686. case 'e':
  1687. txmsg_end = atoi(optarg);
  1688. break;
  1689. case 'p':
  1690. txmsg_start_push = atoi(optarg);
  1691. break;
  1692. case 'q':
  1693. txmsg_end_push = atoi(optarg);
  1694. break;
  1695. case 'w':
  1696. txmsg_start_pop = atoi(optarg);
  1697. break;
  1698. case 'x':
  1699. txmsg_pop = atoi(optarg);
  1700. break;
  1701. case 'a':
  1702. txmsg_apply = atoi(optarg);
  1703. break;
  1704. case 'k':
  1705. txmsg_cork = atoi(optarg);
  1706. break;
  1707. case 'c':
  1708. cg_fd = open(optarg, O_DIRECTORY, O_RDONLY);
  1709. if (cg_fd < 0) {
  1710. fprintf(stderr,
  1711. "ERROR: (%i) open cg path failed: %s\n",
  1712. cg_fd, optarg);
  1713. return cg_fd;
  1714. }
  1715. break;
  1716. case 'r':
  1717. rate = atoi(optarg);
  1718. break;
  1719. case 'v':
  1720. options.verbose = 1;
  1721. if (optarg)
  1722. options.verbose = atoi(optarg);
  1723. break;
  1724. case 'i':
  1725. iov_count = atoi(optarg);
  1726. break;
  1727. case 'l':
  1728. length = atoi(optarg);
  1729. break;
  1730. case 'd':
  1731. options.data_test = true;
  1732. break;
  1733. case 't':
  1734. if (strcmp(optarg, "ping") == 0) {
  1735. test = PING_PONG;
  1736. } else if (strcmp(optarg, "sendmsg") == 0) {
  1737. test = SENDMSG;
  1738. } else if (strcmp(optarg, "base") == 0) {
  1739. test = BASE;
  1740. } else if (strcmp(optarg, "base_sendpage") == 0) {
  1741. test = BASE_SENDPAGE;
  1742. } else if (strcmp(optarg, "sendpage") == 0) {
  1743. test = SENDPAGE;
  1744. } else {
  1745. usage(argv);
  1746. return -1;
  1747. }
  1748. break;
  1749. case 'n':
  1750. options.whitelist = strdup(optarg);
  1751. if (!options.whitelist)
  1752. return -ENOMEM;
  1753. break;
  1754. case 'b':
  1755. options.blacklist = strdup(optarg);
  1756. if (!options.blacklist)
  1757. return -ENOMEM;
  1758. case 0:
  1759. break;
  1760. case 'h':
  1761. default:
  1762. usage(argv);
  1763. return -1;
  1764. }
  1765. }
  1766. if (!cg_fd) {
  1767. cg_fd = cgroup_setup_and_join(CG_PATH);
  1768. if (cg_fd < 0)
  1769. return cg_fd;
  1770. cg_created = 1;
  1771. }
  1772. /* Use libbpf 1.0 API mode */
  1773. libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
  1774. if (test == SELFTESTS) {
  1775. err = test_selftest(cg_fd, &options);
  1776. goto out;
  1777. }
  1778. err = populate_progs(bpf_file);
  1779. if (err) {
  1780. fprintf(stderr, "populate program: (%s) %s\n",
  1781. bpf_file, strerror(errno));
  1782. return 1;
  1783. }
  1784. running = 1;
  1785. /* catch SIGINT */
  1786. signal(SIGINT, running_handler);
  1787. options.iov_count = iov_count;
  1788. options.iov_length = length;
  1789. options.rate = rate;
  1790. err = run_options(&options, cg_fd, test);
  1791. out:
  1792. if (options.whitelist)
  1793. free(options.whitelist);
  1794. if (options.blacklist)
  1795. free(options.blacklist);
  1796. if (cg_created)
  1797. cleanup_cgroup_environment();
  1798. close(cg_fd);
  1799. return err;
  1800. }
  1801. void running_handler(int a)
  1802. {
  1803. running = 0;
  1804. }