diff options
| author | Wang Nan <wangnan0@huawei.com> | 2015-06-30 22:14:07 -0400 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-08-07 09:16:59 -0400 |
| commit | 55cffde2e1a41109cb49f8e94de954c8240242b5 (patch) | |
| tree | 327432a2959dcf1e3d4161c62b7589e2896da8c5 | |
| parent | 7bf98369a73a9a84c56b3f2b247ea8f0eaf8668b (diff) | |
bpf tools: Load eBPF programs in object files into kernel
This patch utilizes previous introduced bpf_load_program to load
programs in the ELF file into kernel. Result is stored in 'fd' field in
'struct bpf_program'.
During loading, it allocs a log buffer and free it before return. Note
that that buffer is not passed to bpf_load_program() if the first
loading try is successful. Doesn't use a statically allocated log buffer
to avoid potention multi-thread problem.
Instructions collected during opening is cleared after loading.
load_program() is created for loading a 'struct bpf_insn' array into
kernel, bpf_program__load() calls it. By this design we have a function
loads instructions into kernel. It will be used by further patches,
which creates different instances from a program and load them into
kernel.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1435716878-189507-20-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
| -rw-r--r-- | tools/lib/bpf/libbpf.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 94f966008887..38447b7d6e73 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c | |||
| @@ -96,6 +96,8 @@ struct bpf_program { | |||
| 96 | int map_idx; | 96 | int map_idx; |
| 97 | } *reloc_desc; | 97 | } *reloc_desc; |
| 98 | int nr_reloc; | 98 | int nr_reloc; |
| 99 | |||
| 100 | int fd; | ||
| 99 | }; | 101 | }; |
| 100 | 102 | ||
| 101 | struct bpf_object { | 103 | struct bpf_object { |
| @@ -135,11 +137,20 @@ struct bpf_object { | |||
| 135 | }; | 137 | }; |
| 136 | #define obj_elf_valid(o) ((o)->efile.elf) | 138 | #define obj_elf_valid(o) ((o)->efile.elf) |
| 137 | 139 | ||
| 140 | static void bpf_program__unload(struct bpf_program *prog) | ||
| 141 | { | ||
| 142 | if (!prog) | ||
| 143 | return; | ||
| 144 | |||
| 145 | zclose(prog->fd); | ||
| 146 | } | ||
| 147 | |||
| 138 | static void bpf_program__exit(struct bpf_program *prog) | 148 | static void bpf_program__exit(struct bpf_program *prog) |
| 139 | { | 149 | { |
| 140 | if (!prog) | 150 | if (!prog) |
| 141 | return; | 151 | return; |
| 142 | 152 | ||
| 153 | bpf_program__unload(prog); | ||
| 143 | zfree(&prog->section_name); | 154 | zfree(&prog->section_name); |
| 144 | zfree(&prog->insns); | 155 | zfree(&prog->insns); |
| 145 | zfree(&prog->reloc_desc); | 156 | zfree(&prog->reloc_desc); |
| @@ -176,6 +187,7 @@ bpf_program__init(void *data, size_t size, char *name, int idx, | |||
| 176 | memcpy(prog->insns, data, | 187 | memcpy(prog->insns, data, |
| 177 | prog->insns_cnt * sizeof(struct bpf_insn)); | 188 | prog->insns_cnt * sizeof(struct bpf_insn)); |
| 178 | prog->idx = idx; | 189 | prog->idx = idx; |
| 190 | prog->fd = -1; | ||
| 179 | 191 | ||
| 180 | return 0; | 192 | return 0; |
| 181 | errout: | 193 | errout: |
| @@ -718,6 +730,79 @@ static int bpf_object__collect_reloc(struct bpf_object *obj) | |||
| 718 | return 0; | 730 | return 0; |
| 719 | } | 731 | } |
| 720 | 732 | ||
| 733 | static int | ||
| 734 | load_program(struct bpf_insn *insns, int insns_cnt, | ||
| 735 | char *license, u32 kern_version, int *pfd) | ||
| 736 | { | ||
| 737 | int ret; | ||
| 738 | char *log_buf; | ||
| 739 | |||
| 740 | if (!insns || !insns_cnt) | ||
| 741 | return -EINVAL; | ||
| 742 | |||
| 743 | log_buf = malloc(BPF_LOG_BUF_SIZE); | ||
| 744 | if (!log_buf) | ||
| 745 | pr_warning("Alloc log buffer for bpf loader error, continue without log\n"); | ||
| 746 | |||
| 747 | ret = bpf_load_program(BPF_PROG_TYPE_KPROBE, insns, | ||
| 748 | insns_cnt, license, kern_version, | ||
| 749 | log_buf, BPF_LOG_BUF_SIZE); | ||
| 750 | |||
| 751 | if (ret >= 0) { | ||
| 752 | *pfd = ret; | ||
| 753 | ret = 0; | ||
| 754 | goto out; | ||
| 755 | } | ||
| 756 | |||
| 757 | ret = -EINVAL; | ||
| 758 | pr_warning("load bpf program failed: %s\n", strerror(errno)); | ||
| 759 | |||
| 760 | if (log_buf) { | ||
| 761 | pr_warning("-- BEGIN DUMP LOG ---\n"); | ||
| 762 | pr_warning("\n%s\n", log_buf); | ||
| 763 | pr_warning("-- END LOG --\n"); | ||
| 764 | } | ||
| 765 | |||
| 766 | out: | ||
| 767 | free(log_buf); | ||
| 768 | return ret; | ||
| 769 | } | ||
| 770 | |||
| 771 | static int | ||
| 772 | bpf_program__load(struct bpf_program *prog, | ||
| 773 | char *license, u32 kern_version) | ||
| 774 | { | ||
| 775 | int err, fd; | ||
| 776 | |||
| 777 | err = load_program(prog->insns, prog->insns_cnt, | ||
| 778 | license, kern_version, &fd); | ||
| 779 | if (!err) | ||
| 780 | prog->fd = fd; | ||
| 781 | |||
| 782 | if (err) | ||
| 783 | pr_warning("failed to load program '%s'\n", | ||
| 784 | prog->section_name); | ||
| 785 | zfree(&prog->insns); | ||
| 786 | prog->insns_cnt = 0; | ||
| 787 | return err; | ||
| 788 | } | ||
| 789 | |||
| 790 | static int | ||
| 791 | bpf_object__load_progs(struct bpf_object *obj) | ||
| 792 | { | ||
| 793 | size_t i; | ||
| 794 | int err; | ||
| 795 | |||
| 796 | for (i = 0; i < obj->nr_programs; i++) { | ||
| 797 | err = bpf_program__load(&obj->programs[i], | ||
| 798 | obj->license, | ||
| 799 | obj->kern_version); | ||
| 800 | if (err) | ||
| 801 | return err; | ||
| 802 | } | ||
| 803 | return 0; | ||
| 804 | } | ||
| 805 | |||
| 721 | static int bpf_object__validate(struct bpf_object *obj) | 806 | static int bpf_object__validate(struct bpf_object *obj) |
| 722 | { | 807 | { |
| 723 | if (obj->kern_version == 0) { | 808 | if (obj->kern_version == 0) { |
| @@ -795,6 +880,9 @@ int bpf_object__unload(struct bpf_object *obj) | |||
| 795 | zfree(&obj->map_fds); | 880 | zfree(&obj->map_fds); |
| 796 | obj->nr_map_fds = 0; | 881 | obj->nr_map_fds = 0; |
| 797 | 882 | ||
| 883 | for (i = 0; i < obj->nr_programs; i++) | ||
| 884 | bpf_program__unload(&obj->programs[i]); | ||
| 885 | |||
| 798 | return 0; | 886 | return 0; |
| 799 | } | 887 | } |
| 800 | 888 | ||
| @@ -813,6 +901,8 @@ int bpf_object__load(struct bpf_object *obj) | |||
| 813 | goto out; | 901 | goto out; |
| 814 | if (bpf_object__relocate(obj)) | 902 | if (bpf_object__relocate(obj)) |
| 815 | goto out; | 903 | goto out; |
| 904 | if (bpf_object__load_progs(obj)) | ||
| 905 | goto out; | ||
| 816 | 906 | ||
| 817 | return 0; | 907 | return 0; |
| 818 | out: | 908 | out: |
