Commit 2e98964b authored by Daniel Müller's avatar Daniel Müller Committed by Andrii Nakryiko
Browse files

bpftool: Use libbpf_bpf_map_type_str



This change switches bpftool over to using the recently introduced
libbpf_bpf_map_type_str function instead of maintaining its own string
representation for the bpf_map_type enum.

Signed-off-by: default avatarDaniel Müller <deso@posteo.net>
Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Acked-by: default avatarQuentin Monnet <quentin@isovalent.com>
Link: https://lore.kernel.org/bpf/20220523230428.3077108-7-deso@posteo.net
parent c3a25740
Loading
Loading
Loading
Loading
+17 −13
Original line number Diff line number Diff line
@@ -615,8 +615,8 @@ static bool probe_map_type_ifindex(enum bpf_map_type map_type, __u32 ifindex)
}

static void
probe_map_type(enum bpf_map_type map_type, const char *define_prefix,
	       __u32 ifindex)
probe_map_type(enum bpf_map_type map_type, char const *map_type_str,
	       const char *define_prefix, __u32 ifindex)
{
	char feat_name[128], plain_desc[128], define_name[128];
	const char *plain_comment = "eBPF map_type ";
@@ -641,20 +641,16 @@ probe_map_type(enum bpf_map_type map_type, const char *define_prefix,
	 * check required for unprivileged users
	 */

	if (!map_type_name[map_type]) {
		p_info("map type name not found (type %d)", map_type);
		return;
	}
	maxlen = sizeof(plain_desc) - strlen(plain_comment) - 1;
	if (strlen(map_type_name[map_type]) > maxlen) {
	if (strlen(map_type_str) > maxlen) {
		p_info("map type name too long");
		return;
	}

	sprintf(feat_name, "have_%s_map_type", map_type_name[map_type]);
	sprintf(define_name, "%s_map_type", map_type_name[map_type]);
	sprintf(feat_name, "have_%s_map_type", map_type_str);
	sprintf(define_name, "%s_map_type", map_type_str);
	uppercase(define_name, sizeof(define_name));
	sprintf(plain_desc, "%s%s", plain_comment, map_type_name[map_type]);
	sprintf(plain_desc, "%s%s", plain_comment, map_type_str);
	print_bool_feature(feat_name, plain_desc, define_name, res,
			   define_prefix);
}
@@ -963,15 +959,23 @@ section_program_types(bool *supported_types, const char *define_prefix,

static void section_map_types(const char *define_prefix, __u32 ifindex)
{
	unsigned int i;
	unsigned int map_type = BPF_MAP_TYPE_UNSPEC;
	const char *map_type_str;

	print_start_section("map_types",
			    "Scanning eBPF map types...",
			    "/*** eBPF map types ***/",
			    define_prefix);

	for (i = BPF_MAP_TYPE_UNSPEC + 1; i < map_type_name_size; i++)
		probe_map_type(i, define_prefix, ifindex);
	while (true) {
		map_type++;
		map_type_str = libbpf_bpf_map_type_str(map_type);
		/* libbpf will return NULL for variants unknown to it. */
		if (!map_type_str)
			break;

		probe_map_type(map_type, map_type_str, define_prefix, ifindex);
	}

	print_end_section();
}
+0 −3
Original line number Diff line number Diff line
@@ -65,9 +65,6 @@ static inline void *u64_to_ptr(__u64 ptr)

extern const char * const attach_type_name[__MAX_BPF_ATTACH_TYPE];

extern const char * const map_type_name[];
extern const size_t map_type_name_size;

/* keep in sync with the definition in skeleton/pid_iter.bpf.c */
enum bpf_obj_type {
	BPF_OBJ_UNKNOWN,
+25 −44
Original line number Diff line number Diff line
@@ -22,42 +22,6 @@
#include "json_writer.h"
#include "main.h"

const char * const map_type_name[] = {
	[BPF_MAP_TYPE_UNSPEC]			= "unspec",
	[BPF_MAP_TYPE_HASH]			= "hash",
	[BPF_MAP_TYPE_ARRAY]			= "array",
	[BPF_MAP_TYPE_PROG_ARRAY]		= "prog_array",
	[BPF_MAP_TYPE_PERF_EVENT_ARRAY]		= "perf_event_array",
	[BPF_MAP_TYPE_PERCPU_HASH]		= "percpu_hash",
	[BPF_MAP_TYPE_PERCPU_ARRAY]		= "percpu_array",
	[BPF_MAP_TYPE_STACK_TRACE]		= "stack_trace",
	[BPF_MAP_TYPE_CGROUP_ARRAY]		= "cgroup_array",
	[BPF_MAP_TYPE_LRU_HASH]			= "lru_hash",
	[BPF_MAP_TYPE_LRU_PERCPU_HASH]		= "lru_percpu_hash",
	[BPF_MAP_TYPE_LPM_TRIE]			= "lpm_trie",
	[BPF_MAP_TYPE_ARRAY_OF_MAPS]		= "array_of_maps",
	[BPF_MAP_TYPE_HASH_OF_MAPS]		= "hash_of_maps",
	[BPF_MAP_TYPE_DEVMAP]			= "devmap",
	[BPF_MAP_TYPE_DEVMAP_HASH]		= "devmap_hash",
	[BPF_MAP_TYPE_SOCKMAP]			= "sockmap",
	[BPF_MAP_TYPE_CPUMAP]			= "cpumap",
	[BPF_MAP_TYPE_XSKMAP]			= "xskmap",
	[BPF_MAP_TYPE_SOCKHASH]			= "sockhash",
	[BPF_MAP_TYPE_CGROUP_STORAGE]		= "cgroup_storage",
	[BPF_MAP_TYPE_REUSEPORT_SOCKARRAY]	= "reuseport_sockarray",
	[BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE]	= "percpu_cgroup_storage",
	[BPF_MAP_TYPE_QUEUE]			= "queue",
	[BPF_MAP_TYPE_STACK]			= "stack",
	[BPF_MAP_TYPE_SK_STORAGE]		= "sk_storage",
	[BPF_MAP_TYPE_STRUCT_OPS]		= "struct_ops",
	[BPF_MAP_TYPE_RINGBUF]			= "ringbuf",
	[BPF_MAP_TYPE_INODE_STORAGE]		= "inode_storage",
	[BPF_MAP_TYPE_TASK_STORAGE]		= "task_storage",
	[BPF_MAP_TYPE_BLOOM_FILTER]		= "bloom_filter",
};

const size_t map_type_name_size = ARRAY_SIZE(map_type_name);

static struct hashmap *map_table;

static bool map_is_per_cpu(__u32 type)
@@ -81,12 +45,18 @@ static bool map_is_map_of_progs(__u32 type)

static int map_type_from_str(const char *type)
{
	const char *map_type_str;
	unsigned int i;

	for (i = 0; i < ARRAY_SIZE(map_type_name); i++)
	for (i = 0; ; i++) {
		map_type_str = libbpf_bpf_map_type_str(i);
		if (!map_type_str)
			break;

		/* Don't allow prefixing in case of possible future shadowing */
		if (map_type_name[i] && !strcmp(map_type_name[i], type))
		if (!strcmp(map_type_str, type))
			return i;
	}
	return -1;
}

@@ -472,9 +442,12 @@ static int parse_elem(char **argv, struct bpf_map_info *info,

static void show_map_header_json(struct bpf_map_info *info, json_writer_t *wtr)
{
	const char *map_type_str;

	jsonw_uint_field(wtr, "id", info->id);
	if (info->type < ARRAY_SIZE(map_type_name))
		jsonw_string_field(wtr, "type", map_type_name[info->type]);
	map_type_str = libbpf_bpf_map_type_str(info->type);
	if (map_type_str)
		jsonw_string_field(wtr, "type", map_type_str);
	else
		jsonw_uint_field(wtr, "type", info->type);

@@ -561,9 +534,13 @@ static int show_map_close_json(int fd, struct bpf_map_info *info)

static void show_map_header_plain(struct bpf_map_info *info)
{
	const char *map_type_str;

	printf("%u: ", info->id);
	if (info->type < ARRAY_SIZE(map_type_name))
		printf("%s  ", map_type_name[info->type]);

	map_type_str = libbpf_bpf_map_type_str(info->type);
	if (map_type_str)
		printf("%s  ", map_type_str);
	else
		printf("type %u  ", info->type);

@@ -879,9 +856,13 @@ map_dump(int fd, struct bpf_map_info *info, json_writer_t *wtr,
	}

	if (info->type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY &&
	    info->value_size != 8)
	    info->value_size != 8) {
		const char *map_type_str;

		map_type_str = libbpf_bpf_map_type_str(info->type);
		p_info("Warning: cannot read values from %s map with value_size != 8",
		       map_type_name[info->type]);
		       map_type_str);
	}
	while (true) {
		err = bpf_map_get_next_key(fd, prev_key, key);
		if (err) {
+29 −19
Original line number Diff line number Diff line
@@ -186,6 +186,27 @@ class FileExtractor(object):
        parser.search_block(start_marker)
        return parser.parse(pattern, end_marker)

    def make_enum_map(self, names, enum_prefix):
        """
        Search for and parse an enum containing BPF_* members, just as get_enum
        does. However, instead of just returning a set of the variant names,
        also generate a textual representation from them by (assuming and)
        removing a provided prefix and lowercasing the remainder. Then return a
        dict mapping from name to textual representation.

        @enum_values: a set of enum values; e.g., as retrieved by get_enum
        @enum_prefix: the prefix to remove from each of the variants to infer
        textual representation
        """
        mapping = {}
        for name in names:
            if not name.startswith(enum_prefix):
                raise Exception(f"enum variant {name} does not start with {enum_prefix}")
            text = name[len(enum_prefix):].lower()
            mapping[name] = text

        return mapping

    def __get_description_list(self, start_marker, pattern, end_marker):
        parser = InlineListParser(self.reader)
        parser.search_block(start_marker)
@@ -345,9 +366,6 @@ class MapFileExtractor(SourceFileExtractor):
    """
    filename = os.path.join(BPFTOOL_DIR, 'map.c')

    def get_map_types(self):
        return self.get_types_from_array('map_type_name')

    def get_map_help(self):
        return self.get_help_list('TYPE')

@@ -403,8 +421,9 @@ class BpfHeaderExtractor(FileExtractor):
    def get_prog_types(self):
        return self.get_enum('bpf_prog_type')

    def get_map_types(self):
        return self.get_enum('bpf_map_type')
    def get_map_type_map(self):
        names = self.get_enum('bpf_map_type')
        return self.make_enum_map(names, 'BPF_MAP_TYPE_')

    def get_attach_types(self):
        return self.get_enum('bpf_attach_type')
@@ -492,21 +511,12 @@ def main():
    """)
    args = argParser.parse_args()

    # Map types (enum)

    bpf_info = BpfHeaderExtractor()
    ref = bpf_info.get_map_types()

    map_info = MapFileExtractor()
    source_map_items = map_info.get_map_types()
    map_types_enum = set(source_map_items.keys())

    verify(ref, map_types_enum,
            f'Comparing BPF header (enum bpf_map_type) and {MapFileExtractor.filename} (map_type_name):')

    # Map types (names)

    source_map_types = set(source_map_items.values())
    map_info = MapFileExtractor()
    source_map_types = set(bpf_info.get_map_type_map().values())
    source_map_types.discard('unspec')

    help_map_types = map_info.get_map_help()
@@ -522,13 +532,13 @@ def main():
    bashcomp_map_types = bashcomp_info.get_map_types()

    verify(source_map_types, help_map_types,
            f'Comparing {MapFileExtractor.filename} (map_type_name) and {MapFileExtractor.filename} (do_help() TYPE):')
            f'Comparing {BpfHeaderExtractor.filename} (bpf_map_type) and {MapFileExtractor.filename} (do_help() TYPE):')
    verify(source_map_types, man_map_types,
            f'Comparing {MapFileExtractor.filename} (map_type_name) and {ManMapExtractor.filename} (TYPE):')
            f'Comparing {BpfHeaderExtractor.filename} (bpf_map_type) and {ManMapExtractor.filename} (TYPE):')
    verify(help_map_options, man_map_options,
            f'Comparing {MapFileExtractor.filename} (do_help() OPTIONS) and {ManMapExtractor.filename} (OPTIONS):')
    verify(source_map_types, bashcomp_map_types,
            f'Comparing {MapFileExtractor.filename} (map_type_name) and {BashcompExtractor.filename} (BPFTOOL_MAP_CREATE_TYPES):')
            f'Comparing {BpfHeaderExtractor.filename} (bpf_map_type) and {BashcompExtractor.filename} (BPFTOOL_MAP_CREATE_TYPES):')

    # Attach types (enum)