Re: [PATCH bpf-next 4/5] bpftool: support dumping metadata

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Yonghong Song <yhs@xxxxxx> writes:

> On 8/20/20 2:42 AM, YiFei Zhu wrote:
>> From: YiFei Zhu <zhuyifei@xxxxxxxxxx>
>> 
>> Added a flag "--metadata" to `bpftool prog list` to dump the metadata
>> contents. For some formatting some BTF code is put directly in the
>> metadata dumping. Sanity checks on the map and the kind of the btf_type
>> to make sure we are actually dumping what we are expecting.
>> 
>> A helper jsonw_reset is added to json writer so we can reuse the same
>> json writer without having extraneous commas.
>> 
>> Sample output:
>> 
>>    $ bpftool prog --metadata
>>    6: cgroup_skb  name prog  tag bcf7977d3b93787c  gpl
>>    [...]
>>    	btf_id 4
>>    	metadata:
>>    		metadata_a = "foo"
>>    		metadata_b = 1
>> 
>>    $ bpftool prog --metadata --json --pretty
>>    [{
>>            "id": 6,
>>    [...]
>>            "btf_id": 4,
>>            "metadata": {
>>                "metadata_a": "foo",
>>                "metadata_b": 1
>>            }
>>        }
>>    ]
>> 
>> Signed-off-by: YiFei Zhu <zhuyifei@xxxxxxxxxx>
>> ---
>>   tools/bpf/bpftool/json_writer.c |   6 ++
>>   tools/bpf/bpftool/json_writer.h |   3 +
>>   tools/bpf/bpftool/main.c        |  10 +++
>>   tools/bpf/bpftool/main.h        |   1 +
>>   tools/bpf/bpftool/prog.c        | 135 ++++++++++++++++++++++++++++++++
>>   5 files changed, 155 insertions(+)
>> 
>> diff --git a/tools/bpf/bpftool/json_writer.c b/tools/bpf/bpftool/json_writer.c
>> index 86501cd3c763..7fea83bedf48 100644
>> --- a/tools/bpf/bpftool/json_writer.c
>> +++ b/tools/bpf/bpftool/json_writer.c
>> @@ -119,6 +119,12 @@ void jsonw_pretty(json_writer_t *self, bool on)
>>   	self->pretty = on;
>>   }
>>   
>> +void jsonw_reset(json_writer_t *self)
>> +{
>> +	assert(self->depth == 0);
>> +	self->sep = '\0';
>> +}
>> +
>>   /* Basic blocks */
>>   static void jsonw_begin(json_writer_t *self, int c)
>>   {
>> diff --git a/tools/bpf/bpftool/json_writer.h b/tools/bpf/bpftool/json_writer.h
>> index 35cf1f00f96c..8ace65cdb92f 100644
>> --- a/tools/bpf/bpftool/json_writer.h
>> +++ b/tools/bpf/bpftool/json_writer.h
>> @@ -27,6 +27,9 @@ void jsonw_destroy(json_writer_t **self_p);
>>   /* Cause output to have pretty whitespace */
>>   void jsonw_pretty(json_writer_t *self, bool on);
>>   
>> +/* Reset separator to create new JSON */
>> +void jsonw_reset(json_writer_t *self);
>> +
>>   /* Add property name */
>>   void jsonw_name(json_writer_t *self, const char *name);
>>   
>> diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c
>> index 4a191fcbeb82..a681d568cfa7 100644
>> --- a/tools/bpf/bpftool/main.c
>> +++ b/tools/bpf/bpftool/main.c
>> @@ -28,6 +28,7 @@ bool show_pinned;
>>   bool block_mount;
>>   bool verifier_logs;
>>   bool relaxed_maps;
>> +bool dump_metadata;
>>   struct pinned_obj_table prog_table;
>>   struct pinned_obj_table map_table;
>>   struct pinned_obj_table link_table;
>> @@ -351,6 +352,10 @@ static int do_batch(int argc, char **argv)
>>   	return err;
>>   }
>>   
>> +enum bpftool_longonly_opts {
>> +	OPT_METADATA = 256,
>> +};
>> +
>>   int main(int argc, char **argv)
>>   {
>>   	static const struct option options[] = {
>> @@ -362,6 +367,7 @@ int main(int argc, char **argv)
>>   		{ "mapcompat",	no_argument,	NULL,	'm' },
>>   		{ "nomount",	no_argument,	NULL,	'n' },
>>   		{ "debug",	no_argument,	NULL,	'd' },
>> +		{ "metadata",	no_argument,	NULL,	OPT_METADATA },
>>   		{ 0 }
>>   	};
>>   	int opt, ret;
>> @@ -371,6 +377,7 @@ int main(int argc, char **argv)
>>   	json_output = false;
>>   	show_pinned = false;
>>   	block_mount = false;
>> +	dump_metadata = false;
>>   	bin_name = argv[0];
>>   
>>   	hash_init(prog_table.table);
>> @@ -412,6 +419,9 @@ int main(int argc, char **argv)
>>   			libbpf_set_print(print_all_levels);
>>   			verifier_logs = true;
>>   			break;
>> +		case OPT_METADATA:
>> +			dump_metadata = true;
>> +			break;
>>   		default:
>>   			p_err("unrecognized option '%s'", argv[optind - 1]);
>>   			if (json_output)
>> diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h
>> index c46e52137b87..8750758e9150 100644
>> --- a/tools/bpf/bpftool/main.h
>> +++ b/tools/bpf/bpftool/main.h
>> @@ -90,6 +90,7 @@ extern bool show_pids;
>>   extern bool block_mount;
>>   extern bool verifier_logs;
>>   extern bool relaxed_maps;
>> +extern bool dump_metadata;
>>   extern struct pinned_obj_table prog_table;
>>   extern struct pinned_obj_table map_table;
>>   extern struct pinned_obj_table link_table;
>> diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
>> index d393eb8263a6..ee767b8d90fb 100644
>> --- a/tools/bpf/bpftool/prog.c
>> +++ b/tools/bpf/bpftool/prog.c
>> @@ -151,6 +151,135 @@ static void show_prog_maps(int fd, __u32 num_maps)
>>   	}
>>   }
>>   
>> +static void show_prog_metadata(int fd, __u32 num_maps)
>> +{
>> +	struct bpf_prog_info prog_info = {};
>> +	struct bpf_map_info map_info = {};
>> +	__u32 prog_info_len = sizeof(prog_info);
>> +	__u32 map_info_len = sizeof(map_info);
>> +	__u32 map_ids[num_maps];
>> +	void *value = NULL;
>> +	struct btf *btf = NULL;
>> +	const struct btf_type *t_datasec, *t_var;
>> +	struct btf_var_secinfo *vsi;
>> +	int key = 0;
>> +	unsigned int i, vlen;
>> +	int map_fd;
>> +	int err;
>
> try to follow reverse christmas tree coding styple?
>
>> +
>> +	prog_info.nr_map_ids = num_maps;
>> +	prog_info.map_ids = ptr_to_u64(map_ids);
>> +
>> +	err = bpf_obj_get_info_by_fd(fd, &prog_info, &prog_info_len);
>> +	if (err || !prog_info.nr_map_ids)
>> +		return;
>
> print out something for "err" case and "!prog_info.nr_map_ids" case?
> The same for some other below returns.
>
>> +
>> +	for (i = 0; i < prog_info.nr_map_ids; i++) {
>> +		map_fd = bpf_map_get_fd_by_id(map_ids[i]);
>> +		if (map_fd < 0)
>> +			return;
>> +
>> +		err = bpf_obj_get_info_by_fd(map_fd, &map_info, &map_info_len);
>> +		if (err)
>> +			goto out_close;
>> +
>> +		if (map_info.type != BPF_MAP_TYPE_ARRAY)
>> +			goto next_map;
>> +		if (map_info.key_size != sizeof(int))
>> +			goto next_map;
>> +		if (map_info.max_entries != 1)
>> +			goto next_map;
>> +		if (!map_info.btf_value_type_id)
>> +			goto next_map;
>> +		if (!strstr(map_info.name, ".metadata"))
>> +			goto next_map;
>> +
>> +		goto found;
>> +
>> +next_map:
>> +		close(map_fd);
>> +	}
>> +
>> +	return;
>> +
>> +found:
>> +	value = malloc(map_info.value_size);
>> +	if (!value)
>> +		goto out_close;
>> +
>> +	if (bpf_map_lookup_elem(map_fd, &key, value))
>> +		goto out_free;
>
> Not sure whether we need formal libbpf API to access metadata or not.
> This may help other applications too. But we can delay until it is
> necessary.

Yeah, please put in a libbpf accessor as well; I would like to use this
from libxdp - without a skeleton :)

-Toke




[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux