diff options
Diffstat (limited to 'tools/bpf')
| -rw-r--r-- | tools/bpf/bpftool/Documentation/bpftool-map.rst | 5 | ||||
| -rw-r--r-- | tools/bpf/bpftool/Documentation/bpftool-prog.rst | 5 | ||||
| -rw-r--r-- | tools/bpf/bpftool/common.c | 97 | ||||
| -rw-r--r-- | tools/bpf/bpftool/main.c | 18 | ||||
| -rw-r--r-- | tools/bpf/bpftool/main.h | 21 | ||||
| -rw-r--r-- | tools/bpf/bpftool/map.c | 22 | ||||
| -rw-r--r-- | tools/bpf/bpftool/prog.c | 25 | 
7 files changed, 187 insertions, 6 deletions
diff --git a/tools/bpf/bpftool/Documentation/bpftool-map.rst b/tools/bpf/bpftool/Documentation/bpftool-map.rst index abb9ee940b15..9f51a268eb06 100644 --- a/tools/bpf/bpftool/Documentation/bpftool-map.rst +++ b/tools/bpf/bpftool/Documentation/bpftool-map.rst @@ -12,7 +12,7 @@ SYNOPSIS  	**bpftool** [*OPTIONS*] **map** *COMMAND* -	*OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] } +	*OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] | { **-f** | **--bpffs** } }  	*COMMANDS* :=  	{ **show** | **dump** | **update** | **lookup** | **getnext** | **delete** @@ -86,6 +86,9 @@ OPTIONS  	-p, --pretty  		  Generate human-readable JSON output. Implies **-j**. +	-f, --bpffs +		  Show file names of pinned maps. +  EXAMPLES  ========  **# bpftool map show** diff --git a/tools/bpf/bpftool/Documentation/bpftool-prog.rst b/tools/bpf/bpftool/Documentation/bpftool-prog.rst index 0f25d3c39e05..36e8d1c3c40d 100644 --- a/tools/bpf/bpftool/Documentation/bpftool-prog.rst +++ b/tools/bpf/bpftool/Documentation/bpftool-prog.rst @@ -12,7 +12,7 @@ SYNOPSIS  	**bpftool** [*OPTIONS*] **prog** *COMMAND* -	*OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] } +	*OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] | { **-f** | **--bpffs** } }  	*COMMANDS* :=  	{ **show** | **dump xlated** | **dump jited** | **pin** | **help** } @@ -75,6 +75,9 @@ OPTIONS  	-p, --pretty  		  Generate human-readable JSON output. Implies **-j**. +	-f, --bpffs +		  Show file names of pinned programs. +  EXAMPLES  ========  **# bpftool prog show** diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c index aa7017098b2a..2bd3b280e6dd 100644 --- a/tools/bpf/bpftool/common.c +++ b/tools/bpf/bpftool/common.c @@ -34,7 +34,9 @@  /* Author: Jakub Kicinski <kubakici@wp.pl> */  #include <errno.h> +#include <fts.h>  #include <libgen.h> +#include <mntent.h>  #include <stdbool.h>  #include <stdio.h>  #include <stdlib.h> @@ -122,9 +124,8 @@ static int mnt_bpffs(const char *target, char *buff, size_t bufflen)  	return 0;  } -int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type) +int open_obj_pinned(char *path)  { -	enum bpf_obj_type type;  	int fd;  	fd = bpf_obj_get(path); @@ -136,6 +137,18 @@ int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type)  		return -1;  	} +	return fd; +} + +int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type) +{ +	enum bpf_obj_type type; +	int fd; + +	fd = open_obj_pinned(path); +	if (fd < 0) +		return -1; +  	type = get_fd_type(fd);  	if (type < 0) {  		close(fd); @@ -310,3 +323,83 @@ void print_hex_data_json(uint8_t *data, size_t len)  		jsonw_printf(json_wtr, "\"0x%02hhx\"", data[i]);  	jsonw_end_array(json_wtr);  } + +int build_pinned_obj_table(struct pinned_obj_table *tab, +			   enum bpf_obj_type type) +{ +	struct bpf_prog_info pinned_info = {}; +	struct pinned_obj *obj_node = NULL; +	__u32 len = sizeof(pinned_info); +	struct mntent *mntent = NULL; +	enum bpf_obj_type objtype; +	FILE *mntfile = NULL; +	FTSENT *ftse = NULL; +	FTS *fts = NULL; +	int fd, err; + +	mntfile = setmntent("/proc/mounts", "r"); +	if (!mntfile) +		return -1; + +	while ((mntent = getmntent(mntfile))) { +		char *path[] = { mntent->mnt_dir, NULL }; + +		if (strncmp(mntent->mnt_type, "bpf", 3) != 0) +			continue; + +		fts = fts_open(path, 0, NULL); +		if (!fts) +			continue; + +		while ((ftse = fts_read(fts))) { +			if (!(ftse->fts_info & FTS_F)) +				continue; +			fd = open_obj_pinned(ftse->fts_path); +			if (fd < 0) +				continue; + +			objtype = get_fd_type(fd); +			if (objtype != type) { +				close(fd); +				continue; +			} +			memset(&pinned_info, 0, sizeof(pinned_info)); +			err = bpf_obj_get_info_by_fd(fd, &pinned_info, &len); +			if (err) { +				close(fd); +				continue; +			} + +			obj_node = malloc(sizeof(*obj_node)); +			if (!obj_node) { +				close(fd); +				fts_close(fts); +				fclose(mntfile); +				return -1; +			} + +			memset(obj_node, 0, sizeof(*obj_node)); +			obj_node->id = pinned_info.id; +			obj_node->path = strdup(ftse->fts_path); +			hash_add(tab->table, &obj_node->hash, obj_node->id); + +			close(fd); +		} +		fts_close(fts); +	} +	fclose(mntfile); +	return 0; +} + +void delete_pinned_obj_table(struct pinned_obj_table *tab) +{ +	struct pinned_obj *obj; +	struct hlist_node *tmp; +	unsigned int bkt; + +	hash_for_each_safe(tab->table, bkt, tmp, obj, hash) { +		hash_del(&obj->hash); +		free(obj->path); +		free(obj); +	} +} diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c index 78d9afb74ef4..d6e4762170a4 100644 --- a/tools/bpf/bpftool/main.c +++ b/tools/bpf/bpftool/main.c @@ -54,6 +54,9 @@ static int (*last_do_help)(int argc, char **argv);  json_writer_t *json_wtr;  bool pretty_output;  bool json_output; +bool show_pinned; +struct pinned_obj_table prog_table; +struct pinned_obj_table map_table;  void usage(void)  { @@ -263,6 +266,7 @@ int main(int argc, char **argv)  		{ "help",	no_argument,	NULL,	'h' },  		{ "pretty",	no_argument,	NULL,	'p' },  		{ "version",	no_argument,	NULL,	'V' }, +		{ "bpffs",	no_argument,	NULL,	'f' },  		{ 0 }  	};  	int opt, ret; @@ -270,9 +274,13 @@ int main(int argc, char **argv)  	last_do_help = do_help;  	pretty_output = false;  	json_output = false; +	show_pinned = false;  	bin_name = argv[0]; -	while ((opt = getopt_long(argc, argv, "Vhpj", +	hash_init(prog_table.table); +	hash_init(map_table.table); + +	while ((opt = getopt_long(argc, argv, "Vhpjf",  				  options, NULL)) >= 0) {  		switch (opt) {  		case 'V': @@ -285,6 +293,9 @@ int main(int argc, char **argv)  		case 'j':  			json_output = true;  			break; +		case 'f': +			show_pinned = true; +			break;  		default:  			usage();  		} @@ -311,5 +322,10 @@ int main(int argc, char **argv)  	if (json_output)  		jsonw_destroy(&json_wtr); +	if (show_pinned) { +		delete_pinned_obj_table(&prog_table); +		delete_pinned_obj_table(&map_table); +	} +  	return ret;  } diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h index ff5ad05b137b..9c191e222d6f 100644 --- a/tools/bpf/bpftool/main.h +++ b/tools/bpf/bpftool/main.h @@ -42,6 +42,7 @@  #include <stdio.h>  #include <linux/bpf.h>  #include <linux/kernel.h> +#include <linux/hashtable.h>  #include "json_writer.h" @@ -58,7 +59,7 @@  #define HELP_SPEC_PROGRAM						\  	"PROG := { id PROG_ID | pinned FILE | tag PROG_TAG }"  #define HELP_SPEC_OPTIONS						\ -	"OPTIONS := { {-j|--json} [{-p|--pretty}] }" +	"OPTIONS := { {-j|--json} [{-p|--pretty}] | {-f|--bpffs} }"  enum bpf_obj_type {  	BPF_OBJ_UNKNOWN, @@ -70,6 +71,9 @@ extern const char *bin_name;  extern json_writer_t *json_wtr;  extern bool json_output; +extern bool show_pinned; +extern struct pinned_obj_table prog_table; +extern struct pinned_obj_table map_table;  void p_err(const char *fmt, ...);  void p_info(const char *fmt, ...); @@ -78,6 +82,20 @@ bool is_prefix(const char *pfx, const char *str);  void fprint_hex(FILE *f, void *arg, unsigned int n, const char *sep);  void usage(void) __attribute__((noreturn)); +struct pinned_obj_table { +	DECLARE_HASHTABLE(table, 16); +}; + +struct pinned_obj { +	__u32 id; +	char *path; +	struct hlist_node hash; +}; + +int build_pinned_obj_table(struct pinned_obj_table *table, +			   enum bpf_obj_type type); +void delete_pinned_obj_table(struct pinned_obj_table *tab); +  struct cmd {  	const char *cmd;  	int (*func)(int argc, char **argv); @@ -89,6 +107,7 @@ int cmd_select(const struct cmd *cmds, int argc, char **argv,  int get_fd_type(int fd);  const char *get_fd_type_name(enum bpf_obj_type type);  char *get_fdinfo(int fd, const char *key); +int open_obj_pinned(char *path);  int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type);  int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32)); diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c index e978ab23a77f..e2450c8e88e6 100644 --- a/tools/bpf/bpftool/map.c +++ b/tools/bpf/bpftool/map.c @@ -436,6 +436,18 @@ static int show_map_close_json(int fd, struct bpf_map_info *info)  		jsonw_int_field(json_wtr, "bytes_memlock", atoi(memlock));  	free(memlock); +	if (!hash_empty(map_table.table)) { +		struct pinned_obj *obj; + +		jsonw_name(json_wtr, "pinned"); +		jsonw_start_array(json_wtr); +		hash_for_each_possible(map_table.table, obj, hash, info->id) { +			if (obj->id == info->id) +				jsonw_string(json_wtr, obj->path); +		} +		jsonw_end_array(json_wtr); +	} +  	jsonw_end_object(json_wtr);  	return 0; @@ -466,7 +478,14 @@ static int show_map_close_plain(int fd, struct bpf_map_info *info)  	free(memlock);  	printf("\n"); +	if (!hash_empty(map_table.table)) { +		struct pinned_obj *obj; +		hash_for_each_possible(map_table.table, obj, hash, info->id) { +			if (obj->id == info->id) +				printf("\tpinned %s\n", obj->path); +		} +	}  	return 0;  } @@ -478,6 +497,9 @@ static int do_show(int argc, char **argv)  	int err;  	int fd; +	if (show_pinned) +		build_pinned_obj_table(&map_table, BPF_OBJ_MAP); +  	if (argc == 2) {  		fd = map_parse_fd_and_info(&argc, &argv, &info, &len);  		if (fd < 0) diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c index d3ab808dc882..f45c44ef9bec 100644 --- a/tools/bpf/bpftool/prog.c +++ b/tools/bpf/bpftool/prog.c @@ -272,6 +272,18 @@ static void print_prog_json(struct bpf_prog_info *info, int fd)  	if (info->nr_map_ids)  		show_prog_maps(fd, info->nr_map_ids); +	if (!hash_empty(prog_table.table)) { +		struct pinned_obj *obj; + +		jsonw_name(json_wtr, "pinned"); +		jsonw_start_array(json_wtr); +		hash_for_each_possible(prog_table.table, obj, hash, info->id) { +			if (obj->id == info->id) +				jsonw_string(json_wtr, obj->path); +		} +		jsonw_end_array(json_wtr); +	} +  	jsonw_end_object(json_wtr);  } @@ -331,6 +343,16 @@ static void print_prog_plain(struct bpf_prog_info *info, int fd)  	if (info->nr_map_ids)  		show_prog_maps(fd, info->nr_map_ids); +	if (!hash_empty(prog_table.table)) { +		struct pinned_obj *obj; + +		printf("\n"); +		hash_for_each_possible(prog_table.table, obj, hash, info->id) { +			if (obj->id == info->id) +				printf("\tpinned %s\n", obj->path); +		} +	} +  	printf("\n");  } @@ -360,6 +382,9 @@ static int do_show(int argc, char **argv)  	int err;  	int fd; +	if (show_pinned) +		build_pinned_obj_table(&prog_table, BPF_OBJ_PROG); +  	if (argc == 2) {  		fd = prog_parse_fd(&argc, &argv);  		if (fd < 0)  | 
