test_sockmap.c 45 KB

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