diff options
Diffstat (limited to 'samples/bpf')
93 files changed, 380 insertions, 6140 deletions
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.* diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile index 727da3c5879b..95a4fa1f1e44 100644 --- a/samples/bpf/Makefile +++ b/samples/bpf/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 -BPF_SAMPLES_PATH ?= $(abspath $(srctree)/$(src)) +BPF_SAMPLES_PATH ?= $(abspath $(src)) TOOLS_PATH := $(BPF_SAMPLES_PATH)/../../tools pound := \# @@ -13,27 +13,16 @@ tprogs-y += sockex1 tprogs-y += sockex2 tprogs-y += sockex3 tprogs-y += tracex1 -tprogs-y += tracex2 tprogs-y += tracex3 tprogs-y += tracex4 tprogs-y += tracex5 tprogs-y += tracex6 -tprogs-y += tracex7 -tprogs-y += test_probe_write_user tprogs-y += trace_output tprogs-y += lathist tprogs-y += offwaketime tprogs-y += spintest tprogs-y += map_perf_test -tprogs-y += test_overhead -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 tprogs-y += sampleip tprogs-y += tc_l2_redirect @@ -41,22 +30,14 @@ 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 tprogs-y += xdp_fwd tprogs-y += task_fd_query -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 -tprogs-y += xdp_monitor - # Libbpf dependencies LIBBPF_SRC = $(TOOLS_PATH)/lib/bpf LIBBPF_OUTPUT = $(abspath $(BPF_SAMPLES_PATH))/libbpf @@ -73,28 +54,16 @@ sockex1-objs := sockex1_user.o sockex2-objs := sockex2_user.o sockex3-objs := sockex3_user.o tracex1-objs := tracex1_user.o $(TRACE_HELPERS) -tracex2-objs := tracex2_user.o tracex3-objs := tracex3_user.o tracex4-objs := tracex4_user.o tracex5-objs := tracex5_user.o $(TRACE_HELPERS) tracex6-objs := tracex6_user.o -tracex7-objs := tracex7_user.o -test_probe_write_user-objs := test_probe_write_user_user.o trace_output-objs := trace_output_user.o lathist-objs := lathist_user.o offwaketime-objs := offwaketime_user.o $(TRACE_HELPERS) spintest-objs := spintest_user.o $(TRACE_HELPERS) map_perf_test-objs := map_perf_test_user.o test_overhead-objs := test_overhead_user.o -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) sampleip-objs := sampleip_user.o $(TRACE_HELPERS) tc_l2_redirect-objs := tc_l2_redirect_user.o @@ -102,21 +71,14 @@ 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 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) -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 @@ -124,35 +86,24 @@ 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 += tracex2_kern.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 += sock_flags_kern.o -always-y += test_probe_write_user_kern.o -always-y += trace_output_kern.o +always-y += tracex1.bpf.o +always-y += tracex3.bpf.o +always-y += tracex4.bpf.o +always-y += tracex5.bpf.o +always-y += tracex6.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 += map_perf_test_kern.o -always-y += test_overhead_tp_kern.o -always-y += test_overhead_raw_tp_kern.o -always-y += test_overhead_kprobe_kern.o +always-y += offwaketime.bpf.o +always-y += spintest.bpf.o +always-y += map_perf_test.bpf.o always-y += parse_varlen.o parse_simple.o parse_ldabs.o -always-y += test_cgrp2_tc_kern.o -always-y += xdp1_kern.o -always-y += xdp2_kern.o -always-y += test_current_task_under_cgroup_kern.o always-y += trace_event_kern.o always-y += sampleip_kern.o -always-y += lwt_len_hist_kern.o +always-y += lwt_len_hist.bpf.o always-y += xdp_tx_iptunnel_kern.o -always-y += test_map_in_map_kern.o +always-y += test_map_in_map.bpf.o always-y += tcp_synrto_kern.o always-y += tcp_rwnd_kern.o always-y += tcp_bufs_kern.o @@ -162,18 +113,19 @@ 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 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 +COMMON_CFLAGS = $(TPROGS_USER_CFLAGS) +TPROGS_LDFLAGS = $(TPROGS_USER_LDFLAGS) + ifeq ($(ARCH), arm) # Strip all except -D__LINUX_ARM_ARCH__ option needed to handle linux # headers when arm instruction set identification is requested. @@ -190,33 +142,36 @@ BPF_EXTRA_CFLAGS += -I$(srctree)/arch/mips/include/asm/mach-generic endif endif -TPROGS_CFLAGS += -Wall -O2 -TPROGS_CFLAGS += -Wmissing-prototypes -TPROGS_CFLAGS += -Wstrict-prototypes +ifeq ($(ARCH), x86) +BPF_EXTRA_CFLAGS += -fcf-protection +endif +COMMON_CFLAGS += -Wall -O2 +COMMON_CFLAGS += -Wmissing-prototypes +COMMON_CFLAGS += -Wstrict-prototypes +COMMON_CFLAGS += $(call try-run,\ + printf "int main() { return 0; }" |\ + $(CC) -Werror -fsanitize=bounds -x c - -o "$$TMP",-fsanitize=bounds,) + +TPROGS_CFLAGS += $(COMMON_CFLAGS) TPROGS_CFLAGS += -I$(objtree)/usr/include TPROGS_CFLAGS += -I$(srctree)/tools/testing/selftests/bpf/ TPROGS_CFLAGS += -I$(LIBBPF_INCLUDE) TPROGS_CFLAGS += -I$(srctree)/tools/include TPROGS_CFLAGS += -I$(srctree)/tools/perf +TPROGS_CFLAGS += -I$(srctree)/tools/lib TPROGS_CFLAGS += -DHAVE_ATTR_TEST=0 ifdef SYSROOT -TPROGS_CFLAGS += --sysroot=$(SYSROOT) +COMMON_CFLAGS += --sysroot=$(SYSROOT) 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 -TPROGLDLIBS_xdp_redirect_map_multi += -lm TPROGLDLIBS_xdp_router_ipv4 += -lm -pthread TPROGLDLIBS_tracex4 += -lrt TPROGLDLIBS_trace_output += -lrt TPROGLDLIBS_map_perf_test += -lrt -TPROGLDLIBS_test_overhead += -lrt # Allows pointing LLC/CLANG to a LLVM backend with bpf support, redefine on cmdline: # make M=samples/bpf LLC=~/git/llvm-project/llvm/build/bin/llc CLANG=~/git/llvm-project/llvm/build/bin/clang @@ -248,7 +203,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) @@ -275,15 +230,16 @@ clean: $(LIBBPF): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(LIBBPF_OUTPUT) # Fix up variables inherited from Kbuild that tools/ build system won't like - $(MAKE) -C $(LIBBPF_SRC) RM='rm -rf' EXTRA_CFLAGS="$(TPROGS_CFLAGS)" \ - LDFLAGS=$(TPROGS_LDFLAGS) srctree=$(BPF_SAMPLES_PATH)/../../ \ + $(MAKE) -C $(LIBBPF_SRC) RM='rm -rf' EXTRA_CFLAGS="$(COMMON_CFLAGS)" \ + LDFLAGS="$(TPROGS_LDFLAGS)" srctree=$(BPF_SAMPLES_PATH)/../../ \ O= OUTPUT=$(LIBBPF_OUTPUT)/ DESTDIR=$(LIBBPF_DESTDIR) prefix= \ $@ install_headers BPFTOOLDIR := $(TOOLS_PATH)/bpf/bpftool BPFTOOL_OUTPUT := $(abspath $(BPF_SAMPLES_PATH))/bpftool -BPFTOOL := $(BPFTOOL_OUTPUT)/bootstrap/bpftool -$(BPFTOOL): $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile) | $(BPFTOOL_OUTPUT) +DEFAULT_BPFTOOL := $(BPFTOOL_OUTPUT)/bootstrap/bpftool +BPFTOOL ?= $(DEFAULT_BPFTOOL) +$(DEFAULT_BPFTOOL): $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile) | $(BPFTOOL_OUTPUT) $(MAKE) -C $(BPFTOOLDIR) srctree=$(BPF_SAMPLES_PATH)/../../ \ OUTPUT=$(BPFTOOL_OUTPUT)/ bootstrap @@ -326,14 +282,9 @@ $(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_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 @@ -346,21 +297,24 @@ XDP_SAMPLE_CFLAGS += -Wall -O2 \ -I$(LIBBPF_INCLUDE) \ -I$(src)/../../tools/testing/selftests/bpf -$(obj)/$(XDP_SAMPLE): TPROGS_CFLAGS = $(XDP_SAMPLE_CFLAGS) +$(obj)/$(XDP_SAMPLE): TPROGS_CFLAGS = $(XDP_SAMPLE_CFLAGS) $(TPROGS_USER_CFLAGS) $(obj)/$(XDP_SAMPLE): $(src)/xdp_sample_user.h $(src)/xdp_sample_shared.h +# Override includes for trace_helpers.o because __must_check won't be defined +# in our include path. +$(obj)/$(TRACE_HELPERS): TPROGS_CFLAGS := $(TPROGS_CFLAGS) -D__must_check= -include $(BPF_SAMPLES_PATH)/Makefile.target VMLINUX_BTF_PATHS ?= $(abspath $(if $(O),$(O)/vmlinux)) \ $(abspath $(if $(KBUILD_OUTPUT),$(KBUILD_OUTPUT)/vmlinux)) \ - $(abspath ./vmlinux) + $(abspath $(objtree)/vmlinux) VMLINUX_BTF ?= $(abspath $(firstword $(wildcard $(VMLINUX_BTF_PATHS)))) $(obj)/vmlinux.h: $(VMLINUX_BTF) $(BPFTOOL) ifeq ($(VMLINUX_H),) ifeq ($(VMLINUX_BTF),) $(error Cannot find a vmlinux for VMLINUX_BTF at any of "$(VMLINUX_BTF_PATHS)",\ - build the kernel or set VMLINUX_BTF or VMLINUX_H variable) + build the kernel or set VMLINUX_BTF like "VMLINUX_BTF=/sys/kernel/btf/vmlinux" or VMLINUX_H variable) endif $(Q)$(BPFTOOL) btf dump file $(VMLINUX_BTF) format c > $@ else @@ -370,7 +324,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 @@ -383,31 +337,19 @@ 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_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 @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) \ -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_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_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))) @@ -434,7 +376,7 @@ $(obj)/%.o: $(src)/%.c @echo " CLANG-bpf " $@ $(Q)$(CLANG) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) $(BPF_EXTRA_CFLAGS) \ -I$(obj) -I$(srctree)/tools/testing/selftests/bpf/ \ - -I$(LIBBPF_INCLUDE) \ + -I$(LIBBPF_INCLUDE) $(CLANG_SYS_INCLUDES) \ -D__KERNEL__ -D__BPF_TRACING__ -Wno-unused-value -Wno-pointer-sign \ -D__TARGET_ARCH_$(SRCARCH) -Wno-compare-distinct-pointer-types \ -Wno-gnu-variable-sized-type-not-at-end \ diff --git a/samples/bpf/README.rst b/samples/bpf/README.rst index 57f93edd1957..cabe2d216997 100644 --- a/samples/bpf/README.rst +++ b/samples/bpf/README.rst @@ -4,15 +4,24 @@ 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 ================== 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 <changes>` 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 +33,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 diff --git a/samples/bpf/asm_goto_workaround.h b/samples/bpf/asm_goto_workaround.h index 7048bb3594d6..634e81d83efd 100644 --- a/samples/bpf/asm_goto_workaround.h +++ b/samples/bpf/asm_goto_workaround.h @@ -4,14 +4,14 @@ #define __ASM_GOTO_WORKAROUND_H /* - * This will bring in asm_volatile_goto and asm_inline macro definitions + * This will bring in asm_goto_output and asm_inline macro definitions * if enabled by compiler and config options. */ #include <linux/types.h> -#ifdef asm_volatile_goto -#undef asm_volatile_goto -#define asm_volatile_goto(x...) asm volatile("invalid use of asm_volatile_goto") +#ifdef asm_goto_output +#undef asm_goto_output +#define asm_goto_output(x...) asm volatile("invalid use of asm_goto_output") #endif /* diff --git a/samples/bpf/cpustat_kern.c b/samples/bpf/cpustat_kern.c index 5aefd19cdfa1..7ec7143e2757 100644 --- a/samples/bpf/cpustat_kern.c +++ b/samples/bpf/cpustat_kern.c @@ -76,8 +76,8 @@ struct { /* * The trace events for cpu_idle and cpu_frequency are taken from: - * /sys/kernel/debug/tracing/events/power/cpu_idle/format - * /sys/kernel/debug/tracing/events/power/cpu_frequency/format + * /sys/kernel/tracing/events/power/cpu_idle/format + * /sys/kernel/tracing/events/power/cpu_frequency/format * * These two events have same format, so define one common structure. */ @@ -211,7 +211,7 @@ int bpf_prog1(struct cpu_args *ctx) SEC("tracepoint/power/cpu_frequency") int bpf_prog2(struct cpu_args *ctx) { - u64 *pts, *cstate, *pstate, prev_state, cur_ts, delta; + u64 *pts, *cstate, *pstate, cur_ts, delta; u32 key, cpu, pstate_idx; u64 *val; @@ -232,7 +232,6 @@ int bpf_prog2(struct cpu_args *ctx) if (!cstate) return 0; - prev_state = *pstate; *pstate = ctx->state; if (!*pts) { diff --git a/samples/bpf/cpustat_user.c b/samples/bpf/cpustat_user.c index ab90bb08a2b4..356f756cba0d 100644 --- a/samples/bpf/cpustat_user.c +++ b/samples/bpf/cpustat_user.c @@ -66,10 +66,10 @@ static void cpu_stat_print(void) printf("CPU-%-6d ", j); for (i = 0; i < MAX_CSTATE_ENTRIES; i++) - printf("%-11ld ", data->cstate[i] / 1000000); + printf("%-11lu ", data->cstate[i] / 1000000); for (i = 0; i < MAX_PSTATE_ENTRIES; i++) - printf("%-11ld ", data->pstate[i] / 1000000); + printf("%-11lu ", data->pstate[i] / 1000000); printf("\n"); } diff --git a/samples/bpf/do_hbm_test.sh b/samples/bpf/do_hbm_test.sh index 38e4599350db..7f4f722787d5 100755 --- a/samples/bpf/do_hbm_test.sh +++ b/samples/bpf/do_hbm_test.sh @@ -112,7 +112,7 @@ function start_hbm () { processArgs () { for i in $args ; do case $i in - # Support for upcomming ingress rate limiting + # Support for upcoming ingress rate limiting #in) # support for upcoming ingress rate limiting # dir="-i" # dir_name="in" diff --git a/samples/bpf/gnu/stubs.h b/samples/bpf/gnu/stubs.h new file mode 100644 index 000000000000..1c638d9dce1a --- /dev/null +++ b/samples/bpf/gnu/stubs.h @@ -0,0 +1 @@ +/* dummy .h to trick /usr/include/features.h to work with 'clang --target=bpf' */ diff --git a/samples/bpf/hbm.c b/samples/bpf/hbm.c index 516fbac28b71..fc88d4dbdf48 100644 --- a/samples/bpf/hbm.c +++ b/samples/bpf/hbm.c @@ -5,7 +5,7 @@ * modify it under the terms of version 2 of the GNU General Public * License as published by the Free Software Foundation. * - * Example program for Host Bandwidth Managment + * Example program for Host Bandwidth Management * * This program loads a cgroup skb BPF program to enforce cgroup output * (egress) or input (ingress) bandwidth limits. @@ -24,7 +24,7 @@ * beyond the rate limit specified while there is available * bandwidth. Current implementation assumes there is only * NIC (eth0), but can be extended to support multiple NICs. - * Currrently only supported for egress. + * Currently only supported for egress. * -h Print this info * prog BPF program file name. Name defaults to hbm_out_kern.o */ @@ -65,7 +65,7 @@ static void Usage(void); static void read_trace_pipe2(void); static void do_error(char *msg, bool errno_flag); -#define DEBUGFS "/sys/kernel/debug/tracing/" +#define TRACEFS "/sys/kernel/tracing/" static struct bpf_program *bpf_prog; static struct bpf_object *obj; @@ -77,7 +77,7 @@ static void read_trace_pipe2(void) FILE *outf; char *outFname = "hbm_out.log"; - trace_fd = open(DEBUGFS "trace_pipe", O_RDONLY, 0); + trace_fd = open(TRACEFS "trace_pipe", O_RDONLY, 0); if (trace_fd < 0) { printf("Error opening trace_pipe\n"); return; @@ -315,6 +315,7 @@ static int run_bpf_prog(char *prog, int cg_id) fout = fopen(fname, "w"); fprintf(fout, "id:%d\n", cg_id); fprintf(fout, "ERROR: Could not lookup queue_stats\n"); + fclose(fout); } else if (stats_flag && qstats.lastPacketTime > qstats.firstPacketTime) { long long delta_us = (qstats.lastPacketTime - @@ -497,7 +498,6 @@ int main(int argc, char **argv) "Option -%c requires an argument.\n\n", optopt); case 'h': - __fallthrough; default: Usage(); return 0; diff --git a/samples/bpf/ibumad_kern.c b/samples/bpf/ibumad_kern.c index 9b193231024a..f07474c72525 100644 --- a/samples/bpf/ibumad_kern.c +++ b/samples/bpf/ibumad_kern.c @@ -39,8 +39,8 @@ struct { /* Taken from the current format defined in * include/trace/events/ib_umad.h * and - * /sys/kernel/debug/tracing/events/ib_umad/ib_umad_read/format - * /sys/kernel/debug/tracing/events/ib_umad/ib_umad_write/format + * /sys/kernel/tracing/events/ib_umad/ib_umad_read/format + * /sys/kernel/tracing/events/ib_umad/ib_umad_write/format */ struct ib_umad_rw_args { u64 pad; diff --git a/samples/bpf/lwt_len_hist_kern.c b/samples/bpf/lwt_len_hist.bpf.c index 1fa14c54963a..dbab80e813fe 100644 --- a/samples/bpf/lwt_len_hist_kern.c +++ b/samples/bpf/lwt_len_hist.bpf.c @@ -10,29 +10,16 @@ * General Public License for more details. */ -#include <uapi/linux/bpf.h> -#include <uapi/linux/if_ether.h> -#include <uapi/linux/ip.h> -#include <uapi/linux/in.h> +#include "vmlinux.h" #include <bpf/bpf_helpers.h> -struct bpf_elf_map { - __u32 type; - __u32 size_key; - __u32 size_value; - __u32 max_elem; - __u32 flags; - __u32 id; - __u32 pinning; -}; - -struct bpf_elf_map SEC("maps") lwt_len_hist_map = { - .type = BPF_MAP_TYPE_PERCPU_HASH, - .size_key = sizeof(__u64), - .size_value = sizeof(__u64), - .pinning = 2, - .max_elem = 1024, -}; +struct { + __uint(type, BPF_MAP_TYPE_PERCPU_HASH); + __type(key, u64); + __type(value, u64); + __uint(pinning, LIBBPF_PIN_BY_NAME); + __uint(max_entries, 1024); +} lwt_len_hist_map SEC(".maps"); static unsigned int log2(unsigned int v) { diff --git a/samples/bpf/lwt_len_hist.sh b/samples/bpf/lwt_len_hist.sh index 0eda9754f50b..381b2c634784 100755 --- a/samples/bpf/lwt_len_hist.sh +++ b/samples/bpf/lwt_len_hist.sh @@ -4,8 +4,8 @@ NS1=lwt_ns1 VETH0=tst_lwt1a VETH1=tst_lwt1b - -TRACE_ROOT=/sys/kernel/debug/tracing +BPF_PROG=lwt_len_hist.bpf.o +TRACE_ROOT=/sys/kernel/tracing function cleanup { # To reset saved histogram, remove pinned map @@ -30,7 +30,7 @@ ip netns exec $NS1 netserver echo 1 > ${TRACE_ROOT}/tracing_on cp /dev/null ${TRACE_ROOT}/trace -ip route add 192.168.253.2/32 encap bpf out obj lwt_len_hist_kern.o section len_hist dev $VETH0 +ip route add 192.168.253.2/32 encap bpf out obj $BPF_PROG section len_hist dev $VETH0 netperf -H 192.168.253.2 -t TCP_STREAM cat ${TRACE_ROOT}/trace | grep -v '^#' ./lwt_len_hist diff --git a/samples/bpf/map_perf_test_kern.c b/samples/bpf/map_perf_test.bpf.c index 7342c5b2f278..3cdeba2afe12 100644 --- a/samples/bpf/map_perf_test_kern.c +++ b/samples/bpf/map_perf_test.bpf.c @@ -4,14 +4,12 @@ * modify it under the terms of version 2 of the GNU General Public * License as published by the Free Software Foundation. */ -#include <linux/skbuff.h> -#include <linux/netdevice.h> +#include "vmlinux.h" +#include <errno.h> #include <linux/version.h> -#include <uapi/linux/bpf.h> #include <bpf/bpf_helpers.h> #include <bpf/bpf_tracing.h> #include <bpf/bpf_core_read.h> -#include "trace_common.h" #define MAX_ENTRIES 1000 #define MAX_NR_CPUS 1024 @@ -102,8 +100,8 @@ struct { __uint(max_entries, MAX_ENTRIES); } lru_hash_lookup_map SEC(".maps"); -SEC("kprobe/" SYSCALL(sys_getuid)) -int stress_hmap(struct pt_regs *ctx) +SEC("ksyscall/getuid") +int BPF_KSYSCALL(stress_hmap) { u32 key = bpf_get_current_pid_tgid(); long init_val = 1; @@ -120,8 +118,8 @@ int stress_hmap(struct pt_regs *ctx) return 0; } -SEC("kprobe/" SYSCALL(sys_geteuid)) -int stress_percpu_hmap(struct pt_regs *ctx) +SEC("ksyscall/geteuid") +int BPF_KSYSCALL(stress_percpu_hmap) { u32 key = bpf_get_current_pid_tgid(); long init_val = 1; @@ -137,8 +135,8 @@ int stress_percpu_hmap(struct pt_regs *ctx) return 0; } -SEC("kprobe/" SYSCALL(sys_getgid)) -int stress_hmap_alloc(struct pt_regs *ctx) +SEC("ksyscall/getgid") +int BPF_KSYSCALL(stress_hmap_alloc) { u32 key = bpf_get_current_pid_tgid(); long init_val = 1; @@ -154,8 +152,8 @@ int stress_hmap_alloc(struct pt_regs *ctx) return 0; } -SEC("kprobe/" SYSCALL(sys_getegid)) -int stress_percpu_hmap_alloc(struct pt_regs *ctx) +SEC("ksyscall/getegid") +int BPF_KSYSCALL(stress_percpu_hmap_alloc) { u32 key = bpf_get_current_pid_tgid(); long init_val = 1; @@ -170,11 +168,10 @@ int stress_percpu_hmap_alloc(struct pt_regs *ctx) } return 0; } - -SEC("kprobe/" SYSCALL(sys_connect)) -int stress_lru_hmap_alloc(struct pt_regs *ctx) +SEC("ksyscall/connect") +int BPF_KSYSCALL(stress_lru_hmap_alloc, int fd, struct sockaddr_in *uservaddr, + int addrlen) { - struct pt_regs *real_regs = (struct pt_regs *)PT_REGS_PARM1_CORE(ctx); char fmt[] = "Failed at stress_lru_hmap_alloc. ret:%dn"; union { u16 dst6[8]; @@ -187,14 +184,11 @@ int stress_lru_hmap_alloc(struct pt_regs *ctx) u32 key; }; } test_params; - struct sockaddr_in6 *in6; + struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)uservaddr; u16 test_case; - int addrlen, ret; long val = 1; u32 key = 0; - - in6 = (struct sockaddr_in6 *)PT_REGS_PARM2_CORE(real_regs); - addrlen = (int)PT_REGS_PARM3_CORE(real_regs); + int ret; if (addrlen != sizeof(*in6)) return 0; @@ -251,8 +245,8 @@ done: return 0; } -SEC("kprobe/" SYSCALL(sys_gettid)) -int stress_lpm_trie_map_alloc(struct pt_regs *ctx) +SEC("ksyscall/gettid") +int BPF_KSYSCALL(stress_lpm_trie_map_alloc) { union { u32 b32[2]; @@ -273,8 +267,8 @@ int stress_lpm_trie_map_alloc(struct pt_regs *ctx) return 0; } -SEC("kprobe/" SYSCALL(sys_getpgid)) -int stress_hash_map_lookup(struct pt_regs *ctx) +SEC("ksyscall/getpgid") +int BPF_KSYSCALL(stress_hash_map_lookup) { u32 key = 1, i; long *value; @@ -286,8 +280,8 @@ int stress_hash_map_lookup(struct pt_regs *ctx) return 0; } -SEC("kprobe/" SYSCALL(sys_getppid)) -int stress_array_map_lookup(struct pt_regs *ctx) +SEC("ksyscall/getppid") +int BPF_KSYSCALL(stress_array_map_lookup) { u32 key = 1, i; long *value; diff --git a/samples/bpf/map_perf_test_user.c b/samples/bpf/map_perf_test_user.c index 1bb53f4b29e1..07ff471ed6ae 100644 --- a/samples/bpf/map_perf_test_user.c +++ b/samples/bpf/map_perf_test_user.c @@ -370,7 +370,7 @@ static void run_perf_test(int tasks) static void fill_lpm_trie(void) { - struct bpf_lpm_trie_key *key; + struct bpf_lpm_trie_key_u8 *key; unsigned long value = 0; unsigned int i; int r; @@ -443,7 +443,7 @@ int main(int argc, char **argv) if (argc > 4) max_cnt = atoi(argv[4]); - 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/net_shared.h b/samples/bpf/net_shared.h new file mode 100644 index 000000000000..88cc52461c98 --- /dev/null +++ b/samples/bpf/net_shared.h @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0 +#ifndef _NET_SHARED_H +#define _NET_SHARED_H + +#define AF_INET 2 +#define AF_INET6 10 + +#define ETH_ALEN 6 +#define ETH_P_802_3_MIN 0x0600 +#define ETH_P_8021Q 0x8100 +#define ETH_P_8021AD 0x88A8 +#define ETH_P_IP 0x0800 +#define ETH_P_IPV6 0x86DD +#define ETH_P_ARP 0x0806 +#define IPPROTO_ICMPV6 58 + +#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) +#define bpf_htons(x) __builtin_bswap16(x) +#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \ + __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define bpf_ntohs(x) (x) +#define bpf_htons(x) (x) +#else +# error "Endianness detection needs to be set up for your compiler?!" +#endif + +#endif diff --git a/samples/bpf/offwaketime_kern.c b/samples/bpf/offwaketime.bpf.c index eb4d94742e6b..4a65ba76c1b1 100644 --- a/samples/bpf/offwaketime_kern.c +++ b/samples/bpf/offwaketime.bpf.c @@ -4,20 +4,15 @@ * modify it under the terms of version 2 of the GNU General Public * License as published by the Free Software Foundation. */ -#include <uapi/linux/bpf.h> -#include <uapi/linux/ptrace.h> -#include <uapi/linux/perf_event.h> +#include "vmlinux.h" #include <linux/version.h> -#include <linux/sched.h> #include <bpf/bpf_helpers.h> #include <bpf/bpf_tracing.h> +#include <bpf/bpf_core_read.h> -#define _(P) \ - ({ \ - typeof(P) val; \ - bpf_probe_read_kernel(&val, sizeof(val), &(P)); \ - val; \ - }) +#ifndef PERF_MAX_STACK_DEPTH +#define PERF_MAX_STACK_DEPTH 127 +#endif #define MINBLOCK_US 1 #define MAX_ENTRIES 10000 @@ -67,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); @@ -110,29 +103,19 @@ static inline int update_counts(void *ctx, u32 pid, u64 delta) } #if 1 -/* taken from /sys/kernel/debug/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; -}; +/* taken from /sys/kernel/tracing/events/sched/sched_switch/format */ 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; #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); + 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/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/sampleip_user.c b/samples/bpf/sampleip_user.c index 921c505bb567..9283f47844fb 100644 --- a/samples/bpf/sampleip_user.c +++ b/samples/bpf/sampleip_user.c @@ -21,10 +21,10 @@ #define DEFAULT_FREQ 99 #define DEFAULT_SECS 5 #define MAX_IPS 8192 -#define PAGE_OFFSET 0xffff880000000000 static int map_fd; static int nr_cpus; +static long _text_addr; static void usage(void) { @@ -108,7 +108,7 @@ static void print_ip_map(int fd) /* sort and print */ qsort(counts, max, sizeof(struct ipcount), count_cmp); for (i = 0; i < max; i++) { - if (counts[i].ip > PAGE_OFFSET) { + if (counts[i].ip > _text_addr) { sym = ksym_search(counts[i].ip); if (!sym) { printf("ksym not found. Is kallsyms loaded?\n"); @@ -169,6 +169,13 @@ int main(int argc, char **argv) return 2; } + /* used to determine whether the address is kernel space */ + _text_addr = ksym_get_addr("_text"); + if (!_text_addr) { + fprintf(stderr, "ERROR: no '_text' in /proc/kallsyms\n"); + return 3; + } + /* create perf FDs for each CPU */ nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); links = calloc(nr_cpus, sizeof(struct bpf_link *)); diff --git a/samples/bpf/sock_flags_kern.c b/samples/bpf/sock_flags_kern.c deleted file mode 100644 index 6d0ac7569d6f..000000000000 --- a/samples/bpf/sock_flags_kern.c +++ /dev/null @@ -1,49 +0,0 @@ -#include <uapi/linux/bpf.h> -#include <linux/socket.h> -#include <linux/net.h> -#include <uapi/linux/in.h> -#include <uapi/linux/in6.h> -#include <bpf/bpf_helpers.h> - -SEC("cgroup/sock1") -int bpf_prog1(struct bpf_sock *sk) -{ - char fmt[] = "socket: family %d type %d protocol %d\n"; - char fmt2[] = "socket: uid %u gid %u\n"; - __u64 gid_uid = bpf_get_current_uid_gid(); - __u32 uid = gid_uid & 0xffffffff; - __u32 gid = gid_uid >> 32; - - bpf_trace_printk(fmt, sizeof(fmt), sk->family, sk->type, sk->protocol); - bpf_trace_printk(fmt2, sizeof(fmt2), uid, gid); - - /* block PF_INET6, SOCK_RAW, IPPROTO_ICMPV6 sockets - * ie., make ping6 fail - */ - if (sk->family == PF_INET6 && - sk->type == SOCK_RAW && - sk->protocol == IPPROTO_ICMPV6) - return 0; - - return 1; -} - -SEC("cgroup/sock2") -int bpf_prog2(struct bpf_sock *sk) -{ - char fmt[] = "socket: family %d type %d protocol %d\n"; - - bpf_trace_printk(fmt, sizeof(fmt), sk->family, sk->type, sk->protocol); - - /* block PF_INET, SOCK_RAW, IPPROTO_ICMP sockets - * ie., make ping fail - */ - if (sk->family == PF_INET && - sk->type == SOCK_RAW && - sk->protocol == IPPROTO_ICMP) - return 0; - - return 1; -} - -char _license[] SEC("license") = "GPL"; diff --git a/samples/bpf/sockex2_kern.c b/samples/bpf/sockex2_kern.c index b7997541f7ee..f93d9145ab8a 100644 --- a/samples/bpf/sockex2_kern.c +++ b/samples/bpf/sockex2_kern.c @@ -31,7 +31,6 @@ static inline int proto_ports_offset(__u64 proto) switch (proto) { case IPPROTO_TCP: case IPPROTO_UDP: - case IPPROTO_DCCP: case IPPROTO_ESP: case IPPROTO_SCTP: case IPPROTO_UDPLITE: diff --git a/samples/bpf/spintest_kern.c b/samples/bpf/spintest.bpf.c index 455da77319d9..cba5a9d50783 100644 --- a/samples/bpf/spintest_kern.c +++ b/samples/bpf/spintest.bpf.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 <linux/skbuff.h> -#include <linux/netdevice.h> +#include "vmlinux.h" #include <linux/version.h> -#include <uapi/linux/bpf.h> -#include <uapi/linux/perf_event.h> #include <bpf/bpf_helpers.h> #include <bpf/bpf_tracing.h> +#ifndef PERF_MAX_STACK_DEPTH +#define PERF_MAX_STACK_DEPTH 127 +#endif + struct { __uint(type, BPF_MAP_TYPE_HASH); __type(key, long); @@ -46,20 +47,10 @@ 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) SEC("kprobe/__htab_percpu_map_update_elem")PROG(p16) diff --git a/samples/bpf/spintest_user.c b/samples/bpf/spintest_user.c index aadac14f748a..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()) { @@ -23,7 +22,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"); @@ -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++) { diff --git a/samples/bpf/syscall_nrs.c b/samples/bpf/syscall_nrs.c index 88f940052450..a6e600f3d477 100644 --- a/samples/bpf/syscall_nrs.c +++ b/samples/bpf/syscall_nrs.c @@ -2,6 +2,9 @@ #include <uapi/linux/unistd.h> #include <linux/kbuild.h> +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + #define SYSNR(_NR) DEFINE(SYS ## _NR, _NR) void syscall_defines(void) @@ -17,3 +20,5 @@ void syscall_defines(void) #endif } + +#pragma GCC diagnostic pop diff --git a/samples/bpf/syscall_tp_kern.c b/samples/bpf/syscall_tp_kern.c index 50231c2eff9c..58fef969a60e 100644 --- a/samples/bpf/syscall_tp_kern.c +++ b/samples/bpf/syscall_tp_kern.c @@ -4,6 +4,7 @@ #include <uapi/linux/bpf.h> #include <bpf/bpf_helpers.h> +#if !defined(__aarch64__) struct syscalls_enter_open_args { unsigned long long unused; long syscall_nr; @@ -11,6 +12,7 @@ struct syscalls_enter_open_args { long flags; long mode; }; +#endif struct syscalls_exit_open_args { unsigned long long unused; @@ -18,6 +20,15 @@ struct syscalls_exit_open_args { long ret; }; +struct syscalls_enter_open_at_args { + unsigned long long unused; + long syscall_nr; + long long dfd; + long filename_ptr; + long flags; + long mode; +}; + struct { __uint(type, BPF_MAP_TYPE_ARRAY); __type(key, u32); @@ -44,26 +55,37 @@ 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) +int trace_enter_open_at(struct syscalls_enter_open_at_args *ctx) { count(&enter_open_map); return 0; } +SEC("tracepoint/syscalls/sys_enter_openat2") +int trace_enter_open_at2(struct syscalls_enter_open_at_args *ctx) +{ + count(&enter_open_map); + 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) @@ -71,3 +93,10 @@ int trace_enter_exit_at(struct syscalls_exit_open_args *ctx) count(&exit_open_map); return 0; } + +SEC("tracepoint/syscalls/sys_exit_openat2") +int trace_enter_exit_at2(struct syscalls_exit_open_args *ctx) +{ + count(&exit_open_map); + return 0; +} diff --git a/samples/bpf/syscall_tp_user.c b/samples/bpf/syscall_tp_user.c index 7a788bb837fc..7a09ac74fac0 100644 --- a/samples/bpf/syscall_tp_user.c +++ b/samples/bpf/syscall_tp_user.c @@ -17,9 +17,9 @@ static void usage(const char *cmd) { - printf("USAGE: %s [-i num_progs] [-h]\n", cmd); - printf(" -i num_progs # number of progs of the test\n"); - printf(" -h # help\n"); + printf("USAGE: %s [-i nr_tests] [-h]\n", cmd); + printf(" -i nr_tests # rounds of test to run\n"); + printf(" -h # help\n"); } static void verify_map(int map_id) @@ -45,14 +45,14 @@ static void verify_map(int map_id) } } -static int test(char *filename, int num_progs) +static int test(char *filename, int nr_tests) { - int map0_fds[num_progs], map1_fds[num_progs], fd, i, j = 0; - struct bpf_link *links[num_progs * 4]; - struct bpf_object *objs[num_progs]; + int map0_fds[nr_tests], map1_fds[nr_tests], fd, i, j = 0; + struct bpf_link **links = NULL; + struct bpf_object *objs[nr_tests]; struct bpf_program *prog; - for (i = 0; i < num_progs; i++) { + for (i = 0; i < nr_tests; i++) { objs[i] = bpf_object__open_file(filename, NULL); if (libbpf_get_error(objs[i])) { fprintf(stderr, "opening BPF object file failed\n"); @@ -60,6 +60,19 @@ static int test(char *filename, int num_progs) goto cleanup; } + /* One-time initialization */ + if (!links) { + int nr_progs = 0; + + bpf_object__for_each_program(prog, objs[i]) + nr_progs += 1; + + links = calloc(nr_progs * nr_tests, sizeof(struct bpf_link *)); + + if (!links) + goto cleanup; + } + /* load BPF program */ if (bpf_object__load(objs[i])) { fprintf(stderr, "loading BPF object file failed\n"); @@ -101,14 +114,18 @@ static int test(char *filename, int num_progs) close(fd); /* verify the map */ - for (i = 0; i < num_progs; i++) { + for (i = 0; i < nr_tests; i++) { verify_map(map0_fds[i]); verify_map(map1_fds[i]); } cleanup: - for (j--; j >= 0; j--) - bpf_link__destroy(links[j]); + if (links) { + for (j--; j >= 0; j--) + bpf_link__destroy(links[j]); + + free(links); + } for (i--; i >= 0; i--) bpf_object__close(objs[i]); @@ -117,13 +134,13 @@ cleanup: int main(int argc, char **argv) { - int opt, num_progs = 1; + int opt, nr_tests = 1; char filename[256]; while ((opt = getopt(argc, argv, "i:h")) != -1) { switch (opt) { case 'i': - num_progs = atoi(optarg); + nr_tests = atoi(optarg); break; case 'h': default: @@ -134,5 +151,5 @@ int main(int argc, char **argv) snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); - return test(filename, num_progs); + return test(filename, nr_tests); } diff --git a/samples/bpf/task_fd_query_user.c b/samples/bpf/task_fd_query_user.c index a33d74bd3a4b..1e61f2180470 100644 --- a/samples/bpf/task_fd_query_user.c +++ b/samples/bpf/task_fd_query_user.c @@ -235,7 +235,7 @@ static int test_debug_fs_uprobe(char *binary_path, long offset, bool is_return) struct bpf_link *link; ssize_t bytes; - snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/%s_events", + snprintf(buf, sizeof(buf), "/sys/kernel/tracing/%s_events", event_type); kfd = open(buf, O_WRONLY | O_TRUNC, 0); CHECK_PERROR_RET(kfd < 0); @@ -252,7 +252,7 @@ static int test_debug_fs_uprobe(char *binary_path, long offset, bool is_return) close(kfd); kfd = -1; - snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/events/%ss/%s/id", + snprintf(buf, sizeof(buf), "/sys/kernel/tracing/events/%ss/%s/id", event_type, event_alias); efd = open(buf, O_RDONLY, 0); CHECK_PERROR_RET(efd < 0); diff --git a/samples/bpf/tc_l2_redirect.sh b/samples/bpf/tc_l2_redirect.sh index 37d95ef3c20f..a28a8fc99dbe 100755 --- a/samples/bpf/tc_l2_redirect.sh +++ b/samples/bpf/tc_l2_redirect.sh @@ -8,6 +8,7 @@ REDIRECT_USER='./tc_l2_redirect' REDIRECT_BPF='./tc_l2_redirect_kern.o' RP_FILTER=$(< /proc/sys/net/ipv4/conf/all/rp_filter) +IPV6_DISABLED=$(< /proc/sys/net/ipv6/conf/all/disable_ipv6) IPV6_FORWARDING=$(< /proc/sys/net/ipv6/conf/all/forwarding) function config_common { @@ -64,6 +65,7 @@ function config_common { sysctl -q -w net.ipv4.conf.all.rp_filter=0 sysctl -q -w net.ipv6.conf.all.forwarding=1 + sysctl -q -w net.ipv6.conf.all.disable_ipv6=0 } function cleanup { @@ -77,6 +79,7 @@ function cleanup { $IP link del ip6t >& /dev/null sysctl -q -w net.ipv4.conf.all.rp_filter=$RP_FILTER sysctl -q -w net.ipv6.conf.all.forwarding=$IPV6_FORWARDING + sysctl -q -w net.ipv6.conf.all.disable_ipv6=$IPV6_DISABLED rm -f /sys/fs/bpf/tc/globals/tun_iface [[ -z $DEBUG ]] || set -x set -e diff --git a/samples/bpf/tc_l2_redirect_kern.c b/samples/bpf/tc_l2_redirect_kern.c index fd2fa0004330..b19fa9b88fe0 100644 --- a/samples/bpf/tc_l2_redirect_kern.c +++ b/samples/bpf/tc_l2_redirect_kern.c @@ -58,14 +58,11 @@ static __always_inline bool is_vip_addr(__be16 eth_proto, __be32 daddr) SEC("l2_to_iptun_ingress_forward") int _l2_to_iptun_ingress_forward(struct __sk_buff *skb) { - struct bpf_tunnel_key tkey = {}; void *data = (void *)(long)skb->data; struct eth_hdr *eth = data; void *data_end = (void *)(long)skb->data_end; int key = 0, *ifindex; - int ret; - if (data + sizeof(*eth) > data_end) return TC_ACT_OK; @@ -115,8 +112,6 @@ int _l2_to_iptun_ingress_redirect(struct __sk_buff *skb) void *data_end = (void *)(long)skb->data_end; int key = 0, *ifindex; - int ret; - if (data + sizeof(*eth) > data_end) return TC_ACT_OK; @@ -205,7 +200,6 @@ int _l2_to_ip6tun_ingress_redirect(struct __sk_buff *skb) SEC("drop_non_tun_vip") int _drop_non_tun_vip(struct __sk_buff *skb) { - struct bpf_tunnel_key tkey = {}; void *data = (void *)(long)skb->data; struct eth_hdr *eth = data; void *data_end = (void *)(long)skb->data_end; diff --git a/samples/bpf/tcp_basertt_kern.c b/samples/bpf/tcp_basertt_kern.c index 8dfe09a92fec..822b0742b815 100644 --- a/samples/bpf/tcp_basertt_kern.c +++ b/samples/bpf/tcp_basertt_kern.c @@ -47,7 +47,7 @@ int bpf_basertt(struct bpf_sock_ops *skops) case BPF_SOCK_OPS_BASE_RTT: n = bpf_getsockopt(skops, SOL_TCP, TCP_CONGESTION, cong, sizeof(cong)); - if (!n && !__builtin_memcmp(cong, nv, sizeof(nv)+1)) { + if (!n && !__builtin_memcmp(cong, nv, sizeof(nv))) { /* Set base_rtt to 80us */ rv = 80; } else if (n) { diff --git a/samples/bpf/tcp_cong_kern.c b/samples/bpf/tcp_cong_kern.c index 2311fc9dde85..339415eac477 100644 --- a/samples/bpf/tcp_cong_kern.c +++ b/samples/bpf/tcp_cong_kern.c @@ -5,7 +5,7 @@ * License as published by the Free Software Foundation. * * BPF program to set congestion control to dctcp when both hosts are - * in the same datacenter (as deteremined by IPv6 prefix). + * in the same datacenter (as determined by IPv6 prefix). * * Use "bpftool cgroup attach $cg sock_ops $prog" to load this BPF program. */ diff --git a/samples/bpf/test_cgrp2_array_pin.c b/samples/bpf/test_cgrp2_array_pin.c deleted file mode 100644 index 05e88aa63009..000000000000 --- a/samples/bpf/test_cgrp2_array_pin.c +++ /dev/null @@ -1,106 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2016 Facebook - */ -#include <linux/unistd.h> -#include <linux/bpf.h> - -#include <stdio.h> -#include <stdint.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> -#include <fcntl.h> - -#include <bpf/bpf.h> - -static void usage(void) -{ - printf("Usage: test_cgrp2_array_pin [...]\n"); - printf(" -F <file> File to pin an BPF cgroup array\n"); - printf(" -U <file> Update an already pinned BPF cgroup array\n"); - printf(" -v <value> Full path of the cgroup2\n"); - printf(" -h Display this help\n"); -} - -int main(int argc, char **argv) -{ - const char *pinned_file = NULL, *cg2 = NULL; - int create_array = 1; - int array_key = 0; - int array_fd = -1; - int cg2_fd = -1; - int ret = -1; - int opt; - - while ((opt = getopt(argc, argv, "F:U:v:")) != -1) { - switch (opt) { - /* General args */ - case 'F': - pinned_file = optarg; - break; - case 'U': - pinned_file = optarg; - create_array = 0; - break; - case 'v': - cg2 = optarg; - break; - default: - usage(); - goto out; - } - } - - if (!cg2 || !pinned_file) { - usage(); - goto out; - } - - cg2_fd = open(cg2, O_RDONLY); - if (cg2_fd < 0) { - fprintf(stderr, "open(%s,...): %s(%d)\n", - cg2, strerror(errno), errno); - goto out; - } - - if (create_array) { - array_fd = bpf_map_create(BPF_MAP_TYPE_CGROUP_ARRAY, NULL, - sizeof(uint32_t), sizeof(uint32_t), - 1, NULL); - if (array_fd < 0) { - fprintf(stderr, - "bpf_create_map(BPF_MAP_TYPE_CGROUP_ARRAY,...): %s(%d)\n", - strerror(errno), errno); - goto out; - } - } else { - array_fd = bpf_obj_get(pinned_file); - if (array_fd < 0) { - fprintf(stderr, "bpf_obj_get(%s): %s(%d)\n", - pinned_file, strerror(errno), errno); - goto out; - } - } - - ret = bpf_map_update_elem(array_fd, &array_key, &cg2_fd, 0); - if (ret) { - perror("bpf_map_update_elem"); - goto out; - } - - if (create_array) { - ret = bpf_obj_pin(array_fd, pinned_file); - if (ret) { - fprintf(stderr, "bpf_obj_pin(..., %s): %s(%d)\n", - pinned_file, strerror(errno), errno); - goto out; - } - } - -out: - if (array_fd != -1) - close(array_fd); - if (cg2_fd != -1) - close(cg2_fd); - return ret; -} diff --git a/samples/bpf/test_cgrp2_attach.c b/samples/bpf/test_cgrp2_attach.c deleted file mode 100644 index 68ce69457afe..000000000000 --- a/samples/bpf/test_cgrp2_attach.c +++ /dev/null @@ -1,177 +0,0 @@ -/* eBPF example program: - * - * - Creates arraymap in kernel with 4 bytes keys and 8 byte values - * - * - Loads eBPF program - * - * The eBPF program accesses the map passed in to store two pieces of - * information. The number of invocations of the program, which maps - * to the number of packets received, is stored to key 0. Key 1 is - * incremented on each iteration by the number of bytes stored in - * the skb. - * - * - Attaches the new program to a cgroup using BPF_PROG_ATTACH - * - * - Every second, reads map[0] and map[1] to see how many bytes and - * packets were seen on any socket of tasks in the given cgroup. - */ - -#define _GNU_SOURCE - -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <string.h> -#include <unistd.h> -#include <assert.h> -#include <errno.h> -#include <fcntl.h> - -#include <linux/bpf.h> -#include <bpf/bpf.h> - -#include "bpf_insn.h" -#include "bpf_util.h" - -enum { - MAP_KEY_PACKETS, - MAP_KEY_BYTES, -}; - -char bpf_log_buf[BPF_LOG_BUF_SIZE]; - -static int prog_load(int map_fd, int verdict) -{ - struct bpf_insn prog[] = { - BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), /* save r6 so it's not clobbered by BPF_CALL */ - - /* Count packets */ - BPF_MOV64_IMM(BPF_REG_0, MAP_KEY_PACKETS), /* r0 = 0 */ - BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4), /* *(u32 *)(fp - 4) = r0 */ - BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), - BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4), /* r2 = fp - 4 */ - BPF_LD_MAP_FD(BPF_REG_1, map_fd), /* load map fd to r1 */ - BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), - BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), - BPF_MOV64_IMM(BPF_REG_1, 1), /* r1 = 1 */ - BPF_ATOMIC_OP(BPF_DW, BPF_ADD, BPF_REG_0, BPF_REG_1, 0), - - /* Count bytes */ - BPF_MOV64_IMM(BPF_REG_0, MAP_KEY_BYTES), /* r0 = 1 */ - BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4), /* *(u32 *)(fp - 4) = r0 */ - BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), - BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4), /* r2 = fp - 4 */ - BPF_LD_MAP_FD(BPF_REG_1, map_fd), - BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), - BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), - BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_6, offsetof(struct __sk_buff, len)), /* r1 = skb->len */ - - BPF_ATOMIC_OP(BPF_DW, BPF_ADD, BPF_REG_0, BPF_REG_1, 0), - - BPF_MOV64_IMM(BPF_REG_0, verdict), /* r0 = verdict */ - BPF_EXIT_INSN(), - }; - size_t insns_cnt = ARRAY_SIZE(prog); - LIBBPF_OPTS(bpf_prog_load_opts, opts, - .log_buf = bpf_log_buf, - .log_size = BPF_LOG_BUF_SIZE, - ); - - return bpf_prog_load(BPF_PROG_TYPE_CGROUP_SKB, NULL, "GPL", - prog, insns_cnt, &opts); -} - -static int usage(const char *argv0) -{ - printf("Usage: %s [-d] [-D] <cg-path> <egress|ingress>\n", argv0); - printf(" -d Drop Traffic\n"); - printf(" -D Detach filter, and exit\n"); - return EXIT_FAILURE; -} - -static int attach_filter(int cg_fd, int type, int verdict) -{ - int prog_fd, map_fd, ret, key; - long long pkt_cnt, byte_cnt; - - map_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, NULL, - sizeof(key), sizeof(byte_cnt), - 256, NULL); - if (map_fd < 0) { - printf("Failed to create map: '%s'\n", strerror(errno)); - return EXIT_FAILURE; - } - - prog_fd = prog_load(map_fd, verdict); - printf("Output from kernel verifier:\n%s\n-------\n", bpf_log_buf); - - if (prog_fd < 0) { - printf("Failed to load prog: '%s'\n", strerror(errno)); - return EXIT_FAILURE; - } - - ret = bpf_prog_attach(prog_fd, cg_fd, type, 0); - if (ret < 0) { - printf("Failed to attach prog to cgroup: '%s'\n", - strerror(errno)); - return EXIT_FAILURE; - } - while (1) { - key = MAP_KEY_PACKETS; - assert(bpf_map_lookup_elem(map_fd, &key, &pkt_cnt) == 0); - - key = MAP_KEY_BYTES; - assert(bpf_map_lookup_elem(map_fd, &key, &byte_cnt) == 0); - - printf("cgroup received %lld packets, %lld bytes\n", - pkt_cnt, byte_cnt); - sleep(1); - } - - return EXIT_SUCCESS; -} - -int main(int argc, char **argv) -{ - int detach_only = 0, verdict = 1; - enum bpf_attach_type type; - int opt, cg_fd, ret; - - while ((opt = getopt(argc, argv, "Dd")) != -1) { - switch (opt) { - case 'd': - verdict = 0; - break; - case 'D': - detach_only = 1; - break; - default: - return usage(argv[0]); - } - } - - if (argc - optind < 2) - return usage(argv[0]); - - if (strcmp(argv[optind + 1], "ingress") == 0) - type = BPF_CGROUP_INET_INGRESS; - else if (strcmp(argv[optind + 1], "egress") == 0) - type = BPF_CGROUP_INET_EGRESS; - else - return usage(argv[0]); - - cg_fd = open(argv[optind], O_DIRECTORY | O_RDONLY); - if (cg_fd < 0) { - printf("Failed to open cgroup path: '%s'\n", strerror(errno)); - return EXIT_FAILURE; - } - - if (detach_only) { - ret = bpf_prog_detach(cg_fd, type); - printf("bpf_prog_detach() returned '%s' (%d)\n", - strerror(errno), errno); - } else - ret = attach_filter(cg_fd, type, verdict); - - return ret; -} diff --git a/samples/bpf/test_cgrp2_sock.c b/samples/bpf/test_cgrp2_sock.c deleted file mode 100644 index a0811df888f4..000000000000 --- a/samples/bpf/test_cgrp2_sock.c +++ /dev/null @@ -1,294 +0,0 @@ -/* eBPF example program: - * - * - Loads eBPF program - * - * The eBPF program sets the sk_bound_dev_if index in new AF_INET{6} - * sockets opened by processes in the cgroup. - * - * - Attaches the new program to a cgroup using BPF_PROG_ATTACH - */ - -#define _GNU_SOURCE - -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <string.h> -#include <unistd.h> -#include <assert.h> -#include <errno.h> -#include <fcntl.h> -#include <net/if.h> -#include <inttypes.h> -#include <linux/bpf.h> -#include <bpf/bpf.h> - -#include "bpf_insn.h" - -char bpf_log_buf[BPF_LOG_BUF_SIZE]; - -static int prog_load(__u32 idx, __u32 mark, __u32 prio) -{ - /* save pointer to context */ - struct bpf_insn prog_start[] = { - BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), - }; - struct bpf_insn prog_end[] = { - BPF_MOV64_IMM(BPF_REG_0, 1), /* r0 = verdict */ - BPF_EXIT_INSN(), - }; - - /* set sk_bound_dev_if on socket */ - struct bpf_insn prog_dev[] = { - BPF_MOV64_IMM(BPF_REG_3, idx), - BPF_MOV64_IMM(BPF_REG_2, offsetof(struct bpf_sock, bound_dev_if)), - BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3, offsetof(struct bpf_sock, bound_dev_if)), - }; - - /* set mark on socket */ - struct bpf_insn prog_mark[] = { - /* get uid of process */ - BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, - BPF_FUNC_get_current_uid_gid), - BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xffffffff), - - /* if uid is 0, use given mark, else use the uid as the mark */ - BPF_MOV64_REG(BPF_REG_3, BPF_REG_0), - BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), - BPF_MOV64_IMM(BPF_REG_3, mark), - - /* set the mark on the new socket */ - BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), - BPF_MOV64_IMM(BPF_REG_2, offsetof(struct bpf_sock, mark)), - BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3, offsetof(struct bpf_sock, mark)), - }; - - /* set priority on socket */ - struct bpf_insn prog_prio[] = { - BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), - BPF_MOV64_IMM(BPF_REG_3, prio), - BPF_MOV64_IMM(BPF_REG_2, offsetof(struct bpf_sock, priority)), - BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3, offsetof(struct bpf_sock, priority)), - }; - LIBBPF_OPTS(bpf_prog_load_opts, opts, - .log_buf = bpf_log_buf, - .log_size = BPF_LOG_BUF_SIZE, - ); - - struct bpf_insn *prog; - size_t insns_cnt; - void *p; - int ret; - - insns_cnt = sizeof(prog_start) + sizeof(prog_end); - if (idx) - insns_cnt += sizeof(prog_dev); - - if (mark) - insns_cnt += sizeof(prog_mark); - - if (prio) - insns_cnt += sizeof(prog_prio); - - p = prog = malloc(insns_cnt); - if (!prog) { - fprintf(stderr, "Failed to allocate memory for instructions\n"); - return EXIT_FAILURE; - } - - memcpy(p, prog_start, sizeof(prog_start)); - p += sizeof(prog_start); - - if (idx) { - memcpy(p, prog_dev, sizeof(prog_dev)); - p += sizeof(prog_dev); - } - - if (mark) { - memcpy(p, prog_mark, sizeof(prog_mark)); - p += sizeof(prog_mark); - } - - if (prio) { - memcpy(p, prog_prio, sizeof(prog_prio)); - p += sizeof(prog_prio); - } - - memcpy(p, prog_end, sizeof(prog_end)); - p += sizeof(prog_end); - - insns_cnt /= sizeof(struct bpf_insn); - - ret = bpf_prog_load(BPF_PROG_TYPE_CGROUP_SOCK, NULL, "GPL", - prog, insns_cnt, &opts); - - free(prog); - - return ret; -} - -static int get_bind_to_device(int sd, char *name, size_t len) -{ - socklen_t optlen = len; - int rc; - - name[0] = '\0'; - rc = getsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, name, &optlen); - if (rc < 0) - perror("setsockopt(SO_BINDTODEVICE)"); - - return rc; -} - -static unsigned int get_somark(int sd) -{ - unsigned int mark = 0; - socklen_t optlen = sizeof(mark); - int rc; - - rc = getsockopt(sd, SOL_SOCKET, SO_MARK, &mark, &optlen); - if (rc < 0) - perror("getsockopt(SO_MARK)"); - - return mark; -} - -static unsigned int get_priority(int sd) -{ - unsigned int prio = 0; - socklen_t optlen = sizeof(prio); - int rc; - - rc = getsockopt(sd, SOL_SOCKET, SO_PRIORITY, &prio, &optlen); - if (rc < 0) - perror("getsockopt(SO_PRIORITY)"); - - return prio; -} - -static int show_sockopts(int family) -{ - unsigned int mark, prio; - char name[16]; - int sd; - - sd = socket(family, SOCK_DGRAM, 17); - if (sd < 0) { - perror("socket"); - return 1; - } - - if (get_bind_to_device(sd, name, sizeof(name)) < 0) - return 1; - - mark = get_somark(sd); - prio = get_priority(sd); - - close(sd); - - printf("sd %d: dev %s, mark %u, priority %u\n", sd, name, mark, prio); - - return 0; -} - -static int usage(const char *argv0) -{ - printf("Usage:\n"); - printf(" Attach a program\n"); - printf(" %s -b bind-to-dev -m mark -p prio cg-path\n", argv0); - printf("\n"); - printf(" Detach a program\n"); - printf(" %s -d cg-path\n", argv0); - printf("\n"); - printf(" Show inherited socket settings (mark, priority, and device)\n"); - printf(" %s [-6]\n", argv0); - return EXIT_FAILURE; -} - -int main(int argc, char **argv) -{ - __u32 idx = 0, mark = 0, prio = 0; - const char *cgrp_path = NULL; - int cg_fd, prog_fd, ret; - int family = PF_INET; - int do_attach = 1; - int rc; - - while ((rc = getopt(argc, argv, "db:m:p:6")) != -1) { - switch (rc) { - case 'd': - do_attach = 0; - break; - case 'b': - idx = if_nametoindex(optarg); - if (!idx) { - idx = strtoumax(optarg, NULL, 0); - if (!idx) { - printf("Invalid device name\n"); - return EXIT_FAILURE; - } - } - break; - case 'm': - mark = strtoumax(optarg, NULL, 0); - break; - case 'p': - prio = strtoumax(optarg, NULL, 0); - break; - case '6': - family = PF_INET6; - break; - default: - return usage(argv[0]); - } - } - - if (optind == argc) - return show_sockopts(family); - - cgrp_path = argv[optind]; - if (!cgrp_path) { - fprintf(stderr, "cgroup path not given\n"); - return EXIT_FAILURE; - } - - if (do_attach && !idx && !mark && !prio) { - fprintf(stderr, - "One of device, mark or priority must be given\n"); - return EXIT_FAILURE; - } - - cg_fd = open(cgrp_path, O_DIRECTORY | O_RDONLY); - if (cg_fd < 0) { - printf("Failed to open cgroup path: '%s'\n", strerror(errno)); - return EXIT_FAILURE; - } - - if (do_attach) { - prog_fd = prog_load(idx, mark, prio); - if (prog_fd < 0) { - printf("Failed to load prog: '%s'\n", strerror(errno)); - printf("Output from kernel verifier:\n%s\n-------\n", - bpf_log_buf); - return EXIT_FAILURE; - } - - ret = bpf_prog_attach(prog_fd, cg_fd, - BPF_CGROUP_INET_SOCK_CREATE, 0); - if (ret < 0) { - printf("Failed to attach prog to cgroup: '%s'\n", - strerror(errno)); - return EXIT_FAILURE; - } - } else { - ret = bpf_prog_detach(cg_fd, BPF_CGROUP_INET_SOCK_CREATE); - if (ret < 0) { - printf("Failed to detach prog from cgroup: '%s'\n", - strerror(errno)); - return EXIT_FAILURE; - } - } - - close(cg_fd); - return EXIT_SUCCESS; -} diff --git a/samples/bpf/test_cgrp2_sock.sh b/samples/bpf/test_cgrp2_sock.sh deleted file mode 100755 index 9f6174236856..000000000000 --- a/samples/bpf/test_cgrp2_sock.sh +++ /dev/null @@ -1,135 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: GPL-2.0 - -# Test various socket options that can be set by attaching programs to cgroups. - -CGRP_MNT="/tmp/cgroupv2-test_cgrp2_sock" - -################################################################################ -# -print_result() -{ - local rc=$1 - local status=" OK " - - [ $rc -ne 0 ] && status="FAIL" - - printf "%-50s [%4s]\n" "$2" "$status" -} - -check_sock() -{ - out=$(test_cgrp2_sock) - echo $out | grep -q "$1" - if [ $? -ne 0 ]; then - print_result 1 "IPv4: $2" - echo " expected: $1" - echo " have: $out" - rc=1 - else - print_result 0 "IPv4: $2" - fi -} - -check_sock6() -{ - out=$(test_cgrp2_sock -6) - echo $out | grep -q "$1" - if [ $? -ne 0 ]; then - print_result 1 "IPv6: $2" - echo " expected: $1" - echo " have: $out" - rc=1 - else - print_result 0 "IPv6: $2" - fi -} - -################################################################################ -# - -cleanup() -{ - echo $$ >> ${CGRP_MNT}/cgroup.procs - rmdir ${CGRP_MNT}/sockopts -} - -cleanup_and_exit() -{ - local rc=$1 - local msg="$2" - - [ -n "$msg" ] && echo "ERROR: $msg" - - test_cgrp2_sock -d ${CGRP_MNT}/sockopts - ip li del cgrp2_sock - umount ${CGRP_MNT} - - exit $rc -} - - -################################################################################ -# main - -rc=0 - -ip li add cgrp2_sock type dummy 2>/dev/null - -set -e -mkdir -p ${CGRP_MNT} -mount -t cgroup2 none ${CGRP_MNT} -set +e - - -# make sure we have a known start point -cleanup 2>/dev/null - -mkdir -p ${CGRP_MNT}/sockopts -[ $? -ne 0 ] && cleanup_and_exit 1 "Failed to create cgroup hierarchy" - - -# set pid into cgroup -echo $$ > ${CGRP_MNT}/sockopts/cgroup.procs - -# no bpf program attached, so socket should show no settings -check_sock "dev , mark 0, priority 0" "No programs attached" -check_sock6 "dev , mark 0, priority 0" "No programs attached" - -# verify device is set -# -test_cgrp2_sock -b cgrp2_sock ${CGRP_MNT}/sockopts -if [ $? -ne 0 ]; then - cleanup_and_exit 1 "Failed to install program to set device" -fi -check_sock "dev cgrp2_sock, mark 0, priority 0" "Device set" -check_sock6 "dev cgrp2_sock, mark 0, priority 0" "Device set" - -# verify mark is set -# -test_cgrp2_sock -m 666 ${CGRP_MNT}/sockopts -if [ $? -ne 0 ]; then - cleanup_and_exit 1 "Failed to install program to set mark" -fi -check_sock "dev , mark 666, priority 0" "Mark set" -check_sock6 "dev , mark 666, priority 0" "Mark set" - -# verify priority is set -# -test_cgrp2_sock -p 123 ${CGRP_MNT}/sockopts -if [ $? -ne 0 ]; then - cleanup_and_exit 1 "Failed to install program to set priority" -fi -check_sock "dev , mark 0, priority 123" "Priority set" -check_sock6 "dev , mark 0, priority 123" "Priority set" - -# all 3 at once -# -test_cgrp2_sock -b cgrp2_sock -m 666 -p 123 ${CGRP_MNT}/sockopts -if [ $? -ne 0 ]; then - cleanup_and_exit 1 "Failed to install program to set device, mark and priority" -fi -check_sock "dev cgrp2_sock, mark 666, priority 123" "Priority set" -check_sock6 "dev cgrp2_sock, mark 666, priority 123" "Priority set" - -cleanup_and_exit $rc diff --git a/samples/bpf/test_cgrp2_sock2.c b/samples/bpf/test_cgrp2_sock2.c deleted file mode 100644 index e7060aaa2f5a..000000000000 --- a/samples/bpf/test_cgrp2_sock2.c +++ /dev/null @@ -1,95 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* eBPF example program: - * - * - Loads eBPF program - * - * The eBPF program loads a filter from file and attaches the - * program to a cgroup using BPF_PROG_ATTACH - */ - -#define _GNU_SOURCE - -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <string.h> -#include <unistd.h> -#include <assert.h> -#include <errno.h> -#include <fcntl.h> -#include <net/if.h> -#include <linux/bpf.h> -#include <bpf/bpf.h> -#include <bpf/libbpf.h> - -#include "bpf_insn.h" - -static int usage(const char *argv0) -{ - printf("Usage: %s cg-path filter-path [filter-id]\n", argv0); - return EXIT_FAILURE; -} - -int main(int argc, char **argv) -{ - int cg_fd, err, ret = EXIT_FAILURE, filter_id = 0, prog_cnt = 0; - const char *link_pin_path = "/sys/fs/bpf/test_cgrp2_sock2"; - struct bpf_link *link = NULL; - struct bpf_program *progs[2]; - struct bpf_program *prog; - struct bpf_object *obj; - - if (argc < 3) - return usage(argv[0]); - - if (argc > 3) - filter_id = atoi(argv[3]); - - cg_fd = open(argv[1], O_DIRECTORY | O_RDONLY); - if (cg_fd < 0) { - printf("Failed to open cgroup path: '%s'\n", strerror(errno)); - return ret; - } - - obj = bpf_object__open_file(argv[2], NULL); - if (libbpf_get_error(obj)) { - printf("ERROR: opening BPF object file failed\n"); - return ret; - } - - bpf_object__for_each_program(prog, obj) { - progs[prog_cnt] = prog; - prog_cnt++; - } - - if (filter_id >= prog_cnt) { - printf("Invalid program id; program not found in file\n"); - goto cleanup; - } - - /* load BPF program */ - if (bpf_object__load(obj)) { - printf("ERROR: loading BPF object file failed\n"); - goto cleanup; - } - - link = bpf_program__attach_cgroup(progs[filter_id], cg_fd); - if (libbpf_get_error(link)) { - printf("ERROR: bpf_program__attach failed\n"); - link = NULL; - goto cleanup; - } - - err = bpf_link__pin(link, link_pin_path); - if (err < 0) { - printf("ERROR: bpf_link__pin failed: %d\n", err); - goto cleanup; - } - - ret = EXIT_SUCCESS; - -cleanup: - bpf_link__destroy(link); - bpf_object__close(obj); - return ret; -} diff --git a/samples/bpf/test_cgrp2_sock2.sh b/samples/bpf/test_cgrp2_sock2.sh deleted file mode 100755 index 6a3dbe642b2b..000000000000 --- a/samples/bpf/test_cgrp2_sock2.sh +++ /dev/null @@ -1,98 +0,0 @@ -#!/bin/bash -# SPDX-License-Identifier: GPL-2.0 - -BPFFS=/sys/fs/bpf -LINK_PIN=$BPFFS/test_cgrp2_sock2 - -function config_device { - ip netns add at_ns0 - ip link add veth0 type veth peer name veth0b - ip link set veth0b up - ip link set veth0 netns at_ns0 - ip netns exec at_ns0 ip addr add 172.16.1.100/24 dev veth0 - ip netns exec at_ns0 ip addr add 2401:db00::1/64 dev veth0 nodad - ip netns exec at_ns0 ip link set dev veth0 up - ip addr add 172.16.1.101/24 dev veth0b - ip addr add 2401:db00::2/64 dev veth0b nodad -} - -function config_cgroup { - rm -rf /tmp/cgroupv2 - mkdir -p /tmp/cgroupv2 - mount -t cgroup2 none /tmp/cgroupv2 - mkdir -p /tmp/cgroupv2/foo - echo $$ >> /tmp/cgroupv2/foo/cgroup.procs -} - -function config_bpffs { - if mount | grep $BPFFS > /dev/null; then - echo "bpffs already mounted" - else - echo "bpffs not mounted. Mounting..." - mount -t bpf none $BPFFS - fi -} - -function attach_bpf { - ./test_cgrp2_sock2 /tmp/cgroupv2/foo sock_flags_kern.o $1 - [ $? -ne 0 ] && exit 1 -} - -function cleanup { - rm -rf $LINK_PIN - ip link del veth0b - ip netns delete at_ns0 - umount /tmp/cgroupv2 - rm -rf /tmp/cgroupv2 -} - -cleanup 2>/dev/null - -set -e -config_device -config_cgroup -config_bpffs -set +e - -# -# Test 1 - fail ping6 -# -attach_bpf 0 -ping -c1 -w1 172.16.1.100 -if [ $? -ne 0 ]; then - echo "ping failed when it should succeed" - cleanup - exit 1 -fi - -ping6 -c1 -w1 2401:db00::1 -if [ $? -eq 0 ]; then - echo "ping6 succeeded when it should not" - cleanup - exit 1 -fi - -rm -rf $LINK_PIN -sleep 1 # Wait for link detach - -# -# Test 2 - fail ping -# -attach_bpf 1 -ping6 -c1 -w1 2401:db00::1 -if [ $? -ne 0 ]; then - echo "ping6 failed when it should succeed" - cleanup - exit 1 -fi - -ping -c1 -w1 172.16.1.100 -if [ $? -eq 0 ]; then - echo "ping succeeded when it should not" - cleanup - exit 1 -fi - -cleanup -echo -echo "*** PASS ***" diff --git a/samples/bpf/test_cgrp2_tc.sh b/samples/bpf/test_cgrp2_tc.sh deleted file mode 100755 index 395573be6ae8..000000000000 --- a/samples/bpf/test_cgrp2_tc.sh +++ /dev/null @@ -1,185 +0,0 @@ -#!/bin/bash -# SPDX-License-Identifier: GPL-2.0 - -MY_DIR=$(dirname $0) -# Details on the bpf prog -BPF_CGRP2_ARRAY_NAME='test_cgrp2_array_pin' -BPF_PROG="$MY_DIR/test_cgrp2_tc_kern.o" -BPF_SECTION='filter' - -[ -z "$TC" ] && TC='tc' -[ -z "$IP" ] && IP='ip' - -# Names of the veth interface, net namespace...etc. -HOST_IFC='ve' -NS_IFC='vens' -NS='ns' - -find_mnt() { - cat /proc/mounts | \ - awk '{ if ($3 == "'$1'" && mnt == "") { mnt = $2 }} END { print mnt }' -} - -# Init cgroup2 vars -init_cgrp2_vars() { - CGRP2_ROOT=$(find_mnt cgroup2) - if [ -z "$CGRP2_ROOT" ] - then - CGRP2_ROOT='/mnt/cgroup2' - MOUNT_CGRP2="yes" - fi - CGRP2_TC="$CGRP2_ROOT/tc" - CGRP2_TC_LEAF="$CGRP2_TC/leaf" -} - -# Init bpf fs vars -init_bpf_fs_vars() { - local bpf_fs_root=$(find_mnt bpf) - [ -n "$bpf_fs_root" ] || return -1 - BPF_FS_TC_SHARE="$bpf_fs_root/tc/globals" -} - -setup_cgrp2() { - case $1 in - start) - if [ "$MOUNT_CGRP2" == 'yes' ] - then - [ -d $CGRP2_ROOT ] || mkdir -p $CGRP2_ROOT - mount -t cgroup2 none $CGRP2_ROOT || return $? - fi - mkdir -p $CGRP2_TC_LEAF - ;; - *) - rmdir $CGRP2_TC_LEAF && rmdir $CGRP2_TC - [ "$MOUNT_CGRP2" == 'yes' ] && umount $CGRP2_ROOT - ;; - esac -} - -setup_bpf_cgrp2_array() { - local bpf_cgrp2_array="$BPF_FS_TC_SHARE/$BPF_CGRP2_ARRAY_NAME" - case $1 in - start) - $MY_DIR/test_cgrp2_array_pin -U $bpf_cgrp2_array -v $CGRP2_TC - ;; - *) - [ -d "$BPF_FS_TC_SHARE" ] && rm -f $bpf_cgrp2_array - ;; - esac -} - -setup_net() { - case $1 in - start) - $IP link add $HOST_IFC type veth peer name $NS_IFC || return $? - $IP link set dev $HOST_IFC up || return $? - sysctl -q net.ipv6.conf.$HOST_IFC.accept_dad=0 - - $IP netns add ns || return $? - $IP link set dev $NS_IFC netns ns || return $? - $IP -n $NS link set dev $NS_IFC up || return $? - $IP netns exec $NS sysctl -q net.ipv6.conf.$NS_IFC.accept_dad=0 - $TC qdisc add dev $HOST_IFC clsact || return $? - $TC filter add dev $HOST_IFC egress bpf da obj $BPF_PROG sec $BPF_SECTION || return $? - ;; - *) - $IP netns del $NS - $IP link del $HOST_IFC - ;; - esac -} - -run_in_cgrp() { - # Fork another bash and move it under the specified cgroup. - # It makes the cgroup cleanup easier at the end of the test. - cmd='echo $$ > ' - cmd="$cmd $1/cgroup.procs; exec $2" - bash -c "$cmd" -} - -do_test() { - run_in_cgrp $CGRP2_TC_LEAF "ping -6 -c3 ff02::1%$HOST_IFC >& /dev/null" - local dropped=$($TC -s qdisc show dev $HOST_IFC | tail -3 | \ - awk '/drop/{print substr($7, 0, index($7, ",")-1)}') - if [[ $dropped -eq 0 ]] - then - echo "FAIL" - return 1 - else - echo "Successfully filtered $dropped packets" - return 0 - fi -} - -do_exit() { - if [ "$DEBUG" == "yes" ] && [ "$MODE" != 'cleanuponly' ] - then - echo "------ DEBUG ------" - echo "mount: "; mount | grep -E '(cgroup2|bpf)'; echo - echo "$CGRP2_TC_LEAF: "; ls -l $CGRP2_TC_LEAF; echo - if [ -d "$BPF_FS_TC_SHARE" ] - then - echo "$BPF_FS_TC_SHARE: "; ls -l $BPF_FS_TC_SHARE; echo - fi - echo "Host net:" - $IP netns - $IP link show dev $HOST_IFC - $IP -6 a show dev $HOST_IFC - $TC -s qdisc show dev $HOST_IFC - echo - echo "$NS net:" - $IP -n $NS link show dev $NS_IFC - $IP -n $NS -6 link show dev $NS_IFC - echo "------ DEBUG ------" - echo - fi - - if [ "$MODE" != 'nocleanup' ] - then - setup_net stop - setup_bpf_cgrp2_array stop - setup_cgrp2 stop - fi -} - -init_cgrp2_vars -init_bpf_fs_vars - -while [[ $# -ge 1 ]] -do - a="$1" - case $a in - debug) - DEBUG='yes' - shift 1 - ;; - cleanup-only) - MODE='cleanuponly' - shift 1 - ;; - no-cleanup) - MODE='nocleanup' - shift 1 - ;; - *) - echo "test_cgrp2_tc [debug] [cleanup-only | no-cleanup]" - echo " debug: Print cgrp and network setup details at the end of the test" - echo " cleanup-only: Try to cleanup things from last test. No test will be run" - echo " no-cleanup: Run the test but don't do cleanup at the end" - echo "[Note: If no arg is given, it will run the test and do cleanup at the end]" - echo - exit -1 - ;; - esac -done - -trap do_exit 0 - -[ "$MODE" == 'cleanuponly' ] && exit - -setup_cgrp2 start || exit $? -setup_net start || exit $? -init_bpf_fs_vars || exit $? -setup_bpf_cgrp2_array start || exit $? -do_test -echo diff --git a/samples/bpf/test_cgrp2_tc_kern.c b/samples/bpf/test_cgrp2_tc_kern.c deleted file mode 100644 index 4dd532a312b9..000000000000 --- a/samples/bpf/test_cgrp2_tc_kern.c +++ /dev/null @@ -1,70 +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. - */ -#define KBUILD_MODNAME "foo" -#include <uapi/linux/if_ether.h> -#include <uapi/linux/in6.h> -#include <uapi/linux/ipv6.h> -#include <uapi/linux/pkt_cls.h> -#include <uapi/linux/bpf.h> -#include <bpf/bpf_helpers.h> - -/* copy of 'struct ethhdr' without __packed */ -struct eth_hdr { - unsigned char h_dest[ETH_ALEN]; - unsigned char h_source[ETH_ALEN]; - unsigned short h_proto; -}; - -#define PIN_GLOBAL_NS 2 -struct bpf_elf_map { - __u32 type; - __u32 size_key; - __u32 size_value; - __u32 max_elem; - __u32 flags; - __u32 id; - __u32 pinning; -}; - -struct bpf_elf_map SEC("maps") test_cgrp2_array_pin = { - .type = BPF_MAP_TYPE_CGROUP_ARRAY, - .size_key = sizeof(uint32_t), - .size_value = sizeof(uint32_t), - .pinning = PIN_GLOBAL_NS, - .max_elem = 1, -}; - -SEC("filter") -int handle_egress(struct __sk_buff *skb) -{ - void *data = (void *)(long)skb->data; - struct eth_hdr *eth = data; - struct ipv6hdr *ip6h = data + sizeof(*eth); - void *data_end = (void *)(long)skb->data_end; - char dont_care_msg[] = "dont care %04x %d\n"; - char pass_msg[] = "pass\n"; - char reject_msg[] = "reject\n"; - - /* single length check */ - if (data + sizeof(*eth) + sizeof(*ip6h) > data_end) - return TC_ACT_OK; - - if (eth->h_proto != htons(ETH_P_IPV6) || - ip6h->nexthdr != IPPROTO_ICMPV6) { - bpf_trace_printk(dont_care_msg, sizeof(dont_care_msg), - eth->h_proto, ip6h->nexthdr); - return TC_ACT_OK; - } else if (bpf_skb_under_cgroup(skb, &test_cgrp2_array_pin, 0) != 1) { - bpf_trace_printk(pass_msg, sizeof(pass_msg)); - return TC_ACT_OK; - } else { - bpf_trace_printk(reject_msg, sizeof(reject_msg)); - return TC_ACT_SHOT; - } -} - -char _license[] SEC("license") = "GPL"; diff --git a/samples/bpf/test_current_task_under_cgroup_kern.c b/samples/bpf/test_current_task_under_cgroup_kern.c deleted file mode 100644 index fbd43e2bb4d3..000000000000 --- a/samples/bpf/test_current_task_under_cgroup_kern.c +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright (c) 2016 Sargun Dhillon <sargun@sargun.me> - * - * 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 <linux/ptrace.h> -#include <uapi/linux/bpf.h> -#include <linux/version.h> -#include <bpf/bpf_helpers.h> -#include <uapi/linux/utsname.h> -#include "trace_common.h" - -struct { - __uint(type, BPF_MAP_TYPE_CGROUP_ARRAY); - __uint(key_size, sizeof(u32)); - __uint(value_size, sizeof(u32)); - __uint(max_entries, 1); -} cgroup_map SEC(".maps"); - -struct { - __uint(type, BPF_MAP_TYPE_ARRAY); - __type(key, u32); - __type(value, u64); - __uint(max_entries, 1); -} perf_map SEC(".maps"); - -/* Writes the last PID that called sync to a map at index 0 */ -SEC("kprobe/" SYSCALL(sys_sync)) -int bpf_prog1(struct pt_regs *ctx) -{ - u64 pid = bpf_get_current_pid_tgid(); - int idx = 0; - - if (!bpf_current_task_under_cgroup(&cgroup_map, 0)) - return 0; - - bpf_map_update_elem(&perf_map, &idx, &pid, BPF_ANY); - return 0; -} - -char _license[] SEC("license") = "GPL"; -u32 _version SEC("version") = LINUX_VERSION_CODE; diff --git a/samples/bpf/test_current_task_under_cgroup_user.c b/samples/bpf/test_current_task_under_cgroup_user.c deleted file mode 100644 index ac251a417f45..000000000000 --- a/samples/bpf/test_current_task_under_cgroup_user.c +++ /dev/null @@ -1,113 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2016 Sargun Dhillon <sargun@sargun.me> - */ - -#define _GNU_SOURCE -#include <stdio.h> -#include <unistd.h> -#include <bpf/bpf.h> -#include <bpf/libbpf.h> -#include "cgroup_helpers.h" - -#define CGROUP_PATH "/my-cgroup" - -int main(int argc, char **argv) -{ - pid_t remote_pid, local_pid = getpid(); - struct bpf_link *link = NULL; - struct bpf_program *prog; - int cg2, idx = 0, rc = 1; - struct bpf_object *obj; - char filename[256]; - int map_fd[2]; - - snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); - obj = bpf_object__open_file(filename, NULL); - if (libbpf_get_error(obj)) { - fprintf(stderr, "ERROR: opening BPF object file failed\n"); - return 0; - } - - prog = bpf_object__find_program_by_name(obj, "bpf_prog1"); - if (!prog) { - printf("finding a prog in obj file failed\n"); - goto cleanup; - } - - /* load BPF program */ - if (bpf_object__load(obj)) { - fprintf(stderr, "ERROR: loading BPF object file failed\n"); - goto cleanup; - } - - map_fd[0] = bpf_object__find_map_fd_by_name(obj, "cgroup_map"); - map_fd[1] = bpf_object__find_map_fd_by_name(obj, "perf_map"); - if (map_fd[0] < 0 || map_fd[1] < 0) { - fprintf(stderr, "ERROR: finding a map in obj file failed\n"); - goto cleanup; - } - - link = bpf_program__attach(prog); - if (libbpf_get_error(link)) { - fprintf(stderr, "ERROR: bpf_program__attach failed\n"); - link = NULL; - goto cleanup; - } - - if (setup_cgroup_environment()) - goto err; - - cg2 = create_and_get_cgroup(CGROUP_PATH); - - if (cg2 < 0) - goto err; - - if (bpf_map_update_elem(map_fd[0], &idx, &cg2, BPF_ANY)) { - log_err("Adding target cgroup to map"); - goto err; - } - - if (join_cgroup(CGROUP_PATH)) - goto err; - - /* - * The installed helper program catched the sync call, and should - * write it to the map. - */ - - sync(); - bpf_map_lookup_elem(map_fd[1], &idx, &remote_pid); - - if (local_pid != remote_pid) { - fprintf(stderr, - "BPF Helper didn't write correct PID to map, but: %d\n", - remote_pid); - goto err; - } - - /* Verify the negative scenario; leave the cgroup */ - if (join_cgroup("/")) - goto err; - - remote_pid = 0; - bpf_map_update_elem(map_fd[1], &idx, &remote_pid, BPF_ANY); - - sync(); - bpf_map_lookup_elem(map_fd[1], &idx, &remote_pid); - - if (local_pid == remote_pid) { - fprintf(stderr, "BPF cgroup negative test did not work\n"); - goto err; - } - - rc = 0; - -err: - close(cg2); - cleanup_cgroup_environment(); - -cleanup: - bpf_link__destroy(link); - bpf_object__close(obj); - return rc; -} diff --git a/samples/bpf/test_lru_dist.c b/samples/bpf/test_lru_dist.c index 5efb91763d65..1c161276d57b 100644 --- a/samples/bpf/test_lru_dist.c +++ b/samples/bpf/test_lru_dist.c @@ -42,11 +42,6 @@ static inline void INIT_LIST_HEAD(struct list_head *list) list->prev = list; } -static inline int list_empty(const struct list_head *head) -{ - return head->next == head; -} - static inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next) diff --git a/samples/bpf/test_lwt_bpf.c b/samples/bpf/test_lwt_bpf.c index 1b568575ad11..9a13dbb81847 100644 --- a/samples/bpf/test_lwt_bpf.c +++ b/samples/bpf/test_lwt_bpf.c @@ -10,16 +10,8 @@ * General Public License for more details. */ -#include <stdint.h> -#include <stddef.h> -#include <linux/bpf.h> -#include <linux/ip.h> -#include <linux/in.h> -#include <linux/in6.h> -#include <linux/tcp.h> -#include <linux/udp.h> -#include <linux/icmpv6.h> -#include <linux/if_ether.h> +#include "vmlinux.h" +#include "net_shared.h" #include <bpf/bpf_helpers.h> #include <string.h> @@ -44,9 +36,9 @@ SEC("test_ctx") int do_test_ctx(struct __sk_buff *skb) { skb->cb[0] = CB_MAGIC; - printk("len %d hash %d protocol %d\n", skb->len, skb->hash, + printk("len %d hash %d protocol %d", skb->len, skb->hash, skb->protocol); - printk("cb %d ingress_ifindex %d ifindex %d\n", skb->cb[0], + printk("cb %d ingress_ifindex %d ifindex %d", skb->cb[0], skb->ingress_ifindex, skb->ifindex); return BPF_OK; @@ -56,9 +48,9 @@ int do_test_ctx(struct __sk_buff *skb) SEC("test_cb") int do_test_cb(struct __sk_buff *skb) { - printk("cb0: %x cb1: %x cb2: %x\n", skb->cb[0], skb->cb[1], + printk("cb0: %x cb1: %x cb2: %x", skb->cb[0], skb->cb[1], skb->cb[2]); - printk("cb3: %x cb4: %x\n", skb->cb[3], skb->cb[4]); + printk("cb3: %x cb4: %x", skb->cb[3], skb->cb[4]); return BPF_OK; } @@ -72,11 +64,11 @@ int do_test_data(struct __sk_buff *skb) struct iphdr *iph = data; if (data + sizeof(*iph) > data_end) { - printk("packet truncated\n"); + printk("packet truncated"); return BPF_DROP; } - printk("src: %x dst: %x\n", iph->saddr, iph->daddr); + printk("src: %x dst: %x", iph->saddr, iph->daddr); return BPF_OK; } @@ -97,7 +89,7 @@ static inline int rewrite(struct __sk_buff *skb, uint32_t old_ip, ret = bpf_skb_load_bytes(skb, IP_PROTO_OFF, &proto, 1); if (ret < 0) { - printk("bpf_l4_csum_replace failed: %d\n", ret); + printk("bpf_l4_csum_replace failed: %d", ret); return BPF_DROP; } @@ -120,14 +112,14 @@ static inline int rewrite(struct __sk_buff *skb, uint32_t old_ip, ret = bpf_l4_csum_replace(skb, off, old_ip, new_ip, flags | sizeof(new_ip)); if (ret < 0) { - printk("bpf_l4_csum_replace failed: %d\n"); + printk("bpf_l4_csum_replace failed: %d"); return BPF_DROP; } } ret = bpf_l3_csum_replace(skb, IP_CSUM_OFF, old_ip, new_ip, sizeof(new_ip)); if (ret < 0) { - printk("bpf_l3_csum_replace failed: %d\n", ret); + printk("bpf_l3_csum_replace failed: %d", ret); return BPF_DROP; } @@ -137,7 +129,7 @@ static inline int rewrite(struct __sk_buff *skb, uint32_t old_ip, ret = bpf_skb_store_bytes(skb, IP_SRC_OFF, &new_ip, sizeof(new_ip), 0); if (ret < 0) { - printk("bpf_skb_store_bytes() failed: %d\n", ret); + printk("bpf_skb_store_bytes() failed: %d", ret); return BPF_DROP; } @@ -153,12 +145,12 @@ int do_test_rewrite(struct __sk_buff *skb) ret = bpf_skb_load_bytes(skb, IP_DST_OFF, &old_ip, 4); if (ret < 0) { - printk("bpf_skb_load_bytes failed: %d\n", ret); + printk("bpf_skb_load_bytes failed: %d", ret); return BPF_DROP; } if (old_ip == 0x2fea8c0) { - printk("out: rewriting from %x to %x\n", old_ip, new_ip); + printk("out: rewriting from %x to %x", old_ip, new_ip); return rewrite(skb, old_ip, new_ip, 1); } @@ -173,16 +165,16 @@ static inline int __do_push_ll_and_redirect(struct __sk_buff *skb) ret = bpf_skb_change_head(skb, 14, 0); if (ret < 0) { - printk("skb_change_head() failed: %d\n", ret); + printk("skb_change_head() failed: %d", ret); } - ehdr.h_proto = __constant_htons(ETH_P_IP); + ehdr.h_proto = bpf_htons(ETH_P_IP); memcpy(&ehdr.h_source, &smac, 6); memcpy(&ehdr.h_dest, &dmac, 6); ret = bpf_skb_store_bytes(skb, 0, &ehdr, sizeof(ehdr), 0); if (ret < 0) { - printk("skb_store_bytes() failed: %d\n", ret); + printk("skb_store_bytes() failed: %d", ret); return BPF_DROP; } @@ -202,7 +194,7 @@ int do_push_ll_and_redirect(struct __sk_buff *skb) ret = __do_push_ll_and_redirect(skb); if (ret >= 0) - printk("redirected to %d\n", ifindex); + printk("redirected to %d", ifindex); return ret; } @@ -229,7 +221,7 @@ SEC("fill_garbage") int do_fill_garbage(struct __sk_buff *skb) { __fill_garbage(skb); - printk("Set initial 96 bytes of header to FF\n"); + printk("Set initial 96 bytes of header to FF"); return BPF_OK; } @@ -238,7 +230,7 @@ int do_fill_garbage_and_redirect(struct __sk_buff *skb) { int ifindex = DST_IFINDEX; __fill_garbage(skb); - printk("redirected to %d\n", ifindex); + printk("redirected to %d", ifindex); return bpf_redirect(ifindex, 0); } @@ -246,7 +238,7 @@ int do_fill_garbage_and_redirect(struct __sk_buff *skb) SEC("drop_all") int do_drop_all(struct __sk_buff *skb) { - printk("dropping with: %d\n", BPF_DROP); + printk("dropping with: %d", BPF_DROP); return BPF_DROP; } diff --git a/samples/bpf/test_lwt_bpf.sh b/samples/bpf/test_lwt_bpf.sh index 65a976058dd3..148e2df6cdce 100755 --- a/samples/bpf/test_lwt_bpf.sh +++ b/samples/bpf/test_lwt_bpf.sh @@ -19,7 +19,10 @@ IPVETH3="192.168.111.2" IP_LOCAL="192.168.99.1" -TRACE_ROOT=/sys/kernel/debug/tracing +PROG_SRC="test_lwt_bpf.c" +BPF_PROG="test_lwt_bpf.o" +TRACE_ROOT=/sys/kernel/tracing +CONTEXT_INFO=$(cat ${TRACE_ROOT}/trace_options | grep context) function lookup_mac() { @@ -36,7 +39,7 @@ function lookup_mac() function cleanup { set +ex - rm test_lwt_bpf.o 2> /dev/null + rm $BPF_PROG 2> /dev/null ip link del $VETH0 2> /dev/null ip link del $VETH1 2> /dev/null ip link del $VETH2 2> /dev/null @@ -76,7 +79,7 @@ function install_test { cleanup_routes cp /dev/null ${TRACE_ROOT}/trace - OPTS="encap bpf headroom 14 $1 obj test_lwt_bpf.o section $2 $VERBOSE" + OPTS="encap bpf headroom 14 $1 obj $BPF_PROG section $2 $VERBOSE" if [ "$1" == "in" ]; then ip route add table local local ${IP_LOCAL}/32 $OPTS dev lo @@ -96,7 +99,7 @@ function remove_prog { function filter_trace { # Add newline to allow starting EXPECT= variables on newline NL=$'\n' - echo "${NL}$*" | sed -e 's/^.*: : //g' + echo "${NL}$*" | sed -e 's/bpf_trace_printk: //g' } function expect_fail { @@ -160,11 +163,11 @@ function test_ctx_out { failure "test_ctx out: packets are dropped" } match_trace "$(get_trace)" " -len 84 hash 0 protocol 0 +len 84 hash 0 protocol 8 cb 1234 ingress_ifindex 0 ifindex 0 -len 84 hash 0 protocol 0 +len 84 hash 0 protocol 8 cb 1234 ingress_ifindex 0 ifindex 0 -len 84 hash 0 protocol 0 +len 84 hash 0 protocol 8 cb 1234 ingress_ifindex 0 ifindex 0" || exit 1 remove_prog out } @@ -367,14 +370,15 @@ setup_one_veth $NS1 $VETH0 $VETH1 $IPVETH0 $IPVETH1 $IPVETH1b setup_one_veth $NS2 $VETH2 $VETH3 $IPVETH2 $IPVETH3 ip netns exec $NS1 netserver echo 1 > ${TRACE_ROOT}/tracing_on +echo nocontext-info > ${TRACE_ROOT}/trace_options 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 test_lwt_bpf.c -o test_lwt_bpf.o +clang $CLANG_OPTS -c $PROG_SRC -o $BPF_PROG test_ctx_xmit test_ctx_out @@ -397,4 +401,5 @@ test_netperf_redirect cleanup echo 0 > ${TRACE_ROOT}/tracing_on +echo $CONTEXT_INFO > ${TRACE_ROOT}/trace_options exit 0 diff --git a/samples/bpf/test_map_in_map_kern.c b/samples/bpf/test_map_in_map.bpf.c index b0200c8eac09..9f030f9c4e1b 100644 --- a/samples/bpf/test_map_in_map_kern.c +++ b/samples/bpf/test_map_in_map.bpf.c @@ -6,17 +6,17 @@ * License as published by the Free Software Foundation. */ #define KBUILD_MODNAME "foo" -#include <linux/ptrace.h> +#include "vmlinux.h" #include <linux/version.h> -#include <uapi/linux/bpf.h> -#include <uapi/linux/in6.h> #include <bpf/bpf_helpers.h> #include <bpf/bpf_tracing.h> #include <bpf/bpf_core_read.h> -#include "trace_common.h" #define MAX_NR_PORTS 65536 +#define EINVAL 22 +#define ENOENT 2 + /* map #0 */ struct inner_a { __uint(type, BPF_MAP_TYPE_ARRAY); @@ -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; diff --git a/samples/bpf/test_map_in_map_user.c b/samples/bpf/test_map_in_map_user.c index 652ec720533d..55dca43f3723 100644 --- a/samples/bpf/test_map_in_map_user.c +++ b/samples/bpf/test_map_in_map_user.c @@ -38,7 +38,7 @@ static void check_map_id(int inner_map_fd, int map_in_map_fd, uint32_t key) uint32_t info_len = sizeof(info); int ret, id; - ret = bpf_obj_get_info_by_fd(inner_map_fd, &info, &info_len); + ret = bpf_map_get_info_by_fd(inner_map_fd, &info, &info_len); assert(!ret); ret = bpf_map_lookup_elem(map_in_map_fd, &key, &id); @@ -120,7 +120,7 @@ int main(int argc, char **argv) struct bpf_object *obj; char filename[256]; - 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/test_overhead_kprobe_kern.c b/samples/bpf/test_overhead_kprobe_kern.c deleted file mode 100644 index 8fdd2c9c56b2..000000000000 --- a/samples/bpf/test_overhead_kprobe_kern.c +++ /dev/null @@ -1,49 +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 <linux/version.h> -#include <linux/ptrace.h> -#include <linux/sched.h> -#include <uapi/linux/bpf.h> -#include <bpf/bpf_helpers.h> -#include <bpf/bpf_tracing.h> - -#define _(P) \ - ({ \ - typeof(P) val = 0; \ - bpf_probe_read_kernel(&val, sizeof(val), &(P)); \ - val; \ - }) - -SEC("kprobe/__set_task_comm") -int prog(struct pt_regs *ctx) -{ - struct signal_struct *signal; - struct task_struct *tsk; - char oldcomm[TASK_COMM_LEN] = {}; - char newcomm[TASK_COMM_LEN] = {}; - u16 oom_score_adj; - u32 pid; - - tsk = (void *)PT_REGS_PARM1(ctx); - - pid = _(tsk->pid); - bpf_probe_read_kernel_str(oldcomm, sizeof(oldcomm), &tsk->comm); - bpf_probe_read_kernel_str(newcomm, sizeof(newcomm), - (void *)PT_REGS_PARM2(ctx)); - signal = _(tsk->signal); - oom_score_adj = _(signal->oom_score_adj); - return 0; -} - -SEC("kprobe/urandom_read") -int prog2(struct pt_regs *ctx) -{ - return 0; -} - -char _license[] SEC("license") = "GPL"; -u32 _version SEC("version") = LINUX_VERSION_CODE; diff --git a/samples/bpf/test_overhead_raw_tp_kern.c b/samples/bpf/test_overhead_raw_tp_kern.c deleted file mode 100644 index 8763181a32f3..000000000000 --- a/samples/bpf/test_overhead_raw_tp_kern.c +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2018 Facebook */ -#include <uapi/linux/bpf.h> -#include <bpf/bpf_helpers.h> - -SEC("raw_tracepoint/task_rename") -int prog(struct bpf_raw_tracepoint_args *ctx) -{ - return 0; -} - -SEC("raw_tracepoint/urandom_read") -int prog2(struct bpf_raw_tracepoint_args *ctx) -{ - return 0; -} -char _license[] SEC("license") = "GPL"; diff --git a/samples/bpf/test_overhead_tp_kern.c b/samples/bpf/test_overhead_tp_kern.c deleted file mode 100644 index 80edadacb692..000000000000 --- a/samples/bpf/test_overhead_tp_kern.c +++ /dev/null @@ -1,37 +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 <linux/sched.h> -#include <uapi/linux/bpf.h> -#include <bpf/bpf_helpers.h> - -/* from /sys/kernel/debug/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) -{ - return 0; -} - -/* from /sys/kernel/debug/tracing/events/random/urandom_read/format */ -struct urandom_read { - __u64 pad; - int got_bits; - int pool_left; - int input_left; -}; -SEC("tracepoint/random/urandom_read") -int prog2(struct urandom_read *ctx) -{ - return 0; -} -char _license[] SEC("license") = "GPL"; diff --git a/samples/bpf/test_overhead_user.c b/samples/bpf/test_overhead_user.c deleted file mode 100644 index 88717f8ec6ac..000000000000 --- a/samples/bpf/test_overhead_user.c +++ /dev/null @@ -1,215 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2016 Facebook - */ -#define _GNU_SOURCE -#include <sched.h> -#include <errno.h> -#include <stdio.h> -#include <sys/types.h> -#include <asm/unistd.h> -#include <fcntl.h> -#include <unistd.h> -#include <assert.h> -#include <sys/wait.h> -#include <stdlib.h> -#include <signal.h> -#include <linux/bpf.h> -#include <string.h> -#include <time.h> -#include <bpf/bpf.h> -#include <bpf/libbpf.h> - -#define MAX_CNT 1000000 - -static struct bpf_link *links[2]; -static struct bpf_object *obj; -static int cnt; - -static __u64 time_get_ns(void) -{ - struct timespec ts; - - clock_gettime(CLOCK_MONOTONIC, &ts); - return ts.tv_sec * 1000000000ull + ts.tv_nsec; -} - -static void test_task_rename(int cpu) -{ - __u64 start_time; - char buf[] = "test\n"; - int i, fd; - - fd = open("/proc/self/comm", O_WRONLY|O_TRUNC); - if (fd < 0) { - printf("couldn't open /proc\n"); - exit(1); - } - start_time = time_get_ns(); - for (i = 0; i < MAX_CNT; i++) { - if (write(fd, buf, sizeof(buf)) < 0) { - printf("task rename failed: %s\n", strerror(errno)); - close(fd); - return; - } - } - printf("task_rename:%d: %lld events per sec\n", - cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); - close(fd); -} - -static void test_urandom_read(int cpu) -{ - __u64 start_time; - char buf[4]; - int i, fd; - - fd = open("/dev/urandom", O_RDONLY); - if (fd < 0) { - printf("couldn't open /dev/urandom\n"); - exit(1); - } - start_time = time_get_ns(); - for (i = 0; i < MAX_CNT; i++) { - if (read(fd, buf, sizeof(buf)) < 0) { - printf("failed to read from /dev/urandom: %s\n", strerror(errno)); - close(fd); - return; - } - } - printf("urandom_read:%d: %lld events per sec\n", - cpu, MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); - close(fd); -} - -static void loop(int cpu, int flags) -{ - cpu_set_t cpuset; - - CPU_ZERO(&cpuset); - CPU_SET(cpu, &cpuset); - sched_setaffinity(0, sizeof(cpuset), &cpuset); - - if (flags & 1) - test_task_rename(cpu); - if (flags & 2) - test_urandom_read(cpu); -} - -static void run_perf_test(int tasks, int flags) -{ - pid_t pid[tasks]; - int i; - - for (i = 0; i < tasks; i++) { - pid[i] = fork(); - if (pid[i] == 0) { - loop(i, flags); - exit(0); - } else if (pid[i] == -1) { - printf("couldn't spawn #%d process\n", i); - exit(1); - } - } - for (i = 0; i < tasks; i++) { - int status; - - assert(waitpid(pid[i], &status, 0) == pid[i]); - assert(status == 0); - } -} - -static int load_progs(char *filename) -{ - struct bpf_program *prog; - int err = 0; - - obj = bpf_object__open_file(filename, NULL); - err = libbpf_get_error(obj); - if (err < 0) { - fprintf(stderr, "ERROR: opening BPF object file failed\n"); - return err; - } - - /* load BPF program */ - err = bpf_object__load(obj); - if (err < 0) { - fprintf(stderr, "ERROR: loading BPF object file failed\n"); - return err; - } - - bpf_object__for_each_program(prog, obj) { - links[cnt] = bpf_program__attach(prog); - err = libbpf_get_error(links[cnt]); - if (err < 0) { - fprintf(stderr, "ERROR: bpf_program__attach failed\n"); - links[cnt] = NULL; - return err; - } - cnt++; - } - - return err; -} - -static void unload_progs(void) -{ - while (cnt) - bpf_link__destroy(links[--cnt]); - - bpf_object__close(obj); -} - -int main(int argc, char **argv) -{ - int num_cpu = sysconf(_SC_NPROCESSORS_ONLN); - int test_flags = ~0; - char filename[256]; - int err = 0; - - - if (argc > 1) - test_flags = atoi(argv[1]) ? : test_flags; - if (argc > 2) - num_cpu = atoi(argv[2]) ? : num_cpu; - - if (test_flags & 0x3) { - printf("BASE\n"); - run_perf_test(num_cpu, test_flags); - } - - if (test_flags & 0xC) { - snprintf(filename, sizeof(filename), - "%s_kprobe_kern.o", argv[0]); - - printf("w/KPROBE\n"); - err = load_progs(filename); - if (!err) - run_perf_test(num_cpu, test_flags >> 2); - - unload_progs(); - } - - if (test_flags & 0x30) { - snprintf(filename, sizeof(filename), - "%s_tp_kern.o", argv[0]); - printf("w/TRACEPOINT\n"); - err = load_progs(filename); - if (!err) - run_perf_test(num_cpu, test_flags >> 4); - - unload_progs(); - } - - if (test_flags & 0xC0) { - snprintf(filename, sizeof(filename), - "%s_raw_tp_kern.o", argv[0]); - printf("w/RAW_TRACEPOINT\n"); - err = load_progs(filename); - if (!err) - run_perf_test(num_cpu, test_flags >> 6); - - unload_progs(); - } - - return err; -} diff --git a/samples/bpf/test_override_return.sh b/samples/bpf/test_override_return.sh deleted file mode 100755 index 35db26f736b9..000000000000 --- a/samples/bpf/test_override_return.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -rm -r tmpmnt -rm -f testfile.img -dd if=/dev/zero of=testfile.img bs=1M seek=1000 count=1 -DEVICE=$(losetup --show -f testfile.img) -mkfs.btrfs -f $DEVICE -mkdir tmpmnt -./tracex7 $DEVICE -if [ $? -eq 0 ] -then - echo "SUCCESS!" -else - echo "FAILED!" -fi -losetup -d $DEVICE diff --git a/samples/bpf/test_probe_write_user_kern.c b/samples/bpf/test_probe_write_user_kern.c deleted file mode 100644 index 220a96438d75..000000000000 --- a/samples/bpf/test_probe_write_user_kern.c +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright (c) 2016 Sargun Dhillon <sargun@sargun.me> - * - * 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 <linux/skbuff.h> -#include <linux/netdevice.h> -#include <uapi/linux/bpf.h> -#include <linux/version.h> -#include <bpf/bpf_helpers.h> -#include <bpf/bpf_tracing.h> -#include <bpf/bpf_core_read.h> -#include "trace_common.h" - -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __type(key, struct sockaddr_in); - __type(value, struct sockaddr_in); - __uint(max_entries, 256); -} dnat_map SEC(".maps"); - -/* 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 - * - * This example sits on a syscall, and the syscall ABI is relatively stable - * of course, across platforms, and over time, the ABI may change. - */ -SEC("kprobe/" SYSCALL(sys_connect)) -int bpf_prog1(struct pt_regs *ctx) -{ - struct pt_regs *real_regs = (struct pt_regs *)PT_REGS_PARM1_CORE(ctx); - void *sockaddr_arg = (void *)PT_REGS_PARM2_CORE(real_regs); - int sockaddr_len = (int)PT_REGS_PARM3_CORE(real_regs); - struct sockaddr_in new_addr, orig_addr = {}; - struct sockaddr_in *mapped_addr; - - if (sockaddr_len > sizeof(orig_addr)) - return 0; - - if (bpf_probe_read_user(&orig_addr, sizeof(orig_addr), sockaddr_arg) != 0) - return 0; - - mapped_addr = bpf_map_lookup_elem(&dnat_map, &orig_addr); - if (mapped_addr != NULL) { - memcpy(&new_addr, mapped_addr, sizeof(new_addr)); - bpf_probe_write_user(sockaddr_arg, &new_addr, - sizeof(new_addr)); - } - return 0; -} - -char _license[] SEC("license") = "GPL"; -u32 _version SEC("version") = LINUX_VERSION_CODE; diff --git a/samples/bpf/test_probe_write_user_user.c b/samples/bpf/test_probe_write_user_user.c deleted file mode 100644 index 00ccfb834e45..000000000000 --- a/samples/bpf/test_probe_write_user_user.c +++ /dev/null @@ -1,108 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include <stdio.h> -#include <assert.h> -#include <unistd.h> -#include <bpf/bpf.h> -#include <bpf/libbpf.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> - -int main(int ac, char **argv) -{ - struct sockaddr_in *serv_addr_in, *mapped_addr_in, *tmp_addr_in; - struct sockaddr serv_addr, mapped_addr, tmp_addr; - int serverfd, serverconnfd, clientfd, map_fd; - struct bpf_link *link = NULL; - struct bpf_program *prog; - struct bpf_object *obj; - socklen_t sockaddr_len; - char filename[256]; - char *ip; - - serv_addr_in = (struct sockaddr_in *)&serv_addr; - mapped_addr_in = (struct sockaddr_in *)&mapped_addr; - tmp_addr_in = (struct sockaddr_in *)&tmp_addr; - - snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); - obj = bpf_object__open_file(filename, NULL); - if (libbpf_get_error(obj)) { - fprintf(stderr, "ERROR: opening BPF object file failed\n"); - return 0; - } - - prog = bpf_object__find_program_by_name(obj, "bpf_prog1"); - if (libbpf_get_error(prog)) { - fprintf(stderr, "ERROR: finding a prog in obj file failed\n"); - goto cleanup; - } - - /* load BPF program */ - if (bpf_object__load(obj)) { - fprintf(stderr, "ERROR: loading BPF object file failed\n"); - goto cleanup; - } - - map_fd = bpf_object__find_map_fd_by_name(obj, "dnat_map"); - if (map_fd < 0) { - fprintf(stderr, "ERROR: finding a map in obj file failed\n"); - goto cleanup; - } - - link = bpf_program__attach(prog); - if (libbpf_get_error(link)) { - fprintf(stderr, "ERROR: bpf_program__attach failed\n"); - link = NULL; - goto cleanup; - } - - assert((serverfd = socket(AF_INET, SOCK_STREAM, 0)) > 0); - assert((clientfd = socket(AF_INET, SOCK_STREAM, 0)) > 0); - - /* Bind server to ephemeral port on lo */ - memset(&serv_addr, 0, sizeof(serv_addr)); - serv_addr_in->sin_family = AF_INET; - serv_addr_in->sin_port = 0; - serv_addr_in->sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - assert(bind(serverfd, &serv_addr, sizeof(serv_addr)) == 0); - - sockaddr_len = sizeof(serv_addr); - assert(getsockname(serverfd, &serv_addr, &sockaddr_len) == 0); - ip = inet_ntoa(serv_addr_in->sin_addr); - printf("Server bound to: %s:%d\n", ip, ntohs(serv_addr_in->sin_port)); - - memset(&mapped_addr, 0, sizeof(mapped_addr)); - mapped_addr_in->sin_family = AF_INET; - mapped_addr_in->sin_port = htons(5555); - mapped_addr_in->sin_addr.s_addr = inet_addr("255.255.255.255"); - - assert(!bpf_map_update_elem(map_fd, &mapped_addr, &serv_addr, BPF_ANY)); - - assert(listen(serverfd, 5) == 0); - - ip = inet_ntoa(mapped_addr_in->sin_addr); - printf("Client connecting to: %s:%d\n", - ip, ntohs(mapped_addr_in->sin_port)); - assert(connect(clientfd, &mapped_addr, sizeof(mapped_addr)) == 0); - - sockaddr_len = sizeof(tmp_addr); - ip = inet_ntoa(tmp_addr_in->sin_addr); - assert((serverconnfd = accept(serverfd, &tmp_addr, &sockaddr_len)) > 0); - printf("Server received connection from: %s:%d\n", - ip, ntohs(tmp_addr_in->sin_port)); - - sockaddr_len = sizeof(tmp_addr); - assert(getpeername(clientfd, &tmp_addr, &sockaddr_len) == 0); - ip = inet_ntoa(tmp_addr_in->sin_addr); - printf("Client's peer address: %s:%d\n", - ip, ntohs(tmp_addr_in->sin_port)); - - /* Is the server's getsockname = the socket getpeername */ - assert(memcmp(&serv_addr, &tmp_addr, sizeof(struct sockaddr_in)) == 0); - -cleanup: - bpf_link__destroy(link); - bpf_object__close(obj); - return 0; -} diff --git a/samples/bpf/trace_common.h b/samples/bpf/trace_common.h deleted file mode 100644 index 8cb5400aed1f..000000000000 --- a/samples/bpf/trace_common.h +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#ifndef __TRACE_COMMON_H -#define __TRACE_COMMON_H - -#ifdef __x86_64__ -#define SYSCALL(SYS) "__x64_" __stringify(SYS) -#elif defined(__s390x__) -#define SYSCALL(SYS) "__s390x_" __stringify(SYS) -#else -#define SYSCALL(SYS) __stringify(SYS) -#endif - -#endif diff --git a/samples/bpf/trace_output_kern.c b/samples/bpf/trace_output.bpf.c index b64815af0943..565a73b51b04 100644 --- a/samples/bpf/trace_output_kern.c +++ b/samples/bpf/trace_output.bpf.c @@ -1,8 +1,6 @@ -#include <linux/ptrace.h> +#include "vmlinux.h" #include <linux/version.h> -#include <uapi/linux/bpf.h> #include <bpf/bpf_helpers.h> -#include "trace_common.h" struct { __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); @@ -11,7 +9,7 @@ struct { __uint(max_entries, 2); } my_map SEC(".maps"); -SEC("kprobe/" SYSCALL(sys_write)) +SEC("ksyscall/write") int bpf_prog1(struct pt_regs *ctx) { struct S { diff --git a/samples/bpf/trace_output_user.c b/samples/bpf/trace_output_user.c index 371732f9cf8e..d316fd2c8e24 100644 --- a/samples/bpf/trace_output_user.c +++ b/samples/bpf/trace_output_user.c @@ -51,7 +51,7 @@ int main(int argc, 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/tracex1_kern.c b/samples/bpf/tracex1.bpf.c index ef30d2b353b0..ceedf0b1d479 100644 --- a/samples/bpf/tracex1_kern.c +++ b/samples/bpf/tracex1.bpf.c @@ -4,42 +4,35 @@ * modify it under the terms of version 2 of the GNU General Public * License as published by the Free Software Foundation. */ -#include <linux/skbuff.h> -#include <linux/netdevice.h> -#include <uapi/linux/bpf.h> +#include "vmlinux.h" +#include "net_shared.h" #include <linux/version.h> #include <bpf/bpf_helpers.h> +#include <bpf/bpf_core_read.h> #include <bpf/bpf_tracing.h> -#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") +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 + * looks for packets on loopback device and prints them + * (wildcard is used for avoiding symbol mismatch due to optimization) */ 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_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/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/tracex2_kern.c b/samples/bpf/tracex2_kern.c deleted file mode 100644 index 93e0b7680b4f..000000000000 --- a/samples/bpf/tracex2_kern.c +++ /dev/null @@ -1,102 +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 <linux/skbuff.h> -#include <linux/netdevice.h> -#include <linux/version.h> -#include <uapi/linux/bpf.h> -#include <bpf/bpf_helpers.h> -#include <bpf/bpf_tracing.h> -#include "trace_common.h" - -struct { - __uint(type, BPF_MAP_TYPE_HASH); - __type(key, long); - __type(value, long); - __uint(max_entries, 1024); -} 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/kfree_skb_reason") -int bpf_prog2(struct pt_regs *ctx) -{ - long loc = 0; - long init_val = 1; - long *value; - - /* read ip of kfree_skb_reason caller. - * non-portable version of __builtin_return_address(0) - */ - BPF_KPROBE_READ_RET_IP(loc, ctx); - - value = bpf_map_lookup_elem(&my_map, &loc); - if (value) - *value += 1; - else - bpf_map_update_elem(&my_map, &loc, &init_val, BPF_ANY); - return 0; -} - -static unsigned int log2(unsigned int v) -{ - unsigned int r; - unsigned int shift; - - r = (v > 0xFFFF) << 4; v >>= r; - shift = (v > 0xFF) << 3; v >>= shift; r |= shift; - shift = (v > 0xF) << 2; v >>= shift; r |= shift; - shift = (v > 0x3) << 1; v >>= shift; r |= shift; - r |= (v >> 1); - return r; -} - -static unsigned int log2l(unsigned long v) -{ - unsigned int hi = v >> 32; - if (hi) - return log2(hi) + 32; - else - return log2(v); -} - -struct hist_key { - char comm[16]; - u64 pid_tgid; - u64 uid_gid; - u64 index; -}; - -struct { - __uint(type, BPF_MAP_TYPE_PERCPU_HASH); - __uint(key_size, sizeof(struct hist_key)); - __uint(value_size, sizeof(long)); - __uint(max_entries, 1024); -} my_hist_map SEC(".maps"); - -SEC("kprobe/" SYSCALL(sys_write)) -int bpf_prog3(struct pt_regs *ctx) -{ - long write_size = PT_REGS_PARM3(ctx); - long init_val = 1; - long *value; - struct hist_key key; - - key.index = log2l(write_size); - key.pid_tgid = bpf_get_current_pid_tgid(); - key.uid_gid = bpf_get_current_uid_gid(); - bpf_get_current_comm(&key.comm, sizeof(key.comm)); - - value = bpf_map_lookup_elem(&my_hist_map, &key); - if (value) - __sync_fetch_and_add(value, 1); - else - bpf_map_update_elem(&my_hist_map, &key, &init_val, BPF_ANY); - return 0; -} -char _license[] SEC("license") = "GPL"; -u32 _version SEC("version") = LINUX_VERSION_CODE; diff --git a/samples/bpf/tracex2_user.c b/samples/bpf/tracex2_user.c deleted file mode 100644 index 089e408abd7a..000000000000 --- a/samples/bpf/tracex2_user.c +++ /dev/null @@ -1,187 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include <signal.h> -#include <string.h> - -#include <bpf/bpf.h> -#include <bpf/libbpf.h> -#include "bpf_util.h" - -#define MAX_INDEX 64 -#define MAX_STARS 38 - -/* my_map, my_hist_map */ -static int map_fd[2]; - -static void stars(char *str, long val, long max, int width) -{ - int i; - - for (i = 0; i < (width * val / max) - 1 && i < width - 1; i++) - str[i] = '*'; - if (val > max) - str[i - 1] = '+'; - str[i] = '\0'; -} - -struct task { - char comm[16]; - __u64 pid_tgid; - __u64 uid_gid; -}; - -struct hist_key { - struct task t; - __u32 index; -}; - -#define SIZE sizeof(struct task) - -static void print_hist_for_pid(int fd, void *task) -{ - unsigned int nr_cpus = bpf_num_possible_cpus(); - struct hist_key key = {}, next_key; - long values[nr_cpus]; - char starstr[MAX_STARS]; - long value; - long data[MAX_INDEX] = {}; - int max_ind = -1; - long max_value = 0; - int i, ind; - - while (bpf_map_get_next_key(fd, &key, &next_key) == 0) { - if (memcmp(&next_key, task, SIZE)) { - key = next_key; - continue; - } - bpf_map_lookup_elem(fd, &next_key, values); - value = 0; - for (i = 0; i < nr_cpus; i++) - value += values[i]; - ind = next_key.index; - data[ind] = value; - if (value && ind > max_ind) - max_ind = ind; - if (value > max_value) - max_value = value; - key = next_key; - } - - printf(" syscall write() stats\n"); - printf(" byte_size : count distribution\n"); - for (i = 1; i <= max_ind + 1; i++) { - stars(starstr, data[i - 1], max_value, MAX_STARS); - printf("%8ld -> %-8ld : %-8ld |%-*s|\n", - (1l << i) >> 1, (1l << i) - 1, data[i - 1], - MAX_STARS, starstr); - } -} - -static void print_hist(int fd) -{ - struct hist_key key = {}, next_key; - static struct task tasks[1024]; - int task_cnt = 0; - int i; - - while (bpf_map_get_next_key(fd, &key, &next_key) == 0) { - int found = 0; - - for (i = 0; i < task_cnt; i++) - if (memcmp(&tasks[i], &next_key, SIZE) == 0) - found = 1; - if (!found) - memcpy(&tasks[task_cnt++], &next_key, SIZE); - key = next_key; - } - - for (i = 0; i < task_cnt; i++) { - printf("\npid %d cmd %s uid %d\n", - (__u32) tasks[i].pid_tgid, - tasks[i].comm, - (__u32) tasks[i].uid_gid); - print_hist_for_pid(fd, &tasks[i]); - } - -} - -static void int_exit(int sig) -{ - print_hist(map_fd[1]); - exit(0); -} - -int main(int ac, char **argv) -{ - long key, next_key, value; - struct bpf_link *links[2]; - struct bpf_program *prog; - struct bpf_object *obj; - char filename[256]; - int i, j = 0; - FILE *f; - - snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); - obj = bpf_object__open_file(filename, NULL); - if (libbpf_get_error(obj)) { - fprintf(stderr, "ERROR: opening BPF object file failed\n"); - return 0; - } - - /* load BPF program */ - if (bpf_object__load(obj)) { - fprintf(stderr, "ERROR: loading BPF object file failed\n"); - goto cleanup; - } - - map_fd[0] = bpf_object__find_map_fd_by_name(obj, "my_map"); - map_fd[1] = bpf_object__find_map_fd_by_name(obj, "my_hist_map"); - if (map_fd[0] < 0 || map_fd[1] < 0) { - fprintf(stderr, "ERROR: finding a map in obj file failed\n"); - goto cleanup; - } - - signal(SIGINT, int_exit); - signal(SIGTERM, int_exit); - - /* start 'ping' in the background to have some kfree_skb_reason - * events */ - f = popen("ping -4 -c5 localhost", "r"); - (void) f; - - /* start 'dd' in the background to have plenty of 'write' syscalls */ - f = popen("dd if=/dev/zero of=/dev/null count=5000000", "r"); - (void) f; - - bpf_object__for_each_program(prog, obj) { - links[j] = bpf_program__attach(prog); - if (libbpf_get_error(links[j])) { - fprintf(stderr, "ERROR: bpf_program__attach failed\n"); - links[j] = NULL; - goto cleanup; - } - j++; - } - - for (i = 0; i < 5; i++) { - key = 0; - while (bpf_map_get_next_key(map_fd[0], &key, &next_key) == 0) { - bpf_map_lookup_elem(map_fd[0], &next_key, &value); - printf("location 0x%lx count %ld\n", next_key, value); - key = next_key; - } - if (key) - printf("\n"); - sleep(1); - } - print_hist(map_fd[1]); - -cleanup: - for (j--; j >= 0; j--) - bpf_link__destroy(links[j]); - - bpf_object__close(obj); - return 0; -} diff --git a/samples/bpf/tracex3_kern.c b/samples/bpf/tracex3.bpf.c index bde6591cb20c..41f37966f5f5 100644 --- a/samples/bpf/tracex3_kern.c +++ b/samples/bpf/tracex3.bpf.c @@ -4,13 +4,17 @@ * modify it under the terms of version 2 of the GNU General Public * License as published by the Free Software Foundation. */ -#include <linux/skbuff.h> -#include <linux/netdevice.h> +#include "vmlinux.h" #include <linux/version.h> -#include <uapi/linux/bpf.h> #include <bpf/bpf_helpers.h> #include <bpf/bpf_tracing.h> +struct start_key { + dev_t dev; + u32 _pad; + sector_t sector; +}; + struct { __uint(type, BPF_MAP_TYPE_HASH); __type(key, long); @@ -18,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; } @@ -49,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 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_kern.c b/samples/bpf/tracex4.bpf.c index eb0f8fdd14bf..d786492fd926 100644 --- a/samples/bpf/tracex4_kern.c +++ b/samples/bpf/tracex4.bpf.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 <linux/ptrace.h> +#include "vmlinux.h" #include <linux/version.h> -#include <uapi/linux/bpf.h> #include <bpf/bpf_helpers.h> #include <bpf/bpf_tracing.h> @@ -34,13 +33,13 @@ int bpf_prog1(struct pt_regs *ctx) return 0; } -SEC("kretprobe/kmem_cache_alloc_node") +SEC("kretprobe/kmem_cache_alloc_node_noprof") 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 */ + /* get ip address of kmem_cache_alloc_node_noprof() caller */ BPF_KRETPROBE_READ_RET_IP(ip, ctx); struct pair v = { diff --git a/samples/bpf/tracex4_user.c b/samples/bpf/tracex4_user.c index 227b05a0bc88..a5145ad72cbf 100644 --- a/samples/bpf/tracex4_user.c +++ b/samples/bpf/tracex4_user.c @@ -51,9 +51,9 @@ int main(int ac, char **argv) struct bpf_program *prog; struct bpf_object *obj; char filename[256]; - int map_fd, i, j = 0; + 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"); @@ -82,7 +82,7 @@ int main(int ac, char **argv) j++; } - for (i = 0; ; i++) { + while (1) { print_old_objects(map_fd); sleep(1); } diff --git a/samples/bpf/tracex5_kern.c b/samples/bpf/tracex5.bpf.c index 64a1f7550d7e..4d3d6c9b25fa 100644 --- a/samples/bpf/tracex5_kern.c +++ b/samples/bpf/tracex5.bpf.c @@ -4,15 +4,15 @@ * modify it under the terms of version 2 of the GNU General Public * License as published by the Free Software Foundation. */ -#include <linux/ptrace.h> +#include "vmlinux.h" +#include "syscall_nrs.h" #include <linux/version.h> -#include <uapi/linux/bpf.h> -#include <uapi/linux/seccomp.h> #include <uapi/linux/unistd.h> -#include "syscall_nrs.h" #include <bpf/bpf_helpers.h> #include <bpf/bpf_tracing.h> +#include <bpf/bpf_core_read.h> +#define __stringify(x) #x #define PROG(F) SEC("kprobe/"__stringify(F)) int bpf_func_##F struct { @@ -47,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), @@ -60,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), 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_kern.c b/samples/bpf/tracex6.bpf.c index acad5712d8b4..9b23b4737cfb 100644 --- a/samples/bpf/tracex6_kern.c +++ b/samples/bpf/tracex6.bpf.c @@ -1,7 +1,8 @@ -#include <linux/ptrace.h> +#include "vmlinux.h" #include <linux/version.h> -#include <uapi/linux/bpf.h> #include <bpf/bpf_helpers.h> +#include <bpf/bpf_tracing.h> +#include <bpf/bpf_core_read.h> struct { __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); @@ -45,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; 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_kern.c b/samples/bpf/tracex7_kern.c deleted file mode 100644 index c5a92df8ac31..000000000000 --- a/samples/bpf/tracex7_kern.c +++ /dev/null @@ -1,16 +0,0 @@ -#include <uapi/linux/ptrace.h> -#include <uapi/linux/bpf.h> -#include <linux/version.h> -#include <bpf/bpf_helpers.h> - -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 deleted file mode 100644 index 8be7ce18d3ba..000000000000 --- a/samples/bpf/tracex7_user.c +++ /dev/null @@ -1,56 +0,0 @@ -#define _GNU_SOURCE - -#include <stdio.h> -#include <unistd.h> -#include <bpf/libbpf.h> - -int main(int argc, char **argv) -{ - struct bpf_link *link = NULL; - struct bpf_program *prog; - struct bpf_object *obj; - char filename[256]; - char command[256]; - int ret = 0; - FILE *f; - - if (!argv[1]) { - fprintf(stderr, "ERROR: Run with the btrfs device argument!\n"); - return 0; - } - - snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); - obj = bpf_object__open_file(filename, NULL); - if (libbpf_get_error(obj)) { - fprintf(stderr, "ERROR: opening BPF object file failed\n"); - return 0; - } - - prog = bpf_object__find_program_by_name(obj, "bpf_prog1"); - if (!prog) { - fprintf(stderr, "ERROR: finding a prog in obj file failed\n"); - goto cleanup; - } - - /* load BPF program */ - if (bpf_object__load(obj)) { - fprintf(stderr, "ERROR: loading BPF object file failed\n"); - goto cleanup; - } - - link = bpf_program__attach(prog); - if (libbpf_get_error(link)) { - fprintf(stderr, "ERROR: bpf_program__attach failed\n"); - link = NULL; - goto cleanup; - } - - snprintf(command, 256, "mount %s tmpmnt/", argv[1]); - f = popen(command, "r"); - ret = pclose(f); - -cleanup: - bpf_link__destroy(link); - bpf_object__close(obj); - return ret ? 0 : 1; -} diff --git a/samples/bpf/xdp1_kern.c b/samples/bpf/xdp1_kern.c deleted file mode 100644 index 0a5c704badd0..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 <uapi/linux/bpf.h> -#include <linux/in.h> -#include <linux/if_ether.h> -#include <linux/if_packet.h> -#include <linux/if_vlan.h> -#include <linux/ip.h> -#include <linux/ipv6.h> -#include <bpf/bpf_helpers.h> - -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 64 -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 281dc964de8d..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 <linux/bpf.h> -#include <linux/if_link.h> -#include <assert.h> -#include <errno.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <libgen.h> -#include <net/if.h> - -#include "bpf_util.h" -#include <bpf/bpf.h> -#include <bpf/libbpf.h> - -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_obj_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 67804ecf7ce3..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 <uapi/linux/bpf.h> -#include <linux/in.h> -#include <linux/if_ether.h> -#include <linux/if_packet.h> -#include <linux/if_vlan.h> -#include <linux/ip.h> -#include <linux/ipv6.h> -#include <bpf/bpf_helpers.h> - -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 64 -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"; diff --git a/samples/bpf/xdp2skb_meta_kern.c b/samples/bpf/xdp2skb_meta_kern.c index d5631014a176..3c36c25d9902 100644 --- a/samples/bpf/xdp2skb_meta_kern.c +++ b/samples/bpf/xdp2skb_meta_kern.c @@ -32,7 +32,7 @@ SEC("xdp_mark") int _xdp_mark(struct xdp_md *ctx) { struct meta_info *meta; - void *data, *data_end; + void *data; int ret; /* Reserve space in-front of data pointer for our meta info. @@ -63,7 +63,6 @@ SEC("tc_mark") int _tc_mark(struct __sk_buff *ctx) { void *data = (void *)(unsigned long)ctx->data; - void *data_end = (void *)(unsigned long)ctx->data_end; void *data_meta = (void *)(unsigned long)ctx->data_meta; struct meta_info *meta = data_meta; diff --git a/samples/bpf/xdp_adjust_tail_kern.c b/samples/bpf/xdp_adjust_tail_kern.c index ffdd548627f0..da67bcad1c63 100644 --- a/samples/bpf/xdp_adjust_tail_kern.c +++ b/samples/bpf/xdp_adjust_tail_kern.c @@ -57,6 +57,7 @@ static __always_inline void swap_mac(void *data, struct ethhdr *orig_eth) static __always_inline __u16 csum_fold_helper(__u32 csum) { + csum = (csum & 0xffff) + (csum >> 16); return ~((csum & 0xffff) + (csum >> 16)); } diff --git a/samples/bpf/xdp_adjust_tail_user.c b/samples/bpf/xdp_adjust_tail_user.c index 167646077c8f..e9426bd65420 100644 --- a/samples/bpf/xdp_adjust_tail_user.c +++ b/samples/bpf/xdp_adjust_tail_user.c @@ -184,7 +184,7 @@ int main(int argc, char **argv) return 1; } - err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len); + 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 1; diff --git a/samples/bpf/xdp_fwd_user.c b/samples/bpf/xdp_fwd_user.c index 84f57f1209ce..193b3b79b31f 100644 --- a/samples/bpf/xdp_fwd_user.c +++ b/samples/bpf/xdp_fwd_user.c @@ -76,9 +76,9 @@ static int do_detach(int ifindex, const char *ifname, const char *app_name) return prog_fd; } - err = bpf_obj_get_info_by_fd(prog_fd, &prog_info, &info_len); + err = bpf_prog_get_info_by_fd(prog_fd, &prog_info, &info_len); if (err) { - printf("ERROR: bpf_obj_get_info_by_fd failed (%s)\n", + printf("ERROR: bpf_prog_get_info_by_fd failed (%s)\n", strerror(errno)); goto close_out; } 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 <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdbool.h> -#include <stdint.h> -#include <string.h> -#include <ctype.h> -#include <unistd.h> -#include <locale.h> -#include <getopt.h> -#include <net/if.h> -#include <time.h> -#include <signal.h> -#include <bpf/bpf.h> -#include <bpf/libbpf.h> -#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); -} 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 <john.r.fastabend@intel.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. - * - * 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 a12381c37d2b..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 <IFINDEX|IFNAME> -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 <ifindex|ifname> (use built-in DEVMAP redirect program)\n" -" Custom CPUMAP BPF program:\n" -" --mprog-filename/-f <filename> --mprog-name/-e <program>\n" -" Optionally, also pass --redirect-map/-m and --redirect-device/-r together\n" -" to configure DEVMAP in BPF object <filename>\n"; - -#include <errno.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdbool.h> -#include <string.h> -#include <unistd.h> -#include <locale.h> -#include <sys/sysinfo.h> -#include <getopt.h> -#include <net/if.h> -#include <time.h> -#include <linux/limits.h> -#include <arpa/inet.h> -#include <linux/if_link.h> -#include <bpf/bpf.h> -#include <bpf/libbpf.h> -#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_obj_get_info_by_fd(bpf_map__fd(skel->maps.cpu_map), &info, &infosz); - if (ret < 0) { - fprintf(stderr, "Failed bpf_obj_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 <IFINDEX|IFNAME> <IFINDEX|IFNAME> ... <IFINDEX|IFNAME>\n"; - -#include <linux/bpf.h> -#include <linux/if_link.h> -#include <assert.h> -#include <getopt.h> -#include <errno.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <net/if.h> -#include <unistd.h> -#include <libgen.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <linux/if_ether.h> -#include <bpf/bpf.h> -#include <bpf/libbpf.h> -#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 <IFINDEX|IFNAME>_IN <IFINDEX|IFNAME>_OUT\n"; - -#include <linux/bpf.h> -#include <linux/if_link.h> -#include <assert.h> -#include <errno.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdbool.h> -#include <string.h> -#include <net/if.h> -#include <unistd.h> -#include <libgen.h> -#include <getopt.h> -#include <bpf/bpf.h> -#include <bpf/libbpf.h> -#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 <john.r.fastabend@intel.com> - */ -static const char *__doc__ = -"XDP redirect tool, using bpf_redirect helper\n" -"Usage: xdp_redirect <IFINDEX|IFNAME>_IN <IFINDEX|IFNAME>_OUT\n"; - -#include <linux/bpf.h> -#include <linux/if_link.h> -#include <assert.h> -#include <errno.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdbool.h> -#include <string.h> -#include <net/if.h> -#include <unistd.h> -#include <libgen.h> -#include <getopt.h> -#include <bpf/bpf.h> -#include <bpf/libbpf.h> -#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); -} diff --git a/samples/bpf/xdp_router_ipv4_user.c b/samples/bpf/xdp_router_ipv4_user.c index 9d41db09c480..266fdd0b025d 100644 --- a/samples/bpf/xdp_router_ipv4_user.c +++ b/samples/bpf/xdp_router_ipv4_user.c @@ -91,7 +91,7 @@ static int recv_msg(struct sockaddr_nl sock_addr, int sock) static void read_route(struct nlmsghdr *nh, int nll) { char dsts[24], gws[24], ifs[16], dsts_len[24], metrics[24]; - struct bpf_lpm_trie_key *prefix_key; + struct bpf_lpm_trie_key_u8 *prefix_key; struct rtattr *rt_attr; struct rtmsg *rt_msg; int rtm_family; 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 <uapi/linux/bpf.h> -#include <uapi/linux/if_ether.h> -#include <uapi/linux/in.h> -#include <bpf/bpf_helpers.h> - -/* 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 08f5331d2b00..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 <errno.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdbool.h> -#include <string.h> -#include <unistd.h> -#include <locale.h> -#include <getopt.h> -#include <net/if.h> -#include <time.h> -#include <limits.h> -#include <arpa/inet.h> -#include <linux/if_link.h> - -#include <bpf/bpf.h> -#include <bpf/libbpf.h> -#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 <options>\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_obj_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; -} diff --git a/samples/bpf/xdp_sample.bpf.h b/samples/bpf/xdp_sample.bpf.h index 25b1dbe9b37b..fecc41c5df04 100644 --- a/samples/bpf/xdp_sample.bpf.h +++ b/samples/bpf/xdp_sample.bpf.h @@ -7,17 +7,9 @@ #include <bpf/bpf_core_read.h> #include <bpf/bpf_helpers.h> +#include "net_shared.h" #include "xdp_sample_shared.h" -#define ETH_ALEN 6 -#define ETH_P_802_3_MIN 0x0600 -#define ETH_P_8021Q 0x8100 -#define ETH_P_8021AD 0x88A8 -#define ETH_P_IP 0x0800 -#define ETH_P_IPV6 0x86DD -#define ETH_P_ARP 0x0806 -#define IPPROTO_ICMPV6 58 - #define EINVAL 22 #define ENETDOWN 100 #define EMSGSIZE 90 @@ -55,18 +47,6 @@ static __always_inline void swap_src_dst_mac(void *data) p[5] = dst[2]; } -#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \ - __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -#define bpf_ntohs(x) __builtin_bswap16(x) -#define bpf_htons(x) __builtin_bswap16(x) -#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \ - __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -#define bpf_ntohs(x) (x) -#define bpf_htons(x) (x) -#else -# error "Endianness detection needs to be set up for your compiler?!" -#endif - /* * Note: including linux/compiler.h or linux/kernel.h for the macros below * conflicts with vmlinux.h include in BPF files, so we define them here. 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 <linux/ptrace.h> -#include <linux/version.h> -#include <uapi/linux/bpf.h> -#include <bpf/bpf_helpers.h> - -#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 7df7163239ac..000000000000 --- a/samples/bpf/xdp_sample_pkts_user.c +++ /dev/null @@ -1,196 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <linux/perf_event.h> -#include <linux/bpf.h> -#include <net/if.h> -#include <errno.h> -#include <assert.h> -#include <sys/sysinfo.h> -#include <sys/ioctl.h> -#include <signal.h> -#include <bpf/libbpf.h> -#include <bpf/bpf.h> -#include <libgen.h> -#include <linux/if_link.h> - -#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_obj_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] <ifname|ifindex>\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; -} diff --git a/samples/bpf/xdp_tx_iptunnel_user.c b/samples/bpf/xdp_tx_iptunnel_user.c index 307baef6861a..7e4b2f7108a6 100644 --- a/samples/bpf/xdp_tx_iptunnel_user.c +++ b/samples/bpf/xdp_tx_iptunnel_user.c @@ -295,7 +295,7 @@ int main(int argc, char **argv) return 1; } - err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len); + 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; |
