[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20190426182057.7d54qljtiah5aump@kafai-mbp.dhcp.thefacebook.com>
Date: Fri, 26 Apr 2019 18:21:00 +0000
From: Martin Lau <kafai@...com>
To: Yonghong Song <yhs@...com>
CC: "bpf@...r.kernel.org" <bpf@...r.kernel.org>,
"netdev@...r.kernel.org" <netdev@...r.kernel.org>,
Alexei Starovoitov <ast@...com>,
Andrii Nakryiko <andriin@...com>,
Daniel Borkmann <daniel@...earbox.net>,
John Fastabend <john.fastabend@...il.com>,
Kernel Team <Kernel-team@...com>
Subject: Re: [PATCH v3 bpf-next 3/6] bpf: Support BPF_MAP_TYPE_SK_STORAGE in
bpf map probing
On Fri, Apr 26, 2019 at 10:50:29AM -0700, Yonghong Song wrote:
>
>
> On 4/26/19 10:11 AM, Martin KaFai Lau wrote:
> > This patch supports probing for the new BPF_MAP_TYPE_SK_STORAGE.
> > BPF_MAP_TYPE_SK_STORAGE enforces BTF usage, so the new probe
> > requires to create and load a BTF also.
> >
> > Signed-off-by: Martin KaFai Lau <kafai@...com>
> > ---
> > tools/bpf/bpftool/map.c | 1 +
> > tools/lib/bpf/libbpf_probes.c | 74 ++++++++++++++++++++++++++++++++++-
> > 2 files changed, 74 insertions(+), 1 deletion(-)
> >
> > diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c
> > index 10b6c9d3e525..693ab3da37de 100644
> > --- a/tools/bpf/bpftool/map.c
> > +++ b/tools/bpf/bpftool/map.c
> > @@ -46,6 +46,7 @@ const char * const map_type_name[] = {
> > [BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE] = "percpu_cgroup_storage",
> > [BPF_MAP_TYPE_QUEUE] = "queue",
> > [BPF_MAP_TYPE_STACK] = "stack",
> > + [BPF_MAP_TYPE_SK_STORAGE] = "sk_storage",
> > };
> >
> > const size_t map_type_name_size = ARRAY_SIZE(map_type_name);
> > diff --git a/tools/lib/bpf/libbpf_probes.c b/tools/lib/bpf/libbpf_probes.c
> > index 0f25541632e3..2e26ddb005e4 100644
> > --- a/tools/lib/bpf/libbpf_probes.c
> > +++ b/tools/lib/bpf/libbpf_probes.c
> > @@ -9,6 +9,7 @@
> > #include <net/if.h>
> > #include <sys/utsname.h>
> >
> > +#include <linux/btf.h>
> > #include <linux/filter.h>
> > #include <linux/kernel.h>
> >
> > @@ -130,11 +131,65 @@ bool bpf_probe_prog_type(enum bpf_prog_type prog_type, __u32 ifindex)
> > return errno != EINVAL && errno != EOPNOTSUPP;
> > }
> >
> > +static int load_btf(void)
> > +{
> > +#define BTF_INFO_ENC(kind, kind_flag, vlen) \
> > + ((!!(kind_flag) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN))
> > +#define BTF_TYPE_ENC(name, info, size_or_type) \
> > + (name), (info), (size_or_type)
> > +#define BTF_INT_ENC(encoding, bits_offset, nr_bits) \
> > + ((encoding) << 24 | (bits_offset) << 16 | (nr_bits))
> > +#define BTF_TYPE_INT_ENC(name, encoding, bits_offset, bits, sz) \
> > + BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_INT, 0, 0), sz), \
> > + BTF_INT_ENC(encoding, bits_offset, bits)
> > +#define BTF_MEMBER_ENC(name, type, bits_offset) \
> > + (name), (type), (bits_offset)
> > +
> > + const char btf_str_sec[] = "\0bpf_spin_lock\0val\0cnt\0l";
> > + /* struct bpf_spin_lock {
> > + * int val;
> > + * };
> > + * struct val {
> > + * int cnt;
> > + * struct bpf_spin_lock l;
> > + * };
> > + */
> > + __u32 btf_raw_types[] = {
> > + /* int */
> > + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
> > + /* struct bpf_spin_lock */ /* [2] */
> > + BTF_TYPE_ENC(1, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), 4),
> > + BTF_MEMBER_ENC(15, 1, 0), /* int val; */
> > + /* struct val */ /* [3] */
> > + BTF_TYPE_ENC(15, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 8),
> > + BTF_MEMBER_ENC(19, 1, 0), /* int cnt; */
> > + BTF_MEMBER_ENC(23, 2, 32),/* struct bpf_spin_lock l; */
> > + };
> > + struct btf_header btf_hdr = {
> > + .magic = BTF_MAGIC,
> > + .version = BTF_VERSION,
> > + .hdr_len = sizeof(struct btf_header),
> > + .type_len = sizeof(btf_raw_types),
> > + .str_off = sizeof(btf_raw_types),
> > + .str_len = sizeof(btf_str_sec),
> > + };
> > + __u8 raw_btf[sizeof(struct btf_header) + sizeof(btf_raw_types) +
> > + sizeof(btf_str_sec)];
> > +
> > + memcpy(raw_btf, &btf_hdr, sizeof(btf_hdr));
> > + memcpy(raw_btf + sizeof(btf_hdr), btf_raw_types, sizeof(btf_raw_types));
> > + memcpy(raw_btf + sizeof(btf_hdr) + sizeof(btf_raw_types),
> > + btf_str_sec, sizeof(btf_str_sec));
> > +
> > + return bpf_load_btf(raw_btf, sizeof(raw_btf), 0, 0, 0);
> > +}
>
> In the future, different map types could want to test different type
> configurations. Maybe btf_raw_types and btf_str_sec could be provided
> as a parameter for load_btf()?
I think it will be cleaner to keep one btf_raw_types[].
Other types can be added to the same btf_raw_types[] later instead of
redefining int/long/unsigned...etc. The bpf_probe_map_type() can
point the btf_key_type_id and btf_value_type_id to different type_id.
It can be revisited if it needs to probe some newly introduced BTF type
(in the type section) later which I think should be very rare.
>
> > +
> > bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex)
> > {
> > int key_size, value_size, max_entries, map_flags;
> > + __u32 btf_key_type_id = 0, btf_value_type_id = 0;
> > struct bpf_create_map_attr attr = {};
> > - int fd = -1, fd_inner;
> > + int fd = -1, btf_fd = -1, fd_inner;
> >
> > key_size = sizeof(__u32);
> > value_size = sizeof(__u32);
> > @@ -160,6 +215,16 @@ bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex)
> > case BPF_MAP_TYPE_STACK:
> > key_size = 0;
> > break;
> > + case BPF_MAP_TYPE_SK_STORAGE:
> > + btf_key_type_id = 1;
> > + btf_value_type_id = 3;
> > + value_size = 8;
> > + max_entries = 0;
> > + map_flags = BPF_F_NO_PREALLOC;
> > + btf_fd = load_btf();
> > + if (btf_fd < 0)
> > + return false;
> > + break;
> > case BPF_MAP_TYPE_UNSPEC:
> > case BPF_MAP_TYPE_HASH:
> > case BPF_MAP_TYPE_ARRAY:
> > @@ -205,11 +270,18 @@ bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex)
> > attr.max_entries = max_entries;
> > attr.map_flags = map_flags;
> > attr.map_ifindex = ifindex;
> > + if (btf_fd >= 0) {
> > + attr.btf_fd = btf_fd;
> > + attr.btf_key_type_id = btf_key_type_id;
> > + attr.btf_value_type_id = btf_value_type_id;
> > + }
> >
> > fd = bpf_create_map_xattr(&attr);
> > }
> > if (fd >= 0)
> > close(fd);
> > + if (btf_fd >= 0)
> > + close(btf_fd);
> >
> > return fd >= 0;
> > }
> >
Powered by blists - more mailing lists