Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753044AbbFAJ6u (ORCPT ); Mon, 1 Jun 2015 05:58:50 -0400 Received: from lhrrgout.huawei.com ([194.213.3.17]:12942 "EHLO lhrrgout.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752022AbbFAJ4Y (ORCPT ); Mon, 1 Jun 2015 05:56:24 -0400 From: Wang Nan To: , , , , , , , , , , CC: , , , , Subject: [RFC PATCH v5 16/30] bpf tools: Create eBPF maps defined in an object file Date: Mon, 1 Jun 2015 07:38:02 +0000 Message-ID: <1433144296-74992-17-git-send-email-wangnan0@huawei.com> X-Mailer: git-send-email 1.8.3.4 In-Reply-To: <1433144296-74992-1-git-send-email-wangnan0@huawei.com> References: <1433144296-74992-1-git-send-email-wangnan0@huawei.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.107.197.200] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4658 Lines: 188 This patch creates maps based on 'map' section in object file using bpf_create_map(), and stores the fds into an array in 'struct bpf_object'. Previous patches parse ELF object file and collecte required data, but doesn't play with kernel. They belong to 'opening' phase. This patch is the first patch in 'loading' phase. 'loaded' field is introduced to 'struct bpf_object' to avoid loading one object twice, because loading phase clears resources collected during opening which become useless after loading. In this patch, maps_buf is cleared. Signed-off-by: Wang Nan --- tools/lib/bpf/libbpf.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++ tools/lib/bpf/libbpf.h | 4 ++ 2 files changed, 106 insertions(+) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 7d871ca..6e4fc62 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -21,6 +21,7 @@ #include #include "libbpf.h" +#include "bpf.h" #define __printf(a, b) __attribute__((format(printf, a, b))) @@ -105,6 +106,13 @@ struct bpf_object { struct bpf_program *programs; size_t nr_programs; + int *map_fds; + /* + * This field is required because maps_buf will be freed and + * maps_buf_sz will be set to 0 after loaded. + */ + size_t nr_map_fds; + bool loaded; /* * Information when doing elf related work. Only valid if fd @@ -208,6 +216,7 @@ static struct bpf_object *bpf_object__new(const char *path) strcpy(obj->path, path); obj->efile.fd = -1; + obj->loaded = false; return obj; } @@ -531,6 +540,62 @@ bpf_program__collect_reloc(struct bpf_program *prog, return 0; } +static int +bpf_object__create_maps(struct bpf_object *obj) +{ + unsigned int i; + size_t nr_maps; + int *pfd; + + nr_maps = obj->maps_buf_sz / sizeof(struct bpf_map_def); + if (!obj->maps_buf || !nr_maps) { + pr_debug("don't need create maps for %s\n", + obj->path); + return 0; + } + + obj->map_fds = malloc(sizeof(int) * nr_maps); + if (!obj->map_fds) { + pr_warning("realloc perf_bpf_map_fds failed\n"); + return -ENOMEM; + } + obj->nr_map_fds = nr_maps; + + /* fill all fd with -1 */ + memset(obj->map_fds, 0xff, sizeof(int) * nr_maps); + + pfd = obj->map_fds; + for (i = 0; i < nr_maps; i++) { + struct bpf_map_def def; + + def = *(struct bpf_map_def *)(obj->maps_buf + + i * sizeof(struct bpf_map_def)); + + *pfd = bpf_create_map(def.type, + def.key_size, + def.value_size, + def.max_entries); + if (*pfd < 0) { + size_t j; + int err = *pfd; + + pr_warning("failed to create map: %s\n", + strerror(errno)); + for (j = 0; j < i; j++) + zclose(obj->map_fds[j]); + obj->nr_map_fds = 0; + zfree(&obj->map_fds); + return err; + } + pr_debug("create map: fd=%d\n", *pfd); + pfd ++; + } + + zfree(&obj->maps_buf); + obj->maps_buf_sz = 0; + return 0; +} + static int bpf_object__collect_reloc(struct bpf_object *obj) { int i, err; @@ -616,6 +681,42 @@ out: return NULL; } +int bpf_object__unload(struct bpf_object *obj) +{ + size_t i; + + if (!obj) + return -EINVAL; + + for (i = 0; i < obj->nr_map_fds; i++) + zclose(obj->map_fds[i]); + zfree(&obj->map_fds); + obj->nr_map_fds = 0; + + return 0; +} + +int bpf_object__load(struct bpf_object *obj) +{ + if (!obj) + return -EINVAL; + + if (obj->loaded) { + pr_warning("object should not be loaded twice\n"); + return -EINVAL; + } + + obj->loaded = true; + if (bpf_object__create_maps(obj)) + goto out; + + return 0; +out: + bpf_object__unload(obj); + pr_warning("failed to load object '%s'\n", obj->path); + return -EINVAL; +} + void bpf_object__close(struct bpf_object *obj) { size_t i; @@ -624,6 +725,7 @@ void bpf_object__close(struct bpf_object *obj) return; bpf_object__elf_finish(obj); + bpf_object__unload(obj); zfree(&obj->maps_buf); diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index 84faa12..ca7a507 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -28,6 +28,10 @@ struct bpf_object; struct bpf_object *bpf_object__open(const char *path); void bpf_object__close(struct bpf_object *object); +/* Load/unload object into/from kernel */ +int bpf_object__load(struct bpf_object *obj); +int bpf_object__unload(struct bpf_object *obj); + /* * We don't need __attribute__((packed)) now since it is * unnecessary for 'bpf_map_def' because they are all aligned. -- 1.8.3.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/