xref: /aosp_15_r20/external/bpftool/src/map.c (revision 858ea5e570667251cdc31d3fe7b846b591105938)
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