Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 671dffa7 authored by Daniel Borkmann's avatar Daniel Borkmann
Browse files

Merge branch 'bpf-bpftool-improved-prog-load'



Jakub Kicinski says:

====================
This series starts with two minor clean ups to test_offload.py
selftest script.

The next 11 patches extend the abilities of bpftool prog load
beyond the simple cgroup use cases.  Three new parameters are
added:

 - type - allows specifying program type, independent of how
   code sections are named;
 - map  - allows reusing existing maps, instead of creating a new
   map on every program load;
 - dev  - offload/binding to a device.

A number of changes to libbpf is required to accomplish the task.
The section - program type logic mapping is exposed.  We should
probably aim to use the libbpf program section naming everywhere.
For reuse of maps we need to allow users to set FD for bpf map
object in libbpf.

Examples

Load program my_xdp.o and pin it as /sys/fs/bpf/my_xdp, for xdp
program type:

$ bpftool prog load my_xdp.o /sys/fs/bpf/my_xdp \
  type xdp

As above but for offload:

$ bpftool prog load my_xdp.o /sys/fs/bpf/my_xdp \
  type xdp \
  dev netdevsim0

Load program my_maps.o, but for the first map reuse map id 17,
and for the map called "other_map" reuse pinned map /sys/fs/bpf/map0:

$ bpftool prog load my_maps.o /sys/fs/bpf/prog \
  map idx 0 id 17 \
  map name other_map pinned /sys/fs/bpf/map0

v3:
 - fix return codes in patch 5;
 - rename libbpf_prog_type_by_string() -> libbpf_prog_type_by_name();
 - fold file path into xattr in patch 8;
 - add patch 10;
 - use dup3() in patch 12;
 - depend on fd value in patch 12;
 - close old fd in patch 12.
v2:
 - add compat for reallocarray().
====================

Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parents d90c936f 3ff5a4dc
Loading
Loading
Loading
Loading
+31 −2
Original line number Diff line number Diff line
@@ -24,10 +24,20 @@ MAP COMMANDS
|	**bpftool** **prog dump xlated** *PROG* [{**file** *FILE* | **opcodes** | **visual**}]
|	**bpftool** **prog dump jited**  *PROG* [{**file** *FILE* | **opcodes**}]
|	**bpftool** **prog pin** *PROG* *FILE*
|	**bpftool** **prog load** *OBJ* *FILE*
|	**bpftool** **prog load** *OBJ* *FILE* [**type** *TYPE*] [**map** {**idx** *IDX* | **name** *NAME*} *MAP*] [**dev** *NAME*]
|	**bpftool** **prog help**
|
|	*MAP* := { **id** *MAP_ID* | **pinned** *FILE* }
|	*PROG* := { **id** *PROG_ID* | **pinned** *FILE* | **tag** *PROG_TAG* }
|	*TYPE* := {
|		**socket** | **kprobe** | **kretprobe** | **classifier** | **action** |
|		**tracepoint** | **raw_tracepoint** | **xdp** | **perf_event** | **cgroup/skb** |
|		**cgroup/sock** | **cgroup/dev** | **lwt_in** | **lwt_out** | **lwt_xmit** |
|		**lwt_seg6local** | **sockops** | **sk_skb** | **sk_msg** | **lirc_mode2** |
|		**cgroup/bind4** | **cgroup/bind6** | **cgroup/post_bind4** | **cgroup/post_bind6** |
|		**cgroup/connect4** | **cgroup/connect6** | **cgroup/sendmsg4** | **cgroup/sendmsg6**
|	}


DESCRIPTION
===========
@@ -64,8 +74,19 @@ DESCRIPTION

		  Note: *FILE* must be located in *bpffs* mount.

	**bpftool prog load** *OBJ* *FILE*
	**bpftool prog load** *OBJ* *FILE* [**type** *TYPE*] [**map** {**idx** *IDX* | **name** *NAME*} *MAP*] [**dev** *NAME*]
		  Load bpf program from binary *OBJ* and pin as *FILE*.
		  **type** is optional, if not specified program type will be
		  inferred from section names.
		  By default bpftool will create new maps as declared in the ELF
		  object being loaded.  **map** parameter allows for the reuse
		  of existing maps.  It can be specified multiple times, each
		  time for a different map.  *IDX* refers to index of the map
		  to be replaced in the ELF file counting from 0, while *NAME*
		  allows to replace a map by name.  *MAP* specifies the map to
		  use, referring to it by **id** or through a **pinned** file.
		  If **dev** *NAME* is specified program will be loaded onto
		  given networking device (offload).

		  Note: *FILE* must be located in *bpffs* mount.

