aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-01-07 21:26:31 -0500
committerDavid S. Miller <davem@davemloft.net>2018-01-07 21:26:31 -0500
commit7f0b800048b562d716372466ea8d9de648c422dd (patch)
tree8fbad920adc333fd00cbc3acaba09cdfa9b63fb3 /tools
parentd0adb51edb73c94a595bfa9d9bd8b35977e74fbf (diff)
parent9be99badee761f0b2c065ecbd8bd54a96cbd0fa0 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
Daniel Borkmann says: ==================== pull-request: bpf-next 2018-01-07 The following pull-request contains BPF updates for your *net-next* tree. The main changes are: 1) Add a start of a framework for extending struct xdp_buff without having the overhead of populating every data at runtime. Idea is to have a new per-queue struct xdp_rxq_info that holds read mostly data (currently that is, queue number and a pointer to the corresponding netdev) which is set up during rxqueue config time. When a XDP program is invoked, struct xdp_buff holds a pointer to struct xdp_rxq_info that the BPF program can then walk. The user facing BPF program that uses struct xdp_md for context can use these members directly, and the verifier rewrites context access transparently by walking the xdp_rxq_info and net_device pointers to load the data, from Jesper. 2) Redo the reporting of offload device information to user space such that it works in combination with network namespaces. The latter is reported through a device/inode tuple as similarly done in other subsystems as well (e.g. perf) in order to identify the namespace. For this to work, ns_get_path() has been generalized such that the namespace can be retrieved not only from a specific task (perf case), but also from a callback where we deduce the netns (ns_common) from a netdevice. bpftool support using the new uapi info and extensive test cases for test_offload.py in BPF selftests have been added as well, from Jakub. 3) Add two bpftool improvements: i) properly report the bpftool version such that it corresponds to the version from the kernel source tree. So pick the right linux/version.h from the source tree instead of the installed one. ii) fix bpftool and also bpf_jit_disasm build with bintutils >= 2.9. The reason for the build breakage is that binutils library changed the function signature to select the disassembler. Given this is needed in multiple tools, add a proper feature detection to the tools/build/features infrastructure, from Roman. 4) Implement the BPF syscall command BPF_MAP_GET_NEXT_KEY for the stacktrace map. It is currently unimplemented, but there are use cases where user space needs to walk all stacktrace map entries e.g. for dumping or deleting map entries w/o having to close and recreate the map. Add BPF selftests along with it, from Yonghong. 5) Few follow-up cleanups for the bpftool cgroup code: i) rename the cgroup 'list' command into 'show' as we have it for other subcommands as well, ii) then alias the 'show' command such that 'list' is accepted which is also common practice in iproute2, and iii) remove couple of newlines from error messages using p_err(), from Jakub. 6) Two follow-up cleanups to sockmap code: i) remove the unused bpf_compute_data_end_sk_skb() function and ii) only build the sockmap infrastructure when CONFIG_INET is enabled since it's only aware of TCP sockets at this time, from John. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'tools')
-rw-r--r--tools/bpf/Makefile29
-rw-r--r--tools/bpf/bpf_jit_disasm.c7
-rw-r--r--tools/bpf/bpftool/Documentation/bpftool-cgroup.rst6
-rw-r--r--tools/bpf/bpftool/Documentation/bpftool-map.rst6
-rw-r--r--tools/bpf/bpftool/Documentation/bpftool-prog.rst6
-rw-r--r--tools/bpf/bpftool/Documentation/bpftool.rst6
-rw-r--r--tools/bpf/bpftool/Makefile27
-rw-r--r--tools/bpf/bpftool/bash-completion/bpftool8
-rw-r--r--tools/bpf/bpftool/cgroup.c35
-rw-r--r--tools/bpf/bpftool/common.c52
-rw-r--r--tools/bpf/bpftool/jit_disasm.c7
-rw-r--r--tools/bpf/bpftool/main.c13
-rw-r--r--tools/bpf/bpftool/main.h2
-rw-r--r--tools/bpf/bpftool/map.c3
-rw-r--r--tools/bpf/bpftool/prog.c10
-rw-r--r--tools/build/feature/Makefile4
-rw-r--r--tools/build/feature/test-disassembler-four-args.c15
-rw-r--r--tools/include/uapi/linux/bpf.h3
-rw-r--r--tools/testing/selftests/bpf/Makefile2
-rwxr-xr-xtools/testing/selftests/bpf/test_offload.py112
-rw-r--r--tools/testing/selftests/bpf/test_progs.c127
-rw-r--r--tools/testing/selftests/bpf/test_stacktrace_map.c62
22 files changed, 482 insertions, 60 deletions
diff --git a/tools/bpf/Makefile b/tools/bpf/Makefile
index 07a6697466ef..c8ec0ae16bf0 100644
--- a/tools/bpf/Makefile
+++ b/tools/bpf/Makefile
@@ -9,6 +9,35 @@ MAKE = make
9CFLAGS += -Wall -O2 9CFLAGS += -Wall -O2
10CFLAGS += -D__EXPORTED_HEADERS__ -I../../include/uapi -I../../include 10CFLAGS += -D__EXPORTED_HEADERS__ -I../../include/uapi -I../../include
11 11
12ifeq ($(srctree),)
13srctree := $(patsubst %/,%,$(dir $(CURDIR)))
14srctree := $(patsubst %/,%,$(dir $(srctree)))
15endif
16
17FEATURE_USER = .bpf
18FEATURE_TESTS = libbfd disassembler-four-args
19FEATURE_DISPLAY = libbfd disassembler-four-args
20
21check_feat := 1
22NON_CHECK_FEAT_TARGETS := clean bpftool_clean
23ifdef MAKECMDGOALS
24ifeq ($(filter-out $(NON_CHECK_FEAT_TARGETS),$(MAKECMDGOALS)),)
25 check_feat := 0
26endif
27endif
28
29ifeq ($(check_feat),1)
30ifeq ($(FEATURES_DUMP),)
31include $(srctree)/tools/build/Makefile.feature
32else
33include $(FEATURES_DUMP)
34endif
35endif
36
37ifeq ($(feature-disassembler-four-args), 1)
38CFLAGS += -DDISASM_FOUR_ARGS_SIGNATURE
39endif
40
12%.yacc.c: %.y 41%.yacc.c: %.y
13 $(YACC) -o $@ -d $< 42 $(YACC) -o $@ -d $<
14 43
diff --git a/tools/bpf/bpf_jit_disasm.c b/tools/bpf/bpf_jit_disasm.c
index 75bf526a0168..30044bc4f389 100644
--- a/tools/bpf/bpf_jit_disasm.c
+++ b/tools/bpf/bpf_jit_disasm.c
@@ -72,7 +72,14 @@ static void get_asm_insns(uint8_t *image, size_t len, int opcodes)
72 72
73 disassemble_init_for_target(&info); 73 disassemble_init_for_target(&info);
74 74
75#ifdef DISASM_FOUR_ARGS_SIGNATURE
76 disassemble = disassembler(info.arch,
77 bfd_big_endian(bfdf),
78 info.mach,
79 bfdf);
80#else
75 disassemble = disassembler(bfdf); 81 disassemble = disassembler(bfdf);
82#endif
76 assert(disassemble); 83 assert(disassemble);
77 84
78 do { 85 do {
diff --git a/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst b/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
index 45c71b1f682b..2fe2a1bdbe3e 100644
--- a/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
@@ -15,12 +15,12 @@ SYNOPSIS
15 *OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] | { **-f** | **--bpffs** } } 15 *OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] | { **-f** | **--bpffs** } }
16 16
17 *COMMANDS* := 17 *COMMANDS* :=
18 { **list** | **attach** | **detach** | **help** } 18 { **show** | **list** | **attach** | **detach** | **help** }
19 19
20MAP COMMANDS 20MAP COMMANDS
21============= 21=============
22 22
23| **bpftool** **cgroup list** *CGROUP* 23| **bpftool** **cgroup { show | list }** *CGROUP*
24| **bpftool** **cgroup attach** *CGROUP* *ATTACH_TYPE* *PROG* [*ATTACH_FLAGS*] 24| **bpftool** **cgroup attach** *CGROUP* *ATTACH_TYPE* *PROG* [*ATTACH_FLAGS*]
25| **bpftool** **cgroup detach** *CGROUP* *ATTACH_TYPE* *PROG* 25| **bpftool** **cgroup detach** *CGROUP* *ATTACH_TYPE* *PROG*
26| **bpftool** **cgroup help** 26| **bpftool** **cgroup help**
@@ -31,7 +31,7 @@ MAP COMMANDS
31 31
32DESCRIPTION 32DESCRIPTION
33=========== 33===========
34 **bpftool cgroup list** *CGROUP* 34 **bpftool cgroup { show | list }** *CGROUP*
35 List all programs attached to the cgroup *CGROUP*. 35 List all programs attached to the cgroup *CGROUP*.
36 36
37 Output will start with program ID followed by attach type, 37 Output will start with program ID followed by attach type,
diff --git a/tools/bpf/bpftool/Documentation/bpftool-map.rst b/tools/bpf/bpftool/Documentation/bpftool-map.rst
index 421cabc417e6..0ab32b312aec 100644
--- a/tools/bpf/bpftool/Documentation/bpftool-map.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool-map.rst
@@ -15,13 +15,13 @@ SYNOPSIS
15 *OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] | { **-f** | **--bpffs** } } 15 *OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] | { **-f** | **--bpffs** } }
16 16
17 *COMMANDS* := 17 *COMMANDS* :=
18 { **show** | **dump** | **update** | **lookup** | **getnext** | **delete** 18 { **show** | **list** | **dump** | **update** | **lookup** | **getnext** | **delete**
19 | **pin** | **help** } 19 | **pin** | **help** }
20 20
21MAP COMMANDS 21MAP COMMANDS
22============= 22=============
23 23
24| **bpftool** **map show** [*MAP*] 24| **bpftool** **map { show | list }** [*MAP*]
25| **bpftool** **map dump** *MAP* 25| **bpftool** **map dump** *MAP*
26| **bpftool** **map update** *MAP* **key** *BYTES* **value** *VALUE* [*UPDATE_FLAGS*] 26| **bpftool** **map update** *MAP* **key** *BYTES* **value** *VALUE* [*UPDATE_FLAGS*]
27| **bpftool** **map lookup** *MAP* **key** *BYTES* 27| **bpftool** **map lookup** *MAP* **key** *BYTES*
@@ -36,7 +36,7 @@ MAP COMMANDS
36 36
37DESCRIPTION 37DESCRIPTION
38=========== 38===========
39 **bpftool map show** [*MAP*] 39 **bpftool map { show | list }** [*MAP*]
40 Show information about loaded maps. If *MAP* is specified 40 Show information about loaded maps. If *MAP* is specified
41 show information only about given map, otherwise list all 41 show information only about given map, otherwise list all
42 maps currently loaded on the system. 42 maps currently loaded on the system.
diff --git a/tools/bpf/bpftool/Documentation/bpftool-prog.rst b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
index 81c97c0e9b67..e4ceee7f2dff 100644
--- a/tools/bpf/bpftool/Documentation/bpftool-prog.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool-prog.rst
@@ -15,12 +15,12 @@ SYNOPSIS
15 *OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] | { **-f** | **--bpffs** } } 15 *OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] | { **-f** | **--bpffs** } }
16 16
17 *COMMANDS* := 17 *COMMANDS* :=
18 { **show** | **dump xlated** | **dump jited** | **pin** | **load** | **help** } 18 { **show** | **list** | **dump xlated** | **dump jited** | **pin** | **load** | **help** }
19 19
20MAP COMMANDS 20MAP COMMANDS
21============= 21=============
22 22
23| **bpftool** **prog show** [*PROG*] 23| **bpftool** **prog { show | list }** [*PROG*]
24| **bpftool** **prog dump xlated** *PROG* [{**file** *FILE* | **opcodes**}] 24| **bpftool** **prog dump xlated** *PROG* [{**file** *FILE* | **opcodes**}]
25| **bpftool** **prog dump jited** *PROG* [{**file** *FILE* | **opcodes**}] 25| **bpftool** **prog dump jited** *PROG* [{**file** *FILE* | **opcodes**}]
26| **bpftool** **prog pin** *PROG* *FILE* 26| **bpftool** **prog pin** *PROG* *FILE*
@@ -31,7 +31,7 @@ MAP COMMANDS
31 31
32DESCRIPTION 32DESCRIPTION
33=========== 33===========
34 **bpftool prog show** [*PROG*] 34 **bpftool prog { show | list }** [*PROG*]
35 Show information about loaded programs. If *PROG* is 35 Show information about loaded programs. If *PROG* is
36 specified show information only about given program, otherwise 36 specified show information only about given program, otherwise
37 list all programs currently loaded on the system. 37 list all programs currently loaded on the system.
diff --git a/tools/bpf/bpftool/Documentation/bpftool.rst b/tools/bpf/bpftool/Documentation/bpftool.rst
index 6732a5a617e4..20689a321ffe 100644
--- a/tools/bpf/bpftool/Documentation/bpftool.rst
+++ b/tools/bpf/bpftool/Documentation/bpftool.rst
@@ -22,13 +22,13 @@ SYNOPSIS
22 | { **-j** | **--json** } [{ **-p** | **--pretty** }] } 22 | { **-j** | **--json** } [{ **-p** | **--pretty** }] }
23 23
24 *MAP-COMMANDS* := 24 *MAP-COMMANDS* :=
25 { **show** | **dump** | **update** | **lookup** | **getnext** | **delete** 25 { **show** | **list** | **dump** | **update** | **lookup** | **getnext** | **delete**
26 | **pin** | **help** } 26 | **pin** | **help** }
27 27
28 *PROG-COMMANDS* := { **show** | **dump jited** | **dump xlated** | **pin** 28 *PROG-COMMANDS* := { **show** | **list** | **dump jited** | **dump xlated** | **pin**
29 | **load** | **help** } 29 | **load** | **help** }
30 30
31 *CGROUP-COMMANDS* := { **list** | **attach** | **detach** | **help** } 31 *CGROUP-COMMANDS* := { **show** | **list** | **attach** | **detach** | **help** }
32 32
33DESCRIPTION 33DESCRIPTION
34=========== 34===========
diff --git a/tools/bpf/bpftool/Makefile b/tools/bpf/bpftool/Makefile
index 3f17ad317512..2237bc43f71c 100644
--- a/tools/bpf/bpftool/Makefile
+++ b/tools/bpf/bpftool/Makefile
@@ -23,6 +23,8 @@ endif
23 23
24LIBBPF = $(BPF_PATH)libbpf.a 24LIBBPF = $(BPF_PATH)libbpf.a
25 25
26BPFTOOL_VERSION=$(shell make --no-print-directory -sC ../../.. kernelversion)
27
26$(LIBBPF): FORCE 28$(LIBBPF): FORCE
27 $(Q)$(MAKE) -C $(BPF_DIR) OUTPUT=$(OUTPUT) $(OUTPUT)libbpf.a FEATURES_DUMP=$(FEATURE_DUMP_EXPORT) 29 $(Q)$(MAKE) -C $(BPF_DIR) OUTPUT=$(OUTPUT) $(OUTPUT)libbpf.a FEATURES_DUMP=$(FEATURE_DUMP_EXPORT)
28 30
@@ -38,11 +40,36 @@ CC = gcc
38CFLAGS += -O2 40CFLAGS += -O2
39CFLAGS += -W -Wall -Wextra -Wno-unused-parameter -Wshadow 41CFLAGS += -W -Wall -Wextra -Wno-unused-parameter -Wshadow
40CFLAGS += -D__EXPORTED_HEADERS__ -I$(srctree)/tools/include/uapi -I$(srctree)/tools/include -I$(srctree)/tools/lib/bpf -I$(srctree)/kernel/bpf/ 42CFLAGS += -D__EXPORTED_HEADERS__ -I$(srctree)/tools/include/uapi -I$(srctree)/tools/include -I$(srctree)/tools/lib/bpf -I$(srctree)/kernel/bpf/
43CFLAGS += -DBPFTOOL_VERSION='"$(BPFTOOL_VERSION)"'
41LIBS = -lelf -lbfd -lopcodes $(LIBBPF) 44LIBS = -lelf -lbfd -lopcodes $(LIBBPF)
42 45
43INSTALL ?= install 46INSTALL ?= install
44RM ?= rm -f 47RM ?= rm -f
45 48
49FEATURE_USER = .bpftool
50FEATURE_TESTS = libbfd disassembler-four-args
51FEATURE_DISPLAY = libbfd disassembler-four-args
52
53check_feat := 1
54NON_CHECK_FEAT_TARGETS := clean uninstall doc doc-clean doc-install doc-uninstall
55ifdef MAKECMDGOALS
56ifeq ($(filter-out $(NON_CHECK_FEAT_TARGETS),$(MAKECMDGOALS)),)
57 check_feat := 0
58endif
59endif
60
61ifeq ($(check_feat),1)
62ifeq ($(FEATURES_DUMP),)
63include $(srctree)/tools/build/Makefile.feature
64else
65include $(FEATURES_DUMP)
66endif
67endif
68
69ifeq ($(feature-disassembler-four-args), 1)
70CFLAGS += -DDISASM_FOUR_ARGS_SIGNATURE
71endif
72
46include $(wildcard *.d) 73include $(wildcard *.d)
47 74
48all: $(OUTPUT)bpftool 75all: $(OUTPUT)bpftool
diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool
index 7febee05c8e7..0137866bb8f6 100644
--- a/tools/bpf/bpftool/bash-completion/bpftool
+++ b/tools/bpf/bpftool/bash-completion/bpftool
@@ -197,7 +197,7 @@ _bpftool()
197 197
198 local PROG_TYPE='id pinned tag' 198 local PROG_TYPE='id pinned tag'
199 case $command in 199 case $command in
200 show) 200 show|list)
201 [[ $prev != "$command" ]] && return 0 201 [[ $prev != "$command" ]] && return 0
202 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) ) 202 COMPREPLY=( $( compgen -W "$PROG_TYPE" -- "$cur" ) )
203 return 0 203 return 0
@@ -232,7 +232,7 @@ _bpftool()
232 ;; 232 ;;
233 *) 233 *)
234 [[ $prev == $object ]] && \ 234 [[ $prev == $object ]] && \
235 COMPREPLY=( $( compgen -W 'dump help pin show' -- \ 235 COMPREPLY=( $( compgen -W 'dump help pin show list' -- \
236 "$cur" ) ) 236 "$cur" ) )
237 ;; 237 ;;
238 esac 238 esac
@@ -240,7 +240,7 @@ _bpftool()
240 map) 240 map)
241 local MAP_TYPE='id pinned' 241 local MAP_TYPE='id pinned'
242 case $command in 242 case $command in
243 show|dump) 243 show|list|dump)
244 case $prev in 244 case $prev in
245 $command) 245 $command)
246 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) ) 246 COMPREPLY=( $( compgen -W "$MAP_TYPE" -- "$cur" ) )
@@ -343,7 +343,7 @@ _bpftool()
343 *) 343 *)
344 [[ $prev == $object ]] && \ 344 [[ $prev == $object ]] && \
345 COMPREPLY=( $( compgen -W 'delete dump getnext help \ 345 COMPREPLY=( $( compgen -W 'delete dump getnext help \
346 lookup pin show update' -- "$cur" ) ) 346 lookup pin show list update' -- "$cur" ) )
347 ;; 347 ;;
348 esac 348 esac
349 ;; 349 ;;
diff --git a/tools/bpf/bpftool/cgroup.c b/tools/bpf/bpftool/cgroup.c
index 34ca303d72bc..cae32a61cb18 100644
--- a/tools/bpf/bpftool/cgroup.c
+++ b/tools/bpf/bpftool/cgroup.c
@@ -41,7 +41,7 @@ static enum bpf_attach_type parse_attach_type(const char *str)
41 return __MAX_BPF_ATTACH_TYPE; 41 return __MAX_BPF_ATTACH_TYPE;
42} 42}
43 43
44static int list_bpf_prog(int id, const char *attach_type_str, 44static int show_bpf_prog(int id, const char *attach_type_str,
45 const char *attach_flags_str) 45 const char *attach_flags_str)
46{ 46{
47 struct bpf_prog_info info = {}; 47 struct bpf_prog_info info = {};
@@ -77,7 +77,7 @@ static int list_bpf_prog(int id, const char *attach_type_str,
77 return 0; 77 return 0;
78} 78}
79 79
80static int list_attached_bpf_progs(int cgroup_fd, enum bpf_attach_type type) 80static int show_attached_bpf_progs(int cgroup_fd, enum bpf_attach_type type)
81{ 81{
82 __u32 prog_ids[1024] = {0}; 82 __u32 prog_ids[1024] = {0};
83 char *attach_flags_str; 83 char *attach_flags_str;
@@ -111,29 +111,29 @@ static int list_attached_bpf_progs(int cgroup_fd, enum bpf_attach_type type)
111 } 111 }
112 112
113 for (iter = 0; iter < prog_cnt; iter++) 113 for (iter = 0; iter < prog_cnt; iter++)
114 list_bpf_prog(prog_ids[iter], attach_type_strings[type], 114 show_bpf_prog(prog_ids[iter], attach_type_strings[type],
115 attach_flags_str); 115 attach_flags_str);
116 116
117 return 0; 117 return 0;
118} 118}
119 119
120static int do_list(int argc, char **argv) 120static int do_show(int argc, char **argv)
121{ 121{
122 enum bpf_attach_type type; 122 enum bpf_attach_type type;
123 int cgroup_fd; 123 int cgroup_fd;
124 int ret = -1; 124 int ret = -1;
125 125
126 if (argc < 1) { 126 if (argc < 1) {
127 p_err("too few parameters for cgroup list\n"); 127 p_err("too few parameters for cgroup show");
128 goto exit; 128 goto exit;
129 } else if (argc > 1) { 129 } else if (argc > 1) {
130 p_err("too many parameters for cgroup list\n"); 130 p_err("too many parameters for cgroup show");
131 goto exit; 131 goto exit;
132 } 132 }
133 133
134 cgroup_fd = open(argv[0], O_RDONLY); 134 cgroup_fd = open(argv[0], O_RDONLY);
135 if (cgroup_fd < 0) { 135 if (cgroup_fd < 0) {
136 p_err("can't open cgroup %s\n", argv[1]); 136 p_err("can't open cgroup %s", argv[1]);
137 goto exit; 137 goto exit;
138 } 138 }
139 139
@@ -147,10 +147,10 @@ static int do_list(int argc, char **argv)
147 /* 147 /*
148 * Not all attach types may be supported, so it's expected, 148 * Not all attach types may be supported, so it's expected,
149 * that some requests will fail. 149 * that some requests will fail.
150 * If we were able to get the list for at least one 150 * If we were able to get the show for at least one
151 * attach type, let's return 0. 151 * attach type, let's return 0.
152 */ 152 */
153 if (list_attached_bpf_progs(cgroup_fd, type) == 0) 153 if (show_attached_bpf_progs(cgroup_fd, type) == 0)
154 ret = 0; 154 ret = 0;
155 } 155 }
156 156
@@ -171,19 +171,19 @@ static int do_attach(int argc, char **argv)
171 int i; 171 int i;
172 172
173 if (argc < 4) { 173 if (argc < 4) {
174 p_err("too few parameters for cgroup attach\n"); 174 p_err("too few parameters for cgroup attach");
175 goto exit; 175 goto exit;
176 } 176 }
177 177
178 cgroup_fd = open(argv[0], O_RDONLY); 178 cgroup_fd = open(argv[0], O_RDONLY);
179 if (cgroup_fd < 0) { 179 if (cgroup_fd < 0) {
180 p_err("can't open cgroup %s\n", argv[1]); 180 p_err("can't open cgroup %s", argv[1]);
181 goto exit; 181 goto exit;
182 } 182 }
183 183
184 attach_type = parse_attach_type(argv[1]); 184 attach_type = parse_attach_type(argv[1]);
185 if (attach_type == __MAX_BPF_ATTACH_TYPE) { 185 if (attach_type == __MAX_BPF_ATTACH_TYPE) {
186 p_err("invalid attach type\n"); 186 p_err("invalid attach type");
187 goto exit_cgroup; 187 goto exit_cgroup;
188 } 188 }
189 189
@@ -199,7 +199,7 @@ static int do_attach(int argc, char **argv)
199 } else if (is_prefix(argv[i], "override")) { 199 } else if (is_prefix(argv[i], "override")) {
200 attach_flags |= BPF_F_ALLOW_OVERRIDE; 200 attach_flags |= BPF_F_ALLOW_OVERRIDE;
201 } else { 201 } else {
202 p_err("unknown option: %s\n", argv[i]); 202 p_err("unknown option: %s", argv[i]);
203 goto exit_cgroup; 203 goto exit_cgroup;
204 } 204 }
205 } 205 }
@@ -229,13 +229,13 @@ static int do_detach(int argc, char **argv)
229 int ret = -1; 229 int ret = -1;
230 230
231 if (argc < 4) { 231 if (argc < 4) {
232 p_err("too few parameters for cgroup detach\n"); 232 p_err("too few parameters for cgroup detach");
233 goto exit; 233 goto exit;
234 } 234 }
235 235
236 cgroup_fd = open(argv[0], O_RDONLY); 236 cgroup_fd = open(argv[0], O_RDONLY);
237 if (cgroup_fd < 0) { 237 if (cgroup_fd < 0) {
238 p_err("can't open cgroup %s\n", argv[1]); 238 p_err("can't open cgroup %s", argv[1]);
239 goto exit; 239 goto exit;
240 } 240 }
241 241
@@ -277,7 +277,7 @@ static int do_help(int argc, char **argv)
277 } 277 }
278 278
279 fprintf(stderr, 279 fprintf(stderr,
280 "Usage: %s %s list CGROUP\n" 280 "Usage: %s %s { show | list } CGROUP\n"
281 " %s %s attach CGROUP ATTACH_TYPE PROG [ATTACH_FLAGS]\n" 281 " %s %s attach CGROUP ATTACH_TYPE PROG [ATTACH_FLAGS]\n"
282 " %s %s detach CGROUP ATTACH_TYPE PROG\n" 282 " %s %s detach CGROUP ATTACH_TYPE PROG\n"
283 " %s %s help\n" 283 " %s %s help\n"
@@ -294,7 +294,8 @@ static int do_help(int argc, char **argv)
294} 294}
295 295
296static const struct cmd cmds[] = { 296static const struct cmd cmds[] = {
297 { "list", do_list }, 297 { "show", do_show },
298 { "list", do_show },
298 { "attach", do_attach }, 299 { "attach", do_attach },
299 { "detach", do_detach }, 300 { "detach", do_detach },
300 { "help", do_help }, 301 { "help", do_help },
diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c
index b62c94e3997a..6601c95a9258 100644
--- a/tools/bpf/bpftool/common.c
+++ b/tools/bpf/bpftool/common.c
@@ -44,7 +44,9 @@
44#include <unistd.h> 44#include <unistd.h>
45#include <linux/limits.h> 45#include <linux/limits.h>
46#include <linux/magic.h> 46#include <linux/magic.h>
47#include <net/if.h>
47#include <sys/mount.h> 48#include <sys/mount.h>
49#include <sys/stat.h>
48#include <sys/types.h> 50#include <sys/types.h>
49#include <sys/vfs.h> 51#include <sys/vfs.h>
50 52
@@ -412,3 +414,53 @@ void delete_pinned_obj_table(struct pinned_obj_table *tab)
412 free(obj); 414 free(obj);
413 } 415 }
414} 416}
417
418static char *
419ifindex_to_name_ns(__u32 ifindex, __u32 ns_dev, __u32 ns_ino, char *buf)
420{
421 struct stat st;
422 int err;
423
424 err = stat("/proc/self/ns/net", &st);
425 if (err) {
426 p_err("Can't stat /proc/self: %s", strerror(errno));
427 return NULL;
428 }
429
430 if (st.st_dev != ns_dev || st.st_ino != ns_ino)
431 return NULL;
432
433 return if_indextoname(ifindex, buf);
434}
435
436void print_dev_plain(__u32 ifindex, __u64 ns_dev, __u64 ns_inode)
437{
438 char name[IF_NAMESIZE];
439
440 if (!ifindex)
441 return;
442
443 printf(" dev ");
444 if (ifindex_to_name_ns(ifindex, ns_dev, ns_inode, name))
445 printf("%s", name);
446 else
447 printf("ifindex %u ns_dev %llu ns_ino %llu",
448 ifindex, ns_dev, ns_inode);
449}
450
451void print_dev_json(__u32 ifindex, __u64 ns_dev, __u64 ns_inode)
452{
453 char name[IF_NAMESIZE];
454
455 if (!ifindex)
456 return;
457
458 jsonw_name(json_wtr, "dev");
459 jsonw_start_object(json_wtr);
460 jsonw_uint_field(json_wtr, "ifindex", ifindex);
461 jsonw_uint_field(json_wtr, "ns_dev", ns_dev);
462 jsonw_uint_field(json_wtr, "ns_inode", ns_inode);
463 if (ifindex_to_name_ns(ifindex, ns_dev, ns_inode, name))
464 jsonw_string_field(json_wtr, "ifname", name);
465 jsonw_end_object(json_wtr);
466}
diff --git a/tools/bpf/bpftool/jit_disasm.c b/tools/bpf/bpftool/jit_disasm.c
index 1551d3918d4c..57d32e8a1391 100644
--- a/tools/bpf/bpftool/jit_disasm.c
+++ b/tools/bpf/bpftool/jit_disasm.c
@@ -107,7 +107,14 @@ void disasm_print_insn(unsigned char *image, ssize_t len, int opcodes)
107 107
108 disassemble_init_for_target(&info); 108 disassemble_init_for_target(&info);
109 109
110#ifdef DISASM_FOUR_ARGS_SIGNATURE
111 disassemble = disassembler(info.arch,
112 bfd_big_endian(bfdf),
113 info.mach,
114 bfdf);
115#else
110 disassemble = disassembler(bfdf); 116 disassemble = disassembler(bfdf);
117#endif
111 assert(disassemble); 118 assert(disassemble);
112 119
113 if (json_output) 120 if (json_output)
diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c
index ecd53ccf1239..3a0396d87c42 100644
--- a/tools/bpf/bpftool/main.c
+++ b/tools/bpf/bpftool/main.c
@@ -38,7 +38,6 @@
38#include <errno.h> 38#include <errno.h>
39#include <getopt.h> 39#include <getopt.h>
40#include <linux/bpf.h> 40#include <linux/bpf.h>
41#include <linux/version.h>
42#include <stdio.h> 41#include <stdio.h>
43#include <stdlib.h> 42#include <stdlib.h>
44#include <string.h> 43#include <string.h>
@@ -95,21 +94,13 @@ static int do_help(int argc, char **argv)
95 94
96static int do_version(int argc, char **argv) 95static int do_version(int argc, char **argv)
97{ 96{
98 unsigned int version[3];
99
100 version[0] = LINUX_VERSION_CODE >> 16;
101 version[1] = LINUX_VERSION_CODE >> 8 & 0xf;
102 version[2] = LINUX_VERSION_CODE & 0xf;
103
104 if (json_output) { 97 if (json_output) {
105 jsonw_start_object(json_wtr); 98 jsonw_start_object(json_wtr);
106 jsonw_name(json_wtr, "version"); 99 jsonw_name(json_wtr, "version");
107 jsonw_printf(json_wtr, "\"%u.%u.%u\"", 100 jsonw_printf(json_wtr, "\"%s\"", BPFTOOL_VERSION);
108 version[0], version[1], version[2]);
109 jsonw_end_object(json_wtr); 101 jsonw_end_object(json_wtr);
110 } else { 102 } else {
111 printf("%s v%u.%u.%u\n", bin_name, 103 printf("%s v%s\n", bin_name, BPFTOOL_VERSION);
112 version[0], version[1], version[2]);
113 } 104 }
114 return 0; 105 return 0;
115} 106}
diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h
index 8f6d3cac0347..65b526fe6e7e 100644
--- a/tools/bpf/bpftool/main.h
+++ b/tools/bpf/bpftool/main.h
@@ -96,6 +96,8 @@ struct pinned_obj {
96int build_pinned_obj_table(struct pinned_obj_table *table, 96int build_pinned_obj_table(struct pinned_obj_table *table,
97 enum bpf_obj_type type); 97 enum bpf_obj_type type);
98void delete_pinned_obj_table(struct pinned_obj_table *tab); 98void delete_pinned_obj_table(struct pinned_obj_table *tab);
99void print_dev_plain(__u32 ifindex, __u64 ns_dev, __u64 ns_inode);
100void print_dev_json(__u32 ifindex, __u64 ns_dev, __u64 ns_inode);
99 101
100struct cmd { 102struct cmd {
101 const char *cmd; 103 const char *cmd;
diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c
index a8c3a33dd185..8d7db9d6b9cd 100644
--- a/tools/bpf/bpftool/map.c
+++ b/tools/bpf/bpftool/map.c
@@ -861,7 +861,7 @@ static int do_help(int argc, char **argv)
861 } 861 }
862 862
863 fprintf(stderr, 863 fprintf(stderr,
864 "Usage: %s %s show [MAP]\n" 864 "Usage: %s %s { show | list } [MAP]\n"
865 " %s %s dump MAP\n" 865 " %s %s dump MAP\n"
866 " %s %s update MAP key BYTES value VALUE [UPDATE_FLAGS]\n" 866 " %s %s update MAP key BYTES value VALUE [UPDATE_FLAGS]\n"
867 " %s %s lookup MAP key BYTES\n" 867 " %s %s lookup MAP key BYTES\n"
@@ -885,6 +885,7 @@ static int do_help(int argc, char **argv)
885 885
886static const struct cmd cmds[] = { 886static const struct cmd cmds[] = {
887 { "show", do_show }, 887 { "show", do_show },
888 { "list", do_show },
888 { "help", do_help }, 889 { "help", do_help },
889 { "dump", do_dump }, 890 { "dump", do_dump },
890 { "update", do_update }, 891 { "update", do_update },
diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
index fd0873178503..c6a28be4665c 100644
--- a/tools/bpf/bpftool/prog.c
+++ b/tools/bpf/bpftool/prog.c
@@ -230,6 +230,8 @@ static void print_prog_json(struct bpf_prog_info *info, int fd)
230 info->tag[0], info->tag[1], info->tag[2], info->tag[3], 230 info->tag[0], info->tag[1], info->tag[2], info->tag[3],
231 info->tag[4], info->tag[5], info->tag[6], info->tag[7]); 231 info->tag[4], info->tag[5], info->tag[6], info->tag[7]);
232 232
233 print_dev_json(info->ifindex, info->netns_dev, info->netns_ino);
234
233 if (info->load_time) { 235 if (info->load_time) {
234 char buf[32]; 236 char buf[32];
235 237
@@ -287,6 +289,7 @@ static void print_prog_plain(struct bpf_prog_info *info, int fd)
287 289
288 printf("tag "); 290 printf("tag ");
289 fprint_hex(stdout, info->tag, BPF_TAG_SIZE, ""); 291 fprint_hex(stdout, info->tag, BPF_TAG_SIZE, "");
292 print_dev_plain(info->ifindex, info->netns_dev, info->netns_ino);
290 printf("\n"); 293 printf("\n");
291 294
292 if (info->load_time) { 295 if (info->load_time) {
@@ -810,12 +813,12 @@ static int do_load(int argc, char **argv)
810 usage(); 813 usage();
811 814
812 if (bpf_prog_load(argv[0], BPF_PROG_TYPE_UNSPEC, &obj, &prog_fd)) { 815 if (bpf_prog_load(argv[0], BPF_PROG_TYPE_UNSPEC, &obj, &prog_fd)) {
813 p_err("failed to load program\n"); 816 p_err("failed to load program");
814 return -1; 817 return -1;
815 } 818 }
816 819
817 if (do_pin_fd(prog_fd, argv[1])) { 820 if (do_pin_fd(prog_fd, argv[1])) {
818 p_err("failed to pin program\n"); 821 p_err("failed to pin program");
819 return -1; 822 return -1;
820 } 823 }
821 824
@@ -833,7 +836,7 @@ static int do_help(int argc, char **argv)
833 } 836 }
834 837
835 fprintf(stderr, 838 fprintf(stderr,
836 "Usage: %s %s show [PROG]\n" 839 "Usage: %s %s { show | list } [PROG]\n"
837 " %s %s dump xlated PROG [{ file FILE | opcodes }]\n" 840 " %s %s dump xlated PROG [{ file FILE | opcodes }]\n"
838 " %s %s dump jited PROG [{ file FILE | opcodes }]\n" 841 " %s %s dump jited PROG [{ file FILE | opcodes }]\n"
839 " %s %s pin PROG FILE\n" 842 " %s %s pin PROG FILE\n"
@@ -851,6 +854,7 @@ static int do_help(int argc, char **argv)
851 854
852static const struct cmd cmds[] = { 855static const struct cmd cmds[] = {
853 { "show", do_show }, 856 { "show", do_show },
857 { "list", do_show },
854 { "help", do_help }, 858 { "help", do_help },
855 { "dump", do_dump }, 859 { "dump", do_dump },
856 { "pin", do_pin }, 860 { "pin", do_pin },
diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index 96982640fbf8..17f2c73fff8b 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -13,6 +13,7 @@ FILES= \
13 test-hello.bin \ 13 test-hello.bin \
14 test-libaudit.bin \ 14 test-libaudit.bin \
15 test-libbfd.bin \ 15 test-libbfd.bin \
16 test-disassembler-four-args.bin \
16 test-liberty.bin \ 17 test-liberty.bin \
17 test-liberty-z.bin \ 18 test-liberty-z.bin \
18 test-cplus-demangle.bin \ 19 test-cplus-demangle.bin \
@@ -188,6 +189,9 @@ $(OUTPUT)test-libpython-version.bin:
188$(OUTPUT)test-libbfd.bin: 189$(OUTPUT)test-libbfd.bin:
189 $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl 190 $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl
190 191
192$(OUTPUT)test-disassembler-four-args.bin:
193 $(BUILD) -lbfd -lopcodes
194
191$(OUTPUT)test-liberty.bin: 195$(OUTPUT)test-liberty.bin:
192 $(CC) $(CFLAGS) -Wall -Werror -o $@ test-libbfd.c -DPACKAGE='"perf"' $(LDFLAGS) -lbfd -ldl -liberty 196 $(CC) $(CFLAGS) -Wall -Werror -o $@ test-libbfd.c -DPACKAGE='"perf"' $(LDFLAGS) -lbfd -ldl -liberty
193 197
diff --git a/tools/build/feature/test-disassembler-four-args.c b/tools/build/feature/test-disassembler-four-args.c
new file mode 100644
index 000000000000..45ce65cfddf0
--- /dev/null
+++ b/tools/build/feature/test-disassembler-four-args.c
@@ -0,0 +1,15 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <bfd.h>
3#include <dis-asm.h>
4
5int main(void)
6{
7 bfd *abfd = bfd_openr(NULL, NULL);
8
9 disassembler(bfd_get_arch(abfd),
10 bfd_big_endian(abfd),
11 bfd_get_mach(abfd),
12 abfd);
13
14 return 0;
15}
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index db1b0923a308..4e8c60acfa32 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -921,6 +921,9 @@ struct bpf_prog_info {
921 __u32 nr_map_ids; 921 __u32 nr_map_ids;
922 __aligned_u64 map_ids; 922 __aligned_u64 map_ids;
923 char name[BPF_OBJ_NAME_LEN]; 923 char name[BPF_OBJ_NAME_LEN];
924 __u32 ifindex;
925 __u64 netns_dev;
926 __u64 netns_ino;
924} __attribute__((aligned(8))); 927} __attribute__((aligned(8)));
925 928
926struct bpf_map_info { 929struct bpf_map_info {
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 1304753d29ea..a8aa7e251c8e 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -19,7 +19,7 @@ TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test
19TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test_obj_id.o \ 19TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test_obj_id.o \
20 test_pkt_md_access.o test_xdp_redirect.o test_xdp_meta.o sockmap_parse_prog.o \ 20 test_pkt_md_access.o test_xdp_redirect.o test_xdp_meta.o sockmap_parse_prog.o \
21 sockmap_verdict_prog.o dev_cgroup.o sample_ret0.o test_tracepoint.o \ 21 sockmap_verdict_prog.o dev_cgroup.o sample_ret0.o test_tracepoint.o \
22 test_l4lb_noinline.o test_xdp_noinline.o 22 test_l4lb_noinline.o test_xdp_noinline.o test_stacktrace_map.o
23 23
24TEST_PROGS := test_kmod.sh test_xdp_redirect.sh test_xdp_meta.sh \ 24TEST_PROGS := test_kmod.sh test_xdp_redirect.sh test_xdp_meta.sh \
25 test_offload.py 25 test_offload.py
diff --git a/tools/testing/selftests/bpf/test_offload.py b/tools/testing/selftests/bpf/test_offload.py
index c940505c2978..e3c750f17cb8 100755
--- a/tools/testing/selftests/bpf/test_offload.py
+++ b/tools/testing/selftests/bpf/test_offload.py
@@ -18,6 +18,8 @@ import argparse
18import json 18import json
19import os 19import os
20import pprint 20import pprint
21import random
22import string
21import subprocess 23import subprocess
22import time 24import time
23 25
@@ -27,6 +29,7 @@ bpf_test_dir = os.path.dirname(os.path.realpath(__file__))
27pp = pprint.PrettyPrinter() 29pp = pprint.PrettyPrinter()
28devs = [] # devices we created for clean up 30devs = [] # devices we created for clean up
29files = [] # files to be removed 31files = [] # files to be removed
32netns = [] # net namespaces to be removed
30 33
31def log_get_sec(level=0): 34def log_get_sec(level=0):
32 return "*" * (log_level + level) 35 return "*" * (log_level + level)
@@ -128,22 +131,25 @@ def rm(f):
128 if f in files: 131 if f in files:
129 files.remove(f) 132 files.remove(f)
130 133
131def tool(name, args, flags, JSON=True, fail=True): 134def tool(name, args, flags, JSON=True, ns="", fail=True):
132 params = "" 135 params = ""
133 if JSON: 136 if JSON:
134 params += "%s " % (flags["json"]) 137 params += "%s " % (flags["json"])
135 138
136 ret, out = cmd(name + " " + params + args, fail=fail) 139 if ns != "":
140 ns = "ip netns exec %s " % (ns)
141
142 ret, out = cmd(ns + name + " " + params + args, fail=fail)
137 if JSON and len(out.strip()) != 0: 143 if JSON and len(out.strip()) != 0:
138 return ret, json.loads(out) 144 return ret, json.loads(out)
139 else: 145 else:
140 return ret, out 146 return ret, out
141 147
142def bpftool(args, JSON=True, fail=True): 148def bpftool(args, JSON=True, ns="", fail=True):
143 return tool("bpftool", args, {"json":"-p"}, JSON=JSON, fail=fail) 149 return tool("bpftool", args, {"json":"-p"}, JSON=JSON, ns=ns, fail=fail)
144 150
145def bpftool_prog_list(expected=None): 151def bpftool_prog_list(expected=None, ns=""):
146 _, progs = bpftool("prog show", JSON=True, fail=True) 152 _, progs = bpftool("prog show", JSON=True, ns=ns, fail=True)
147 if expected is not None: 153 if expected is not None:
148 if len(progs) != expected: 154 if len(progs) != expected:
149 fail(True, "%d BPF programs loaded, expected %d" % 155 fail(True, "%d BPF programs loaded, expected %d" %
@@ -158,13 +164,13 @@ def bpftool_prog_list_wait(expected=0, n_retry=20):
158 time.sleep(0.05) 164 time.sleep(0.05)
159 raise Exception("Time out waiting for program counts to stabilize want %d, have %d" % (expected, nprogs)) 165 raise Exception("Time out waiting for program counts to stabilize want %d, have %d" % (expected, nprogs))
160 166
161def ip(args, force=False, JSON=True, fail=True): 167def ip(args, force=False, JSON=True, ns="", fail=True):
162 if force: 168 if force:
163 args = "-force " + args 169 args = "-force " + args
164 return tool("ip", args, {"json":"-j"}, JSON=JSON, fail=fail) 170 return tool("ip", args, {"json":"-j"}, JSON=JSON, ns=ns, fail=fail)
165 171
166def tc(args, JSON=True, fail=True): 172def tc(args, JSON=True, ns="", fail=True):
167 return tool("tc", args, {"json":"-p"}, JSON=JSON, fail=fail) 173 return tool("tc", args, {"json":"-p"}, JSON=JSON, ns=ns, fail=fail)
168 174
169def ethtool(dev, opt, args, fail=True): 175def ethtool(dev, opt, args, fail=True):
170 return cmd("ethtool %s %s %s" % (opt, dev["ifname"], args), fail=fail) 176 return cmd("ethtool %s %s %s" % (opt, dev["ifname"], args), fail=fail)
@@ -178,6 +184,15 @@ def bpf_pinned(name):
178def bpf_bytecode(bytecode): 184def bpf_bytecode(bytecode):
179 return "bytecode \"%s\"" % (bytecode) 185 return "bytecode \"%s\"" % (bytecode)
180 186
187def mknetns(n_retry=10):
188 for i in range(n_retry):
189 name = ''.join([random.choice(string.ascii_letters) for i in range(8)])
190 ret, _ = ip("netns add %s" % (name), fail=False)
191 if ret == 0:
192 netns.append(name)
193 return name
194 return None
195
181class DebugfsDir: 196class DebugfsDir:
182 """ 197 """
183 Class for accessing DebugFS directories as a dictionary. 198 Class for accessing DebugFS directories as a dictionary.
@@ -237,6 +252,8 @@ class NetdevSim:
237 self.dev = self._netdevsim_create() 252 self.dev = self._netdevsim_create()
238 devs.append(self) 253 devs.append(self)
239 254
255 self.ns = ""
256
240 self.dfs_dir = '/sys/kernel/debug/netdevsim/%s' % (self.dev['ifname']) 257 self.dfs_dir = '/sys/kernel/debug/netdevsim/%s' % (self.dev['ifname'])
241 self.dfs_refresh() 258 self.dfs_refresh()
242 259
@@ -257,7 +274,7 @@ class NetdevSim:
257 274
258 def remove(self): 275 def remove(self):
259 devs.remove(self) 276 devs.remove(self)
260 ip("link del dev %s" % (self.dev["ifname"])) 277 ip("link del dev %s" % (self.dev["ifname"]), ns=self.ns)
261 278
262 def dfs_refresh(self): 279 def dfs_refresh(self):
263 self.dfs = DebugfsDir(self.dfs_dir) 280 self.dfs = DebugfsDir(self.dfs_dir)
@@ -285,6 +302,11 @@ class NetdevSim:
285 time.sleep(0.05) 302 time.sleep(0.05)
286 raise Exception("Time out waiting for program counts to stabilize want %d/%d, have %d bound, %d loaded" % (bound, total, nbound, nprogs)) 303 raise Exception("Time out waiting for program counts to stabilize want %d/%d, have %d bound, %d loaded" % (bound, total, nbound, nprogs))
287 304
305 def set_ns(self, ns):
306 name = "1" if ns == "" else ns
307 ip("link set dev %s netns %s" % (self.dev["ifname"], name), ns=self.ns)
308 self.ns = ns
309
288 def set_mtu(self, mtu, fail=True): 310 def set_mtu(self, mtu, fail=True):
289 return ip("link set dev %s mtu %d" % (self.dev["ifname"], mtu), 311 return ip("link set dev %s mtu %d" % (self.dev["ifname"], mtu),
290 fail=fail) 312 fail=fail)
@@ -372,6 +394,8 @@ def clean_up():
372 dev.remove() 394 dev.remove()
373 for f in files: 395 for f in files:
374 cmd("rm -f %s" % (f)) 396 cmd("rm -f %s" % (f))
397 for ns in netns:
398 cmd("ip netns delete %s" % (ns))
375 399
376def pin_prog(file_name, idx=0): 400def pin_prog(file_name, idx=0):
377 progs = bpftool_prog_list(expected=(idx + 1)) 401 progs = bpftool_prog_list(expected=(idx + 1))
@@ -381,6 +405,35 @@ def pin_prog(file_name, idx=0):
381 405
382 return file_name, bpf_pinned(file_name) 406 return file_name, bpf_pinned(file_name)
383 407
408def check_dev_info(other_ns, ns, pin_file=None, removed=False):
409 if removed:
410 bpftool_prog_list(expected=0)
411 ret, err = bpftool("prog show pin %s" % (pin_file), fail=False)
412 fail(ret == 0, "Showing prog with removed device did not fail")
413 fail(err["error"].find("No such device") == -1,
414 "Showing prog with removed device expected ENODEV, error is %s" %
415 (err["error"]))
416 return
417 progs = bpftool_prog_list(expected=int(not removed), ns=ns)
418 prog = progs[0]
419
420 fail("dev" not in prog.keys(), "Device parameters not reported")
421 dev = prog["dev"]
422 fail("ifindex" not in dev.keys(), "Device parameters not reported")
423 fail("ns_dev" not in dev.keys(), "Device parameters not reported")
424 fail("ns_inode" not in dev.keys(), "Device parameters not reported")
425
426 if not removed and not other_ns:
427 fail("ifname" not in dev.keys(), "Ifname not reported")
428 fail(dev["ifname"] != sim["ifname"],
429 "Ifname incorrect %s vs %s" % (dev["ifname"], sim["ifname"]))
430 else:
431 fail("ifname" in dev.keys(), "Ifname is reported for other ns")
432 if removed:
433 fail(dev["ifindex"] != 0, "Device perameters not zero on removed")
434 fail(dev["ns_dev"] != 0, "Device perameters not zero on removed")
435 fail(dev["ns_inode"] != 0, "Device perameters not zero on removed")
436
384# Parse command line 437# Parse command line
385parser = argparse.ArgumentParser() 438parser = argparse.ArgumentParser()
386parser.add_argument("--log", help="output verbose log to given file") 439parser.add_argument("--log", help="output verbose log to given file")
@@ -417,6 +470,12 @@ for s in samples:
417 skip(ret != 0, "sample %s/%s not found, please compile it" % 470 skip(ret != 0, "sample %s/%s not found, please compile it" %
418 (bpf_test_dir, s)) 471 (bpf_test_dir, s))
419 472
473# Check if net namespaces seem to work
474ns = mknetns()
475skip(ns is None, "Could not create a net namespace")
476cmd("ip netns delete %s" % (ns))
477netns = []
478
420try: 479try:
421 obj = bpf_obj("sample_ret0.o") 480 obj = bpf_obj("sample_ret0.o")
422 bytecode = bpf_bytecode("1,6 0 0 4294967295,") 481 bytecode = bpf_bytecode("1,6 0 0 4294967295,")
@@ -549,6 +608,8 @@ try:
549 progs = bpftool_prog_list(expected=1) 608 progs = bpftool_prog_list(expected=1)
550 fail(ipl["xdp"]["prog"]["id"] != progs[0]["id"], 609 fail(ipl["xdp"]["prog"]["id"] != progs[0]["id"],
551 "Loaded program has wrong ID") 610 "Loaded program has wrong ID")
611 fail("dev" in progs[0].keys(),
612 "Device parameters reported for non-offloaded program")
552 613
553 start_test("Test XDP prog replace with bad flags...") 614 start_test("Test XDP prog replace with bad flags...")
554 ret, _ = sim.set_xdp(obj, "offload", force=True, fail=False) 615 ret, _ = sim.set_xdp(obj, "offload", force=True, fail=False)
@@ -673,6 +734,35 @@ try:
673 fail(time_diff < delay_sec, "Removal process took %s, expected %s" % 734 fail(time_diff < delay_sec, "Removal process took %s, expected %s" %
674 (time_diff, delay_sec)) 735 (time_diff, delay_sec))
675 736
737 # Remove all pinned files and reinstantiate the netdev
738 clean_up()
739 bpftool_prog_list_wait(expected=0)
740
741 sim = NetdevSim()
742 sim.set_ethtool_tc_offloads(True)
743 sim.set_xdp(obj, "offload")
744
745 start_test("Test bpftool bound info reporting (own ns)...")
746 check_dev_info(False, "")
747
748 start_test("Test bpftool bound info reporting (other ns)...")
749 ns = mknetns()
750 sim.set_ns(ns)
751 check_dev_info(True, "")
752
753 start_test("Test bpftool bound info reporting (remote ns)...")
754 check_dev_info(False, ns)
755
756 start_test("Test bpftool bound info reporting (back to own ns)...")
757 sim.set_ns("")
758 check_dev_info(False, "")
759
760 pin_file, _ = pin_prog("/sys/fs/bpf/tmp")
761 sim.remove()
762
763 start_test("Test bpftool bound info reporting (removed dev)...")
764 check_dev_info(True, "", pin_file=pin_file, removed=True)
765
676 print("%s: OK" % (os.path.basename(__file__))) 766 print("%s: OK" % (os.path.basename(__file__)))
677 767
678finally: 768finally:
diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c
index 09087ab12293..b549308abd19 100644
--- a/tools/testing/selftests/bpf/test_progs.c
+++ b/tools/testing/selftests/bpf/test_progs.c
@@ -837,6 +837,132 @@ static void test_tp_attach_query(void)
837 free(query); 837 free(query);
838} 838}
839 839
840static int compare_map_keys(int map1_fd, int map2_fd)
841{
842 __u32 key, next_key;
843 char val_buf[PERF_MAX_STACK_DEPTH * sizeof(__u64)];
844 int err;
845
846 err = bpf_map_get_next_key(map1_fd, NULL, &key);
847 if (err)
848 return err;
849 err = bpf_map_lookup_elem(map2_fd, &key, val_buf);
850 if (err)
851 return err;
852
853 while (bpf_map_get_next_key(map1_fd, &key, &next_key) == 0) {
854 err = bpf_map_lookup_elem(map2_fd, &next_key, val_buf);
855 if (err)
856 return err;
857
858 key = next_key;
859 }
860 if (errno != ENOENT)
861 return -1;
862
863 return 0;
864}
865
866static void test_stacktrace_map()
867{
868 int control_map_fd, stackid_hmap_fd, stackmap_fd;
869 const char *file = "./test_stacktrace_map.o";
870 int bytes, efd, err, pmu_fd, prog_fd;
871 struct perf_event_attr attr = {};
872 __u32 key, val, duration = 0;
873 struct bpf_object *obj;
874 char buf[256];
875
876 err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd);
877 if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno))
878 goto out;
879
880 /* Get the ID for the sched/sched_switch tracepoint */
881 snprintf(buf, sizeof(buf),
882 "/sys/kernel/debug/tracing/events/sched/sched_switch/id");
883 efd = open(buf, O_RDONLY, 0);
884 if (CHECK(efd < 0, "open", "err %d errno %d\n", efd, errno))
885 goto close_prog;
886
887 bytes = read(efd, buf, sizeof(buf));
888 close(efd);
889 if (CHECK(bytes <= 0 || bytes >= sizeof(buf),
890 "read", "bytes %d errno %d\n", bytes, errno))
891 goto close_prog;
892
893 /* Open the perf event and attach bpf progrram */
894 attr.config = strtol(buf, NULL, 0);
895 attr.type = PERF_TYPE_TRACEPOINT;
896 attr.sample_type = PERF_SAMPLE_RAW | PERF_SAMPLE_CALLCHAIN;
897 attr.sample_period = 1;
898 attr.wakeup_events = 1;
899 pmu_fd = syscall(__NR_perf_event_open, &attr, -1 /* pid */,
900 0 /* cpu 0 */, -1 /* group id */,
901 0 /* flags */);
902 if (CHECK(pmu_fd < 0, "perf_event_open", "err %d errno %d\n",
903 pmu_fd, errno))
904 goto close_prog;
905
906 err = ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0);
907 if (CHECK(err, "perf_event_ioc_enable", "err %d errno %d\n",
908 err, errno))
909 goto close_pmu;
910
911 err = ioctl(pmu_fd, PERF_EVENT_IOC_SET_BPF, prog_fd);
912 if (CHECK(err, "perf_event_ioc_set_bpf", "err %d errno %d\n",
913 err, errno))
914 goto disable_pmu;
915
916 /* find map fds */
917 control_map_fd = bpf_find_map(__func__, obj, "control_map");
918 if (CHECK(control_map_fd < 0, "bpf_find_map control_map",
919 "err %d errno %d\n", err, errno))
920 goto disable_pmu;
921
922 stackid_hmap_fd = bpf_find_map(__func__, obj, "stackid_hmap");
923 if (CHECK(stackid_hmap_fd < 0, "bpf_find_map stackid_hmap",
924 "err %d errno %d\n", err, errno))
925 goto disable_pmu;
926
927 stackmap_fd = bpf_find_map(__func__, obj, "stackmap");
928 if (CHECK(stackmap_fd < 0, "bpf_find_map stackmap", "err %d errno %d\n",
929 err, errno))
930 goto disable_pmu;
931
932 /* give some time for bpf program run */
933 sleep(1);
934
935 /* disable stack trace collection */
936 key = 0;
937 val = 1;
938 bpf_map_update_elem(control_map_fd, &key, &val, 0);
939
940 /* for every element in stackid_hmap, we can find a corresponding one
941 * in stackmap, and vise versa.
942 */
943 err = compare_map_keys(stackid_hmap_fd, stackmap_fd);
944 if (CHECK(err, "compare_map_keys stackid_hmap vs. stackmap",
945 "err %d errno %d\n", err, errno))
946 goto disable_pmu;
947
948 err = compare_map_keys(stackmap_fd, stackid_hmap_fd);
949 if (CHECK(err, "compare_map_keys stackmap vs. stackid_hmap",
950 "err %d errno %d\n", err, errno))
951 ; /* fall through */
952
953disable_pmu:
954 ioctl(pmu_fd, PERF_EVENT_IOC_DISABLE);
955
956close_pmu:
957 close(pmu_fd);
958
959close_prog:
960 bpf_object__close(obj);
961
962out:
963 return;
964}
965
840int main(void) 966int main(void)
841{ 967{
842 struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY }; 968 struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
@@ -852,6 +978,7 @@ int main(void)
852 test_pkt_md_access(); 978 test_pkt_md_access();
853 test_obj_name(); 979 test_obj_name();
854 test_tp_attach_query(); 980 test_tp_attach_query();
981 test_stacktrace_map();
855 982
856 printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, error_cnt); 983 printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, error_cnt);
857 return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS; 984 return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS;
diff --git a/tools/testing/selftests/bpf/test_stacktrace_map.c b/tools/testing/selftests/bpf/test_stacktrace_map.c
new file mode 100644
index 000000000000..76d85c5d08bd
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_stacktrace_map.c
@@ -0,0 +1,62 @@
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2018 Facebook
3
4#include <linux/bpf.h>
5#include "bpf_helpers.h"
6
7#ifndef PERF_MAX_STACK_DEPTH
8#define PERF_MAX_STACK_DEPTH 127
9#endif
10
11struct bpf_map_def SEC("maps") control_map = {
12 .type = BPF_MAP_TYPE_ARRAY,
13 .key_size = sizeof(__u32),
14 .value_size = sizeof(__u32),
15 .max_entries = 1,
16};
17
18struct bpf_map_def SEC("maps") stackid_hmap = {
19 .type = BPF_MAP_TYPE_HASH,
20 .key_size = sizeof(__u32),
21 .value_size = sizeof(__u32),
22 .max_entries = 10000,
23};
24
25struct bpf_map_def SEC("maps") stackmap = {
26 .type = BPF_MAP_TYPE_STACK_TRACE,
27 .key_size = sizeof(__u32),
28 .value_size = sizeof(__u64) * PERF_MAX_STACK_DEPTH,
29 .max_entries = 10000,
30};
31
32/* taken from /sys/kernel/debug/tracing/events/sched/sched_switch/format */
33struct sched_switch_args {
34 unsigned long long pad;
35 char prev_comm[16];
36 int prev_pid;
37 int prev_prio;
38 long long prev_state;
39 char next_comm[16];
40 int next_pid;
41 int next_prio;
42};
43
44SEC("tracepoint/sched/sched_switch")
45int oncpu(struct sched_switch_args *ctx)
46{
47 __u32 key = 0, val = 0, *value_p;
48
49 value_p = bpf_map_lookup_elem(&control_map, &key);
50 if (value_p && *value_p)
51 return 0; /* skip if non-zero *value_p */
52
53 /* The size of stackmap and stackid_hmap should be the same */
54 key = bpf_get_stackid(ctx, &stackmap, 0);
55 if ((int)key >= 0)
56 bpf_map_update_elem(&stackid_hmap, &key, &val, 0);
57
58 return 0;
59}
60
61char _license[] SEC("license") = "GPL";
62__u32 _version SEC("version") = 1; /* ignored by tracepoints, required by libbpf.a */