From 61e53814c41c5b1e138fea3f34668c5621d3c05c Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Sun, 17 Mar 2019 16:08:29 +0100 Subject: [PATCH 1/9] advanced02-BTF: copy BPF code from basic04 Signed-off-by: Jesper Dangaard Brouer --- advanced02-BTF/common_kern_user.h | 17 +++++ advanced02-BTF/xdp_prog_kern.c | 105 ++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 advanced02-BTF/common_kern_user.h create mode 100644 advanced02-BTF/xdp_prog_kern.c diff --git a/advanced02-BTF/common_kern_user.h b/advanced02-BTF/common_kern_user.h new file mode 100644 index 00000000..04f3344b --- /dev/null +++ b/advanced02-BTF/common_kern_user.h @@ -0,0 +1,17 @@ +/* This common_kern_user.h is used by kernel side BPF-progs and + * userspace programs, for sharing common struct's and DEFINEs. + */ +#ifndef __COMMON_KERN_USER_H +#define __COMMON_KERN_USER_H + +/* This is the data record stored in the map */ +struct datarec { + __u64 rx_packets; + __u64 rx_bytes; +}; + +#ifndef XDP_ACTION_MAX +#define XDP_ACTION_MAX (XDP_REDIRECT + 1) +#endif + +#endif /* __COMMON_KERN_USER_H */ diff --git a/advanced02-BTF/xdp_prog_kern.c b/advanced02-BTF/xdp_prog_kern.c new file mode 100644 index 00000000..676fa6e2 --- /dev/null +++ b/advanced02-BTF/xdp_prog_kern.c @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include +#include "bpf_helpers.h" + +#include "common_kern_user.h" /* defines: struct datarec; */ + +/* Lesson: See how a map is defined. + * - Here an array with XDP_ACTION_MAX (max_)entries are created. + * - The idea is to keep stats per (enum) xdp_action + */ +struct bpf_map_def SEC("maps") xdp_stats_map = { + .type = BPF_MAP_TYPE_PERCPU_ARRAY, + .key_size = sizeof(__u32), + .value_size = sizeof(struct datarec), + .max_entries = XDP_ACTION_MAX, +}; + +/* LLVM maps __sync_fetch_and_add() as a built-in function to the BPF atomic add + * instruction (that is BPF_STX | BPF_XADD | BPF_W for word sizes) + */ +#ifndef lock_xadd +#define lock_xadd(ptr, val) ((void) __sync_fetch_and_add(ptr, val)) +#endif + +static __always_inline +__u32 record_xdp_stats_action(struct xdp_md *ctx, __u32 action) +{ + void *data_end = (void *)(long)ctx->data_end; + void *data = (void *)(long)ctx->data; + + if (action >= XDP_ACTION_MAX) + return XDP_ABORTED; + + /* Lookup in kernel BPF-side return pointer to actual data record */ + struct datarec *rec = bpf_map_lookup_elem(&xdp_stats_map, &action); + if (!rec) + return XDP_ABORTED; + + /* Calculate packet length */ + __u64 bytes = data_end - data; + + /* BPF_MAP_TYPE_PERCPU_ARRAY returns a data record specific to current + * CPU and XDP hooks runs under Softirq, which makes it safe to update + * without atomic operations. + */ + rec->rx_packets++; + rec->rx_bytes += bytes; + + return action; +} + +SEC("xdp_pass") +int xdp_pass_func(struct xdp_md *ctx) +{ + __u32 action = XDP_PASS; /* XDP_PASS = 2 */ + + return record_xdp_stats_action(ctx, action); +} + +SEC("xdp_drop") +int xdp_drop_func(struct xdp_md *ctx) +{ + __u32 action = XDP_DROP; + + return record_xdp_stats_action(ctx, action); +} + +SEC("xdp_abort") +int xdp_abort_func(struct xdp_md *ctx) +{ + __u32 action = XDP_ABORTED; + + return record_xdp_stats_action(ctx, action); +} + +char _license[] SEC("license") = "GPL"; + +/* Copied from: $KERNEL/include/uapi/linux/bpf.h + * + * User return codes for XDP prog type. + * A valid XDP program must return one of these defined values. All other + * return codes are reserved for future use. Unknown return codes will + * result in packet drops and a warning via bpf_warn_invalid_xdp_action(). + * +enum xdp_action { + XDP_ABORTED = 0, + XDP_DROP, + XDP_PASS, + XDP_TX, + XDP_REDIRECT, +}; + + * user accessible metadata for XDP packet hook + * new fields must be added to the end of this structure + * +struct xdp_md { + // (Note: type __u32 is NOT the real-type) + __u32 data; + __u32 data_end; + __u32 data_meta; + // Below access go through struct xdp_rxq_info + __u32 ingress_ifindex; // rxq->dev->ifindex + __u32 rx_queue_index; // rxq->queue_index +}; +*/ From 07def46bc7a82d2dd3c17b725cec3f8ccd48119e Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Sun, 17 Mar 2019 16:53:50 +0100 Subject: [PATCH 2/9] advanced02: Add Makefile that use pahole --btf_encode Signed-off-by: Jesper Dangaard Brouer --- advanced02-BTF/Makefile | 45 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 advanced02-BTF/Makefile diff --git a/advanced02-BTF/Makefile b/advanced02-BTF/Makefile new file mode 100644 index 00000000..dda2fd69 --- /dev/null +++ b/advanced02-BTF/Makefile @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) + +XDP_BTF_TARGETS := xdp_prog_kern +XDP_BTF_OBJ = ${XDP_BTF_TARGETS:=.o} + +_all: llvm-check pahole-check $(XDP_BTF_OBJ) + +COMMON_DIR = ../common/ +include $(COMMON_DIR)/common.mk + +PAHOLE ?= pahole + +.PHONY: $(PAHOLE) + +TEST_PAHOLE := "$(PAHOLE) --help 2>&1 | grep BTF" + +pahole-check: $(PAHOLE) + for TOOL in $^ ; do \ + if [ ! $$(command -v $${TOOL} 2>/dev/null) ]; then \ + echo "*** ERROR: Cannot find tool $${TOOL}" ;\ + exit 1; \ + else true; fi; \ + done + echo OOO + if [ ! $(TEST_PAHOLE) > /dev/null 2>&1 ]; then \ + echo "Tool pahole too old, missing BTF support" ;\ + exit 1; \ + else \ + echo "Using pahole to encode BTF info in ELF-object"; \ + fi + +$(XDP_BTF_OBJ): %.o: %.c Makefile $(COMMON_MK) + echo $(USE_PAHOLE) + $(CLANG) -S \ + -target bpf \ + -D __BPF_TRACING__ \ + $(CFLAGS) \ + -Wall \ + -Wno-unused-value \ + -Wno-pointer-sign \ + -Wno-compare-distinct-pointer-types \ + -Werror \ + -O2 -emit-llvm -c -g $< + $(LLC) -march=bpf -filetype=obj -o $@ ${@:.o=.ll} + $(PAHOLE) --btf_encode $@ From 3ce318297da1a50fb3ca3484b54e86a1ec6e1e82 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Sun, 17 Mar 2019 17:09:44 +0100 Subject: [PATCH 3/9] advanced02: BTF annotate BPF-map xdp_stats_map Signed-off-by: Jesper Dangaard Brouer --- advanced02-BTF/xdp_prog_kern.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/advanced02-BTF/xdp_prog_kern.c b/advanced02-BTF/xdp_prog_kern.c index 676fa6e2..1544a7ae 100644 --- a/advanced02-BTF/xdp_prog_kern.c +++ b/advanced02-BTF/xdp_prog_kern.c @@ -4,6 +4,15 @@ #include "common_kern_user.h" /* defines: struct datarec; */ +#define _BPF_ANNOTATE_KV_PAIR(name, type_key, type_val) \ + struct ____btf_map_##name { \ + type_key key; \ + type_val value; \ + }; \ + struct ____btf_map_##name \ + __attribute__ ((section(".maps." #name), used)) \ + ____btf_map_##name = { } + /* Lesson: See how a map is defined. * - Here an array with XDP_ACTION_MAX (max_)entries are created. * - The idea is to keep stats per (enum) xdp_action @@ -14,6 +23,8 @@ struct bpf_map_def SEC("maps") xdp_stats_map = { .value_size = sizeof(struct datarec), .max_entries = XDP_ACTION_MAX, }; +_BPF_ANNOTATE_KV_PAIR(xdp_stats_map, int, struct datarec); + /* LLVM maps __sync_fetch_and_add() as a built-in function to the BPF atomic add * instruction (that is BPF_STX | BPF_XADD | BPF_W for word sizes) From d94a9ead4b5edb79b2c71f1805fa1c4993dbd0f7 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Sun, 17 Mar 2019 17:11:05 +0100 Subject: [PATCH 4/9] advanced02: existing libbpf xdp_loader should work with BTF Signed-off-by: Jesper Dangaard Brouer --- advanced02-BTF/Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/advanced02-BTF/Makefile b/advanced02-BTF/Makefile index dda2fd69..7a6fde64 100644 --- a/advanced02-BTF/Makefile +++ b/advanced02-BTF/Makefile @@ -3,7 +3,9 @@ XDP_BTF_TARGETS := xdp_prog_kern XDP_BTF_OBJ = ${XDP_BTF_TARGETS:=.o} -_all: llvm-check pahole-check $(XDP_BTF_OBJ) +_all: llvm-check pahole-check $(XDP_BTF_OBJ) xdp_loader + +COPY_LOADER := xdp_loader COMMON_DIR = ../common/ include $(COMMON_DIR)/common.mk From fe52243be1001bf9abef3c99a07d1bb1bc44b54a Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Sun, 17 Mar 2019 17:12:54 +0100 Subject: [PATCH 5/9] advanced02: Makefile remove debug output Signed-off-by: Jesper Dangaard Brouer --- advanced02-BTF/Makefile | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/advanced02-BTF/Makefile b/advanced02-BTF/Makefile index 7a6fde64..ceba0283 100644 --- a/advanced02-BTF/Makefile +++ b/advanced02-BTF/Makefile @@ -17,14 +17,13 @@ PAHOLE ?= pahole TEST_PAHOLE := "$(PAHOLE) --help 2>&1 | grep BTF" pahole-check: $(PAHOLE) - for TOOL in $^ ; do \ + @for TOOL in $^ ; do \ if [ ! $$(command -v $${TOOL} 2>/dev/null) ]; then \ echo "*** ERROR: Cannot find tool $${TOOL}" ;\ exit 1; \ else true; fi; \ done - echo OOO - if [ ! $(TEST_PAHOLE) > /dev/null 2>&1 ]; then \ + @if [ ! $(TEST_PAHOLE) > /dev/null 2>&1 ]; then \ echo "Tool pahole too old, missing BTF support" ;\ exit 1; \ else \ @@ -32,7 +31,6 @@ pahole-check: $(PAHOLE) fi $(XDP_BTF_OBJ): %.o: %.c Makefile $(COMMON_MK) - echo $(USE_PAHOLE) $(CLANG) -S \ -target bpf \ -D __BPF_TRACING__ \ From 62f34db8ee35306cc81543ac8292baba547601b6 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Sun, 17 Mar 2019 17:16:48 +0100 Subject: [PATCH 6/9] headers: bpf_helper.h add BPF_ANNOTATE_KV_PAIR Signed-off-by: Jesper Dangaard Brouer --- headers/bpf_helpers.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/headers/bpf_helpers.h b/headers/bpf_helpers.h index 98d6496c..8aa89e4d 100644 --- a/headers/bpf_helpers.h +++ b/headers/bpf_helpers.h @@ -88,6 +88,15 @@ struct bpf_map_def { unsigned int inner_map_idx; }; +#define BPF_ANNOTATE_KV_PAIR(name, type_key, type_val) \ + struct ____btf_map_##name { \ + type_key key; \ + type_val value; \ + }; \ + struct ____btf_map_##name \ + __attribute__ ((section(".maps." #name), used)) \ + ____btf_map_##name = { } + static int (*bpf_skb_load_bytes)(void *ctx, int off, void *to, int len) = (void *) BPF_FUNC_skb_load_bytes; static int (*bpf_skb_store_bytes)(void *ctx, int off, void *from, int len, int flags) = From 5d6b9a7b3b64b72b13b72bf195b21b3e0b57775b Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Sun, 17 Mar 2019 17:44:15 +0100 Subject: [PATCH 7/9] advanced02: adding LLC option -mattr=dwarfris When loading with libbpf I'm getting some BTF loading errors. Adding this doesn't solve the problem, but is looks like I should add it anyhow. Signed-off-by: Jesper Dangaard Brouer --- advanced02-BTF/Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/advanced02-BTF/Makefile b/advanced02-BTF/Makefile index ceba0283..d2cfe49f 100644 --- a/advanced02-BTF/Makefile +++ b/advanced02-BTF/Makefile @@ -30,6 +30,9 @@ pahole-check: $(PAHOLE) echo "Using pahole to encode BTF info in ELF-object"; \ fi +#LLC_FLAGS += -mcpu=probe +LLC_FLAGS += -mattr=dwarfris + $(XDP_BTF_OBJ): %.o: %.c Makefile $(COMMON_MK) $(CLANG) -S \ -target bpf \ @@ -41,5 +44,5 @@ $(XDP_BTF_OBJ): %.o: %.c Makefile $(COMMON_MK) -Wno-compare-distinct-pointer-types \ -Werror \ -O2 -emit-llvm -c -g $< - $(LLC) -march=bpf -filetype=obj -o $@ ${@:.o=.ll} + $(LLC) -march=bpf $(LLC_FLAGS) -filetype=obj -o $@ ${@:.o=.ll} $(PAHOLE) --btf_encode $@ From 617560fc9b286f167f774caf2c3f0147d0d1c8a7 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Sun, 17 Mar 2019 18:02:17 +0100 Subject: [PATCH 8/9] advanced02-BTF: reduce xdp_prog_kern.c program This is still getting rejected when loading BTF. Last error is: [12] Invalid kind:13 Signed-off-by: Jesper Dangaard Brouer --- advanced02-BTF/xdp_prog_kern.c | 57 ---------------------------------- 1 file changed, 57 deletions(-) diff --git a/advanced02-BTF/xdp_prog_kern.c b/advanced02-BTF/xdp_prog_kern.c index 1544a7ae..a3e97951 100644 --- a/advanced02-BTF/xdp_prog_kern.c +++ b/advanced02-BTF/xdp_prog_kern.c @@ -13,10 +13,6 @@ __attribute__ ((section(".maps." #name), used)) \ ____btf_map_##name = { } -/* Lesson: See how a map is defined. - * - Here an array with XDP_ACTION_MAX (max_)entries are created. - * - The idea is to keep stats per (enum) xdp_action - */ struct bpf_map_def SEC("maps") xdp_stats_map = { .type = BPF_MAP_TYPE_PERCPU_ARRAY, .key_size = sizeof(__u32), @@ -25,14 +21,6 @@ struct bpf_map_def SEC("maps") xdp_stats_map = { }; _BPF_ANNOTATE_KV_PAIR(xdp_stats_map, int, struct datarec); - -/* LLVM maps __sync_fetch_and_add() as a built-in function to the BPF atomic add - * instruction (that is BPF_STX | BPF_XADD | BPF_W for word sizes) - */ -#ifndef lock_xadd -#define lock_xadd(ptr, val) ((void) __sync_fetch_and_add(ptr, val)) -#endif - static __always_inline __u32 record_xdp_stats_action(struct xdp_md *ctx, __u32 action) { @@ -68,49 +56,4 @@ int xdp_pass_func(struct xdp_md *ctx) return record_xdp_stats_action(ctx, action); } -SEC("xdp_drop") -int xdp_drop_func(struct xdp_md *ctx) -{ - __u32 action = XDP_DROP; - - return record_xdp_stats_action(ctx, action); -} - -SEC("xdp_abort") -int xdp_abort_func(struct xdp_md *ctx) -{ - __u32 action = XDP_ABORTED; - - return record_xdp_stats_action(ctx, action); -} - char _license[] SEC("license") = "GPL"; - -/* Copied from: $KERNEL/include/uapi/linux/bpf.h - * - * User return codes for XDP prog type. - * A valid XDP program must return one of these defined values. All other - * return codes are reserved for future use. Unknown return codes will - * result in packet drops and a warning via bpf_warn_invalid_xdp_action(). - * -enum xdp_action { - XDP_ABORTED = 0, - XDP_DROP, - XDP_PASS, - XDP_TX, - XDP_REDIRECT, -}; - - * user accessible metadata for XDP packet hook - * new fields must be added to the end of this structure - * -struct xdp_md { - // (Note: type __u32 is NOT the real-type) - __u32 data; - __u32 data_end; - __u32 data_meta; - // Below access go through struct xdp_rxq_info - __u32 ingress_ifindex; // rxq->dev->ifindex - __u32 rx_queue_index; // rxq->queue_index -}; -*/ From fa6958c23b8a07fdee3343c872658b611faefceb Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Sun, 17 Mar 2019 18:20:54 +0100 Subject: [PATCH 9/9] advanced02: record pahole BTF conversion verbose info in file Signed-off-by: Jesper Dangaard Brouer --- advanced02-BTF/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/advanced02-BTF/Makefile b/advanced02-BTF/Makefile index d2cfe49f..9fea1961 100644 --- a/advanced02-BTF/Makefile +++ b/advanced02-BTF/Makefile @@ -45,4 +45,4 @@ $(XDP_BTF_OBJ): %.o: %.c Makefile $(COMMON_MK) -Werror \ -O2 -emit-llvm -c -g $< $(LLC) -march=bpf $(LLC_FLAGS) -filetype=obj -o $@ ${@:.o=.ll} - $(PAHOLE) --btf_encode $@ + $(PAHOLE) -V --btf_encode $@ > ${@:.o=.pahole-btf-info}