@@ -159,6 +180,14 @@ EXAMPLES
    mov    %rbx,0x0(%rbp)
    48 89 5d 00

|
| **# bpftool prog load xdp1_kern.o /sys/fs/bpf/xdp1 type xdp map name rxcnt id 7**
| **# bpftool prog show pinned /sys/fs/bpf/xdp1**
|   9: xdp  name xdp_prog1  tag 539ec6ce11b52f98  gpl
|	loaded_at 2018-06-25T16:17:31-0700  uid 0
|	xlated 488B  jited 336B  memlock 4096B  map_ids 7
| **# rm /sys/fs/bpf/xdp1**
|

SEE ALSO
========
+5 −1
Original line number Diff line number Diff line
@@ -52,7 +52,7 @@ INSTALL ?= install
RM ?= rm -f

FEATURE_USER = .bpftool
FEATURE_TESTS = libbfd disassembler-four-args
FEATURE_TESTS = libbfd disassembler-four-args reallocarray
FEATURE_DISPLAY = libbfd disassembler-four-args

check_feat := 1
@@ -75,6 +75,10 @@ ifeq ($(feature-disassembler-four-args), 1)
CFLAGS += -DDISASM_FOUR_ARGS_SIGNATURE
endif

ifeq ($(feature-reallocarray), 0)
CFLAGS += -DCOMPAT_NEED_REALLOCARRAY
endif

include $(wildcard $(OUTPUT)*.d)

all: $(OUTPUT)bpftool
+88 −8
Original line number Diff line number Diff line
@@ -99,6 +99,35 @@ _bpftool_get_prog_tags()
        command sed -n 's/.*"tag": "\(.*\)",$/\1/p' )" -- "$cur" ) )
}

_bpftool_get_obj_map_names()
{
    local obj

    obj=$1

    maps=$(objdump -j maps -t $obj 2>/dev/null | \
        command awk '/g     . maps/ {print $NF}')

    COMPREPLY+=( $( compgen -W "$maps" -- "$cur" ) )
}

_bpftool_get_obj_map_idxs()
{
    local obj

    obj=$1

    nmaps=$(objdump -j maps -t $obj 2>/dev/null | grep -c 'g     . maps')

    COMPREPLY+=( $( compgen -W "$(seq 0 $((nmaps - 1)))" -- "$cur" ) )
}

_sysfs_get_netdevs()
{
    COMPREPLY+=( $( compgen -W "$( ls /sys/class/net 2>/dev/null )" -- \
        "$cur" ) )
}

# For bpftool map update: retrieve type of the map to update.
_bpftool_map_update_map_type()
{
@@ -214,12 +243,14 @@ _bpftool()
    # Completion depends on object and command in use
    case $object in
        prog)
            if [[ $command != "load" ]]; then
                case $prev in
                    id)
                        _bpftool_get_prog_ids
                        return 0
                        ;;
                esac
            fi

            local PROG_TYPE='id pinned tag'
            case $command in
