tools/bpftool: Add bpftool support for bpf map element iterator

The optional parameter "map MAP" can be added to "bpftool iter"
command to create a bpf iterator for map elements. For example,
  bpftool iter pin ./prog.o /sys/fs/bpf/p1 map id 333

For map element bpf iterator "map MAP" parameter is required.
Otherwise, bpf link creation will return an error.

Quentin Monnet kindly provided bash-completion implementation
for new "map MAP" option.

Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20200723184119.590799-1-yhs@fb.com
This commit is contained in:
Yonghong Song 2020-07-23 11:41:19 -07:00 committed by Alexei Starovoitov
parent cd31039a73
commit d8793aca70
3 changed files with 62 additions and 7 deletions

View File

@ -17,14 +17,15 @@ SYNOPSIS
ITER COMMANDS
===================
| **bpftool** **iter pin** *OBJ* *PATH*
| **bpftool** **iter pin** *OBJ* *PATH* [**map** *MAP*]
| **bpftool** **iter help**
|
| *OBJ* := /a/file/of/bpf_iter_target.o
| *MAP* := { **id** *MAP_ID* | **pinned** *FILE* }
DESCRIPTION
===========
**bpftool iter pin** *OBJ* *PATH*
**bpftool iter pin** *OBJ* *PATH* [**map** *MAP*]
A bpf iterator combines a kernel iterating of
particular kernel data (e.g., tasks, bpf_maps, etc.)
and a bpf program called for each kernel data object
@ -37,6 +38,12 @@ DESCRIPTION
character ('.'), which is reserved for future extensions
of *bpffs*.
Map element bpf iterator requires an additional parameter
*MAP* so bpf program can iterate over map elements for
that map. User can have a bpf program in kernel to run
with each map element, do checking, filtering, aggregation,
etc. without copying data to user space.
User can then *cat PATH* to see the bpf iterator output.
**bpftool iter help**
@ -64,6 +71,13 @@ EXAMPLES
Create a file-based bpf iterator from bpf_iter_netlink.o and pin it
to /sys/fs/bpf/my_netlink
**# bpftool iter pin bpf_iter_hashmap.o /sys/fs/bpf/my_hashmap map id 20**
::
Create a file-based bpf iterator from bpf_iter_hashmap.o and map with
id 20, and pin it to /sys/fs/bpf/my_hashmap
SEE ALSO
========
**bpf**\ (2),

View File

@ -615,7 +615,23 @@ _bpftool()
iter)
case $command in
pin)
case $prev in
$command)
_filedir
;;
id)
_bpftool_get_map_ids
;;
name)
_bpftool_get_map_names
;;
pinned)
_filedir
;;
*)
_bpftool_one_of_list $MAP_TYPE
;;
esac
return 0
;;
*)

View File

@ -2,6 +2,7 @@
// Copyright (C) 2020 Facebook
#define _GNU_SOURCE
#include <unistd.h>
#include <linux/err.h>
#include <bpf/libbpf.h>
@ -9,11 +10,12 @@
static int do_pin(int argc, char **argv)
{
DECLARE_LIBBPF_OPTS(bpf_iter_attach_opts, iter_opts);
const char *objfile, *path;
struct bpf_program *prog;
struct bpf_object *obj;
struct bpf_link *link;
int err;
int err = -1, map_fd = -1;
if (!REQ_ARGS(2))
usage();
@ -21,10 +23,26 @@ static int do_pin(int argc, char **argv)
objfile = GET_ARG();
path = GET_ARG();
/* optional arguments */
if (argc) {
if (is_prefix(*argv, "map")) {
NEXT_ARG();
if (!REQ_ARGS(2)) {
p_err("incorrect map spec");
return -1;
}
map_fd = map_parse_fd(&argc, &argv);
if (map_fd < 0)
return -1;
}
}
obj = bpf_object__open(objfile);
if (IS_ERR(obj)) {
p_err("can't open objfile %s", objfile);
return -1;
goto close_map_fd;
}
err = bpf_object__load(obj);
@ -39,7 +57,10 @@ static int do_pin(int argc, char **argv)
goto close_obj;
}
link = bpf_program__attach_iter(prog, NULL);
if (map_fd >= 0)
iter_opts.map_fd = map_fd;
link = bpf_program__attach_iter(prog, &iter_opts);
if (IS_ERR(link)) {
err = PTR_ERR(link);
p_err("attach_iter failed for program %s",
@ -62,14 +83,18 @@ close_link:
bpf_link__destroy(link);
close_obj:
bpf_object__close(obj);
close_map_fd:
if (map_fd >= 0)
close(map_fd);
return err;
}
static int do_help(int argc, char **argv)
{
fprintf(stderr,
"Usage: %1$s %2$s pin OBJ PATH\n"
"Usage: %1$s %2$s pin OBJ PATH [map MAP]\n"
" %1$s %2$s help\n"
" " HELP_SPEC_MAP "\n"
"",
bin_name, "iter");