diff --git a/testing/pwru/APKBUILD b/testing/pwru/APKBUILD index 3f8bbf045d0..74797092ea0 100644 --- a/testing/pwru/APKBUILD +++ b/testing/pwru/APKBUILD @@ -7,7 +7,10 @@ url="https://github.com/cilium/pwru" arch="x86_64 aarch64" # the only platforms supported upstream license="GPL-2.0-or-later" makedepends="go clang llvm libpcap-dev" -source="$pkgname-$pkgver.tar.gz::https://github.com/cilium/pwru/archive/refs/tags/v$pkgver.tar.gz" +source="$pkgname-$pkgver.tar.gz::https://github.com/cilium/pwru/archive/refs/tags/v$pkgver.tar.gz + invalid-xadd-389.patch + " +options="net" # go packages export GOCACHE="${GOCACHE:-"$srcdir/go-cache"}" export GOTMPDIR="${GOTMPDIR:-"$srcdir"}" @@ -31,4 +34,5 @@ package() { sha512sums=" 3192426824d8261a4f637622c43361f2b6855e42b6791432ca254794ff8b19e002aa8da3cbc08e8f1b19562f480c0bde0aa2d4aca8f19f952bd54bc96a695256 pwru-1.0.7.tar.gz +a7e2f2aaf3880ee5d205fd73a34ec49c6518b800e7f648e8aeadfced7c5f8370c0d6dca5d777569472fc28d01f653cc2fa99aa982ea61bc89e003ba953e1aff2 invalid-xadd-389.patch " diff --git a/testing/pwru/invalid-xadd-389.patch b/testing/pwru/invalid-xadd-389.patch new file mode 100644 index 00000000000..e5f6e79ed87 --- /dev/null +++ b/testing/pwru/invalid-xadd-389.patch @@ -0,0 +1,228 @@ +see https://github.com/cilium/pwru/issues/389 + +From ce21b830c469a25a1d4baca482322aabd2b36066 Mon Sep 17 00:00:00 2001 +From: gray +Date: Wed, 7 Aug 2024 17:19:34 +0800 +Subject: [PATCH] bpf: Use percpu array to replace __sync_fetch_and_add + +Fixes: https://github.com/cilium/pwru/issues/409 + +Signed-off-by: gray +--- + bpf/kprobe_pwru.c | 78 ++++++++++++++++++++--------------------- + internal/pwru/output.go | 19 +++++----- + 2 files changed, 47 insertions(+), 50 deletions(-) + +diff --git a/bpf/kprobe_pwru.c b/bpf/kprobe_pwru.c +index 092f53a4..73c8d950 100644 +--- a/bpf/kprobe_pwru.c ++++ b/bpf/kprobe_pwru.c +@@ -28,6 +28,7 @@ + + + const static bool TRUE = true; ++const static u32 ZERO = 0; + + volatile const static __u64 BPF_PROG_ADDR = 0; + +@@ -65,9 +66,6 @@ struct tuple { + u8 pad; + } __attribute__((packed)); + +-u64 print_skb_id = 0; +-u64 print_shinfo_id = 0; +- + enum event_type { + EVENT_TYPE_KPROBE = 0, + EVENT_TYPE_TC = 1, +@@ -81,8 +79,8 @@ struct event_t { + u64 caller_addr; + u64 skb_head; + u64 ts; +- typeof(print_skb_id) print_skb_id; +- typeof(print_shinfo_id) print_shinfo_id; ++ u64 print_skb_id; ++ u64 print_shinfo_id; + struct skb_meta meta; + struct tuple tuple; + s64 print_stack_id; +@@ -164,15 +162,27 @@ struct print_shinfo_value { + char str[PRINT_SHINFO_STR_SIZE]; + }; + struct { +- __uint(type, BPF_MAP_TYPE_ARRAY); +- __uint(max_entries, 256); ++ __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); ++ __uint(max_entries, 1); + __type(key, u32); ++ __type(value, u32); ++} print_skb_id_map SEC(".maps"); ++struct { ++ __uint(type, BPF_MAP_TYPE_HASH); ++ __uint(max_entries, 256); ++ __type(key, u64); + __type(value, struct print_skb_value); + } print_skb_map SEC(".maps"); + struct { +- __uint(type, BPF_MAP_TYPE_ARRAY); +- __uint(max_entries, 256); ++ __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); ++ __uint(max_entries, 1); + __type(key, u32); ++ __type(value, u32); ++} print_shinfo_id_map SEC(".maps"); ++struct { ++ __uint(type, BPF_MAP_TYPE_HASH); ++ __uint(max_entries, 256); ++ __type(key, u64); + __type(value, struct print_shinfo_value); + } print_shinfo_map SEC(".maps"); + #endif +@@ -312,45 +322,42 @@ set_tuple(struct sk_buff *skb, struct tuple *tpl) { + __set_tuple(tpl, skb_head, l3_off, is_ipv4); + } + ++static __always_inline u64 ++sync_fetch_and_add(void *id_map) { ++ u32 *id = bpf_map_lookup_elem(id_map, &ZERO); ++ if (id) ++ return ((*id)++) | ((u64)bpf_get_smp_processor_id() << 32); ++ return 0; ++} + + static __always_inline void +-set_skb_btf(struct sk_buff *skb, typeof(print_skb_id) *event_id) { ++set_skb_btf(struct sk_buff *skb, u64 *event_id) { + #ifdef OUTPUT_SKB + static struct btf_ptr p = {}; +- struct print_skb_value *v; +- typeof(print_skb_id) id; +- long n; ++ static struct print_skb_value v = {}; ++ u64 id; + + p.type_id = bpf_core_type_id_kernel(struct sk_buff); + p.ptr = skb; +- id = __sync_fetch_and_add(&print_skb_id, 1) % 256; ++ *event_id = sync_fetch_and_add(&print_skb_id_map); + +- v = bpf_map_lookup_elem(&print_skb_map, (u32 *) &id); +- if (!v) { ++ v.len = bpf_snprintf_btf(v.str, PRINT_SKB_STR_SIZE, &p, sizeof(p), 0); ++ if (v.len < 0) { + return; + } + +- n = bpf_snprintf_btf(v->str, PRINT_SKB_STR_SIZE, &p, sizeof(p), 0); +- if (n < 0) { +- return; +- } +- +- v->len = n; +- +- *event_id = id; ++ bpf_map_update_elem(&print_skb_map, event_id, &v, BPF_ANY); + #endif + } + + static __always_inline void +-set_shinfo_btf(struct sk_buff *skb, typeof(print_shinfo_id) *event_id) { ++set_shinfo_btf(struct sk_buff *skb, u64 *event_id) { + #ifdef OUTPUT_SKB + struct skb_shared_info *shinfo; + static struct btf_ptr p = {}; +- struct print_shinfo_value *v; +- typeof(print_shinfo_id) id; ++ static struct print_shinfo_value v = {}; + unsigned char *head; + unsigned int end; +- long n; + + /* skb_shared_info is located at the end of skb data. + * When CONFIG_NET_SKBUFF_DATA_USES_OFFSET is enabled, skb->end +@@ -366,21 +373,14 @@ set_shinfo_btf(struct sk_buff *skb, typeof(print_shinfo_id) *event_id) { + p.type_id = bpf_core_type_id_kernel(struct skb_shared_info); + p.ptr = shinfo; + +- id = __sync_fetch_and_add(&print_shinfo_id, 1) % 256; ++ *event_id = sync_fetch_and_add(&print_shinfo_id_map); + +- v = bpf_map_lookup_elem(&print_shinfo_map, (u32 *) &id); +- if (!v) { ++ v.len = bpf_snprintf_btf(v.str, PRINT_SHINFO_STR_SIZE, &p, sizeof(p), 0); ++ if (v.len < 0) { + return; + } + +- n = bpf_snprintf_btf(v->str, PRINT_SHINFO_STR_SIZE, &p, sizeof(p), 0); +- if (n < 0) { +- return; +- } +- +- v->len = n; +- +- *event_id = id; ++ bpf_map_update_elem(&print_shinfo_map, event_id, &v, BPF_ANY); + #endif + } + +diff --git a/internal/pwru/output.go b/internal/pwru/output.go +index b284b5a8..189f7371 100644 +--- a/internal/pwru/output.go ++++ b/internal/pwru/output.go +@@ -5,7 +5,6 @@ + package pwru + + import ( +- "encoding/binary" + "encoding/json" + "errors" + "fmt" +@@ -287,39 +286,37 @@ func getStackData(event *Event, o *output) (stackData string) { + } + + func getSkbData(event *Event, o *output) (skbData string) { +- id := uint32(event.PrintSkbId) ++ id := uint64(event.PrintSkbId) + + b, err := o.printSkbMap.LookupBytes(&id) + if err != nil { + return "" + } + +- length := binary.NativeEndian.Uint32(b[:4]) ++ defer o.printSkbMap.Delete(&id) + +- // Bounds check +- if int(length+4) > len(b) { ++ if len(b) < 4 { + return "" + } + +- return "\n" + string(b[4:4+length]) ++ return "\n" + string(b[4:]) + } + + func getShinfoData(event *Event, o *output) (shinfoData string) { +- id := uint32(event.PrintShinfoId) ++ id := uint64(event.PrintShinfoId) + + b, err := o.printShinfoMap.LookupBytes(&id) + if err != nil { + return "" + } + +- length := binary.NativeEndian.Uint32(b[:4]) ++ defer o.printShinfoMap.Delete(&id) + +- // Bounds check +- if int(length+4) > len(b) { ++ if len(b) < 4 { + return "" + } + +- return "\n" + string(b[4:4+length]) ++ return "\n" + string(b[4:]) + } + + func getMetaData(event *Event, o *output) (metaData string) {