PageRenderTime 29ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

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

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