From 1ecb3513093ef4e40fdd27da479bc8ef844df3eb Mon Sep 17 00:00:00 2001 From: Lianbo Jiang Date: Mon, 14 Feb 2022 16:59:10 +0800 Subject: [PATCH] Fix for "bpf -m|-M" options to appropriately display MEMLOCK and UID Kernel commit 80ee81e0403c ("bpf: Eliminate rlimit-based memory accounting infra for bpf maps") removed the struct bpf_map_memory member from struct bpf_map at Linux 5.11. Without the patch, the "bpf -m|-M" options will print "(unknown)" for MEMLOCK and UID: crash> bpf -m 1 ID BPF_MAP BPF_MAP_TYPE MAP_FLAGS 1 ffff96ba41804400 ARRAY 00000000 KEY_SIZE: 4 VALUE_SIZE: 8 MAX_ENTRIES: 64 MEMLOCK: (unknown) NAME: "dist" UID: (unknown) Signed-off-by: Lianbo Jiang Signed-off-by: Kazuhito Hagio --- bpf.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 4 deletions(-) diff --git a/bpf.c b/bpf.c index cb6b0ed..466b244 100644 --- a/bpf.c +++ b/bpf.c @@ -63,6 +63,64 @@ static int do_old_idr(int, ulong, struct list_pair *); #define PROG_VERBOSE (0x40) #define MAP_VERBOSE (0x80) +static int map_is_per_cpu(int type) +{ + +/* See the definition of bpf_map_type: include/uapi/linux/bpf.h */ +#define BPF_MAP_TYPE_PERCPU_HASH (5UL) +#define BPF_MAP_TYPE_PERCPU_ARRAY (6UL) +#define BPF_MAP_TYPE_LRU_PERCPU_HASH (10UL) +#define BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE (21UL) + + return type == BPF_MAP_TYPE_PERCPU_HASH || + type == BPF_MAP_TYPE_PERCPU_ARRAY || + type == BPF_MAP_TYPE_LRU_PERCPU_HASH || + type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE; +} + +static int map_is_fd_map(int type) +{ + +/* See the definition of bpf_map_type: include/uapi/linux/bpf.h */ +#define BPF_MAP_TYPE_PROG_ARRAY (3UL) +#define BPF_MAP_TYPE_PERF_EVENT_ARRAY (4UL) +#define BPF_MAP_TYPE_CGROUP_ARRAY (8UL) +#define BPF_MAP_TYPE_ARRAY_OF_MAPS (12UL) +#define BPF_MAP_TYPE_HASH_OF_MAPS (13UL) + + return type == BPF_MAP_TYPE_PROG_ARRAY || + type == BPF_MAP_TYPE_PERF_EVENT_ARRAY || + type == BPF_MAP_TYPE_CGROUP_ARRAY || + type == BPF_MAP_TYPE_ARRAY_OF_MAPS || + type == BPF_MAP_TYPE_HASH_OF_MAPS; + +} + +static ulong bpf_map_memory_size(int map_type, uint value_size, + uint key_size, uint max_entries) +{ + ulong size; + uint valsize; + int cpus = 0; + + if (map_is_per_cpu(map_type)) { + cpus = get_cpus_possible(); + if (!cpus) { + error(WARNING, "cpu_possible_map does not exist, possible cpus: %d\n", cpus); + return 0; + } + + valsize = roundup(value_size, 8) * cpus; + } else if (map_is_fd_map(map_type)) + valsize = sizeof(uint); + else + valsize = value_size; + + size = roundup((key_size + valsize), 8); + + return roundup((max_entries * size), PAGESIZE()); +} + void cmd_bpf(void) { @@ -332,7 +390,7 @@ do_bpf(ulong flags, ulong prog_id, ulong map_id, int radix) { struct bpf_info *bpf; int i, c, found, entries, type; - uint uid, map_pages, key_size, value_size, max_entries; + uint uid, map_pages, key_size = 0, value_size = 0, max_entries = 0; ulong bpf_prog_aux, bpf_func, end_func, addr, insnsi, user; ulong do_progs, do_maps; ulonglong load_time; @@ -572,6 +630,8 @@ do_map_only: fprintf(fp, "\n"); if (flags & (MAP_ID|MAP_VERBOSE)) { + ulong msize = 0; + fprintf(fp, " KEY_SIZE: "); if (VALID_MEMBER(bpf_map_key_size)) { key_size = UINT(bpf->bpf_map_buf + OFFSET(bpf_map_key_size)); @@ -602,8 +662,10 @@ do_map_only: } else if (VALID_MEMBER(bpf_map_pages)) { map_pages = UINT(bpf->bpf_map_buf + OFFSET(bpf_map_pages)); fprintf(fp, "%d\n", map_pages * PAGESIZE()); - } else - fprintf(fp, "(unknown)\n"); + } else if ((msize = bpf_map_memory_size(type, value_size, key_size, max_entries))) + fprintf(fp, "%ld\n", msize); + else + fprintf(fp, "(unknown)"); fprintf(fp, " NAME: "); if (VALID_MEMBER(bpf_map_name)) { @@ -632,7 +694,7 @@ do_map_only: else fprintf(fp, "(unknown)\n"); } else - fprintf(fp, "(unknown)\n"); + fprintf(fp, "(unused)\n"); } if (flags & DUMP_STRUCT) {