From bbaf1ff06af49e856501024abbe161d96c1f0d66 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 24 Jun 2023 00:18:56 +0000 Subject: bpf: Replace deprecated -target with --target= for Clang The -target option has been deprecated since clang 3.4 in 2013. Therefore, use the preferred --target=bpf form instead. This also matches how we use --target= in scripts/Makefile.clang. Signed-off-by: Fangrui Song Signed-off-by: Daniel Borkmann Acked-by: Yonghong Song Acked-by: Quentin Monnet Link: https://github.com/llvm/llvm-project/commit/274b6f0c87a6a1798de0a68135afc7f95def6277 Link: https://lore.kernel.org/bpf/20230624001856.1903733-1-maskray@google.com --- samples/bpf/Makefile | 6 +++--- samples/bpf/gnu/stubs.h | 2 +- samples/bpf/test_lwt_bpf.sh | 2 +- samples/hid/Makefile | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'samples') diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile index 615f24ebc49c..595b98d825ce 100644 --- a/samples/bpf/Makefile +++ b/samples/bpf/Makefile @@ -248,7 +248,7 @@ BTF_LLC_PROBE := $(shell $(LLC) -march=bpf -mattr=help 2>&1 | grep dwarfris) BTF_PAHOLE_PROBE := $(shell $(BTF_PAHOLE) --help 2>&1 | grep BTF) BTF_OBJCOPY_PROBE := $(shell $(LLVM_OBJCOPY) --help 2>&1 | grep -i 'usage.*llvm') BTF_LLVM_PROBE := $(shell echo "int main() { return 0; }" | \ - $(CLANG) -target bpf -O2 -g -c -x c - -o ./llvm_btf_verify.o; \ + $(CLANG) --target=bpf -O2 -g -c -x c - -o ./llvm_btf_verify.o; \ $(LLVM_READELF) -S ./llvm_btf_verify.o | grep BTF; \ /bin/rm -f ./llvm_btf_verify.o) @@ -370,7 +370,7 @@ endif clean-files += vmlinux.h # Get Clang's default includes on this system, as opposed to those seen by -# '-target bpf'. This fixes "missing" files on some architectures/distros, +# '--target=bpf'. This fixes "missing" files on some architectures/distros, # such as asm/byteorder.h, asm/socket.h, asm/sockios.h, sys/cdefs.h etc. # # Use '-idirafter': Don't interfere with include mechanics except where the @@ -392,7 +392,7 @@ $(obj)/xdp_router_ipv4.bpf.o: $(obj)/xdp_sample.bpf.o $(obj)/%.bpf.o: $(src)/%.bpf.c $(obj)/vmlinux.h $(src)/xdp_sample.bpf.h $(src)/xdp_sample_shared.h @echo " CLANG-BPF " $@ - $(Q)$(CLANG) -g -O2 -target bpf -D__TARGET_ARCH_$(SRCARCH) \ + $(Q)$(CLANG) -g -O2 --target=bpf -D__TARGET_ARCH_$(SRCARCH) \ -Wno-compare-distinct-pointer-types -I$(srctree)/include \ -I$(srctree)/samples/bpf -I$(srctree)/tools/include \ -I$(LIBBPF_INCLUDE) $(CLANG_SYS_INCLUDES) \ diff --git a/samples/bpf/gnu/stubs.h b/samples/bpf/gnu/stubs.h index 719225b16626..1c638d9dce1a 100644 --- a/samples/bpf/gnu/stubs.h +++ b/samples/bpf/gnu/stubs.h @@ -1 +1 @@ -/* dummy .h to trick /usr/include/features.h to work with 'clang -target bpf' */ +/* dummy .h to trick /usr/include/features.h to work with 'clang --target=bpf' */ diff --git a/samples/bpf/test_lwt_bpf.sh b/samples/bpf/test_lwt_bpf.sh index 0bf2d0f6bf4b..148e2df6cdce 100755 --- a/samples/bpf/test_lwt_bpf.sh +++ b/samples/bpf/test_lwt_bpf.sh @@ -376,7 +376,7 @@ DST_MAC=$(lookup_mac $VETH1 $NS1) SRC_MAC=$(lookup_mac $VETH0) DST_IFINDEX=$(cat /sys/class/net/$VETH0/ifindex) -CLANG_OPTS="-O2 -target bpf -I ../include/" +CLANG_OPTS="-O2 --target=bpf -I ../include/" CLANG_OPTS+=" -DSRC_MAC=$SRC_MAC -DDST_MAC=$DST_MAC -DDST_IFINDEX=$DST_IFINDEX" clang $CLANG_OPTS -c $PROG_SRC -o $BPF_PROG diff --git a/samples/hid/Makefile b/samples/hid/Makefile index 026288280a03..9f7fe29dd749 100644 --- a/samples/hid/Makefile +++ b/samples/hid/Makefile @@ -86,7 +86,7 @@ BTF_LLC_PROBE := $(shell $(LLC) -march=bpf -mattr=help 2>&1 | grep dwarfris) BTF_PAHOLE_PROBE := $(shell $(BTF_PAHOLE) --help 2>&1 | grep BTF) BTF_OBJCOPY_PROBE := $(shell $(LLVM_OBJCOPY) --help 2>&1 | grep -i 'usage.*llvm') BTF_LLVM_PROBE := $(shell echo "int main() { return 0; }" | \ - $(CLANG) -target bpf -O2 -g -c -x c - -o ./llvm_btf_verify.o; \ + $(CLANG) --target=bpf -O2 -g -c -x c - -o ./llvm_btf_verify.o; \ $(LLVM_READELF) -S ./llvm_btf_verify.o | grep BTF; \ /bin/rm -f ./llvm_btf_verify.o) @@ -181,7 +181,7 @@ endif clean-files += vmlinux.h # Get Clang's default includes on this system, as opposed to those seen by -# '-target bpf'. This fixes "missing" files on some architectures/distros, +# '--target=bpf'. This fixes "missing" files on some architectures/distros, # such as asm/byteorder.h, asm/socket.h, asm/sockios.h, sys/cdefs.h etc. # # Use '-idirafter': Don't interfere with include mechanics except where the @@ -198,7 +198,7 @@ EXTRA_BPF_HEADERS_SRC := $(addprefix $(src)/,$(EXTRA_BPF_HEADERS)) $(obj)/%.bpf.o: $(src)/%.bpf.c $(EXTRA_BPF_HEADERS_SRC) $(obj)/vmlinux.h @echo " CLANG-BPF " $@ - $(Q)$(CLANG) -g -O2 -target bpf -D__TARGET_ARCH_$(SRCARCH) \ + $(Q)$(CLANG) -g -O2 --target=bpf -D__TARGET_ARCH_$(SRCARCH) \ -Wno-compare-distinct-pointer-types -I$(srctree)/include \ -I$(srctree)/samples/bpf -I$(srctree)/tools/include \ -I$(LIBBPF_INCLUDE) $(CLANG_SYS_INCLUDES) \ -- cgit v1.2.3 From 07018b57066e0009c0b9945723f30e532d347ed3 Mon Sep 17 00:00:00 2001 From: Rong Tao Date: Tue, 11 Jul 2023 19:14:59 +0800 Subject: samples/bpf: syscall_tp: Aarch64 no open syscall __NR_open never exist on AArch64. Signed-off-by: Rong Tao Signed-off-by: Andrii Nakryiko Link: https://lore.kernel.org/bpf/tencent_C6AD4AD72BEFE813228FC188905F96C6A506@qq.com --- samples/bpf/syscall_tp_kern.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'samples') diff --git a/samples/bpf/syscall_tp_kern.c b/samples/bpf/syscall_tp_kern.c index e7121dd1ee37..090fecfe641a 100644 --- a/samples/bpf/syscall_tp_kern.c +++ b/samples/bpf/syscall_tp_kern.c @@ -44,12 +44,14 @@ static __always_inline void count(void *map) bpf_map_update_elem(map, &key, &init_val, BPF_NOEXIST); } +#if !defined(__aarch64__) SEC("tracepoint/syscalls/sys_enter_open") int trace_enter_open(struct syscalls_enter_open_args *ctx) { count(&enter_open_map); return 0; } +#endif SEC("tracepoint/syscalls/sys_enter_openat") int trace_enter_open_at(struct syscalls_enter_open_args *ctx) @@ -65,12 +67,14 @@ int trace_enter_open_at2(struct syscalls_enter_open_args *ctx) return 0; } +#if !defined(__aarch64__) SEC("tracepoint/syscalls/sys_exit_open") int trace_enter_exit(struct syscalls_exit_open_args *ctx) { count(&exit_open_map); return 0; } +#endif SEC("tracepoint/syscalls/sys_exit_openat") int trace_enter_exit_at(struct syscalls_exit_open_args *ctx) -- cgit v1.2.3 From 89dc4037dda1219a3f5e3f367c2fe5e69c44a0d0 Mon Sep 17 00:00:00 2001 From: Anh Tuan Phan Date: Sun, 16 Jul 2023 23:13:51 +0700 Subject: samples/bpf: README: Update build dependencies required Update samples/bpf/README.rst to add pahole to the build dependencies list. Add the reference to "Documentation/process/changes.rst" for minimum version required so that the version required will not be outdated in the future. Signed-off-by: Anh Tuan Phan Link: https://lore.kernel.org/r/aecaf7a2-9100-cd5b-5cf4-91e5dbb2c90d@gmail.com Signed-off-by: Alexei Starovoitov --- samples/bpf/README.rst | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'samples') diff --git a/samples/bpf/README.rst b/samples/bpf/README.rst index 57f93edd1957..f16fc48e55a5 100644 --- a/samples/bpf/README.rst +++ b/samples/bpf/README.rst @@ -8,11 +8,14 @@ Build dependencies ================== Compiling requires having installed: - * clang >= version 3.4.0 - * llvm >= version 3.7.1 + * clang + * llvm + * pahole -Note that LLVM's tool 'llc' must support target 'bpf', list version -and supported targets with command: ``llc --version`` +Consult :ref:`Documentation/process/changes.rst ` for the minimum +version numbers required and how to update them. Note that LLVM's tool +'llc' must support target 'bpf', list version and supported targets with +command: ``llc --version`` Clean and configuration ----------------------- @@ -24,7 +27,8 @@ after some changes (on demand):: make -C samples/bpf clean make clean -Configure kernel, defconfig for instance:: +Configure kernel, defconfig for instance +(see "tools/testing/selftests/bpf/config" for a reference config):: make defconfig -- cgit v1.2.3 From 34f6e38f58db9a94718c273edc9ca3fc8b4dba5f Mon Sep 17 00:00:00 2001 From: "Daniel T. Lee" Date: Fri, 18 Aug 2023 18:01:11 +0900 Subject: samples/bpf: fix warning with ignored-attributes Currently, compiling the bpf programs will result the warning with the ignored attribute as follows. This commit fixes the warning by adding cf-protection option. In file included from ./arch/x86/include/asm/linkage.h:6: ./arch/x86/include/asm/ibt.h:77:8: warning: 'nocf_check' attribute ignored; use -fcf-protection to enable the attribute [-Wignored-attributes] extern __noendbr u64 ibt_save(bool disable); ^ ./arch/x86/include/asm/ibt.h:32:34: note: expanded from macro '__noendbr' ^ Signed-off-by: Daniel T. Lee Link: https://lore.kernel.org/r/20230818090119.477441-2-danieltimlee@gmail.com Signed-off-by: Alexei Starovoitov --- samples/bpf/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'samples') diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile index 595b98d825ce..b32cb8a62335 100644 --- a/samples/bpf/Makefile +++ b/samples/bpf/Makefile @@ -440,7 +440,7 @@ $(obj)/%.o: $(src)/%.c -Wno-gnu-variable-sized-type-not-at-end \ -Wno-address-of-packed-member -Wno-tautological-compare \ -Wno-unknown-warning-option $(CLANG_ARCH_ARGS) \ - -fno-asynchronous-unwind-tables \ + -fno-asynchronous-unwind-tables -fcf-protection \ -I$(srctree)/samples/bpf/ -include asm_goto_workaround.h \ -O2 -emit-llvm -Xclang -disable-llvm-passes -c $< -o - | \ $(OPT) -O2 -mtriple=bpf-pc-linux | $(LLVM_DIS) | \ -- cgit v1.2.3 From e7e6c774f5d40244444f23b8c49dac2ded158d8c Mon Sep 17 00:00:00 2001 From: "Daniel T. Lee" Date: Fri, 18 Aug 2023 18:01:12 +0900 Subject: samples/bpf: convert to vmlinux.h with tracing programs This commit replaces separate headers with a single vmlinux.h to tracing programs. Thanks to that, we no longer need to define the argument structure for tracing programs directly. For example, argument for the sched_switch tracpepoint (sched_switch_args) can be replaced with the vmlinux.h provided trace_event_raw_sched_switch. Additional defines have been added to the BPF program either directly or through the inclusion of net_shared.h. Defined values are PERF_MAX_STACK_DEPTH, IFNAMSIZ constants and __stringify() macro. This change enables the BPF program to access internal structures with BTF generated "vmlinux.h" header. Signed-off-by: Daniel T. Lee Link: https://lore.kernel.org/r/20230818090119.477441-3-danieltimlee@gmail.com Signed-off-by: Alexei Starovoitov --- samples/bpf/net_shared.h | 2 ++ samples/bpf/offwaketime_kern.c | 21 ++++++--------------- samples/bpf/spintest_kern.c | 10 ++++++---- samples/bpf/test_overhead_tp.bpf.c | 29 ++--------------------------- samples/bpf/tracex1_kern.c | 5 ++--- samples/bpf/tracex3_kern.c | 4 +--- samples/bpf/tracex4_kern.c | 3 +-- samples/bpf/tracex5_kern.c | 7 +++---- samples/bpf/tracex6_kern.c | 3 +-- samples/bpf/tracex7_kern.c | 3 +-- 10 files changed, 25 insertions(+), 62 deletions(-) (limited to 'samples') diff --git a/samples/bpf/net_shared.h b/samples/bpf/net_shared.h index e9429af9aa44..88cc52461c98 100644 --- a/samples/bpf/net_shared.h +++ b/samples/bpf/net_shared.h @@ -17,6 +17,8 @@ #define TC_ACT_OK 0 #define TC_ACT_SHOT 2 +#define IFNAMSIZ 16 + #if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \ __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #define bpf_ntohs(x) __builtin_bswap16(x) diff --git a/samples/bpf/offwaketime_kern.c b/samples/bpf/offwaketime_kern.c index 23f12b47e9e5..8e5105811178 100644 --- a/samples/bpf/offwaketime_kern.c +++ b/samples/bpf/offwaketime_kern.c @@ -4,14 +4,15 @@ * modify it under the terms of version 2 of the GNU General Public * License as published by the Free Software Foundation. */ -#include -#include -#include +#include "vmlinux.h" #include -#include #include #include +#ifndef PERF_MAX_STACK_DEPTH +#define PERF_MAX_STACK_DEPTH 127 +#endif + #define _(P) \ ({ \ typeof(P) val; \ @@ -111,18 +112,8 @@ static inline int update_counts(void *ctx, u32 pid, u64 delta) #if 1 /* taken from /sys/kernel/tracing/events/sched/sched_switch/format */ -struct sched_switch_args { - unsigned long long pad; - char prev_comm[TASK_COMM_LEN]; - int prev_pid; - int prev_prio; - long long prev_state; - char next_comm[TASK_COMM_LEN]; - int next_pid; - int next_prio; -}; SEC("tracepoint/sched/sched_switch") -int oncpu(struct sched_switch_args *ctx) +int oncpu(struct trace_event_raw_sched_switch *ctx) { /* record previous thread sleep time */ u32 pid = ctx->prev_pid; diff --git a/samples/bpf/spintest_kern.c b/samples/bpf/spintest_kern.c index 455da77319d9..15740b16a3f7 100644 --- a/samples/bpf/spintest_kern.c +++ b/samples/bpf/spintest_kern.c @@ -4,14 +4,15 @@ * modify it under the terms of version 2 of the GNU General Public * License as published by the Free Software Foundation. */ -#include -#include +#include "vmlinux.h" #include -#include -#include #include #include +#ifndef PERF_MAX_STACK_DEPTH +#define PERF_MAX_STACK_DEPTH 127 +#endif + struct { __uint(type, BPF_MAP_TYPE_HASH); __type(key, long); @@ -60,6 +61,7 @@ SEC("kprobe/_raw_spin_lock_irq")PROG(p11) SEC("kprobe/_raw_spin_trylock")PROG(p12) SEC("kprobe/_raw_spin_lock")PROG(p13) SEC("kprobe/_raw_spin_lock_bh")PROG(p14) + /* and to inner bpf helpers */ SEC("kprobe/htab_map_update_elem")PROG(p15) SEC("kprobe/__htab_percpu_map_update_elem")PROG(p16) diff --git a/samples/bpf/test_overhead_tp.bpf.c b/samples/bpf/test_overhead_tp.bpf.c index 8b498328e961..5dc08b587978 100644 --- a/samples/bpf/test_overhead_tp.bpf.c +++ b/samples/bpf/test_overhead_tp.bpf.c @@ -8,40 +8,15 @@ #include /* from /sys/kernel/tracing/events/task/task_rename/format */ -struct task_rename { - __u64 pad; - __u32 pid; - char oldcomm[TASK_COMM_LEN]; - char newcomm[TASK_COMM_LEN]; - __u16 oom_score_adj; -}; SEC("tracepoint/task/task_rename") -int prog(struct task_rename *ctx) +int prog(struct trace_event_raw_task_rename *ctx) { return 0; } /* from /sys/kernel/tracing/events/fib/fib_table_lookup/format */ -struct fib_table_lookup { - __u64 pad; - __u32 tb_id; - int err; - int oif; - int iif; - __u8 proto; - __u8 tos; - __u8 scope; - __u8 flags; - __u8 src[4]; - __u8 dst[4]; - __u8 gw4[4]; - __u8 gw6[16]; - __u16 sport; - __u16 dport; - char name[16]; -}; SEC("tracepoint/fib/fib_table_lookup") -int prog2(struct fib_table_lookup *ctx) +int prog2(struct trace_event_raw_fib_table_lookup *ctx) { return 0; } diff --git a/samples/bpf/tracex1_kern.c b/samples/bpf/tracex1_kern.c index ef30d2b353b0..bb78bdbffa87 100644 --- a/samples/bpf/tracex1_kern.c +++ b/samples/bpf/tracex1_kern.c @@ -4,9 +4,8 @@ * modify it under the terms of version 2 of the GNU General Public * License as published by the Free Software Foundation. */ -#include -#include -#include +#include "vmlinux.h" +#include "net_shared.h" #include #include #include diff --git a/samples/bpf/tracex3_kern.c b/samples/bpf/tracex3_kern.c index bde6591cb20c..7cc60f10d2e5 100644 --- a/samples/bpf/tracex3_kern.c +++ b/samples/bpf/tracex3_kern.c @@ -4,10 +4,8 @@ * modify it under the terms of version 2 of the GNU General Public * License as published by the Free Software Foundation. */ -#include -#include +#include "vmlinux.h" #include -#include #include #include diff --git a/samples/bpf/tracex4_kern.c b/samples/bpf/tracex4_kern.c index eb0f8fdd14bf..ca826750901a 100644 --- a/samples/bpf/tracex4_kern.c +++ b/samples/bpf/tracex4_kern.c @@ -4,9 +4,8 @@ * modify it under the terms of version 2 of the GNU General Public * License as published by the Free Software Foundation. */ -#include +#include "vmlinux.h" #include -#include #include #include diff --git a/samples/bpf/tracex5_kern.c b/samples/bpf/tracex5_kern.c index 64a1f7550d7e..8cd697ee7047 100644 --- a/samples/bpf/tracex5_kern.c +++ b/samples/bpf/tracex5_kern.c @@ -4,15 +4,14 @@ * modify it under the terms of version 2 of the GNU General Public * License as published by the Free Software Foundation. */ -#include +#include "vmlinux.h" +#include "syscall_nrs.h" #include -#include -#include #include -#include "syscall_nrs.h" #include #include +#define __stringify(x) #x #define PROG(F) SEC("kprobe/"__stringify(F)) int bpf_func_##F struct { diff --git a/samples/bpf/tracex6_kern.c b/samples/bpf/tracex6_kern.c index acad5712d8b4..6ad82e68f998 100644 --- a/samples/bpf/tracex6_kern.c +++ b/samples/bpf/tracex6_kern.c @@ -1,6 +1,5 @@ -#include +#include "vmlinux.h" #include -#include #include struct { diff --git a/samples/bpf/tracex7_kern.c b/samples/bpf/tracex7_kern.c index c5a92df8ac31..ab8d6704a5a4 100644 --- a/samples/bpf/tracex7_kern.c +++ b/samples/bpf/tracex7_kern.c @@ -1,5 +1,4 @@ -#include -#include +#include "vmlinux.h" #include #include -- cgit v1.2.3 From 4a0ee78890699706f59cc9bdf8283ecaa4e0a141 Mon Sep 17 00:00:00 2001 From: "Daniel T. Lee" Date: Fri, 18 Aug 2023 18:01:13 +0900 Subject: samples/bpf: unify bpf program suffix to .bpf with tracing programs Currently, BPF programs typically have a suffix of .bpf.c. However, some programs still utilize a mixture of _kern.c suffix alongside the naming convention. In order to achieve consistency in the naming of these programs, this commit unifies the inconsistency in the naming convention of BPF kernel programs. Signed-off-by: Daniel T. Lee Link: https://lore.kernel.org/r/20230818090119.477441-4-danieltimlee@gmail.com Signed-off-by: Alexei Starovoitov --- samples/bpf/Makefile | 18 ++--- samples/bpf/offwaketime.bpf.c | 149 +++++++++++++++++++++++++++++++++++++++++ samples/bpf/offwaketime_kern.c | 149 ----------------------------------------- samples/bpf/offwaketime_user.c | 2 +- samples/bpf/spintest.bpf.c | 71 ++++++++++++++++++++ samples/bpf/spintest_kern.c | 71 -------------------- samples/bpf/spintest_user.c | 2 +- samples/bpf/tracex1.bpf.c | 53 +++++++++++++++ samples/bpf/tracex1_kern.c | 53 --------------- samples/bpf/tracex1_user.c | 2 +- samples/bpf/tracex3.bpf.c | 88 ++++++++++++++++++++++++ samples/bpf/tracex3_kern.c | 88 ------------------------ samples/bpf/tracex3_user.c | 2 +- samples/bpf/tracex4.bpf.c | 54 +++++++++++++++ samples/bpf/tracex4_kern.c | 54 --------------- samples/bpf/tracex4_user.c | 2 +- samples/bpf/tracex5.bpf.c | 92 +++++++++++++++++++++++++ samples/bpf/tracex5_kern.c | 92 ------------------------- samples/bpf/tracex5_user.c | 2 +- samples/bpf/tracex6.bpf.c | 68 +++++++++++++++++++ samples/bpf/tracex6_kern.c | 68 ------------------- samples/bpf/tracex6_user.c | 2 +- samples/bpf/tracex7.bpf.c | 15 +++++ samples/bpf/tracex7_kern.c | 15 ----- samples/bpf/tracex7_user.c | 2 +- 25 files changed, 607 insertions(+), 607 deletions(-) create mode 100644 samples/bpf/offwaketime.bpf.c delete mode 100644 samples/bpf/offwaketime_kern.c create mode 100644 samples/bpf/spintest.bpf.c delete mode 100644 samples/bpf/spintest_kern.c create mode 100644 samples/bpf/tracex1.bpf.c delete mode 100644 samples/bpf/tracex1_kern.c create mode 100644 samples/bpf/tracex3.bpf.c delete mode 100644 samples/bpf/tracex3_kern.c create mode 100644 samples/bpf/tracex4.bpf.c delete mode 100644 samples/bpf/tracex4_kern.c create mode 100644 samples/bpf/tracex5.bpf.c delete mode 100644 samples/bpf/tracex5_kern.c create mode 100644 samples/bpf/tracex6.bpf.c delete mode 100644 samples/bpf/tracex6_kern.c create mode 100644 samples/bpf/tracex7.bpf.c delete mode 100644 samples/bpf/tracex7_kern.c (limited to 'samples') diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile index b32cb8a62335..f90bcd3696bd 100644 --- a/samples/bpf/Makefile +++ b/samples/bpf/Makefile @@ -124,21 +124,21 @@ always-y := $(tprogs-y) always-y += sockex1_kern.o always-y += sockex2_kern.o always-y += sockex3_kern.o -always-y += tracex1_kern.o +always-y += tracex1.bpf.o always-y += tracex2.bpf.o -always-y += tracex3_kern.o -always-y += tracex4_kern.o -always-y += tracex5_kern.o -always-y += tracex6_kern.o -always-y += tracex7_kern.o +always-y += tracex3.bpf.o +always-y += tracex4.bpf.o +always-y += tracex5.bpf.o +always-y += tracex6.bpf.o +always-y += tracex7.bpf.o always-y += sock_flags.bpf.o always-y += test_probe_write_user.bpf.o always-y += trace_output.bpf.o always-y += tcbpf1_kern.o always-y += tc_l2_redirect_kern.o always-y += lathist_kern.o -always-y += offwaketime_kern.o -always-y += spintest_kern.o +always-y += offwaketime.bpf.o +always-y += spintest.bpf.o always-y += map_perf_test.bpf.o always-y += test_overhead_tp.bpf.o always-y += test_overhead_raw_tp.bpf.o @@ -333,7 +333,7 @@ $(obj)/xdp_redirect_user.o: $(obj)/xdp_redirect.skel.h $(obj)/xdp_monitor_user.o: $(obj)/xdp_monitor.skel.h $(obj)/xdp_router_ipv4_user.o: $(obj)/xdp_router_ipv4.skel.h -$(obj)/tracex5_kern.o: $(obj)/syscall_nrs.h +$(obj)/tracex5.bpf.o: $(obj)/syscall_nrs.h $(obj)/hbm_out_kern.o: $(src)/hbm.h $(src)/hbm_kern.h $(obj)/hbm.o: $(src)/hbm.h $(obj)/hbm_edt_kern.o: $(src)/hbm.h $(src)/hbm_kern.h diff --git a/samples/bpf/offwaketime.bpf.c b/samples/bpf/offwaketime.bpf.c new file mode 100644 index 000000000000..8e5105811178 --- /dev/null +++ b/samples/bpf/offwaketime.bpf.c @@ -0,0 +1,149 @@ +/* Copyright (c) 2016 Facebook + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + */ +#include "vmlinux.h" +#include +#include +#include + +#ifndef PERF_MAX_STACK_DEPTH +#define PERF_MAX_STACK_DEPTH 127 +#endif + +#define _(P) \ + ({ \ + typeof(P) val; \ + bpf_probe_read_kernel(&val, sizeof(val), &(P)); \ + val; \ + }) + +#define MINBLOCK_US 1 +#define MAX_ENTRIES 10000 + +struct key_t { + char waker[TASK_COMM_LEN]; + char target[TASK_COMM_LEN]; + u32 wret; + u32 tret; +}; + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __type(key, struct key_t); + __type(value, u64); + __uint(max_entries, MAX_ENTRIES); +} counts SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __type(key, u32); + __type(value, u64); + __uint(max_entries, MAX_ENTRIES); +} start SEC(".maps"); + +struct wokeby_t { + char name[TASK_COMM_LEN]; + u32 ret; +}; + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __type(key, u32); + __type(value, struct wokeby_t); + __uint(max_entries, MAX_ENTRIES); +} wokeby SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_STACK_TRACE); + __uint(key_size, sizeof(u32)); + __uint(value_size, PERF_MAX_STACK_DEPTH * sizeof(u64)); + __uint(max_entries, MAX_ENTRIES); +} stackmap SEC(".maps"); + +#define STACKID_FLAGS (0 | BPF_F_FAST_STACK_CMP) + +SEC("kprobe/try_to_wake_up") +int waker(struct pt_regs *ctx) +{ + struct task_struct *p = (void *) PT_REGS_PARM1(ctx); + struct wokeby_t woke; + u32 pid; + + pid = _(p->pid); + + bpf_get_current_comm(&woke.name, sizeof(woke.name)); + woke.ret = bpf_get_stackid(ctx, &stackmap, STACKID_FLAGS); + + bpf_map_update_elem(&wokeby, &pid, &woke, BPF_ANY); + return 0; +} + +static inline int update_counts(void *ctx, u32 pid, u64 delta) +{ + struct wokeby_t *woke; + u64 zero = 0, *val; + struct key_t key; + + __builtin_memset(&key.waker, 0, sizeof(key.waker)); + bpf_get_current_comm(&key.target, sizeof(key.target)); + key.tret = bpf_get_stackid(ctx, &stackmap, STACKID_FLAGS); + key.wret = 0; + + woke = bpf_map_lookup_elem(&wokeby, &pid); + if (woke) { + key.wret = woke->ret; + __builtin_memcpy(&key.waker, woke->name, sizeof(key.waker)); + bpf_map_delete_elem(&wokeby, &pid); + } + + val = bpf_map_lookup_elem(&counts, &key); + if (!val) { + bpf_map_update_elem(&counts, &key, &zero, BPF_NOEXIST); + val = bpf_map_lookup_elem(&counts, &key); + if (!val) + return 0; + } + (*val) += delta; + return 0; +} + +#if 1 +/* taken from /sys/kernel/tracing/events/sched/sched_switch/format */ +SEC("tracepoint/sched/sched_switch") +int oncpu(struct trace_event_raw_sched_switch *ctx) +{ + /* record previous thread sleep time */ + u32 pid = ctx->prev_pid; +#else +SEC("kprobe/finish_task_switch") +int oncpu(struct pt_regs *ctx) +{ + struct task_struct *p = (void *) PT_REGS_PARM1(ctx); + /* record previous thread sleep time */ + u32 pid = _(p->pid); +#endif + u64 delta, ts, *tsp; + + ts = bpf_ktime_get_ns(); + bpf_map_update_elem(&start, &pid, &ts, BPF_ANY); + + /* calculate current thread's delta time */ + pid = bpf_get_current_pid_tgid(); + tsp = bpf_map_lookup_elem(&start, &pid); + if (!tsp) + /* missed start or filtered */ + return 0; + + delta = bpf_ktime_get_ns() - *tsp; + bpf_map_delete_elem(&start, &pid); + delta = delta / 1000; + if (delta < MINBLOCK_US) + return 0; + + return update_counts(ctx, pid, delta); +} +char _license[] SEC("license") = "GPL"; +u32 _version SEC("version") = LINUX_VERSION_CODE; diff --git a/samples/bpf/offwaketime_kern.c b/samples/bpf/offwaketime_kern.c deleted file mode 100644 index 8e5105811178..000000000000 --- a/samples/bpf/offwaketime_kern.c +++ /dev/null @@ -1,149 +0,0 @@ -/* Copyright (c) 2016 Facebook - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - */ -#include "vmlinux.h" -#include -#include -#include - -#ifndef PERF_MAX_STACK_DEPTH -#define PERF_MAX_STACK_DEPTH 127 -#endif - -#define _(P) \ - ({ \ - typeof(P) val; \ - bpf_probe_read_kernel(&val, sizeof(val), &(P)); \ - val; \ - }) - -#define MINBLOCK_US 1 -#define MAX_ENTRIES 10000 - -struct key_t { - char waker[TASK_COMM_LEN]; - char target[TASK_COMM_LEN]; - u32 wret; - u32 tret; -}; - -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __type(key, struct key_t); - __type(value, u64); - __uint(max_entries, MAX_ENTRIES); -} counts SEC(".maps"); - -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __type(key, u32); - __type(value, u64); - __uint(max_entries, MAX_ENTRIES); -} start SEC(".maps"); - -struct wokeby_t { - char name[TASK_COMM_LEN]; - u32 ret; -}; - -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __type(key, u32); - __type(value, struct wokeby_t); - __uint(max_entries, MAX_ENTRIES); -} wokeby SEC(".maps"); - -struct { - __uint(type, BPF_MAP_TYPE_STACK_TRACE); - __uint(key_size, sizeof(u32)); - __uint(value_size, PERF_MAX_STACK_DEPTH * sizeof(u64)); - __uint(max_entries, MAX_ENTRIES); -} stackmap SEC(".maps"); - -#define STACKID_FLAGS (0 | BPF_F_FAST_STACK_CMP) - -SEC("kprobe/try_to_wake_up") -int waker(struct pt_regs *ctx) -{ - struct task_struct *p = (void *) PT_REGS_PARM1(ctx); - struct wokeby_t woke; - u32 pid; - - pid = _(p->pid); - - bpf_get_current_comm(&woke.name, sizeof(woke.name)); - woke.ret = bpf_get_stackid(ctx, &stackmap, STACKID_FLAGS); - - bpf_map_update_elem(&wokeby, &pid, &woke, BPF_ANY); - return 0; -} - -static inline int update_counts(void *ctx, u32 pid, u64 delta) -{ - struct wokeby_t *woke; - u64 zero = 0, *val; - struct key_t key; - - __builtin_memset(&key.waker, 0, sizeof(key.waker)); - bpf_get_current_comm(&key.target, sizeof(key.target)); - key.tret = bpf_get_stackid(ctx, &stackmap, STACKID_FLAGS); - key.wret = 0; - - woke = bpf_map_lookup_elem(&wokeby, &pid); - if (woke) { - key.wret = woke->ret; - __builtin_memcpy(&key.waker, woke->name, sizeof(key.waker)); - bpf_map_delete_elem(&wokeby, &pid); - } - - val = bpf_map_lookup_elem(&counts, &key); - if (!val) { - bpf_map_update_elem(&counts, &key, &zero, BPF_NOEXIST); - val = bpf_map_lookup_elem(&counts, &key); - if (!val) - return 0; - } - (*val) += delta; - return 0; -} - -#if 1 -/* taken from /sys/kernel/tracing/events/sched/sched_switch/format */ -SEC("tracepoint/sched/sched_switch") -int oncpu(struct trace_event_raw_sched_switch *ctx) -{ - /* record previous thread sleep time */ - u32 pid = ctx->prev_pid; -#else -SEC("kprobe/finish_task_switch") -int oncpu(struct pt_regs *ctx) -{ - struct task_struct *p = (void *) PT_REGS_PARM1(ctx); - /* record previous thread sleep time */ - u32 pid = _(p->pid); -#endif - u64 delta, ts, *tsp; - - ts = bpf_ktime_get_ns(); - bpf_map_update_elem(&start, &pid, &ts, BPF_ANY); - - /* calculate current thread's delta time */ - pid = bpf_get_current_pid_tgid(); - tsp = bpf_map_lookup_elem(&start, &pid); - if (!tsp) - /* missed start or filtered */ - return 0; - - delta = bpf_ktime_get_ns() - *tsp; - bpf_map_delete_elem(&start, &pid); - delta = delta / 1000; - if (delta < MINBLOCK_US) - return 0; - - return update_counts(ctx, pid, delta); -} -char _license[] SEC("license") = "GPL"; -u32 _version SEC("version") = LINUX_VERSION_CODE; diff --git a/samples/bpf/offwaketime_user.c b/samples/bpf/offwaketime_user.c index b6eedcb98fb9..5557b5393642 100644 --- a/samples/bpf/offwaketime_user.c +++ b/samples/bpf/offwaketime_user.c @@ -105,7 +105,7 @@ int main(int argc, char **argv) return 2; } - snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); + snprintf(filename, sizeof(filename), "%s.bpf.o", argv[0]); obj = bpf_object__open_file(filename, NULL); if (libbpf_get_error(obj)) { fprintf(stderr, "ERROR: opening BPF object file failed\n"); diff --git a/samples/bpf/spintest.bpf.c b/samples/bpf/spintest.bpf.c new file mode 100644 index 000000000000..15740b16a3f7 --- /dev/null +++ b/samples/bpf/spintest.bpf.c @@ -0,0 +1,71 @@ +/* Copyright (c) 2016, Facebook + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + */ +#include "vmlinux.h" +#include +#include +#include + +#ifndef PERF_MAX_STACK_DEPTH +#define PERF_MAX_STACK_DEPTH 127 +#endif + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __type(key, long); + __type(value, long); + __uint(max_entries, 1024); +} my_map SEC(".maps"); +struct { + __uint(type, BPF_MAP_TYPE_PERCPU_HASH); + __uint(key_size, sizeof(long)); + __uint(value_size, sizeof(long)); + __uint(max_entries, 1024); +} my_map2 SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_STACK_TRACE); + __uint(key_size, sizeof(u32)); + __uint(value_size, PERF_MAX_STACK_DEPTH * sizeof(u64)); + __uint(max_entries, 10000); +} stackmap SEC(".maps"); + +#define PROG(foo) \ +int foo(struct pt_regs *ctx) \ +{ \ + long v = PT_REGS_IP(ctx), *val; \ +\ + val = bpf_map_lookup_elem(&my_map, &v); \ + bpf_map_update_elem(&my_map, &v, &v, BPF_ANY); \ + bpf_map_update_elem(&my_map2, &v, &v, BPF_ANY); \ + bpf_map_delete_elem(&my_map2, &v); \ + bpf_get_stackid(ctx, &stackmap, BPF_F_REUSE_STACKID); \ + return 0; \ +} + +/* add kprobes to all possible *spin* functions */ +SEC("kprobe/spin_unlock")PROG(p1) +SEC("kprobe/spin_lock")PROG(p2) +SEC("kprobe/mutex_spin_on_owner")PROG(p3) +SEC("kprobe/rwsem_spin_on_owner")PROG(p4) +SEC("kprobe/spin_unlock_irqrestore")PROG(p5) +SEC("kprobe/_raw_spin_unlock_irqrestore")PROG(p6) +SEC("kprobe/_raw_spin_unlock_bh")PROG(p7) +SEC("kprobe/_raw_spin_unlock")PROG(p8) +SEC("kprobe/_raw_spin_lock_irqsave")PROG(p9) +SEC("kprobe/_raw_spin_trylock_bh")PROG(p10) +SEC("kprobe/_raw_spin_lock_irq")PROG(p11) +SEC("kprobe/_raw_spin_trylock")PROG(p12) +SEC("kprobe/_raw_spin_lock")PROG(p13) +SEC("kprobe/_raw_spin_lock_bh")PROG(p14) + +/* and to inner bpf helpers */ +SEC("kprobe/htab_map_update_elem")PROG(p15) +SEC("kprobe/__htab_percpu_map_update_elem")PROG(p16) +SEC("kprobe/htab_map_alloc")PROG(p17) + +char _license[] SEC("license") = "GPL"; +u32 _version SEC("version") = LINUX_VERSION_CODE; diff --git a/samples/bpf/spintest_kern.c b/samples/bpf/spintest_kern.c deleted file mode 100644 index 15740b16a3f7..000000000000 --- a/samples/bpf/spintest_kern.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Copyright (c) 2016, Facebook - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - */ -#include "vmlinux.h" -#include -#include -#include - -#ifndef PERF_MAX_STACK_DEPTH -#define PERF_MAX_STACK_DEPTH 127 -#endif - -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __type(key, long); - __type(value, long); - __uint(max_entries, 1024); -} my_map SEC(".maps"); -struct { - __uint(type, BPF_MAP_TYPE_PERCPU_HASH); - __uint(key_size, sizeof(long)); - __uint(value_size, sizeof(long)); - __uint(max_entries, 1024); -} my_map2 SEC(".maps"); - -struct { - __uint(type, BPF_MAP_TYPE_STACK_TRACE); - __uint(key_size, sizeof(u32)); - __uint(value_size, PERF_MAX_STACK_DEPTH * sizeof(u64)); - __uint(max_entries, 10000); -} stackmap SEC(".maps"); - -#define PROG(foo) \ -int foo(struct pt_regs *ctx) \ -{ \ - long v = PT_REGS_IP(ctx), *val; \ -\ - val = bpf_map_lookup_elem(&my_map, &v); \ - bpf_map_update_elem(&my_map, &v, &v, BPF_ANY); \ - bpf_map_update_elem(&my_map2, &v, &v, BPF_ANY); \ - bpf_map_delete_elem(&my_map2, &v); \ - bpf_get_stackid(ctx, &stackmap, BPF_F_REUSE_STACKID); \ - return 0; \ -} - -/* add kprobes to all possible *spin* functions */ -SEC("kprobe/spin_unlock")PROG(p1) -SEC("kprobe/spin_lock")PROG(p2) -SEC("kprobe/mutex_spin_on_owner")PROG(p3) -SEC("kprobe/rwsem_spin_on_owner")PROG(p4) -SEC("kprobe/spin_unlock_irqrestore")PROG(p5) -SEC("kprobe/_raw_spin_unlock_irqrestore")PROG(p6) -SEC("kprobe/_raw_spin_unlock_bh")PROG(p7) -SEC("kprobe/_raw_spin_unlock")PROG(p8) -SEC("kprobe/_raw_spin_lock_irqsave")PROG(p9) -SEC("kprobe/_raw_spin_trylock_bh")PROG(p10) -SEC("kprobe/_raw_spin_lock_irq")PROG(p11) -SEC("kprobe/_raw_spin_trylock")PROG(p12) -SEC("kprobe/_raw_spin_lock")PROG(p13) -SEC("kprobe/_raw_spin_lock_bh")PROG(p14) - -/* and to inner bpf helpers */ -SEC("kprobe/htab_map_update_elem")PROG(p15) -SEC("kprobe/__htab_percpu_map_update_elem")PROG(p16) -SEC("kprobe/htab_map_alloc")PROG(p17) - -char _license[] SEC("license") = "GPL"; -u32 _version SEC("version") = LINUX_VERSION_CODE; diff --git a/samples/bpf/spintest_user.c b/samples/bpf/spintest_user.c index aadac14f748a..8c77600776fb 100644 --- a/samples/bpf/spintest_user.c +++ b/samples/bpf/spintest_user.c @@ -23,7 +23,7 @@ int main(int ac, char **argv) return 2; } - snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); + snprintf(filename, sizeof(filename), "%s.bpf.o", argv[0]); obj = bpf_object__open_file(filename, NULL); if (libbpf_get_error(obj)) { fprintf(stderr, "ERROR: opening BPF object file failed\n"); diff --git a/samples/bpf/tracex1.bpf.c b/samples/bpf/tracex1.bpf.c new file mode 100644 index 000000000000..bb78bdbffa87 --- /dev/null +++ b/samples/bpf/tracex1.bpf.c @@ -0,0 +1,53 @@ +/* Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + */ +#include "vmlinux.h" +#include "net_shared.h" +#include +#include +#include + +#define _(P) \ + ({ \ + typeof(P) val = 0; \ + bpf_probe_read_kernel(&val, sizeof(val), &(P)); \ + val; \ + }) + +/* kprobe is NOT a stable ABI + * kernel functions can be removed, renamed or completely change semantics. + * Number of arguments and their positions can change, etc. + * In such case this bpf+kprobe example will no longer be meaningful + */ +SEC("kprobe/__netif_receive_skb_core") +int bpf_prog1(struct pt_regs *ctx) +{ + /* attaches to kprobe __netif_receive_skb_core, + * looks for packets on loobpack device and prints them + */ + char devname[IFNAMSIZ]; + struct net_device *dev; + struct sk_buff *skb; + int len; + + /* non-portable! works for the given kernel only */ + bpf_probe_read_kernel(&skb, sizeof(skb), (void *)PT_REGS_PARM1(ctx)); + dev = _(skb->dev); + len = _(skb->len); + + bpf_probe_read_kernel(devname, sizeof(devname), dev->name); + + if (devname[0] == 'l' && devname[1] == 'o') { + char fmt[] = "skb %p len %d\n"; + /* using bpf_trace_printk() for DEBUG ONLY */ + bpf_trace_printk(fmt, sizeof(fmt), skb, len); + } + + return 0; +} + +char _license[] SEC("license") = "GPL"; +u32 _version SEC("version") = LINUX_VERSION_CODE; diff --git a/samples/bpf/tracex1_kern.c b/samples/bpf/tracex1_kern.c deleted file mode 100644 index bb78bdbffa87..000000000000 --- a/samples/bpf/tracex1_kern.c +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - */ -#include "vmlinux.h" -#include "net_shared.h" -#include -#include -#include - -#define _(P) \ - ({ \ - typeof(P) val = 0; \ - bpf_probe_read_kernel(&val, sizeof(val), &(P)); \ - val; \ - }) - -/* kprobe is NOT a stable ABI - * kernel functions can be removed, renamed or completely change semantics. - * Number of arguments and their positions can change, etc. - * In such case this bpf+kprobe example will no longer be meaningful - */ -SEC("kprobe/__netif_receive_skb_core") -int bpf_prog1(struct pt_regs *ctx) -{ - /* attaches to kprobe __netif_receive_skb_core, - * looks for packets on loobpack device and prints them - */ - char devname[IFNAMSIZ]; - struct net_device *dev; - struct sk_buff *skb; - int len; - - /* non-portable! works for the given kernel only */ - bpf_probe_read_kernel(&skb, sizeof(skb), (void *)PT_REGS_PARM1(ctx)); - dev = _(skb->dev); - len = _(skb->len); - - bpf_probe_read_kernel(devname, sizeof(devname), dev->name); - - if (devname[0] == 'l' && devname[1] == 'o') { - char fmt[] = "skb %p len %d\n"; - /* using bpf_trace_printk() for DEBUG ONLY */ - bpf_trace_printk(fmt, sizeof(fmt), skb, len); - } - - return 0; -} - -char _license[] SEC("license") = "GPL"; -u32 _version SEC("version") = LINUX_VERSION_CODE; diff --git a/samples/bpf/tracex1_user.c b/samples/bpf/tracex1_user.c index 9d4adb7fd834..8c3d9043a2b6 100644 --- a/samples/bpf/tracex1_user.c +++ b/samples/bpf/tracex1_user.c @@ -12,7 +12,7 @@ int main(int ac, char **argv) char filename[256]; FILE *f; - snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); + snprintf(filename, sizeof(filename), "%s.bpf.o", argv[0]); obj = bpf_object__open_file(filename, NULL); if (libbpf_get_error(obj)) { fprintf(stderr, "ERROR: opening BPF object file failed\n"); diff --git a/samples/bpf/tracex3.bpf.c b/samples/bpf/tracex3.bpf.c new file mode 100644 index 000000000000..7cc60f10d2e5 --- /dev/null +++ b/samples/bpf/tracex3.bpf.c @@ -0,0 +1,88 @@ +/* Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + */ +#include "vmlinux.h" +#include +#include +#include + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __type(key, long); + __type(value, u64); + __uint(max_entries, 4096); +} my_map SEC(".maps"); + +/* kprobe is NOT a stable ABI. If kernel internals change this bpf+kprobe + * example will no longer be meaningful + */ +SEC("kprobe/blk_mq_start_request") +int bpf_prog1(struct pt_regs *ctx) +{ + long rq = PT_REGS_PARM1(ctx); + u64 val = bpf_ktime_get_ns(); + + bpf_map_update_elem(&my_map, &rq, &val, BPF_ANY); + return 0; +} + +static unsigned int log2l(unsigned long long n) +{ +#define S(k) if (n >= (1ull << k)) { i += k; n >>= k; } + int i = -(n == 0); + S(32); S(16); S(8); S(4); S(2); S(1); + return i; +#undef S +} + +#define SLOTS 100 + +struct { + __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); + __uint(key_size, sizeof(u32)); + __uint(value_size, sizeof(u64)); + __uint(max_entries, SLOTS); +} lat_map SEC(".maps"); + +SEC("kprobe/__blk_account_io_done") +int bpf_prog2(struct pt_regs *ctx) +{ + long rq = PT_REGS_PARM1(ctx); + u64 *value, l, base; + u32 index; + + value = bpf_map_lookup_elem(&my_map, &rq); + if (!value) + return 0; + + u64 cur_time = bpf_ktime_get_ns(); + u64 delta = cur_time - *value; + + bpf_map_delete_elem(&my_map, &rq); + + /* the lines below are computing index = log10(delta)*10 + * using integer arithmetic + * index = 29 ~ 1 usec + * index = 59 ~ 1 msec + * index = 89 ~ 1 sec + * index = 99 ~ 10sec or more + * log10(x)*10 = log2(x)*10/log2(10) = log2(x)*3 + */ + l = log2l(delta); + base = 1ll << l; + index = (l * 64 + (delta - base) * 64 / base) * 3 / 64; + + if (index >= SLOTS) + index = SLOTS - 1; + + value = bpf_map_lookup_elem(&lat_map, &index); + if (value) + *value += 1; + + return 0; +} +char _license[] SEC("license") = "GPL"; +u32 _version SEC("version") = LINUX_VERSION_CODE; diff --git a/samples/bpf/tracex3_kern.c b/samples/bpf/tracex3_kern.c deleted file mode 100644 index 7cc60f10d2e5..000000000000 --- a/samples/bpf/tracex3_kern.c +++ /dev/null @@ -1,88 +0,0 @@ -/* Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - */ -#include "vmlinux.h" -#include -#include -#include - -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __type(key, long); - __type(value, u64); - __uint(max_entries, 4096); -} my_map SEC(".maps"); - -/* kprobe is NOT a stable ABI. If kernel internals change this bpf+kprobe - * example will no longer be meaningful - */ -SEC("kprobe/blk_mq_start_request") -int bpf_prog1(struct pt_regs *ctx) -{ - long rq = PT_REGS_PARM1(ctx); - u64 val = bpf_ktime_get_ns(); - - bpf_map_update_elem(&my_map, &rq, &val, BPF_ANY); - return 0; -} - -static unsigned int log2l(unsigned long long n) -{ -#define S(k) if (n >= (1ull << k)) { i += k; n >>= k; } - int i = -(n == 0); - S(32); S(16); S(8); S(4); S(2); S(1); - return i; -#undef S -} - -#define SLOTS 100 - -struct { - __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); - __uint(key_size, sizeof(u32)); - __uint(value_size, sizeof(u64)); - __uint(max_entries, SLOTS); -} lat_map SEC(".maps"); - -SEC("kprobe/__blk_account_io_done") -int bpf_prog2(struct pt_regs *ctx) -{ - long rq = PT_REGS_PARM1(ctx); - u64 *value, l, base; - u32 index; - - value = bpf_map_lookup_elem(&my_map, &rq); - if (!value) - return 0; - - u64 cur_time = bpf_ktime_get_ns(); - u64 delta = cur_time - *value; - - bpf_map_delete_elem(&my_map, &rq); - - /* the lines below are computing index = log10(delta)*10 - * using integer arithmetic - * index = 29 ~ 1 usec - * index = 59 ~ 1 msec - * index = 89 ~ 1 sec - * index = 99 ~ 10sec or more - * log10(x)*10 = log2(x)*10/log2(10) = log2(x)*3 - */ - l = log2l(delta); - base = 1ll << l; - index = (l * 64 + (delta - base) * 64 / base) * 3 / 64; - - if (index >= SLOTS) - index = SLOTS - 1; - - value = bpf_map_lookup_elem(&lat_map, &index); - if (value) - *value += 1; - - return 0; -} -char _license[] SEC("license") = "GPL"; -u32 _version SEC("version") = LINUX_VERSION_CODE; diff --git a/samples/bpf/tracex3_user.c b/samples/bpf/tracex3_user.c index d5eebace31e6..1002eb0323b4 100644 --- a/samples/bpf/tracex3_user.c +++ b/samples/bpf/tracex3_user.c @@ -125,7 +125,7 @@ int main(int ac, char **argv) } } - snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); + snprintf(filename, sizeof(filename), "%s.bpf.o", argv[0]); obj = bpf_object__open_file(filename, NULL); if (libbpf_get_error(obj)) { fprintf(stderr, "ERROR: opening BPF object file failed\n"); diff --git a/samples/bpf/tracex4.bpf.c b/samples/bpf/tracex4.bpf.c new file mode 100644 index 000000000000..ca826750901a --- /dev/null +++ b/samples/bpf/tracex4.bpf.c @@ -0,0 +1,54 @@ +/* Copyright (c) 2015 PLUMgrid, http://plumgrid.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + */ +#include "vmlinux.h" +#include +#include +#include + +struct pair { + u64 val; + u64 ip; +}; + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __type(key, long); + __type(value, struct pair); + __uint(max_entries, 1000000); +} my_map SEC(".maps"); + +/* kprobe is NOT a stable ABI. If kernel internals change this bpf+kprobe + * example will no longer be meaningful + */ +SEC("kprobe/kmem_cache_free") +int bpf_prog1(struct pt_regs *ctx) +{ + long ptr = PT_REGS_PARM2(ctx); + + bpf_map_delete_elem(&my_map, &ptr); + return 0; +} + +SEC("kretprobe/kmem_cache_alloc_node") +int bpf_prog2(struct pt_regs *ctx) +{ + long ptr = PT_REGS_RC(ctx); + long ip = 0; + + /* get ip address of kmem_cache_alloc_node() caller */ + BPF_KRETPROBE_READ_RET_IP(ip, ctx); + + struct pair v = { + .val = bpf_ktime_get_ns(), + .ip = ip, + }; + + bpf_map_update_elem(&my_map, &ptr, &v, BPF_ANY); + return 0; +} +char _license[] SEC("license") = "GPL"; +u32 _version SEC("version") = LINUX_VERSION_CODE; diff --git a/samples/bpf/tracex4_kern.c b/samples/bpf/tracex4_kern.c deleted file mode 100644 index ca826750901a..000000000000 --- a/samples/bpf/tracex4_kern.c +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright (c) 2015 PLUMgrid, http://plumgrid.com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - */ -#include "vmlinux.h" -#include -#include -#include - -struct pair { - u64 val; - u64 ip; -}; - -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __type(key, long); - __type(value, struct pair); - __uint(max_entries, 1000000); -} my_map SEC(".maps"); - -/* kprobe is NOT a stable ABI. If kernel internals change this bpf+kprobe - * example will no longer be meaningful - */ -SEC("kprobe/kmem_cache_free") -int bpf_prog1(struct pt_regs *ctx) -{ - long ptr = PT_REGS_PARM2(ctx); - - bpf_map_delete_elem(&my_map, &ptr); - return 0; -} - -SEC("kretprobe/kmem_cache_alloc_node") -int bpf_prog2(struct pt_regs *ctx) -{ - long ptr = PT_REGS_RC(ctx); - long ip = 0; - - /* get ip address of kmem_cache_alloc_node() caller */ - BPF_KRETPROBE_READ_RET_IP(ip, ctx); - - struct pair v = { - .val = bpf_ktime_get_ns(), - .ip = ip, - }; - - bpf_map_update_elem(&my_map, &ptr, &v, BPF_ANY); - return 0; -} -char _license[] SEC("license") = "GPL"; -u32 _version SEC("version") = LINUX_VERSION_CODE; diff --git a/samples/bpf/tracex4_user.c b/samples/bpf/tracex4_user.c index dee8f0a091ba..a5145ad72cbf 100644 --- a/samples/bpf/tracex4_user.c +++ b/samples/bpf/tracex4_user.c @@ -53,7 +53,7 @@ int main(int ac, char **argv) char filename[256]; int map_fd, j = 0; - snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); + snprintf(filename, sizeof(filename), "%s.bpf.o", argv[0]); obj = bpf_object__open_file(filename, NULL); if (libbpf_get_error(obj)) { fprintf(stderr, "ERROR: opening BPF object file failed\n"); diff --git a/samples/bpf/tracex5.bpf.c b/samples/bpf/tracex5.bpf.c new file mode 100644 index 000000000000..8cd697ee7047 --- /dev/null +++ b/samples/bpf/tracex5.bpf.c @@ -0,0 +1,92 @@ +/* Copyright (c) 2015 PLUMgrid, http://plumgrid.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + */ +#include "vmlinux.h" +#include "syscall_nrs.h" +#include +#include +#include +#include + +#define __stringify(x) #x +#define PROG(F) SEC("kprobe/"__stringify(F)) int bpf_func_##F + +struct { + __uint(type, BPF_MAP_TYPE_PROG_ARRAY); + __uint(key_size, sizeof(u32)); + __uint(value_size, sizeof(u32)); +#ifdef __mips__ + __uint(max_entries, 6000); /* MIPS n64 syscalls start at 5000 */ +#else + __uint(max_entries, 1024); +#endif +} progs SEC(".maps"); + +SEC("kprobe/__seccomp_filter") +int bpf_prog1(struct pt_regs *ctx) +{ + int sc_nr = (int)PT_REGS_PARM1(ctx); + + /* dispatch into next BPF program depending on syscall number */ + bpf_tail_call(ctx, &progs, sc_nr); + + /* fall through -> unknown syscall */ + if (sc_nr >= __NR_getuid && sc_nr <= __NR_getsid) { + char fmt[] = "syscall=%d (one of get/set uid/pid/gid)\n"; + bpf_trace_printk(fmt, sizeof(fmt), sc_nr); + } + return 0; +} + +/* we jump here when syscall number == __NR_write */ +PROG(SYS__NR_write)(struct pt_regs *ctx) +{ + struct seccomp_data sd; + + bpf_probe_read_kernel(&sd, sizeof(sd), (void *)PT_REGS_PARM2(ctx)); + if (sd.args[2] == 512) { + char fmt[] = "write(fd=%d, buf=%p, size=%d)\n"; + bpf_trace_printk(fmt, sizeof(fmt), + sd.args[0], sd.args[1], sd.args[2]); + } + return 0; +} + +PROG(SYS__NR_read)(struct pt_regs *ctx) +{ + struct seccomp_data sd; + + bpf_probe_read_kernel(&sd, sizeof(sd), (void *)PT_REGS_PARM2(ctx)); + if (sd.args[2] > 128 && sd.args[2] <= 1024) { + char fmt[] = "read(fd=%d, buf=%p, size=%d)\n"; + bpf_trace_printk(fmt, sizeof(fmt), + sd.args[0], sd.args[1], sd.args[2]); + } + return 0; +} + +#ifdef __NR_mmap2 +PROG(SYS__NR_mmap2)(struct pt_regs *ctx) +{ + char fmt[] = "mmap2\n"; + + bpf_trace_printk(fmt, sizeof(fmt)); + return 0; +} +#endif + +#ifdef __NR_mmap +PROG(SYS__NR_mmap)(struct pt_regs *ctx) +{ + char fmt[] = "mmap\n"; + + bpf_trace_printk(fmt, sizeof(fmt)); + return 0; +} +#endif + +char _license[] SEC("license") = "GPL"; +u32 _version SEC("version") = LINUX_VERSION_CODE; diff --git a/samples/bpf/tracex5_kern.c b/samples/bpf/tracex5_kern.c deleted file mode 100644 index 8cd697ee7047..000000000000 --- a/samples/bpf/tracex5_kern.c +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright (c) 2015 PLUMgrid, http://plumgrid.com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - */ -#include "vmlinux.h" -#include "syscall_nrs.h" -#include -#include -#include -#include - -#define __stringify(x) #x -#define PROG(F) SEC("kprobe/"__stringify(F)) int bpf_func_##F - -struct { - __uint(type, BPF_MAP_TYPE_PROG_ARRAY); - __uint(key_size, sizeof(u32)); - __uint(value_size, sizeof(u32)); -#ifdef __mips__ - __uint(max_entries, 6000); /* MIPS n64 syscalls start at 5000 */ -#else - __uint(max_entries, 1024); -#endif -} progs SEC(".maps"); - -SEC("kprobe/__seccomp_filter") -int bpf_prog1(struct pt_regs *ctx) -{ - int sc_nr = (int)PT_REGS_PARM1(ctx); - - /* dispatch into next BPF program depending on syscall number */ - bpf_tail_call(ctx, &progs, sc_nr); - - /* fall through -> unknown syscall */ - if (sc_nr >= __NR_getuid && sc_nr <= __NR_getsid) { - char fmt[] = "syscall=%d (one of get/set uid/pid/gid)\n"; - bpf_trace_printk(fmt, sizeof(fmt), sc_nr); - } - return 0; -} - -/* we jump here when syscall number == __NR_write */ -PROG(SYS__NR_write)(struct pt_regs *ctx) -{ - struct seccomp_data sd; - - bpf_probe_read_kernel(&sd, sizeof(sd), (void *)PT_REGS_PARM2(ctx)); - if (sd.args[2] == 512) { - char fmt[] = "write(fd=%d, buf=%p, size=%d)\n"; - bpf_trace_printk(fmt, sizeof(fmt), - sd.args[0], sd.args[1], sd.args[2]); - } - return 0; -} - -PROG(SYS__NR_read)(struct pt_regs *ctx) -{ - struct seccomp_data sd; - - bpf_probe_read_kernel(&sd, sizeof(sd), (void *)PT_REGS_PARM2(ctx)); - if (sd.args[2] > 128 && sd.args[2] <= 1024) { - char fmt[] = "read(fd=%d, buf=%p, size=%d)\n"; - bpf_trace_printk(fmt, sizeof(fmt), - sd.args[0], sd.args[1], sd.args[2]); - } - return 0; -} - -#ifdef __NR_mmap2 -PROG(SYS__NR_mmap2)(struct pt_regs *ctx) -{ - char fmt[] = "mmap2\n"; - - bpf_trace_printk(fmt, sizeof(fmt)); - return 0; -} -#endif - -#ifdef __NR_mmap -PROG(SYS__NR_mmap)(struct pt_regs *ctx) -{ - char fmt[] = "mmap\n"; - - bpf_trace_printk(fmt, sizeof(fmt)); - return 0; -} -#endif - -char _license[] SEC("license") = "GPL"; -u32 _version SEC("version") = LINUX_VERSION_CODE; diff --git a/samples/bpf/tracex5_user.c b/samples/bpf/tracex5_user.c index 9d7d79f0d47d..7e2d8397fb98 100644 --- a/samples/bpf/tracex5_user.c +++ b/samples/bpf/tracex5_user.c @@ -42,7 +42,7 @@ int main(int ac, char **argv) char filename[256]; FILE *f; - snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); + snprintf(filename, sizeof(filename), "%s.bpf.o", argv[0]); obj = bpf_object__open_file(filename, NULL); if (libbpf_get_error(obj)) { fprintf(stderr, "ERROR: opening BPF object file failed\n"); diff --git a/samples/bpf/tracex6.bpf.c b/samples/bpf/tracex6.bpf.c new file mode 100644 index 000000000000..6ad82e68f998 --- /dev/null +++ b/samples/bpf/tracex6.bpf.c @@ -0,0 +1,68 @@ +#include "vmlinux.h" +#include +#include + +struct { + __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); + __uint(key_size, sizeof(int)); + __uint(value_size, sizeof(u32)); + __uint(max_entries, 64); +} counters SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __type(key, int); + __type(value, u64); + __uint(max_entries, 64); +} values SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __type(key, int); + __type(value, struct bpf_perf_event_value); + __uint(max_entries, 64); +} values2 SEC(".maps"); + +SEC("kprobe/htab_map_get_next_key") +int bpf_prog1(struct pt_regs *ctx) +{ + u32 key = bpf_get_smp_processor_id(); + u64 count, *val; + s64 error; + + count = bpf_perf_event_read(&counters, key); + error = (s64)count; + if (error <= -2 && error >= -22) + return 0; + + val = bpf_map_lookup_elem(&values, &key); + if (val) + *val = count; + else + bpf_map_update_elem(&values, &key, &count, BPF_NOEXIST); + + return 0; +} + +SEC("kprobe/htab_map_lookup_elem") +int bpf_prog2(struct pt_regs *ctx) +{ + u32 key = bpf_get_smp_processor_id(); + struct bpf_perf_event_value *val, buf; + int error; + + error = bpf_perf_event_read_value(&counters, key, &buf, sizeof(buf)); + if (error) + return 0; + + val = bpf_map_lookup_elem(&values2, &key); + if (val) + *val = buf; + else + bpf_map_update_elem(&values2, &key, &buf, BPF_NOEXIST); + + return 0; +} + +char _license[] SEC("license") = "GPL"; +u32 _version SEC("version") = LINUX_VERSION_CODE; diff --git a/samples/bpf/tracex6_kern.c b/samples/bpf/tracex6_kern.c deleted file mode 100644 index 6ad82e68f998..000000000000 --- a/samples/bpf/tracex6_kern.c +++ /dev/null @@ -1,68 +0,0 @@ -#include "vmlinux.h" -#include -#include - -struct { - __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); - __uint(key_size, sizeof(int)); - __uint(value_size, sizeof(u32)); - __uint(max_entries, 64); -} counters SEC(".maps"); - -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __type(key, int); - __type(value, u64); - __uint(max_entries, 64); -} values SEC(".maps"); - -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __type(key, int); - __type(value, struct bpf_perf_event_value); - __uint(max_entries, 64); -} values2 SEC(".maps"); - -SEC("kprobe/htab_map_get_next_key") -int bpf_prog1(struct pt_regs *ctx) -{ - u32 key = bpf_get_smp_processor_id(); - u64 count, *val; - s64 error; - - count = bpf_perf_event_read(&counters, key); - error = (s64)count; - if (error <= -2 && error >= -22) - return 0; - - val = bpf_map_lookup_elem(&values, &key); - if (val) - *val = count; - else - bpf_map_update_elem(&values, &key, &count, BPF_NOEXIST); - - return 0; -} - -SEC("kprobe/htab_map_lookup_elem") -int bpf_prog2(struct pt_regs *ctx) -{ - u32 key = bpf_get_smp_processor_id(); - struct bpf_perf_event_value *val, buf; - int error; - - error = bpf_perf_event_read_value(&counters, key, &buf, sizeof(buf)); - if (error) - return 0; - - val = bpf_map_lookup_elem(&values2, &key); - if (val) - *val = buf; - else - bpf_map_update_elem(&values2, &key, &buf, BPF_NOEXIST); - - return 0; -} - -char _license[] SEC("license") = "GPL"; -u32 _version SEC("version") = LINUX_VERSION_CODE; diff --git a/samples/bpf/tracex6_user.c b/samples/bpf/tracex6_user.c index 8e83bf2a84a4..ae811ac83bc2 100644 --- a/samples/bpf/tracex6_user.c +++ b/samples/bpf/tracex6_user.c @@ -180,7 +180,7 @@ int main(int argc, char **argv) char filename[256]; int i = 0; - snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); + snprintf(filename, sizeof(filename), "%s.bpf.o", argv[0]); obj = bpf_object__open_file(filename, NULL); if (libbpf_get_error(obj)) { fprintf(stderr, "ERROR: opening BPF object file failed\n"); diff --git a/samples/bpf/tracex7.bpf.c b/samples/bpf/tracex7.bpf.c new file mode 100644 index 000000000000..ab8d6704a5a4 --- /dev/null +++ b/samples/bpf/tracex7.bpf.c @@ -0,0 +1,15 @@ +#include "vmlinux.h" +#include +#include + +SEC("kprobe/open_ctree") +int bpf_prog1(struct pt_regs *ctx) +{ + unsigned long rc = -12; + + bpf_override_return(ctx, rc); + return 0; +} + +char _license[] SEC("license") = "GPL"; +u32 _version SEC("version") = LINUX_VERSION_CODE; diff --git a/samples/bpf/tracex7_kern.c b/samples/bpf/tracex7_kern.c deleted file mode 100644 index ab8d6704a5a4..000000000000 --- a/samples/bpf/tracex7_kern.c +++ /dev/null @@ -1,15 +0,0 @@ -#include "vmlinux.h" -#include -#include - -SEC("kprobe/open_ctree") -int bpf_prog1(struct pt_regs *ctx) -{ - unsigned long rc = -12; - - bpf_override_return(ctx, rc); - return 0; -} - -char _license[] SEC("license") = "GPL"; -u32 _version SEC("version") = LINUX_VERSION_CODE; diff --git a/samples/bpf/tracex7_user.c b/samples/bpf/tracex7_user.c index 8be7ce18d3ba..b10b5e03a226 100644 --- a/samples/bpf/tracex7_user.c +++ b/samples/bpf/tracex7_user.c @@ -19,7 +19,7 @@ int main(int argc, char **argv) return 0; } - snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); + snprintf(filename, sizeof(filename), "%s.bpf.o", argv[0]); obj = bpf_object__open_file(filename, NULL); if (libbpf_get_error(obj)) { fprintf(stderr, "ERROR: opening BPF object file failed\n"); -- cgit v1.2.3 From 02dabc247ad68b41758bf39f11e2d682b8b32dd7 Mon Sep 17 00:00:00 2001 From: "Daniel T. Lee" Date: Fri, 18 Aug 2023 18:01:14 +0900 Subject: samples/bpf: fix symbol mismatch by compiler optimization Currently, multiple kprobe programs are suffering from symbol mismatch due to compiler optimization. These optimizations might induce additional suffix to the symbol name such as '.isra' or '.constprop'. # egrep ' finish_task_switch| __netif_receive_skb_core' /proc/kallsyms ffffffff81135e50 t finish_task_switch.isra.0 ffffffff81dd36d0 t __netif_receive_skb_core.constprop.0 ffffffff8205cc0e t finish_task_switch.isra.0.cold ffffffff820b1aba t __netif_receive_skb_core.constprop.0.cold To avoid this, this commit replaces the original kprobe section to kprobe.multi in order to match symbol with wildcard characters. Here, asterisk is used for avoiding symbol mismatch. Signed-off-by: Daniel T. Lee Link: https://lore.kernel.org/r/20230818090119.477441-5-danieltimlee@gmail.com Signed-off-by: Alexei Starovoitov --- samples/bpf/offwaketime.bpf.c | 2 +- samples/bpf/tracex1.bpf.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'samples') diff --git a/samples/bpf/offwaketime.bpf.c b/samples/bpf/offwaketime.bpf.c index 8e5105811178..3200a0f44969 100644 --- a/samples/bpf/offwaketime.bpf.c +++ b/samples/bpf/offwaketime.bpf.c @@ -118,7 +118,7 @@ int oncpu(struct trace_event_raw_sched_switch *ctx) /* record previous thread sleep time */ u32 pid = ctx->prev_pid; #else -SEC("kprobe/finish_task_switch") +SEC("kprobe.multi/finish_task_switch*") int oncpu(struct pt_regs *ctx) { struct task_struct *p = (void *) PT_REGS_PARM1(ctx); diff --git a/samples/bpf/tracex1.bpf.c b/samples/bpf/tracex1.bpf.c index bb78bdbffa87..f3be14a03964 100644 --- a/samples/bpf/tracex1.bpf.c +++ b/samples/bpf/tracex1.bpf.c @@ -22,11 +22,12 @@ * Number of arguments and their positions can change, etc. * In such case this bpf+kprobe example will no longer be meaningful */ -SEC("kprobe/__netif_receive_skb_core") +SEC("kprobe.multi/__netif_receive_skb_core*") int bpf_prog1(struct pt_regs *ctx) { /* attaches to kprobe __netif_receive_skb_core, * looks for packets on loobpack device and prints them + * (wildcard is used for avoiding symbol mismatch due to optimization) */ char devname[IFNAMSIZ]; struct net_device *dev; -- cgit v1.2.3 From 11430421b440427e10dfb4bd2bdc418fab0ff166 Mon Sep 17 00:00:00 2001 From: "Daniel T. Lee" Date: Fri, 18 Aug 2023 18:01:15 +0900 Subject: samples/bpf: make tracing programs to be more CO-RE centric The existing tracing programs have been developed for a considerable period of time and, as a result, do not properly incorporate the features of the current libbpf, such as CO-RE. This is evident in frequent usage of functions like PT_REGS* and the persistence of "hack" methods using underscore-style bpf_probe_read_kernel from the past. These programs are far behind the current level of libbpf and can potentially confuse users. Therefore, this commit aims to convert the outdated BPF programs to be more CO-RE centric. Signed-off-by: Daniel T. Lee Link: https://lore.kernel.org/r/20230818090119.477441-6-danieltimlee@gmail.com Signed-off-by: Alexei Starovoitov --- samples/bpf/offwaketime.bpf.c | 18 +++++------------- samples/bpf/test_overhead_kprobe.bpf.c | 20 +++++++------------- samples/bpf/tracex1.bpf.c | 17 +++++------------ samples/bpf/tracex5.bpf.c | 5 +++-- 4 files changed, 20 insertions(+), 40 deletions(-) (limited to 'samples') diff --git a/samples/bpf/offwaketime.bpf.c b/samples/bpf/offwaketime.bpf.c index 3200a0f44969..4a65ba76c1b1 100644 --- a/samples/bpf/offwaketime.bpf.c +++ b/samples/bpf/offwaketime.bpf.c @@ -8,18 +8,12 @@ #include #include #include +#include #ifndef PERF_MAX_STACK_DEPTH #define PERF_MAX_STACK_DEPTH 127 #endif -#define _(P) \ - ({ \ - typeof(P) val; \ - bpf_probe_read_kernel(&val, sizeof(val), &(P)); \ - val; \ - }) - #define MINBLOCK_US 1 #define MAX_ENTRIES 10000 @@ -68,11 +62,9 @@ struct { SEC("kprobe/try_to_wake_up") int waker(struct pt_regs *ctx) { - struct task_struct *p = (void *) PT_REGS_PARM1(ctx); + struct task_struct *p = (void *)PT_REGS_PARM1_CORE(ctx); + u32 pid = BPF_CORE_READ(p, pid); struct wokeby_t woke; - u32 pid; - - pid = _(p->pid); bpf_get_current_comm(&woke.name, sizeof(woke.name)); woke.ret = bpf_get_stackid(ctx, &stackmap, STACKID_FLAGS); @@ -121,9 +113,9 @@ int oncpu(struct trace_event_raw_sched_switch *ctx) SEC("kprobe.multi/finish_task_switch*") int oncpu(struct pt_regs *ctx) { - struct task_struct *p = (void *) PT_REGS_PARM1(ctx); + struct task_struct *p = (void *)PT_REGS_PARM1_CORE(ctx); /* record previous thread sleep time */ - u32 pid = _(p->pid); + u32 pid = BPF_CORE_READ(p, pid); #endif u64 delta, ts, *tsp; diff --git a/samples/bpf/test_overhead_kprobe.bpf.c b/samples/bpf/test_overhead_kprobe.bpf.c index c3528731e0e1..668cf5259c60 100644 --- a/samples/bpf/test_overhead_kprobe.bpf.c +++ b/samples/bpf/test_overhead_kprobe.bpf.c @@ -8,13 +8,7 @@ #include #include #include - -#define _(P) \ - ({ \ - typeof(P) val = 0; \ - bpf_probe_read_kernel(&val, sizeof(val), &(P)); \ - val; \ - }) +#include SEC("kprobe/__set_task_comm") int prog(struct pt_regs *ctx) @@ -26,14 +20,14 @@ int prog(struct pt_regs *ctx) u16 oom_score_adj; u32 pid; - tsk = (void *)PT_REGS_PARM1(ctx); + tsk = (void *)PT_REGS_PARM1_CORE(ctx); - pid = _(tsk->pid); - bpf_probe_read_kernel_str(oldcomm, sizeof(oldcomm), &tsk->comm); - bpf_probe_read_kernel_str(newcomm, sizeof(newcomm), + pid = BPF_CORE_READ(tsk, pid); + bpf_core_read_str(oldcomm, sizeof(oldcomm), &tsk->comm); + bpf_core_read_str(newcomm, sizeof(newcomm), (void *)PT_REGS_PARM2(ctx)); - signal = _(tsk->signal); - oom_score_adj = _(signal->oom_score_adj); + signal = BPF_CORE_READ(tsk, signal); + oom_score_adj = BPF_CORE_READ(signal, oom_score_adj); return 0; } diff --git a/samples/bpf/tracex1.bpf.c b/samples/bpf/tracex1.bpf.c index f3be14a03964..0ab39d76ff8f 100644 --- a/samples/bpf/tracex1.bpf.c +++ b/samples/bpf/tracex1.bpf.c @@ -8,15 +8,9 @@ #include "net_shared.h" #include #include +#include #include -#define _(P) \ - ({ \ - typeof(P) val = 0; \ - bpf_probe_read_kernel(&val, sizeof(val), &(P)); \ - val; \ - }) - /* kprobe is NOT a stable ABI * kernel functions can be removed, renamed or completely change semantics. * Number of arguments and their positions can change, etc. @@ -34,12 +28,11 @@ int bpf_prog1(struct pt_regs *ctx) struct sk_buff *skb; int len; - /* non-portable! works for the given kernel only */ - bpf_probe_read_kernel(&skb, sizeof(skb), (void *)PT_REGS_PARM1(ctx)); - dev = _(skb->dev); - len = _(skb->len); + bpf_core_read(&skb, sizeof(skb), (void *)PT_REGS_PARM1(ctx)); + dev = BPF_CORE_READ(skb, dev); + len = BPF_CORE_READ(skb, len); - bpf_probe_read_kernel(devname, sizeof(devname), dev->name); + BPF_CORE_READ_STR_INTO(&devname, dev, name); if (devname[0] == 'l' && devname[1] == 'o') { char fmt[] = "skb %p len %d\n"; diff --git a/samples/bpf/tracex5.bpf.c b/samples/bpf/tracex5.bpf.c index 8cd697ee7047..4d3d6c9b25fa 100644 --- a/samples/bpf/tracex5.bpf.c +++ b/samples/bpf/tracex5.bpf.c @@ -10,6 +10,7 @@ #include #include #include +#include #define __stringify(x) #x #define PROG(F) SEC("kprobe/"__stringify(F)) int bpf_func_##F @@ -46,7 +47,7 @@ PROG(SYS__NR_write)(struct pt_regs *ctx) { struct seccomp_data sd; - bpf_probe_read_kernel(&sd, sizeof(sd), (void *)PT_REGS_PARM2(ctx)); + bpf_core_read(&sd, sizeof(sd), (void *)PT_REGS_PARM2(ctx)); if (sd.args[2] == 512) { char fmt[] = "write(fd=%d, buf=%p, size=%d)\n"; bpf_trace_printk(fmt, sizeof(fmt), @@ -59,7 +60,7 @@ PROG(SYS__NR_read)(struct pt_regs *ctx) { struct seccomp_data sd; - bpf_probe_read_kernel(&sd, sizeof(sd), (void *)PT_REGS_PARM2(ctx)); + bpf_core_read(&sd, sizeof(sd), (void *)PT_REGS_PARM2(ctx)); if (sd.args[2] > 128 && sd.args[2] <= 1024) { char fmt[] = "read(fd=%d, buf=%p, size=%d)\n"; bpf_trace_printk(fmt, sizeof(fmt), -- cgit v1.2.3 From 92632115fb57ff9e368f256913e96d6fd5abf5ab Mon Sep 17 00:00:00 2001 From: "Daniel T. Lee" Date: Fri, 18 Aug 2023 18:01:16 +0900 Subject: samples/bpf: fix bio latency check with tracepoint Recently, a new tracepoint for the block layer, specifically the block_io_start/done tracepoints, was introduced in commit 5a80bd075f3b ("block: introduce block_io_start/block_io_done tracepoints"). Previously, the kprobe entry used for this purpose was quite unstable and inherently broke relevant probes [1]. Now that a stable tracepoint is available, this commit replaces the bio latency check with it. One of the changes made during this replacement is the key used for the hash table. Since 'struct request' cannot be used as a hash key, the approach taken follows that which was implemented in bcc/biolatency [2]. (uses dev:sector for the key) [1]: https://github.com/iovisor/bcc/issues/4261 [2]: https://github.com/iovisor/bcc/pull/4691 Fixes: 450b7879e345 ("block: move blk_account_io_{start,done} to blk-mq.c") Signed-off-by: Daniel T. Lee Link: https://lore.kernel.org/r/20230818090119.477441-7-danieltimlee@gmail.com Signed-off-by: Alexei Starovoitov --- samples/bpf/tracex3.bpf.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) (limited to 'samples') diff --git a/samples/bpf/tracex3.bpf.c b/samples/bpf/tracex3.bpf.c index 7cc60f10d2e5..41f37966f5f5 100644 --- a/samples/bpf/tracex3.bpf.c +++ b/samples/bpf/tracex3.bpf.c @@ -9,6 +9,12 @@ #include #include +struct start_key { + dev_t dev; + u32 _pad; + sector_t sector; +}; + struct { __uint(type, BPF_MAP_TYPE_HASH); __type(key, long); @@ -16,16 +22,17 @@ struct { __uint(max_entries, 4096); } my_map SEC(".maps"); -/* kprobe is NOT a stable ABI. If kernel internals change this bpf+kprobe - * example will no longer be meaningful - */ -SEC("kprobe/blk_mq_start_request") -int bpf_prog1(struct pt_regs *ctx) +/* from /sys/kernel/tracing/events/block/block_io_start/format */ +SEC("tracepoint/block/block_io_start") +int bpf_prog1(struct trace_event_raw_block_rq *ctx) { - long rq = PT_REGS_PARM1(ctx); u64 val = bpf_ktime_get_ns(); + struct start_key key = { + .dev = ctx->dev, + .sector = ctx->sector + }; - bpf_map_update_elem(&my_map, &rq, &val, BPF_ANY); + bpf_map_update_elem(&my_map, &key, &val, BPF_ANY); return 0; } @@ -47,21 +54,26 @@ struct { __uint(max_entries, SLOTS); } lat_map SEC(".maps"); -SEC("kprobe/__blk_account_io_done") -int bpf_prog2(struct pt_regs *ctx) +/* from /sys/kernel/tracing/events/block/block_io_done/format */ +SEC("tracepoint/block/block_io_done") +int bpf_prog2(struct trace_event_raw_block_rq *ctx) { - long rq = PT_REGS_PARM1(ctx); + struct start_key key = { + .dev = ctx->dev, + .sector = ctx->sector + }; + u64 *value, l, base; u32 index; - value = bpf_map_lookup_elem(&my_map, &rq); + value = bpf_map_lookup_elem(&my_map, &key); if (!value) return 0; u64 cur_time = bpf_ktime_get_ns(); u64 delta = cur_time - *value; - bpf_map_delete_elem(&my_map, &rq); + bpf_map_delete_elem(&my_map, &key); /* the lines below are computing index = log10(delta)*10 * using integer arithmetic -- cgit v1.2.3 From d93a7cf6ca2cfcd7de5d06f753ce8d5e863316ac Mon Sep 17 00:00:00 2001 From: "Daniel T. Lee" Date: Fri, 18 Aug 2023 18:01:17 +0900 Subject: samples/bpf: fix broken map lookup probe In the commit 7c4cd051add3 ("bpf: Fix syscall's stackmap lookup potential deadlock"), a potential deadlock issue was addressed, which resulted in *_map_lookup_elem not triggering BPF programs. (prior to lookup, bpf_disable_instrumentation() is used) To resolve the broken map lookup probe using "htab_map_lookup_elem", this commit introduces an alternative approach. Instead, it utilize "bpf_map_copy_value" and apply a filter specifically for the hash table with map_type. Signed-off-by: Daniel T. Lee Fixes: 7c4cd051add3 ("bpf: Fix syscall's stackmap lookup potential deadlock") Link: https://lore.kernel.org/r/20230818090119.477441-8-danieltimlee@gmail.com Signed-off-by: Alexei Starovoitov --- samples/bpf/tracex6.bpf.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'samples') diff --git a/samples/bpf/tracex6.bpf.c b/samples/bpf/tracex6.bpf.c index 6ad82e68f998..9b23b4737cfb 100644 --- a/samples/bpf/tracex6.bpf.c +++ b/samples/bpf/tracex6.bpf.c @@ -1,6 +1,8 @@ #include "vmlinux.h" #include #include +#include +#include struct { __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); @@ -44,13 +46,24 @@ int bpf_prog1(struct pt_regs *ctx) return 0; } -SEC("kprobe/htab_map_lookup_elem") -int bpf_prog2(struct pt_regs *ctx) +/* + * Since *_map_lookup_elem can't be expected to trigger bpf programs + * due to potential deadlocks (bpf_disable_instrumentation), this bpf + * program will be attached to bpf_map_copy_value (which is called + * from map_lookup_elem) and will only filter the hashtable type. + */ +SEC("kprobe/bpf_map_copy_value") +int BPF_KPROBE(bpf_prog2, struct bpf_map *map) { u32 key = bpf_get_smp_processor_id(); struct bpf_perf_event_value *val, buf; + enum bpf_map_type type; int error; + type = BPF_CORE_READ(map, map_type); + if (type != BPF_MAP_TYPE_HASH) + return 0; + error = bpf_perf_event_read_value(&counters, key, &buf, sizeof(buf)); if (error) return 0; -- cgit v1.2.3 From 8dc80551463197ec79ce0966ec2b5bd700042614 Mon Sep 17 00:00:00 2001 From: "Daniel T. Lee" Date: Fri, 18 Aug 2023 18:01:18 +0900 Subject: samples/bpf: refactor syscall tracing programs using BPF_KSYSCALL macro This commit refactors the syscall tracing programs by adopting the BPF_KSYSCALL macro. This change aims to enhance the clarity and simplicity of the BPF programs by reducing the complexity of argument parsing from pt_regs. Signed-off-by: Daniel T. Lee Link: https://lore.kernel.org/r/20230818090119.477441-9-danieltimlee@gmail.com Signed-off-by: Alexei Starovoitov --- samples/bpf/test_map_in_map.bpf.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'samples') diff --git a/samples/bpf/test_map_in_map.bpf.c b/samples/bpf/test_map_in_map.bpf.c index 1883559e5977..9f030f9c4e1b 100644 --- a/samples/bpf/test_map_in_map.bpf.c +++ b/samples/bpf/test_map_in_map.bpf.c @@ -103,19 +103,15 @@ static __always_inline int do_inline_hash_lookup(void *inner_map, u32 port) return result ? *result : -ENOENT; } -SEC("kprobe/__sys_connect") -int trace_sys_connect(struct pt_regs *ctx) +SEC("ksyscall/connect") +int BPF_KSYSCALL(trace_sys_connect, unsigned int fd, struct sockaddr_in6 *in6, int addrlen) { - struct sockaddr_in6 *in6; u16 test_case, port, dst6[8]; - int addrlen, ret, inline_ret, ret_key = 0; + int ret, inline_ret, ret_key = 0; u32 port_key; void *outer_map, *inner_map; bool inline_hash = false; - in6 = (struct sockaddr_in6 *)PT_REGS_PARM2_CORE(ctx); - addrlen = (int)PT_REGS_PARM3_CORE(ctx); - if (addrlen != sizeof(*in6)) return 0; -- cgit v1.2.3 From 456d53554ca7e93d7e5e8eb7fe8c906d5ec6e7d0 Mon Sep 17 00:00:00 2001 From: "Daniel T. Lee" Date: Fri, 18 Aug 2023 18:01:19 +0900 Subject: samples/bpf: simplify spintest with kprobe.multi With the introduction of kprobe.multi, it is now possible to attach multiple kprobes to a single BPF program without the need for multiple definitions. Additionally, this method supports wildcard-based matching, allowing for further simplification of BPF programs. In here, an asterisk (*) wildcard is used to map to all symbols relevant to spin_{lock|unlock}. Furthermore, since kprobe.multi handles symbol matching, this commit eliminates the need for the previous logic of reading the ksym table to verify the existence of symbols. Signed-off-by: Daniel T. Lee Link: https://lore.kernel.org/r/20230818090119.477441-10-danieltimlee@gmail.com Signed-off-by: Alexei Starovoitov --- samples/bpf/spintest.bpf.c | 17 +++-------------- samples/bpf/spintest_user.c | 22 +++++++--------------- 2 files changed, 10 insertions(+), 29 deletions(-) (limited to 'samples') diff --git a/samples/bpf/spintest.bpf.c b/samples/bpf/spintest.bpf.c index 15740b16a3f7..cba5a9d50783 100644 --- a/samples/bpf/spintest.bpf.c +++ b/samples/bpf/spintest.bpf.c @@ -47,20 +47,9 @@ int foo(struct pt_regs *ctx) \ } /* add kprobes to all possible *spin* functions */ -SEC("kprobe/spin_unlock")PROG(p1) -SEC("kprobe/spin_lock")PROG(p2) -SEC("kprobe/mutex_spin_on_owner")PROG(p3) -SEC("kprobe/rwsem_spin_on_owner")PROG(p4) -SEC("kprobe/spin_unlock_irqrestore")PROG(p5) -SEC("kprobe/_raw_spin_unlock_irqrestore")PROG(p6) -SEC("kprobe/_raw_spin_unlock_bh")PROG(p7) -SEC("kprobe/_raw_spin_unlock")PROG(p8) -SEC("kprobe/_raw_spin_lock_irqsave")PROG(p9) -SEC("kprobe/_raw_spin_trylock_bh")PROG(p10) -SEC("kprobe/_raw_spin_lock_irq")PROG(p11) -SEC("kprobe/_raw_spin_trylock")PROG(p12) -SEC("kprobe/_raw_spin_lock")PROG(p13) -SEC("kprobe/_raw_spin_lock_bh")PROG(p14) +SEC("kprobe.multi/spin_*lock*")PROG(spin_lock) +SEC("kprobe.multi/*_spin_on_owner")PROG(spin_on_owner) +SEC("kprobe.multi/_raw_spin_*lock*")PROG(raw_spin_lock) /* and to inner bpf helpers */ SEC("kprobe/htab_map_update_elem")PROG(p15) diff --git a/samples/bpf/spintest_user.c b/samples/bpf/spintest_user.c index 8c77600776fb..55971edb1088 100644 --- a/samples/bpf/spintest_user.c +++ b/samples/bpf/spintest_user.c @@ -9,13 +9,12 @@ int main(int ac, char **argv) { - char filename[256], symbol[256]; struct bpf_object *obj = NULL; struct bpf_link *links[20]; long key, next_key, value; struct bpf_program *prog; int map_fd, i, j = 0; - const char *section; + char filename[256]; struct ksym *sym; if (load_kallsyms()) { @@ -44,20 +43,13 @@ int main(int ac, char **argv) } bpf_object__for_each_program(prog, obj) { - section = bpf_program__section_name(prog); - if (sscanf(section, "kprobe/%s", symbol) != 1) - continue; - - /* Attach prog only when symbol exists */ - if (ksym_get_addr(symbol)) { - links[j] = bpf_program__attach(prog); - if (libbpf_get_error(links[j])) { - fprintf(stderr, "bpf_program__attach failed\n"); - links[j] = NULL; - goto cleanup; - } - j++; + links[j] = bpf_program__attach(prog); + if (libbpf_get_error(links[j])) { + fprintf(stderr, "bpf_program__attach failed\n"); + links[j] = NULL; + goto cleanup; } + j++; } for (i = 0; i < 5; i++) { -- cgit v1.2.3 From e7c9e73d082252ecd026f7e01d8015a347c375c1 Mon Sep 17 00:00:00 2001 From: Toke Høiland-Jørgensen Date: Thu, 24 Aug 2023 12:22:44 +0200 Subject: samples/bpf: Remove the xdp_monitor utility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This utility has been ported as-is to xdp-tools as 'xdp-monitor'. The only difference in usage between the samples and xdp-tools versions is that the '-v' command line parameter has been changed to '-e' in the xdp-tools version for consistency with the other utilities. Signed-off-by: Toke Høiland-Jørgensen Link: https://lore.kernel.org/r/20230824102255.1561885-2-toke@redhat.com Signed-off-by: Alexei Starovoitov --- samples/bpf/Makefile | 8 +-- samples/bpf/xdp_monitor.bpf.c | 8 --- samples/bpf/xdp_monitor_user.c | 118 ----------------------------------------- 3 files changed, 1 insertion(+), 133 deletions(-) delete mode 100644 samples/bpf/xdp_monitor.bpf.c delete mode 100644 samples/bpf/xdp_monitor_user.c (limited to 'samples') diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile index f90bcd3696bd..29b07c4ec066 100644 --- a/samples/bpf/Makefile +++ b/samples/bpf/Makefile @@ -55,7 +55,6 @@ tprogs-y += xdp_redirect_cpu tprogs-y += xdp_redirect_map_multi tprogs-y += xdp_redirect_map tprogs-y += xdp_redirect -tprogs-y += xdp_monitor # Libbpf dependencies LIBBPF_SRC = $(TOOLS_PATH)/lib/bpf @@ -116,7 +115,6 @@ xdp_redirect_map_multi-objs := xdp_redirect_map_multi_user.o $(XDP_SAMPLE) xdp_redirect_cpu-objs := xdp_redirect_cpu_user.o $(XDP_SAMPLE) xdp_redirect_map-objs := xdp_redirect_map_user.o $(XDP_SAMPLE) xdp_redirect-objs := xdp_redirect_user.o $(XDP_SAMPLE) -xdp_monitor-objs := xdp_monitor_user.o $(XDP_SAMPLE) xdp_router_ipv4-objs := xdp_router_ipv4_user.o $(XDP_SAMPLE) # Tell kbuild to always build the programs @@ -207,7 +205,6 @@ TPROGS_LDFLAGS := -L$(SYSROOT)/usr/lib endif TPROGS_LDLIBS += $(LIBBPF) -lelf -lz -TPROGLDLIBS_xdp_monitor += -lm TPROGLDLIBS_xdp_redirect += -lm TPROGLDLIBS_xdp_redirect_cpu += -lm TPROGLDLIBS_xdp_redirect_map += -lm @@ -330,7 +327,6 @@ $(obj)/xdp_redirect_cpu_user.o: $(obj)/xdp_redirect_cpu.skel.h $(obj)/xdp_redirect_map_multi_user.o: $(obj)/xdp_redirect_map_multi.skel.h $(obj)/xdp_redirect_map_user.o: $(obj)/xdp_redirect_map.skel.h $(obj)/xdp_redirect_user.o: $(obj)/xdp_redirect.skel.h -$(obj)/xdp_monitor_user.o: $(obj)/xdp_monitor.skel.h $(obj)/xdp_router_ipv4_user.o: $(obj)/xdp_router_ipv4.skel.h $(obj)/tracex5.bpf.o: $(obj)/syscall_nrs.h @@ -387,7 +383,6 @@ $(obj)/xdp_redirect_cpu.bpf.o: $(obj)/xdp_sample.bpf.o $(obj)/xdp_redirect_map_multi.bpf.o: $(obj)/xdp_sample.bpf.o $(obj)/xdp_redirect_map.bpf.o: $(obj)/xdp_sample.bpf.o $(obj)/xdp_redirect.bpf.o: $(obj)/xdp_sample.bpf.o -$(obj)/xdp_monitor.bpf.o: $(obj)/xdp_sample.bpf.o $(obj)/xdp_router_ipv4.bpf.o: $(obj)/xdp_sample.bpf.o $(obj)/%.bpf.o: $(src)/%.bpf.c $(obj)/vmlinux.h $(src)/xdp_sample.bpf.h $(src)/xdp_sample_shared.h @@ -399,7 +394,7 @@ $(obj)/%.bpf.o: $(src)/%.bpf.c $(obj)/vmlinux.h $(src)/xdp_sample.bpf.h $(src)/x -c $(filter %.bpf.c,$^) -o $@ LINKED_SKELS := xdp_redirect_cpu.skel.h xdp_redirect_map_multi.skel.h \ - xdp_redirect_map.skel.h xdp_redirect.skel.h xdp_monitor.skel.h \ + xdp_redirect_map.skel.h xdp_redirect.skel.h \ xdp_router_ipv4.skel.h clean-files += $(LINKED_SKELS) @@ -407,7 +402,6 @@ xdp_redirect_cpu.skel.h-deps := xdp_redirect_cpu.bpf.o xdp_sample.bpf.o xdp_redirect_map_multi.skel.h-deps := xdp_redirect_map_multi.bpf.o xdp_sample.bpf.o xdp_redirect_map.skel.h-deps := xdp_redirect_map.bpf.o xdp_sample.bpf.o xdp_redirect.skel.h-deps := xdp_redirect.bpf.o xdp_sample.bpf.o -xdp_monitor.skel.h-deps := xdp_monitor.bpf.o xdp_sample.bpf.o xdp_router_ipv4.skel.h-deps := xdp_router_ipv4.bpf.o xdp_sample.bpf.o LINKED_BPF_SRCS := $(patsubst %.bpf.o,%.bpf.c,$(foreach skel,$(LINKED_SKELS),$($(skel)-deps))) diff --git a/samples/bpf/xdp_monitor.bpf.c b/samples/bpf/xdp_monitor.bpf.c deleted file mode 100644 index cfb41e2205f4..000000000000 --- a/samples/bpf/xdp_monitor.bpf.c +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2017-2018 Jesper Dangaard Brouer, Red Hat Inc. - * - * XDP monitor tool, based on tracepoints - */ -#include "xdp_sample.bpf.h" - -char _license[] SEC("license") = "GPL"; diff --git a/samples/bpf/xdp_monitor_user.c b/samples/bpf/xdp_monitor_user.c deleted file mode 100644 index 58015eb2ffae..000000000000 --- a/samples/bpf/xdp_monitor_user.c +++ /dev/null @@ -1,118 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2017 Jesper Dangaard Brouer, Red Hat, Inc. */ -static const char *__doc__= -"XDP monitor tool, based on tracepoints\n"; - -static const char *__doc_err_only__= -" NOTICE: Only tracking XDP redirect errors\n" -" Enable redirect success stats via '-s/--stats'\n" -" (which comes with a per packet processing overhead)\n"; - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "bpf_util.h" -#include "xdp_sample_user.h" -#include "xdp_monitor.skel.h" - -static int mask = SAMPLE_REDIRECT_ERR_CNT | SAMPLE_CPUMAP_ENQUEUE_CNT | - SAMPLE_CPUMAP_KTHREAD_CNT | SAMPLE_EXCEPTION_CNT | - SAMPLE_DEVMAP_XMIT_CNT | SAMPLE_DEVMAP_XMIT_CNT_MULTI; - -DEFINE_SAMPLE_INIT(xdp_monitor); - -static const struct option long_options[] = { - { "help", no_argument, NULL, 'h' }, - { "stats", no_argument, NULL, 's' }, - { "interval", required_argument, NULL, 'i' }, - { "verbose", no_argument, NULL, 'v' }, - {} -}; - -int main(int argc, char **argv) -{ - unsigned long interval = 2; - int ret = EXIT_FAIL_OPTION; - struct xdp_monitor *skel; - bool errors_only = true; - int longindex = 0, opt; - bool error = true; - - /* Parse commands line args */ - while ((opt = getopt_long(argc, argv, "si:vh", - long_options, &longindex)) != -1) { - switch (opt) { - case 's': - errors_only = false; - mask |= SAMPLE_REDIRECT_CNT; - break; - case 'i': - interval = strtoul(optarg, NULL, 0); - break; - case 'v': - sample_switch_mode(); - break; - case 'h': - error = false; - default: - sample_usage(argv, long_options, __doc__, mask, error); - return ret; - } - } - - skel = xdp_monitor__open(); - if (!skel) { - fprintf(stderr, "Failed to xdp_monitor__open: %s\n", - strerror(errno)); - ret = EXIT_FAIL_BPF; - goto end; - } - - ret = sample_init_pre_load(skel); - if (ret < 0) { - fprintf(stderr, "Failed to sample_init_pre_load: %s\n", strerror(-ret)); - ret = EXIT_FAIL_BPF; - goto end_destroy; - } - - ret = xdp_monitor__load(skel); - if (ret < 0) { - fprintf(stderr, "Failed to xdp_monitor__load: %s\n", strerror(errno)); - ret = EXIT_FAIL_BPF; - goto end_destroy; - } - - ret = sample_init(skel, mask); - if (ret < 0) { - fprintf(stderr, "Failed to initialize sample: %s\n", strerror(-ret)); - ret = EXIT_FAIL_BPF; - goto end_destroy; - } - - if (errors_only) - printf("%s", __doc_err_only__); - - ret = sample_run(interval, NULL, NULL); - if (ret < 0) { - fprintf(stderr, "Failed during sample run: %s\n", strerror(-ret)); - ret = EXIT_FAIL; - goto end_destroy; - } - ret = EXIT_OK; -end_destroy: - xdp_monitor__destroy(skel); -end: - sample_exit(ret); -} -- cgit v1.2.3 From 91dda69b08de93465632561701a337ec18321ea4 Mon Sep 17 00:00:00 2001 From: Toke Høiland-Jørgensen Date: Thu, 24 Aug 2023 12:22:45 +0200 Subject: samples/bpf: Remove the xdp_redirect* utilities MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These utilities have all been ported to xdp-tools as functions of the xdp-bench utility. The four different utilities in samples are incorporated as separate subcommands to xdp-bench, with most of the command line parameters left intact, except that mandatory arguments are always positional in xdp-bench. For full usage details see the --help output of each command, or the xdp-bench man page. Some examples of how to convert usage to xdp-bench are: xdp_redirect eth0 eth1 --> xdp-bench redirect eth0 eth1 xdp_redirect_map eth0 eth1 --> xdp-bench redirect-map eth0 eth1 xdp_redirect_map_multi eth0 eth1 eth2 eth3 --> xdp-bench redirect-multi eth0 eth1 eth2 eth3 xdp_redirect_cpu -d eth0 -c 0 -c 1 --> xdp-bench redirect-cpu -c 0 -c 1 eth0 xdp_redirect_cpu -d eth0 -c 0 -c 1 -r eth1 --> xdp-bench redirect-cpu -c 0 -c 1 eth0 -r redirect -D eth1 Signed-off-by: Toke Høiland-Jørgensen Link: https://lore.kernel.org/r/20230824102255.1561885-3-toke@redhat.com Signed-off-by: Alexei Starovoitov --- samples/bpf/Makefile | 29 +- samples/bpf/xdp_redirect.bpf.c | 49 --- samples/bpf/xdp_redirect_cpu.bpf.c | 539 ---------------------------- samples/bpf/xdp_redirect_cpu_user.c | 559 ------------------------------ samples/bpf/xdp_redirect_map.bpf.c | 97 ------ samples/bpf/xdp_redirect_map_multi.bpf.c | 77 ---- samples/bpf/xdp_redirect_map_multi_user.c | 232 ------------- samples/bpf/xdp_redirect_map_user.c | 228 ------------ samples/bpf/xdp_redirect_user.c | 172 --------- 9 files changed, 1 insertion(+), 1981 deletions(-) delete mode 100644 samples/bpf/xdp_redirect.bpf.c delete mode 100644 samples/bpf/xdp_redirect_cpu.bpf.c delete mode 100644 samples/bpf/xdp_redirect_cpu_user.c delete mode 100644 samples/bpf/xdp_redirect_map.bpf.c delete mode 100644 samples/bpf/xdp_redirect_map_multi.bpf.c delete mode 100644 samples/bpf/xdp_redirect_map_multi_user.c delete mode 100644 samples/bpf/xdp_redirect_map_user.c delete mode 100644 samples/bpf/xdp_redirect_user.c (limited to 'samples') diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile index 29b07c4ec066..d2f5c043e4f3 100644 --- a/samples/bpf/Makefile +++ b/samples/bpf/Makefile @@ -51,11 +51,6 @@ tprogs-y += xdp_sample_pkts tprogs-y += ibumad tprogs-y += hbm -tprogs-y += xdp_redirect_cpu -tprogs-y += xdp_redirect_map_multi -tprogs-y += xdp_redirect_map -tprogs-y += xdp_redirect - # Libbpf dependencies LIBBPF_SRC = $(TOOLS_PATH)/lib/bpf LIBBPF_OUTPUT = $(abspath $(BPF_SAMPLES_PATH))/libbpf @@ -111,10 +106,6 @@ xdp_sample_pkts-objs := xdp_sample_pkts_user.o ibumad-objs := ibumad_user.o hbm-objs := hbm.o $(CGROUP_HELPERS) -xdp_redirect_map_multi-objs := xdp_redirect_map_multi_user.o $(XDP_SAMPLE) -xdp_redirect_cpu-objs := xdp_redirect_cpu_user.o $(XDP_SAMPLE) -xdp_redirect_map-objs := xdp_redirect_map_user.o $(XDP_SAMPLE) -xdp_redirect-objs := xdp_redirect_user.o $(XDP_SAMPLE) xdp_router_ipv4-objs := xdp_router_ipv4_user.o $(XDP_SAMPLE) # Tell kbuild to always build the programs @@ -205,10 +196,6 @@ TPROGS_LDFLAGS := -L$(SYSROOT)/usr/lib endif TPROGS_LDLIBS += $(LIBBPF) -lelf -lz -TPROGLDLIBS_xdp_redirect += -lm -TPROGLDLIBS_xdp_redirect_cpu += -lm -TPROGLDLIBS_xdp_redirect_map += -lm -TPROGLDLIBS_xdp_redirect_map_multi += -lm TPROGLDLIBS_xdp_router_ipv4 += -lm -pthread TPROGLDLIBS_tracex4 += -lrt TPROGLDLIBS_trace_output += -lrt @@ -323,10 +310,6 @@ $(obj)/$(TRACE_HELPERS) $(obj)/$(CGROUP_HELPERS) $(obj)/$(XDP_SAMPLE): | libbpf_ .PHONY: libbpf_hdrs -$(obj)/xdp_redirect_cpu_user.o: $(obj)/xdp_redirect_cpu.skel.h -$(obj)/xdp_redirect_map_multi_user.o: $(obj)/xdp_redirect_map_multi.skel.h -$(obj)/xdp_redirect_map_user.o: $(obj)/xdp_redirect_map.skel.h -$(obj)/xdp_redirect_user.o: $(obj)/xdp_redirect.skel.h $(obj)/xdp_router_ipv4_user.o: $(obj)/xdp_router_ipv4.skel.h $(obj)/tracex5.bpf.o: $(obj)/syscall_nrs.h @@ -379,10 +362,6 @@ endef CLANG_SYS_INCLUDES = $(call get_sys_includes,$(CLANG)) -$(obj)/xdp_redirect_cpu.bpf.o: $(obj)/xdp_sample.bpf.o -$(obj)/xdp_redirect_map_multi.bpf.o: $(obj)/xdp_sample.bpf.o -$(obj)/xdp_redirect_map.bpf.o: $(obj)/xdp_sample.bpf.o -$(obj)/xdp_redirect.bpf.o: $(obj)/xdp_sample.bpf.o $(obj)/xdp_router_ipv4.bpf.o: $(obj)/xdp_sample.bpf.o $(obj)/%.bpf.o: $(src)/%.bpf.c $(obj)/vmlinux.h $(src)/xdp_sample.bpf.h $(src)/xdp_sample_shared.h @@ -393,15 +372,9 @@ $(obj)/%.bpf.o: $(src)/%.bpf.c $(obj)/vmlinux.h $(src)/xdp_sample.bpf.h $(src)/x -I$(LIBBPF_INCLUDE) $(CLANG_SYS_INCLUDES) \ -c $(filter %.bpf.c,$^) -o $@ -LINKED_SKELS := xdp_redirect_cpu.skel.h xdp_redirect_map_multi.skel.h \ - xdp_redirect_map.skel.h xdp_redirect.skel.h \ - xdp_router_ipv4.skel.h +LINKED_SKELS := xdp_router_ipv4.skel.h clean-files += $(LINKED_SKELS) -xdp_redirect_cpu.skel.h-deps := xdp_redirect_cpu.bpf.o xdp_sample.bpf.o -xdp_redirect_map_multi.skel.h-deps := xdp_redirect_map_multi.bpf.o xdp_sample.bpf.o -xdp_redirect_map.skel.h-deps := xdp_redirect_map.bpf.o xdp_sample.bpf.o -xdp_redirect.skel.h-deps := xdp_redirect.bpf.o xdp_sample.bpf.o xdp_router_ipv4.skel.h-deps := xdp_router_ipv4.bpf.o xdp_sample.bpf.o LINKED_BPF_SRCS := $(patsubst %.bpf.o,%.bpf.c,$(foreach skel,$(LINKED_SKELS),$($(skel)-deps))) diff --git a/samples/bpf/xdp_redirect.bpf.c b/samples/bpf/xdp_redirect.bpf.c deleted file mode 100644 index 7c02bacfe96b..000000000000 --- a/samples/bpf/xdp_redirect.bpf.c +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2016 John Fastabend - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - */ -#include "vmlinux.h" -#include "xdp_sample.bpf.h" -#include "xdp_sample_shared.h" - -const volatile int ifindex_out; - -SEC("xdp") -int xdp_redirect_prog(struct xdp_md *ctx) -{ - void *data_end = (void *)(long)ctx->data_end; - void *data = (void *)(long)ctx->data; - u32 key = bpf_get_smp_processor_id(); - struct ethhdr *eth = data; - struct datarec *rec; - u64 nh_off; - - nh_off = sizeof(*eth); - if (data + nh_off > data_end) - return XDP_DROP; - - rec = bpf_map_lookup_elem(&rx_cnt, &key); - if (!rec) - return XDP_PASS; - NO_TEAR_INC(rec->processed); - - swap_src_dst_mac(data); - return bpf_redirect(ifindex_out, 0); -} - -/* Redirect require an XDP bpf_prog loaded on the TX device */ -SEC("xdp") -int xdp_redirect_dummy_prog(struct xdp_md *ctx) -{ - return XDP_PASS; -} - -char _license[] SEC("license") = "GPL"; diff --git a/samples/bpf/xdp_redirect_cpu.bpf.c b/samples/bpf/xdp_redirect_cpu.bpf.c deleted file mode 100644 index 87c54bfdbb70..000000000000 --- a/samples/bpf/xdp_redirect_cpu.bpf.c +++ /dev/null @@ -1,539 +0,0 @@ -/* XDP redirect to CPUs via cpumap (BPF_MAP_TYPE_CPUMAP) - * - * GPLv2, Copyright(c) 2017 Jesper Dangaard Brouer, Red Hat, Inc. - */ -#include "vmlinux.h" -#include "xdp_sample.bpf.h" -#include "xdp_sample_shared.h" -#include "hash_func01.h" - -/* Special map type that can XDP_REDIRECT frames to another CPU */ -struct { - __uint(type, BPF_MAP_TYPE_CPUMAP); - __uint(key_size, sizeof(u32)); - __uint(value_size, sizeof(struct bpf_cpumap_val)); -} cpu_map SEC(".maps"); - -/* Set of maps controlling available CPU, and for iterating through - * selectable redirect CPUs. - */ -struct { - __uint(type, BPF_MAP_TYPE_ARRAY); - __type(key, u32); - __type(value, u32); -} cpus_available SEC(".maps"); - -struct { - __uint(type, BPF_MAP_TYPE_ARRAY); - __type(key, u32); - __type(value, u32); - __uint(max_entries, 1); -} cpus_count SEC(".maps"); - -struct { - __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); - __type(key, u32); - __type(value, u32); - __uint(max_entries, 1); -} cpus_iterator SEC(".maps"); - -struct { - __uint(type, BPF_MAP_TYPE_DEVMAP); - __uint(key_size, sizeof(int)); - __uint(value_size, sizeof(struct bpf_devmap_val)); - __uint(max_entries, 1); -} tx_port SEC(".maps"); - -char tx_mac_addr[ETH_ALEN]; - -/* Helper parse functions */ - -static __always_inline -bool parse_eth(struct ethhdr *eth, void *data_end, - u16 *eth_proto, u64 *l3_offset) -{ - u16 eth_type; - u64 offset; - - offset = sizeof(*eth); - if ((void *)eth + offset > data_end) - return false; - - eth_type = eth->h_proto; - - /* Skip non 802.3 Ethertypes */ - if (__builtin_expect(bpf_ntohs(eth_type) < ETH_P_802_3_MIN, 0)) - return false; - - /* Handle VLAN tagged packet */ - if (eth_type == bpf_htons(ETH_P_8021Q) || - eth_type == bpf_htons(ETH_P_8021AD)) { - struct vlan_hdr *vlan_hdr; - - vlan_hdr = (void *)eth + offset; - offset += sizeof(*vlan_hdr); - if ((void *)eth + offset > data_end) - return false; - eth_type = vlan_hdr->h_vlan_encapsulated_proto; - } - /* Handle double VLAN tagged packet */ - if (eth_type == bpf_htons(ETH_P_8021Q) || - eth_type == bpf_htons(ETH_P_8021AD)) { - struct vlan_hdr *vlan_hdr; - - vlan_hdr = (void *)eth + offset; - offset += sizeof(*vlan_hdr); - if ((void *)eth + offset > data_end) - return false; - eth_type = vlan_hdr->h_vlan_encapsulated_proto; - } - - *eth_proto = bpf_ntohs(eth_type); - *l3_offset = offset; - return true; -} - -static __always_inline -u16 get_dest_port_ipv4_udp(struct xdp_md *ctx, u64 nh_off) -{ - void *data_end = (void *)(long)ctx->data_end; - void *data = (void *)(long)ctx->data; - struct iphdr *iph = data + nh_off; - struct udphdr *udph; - - if (iph + 1 > data_end) - return 0; - if (!(iph->protocol == IPPROTO_UDP)) - return 0; - - udph = (void *)(iph + 1); - if (udph + 1 > data_end) - return 0; - - return bpf_ntohs(udph->dest); -} - -static __always_inline -int get_proto_ipv4(struct xdp_md *ctx, u64 nh_off) -{ - void *data_end = (void *)(long)ctx->data_end; - void *data = (void *)(long)ctx->data; - struct iphdr *iph = data + nh_off; - - if (iph + 1 > data_end) - return 0; - return iph->protocol; -} - -static __always_inline -int get_proto_ipv6(struct xdp_md *ctx, u64 nh_off) -{ - void *data_end = (void *)(long)ctx->data_end; - void *data = (void *)(long)ctx->data; - struct ipv6hdr *ip6h = data + nh_off; - - if (ip6h + 1 > data_end) - return 0; - return ip6h->nexthdr; -} - -SEC("xdp") -int xdp_prognum0_no_touch(struct xdp_md *ctx) -{ - u32 key = bpf_get_smp_processor_id(); - struct datarec *rec; - u32 *cpu_selected; - u32 cpu_dest = 0; - u32 key0 = 0; - - /* Only use first entry in cpus_available */ - cpu_selected = bpf_map_lookup_elem(&cpus_available, &key0); - if (!cpu_selected) - return XDP_ABORTED; - cpu_dest = *cpu_selected; - - rec = bpf_map_lookup_elem(&rx_cnt, &key); - if (!rec) - return XDP_PASS; - NO_TEAR_INC(rec->processed); - - if (cpu_dest >= nr_cpus) { - NO_TEAR_INC(rec->issue); - return XDP_ABORTED; - } - return bpf_redirect_map(&cpu_map, cpu_dest, 0); -} - -SEC("xdp") -int xdp_prognum1_touch_data(struct xdp_md *ctx) -{ - void *data_end = (void *)(long)ctx->data_end; - void *data = (void *)(long)ctx->data; - u32 key = bpf_get_smp_processor_id(); - struct ethhdr *eth = data; - struct datarec *rec; - u32 *cpu_selected; - u32 cpu_dest = 0; - u32 key0 = 0; - u16 eth_type; - - /* Only use first entry in cpus_available */ - cpu_selected = bpf_map_lookup_elem(&cpus_available, &key0); - if (!cpu_selected) - return XDP_ABORTED; - cpu_dest = *cpu_selected; - - /* Validate packet length is minimum Eth header size */ - if (eth + 1 > data_end) - return XDP_ABORTED; - - rec = bpf_map_lookup_elem(&rx_cnt, &key); - if (!rec) - return XDP_PASS; - NO_TEAR_INC(rec->processed); - - /* Read packet data, and use it (drop non 802.3 Ethertypes) */ - eth_type = eth->h_proto; - if (bpf_ntohs(eth_type) < ETH_P_802_3_MIN) { - NO_TEAR_INC(rec->dropped); - return XDP_DROP; - } - - if (cpu_dest >= nr_cpus) { - NO_TEAR_INC(rec->issue); - return XDP_ABORTED; - } - return bpf_redirect_map(&cpu_map, cpu_dest, 0); -} - -SEC("xdp") -int xdp_prognum2_round_robin(struct xdp_md *ctx) -{ - void *data_end = (void *)(long)ctx->data_end; - void *data = (void *)(long)ctx->data; - u32 key = bpf_get_smp_processor_id(); - struct datarec *rec; - u32 cpu_dest = 0; - u32 key0 = 0; - - u32 *cpu_selected; - u32 *cpu_iterator; - u32 *cpu_max; - u32 cpu_idx; - - cpu_max = bpf_map_lookup_elem(&cpus_count, &key0); - if (!cpu_max) - return XDP_ABORTED; - - cpu_iterator = bpf_map_lookup_elem(&cpus_iterator, &key0); - if (!cpu_iterator) - return XDP_ABORTED; - cpu_idx = *cpu_iterator; - - *cpu_iterator += 1; - if (*cpu_iterator == *cpu_max) - *cpu_iterator = 0; - - cpu_selected = bpf_map_lookup_elem(&cpus_available, &cpu_idx); - if (!cpu_selected) - return XDP_ABORTED; - cpu_dest = *cpu_selected; - - rec = bpf_map_lookup_elem(&rx_cnt, &key); - if (!rec) - return XDP_PASS; - NO_TEAR_INC(rec->processed); - - if (cpu_dest >= nr_cpus) { - NO_TEAR_INC(rec->issue); - return XDP_ABORTED; - } - return bpf_redirect_map(&cpu_map, cpu_dest, 0); -} - -SEC("xdp") -int xdp_prognum3_proto_separate(struct xdp_md *ctx) -{ - void *data_end = (void *)(long)ctx->data_end; - void *data = (void *)(long)ctx->data; - u32 key = bpf_get_smp_processor_id(); - struct ethhdr *eth = data; - u8 ip_proto = IPPROTO_UDP; - struct datarec *rec; - u16 eth_proto = 0; - u64 l3_offset = 0; - u32 cpu_dest = 0; - u32 *cpu_lookup; - u32 cpu_idx = 0; - - rec = bpf_map_lookup_elem(&rx_cnt, &key); - if (!rec) - return XDP_PASS; - NO_TEAR_INC(rec->processed); - - if (!(parse_eth(eth, data_end, ð_proto, &l3_offset))) - return XDP_PASS; /* Just skip */ - - /* Extract L4 protocol */ - switch (eth_proto) { - case ETH_P_IP: - ip_proto = get_proto_ipv4(ctx, l3_offset); - break; - case ETH_P_IPV6: - ip_proto = get_proto_ipv6(ctx, l3_offset); - break; - case ETH_P_ARP: - cpu_idx = 0; /* ARP packet handled on separate CPU */ - break; - default: - cpu_idx = 0; - } - - /* Choose CPU based on L4 protocol */ - switch (ip_proto) { - case IPPROTO_ICMP: - case IPPROTO_ICMPV6: - cpu_idx = 2; - break; - case IPPROTO_TCP: - cpu_idx = 0; - break; - case IPPROTO_UDP: - cpu_idx = 1; - break; - default: - cpu_idx = 0; - } - - cpu_lookup = bpf_map_lookup_elem(&cpus_available, &cpu_idx); - if (!cpu_lookup) - return XDP_ABORTED; - cpu_dest = *cpu_lookup; - - if (cpu_dest >= nr_cpus) { - NO_TEAR_INC(rec->issue); - return XDP_ABORTED; - } - return bpf_redirect_map(&cpu_map, cpu_dest, 0); -} - -SEC("xdp") -int xdp_prognum4_ddos_filter_pktgen(struct xdp_md *ctx) -{ - void *data_end = (void *)(long)ctx->data_end; - void *data = (void *)(long)ctx->data; - u32 key = bpf_get_smp_processor_id(); - struct ethhdr *eth = data; - u8 ip_proto = IPPROTO_UDP; - struct datarec *rec; - u16 eth_proto = 0; - u64 l3_offset = 0; - u32 cpu_dest = 0; - u32 *cpu_lookup; - u32 cpu_idx = 0; - u16 dest_port; - - rec = bpf_map_lookup_elem(&rx_cnt, &key); - if (!rec) - return XDP_PASS; - NO_TEAR_INC(rec->processed); - - if (!(parse_eth(eth, data_end, ð_proto, &l3_offset))) - return XDP_PASS; /* Just skip */ - - /* Extract L4 protocol */ - switch (eth_proto) { - case ETH_P_IP: - ip_proto = get_proto_ipv4(ctx, l3_offset); - break; - case ETH_P_IPV6: - ip_proto = get_proto_ipv6(ctx, l3_offset); - break; - case ETH_P_ARP: - cpu_idx = 0; /* ARP packet handled on separate CPU */ - break; - default: - cpu_idx = 0; - } - - /* Choose CPU based on L4 protocol */ - switch (ip_proto) { - case IPPROTO_ICMP: - case IPPROTO_ICMPV6: - cpu_idx = 2; - break; - case IPPROTO_TCP: - cpu_idx = 0; - break; - case IPPROTO_UDP: - cpu_idx = 1; - /* DDoS filter UDP port 9 (pktgen) */ - dest_port = get_dest_port_ipv4_udp(ctx, l3_offset); - if (dest_port == 9) { - NO_TEAR_INC(rec->dropped); - return XDP_DROP; - } - break; - default: - cpu_idx = 0; - } - - cpu_lookup = bpf_map_lookup_elem(&cpus_available, &cpu_idx); - if (!cpu_lookup) - return XDP_ABORTED; - cpu_dest = *cpu_lookup; - - if (cpu_dest >= nr_cpus) { - NO_TEAR_INC(rec->issue); - return XDP_ABORTED; - } - return bpf_redirect_map(&cpu_map, cpu_dest, 0); -} - -/* Hashing initval */ -#define INITVAL 15485863 - -static __always_inline -u32 get_ipv4_hash_ip_pair(struct xdp_md *ctx, u64 nh_off) -{ - void *data_end = (void *)(long)ctx->data_end; - void *data = (void *)(long)ctx->data; - struct iphdr *iph = data + nh_off; - u32 cpu_hash; - - if (iph + 1 > data_end) - return 0; - - cpu_hash = iph->saddr + iph->daddr; - cpu_hash = SuperFastHash((char *)&cpu_hash, 4, INITVAL + iph->protocol); - - return cpu_hash; -} - -static __always_inline -u32 get_ipv6_hash_ip_pair(struct xdp_md *ctx, u64 nh_off) -{ - void *data_end = (void *)(long)ctx->data_end; - void *data = (void *)(long)ctx->data; - struct ipv6hdr *ip6h = data + nh_off; - u32 cpu_hash; - - if (ip6h + 1 > data_end) - return 0; - - cpu_hash = ip6h->saddr.in6_u.u6_addr32[0] + ip6h->daddr.in6_u.u6_addr32[0]; - cpu_hash += ip6h->saddr.in6_u.u6_addr32[1] + ip6h->daddr.in6_u.u6_addr32[1]; - cpu_hash += ip6h->saddr.in6_u.u6_addr32[2] + ip6h->daddr.in6_u.u6_addr32[2]; - cpu_hash += ip6h->saddr.in6_u.u6_addr32[3] + ip6h->daddr.in6_u.u6_addr32[3]; - cpu_hash = SuperFastHash((char *)&cpu_hash, 4, INITVAL + ip6h->nexthdr); - - return cpu_hash; -} - -/* Load-Balance traffic based on hashing IP-addrs + L4-proto. The - * hashing scheme is symmetric, meaning swapping IP src/dest still hit - * same CPU. - */ -SEC("xdp") -int xdp_prognum5_lb_hash_ip_pairs(struct xdp_md *ctx) -{ - void *data_end = (void *)(long)ctx->data_end; - void *data = (void *)(long)ctx->data; - u32 key = bpf_get_smp_processor_id(); - struct ethhdr *eth = data; - struct datarec *rec; - u16 eth_proto = 0; - u64 l3_offset = 0; - u32 cpu_dest = 0; - u32 cpu_idx = 0; - u32 *cpu_lookup; - u32 key0 = 0; - u32 *cpu_max; - u32 cpu_hash; - - rec = bpf_map_lookup_elem(&rx_cnt, &key); - if (!rec) - return XDP_PASS; - NO_TEAR_INC(rec->processed); - - cpu_max = bpf_map_lookup_elem(&cpus_count, &key0); - if (!cpu_max) - return XDP_ABORTED; - - if (!(parse_eth(eth, data_end, ð_proto, &l3_offset))) - return XDP_PASS; /* Just skip */ - - /* Hash for IPv4 and IPv6 */ - switch (eth_proto) { - case ETH_P_IP: - cpu_hash = get_ipv4_hash_ip_pair(ctx, l3_offset); - break; - case ETH_P_IPV6: - cpu_hash = get_ipv6_hash_ip_pair(ctx, l3_offset); - break; - case ETH_P_ARP: /* ARP packet handled on CPU idx 0 */ - default: - cpu_hash = 0; - } - - /* Choose CPU based on hash */ - cpu_idx = cpu_hash % *cpu_max; - - cpu_lookup = bpf_map_lookup_elem(&cpus_available, &cpu_idx); - if (!cpu_lookup) - return XDP_ABORTED; - cpu_dest = *cpu_lookup; - - if (cpu_dest >= nr_cpus) { - NO_TEAR_INC(rec->issue); - return XDP_ABORTED; - } - return bpf_redirect_map(&cpu_map, cpu_dest, 0); -} - -SEC("xdp/cpumap") -int xdp_redirect_cpu_devmap(struct xdp_md *ctx) -{ - void *data_end = (void *)(long)ctx->data_end; - void *data = (void *)(long)ctx->data; - struct ethhdr *eth = data; - u64 nh_off; - - nh_off = sizeof(*eth); - if (data + nh_off > data_end) - return XDP_DROP; - - swap_src_dst_mac(data); - return bpf_redirect_map(&tx_port, 0, 0); -} - -SEC("xdp/cpumap") -int xdp_redirect_cpu_pass(struct xdp_md *ctx) -{ - return XDP_PASS; -} - -SEC("xdp/cpumap") -int xdp_redirect_cpu_drop(struct xdp_md *ctx) -{ - return XDP_DROP; -} - -SEC("xdp/devmap") -int xdp_redirect_egress_prog(struct xdp_md *ctx) -{ - void *data_end = (void *)(long)ctx->data_end; - void *data = (void *)(long)ctx->data; - struct ethhdr *eth = data; - u64 nh_off; - - nh_off = sizeof(*eth); - if (data + nh_off > data_end) - return XDP_DROP; - - __builtin_memcpy(eth->h_source, (const char *)tx_mac_addr, ETH_ALEN); - - return XDP_PASS; -} - -char _license[] SEC("license") = "GPL"; diff --git a/samples/bpf/xdp_redirect_cpu_user.c b/samples/bpf/xdp_redirect_cpu_user.c deleted file mode 100644 index e1458405e2ba..000000000000 --- a/samples/bpf/xdp_redirect_cpu_user.c +++ /dev/null @@ -1,559 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright(c) 2017 Jesper Dangaard Brouer, Red Hat, Inc. - */ -static const char *__doc__ = -"XDP CPU redirect tool, using BPF_MAP_TYPE_CPUMAP\n" -"Usage: xdp_redirect_cpu -d -c 0 ... -c N\n" -"Valid specification for CPUMAP BPF program:\n" -" --mprog-name/-e pass (use built-in XDP_PASS program)\n" -" --mprog-name/-e drop (use built-in XDP_DROP program)\n" -" --redirect-device/-r (use built-in DEVMAP redirect program)\n" -" Custom CPUMAP BPF program:\n" -" --mprog-filename/-f --mprog-name/-e \n" -" Optionally, also pass --redirect-map/-m and --redirect-device/-r together\n" -" to configure DEVMAP in BPF object \n"; - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "bpf_util.h" -#include "xdp_sample_user.h" -#include "xdp_redirect_cpu.skel.h" - -static int map_fd; -static int avail_fd; -static int count_fd; - -static int mask = SAMPLE_RX_CNT | SAMPLE_REDIRECT_ERR_MAP_CNT | - SAMPLE_CPUMAP_ENQUEUE_CNT | SAMPLE_CPUMAP_KTHREAD_CNT | - SAMPLE_EXCEPTION_CNT; - -DEFINE_SAMPLE_INIT(xdp_redirect_cpu); - -static const struct option long_options[] = { - { "help", no_argument, NULL, 'h' }, - { "dev", required_argument, NULL, 'd' }, - { "skb-mode", no_argument, NULL, 'S' }, - { "progname", required_argument, NULL, 'p' }, - { "qsize", required_argument, NULL, 'q' }, - { "cpu", required_argument, NULL, 'c' }, - { "stress-mode", no_argument, NULL, 'x' }, - { "force", no_argument, NULL, 'F' }, - { "interval", required_argument, NULL, 'i' }, - { "verbose", no_argument, NULL, 'v' }, - { "stats", no_argument, NULL, 's' }, - { "mprog-name", required_argument, NULL, 'e' }, - { "mprog-filename", required_argument, NULL, 'f' }, - { "redirect-device", required_argument, NULL, 'r' }, - { "redirect-map", required_argument, NULL, 'm' }, - {} -}; - -static void print_avail_progs(struct bpf_object *obj) -{ - struct bpf_program *pos; - - printf(" Programs to be used for -p/--progname:\n"); - bpf_object__for_each_program(pos, obj) { - if (bpf_program__type(pos) == BPF_PROG_TYPE_XDP) { - if (!strncmp(bpf_program__name(pos), "xdp_prognum", - sizeof("xdp_prognum") - 1)) - printf(" %s\n", bpf_program__name(pos)); - } - } -} - -static void usage(char *argv[], const struct option *long_options, - const char *doc, int mask, bool error, struct bpf_object *obj) -{ - sample_usage(argv, long_options, doc, mask, error); - print_avail_progs(obj); -} - -static int create_cpu_entry(__u32 cpu, struct bpf_cpumap_val *value, - __u32 avail_idx, bool new) -{ - __u32 curr_cpus_count = 0; - __u32 key = 0; - int ret; - - /* Add a CPU entry to cpumap, as this allocate a cpu entry in - * the kernel for the cpu. - */ - ret = bpf_map_update_elem(map_fd, &cpu, value, 0); - if (ret < 0) { - fprintf(stderr, "Create CPU entry failed: %s\n", strerror(errno)); - return ret; - } - - /* Inform bpf_prog's that a new CPU is available to select - * from via some control maps. - */ - ret = bpf_map_update_elem(avail_fd, &avail_idx, &cpu, 0); - if (ret < 0) { - fprintf(stderr, "Add to avail CPUs failed: %s\n", strerror(errno)); - return ret; - } - - /* When not replacing/updating existing entry, bump the count */ - ret = bpf_map_lookup_elem(count_fd, &key, &curr_cpus_count); - if (ret < 0) { - fprintf(stderr, "Failed reading curr cpus_count: %s\n", - strerror(errno)); - return ret; - } - if (new) { - curr_cpus_count++; - ret = bpf_map_update_elem(count_fd, &key, - &curr_cpus_count, 0); - if (ret < 0) { - fprintf(stderr, "Failed write curr cpus_count: %s\n", - strerror(errno)); - return ret; - } - } - - printf("%s CPU: %u as idx: %u qsize: %d cpumap_prog_fd: %d (cpus_count: %u)\n", - new ? "Add new" : "Replace", cpu, avail_idx, - value->qsize, value->bpf_prog.fd, curr_cpus_count); - - return 0; -} - -/* CPUs are zero-indexed. Thus, add a special sentinel default value - * in map cpus_available to mark CPU index'es not configured - */ -static int mark_cpus_unavailable(void) -{ - int ret, i, n_cpus = libbpf_num_possible_cpus(); - __u32 invalid_cpu = n_cpus; - - for (i = 0; i < n_cpus; i++) { - ret = bpf_map_update_elem(avail_fd, &i, - &invalid_cpu, 0); - if (ret < 0) { - fprintf(stderr, "Failed marking CPU unavailable: %s\n", - strerror(errno)); - return ret; - } - } - - return 0; -} - -/* Stress cpumap management code by concurrently changing underlying cpumap */ -static void stress_cpumap(void *ctx) -{ - struct bpf_cpumap_val *value = ctx; - - /* Changing qsize will cause kernel to free and alloc a new - * bpf_cpu_map_entry, with an associated/complicated tear-down - * procedure. - */ - value->qsize = 1024; - create_cpu_entry(1, value, 0, false); - value->qsize = 8; - create_cpu_entry(1, value, 0, false); - value->qsize = 16000; - create_cpu_entry(1, value, 0, false); -} - -static int set_cpumap_prog(struct xdp_redirect_cpu *skel, - const char *redir_interface, const char *redir_map, - const char *mprog_filename, const char *mprog_name) -{ - if (mprog_filename) { - struct bpf_program *prog; - struct bpf_object *obj; - int ret; - - if (!mprog_name) { - fprintf(stderr, "BPF program not specified for file %s\n", - mprog_filename); - goto end; - } - if ((redir_interface && !redir_map) || (!redir_interface && redir_map)) { - fprintf(stderr, "--redirect-%s specified but --redirect-%s not specified\n", - redir_interface ? "device" : "map", redir_interface ? "map" : "device"); - goto end; - } - - /* Custom BPF program */ - obj = bpf_object__open_file(mprog_filename, NULL); - if (!obj) { - ret = -errno; - fprintf(stderr, "Failed to bpf_prog_load_xattr: %s\n", - strerror(errno)); - return ret; - } - - ret = bpf_object__load(obj); - if (ret < 0) { - ret = -errno; - fprintf(stderr, "Failed to bpf_object__load: %s\n", - strerror(errno)); - return ret; - } - - if (redir_map) { - int err, redir_map_fd, ifindex_out, key = 0; - - redir_map_fd = bpf_object__find_map_fd_by_name(obj, redir_map); - if (redir_map_fd < 0) { - fprintf(stderr, "Failed to bpf_object__find_map_fd_by_name: %s\n", - strerror(errno)); - return redir_map_fd; - } - - ifindex_out = if_nametoindex(redir_interface); - if (!ifindex_out) - ifindex_out = strtoul(redir_interface, NULL, 0); - if (!ifindex_out) { - fprintf(stderr, "Bad interface name or index\n"); - return -EINVAL; - } - - err = bpf_map_update_elem(redir_map_fd, &key, &ifindex_out, 0); - if (err < 0) - return err; - } - - prog = bpf_object__find_program_by_name(obj, mprog_name); - if (!prog) { - ret = -errno; - fprintf(stderr, "Failed to bpf_object__find_program_by_name: %s\n", - strerror(errno)); - return ret; - } - - return bpf_program__fd(prog); - } else { - if (mprog_name) { - if (redir_interface || redir_map) { - fprintf(stderr, "Need to specify --mprog-filename/-f\n"); - goto end; - } - if (!strcmp(mprog_name, "pass") || !strcmp(mprog_name, "drop")) { - /* Use built-in pass/drop programs */ - return *mprog_name == 'p' ? bpf_program__fd(skel->progs.xdp_redirect_cpu_pass) - : bpf_program__fd(skel->progs.xdp_redirect_cpu_drop); - } else { - fprintf(stderr, "Unknown name \"%s\" for built-in BPF program\n", - mprog_name); - goto end; - } - } else { - if (redir_map) { - fprintf(stderr, "Need to specify --mprog-filename, --mprog-name and" - " --redirect-device with --redirect-map\n"); - goto end; - } - if (redir_interface) { - /* Use built-in devmap redirect */ - struct bpf_devmap_val val = {}; - int ifindex_out, err; - __u32 key = 0; - - if (!redir_interface) - return 0; - - ifindex_out = if_nametoindex(redir_interface); - if (!ifindex_out) - ifindex_out = strtoul(redir_interface, NULL, 0); - if (!ifindex_out) { - fprintf(stderr, "Bad interface name or index\n"); - return -EINVAL; - } - - if (get_mac_addr(ifindex_out, skel->bss->tx_mac_addr) < 0) { - printf("Get interface %d mac failed\n", ifindex_out); - return -EINVAL; - } - - val.ifindex = ifindex_out; - val.bpf_prog.fd = bpf_program__fd(skel->progs.xdp_redirect_egress_prog); - err = bpf_map_update_elem(bpf_map__fd(skel->maps.tx_port), &key, &val, 0); - if (err < 0) - return -errno; - - return bpf_program__fd(skel->progs.xdp_redirect_cpu_devmap); - } - } - } - - /* Disabled */ - return 0; -end: - fprintf(stderr, "Invalid options for CPUMAP BPF program\n"); - return -EINVAL; -} - -int main(int argc, char **argv) -{ - const char *redir_interface = NULL, *redir_map = NULL; - const char *mprog_filename = NULL, *mprog_name = NULL; - struct xdp_redirect_cpu *skel; - struct bpf_map_info info = {}; - struct bpf_cpumap_val value; - __u32 infosz = sizeof(info); - int ret = EXIT_FAIL_OPTION; - unsigned long interval = 2; - bool stress_mode = false; - struct bpf_program *prog; - const char *prog_name; - bool generic = false; - bool force = false; - int added_cpus = 0; - bool error = true; - int longindex = 0; - int add_cpu = -1; - int ifindex = -1; - int *cpu, i, opt; - __u32 qsize; - int n_cpus; - - n_cpus = libbpf_num_possible_cpus(); - - /* Notice: Choosing the queue size is very important when CPU is - * configured with power-saving states. - * - * If deepest state take 133 usec to wakeup from (133/10^6). When link - * speed is 10Gbit/s ((10*10^9/8) in bytes/sec). How many bytes can - * arrive with in 133 usec at this speed: (10*10^9/8)*(133/10^6) = - * 166250 bytes. With MTU size packets this is 110 packets, and with - * minimum Ethernet (MAC-preamble + intergap) 84 bytes is 1979 packets. - * - * Setting default cpumap queue to 2048 as worst-case (small packet) - * should be +64 packet due kthread wakeup call (due to xdp_do_flush) - * worst-case is 2043 packets. - * - * Sysadm can configured system to avoid deep-sleep via: - * tuned-adm profile network-latency - */ - qsize = 2048; - - skel = xdp_redirect_cpu__open(); - if (!skel) { - fprintf(stderr, "Failed to xdp_redirect_cpu__open: %s\n", - strerror(errno)); - ret = EXIT_FAIL_BPF; - goto end; - } - - ret = sample_init_pre_load(skel); - if (ret < 0) { - fprintf(stderr, "Failed to sample_init_pre_load: %s\n", strerror(-ret)); - ret = EXIT_FAIL_BPF; - goto end_destroy; - } - - if (bpf_map__set_max_entries(skel->maps.cpu_map, n_cpus) < 0) { - fprintf(stderr, "Failed to set max entries for cpu_map map: %s", - strerror(errno)); - ret = EXIT_FAIL_BPF; - goto end_destroy; - } - - if (bpf_map__set_max_entries(skel->maps.cpus_available, n_cpus) < 0) { - fprintf(stderr, "Failed to set max entries for cpus_available map: %s", - strerror(errno)); - ret = EXIT_FAIL_BPF; - goto end_destroy; - } - - cpu = calloc(n_cpus, sizeof(int)); - if (!cpu) { - fprintf(stderr, "Failed to allocate cpu array\n"); - goto end_destroy; - } - - prog = skel->progs.xdp_prognum5_lb_hash_ip_pairs; - while ((opt = getopt_long(argc, argv, "d:si:Sxp:f:e:r:m:c:q:Fvh", - long_options, &longindex)) != -1) { - switch (opt) { - case 'd': - if (strlen(optarg) >= IF_NAMESIZE) { - fprintf(stderr, "-d/--dev name too long\n"); - usage(argv, long_options, __doc__, mask, true, skel->obj); - goto end_cpu; - } - ifindex = if_nametoindex(optarg); - if (!ifindex) - ifindex = strtoul(optarg, NULL, 0); - if (!ifindex) { - fprintf(stderr, "Bad interface index or name (%d): %s\n", - errno, strerror(errno)); - usage(argv, long_options, __doc__, mask, true, skel->obj); - goto end_cpu; - } - break; - case 's': - mask |= SAMPLE_REDIRECT_MAP_CNT; - break; - case 'i': - interval = strtoul(optarg, NULL, 0); - break; - case 'S': - generic = true; - break; - case 'x': - stress_mode = true; - break; - case 'p': - /* Selecting eBPF prog to load */ - prog_name = optarg; - prog = bpf_object__find_program_by_name(skel->obj, - prog_name); - if (!prog) { - fprintf(stderr, - "Failed to find program %s specified by" - " option -p/--progname\n", - prog_name); - print_avail_progs(skel->obj); - goto end_cpu; - } - break; - case 'f': - mprog_filename = optarg; - break; - case 'e': - mprog_name = optarg; - break; - case 'r': - redir_interface = optarg; - mask |= SAMPLE_DEVMAP_XMIT_CNT_MULTI; - break; - case 'm': - redir_map = optarg; - break; - case 'c': - /* Add multiple CPUs */ - add_cpu = strtoul(optarg, NULL, 0); - if (add_cpu >= n_cpus) { - fprintf(stderr, - "--cpu nr too large for cpumap err (%d):%s\n", - errno, strerror(errno)); - usage(argv, long_options, __doc__, mask, true, skel->obj); - goto end_cpu; - } - cpu[added_cpus++] = add_cpu; - break; - case 'q': - qsize = strtoul(optarg, NULL, 0); - break; - case 'F': - force = true; - break; - case 'v': - sample_switch_mode(); - break; - case 'h': - error = false; - default: - usage(argv, long_options, __doc__, mask, error, skel->obj); - goto end_cpu; - } - } - - ret = EXIT_FAIL_OPTION; - if (ifindex == -1) { - fprintf(stderr, "Required option --dev missing\n"); - usage(argv, long_options, __doc__, mask, true, skel->obj); - goto end_cpu; - } - - if (add_cpu == -1) { - fprintf(stderr, "Required option --cpu missing\n" - "Specify multiple --cpu option to add more\n"); - usage(argv, long_options, __doc__, mask, true, skel->obj); - goto end_cpu; - } - - skel->rodata->from_match[0] = ifindex; - if (redir_interface) - skel->rodata->to_match[0] = if_nametoindex(redir_interface); - - ret = xdp_redirect_cpu__load(skel); - if (ret < 0) { - fprintf(stderr, "Failed to xdp_redirect_cpu__load: %s\n", - strerror(errno)); - goto end_cpu; - } - - ret = bpf_map_get_info_by_fd(bpf_map__fd(skel->maps.cpu_map), &info, &infosz); - if (ret < 0) { - fprintf(stderr, "Failed bpf_map_get_info_by_fd for cpumap: %s\n", - strerror(errno)); - goto end_cpu; - } - - skel->bss->cpumap_map_id = info.id; - - map_fd = bpf_map__fd(skel->maps.cpu_map); - avail_fd = bpf_map__fd(skel->maps.cpus_available); - count_fd = bpf_map__fd(skel->maps.cpus_count); - - ret = mark_cpus_unavailable(); - if (ret < 0) { - fprintf(stderr, "Unable to mark CPUs as unavailable\n"); - goto end_cpu; - } - - ret = sample_init(skel, mask); - if (ret < 0) { - fprintf(stderr, "Failed to initialize sample: %s\n", strerror(-ret)); - ret = EXIT_FAIL; - goto end_cpu; - } - - value.bpf_prog.fd = set_cpumap_prog(skel, redir_interface, redir_map, - mprog_filename, mprog_name); - if (value.bpf_prog.fd < 0) { - fprintf(stderr, "Failed to set CPUMAP BPF program: %s\n", - strerror(-value.bpf_prog.fd)); - usage(argv, long_options, __doc__, mask, true, skel->obj); - ret = EXIT_FAIL_BPF; - goto end_cpu; - } - value.qsize = qsize; - - for (i = 0; i < added_cpus; i++) { - if (create_cpu_entry(cpu[i], &value, i, true) < 0) { - fprintf(stderr, "Cannot proceed, exiting\n"); - usage(argv, long_options, __doc__, mask, true, skel->obj); - goto end_cpu; - } - } - - ret = EXIT_FAIL_XDP; - if (sample_install_xdp(prog, ifindex, generic, force) < 0) - goto end_cpu; - - ret = sample_run(interval, stress_mode ? stress_cpumap : NULL, &value); - if (ret < 0) { - fprintf(stderr, "Failed during sample run: %s\n", strerror(-ret)); - ret = EXIT_FAIL; - goto end_cpu; - } - ret = EXIT_OK; -end_cpu: - free(cpu); -end_destroy: - xdp_redirect_cpu__destroy(skel); -end: - sample_exit(ret); -} diff --git a/samples/bpf/xdp_redirect_map.bpf.c b/samples/bpf/xdp_redirect_map.bpf.c deleted file mode 100644 index 8557c278df77..000000000000 --- a/samples/bpf/xdp_redirect_map.bpf.c +++ /dev/null @@ -1,97 +0,0 @@ -/* Copyright (c) 2017 Covalent IO, Inc. http://covalent.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - */ -#define KBUILD_MODNAME "foo" - -#include "vmlinux.h" -#include "xdp_sample.bpf.h" -#include "xdp_sample_shared.h" - -/* The 2nd xdp prog on egress does not support skb mode, so we define two - * maps, tx_port_general and tx_port_native. - */ -struct { - __uint(type, BPF_MAP_TYPE_DEVMAP); - __uint(key_size, sizeof(int)); - __uint(value_size, sizeof(int)); - __uint(max_entries, 1); -} tx_port_general SEC(".maps"); - -struct { - __uint(type, BPF_MAP_TYPE_DEVMAP); - __uint(key_size, sizeof(int)); - __uint(value_size, sizeof(struct bpf_devmap_val)); - __uint(max_entries, 1); -} tx_port_native SEC(".maps"); - -/* store egress interface mac address */ -const volatile __u8 tx_mac_addr[ETH_ALEN]; - -static __always_inline int xdp_redirect_map(struct xdp_md *ctx, void *redirect_map) -{ - void *data_end = (void *)(long)ctx->data_end; - void *data = (void *)(long)ctx->data; - u32 key = bpf_get_smp_processor_id(); - struct ethhdr *eth = data; - struct datarec *rec; - u64 nh_off; - - nh_off = sizeof(*eth); - if (data + nh_off > data_end) - return XDP_DROP; - - rec = bpf_map_lookup_elem(&rx_cnt, &key); - if (!rec) - return XDP_PASS; - NO_TEAR_INC(rec->processed); - swap_src_dst_mac(data); - return bpf_redirect_map(redirect_map, 0, 0); -} - -SEC("xdp") -int xdp_redirect_map_general(struct xdp_md *ctx) -{ - return xdp_redirect_map(ctx, &tx_port_general); -} - -SEC("xdp") -int xdp_redirect_map_native(struct xdp_md *ctx) -{ - return xdp_redirect_map(ctx, &tx_port_native); -} - -SEC("xdp/devmap") -int xdp_redirect_map_egress(struct xdp_md *ctx) -{ - void *data_end = (void *)(long)ctx->data_end; - void *data = (void *)(long)ctx->data; - u8 *mac_addr = (u8 *) tx_mac_addr; - struct ethhdr *eth = data; - u64 nh_off; - - nh_off = sizeof(*eth); - if (data + nh_off > data_end) - return XDP_DROP; - - barrier_var(mac_addr); /* prevent optimizing out memcpy */ - __builtin_memcpy(eth->h_source, mac_addr, ETH_ALEN); - - return XDP_PASS; -} - -/* Redirect require an XDP bpf_prog loaded on the TX device */ -SEC("xdp") -int xdp_redirect_dummy_prog(struct xdp_md *ctx) -{ - return XDP_PASS; -} - -char _license[] SEC("license") = "GPL"; diff --git a/samples/bpf/xdp_redirect_map_multi.bpf.c b/samples/bpf/xdp_redirect_map_multi.bpf.c deleted file mode 100644 index 8b2fd4ec2c76..000000000000 --- a/samples/bpf/xdp_redirect_map_multi.bpf.c +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#define KBUILD_MODNAME "foo" - -#include "vmlinux.h" -#include "xdp_sample.bpf.h" -#include "xdp_sample_shared.h" - -struct { - __uint(type, BPF_MAP_TYPE_DEVMAP_HASH); - __uint(key_size, sizeof(int)); - __uint(value_size, sizeof(int)); - __uint(max_entries, 32); -} forward_map_general SEC(".maps"); - -struct { - __uint(type, BPF_MAP_TYPE_DEVMAP_HASH); - __uint(key_size, sizeof(int)); - __uint(value_size, sizeof(struct bpf_devmap_val)); - __uint(max_entries, 32); -} forward_map_native SEC(".maps"); - -/* map to store egress interfaces mac addresses */ -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __type(key, u32); - __type(value, __be64); - __uint(max_entries, 32); -} mac_map SEC(".maps"); - -static int xdp_redirect_map(struct xdp_md *ctx, void *forward_map) -{ - u32 key = bpf_get_smp_processor_id(); - struct datarec *rec; - - rec = bpf_map_lookup_elem(&rx_cnt, &key); - if (!rec) - return XDP_PASS; - NO_TEAR_INC(rec->processed); - - return bpf_redirect_map(forward_map, 0, - BPF_F_BROADCAST | BPF_F_EXCLUDE_INGRESS); -} - -SEC("xdp") -int xdp_redirect_map_general(struct xdp_md *ctx) -{ - return xdp_redirect_map(ctx, &forward_map_general); -} - -SEC("xdp") -int xdp_redirect_map_native(struct xdp_md *ctx) -{ - return xdp_redirect_map(ctx, &forward_map_native); -} - -SEC("xdp/devmap") -int xdp_devmap_prog(struct xdp_md *ctx) -{ - void *data_end = (void *)(long)ctx->data_end; - void *data = (void *)(long)ctx->data; - u32 key = ctx->egress_ifindex; - struct ethhdr *eth = data; - __be64 *mac; - u64 nh_off; - - nh_off = sizeof(*eth); - if (data + nh_off > data_end) - return XDP_DROP; - - mac = bpf_map_lookup_elem(&mac_map, &key); - if (mac) - __builtin_memcpy(eth->h_source, mac, ETH_ALEN); - - return XDP_PASS; -} - -char _license[] SEC("license") = "GPL"; diff --git a/samples/bpf/xdp_redirect_map_multi_user.c b/samples/bpf/xdp_redirect_map_multi_user.c deleted file mode 100644 index 9e24f2705b67..000000000000 --- a/samples/bpf/xdp_redirect_map_multi_user.c +++ /dev/null @@ -1,232 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -static const char *__doc__ = -"XDP multi redirect tool, using BPF_MAP_TYPE_DEVMAP and BPF_F_BROADCAST flag for bpf_redirect_map\n" -"Usage: xdp_redirect_map_multi ... \n"; - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "bpf_util.h" -#include "xdp_sample_user.h" -#include "xdp_redirect_map_multi.skel.h" - -#define MAX_IFACE_NUM 32 -static int ifaces[MAX_IFACE_NUM] = {}; - -static int mask = SAMPLE_RX_CNT | SAMPLE_REDIRECT_ERR_MAP_CNT | - SAMPLE_EXCEPTION_CNT | SAMPLE_DEVMAP_XMIT_CNT | - SAMPLE_DEVMAP_XMIT_CNT_MULTI | SAMPLE_SKIP_HEADING; - -DEFINE_SAMPLE_INIT(xdp_redirect_map_multi); - -static const struct option long_options[] = { - { "help", no_argument, NULL, 'h' }, - { "skb-mode", no_argument, NULL, 'S' }, - { "force", no_argument, NULL, 'F' }, - { "load-egress", no_argument, NULL, 'X' }, - { "stats", no_argument, NULL, 's' }, - { "interval", required_argument, NULL, 'i' }, - { "verbose", no_argument, NULL, 'v' }, - {} -}; - -static int update_mac_map(struct bpf_map *map) -{ - int mac_map_fd = bpf_map__fd(map); - unsigned char mac_addr[6]; - unsigned int ifindex; - int i, ret = -1; - - for (i = 0; ifaces[i] > 0; i++) { - ifindex = ifaces[i]; - - ret = get_mac_addr(ifindex, mac_addr); - if (ret < 0) { - fprintf(stderr, "get interface %d mac failed\n", - ifindex); - return ret; - } - - ret = bpf_map_update_elem(mac_map_fd, &ifindex, mac_addr, 0); - if (ret < 0) { - fprintf(stderr, "Failed to update mac address for ifindex %d\n", - ifindex); - return ret; - } - } - - return 0; -} - -int main(int argc, char **argv) -{ - struct bpf_devmap_val devmap_val = {}; - struct xdp_redirect_map_multi *skel; - struct bpf_program *ingress_prog; - bool xdp_devmap_attached = false; - struct bpf_map *forward_map; - int ret = EXIT_FAIL_OPTION; - unsigned long interval = 2; - char ifname[IF_NAMESIZE]; - unsigned int ifindex; - bool generic = false; - bool force = false; - bool tried = false; - bool error = true; - int i, opt; - - while ((opt = getopt_long(argc, argv, "hSFXi:vs", - long_options, NULL)) != -1) { - switch (opt) { - case 'S': - generic = true; - /* devmap_xmit tracepoint not available */ - mask &= ~(SAMPLE_DEVMAP_XMIT_CNT | - SAMPLE_DEVMAP_XMIT_CNT_MULTI); - break; - case 'F': - force = true; - break; - case 'X': - xdp_devmap_attached = true; - break; - case 'i': - interval = strtoul(optarg, NULL, 0); - break; - case 'v': - sample_switch_mode(); - break; - case 's': - mask |= SAMPLE_REDIRECT_MAP_CNT; - break; - case 'h': - error = false; - default: - sample_usage(argv, long_options, __doc__, mask, error); - return ret; - } - } - - if (argc <= optind + 1) { - sample_usage(argv, long_options, __doc__, mask, error); - return ret; - } - - skel = xdp_redirect_map_multi__open(); - if (!skel) { - fprintf(stderr, "Failed to xdp_redirect_map_multi__open: %s\n", - strerror(errno)); - ret = EXIT_FAIL_BPF; - goto end; - } - - ret = sample_init_pre_load(skel); - if (ret < 0) { - fprintf(stderr, "Failed to sample_init_pre_load: %s\n", strerror(-ret)); - ret = EXIT_FAIL_BPF; - goto end_destroy; - } - - ret = EXIT_FAIL_OPTION; - for (i = 0; i < MAX_IFACE_NUM && argv[optind + i]; i++) { - ifaces[i] = if_nametoindex(argv[optind + i]); - if (!ifaces[i]) - ifaces[i] = strtoul(argv[optind + i], NULL, 0); - if (!if_indextoname(ifaces[i], ifname)) { - fprintf(stderr, "Bad interface index or name\n"); - sample_usage(argv, long_options, __doc__, mask, true); - goto end_destroy; - } - - skel->rodata->from_match[i] = ifaces[i]; - skel->rodata->to_match[i] = ifaces[i]; - } - - ret = xdp_redirect_map_multi__load(skel); - if (ret < 0) { - fprintf(stderr, "Failed to xdp_redirect_map_multi__load: %s\n", - strerror(errno)); - ret = EXIT_FAIL_BPF; - goto end_destroy; - } - - if (xdp_devmap_attached) { - /* Update mac_map with all egress interfaces' mac addr */ - if (update_mac_map(skel->maps.mac_map) < 0) { - fprintf(stderr, "Updating mac address failed\n"); - ret = EXIT_FAIL; - goto end_destroy; - } - } - - ret = sample_init(skel, mask); - if (ret < 0) { - fprintf(stderr, "Failed to initialize sample: %s\n", strerror(-ret)); - ret = EXIT_FAIL; - goto end_destroy; - } - - ingress_prog = skel->progs.xdp_redirect_map_native; - forward_map = skel->maps.forward_map_native; - - for (i = 0; ifaces[i] > 0; i++) { - ifindex = ifaces[i]; - - ret = EXIT_FAIL_XDP; -restart: - /* bind prog_fd to each interface */ - if (sample_install_xdp(ingress_prog, ifindex, generic, force) < 0) { - if (generic && !tried) { - fprintf(stderr, - "Trying fallback to sizeof(int) as value_size for devmap in generic mode\n"); - ingress_prog = skel->progs.xdp_redirect_map_general; - forward_map = skel->maps.forward_map_general; - tried = true; - goto restart; - } - goto end_destroy; - } - - /* Add all the interfaces to forward group and attach - * egress devmap program if exist - */ - devmap_val.ifindex = ifindex; - if (xdp_devmap_attached) - devmap_val.bpf_prog.fd = bpf_program__fd(skel->progs.xdp_devmap_prog); - ret = bpf_map_update_elem(bpf_map__fd(forward_map), &ifindex, &devmap_val, 0); - if (ret < 0) { - fprintf(stderr, "Failed to update devmap value: %s\n", - strerror(errno)); - ret = EXIT_FAIL_BPF; - goto end_destroy; - } - } - - ret = sample_run(interval, NULL, NULL); - if (ret < 0) { - fprintf(stderr, "Failed during sample run: %s\n", strerror(-ret)); - ret = EXIT_FAIL; - goto end_destroy; - } - ret = EXIT_OK; -end_destroy: - xdp_redirect_map_multi__destroy(skel); -end: - sample_exit(ret); -} diff --git a/samples/bpf/xdp_redirect_map_user.c b/samples/bpf/xdp_redirect_map_user.c deleted file mode 100644 index c889a1394dc1..000000000000 --- a/samples/bpf/xdp_redirect_map_user.c +++ /dev/null @@ -1,228 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2017 Covalent IO, Inc. http://covalent.io - */ -static const char *__doc__ = -"XDP redirect tool, using BPF_MAP_TYPE_DEVMAP\n" -"Usage: xdp_redirect_map _IN _OUT\n"; - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "bpf_util.h" -#include "xdp_sample_user.h" -#include "xdp_redirect_map.skel.h" - -static int mask = SAMPLE_RX_CNT | SAMPLE_REDIRECT_ERR_MAP_CNT | - SAMPLE_EXCEPTION_CNT | SAMPLE_DEVMAP_XMIT_CNT_MULTI; - -DEFINE_SAMPLE_INIT(xdp_redirect_map); - -static const struct option long_options[] = { - { "help", no_argument, NULL, 'h' }, - { "skb-mode", no_argument, NULL, 'S' }, - { "force", no_argument, NULL, 'F' }, - { "load-egress", no_argument, NULL, 'X' }, - { "stats", no_argument, NULL, 's' }, - { "interval", required_argument, NULL, 'i' }, - { "verbose", no_argument, NULL, 'v' }, - {} -}; - -static int verbose = 0; - -int main(int argc, char **argv) -{ - struct bpf_devmap_val devmap_val = {}; - bool xdp_devmap_attached = false; - struct xdp_redirect_map *skel; - char str[2 * IF_NAMESIZE + 1]; - char ifname_out[IF_NAMESIZE]; - struct bpf_map *tx_port_map; - char ifname_in[IF_NAMESIZE]; - int ifindex_in, ifindex_out; - unsigned long interval = 2; - int ret = EXIT_FAIL_OPTION; - struct bpf_program *prog; - bool generic = false; - bool force = false; - bool tried = false; - bool error = true; - int opt, key = 0; - - while ((opt = getopt_long(argc, argv, "hSFXi:vs", - long_options, NULL)) != -1) { - switch (opt) { - case 'S': - generic = true; - /* devmap_xmit tracepoint not available */ - mask &= ~(SAMPLE_DEVMAP_XMIT_CNT | - SAMPLE_DEVMAP_XMIT_CNT_MULTI); - break; - case 'F': - force = true; - break; - case 'X': - xdp_devmap_attached = true; - break; - case 'i': - interval = strtoul(optarg, NULL, 0); - break; - case 'v': - sample_switch_mode(); - verbose = 1; - break; - case 's': - mask |= SAMPLE_REDIRECT_MAP_CNT; - break; - case 'h': - error = false; - default: - sample_usage(argv, long_options, __doc__, mask, error); - return ret; - } - } - - if (argc <= optind + 1) { - sample_usage(argv, long_options, __doc__, mask, true); - goto end; - } - - ifindex_in = if_nametoindex(argv[optind]); - if (!ifindex_in) - ifindex_in = strtoul(argv[optind], NULL, 0); - - ifindex_out = if_nametoindex(argv[optind + 1]); - if (!ifindex_out) - ifindex_out = strtoul(argv[optind + 1], NULL, 0); - - if (!ifindex_in || !ifindex_out) { - fprintf(stderr, "Bad interface index or name\n"); - sample_usage(argv, long_options, __doc__, mask, true); - goto end; - } - - skel = xdp_redirect_map__open(); - if (!skel) { - fprintf(stderr, "Failed to xdp_redirect_map__open: %s\n", - strerror(errno)); - ret = EXIT_FAIL_BPF; - goto end; - } - - ret = sample_init_pre_load(skel); - if (ret < 0) { - fprintf(stderr, "Failed to sample_init_pre_load: %s\n", strerror(-ret)); - ret = EXIT_FAIL_BPF; - goto end_destroy; - } - - /* Load 2nd xdp prog on egress. */ - if (xdp_devmap_attached) { - ret = get_mac_addr(ifindex_out, skel->rodata->tx_mac_addr); - if (ret < 0) { - fprintf(stderr, "Failed to get interface %d mac address: %s\n", - ifindex_out, strerror(-ret)); - ret = EXIT_FAIL; - goto end_destroy; - } - if (verbose) - printf("Egress ifindex:%d using src MAC %02x:%02x:%02x:%02x:%02x:%02x\n", - ifindex_out, - skel->rodata->tx_mac_addr[0], skel->rodata->tx_mac_addr[1], - skel->rodata->tx_mac_addr[2], skel->rodata->tx_mac_addr[3], - skel->rodata->tx_mac_addr[4], skel->rodata->tx_mac_addr[5]); - } - - skel->rodata->from_match[0] = ifindex_in; - skel->rodata->to_match[0] = ifindex_out; - - ret = xdp_redirect_map__load(skel); - if (ret < 0) { - fprintf(stderr, "Failed to xdp_redirect_map__load: %s\n", - strerror(errno)); - ret = EXIT_FAIL_BPF; - goto end_destroy; - } - - ret = sample_init(skel, mask); - if (ret < 0) { - fprintf(stderr, "Failed to initialize sample: %s\n", strerror(-ret)); - ret = EXIT_FAIL; - goto end_destroy; - } - - prog = skel->progs.xdp_redirect_map_native; - tx_port_map = skel->maps.tx_port_native; -restart: - if (sample_install_xdp(prog, ifindex_in, generic, force) < 0) { - /* First try with struct bpf_devmap_val as value for generic - * mode, then fallback to sizeof(int) for older kernels. - */ - fprintf(stderr, - "Trying fallback to sizeof(int) as value_size for devmap in generic mode\n"); - if (generic && !tried) { - prog = skel->progs.xdp_redirect_map_general; - tx_port_map = skel->maps.tx_port_general; - tried = true; - goto restart; - } - ret = EXIT_FAIL_XDP; - goto end_destroy; - } - - /* Loading dummy XDP prog on out-device */ - sample_install_xdp(skel->progs.xdp_redirect_dummy_prog, ifindex_out, generic, force); - - devmap_val.ifindex = ifindex_out; - if (xdp_devmap_attached) - devmap_val.bpf_prog.fd = bpf_program__fd(skel->progs.xdp_redirect_map_egress); - ret = bpf_map_update_elem(bpf_map__fd(tx_port_map), &key, &devmap_val, 0); - if (ret < 0) { - fprintf(stderr, "Failed to update devmap value: %s\n", - strerror(errno)); - ret = EXIT_FAIL_BPF; - goto end_destroy; - } - - ret = EXIT_FAIL; - if (!if_indextoname(ifindex_in, ifname_in)) { - fprintf(stderr, "Failed to if_indextoname for %d: %s\n", ifindex_in, - strerror(errno)); - goto end_destroy; - } - - if (!if_indextoname(ifindex_out, ifname_out)) { - fprintf(stderr, "Failed to if_indextoname for %d: %s\n", ifindex_out, - strerror(errno)); - goto end_destroy; - } - - safe_strncpy(str, get_driver_name(ifindex_in), sizeof(str)); - printf("Redirecting from %s (ifindex %d; driver %s) to %s (ifindex %d; driver %s)\n", - ifname_in, ifindex_in, str, ifname_out, ifindex_out, get_driver_name(ifindex_out)); - snprintf(str, sizeof(str), "%s->%s", ifname_in, ifname_out); - - ret = sample_run(interval, NULL, NULL); - if (ret < 0) { - fprintf(stderr, "Failed during sample run: %s\n", strerror(-ret)); - ret = EXIT_FAIL; - goto end_destroy; - } - ret = EXIT_OK; -end_destroy: - xdp_redirect_map__destroy(skel); -end: - sample_exit(ret); -} diff --git a/samples/bpf/xdp_redirect_user.c b/samples/bpf/xdp_redirect_user.c deleted file mode 100644 index 8663dd631b6e..000000000000 --- a/samples/bpf/xdp_redirect_user.c +++ /dev/null @@ -1,172 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2016 John Fastabend - */ -static const char *__doc__ = -"XDP redirect tool, using bpf_redirect helper\n" -"Usage: xdp_redirect _IN _OUT\n"; - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "bpf_util.h" -#include "xdp_sample_user.h" -#include "xdp_redirect.skel.h" - -static int mask = SAMPLE_RX_CNT | SAMPLE_REDIRECT_ERR_CNT | - SAMPLE_EXCEPTION_CNT | SAMPLE_DEVMAP_XMIT_CNT_MULTI; - -DEFINE_SAMPLE_INIT(xdp_redirect); - -static const struct option long_options[] = { - {"help", no_argument, NULL, 'h' }, - {"skb-mode", no_argument, NULL, 'S' }, - {"force", no_argument, NULL, 'F' }, - {"stats", no_argument, NULL, 's' }, - {"interval", required_argument, NULL, 'i' }, - {"verbose", no_argument, NULL, 'v' }, - {} -}; - -int main(int argc, char **argv) -{ - int ifindex_in, ifindex_out, opt; - char str[2 * IF_NAMESIZE + 1]; - char ifname_out[IF_NAMESIZE]; - char ifname_in[IF_NAMESIZE]; - int ret = EXIT_FAIL_OPTION; - unsigned long interval = 2; - struct xdp_redirect *skel; - bool generic = false; - bool force = false; - bool error = true; - - while ((opt = getopt_long(argc, argv, "hSFi:vs", - long_options, NULL)) != -1) { - switch (opt) { - case 'S': - generic = true; - mask &= ~(SAMPLE_DEVMAP_XMIT_CNT | - SAMPLE_DEVMAP_XMIT_CNT_MULTI); - break; - case 'F': - force = true; - break; - case 'i': - interval = strtoul(optarg, NULL, 0); - break; - case 'v': - sample_switch_mode(); - break; - case 's': - mask |= SAMPLE_REDIRECT_CNT; - break; - case 'h': - error = false; - default: - sample_usage(argv, long_options, __doc__, mask, error); - return ret; - } - } - - if (argc <= optind + 1) { - sample_usage(argv, long_options, __doc__, mask, true); - return ret; - } - - ifindex_in = if_nametoindex(argv[optind]); - if (!ifindex_in) - ifindex_in = strtoul(argv[optind], NULL, 0); - - ifindex_out = if_nametoindex(argv[optind + 1]); - if (!ifindex_out) - ifindex_out = strtoul(argv[optind + 1], NULL, 0); - - if (!ifindex_in || !ifindex_out) { - fprintf(stderr, "Bad interface index or name\n"); - sample_usage(argv, long_options, __doc__, mask, true); - goto end; - } - - skel = xdp_redirect__open(); - if (!skel) { - fprintf(stderr, "Failed to xdp_redirect__open: %s\n", strerror(errno)); - ret = EXIT_FAIL_BPF; - goto end; - } - - ret = sample_init_pre_load(skel); - if (ret < 0) { - fprintf(stderr, "Failed to sample_init_pre_load: %s\n", strerror(-ret)); - ret = EXIT_FAIL_BPF; - goto end_destroy; - } - - skel->rodata->from_match[0] = ifindex_in; - skel->rodata->to_match[0] = ifindex_out; - skel->rodata->ifindex_out = ifindex_out; - - ret = xdp_redirect__load(skel); - if (ret < 0) { - fprintf(stderr, "Failed to xdp_redirect__load: %s\n", strerror(errno)); - ret = EXIT_FAIL_BPF; - goto end_destroy; - } - - ret = sample_init(skel, mask); - if (ret < 0) { - fprintf(stderr, "Failed to initialize sample: %s\n", strerror(-ret)); - ret = EXIT_FAIL; - goto end_destroy; - } - - ret = EXIT_FAIL_XDP; - if (sample_install_xdp(skel->progs.xdp_redirect_prog, ifindex_in, - generic, force) < 0) - goto end_destroy; - - /* Loading dummy XDP prog on out-device */ - sample_install_xdp(skel->progs.xdp_redirect_dummy_prog, ifindex_out, - generic, force); - - ret = EXIT_FAIL; - if (!if_indextoname(ifindex_in, ifname_in)) { - fprintf(stderr, "Failed to if_indextoname for %d: %s\n", ifindex_in, - strerror(errno)); - goto end_destroy; - } - - if (!if_indextoname(ifindex_out, ifname_out)) { - fprintf(stderr, "Failed to if_indextoname for %d: %s\n", ifindex_out, - strerror(errno)); - goto end_destroy; - } - - safe_strncpy(str, get_driver_name(ifindex_in), sizeof(str)); - printf("Redirecting from %s (ifindex %d; driver %s) to %s (ifindex %d; driver %s)\n", - ifname_in, ifindex_in, str, ifname_out, ifindex_out, get_driver_name(ifindex_out)); - snprintf(str, sizeof(str), "%s->%s", ifname_in, ifname_out); - - ret = sample_run(interval, NULL, NULL); - if (ret < 0) { - fprintf(stderr, "Failed during sample run: %s\n", strerror(-ret)); - ret = EXIT_FAIL; - goto end_destroy; - } - ret = EXIT_OK; -end_destroy: - xdp_redirect__destroy(skel); -end: - sample_exit(ret); -} -- cgit v1.2.3 From 0e445e115f8f4f3d3de5b9199dc2da83d75b1f3c Mon Sep 17 00:00:00 2001 From: Toke Høiland-Jørgensen Date: Thu, 24 Aug 2023 12:22:46 +0200 Subject: samples/bpf: Remove the xdp_rxq_info utility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The functionality of this utility has been incorporated into the xdp-bench utility in xdp-tools, by way of the --rxq-stats argument to the 'drop', 'pass' and 'tx' commands of xdp-bench. Some examples of how to convert xdp_rxq_info invocations into equivalent xdp-bench commands: xdp_rxq_info -d eth0 --> xdp-bench pass --rxq-stats eth0 xdp_rxq_info -d eth0 -a XDP_DROP -m --> xdp-bench drop --rxq-stats -p swap-macs eth0 Signed-off-by: Toke Høiland-Jørgensen Link: https://lore.kernel.org/r/20230824102255.1561885-4-toke@redhat.com Signed-off-by: Alexei Starovoitov --- samples/bpf/Makefile | 3 - samples/bpf/xdp_rxq_info_kern.c | 140 --------- samples/bpf/xdp_rxq_info_user.c | 614 ---------------------------------------- 3 files changed, 757 deletions(-) delete mode 100644 samples/bpf/xdp_rxq_info_kern.c delete mode 100644 samples/bpf/xdp_rxq_info_user.c (limited to 'samples') diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile index d2f5c043e4f3..fb1dc9d96b2a 100644 --- a/samples/bpf/Makefile +++ b/samples/bpf/Makefile @@ -41,7 +41,6 @@ tprogs-y += lwt_len_hist tprogs-y += xdp_tx_iptunnel tprogs-y += test_map_in_map tprogs-y += per_socket_stats_example -tprogs-y += xdp_rxq_info tprogs-y += syscall_tp tprogs-y += cpustat tprogs-y += xdp_adjust_tail @@ -96,7 +95,6 @@ lwt_len_hist-objs := lwt_len_hist_user.o xdp_tx_iptunnel-objs := xdp_tx_iptunnel_user.o test_map_in_map-objs := test_map_in_map_user.o per_socket_stats_example-objs := cookie_uid_helper_example.o -xdp_rxq_info-objs := xdp_rxq_info_user.o syscall_tp-objs := syscall_tp_user.o cpustat-objs := cpustat_user.o xdp_adjust_tail-objs := xdp_adjust_tail_user.o @@ -151,7 +149,6 @@ always-y += tcp_clamp_kern.o always-y += tcp_basertt_kern.o always-y += tcp_tos_reflect_kern.o always-y += tcp_dumpstats_kern.o -always-y += xdp_rxq_info_kern.o always-y += xdp2skb_meta_kern.o always-y += syscall_tp_kern.o always-y += cpustat_kern.o diff --git a/samples/bpf/xdp_rxq_info_kern.c b/samples/bpf/xdp_rxq_info_kern.c deleted file mode 100644 index 5e7459f9bf3e..000000000000 --- a/samples/bpf/xdp_rxq_info_kern.c +++ /dev/null @@ -1,140 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 - * Copyright (c) 2017 Jesper Dangaard Brouer, Red Hat Inc. - * - * Example howto extract XDP RX-queue info - */ -#include -#include -#include -#include - -/* Config setup from with userspace - * - * User-side setup ifindex in config_map, to verify that - * ctx->ingress_ifindex is correct (against configured ifindex) - */ -struct config { - __u32 action; - int ifindex; - __u32 options; -}; -enum cfg_options_flags { - NO_TOUCH = 0x0U, - READ_MEM = 0x1U, - SWAP_MAC = 0x2U, -}; - -struct { - __uint(type, BPF_MAP_TYPE_ARRAY); - __type(key, int); - __type(value, struct config); - __uint(max_entries, 1); -} config_map SEC(".maps"); - -/* Common stats data record (shared with userspace) */ -struct datarec { - __u64 processed; - __u64 issue; -}; - -struct { - __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); - __type(key, u32); - __type(value, struct datarec); - __uint(max_entries, 1); -} stats_global_map SEC(".maps"); - -#define MAX_RXQs 64 - -/* Stats per rx_queue_index (per CPU) */ -struct { - __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); - __type(key, u32); - __type(value, struct datarec); - __uint(max_entries, MAX_RXQs + 1); -} rx_queue_index_map SEC(".maps"); - -static __always_inline -void swap_src_dst_mac(void *data) -{ - unsigned short *p = data; - unsigned short dst[3]; - - dst[0] = p[0]; - dst[1] = p[1]; - dst[2] = p[2]; - p[0] = p[3]; - p[1] = p[4]; - p[2] = p[5]; - p[3] = dst[0]; - p[4] = dst[1]; - p[5] = dst[2]; -} - -SEC("xdp_prog0") -int xdp_prognum0(struct xdp_md *ctx) -{ - void *data_end = (void *)(long)ctx->data_end; - void *data = (void *)(long)ctx->data; - struct datarec *rec, *rxq_rec; - int ingress_ifindex; - struct config *config; - u32 key = 0; - - /* Global stats record */ - rec = bpf_map_lookup_elem(&stats_global_map, &key); - if (!rec) - return XDP_ABORTED; - rec->processed++; - - /* Accessing ctx->ingress_ifindex, cause BPF to rewrite BPF - * instructions inside kernel to access xdp_rxq->dev->ifindex - */ - ingress_ifindex = ctx->ingress_ifindex; - - config = bpf_map_lookup_elem(&config_map, &key); - if (!config) - return XDP_ABORTED; - - /* Simple test: check ctx provided ifindex is as expected */ - if (ingress_ifindex != config->ifindex) { - /* count this error case */ - rec->issue++; - return XDP_ABORTED; - } - - /* Update stats per rx_queue_index. Handle if rx_queue_index - * is larger than stats map can contain info for. - */ - key = ctx->rx_queue_index; - if (key >= MAX_RXQs) - key = MAX_RXQs; - rxq_rec = bpf_map_lookup_elem(&rx_queue_index_map, &key); - if (!rxq_rec) - return XDP_ABORTED; - rxq_rec->processed++; - if (key == MAX_RXQs) - rxq_rec->issue++; - - /* Default: Don't touch packet data, only count packets */ - if (unlikely(config->options & (READ_MEM|SWAP_MAC))) { - struct ethhdr *eth = data; - - if (eth + 1 > data_end) - return XDP_ABORTED; - - /* Avoid compiler removing this: Drop non 802.3 Ethertypes */ - if (ntohs(eth->h_proto) < ETH_P_802_3_MIN) - return XDP_ABORTED; - - /* XDP_TX requires changing MAC-addrs, else HW may drop. - * Can also be enabled with --swapmac (for test purposes) - */ - if (unlikely(config->options & SWAP_MAC)) - swap_src_dst_mac(data); - } - - return config->action; -} - -char _license[] SEC("license") = "GPL"; diff --git a/samples/bpf/xdp_rxq_info_user.c b/samples/bpf/xdp_rxq_info_user.c deleted file mode 100644 index b95e0ef61f06..000000000000 --- a/samples/bpf/xdp_rxq_info_user.c +++ /dev/null @@ -1,614 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 - * Copyright (c) 2017 Jesper Dangaard Brouer, Red Hat Inc. - */ -static const char *__doc__ = " XDP RX-queue info extract example\n\n" - "Monitor how many packets per sec (pps) are received\n" - "per NIC RX queue index and which CPU processed the packet\n" - ; - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "bpf_util.h" - -static int ifindex = -1; -static char ifname_buf[IF_NAMESIZE]; -static char *ifname; -static __u32 prog_id; - -static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST; - -static struct bpf_map *stats_global_map; -static struct bpf_map *rx_queue_index_map; - -/* Exit return codes */ -#define EXIT_OK 0 -#define EXIT_FAIL 1 -#define EXIT_FAIL_OPTION 2 -#define EXIT_FAIL_XDP 3 -#define EXIT_FAIL_BPF 4 -#define EXIT_FAIL_MEM 5 - -#define FAIL_MEM_SIG INT_MAX -#define FAIL_STAT_SIG (INT_MAX - 1) - -static const struct option long_options[] = { - {"help", no_argument, NULL, 'h' }, - {"dev", required_argument, NULL, 'd' }, - {"skb-mode", no_argument, NULL, 'S' }, - {"sec", required_argument, NULL, 's' }, - {"no-separators", no_argument, NULL, 'z' }, - {"action", required_argument, NULL, 'a' }, - {"readmem", no_argument, NULL, 'r' }, - {"swapmac", no_argument, NULL, 'm' }, - {"force", no_argument, NULL, 'F' }, - {0, 0, NULL, 0 } -}; - -static void int_exit(int sig) -{ - __u32 curr_prog_id = 0; - - if (ifindex > -1) { - if (bpf_xdp_query_id(ifindex, xdp_flags, &curr_prog_id)) { - printf("bpf_xdp_query_id failed\n"); - exit(EXIT_FAIL); - } - if (prog_id == curr_prog_id) { - fprintf(stderr, - "Interrupted: Removing XDP program on ifindex:%d device:%s\n", - ifindex, ifname); - bpf_xdp_detach(ifindex, xdp_flags, NULL); - } else if (!curr_prog_id) { - printf("couldn't find a prog id on a given iface\n"); - } else { - printf("program on interface changed, not removing\n"); - } - } - - if (sig == FAIL_MEM_SIG) - exit(EXIT_FAIL_MEM); - else if (sig == FAIL_STAT_SIG) - exit(EXIT_FAIL); - - exit(EXIT_OK); -} - -struct config { - __u32 action; - int ifindex; - __u32 options; -}; -enum cfg_options_flags { - NO_TOUCH = 0x0U, - READ_MEM = 0x1U, - SWAP_MAC = 0x2U, -}; -#define XDP_ACTION_MAX (XDP_TX + 1) -#define XDP_ACTION_MAX_STRLEN 11 -static const char *xdp_action_names[XDP_ACTION_MAX] = { - [XDP_ABORTED] = "XDP_ABORTED", - [XDP_DROP] = "XDP_DROP", - [XDP_PASS] = "XDP_PASS", - [XDP_TX] = "XDP_TX", -}; - -static const char *action2str(int action) -{ - if (action < XDP_ACTION_MAX) - return xdp_action_names[action]; - return NULL; -} - -static int parse_xdp_action(char *action_str) -{ - size_t maxlen; - __u64 action = -1; - int i; - - for (i = 0; i < XDP_ACTION_MAX; i++) { - maxlen = XDP_ACTION_MAX_STRLEN; - if (strncmp(xdp_action_names[i], action_str, maxlen) == 0) { - action = i; - break; - } - } - return action; -} - -static void list_xdp_actions(void) -{ - int i; - - printf("Available XDP --action \n"); - for (i = 0; i < XDP_ACTION_MAX; i++) - printf("\t%s\n", xdp_action_names[i]); - printf("\n"); -} - -static char* options2str(enum cfg_options_flags flag) -{ - if (flag == NO_TOUCH) - return "no_touch"; - if (flag & SWAP_MAC) - return "swapmac"; - if (flag & READ_MEM) - return "read"; - fprintf(stderr, "ERR: Unknown config option flags"); - int_exit(FAIL_STAT_SIG); - return "unknown"; -} - -static void usage(char *argv[]) -{ - int i; - - printf("\nDOCUMENTATION:\n%s\n", __doc__); - printf(" Usage: %s (options-see-below)\n", argv[0]); - printf(" Listing options:\n"); - for (i = 0; long_options[i].name != 0; i++) { - printf(" --%-12s", long_options[i].name); - if (long_options[i].flag != NULL) - printf(" flag (internal value:%d)", - *long_options[i].flag); - else - printf(" short-option: -%c", - long_options[i].val); - printf("\n"); - } - printf("\n"); - list_xdp_actions(); -} - -#define NANOSEC_PER_SEC 1000000000 /* 10^9 */ -static __u64 gettime(void) -{ - struct timespec t; - int res; - - res = clock_gettime(CLOCK_MONOTONIC, &t); - if (res < 0) { - fprintf(stderr, "Error with gettimeofday! (%i)\n", res); - int_exit(FAIL_STAT_SIG); - } - return (__u64) t.tv_sec * NANOSEC_PER_SEC + t.tv_nsec; -} - -/* Common stats data record shared with _kern.c */ -struct datarec { - __u64 processed; - __u64 issue; -}; -struct record { - __u64 timestamp; - struct datarec total; - struct datarec *cpu; -}; -struct stats_record { - struct record stats; - struct record *rxq; -}; - -static struct datarec *alloc_record_per_cpu(void) -{ - unsigned int nr_cpus = bpf_num_possible_cpus(); - struct datarec *array; - - array = calloc(nr_cpus, sizeof(struct datarec)); - if (!array) { - fprintf(stderr, "Mem alloc error (nr_cpus:%u)\n", nr_cpus); - int_exit(FAIL_MEM_SIG); - } - return array; -} - -static struct record *alloc_record_per_rxq(void) -{ - unsigned int nr_rxqs = bpf_map__max_entries(rx_queue_index_map); - struct record *array; - - array = calloc(nr_rxqs, sizeof(struct record)); - if (!array) { - fprintf(stderr, "Mem alloc error (nr_rxqs:%u)\n", nr_rxqs); - int_exit(FAIL_MEM_SIG); - } - return array; -} - -static struct stats_record *alloc_stats_record(void) -{ - unsigned int nr_rxqs = bpf_map__max_entries(rx_queue_index_map); - struct stats_record *rec; - int i; - - rec = calloc(1, sizeof(struct stats_record)); - if (!rec) { - fprintf(stderr, "Mem alloc error\n"); - int_exit(FAIL_MEM_SIG); - } - rec->rxq = alloc_record_per_rxq(); - for (i = 0; i < nr_rxqs; i++) - rec->rxq[i].cpu = alloc_record_per_cpu(); - - rec->stats.cpu = alloc_record_per_cpu(); - return rec; -} - -static void free_stats_record(struct stats_record *r) -{ - unsigned int nr_rxqs = bpf_map__max_entries(rx_queue_index_map); - int i; - - for (i = 0; i < nr_rxqs; i++) - free(r->rxq[i].cpu); - - free(r->rxq); - free(r->stats.cpu); - free(r); -} - -static bool map_collect_percpu(int fd, __u32 key, struct record *rec) -{ - /* For percpu maps, userspace gets a value per possible CPU */ - unsigned int nr_cpus = bpf_num_possible_cpus(); - struct datarec values[nr_cpus]; - __u64 sum_processed = 0; - __u64 sum_issue = 0; - int i; - - if ((bpf_map_lookup_elem(fd, &key, values)) != 0) { - fprintf(stderr, - "ERR: bpf_map_lookup_elem failed key:0x%X\n", key); - return false; - } - /* Get time as close as possible to reading map contents */ - rec->timestamp = gettime(); - - /* Record and sum values from each CPU */ - for (i = 0; i < nr_cpus; i++) { - rec->cpu[i].processed = values[i].processed; - sum_processed += values[i].processed; - rec->cpu[i].issue = values[i].issue; - sum_issue += values[i].issue; - } - rec->total.processed = sum_processed; - rec->total.issue = sum_issue; - return true; -} - -static void stats_collect(struct stats_record *rec) -{ - int fd, i, max_rxqs; - - fd = bpf_map__fd(stats_global_map); - map_collect_percpu(fd, 0, &rec->stats); - - fd = bpf_map__fd(rx_queue_index_map); - max_rxqs = bpf_map__max_entries(rx_queue_index_map); - for (i = 0; i < max_rxqs; i++) - map_collect_percpu(fd, i, &rec->rxq[i]); -} - -static double calc_period(struct record *r, struct record *p) -{ - double period_ = 0; - __u64 period = 0; - - period = r->timestamp - p->timestamp; - if (period > 0) - period_ = ((double) period / NANOSEC_PER_SEC); - - return period_; -} - -static __u64 calc_pps(struct datarec *r, struct datarec *p, double period_) -{ - __u64 packets = 0; - __u64 pps = 0; - - if (period_ > 0) { - packets = r->processed - p->processed; - pps = packets / period_; - } - return pps; -} - -static __u64 calc_errs_pps(struct datarec *r, - struct datarec *p, double period_) -{ - __u64 packets = 0; - __u64 pps = 0; - - if (period_ > 0) { - packets = r->issue - p->issue; - pps = packets / period_; - } - return pps; -} - -static void stats_print(struct stats_record *stats_rec, - struct stats_record *stats_prev, - int action, __u32 cfg_opt) -{ - unsigned int nr_rxqs = bpf_map__max_entries(rx_queue_index_map); - unsigned int nr_cpus = bpf_num_possible_cpus(); - double pps = 0, err = 0; - struct record *rec, *prev; - double t; - int rxq; - int i; - - /* Header */ - printf("\nRunning XDP on dev:%s (ifindex:%d) action:%s options:%s\n", - ifname, ifindex, action2str(action), options2str(cfg_opt)); - - /* stats_global_map */ - { - char *fmt_rx = "%-15s %-7d %'-11.0f %'-10.0f %s\n"; - char *fm2_rx = "%-15s %-7s %'-11.0f\n"; - char *errstr = ""; - - printf("%-15s %-7s %-11s %-11s\n", - "XDP stats", "CPU", "pps", "issue-pps"); - - rec = &stats_rec->stats; - prev = &stats_prev->stats; - t = calc_period(rec, prev); - for (i = 0; i < nr_cpus; i++) { - struct datarec *r = &rec->cpu[i]; - struct datarec *p = &prev->cpu[i]; - - pps = calc_pps (r, p, t); - err = calc_errs_pps(r, p, t); - if (err > 0) - errstr = "invalid-ifindex"; - if (pps > 0) - printf(fmt_rx, "XDP-RX CPU", - i, pps, err, errstr); - } - pps = calc_pps (&rec->total, &prev->total, t); - err = calc_errs_pps(&rec->total, &prev->total, t); - printf(fm2_rx, "XDP-RX CPU", "total", pps, err); - } - - /* rx_queue_index_map */ - printf("\n%-15s %-7s %-11s %-11s\n", - "RXQ stats", "RXQ:CPU", "pps", "issue-pps"); - - for (rxq = 0; rxq < nr_rxqs; rxq++) { - char *fmt_rx = "%-15s %3d:%-3d %'-11.0f %'-10.0f %s\n"; - char *fm2_rx = "%-15s %3d:%-3s %'-11.0f\n"; - char *errstr = ""; - int rxq_ = rxq; - - /* Last RXQ in map catch overflows */ - if (rxq_ == nr_rxqs - 1) - rxq_ = -1; - - rec = &stats_rec->rxq[rxq]; - prev = &stats_prev->rxq[rxq]; - t = calc_period(rec, prev); - for (i = 0; i < nr_cpus; i++) { - struct datarec *r = &rec->cpu[i]; - struct datarec *p = &prev->cpu[i]; - - pps = calc_pps (r, p, t); - err = calc_errs_pps(r, p, t); - if (err > 0) { - if (rxq_ == -1) - errstr = "map-overflow-RXQ"; - else - errstr = "err"; - } - if (pps > 0) - printf(fmt_rx, "rx_queue_index", - rxq_, i, pps, err, errstr); - } - pps = calc_pps (&rec->total, &prev->total, t); - err = calc_errs_pps(&rec->total, &prev->total, t); - if (pps || err) - printf(fm2_rx, "rx_queue_index", rxq_, "sum", pps, err); - } -} - - -/* Pointer swap trick */ -static inline void swap(struct stats_record **a, struct stats_record **b) -{ - struct stats_record *tmp; - - tmp = *a; - *a = *b; - *b = tmp; -} - -static void stats_poll(int interval, int action, __u32 cfg_opt) -{ - struct stats_record *record, *prev; - - record = alloc_stats_record(); - prev = alloc_stats_record(); - stats_collect(record); - - while (1) { - swap(&prev, &record); - stats_collect(record); - stats_print(record, prev, action, cfg_opt); - sleep(interval); - } - - free_stats_record(record); - free_stats_record(prev); -} - - -int main(int argc, char **argv) -{ - __u32 cfg_options= NO_TOUCH ; /* Default: Don't touch packet memory */ - struct bpf_prog_info info = {}; - __u32 info_len = sizeof(info); - int prog_fd, map_fd, opt, err; - bool use_separators = true; - struct config cfg = { 0 }; - struct bpf_program *prog; - struct bpf_object *obj; - struct bpf_map *map; - char filename[256]; - int longindex = 0; - int interval = 2; - __u32 key = 0; - - - char action_str_buf[XDP_ACTION_MAX_STRLEN + 1 /* for \0 */] = { 0 }; - int action = XDP_PASS; /* Default action */ - char *action_str = NULL; - - snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); - - obj = bpf_object__open_file(filename, NULL); - if (libbpf_get_error(obj)) - return EXIT_FAIL; - - prog = bpf_object__next_program(obj, NULL); - bpf_program__set_type(prog, BPF_PROG_TYPE_XDP); - - err = bpf_object__load(obj); - if (err) - return EXIT_FAIL; - prog_fd = bpf_program__fd(prog); - - map = bpf_object__find_map_by_name(obj, "config_map"); - stats_global_map = bpf_object__find_map_by_name(obj, "stats_global_map"); - rx_queue_index_map = bpf_object__find_map_by_name(obj, "rx_queue_index_map"); - if (!map || !stats_global_map || !rx_queue_index_map) { - printf("finding a map in obj file failed\n"); - return EXIT_FAIL; - } - map_fd = bpf_map__fd(map); - - if (!prog_fd) { - fprintf(stderr, "ERR: bpf_prog_load_xattr: %s\n", strerror(errno)); - return EXIT_FAIL; - } - - /* Parse commands line args */ - while ((opt = getopt_long(argc, argv, "FhSrmzd:s:a:", - long_options, &longindex)) != -1) { - switch (opt) { - case 'd': - if (strlen(optarg) >= IF_NAMESIZE) { - fprintf(stderr, "ERR: --dev name too long\n"); - goto error; - } - ifname = (char *)&ifname_buf; - strncpy(ifname, optarg, IF_NAMESIZE); - ifindex = if_nametoindex(ifname); - if (ifindex == 0) { - fprintf(stderr, - "ERR: --dev name unknown err(%d):%s\n", - errno, strerror(errno)); - goto error; - } - break; - case 's': - interval = atoi(optarg); - break; - case 'S': - xdp_flags |= XDP_FLAGS_SKB_MODE; - break; - case 'z': - use_separators = false; - break; - case 'a': - action_str = (char *)&action_str_buf; - strncpy(action_str, optarg, XDP_ACTION_MAX_STRLEN); - break; - case 'r': - cfg_options |= READ_MEM; - break; - case 'm': - cfg_options |= SWAP_MAC; - break; - case 'F': - xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST; - break; - case 'h': - error: - default: - usage(argv); - return EXIT_FAIL_OPTION; - } - } - - if (!(xdp_flags & XDP_FLAGS_SKB_MODE)) - xdp_flags |= XDP_FLAGS_DRV_MODE; - - /* Required option */ - if (ifindex == -1) { - fprintf(stderr, "ERR: required option --dev missing\n"); - usage(argv); - return EXIT_FAIL_OPTION; - } - cfg.ifindex = ifindex; - - /* Parse action string */ - if (action_str) { - action = parse_xdp_action(action_str); - if (action < 0) { - fprintf(stderr, "ERR: Invalid XDP --action: %s\n", - action_str); - list_xdp_actions(); - return EXIT_FAIL_OPTION; - } - } - cfg.action = action; - - /* XDP_TX requires changing MAC-addrs, else HW may drop */ - if (action == XDP_TX) - cfg_options |= SWAP_MAC; - cfg.options = cfg_options; - - /* Trick to pretty printf with thousands separators use %' */ - if (use_separators) - setlocale(LC_NUMERIC, "en_US"); - - /* User-side setup ifindex in config_map */ - err = bpf_map_update_elem(map_fd, &key, &cfg, 0); - if (err) { - fprintf(stderr, "Store config failed (err:%d)\n", err); - exit(EXIT_FAIL_BPF); - } - - /* Remove XDP program when program is interrupted or killed */ - signal(SIGINT, int_exit); - signal(SIGTERM, int_exit); - - if (bpf_xdp_attach(ifindex, prog_fd, xdp_flags, NULL) < 0) { - fprintf(stderr, "link set xdp fd failed\n"); - return EXIT_FAIL_XDP; - } - - err = bpf_prog_get_info_by_fd(prog_fd, &info, &info_len); - if (err) { - printf("can't get prog info - %s\n", strerror(errno)); - return err; - } - prog_id = info.id; - - stats_poll(interval, action, cfg_options); - return EXIT_OK; -} -- cgit v1.2.3 From eaca21d6eee9bb9b9f53c1c187d488ff1cbb6168 Mon Sep 17 00:00:00 2001 From: Toke Høiland-Jørgensen Date: Thu, 24 Aug 2023 12:22:47 +0200 Subject: samples/bpf: Remove the xdp1 and xdp2 utilities MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The functionality of these utilities have been incorporated into the xdp-bench utility in xdp-tools. Equivalent functionality is: xdp1 eth0 --> xdp-bench drop -p parse-ip -l load-bytes eth0 xdp2 eth0 --> xdp-bench drop -p swap-macs eth0 Note that there's a slight difference in behaviour of those examples: the swap-macs operation of xdp-bench doesn't use the bpf_xdp_load_bytes() helper to load the packet data, whereas the xdp2 utility did so unconditionally. For the parse-ip action the use of bpf_xdp_load_bytes() can be selected by the '-l load-bytes' switch, with the difference that the xdp-bench utility will perform two separate calls to the helper, one to load the ethernet header and another to load the IP header; where the xdp1 utility only performed one call always loading 60 bytes of data. Signed-off-by: Toke Høiland-Jørgensen Link: https://lore.kernel.org/r/20230824102255.1561885-5-toke@redhat.com Signed-off-by: Alexei Starovoitov --- samples/bpf/Makefile | 7 -- samples/bpf/xdp1_kern.c | 100 ----------------------------- samples/bpf/xdp1_user.c | 166 ------------------------------------------------ samples/bpf/xdp2_kern.c | 125 ------------------------------------ 4 files changed, 398 deletions(-) delete mode 100644 samples/bpf/xdp1_kern.c delete mode 100644 samples/bpf/xdp1_user.c delete mode 100644 samples/bpf/xdp2_kern.c (limited to 'samples') diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile index fb1dc9d96b2a..decd31167ee4 100644 --- a/samples/bpf/Makefile +++ b/samples/bpf/Makefile @@ -30,8 +30,6 @@ tprogs-y += test_cgrp2_array_pin tprogs-y += test_cgrp2_attach tprogs-y += test_cgrp2_sock tprogs-y += test_cgrp2_sock2 -tprogs-y += xdp1 -tprogs-y += xdp2 tprogs-y += xdp_router_ipv4 tprogs-y += test_current_task_under_cgroup tprogs-y += trace_event @@ -83,9 +81,6 @@ test_cgrp2_array_pin-objs := test_cgrp2_array_pin.o test_cgrp2_attach-objs := test_cgrp2_attach.o test_cgrp2_sock-objs := test_cgrp2_sock.o test_cgrp2_sock2-objs := test_cgrp2_sock2.o -xdp1-objs := xdp1_user.o -# reuse xdp1 source intentionally -xdp2-objs := xdp1_user.o test_current_task_under_cgroup-objs := $(CGROUP_HELPERS) \ test_current_task_under_cgroup_user.o trace_event-objs := trace_event_user.o $(TRACE_HELPERS) @@ -132,8 +127,6 @@ always-y += test_overhead_raw_tp.bpf.o always-y += test_overhead_kprobe.bpf.o always-y += parse_varlen.o parse_simple.o parse_ldabs.o always-y += test_cgrp2_tc.bpf.o -always-y += xdp1_kern.o -always-y += xdp2_kern.o always-y += test_current_task_under_cgroup.bpf.o always-y += trace_event_kern.o always-y += sampleip_kern.o diff --git a/samples/bpf/xdp1_kern.c b/samples/bpf/xdp1_kern.c deleted file mode 100644 index d91f27cbcfa9..000000000000 --- a/samples/bpf/xdp1_kern.c +++ /dev/null @@ -1,100 +0,0 @@ -/* Copyright (c) 2016 PLUMgrid - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - */ -#define KBUILD_MODNAME "foo" -#include -#include -#include -#include -#include -#include -#include -#include - -struct { - __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); - __type(key, u32); - __type(value, long); - __uint(max_entries, 256); -} rxcnt SEC(".maps"); - -static int parse_ipv4(void *data, u64 nh_off, void *data_end) -{ - struct iphdr *iph = data + nh_off; - - if (iph + 1 > data_end) - return 0; - return iph->protocol; -} - -static int parse_ipv6(void *data, u64 nh_off, void *data_end) -{ - struct ipv6hdr *ip6h = data + nh_off; - - if (ip6h + 1 > data_end) - return 0; - return ip6h->nexthdr; -} - -#define XDPBUFSIZE 60 -SEC("xdp.frags") -int xdp_prog1(struct xdp_md *ctx) -{ - __u8 pkt[XDPBUFSIZE] = {}; - void *data_end = &pkt[XDPBUFSIZE-1]; - void *data = pkt; - struct ethhdr *eth = data; - int rc = XDP_DROP; - long *value; - u16 h_proto; - u64 nh_off; - u32 ipproto; - - if (bpf_xdp_load_bytes(ctx, 0, pkt, sizeof(pkt))) - return rc; - - nh_off = sizeof(*eth); - if (data + nh_off > data_end) - return rc; - - h_proto = eth->h_proto; - - /* Handle VLAN tagged packet */ - if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) { - struct vlan_hdr *vhdr; - - vhdr = data + nh_off; - nh_off += sizeof(struct vlan_hdr); - if (data + nh_off > data_end) - return rc; - h_proto = vhdr->h_vlan_encapsulated_proto; - } - /* Handle double VLAN tagged packet */ - if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) { - struct vlan_hdr *vhdr; - - vhdr = data + nh_off; - nh_off += sizeof(struct vlan_hdr); - if (data + nh_off > data_end) - return rc; - h_proto = vhdr->h_vlan_encapsulated_proto; - } - - if (h_proto == htons(ETH_P_IP)) - ipproto = parse_ipv4(data, nh_off, data_end); - else if (h_proto == htons(ETH_P_IPV6)) - ipproto = parse_ipv6(data, nh_off, data_end); - else - ipproto = 0; - - value = bpf_map_lookup_elem(&rxcnt, &ipproto); - if (value) - *value += 1; - - return rc; -} - -char _license[] SEC("license") = "GPL"; diff --git a/samples/bpf/xdp1_user.c b/samples/bpf/xdp1_user.c deleted file mode 100644 index f05e797013e9..000000000000 --- a/samples/bpf/xdp1_user.c +++ /dev/null @@ -1,166 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2016 PLUMgrid - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "bpf_util.h" -#include -#include - -static int ifindex; -static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST; -static __u32 prog_id; - -static void int_exit(int sig) -{ - __u32 curr_prog_id = 0; - - if (bpf_xdp_query_id(ifindex, xdp_flags, &curr_prog_id)) { - printf("bpf_xdp_query_id failed\n"); - exit(1); - } - if (prog_id == curr_prog_id) - bpf_xdp_detach(ifindex, xdp_flags, NULL); - else if (!curr_prog_id) - printf("couldn't find a prog id on a given interface\n"); - else - printf("program on interface changed, not removing\n"); - exit(0); -} - -/* simple per-protocol drop counter - */ -static void poll_stats(int map_fd, int interval) -{ - unsigned int nr_cpus = bpf_num_possible_cpus(); - __u64 values[nr_cpus], prev[UINT8_MAX] = { 0 }; - int i; - - while (1) { - __u32 key = UINT32_MAX; - - sleep(interval); - - while (bpf_map_get_next_key(map_fd, &key, &key) == 0) { - __u64 sum = 0; - - assert(bpf_map_lookup_elem(map_fd, &key, values) == 0); - for (i = 0; i < nr_cpus; i++) - sum += values[i]; - if (sum > prev[key]) - printf("proto %u: %10llu pkt/s\n", - key, (sum - prev[key]) / interval); - prev[key] = sum; - } - } -} - -static void usage(const char *prog) -{ - fprintf(stderr, - "usage: %s [OPTS] IFACE\n\n" - "OPTS:\n" - " -S use skb-mode\n" - " -N enforce native mode\n" - " -F force loading prog\n", - prog); -} - -int main(int argc, char **argv) -{ - struct bpf_prog_info info = {}; - __u32 info_len = sizeof(info); - const char *optstr = "FSN"; - int prog_fd, map_fd, opt; - struct bpf_program *prog; - struct bpf_object *obj; - struct bpf_map *map; - char filename[256]; - int err; - - while ((opt = getopt(argc, argv, optstr)) != -1) { - switch (opt) { - case 'S': - xdp_flags |= XDP_FLAGS_SKB_MODE; - break; - case 'N': - /* default, set below */ - break; - case 'F': - xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST; - break; - default: - usage(basename(argv[0])); - return 1; - } - } - - if (!(xdp_flags & XDP_FLAGS_SKB_MODE)) - xdp_flags |= XDP_FLAGS_DRV_MODE; - - if (optind == argc) { - usage(basename(argv[0])); - return 1; - } - - ifindex = if_nametoindex(argv[optind]); - if (!ifindex) { - perror("if_nametoindex"); - return 1; - } - - snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); - obj = bpf_object__open_file(filename, NULL); - if (libbpf_get_error(obj)) - return 1; - - prog = bpf_object__next_program(obj, NULL); - bpf_program__set_type(prog, BPF_PROG_TYPE_XDP); - - err = bpf_object__load(obj); - if (err) - return 1; - - prog_fd = bpf_program__fd(prog); - - map = bpf_object__next_map(obj, NULL); - if (!map) { - printf("finding a map in obj file failed\n"); - return 1; - } - map_fd = bpf_map__fd(map); - - if (!prog_fd) { - printf("bpf_prog_load_xattr: %s\n", strerror(errno)); - return 1; - } - - signal(SIGINT, int_exit); - signal(SIGTERM, int_exit); - - if (bpf_xdp_attach(ifindex, prog_fd, xdp_flags, NULL) < 0) { - printf("link set xdp fd failed\n"); - return 1; - } - - err = bpf_prog_get_info_by_fd(prog_fd, &info, &info_len); - if (err) { - printf("can't get prog info - %s\n", strerror(errno)); - return err; - } - prog_id = info.id; - - poll_stats(map_fd, 1); - - return 0; -} diff --git a/samples/bpf/xdp2_kern.c b/samples/bpf/xdp2_kern.c deleted file mode 100644 index 8bca674451ed..000000000000 --- a/samples/bpf/xdp2_kern.c +++ /dev/null @@ -1,125 +0,0 @@ -/* Copyright (c) 2016 PLUMgrid - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - */ -#define KBUILD_MODNAME "foo" -#include -#include -#include -#include -#include -#include -#include -#include - -struct { - __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); - __type(key, u32); - __type(value, long); - __uint(max_entries, 256); -} rxcnt SEC(".maps"); - -static void swap_src_dst_mac(void *data) -{ - unsigned short *p = data; - unsigned short dst[3]; - - dst[0] = p[0]; - dst[1] = p[1]; - dst[2] = p[2]; - p[0] = p[3]; - p[1] = p[4]; - p[2] = p[5]; - p[3] = dst[0]; - p[4] = dst[1]; - p[5] = dst[2]; -} - -static int parse_ipv4(void *data, u64 nh_off, void *data_end) -{ - struct iphdr *iph = data + nh_off; - - if (iph + 1 > data_end) - return 0; - return iph->protocol; -} - -static int parse_ipv6(void *data, u64 nh_off, void *data_end) -{ - struct ipv6hdr *ip6h = data + nh_off; - - if (ip6h + 1 > data_end) - return 0; - return ip6h->nexthdr; -} - -#define XDPBUFSIZE 60 -SEC("xdp.frags") -int xdp_prog1(struct xdp_md *ctx) -{ - __u8 pkt[XDPBUFSIZE] = {}; - void *data_end = &pkt[XDPBUFSIZE-1]; - void *data = pkt; - struct ethhdr *eth = data; - int rc = XDP_DROP; - long *value; - u16 h_proto; - u64 nh_off; - u32 ipproto; - - if (bpf_xdp_load_bytes(ctx, 0, pkt, sizeof(pkt))) - return rc; - - nh_off = sizeof(*eth); - if (data + nh_off > data_end) - return rc; - - h_proto = eth->h_proto; - - /* Handle VLAN tagged packet */ - if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) { - struct vlan_hdr *vhdr; - - vhdr = data + nh_off; - nh_off += sizeof(struct vlan_hdr); - if (data + nh_off > data_end) - return rc; - h_proto = vhdr->h_vlan_encapsulated_proto; - } - /* Handle double VLAN tagged packet */ - if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) { - struct vlan_hdr *vhdr; - - vhdr = data + nh_off; - nh_off += sizeof(struct vlan_hdr); - if (data + nh_off > data_end) - return rc; - h_proto = vhdr->h_vlan_encapsulated_proto; - } - - if (h_proto == htons(ETH_P_IP)) - ipproto = parse_ipv4(data, nh_off, data_end); - else if (h_proto == htons(ETH_P_IPV6)) - ipproto = parse_ipv6(data, nh_off, data_end); - else - ipproto = 0; - - value = bpf_map_lookup_elem(&rxcnt, &ipproto); - if (value) - *value += 1; - - if (ipproto == IPPROTO_UDP) { - swap_src_dst_mac(data); - - if (bpf_xdp_store_bytes(ctx, 0, pkt, sizeof(pkt))) - return rc; - - rc = XDP_TX; - } - - return rc; -} - -char _license[] SEC("license") = "GPL"; -- cgit v1.2.3 From cced0699cbf1ebfb39234d764ade2f907c5ca0b5 Mon Sep 17 00:00:00 2001 From: Toke Høiland-Jørgensen Date: Thu, 24 Aug 2023 12:22:48 +0200 Subject: samples/bpf: Remove the xdp_sample_pkts utility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The functionality of this utility is covered by the xdpdump utility in xdp-tools. There's a slight difference in usage as the xdpdump utility's main focus is to dump packets before or after they are processed by an existing XDP program. However, xdpdump also has the --load-xdp-program switch, which will make it attach its own program if no existing program is loaded. With this, xdp_sample_pkts usage can be converted as: xdp_sample_pkts eth0 --> xdpdump --load-xdp-program eth0 To get roughly equivalent behaviour. Signed-off-by: Toke Høiland-Jørgensen Link: https://lore.kernel.org/r/20230824102255.1561885-6-toke@redhat.com Signed-off-by: Alexei Starovoitov --- samples/bpf/Makefile | 3 - samples/bpf/xdp_sample_pkts_kern.c | 57 ----------- samples/bpf/xdp_sample_pkts_user.c | 196 ------------------------------------- 3 files changed, 256 deletions(-) delete mode 100644 samples/bpf/xdp_sample_pkts_kern.c delete mode 100644 samples/bpf/xdp_sample_pkts_user.c (limited to 'samples') diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile index decd31167ee4..4ccf4236031c 100644 --- a/samples/bpf/Makefile +++ b/samples/bpf/Makefile @@ -44,7 +44,6 @@ tprogs-y += cpustat tprogs-y += xdp_adjust_tail tprogs-y += xdp_fwd tprogs-y += task_fd_query -tprogs-y += xdp_sample_pkts tprogs-y += ibumad tprogs-y += hbm @@ -95,7 +94,6 @@ cpustat-objs := cpustat_user.o xdp_adjust_tail-objs := xdp_adjust_tail_user.o xdp_fwd-objs := xdp_fwd_user.o task_fd_query-objs := task_fd_query_user.o $(TRACE_HELPERS) -xdp_sample_pkts-objs := xdp_sample_pkts_user.o ibumad-objs := ibumad_user.o hbm-objs := hbm.o $(CGROUP_HELPERS) @@ -148,7 +146,6 @@ always-y += cpustat_kern.o always-y += xdp_adjust_tail_kern.o always-y += xdp_fwd_kern.o always-y += task_fd_query_kern.o -always-y += xdp_sample_pkts_kern.o always-y += ibumad_kern.o always-y += hbm_out_kern.o always-y += hbm_edt_kern.o diff --git a/samples/bpf/xdp_sample_pkts_kern.c b/samples/bpf/xdp_sample_pkts_kern.c deleted file mode 100644 index 9cf76b340dd7..000000000000 --- a/samples/bpf/xdp_sample_pkts_kern.c +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include -#include -#include - -#define SAMPLE_SIZE 64ul - -struct { - __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); - __uint(key_size, sizeof(int)); - __uint(value_size, sizeof(u32)); -} my_map SEC(".maps"); - -SEC("xdp_sample") -int xdp_sample_prog(struct xdp_md *ctx) -{ - void *data_end = (void *)(long)ctx->data_end; - void *data = (void *)(long)ctx->data; - - /* Metadata will be in the perf event before the packet data. */ - struct S { - u16 cookie; - u16 pkt_len; - } __packed metadata; - - if (data < data_end) { - /* The XDP perf_event_output handler will use the upper 32 bits - * of the flags argument as a number of bytes to include of the - * packet payload in the event data. If the size is too big, the - * call to bpf_perf_event_output will fail and return -EFAULT. - * - * See bpf_xdp_event_output in net/core/filter.c. - * - * The BPF_F_CURRENT_CPU flag means that the event output fd - * will be indexed by the CPU number in the event map. - */ - u64 flags = BPF_F_CURRENT_CPU; - u16 sample_size; - int ret; - - metadata.cookie = 0xdead; - metadata.pkt_len = (u16)(data_end - data); - sample_size = min(metadata.pkt_len, SAMPLE_SIZE); - flags |= (u64)sample_size << 32; - - ret = bpf_perf_event_output(ctx, &my_map, flags, - &metadata, sizeof(metadata)); - if (ret) - bpf_printk("perf_event_output failed: %d\n", ret); - } - - return XDP_PASS; -} - -char _license[] SEC("license") = "GPL"; -u32 _version SEC("version") = LINUX_VERSION_CODE; diff --git a/samples/bpf/xdp_sample_pkts_user.c b/samples/bpf/xdp_sample_pkts_user.c deleted file mode 100644 index e39d7f654f30..000000000000 --- a/samples/bpf/xdp_sample_pkts_user.c +++ /dev/null @@ -1,196 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "perf-sys.h" - -static int if_idx; -static char *if_name; -static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST; -static __u32 prog_id; -static struct perf_buffer *pb = NULL; - -static int do_attach(int idx, int fd, const char *name) -{ - struct bpf_prog_info info = {}; - __u32 info_len = sizeof(info); - int err; - - err = bpf_xdp_attach(idx, fd, xdp_flags, NULL); - if (err < 0) { - printf("ERROR: failed to attach program to %s\n", name); - return err; - } - - err = bpf_prog_get_info_by_fd(fd, &info, &info_len); - if (err) { - printf("can't get prog info - %s\n", strerror(errno)); - return err; - } - prog_id = info.id; - - return err; -} - -static int do_detach(int idx, const char *name) -{ - __u32 curr_prog_id = 0; - int err = 0; - - err = bpf_xdp_query_id(idx, xdp_flags, &curr_prog_id); - if (err) { - printf("bpf_xdp_query_id failed\n"); - return err; - } - if (prog_id == curr_prog_id) { - err = bpf_xdp_detach(idx, xdp_flags, NULL); - if (err < 0) - printf("ERROR: failed to detach prog from %s\n", name); - } else if (!curr_prog_id) { - printf("couldn't find a prog id on a %s\n", name); - } else { - printf("program on interface changed, not removing\n"); - } - - return err; -} - -#define SAMPLE_SIZE 64 - -static void print_bpf_output(void *ctx, int cpu, void *data, __u32 size) -{ - struct { - __u16 cookie; - __u16 pkt_len; - __u8 pkt_data[SAMPLE_SIZE]; - } __packed *e = data; - int i; - - if (e->cookie != 0xdead) { - printf("BUG cookie %x sized %d\n", e->cookie, size); - return; - } - - printf("Pkt len: %-5d bytes. Ethernet hdr: ", e->pkt_len); - for (i = 0; i < 14 && i < e->pkt_len; i++) - printf("%02x ", e->pkt_data[i]); - printf("\n"); -} - -static void sig_handler(int signo) -{ - do_detach(if_idx, if_name); - perf_buffer__free(pb); - exit(0); -} - -static void usage(const char *prog) -{ - fprintf(stderr, - "%s: %s [OPTS] \n\n" - "OPTS:\n" - " -F force loading prog\n" - " -S use skb-mode\n", - __func__, prog); -} - -int main(int argc, char **argv) -{ - const char *optstr = "FS"; - int prog_fd, map_fd, opt; - struct bpf_program *prog; - struct bpf_object *obj; - struct bpf_map *map; - char filename[256]; - int ret, err; - - while ((opt = getopt(argc, argv, optstr)) != -1) { - switch (opt) { - case 'F': - xdp_flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST; - break; - case 'S': - xdp_flags |= XDP_FLAGS_SKB_MODE; - break; - default: - usage(basename(argv[0])); - return 1; - } - } - - if (!(xdp_flags & XDP_FLAGS_SKB_MODE)) - xdp_flags |= XDP_FLAGS_DRV_MODE; - - if (optind == argc) { - usage(basename(argv[0])); - return 1; - } - - snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); - - obj = bpf_object__open_file(filename, NULL); - if (libbpf_get_error(obj)) - return 1; - - prog = bpf_object__next_program(obj, NULL); - bpf_program__set_type(prog, BPF_PROG_TYPE_XDP); - - err = bpf_object__load(obj); - if (err) - return 1; - - prog_fd = bpf_program__fd(prog); - - map = bpf_object__next_map(obj, NULL); - if (!map) { - printf("finding a map in obj file failed\n"); - return 1; - } - map_fd = bpf_map__fd(map); - - if_idx = if_nametoindex(argv[optind]); - if (!if_idx) - if_idx = strtoul(argv[optind], NULL, 0); - - if (!if_idx) { - fprintf(stderr, "Invalid ifname\n"); - return 1; - } - if_name = argv[optind]; - err = do_attach(if_idx, prog_fd, if_name); - if (err) - return err; - - if (signal(SIGINT, sig_handler) || - signal(SIGHUP, sig_handler) || - signal(SIGTERM, sig_handler)) { - perror("signal"); - return 1; - } - - pb = perf_buffer__new(map_fd, 8, print_bpf_output, NULL, NULL, NULL); - err = libbpf_get_error(pb); - if (err) { - perror("perf_buffer setup failed"); - return 1; - } - - while ((ret = perf_buffer__poll(pb, 1000)) >= 0) { - } - - kill(0, SIGINT); - return ret; -} -- cgit v1.2.3 From 91b965136d536a981ed22097bc2b72625f5c4211 Mon Sep 17 00:00:00 2001 From: Toke Høiland-Jørgensen Date: Thu, 24 Aug 2023 12:22:49 +0200 Subject: samples/bpf: Cleanup .gitignore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove no longer present XDP utilities from .gitignore. Apart from the recently removed XDP utilities this also includes the previously removed xdpsock and xsk utilities. Signed-off-by: Toke Høiland-Jørgensen Link: https://lore.kernel.org/r/20230824102255.1561885-7-toke@redhat.com Signed-off-by: Alexei Starovoitov --- samples/bpf/.gitignore | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'samples') diff --git a/samples/bpf/.gitignore b/samples/bpf/.gitignore index 0e7bfdbff80a..0002cd359fb1 100644 --- a/samples/bpf/.gitignore +++ b/samples/bpf/.gitignore @@ -37,22 +37,10 @@ tracex4 tracex5 tracex6 tracex7 -xdp1 -xdp2 xdp_adjust_tail xdp_fwd -xdp_monitor -xdp_redirect -xdp_redirect_cpu -xdp_redirect_map -xdp_redirect_map_multi xdp_router_ipv4 -xdp_rxq_info -xdp_sample_pkts xdp_tx_iptunnel -xdpsock -xdpsock_ctrl_proc -xsk_fwd testfile.img hbm_out.log iperf.* -- cgit v1.2.3 From 5a9fd0f778ebb2076fa1098df23e741c794d9992 Mon Sep 17 00:00:00 2001 From: Toke Høiland-Jørgensen Date: Thu, 24 Aug 2023 12:22:50 +0200 Subject: samples/bpf: Add note to README about the XDP utilities moved to xdp-tools MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To help users find the XDP utilities, add a note to the README about the new location and the conversion documentation in the commit messages. Signed-off-by: Toke Høiland-Jørgensen Link: https://lore.kernel.org/r/20230824102255.1561885-8-toke@redhat.com Signed-off-by: Alexei Starovoitov --- samples/bpf/README.rst | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'samples') diff --git a/samples/bpf/README.rst b/samples/bpf/README.rst index f16fc48e55a5..cabe2d216997 100644 --- a/samples/bpf/README.rst +++ b/samples/bpf/README.rst @@ -4,6 +4,12 @@ eBPF sample programs This directory contains a test stubs, verifier test-suite and examples for using eBPF. The examples use libbpf from tools/lib/bpf. +Note that the XDP-specific samples have been removed from this directory and +moved to the xdp-tools repository: https://github.com/xdp-project/xdp-tools +See the commit messages removing each tool from this directory for how to +convert specific command invocations between the old samples and the utilities +in xdp-tools. + Build dependencies ================== -- cgit v1.2.3