map.c 22 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048
  1. /*
  2. * Copyright (C) 2017-2018 Netronome Systems, Inc.
  3. *
  4. * This software is dual licensed under the GNU General License Version 2,
  5. * June 1991 as shown in the file COPYING in the top-level directory of this
  6. * source tree or the BSD 2-Clause License provided below. You have the
  7. * option to license this software under the complete terms of either license.
  8. *
  9. * The BSD 2-Clause License:
  10. *
  11. * Redistribution and use in source and binary forms, with or
  12. * without modification, are permitted provided that the following
  13. * conditions are met:
  14. *
  15. * 1. Redistributions of source code must retain the above
  16. * copyright notice, this list of conditions and the following
  17. * disclaimer.
  18. *
  19. * 2. Redistributions in binary form must reproduce the above
  20. * copyright notice, this list of conditions and the following
  21. * disclaimer in the documentation and/or other materials
  22. * provided with the distribution.
  23. *
  24. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  25. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  26. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  27. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  28. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  29. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  30. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  31. * SOFTWARE.
  32. */
  33. #include <assert.h>
  34. #include <errno.h>
  35. #include <fcntl.h>
  36. #include <linux/err.h>
  37. #include <linux/kernel.h>
  38. #include <stdbool.h>
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <string.h>
  42. #include <unistd.h>
  43. #include <sys/types.h>
  44. #include <sys/stat.h>
  45. #include <bpf.h>
  46. #include "btf.h"
  47. #include "json_writer.h"
  48. #include "main.h"
  49. static const char * const map_type_name[] = {
  50. [BPF_MAP_TYPE_UNSPEC] = "unspec",
  51. [BPF_MAP_TYPE_HASH] = "hash",
  52. [BPF_MAP_TYPE_ARRAY] = "array",
  53. [BPF_MAP_TYPE_PROG_ARRAY] = "prog_array",
  54. [BPF_MAP_TYPE_PERF_EVENT_ARRAY] = "perf_event_array",
  55. [BPF_MAP_TYPE_PERCPU_HASH] = "percpu_hash",
  56. [BPF_MAP_TYPE_PERCPU_ARRAY] = "percpu_array",
  57. [BPF_MAP_TYPE_STACK_TRACE] = "stack_trace",
  58. [BPF_MAP_TYPE_CGROUP_ARRAY] = "cgroup_array",
  59. [BPF_MAP_TYPE_LRU_HASH] = "lru_hash",
  60. [BPF_MAP_TYPE_LRU_PERCPU_HASH] = "lru_percpu_hash",
  61. [BPF_MAP_TYPE_LPM_TRIE] = "lpm_trie",
  62. [BPF_MAP_TYPE_ARRAY_OF_MAPS] = "array_of_maps",
  63. [BPF_MAP_TYPE_HASH_OF_MAPS] = "hash_of_maps",
  64. [BPF_MAP_TYPE_DEVMAP] = "devmap",
  65. [BPF_MAP_TYPE_SOCKMAP] = "sockmap",
  66. [BPF_MAP_TYPE_CPUMAP] = "cpumap",
  67. [BPF_MAP_TYPE_SOCKHASH] = "sockhash",
  68. [BPF_MAP_TYPE_CGROUP_STORAGE] = "cgroup_storage",
  69. };
  70. static bool map_is_per_cpu(__u32 type)
  71. {
  72. return type == BPF_MAP_TYPE_PERCPU_HASH ||
  73. type == BPF_MAP_TYPE_PERCPU_ARRAY ||
  74. type == BPF_MAP_TYPE_LRU_PERCPU_HASH;
  75. }
  76. static bool map_is_map_of_maps(__u32 type)
  77. {
  78. return type == BPF_MAP_TYPE_ARRAY_OF_MAPS ||
  79. type == BPF_MAP_TYPE_HASH_OF_MAPS;
  80. }
  81. static bool map_is_map_of_progs(__u32 type)
  82. {
  83. return type == BPF_MAP_TYPE_PROG_ARRAY;
  84. }
  85. static void *alloc_value(struct bpf_map_info *info)
  86. {
  87. if (map_is_per_cpu(info->type))
  88. return malloc(round_up(info->value_size, 8) *
  89. get_possible_cpus());
  90. else
  91. return malloc(info->value_size);
  92. }
  93. int map_parse_fd(int *argc, char ***argv)
  94. {
  95. int fd;
  96. if (is_prefix(**argv, "id")) {
  97. unsigned int id;
  98. char *endptr;
  99. NEXT_ARGP();
  100. id = strtoul(**argv, &endptr, 0);
  101. if (*endptr) {
  102. p_err("can't parse %s as ID", **argv);
  103. return -1;
  104. }
  105. NEXT_ARGP();
  106. fd = bpf_map_get_fd_by_id(id);
  107. if (fd < 0)
  108. p_err("get map by id (%u): %s", id, strerror(errno));
  109. return fd;
  110. } else if (is_prefix(**argv, "pinned")) {
  111. char *path;
  112. NEXT_ARGP();
  113. path = **argv;
  114. NEXT_ARGP();
  115. return open_obj_pinned_any(path, BPF_OBJ_MAP);
  116. }
  117. p_err("expected 'id' or 'pinned', got: '%s'?", **argv);
  118. return -1;
  119. }
  120. int map_parse_fd_and_info(int *argc, char ***argv, void *info, __u32 *info_len)
  121. {
  122. int err;
  123. int fd;
  124. fd = map_parse_fd(argc, argv);
  125. if (fd < 0)
  126. return -1;
  127. err = bpf_obj_get_info_by_fd(fd, info, info_len);
  128. if (err) {
  129. p_err("can't get map info: %s", strerror(errno));
  130. close(fd);
  131. return err;
  132. }
  133. return fd;
  134. }
  135. static int do_dump_btf(const struct btf_dumper *d,
  136. struct bpf_map_info *map_info, void *key,
  137. void *value)
  138. {
  139. int ret;
  140. /* start of key-value pair */
  141. jsonw_start_object(d->jw);
  142. jsonw_name(d->jw, "key");
  143. ret = btf_dumper_type(d, map_info->btf_key_type_id, key);
  144. if (ret)
  145. goto err_end_obj;
  146. jsonw_name(d->jw, "value");
  147. ret = btf_dumper_type(d, map_info->btf_value_type_id, value);
  148. err_end_obj:
  149. /* end of key-value pair */
  150. jsonw_end_object(d->jw);
  151. return ret;
  152. }
  153. static int get_btf(struct bpf_map_info *map_info, struct btf **btf)
  154. {
  155. struct bpf_btf_info btf_info = { 0 };
  156. __u32 len = sizeof(btf_info);
  157. __u32 last_size;
  158. int btf_fd;
  159. void *ptr;
  160. int err;
  161. err = 0;
  162. *btf = NULL;
  163. btf_fd = bpf_btf_get_fd_by_id(map_info->btf_id);
  164. if (btf_fd < 0)
  165. return 0;
  166. /* we won't know btf_size until we call bpf_obj_get_info_by_fd(). so
  167. * let's start with a sane default - 4KiB here - and resize it only if
  168. * bpf_obj_get_info_by_fd() needs a bigger buffer.
  169. */
  170. btf_info.btf_size = 4096;
  171. last_size = btf_info.btf_size;
  172. ptr = malloc(last_size);
  173. if (!ptr) {
  174. err = -ENOMEM;
  175. goto exit_free;
  176. }
  177. bzero(ptr, last_size);
  178. btf_info.btf = ptr_to_u64(ptr);
  179. err = bpf_obj_get_info_by_fd(btf_fd, &btf_info, &len);
  180. if (!err && btf_info.btf_size > last_size) {
  181. void *temp_ptr;
  182. last_size = btf_info.btf_size;
  183. temp_ptr = realloc(ptr, last_size);
  184. if (!temp_ptr) {
  185. err = -ENOMEM;
  186. goto exit_free;
  187. }
  188. ptr = temp_ptr;
  189. bzero(ptr, last_size);
  190. btf_info.btf = ptr_to_u64(ptr);
  191. err = bpf_obj_get_info_by_fd(btf_fd, &btf_info, &len);
  192. }
  193. if (err || btf_info.btf_size > last_size) {
  194. err = errno;
  195. goto exit_free;
  196. }
  197. *btf = btf__new((__u8 *)btf_info.btf, btf_info.btf_size, NULL);
  198. if (IS_ERR(*btf)) {
  199. err = PTR_ERR(*btf);
  200. *btf = NULL;
  201. }
  202. exit_free:
  203. close(btf_fd);
  204. free(ptr);
  205. return err;
  206. }
  207. static json_writer_t *get_btf_writer(void)
  208. {
  209. json_writer_t *jw = jsonw_new(stdout);
  210. if (!jw)
  211. return NULL;
  212. jsonw_pretty(jw, true);
  213. return jw;
  214. }
  215. static void print_entry_json(struct bpf_map_info *info, unsigned char *key,
  216. unsigned char *value, struct btf *btf)
  217. {
  218. jsonw_start_object(json_wtr);
  219. if (!map_is_per_cpu(info->type)) {
  220. jsonw_name(json_wtr, "key");
  221. print_hex_data_json(key, info->key_size);
  222. jsonw_name(json_wtr, "value");
  223. print_hex_data_json(value, info->value_size);
  224. if (btf) {
  225. struct btf_dumper d = {
  226. .btf = btf,
  227. .jw = json_wtr,
  228. .is_plain_text = false,
  229. };
  230. jsonw_name(json_wtr, "formatted");
  231. do_dump_btf(&d, info, key, value);
  232. }
  233. } else {
  234. unsigned int i, n, step;
  235. n = get_possible_cpus();
  236. step = round_up(info->value_size, 8);
  237. jsonw_name(json_wtr, "key");
  238. print_hex_data_json(key, info->key_size);
  239. jsonw_name(json_wtr, "values");
  240. jsonw_start_array(json_wtr);
  241. for (i = 0; i < n; i++) {
  242. jsonw_start_object(json_wtr);
  243. jsonw_int_field(json_wtr, "cpu", i);
  244. jsonw_name(json_wtr, "value");
  245. print_hex_data_json(value + i * step,
  246. info->value_size);
  247. jsonw_end_object(json_wtr);
  248. }
  249. jsonw_end_array(json_wtr);
  250. }
  251. jsonw_end_object(json_wtr);
  252. }
  253. static void print_entry_plain(struct bpf_map_info *info, unsigned char *key,
  254. unsigned char *value)
  255. {
  256. if (!map_is_per_cpu(info->type)) {
  257. bool single_line, break_names;
  258. break_names = info->key_size > 16 || info->value_size > 16;
  259. single_line = info->key_size + info->value_size <= 24 &&
  260. !break_names;
  261. printf("key:%c", break_names ? '\n' : ' ');
  262. fprint_hex(stdout, key, info->key_size, " ");
  263. printf(single_line ? " " : "\n");
  264. printf("value:%c", break_names ? '\n' : ' ');
  265. fprint_hex(stdout, value, info->value_size, " ");
  266. printf("\n");
  267. } else {
  268. unsigned int i, n, step;
  269. n = get_possible_cpus();
  270. step = round_up(info->value_size, 8);
  271. printf("key:\n");
  272. fprint_hex(stdout, key, info->key_size, " ");
  273. printf("\n");
  274. for (i = 0; i < n; i++) {
  275. printf("value (CPU %02d):%c",
  276. i, info->value_size > 16 ? '\n' : ' ');
  277. fprint_hex(stdout, value + i * step,
  278. info->value_size, " ");
  279. printf("\n");
  280. }
  281. }
  282. }
  283. static char **parse_bytes(char **argv, const char *name, unsigned char *val,
  284. unsigned int n)
  285. {
  286. unsigned int i = 0, base = 0;
  287. char *endptr;
  288. if (is_prefix(*argv, "hex")) {
  289. base = 16;
  290. argv++;
  291. }
  292. while (i < n && argv[i]) {
  293. val[i] = strtoul(argv[i], &endptr, base);
  294. if (*endptr) {
  295. p_err("error parsing byte: %s", argv[i]);
  296. return NULL;
  297. }
  298. i++;
  299. }
  300. if (i != n) {
  301. p_err("%s expected %d bytes got %d", name, n, i);
  302. return NULL;
  303. }
  304. return argv + i;
  305. }
  306. static int parse_elem(char **argv, struct bpf_map_info *info,
  307. void *key, void *value, __u32 key_size, __u32 value_size,
  308. __u32 *flags, __u32 **value_fd)
  309. {
  310. if (!*argv) {
  311. if (!key && !value)
  312. return 0;
  313. p_err("did not find %s", key ? "key" : "value");
  314. return -1;
  315. }
  316. if (is_prefix(*argv, "key")) {
  317. if (!key) {
  318. if (key_size)
  319. p_err("duplicate key");
  320. else
  321. p_err("unnecessary key");
  322. return -1;
  323. }
  324. argv = parse_bytes(argv + 1, "key", key, key_size);
  325. if (!argv)
  326. return -1;
  327. return parse_elem(argv, info, NULL, value, key_size, value_size,
  328. flags, value_fd);
  329. } else if (is_prefix(*argv, "value")) {
  330. int fd;
  331. if (!value) {
  332. if (value_size)
  333. p_err("duplicate value");
  334. else
  335. p_err("unnecessary value");
  336. return -1;
  337. }
  338. argv++;
  339. if (map_is_map_of_maps(info->type)) {
  340. int argc = 2;
  341. if (value_size != 4) {
  342. p_err("value smaller than 4B for map in map?");
  343. return -1;
  344. }
  345. if (!argv[0] || !argv[1]) {
  346. p_err("not enough value arguments for map in map");
  347. return -1;
  348. }
  349. fd = map_parse_fd(&argc, &argv);
  350. if (fd < 0)
  351. return -1;
  352. *value_fd = value;
  353. **value_fd = fd;
  354. } else if (map_is_map_of_progs(info->type)) {
  355. int argc = 2;
  356. if (value_size != 4) {
  357. p_err("value smaller than 4B for map of progs?");
  358. return -1;
  359. }
  360. if (!argv[0] || !argv[1]) {
  361. p_err("not enough value arguments for map of progs");
  362. return -1;
  363. }
  364. fd = prog_parse_fd(&argc, &argv);
  365. if (fd < 0)
  366. return -1;
  367. *value_fd = value;
  368. **value_fd = fd;
  369. } else {
  370. argv = parse_bytes(argv, "value", value, value_size);
  371. if (!argv)
  372. return -1;
  373. }
  374. return parse_elem(argv, info, key, NULL, key_size, value_size,
  375. flags, NULL);
  376. } else if (is_prefix(*argv, "any") || is_prefix(*argv, "noexist") ||
  377. is_prefix(*argv, "exist")) {
  378. if (!flags) {
  379. p_err("flags specified multiple times: %s", *argv);
  380. return -1;
  381. }
  382. if (is_prefix(*argv, "any"))
  383. *flags = BPF_ANY;
  384. else if (is_prefix(*argv, "noexist"))
  385. *flags = BPF_NOEXIST;
  386. else if (is_prefix(*argv, "exist"))
  387. *flags = BPF_EXIST;
  388. return parse_elem(argv + 1, info, key, value, key_size,
  389. value_size, NULL, value_fd);
  390. }
  391. p_err("expected key or value, got: %s", *argv);
  392. return -1;
  393. }
  394. static int show_map_close_json(int fd, struct bpf_map_info *info)
  395. {
  396. char *memlock;
  397. memlock = get_fdinfo(fd, "memlock");
  398. close(fd);
  399. jsonw_start_object(json_wtr);
  400. jsonw_uint_field(json_wtr, "id", info->id);
  401. if (info->type < ARRAY_SIZE(map_type_name))
  402. jsonw_string_field(json_wtr, "type",
  403. map_type_name[info->type]);
  404. else
  405. jsonw_uint_field(json_wtr, "type", info->type);
  406. if (*info->name)
  407. jsonw_string_field(json_wtr, "name", info->name);
  408. jsonw_name(json_wtr, "flags");
  409. jsonw_printf(json_wtr, "%d", info->map_flags);
  410. print_dev_json(info->ifindex, info->netns_dev, info->netns_ino);
  411. jsonw_uint_field(json_wtr, "bytes_key", info->key_size);
  412. jsonw_uint_field(json_wtr, "bytes_value", info->value_size);
  413. jsonw_uint_field(json_wtr, "max_entries", info->max_entries);
  414. if (memlock)
  415. jsonw_int_field(json_wtr, "bytes_memlock", atoi(memlock));
  416. free(memlock);
  417. if (!hash_empty(map_table.table)) {
  418. struct pinned_obj *obj;
  419. jsonw_name(json_wtr, "pinned");
  420. jsonw_start_array(json_wtr);
  421. hash_for_each_possible(map_table.table, obj, hash, info->id) {
  422. if (obj->id == info->id)
  423. jsonw_string(json_wtr, obj->path);
  424. }
  425. jsonw_end_array(json_wtr);
  426. }
  427. jsonw_end_object(json_wtr);
  428. return 0;
  429. }
  430. static int show_map_close_plain(int fd, struct bpf_map_info *info)
  431. {
  432. char *memlock;
  433. memlock = get_fdinfo(fd, "memlock");
  434. close(fd);
  435. printf("%u: ", info->id);
  436. if (info->type < ARRAY_SIZE(map_type_name))
  437. printf("%s ", map_type_name[info->type]);
  438. else
  439. printf("type %u ", info->type);
  440. if (*info->name)
  441. printf("name %s ", info->name);
  442. printf("flags 0x%x", info->map_flags);
  443. print_dev_plain(info->ifindex, info->netns_dev, info->netns_ino);
  444. printf("\n");
  445. printf("\tkey %uB value %uB max_entries %u",
  446. info->key_size, info->value_size, info->max_entries);
  447. if (memlock)
  448. printf(" memlock %sB", memlock);
  449. free(memlock);
  450. printf("\n");
  451. if (!hash_empty(map_table.table)) {
  452. struct pinned_obj *obj;
  453. hash_for_each_possible(map_table.table, obj, hash, info->id) {
  454. if (obj->id == info->id)
  455. printf("\tpinned %s\n", obj->path);
  456. }
  457. }
  458. return 0;
  459. }
  460. static int do_show(int argc, char **argv)
  461. {
  462. struct bpf_map_info info = {};
  463. __u32 len = sizeof(info);
  464. __u32 id = 0;
  465. int err;
  466. int fd;
  467. if (show_pinned)
  468. build_pinned_obj_table(&map_table, BPF_OBJ_MAP);
  469. if (argc == 2) {
  470. fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
  471. if (fd < 0)
  472. return -1;
  473. if (json_output)
  474. return show_map_close_json(fd, &info);
  475. else
  476. return show_map_close_plain(fd, &info);
  477. }
  478. if (argc)
  479. return BAD_ARG();
  480. if (json_output)
  481. jsonw_start_array(json_wtr);
  482. while (true) {
  483. err = bpf_map_get_next_id(id, &id);
  484. if (err) {
  485. if (errno == ENOENT)
  486. break;
  487. p_err("can't get next map: %s%s", strerror(errno),
  488. errno == EINVAL ? " -- kernel too old?" : "");
  489. break;
  490. }
  491. fd = bpf_map_get_fd_by_id(id);
  492. if (fd < 0) {
  493. if (errno == ENOENT)
  494. continue;
  495. p_err("can't get map by id (%u): %s",
  496. id, strerror(errno));
  497. break;
  498. }
  499. err = bpf_obj_get_info_by_fd(fd, &info, &len);
  500. if (err) {
  501. p_err("can't get map info: %s", strerror(errno));
  502. close(fd);
  503. break;
  504. }
  505. if (json_output)
  506. show_map_close_json(fd, &info);
  507. else
  508. show_map_close_plain(fd, &info);
  509. }
  510. if (json_output)
  511. jsonw_end_array(json_wtr);
  512. return errno == ENOENT ? 0 : -1;
  513. }
  514. static int do_dump(int argc, char **argv)
  515. {
  516. struct bpf_map_info info = {};
  517. void *key, *value, *prev_key;
  518. unsigned int num_elems = 0;
  519. __u32 len = sizeof(info);
  520. json_writer_t *btf_wtr;
  521. struct btf *btf = NULL;
  522. int err;
  523. int fd;
  524. if (argc != 2)
  525. usage();
  526. fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
  527. if (fd < 0)
  528. return -1;
  529. if (map_is_map_of_maps(info.type) || map_is_map_of_progs(info.type)) {
  530. p_err("Dumping maps of maps and program maps not supported");
  531. close(fd);
  532. return -1;
  533. }
  534. key = malloc(info.key_size);
  535. value = alloc_value(&info);
  536. if (!key || !value) {
  537. p_err("mem alloc failed");
  538. err = -1;
  539. goto exit_free;
  540. }
  541. prev_key = NULL;
  542. err = get_btf(&info, &btf);
  543. if (err) {
  544. p_err("failed to get btf");
  545. goto exit_free;
  546. }
  547. if (json_output)
  548. jsonw_start_array(json_wtr);
  549. else
  550. if (btf) {
  551. btf_wtr = get_btf_writer();
  552. if (!btf_wtr) {
  553. p_info("failed to create json writer for btf. falling back to plain output");
  554. btf__free(btf);
  555. btf = NULL;
  556. } else {
  557. jsonw_start_array(btf_wtr);
  558. }
  559. }
  560. while (true) {
  561. err = bpf_map_get_next_key(fd, prev_key, key);
  562. if (err) {
  563. if (errno == ENOENT)
  564. err = 0;
  565. break;
  566. }
  567. if (!bpf_map_lookup_elem(fd, key, value)) {
  568. if (json_output)
  569. print_entry_json(&info, key, value, btf);
  570. else
  571. if (btf) {
  572. struct btf_dumper d = {
  573. .btf = btf,
  574. .jw = btf_wtr,
  575. .is_plain_text = true,
  576. };
  577. do_dump_btf(&d, &info, key, value);
  578. } else {
  579. print_entry_plain(&info, key, value);
  580. }
  581. } else {
  582. if (json_output) {
  583. jsonw_name(json_wtr, "key");
  584. print_hex_data_json(key, info.key_size);
  585. jsonw_name(json_wtr, "value");
  586. jsonw_start_object(json_wtr);
  587. jsonw_string_field(json_wtr, "error",
  588. "can't lookup element");
  589. jsonw_end_object(json_wtr);
  590. } else {
  591. p_info("can't lookup element with key: ");
  592. fprint_hex(stderr, key, info.key_size, " ");
  593. fprintf(stderr, "\n");
  594. }
  595. }
  596. prev_key = key;
  597. num_elems++;
  598. }
  599. if (json_output)
  600. jsonw_end_array(json_wtr);
  601. else if (btf) {
  602. jsonw_end_array(btf_wtr);
  603. jsonw_destroy(&btf_wtr);
  604. } else {
  605. printf("Found %u element%s\n", num_elems,
  606. num_elems != 1 ? "s" : "");
  607. }
  608. exit_free:
  609. free(key);
  610. free(value);
  611. close(fd);
  612. btf__free(btf);
  613. return err;
  614. }
  615. static int do_update(int argc, char **argv)
  616. {
  617. struct bpf_map_info info = {};
  618. __u32 len = sizeof(info);
  619. __u32 *value_fd = NULL;
  620. __u32 flags = BPF_ANY;
  621. void *key, *value;
  622. int fd, err;
  623. if (argc < 2)
  624. usage();
  625. fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
  626. if (fd < 0)
  627. return -1;
  628. key = malloc(info.key_size);
  629. value = alloc_value(&info);
  630. if (!key || !value) {
  631. p_err("mem alloc failed");
  632. err = -1;
  633. goto exit_free;
  634. }
  635. err = parse_elem(argv, &info, key, value, info.key_size,
  636. info.value_size, &flags, &value_fd);
  637. if (err)
  638. goto exit_free;
  639. err = bpf_map_update_elem(fd, key, value, flags);
  640. if (err) {
  641. p_err("update failed: %s", strerror(errno));
  642. goto exit_free;
  643. }
  644. exit_free:
  645. if (value_fd)
  646. close(*value_fd);
  647. free(key);
  648. free(value);
  649. close(fd);
  650. if (!err && json_output)
  651. jsonw_null(json_wtr);
  652. return err;
  653. }
  654. static int do_lookup(int argc, char **argv)
  655. {
  656. struct bpf_map_info info = {};
  657. __u32 len = sizeof(info);
  658. json_writer_t *btf_wtr;
  659. struct btf *btf = NULL;
  660. void *key, *value;
  661. int err;
  662. int fd;
  663. if (argc < 2)
  664. usage();
  665. fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
  666. if (fd < 0)
  667. return -1;
  668. key = malloc(info.key_size);
  669. value = alloc_value(&info);
  670. if (!key || !value) {
  671. p_err("mem alloc failed");
  672. err = -1;
  673. goto exit_free;
  674. }
  675. err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL);
  676. if (err)
  677. goto exit_free;
  678. err = bpf_map_lookup_elem(fd, key, value);
  679. if (err) {
  680. if (errno == ENOENT) {
  681. if (json_output) {
  682. jsonw_null(json_wtr);
  683. } else {
  684. printf("key:\n");
  685. fprint_hex(stdout, key, info.key_size, " ");
  686. printf("\n\nNot found\n");
  687. }
  688. } else {
  689. p_err("lookup failed: %s", strerror(errno));
  690. }
  691. goto exit_free;
  692. }
  693. /* here means bpf_map_lookup_elem() succeeded */
  694. err = get_btf(&info, &btf);
  695. if (err) {
  696. p_err("failed to get btf");
  697. goto exit_free;
  698. }
  699. if (json_output) {
  700. print_entry_json(&info, key, value, btf);
  701. } else if (btf) {
  702. /* if here json_wtr wouldn't have been initialised,
  703. * so let's create separate writer for btf
  704. */
  705. btf_wtr = get_btf_writer();
  706. if (!btf_wtr) {
  707. p_info("failed to create json writer for btf. falling back to plain output");
  708. btf__free(btf);
  709. btf = NULL;
  710. print_entry_plain(&info, key, value);
  711. } else {
  712. struct btf_dumper d = {
  713. .btf = btf,
  714. .jw = btf_wtr,
  715. .is_plain_text = true,
  716. };
  717. do_dump_btf(&d, &info, key, value);
  718. jsonw_destroy(&btf_wtr);
  719. }
  720. } else {
  721. print_entry_plain(&info, key, value);
  722. }
  723. exit_free:
  724. free(key);
  725. free(value);
  726. close(fd);
  727. btf__free(btf);
  728. return err;
  729. }
  730. static int do_getnext(int argc, char **argv)
  731. {
  732. struct bpf_map_info info = {};
  733. __u32 len = sizeof(info);
  734. void *key, *nextkey;
  735. int err;
  736. int fd;
  737. if (argc < 2)
  738. usage();
  739. fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
  740. if (fd < 0)
  741. return -1;
  742. key = malloc(info.key_size);
  743. nextkey = malloc(info.key_size);
  744. if (!key || !nextkey) {
  745. p_err("mem alloc failed");
  746. err = -1;
  747. goto exit_free;
  748. }
  749. if (argc) {
  750. err = parse_elem(argv, &info, key, NULL, info.key_size, 0,
  751. NULL, NULL);
  752. if (err)
  753. goto exit_free;
  754. } else {
  755. free(key);
  756. key = NULL;
  757. }
  758. err = bpf_map_get_next_key(fd, key, nextkey);
  759. if (err) {
  760. p_err("can't get next key: %s", strerror(errno));
  761. goto exit_free;
  762. }
  763. if (json_output) {
  764. jsonw_start_object(json_wtr);
  765. if (key) {
  766. jsonw_name(json_wtr, "key");
  767. print_hex_data_json(key, info.key_size);
  768. } else {
  769. jsonw_null_field(json_wtr, "key");
  770. }
  771. jsonw_name(json_wtr, "next_key");
  772. print_hex_data_json(nextkey, info.key_size);
  773. jsonw_end_object(json_wtr);
  774. } else {
  775. if (key) {
  776. printf("key:\n");
  777. fprint_hex(stdout, key, info.key_size, " ");
  778. printf("\n");
  779. } else {
  780. printf("key: None\n");
  781. }
  782. printf("next key:\n");
  783. fprint_hex(stdout, nextkey, info.key_size, " ");
  784. printf("\n");
  785. }
  786. exit_free:
  787. free(nextkey);
  788. free(key);
  789. close(fd);
  790. return err;
  791. }
  792. static int do_delete(int argc, char **argv)
  793. {
  794. struct bpf_map_info info = {};
  795. __u32 len = sizeof(info);
  796. void *key;
  797. int err;
  798. int fd;
  799. if (argc < 2)
  800. usage();
  801. fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
  802. if (fd < 0)
  803. return -1;
  804. key = malloc(info.key_size);
  805. if (!key) {
  806. p_err("mem alloc failed");
  807. err = -1;
  808. goto exit_free;
  809. }
  810. err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL);
  811. if (err)
  812. goto exit_free;
  813. err = bpf_map_delete_elem(fd, key);
  814. if (err)
  815. p_err("delete failed: %s", strerror(errno));
  816. exit_free:
  817. free(key);
  818. close(fd);
  819. if (!err && json_output)
  820. jsonw_null(json_wtr);
  821. return err;
  822. }
  823. static int do_pin(int argc, char **argv)
  824. {
  825. int err;
  826. err = do_pin_any(argc, argv, bpf_map_get_fd_by_id);
  827. if (!err && json_output)
  828. jsonw_null(json_wtr);
  829. return err;
  830. }
  831. static int do_help(int argc, char **argv)
  832. {
  833. if (json_output) {
  834. jsonw_null(json_wtr);
  835. return 0;
  836. }
  837. fprintf(stderr,
  838. "Usage: %s %s { show | list } [MAP]\n"
  839. " %s %s dump MAP\n"
  840. " %s %s update MAP key DATA value VALUE [UPDATE_FLAGS]\n"
  841. " %s %s lookup MAP key DATA\n"
  842. " %s %s getnext MAP [key DATA]\n"
  843. " %s %s delete MAP key DATA\n"
  844. " %s %s pin MAP FILE\n"
  845. " %s %s event_pipe MAP [cpu N index M]\n"
  846. " %s %s help\n"
  847. "\n"
  848. " " HELP_SPEC_MAP "\n"
  849. " DATA := { [hex] BYTES }\n"
  850. " " HELP_SPEC_PROGRAM "\n"
  851. " VALUE := { DATA | MAP | PROG }\n"
  852. " UPDATE_FLAGS := { any | exist | noexist }\n"
  853. " " HELP_SPEC_OPTIONS "\n"
  854. "",
  855. bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
  856. bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
  857. bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2]);
  858. return 0;
  859. }
  860. static const struct cmd cmds[] = {
  861. { "show", do_show },
  862. { "list", do_show },
  863. { "help", do_help },
  864. { "dump", do_dump },
  865. { "update", do_update },
  866. { "lookup", do_lookup },
  867. { "getnext", do_getnext },
  868. { "delete", do_delete },
  869. { "pin", do_pin },
  870. { "event_pipe", do_event_pipe },
  871. { 0 }
  872. };
  873. int do_map(int argc, char **argv)
  874. {
  875. return cmd_select(cmds, argc, argv, do_help);
  876. }