@@ -262,9 +293,58 @@ _bpftool()
                    return 0
                    ;;
                load)
                    local obj

                    if [[ ${#words[@]} -lt 6 ]]; then
                        _filedir
                        return 0
                    fi

                    obj=${words[3]}

                    if [[ ${words[-4]} == "map" ]]; then
                        COMPREPLY=( $( compgen -W "id pinned" -- "$cur" ) )
                        return 0
                    fi
                    if [[ ${words[-3]} == "map" ]]; then
                        if [[ ${words[-2]} == "idx" ]]; then
                            _bpftool_get_obj_map_idxs $obj
                        elif [[ ${words[-2]} == "name" ]]; then
                            _bpftool_get_obj_map_names $obj
                        fi
                        return 0
                    fi
                    if [[ ${words[-2]} == "map" ]]; then
                        COMPREPLY=( $( compgen -W "idx name" -- "$cur" ) )
                        return 0
                    fi

                    case $prev in
                        type)
                            COMPREPLY=( $( compgen -W "socket kprobe kretprobe classifier action tracepoint raw_tracepoint xdp perf_event cgroup/skb cgroup/sock cgroup/dev lwt_in lwt_out lwt_xmit lwt_seg6local sockops sk_skb sk_msg lirc_mode2 cgroup/bind4 cgroup/bind6 cgroup/connect4 cgroup/connect6 cgroup/sendmsg4 cgroup/sendmsg6 cgroup/post_bind4 cgroup/post_bind6" -- \
                                                   "$cur" ) )
                            return 0
                            ;;
                        id)
                            _bpftool_get_map_ids
                            return 0
                            ;;
                        pinned)
                            _filedir
                            return 0
                            ;;
                        dev)
                            _sysfs_get_netdevs
                            return 0
                            ;;
                        *)
                            COMPREPLY=( $( compgen -W "map" -- "$cur" ) )
                            _bpftool_once_attr 'type'
                            _bpftool_once_attr 'dev'
                            return 0
                            ;;
                    esac
                    ;;
                *)
                    [[ $prev == $object ]] && \
                        COMPREPLY=( $( compgen -W 'dump help pin load \
+19 −0
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@
#include <linux/compiler.h>
#include <linux/kernel.h>
#include <linux/hashtable.h>
#include <tools/libc_compat.h>

#include "json_writer.h"

@@ -50,6 +51,21 @@
#define NEXT_ARG()	({ argc--; argv++; if (argc < 0) usage(); })
#define NEXT_ARGP()	({ (*argc)--; (*argv)++; if (*argc < 0) usage(); })
#define BAD_ARG()	({ p_err("what is '%s'?", *argv); -1; })
#define GET_ARG()	({ argc--; *argv++; })
#define REQ_ARGS(cnt)							\
	({								\
		int _cnt = (cnt);					\
		bool _res;						\
									\
		if (argc < _cnt) {					\
			p_err("'%s' needs at least %d arguments, %d found", \
			      argv[-1], _cnt, argc);			\
			_res = false;					\
		} else {						\
			_res = true;					\
		}							\
		_res;							\
	})

#define ERR_MAX_LEN	1024

@@ -59,6 +75,8 @@
	"PROG := { id PROG_ID | pinned FILE | tag PROG_TAG }"
#define HELP_SPEC_OPTIONS						\
	"OPTIONS := { {-j|--json} [{-p|--pretty}] | {-f|--bpffs} }"
#define HELP_SPEC_MAP							\
	"MAP := { id MAP_ID | pinned FILE }"

enum bpf_obj_type {
	BPF_OBJ_UNKNOWN,
@@ -120,6 +138,7 @@ int do_cgroup(int argc, char **arg);
int do_perf(int argc, char **arg);

int prog_parse_fd(int *argc, char ***argv);
int map_parse_fd(int *argc, char ***argv);
int map_parse_fd_and_info(int *argc, char ***argv, void *info, __u32 *info_len);

void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
+2 −2
Original line number Diff line number Diff line
@@ -93,7 +93,7 @@ static void *alloc_value(struct bpf_map_info *info)
		return malloc(info->value_size);
}

static int map_parse_fd(int *argc, char ***argv)
int map_parse_fd(int *argc, char ***argv)
{
	int fd;

@@ -824,7 +824,7 @@ static int do_help(int argc, char **argv)
		"       %s %s event_pipe MAP [cpu N index M]\n"
		"       %s %s help\n"
		"\n"
		"       MAP := { id MAP_ID | pinned FILE }\n"
		"       " HELP_SPEC_MAP "\n"
		"       DATA := { [hex] BYTES }\n"
		"       " HELP_SPEC_PROGRAM "\n"
		"       VALUE := { DATA | MAP | PROG }\n"
Loading