From bddbc54b5c65df35b40e188c7d30a39d196e8f93 Mon Sep 17 00:00:00 2001 From: gray Date: Thu, 5 Dec 2024 01:57:32 +0800 Subject: [PATCH] Collect and output skb->cb when --filter-trace-tc According to kernel verifier implementation[1], __sk_buff->cb will be mapped to ((struct qdisc_skb_cb*)&sk_buff->cb)->data, let's collect 20 bytes from there and output cb as u32[5] when --filter-trace-tc is turned on. [1] https://elixir.bootlin.com/linux/v6.8/source/net/core/filter.c#L9593 Signed-off-by: gray --- bpf/kprobe_pwru.c | 10 ++++++++-- internal/pwru/config.go | 4 ++++ internal/pwru/output.go | 18 ++++++++++++++++++ internal/pwru/types.go | 2 +- 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/bpf/kprobe_pwru.c b/bpf/kprobe_pwru.c index c91d0a87..73dbec0c 100644 --- a/bpf/kprobe_pwru.c +++ b/bpf/kprobe_pwru.c @@ -54,7 +54,7 @@ struct skb_meta { u32 len; u32 mtu; u16 protocol; - u16 pad; + u32 cb[5]; } __attribute__((packed)); struct tuple { @@ -143,7 +143,8 @@ struct config { u8 output_shinfo: 1; u8 output_stack: 1; u8 output_caller: 1; - u8 output_unused: 2; + u8 output_cb: 1; + u8 output_unused: 1; u8 is_set: 1; u8 track_skb: 1; u8 track_skb_by_stackid: 1; @@ -443,6 +444,11 @@ set_output(void *ctx, struct sk_buff *skb, struct event_t *event) { if (cfg->output_stack) { event->print_stack_id = bpf_get_stackid(ctx, &print_stack_map, BPF_F_FAST_STACK_CMP); } + + if (cfg->output_cb) { + struct qdisc_skb_cb *cb = (struct qdisc_skb_cb *)&skb->cb; + bpf_probe_read_kernel(&event->meta.cb, sizeof(event->meta.cb), (void *)&cb->data); + } } static __noinline bool diff --git a/internal/pwru/config.go b/internal/pwru/config.go index 1f7d8b23..4fbc4532 100644 --- a/internal/pwru/config.go +++ b/internal/pwru/config.go @@ -22,6 +22,7 @@ const ( OutputShinfoMask OutputStackMask OutputCallerMask + OutputCbMask ) const ( @@ -69,6 +70,9 @@ func GetConfig(flags *Flags) (cfg FilterCfg, err error) { if flags.OutputCaller { cfg.OutputFlags |= OutputCallerMask } + if flags.FilterTraceTc { + cfg.OutputFlags |= OutputCbMask + } if flags.FilterTrackSkb { cfg.FilterFlags |= TrackSkbMask } diff --git a/internal/pwru/output.go b/internal/pwru/output.go index 254b9064..35d15a5b 100644 --- a/internal/pwru/output.go +++ b/internal/pwru/output.go @@ -64,6 +64,7 @@ type jsonPrinter struct { Proto uint16 `json:"proto,omitempty"` Mtu uint32 `json:"mtu,omitempty"` Len uint32 `json:"len,omitempty"` + Cb [5]uint32 `json:"cb,omitempty"` Tuple *jsonTuple `json:"tuple,omitempty"` Stack interface{} `json:"stack,omitempty"` SkbMetadata interface{} `json:"skb_metadata,omitempty"` @@ -141,6 +142,9 @@ func (o *output) PrintHeader() { } if o.flags.OutputMeta { fmt.Fprintf(o.writer, " %-10s %-8s %16s %-6s %-5s %-5s", "NETNS", "MARK/x", centerAlignString("IFACE", 16), "PROTO", "MTU", "LEN") + if o.flags.FilterTraceTc { + fmt.Fprintf(o.writer, " %-56s", "__sk_buff->cb[]") + } } if o.flags.OutputTuple { fmt.Fprintf(o.writer, " %s", "TUPLE") @@ -187,6 +191,9 @@ func (o *output) PrintJson(event *Event) { d.Proto = byteorder.NetworkToHost16(event.Meta.Proto) d.Mtu = event.Meta.MTU d.Len = event.Meta.Len + if o.flags.FilterTraceTc { + d.Cb = event.Meta.Cb + } } if o.flags.OutputTuple { @@ -330,6 +337,14 @@ func getMetaData(event *Event, o *output) (metaData string) { return metaData } +func getCb(event *Event) (cb string) { + res := []string{} + for _, val := range event.Meta.Cb { + res = append(res, fmt.Sprintf("0x%08X", val)) + } + return fmt.Sprintf("[%s]", strings.Join(res, ",")) +} + func getOutFuncName(o *output, event *Event, addr uint64) string { var funcName string @@ -410,6 +425,9 @@ func (o *output) Print(event *Event) { if o.flags.OutputMeta { fmt.Fprintf(o.writer, " %s", getMetaData(event, o)) + if o.flags.FilterTraceTc { + fmt.Fprintf(o.writer, " %s", getCb(event)) + } } if o.flags.OutputTuple { diff --git a/internal/pwru/types.go b/internal/pwru/types.go index b6276487..c75d419e 100644 --- a/internal/pwru/types.go +++ b/internal/pwru/types.go @@ -130,7 +130,7 @@ type Meta struct { Len uint32 MTU uint32 Proto uint16 - Pad uint16 + Cb [5]uint32 } type StackData struct {