map.c 23 KB

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