Re: [RFC PATCH bpf-next 3/4] bpf: add bpf_trace_btf helper

From: Andrii Nakryiko
Date: Thu Aug 20 2020 - 02:36:15 EST


On Thu, Aug 6, 2020 at 1:24 PM Alan Maguire <alan.maguire@xxxxxxxxxx> wrote:
>
> A helper is added to support tracing kernel type information in BPF
> using the BPF Type Format (BTF). Its signature is
>
> long bpf_trace_btf(struct btf_ptr *ptr, u32 btf_ptr_size, u32 trace_id,
> u64 flags);
>
> struct btf_ptr * specifies
>
> - a pointer to the data to be traced;
> - the BTF id of the type of data pointed to; or
> - a string representation of the type of data pointed to
> - a flags field is provided for future use; these flags
> are not to be confused with the BTF_TRACE_F_* flags
> below that control how the btf_ptr is displayed; the
> flags member of the struct btf_ptr may be used to
> disambiguate types in kernel versus module BTF, etc;
> the main distinction is the flags relate to the type
> and information needed in identifying it; not how it
> is displayed.
>
> The helper also specifies a trace id which is set for the
> bpf_trace_printk tracepoint; this allows BPF programs
> to filter on specific trace ids, ensuring output does
> not become mixed between different traced events and
> hard to read.
>
> For example a BPF program with a struct sk_buff *skb
> could do the following:
>
> static const char *skb_type = "struct sk_buff";
> static struct btf_ptr b = { };
>
> b.ptr = skb;
> b.type = skb_type;
> bpf_trace_btf(&b, sizeof(b), 0, 0);
>
> Default output in the trace_pipe looks like this:
>
> <idle>-0 [023] d.s. 1825.778400: bpf_trace_printk: (struct sk_buff){
> <idle>-0 [023] d.s. 1825.778409: bpf_trace_printk: (union){
> <idle>-0 [023] d.s. 1825.778410: bpf_trace_printk: (struct){
> <idle>-0 [023] d.s. 1825.778412: bpf_trace_printk: .prev = (struct sk_buff *)0x00000000b2a3df7e,
> <idle>-0 [023] d.s. 1825.778413: bpf_trace_printk: (union){
> <idle>-0 [023] d.s. 1825.778414: bpf_trace_printk: .dev = (struct net_device *)0x000000001658808b,
> <idle>-0 [023] d.s. 1825.778416: bpf_trace_printk: .dev_scratch = (long unsigned int)18446628460391432192,
> <idle>-0 [023] d.s. 1825.778417: bpf_trace_printk: },
> <idle>-0 [023] d.s. 1825.778417: bpf_trace_printk: },
> <idle>-0 [023] d.s. 1825.778418: bpf_trace_printk: .rbnode = (struct rb_node){
> <idle>-0 [023] d.s. 1825.778419: bpf_trace_printk: .rb_right = (struct rb_node *)0x00000000b2a3df7e,
> <idle>-0 [023] d.s. 1825.778420: bpf_trace_printk: .rb_left = (struct rb_node *)0x000000001658808b,
> <idle>-0 [023] d.s. 1825.778420: bpf_trace_printk: },
> <idle>-0 [023] d.s. 1825.778421: bpf_trace_printk: .list = (struct list_head){
> <idle>-0 [023] d.s. 1825.778422: bpf_trace_printk: .prev = (struct list_head *)0x00000000b2a3df7e,
> <idle>-0 [023] d.s. 1825.778422: bpf_trace_printk: },
> <idle>-0 [023] d.s. 1825.778422: bpf_trace_printk: },
> <idle>-0 [023] d.s. 1825.778426: bpf_trace_printk: .len = (unsigned int)168,
> <idle>-0 [023] d.s. 1825.778427: bpf_trace_printk: .mac_len = (__u16)14,
> <idle>-0 [023] d.s. 1825.778428: bpf_trace_printk: .queue_mapping = (__u16)17,
> <idle>-0 [023] d.s. 1825.778430: bpf_trace_printk: .head_frag = (__u8)0x1,
> <idle>-0 [023] d.s. 1825.778431: bpf_trace_printk: .ip_summed = (__u8)0x1,
> <idle>-0 [023] d.s. 1825.778432: bpf_trace_printk: .l4_hash = (__u8)0x1,
> <idle>-0 [023] d.s. 1825.778433: bpf_trace_printk: .hash = (__u32)1873247608,
> <idle>-0 [023] d.s. 1825.778434: bpf_trace_printk: (union){
> <idle>-0 [023] d.s. 1825.778435: bpf_trace_printk: .napi_id = (unsigned int)8209,
> <idle>-0 [023] d.s. 1825.778436: bpf_trace_printk: .sender_cpu = (unsigned int)8209,
> <idle>-0 [023] d.s. 1825.778436: bpf_trace_printk: },
> <idle>-0 [023] d.s. 1825.778437: bpf_trace_printk: .protocol = (__be16)8,
> <idle>-0 [023] d.s. 1825.778438: bpf_trace_printk: .transport_header = (__u16)226,
> <idle>-0 [023] d.s. 1825.778439: bpf_trace_printk: .network_header = (__u16)206,
> <idle>-0 [023] d.s. 1825.778440: bpf_trace_printk: .mac_header = (__u16)192,
> <idle>-0 [023] d.s. 1825.778440: bpf_trace_printk: .tail = (sk_buff_data_t)374,
> <idle>-0 [023] d.s. 1825.778441: bpf_trace_printk: .end = (sk_buff_data_t)1728,
> <idle>-0 [023] d.s. 1825.778442: bpf_trace_printk: .head = (unsigned char *)0x000000009798cb6b,
> <idle>-0 [023] d.s. 1825.778443: bpf_trace_printk: .data = (unsigned char *)0x0000000064823282,
> <idle>-0 [023] d.s. 1825.778444: bpf_trace_printk: .truesize = (unsigned int)2304,
> <idle>-0 [023] d.s. 1825.778445: bpf_trace_printk: .users = (refcount_t){
> <idle>-0 [023] d.s. 1825.778445: bpf_trace_printk: .refs = (atomic_t){
> <idle>-0 [023] d.s. 1825.778447: bpf_trace_printk: .counter = (int)1,
> <idle>-0 [023] d.s. 1825.778447: bpf_trace_printk: },
> <idle>-0 [023] d.s. 1825.778447: bpf_trace_printk: },
> <idle>-0 [023] d.s. 1825.778448: bpf_trace_printk: }
>
> Flags modifying display are as follows:
>
> - BTF_TRACE_F_COMPACT: no formatting around type information
> - BTF_TRACE_F_NONAME: no struct/union member names/types
> - BTF_TRACE_F_PTR_RAW: show raw (unobfuscated) pointer values;
> equivalent to %px.
> - BTF_TRACE_F_ZERO: show zero-valued struct/union members;
> they are not displayed by default
>
> Signed-off-by: Alan Maguire <alan.maguire@xxxxxxxxxx>
> ---
> include/linux/bpf.h | 1 +
> include/linux/btf.h | 9 ++--
> include/uapi/linux/bpf.h | 63 +++++++++++++++++++++++++
> kernel/bpf/core.c | 5 ++
> kernel/bpf/helpers.c | 4 ++
> kernel/trace/bpf_trace.c | 102 ++++++++++++++++++++++++++++++++++++++++-
> scripts/bpf_helpers_doc.py | 2 +
> tools/include/uapi/linux/bpf.h | 63 +++++++++++++++++++++++++
> 8 files changed, 243 insertions(+), 6 deletions(-)
>

[...]

> +/*
> + * struct btf_ptr is used for typed pointer display; the
> + * additional type string/BTF type id are used to render the pointer
> + * data as the appropriate type via the bpf_trace_btf() helper
> + * above. A flags field - potentially to specify additional details
> + * about the BTF pointer (rather than its mode of display) - is
> + * present for future use. Display flags - BTF_TRACE_F_* - are
> + * passed to display functions separately.
> + */
> +struct btf_ptr {
> + void *ptr;
> + const char *type;
> + __u32 type_id;
> + __u32 flags; /* BTF ptr flags; unused at present. */
> +};

Would it be possible to just utilize __builtin_btf_type_id() to pass
BTF type id directly, without this string -> BTF type translation?
Please check [0] to see if that would make sense here. Thanks.

[0] https://patchwork.ozlabs.org/project/netdev/patch/20200819194519.3375898-4-andriin@xxxxxx/

[...]