test_maps.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185
  1. /*
  2. * Testsuite for eBPF maps
  3. *
  4. * Copyright (c) 2014 PLUMgrid, http://plumgrid.com
  5. * Copyright (c) 2016 Facebook
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of version 2 of the GNU General Public
  9. * License as published by the Free Software Foundation.
  10. */
  11. #include <stdio.h>
  12. #include <unistd.h>
  13. #include <errno.h>
  14. #include <string.h>
  15. #include <assert.h>
  16. #include <stdlib.h>
  17. #include <sys/wait.h>
  18. #include <linux/bpf.h>
  19. #include <bpf/bpf.h>
  20. #include <bpf/libbpf.h>
  21. #include "bpf_util.h"
  22. #include "bpf_rlimit.h"
  23. static int map_flags;
  24. static void test_hashmap(int task, void *data)
  25. {
  26. long long key, next_key, first_key, value;
  27. int fd;
  28. fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
  29. 2, map_flags);
  30. if (fd < 0) {
  31. printf("Failed to create hashmap '%s'!\n", strerror(errno));
  32. exit(1);
  33. }
  34. key = 1;
  35. value = 1234;
  36. /* Insert key=1 element. */
  37. assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
  38. value = 0;
  39. /* BPF_NOEXIST means add new element if it doesn't exist. */
  40. assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
  41. /* key=1 already exists. */
  42. errno == EEXIST);
  43. /* -1 is an invalid flag. */
  44. assert(bpf_map_update_elem(fd, &key, &value, -1) == -1 &&
  45. errno == EINVAL);
  46. /* Check that key=1 can be found. */
  47. assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 1234);
  48. key = 2;
  49. /* Check that key=2 is not found. */
  50. assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT);
  51. /* BPF_EXIST means update existing element. */
  52. assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == -1 &&
  53. /* key=2 is not there. */
  54. errno == ENOENT);
  55. /* Insert key=2 element. */
  56. assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0);
  57. /* key=1 and key=2 were inserted, check that key=0 cannot be
  58. * inserted due to max_entries limit.
  59. */
  60. key = 0;
  61. assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
  62. errno == E2BIG);
  63. /* Update existing element, though the map is full. */
  64. key = 1;
  65. assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == 0);
  66. key = 2;
  67. assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
  68. key = 3;
  69. assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
  70. errno == E2BIG);
  71. /* Check that key = 0 doesn't exist. */
  72. key = 0;
  73. assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT);
  74. /* Iterate over two elements. */
  75. assert(bpf_map_get_next_key(fd, NULL, &first_key) == 0 &&
  76. (first_key == 1 || first_key == 2));
  77. assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 &&
  78. (next_key == first_key));
  79. assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 &&
  80. (next_key == 1 || next_key == 2) &&
  81. (next_key != first_key));
  82. assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 &&
  83. errno == ENOENT);
  84. /* Delete both elements. */
  85. key = 1;
  86. assert(bpf_map_delete_elem(fd, &key) == 0);
  87. key = 2;
  88. assert(bpf_map_delete_elem(fd, &key) == 0);
  89. assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT);
  90. key = 0;
  91. /* Check that map is empty. */
  92. assert(bpf_map_get_next_key(fd, NULL, &next_key) == -1 &&
  93. errno == ENOENT);
  94. assert(bpf_map_get_next_key(fd, &key, &next_key) == -1 &&
  95. errno == ENOENT);
  96. close(fd);
  97. }
  98. static void test_hashmap_sizes(int task, void *data)
  99. {
  100. int fd, i, j;
  101. for (i = 1; i <= 512; i <<= 1)
  102. for (j = 1; j <= 1 << 18; j <<= 1) {
  103. fd = bpf_create_map(BPF_MAP_TYPE_HASH, i, j,
  104. 2, map_flags);
  105. if (fd < 0) {
  106. if (errno == ENOMEM)
  107. return;
  108. printf("Failed to create hashmap key=%d value=%d '%s'\n",
  109. i, j, strerror(errno));
  110. exit(1);
  111. }
  112. close(fd);
  113. usleep(10); /* give kernel time to destroy */
  114. }
  115. }
  116. static void test_hashmap_percpu(int task, void *data)
  117. {
  118. unsigned int nr_cpus = bpf_num_possible_cpus();
  119. BPF_DECLARE_PERCPU(long, value);
  120. long long key, next_key, first_key;
  121. int expected_key_mask = 0;
  122. int fd, i;
  123. fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_HASH, sizeof(key),
  124. sizeof(bpf_percpu(value, 0)), 2, map_flags);
  125. if (fd < 0) {
  126. printf("Failed to create hashmap '%s'!\n", strerror(errno));
  127. exit(1);
  128. }
  129. for (i = 0; i < nr_cpus; i++)
  130. bpf_percpu(value, i) = i + 100;
  131. key = 1;
  132. /* Insert key=1 element. */
  133. assert(!(expected_key_mask & key));
  134. assert(bpf_map_update_elem(fd, &key, value, BPF_ANY) == 0);
  135. expected_key_mask |= key;
  136. /* BPF_NOEXIST means add new element if it doesn't exist. */
  137. assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == -1 &&
  138. /* key=1 already exists. */
  139. errno == EEXIST);
  140. /* -1 is an invalid flag. */
  141. assert(bpf_map_update_elem(fd, &key, value, -1) == -1 &&
  142. errno == EINVAL);
  143. /* Check that key=1 can be found. Value could be 0 if the lookup
  144. * was run from a different CPU.
  145. */
  146. bpf_percpu(value, 0) = 1;
  147. assert(bpf_map_lookup_elem(fd, &key, value) == 0 &&
  148. bpf_percpu(value, 0) == 100);
  149. key = 2;
  150. /* Check that key=2 is not found. */
  151. assert(bpf_map_lookup_elem(fd, &key, value) == -1 && errno == ENOENT);
  152. /* BPF_EXIST means update existing element. */
  153. assert(bpf_map_update_elem(fd, &key, value, BPF_EXIST) == -1 &&
  154. /* key=2 is not there. */
  155. errno == ENOENT);
  156. /* Insert key=2 element. */
  157. assert(!(expected_key_mask & key));
  158. assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == 0);
  159. expected_key_mask |= key;
  160. /* key=1 and key=2 were inserted, check that key=0 cannot be
  161. * inserted due to max_entries limit.
  162. */
  163. key = 0;
  164. assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == -1 &&
  165. errno == E2BIG);
  166. /* Check that key = 0 doesn't exist. */
  167. assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT);
  168. /* Iterate over two elements. */
  169. assert(bpf_map_get_next_key(fd, NULL, &first_key) == 0 &&
  170. ((expected_key_mask & first_key) == first_key));
  171. while (!bpf_map_get_next_key(fd, &key, &next_key)) {
  172. if (first_key) {
  173. assert(next_key == first_key);
  174. first_key = 0;
  175. }
  176. assert((expected_key_mask & next_key) == next_key);
  177. expected_key_mask &= ~next_key;
  178. assert(bpf_map_lookup_elem(fd, &next_key, value) == 0);
  179. for (i = 0; i < nr_cpus; i++)
  180. assert(bpf_percpu(value, i) == i + 100);
  181. key = next_key;
  182. }
  183. assert(errno == ENOENT);
  184. /* Update with BPF_EXIST. */
  185. key = 1;
  186. assert(bpf_map_update_elem(fd, &key, value, BPF_EXIST) == 0);
  187. /* Delete both elements. */
  188. key = 1;
  189. assert(bpf_map_delete_elem(fd, &key) == 0);
  190. key = 2;
  191. assert(bpf_map_delete_elem(fd, &key) == 0);
  192. assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT);
  193. key = 0;
  194. /* Check that map is empty. */
  195. assert(bpf_map_get_next_key(fd, NULL, &next_key) == -1 &&
  196. errno == ENOENT);
  197. assert(bpf_map_get_next_key(fd, &key, &next_key) == -1 &&
  198. errno == ENOENT);
  199. close(fd);
  200. }
  201. static void test_hashmap_walk(int task, void *data)
  202. {
  203. int fd, i, max_entries = 1000;
  204. long long key, value, next_key;
  205. bool next_key_valid = true;
  206. fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
  207. max_entries, map_flags);
  208. if (fd < 0) {
  209. printf("Failed to create hashmap '%s'!\n", strerror(errno));
  210. exit(1);
  211. }
  212. for (i = 0; i < max_entries; i++) {
  213. key = i; value = key;
  214. assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0);
  215. }
  216. for (i = 0; bpf_map_get_next_key(fd, !i ? NULL : &key,
  217. &next_key) == 0; i++) {
  218. key = next_key;
  219. assert(bpf_map_lookup_elem(fd, &key, &value) == 0);
  220. }
  221. assert(i == max_entries);
  222. assert(bpf_map_get_next_key(fd, NULL, &key) == 0);
  223. for (i = 0; next_key_valid; i++) {
  224. next_key_valid = bpf_map_get_next_key(fd, &key, &next_key) == 0;
  225. assert(bpf_map_lookup_elem(fd, &key, &value) == 0);
  226. value++;
  227. assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == 0);
  228. key = next_key;
  229. }
  230. assert(i == max_entries);
  231. for (i = 0; bpf_map_get_next_key(fd, !i ? NULL : &key,
  232. &next_key) == 0; i++) {
  233. key = next_key;
  234. assert(bpf_map_lookup_elem(fd, &key, &value) == 0);
  235. assert(value - 1 == key);
  236. }
  237. assert(i == max_entries);
  238. close(fd);
  239. }
  240. static void test_arraymap(int task, void *data)
  241. {
  242. int key, next_key, fd;
  243. long long value;
  244. fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(key), sizeof(value),
  245. 2, 0);
  246. if (fd < 0) {
  247. printf("Failed to create arraymap '%s'!\n", strerror(errno));
  248. exit(1);
  249. }
  250. key = 1;
  251. value = 1234;
  252. /* Insert key=1 element. */
  253. assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
  254. value = 0;
  255. assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
  256. errno == EEXIST);
  257. /* Check that key=1 can be found. */
  258. assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 1234);
  259. key = 0;
  260. /* Check that key=0 is also found and zero initialized. */
  261. assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 0);
  262. /* key=0 and key=1 were inserted, check that key=2 cannot be inserted
  263. * due to max_entries limit.
  264. */
  265. key = 2;
  266. assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == -1 &&
  267. errno == E2BIG);
  268. /* Check that key = 2 doesn't exist. */
  269. assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT);
  270. /* Iterate over two elements. */
  271. assert(bpf_map_get_next_key(fd, NULL, &next_key) == 0 &&
  272. next_key == 0);
  273. assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 &&
  274. next_key == 0);
  275. assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 &&
  276. next_key == 1);
  277. assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 &&
  278. errno == ENOENT);
  279. /* Delete shouldn't succeed. */
  280. key = 1;
  281. assert(bpf_map_delete_elem(fd, &key) == -1 && errno == EINVAL);
  282. close(fd);
  283. }
  284. static void test_arraymap_percpu(int task, void *data)
  285. {
  286. unsigned int nr_cpus = bpf_num_possible_cpus();
  287. BPF_DECLARE_PERCPU(long, values);
  288. int key, next_key, fd, i;
  289. fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key),
  290. sizeof(bpf_percpu(values, 0)), 2, 0);
  291. if (fd < 0) {
  292. printf("Failed to create arraymap '%s'!\n", strerror(errno));
  293. exit(1);
  294. }
  295. for (i = 0; i < nr_cpus; i++)
  296. bpf_percpu(values, i) = i + 100;
  297. key = 1;
  298. /* Insert key=1 element. */
  299. assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0);
  300. bpf_percpu(values, 0) = 0;
  301. assert(bpf_map_update_elem(fd, &key, values, BPF_NOEXIST) == -1 &&
  302. errno == EEXIST);
  303. /* Check that key=1 can be found. */
  304. assert(bpf_map_lookup_elem(fd, &key, values) == 0 &&
  305. bpf_percpu(values, 0) == 100);
  306. key = 0;
  307. /* Check that key=0 is also found and zero initialized. */
  308. assert(bpf_map_lookup_elem(fd, &key, values) == 0 &&
  309. bpf_percpu(values, 0) == 0 &&
  310. bpf_percpu(values, nr_cpus - 1) == 0);
  311. /* Check that key=2 cannot be inserted due to max_entries limit. */
  312. key = 2;
  313. assert(bpf_map_update_elem(fd, &key, values, BPF_EXIST) == -1 &&
  314. errno == E2BIG);
  315. /* Check that key = 2 doesn't exist. */
  316. assert(bpf_map_lookup_elem(fd, &key, values) == -1 && errno == ENOENT);
  317. /* Iterate over two elements. */
  318. assert(bpf_map_get_next_key(fd, NULL, &next_key) == 0 &&
  319. next_key == 0);
  320. assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 &&
  321. next_key == 0);
  322. assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 &&
  323. next_key == 1);
  324. assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 &&
  325. errno == ENOENT);
  326. /* Delete shouldn't succeed. */
  327. key = 1;
  328. assert(bpf_map_delete_elem(fd, &key) == -1 && errno == EINVAL);
  329. close(fd);
  330. }
  331. static void test_arraymap_percpu_many_keys(void)
  332. {
  333. unsigned int nr_cpus = bpf_num_possible_cpus();
  334. BPF_DECLARE_PERCPU(long, values);
  335. /* nr_keys is not too large otherwise the test stresses percpu
  336. * allocator more than anything else
  337. */
  338. unsigned int nr_keys = 2000;
  339. int key, fd, i;
  340. fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key),
  341. sizeof(bpf_percpu(values, 0)), nr_keys, 0);
  342. if (fd < 0) {
  343. printf("Failed to create per-cpu arraymap '%s'!\n",
  344. strerror(errno));
  345. exit(1);
  346. }
  347. for (i = 0; i < nr_cpus; i++)
  348. bpf_percpu(values, i) = i + 10;
  349. for (key = 0; key < nr_keys; key++)
  350. assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0);
  351. for (key = 0; key < nr_keys; key++) {
  352. for (i = 0; i < nr_cpus; i++)
  353. bpf_percpu(values, i) = 0;
  354. assert(bpf_map_lookup_elem(fd, &key, values) == 0);
  355. for (i = 0; i < nr_cpus; i++)
  356. assert(bpf_percpu(values, i) == i + 10);
  357. }
  358. close(fd);
  359. }
  360. static void test_devmap(int task, void *data)
  361. {
  362. int fd;
  363. __u32 key, value;
  364. fd = bpf_create_map(BPF_MAP_TYPE_DEVMAP, sizeof(key), sizeof(value),
  365. 2, 0);
  366. if (fd < 0) {
  367. printf("Failed to create arraymap '%s'!\n", strerror(errno));
  368. exit(1);
  369. }
  370. close(fd);
  371. }
  372. #include <sys/socket.h>
  373. #include <sys/ioctl.h>
  374. #include <arpa/inet.h>
  375. #include <sys/select.h>
  376. #include <linux/err.h>
  377. #define SOCKMAP_PARSE_PROG "./sockmap_parse_prog.o"
  378. #define SOCKMAP_VERDICT_PROG "./sockmap_verdict_prog.o"
  379. #define SOCKMAP_TCP_MSG_PROG "./sockmap_tcp_msg_prog.o"
  380. static void test_sockmap(int tasks, void *data)
  381. {
  382. struct bpf_map *bpf_map_rx, *bpf_map_tx, *bpf_map_msg, *bpf_map_break;
  383. int map_fd_msg = 0, map_fd_rx = 0, map_fd_tx = 0, map_fd_break;
  384. int ports[] = {50200, 50201, 50202, 50204};
  385. int err, i, fd, udp, sfd[6] = {0xdeadbeef};
  386. u8 buf[20] = {0x0, 0x5, 0x3, 0x2, 0x1, 0x0};
  387. int parse_prog, verdict_prog, msg_prog;
  388. struct sockaddr_in addr;
  389. int one = 1, s, sc, rc;
  390. struct bpf_object *obj;
  391. struct timeval to;
  392. __u32 key, value;
  393. pid_t pid[tasks];
  394. fd_set w;
  395. /* Create some sockets to use with sockmap */
  396. for (i = 0; i < 2; i++) {
  397. sfd[i] = socket(AF_INET, SOCK_STREAM, 0);
  398. if (sfd[i] < 0)
  399. goto out;
  400. err = setsockopt(sfd[i], SOL_SOCKET, SO_REUSEADDR,
  401. (char *)&one, sizeof(one));
  402. if (err) {
  403. printf("failed to setsockopt\n");
  404. goto out;
  405. }
  406. err = ioctl(sfd[i], FIONBIO, (char *)&one);
  407. if (err < 0) {
  408. printf("failed to ioctl\n");
  409. goto out;
  410. }
  411. memset(&addr, 0, sizeof(struct sockaddr_in));
  412. addr.sin_family = AF_INET;
  413. addr.sin_addr.s_addr = inet_addr("127.0.0.1");
  414. addr.sin_port = htons(ports[i]);
  415. err = bind(sfd[i], (struct sockaddr *)&addr, sizeof(addr));
  416. if (err < 0) {
  417. printf("failed to bind: err %i: %i:%i\n",
  418. err, i, sfd[i]);
  419. goto out;
  420. }
  421. err = listen(sfd[i], 32);
  422. if (err < 0) {
  423. printf("failed to listen\n");
  424. goto out;
  425. }
  426. }
  427. for (i = 2; i < 4; i++) {
  428. sfd[i] = socket(AF_INET, SOCK_STREAM, 0);
  429. if (sfd[i] < 0)
  430. goto out;
  431. err = setsockopt(sfd[i], SOL_SOCKET, SO_REUSEADDR,
  432. (char *)&one, sizeof(one));
  433. if (err) {
  434. printf("set sock opt\n");
  435. goto out;
  436. }
  437. memset(&addr, 0, sizeof(struct sockaddr_in));
  438. addr.sin_family = AF_INET;
  439. addr.sin_addr.s_addr = inet_addr("127.0.0.1");
  440. addr.sin_port = htons(ports[i - 2]);
  441. err = connect(sfd[i], (struct sockaddr *)&addr, sizeof(addr));
  442. if (err) {
  443. printf("failed to connect\n");
  444. goto out;
  445. }
  446. }
  447. for (i = 4; i < 6; i++) {
  448. sfd[i] = accept(sfd[i - 4], NULL, NULL);
  449. if (sfd[i] < 0) {
  450. printf("accept failed\n");
  451. goto out;
  452. }
  453. }
  454. /* Test sockmap with connected sockets */
  455. fd = bpf_create_map(BPF_MAP_TYPE_SOCKMAP,
  456. sizeof(key), sizeof(value),
  457. 6, 0);
  458. if (fd < 0) {
  459. printf("Failed to create sockmap %i\n", fd);
  460. goto out_sockmap;
  461. }
  462. /* Test update with unsupported UDP socket */
  463. udp = socket(AF_INET, SOCK_DGRAM, 0);
  464. i = 0;
  465. err = bpf_map_update_elem(fd, &i, &udp, BPF_ANY);
  466. if (!err) {
  467. printf("Failed socket SOCK_DGRAM allowed '%i:%i'\n",
  468. i, udp);
  469. goto out_sockmap;
  470. }
  471. /* Test update without programs */
  472. for (i = 0; i < 6; i++) {
  473. err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
  474. if (err) {
  475. printf("Failed noprog update sockmap '%i:%i'\n",
  476. i, sfd[i]);
  477. goto out_sockmap;
  478. }
  479. }
  480. /* Test attaching/detaching bad fds */
  481. err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_PARSER, 0);
  482. if (!err) {
  483. printf("Failed invalid parser prog attach\n");
  484. goto out_sockmap;
  485. }
  486. err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_VERDICT, 0);
  487. if (!err) {
  488. printf("Failed invalid verdict prog attach\n");
  489. goto out_sockmap;
  490. }
  491. err = bpf_prog_attach(-1, fd, BPF_SK_MSG_VERDICT, 0);
  492. if (!err) {
  493. printf("Failed invalid msg verdict prog attach\n");
  494. goto out_sockmap;
  495. }
  496. err = bpf_prog_attach(-1, fd, __MAX_BPF_ATTACH_TYPE, 0);
  497. if (!err) {
  498. printf("Failed unknown prog attach\n");
  499. goto out_sockmap;
  500. }
  501. err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_PARSER);
  502. if (err) {
  503. printf("Failed empty parser prog detach\n");
  504. goto out_sockmap;
  505. }
  506. err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_VERDICT);
  507. if (err) {
  508. printf("Failed empty verdict prog detach\n");
  509. goto out_sockmap;
  510. }
  511. err = bpf_prog_detach(fd, BPF_SK_MSG_VERDICT);
  512. if (err) {
  513. printf("Failed empty msg verdict prog detach\n");
  514. goto out_sockmap;
  515. }
  516. err = bpf_prog_detach(fd, __MAX_BPF_ATTACH_TYPE);
  517. if (!err) {
  518. printf("Detach invalid prog successful\n");
  519. goto out_sockmap;
  520. }
  521. /* Load SK_SKB program and Attach */
  522. err = bpf_prog_load(SOCKMAP_PARSE_PROG,
  523. BPF_PROG_TYPE_SK_SKB, &obj, &parse_prog);
  524. if (err) {
  525. printf("Failed to load SK_SKB parse prog\n");
  526. goto out_sockmap;
  527. }
  528. err = bpf_prog_load(SOCKMAP_TCP_MSG_PROG,
  529. BPF_PROG_TYPE_SK_MSG, &obj, &msg_prog);
  530. if (err) {
  531. printf("Failed to load SK_SKB msg prog\n");
  532. goto out_sockmap;
  533. }
  534. err = bpf_prog_load(SOCKMAP_VERDICT_PROG,
  535. BPF_PROG_TYPE_SK_SKB, &obj, &verdict_prog);
  536. if (err) {
  537. printf("Failed to load SK_SKB verdict prog\n");
  538. goto out_sockmap;
  539. }
  540. bpf_map_rx = bpf_object__find_map_by_name(obj, "sock_map_rx");
  541. if (IS_ERR(bpf_map_rx)) {
  542. printf("Failed to load map rx from verdict prog\n");
  543. goto out_sockmap;
  544. }
  545. map_fd_rx = bpf_map__fd(bpf_map_rx);
  546. if (map_fd_rx < 0) {
  547. printf("Failed to get map rx fd\n");
  548. goto out_sockmap;
  549. }
  550. bpf_map_tx = bpf_object__find_map_by_name(obj, "sock_map_tx");
  551. if (IS_ERR(bpf_map_tx)) {
  552. printf("Failed to load map tx from verdict prog\n");
  553. goto out_sockmap;
  554. }
  555. map_fd_tx = bpf_map__fd(bpf_map_tx);
  556. if (map_fd_tx < 0) {
  557. printf("Failed to get map tx fd\n");
  558. goto out_sockmap;
  559. }
  560. bpf_map_msg = bpf_object__find_map_by_name(obj, "sock_map_msg");
  561. if (IS_ERR(bpf_map_msg)) {
  562. printf("Failed to load map msg from msg_verdict prog\n");
  563. goto out_sockmap;
  564. }
  565. map_fd_msg = bpf_map__fd(bpf_map_msg);
  566. if (map_fd_msg < 0) {
  567. printf("Failed to get map msg fd\n");
  568. goto out_sockmap;
  569. }
  570. bpf_map_break = bpf_object__find_map_by_name(obj, "sock_map_break");
  571. if (IS_ERR(bpf_map_break)) {
  572. printf("Failed to load map tx from verdict prog\n");
  573. goto out_sockmap;
  574. }
  575. map_fd_break = bpf_map__fd(bpf_map_break);
  576. if (map_fd_break < 0) {
  577. printf("Failed to get map tx fd\n");
  578. goto out_sockmap;
  579. }
  580. err = bpf_prog_attach(parse_prog, map_fd_break,
  581. BPF_SK_SKB_STREAM_PARSER, 0);
  582. if (!err) {
  583. printf("Allowed attaching SK_SKB program to invalid map\n");
  584. goto out_sockmap;
  585. }
  586. err = bpf_prog_attach(parse_prog, map_fd_rx,
  587. BPF_SK_SKB_STREAM_PARSER, 0);
  588. if (err) {
  589. printf("Failed stream parser bpf prog attach\n");
  590. goto out_sockmap;
  591. }
  592. err = bpf_prog_attach(verdict_prog, map_fd_rx,
  593. BPF_SK_SKB_STREAM_VERDICT, 0);
  594. if (err) {
  595. printf("Failed stream verdict bpf prog attach\n");
  596. goto out_sockmap;
  597. }
  598. err = bpf_prog_attach(msg_prog, map_fd_msg, BPF_SK_MSG_VERDICT, 0);
  599. if (err) {
  600. printf("Failed msg verdict bpf prog attach\n");
  601. goto out_sockmap;
  602. }
  603. err = bpf_prog_attach(verdict_prog, map_fd_rx,
  604. __MAX_BPF_ATTACH_TYPE, 0);
  605. if (!err) {
  606. printf("Attached unknown bpf prog\n");
  607. goto out_sockmap;
  608. }
  609. /* Test map update elem afterwards fd lives in fd and map_fd */
  610. for (i = 0; i < 6; i++) {
  611. err = bpf_map_update_elem(map_fd_rx, &i, &sfd[i], BPF_ANY);
  612. if (err) {
  613. printf("Failed map_fd_rx update sockmap %i '%i:%i'\n",
  614. err, i, sfd[i]);
  615. goto out_sockmap;
  616. }
  617. err = bpf_map_update_elem(map_fd_tx, &i, &sfd[i], BPF_ANY);
  618. if (err) {
  619. printf("Failed map_fd_tx update sockmap %i '%i:%i'\n",
  620. err, i, sfd[i]);
  621. goto out_sockmap;
  622. }
  623. }
  624. /* Test map delete elem and remove send/recv sockets */
  625. for (i = 2; i < 4; i++) {
  626. err = bpf_map_delete_elem(map_fd_rx, &i);
  627. if (err) {
  628. printf("Failed delete sockmap rx %i '%i:%i'\n",
  629. err, i, sfd[i]);
  630. goto out_sockmap;
  631. }
  632. err = bpf_map_delete_elem(map_fd_tx, &i);
  633. if (err) {
  634. printf("Failed delete sockmap tx %i '%i:%i'\n",
  635. err, i, sfd[i]);
  636. goto out_sockmap;
  637. }
  638. }
  639. /* Put sfd[2] (sending fd below) into msg map to test sendmsg bpf */
  640. i = 0;
  641. err = bpf_map_update_elem(map_fd_msg, &i, &sfd[2], BPF_ANY);
  642. if (err) {
  643. printf("Failed map_fd_msg update sockmap %i\n", err);
  644. goto out_sockmap;
  645. }
  646. /* Test map send/recv */
  647. for (i = 0; i < 2; i++) {
  648. buf[0] = i;
  649. buf[1] = 0x5;
  650. sc = send(sfd[2], buf, 20, 0);
  651. if (sc < 0) {
  652. printf("Failed sockmap send\n");
  653. goto out_sockmap;
  654. }
  655. FD_ZERO(&w);
  656. FD_SET(sfd[3], &w);
  657. to.tv_sec = 1;
  658. to.tv_usec = 0;
  659. s = select(sfd[3] + 1, &w, NULL, NULL, &to);
  660. if (s == -1) {
  661. perror("Failed sockmap select()");
  662. goto out_sockmap;
  663. } else if (!s) {
  664. printf("Failed sockmap unexpected timeout\n");
  665. goto out_sockmap;
  666. }
  667. if (!FD_ISSET(sfd[3], &w)) {
  668. printf("Failed sockmap select/recv\n");
  669. goto out_sockmap;
  670. }
  671. rc = recv(sfd[3], buf, sizeof(buf), 0);
  672. if (rc < 0) {
  673. printf("Failed sockmap recv\n");
  674. goto out_sockmap;
  675. }
  676. }
  677. /* Negative null entry lookup from datapath should be dropped */
  678. buf[0] = 1;
  679. buf[1] = 12;
  680. sc = send(sfd[2], buf, 20, 0);
  681. if (sc < 0) {
  682. printf("Failed sockmap send\n");
  683. goto out_sockmap;
  684. }
  685. /* Push fd into same slot */
  686. i = 2;
  687. err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST);
  688. if (!err) {
  689. printf("Failed allowed sockmap dup slot BPF_NOEXIST\n");
  690. goto out_sockmap;
  691. }
  692. err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
  693. if (err) {
  694. printf("Failed sockmap update new slot BPF_ANY\n");
  695. goto out_sockmap;
  696. }
  697. err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST);
  698. if (err) {
  699. printf("Failed sockmap update new slot BPF_EXIST\n");
  700. goto out_sockmap;
  701. }
  702. /* Delete the elems without programs */
  703. for (i = 0; i < 6; i++) {
  704. err = bpf_map_delete_elem(fd, &i);
  705. if (err) {
  706. printf("Failed delete sockmap %i '%i:%i'\n",
  707. err, i, sfd[i]);
  708. }
  709. }
  710. /* Test having multiple maps open and set with programs on same fds */
  711. err = bpf_prog_attach(parse_prog, fd,
  712. BPF_SK_SKB_STREAM_PARSER, 0);
  713. if (err) {
  714. printf("Failed fd bpf parse prog attach\n");
  715. goto out_sockmap;
  716. }
  717. err = bpf_prog_attach(verdict_prog, fd,
  718. BPF_SK_SKB_STREAM_VERDICT, 0);
  719. if (err) {
  720. printf("Failed fd bpf verdict prog attach\n");
  721. goto out_sockmap;
  722. }
  723. for (i = 4; i < 6; i++) {
  724. err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
  725. if (!err) {
  726. printf("Failed allowed duplicate programs in update ANY sockmap %i '%i:%i'\n",
  727. err, i, sfd[i]);
  728. goto out_sockmap;
  729. }
  730. err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST);
  731. if (!err) {
  732. printf("Failed allowed duplicate program in update NOEXIST sockmap %i '%i:%i'\n",
  733. err, i, sfd[i]);
  734. goto out_sockmap;
  735. }
  736. err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST);
  737. if (!err) {
  738. printf("Failed allowed duplicate program in update EXIST sockmap %i '%i:%i'\n",
  739. err, i, sfd[i]);
  740. goto out_sockmap;
  741. }
  742. }
  743. /* Test tasks number of forked operations */
  744. for (i = 0; i < tasks; i++) {
  745. pid[i] = fork();
  746. if (pid[i] == 0) {
  747. for (i = 0; i < 6; i++) {
  748. bpf_map_delete_elem(map_fd_tx, &i);
  749. bpf_map_delete_elem(map_fd_rx, &i);
  750. bpf_map_update_elem(map_fd_tx, &i,
  751. &sfd[i], BPF_ANY);
  752. bpf_map_update_elem(map_fd_rx, &i,
  753. &sfd[i], BPF_ANY);
  754. }
  755. exit(0);
  756. } else if (pid[i] == -1) {
  757. printf("Couldn't spawn #%d process!\n", i);
  758. exit(1);
  759. }
  760. }
  761. for (i = 0; i < tasks; i++) {
  762. int status;
  763. assert(waitpid(pid[i], &status, 0) == pid[i]);
  764. assert(status == 0);
  765. }
  766. err = bpf_prog_detach(map_fd_rx, __MAX_BPF_ATTACH_TYPE);
  767. if (!err) {
  768. printf("Detached an invalid prog type.\n");
  769. goto out_sockmap;
  770. }
  771. err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_PARSER);
  772. if (err) {
  773. printf("Failed parser prog detach\n");
  774. goto out_sockmap;
  775. }
  776. err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_VERDICT);
  777. if (err) {
  778. printf("Failed parser prog detach\n");
  779. goto out_sockmap;
  780. }
  781. /* Test map close sockets and empty maps */
  782. for (i = 0; i < 6; i++) {
  783. bpf_map_delete_elem(map_fd_tx, &i);
  784. bpf_map_delete_elem(map_fd_rx, &i);
  785. close(sfd[i]);
  786. }
  787. close(fd);
  788. close(map_fd_rx);
  789. bpf_object__close(obj);
  790. return;
  791. out:
  792. for (i = 0; i < 6; i++)
  793. close(sfd[i]);
  794. printf("Failed to create sockmap '%i:%s'!\n", i, strerror(errno));
  795. exit(1);
  796. out_sockmap:
  797. for (i = 0; i < 6; i++) {
  798. if (map_fd_tx)
  799. bpf_map_delete_elem(map_fd_tx, &i);
  800. if (map_fd_rx)
  801. bpf_map_delete_elem(map_fd_rx, &i);
  802. close(sfd[i]);
  803. }
  804. close(fd);
  805. exit(1);
  806. }
  807. #define MAP_SIZE (32 * 1024)
  808. static void test_map_large(void)
  809. {
  810. struct bigkey {
  811. int a;
  812. char b[116];
  813. long long c;
  814. } key;
  815. int fd, i, value;
  816. fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
  817. MAP_SIZE, map_flags);
  818. if (fd < 0) {
  819. printf("Failed to create large map '%s'!\n", strerror(errno));
  820. exit(1);
  821. }
  822. for (i = 0; i < MAP_SIZE; i++) {
  823. key = (struct bigkey) { .c = i };
  824. value = i;
  825. assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0);
  826. }
  827. key.c = -1;
  828. assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
  829. errno == E2BIG);
  830. /* Iterate through all elements. */
  831. assert(bpf_map_get_next_key(fd, NULL, &key) == 0);
  832. key.c = -1;
  833. for (i = 0; i < MAP_SIZE; i++)
  834. assert(bpf_map_get_next_key(fd, &key, &key) == 0);
  835. assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT);
  836. key.c = 0;
  837. assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 0);
  838. key.a = 1;
  839. assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT);
  840. close(fd);
  841. }
  842. #define run_parallel(N, FN, DATA) \
  843. printf("Fork %d tasks to '" #FN "'\n", N); \
  844. __run_parallel(N, FN, DATA)
  845. static void __run_parallel(int tasks, void (*fn)(int task, void *data),
  846. void *data)
  847. {
  848. pid_t pid[tasks];
  849. int i;
  850. for (i = 0; i < tasks; i++) {
  851. pid[i] = fork();
  852. if (pid[i] == 0) {
  853. fn(i, data);
  854. exit(0);
  855. } else if (pid[i] == -1) {
  856. printf("Couldn't spawn #%d process!\n", i);
  857. exit(1);
  858. }
  859. }
  860. for (i = 0; i < tasks; i++) {
  861. int status;
  862. assert(waitpid(pid[i], &status, 0) == pid[i]);
  863. assert(status == 0);
  864. }
  865. }
  866. static void test_map_stress(void)
  867. {
  868. run_parallel(100, test_hashmap, NULL);
  869. run_parallel(100, test_hashmap_percpu, NULL);
  870. run_parallel(100, test_hashmap_sizes, NULL);
  871. run_parallel(100, test_hashmap_walk, NULL);
  872. run_parallel(100, test_arraymap, NULL);
  873. run_parallel(100, test_arraymap_percpu, NULL);
  874. }
  875. #define TASKS 1024
  876. #define DO_UPDATE 1
  877. #define DO_DELETE 0
  878. static void test_update_delete(int fn, void *data)
  879. {
  880. int do_update = ((int *)data)[1];
  881. int fd = ((int *)data)[0];
  882. int i, key, value;
  883. for (i = fn; i < MAP_SIZE; i += TASKS) {
  884. key = value = i;
  885. if (do_update) {
  886. assert(bpf_map_update_elem(fd, &key, &value,
  887. BPF_NOEXIST) == 0);
  888. assert(bpf_map_update_elem(fd, &key, &value,
  889. BPF_EXIST) == 0);
  890. } else {
  891. assert(bpf_map_delete_elem(fd, &key) == 0);
  892. }
  893. }
  894. }
  895. static void test_map_parallel(void)
  896. {
  897. int i, fd, key = 0, value = 0;
  898. int data[2];
  899. fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
  900. MAP_SIZE, map_flags);
  901. if (fd < 0) {
  902. printf("Failed to create map for parallel test '%s'!\n",
  903. strerror(errno));
  904. exit(1);
  905. }
  906. /* Use the same fd in children to add elements to this map:
  907. * child_0 adds key=0, key=1024, key=2048, ...
  908. * child_1 adds key=1, key=1025, key=2049, ...
  909. * child_1023 adds key=1023, ...
  910. */
  911. data[0] = fd;
  912. data[1] = DO_UPDATE;
  913. run_parallel(TASKS, test_update_delete, data);
  914. /* Check that key=0 is already there. */
  915. assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
  916. errno == EEXIST);
  917. /* Check that all elements were inserted. */
  918. assert(bpf_map_get_next_key(fd, NULL, &key) == 0);
  919. key = -1;
  920. for (i = 0; i < MAP_SIZE; i++)
  921. assert(bpf_map_get_next_key(fd, &key, &key) == 0);
  922. assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT);
  923. /* Another check for all elements */
  924. for (i = 0; i < MAP_SIZE; i++) {
  925. key = MAP_SIZE - i - 1;
  926. assert(bpf_map_lookup_elem(fd, &key, &value) == 0 &&
  927. value == key);
  928. }
  929. /* Now let's delete all elemenets in parallel. */
  930. data[1] = DO_DELETE;
  931. run_parallel(TASKS, test_update_delete, data);
  932. /* Nothing should be left. */
  933. key = -1;
  934. assert(bpf_map_get_next_key(fd, NULL, &key) == -1 && errno == ENOENT);
  935. assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT);
  936. }
  937. static void test_map_rdonly(void)
  938. {
  939. int fd, key = 0, value = 0;
  940. fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
  941. MAP_SIZE, map_flags | BPF_F_RDONLY);
  942. if (fd < 0) {
  943. printf("Failed to create map for read only test '%s'!\n",
  944. strerror(errno));
  945. exit(1);
  946. }
  947. key = 1;
  948. value = 1234;
  949. /* Insert key=1 element. */
  950. assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == -1 &&
  951. errno == EPERM);
  952. /* Check that key=2 is not found. */
  953. assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT);
  954. assert(bpf_map_get_next_key(fd, &key, &value) == -1 && errno == ENOENT);
  955. }
  956. static void test_map_wronly(void)
  957. {
  958. int fd, key = 0, value = 0;
  959. fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
  960. MAP_SIZE, map_flags | BPF_F_WRONLY);
  961. if (fd < 0) {
  962. printf("Failed to create map for read only test '%s'!\n",
  963. strerror(errno));
  964. exit(1);
  965. }
  966. key = 1;
  967. value = 1234;
  968. /* Insert key=1 element. */
  969. assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
  970. /* Check that key=2 is not found. */
  971. assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == EPERM);
  972. assert(bpf_map_get_next_key(fd, &key, &value) == -1 && errno == EPERM);
  973. }
  974. static void run_all_tests(void)
  975. {
  976. test_hashmap(0, NULL);
  977. test_hashmap_percpu(0, NULL);
  978. test_hashmap_walk(0, NULL);
  979. test_arraymap(0, NULL);
  980. test_arraymap_percpu(0, NULL);
  981. test_arraymap_percpu_many_keys();
  982. test_devmap(0, NULL);
  983. test_sockmap(0, NULL);
  984. test_map_large();
  985. test_map_parallel();
  986. test_map_stress();
  987. test_map_rdonly();
  988. test_map_wronly();
  989. }
  990. int main(void)
  991. {
  992. map_flags = 0;
  993. run_all_tests();
  994. map_flags = BPF_F_NO_PREALLOC;
  995. run_all_tests();
  996. printf("test_maps: OK\n");
  997. return 0;
  998. }