Skip to content

Commit f0fdfef

Browse files
Alexei Starovoitovborkmann
authored andcommitted
bpf: Add BPF program and map iterators as built-in BPF programs.
The program and map iterators work similar to seq_file-s. Once the program is pinned in bpffs it can be read with "cat" tool to print human readable output. In this case about BPF programs and maps. For example: $ cat /sys/fs/bpf/progs.debug id name attached 5 dump_bpf_map bpf_iter_bpf_map 6 dump_bpf_prog bpf_iter_bpf_prog $ cat /sys/fs/bpf/maps.debug id name max_entries 3 iterator.rodata 1 To avoid kernel build dependency on clang 10 separate bpf skeleton generation into manual "make" step and instead check-in generated .skel.h into git. Unlike 'bpftool prog show' in-kernel BTF name is used (when available) to print full name of BPF program instead of 16-byte truncated name. Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Andrii Nakryiko <andriin@fb.com> Link: https://lore.kernel.org/bpf/20200819042759.51280-3-alexei.starovoitov@gmail.com
1 parent 005142b commit f0fdfef

File tree

5 files changed

+587
-0
lines changed

5 files changed

+587
-0
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# SPDX-License-Identifier: GPL-2.0-only
2+
/.output
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# SPDX-License-Identifier: GPL-2.0
2+
OUTPUT := .output
3+
CLANG ?= clang
4+
LLC ?= llc
5+
LLVM_STRIP ?= llvm-strip
6+
DEFAULT_BPFTOOL := $(OUTPUT)/sbin/bpftool
7+
BPFTOOL ?= $(DEFAULT_BPFTOOL)
8+
LIBBPF_SRC := $(abspath ../../../../tools/lib/bpf)
9+
BPFOBJ := $(OUTPUT)/libbpf.a
10+
BPF_INCLUDE := $(OUTPUT)
11+
INCLUDES := -I$(OUTPUT) -I$(BPF_INCLUDE) -I$(abspath ../../../../tools/lib) \
12+
-I$(abspath ../../../../tools/include/uapi)
13+
CFLAGS := -g -Wall
14+
15+
abs_out := $(abspath $(OUTPUT))
16+
ifeq ($(V),1)
17+
Q =
18+
msg =
19+
else
20+
Q = @
21+
msg = @printf ' %-8s %s%s\n' "$(1)" "$(notdir $(2))" "$(if $(3), $(3))";
22+
MAKEFLAGS += --no-print-directory
23+
submake_extras := feature_display=0
24+
endif
25+
26+
.DELETE_ON_ERROR:
27+
28+
.PHONY: all clean
29+
30+
all: iterators.skel.h
31+
32+
clean:
33+
$(call msg,CLEAN)
34+
$(Q)rm -rf $(OUTPUT) iterators
35+
36+
iterators.skel.h: $(OUTPUT)/iterators.bpf.o | $(BPFTOOL)
37+
$(call msg,GEN-SKEL,$@)
38+
$(Q)$(BPFTOOL) gen skeleton $< > $@
39+
40+
41+
$(OUTPUT)/iterators.bpf.o: iterators.bpf.c $(BPFOBJ) | $(OUTPUT)
42+
$(call msg,BPF,$@)
43+
$(Q)$(CLANG) -g -O2 -target bpf $(INCLUDES) \
44+
-c $(filter %.c,$^) -o $@ && \
45+
$(LLVM_STRIP) -g $@
46+
47+
$(OUTPUT):
48+
$(call msg,MKDIR,$@)
49+
$(Q)mkdir -p $(OUTPUT)
50+
51+
$(BPFOBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(OUTPUT)
52+
$(Q)$(MAKE) $(submake_extras) -C $(LIBBPF_SRC) \
53+
OUTPUT=$(abspath $(dir $@))/ $(abspath $@)
54+
55+
$(DEFAULT_BPFTOOL):
56+
$(Q)$(MAKE) $(submake_extras) -C ../../../../tools/bpf/bpftool \
57+
prefix= OUTPUT=$(abs_out)/ DESTDIR=$(abs_out) install
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
WARNING:
2+
If you change "iterators.bpf.c" do "make -j" in this directory to rebuild "iterators.skel.h".
3+
Make sure to have clang 10 installed.
4+
See Documentation/bpf/bpf_devel_QA.rst
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2020 Facebook */
3+
#include <linux/bpf.h>
4+
#include <bpf/bpf_helpers.h>
5+
#include <bpf/bpf_tracing.h>
6+
#include <bpf/bpf_core_read.h>
7+
8+
#pragma clang attribute push (__attribute__((preserve_access_index)), apply_to = record)
9+
struct seq_file;
10+
struct bpf_iter_meta {
11+
struct seq_file *seq;
12+
__u64 session_id;
13+
__u64 seq_num;
14+
};
15+
16+
struct bpf_map {
17+
__u32 id;
18+
char name[16];
19+
__u32 max_entries;
20+
};
21+
22+
struct bpf_iter__bpf_map {
23+
struct bpf_iter_meta *meta;
24+
struct bpf_map *map;
25+
};
26+
27+
struct btf_type {
28+
__u32 name_off;
29+
};
30+
31+
struct btf_header {
32+
__u32 str_len;
33+
};
34+
35+
struct btf {
36+
const char *strings;
37+
struct btf_type **types;
38+
struct btf_header hdr;
39+
};
40+
41+
struct bpf_prog_aux {
42+
__u32 id;
43+
char name[16];
44+
const char *attach_func_name;
45+
struct bpf_prog *linked_prog;
46+
struct bpf_func_info *func_info;
47+
struct btf *btf;
48+
};
49+
50+
struct bpf_prog {
51+
struct bpf_prog_aux *aux;
52+
};
53+
54+
struct bpf_iter__bpf_prog {
55+
struct bpf_iter_meta *meta;
56+
struct bpf_prog *prog;
57+
};
58+
#pragma clang attribute pop
59+
60+
static const char *get_name(struct btf *btf, long btf_id, const char *fallback)
61+
{
62+
struct btf_type **types, *t;
63+
unsigned int name_off;
64+
const char *str;
65+
66+
if (!btf)
67+
return fallback;
68+
str = btf->strings;
69+
types = btf->types;
70+
bpf_probe_read_kernel(&t, sizeof(t), types + btf_id);
71+
name_off = BPF_CORE_READ(t, name_off);
72+
if (name_off >= btf->hdr.str_len)
73+
return fallback;
74+
return str + name_off;
75+
}
76+
77+
SEC("iter/bpf_map")
78+
int dump_bpf_map(struct bpf_iter__bpf_map *ctx)
79+
{
80+
struct seq_file *seq = ctx->meta->seq;
81+
__u64 seq_num = ctx->meta->seq_num;
82+
struct bpf_map *map = ctx->map;
83+
84+
if (!map)
85+
return 0;
86+
87+
if (seq_num == 0)
88+
BPF_SEQ_PRINTF(seq, " id name max_entries\n");
89+
90+
BPF_SEQ_PRINTF(seq, "%4u %-16s%6d\n", map->id, map->name, map->max_entries);
91+
return 0;
92+
}
93+
94+
SEC("iter/bpf_prog")
95+
int dump_bpf_prog(struct bpf_iter__bpf_prog *ctx)
96+
{
97+
struct seq_file *seq = ctx->meta->seq;
98+
__u64 seq_num = ctx->meta->seq_num;
99+
struct bpf_prog *prog = ctx->prog;
100+
struct bpf_prog_aux *aux;
101+
102+
if (!prog)
103+
return 0;
104+
105+
aux = prog->aux;
106+
if (seq_num == 0)
107+
BPF_SEQ_PRINTF(seq, " id name attached\n");
108+
109+
BPF_SEQ_PRINTF(seq, "%4u %-16s %s %s\n", aux->id,
110+
get_name(aux->btf, aux->func_info[0].type_id, aux->name),
111+
aux->attach_func_name, aux->linked_prog->aux->name);
112+
return 0;
113+
}
114+
char LICENSE[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)