test_sockmap.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524
  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 <sys/ioctl.h>
  14. #include <stdbool.h>
  15. #include <signal.h>
  16. #include <fcntl.h>
  17. #include <sys/wait.h>
  18. #include <time.h>
  19. #include <sched.h>
  20. #include <sys/time.h>
  21. #include <sys/resource.h>
  22. #include <sys/types.h>
  23. #include <sys/sendfile.h>
  24. #include <linux/netlink.h>
  25. #include <linux/socket.h>
  26. #include <linux/sock_diag.h>
  27. #include <linux/bpf.h>
  28. #include <linux/if_link.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. /* randomly selected ports for testing on lo */
  40. #define S1_PORT 10000
  41. #define S2_PORT 10001
  42. #define BPF_SOCKMAP_FILENAME "test_sockmap_kern.o"
  43. #define BPF_SOCKHASH_FILENAME "test_sockhash_kern.o"
  44. #define CG_PATH "/sockmap"
  45. /* global sockets */
  46. int s1, s2, c1, c2, p1, p2;
  47. int test_cnt;
  48. int passed;
  49. int failed;
  50. int map_fd[8];
  51. struct bpf_map *maps[8];
  52. int prog_fd[11];
  53. int txmsg_pass;
  54. int txmsg_noisy;
  55. int txmsg_redir;
  56. int txmsg_redir_noisy;
  57. int txmsg_drop;
  58. int txmsg_apply;
  59. int txmsg_cork;
  60. int txmsg_start;
  61. int txmsg_end;
  62. int txmsg_ingress;
  63. int txmsg_skb;
  64. static const struct option long_options[] = {
  65. {"help", no_argument, NULL, 'h' },
  66. {"cgroup", required_argument, NULL, 'c' },
  67. {"rate", required_argument, NULL, 'r' },
  68. {"verbose", no_argument, NULL, 'v' },
  69. {"iov_count", required_argument, NULL, 'i' },
  70. {"length", required_argument, NULL, 'l' },
  71. {"test", required_argument, NULL, 't' },
  72. {"data_test", no_argument, NULL, 'd' },
  73. {"txmsg", no_argument, &txmsg_pass, 1 },
  74. {"txmsg_noisy", no_argument, &txmsg_noisy, 1 },
  75. {"txmsg_redir", no_argument, &txmsg_redir, 1 },
  76. {"txmsg_redir_noisy", no_argument, &txmsg_redir_noisy, 1},
  77. {"txmsg_drop", no_argument, &txmsg_drop, 1 },
  78. {"txmsg_apply", required_argument, NULL, 'a'},
  79. {"txmsg_cork", required_argument, NULL, 'k'},
  80. {"txmsg_start", required_argument, NULL, 's'},
  81. {"txmsg_end", required_argument, NULL, 'e'},
  82. {"txmsg_ingress", no_argument, &txmsg_ingress, 1 },
  83. {"txmsg_skb", no_argument, &txmsg_skb, 1 },
  84. {0, 0, NULL, 0 }
  85. };
  86. static void usage(char *argv[])
  87. {
  88. int i;
  89. printf(" Usage: %s --cgroup <cgroup_path>\n", argv[0]);
  90. printf(" options:\n");
  91. for (i = 0; long_options[i].name != 0; i++) {
  92. printf(" --%-12s", long_options[i].name);
  93. if (long_options[i].flag != NULL)
  94. printf(" flag (internal value:%d)\n",
  95. *long_options[i].flag);
  96. else
  97. printf(" -%c\n", long_options[i].val);
  98. }
  99. printf("\n");
  100. }
  101. static int sockmap_init_sockets(int verbose)
  102. {
  103. int i, err, one = 1;
  104. struct sockaddr_in addr;
  105. int *fds[4] = {&s1, &s2, &c1, &c2};
  106. s1 = s2 = p1 = p2 = c1 = c2 = 0;
  107. /* Init sockets */
  108. for (i = 0; i < 4; i++) {
  109. *fds[i] = socket(AF_INET, SOCK_STREAM, 0);
  110. if (*fds[i] < 0) {
  111. perror("socket s1 failed()");
  112. return errno;
  113. }
  114. }
  115. /* Allow reuse */
  116. for (i = 0; i < 2; i++) {
  117. err = setsockopt(*fds[i], SOL_SOCKET, SO_REUSEADDR,
  118. (char *)&one, sizeof(one));
  119. if (err) {
  120. perror("setsockopt failed()");
  121. return errno;
  122. }
  123. }
  124. /* Non-blocking sockets */
  125. for (i = 0; i < 2; i++) {
  126. err = ioctl(*fds[i], FIONBIO, (char *)&one);
  127. if (err < 0) {
  128. perror("ioctl s1 failed()");
  129. return errno;
  130. }
  131. }
  132. /* Bind server sockets */
  133. memset(&addr, 0, sizeof(struct sockaddr_in));
  134. addr.sin_family = AF_INET;
  135. addr.sin_addr.s_addr = inet_addr("127.0.0.1");
  136. addr.sin_port = htons(S1_PORT);
  137. err = bind(s1, (struct sockaddr *)&addr, sizeof(addr));
  138. if (err < 0) {
  139. perror("bind s1 failed()\n");
  140. return errno;
  141. }
  142. addr.sin_port = htons(S2_PORT);
  143. err = bind(s2, (struct sockaddr *)&addr, sizeof(addr));
  144. if (err < 0) {
  145. perror("bind s2 failed()\n");
  146. return errno;
  147. }
  148. /* Listen server sockets */
  149. addr.sin_port = htons(S1_PORT);
  150. err = listen(s1, 32);
  151. if (err < 0) {
  152. perror("listen s1 failed()\n");
  153. return errno;
  154. }
  155. addr.sin_port = htons(S2_PORT);
  156. err = listen(s2, 32);
  157. if (err < 0) {
  158. perror("listen s1 failed()\n");
  159. return errno;
  160. }
  161. /* Initiate Connect */
  162. addr.sin_port = htons(S1_PORT);
  163. err = connect(c1, (struct sockaddr *)&addr, sizeof(addr));
  164. if (err < 0 && errno != EINPROGRESS) {
  165. perror("connect c1 failed()\n");
  166. return errno;
  167. }
  168. addr.sin_port = htons(S2_PORT);
  169. err = connect(c2, (struct sockaddr *)&addr, sizeof(addr));
  170. if (err < 0 && errno != EINPROGRESS) {
  171. perror("connect c2 failed()\n");
  172. return errno;
  173. } else if (err < 0) {
  174. err = 0;
  175. }
  176. /* Accept Connecrtions */
  177. p1 = accept(s1, NULL, NULL);
  178. if (p1 < 0) {
  179. perror("accept s1 failed()\n");
  180. return errno;
  181. }
  182. p2 = accept(s2, NULL, NULL);
  183. if (p2 < 0) {
  184. perror("accept s1 failed()\n");
  185. return errno;
  186. }
  187. if (verbose) {
  188. printf("connected sockets: c1 <-> p1, c2 <-> p2\n");
  189. printf("cgroups binding: c1(%i) <-> s1(%i) - - - c2(%i) <-> s2(%i)\n",
  190. c1, s1, c2, s2);
  191. }
  192. return 0;
  193. }
  194. struct msg_stats {
  195. size_t bytes_sent;
  196. size_t bytes_recvd;
  197. struct timespec start;
  198. struct timespec end;
  199. };
  200. struct sockmap_options {
  201. int verbose;
  202. bool base;
  203. bool sendpage;
  204. bool data_test;
  205. bool drop_expected;
  206. int iov_count;
  207. int iov_length;
  208. int rate;
  209. };
  210. static int msg_loop_sendpage(int fd, int iov_length, int cnt,
  211. struct msg_stats *s,
  212. struct sockmap_options *opt)
  213. {
  214. bool drop = opt->drop_expected;
  215. unsigned char k = 0;
  216. FILE *file;
  217. int i, fp;
  218. file = fopen(".sendpage_tst.tmp", "w+");
  219. for (i = 0; i < iov_length * cnt; i++, k++)
  220. fwrite(&k, sizeof(char), 1, file);
  221. fflush(file);
  222. fseek(file, 0, SEEK_SET);
  223. fclose(file);
  224. fp = open(".sendpage_tst.tmp", O_RDONLY);
  225. clock_gettime(CLOCK_MONOTONIC, &s->start);
  226. for (i = 0; i < cnt; i++) {
  227. int sent = sendfile(fd, fp, NULL, iov_length);
  228. if (!drop && sent < 0) {
  229. perror("send loop error:");
  230. close(fp);
  231. return sent;
  232. } else if (drop && sent >= 0) {
  233. printf("sendpage loop error expected: %i\n", sent);
  234. close(fp);
  235. return -EIO;
  236. }
  237. if (sent > 0)
  238. s->bytes_sent += sent;
  239. }
  240. clock_gettime(CLOCK_MONOTONIC, &s->end);
  241. close(fp);
  242. return 0;
  243. }
  244. static int msg_loop(int fd, int iov_count, int iov_length, int cnt,
  245. struct msg_stats *s, bool tx,
  246. struct sockmap_options *opt)
  247. {
  248. struct msghdr msg = {0};
  249. int err, i, flags = MSG_NOSIGNAL;
  250. struct iovec *iov;
  251. unsigned char k;
  252. bool data_test = opt->data_test;
  253. bool drop = opt->drop_expected;
  254. iov = calloc(iov_count, sizeof(struct iovec));
  255. if (!iov)
  256. return errno;
  257. k = 0;
  258. for (i = 0; i < iov_count; i++) {
  259. unsigned char *d = calloc(iov_length, sizeof(char));
  260. if (!d) {
  261. fprintf(stderr, "iov_count %i/%i OOM\n", i, iov_count);
  262. goto out_errno;
  263. }
  264. iov[i].iov_base = d;
  265. iov[i].iov_len = iov_length;
  266. if (data_test && tx) {
  267. int j;
  268. for (j = 0; j < iov_length; j++)
  269. d[j] = k++;
  270. }
  271. }
  272. msg.msg_iov = iov;
  273. msg.msg_iovlen = iov_count;
  274. k = 0;
  275. if (tx) {
  276. clock_gettime(CLOCK_MONOTONIC, &s->start);
  277. for (i = 0; i < cnt; i++) {
  278. int sent = sendmsg(fd, &msg, flags);
  279. if (!drop && sent < 0) {
  280. perror("send loop error:");
  281. goto out_errno;
  282. } else if (drop && sent >= 0) {
  283. printf("send loop error expected: %i\n", sent);
  284. errno = -EIO;
  285. goto out_errno;
  286. }
  287. if (sent > 0)
  288. s->bytes_sent += sent;
  289. }
  290. clock_gettime(CLOCK_MONOTONIC, &s->end);
  291. } else {
  292. int slct, recv, max_fd = fd;
  293. int fd_flags = O_NONBLOCK;
  294. struct timeval timeout;
  295. float total_bytes;
  296. int bytes_cnt = 0;
  297. int chunk_sz;
  298. fd_set w;
  299. if (opt->sendpage)
  300. chunk_sz = iov_length * cnt;
  301. else
  302. chunk_sz = iov_length * iov_count;
  303. fcntl(fd, fd_flags);
  304. total_bytes = (float)iov_count * (float)iov_length * (float)cnt;
  305. err = clock_gettime(CLOCK_MONOTONIC, &s->start);
  306. if (err < 0)
  307. perror("recv start time: ");
  308. while (s->bytes_recvd < total_bytes) {
  309. if (txmsg_cork) {
  310. timeout.tv_sec = 0;
  311. timeout.tv_usec = 1000;
  312. } else {
  313. timeout.tv_sec = 1;
  314. timeout.tv_usec = 0;
  315. }
  316. /* FD sets */
  317. FD_ZERO(&w);
  318. FD_SET(fd, &w);
  319. slct = select(max_fd + 1, &w, NULL, NULL, &timeout);
  320. if (slct == -1) {
  321. perror("select()");
  322. clock_gettime(CLOCK_MONOTONIC, &s->end);
  323. goto out_errno;
  324. } else if (!slct) {
  325. if (opt->verbose)
  326. fprintf(stderr, "unexpected timeout\n");
  327. errno = -EIO;
  328. clock_gettime(CLOCK_MONOTONIC, &s->end);
  329. goto out_errno;
  330. }
  331. recv = recvmsg(fd, &msg, flags);
  332. if (recv < 0) {
  333. if (errno != EWOULDBLOCK) {
  334. clock_gettime(CLOCK_MONOTONIC, &s->end);
  335. perror("recv failed()\n");
  336. goto out_errno;
  337. }
  338. }
  339. s->bytes_recvd += recv;
  340. if (data_test) {
  341. int j;
  342. for (i = 0; i < msg.msg_iovlen; i++) {
  343. unsigned char *d = iov[i].iov_base;
  344. for (j = 0;
  345. j < iov[i].iov_len && recv; j++) {
  346. if (d[j] != k++) {
  347. errno = -EIO;
  348. fprintf(stderr,
  349. "detected data corruption @iov[%i]:%i %02x != %02x, %02x ?= %02x\n",
  350. i, j, d[j], k - 1, d[j+1], k);
  351. goto out_errno;
  352. }
  353. bytes_cnt++;
  354. if (bytes_cnt == chunk_sz) {
  355. k = 0;
  356. bytes_cnt = 0;
  357. }
  358. recv--;
  359. }
  360. }
  361. }
  362. }
  363. clock_gettime(CLOCK_MONOTONIC, &s->end);
  364. }
  365. for (i = 0; i < iov_count; i++)
  366. free(iov[i].iov_base);
  367. free(iov);
  368. return 0;
  369. out_errno:
  370. for (i = 0; i < iov_count; i++)
  371. free(iov[i].iov_base);
  372. free(iov);
  373. return errno;
  374. }
  375. static float giga = 1000000000;
  376. static inline float sentBps(struct msg_stats s)
  377. {
  378. return s.bytes_sent / (s.end.tv_sec - s.start.tv_sec);
  379. }
  380. static inline float recvdBps(struct msg_stats s)
  381. {
  382. return s.bytes_recvd / (s.end.tv_sec - s.start.tv_sec);
  383. }
  384. static int sendmsg_test(struct sockmap_options *opt)
  385. {
  386. float sent_Bps = 0, recvd_Bps = 0;
  387. int rx_fd, txpid, rxpid, err = 0;
  388. struct msg_stats s = {0};
  389. int iov_count = opt->iov_count;
  390. int iov_buf = opt->iov_length;
  391. int rx_status, tx_status;
  392. int cnt = opt->rate;
  393. errno = 0;
  394. if (opt->base)
  395. rx_fd = p1;
  396. else
  397. rx_fd = p2;
  398. rxpid = fork();
  399. if (rxpid == 0) {
  400. if (opt->drop_expected)
  401. exit(0);
  402. if (opt->sendpage)
  403. iov_count = 1;
  404. err = msg_loop(rx_fd, iov_count, iov_buf,
  405. cnt, &s, false, opt);
  406. if (err && opt->verbose)
  407. fprintf(stderr,
  408. "msg_loop_rx: iov_count %i iov_buf %i cnt %i err %i\n",
  409. iov_count, iov_buf, cnt, err);
  410. shutdown(p2, SHUT_RDWR);
  411. shutdown(p1, SHUT_RDWR);
  412. if (s.end.tv_sec - s.start.tv_sec) {
  413. sent_Bps = sentBps(s);
  414. recvd_Bps = recvdBps(s);
  415. }
  416. if (opt->verbose)
  417. fprintf(stdout,
  418. "rx_sendmsg: TX: %zuB %fB/s %fGB/s RX: %zuB %fB/s %fGB/s\n",
  419. s.bytes_sent, sent_Bps, sent_Bps/giga,
  420. s.bytes_recvd, recvd_Bps, recvd_Bps/giga);
  421. if (err && txmsg_cork)
  422. err = 0;
  423. exit(err ? 1 : 0);
  424. } else if (rxpid == -1) {
  425. perror("msg_loop_rx: ");
  426. return errno;
  427. }
  428. txpid = fork();
  429. if (txpid == 0) {
  430. if (opt->sendpage)
  431. err = msg_loop_sendpage(c1, iov_buf, cnt, &s, opt);
  432. else
  433. err = msg_loop(c1, iov_count, iov_buf,
  434. cnt, &s, true, opt);
  435. if (err)
  436. fprintf(stderr,
  437. "msg_loop_tx: iov_count %i iov_buf %i cnt %i err %i\n",
  438. iov_count, iov_buf, cnt, err);
  439. shutdown(c1, SHUT_RDWR);
  440. if (s.end.tv_sec - s.start.tv_sec) {
  441. sent_Bps = sentBps(s);
  442. recvd_Bps = recvdBps(s);
  443. }
  444. if (opt->verbose)
  445. fprintf(stdout,
  446. "tx_sendmsg: TX: %zuB %fB/s %f GB/s RX: %zuB %fB/s %fGB/s\n",
  447. s.bytes_sent, sent_Bps, sent_Bps/giga,
  448. s.bytes_recvd, recvd_Bps, recvd_Bps/giga);
  449. exit(err ? 1 : 0);
  450. } else if (txpid == -1) {
  451. perror("msg_loop_tx: ");
  452. return errno;
  453. }
  454. assert(waitpid(rxpid, &rx_status, 0) == rxpid);
  455. assert(waitpid(txpid, &tx_status, 0) == txpid);
  456. if (WIFEXITED(rx_status)) {
  457. err = WEXITSTATUS(rx_status);
  458. if (err) {
  459. fprintf(stderr, "rx thread exited with err %d. ", err);
  460. goto out;
  461. }
  462. }
  463. if (WIFEXITED(tx_status)) {
  464. err = WEXITSTATUS(tx_status);
  465. if (err)
  466. fprintf(stderr, "tx thread exited with err %d. ", err);
  467. }
  468. out:
  469. return err;
  470. }
  471. static int forever_ping_pong(int rate, struct sockmap_options *opt)
  472. {
  473. struct timeval timeout;
  474. char buf[1024] = {0};
  475. int sc;
  476. timeout.tv_sec = 10;
  477. timeout.tv_usec = 0;
  478. /* Ping/Pong data from client to server */
  479. sc = send(c1, buf, sizeof(buf), 0);
  480. if (sc < 0) {
  481. perror("send failed()\n");
  482. return sc;
  483. }
  484. do {
  485. int s, rc, i, max_fd = p2;
  486. fd_set w;
  487. /* FD sets */
  488. FD_ZERO(&w);
  489. FD_SET(c1, &w);
  490. FD_SET(c2, &w);
  491. FD_SET(p1, &w);
  492. FD_SET(p2, &w);
  493. s = select(max_fd + 1, &w, NULL, NULL, &timeout);
  494. if (s == -1) {
  495. perror("select()");
  496. break;
  497. } else if (!s) {
  498. fprintf(stderr, "unexpected timeout\n");
  499. break;
  500. }
  501. for (i = 0; i <= max_fd && s > 0; ++i) {
  502. if (!FD_ISSET(i, &w))
  503. continue;
  504. s--;
  505. rc = recv(i, buf, sizeof(buf), 0);
  506. if (rc < 0) {
  507. if (errno != EWOULDBLOCK) {
  508. perror("recv failed()\n");
  509. return rc;
  510. }
  511. }
  512. if (rc == 0) {
  513. close(i);
  514. break;
  515. }
  516. sc = send(i, buf, rc, 0);
  517. if (sc < 0) {
  518. perror("send failed()\n");
  519. return sc;
  520. }
  521. }
  522. if (rate)
  523. sleep(rate);
  524. if (opt->verbose) {
  525. printf(".");
  526. fflush(stdout);
  527. }
  528. } while (running);
  529. return 0;
  530. }
  531. enum {
  532. PING_PONG,
  533. SENDMSG,
  534. BASE,
  535. BASE_SENDPAGE,
  536. SENDPAGE,
  537. };
  538. static int run_options(struct sockmap_options *options, int cg_fd, int test)
  539. {
  540. int i, key, next_key, err, tx_prog_fd = -1, zero = 0;
  541. /* If base test skip BPF setup */
  542. if (test == BASE || test == BASE_SENDPAGE)
  543. goto run;
  544. /* Attach programs to sockmap */
  545. err = bpf_prog_attach(prog_fd[0], map_fd[0],
  546. BPF_SK_SKB_STREAM_PARSER, 0);
  547. if (err) {
  548. fprintf(stderr,
  549. "ERROR: bpf_prog_attach (sockmap %i->%i): %d (%s)\n",
  550. prog_fd[0], map_fd[0], err, strerror(errno));
  551. return err;
  552. }
  553. err = bpf_prog_attach(prog_fd[1], map_fd[0],
  554. BPF_SK_SKB_STREAM_VERDICT, 0);
  555. if (err) {
  556. fprintf(stderr, "ERROR: bpf_prog_attach (sockmap): %d (%s)\n",
  557. err, strerror(errno));
  558. return err;
  559. }
  560. /* Attach to cgroups */
  561. err = bpf_prog_attach(prog_fd[2], cg_fd, BPF_CGROUP_SOCK_OPS, 0);
  562. if (err) {
  563. fprintf(stderr, "ERROR: bpf_prog_attach (groups): %d (%s)\n",
  564. err, strerror(errno));
  565. return err;
  566. }
  567. run:
  568. err = sockmap_init_sockets(options->verbose);
  569. if (err) {
  570. fprintf(stderr, "ERROR: test socket failed: %d\n", err);
  571. goto out;
  572. }
  573. /* Attach txmsg program to sockmap */
  574. if (txmsg_pass)
  575. tx_prog_fd = prog_fd[3];
  576. else if (txmsg_noisy)
  577. tx_prog_fd = prog_fd[4];
  578. else if (txmsg_redir)
  579. tx_prog_fd = prog_fd[5];
  580. else if (txmsg_redir_noisy)
  581. tx_prog_fd = prog_fd[6];
  582. else if (txmsg_drop)
  583. tx_prog_fd = prog_fd[9];
  584. /* apply and cork must be last */
  585. else if (txmsg_apply)
  586. tx_prog_fd = prog_fd[7];
  587. else if (txmsg_cork)
  588. tx_prog_fd = prog_fd[8];
  589. else
  590. tx_prog_fd = 0;
  591. if (tx_prog_fd) {
  592. int redir_fd, i = 0;
  593. err = bpf_prog_attach(tx_prog_fd,
  594. map_fd[1], BPF_SK_MSG_VERDICT, 0);
  595. if (err) {
  596. fprintf(stderr,
  597. "ERROR: bpf_prog_attach (txmsg): %d (%s)\n",
  598. err, strerror(errno));
  599. goto out;
  600. }
  601. err = bpf_map_update_elem(map_fd[1], &i, &c1, BPF_ANY);
  602. if (err) {
  603. fprintf(stderr,
  604. "ERROR: bpf_map_update_elem (txmsg): %d (%s\n",
  605. err, strerror(errno));
  606. goto out;
  607. }
  608. if (txmsg_redir || txmsg_redir_noisy)
  609. redir_fd = c2;
  610. else
  611. redir_fd = c1;
  612. err = bpf_map_update_elem(map_fd[2], &i, &redir_fd, BPF_ANY);
  613. if (err) {
  614. fprintf(stderr,
  615. "ERROR: bpf_map_update_elem (txmsg): %d (%s\n",
  616. err, strerror(errno));
  617. goto out;
  618. }
  619. if (txmsg_apply) {
  620. err = bpf_map_update_elem(map_fd[3],
  621. &i, &txmsg_apply, BPF_ANY);
  622. if (err) {
  623. fprintf(stderr,
  624. "ERROR: bpf_map_update_elem (apply_bytes): %d (%s\n",
  625. err, strerror(errno));
  626. goto out;
  627. }
  628. }
  629. if (txmsg_cork) {
  630. err = bpf_map_update_elem(map_fd[4],
  631. &i, &txmsg_cork, BPF_ANY);
  632. if (err) {
  633. fprintf(stderr,
  634. "ERROR: bpf_map_update_elem (cork_bytes): %d (%s\n",
  635. err, strerror(errno));
  636. goto out;
  637. }
  638. }
  639. if (txmsg_start) {
  640. err = bpf_map_update_elem(map_fd[5],
  641. &i, &txmsg_start, BPF_ANY);
  642. if (err) {
  643. fprintf(stderr,
  644. "ERROR: bpf_map_update_elem (txmsg_start): %d (%s)\n",
  645. err, strerror(errno));
  646. goto out;
  647. }
  648. }
  649. if (txmsg_end) {
  650. i = 1;
  651. err = bpf_map_update_elem(map_fd[5],
  652. &i, &txmsg_end, BPF_ANY);
  653. if (err) {
  654. fprintf(stderr,
  655. "ERROR: bpf_map_update_elem (txmsg_end): %d (%s)\n",
  656. err, strerror(errno));
  657. goto out;
  658. }
  659. }
  660. if (txmsg_ingress) {
  661. int in = BPF_F_INGRESS;
  662. i = 0;
  663. err = bpf_map_update_elem(map_fd[6], &i, &in, BPF_ANY);
  664. if (err) {
  665. fprintf(stderr,
  666. "ERROR: bpf_map_update_elem (txmsg_ingress): %d (%s)\n",
  667. err, strerror(errno));
  668. }
  669. i = 1;
  670. err = bpf_map_update_elem(map_fd[1], &i, &p1, BPF_ANY);
  671. if (err) {
  672. fprintf(stderr,
  673. "ERROR: bpf_map_update_elem (p1 txmsg): %d (%s)\n",
  674. err, strerror(errno));
  675. }
  676. err = bpf_map_update_elem(map_fd[2], &i, &p1, BPF_ANY);
  677. if (err) {
  678. fprintf(stderr,
  679. "ERROR: bpf_map_update_elem (p1 redir): %d (%s)\n",
  680. err, strerror(errno));
  681. }
  682. i = 2;
  683. err = bpf_map_update_elem(map_fd[2], &i, &p2, BPF_ANY);
  684. if (err) {
  685. fprintf(stderr,
  686. "ERROR: bpf_map_update_elem (p2 txmsg): %d (%s)\n",
  687. err, strerror(errno));
  688. }
  689. }
  690. if (txmsg_skb) {
  691. int skb_fd = (test == SENDMSG || test == SENDPAGE) ?
  692. p2 : p1;
  693. int ingress = BPF_F_INGRESS;
  694. i = 0;
  695. err = bpf_map_update_elem(map_fd[7],
  696. &i, &ingress, BPF_ANY);
  697. if (err) {
  698. fprintf(stderr,
  699. "ERROR: bpf_map_update_elem (txmsg_ingress): %d (%s)\n",
  700. err, strerror(errno));
  701. }
  702. i = 3;
  703. err = bpf_map_update_elem(map_fd[0],
  704. &i, &skb_fd, BPF_ANY);
  705. if (err) {
  706. fprintf(stderr,
  707. "ERROR: bpf_map_update_elem (c1 sockmap): %d (%s)\n",
  708. err, strerror(errno));
  709. }
  710. }
  711. }
  712. if (txmsg_drop)
  713. options->drop_expected = true;
  714. if (test == PING_PONG)
  715. err = forever_ping_pong(options->rate, options);
  716. else if (test == SENDMSG) {
  717. options->base = false;
  718. options->sendpage = false;
  719. err = sendmsg_test(options);
  720. } else if (test == SENDPAGE) {
  721. options->base = false;
  722. options->sendpage = true;
  723. err = sendmsg_test(options);
  724. } else if (test == BASE) {
  725. options->base = true;
  726. options->sendpage = false;
  727. err = sendmsg_test(options);
  728. } else if (test == BASE_SENDPAGE) {
  729. options->base = true;
  730. options->sendpage = true;
  731. err = sendmsg_test(options);
  732. } else
  733. fprintf(stderr, "unknown test\n");
  734. out:
  735. /* Detatch and zero all the maps */
  736. bpf_prog_detach2(prog_fd[2], cg_fd, BPF_CGROUP_SOCK_OPS);
  737. bpf_prog_detach2(prog_fd[0], map_fd[0], BPF_SK_SKB_STREAM_PARSER);
  738. bpf_prog_detach2(prog_fd[1], map_fd[0], BPF_SK_SKB_STREAM_VERDICT);
  739. if (tx_prog_fd >= 0)
  740. bpf_prog_detach2(tx_prog_fd, map_fd[1], BPF_SK_MSG_VERDICT);
  741. for (i = 0; i < 8; i++) {
  742. key = next_key = 0;
  743. bpf_map_update_elem(map_fd[i], &key, &zero, BPF_ANY);
  744. while (bpf_map_get_next_key(map_fd[i], &key, &next_key) == 0) {
  745. bpf_map_update_elem(map_fd[i], &key, &zero, BPF_ANY);
  746. key = next_key;
  747. }
  748. }
  749. close(s1);
  750. close(s2);
  751. close(p1);
  752. close(p2);
  753. close(c1);
  754. close(c2);
  755. return err;
  756. }
  757. static char *test_to_str(int test)
  758. {
  759. switch (test) {
  760. case SENDMSG:
  761. return "sendmsg";
  762. case SENDPAGE:
  763. return "sendpage";
  764. }
  765. return "unknown";
  766. }
  767. #define OPTSTRING 60
  768. static void test_options(char *options)
  769. {
  770. char tstr[OPTSTRING];
  771. memset(options, 0, OPTSTRING);
  772. if (txmsg_pass)
  773. strncat(options, "pass,", OPTSTRING);
  774. if (txmsg_noisy)
  775. strncat(options, "pass_noisy,", OPTSTRING);
  776. if (txmsg_redir)
  777. strncat(options, "redir,", OPTSTRING);
  778. if (txmsg_redir_noisy)
  779. strncat(options, "redir_noisy,", OPTSTRING);
  780. if (txmsg_drop)
  781. strncat(options, "drop,", OPTSTRING);
  782. if (txmsg_apply) {
  783. snprintf(tstr, OPTSTRING, "apply %d,", txmsg_apply);
  784. strncat(options, tstr, OPTSTRING);
  785. }
  786. if (txmsg_cork) {
  787. snprintf(tstr, OPTSTRING, "cork %d,", txmsg_cork);
  788. strncat(options, tstr, OPTSTRING);
  789. }
  790. if (txmsg_start) {
  791. snprintf(tstr, OPTSTRING, "start %d,", txmsg_start);
  792. strncat(options, tstr, OPTSTRING);
  793. }
  794. if (txmsg_end) {
  795. snprintf(tstr, OPTSTRING, "end %d,", txmsg_end);
  796. strncat(options, tstr, OPTSTRING);
  797. }
  798. if (txmsg_ingress)
  799. strncat(options, "ingress,", OPTSTRING);
  800. if (txmsg_skb)
  801. strncat(options, "skb,", OPTSTRING);
  802. }
  803. static int __test_exec(int cgrp, int test, struct sockmap_options *opt)
  804. {
  805. char *options = calloc(OPTSTRING, sizeof(char));
  806. int err;
  807. if (test == SENDPAGE)
  808. opt->sendpage = true;
  809. else
  810. opt->sendpage = false;
  811. if (txmsg_drop)
  812. opt->drop_expected = true;
  813. else
  814. opt->drop_expected = false;
  815. test_options(options);
  816. fprintf(stdout,
  817. "[TEST %i]: (%i, %i, %i, %s, %s): ",
  818. test_cnt, opt->rate, opt->iov_count, opt->iov_length,
  819. test_to_str(test), options);
  820. fflush(stdout);
  821. err = run_options(opt, cgrp, test);
  822. fprintf(stdout, "%s\n", !err ? "PASS" : "FAILED");
  823. test_cnt++;
  824. !err ? passed++ : failed++;
  825. free(options);
  826. return err;
  827. }
  828. static int test_exec(int cgrp, struct sockmap_options *opt)
  829. {
  830. int err = __test_exec(cgrp, SENDMSG, opt);
  831. if (err)
  832. goto out;
  833. err = __test_exec(cgrp, SENDPAGE, opt);
  834. out:
  835. return err;
  836. }
  837. static int test_loop(int cgrp)
  838. {
  839. struct sockmap_options opt;
  840. int err, i, l, r;
  841. opt.verbose = 0;
  842. opt.base = false;
  843. opt.sendpage = false;
  844. opt.data_test = false;
  845. opt.drop_expected = false;
  846. opt.iov_count = 0;
  847. opt.iov_length = 0;
  848. opt.rate = 0;
  849. r = 1;
  850. for (i = 1; i < 100; i += 33) {
  851. for (l = 1; l < 100; l += 33) {
  852. opt.rate = r;
  853. opt.iov_count = i;
  854. opt.iov_length = l;
  855. err = test_exec(cgrp, &opt);
  856. if (err)
  857. goto out;
  858. }
  859. }
  860. sched_yield();
  861. out:
  862. return err;
  863. }
  864. static int test_txmsg(int cgrp)
  865. {
  866. int err;
  867. txmsg_pass = txmsg_noisy = txmsg_redir_noisy = txmsg_drop = 0;
  868. txmsg_apply = txmsg_cork = 0;
  869. txmsg_ingress = txmsg_skb = 0;
  870. txmsg_pass = 1;
  871. err = test_loop(cgrp);
  872. txmsg_pass = 0;
  873. if (err)
  874. goto out;
  875. txmsg_redir = 1;
  876. err = test_loop(cgrp);
  877. txmsg_redir = 0;
  878. if (err)
  879. goto out;
  880. txmsg_drop = 1;
  881. err = test_loop(cgrp);
  882. txmsg_drop = 0;
  883. if (err)
  884. goto out;
  885. txmsg_redir = 1;
  886. txmsg_ingress = 1;
  887. err = test_loop(cgrp);
  888. txmsg_redir = 0;
  889. txmsg_ingress = 0;
  890. if (err)
  891. goto out;
  892. out:
  893. txmsg_pass = 0;
  894. txmsg_redir = 0;
  895. txmsg_drop = 0;
  896. return err;
  897. }
  898. static int test_send(struct sockmap_options *opt, int cgrp)
  899. {
  900. int err;
  901. opt->iov_length = 1;
  902. opt->iov_count = 1;
  903. opt->rate = 1;
  904. err = test_exec(cgrp, opt);
  905. if (err)
  906. goto out;
  907. opt->iov_length = 1;
  908. opt->iov_count = 1024;
  909. opt->rate = 1;
  910. err = test_exec(cgrp, opt);
  911. if (err)
  912. goto out;
  913. opt->iov_length = 1024;
  914. opt->iov_count = 1;
  915. opt->rate = 1;
  916. err = test_exec(cgrp, opt);
  917. if (err)
  918. goto out;
  919. opt->iov_length = 1;
  920. opt->iov_count = 1;
  921. opt->rate = 512;
  922. err = test_exec(cgrp, opt);
  923. if (err)
  924. goto out;
  925. opt->iov_length = 256;
  926. opt->iov_count = 1024;
  927. opt->rate = 2;
  928. err = test_exec(cgrp, opt);
  929. if (err)
  930. goto out;
  931. opt->rate = 100;
  932. opt->iov_count = 1;
  933. opt->iov_length = 5;
  934. err = test_exec(cgrp, opt);
  935. if (err)
  936. goto out;
  937. out:
  938. sched_yield();
  939. return err;
  940. }
  941. static int test_mixed(int cgrp)
  942. {
  943. struct sockmap_options opt = {0};
  944. int err;
  945. txmsg_pass = txmsg_noisy = txmsg_redir_noisy = txmsg_drop = 0;
  946. txmsg_apply = txmsg_cork = 0;
  947. txmsg_start = txmsg_end = 0;
  948. /* Test small and large iov_count values with pass/redir/apply/cork */
  949. txmsg_pass = 1;
  950. txmsg_redir = 0;
  951. txmsg_apply = 1;
  952. txmsg_cork = 0;
  953. err = test_send(&opt, cgrp);
  954. if (err)
  955. goto out;
  956. txmsg_pass = 1;
  957. txmsg_redir = 0;
  958. txmsg_apply = 0;
  959. txmsg_cork = 1;
  960. err = test_send(&opt, cgrp);
  961. if (err)
  962. goto out;
  963. txmsg_pass = 1;
  964. txmsg_redir = 0;
  965. txmsg_apply = 1;
  966. txmsg_cork = 1;
  967. err = test_send(&opt, cgrp);
  968. if (err)
  969. goto out;
  970. txmsg_pass = 1;
  971. txmsg_redir = 0;
  972. txmsg_apply = 1024;
  973. txmsg_cork = 0;
  974. err = test_send(&opt, cgrp);
  975. if (err)
  976. goto out;
  977. txmsg_pass = 1;
  978. txmsg_redir = 0;
  979. txmsg_apply = 0;
  980. txmsg_cork = 1024;
  981. err = test_send(&opt, cgrp);
  982. if (err)
  983. goto out;
  984. txmsg_pass = 1;
  985. txmsg_redir = 0;
  986. txmsg_apply = 1024;
  987. txmsg_cork = 1024;
  988. err = test_send(&opt, cgrp);
  989. if (err)
  990. goto out;
  991. txmsg_pass = 1;
  992. txmsg_redir = 0;
  993. txmsg_cork = 4096;
  994. txmsg_apply = 4096;
  995. err = test_send(&opt, cgrp);
  996. if (err)
  997. goto out;
  998. txmsg_pass = 0;
  999. txmsg_redir = 1;
  1000. txmsg_apply = 1;
  1001. txmsg_cork = 0;
  1002. err = test_send(&opt, cgrp);
  1003. if (err)
  1004. goto out;
  1005. txmsg_pass = 0;
  1006. txmsg_redir = 1;
  1007. txmsg_apply = 0;
  1008. txmsg_cork = 1;
  1009. err = test_send(&opt, cgrp);
  1010. if (err)
  1011. goto out;
  1012. txmsg_pass = 0;
  1013. txmsg_redir = 1;
  1014. txmsg_apply = 1024;
  1015. txmsg_cork = 0;
  1016. err = test_send(&opt, cgrp);
  1017. if (err)
  1018. goto out;
  1019. txmsg_pass = 0;
  1020. txmsg_redir = 1;
  1021. txmsg_apply = 0;
  1022. txmsg_cork = 1024;
  1023. err = test_send(&opt, cgrp);
  1024. if (err)
  1025. goto out;
  1026. txmsg_pass = 0;
  1027. txmsg_redir = 1;
  1028. txmsg_apply = 1024;
  1029. txmsg_cork = 1024;
  1030. err = test_send(&opt, cgrp);
  1031. if (err)
  1032. goto out;
  1033. txmsg_pass = 0;
  1034. txmsg_redir = 1;
  1035. txmsg_cork = 4096;
  1036. txmsg_apply = 4096;
  1037. err = test_send(&opt, cgrp);
  1038. if (err)
  1039. goto out;
  1040. out:
  1041. return err;
  1042. }
  1043. static int test_start_end(int cgrp)
  1044. {
  1045. struct sockmap_options opt = {0};
  1046. int err, i;
  1047. /* Test basic start/end with lots of iov_count and iov_lengths */
  1048. txmsg_start = 1;
  1049. txmsg_end = 2;
  1050. err = test_txmsg(cgrp);
  1051. if (err)
  1052. goto out;
  1053. /* Test start/end with cork */
  1054. opt.rate = 16;
  1055. opt.iov_count = 1;
  1056. opt.iov_length = 100;
  1057. txmsg_cork = 1600;
  1058. for (i = 99; i <= 1600; i += 500) {
  1059. txmsg_start = 0;
  1060. txmsg_end = i;
  1061. err = test_exec(cgrp, &opt);
  1062. if (err)
  1063. goto out;
  1064. }
  1065. /* Test start/end with cork but pull data in middle */
  1066. for (i = 199; i <= 1600; i += 500) {
  1067. txmsg_start = 100;
  1068. txmsg_end = i;
  1069. err = test_exec(cgrp, &opt);
  1070. if (err)
  1071. goto out;
  1072. }
  1073. /* Test start/end with cork pulling last sg entry */
  1074. txmsg_start = 1500;
  1075. txmsg_end = 1600;
  1076. err = test_exec(cgrp, &opt);
  1077. if (err)
  1078. goto out;
  1079. /* Test start/end pull of single byte in last page */
  1080. txmsg_start = 1111;
  1081. txmsg_end = 1112;
  1082. err = test_exec(cgrp, &opt);
  1083. if (err)
  1084. goto out;
  1085. /* Test start/end with end < start */
  1086. txmsg_start = 1111;
  1087. txmsg_end = 0;
  1088. err = test_exec(cgrp, &opt);
  1089. if (err)
  1090. goto out;
  1091. /* Test start/end with end > data */
  1092. txmsg_start = 0;
  1093. txmsg_end = 1601;
  1094. err = test_exec(cgrp, &opt);
  1095. if (err)
  1096. goto out;
  1097. /* Test start/end with start > data */
  1098. txmsg_start = 1601;
  1099. txmsg_end = 1600;
  1100. err = test_exec(cgrp, &opt);
  1101. out:
  1102. txmsg_start = 0;
  1103. txmsg_end = 0;
  1104. sched_yield();
  1105. return err;
  1106. }
  1107. char *map_names[] = {
  1108. "sock_map",
  1109. "sock_map_txmsg",
  1110. "sock_map_redir",
  1111. "sock_apply_bytes",
  1112. "sock_cork_bytes",
  1113. "sock_pull_bytes",
  1114. "sock_redir_flags",
  1115. "sock_skb_opts",
  1116. };
  1117. int prog_attach_type[] = {
  1118. BPF_SK_SKB_STREAM_PARSER,
  1119. BPF_SK_SKB_STREAM_VERDICT,
  1120. BPF_CGROUP_SOCK_OPS,
  1121. BPF_SK_MSG_VERDICT,
  1122. BPF_SK_MSG_VERDICT,
  1123. BPF_SK_MSG_VERDICT,
  1124. BPF_SK_MSG_VERDICT,
  1125. BPF_SK_MSG_VERDICT,
  1126. BPF_SK_MSG_VERDICT,
  1127. BPF_SK_MSG_VERDICT,
  1128. };
  1129. int prog_type[] = {
  1130. BPF_PROG_TYPE_SK_SKB,
  1131. BPF_PROG_TYPE_SK_SKB,
  1132. BPF_PROG_TYPE_SOCK_OPS,
  1133. BPF_PROG_TYPE_SK_MSG,
  1134. BPF_PROG_TYPE_SK_MSG,
  1135. BPF_PROG_TYPE_SK_MSG,
  1136. BPF_PROG_TYPE_SK_MSG,
  1137. BPF_PROG_TYPE_SK_MSG,
  1138. BPF_PROG_TYPE_SK_MSG,
  1139. BPF_PROG_TYPE_SK_MSG,
  1140. };
  1141. static int populate_progs(char *bpf_file)
  1142. {
  1143. struct bpf_program *prog;
  1144. struct bpf_object *obj;
  1145. int i = 0;
  1146. long err;
  1147. obj = bpf_object__open(bpf_file);
  1148. err = libbpf_get_error(obj);
  1149. if (err) {
  1150. char err_buf[256];
  1151. libbpf_strerror(err, err_buf, sizeof(err_buf));
  1152. printf("Unable to load eBPF objects in file '%s' : %s\n",
  1153. bpf_file, err_buf);
  1154. return -1;
  1155. }
  1156. bpf_object__for_each_program(prog, obj) {
  1157. bpf_program__set_type(prog, prog_type[i]);
  1158. bpf_program__set_expected_attach_type(prog,
  1159. prog_attach_type[i]);
  1160. i++;
  1161. }
  1162. i = bpf_object__load(obj);
  1163. i = 0;
  1164. bpf_object__for_each_program(prog, obj) {
  1165. prog_fd[i] = bpf_program__fd(prog);
  1166. i++;
  1167. }
  1168. for (i = 0; i < sizeof(map_fd)/sizeof(int); i++) {
  1169. maps[i] = bpf_object__find_map_by_name(obj, map_names[i]);
  1170. map_fd[i] = bpf_map__fd(maps[i]);
  1171. if (map_fd[i] < 0) {
  1172. fprintf(stderr, "load_bpf_file: (%i) %s\n",
  1173. map_fd[i], strerror(errno));
  1174. return -1;
  1175. }
  1176. }
  1177. return 0;
  1178. }
  1179. static int __test_suite(char *bpf_file)
  1180. {
  1181. int cg_fd, err;
  1182. err = populate_progs(bpf_file);
  1183. if (err < 0) {
  1184. fprintf(stderr, "ERROR: (%i) load bpf failed\n", err);
  1185. return err;
  1186. }
  1187. if (setup_cgroup_environment()) {
  1188. fprintf(stderr, "ERROR: cgroup env failed\n");
  1189. return -EINVAL;
  1190. }
  1191. cg_fd = create_and_get_cgroup(CG_PATH);
  1192. if (cg_fd < 0) {
  1193. fprintf(stderr,
  1194. "ERROR: (%i) open cg path failed: %s\n",
  1195. cg_fd, optarg);
  1196. return cg_fd;
  1197. }
  1198. if (join_cgroup(CG_PATH)) {
  1199. fprintf(stderr, "ERROR: failed to join cgroup\n");
  1200. return -EINVAL;
  1201. }
  1202. /* Tests basic commands and APIs with range of iov values */
  1203. txmsg_start = txmsg_end = 0;
  1204. err = test_txmsg(cg_fd);
  1205. if (err)
  1206. goto out;
  1207. /* Tests interesting combinations of APIs used together */
  1208. err = test_mixed(cg_fd);
  1209. if (err)
  1210. goto out;
  1211. /* Tests pull_data API using start/end API */
  1212. err = test_start_end(cg_fd);
  1213. if (err)
  1214. goto out;
  1215. out:
  1216. printf("Summary: %i PASSED %i FAILED\n", passed, failed);
  1217. cleanup_cgroup_environment();
  1218. close(cg_fd);
  1219. return err;
  1220. }
  1221. static int test_suite(void)
  1222. {
  1223. int err;
  1224. err = __test_suite(BPF_SOCKMAP_FILENAME);
  1225. if (err)
  1226. goto out;
  1227. err = __test_suite(BPF_SOCKHASH_FILENAME);
  1228. out:
  1229. return err;
  1230. }
  1231. int main(int argc, char **argv)
  1232. {
  1233. struct rlimit r = {10 * 1024 * 1024, RLIM_INFINITY};
  1234. int iov_count = 1, length = 1024, rate = 1;
  1235. struct sockmap_options options = {0};
  1236. int opt, longindex, err, cg_fd = 0;
  1237. char *bpf_file = BPF_SOCKMAP_FILENAME;
  1238. int test = PING_PONG;
  1239. if (setrlimit(RLIMIT_MEMLOCK, &r)) {
  1240. perror("setrlimit(RLIMIT_MEMLOCK)");
  1241. return 1;
  1242. }
  1243. if (argc < 2)
  1244. return test_suite();
  1245. while ((opt = getopt_long(argc, argv, ":dhvc:r:i:l:t:",
  1246. long_options, &longindex)) != -1) {
  1247. switch (opt) {
  1248. case 's':
  1249. txmsg_start = atoi(optarg);
  1250. break;
  1251. case 'e':
  1252. txmsg_end = atoi(optarg);
  1253. break;
  1254. case 'a':
  1255. txmsg_apply = atoi(optarg);
  1256. break;
  1257. case 'k':
  1258. txmsg_cork = atoi(optarg);
  1259. break;
  1260. case 'c':
  1261. cg_fd = open(optarg, O_DIRECTORY, O_RDONLY);
  1262. if (cg_fd < 0) {
  1263. fprintf(stderr,
  1264. "ERROR: (%i) open cg path failed: %s\n",
  1265. cg_fd, optarg);
  1266. return cg_fd;
  1267. }
  1268. break;
  1269. case 'r':
  1270. rate = atoi(optarg);
  1271. break;
  1272. case 'v':
  1273. options.verbose = 1;
  1274. break;
  1275. case 'i':
  1276. iov_count = atoi(optarg);
  1277. break;
  1278. case 'l':
  1279. length = atoi(optarg);
  1280. break;
  1281. case 'd':
  1282. options.data_test = true;
  1283. break;
  1284. case 't':
  1285. if (strcmp(optarg, "ping") == 0) {
  1286. test = PING_PONG;
  1287. } else if (strcmp(optarg, "sendmsg") == 0) {
  1288. test = SENDMSG;
  1289. } else if (strcmp(optarg, "base") == 0) {
  1290. test = BASE;
  1291. } else if (strcmp(optarg, "base_sendpage") == 0) {
  1292. test = BASE_SENDPAGE;
  1293. } else if (strcmp(optarg, "sendpage") == 0) {
  1294. test = SENDPAGE;
  1295. } else {
  1296. usage(argv);
  1297. return -1;
  1298. }
  1299. break;
  1300. case 0:
  1301. break;
  1302. case 'h':
  1303. default:
  1304. usage(argv);
  1305. return -1;
  1306. }
  1307. }
  1308. if (!cg_fd) {
  1309. fprintf(stderr, "%s requires cgroup option: --cgroup <path>\n",
  1310. argv[0]);
  1311. return -1;
  1312. }
  1313. err = populate_progs(bpf_file);
  1314. if (err) {
  1315. fprintf(stderr, "populate program: (%s) %s\n",
  1316. bpf_file, strerror(errno));
  1317. return 1;
  1318. }
  1319. running = 1;
  1320. /* catch SIGINT */
  1321. signal(SIGINT, running_handler);
  1322. options.iov_count = iov_count;
  1323. options.iov_length = length;
  1324. options.rate = rate;
  1325. err = run_options(&options, cg_fd, test);
  1326. close(cg_fd);
  1327. return err;
  1328. }
  1329. void running_handler(int a)
  1330. {
  1331. running = 0;
  1332. }