Commit 2f1d774f authored by Alexei Starovoitov's avatar Alexei Starovoitov

Merge branch 'bpftool_sockmap'

John Fastabend says:

====================
The first patch adds support for attaching programs to maps. This is
needed to support sock{map|hash} use from bpftool. Currently, I carry
around custom code to do this so doing it using standard bpftool will
be great.

The second patch adds a compat mode to ignore non-zero entries in
the map def. This allows using bpftool with maps that have a extra
fields that the user knows can be ignored. This is needed to work
correctly with maps being loaded by other tools or directly via
syscalls.

v3: add bash completion and doc updates for --mapcompat
====================
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parents 7d1f12b8 c034a177
...@@ -25,6 +25,8 @@ MAP COMMANDS ...@@ -25,6 +25,8 @@ MAP COMMANDS
| **bpftool** **prog dump jited** *PROG* [{**file** *FILE* | **opcodes**}] | **bpftool** **prog dump jited** *PROG* [{**file** *FILE* | **opcodes**}]
| **bpftool** **prog pin** *PROG* *FILE* | **bpftool** **prog pin** *PROG* *FILE*
| **bpftool** **prog load** *OBJ* *FILE* [**type** *TYPE*] [**map** {**idx** *IDX* | **name** *NAME*} *MAP*] [**dev** *NAME*] | **bpftool** **prog load** *OBJ* *FILE* [**type** *TYPE*] [**map** {**idx** *IDX* | **name** *NAME*} *MAP*] [**dev** *NAME*]
| **bpftool** **prog attach** *PROG* *ATTACH_TYPE* *MAP*
| **bpftool** **prog detach** *PROG* *ATTACH_TYPE* *MAP*
| **bpftool** **prog help** | **bpftool** **prog help**
| |
| *MAP* := { **id** *MAP_ID* | **pinned** *FILE* } | *MAP* := { **id** *MAP_ID* | **pinned** *FILE* }
...@@ -37,6 +39,7 @@ MAP COMMANDS ...@@ -37,6 +39,7 @@ MAP COMMANDS
| **cgroup/bind4** | **cgroup/bind6** | **cgroup/post_bind4** | **cgroup/post_bind6** | | **cgroup/bind4** | **cgroup/bind6** | **cgroup/post_bind4** | **cgroup/post_bind6** |
| **cgroup/connect4** | **cgroup/connect6** | **cgroup/sendmsg4** | **cgroup/sendmsg6** | **cgroup/connect4** | **cgroup/connect6** | **cgroup/sendmsg4** | **cgroup/sendmsg6**
| } | }
| *ATTACH_TYPE* := { **msg_verdict** | **skb_verdict** | **skb_parse** }
DESCRIPTION DESCRIPTION
...@@ -90,6 +93,14 @@ DESCRIPTION ...@@ -90,6 +93,14 @@ DESCRIPTION
Note: *FILE* must be located in *bpffs* mount. Note: *FILE* must be located in *bpffs* mount.
**bpftool prog attach** *PROG* *ATTACH_TYPE* *MAP*
Attach bpf program *PROG* (with type specified by *ATTACH_TYPE*)
to the map *MAP*.
**bpftool prog detach** *PROG* *ATTACH_TYPE* *MAP*
Detach bpf program *PROG* (with type specified by *ATTACH_TYPE*)
from the map *MAP*.
**bpftool prog help** **bpftool prog help**
Print short help message. Print short help message.
......
...@@ -26,7 +26,7 @@ SYNOPSIS ...@@ -26,7 +26,7 @@ SYNOPSIS
| **pin** | **event_pipe** | **help** } | **pin** | **event_pipe** | **help** }
*PROG-COMMANDS* := { **show** | **list** | **dump jited** | **dump xlated** | **pin** *PROG-COMMANDS* := { **show** | **list** | **dump jited** | **dump xlated** | **pin**
| **load** | **help** } | **load** | **attach** | **detach** | **help** }
*CGROUP-COMMANDS* := { **show** | **list** | **attach** | **detach** | **help** } *CGROUP-COMMANDS* := { **show** | **list** | **attach** | **detach** | **help** }
...@@ -57,6 +57,10 @@ OPTIONS ...@@ -57,6 +57,10 @@ OPTIONS
-p, --pretty -p, --pretty
Generate human-readable JSON output. Implies **-j**. Generate human-readable JSON output. Implies **-j**.
-m, --mapcompat
Allow loading maps with unknown map definitions.
SEE ALSO SEE ALSO
======== ========
**bpftool-map**\ (8), **bpftool-prog**\ (8), **bpftool-cgroup**\ (8) **bpftool-map**\ (8), **bpftool-prog**\ (8), **bpftool-cgroup**\ (8)
......
...@@ -184,7 +184,7 @@ _bpftool() ...@@ -184,7 +184,7 @@ _bpftool()
# Deal with options # Deal with options
if [[ ${words[cword]} == -* ]]; then if [[ ${words[cword]} == -* ]]; then
local c='--version --json --pretty --bpffs' local c='--version --json --pretty --bpffs --mapcompat'
COMPREPLY=( $( compgen -W "$c" -- "$cur" ) ) COMPREPLY=( $( compgen -W "$c" -- "$cur" ) )
return 0 return 0
fi fi
...@@ -292,6 +292,23 @@ _bpftool() ...@@ -292,6 +292,23 @@ _bpftool()
fi fi
return 0 return 0
;; ;;
attach|detach)
if [[ ${#words[@]} == 7 ]]; then
COMPREPLY=( $( compgen -W "id pinned" -- "$cur" ) )
return 0
fi
if [[ ${#words[@]} == 6 ]]; then
COMPREPLY=( $( compgen -W "msg_verdict skb_verdict skb_parse" -- "$cur" ) )
return 0
fi
if [[ $prev == "$command" ]]; then
COMPREPLY=( $( compgen -W "id pinned" -- "$cur" ) )
return 0
fi
return 0
;;
load) load)
local obj local obj
...@@ -347,7 +364,7 @@ _bpftool() ...@@ -347,7 +364,7 @@ _bpftool()
;; ;;
*) *)
[[ $prev == $object ]] && \ [[ $prev == $object ]] && \
COMPREPLY=( $( compgen -W 'dump help pin load \ COMPREPLY=( $( compgen -W 'dump help pin attach detach load \
show list' -- "$cur" ) ) show list' -- "$cur" ) )
;; ;;
esac esac
......
...@@ -55,6 +55,7 @@ json_writer_t *json_wtr; ...@@ -55,6 +55,7 @@ json_writer_t *json_wtr;
bool pretty_output; bool pretty_output;
bool json_output; bool json_output;
bool show_pinned; bool show_pinned;
int bpf_flags;
struct pinned_obj_table prog_table; struct pinned_obj_table prog_table;
struct pinned_obj_table map_table; struct pinned_obj_table map_table;
...@@ -341,6 +342,7 @@ int main(int argc, char **argv) ...@@ -341,6 +342,7 @@ int main(int argc, char **argv)
{ "pretty", no_argument, NULL, 'p' }, { "pretty", no_argument, NULL, 'p' },
{ "version", no_argument, NULL, 'V' }, { "version", no_argument, NULL, 'V' },
{ "bpffs", no_argument, NULL, 'f' }, { "bpffs", no_argument, NULL, 'f' },
{ "mapcompat", no_argument, NULL, 'm' },
{ 0 } { 0 }
}; };
int opt, ret; int opt, ret;
...@@ -355,7 +357,7 @@ int main(int argc, char **argv) ...@@ -355,7 +357,7 @@ int main(int argc, char **argv)
hash_init(map_table.table); hash_init(map_table.table);
opterr = 0; opterr = 0;
while ((opt = getopt_long(argc, argv, "Vhpjf", while ((opt = getopt_long(argc, argv, "Vhpjfm",
options, NULL)) >= 0) { options, NULL)) >= 0) {
switch (opt) { switch (opt) {
case 'V': case 'V':
...@@ -379,6 +381,9 @@ int main(int argc, char **argv) ...@@ -379,6 +381,9 @@ int main(int argc, char **argv)
case 'f': case 'f':
show_pinned = true; show_pinned = true;
break; break;
case 'm':
bpf_flags = MAPS_RELAX_COMPAT;
break;
default: default:
p_err("unrecognized option '%s'", argv[optind - 1]); p_err("unrecognized option '%s'", argv[optind - 1]);
if (json_output) if (json_output)
......
...@@ -74,7 +74,7 @@ ...@@ -74,7 +74,7 @@
#define HELP_SPEC_PROGRAM \ #define HELP_SPEC_PROGRAM \
"PROG := { id PROG_ID | pinned FILE | tag PROG_TAG }" "PROG := { id PROG_ID | pinned FILE | tag PROG_TAG }"
#define HELP_SPEC_OPTIONS \ #define HELP_SPEC_OPTIONS \
"OPTIONS := { {-j|--json} [{-p|--pretty}] | {-f|--bpffs} }" "OPTIONS := { {-j|--json} [{-p|--pretty}] | {-f|--bpffs} | {-m|--mapcompat}"
#define HELP_SPEC_MAP \ #define HELP_SPEC_MAP \
"MAP := { id MAP_ID | pinned FILE }" "MAP := { id MAP_ID | pinned FILE }"
...@@ -89,6 +89,7 @@ extern const char *bin_name; ...@@ -89,6 +89,7 @@ extern const char *bin_name;
extern json_writer_t *json_wtr; extern json_writer_t *json_wtr;
extern bool json_output; extern bool json_output;
extern bool show_pinned; extern bool show_pinned;
extern int bpf_flags;
extern struct pinned_obj_table prog_table; extern struct pinned_obj_table prog_table;
extern struct pinned_obj_table map_table; extern struct pinned_obj_table map_table;
......
...@@ -77,6 +77,26 @@ static const char * const prog_type_name[] = { ...@@ -77,6 +77,26 @@ static const char * const prog_type_name[] = {
[BPF_PROG_TYPE_FLOW_DISSECTOR] = "flow_dissector", [BPF_PROG_TYPE_FLOW_DISSECTOR] = "flow_dissector",
}; };
static const char * const attach_type_strings[] = {
[BPF_SK_SKB_STREAM_PARSER] = "stream_parser",
[BPF_SK_SKB_STREAM_VERDICT] = "stream_verdict",
[BPF_SK_MSG_VERDICT] = "msg_verdict",
[__MAX_BPF_ATTACH_TYPE] = NULL,
};
enum bpf_attach_type parse_attach_type(const char *str)
{
enum bpf_attach_type type;
for (type = 0; type < __MAX_BPF_ATTACH_TYPE; type++) {
if (attach_type_strings[type] &&
is_prefix(str, attach_type_strings[type]))
return type;
}
return __MAX_BPF_ATTACH_TYPE;
}
static void print_boot_time(__u64 nsecs, char *buf, unsigned int size) static void print_boot_time(__u64 nsecs, char *buf, unsigned int size)
{ {
struct timespec real_time_ts, boot_time_ts; struct timespec real_time_ts, boot_time_ts;
...@@ -697,6 +717,77 @@ int map_replace_compar(const void *p1, const void *p2) ...@@ -697,6 +717,77 @@ int map_replace_compar(const void *p1, const void *p2)
return a->idx - b->idx; return a->idx - b->idx;
} }
static int do_attach(int argc, char **argv)
{
enum bpf_attach_type attach_type;
int err, mapfd, progfd;
if (!REQ_ARGS(5)) {
p_err("too few parameters for map attach");
return -EINVAL;
}
progfd = prog_parse_fd(&argc, &argv);
if (progfd < 0)
return progfd;
attach_type = parse_attach_type(*argv);
if (attach_type == __MAX_BPF_ATTACH_TYPE) {
p_err("invalid attach type");
return -EINVAL;
}
NEXT_ARG();
mapfd = map_parse_fd(&argc, &argv);
if (mapfd < 0)
return mapfd;
err = bpf_prog_attach(progfd, mapfd, attach_type, 0);
if (err) {
p_err("failed prog attach to map");
return -EINVAL;
}
if (json_output)
jsonw_null(json_wtr);
return 0;
}
static int do_detach(int argc, char **argv)
{
enum bpf_attach_type attach_type;
int err, mapfd, progfd;
if (!REQ_ARGS(5)) {
p_err("too few parameters for map detach");
return -EINVAL;
}
progfd = prog_parse_fd(&argc, &argv);
if (progfd < 0)
return progfd;
attach_type = parse_attach_type(*argv);
if (attach_type == __MAX_BPF_ATTACH_TYPE) {
p_err("invalid attach type");
return -EINVAL;
}
NEXT_ARG();
mapfd = map_parse_fd(&argc, &argv);
if (mapfd < 0)
return mapfd;
err = bpf_prog_detach2(progfd, mapfd, attach_type);
if (err) {
p_err("failed prog detach from map");
return -EINVAL;
}
if (json_output)
jsonw_null(json_wtr);
return 0;
}
static int do_load(int argc, char **argv) static int do_load(int argc, char **argv)
{ {
enum bpf_attach_type expected_attach_type; enum bpf_attach_type expected_attach_type;
...@@ -817,7 +908,7 @@ static int do_load(int argc, char **argv) ...@@ -817,7 +908,7 @@ static int do_load(int argc, char **argv)
} }
} }
obj = bpf_object__open_xattr(&attr); obj = __bpf_object__open_xattr(&attr, bpf_flags);
if (IS_ERR_OR_NULL(obj)) { if (IS_ERR_OR_NULL(obj)) {
p_err("failed to open object file"); p_err("failed to open object file");
goto err_free_reuse_maps; goto err_free_reuse_maps;
...@@ -942,6 +1033,8 @@ static int do_help(int argc, char **argv) ...@@ -942,6 +1033,8 @@ static int do_help(int argc, char **argv)
" %s %s pin PROG FILE\n" " %s %s pin PROG FILE\n"
" %s %s load OBJ FILE [type TYPE] [dev NAME] \\\n" " %s %s load OBJ FILE [type TYPE] [dev NAME] \\\n"
" [map { idx IDX | name NAME } MAP]\n" " [map { idx IDX | name NAME } MAP]\n"
" %s %s attach PROG ATTACH_TYPE MAP\n"
" %s %s detach PROG ATTACH_TYPE MAP\n"
" %s %s help\n" " %s %s help\n"
"\n" "\n"
" " HELP_SPEC_MAP "\n" " " HELP_SPEC_MAP "\n"
...@@ -953,10 +1046,12 @@ static int do_help(int argc, char **argv) ...@@ -953,10 +1046,12 @@ static int do_help(int argc, char **argv)
" cgroup/bind4 | cgroup/bind6 | cgroup/post_bind4 |\n" " cgroup/bind4 | cgroup/bind6 | cgroup/post_bind4 |\n"
" cgroup/post_bind6 | cgroup/connect4 | cgroup/connect6 |\n" " cgroup/post_bind6 | cgroup/connect4 | cgroup/connect6 |\n"
" cgroup/sendmsg4 | cgroup/sendmsg6 }\n" " cgroup/sendmsg4 | cgroup/sendmsg6 }\n"
" ATTACH_TYPE := { msg_verdict | skb_verdict | skb_parse }\n"
" " HELP_SPEC_OPTIONS "\n" " " HELP_SPEC_OPTIONS "\n"
"", "",
bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2]); bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
bin_name, argv[-2], bin_name, argv[-2]);
return 0; return 0;
} }
...@@ -968,6 +1063,8 @@ static const struct cmd cmds[] = { ...@@ -968,6 +1063,8 @@ static const struct cmd cmds[] = {
{ "dump", do_dump }, { "dump", do_dump },
{ "pin", do_pin }, { "pin", do_pin },
{ "load", do_load }, { "load", do_load },
{ "attach", do_attach },
{ "detach", do_detach },
{ 0 } { 0 }
}; };
......
...@@ -69,6 +69,9 @@ struct bpf_load_program_attr { ...@@ -69,6 +69,9 @@ struct bpf_load_program_attr {
__u32 prog_ifindex; __u32 prog_ifindex;
}; };
/* Flags to direct loading requirements */
#define MAPS_RELAX_COMPAT 0x01
/* Recommend log buffer size */ /* Recommend log buffer size */
#define BPF_LOG_BUF_SIZE (256 * 1024) #define BPF_LOG_BUF_SIZE (256 * 1024)
int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr, int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
......
...@@ -562,8 +562,9 @@ static int compare_bpf_map(const void *_a, const void *_b) ...@@ -562,8 +562,9 @@ static int compare_bpf_map(const void *_a, const void *_b)
} }
static int static int
bpf_object__init_maps(struct bpf_object *obj) bpf_object__init_maps(struct bpf_object *obj, int flags)
{ {
bool strict = !(flags & MAPS_RELAX_COMPAT);
int i, map_idx, map_def_sz, nr_maps = 0; int i, map_idx, map_def_sz, nr_maps = 0;
Elf_Scn *scn; Elf_Scn *scn;
Elf_Data *data; Elf_Data *data;
...@@ -685,7 +686,8 @@ bpf_object__init_maps(struct bpf_object *obj) ...@@ -685,7 +686,8 @@ bpf_object__init_maps(struct bpf_object *obj)
"has unrecognized, non-zero " "has unrecognized, non-zero "
"options\n", "options\n",
obj->path, map_name); obj->path, map_name);
return -EINVAL; if (strict)
return -EINVAL;
} }
} }
memcpy(&obj->maps[map_idx].def, def, memcpy(&obj->maps[map_idx].def, def,
...@@ -716,7 +718,7 @@ static bool section_have_execinstr(struct bpf_object *obj, int idx) ...@@ -716,7 +718,7 @@ static bool section_have_execinstr(struct bpf_object *obj, int idx)
return false; return false;
} }
static int bpf_object__elf_collect(struct bpf_object *obj) static int bpf_object__elf_collect(struct bpf_object *obj, int flags)
{ {
Elf *elf = obj->efile.elf; Elf *elf = obj->efile.elf;
GElf_Ehdr *ep = &obj->efile.ehdr; GElf_Ehdr *ep = &obj->efile.ehdr;
...@@ -843,7 +845,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj) ...@@ -843,7 +845,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
return LIBBPF_ERRNO__FORMAT; return LIBBPF_ERRNO__FORMAT;
} }
if (obj->efile.maps_shndx >= 0) { if (obj->efile.maps_shndx >= 0) {
err = bpf_object__init_maps(obj); err = bpf_object__init_maps(obj, flags);
if (err) if (err)
goto out; goto out;
} }
...@@ -1515,7 +1517,7 @@ static int bpf_object__validate(struct bpf_object *obj, bool needs_kver) ...@@ -1515,7 +1517,7 @@ static int bpf_object__validate(struct bpf_object *obj, bool needs_kver)
static struct bpf_object * static struct bpf_object *
__bpf_object__open(const char *path, void *obj_buf, size_t obj_buf_sz, __bpf_object__open(const char *path, void *obj_buf, size_t obj_buf_sz,
bool needs_kver) bool needs_kver, int flags)
{ {
struct bpf_object *obj; struct bpf_object *obj;
int err; int err;
...@@ -1531,7 +1533,7 @@ __bpf_object__open(const char *path, void *obj_buf, size_t obj_buf_sz, ...@@ -1531,7 +1533,7 @@ __bpf_object__open(const char *path, void *obj_buf, size_t obj_buf_sz,
CHECK_ERR(bpf_object__elf_init(obj), err, out); CHECK_ERR(bpf_object__elf_init(obj), err, out);
CHECK_ERR(bpf_object__check_endianness(obj), err, out); CHECK_ERR(bpf_object__check_endianness(obj), err, out);
CHECK_ERR(bpf_object__elf_collect(obj), err, out); CHECK_ERR(bpf_object__elf_collect(obj, flags), err, out);
CHECK_ERR(bpf_object__collect_reloc(obj), err, out); CHECK_ERR(bpf_object__collect_reloc(obj), err, out);
CHECK_ERR(bpf_object__validate(obj, needs_kver), err, out); CHECK_ERR(bpf_object__validate(obj, needs_kver), err, out);
...@@ -1542,7 +1544,8 @@ __bpf_object__open(const char *path, void *obj_buf, size_t obj_buf_sz, ...@@ -1542,7 +1544,8 @@ __bpf_object__open(const char *path, void *obj_buf, size_t obj_buf_sz,
return ERR_PTR(err); return ERR_PTR(err);
} }
struct bpf_object *bpf_object__open_xattr(struct bpf_object_open_attr *attr) struct bpf_object *__bpf_object__open_xattr(struct bpf_object_open_attr *attr,
int flags)
{ {
/* param validation */ /* param validation */
if (!attr->file) if (!attr->file)
...@@ -1551,7 +1554,13 @@ struct bpf_object *bpf_object__open_xattr(struct bpf_object_open_attr *attr) ...@@ -1551,7 +1554,13 @@ struct bpf_object *bpf_object__open_xattr(struct bpf_object_open_attr *attr)
pr_debug("loading %s\n", attr->file); pr_debug("loading %s\n", attr->file);
return __bpf_object__open(attr->file, NULL, 0, return __bpf_object__open(attr->file, NULL, 0,
bpf_prog_type__needs_kver(attr->prog_type)); bpf_prog_type__needs_kver(attr->prog_type),
flags);
}
struct bpf_object *bpf_object__open_xattr(struct bpf_object_open_attr *attr)
{
return __bpf_object__open_xattr(attr, 0);
} }
struct bpf_object *bpf_object__open(const char *path) struct bpf_object *bpf_object__open(const char *path)
...@@ -1584,7 +1593,7 @@ struct bpf_object *bpf_object__open_buffer(void *obj_buf, ...@@ -1584,7 +1593,7 @@ struct bpf_object *bpf_object__open_buffer(void *obj_buf,
pr_debug("loading object '%s' from buffer\n", pr_debug("loading object '%s' from buffer\n",
name); name);
return __bpf_object__open(name, obj_buf, obj_buf_sz, true); return __bpf_object__open(name, obj_buf, obj_buf_sz, true, true);
} }
int bpf_object__unload(struct bpf_object *obj) int bpf_object__unload(struct bpf_object *obj)
......
...@@ -61,6 +61,8 @@ struct bpf_object_open_attr { ...@@ -61,6 +61,8 @@ struct bpf_object_open_attr {
struct bpf_object *bpf_object__open(const char *path); struct bpf_object *bpf_object__open(const char *path);
struct bpf_object *bpf_object__open_xattr(struct bpf_object_open_attr *attr); struct bpf_object *bpf_object__open_xattr(struct bpf_object_open_attr *attr);
struct bpf_object *__bpf_object__open_xattr(struct bpf_object_open_attr *attr,
int flags);
struct bpf_object *bpf_object__open_buffer(void *obj_buf, struct bpf_object *bpf_object__open_buffer(void *obj_buf,
size_t obj_buf_sz, size_t obj_buf_sz,
const char *name); const char *name);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment