map.c 22 KB

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