1*858ea5e5SAndroid Build Coastguard Worker // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2*858ea5e5SAndroid Build Coastguard Worker /* Copyright (C) 2017-2018 Netronome Systems, Inc. */
3*858ea5e5SAndroid Build Coastguard Worker
4*858ea5e5SAndroid Build Coastguard Worker #include <errno.h>
5*858ea5e5SAndroid Build Coastguard Worker #include <fcntl.h>
6*858ea5e5SAndroid Build Coastguard Worker #include <linux/err.h>
7*858ea5e5SAndroid Build Coastguard Worker #include <linux/kernel.h>
8*858ea5e5SAndroid Build Coastguard Worker #include <net/if.h>
9*858ea5e5SAndroid Build Coastguard Worker #include <stdbool.h>
10*858ea5e5SAndroid Build Coastguard Worker #include <stdio.h>
11*858ea5e5SAndroid Build Coastguard Worker #include <stdlib.h>
12*858ea5e5SAndroid Build Coastguard Worker #include <string.h>
13*858ea5e5SAndroid Build Coastguard Worker #include <unistd.h>
14*858ea5e5SAndroid Build Coastguard Worker #include <sys/types.h>
15*858ea5e5SAndroid Build Coastguard Worker #include <sys/stat.h>
16*858ea5e5SAndroid Build Coastguard Worker
17*858ea5e5SAndroid Build Coastguard Worker #include <bpf/bpf.h>
18*858ea5e5SAndroid Build Coastguard Worker #include <bpf/btf.h>
19*858ea5e5SAndroid Build Coastguard Worker #include <bpf/hashmap.h>
20*858ea5e5SAndroid Build Coastguard Worker
21*858ea5e5SAndroid Build Coastguard Worker #include "json_writer.h"
22*858ea5e5SAndroid Build Coastguard Worker #include "main.h"
23*858ea5e5SAndroid Build Coastguard Worker
24*858ea5e5SAndroid Build Coastguard Worker static struct hashmap *map_table;
25*858ea5e5SAndroid Build Coastguard Worker
map_is_per_cpu(__u32 type)26*858ea5e5SAndroid Build Coastguard Worker static bool map_is_per_cpu(__u32 type)
27*858ea5e5SAndroid Build Coastguard Worker {
28*858ea5e5SAndroid Build Coastguard Worker return type == BPF_MAP_TYPE_PERCPU_HASH ||
29*858ea5e5SAndroid Build Coastguard Worker type == BPF_MAP_TYPE_PERCPU_ARRAY ||
30*858ea5e5SAndroid Build Coastguard Worker type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
31*858ea5e5SAndroid Build Coastguard Worker type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE;
32*858ea5e5SAndroid Build Coastguard Worker }
33*858ea5e5SAndroid Build Coastguard Worker
map_is_map_of_maps(__u32 type)34*858ea5e5SAndroid Build Coastguard Worker static bool map_is_map_of_maps(__u32 type)
35*858ea5e5SAndroid Build Coastguard Worker {
36*858ea5e5SAndroid Build Coastguard Worker return type == BPF_MAP_TYPE_ARRAY_OF_MAPS ||
37*858ea5e5SAndroid Build Coastguard Worker type == BPF_MAP_TYPE_HASH_OF_MAPS;
38*858ea5e5SAndroid Build Coastguard Worker }
39*858ea5e5SAndroid Build Coastguard Worker
map_is_map_of_progs(__u32 type)40*858ea5e5SAndroid Build Coastguard Worker static bool map_is_map_of_progs(__u32 type)
41*858ea5e5SAndroid Build Coastguard Worker {
42*858ea5e5SAndroid Build Coastguard Worker return type == BPF_MAP_TYPE_PROG_ARRAY;
43*858ea5e5SAndroid Build Coastguard Worker }
44*858ea5e5SAndroid Build Coastguard Worker
map_type_from_str(const char * type)45*858ea5e5SAndroid Build Coastguard Worker static int map_type_from_str(const char *type)
46*858ea5e5SAndroid Build Coastguard Worker {
47*858ea5e5SAndroid Build Coastguard Worker const char *map_type_str;
48*858ea5e5SAndroid Build Coastguard Worker unsigned int i;
49*858ea5e5SAndroid Build Coastguard Worker
50*858ea5e5SAndroid Build Coastguard Worker for (i = 0; ; i++) {
51*858ea5e5SAndroid Build Coastguard Worker map_type_str = libbpf_bpf_map_type_str(i);
52*858ea5e5SAndroid Build Coastguard Worker if (!map_type_str)
53*858ea5e5SAndroid Build Coastguard Worker break;
54*858ea5e5SAndroid Build Coastguard Worker
55*858ea5e5SAndroid Build Coastguard Worker /* Don't allow prefixing in case of possible future shadowing */
56*858ea5e5SAndroid Build Coastguard Worker if (!strcmp(map_type_str, type))
57*858ea5e5SAndroid Build Coastguard Worker return i;
58*858ea5e5SAndroid Build Coastguard Worker }
59*858ea5e5SAndroid Build Coastguard Worker return -1;
60*858ea5e5SAndroid Build Coastguard Worker }
61*858ea5e5SAndroid Build Coastguard Worker
alloc_value(struct bpf_map_info * info)62*858ea5e5SAndroid Build Coastguard Worker static void *alloc_value(struct bpf_map_info *info)
63*858ea5e5SAndroid Build Coastguard Worker {
64*858ea5e5SAndroid Build Coastguard Worker if (map_is_per_cpu(info->type))
65*858ea5e5SAndroid Build Coastguard Worker return malloc(round_up(info->value_size, 8) *
66*858ea5e5SAndroid Build Coastguard Worker get_possible_cpus());
67*858ea5e5SAndroid Build Coastguard Worker else
68*858ea5e5SAndroid Build Coastguard Worker return malloc(info->value_size);
69*858ea5e5SAndroid Build Coastguard Worker }
70*858ea5e5SAndroid Build Coastguard Worker
do_dump_btf(const struct btf_dumper * d,struct bpf_map_info * map_info,void * key,void * value)71*858ea5e5SAndroid Build Coastguard Worker static int do_dump_btf(const struct btf_dumper *d,
72*858ea5e5SAndroid Build Coastguard Worker struct bpf_map_info *map_info, void *key,
73*858ea5e5SAndroid Build Coastguard Worker void *value)
74*858ea5e5SAndroid Build Coastguard Worker {
75*858ea5e5SAndroid Build Coastguard Worker __u32 value_id;
76*858ea5e5SAndroid Build Coastguard Worker int ret = 0;
77*858ea5e5SAndroid Build Coastguard Worker
78*858ea5e5SAndroid Build Coastguard Worker /* start of key-value pair */
79*858ea5e5SAndroid Build Coastguard Worker jsonw_start_object(d->jw);
80*858ea5e5SAndroid Build Coastguard Worker
81*858ea5e5SAndroid Build Coastguard Worker if (map_info->btf_key_type_id) {
82*858ea5e5SAndroid Build Coastguard Worker jsonw_name(d->jw, "key");
83*858ea5e5SAndroid Build Coastguard Worker
84*858ea5e5SAndroid Build Coastguard Worker ret = btf_dumper_type(d, map_info->btf_key_type_id, key);
85*858ea5e5SAndroid Build Coastguard Worker if (ret)
86*858ea5e5SAndroid Build Coastguard Worker goto err_end_obj;
87*858ea5e5SAndroid Build Coastguard Worker }
88*858ea5e5SAndroid Build Coastguard Worker
89*858ea5e5SAndroid Build Coastguard Worker value_id = map_info->btf_vmlinux_value_type_id ?
90*858ea5e5SAndroid Build Coastguard Worker : map_info->btf_value_type_id;
91*858ea5e5SAndroid Build Coastguard Worker
92*858ea5e5SAndroid Build Coastguard Worker if (!map_is_per_cpu(map_info->type)) {
93*858ea5e5SAndroid Build Coastguard Worker jsonw_name(d->jw, "value");
94*858ea5e5SAndroid Build Coastguard Worker ret = btf_dumper_type(d, value_id, value);
95*858ea5e5SAndroid Build Coastguard Worker } else {
96*858ea5e5SAndroid Build Coastguard Worker unsigned int i, n, step;
97*858ea5e5SAndroid Build Coastguard Worker
98*858ea5e5SAndroid Build Coastguard Worker jsonw_name(d->jw, "values");
99*858ea5e5SAndroid Build Coastguard Worker jsonw_start_array(d->jw);
100*858ea5e5SAndroid Build Coastguard Worker n = get_possible_cpus();
101*858ea5e5SAndroid Build Coastguard Worker step = round_up(map_info->value_size, 8);
102*858ea5e5SAndroid Build Coastguard Worker for (i = 0; i < n; i++) {
103*858ea5e5SAndroid Build Coastguard Worker jsonw_start_object(d->jw);
104*858ea5e5SAndroid Build Coastguard Worker jsonw_int_field(d->jw, "cpu", i);
105*858ea5e5SAndroid Build Coastguard Worker jsonw_name(d->jw, "value");
106*858ea5e5SAndroid Build Coastguard Worker ret = btf_dumper_type(d, value_id, value + i * step);
107*858ea5e5SAndroid Build Coastguard Worker jsonw_end_object(d->jw);
108*858ea5e5SAndroid Build Coastguard Worker if (ret)
109*858ea5e5SAndroid Build Coastguard Worker break;
110*858ea5e5SAndroid Build Coastguard Worker }
111*858ea5e5SAndroid Build Coastguard Worker jsonw_end_array(d->jw);
112*858ea5e5SAndroid Build Coastguard Worker }
113*858ea5e5SAndroid Build Coastguard Worker
114*858ea5e5SAndroid Build Coastguard Worker err_end_obj:
115*858ea5e5SAndroid Build Coastguard Worker /* end of key-value pair */
116*858ea5e5SAndroid Build Coastguard Worker jsonw_end_object(d->jw);
117*858ea5e5SAndroid Build Coastguard Worker
118*858ea5e5SAndroid Build Coastguard Worker return ret;
119*858ea5e5SAndroid Build Coastguard Worker }
120*858ea5e5SAndroid Build Coastguard Worker
get_btf_writer(void)121*858ea5e5SAndroid Build Coastguard Worker static json_writer_t *get_btf_writer(void)
122*858ea5e5SAndroid Build Coastguard Worker {
123*858ea5e5SAndroid Build Coastguard Worker json_writer_t *jw = jsonw_new(stdout);
124*858ea5e5SAndroid Build Coastguard Worker
125*858ea5e5SAndroid Build Coastguard Worker if (!jw)
126*858ea5e5SAndroid Build Coastguard Worker return NULL;
127*858ea5e5SAndroid Build Coastguard Worker jsonw_pretty(jw, true);
128*858ea5e5SAndroid Build Coastguard Worker
129*858ea5e5SAndroid Build Coastguard Worker return jw;
130*858ea5e5SAndroid Build Coastguard Worker }
131*858ea5e5SAndroid Build Coastguard Worker
print_entry_json(struct bpf_map_info * info,unsigned char * key,unsigned char * value,struct btf * btf)132*858ea5e5SAndroid Build Coastguard Worker static void print_entry_json(struct bpf_map_info *info, unsigned char *key,
133*858ea5e5SAndroid Build Coastguard Worker unsigned char *value, struct btf *btf)
134*858ea5e5SAndroid Build Coastguard Worker {
135*858ea5e5SAndroid Build Coastguard Worker jsonw_start_object(json_wtr);
136*858ea5e5SAndroid Build Coastguard Worker
137*858ea5e5SAndroid Build Coastguard Worker if (!map_is_per_cpu(info->type)) {
138*858ea5e5SAndroid Build Coastguard Worker jsonw_name(json_wtr, "key");
139*858ea5e5SAndroid Build Coastguard Worker print_hex_data_json(key, info->key_size);
140*858ea5e5SAndroid Build Coastguard Worker jsonw_name(json_wtr, "value");
141*858ea5e5SAndroid Build Coastguard Worker print_hex_data_json(value, info->value_size);
142*858ea5e5SAndroid Build Coastguard Worker if (map_is_map_of_maps(info->type))
143*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(json_wtr, "inner_map_id",
144*858ea5e5SAndroid Build Coastguard Worker *(unsigned int *)value);
145*858ea5e5SAndroid Build Coastguard Worker if (btf) {
146*858ea5e5SAndroid Build Coastguard Worker struct btf_dumper d = {
147*858ea5e5SAndroid Build Coastguard Worker .btf = btf,
148*858ea5e5SAndroid Build Coastguard Worker .jw = json_wtr,
149*858ea5e5SAndroid Build Coastguard Worker .is_plain_text = false,
150*858ea5e5SAndroid Build Coastguard Worker };
151*858ea5e5SAndroid Build Coastguard Worker
152*858ea5e5SAndroid Build Coastguard Worker jsonw_name(json_wtr, "formatted");
153*858ea5e5SAndroid Build Coastguard Worker do_dump_btf(&d, info, key, value);
154*858ea5e5SAndroid Build Coastguard Worker }
155*858ea5e5SAndroid Build Coastguard Worker } else {
156*858ea5e5SAndroid Build Coastguard Worker unsigned int i, n, step;
157*858ea5e5SAndroid Build Coastguard Worker
158*858ea5e5SAndroid Build Coastguard Worker n = get_possible_cpus();
159*858ea5e5SAndroid Build Coastguard Worker step = round_up(info->value_size, 8);
160*858ea5e5SAndroid Build Coastguard Worker
161*858ea5e5SAndroid Build Coastguard Worker jsonw_name(json_wtr, "key");
162*858ea5e5SAndroid Build Coastguard Worker print_hex_data_json(key, info->key_size);
163*858ea5e5SAndroid Build Coastguard Worker
164*858ea5e5SAndroid Build Coastguard Worker jsonw_name(json_wtr, "values");
165*858ea5e5SAndroid Build Coastguard Worker jsonw_start_array(json_wtr);
166*858ea5e5SAndroid Build Coastguard Worker for (i = 0; i < n; i++) {
167*858ea5e5SAndroid Build Coastguard Worker jsonw_start_object(json_wtr);
168*858ea5e5SAndroid Build Coastguard Worker
169*858ea5e5SAndroid Build Coastguard Worker jsonw_int_field(json_wtr, "cpu", i);
170*858ea5e5SAndroid Build Coastguard Worker
171*858ea5e5SAndroid Build Coastguard Worker jsonw_name(json_wtr, "value");
172*858ea5e5SAndroid Build Coastguard Worker print_hex_data_json(value + i * step,
173*858ea5e5SAndroid Build Coastguard Worker info->value_size);
174*858ea5e5SAndroid Build Coastguard Worker
175*858ea5e5SAndroid Build Coastguard Worker jsonw_end_object(json_wtr);
176*858ea5e5SAndroid Build Coastguard Worker }
177*858ea5e5SAndroid Build Coastguard Worker jsonw_end_array(json_wtr);
178*858ea5e5SAndroid Build Coastguard Worker if (btf) {
179*858ea5e5SAndroid Build Coastguard Worker struct btf_dumper d = {
180*858ea5e5SAndroid Build Coastguard Worker .btf = btf,
181*858ea5e5SAndroid Build Coastguard Worker .jw = json_wtr,
182*858ea5e5SAndroid Build Coastguard Worker .is_plain_text = false,
183*858ea5e5SAndroid Build Coastguard Worker };
184*858ea5e5SAndroid Build Coastguard Worker
185*858ea5e5SAndroid Build Coastguard Worker jsonw_name(json_wtr, "formatted");
186*858ea5e5SAndroid Build Coastguard Worker do_dump_btf(&d, info, key, value);
187*858ea5e5SAndroid Build Coastguard Worker }
188*858ea5e5SAndroid Build Coastguard Worker }
189*858ea5e5SAndroid Build Coastguard Worker
190*858ea5e5SAndroid Build Coastguard Worker jsonw_end_object(json_wtr);
191*858ea5e5SAndroid Build Coastguard Worker }
192*858ea5e5SAndroid Build Coastguard Worker
193*858ea5e5SAndroid Build Coastguard Worker static void
print_entry_error_msg(struct bpf_map_info * info,unsigned char * key,const char * error_msg)194*858ea5e5SAndroid Build Coastguard Worker print_entry_error_msg(struct bpf_map_info *info, unsigned char *key,
195*858ea5e5SAndroid Build Coastguard Worker const char *error_msg)
196*858ea5e5SAndroid Build Coastguard Worker {
197*858ea5e5SAndroid Build Coastguard Worker int msg_size = strlen(error_msg);
198*858ea5e5SAndroid Build Coastguard Worker bool single_line, break_names;
199*858ea5e5SAndroid Build Coastguard Worker
200*858ea5e5SAndroid Build Coastguard Worker break_names = info->key_size > 16 || msg_size > 16;
201*858ea5e5SAndroid Build Coastguard Worker single_line = info->key_size + msg_size <= 24 && !break_names;
202*858ea5e5SAndroid Build Coastguard Worker
203*858ea5e5SAndroid Build Coastguard Worker printf("key:%c", break_names ? '\n' : ' ');
204*858ea5e5SAndroid Build Coastguard Worker fprint_hex(stdout, key, info->key_size, " ");
205*858ea5e5SAndroid Build Coastguard Worker
206*858ea5e5SAndroid Build Coastguard Worker printf(single_line ? " " : "\n");
207*858ea5e5SAndroid Build Coastguard Worker
208*858ea5e5SAndroid Build Coastguard Worker printf("value:%c%s", break_names ? '\n' : ' ', error_msg);
209*858ea5e5SAndroid Build Coastguard Worker
210*858ea5e5SAndroid Build Coastguard Worker printf("\n");
211*858ea5e5SAndroid Build Coastguard Worker }
212*858ea5e5SAndroid Build Coastguard Worker
213*858ea5e5SAndroid Build Coastguard Worker static void
print_entry_error(struct bpf_map_info * map_info,void * key,int lookup_errno)214*858ea5e5SAndroid Build Coastguard Worker print_entry_error(struct bpf_map_info *map_info, void *key, int lookup_errno)
215*858ea5e5SAndroid Build Coastguard Worker {
216*858ea5e5SAndroid Build Coastguard Worker /* For prog_array maps or arrays of maps, failure to lookup the value
217*858ea5e5SAndroid Build Coastguard Worker * means there is no entry for that key. Do not print an error message
218*858ea5e5SAndroid Build Coastguard Worker * in that case.
219*858ea5e5SAndroid Build Coastguard Worker */
220*858ea5e5SAndroid Build Coastguard Worker if ((map_is_map_of_maps(map_info->type) ||
221*858ea5e5SAndroid Build Coastguard Worker map_is_map_of_progs(map_info->type)) && lookup_errno == ENOENT)
222*858ea5e5SAndroid Build Coastguard Worker return;
223*858ea5e5SAndroid Build Coastguard Worker
224*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
225*858ea5e5SAndroid Build Coastguard Worker jsonw_start_object(json_wtr); /* entry */
226*858ea5e5SAndroid Build Coastguard Worker jsonw_name(json_wtr, "key");
227*858ea5e5SAndroid Build Coastguard Worker print_hex_data_json(key, map_info->key_size);
228*858ea5e5SAndroid Build Coastguard Worker jsonw_name(json_wtr, "value");
229*858ea5e5SAndroid Build Coastguard Worker jsonw_start_object(json_wtr); /* error */
230*858ea5e5SAndroid Build Coastguard Worker jsonw_string_field(json_wtr, "error", strerror(lookup_errno));
231*858ea5e5SAndroid Build Coastguard Worker jsonw_end_object(json_wtr); /* error */
232*858ea5e5SAndroid Build Coastguard Worker jsonw_end_object(json_wtr); /* entry */
233*858ea5e5SAndroid Build Coastguard Worker } else {
234*858ea5e5SAndroid Build Coastguard Worker const char *msg = NULL;
235*858ea5e5SAndroid Build Coastguard Worker
236*858ea5e5SAndroid Build Coastguard Worker if (lookup_errno == ENOENT)
237*858ea5e5SAndroid Build Coastguard Worker msg = "<no entry>";
238*858ea5e5SAndroid Build Coastguard Worker else if (lookup_errno == ENOSPC &&
239*858ea5e5SAndroid Build Coastguard Worker map_info->type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY)
240*858ea5e5SAndroid Build Coastguard Worker msg = "<cannot read>";
241*858ea5e5SAndroid Build Coastguard Worker
242*858ea5e5SAndroid Build Coastguard Worker print_entry_error_msg(map_info, key,
243*858ea5e5SAndroid Build Coastguard Worker msg ? : strerror(lookup_errno));
244*858ea5e5SAndroid Build Coastguard Worker }
245*858ea5e5SAndroid Build Coastguard Worker }
246*858ea5e5SAndroid Build Coastguard Worker
print_entry_plain(struct bpf_map_info * info,unsigned char * key,unsigned char * value)247*858ea5e5SAndroid Build Coastguard Worker static void print_entry_plain(struct bpf_map_info *info, unsigned char *key,
248*858ea5e5SAndroid Build Coastguard Worker unsigned char *value)
249*858ea5e5SAndroid Build Coastguard Worker {
250*858ea5e5SAndroid Build Coastguard Worker if (!map_is_per_cpu(info->type)) {
251*858ea5e5SAndroid Build Coastguard Worker bool single_line, break_names;
252*858ea5e5SAndroid Build Coastguard Worker
253*858ea5e5SAndroid Build Coastguard Worker break_names = info->key_size > 16 || info->value_size > 16;
254*858ea5e5SAndroid Build Coastguard Worker single_line = info->key_size + info->value_size <= 24 &&
255*858ea5e5SAndroid Build Coastguard Worker !break_names;
256*858ea5e5SAndroid Build Coastguard Worker
257*858ea5e5SAndroid Build Coastguard Worker if (info->key_size) {
258*858ea5e5SAndroid Build Coastguard Worker printf("key:%c", break_names ? '\n' : ' ');
259*858ea5e5SAndroid Build Coastguard Worker fprint_hex(stdout, key, info->key_size, " ");
260*858ea5e5SAndroid Build Coastguard Worker
261*858ea5e5SAndroid Build Coastguard Worker printf(single_line ? " " : "\n");
262*858ea5e5SAndroid Build Coastguard Worker }
263*858ea5e5SAndroid Build Coastguard Worker
264*858ea5e5SAndroid Build Coastguard Worker if (info->value_size) {
265*858ea5e5SAndroid Build Coastguard Worker if (map_is_map_of_maps(info->type)) {
266*858ea5e5SAndroid Build Coastguard Worker printf("inner_map_id:%c", break_names ? '\n' : ' ');
267*858ea5e5SAndroid Build Coastguard Worker printf("%u ", *(unsigned int *)value);
268*858ea5e5SAndroid Build Coastguard Worker } else {
269*858ea5e5SAndroid Build Coastguard Worker printf("value:%c", break_names ? '\n' : ' ');
270*858ea5e5SAndroid Build Coastguard Worker fprint_hex(stdout, value, info->value_size, " ");
271*858ea5e5SAndroid Build Coastguard Worker }
272*858ea5e5SAndroid Build Coastguard Worker }
273*858ea5e5SAndroid Build Coastguard Worker
274*858ea5e5SAndroid Build Coastguard Worker printf("\n");
275*858ea5e5SAndroid Build Coastguard Worker } else {
276*858ea5e5SAndroid Build Coastguard Worker unsigned int i, n, step;
277*858ea5e5SAndroid Build Coastguard Worker
278*858ea5e5SAndroid Build Coastguard Worker n = get_possible_cpus();
279*858ea5e5SAndroid Build Coastguard Worker step = round_up(info->value_size, 8);
280*858ea5e5SAndroid Build Coastguard Worker
281*858ea5e5SAndroid Build Coastguard Worker if (info->key_size) {
282*858ea5e5SAndroid Build Coastguard Worker printf("key:\n");
283*858ea5e5SAndroid Build Coastguard Worker fprint_hex(stdout, key, info->key_size, " ");
284*858ea5e5SAndroid Build Coastguard Worker printf("\n");
285*858ea5e5SAndroid Build Coastguard Worker }
286*858ea5e5SAndroid Build Coastguard Worker if (info->value_size) {
287*858ea5e5SAndroid Build Coastguard Worker for (i = 0; i < n; i++) {
288*858ea5e5SAndroid Build Coastguard Worker printf("value (CPU %02d):%c",
289*858ea5e5SAndroid Build Coastguard Worker i, info->value_size > 16 ? '\n' : ' ');
290*858ea5e5SAndroid Build Coastguard Worker fprint_hex(stdout, value + i * step,
291*858ea5e5SAndroid Build Coastguard Worker info->value_size, " ");
292*858ea5e5SAndroid Build Coastguard Worker printf("\n");
293*858ea5e5SAndroid Build Coastguard Worker }
294*858ea5e5SAndroid Build Coastguard Worker }
295*858ea5e5SAndroid Build Coastguard Worker }
296*858ea5e5SAndroid Build Coastguard Worker }
297*858ea5e5SAndroid Build Coastguard Worker
parse_bytes(char ** argv,const char * name,unsigned char * val,unsigned int n)298*858ea5e5SAndroid Build Coastguard Worker static char **parse_bytes(char **argv, const char *name, unsigned char *val,
299*858ea5e5SAndroid Build Coastguard Worker unsigned int n)
300*858ea5e5SAndroid Build Coastguard Worker {
301*858ea5e5SAndroid Build Coastguard Worker unsigned int i = 0, base = 0;
302*858ea5e5SAndroid Build Coastguard Worker char *endptr;
303*858ea5e5SAndroid Build Coastguard Worker
304*858ea5e5SAndroid Build Coastguard Worker if (is_prefix(*argv, "hex")) {
305*858ea5e5SAndroid Build Coastguard Worker base = 16;
306*858ea5e5SAndroid Build Coastguard Worker argv++;
307*858ea5e5SAndroid Build Coastguard Worker }
308*858ea5e5SAndroid Build Coastguard Worker
309*858ea5e5SAndroid Build Coastguard Worker while (i < n && argv[i]) {
310*858ea5e5SAndroid Build Coastguard Worker val[i] = strtoul(argv[i], &endptr, base);
311*858ea5e5SAndroid Build Coastguard Worker if (*endptr) {
312*858ea5e5SAndroid Build Coastguard Worker p_err("error parsing byte: %s", argv[i]);
313*858ea5e5SAndroid Build Coastguard Worker return NULL;
314*858ea5e5SAndroid Build Coastguard Worker }
315*858ea5e5SAndroid Build Coastguard Worker i++;
316*858ea5e5SAndroid Build Coastguard Worker }
317*858ea5e5SAndroid Build Coastguard Worker
318*858ea5e5SAndroid Build Coastguard Worker if (i != n) {
319*858ea5e5SAndroid Build Coastguard Worker p_err("%s expected %d bytes got %d", name, n, i);
320*858ea5e5SAndroid Build Coastguard Worker return NULL;
321*858ea5e5SAndroid Build Coastguard Worker }
322*858ea5e5SAndroid Build Coastguard Worker
323*858ea5e5SAndroid Build Coastguard Worker return argv + i;
324*858ea5e5SAndroid Build Coastguard Worker }
325*858ea5e5SAndroid Build Coastguard Worker
326*858ea5e5SAndroid Build Coastguard Worker /* on per cpu maps we must copy the provided value on all value instances */
fill_per_cpu_value(struct bpf_map_info * info,void * value)327*858ea5e5SAndroid Build Coastguard Worker static void fill_per_cpu_value(struct bpf_map_info *info, void *value)
328*858ea5e5SAndroid Build Coastguard Worker {
329*858ea5e5SAndroid Build Coastguard Worker unsigned int i, n, step;
330*858ea5e5SAndroid Build Coastguard Worker
331*858ea5e5SAndroid Build Coastguard Worker if (!map_is_per_cpu(info->type))
332*858ea5e5SAndroid Build Coastguard Worker return;
333*858ea5e5SAndroid Build Coastguard Worker
334*858ea5e5SAndroid Build Coastguard Worker n = get_possible_cpus();
335*858ea5e5SAndroid Build Coastguard Worker step = round_up(info->value_size, 8);
336*858ea5e5SAndroid Build Coastguard Worker for (i = 1; i < n; i++)
337*858ea5e5SAndroid Build Coastguard Worker memcpy(value + i * step, value, info->value_size);
338*858ea5e5SAndroid Build Coastguard Worker }
339*858ea5e5SAndroid Build Coastguard Worker
parse_elem(char ** argv,struct bpf_map_info * info,void * key,void * value,__u32 key_size,__u32 value_size,__u32 * flags,__u32 ** value_fd)340*858ea5e5SAndroid Build Coastguard Worker static int parse_elem(char **argv, struct bpf_map_info *info,
341*858ea5e5SAndroid Build Coastguard Worker void *key, void *value, __u32 key_size, __u32 value_size,
342*858ea5e5SAndroid Build Coastguard Worker __u32 *flags, __u32 **value_fd)
343*858ea5e5SAndroid Build Coastguard Worker {
344*858ea5e5SAndroid Build Coastguard Worker if (!*argv) {
345*858ea5e5SAndroid Build Coastguard Worker if (!key && !value)
346*858ea5e5SAndroid Build Coastguard Worker return 0;
347*858ea5e5SAndroid Build Coastguard Worker p_err("did not find %s", key ? "key" : "value");
348*858ea5e5SAndroid Build Coastguard Worker return -1;
349*858ea5e5SAndroid Build Coastguard Worker }
350*858ea5e5SAndroid Build Coastguard Worker
351*858ea5e5SAndroid Build Coastguard Worker if (is_prefix(*argv, "key")) {
352*858ea5e5SAndroid Build Coastguard Worker if (!key) {
353*858ea5e5SAndroid Build Coastguard Worker if (key_size)
354*858ea5e5SAndroid Build Coastguard Worker p_err("duplicate key");
355*858ea5e5SAndroid Build Coastguard Worker else
356*858ea5e5SAndroid Build Coastguard Worker p_err("unnecessary key");
357*858ea5e5SAndroid Build Coastguard Worker return -1;
358*858ea5e5SAndroid Build Coastguard Worker }
359*858ea5e5SAndroid Build Coastguard Worker
360*858ea5e5SAndroid Build Coastguard Worker argv = parse_bytes(argv + 1, "key", key, key_size);
361*858ea5e5SAndroid Build Coastguard Worker if (!argv)
362*858ea5e5SAndroid Build Coastguard Worker return -1;
363*858ea5e5SAndroid Build Coastguard Worker
364*858ea5e5SAndroid Build Coastguard Worker return parse_elem(argv, info, NULL, value, key_size, value_size,
365*858ea5e5SAndroid Build Coastguard Worker flags, value_fd);
366*858ea5e5SAndroid Build Coastguard Worker } else if (is_prefix(*argv, "value")) {
367*858ea5e5SAndroid Build Coastguard Worker int fd;
368*858ea5e5SAndroid Build Coastguard Worker
369*858ea5e5SAndroid Build Coastguard Worker if (!value) {
370*858ea5e5SAndroid Build Coastguard Worker if (value_size)
371*858ea5e5SAndroid Build Coastguard Worker p_err("duplicate value");
372*858ea5e5SAndroid Build Coastguard Worker else
373*858ea5e5SAndroid Build Coastguard Worker p_err("unnecessary value");
374*858ea5e5SAndroid Build Coastguard Worker return -1;
375*858ea5e5SAndroid Build Coastguard Worker }
376*858ea5e5SAndroid Build Coastguard Worker
377*858ea5e5SAndroid Build Coastguard Worker argv++;
378*858ea5e5SAndroid Build Coastguard Worker
379*858ea5e5SAndroid Build Coastguard Worker if (map_is_map_of_maps(info->type)) {
380*858ea5e5SAndroid Build Coastguard Worker int argc = 2;
381*858ea5e5SAndroid Build Coastguard Worker
382*858ea5e5SAndroid Build Coastguard Worker if (value_size != 4) {
383*858ea5e5SAndroid Build Coastguard Worker p_err("value smaller than 4B for map in map?");
384*858ea5e5SAndroid Build Coastguard Worker return -1;
385*858ea5e5SAndroid Build Coastguard Worker }
386*858ea5e5SAndroid Build Coastguard Worker if (!argv[0] || !argv[1]) {
387*858ea5e5SAndroid Build Coastguard Worker p_err("not enough value arguments for map in map");
388*858ea5e5SAndroid Build Coastguard Worker return -1;
389*858ea5e5SAndroid Build Coastguard Worker }
390*858ea5e5SAndroid Build Coastguard Worker
391*858ea5e5SAndroid Build Coastguard Worker fd = map_parse_fd(&argc, &argv);
392*858ea5e5SAndroid Build Coastguard Worker if (fd < 0)
393*858ea5e5SAndroid Build Coastguard Worker return -1;
394*858ea5e5SAndroid Build Coastguard Worker
395*858ea5e5SAndroid Build Coastguard Worker *value_fd = value;
396*858ea5e5SAndroid Build Coastguard Worker **value_fd = fd;
397*858ea5e5SAndroid Build Coastguard Worker } else if (map_is_map_of_progs(info->type)) {
398*858ea5e5SAndroid Build Coastguard Worker int argc = 2;
399*858ea5e5SAndroid Build Coastguard Worker
400*858ea5e5SAndroid Build Coastguard Worker if (value_size != 4) {
401*858ea5e5SAndroid Build Coastguard Worker p_err("value smaller than 4B for map of progs?");
402*858ea5e5SAndroid Build Coastguard Worker return -1;
403*858ea5e5SAndroid Build Coastguard Worker }
404*858ea5e5SAndroid Build Coastguard Worker if (!argv[0] || !argv[1]) {
405*858ea5e5SAndroid Build Coastguard Worker p_err("not enough value arguments for map of progs");
406*858ea5e5SAndroid Build Coastguard Worker return -1;
407*858ea5e5SAndroid Build Coastguard Worker }
408*858ea5e5SAndroid Build Coastguard Worker if (is_prefix(*argv, "id"))
409*858ea5e5SAndroid Build Coastguard Worker p_info("Warning: updating program array via MAP_ID, make sure this map is kept open\n"
410*858ea5e5SAndroid Build Coastguard Worker " by some process or pinned otherwise update will be lost");
411*858ea5e5SAndroid Build Coastguard Worker
412*858ea5e5SAndroid Build Coastguard Worker fd = prog_parse_fd(&argc, &argv);
413*858ea5e5SAndroid Build Coastguard Worker if (fd < 0)
414*858ea5e5SAndroid Build Coastguard Worker return -1;
415*858ea5e5SAndroid Build Coastguard Worker
416*858ea5e5SAndroid Build Coastguard Worker *value_fd = value;
417*858ea5e5SAndroid Build Coastguard Worker **value_fd = fd;
418*858ea5e5SAndroid Build Coastguard Worker } else {
419*858ea5e5SAndroid Build Coastguard Worker argv = parse_bytes(argv, "value", value, value_size);
420*858ea5e5SAndroid Build Coastguard Worker if (!argv)
421*858ea5e5SAndroid Build Coastguard Worker return -1;
422*858ea5e5SAndroid Build Coastguard Worker
423*858ea5e5SAndroid Build Coastguard Worker fill_per_cpu_value(info, value);
424*858ea5e5SAndroid Build Coastguard Worker }
425*858ea5e5SAndroid Build Coastguard Worker
426*858ea5e5SAndroid Build Coastguard Worker return parse_elem(argv, info, key, NULL, key_size, value_size,
427*858ea5e5SAndroid Build Coastguard Worker flags, NULL);
428*858ea5e5SAndroid Build Coastguard Worker } else if (is_prefix(*argv, "any") || is_prefix(*argv, "noexist") ||
429*858ea5e5SAndroid Build Coastguard Worker is_prefix(*argv, "exist")) {
430*858ea5e5SAndroid Build Coastguard Worker if (!flags) {
431*858ea5e5SAndroid Build Coastguard Worker p_err("flags specified multiple times: %s", *argv);
432*858ea5e5SAndroid Build Coastguard Worker return -1;
433*858ea5e5SAndroid Build Coastguard Worker }
434*858ea5e5SAndroid Build Coastguard Worker
435*858ea5e5SAndroid Build Coastguard Worker if (is_prefix(*argv, "any"))
436*858ea5e5SAndroid Build Coastguard Worker *flags = BPF_ANY;
437*858ea5e5SAndroid Build Coastguard Worker else if (is_prefix(*argv, "noexist"))
438*858ea5e5SAndroid Build Coastguard Worker *flags = BPF_NOEXIST;
439*858ea5e5SAndroid Build Coastguard Worker else if (is_prefix(*argv, "exist"))
440*858ea5e5SAndroid Build Coastguard Worker *flags = BPF_EXIST;
441*858ea5e5SAndroid Build Coastguard Worker
442*858ea5e5SAndroid Build Coastguard Worker return parse_elem(argv + 1, info, key, value, key_size,
443*858ea5e5SAndroid Build Coastguard Worker value_size, NULL, value_fd);
444*858ea5e5SAndroid Build Coastguard Worker }
445*858ea5e5SAndroid Build Coastguard Worker
446*858ea5e5SAndroid Build Coastguard Worker p_err("expected key or value, got: %s", *argv);
447*858ea5e5SAndroid Build Coastguard Worker return -1;
448*858ea5e5SAndroid Build Coastguard Worker }
449*858ea5e5SAndroid Build Coastguard Worker
show_map_header_json(struct bpf_map_info * info,json_writer_t * wtr)450*858ea5e5SAndroid Build Coastguard Worker static void show_map_header_json(struct bpf_map_info *info, json_writer_t *wtr)
451*858ea5e5SAndroid Build Coastguard Worker {
452*858ea5e5SAndroid Build Coastguard Worker const char *map_type_str;
453*858ea5e5SAndroid Build Coastguard Worker
454*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(wtr, "id", info->id);
455*858ea5e5SAndroid Build Coastguard Worker map_type_str = libbpf_bpf_map_type_str(info->type);
456*858ea5e5SAndroid Build Coastguard Worker if (map_type_str)
457*858ea5e5SAndroid Build Coastguard Worker jsonw_string_field(wtr, "type", map_type_str);
458*858ea5e5SAndroid Build Coastguard Worker else
459*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(wtr, "type", info->type);
460*858ea5e5SAndroid Build Coastguard Worker
461*858ea5e5SAndroid Build Coastguard Worker if (*info->name)
462*858ea5e5SAndroid Build Coastguard Worker jsonw_string_field(wtr, "name", info->name);
463*858ea5e5SAndroid Build Coastguard Worker
464*858ea5e5SAndroid Build Coastguard Worker jsonw_name(wtr, "flags");
465*858ea5e5SAndroid Build Coastguard Worker jsonw_printf(wtr, "%d", info->map_flags);
466*858ea5e5SAndroid Build Coastguard Worker }
467*858ea5e5SAndroid Build Coastguard Worker
show_map_close_json(int fd,struct bpf_map_info * info)468*858ea5e5SAndroid Build Coastguard Worker static int show_map_close_json(int fd, struct bpf_map_info *info)
469*858ea5e5SAndroid Build Coastguard Worker {
470*858ea5e5SAndroid Build Coastguard Worker char *memlock, *frozen_str;
471*858ea5e5SAndroid Build Coastguard Worker int frozen = 0;
472*858ea5e5SAndroid Build Coastguard Worker
473*858ea5e5SAndroid Build Coastguard Worker memlock = get_fdinfo(fd, "memlock");
474*858ea5e5SAndroid Build Coastguard Worker frozen_str = get_fdinfo(fd, "frozen");
475*858ea5e5SAndroid Build Coastguard Worker
476*858ea5e5SAndroid Build Coastguard Worker jsonw_start_object(json_wtr);
477*858ea5e5SAndroid Build Coastguard Worker
478*858ea5e5SAndroid Build Coastguard Worker show_map_header_json(info, json_wtr);
479*858ea5e5SAndroid Build Coastguard Worker
480*858ea5e5SAndroid Build Coastguard Worker print_dev_json(info->ifindex, info->netns_dev, info->netns_ino);
481*858ea5e5SAndroid Build Coastguard Worker
482*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(json_wtr, "bytes_key", info->key_size);
483*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(json_wtr, "bytes_value", info->value_size);
484*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(json_wtr, "max_entries", info->max_entries);
485*858ea5e5SAndroid Build Coastguard Worker
486*858ea5e5SAndroid Build Coastguard Worker if (memlock)
487*858ea5e5SAndroid Build Coastguard Worker jsonw_int_field(json_wtr, "bytes_memlock", atoll(memlock));
488*858ea5e5SAndroid Build Coastguard Worker free(memlock);
489*858ea5e5SAndroid Build Coastguard Worker
490*858ea5e5SAndroid Build Coastguard Worker if (info->type == BPF_MAP_TYPE_PROG_ARRAY) {
491*858ea5e5SAndroid Build Coastguard Worker char *owner_prog_type = get_fdinfo(fd, "owner_prog_type");
492*858ea5e5SAndroid Build Coastguard Worker char *owner_jited = get_fdinfo(fd, "owner_jited");
493*858ea5e5SAndroid Build Coastguard Worker
494*858ea5e5SAndroid Build Coastguard Worker if (owner_prog_type) {
495*858ea5e5SAndroid Build Coastguard Worker unsigned int prog_type = atoi(owner_prog_type);
496*858ea5e5SAndroid Build Coastguard Worker const char *prog_type_str;
497*858ea5e5SAndroid Build Coastguard Worker
498*858ea5e5SAndroid Build Coastguard Worker prog_type_str = libbpf_bpf_prog_type_str(prog_type);
499*858ea5e5SAndroid Build Coastguard Worker if (prog_type_str)
500*858ea5e5SAndroid Build Coastguard Worker jsonw_string_field(json_wtr, "owner_prog_type",
501*858ea5e5SAndroid Build Coastguard Worker prog_type_str);
502*858ea5e5SAndroid Build Coastguard Worker else
503*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(json_wtr, "owner_prog_type",
504*858ea5e5SAndroid Build Coastguard Worker prog_type);
505*858ea5e5SAndroid Build Coastguard Worker }
506*858ea5e5SAndroid Build Coastguard Worker if (owner_jited)
507*858ea5e5SAndroid Build Coastguard Worker jsonw_bool_field(json_wtr, "owner_jited",
508*858ea5e5SAndroid Build Coastguard Worker !!atoi(owner_jited));
509*858ea5e5SAndroid Build Coastguard Worker
510*858ea5e5SAndroid Build Coastguard Worker free(owner_prog_type);
511*858ea5e5SAndroid Build Coastguard Worker free(owner_jited);
512*858ea5e5SAndroid Build Coastguard Worker }
513*858ea5e5SAndroid Build Coastguard Worker close(fd);
514*858ea5e5SAndroid Build Coastguard Worker
515*858ea5e5SAndroid Build Coastguard Worker if (frozen_str) {
516*858ea5e5SAndroid Build Coastguard Worker frozen = atoi(frozen_str);
517*858ea5e5SAndroid Build Coastguard Worker free(frozen_str);
518*858ea5e5SAndroid Build Coastguard Worker }
519*858ea5e5SAndroid Build Coastguard Worker jsonw_int_field(json_wtr, "frozen", frozen);
520*858ea5e5SAndroid Build Coastguard Worker
521*858ea5e5SAndroid Build Coastguard Worker if (info->btf_id)
522*858ea5e5SAndroid Build Coastguard Worker jsonw_int_field(json_wtr, "btf_id", info->btf_id);
523*858ea5e5SAndroid Build Coastguard Worker
524*858ea5e5SAndroid Build Coastguard Worker if (!hashmap__empty(map_table)) {
525*858ea5e5SAndroid Build Coastguard Worker struct hashmap_entry *entry;
526*858ea5e5SAndroid Build Coastguard Worker
527*858ea5e5SAndroid Build Coastguard Worker jsonw_name(json_wtr, "pinned");
528*858ea5e5SAndroid Build Coastguard Worker jsonw_start_array(json_wtr);
529*858ea5e5SAndroid Build Coastguard Worker hashmap__for_each_key_entry(map_table, entry, info->id)
530*858ea5e5SAndroid Build Coastguard Worker jsonw_string(json_wtr, entry->pvalue);
531*858ea5e5SAndroid Build Coastguard Worker jsonw_end_array(json_wtr);
532*858ea5e5SAndroid Build Coastguard Worker }
533*858ea5e5SAndroid Build Coastguard Worker
534*858ea5e5SAndroid Build Coastguard Worker emit_obj_refs_json(refs_table, info->id, json_wtr);
535*858ea5e5SAndroid Build Coastguard Worker
536*858ea5e5SAndroid Build Coastguard Worker jsonw_end_object(json_wtr);
537*858ea5e5SAndroid Build Coastguard Worker
538*858ea5e5SAndroid Build Coastguard Worker return 0;
539*858ea5e5SAndroid Build Coastguard Worker }
540*858ea5e5SAndroid Build Coastguard Worker
show_map_header_plain(struct bpf_map_info * info)541*858ea5e5SAndroid Build Coastguard Worker static void show_map_header_plain(struct bpf_map_info *info)
542*858ea5e5SAndroid Build Coastguard Worker {
543*858ea5e5SAndroid Build Coastguard Worker const char *map_type_str;
544*858ea5e5SAndroid Build Coastguard Worker
545*858ea5e5SAndroid Build Coastguard Worker printf("%u: ", info->id);
546*858ea5e5SAndroid Build Coastguard Worker
547*858ea5e5SAndroid Build Coastguard Worker map_type_str = libbpf_bpf_map_type_str(info->type);
548*858ea5e5SAndroid Build Coastguard Worker if (map_type_str)
549*858ea5e5SAndroid Build Coastguard Worker printf("%s ", map_type_str);
550*858ea5e5SAndroid Build Coastguard Worker else
551*858ea5e5SAndroid Build Coastguard Worker printf("type %u ", info->type);
552*858ea5e5SAndroid Build Coastguard Worker
553*858ea5e5SAndroid Build Coastguard Worker if (*info->name)
554*858ea5e5SAndroid Build Coastguard Worker printf("name %s ", info->name);
555*858ea5e5SAndroid Build Coastguard Worker
556*858ea5e5SAndroid Build Coastguard Worker printf("flags 0x%x", info->map_flags);
557*858ea5e5SAndroid Build Coastguard Worker print_dev_plain(info->ifindex, info->netns_dev, info->netns_ino);
558*858ea5e5SAndroid Build Coastguard Worker printf("\n");
559*858ea5e5SAndroid Build Coastguard Worker }
560*858ea5e5SAndroid Build Coastguard Worker
show_map_close_plain(int fd,struct bpf_map_info * info)561*858ea5e5SAndroid Build Coastguard Worker static int show_map_close_plain(int fd, struct bpf_map_info *info)
562*858ea5e5SAndroid Build Coastguard Worker {
563*858ea5e5SAndroid Build Coastguard Worker char *memlock, *frozen_str;
564*858ea5e5SAndroid Build Coastguard Worker int frozen = 0;
565*858ea5e5SAndroid Build Coastguard Worker
566*858ea5e5SAndroid Build Coastguard Worker memlock = get_fdinfo(fd, "memlock");
567*858ea5e5SAndroid Build Coastguard Worker frozen_str = get_fdinfo(fd, "frozen");
568*858ea5e5SAndroid Build Coastguard Worker
569*858ea5e5SAndroid Build Coastguard Worker show_map_header_plain(info);
570*858ea5e5SAndroid Build Coastguard Worker printf("\tkey %uB value %uB max_entries %u",
571*858ea5e5SAndroid Build Coastguard Worker info->key_size, info->value_size, info->max_entries);
572*858ea5e5SAndroid Build Coastguard Worker
573*858ea5e5SAndroid Build Coastguard Worker if (memlock)
574*858ea5e5SAndroid Build Coastguard Worker printf(" memlock %sB", memlock);
575*858ea5e5SAndroid Build Coastguard Worker free(memlock);
576*858ea5e5SAndroid Build Coastguard Worker
577*858ea5e5SAndroid Build Coastguard Worker if (info->type == BPF_MAP_TYPE_PROG_ARRAY) {
578*858ea5e5SAndroid Build Coastguard Worker char *owner_prog_type = get_fdinfo(fd, "owner_prog_type");
579*858ea5e5SAndroid Build Coastguard Worker char *owner_jited = get_fdinfo(fd, "owner_jited");
580*858ea5e5SAndroid Build Coastguard Worker
581*858ea5e5SAndroid Build Coastguard Worker if (owner_prog_type || owner_jited)
582*858ea5e5SAndroid Build Coastguard Worker printf("\n\t");
583*858ea5e5SAndroid Build Coastguard Worker if (owner_prog_type) {
584*858ea5e5SAndroid Build Coastguard Worker unsigned int prog_type = atoi(owner_prog_type);
585*858ea5e5SAndroid Build Coastguard Worker const char *prog_type_str;
586*858ea5e5SAndroid Build Coastguard Worker
587*858ea5e5SAndroid Build Coastguard Worker prog_type_str = libbpf_bpf_prog_type_str(prog_type);
588*858ea5e5SAndroid Build Coastguard Worker if (prog_type_str)
589*858ea5e5SAndroid Build Coastguard Worker printf("owner_prog_type %s ", prog_type_str);
590*858ea5e5SAndroid Build Coastguard Worker else
591*858ea5e5SAndroid Build Coastguard Worker printf("owner_prog_type %d ", prog_type);
592*858ea5e5SAndroid Build Coastguard Worker }
593*858ea5e5SAndroid Build Coastguard Worker if (owner_jited)
594*858ea5e5SAndroid Build Coastguard Worker printf("owner%s jited",
595*858ea5e5SAndroid Build Coastguard Worker atoi(owner_jited) ? "" : " not");
596*858ea5e5SAndroid Build Coastguard Worker
597*858ea5e5SAndroid Build Coastguard Worker free(owner_prog_type);
598*858ea5e5SAndroid Build Coastguard Worker free(owner_jited);
599*858ea5e5SAndroid Build Coastguard Worker }
600*858ea5e5SAndroid Build Coastguard Worker close(fd);
601*858ea5e5SAndroid Build Coastguard Worker
602*858ea5e5SAndroid Build Coastguard Worker if (!hashmap__empty(map_table)) {
603*858ea5e5SAndroid Build Coastguard Worker struct hashmap_entry *entry;
604*858ea5e5SAndroid Build Coastguard Worker
605*858ea5e5SAndroid Build Coastguard Worker hashmap__for_each_key_entry(map_table, entry, info->id)
606*858ea5e5SAndroid Build Coastguard Worker printf("\n\tpinned %s", (char *)entry->pvalue);
607*858ea5e5SAndroid Build Coastguard Worker }
608*858ea5e5SAndroid Build Coastguard Worker
609*858ea5e5SAndroid Build Coastguard Worker if (frozen_str) {
610*858ea5e5SAndroid Build Coastguard Worker frozen = atoi(frozen_str);
611*858ea5e5SAndroid Build Coastguard Worker free(frozen_str);
612*858ea5e5SAndroid Build Coastguard Worker }
613*858ea5e5SAndroid Build Coastguard Worker
614*858ea5e5SAndroid Build Coastguard Worker if (info->btf_id || frozen)
615*858ea5e5SAndroid Build Coastguard Worker printf("\n\t");
616*858ea5e5SAndroid Build Coastguard Worker
617*858ea5e5SAndroid Build Coastguard Worker if (info->btf_id)
618*858ea5e5SAndroid Build Coastguard Worker printf("btf_id %d", info->btf_id);
619*858ea5e5SAndroid Build Coastguard Worker
620*858ea5e5SAndroid Build Coastguard Worker if (frozen)
621*858ea5e5SAndroid Build Coastguard Worker printf("%sfrozen", info->btf_id ? " " : "");
622*858ea5e5SAndroid Build Coastguard Worker
623*858ea5e5SAndroid Build Coastguard Worker emit_obj_refs_plain(refs_table, info->id, "\n\tpids ");
624*858ea5e5SAndroid Build Coastguard Worker
625*858ea5e5SAndroid Build Coastguard Worker printf("\n");
626*858ea5e5SAndroid Build Coastguard Worker return 0;
627*858ea5e5SAndroid Build Coastguard Worker }
628*858ea5e5SAndroid Build Coastguard Worker
do_show_subset(int argc,char ** argv)629*858ea5e5SAndroid Build Coastguard Worker static int do_show_subset(int argc, char **argv)
630*858ea5e5SAndroid Build Coastguard Worker {
631*858ea5e5SAndroid Build Coastguard Worker struct bpf_map_info info = {};
632*858ea5e5SAndroid Build Coastguard Worker __u32 len = sizeof(info);
633*858ea5e5SAndroid Build Coastguard Worker int *fds = NULL;
634*858ea5e5SAndroid Build Coastguard Worker int nb_fds, i;
635*858ea5e5SAndroid Build Coastguard Worker int err = -1;
636*858ea5e5SAndroid Build Coastguard Worker
637*858ea5e5SAndroid Build Coastguard Worker fds = malloc(sizeof(int));
638*858ea5e5SAndroid Build Coastguard Worker if (!fds) {
639*858ea5e5SAndroid Build Coastguard Worker p_err("mem alloc failed");
640*858ea5e5SAndroid Build Coastguard Worker return -1;
641*858ea5e5SAndroid Build Coastguard Worker }
642*858ea5e5SAndroid Build Coastguard Worker nb_fds = map_parse_fds(&argc, &argv, &fds);
643*858ea5e5SAndroid Build Coastguard Worker if (nb_fds < 1)
644*858ea5e5SAndroid Build Coastguard Worker goto exit_free;
645*858ea5e5SAndroid Build Coastguard Worker
646*858ea5e5SAndroid Build Coastguard Worker if (json_output && nb_fds > 1)
647*858ea5e5SAndroid Build Coastguard Worker jsonw_start_array(json_wtr); /* root array */
648*858ea5e5SAndroid Build Coastguard Worker for (i = 0; i < nb_fds; i++) {
649*858ea5e5SAndroid Build Coastguard Worker err = bpf_map_get_info_by_fd(fds[i], &info, &len);
650*858ea5e5SAndroid Build Coastguard Worker if (err) {
651*858ea5e5SAndroid Build Coastguard Worker p_err("can't get map info: %s",
652*858ea5e5SAndroid Build Coastguard Worker strerror(errno));
653*858ea5e5SAndroid Build Coastguard Worker for (; i < nb_fds; i++)
654*858ea5e5SAndroid Build Coastguard Worker close(fds[i]);
655*858ea5e5SAndroid Build Coastguard Worker break;
656*858ea5e5SAndroid Build Coastguard Worker }
657*858ea5e5SAndroid Build Coastguard Worker
658*858ea5e5SAndroid Build Coastguard Worker if (json_output)
659*858ea5e5SAndroid Build Coastguard Worker show_map_close_json(fds[i], &info);
660*858ea5e5SAndroid Build Coastguard Worker else
661*858ea5e5SAndroid Build Coastguard Worker show_map_close_plain(fds[i], &info);
662*858ea5e5SAndroid Build Coastguard Worker
663*858ea5e5SAndroid Build Coastguard Worker close(fds[i]);
664*858ea5e5SAndroid Build Coastguard Worker }
665*858ea5e5SAndroid Build Coastguard Worker if (json_output && nb_fds > 1)
666*858ea5e5SAndroid Build Coastguard Worker jsonw_end_array(json_wtr); /* root array */
667*858ea5e5SAndroid Build Coastguard Worker
668*858ea5e5SAndroid Build Coastguard Worker exit_free:
669*858ea5e5SAndroid Build Coastguard Worker free(fds);
670*858ea5e5SAndroid Build Coastguard Worker return err;
671*858ea5e5SAndroid Build Coastguard Worker }
672*858ea5e5SAndroid Build Coastguard Worker
do_show(int argc,char ** argv)673*858ea5e5SAndroid Build Coastguard Worker static int do_show(int argc, char **argv)
674*858ea5e5SAndroid Build Coastguard Worker {
675*858ea5e5SAndroid Build Coastguard Worker struct bpf_map_info info = {};
676*858ea5e5SAndroid Build Coastguard Worker __u32 len = sizeof(info);
677*858ea5e5SAndroid Build Coastguard Worker __u32 id = 0;
678*858ea5e5SAndroid Build Coastguard Worker int err;
679*858ea5e5SAndroid Build Coastguard Worker int fd;
680*858ea5e5SAndroid Build Coastguard Worker
681*858ea5e5SAndroid Build Coastguard Worker if (show_pinned) {
682*858ea5e5SAndroid Build Coastguard Worker map_table = hashmap__new(hash_fn_for_key_as_id,
683*858ea5e5SAndroid Build Coastguard Worker equal_fn_for_key_as_id, NULL);
684*858ea5e5SAndroid Build Coastguard Worker if (IS_ERR(map_table)) {
685*858ea5e5SAndroid Build Coastguard Worker p_err("failed to create hashmap for pinned paths");
686*858ea5e5SAndroid Build Coastguard Worker return -1;
687*858ea5e5SAndroid Build Coastguard Worker }
688*858ea5e5SAndroid Build Coastguard Worker build_pinned_obj_table(map_table, BPF_OBJ_MAP);
689*858ea5e5SAndroid Build Coastguard Worker }
690*858ea5e5SAndroid Build Coastguard Worker build_obj_refs_table(&refs_table, BPF_OBJ_MAP);
691*858ea5e5SAndroid Build Coastguard Worker
692*858ea5e5SAndroid Build Coastguard Worker if (argc == 2)
693*858ea5e5SAndroid Build Coastguard Worker return do_show_subset(argc, argv);
694*858ea5e5SAndroid Build Coastguard Worker
695*858ea5e5SAndroid Build Coastguard Worker if (argc)
696*858ea5e5SAndroid Build Coastguard Worker return BAD_ARG();
697*858ea5e5SAndroid Build Coastguard Worker
698*858ea5e5SAndroid Build Coastguard Worker if (json_output)
699*858ea5e5SAndroid Build Coastguard Worker jsonw_start_array(json_wtr);
700*858ea5e5SAndroid Build Coastguard Worker while (true) {
701*858ea5e5SAndroid Build Coastguard Worker err = bpf_map_get_next_id(id, &id);
702*858ea5e5SAndroid Build Coastguard Worker if (err) {
703*858ea5e5SAndroid Build Coastguard Worker if (errno == ENOENT)
704*858ea5e5SAndroid Build Coastguard Worker break;
705*858ea5e5SAndroid Build Coastguard Worker p_err("can't get next map: %s%s", strerror(errno),
706*858ea5e5SAndroid Build Coastguard Worker errno == EINVAL ? " -- kernel too old?" : "");
707*858ea5e5SAndroid Build Coastguard Worker break;
708*858ea5e5SAndroid Build Coastguard Worker }
709*858ea5e5SAndroid Build Coastguard Worker
710*858ea5e5SAndroid Build Coastguard Worker fd = bpf_map_get_fd_by_id(id);
711*858ea5e5SAndroid Build Coastguard Worker if (fd < 0) {
712*858ea5e5SAndroid Build Coastguard Worker if (errno == ENOENT)
713*858ea5e5SAndroid Build Coastguard Worker continue;
714*858ea5e5SAndroid Build Coastguard Worker p_err("can't get map by id (%u): %s",
715*858ea5e5SAndroid Build Coastguard Worker id, strerror(errno));
716*858ea5e5SAndroid Build Coastguard Worker break;
717*858ea5e5SAndroid Build Coastguard Worker }
718*858ea5e5SAndroid Build Coastguard Worker
719*858ea5e5SAndroid Build Coastguard Worker err = bpf_map_get_info_by_fd(fd, &info, &len);
720*858ea5e5SAndroid Build Coastguard Worker if (err) {
721*858ea5e5SAndroid Build Coastguard Worker p_err("can't get map info: %s", strerror(errno));
722*858ea5e5SAndroid Build Coastguard Worker close(fd);
723*858ea5e5SAndroid Build Coastguard Worker break;
724*858ea5e5SAndroid Build Coastguard Worker }
725*858ea5e5SAndroid Build Coastguard Worker
726*858ea5e5SAndroid Build Coastguard Worker if (json_output)
727*858ea5e5SAndroid Build Coastguard Worker show_map_close_json(fd, &info);
728*858ea5e5SAndroid Build Coastguard Worker else
729*858ea5e5SAndroid Build Coastguard Worker show_map_close_plain(fd, &info);
730*858ea5e5SAndroid Build Coastguard Worker }
731*858ea5e5SAndroid Build Coastguard Worker if (json_output)
732*858ea5e5SAndroid Build Coastguard Worker jsonw_end_array(json_wtr);
733*858ea5e5SAndroid Build Coastguard Worker
734*858ea5e5SAndroid Build Coastguard Worker delete_obj_refs_table(refs_table);
735*858ea5e5SAndroid Build Coastguard Worker
736*858ea5e5SAndroid Build Coastguard Worker if (show_pinned)
737*858ea5e5SAndroid Build Coastguard Worker delete_pinned_obj_table(map_table);
738*858ea5e5SAndroid Build Coastguard Worker
739*858ea5e5SAndroid Build Coastguard Worker return errno == ENOENT ? 0 : -1;
740*858ea5e5SAndroid Build Coastguard Worker }
741*858ea5e5SAndroid Build Coastguard Worker
dump_map_elem(int fd,void * key,void * value,struct bpf_map_info * map_info,struct btf * btf,json_writer_t * btf_wtr)742*858ea5e5SAndroid Build Coastguard Worker static int dump_map_elem(int fd, void *key, void *value,
743*858ea5e5SAndroid Build Coastguard Worker struct bpf_map_info *map_info, struct btf *btf,
744*858ea5e5SAndroid Build Coastguard Worker json_writer_t *btf_wtr)
745*858ea5e5SAndroid Build Coastguard Worker {
746*858ea5e5SAndroid Build Coastguard Worker if (bpf_map_lookup_elem(fd, key, value)) {
747*858ea5e5SAndroid Build Coastguard Worker print_entry_error(map_info, key, errno);
748*858ea5e5SAndroid Build Coastguard Worker return -1;
749*858ea5e5SAndroid Build Coastguard Worker }
750*858ea5e5SAndroid Build Coastguard Worker
751*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
752*858ea5e5SAndroid Build Coastguard Worker print_entry_json(map_info, key, value, btf);
753*858ea5e5SAndroid Build Coastguard Worker } else if (btf) {
754*858ea5e5SAndroid Build Coastguard Worker struct btf_dumper d = {
755*858ea5e5SAndroid Build Coastguard Worker .btf = btf,
756*858ea5e5SAndroid Build Coastguard Worker .jw = btf_wtr,
757*858ea5e5SAndroid Build Coastguard Worker .is_plain_text = true,
758*858ea5e5SAndroid Build Coastguard Worker };
759*858ea5e5SAndroid Build Coastguard Worker
760*858ea5e5SAndroid Build Coastguard Worker do_dump_btf(&d, map_info, key, value);
761*858ea5e5SAndroid Build Coastguard Worker } else {
762*858ea5e5SAndroid Build Coastguard Worker print_entry_plain(map_info, key, value);
763*858ea5e5SAndroid Build Coastguard Worker }
764*858ea5e5SAndroid Build Coastguard Worker
765*858ea5e5SAndroid Build Coastguard Worker return 0;
766*858ea5e5SAndroid Build Coastguard Worker }
767*858ea5e5SAndroid Build Coastguard Worker
maps_have_btf(int * fds,int nb_fds)768*858ea5e5SAndroid Build Coastguard Worker static int maps_have_btf(int *fds, int nb_fds)
769*858ea5e5SAndroid Build Coastguard Worker {
770*858ea5e5SAndroid Build Coastguard Worker struct bpf_map_info info = {};
771*858ea5e5SAndroid Build Coastguard Worker __u32 len = sizeof(info);
772*858ea5e5SAndroid Build Coastguard Worker int err, i;
773*858ea5e5SAndroid Build Coastguard Worker
774*858ea5e5SAndroid Build Coastguard Worker for (i = 0; i < nb_fds; i++) {
775*858ea5e5SAndroid Build Coastguard Worker err = bpf_map_get_info_by_fd(fds[i], &info, &len);
776*858ea5e5SAndroid Build Coastguard Worker if (err) {
777*858ea5e5SAndroid Build Coastguard Worker p_err("can't get map info: %s", strerror(errno));
778*858ea5e5SAndroid Build Coastguard Worker return -1;
779*858ea5e5SAndroid Build Coastguard Worker }
780*858ea5e5SAndroid Build Coastguard Worker
781*858ea5e5SAndroid Build Coastguard Worker if (!info.btf_id)
782*858ea5e5SAndroid Build Coastguard Worker return 0;
783*858ea5e5SAndroid Build Coastguard Worker }
784*858ea5e5SAndroid Build Coastguard Worker
785*858ea5e5SAndroid Build Coastguard Worker return 1;
786*858ea5e5SAndroid Build Coastguard Worker }
787*858ea5e5SAndroid Build Coastguard Worker
788*858ea5e5SAndroid Build Coastguard Worker static struct btf *btf_vmlinux;
789*858ea5e5SAndroid Build Coastguard Worker
get_map_kv_btf(const struct bpf_map_info * info,struct btf ** btf)790*858ea5e5SAndroid Build Coastguard Worker static int get_map_kv_btf(const struct bpf_map_info *info, struct btf **btf)
791*858ea5e5SAndroid Build Coastguard Worker {
792*858ea5e5SAndroid Build Coastguard Worker int err = 0;
793*858ea5e5SAndroid Build Coastguard Worker
794*858ea5e5SAndroid Build Coastguard Worker if (info->btf_vmlinux_value_type_id) {
795*858ea5e5SAndroid Build Coastguard Worker if (!btf_vmlinux) {
796*858ea5e5SAndroid Build Coastguard Worker btf_vmlinux = libbpf_find_kernel_btf();
797*858ea5e5SAndroid Build Coastguard Worker if (!btf_vmlinux) {
798*858ea5e5SAndroid Build Coastguard Worker p_err("failed to get kernel btf");
799*858ea5e5SAndroid Build Coastguard Worker return -errno;
800*858ea5e5SAndroid Build Coastguard Worker }
801*858ea5e5SAndroid Build Coastguard Worker }
802*858ea5e5SAndroid Build Coastguard Worker *btf = btf_vmlinux;
803*858ea5e5SAndroid Build Coastguard Worker } else if (info->btf_value_type_id) {
804*858ea5e5SAndroid Build Coastguard Worker *btf = btf__load_from_kernel_by_id(info->btf_id);
805*858ea5e5SAndroid Build Coastguard Worker if (!*btf) {
806*858ea5e5SAndroid Build Coastguard Worker err = -errno;
807*858ea5e5SAndroid Build Coastguard Worker p_err("failed to get btf");
808*858ea5e5SAndroid Build Coastguard Worker }
809*858ea5e5SAndroid Build Coastguard Worker } else {
810*858ea5e5SAndroid Build Coastguard Worker *btf = NULL;
811*858ea5e5SAndroid Build Coastguard Worker }
812*858ea5e5SAndroid Build Coastguard Worker
813*858ea5e5SAndroid Build Coastguard Worker return err;
814*858ea5e5SAndroid Build Coastguard Worker }
815*858ea5e5SAndroid Build Coastguard Worker
free_map_kv_btf(struct btf * btf)816*858ea5e5SAndroid Build Coastguard Worker static void free_map_kv_btf(struct btf *btf)
817*858ea5e5SAndroid Build Coastguard Worker {
818*858ea5e5SAndroid Build Coastguard Worker if (btf != btf_vmlinux)
819*858ea5e5SAndroid Build Coastguard Worker btf__free(btf);
820*858ea5e5SAndroid Build Coastguard Worker }
821*858ea5e5SAndroid Build Coastguard Worker
822*858ea5e5SAndroid Build Coastguard Worker static int
map_dump(int fd,struct bpf_map_info * info,json_writer_t * wtr,bool show_header)823*858ea5e5SAndroid Build Coastguard Worker map_dump(int fd, struct bpf_map_info *info, json_writer_t *wtr,
824*858ea5e5SAndroid Build Coastguard Worker bool show_header)
825*858ea5e5SAndroid Build Coastguard Worker {
826*858ea5e5SAndroid Build Coastguard Worker void *key, *value, *prev_key;
827*858ea5e5SAndroid Build Coastguard Worker unsigned int num_elems = 0;
828*858ea5e5SAndroid Build Coastguard Worker struct btf *btf = NULL;
829*858ea5e5SAndroid Build Coastguard Worker int err;
830*858ea5e5SAndroid Build Coastguard Worker
831*858ea5e5SAndroid Build Coastguard Worker key = malloc(info->key_size);
832*858ea5e5SAndroid Build Coastguard Worker value = alloc_value(info);
833*858ea5e5SAndroid Build Coastguard Worker if (!key || !value) {
834*858ea5e5SAndroid Build Coastguard Worker p_err("mem alloc failed");
835*858ea5e5SAndroid Build Coastguard Worker err = -1;
836*858ea5e5SAndroid Build Coastguard Worker goto exit_free;
837*858ea5e5SAndroid Build Coastguard Worker }
838*858ea5e5SAndroid Build Coastguard Worker
839*858ea5e5SAndroid Build Coastguard Worker prev_key = NULL;
840*858ea5e5SAndroid Build Coastguard Worker
841*858ea5e5SAndroid Build Coastguard Worker if (wtr) {
842*858ea5e5SAndroid Build Coastguard Worker err = get_map_kv_btf(info, &btf);
843*858ea5e5SAndroid Build Coastguard Worker if (err) {
844*858ea5e5SAndroid Build Coastguard Worker goto exit_free;
845*858ea5e5SAndroid Build Coastguard Worker }
846*858ea5e5SAndroid Build Coastguard Worker
847*858ea5e5SAndroid Build Coastguard Worker if (show_header) {
848*858ea5e5SAndroid Build Coastguard Worker jsonw_start_object(wtr); /* map object */
849*858ea5e5SAndroid Build Coastguard Worker show_map_header_json(info, wtr);
850*858ea5e5SAndroid Build Coastguard Worker jsonw_name(wtr, "elements");
851*858ea5e5SAndroid Build Coastguard Worker }
852*858ea5e5SAndroid Build Coastguard Worker jsonw_start_array(wtr); /* elements */
853*858ea5e5SAndroid Build Coastguard Worker } else if (show_header) {
854*858ea5e5SAndroid Build Coastguard Worker show_map_header_plain(info);
855*858ea5e5SAndroid Build Coastguard Worker }
856*858ea5e5SAndroid Build Coastguard Worker
857*858ea5e5SAndroid Build Coastguard Worker if (info->type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY &&
858*858ea5e5SAndroid Build Coastguard Worker info->value_size != 8) {
859*858ea5e5SAndroid Build Coastguard Worker const char *map_type_str;
860*858ea5e5SAndroid Build Coastguard Worker
861*858ea5e5SAndroid Build Coastguard Worker map_type_str = libbpf_bpf_map_type_str(info->type);
862*858ea5e5SAndroid Build Coastguard Worker p_info("Warning: cannot read values from %s map with value_size != 8",
863*858ea5e5SAndroid Build Coastguard Worker map_type_str);
864*858ea5e5SAndroid Build Coastguard Worker }
865*858ea5e5SAndroid Build Coastguard Worker while (true) {
866*858ea5e5SAndroid Build Coastguard Worker err = bpf_map_get_next_key(fd, prev_key, key);
867*858ea5e5SAndroid Build Coastguard Worker if (err) {
868*858ea5e5SAndroid Build Coastguard Worker if (errno == ENOENT)
869*858ea5e5SAndroid Build Coastguard Worker err = 0;
870*858ea5e5SAndroid Build Coastguard Worker break;
871*858ea5e5SAndroid Build Coastguard Worker }
872*858ea5e5SAndroid Build Coastguard Worker if (!dump_map_elem(fd, key, value, info, btf, wtr))
873*858ea5e5SAndroid Build Coastguard Worker num_elems++;
874*858ea5e5SAndroid Build Coastguard Worker prev_key = key;
875*858ea5e5SAndroid Build Coastguard Worker }
876*858ea5e5SAndroid Build Coastguard Worker
877*858ea5e5SAndroid Build Coastguard Worker if (wtr) {
878*858ea5e5SAndroid Build Coastguard Worker jsonw_end_array(wtr); /* elements */
879*858ea5e5SAndroid Build Coastguard Worker if (show_header)
880*858ea5e5SAndroid Build Coastguard Worker jsonw_end_object(wtr); /* map object */
881*858ea5e5SAndroid Build Coastguard Worker } else {
882*858ea5e5SAndroid Build Coastguard Worker printf("Found %u element%s\n", num_elems,
883*858ea5e5SAndroid Build Coastguard Worker num_elems != 1 ? "s" : "");
884*858ea5e5SAndroid Build Coastguard Worker }
885*858ea5e5SAndroid Build Coastguard Worker
886*858ea5e5SAndroid Build Coastguard Worker exit_free:
887*858ea5e5SAndroid Build Coastguard Worker free(key);
888*858ea5e5SAndroid Build Coastguard Worker free(value);
889*858ea5e5SAndroid Build Coastguard Worker close(fd);
890*858ea5e5SAndroid Build Coastguard Worker free_map_kv_btf(btf);
891*858ea5e5SAndroid Build Coastguard Worker
892*858ea5e5SAndroid Build Coastguard Worker return err;
893*858ea5e5SAndroid Build Coastguard Worker }
894*858ea5e5SAndroid Build Coastguard Worker
do_dump(int argc,char ** argv)895*858ea5e5SAndroid Build Coastguard Worker static int do_dump(int argc, char **argv)
896*858ea5e5SAndroid Build Coastguard Worker {
897*858ea5e5SAndroid Build Coastguard Worker json_writer_t *wtr = NULL, *btf_wtr = NULL;
898*858ea5e5SAndroid Build Coastguard Worker struct bpf_map_info info = {};
899*858ea5e5SAndroid Build Coastguard Worker int nb_fds, i = 0;
900*858ea5e5SAndroid Build Coastguard Worker __u32 len = sizeof(info);
901*858ea5e5SAndroid Build Coastguard Worker int *fds = NULL;
902*858ea5e5SAndroid Build Coastguard Worker int err = -1;
903*858ea5e5SAndroid Build Coastguard Worker
904*858ea5e5SAndroid Build Coastguard Worker if (argc != 2)
905*858ea5e5SAndroid Build Coastguard Worker usage();
906*858ea5e5SAndroid Build Coastguard Worker
907*858ea5e5SAndroid Build Coastguard Worker fds = malloc(sizeof(int));
908*858ea5e5SAndroid Build Coastguard Worker if (!fds) {
909*858ea5e5SAndroid Build Coastguard Worker p_err("mem alloc failed");
910*858ea5e5SAndroid Build Coastguard Worker return -1;
911*858ea5e5SAndroid Build Coastguard Worker }
912*858ea5e5SAndroid Build Coastguard Worker nb_fds = map_parse_fds(&argc, &argv, &fds);
913*858ea5e5SAndroid Build Coastguard Worker if (nb_fds < 1)
914*858ea5e5SAndroid Build Coastguard Worker goto exit_free;
915*858ea5e5SAndroid Build Coastguard Worker
916*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
917*858ea5e5SAndroid Build Coastguard Worker wtr = json_wtr;
918*858ea5e5SAndroid Build Coastguard Worker } else {
919*858ea5e5SAndroid Build Coastguard Worker int do_plain_btf;
920*858ea5e5SAndroid Build Coastguard Worker
921*858ea5e5SAndroid Build Coastguard Worker do_plain_btf = maps_have_btf(fds, nb_fds);
922*858ea5e5SAndroid Build Coastguard Worker if (do_plain_btf < 0)
923*858ea5e5SAndroid Build Coastguard Worker goto exit_close;
924*858ea5e5SAndroid Build Coastguard Worker
925*858ea5e5SAndroid Build Coastguard Worker if (do_plain_btf) {
926*858ea5e5SAndroid Build Coastguard Worker btf_wtr = get_btf_writer();
927*858ea5e5SAndroid Build Coastguard Worker wtr = btf_wtr;
928*858ea5e5SAndroid Build Coastguard Worker if (!btf_wtr)
929*858ea5e5SAndroid Build Coastguard Worker p_info("failed to create json writer for btf. falling back to plain output");
930*858ea5e5SAndroid Build Coastguard Worker }
931*858ea5e5SAndroid Build Coastguard Worker }
932*858ea5e5SAndroid Build Coastguard Worker
933*858ea5e5SAndroid Build Coastguard Worker if (wtr && nb_fds > 1)
934*858ea5e5SAndroid Build Coastguard Worker jsonw_start_array(wtr); /* root array */
935*858ea5e5SAndroid Build Coastguard Worker for (i = 0; i < nb_fds; i++) {
936*858ea5e5SAndroid Build Coastguard Worker if (bpf_map_get_info_by_fd(fds[i], &info, &len)) {
937*858ea5e5SAndroid Build Coastguard Worker p_err("can't get map info: %s", strerror(errno));
938*858ea5e5SAndroid Build Coastguard Worker break;
939*858ea5e5SAndroid Build Coastguard Worker }
940*858ea5e5SAndroid Build Coastguard Worker err = map_dump(fds[i], &info, wtr, nb_fds > 1);
941*858ea5e5SAndroid Build Coastguard Worker if (!wtr && i != nb_fds - 1)
942*858ea5e5SAndroid Build Coastguard Worker printf("\n");
943*858ea5e5SAndroid Build Coastguard Worker
944*858ea5e5SAndroid Build Coastguard Worker if (err)
945*858ea5e5SAndroid Build Coastguard Worker break;
946*858ea5e5SAndroid Build Coastguard Worker close(fds[i]);
947*858ea5e5SAndroid Build Coastguard Worker }
948*858ea5e5SAndroid Build Coastguard Worker if (wtr && nb_fds > 1)
949*858ea5e5SAndroid Build Coastguard Worker jsonw_end_array(wtr); /* root array */
950*858ea5e5SAndroid Build Coastguard Worker
951*858ea5e5SAndroid Build Coastguard Worker if (btf_wtr)
952*858ea5e5SAndroid Build Coastguard Worker jsonw_destroy(&btf_wtr);
953*858ea5e5SAndroid Build Coastguard Worker exit_close:
954*858ea5e5SAndroid Build Coastguard Worker for (; i < nb_fds; i++)
955*858ea5e5SAndroid Build Coastguard Worker close(fds[i]);
956*858ea5e5SAndroid Build Coastguard Worker exit_free:
957*858ea5e5SAndroid Build Coastguard Worker free(fds);
958*858ea5e5SAndroid Build Coastguard Worker btf__free(btf_vmlinux);
959*858ea5e5SAndroid Build Coastguard Worker return err;
960*858ea5e5SAndroid Build Coastguard Worker }
961*858ea5e5SAndroid Build Coastguard Worker
alloc_key_value(struct bpf_map_info * info,void ** key,void ** value)962*858ea5e5SAndroid Build Coastguard Worker static int alloc_key_value(struct bpf_map_info *info, void **key, void **value)
963*858ea5e5SAndroid Build Coastguard Worker {
964*858ea5e5SAndroid Build Coastguard Worker *key = NULL;
965*858ea5e5SAndroid Build Coastguard Worker *value = NULL;
966*858ea5e5SAndroid Build Coastguard Worker
967*858ea5e5SAndroid Build Coastguard Worker if (info->key_size) {
968*858ea5e5SAndroid Build Coastguard Worker *key = malloc(info->key_size);
969*858ea5e5SAndroid Build Coastguard Worker if (!*key) {
970*858ea5e5SAndroid Build Coastguard Worker p_err("key mem alloc failed");
971*858ea5e5SAndroid Build Coastguard Worker return -1;
972*858ea5e5SAndroid Build Coastguard Worker }
973*858ea5e5SAndroid Build Coastguard Worker }
974*858ea5e5SAndroid Build Coastguard Worker
975*858ea5e5SAndroid Build Coastguard Worker if (info->value_size) {
976*858ea5e5SAndroid Build Coastguard Worker *value = alloc_value(info);
977*858ea5e5SAndroid Build Coastguard Worker if (!*value) {
978*858ea5e5SAndroid Build Coastguard Worker p_err("value mem alloc failed");
979*858ea5e5SAndroid Build Coastguard Worker free(*key);
980*858ea5e5SAndroid Build Coastguard Worker *key = NULL;
981*858ea5e5SAndroid Build Coastguard Worker return -1;
982*858ea5e5SAndroid Build Coastguard Worker }
983*858ea5e5SAndroid Build Coastguard Worker }
984*858ea5e5SAndroid Build Coastguard Worker
985*858ea5e5SAndroid Build Coastguard Worker return 0;
986*858ea5e5SAndroid Build Coastguard Worker }
987*858ea5e5SAndroid Build Coastguard Worker
do_update(int argc,char ** argv)988*858ea5e5SAndroid Build Coastguard Worker static int do_update(int argc, char **argv)
989*858ea5e5SAndroid Build Coastguard Worker {
990*858ea5e5SAndroid Build Coastguard Worker struct bpf_map_info info = {};
991*858ea5e5SAndroid Build Coastguard Worker __u32 len = sizeof(info);
992*858ea5e5SAndroid Build Coastguard Worker __u32 *value_fd = NULL;
993*858ea5e5SAndroid Build Coastguard Worker __u32 flags = BPF_ANY;
994*858ea5e5SAndroid Build Coastguard Worker void *key, *value;
995*858ea5e5SAndroid Build Coastguard Worker int fd, err;
996*858ea5e5SAndroid Build Coastguard Worker
997*858ea5e5SAndroid Build Coastguard Worker if (argc < 2)
998*858ea5e5SAndroid Build Coastguard Worker usage();
999*858ea5e5SAndroid Build Coastguard Worker
1000*858ea5e5SAndroid Build Coastguard Worker fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
1001*858ea5e5SAndroid Build Coastguard Worker if (fd < 0)
1002*858ea5e5SAndroid Build Coastguard Worker return -1;
1003*858ea5e5SAndroid Build Coastguard Worker
1004*858ea5e5SAndroid Build Coastguard Worker err = alloc_key_value(&info, &key, &value);
1005*858ea5e5SAndroid Build Coastguard Worker if (err)
1006*858ea5e5SAndroid Build Coastguard Worker goto exit_free;
1007*858ea5e5SAndroid Build Coastguard Worker
1008*858ea5e5SAndroid Build Coastguard Worker err = parse_elem(argv, &info, key, value, info.key_size,
1009*858ea5e5SAndroid Build Coastguard Worker info.value_size, &flags, &value_fd);
1010*858ea5e5SAndroid Build Coastguard Worker if (err)
1011*858ea5e5SAndroid Build Coastguard Worker goto exit_free;
1012*858ea5e5SAndroid Build Coastguard Worker
1013*858ea5e5SAndroid Build Coastguard Worker err = bpf_map_update_elem(fd, key, value, flags);
1014*858ea5e5SAndroid Build Coastguard Worker if (err) {
1015*858ea5e5SAndroid Build Coastguard Worker p_err("update failed: %s", strerror(errno));
1016*858ea5e5SAndroid Build Coastguard Worker goto exit_free;
1017*858ea5e5SAndroid Build Coastguard Worker }
1018*858ea5e5SAndroid Build Coastguard Worker
1019*858ea5e5SAndroid Build Coastguard Worker exit_free:
1020*858ea5e5SAndroid Build Coastguard Worker if (value_fd)
1021*858ea5e5SAndroid Build Coastguard Worker close(*value_fd);
1022*858ea5e5SAndroid Build Coastguard Worker free(key);
1023*858ea5e5SAndroid Build Coastguard Worker free(value);
1024*858ea5e5SAndroid Build Coastguard Worker close(fd);
1025*858ea5e5SAndroid Build Coastguard Worker
1026*858ea5e5SAndroid Build Coastguard Worker if (!err && json_output)
1027*858ea5e5SAndroid Build Coastguard Worker jsonw_null(json_wtr);
1028*858ea5e5SAndroid Build Coastguard Worker return err;
1029*858ea5e5SAndroid Build Coastguard Worker }
1030*858ea5e5SAndroid Build Coastguard Worker
print_key_value(struct bpf_map_info * info,void * key,void * value)1031*858ea5e5SAndroid Build Coastguard Worker static void print_key_value(struct bpf_map_info *info, void *key,
1032*858ea5e5SAndroid Build Coastguard Worker void *value)
1033*858ea5e5SAndroid Build Coastguard Worker {
1034*858ea5e5SAndroid Build Coastguard Worker json_writer_t *btf_wtr;
1035*858ea5e5SAndroid Build Coastguard Worker struct btf *btf;
1036*858ea5e5SAndroid Build Coastguard Worker
1037*858ea5e5SAndroid Build Coastguard Worker if (get_map_kv_btf(info, &btf))
1038*858ea5e5SAndroid Build Coastguard Worker return;
1039*858ea5e5SAndroid Build Coastguard Worker
1040*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
1041*858ea5e5SAndroid Build Coastguard Worker print_entry_json(info, key, value, btf);
1042*858ea5e5SAndroid Build Coastguard Worker } else if (btf) {
1043*858ea5e5SAndroid Build Coastguard Worker /* if here json_wtr wouldn't have been initialised,
1044*858ea5e5SAndroid Build Coastguard Worker * so let's create separate writer for btf
1045*858ea5e5SAndroid Build Coastguard Worker */
1046*858ea5e5SAndroid Build Coastguard Worker btf_wtr = get_btf_writer();
1047*858ea5e5SAndroid Build Coastguard Worker if (!btf_wtr) {
1048*858ea5e5SAndroid Build Coastguard Worker p_info("failed to create json writer for btf. falling back to plain output");
1049*858ea5e5SAndroid Build Coastguard Worker btf__free(btf);
1050*858ea5e5SAndroid Build Coastguard Worker btf = NULL;
1051*858ea5e5SAndroid Build Coastguard Worker print_entry_plain(info, key, value);
1052*858ea5e5SAndroid Build Coastguard Worker } else {
1053*858ea5e5SAndroid Build Coastguard Worker struct btf_dumper d = {
1054*858ea5e5SAndroid Build Coastguard Worker .btf = btf,
1055*858ea5e5SAndroid Build Coastguard Worker .jw = btf_wtr,
1056*858ea5e5SAndroid Build Coastguard Worker .is_plain_text = true,
1057*858ea5e5SAndroid Build Coastguard Worker };
1058*858ea5e5SAndroid Build Coastguard Worker
1059*858ea5e5SAndroid Build Coastguard Worker do_dump_btf(&d, info, key, value);
1060*858ea5e5SAndroid Build Coastguard Worker jsonw_destroy(&btf_wtr);
1061*858ea5e5SAndroid Build Coastguard Worker }
1062*858ea5e5SAndroid Build Coastguard Worker } else {
1063*858ea5e5SAndroid Build Coastguard Worker print_entry_plain(info, key, value);
1064*858ea5e5SAndroid Build Coastguard Worker }
1065*858ea5e5SAndroid Build Coastguard Worker btf__free(btf);
1066*858ea5e5SAndroid Build Coastguard Worker }
1067*858ea5e5SAndroid Build Coastguard Worker
do_lookup(int argc,char ** argv)1068*858ea5e5SAndroid Build Coastguard Worker static int do_lookup(int argc, char **argv)
1069*858ea5e5SAndroid Build Coastguard Worker {
1070*858ea5e5SAndroid Build Coastguard Worker struct bpf_map_info info = {};
1071*858ea5e5SAndroid Build Coastguard Worker __u32 len = sizeof(info);
1072*858ea5e5SAndroid Build Coastguard Worker void *key, *value;
1073*858ea5e5SAndroid Build Coastguard Worker int err;
1074*858ea5e5SAndroid Build Coastguard Worker int fd;
1075*858ea5e5SAndroid Build Coastguard Worker
1076*858ea5e5SAndroid Build Coastguard Worker if (argc < 2)
1077*858ea5e5SAndroid Build Coastguard Worker usage();
1078*858ea5e5SAndroid Build Coastguard Worker
1079*858ea5e5SAndroid Build Coastguard Worker fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
1080*858ea5e5SAndroid Build Coastguard Worker if (fd < 0)
1081*858ea5e5SAndroid Build Coastguard Worker return -1;
1082*858ea5e5SAndroid Build Coastguard Worker
1083*858ea5e5SAndroid Build Coastguard Worker err = alloc_key_value(&info, &key, &value);
1084*858ea5e5SAndroid Build Coastguard Worker if (err)
1085*858ea5e5SAndroid Build Coastguard Worker goto exit_free;
1086*858ea5e5SAndroid Build Coastguard Worker
1087*858ea5e5SAndroid Build Coastguard Worker err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL);
1088*858ea5e5SAndroid Build Coastguard Worker if (err)
1089*858ea5e5SAndroid Build Coastguard Worker goto exit_free;
1090*858ea5e5SAndroid Build Coastguard Worker
1091*858ea5e5SAndroid Build Coastguard Worker err = bpf_map_lookup_elem(fd, key, value);
1092*858ea5e5SAndroid Build Coastguard Worker if (err) {
1093*858ea5e5SAndroid Build Coastguard Worker if (errno == ENOENT) {
1094*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
1095*858ea5e5SAndroid Build Coastguard Worker jsonw_null(json_wtr);
1096*858ea5e5SAndroid Build Coastguard Worker } else {
1097*858ea5e5SAndroid Build Coastguard Worker printf("key:\n");
1098*858ea5e5SAndroid Build Coastguard Worker fprint_hex(stdout, key, info.key_size, " ");
1099*858ea5e5SAndroid Build Coastguard Worker printf("\n\nNot found\n");
1100*858ea5e5SAndroid Build Coastguard Worker }
1101*858ea5e5SAndroid Build Coastguard Worker } else {
1102*858ea5e5SAndroid Build Coastguard Worker p_err("lookup failed: %s", strerror(errno));
1103*858ea5e5SAndroid Build Coastguard Worker }
1104*858ea5e5SAndroid Build Coastguard Worker
1105*858ea5e5SAndroid Build Coastguard Worker goto exit_free;
1106*858ea5e5SAndroid Build Coastguard Worker }
1107*858ea5e5SAndroid Build Coastguard Worker
1108*858ea5e5SAndroid Build Coastguard Worker /* here means bpf_map_lookup_elem() succeeded */
1109*858ea5e5SAndroid Build Coastguard Worker print_key_value(&info, key, value);
1110*858ea5e5SAndroid Build Coastguard Worker
1111*858ea5e5SAndroid Build Coastguard Worker exit_free:
1112*858ea5e5SAndroid Build Coastguard Worker free(key);
1113*858ea5e5SAndroid Build Coastguard Worker free(value);
1114*858ea5e5SAndroid Build Coastguard Worker close(fd);
1115*858ea5e5SAndroid Build Coastguard Worker
1116*858ea5e5SAndroid Build Coastguard Worker return err;
1117*858ea5e5SAndroid Build Coastguard Worker }
1118*858ea5e5SAndroid Build Coastguard Worker
do_getnext(int argc,char ** argv)1119*858ea5e5SAndroid Build Coastguard Worker static int do_getnext(int argc, char **argv)
1120*858ea5e5SAndroid Build Coastguard Worker {
1121*858ea5e5SAndroid Build Coastguard Worker struct bpf_map_info info = {};
1122*858ea5e5SAndroid Build Coastguard Worker __u32 len = sizeof(info);
1123*858ea5e5SAndroid Build Coastguard Worker void *key, *nextkey;
1124*858ea5e5SAndroid Build Coastguard Worker int err;
1125*858ea5e5SAndroid Build Coastguard Worker int fd;
1126*858ea5e5SAndroid Build Coastguard Worker
1127*858ea5e5SAndroid Build Coastguard Worker if (argc < 2)
1128*858ea5e5SAndroid Build Coastguard Worker usage();
1129*858ea5e5SAndroid Build Coastguard Worker
1130*858ea5e5SAndroid Build Coastguard Worker fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
1131*858ea5e5SAndroid Build Coastguard Worker if (fd < 0)
1132*858ea5e5SAndroid Build Coastguard Worker return -1;
1133*858ea5e5SAndroid Build Coastguard Worker
1134*858ea5e5SAndroid Build Coastguard Worker key = malloc(info.key_size);
1135*858ea5e5SAndroid Build Coastguard Worker nextkey = malloc(info.key_size);
1136*858ea5e5SAndroid Build Coastguard Worker if (!key || !nextkey) {
1137*858ea5e5SAndroid Build Coastguard Worker p_err("mem alloc failed");
1138*858ea5e5SAndroid Build Coastguard Worker err = -1;
1139*858ea5e5SAndroid Build Coastguard Worker goto exit_free;
1140*858ea5e5SAndroid Build Coastguard Worker }
1141*858ea5e5SAndroid Build Coastguard Worker
1142*858ea5e5SAndroid Build Coastguard Worker if (argc) {
1143*858ea5e5SAndroid Build Coastguard Worker err = parse_elem(argv, &info, key, NULL, info.key_size, 0,
1144*858ea5e5SAndroid Build Coastguard Worker NULL, NULL);
1145*858ea5e5SAndroid Build Coastguard Worker if (err)
1146*858ea5e5SAndroid Build Coastguard Worker goto exit_free;
1147*858ea5e5SAndroid Build Coastguard Worker } else {
1148*858ea5e5SAndroid Build Coastguard Worker free(key);
1149*858ea5e5SAndroid Build Coastguard Worker key = NULL;
1150*858ea5e5SAndroid Build Coastguard Worker }
1151*858ea5e5SAndroid Build Coastguard Worker
1152*858ea5e5SAndroid Build Coastguard Worker err = bpf_map_get_next_key(fd, key, nextkey);
1153*858ea5e5SAndroid Build Coastguard Worker if (err) {
1154*858ea5e5SAndroid Build Coastguard Worker p_err("can't get next key: %s", strerror(errno));
1155*858ea5e5SAndroid Build Coastguard Worker goto exit_free;
1156*858ea5e5SAndroid Build Coastguard Worker }
1157*858ea5e5SAndroid Build Coastguard Worker
1158*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
1159*858ea5e5SAndroid Build Coastguard Worker jsonw_start_object(json_wtr);
1160*858ea5e5SAndroid Build Coastguard Worker if (key) {
1161*858ea5e5SAndroid Build Coastguard Worker jsonw_name(json_wtr, "key");
1162*858ea5e5SAndroid Build Coastguard Worker print_hex_data_json(key, info.key_size);
1163*858ea5e5SAndroid Build Coastguard Worker } else {
1164*858ea5e5SAndroid Build Coastguard Worker jsonw_null_field(json_wtr, "key");
1165*858ea5e5SAndroid Build Coastguard Worker }
1166*858ea5e5SAndroid Build Coastguard Worker jsonw_name(json_wtr, "next_key");
1167*858ea5e5SAndroid Build Coastguard Worker print_hex_data_json(nextkey, info.key_size);
1168*858ea5e5SAndroid Build Coastguard Worker jsonw_end_object(json_wtr);
1169*858ea5e5SAndroid Build Coastguard Worker } else {
1170*858ea5e5SAndroid Build Coastguard Worker if (key) {
1171*858ea5e5SAndroid Build Coastguard Worker printf("key:\n");
1172*858ea5e5SAndroid Build Coastguard Worker fprint_hex(stdout, key, info.key_size, " ");
1173*858ea5e5SAndroid Build Coastguard Worker printf("\n");
1174*858ea5e5SAndroid Build Coastguard Worker } else {
1175*858ea5e5SAndroid Build Coastguard Worker printf("key: None\n");
1176*858ea5e5SAndroid Build Coastguard Worker }
1177*858ea5e5SAndroid Build Coastguard Worker printf("next key:\n");
1178*858ea5e5SAndroid Build Coastguard Worker fprint_hex(stdout, nextkey, info.key_size, " ");
1179*858ea5e5SAndroid Build Coastguard Worker printf("\n");
1180*858ea5e5SAndroid Build Coastguard Worker }
1181*858ea5e5SAndroid Build Coastguard Worker
1182*858ea5e5SAndroid Build Coastguard Worker exit_free:
1183*858ea5e5SAndroid Build Coastguard Worker free(nextkey);
1184*858ea5e5SAndroid Build Coastguard Worker free(key);
1185*858ea5e5SAndroid Build Coastguard Worker close(fd);
1186*858ea5e5SAndroid Build Coastguard Worker
1187*858ea5e5SAndroid Build Coastguard Worker return err;
1188*858ea5e5SAndroid Build Coastguard Worker }
1189*858ea5e5SAndroid Build Coastguard Worker
do_delete(int argc,char ** argv)1190*858ea5e5SAndroid Build Coastguard Worker static int do_delete(int argc, char **argv)
1191*858ea5e5SAndroid Build Coastguard Worker {
1192*858ea5e5SAndroid Build Coastguard Worker struct bpf_map_info info = {};
1193*858ea5e5SAndroid Build Coastguard Worker __u32 len = sizeof(info);
1194*858ea5e5SAndroid Build Coastguard Worker void *key;
1195*858ea5e5SAndroid Build Coastguard Worker int err;
1196*858ea5e5SAndroid Build Coastguard Worker int fd;
1197*858ea5e5SAndroid Build Coastguard Worker
1198*858ea5e5SAndroid Build Coastguard Worker if (argc < 2)
1199*858ea5e5SAndroid Build Coastguard Worker usage();
1200*858ea5e5SAndroid Build Coastguard Worker
1201*858ea5e5SAndroid Build Coastguard Worker fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
1202*858ea5e5SAndroid Build Coastguard Worker if (fd < 0)
1203*858ea5e5SAndroid Build Coastguard Worker return -1;
1204*858ea5e5SAndroid Build Coastguard Worker
1205*858ea5e5SAndroid Build Coastguard Worker key = malloc(info.key_size);
1206*858ea5e5SAndroid Build Coastguard Worker if (!key) {
1207*858ea5e5SAndroid Build Coastguard Worker p_err("mem alloc failed");
1208*858ea5e5SAndroid Build Coastguard Worker err = -1;
1209*858ea5e5SAndroid Build Coastguard Worker goto exit_free;
1210*858ea5e5SAndroid Build Coastguard Worker }
1211*858ea5e5SAndroid Build Coastguard Worker
1212*858ea5e5SAndroid Build Coastguard Worker err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL);
1213*858ea5e5SAndroid Build Coastguard Worker if (err)
1214*858ea5e5SAndroid Build Coastguard Worker goto exit_free;
1215*858ea5e5SAndroid Build Coastguard Worker
1216*858ea5e5SAndroid Build Coastguard Worker err = bpf_map_delete_elem(fd, key);
1217*858ea5e5SAndroid Build Coastguard Worker if (err)
1218*858ea5e5SAndroid Build Coastguard Worker p_err("delete failed: %s", strerror(errno));
1219*858ea5e5SAndroid Build Coastguard Worker
1220*858ea5e5SAndroid Build Coastguard Worker exit_free:
1221*858ea5e5SAndroid Build Coastguard Worker free(key);
1222*858ea5e5SAndroid Build Coastguard Worker close(fd);
1223*858ea5e5SAndroid Build Coastguard Worker
1224*858ea5e5SAndroid Build Coastguard Worker if (!err && json_output)
1225*858ea5e5SAndroid Build Coastguard Worker jsonw_null(json_wtr);
1226*858ea5e5SAndroid Build Coastguard Worker return err;
1227*858ea5e5SAndroid Build Coastguard Worker }
1228*858ea5e5SAndroid Build Coastguard Worker
do_pin(int argc,char ** argv)1229*858ea5e5SAndroid Build Coastguard Worker static int do_pin(int argc, char **argv)
1230*858ea5e5SAndroid Build Coastguard Worker {
1231*858ea5e5SAndroid Build Coastguard Worker int err;
1232*858ea5e5SAndroid Build Coastguard Worker
1233*858ea5e5SAndroid Build Coastguard Worker err = do_pin_any(argc, argv, map_parse_fd);
1234*858ea5e5SAndroid Build Coastguard Worker if (!err && json_output)
1235*858ea5e5SAndroid Build Coastguard Worker jsonw_null(json_wtr);
1236*858ea5e5SAndroid Build Coastguard Worker return err;
1237*858ea5e5SAndroid Build Coastguard Worker }
1238*858ea5e5SAndroid Build Coastguard Worker
do_create(int argc,char ** argv)1239*858ea5e5SAndroid Build Coastguard Worker static int do_create(int argc, char **argv)
1240*858ea5e5SAndroid Build Coastguard Worker {
1241*858ea5e5SAndroid Build Coastguard Worker LIBBPF_OPTS(bpf_map_create_opts, attr);
1242*858ea5e5SAndroid Build Coastguard Worker enum bpf_map_type map_type = BPF_MAP_TYPE_UNSPEC;
1243*858ea5e5SAndroid Build Coastguard Worker __u32 key_size = 0, value_size = 0, max_entries = 0;
1244*858ea5e5SAndroid Build Coastguard Worker const char *map_name = NULL;
1245*858ea5e5SAndroid Build Coastguard Worker const char *pinfile;
1246*858ea5e5SAndroid Build Coastguard Worker int err = -1, fd;
1247*858ea5e5SAndroid Build Coastguard Worker
1248*858ea5e5SAndroid Build Coastguard Worker if (!REQ_ARGS(7))
1249*858ea5e5SAndroid Build Coastguard Worker return -1;
1250*858ea5e5SAndroid Build Coastguard Worker pinfile = GET_ARG();
1251*858ea5e5SAndroid Build Coastguard Worker
1252*858ea5e5SAndroid Build Coastguard Worker while (argc) {
1253*858ea5e5SAndroid Build Coastguard Worker if (!REQ_ARGS(2))
1254*858ea5e5SAndroid Build Coastguard Worker return -1;
1255*858ea5e5SAndroid Build Coastguard Worker
1256*858ea5e5SAndroid Build Coastguard Worker if (is_prefix(*argv, "type")) {
1257*858ea5e5SAndroid Build Coastguard Worker NEXT_ARG();
1258*858ea5e5SAndroid Build Coastguard Worker
1259*858ea5e5SAndroid Build Coastguard Worker if (map_type) {
1260*858ea5e5SAndroid Build Coastguard Worker p_err("map type already specified");
1261*858ea5e5SAndroid Build Coastguard Worker goto exit;
1262*858ea5e5SAndroid Build Coastguard Worker }
1263*858ea5e5SAndroid Build Coastguard Worker
1264*858ea5e5SAndroid Build Coastguard Worker map_type = map_type_from_str(*argv);
1265*858ea5e5SAndroid Build Coastguard Worker if ((int)map_type < 0) {
1266*858ea5e5SAndroid Build Coastguard Worker p_err("unrecognized map type: %s", *argv);
1267*858ea5e5SAndroid Build Coastguard Worker goto exit;
1268*858ea5e5SAndroid Build Coastguard Worker }
1269*858ea5e5SAndroid Build Coastguard Worker NEXT_ARG();
1270*858ea5e5SAndroid Build Coastguard Worker } else if (is_prefix(*argv, "name")) {
1271*858ea5e5SAndroid Build Coastguard Worker NEXT_ARG();
1272*858ea5e5SAndroid Build Coastguard Worker map_name = GET_ARG();
1273*858ea5e5SAndroid Build Coastguard Worker } else if (is_prefix(*argv, "key")) {
1274*858ea5e5SAndroid Build Coastguard Worker if (parse_u32_arg(&argc, &argv, &key_size,
1275*858ea5e5SAndroid Build Coastguard Worker "key size"))
1276*858ea5e5SAndroid Build Coastguard Worker goto exit;
1277*858ea5e5SAndroid Build Coastguard Worker } else if (is_prefix(*argv, "value")) {
1278*858ea5e5SAndroid Build Coastguard Worker if (parse_u32_arg(&argc, &argv, &value_size,
1279*858ea5e5SAndroid Build Coastguard Worker "value size"))
1280*858ea5e5SAndroid Build Coastguard Worker goto exit;
1281*858ea5e5SAndroid Build Coastguard Worker } else if (is_prefix(*argv, "entries")) {
1282*858ea5e5SAndroid Build Coastguard Worker if (parse_u32_arg(&argc, &argv, &max_entries,
1283*858ea5e5SAndroid Build Coastguard Worker "max entries"))
1284*858ea5e5SAndroid Build Coastguard Worker goto exit;
1285*858ea5e5SAndroid Build Coastguard Worker } else if (is_prefix(*argv, "flags")) {
1286*858ea5e5SAndroid Build Coastguard Worker if (parse_u32_arg(&argc, &argv, &attr.map_flags,
1287*858ea5e5SAndroid Build Coastguard Worker "flags"))
1288*858ea5e5SAndroid Build Coastguard Worker goto exit;
1289*858ea5e5SAndroid Build Coastguard Worker } else if (is_prefix(*argv, "dev")) {
1290*858ea5e5SAndroid Build Coastguard Worker p_info("Warning: 'bpftool map create [...] dev <ifname>' syntax is deprecated.\n"
1291*858ea5e5SAndroid Build Coastguard Worker "Going further, please use 'offload_dev <ifname>' to request hardware offload for the map.");
1292*858ea5e5SAndroid Build Coastguard Worker goto offload_dev;
1293*858ea5e5SAndroid Build Coastguard Worker } else if (is_prefix(*argv, "offload_dev")) {
1294*858ea5e5SAndroid Build Coastguard Worker offload_dev:
1295*858ea5e5SAndroid Build Coastguard Worker NEXT_ARG();
1296*858ea5e5SAndroid Build Coastguard Worker
1297*858ea5e5SAndroid Build Coastguard Worker if (attr.map_ifindex) {
1298*858ea5e5SAndroid Build Coastguard Worker p_err("offload device already specified");
1299*858ea5e5SAndroid Build Coastguard Worker goto exit;
1300*858ea5e5SAndroid Build Coastguard Worker }
1301*858ea5e5SAndroid Build Coastguard Worker
1302*858ea5e5SAndroid Build Coastguard Worker attr.map_ifindex = if_nametoindex(*argv);
1303*858ea5e5SAndroid Build Coastguard Worker if (!attr.map_ifindex) {
1304*858ea5e5SAndroid Build Coastguard Worker p_err("unrecognized netdevice '%s': %s",
1305*858ea5e5SAndroid Build Coastguard Worker *argv, strerror(errno));
1306*858ea5e5SAndroid Build Coastguard Worker goto exit;
1307*858ea5e5SAndroid Build Coastguard Worker }
1308*858ea5e5SAndroid Build Coastguard Worker NEXT_ARG();
1309*858ea5e5SAndroid Build Coastguard Worker } else if (is_prefix(*argv, "inner_map")) {
1310*858ea5e5SAndroid Build Coastguard Worker struct bpf_map_info info = {};
1311*858ea5e5SAndroid Build Coastguard Worker __u32 len = sizeof(info);
1312*858ea5e5SAndroid Build Coastguard Worker int inner_map_fd;
1313*858ea5e5SAndroid Build Coastguard Worker
1314*858ea5e5SAndroid Build Coastguard Worker NEXT_ARG();
1315*858ea5e5SAndroid Build Coastguard Worker if (!REQ_ARGS(2))
1316*858ea5e5SAndroid Build Coastguard Worker usage();
1317*858ea5e5SAndroid Build Coastguard Worker inner_map_fd = map_parse_fd_and_info(&argc, &argv,
1318*858ea5e5SAndroid Build Coastguard Worker &info, &len);
1319*858ea5e5SAndroid Build Coastguard Worker if (inner_map_fd < 0)
1320*858ea5e5SAndroid Build Coastguard Worker return -1;
1321*858ea5e5SAndroid Build Coastguard Worker attr.inner_map_fd = inner_map_fd;
1322*858ea5e5SAndroid Build Coastguard Worker } else {
1323*858ea5e5SAndroid Build Coastguard Worker p_err("unknown arg %s", *argv);
1324*858ea5e5SAndroid Build Coastguard Worker goto exit;
1325*858ea5e5SAndroid Build Coastguard Worker }
1326*858ea5e5SAndroid Build Coastguard Worker }
1327*858ea5e5SAndroid Build Coastguard Worker
1328*858ea5e5SAndroid Build Coastguard Worker if (!map_name) {
1329*858ea5e5SAndroid Build Coastguard Worker p_err("map name not specified");
1330*858ea5e5SAndroid Build Coastguard Worker goto exit;
1331*858ea5e5SAndroid Build Coastguard Worker }
1332*858ea5e5SAndroid Build Coastguard Worker
1333*858ea5e5SAndroid Build Coastguard Worker set_max_rlimit();
1334*858ea5e5SAndroid Build Coastguard Worker
1335*858ea5e5SAndroid Build Coastguard Worker fd = bpf_map_create(map_type, map_name, key_size, value_size, max_entries, &attr);
1336*858ea5e5SAndroid Build Coastguard Worker if (fd < 0) {
1337*858ea5e5SAndroid Build Coastguard Worker p_err("map create failed: %s", strerror(errno));
1338*858ea5e5SAndroid Build Coastguard Worker goto exit;
1339*858ea5e5SAndroid Build Coastguard Worker }
1340*858ea5e5SAndroid Build Coastguard Worker
1341*858ea5e5SAndroid Build Coastguard Worker err = do_pin_fd(fd, pinfile);
1342*858ea5e5SAndroid Build Coastguard Worker close(fd);
1343*858ea5e5SAndroid Build Coastguard Worker if (err)
1344*858ea5e5SAndroid Build Coastguard Worker goto exit;
1345*858ea5e5SAndroid Build Coastguard Worker
1346*858ea5e5SAndroid Build Coastguard Worker if (json_output)
1347*858ea5e5SAndroid Build Coastguard Worker jsonw_null(json_wtr);
1348*858ea5e5SAndroid Build Coastguard Worker
1349*858ea5e5SAndroid Build Coastguard Worker exit:
1350*858ea5e5SAndroid Build Coastguard Worker if (attr.inner_map_fd > 0)
1351*858ea5e5SAndroid Build Coastguard Worker close(attr.inner_map_fd);
1352*858ea5e5SAndroid Build Coastguard Worker
1353*858ea5e5SAndroid Build Coastguard Worker return err;
1354*858ea5e5SAndroid Build Coastguard Worker }
1355*858ea5e5SAndroid Build Coastguard Worker
do_pop_dequeue(int argc,char ** argv)1356*858ea5e5SAndroid Build Coastguard Worker static int do_pop_dequeue(int argc, char **argv)
1357*858ea5e5SAndroid Build Coastguard Worker {
1358*858ea5e5SAndroid Build Coastguard Worker struct bpf_map_info info = {};
1359*858ea5e5SAndroid Build Coastguard Worker __u32 len = sizeof(info);
1360*858ea5e5SAndroid Build Coastguard Worker void *key, *value;
1361*858ea5e5SAndroid Build Coastguard Worker int err;
1362*858ea5e5SAndroid Build Coastguard Worker int fd;
1363*858ea5e5SAndroid Build Coastguard Worker
1364*858ea5e5SAndroid Build Coastguard Worker if (argc < 2)
1365*858ea5e5SAndroid Build Coastguard Worker usage();
1366*858ea5e5SAndroid Build Coastguard Worker
1367*858ea5e5SAndroid Build Coastguard Worker fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
1368*858ea5e5SAndroid Build Coastguard Worker if (fd < 0)
1369*858ea5e5SAndroid Build Coastguard Worker return -1;
1370*858ea5e5SAndroid Build Coastguard Worker
1371*858ea5e5SAndroid Build Coastguard Worker err = alloc_key_value(&info, &key, &value);
1372*858ea5e5SAndroid Build Coastguard Worker if (err)
1373*858ea5e5SAndroid Build Coastguard Worker goto exit_free;
1374*858ea5e5SAndroid Build Coastguard Worker
1375*858ea5e5SAndroid Build Coastguard Worker err = bpf_map_lookup_and_delete_elem(fd, key, value);
1376*858ea5e5SAndroid Build Coastguard Worker if (err) {
1377*858ea5e5SAndroid Build Coastguard Worker if (errno == ENOENT) {
1378*858ea5e5SAndroid Build Coastguard Worker if (json_output)
1379*858ea5e5SAndroid Build Coastguard Worker jsonw_null(json_wtr);
1380*858ea5e5SAndroid Build Coastguard Worker else
1381*858ea5e5SAndroid Build Coastguard Worker printf("Error: empty map\n");
1382*858ea5e5SAndroid Build Coastguard Worker } else {
1383*858ea5e5SAndroid Build Coastguard Worker p_err("pop failed: %s", strerror(errno));
1384*858ea5e5SAndroid Build Coastguard Worker }
1385*858ea5e5SAndroid Build Coastguard Worker
1386*858ea5e5SAndroid Build Coastguard Worker goto exit_free;
1387*858ea5e5SAndroid Build Coastguard Worker }
1388*858ea5e5SAndroid Build Coastguard Worker
1389*858ea5e5SAndroid Build Coastguard Worker print_key_value(&info, key, value);
1390*858ea5e5SAndroid Build Coastguard Worker
1391*858ea5e5SAndroid Build Coastguard Worker exit_free:
1392*858ea5e5SAndroid Build Coastguard Worker free(key);
1393*858ea5e5SAndroid Build Coastguard Worker free(value);
1394*858ea5e5SAndroid Build Coastguard Worker close(fd);
1395*858ea5e5SAndroid Build Coastguard Worker
1396*858ea5e5SAndroid Build Coastguard Worker return err;
1397*858ea5e5SAndroid Build Coastguard Worker }
1398*858ea5e5SAndroid Build Coastguard Worker
do_freeze(int argc,char ** argv)1399*858ea5e5SAndroid Build Coastguard Worker static int do_freeze(int argc, char **argv)
1400*858ea5e5SAndroid Build Coastguard Worker {
1401*858ea5e5SAndroid Build Coastguard Worker int err, fd;
1402*858ea5e5SAndroid Build Coastguard Worker
1403*858ea5e5SAndroid Build Coastguard Worker if (!REQ_ARGS(2))
1404*858ea5e5SAndroid Build Coastguard Worker return -1;
1405*858ea5e5SAndroid Build Coastguard Worker
1406*858ea5e5SAndroid Build Coastguard Worker fd = map_parse_fd(&argc, &argv);
1407*858ea5e5SAndroid Build Coastguard Worker if (fd < 0)
1408*858ea5e5SAndroid Build Coastguard Worker return -1;
1409*858ea5e5SAndroid Build Coastguard Worker
1410*858ea5e5SAndroid Build Coastguard Worker if (argc) {
1411*858ea5e5SAndroid Build Coastguard Worker close(fd);
1412*858ea5e5SAndroid Build Coastguard Worker return BAD_ARG();
1413*858ea5e5SAndroid Build Coastguard Worker }
1414*858ea5e5SAndroid Build Coastguard Worker
1415*858ea5e5SAndroid Build Coastguard Worker err = bpf_map_freeze(fd);
1416*858ea5e5SAndroid Build Coastguard Worker close(fd);
1417*858ea5e5SAndroid Build Coastguard Worker if (err) {
1418*858ea5e5SAndroid Build Coastguard Worker p_err("failed to freeze map: %s", strerror(errno));
1419*858ea5e5SAndroid Build Coastguard Worker return err;
1420*858ea5e5SAndroid Build Coastguard Worker }
1421*858ea5e5SAndroid Build Coastguard Worker
1422*858ea5e5SAndroid Build Coastguard Worker if (json_output)
1423*858ea5e5SAndroid Build Coastguard Worker jsonw_null(json_wtr);
1424*858ea5e5SAndroid Build Coastguard Worker
1425*858ea5e5SAndroid Build Coastguard Worker return 0;
1426*858ea5e5SAndroid Build Coastguard Worker }
1427*858ea5e5SAndroid Build Coastguard Worker
do_help(int argc,char ** argv)1428*858ea5e5SAndroid Build Coastguard Worker static int do_help(int argc, char **argv)
1429*858ea5e5SAndroid Build Coastguard Worker {
1430*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
1431*858ea5e5SAndroid Build Coastguard Worker jsonw_null(json_wtr);
1432*858ea5e5SAndroid Build Coastguard Worker return 0;
1433*858ea5e5SAndroid Build Coastguard Worker }
1434*858ea5e5SAndroid Build Coastguard Worker
1435*858ea5e5SAndroid Build Coastguard Worker fprintf(stderr,
1436*858ea5e5SAndroid Build Coastguard Worker "Usage: %1$s %2$s { show | list } [MAP]\n"
1437*858ea5e5SAndroid Build Coastguard Worker " %1$s %2$s create FILE type TYPE key KEY_SIZE value VALUE_SIZE \\\n"
1438*858ea5e5SAndroid Build Coastguard Worker " entries MAX_ENTRIES name NAME [flags FLAGS] \\\n"
1439*858ea5e5SAndroid Build Coastguard Worker " [inner_map MAP] [offload_dev NAME]\n"
1440*858ea5e5SAndroid Build Coastguard Worker " %1$s %2$s dump MAP\n"
1441*858ea5e5SAndroid Build Coastguard Worker " %1$s %2$s update MAP [key DATA] [value VALUE] [UPDATE_FLAGS]\n"
1442*858ea5e5SAndroid Build Coastguard Worker " %1$s %2$s lookup MAP [key DATA]\n"
1443*858ea5e5SAndroid Build Coastguard Worker " %1$s %2$s getnext MAP [key DATA]\n"
1444*858ea5e5SAndroid Build Coastguard Worker " %1$s %2$s delete MAP key DATA\n"
1445*858ea5e5SAndroid Build Coastguard Worker " %1$s %2$s pin MAP FILE\n"
1446*858ea5e5SAndroid Build Coastguard Worker " %1$s %2$s event_pipe MAP [cpu N index M]\n"
1447*858ea5e5SAndroid Build Coastguard Worker " %1$s %2$s peek MAP\n"
1448*858ea5e5SAndroid Build Coastguard Worker " %1$s %2$s push MAP value VALUE\n"
1449*858ea5e5SAndroid Build Coastguard Worker " %1$s %2$s pop MAP\n"
1450*858ea5e5SAndroid Build Coastguard Worker " %1$s %2$s enqueue MAP value VALUE\n"
1451*858ea5e5SAndroid Build Coastguard Worker " %1$s %2$s dequeue MAP\n"
1452*858ea5e5SAndroid Build Coastguard Worker " %1$s %2$s freeze MAP\n"
1453*858ea5e5SAndroid Build Coastguard Worker " %1$s %2$s help\n"
1454*858ea5e5SAndroid Build Coastguard Worker "\n"
1455*858ea5e5SAndroid Build Coastguard Worker " " HELP_SPEC_MAP "\n"
1456*858ea5e5SAndroid Build Coastguard Worker " DATA := { [hex] BYTES }\n"
1457*858ea5e5SAndroid Build Coastguard Worker " " HELP_SPEC_PROGRAM "\n"
1458*858ea5e5SAndroid Build Coastguard Worker " VALUE := { DATA | MAP | PROG }\n"
1459*858ea5e5SAndroid Build Coastguard Worker " UPDATE_FLAGS := { any | exist | noexist }\n"
1460*858ea5e5SAndroid Build Coastguard Worker " TYPE := { hash | array | prog_array | perf_event_array | percpu_hash |\n"
1461*858ea5e5SAndroid Build Coastguard Worker " percpu_array | stack_trace | cgroup_array | lru_hash |\n"
1462*858ea5e5SAndroid Build Coastguard Worker " lru_percpu_hash | lpm_trie | array_of_maps | hash_of_maps |\n"
1463*858ea5e5SAndroid Build Coastguard Worker " devmap | devmap_hash | sockmap | cpumap | xskmap | sockhash |\n"
1464*858ea5e5SAndroid Build Coastguard Worker " cgroup_storage | reuseport_sockarray | percpu_cgroup_storage |\n"
1465*858ea5e5SAndroid Build Coastguard Worker " queue | stack | sk_storage | struct_ops | ringbuf | inode_storage |\n"
1466*858ea5e5SAndroid Build Coastguard Worker " task_storage | bloom_filter | user_ringbuf | cgrp_storage | arena }\n"
1467*858ea5e5SAndroid Build Coastguard Worker " " HELP_SPEC_OPTIONS " |\n"
1468*858ea5e5SAndroid Build Coastguard Worker " {-f|--bpffs} | {-n|--nomount} }\n"
1469*858ea5e5SAndroid Build Coastguard Worker "",
1470*858ea5e5SAndroid Build Coastguard Worker bin_name, argv[-2]);
1471*858ea5e5SAndroid Build Coastguard Worker
1472*858ea5e5SAndroid Build Coastguard Worker return 0;
1473*858ea5e5SAndroid Build Coastguard Worker }
1474*858ea5e5SAndroid Build Coastguard Worker
1475*858ea5e5SAndroid Build Coastguard Worker static const struct cmd cmds[] = {
1476*858ea5e5SAndroid Build Coastguard Worker { "show", do_show },
1477*858ea5e5SAndroid Build Coastguard Worker { "list", do_show },
1478*858ea5e5SAndroid Build Coastguard Worker { "help", do_help },
1479*858ea5e5SAndroid Build Coastguard Worker { "dump", do_dump },
1480*858ea5e5SAndroid Build Coastguard Worker { "update", do_update },
1481*858ea5e5SAndroid Build Coastguard Worker { "lookup", do_lookup },
1482*858ea5e5SAndroid Build Coastguard Worker { "getnext", do_getnext },
1483*858ea5e5SAndroid Build Coastguard Worker { "delete", do_delete },
1484*858ea5e5SAndroid Build Coastguard Worker { "pin", do_pin },
1485*858ea5e5SAndroid Build Coastguard Worker { "event_pipe", do_event_pipe },
1486*858ea5e5SAndroid Build Coastguard Worker { "create", do_create },
1487*858ea5e5SAndroid Build Coastguard Worker { "peek", do_lookup },
1488*858ea5e5SAndroid Build Coastguard Worker { "push", do_update },
1489*858ea5e5SAndroid Build Coastguard Worker { "enqueue", do_update },
1490*858ea5e5SAndroid Build Coastguard Worker { "pop", do_pop_dequeue },
1491*858ea5e5SAndroid Build Coastguard Worker { "dequeue", do_pop_dequeue },
1492*858ea5e5SAndroid Build Coastguard Worker { "freeze", do_freeze },
1493*858ea5e5SAndroid Build Coastguard Worker { 0 }
1494*858ea5e5SAndroid Build Coastguard Worker };
1495*858ea5e5SAndroid Build Coastguard Worker
do_map(int argc,char ** argv)1496*858ea5e5SAndroid Build Coastguard Worker int do_map(int argc, char **argv)
1497*858ea5e5SAndroid Build Coastguard Worker {
1498*858ea5e5SAndroid Build Coastguard Worker return cmd_select(cmds, argc, argv, do_help);
1499*858ea5e5SAndroid Build Coastguard Worker }
1500