Some BPF commands return ENOTSUPP (524) to user space: iterating local storage maps, element operations on ringbuf maps, creating an LRU hash map without preallocation, freezing a struct_ops map, or running a program type that has no test_run. ENOTSUPP is kernel internal, so strerror() only gives "Unknown error 524":
# bpftool map getnext pinned /sys/fs/bpf/sk_storage Error: can't get next key: Unknown error 524 Add a small helper that knows ENOTSUPP and use it where bpftool prints the error of map create, map element operations, map freeze and prog run. Suggested-by: Daniel Borkmann <[email protected]> Assisted-by: LLM Signed-off-by: Maxim Skokov <[email protected]> --- tools/bpf/bpftool/common.c | 11 +++++++++++ tools/bpf/bpftool/main.h | 1 + tools/bpf/bpftool/map.c | 18 +++++++++--------- tools/bpf/bpftool/prog.c | 2 +- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c index f9b87efa7c9a7..ca5fa2f0bf9b1 100644 --- a/tools/bpf/bpftool/common.c +++ b/tools/bpf/bpftool/common.c @@ -72,6 +72,17 @@ void p_info(const char *fmt, ...) va_end(ap); } +/* + * Like strerror(), but also knows ENOTSUPP (524), which the kernel returns + * to user space from some BPF commands although it is not a userspace errno. + */ +const char *bpf_strerror(int err) +{ + if (err == 524 /* ENOTSUPP */) + return "Operation not supported"; + return strerror(err); +} + static bool is_bpffs(const char *path) { struct statfs st_fs; diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h index 6851346a60305..b1eb4b5d991b8 100644 --- a/tools/bpf/bpftool/main.h +++ b/tools/bpf/bpftool/main.h @@ -98,6 +98,7 @@ extern const char *cert_path; void __printf(1, 2) p_err(const char *fmt, ...); void __printf(1, 2) p_info(const char *fmt, ...); +const char *bpf_strerror(int err); bool is_prefix(const char *pfx, const char *str); int detect_common_prefix(const char *arg, ...); diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c index 20d59eab09a12..d809b075e734f 100644 --- a/tools/bpf/bpftool/map.c +++ b/tools/bpf/bpftool/map.c @@ -228,7 +228,7 @@ print_entry_error(struct bpf_map_info *map_info, void *key, int lookup_errno) print_hex_data_json(key, map_info->key_size); jsonw_name(json_wtr, "value"); jsonw_start_object(json_wtr); /* error */ - jsonw_string_field(json_wtr, "error", strerror(lookup_errno)); + jsonw_string_field(json_wtr, "error", bpf_strerror(lookup_errno)); jsonw_end_object(json_wtr); /* error */ jsonw_end_object(json_wtr); /* entry */ } else { @@ -241,7 +241,7 @@ print_entry_error(struct bpf_map_info *map_info, void *key, int lookup_errno) msg = "<cannot read>"; print_entry_error_msg(map_info, key, - msg ? : strerror(lookup_errno)); + msg ? : bpf_strerror(lookup_errno)); } } @@ -1032,7 +1032,7 @@ static int do_update(int argc, char **argv) err = bpf_map_update_elem(fd, key, value, flags); if (err) { - p_err("update failed: %s", strerror(errno)); + p_err("update failed: %s", bpf_strerror(errno)); goto exit_free; } @@ -1136,7 +1136,7 @@ static int do_lookup(int argc, char **argv) printf("\n\nNot found\n"); } } else { - p_err("lookup failed: %s", strerror(errno)); + p_err("lookup failed: %s", bpf_strerror(errno)); } goto exit_free; @@ -1188,7 +1188,7 @@ static int do_getnext(int argc, char **argv) err = bpf_map_get_next_key(fd, key, nextkey); if (err) { - p_err("can't get next key: %s", strerror(errno)); + p_err("can't get next key: %s", bpf_strerror(errno)); goto exit_free; } @@ -1253,7 +1253,7 @@ static int do_delete(int argc, char **argv) err = bpf_map_delete_elem(fd, key); if (err) - p_err("delete failed: %s", strerror(errno)); + p_err("delete failed: %s", bpf_strerror(errno)); exit_free: free(key); @@ -1381,7 +1381,7 @@ static int do_create(int argc, char **argv) fd = bpf_map_create(map_type, map_name, key_size, value_size, max_entries, &attr); if (fd < 0) { - p_err("map create failed: %s", strerror(errno)); + p_err("map create failed: %s", bpf_strerror(errno)); goto exit; } @@ -1427,7 +1427,7 @@ static int do_pop_dequeue(int argc, char **argv) else printf("Error: empty map\n"); } else { - p_err("pop failed: %s", strerror(errno)); + p_err("pop failed: %s", bpf_strerror(errno)); } goto exit_free; @@ -1462,7 +1462,7 @@ static int do_freeze(int argc, char **argv) err = bpf_map_freeze(fd); close(fd); if (err) { - p_err("failed to freeze map: %s", strerror(errno)); + p_err("failed to freeze map: %s", bpf_strerror(errno)); return err; } diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c index eb077236d2eaa..43599c79c93ac 100644 --- a/tools/bpf/bpftool/prog.c +++ b/tools/bpf/bpftool/prog.c @@ -1499,7 +1499,7 @@ static int do_run(int argc, char **argv) err = bpf_prog_test_run_opts(fd, &test_attr); if (err) { - p_err("failed to run program: %s", strerror(errno)); + p_err("failed to run program: %s", bpf_strerror(errno)); goto free_ctx_out; } -- 2.47.3
