test_sockmap.c 31 KB

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