From patchwork Thu Dec 17 05:23:13 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wang Nan X-Patchwork-Id: 58528 Delivered-To: patch@linaro.org Received: by 10.112.89.199 with SMTP id bq7csp154077lbb; Wed, 16 Dec 2015 21:30:24 -0800 (PST) X-Received: by 10.67.3.230 with SMTP id bz6mr45070736pad.118.1450330224268; Wed, 16 Dec 2015 21:30:24 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id d10si13943035pap.237.2015.12.16.21.30.23; Wed, 16 Dec 2015 21:30:24 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751356AbbLQFaU (ORCPT + 29 others); Thu, 17 Dec 2015 00:30:20 -0500 Received: from szxga03-in.huawei.com ([119.145.14.66]:14562 "EHLO szxga03-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750728AbbLQFaQ (ORCPT ); Thu, 17 Dec 2015 00:30:16 -0500 Received: from 172.24.1.48 (EHLO szxeml428-hub.china.huawei.com) ([172.24.1.48]) by szxrg03-dlp.huawei.com (MOS 4.4.3-GA FastPath queued) with ESMTP id BSX91261; Thu, 17 Dec 2015 13:23:36 +0800 (CST) Received: from linux-4hy3.site (10.107.193.248) by szxeml428-hub.china.huawei.com (10.82.67.183) with Microsoft SMTP Server id 14.3.235.1; Thu, 17 Dec 2015 13:23:27 +0800 From: Wang Nan To: , , , , , , , , , , , CC: , , Wang Nan Subject: [PATCH 09/10] bpf samples: Uses libbpf in tools/lib to deal with BPF operations Date: Thu, 17 Dec 2015 05:23:13 +0000 Message-ID: <1450329794-161948-10-git-send-email-wangnan0@huawei.com> X-Mailer: git-send-email 1.8.3.4 In-Reply-To: <1450329794-161948-1-git-send-email-wangnan0@huawei.com> References: <1450329794-161948-1-git-send-email-wangnan0@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.107.193.248] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A020205.567246D9.009C, ss=1, re=0.000, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0, ip=0.0.0.0, so=2013-05-26 15:14:31, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: 008e6c04fa4c0a1c7948ec0ff15adc7b Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Since we already have libbpf in tools/lib, there's no need to maintain a duplicate BPF loading and operations library in samples. This patch utilises previous introduced utils.[ch], which calls libbpf to do these work. The main changing in this relative large patch is very simple: 1. Makefile modification, makes all hostprogs depend on libbpf.a. Add include and library searching patch and rules for linker. Remove old bpf_load.o and libbpf.o, replaces them with utils.o 2. Make sure there are correct 'version' section so the BPF source files can be loaded by libbpf. 3. Uses API provided by utils.h and libbpf. Signed-off-by: Wang Nan Cc: Alexei Starovoitov Cc: Alex Gartrell Cc: Arnaldo Carvalho de Melo Cc: Brenden Blanco Cc: Daniel Borkmann Cc: Daniel Wagner Cc: David S. Miller Cc: Ingo Molnar Cc: Kaixu Xia Cc: Michael Holzheu Cc: Yang Shi --- samples/bpf/Makefile | 65 ++++++++++++++++++--------------- samples/bpf/fds_example.c | 26 +++++++------- samples/bpf/lathist_user.c | 13 ++++--- samples/bpf/sock_example.c | 13 +++---- samples/bpf/sockex1_kern.c | 2 ++ samples/bpf/sockex1_user.c | 27 ++++++++------ samples/bpf/sockex2_kern.c | 2 ++ samples/bpf/sockex2_user.c | 26 ++++++++------ samples/bpf/sockex3_kern.c | 2 ++ samples/bpf/sockex3_user.c | 23 +++++++----- samples/bpf/test_maps.c | 80 ++++++++++++++++++++--------------------- samples/bpf/test_verifier.c | 13 ++++--- samples/bpf/trace_output_user.c | 17 +++++---- samples/bpf/tracex1_user.c | 9 +++-- samples/bpf/tracex2_user.c | 31 +++++++++------- samples/bpf/tracex3_user.c | 15 ++++---- samples/bpf/tracex4_user.c | 15 ++++---- samples/bpf/tracex5_user.c | 9 +++-- samples/bpf/tracex6_user.c | 16 ++++----- 19 files changed, 221 insertions(+), 183 deletions(-) -- 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/ diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile index edd638b..edb7c04 100644 --- a/samples/bpf/Makefile +++ b/samples/bpf/Makefile @@ -1,6 +1,20 @@ # kbuild trick to avoid linker error. Can be omitted if a module is built. obj- := dummy.o +INC_DIR = $(src)/include +TOOLS_DIR = $(realpath $(srctree))/tools +TOOLS_LIB_DIR = $(TOOLS_DIR)/lib +LIBBPF_DIR = $(TOOLS_LIB_DIR)/bpf + +$(obj)/libbpf/libbpf.a: + $(Q)mkdir -p $(obj)/libbpf + $(MAKE) -C $(LIBBPF_DIR) O=$(realpath $(obj))/libbpf CFLAGS= LDFLAGS= V=1 $(realpath $(obj))/libbpf/libbpf.a + +HOSTCFLAGS += -I$(TOOLS_LIB_DIR) -I$(INC_DIR) +HOSTLDFLAGS += -L$(obj)/libbpf +HOSTCFLAGS += -I$(INC_DIR) -I$(TOOLS_LIB_DIR) +HOST_LOADLIBES += -lelf -lbpf + # List of programs to build hostprogs-y := test_verifier test_maps hostprogs-y += sock_example @@ -17,21 +31,27 @@ hostprogs-y += tracex6 hostprogs-y += trace_output hostprogs-y += lathist -test_verifier-objs := test_verifier.o libbpf.o -test_maps-objs := test_maps.o libbpf.o -sock_example-objs := sock_example.o libbpf.o -fds_example-objs := bpf_load.o libbpf.o fds_example.o -sockex1-objs := bpf_load.o libbpf.o sockex1_user.o -sockex2-objs := bpf_load.o libbpf.o sockex2_user.o -sockex3-objs := bpf_load.o libbpf.o sockex3_user.o -tracex1-objs := bpf_load.o libbpf.o tracex1_user.o -tracex2-objs := bpf_load.o libbpf.o tracex2_user.o -tracex3-objs := bpf_load.o libbpf.o tracex3_user.o -tracex4-objs := bpf_load.o libbpf.o tracex4_user.o -tracex5-objs := bpf_load.o libbpf.o tracex5_user.o -tracex6-objs := bpf_load.o libbpf.o tracex6_user.o -trace_output-objs := bpf_load.o libbpf.o trace_output_user.o -lathist-objs := bpf_load.o libbpf.o lathist_user.o +test_verifier-objs := test_verifier.o +test_maps-objs := test_maps.o +sock_example-objs := sock_example.o utils.o +fds_example-objs := utils.o fds_example.o +sockex1-objs := utils.o sockex1_user.o +sockex2-objs := utils.o sockex2_user.o +sockex3-objs := utils.o sockex3_user.o +tracex1-objs := utils.o tracex1_user.o +tracex2-objs := utils.o tracex2_user.o +tracex3-objs := utils.o tracex3_user.o +tracex4-objs := utils.o tracex4_user.o +tracex5-objs := utils.o tracex5_user.o +tracex6-objs := utils.o tracex6_user.o +trace_output-objs := utils.o trace_output_user.o +lathist-objs := utils.o lathist_user.o + +define add_depend +$(foreach m, $(notdir $1), \ + $(eval $(obj)/$m: $(obj)/libbpf/libbpf.a)) +endef +$(call add_depend, $(hostprogs-y)) # Tell kbuild to always build the programs always := $(hostprogs-y) @@ -50,19 +70,8 @@ always += lathist_kern.o HOSTCFLAGS += -I$(objtree)/usr/include -HOSTCFLAGS_bpf_load.o += -I$(objtree)/usr/include -Wno-unused-variable -HOSTLOADLIBES_fds_example += -lelf -HOSTLOADLIBES_sockex1 += -lelf -HOSTLOADLIBES_sockex2 += -lelf -HOSTLOADLIBES_sockex3 += -lelf -HOSTLOADLIBES_tracex1 += -lelf -HOSTLOADLIBES_tracex2 += -lelf -HOSTLOADLIBES_tracex3 += -lelf -HOSTLOADLIBES_tracex4 += -lelf -lrt -HOSTLOADLIBES_tracex5 += -lelf -HOSTLOADLIBES_tracex6 += -lelf -HOSTLOADLIBES_trace_output += -lelf -lrt -HOSTLOADLIBES_lathist += -lelf +HOSTLOADLIBES_tracex4 += -lrt +HOSTLOADLIBES_trace_output += -lrt # point this to your LLVM backend with bpf support LLC=$(srctree)/tools/bpf/llvm/bld/Debug+Asserts/bin/llc diff --git a/samples/bpf/fds_example.c b/samples/bpf/fds_example.c index e2fd16c..bdcfce0 100644 --- a/samples/bpf/fds_example.c +++ b/samples/bpf/fds_example.c @@ -12,8 +12,7 @@ #include #include -#include "bpf_load.h" -#include "libbpf.h" +#include "utils.h" #define BPF_F_PIN (1 << 0) #define BPF_F_GET (1 << 1) @@ -55,11 +54,14 @@ static int bpf_prog_create(const char *object) }; if (object) { - assert(!load_bpf_file((char *)object)); - return prog_fd[0]; + struct bpf_object *obj = load_bpf_file((char *)object); + + assert(obj); + return get_prog_fd(obj, 0); } else { - return bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, - insns, sizeof(insns), "GPL", 0); + return bpf_load_program(BPF_PROG_TYPE_SOCKET_FILTER, + insns, sizeof(insns) / sizeof(insns[0]), + "GPL", 0, NULL, 0); } } @@ -73,22 +75,22 @@ static int bpf_do_map(const char *file, uint32_t flags, uint32_t key, printf("bpf: map fd:%d (%s)\n", fd, strerror(errno)); assert(fd > 0); - ret = bpf_obj_pin(fd, file); + ret = bpf_pin_object(fd, file); printf("bpf: pin ret:(%d,%s)\n", ret, strerror(errno)); assert(ret == 0); } else { - fd = bpf_obj_get(file); + fd = bpf_get_pinned_object(file); printf("bpf: get fd:%d (%s)\n", fd, strerror(errno)); assert(fd > 0); } if ((flags & BPF_F_KEY_VAL) == BPF_F_KEY_VAL) { - ret = bpf_update_elem(fd, &key, &value, 0); + ret = bpf_map_update_elem(fd, &key, &value, 0); printf("bpf: fd:%d u->(%u:%u) ret:(%d,%s)\n", fd, key, value, ret, strerror(errno)); assert(ret == 0); } else if (flags & BPF_F_KEY) { - ret = bpf_lookup_elem(fd, &key, &value); + ret = bpf_map_lookup_elem(fd, &key, &value); printf("bpf: fd:%d l->(%u):%u ret:(%d,%s)\n", fd, key, value, ret, strerror(errno)); assert(ret == 0); @@ -106,11 +108,11 @@ static int bpf_do_prog(const char *file, uint32_t flags, const char *object) printf("bpf: prog fd:%d (%s)\n", fd, strerror(errno)); assert(fd > 0); - ret = bpf_obj_pin(fd, file); + ret = bpf_pin_object(fd, file); printf("bpf: pin ret:(%d,%s)\n", ret, strerror(errno)); assert(ret == 0); } else { - fd = bpf_obj_get(file); + fd = bpf_get_pinned_object(file); printf("bpf: get fd:%d (%s)\n", fd, strerror(errno)); assert(fd > 0); } diff --git a/samples/bpf/lathist_user.c b/samples/bpf/lathist_user.c index 65da8c1..9160af8 100644 --- a/samples/bpf/lathist_user.c +++ b/samples/bpf/lathist_user.c @@ -10,8 +10,7 @@ #include #include #include -#include "libbpf.h" -#include "bpf_load.h" +#include "utils.h" #define MAX_ENTRIES 20 #define MAX_CPU 4 @@ -73,7 +72,7 @@ static void get_data(int fd) for (c = 0; c < MAX_CPU; c++) { for (i = 0; i < MAX_ENTRIES; i++) { key = c * MAX_ENTRIES + i; - bpf_lookup_elem(fd, &key, &value); + bpf_map_lookup_elem(fd, &key, &value); cpu_hist[c].data[i] = value; if (value > cpu_hist[c].max) @@ -85,16 +84,16 @@ static void get_data(int fd) int main(int argc, char **argv) { char filename[256]; + struct bpf_object *obj; snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); - if (load_bpf_file(filename)) { - printf("%s", bpf_log_buf); + obj = load_bpf_file(filename); + if (!obj) return 1; - } while (1) { - get_data(map_fd[1]); + get_data(get_map_fd(obj, 1)); print_hist(); sleep(5); } diff --git a/samples/bpf/sock_example.c b/samples/bpf/sock_example.c index a0ce251..a6a875f 100644 --- a/samples/bpf/sock_example.c +++ b/samples/bpf/sock_example.c @@ -26,7 +26,7 @@ #include #include #include -#include "libbpf.h" +#include "utils.h" static int test_sock(void) { @@ -55,8 +55,9 @@ static int test_sock(void) BPF_EXIT_INSN(), }; - prog_fd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, prog, sizeof(prog), - "GPL", 0); + prog_fd = bpf_load_program(BPF_PROG_TYPE_SOCKET_FILTER, prog, + sizeof(prog) / sizeof(prog[0]), + "GPL", 0, NULL, 0); if (prog_fd < 0) { printf("failed to load prog '%s'\n", strerror(errno)); goto cleanup; @@ -72,13 +73,13 @@ static int test_sock(void) for (i = 0; i < 10; i++) { key = IPPROTO_TCP; - assert(bpf_lookup_elem(map_fd, &key, &tcp_cnt) == 0); + assert(bpf_map_lookup_elem(map_fd, &key, &tcp_cnt) == 0); key = IPPROTO_UDP; - assert(bpf_lookup_elem(map_fd, &key, &udp_cnt) == 0); + assert(bpf_map_lookup_elem(map_fd, &key, &udp_cnt) == 0); key = IPPROTO_ICMP; - assert(bpf_lookup_elem(map_fd, &key, &icmp_cnt) == 0); + assert(bpf_map_lookup_elem(map_fd, &key, &icmp_cnt) == 0); printf("TCP %lld UDP %lld ICMP %lld packets\n", tcp_cnt, udp_cnt, icmp_cnt); diff --git a/samples/bpf/sockex1_kern.c b/samples/bpf/sockex1_kern.c index ed18e9a..0ab3d9a 100644 --- a/samples/bpf/sockex1_kern.c +++ b/samples/bpf/sockex1_kern.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "bpf_helpers.h" struct bpf_map_def SEC("maps") my_map = { @@ -27,3 +28,4 @@ int bpf_prog1(struct __sk_buff *skb) return 0; } char _license[] SEC("license") = "GPL"; +int _version SEC("version") = LINUX_VERSION_CODE; diff --git a/samples/bpf/sockex1_user.c b/samples/bpf/sockex1_user.c index 678ce46..d1ece36 100644 --- a/samples/bpf/sockex1_user.c +++ b/samples/bpf/sockex1_user.c @@ -1,28 +1,33 @@ #include #include -#include -#include "libbpf.h" -#include "bpf_load.h" #include #include +#include "utils.h" int main(int ac, char **argv) { char filename[256]; FILE *f; - int i, sock; + int i, sock, map_fd, prog_fd; + struct bpf_object *obj; snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); - if (load_bpf_file(filename)) { - printf("%s", bpf_log_buf); + obj = load_bpf_file(filename); + if (!obj) + return 1; + + map_fd = get_map_fd(obj, 0); + prog_fd = get_prog_fd(obj, 0); + if (map_fd < 0 || prog_fd < 0) { + fprintf(stderr, "failed to get file descriptor\n"); return 1; } sock = open_raw_sock("lo"); - assert(setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, prog_fd, - sizeof(prog_fd[0])) == 0); + assert(setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, &prog_fd, + sizeof(prog_fd)) == 0); f = popen("ping -c5 localhost", "r"); (void) f; @@ -32,13 +37,13 @@ int main(int ac, char **argv) int key; key = IPPROTO_TCP; - assert(bpf_lookup_elem(map_fd[0], &key, &tcp_cnt) == 0); + assert(bpf_map_lookup_elem(map_fd, &key, &tcp_cnt) == 0); key = IPPROTO_UDP; - assert(bpf_lookup_elem(map_fd[0], &key, &udp_cnt) == 0); + assert(bpf_map_lookup_elem(map_fd, &key, &udp_cnt) == 0); key = IPPROTO_ICMP; - assert(bpf_lookup_elem(map_fd[0], &key, &icmp_cnt) == 0); + assert(bpf_map_lookup_elem(map_fd, &key, &icmp_cnt) == 0); printf("TCP %lld UDP %lld ICMP %lld bytes\n", tcp_cnt, udp_cnt, icmp_cnt); diff --git a/samples/bpf/sockex2_kern.c b/samples/bpf/sockex2_kern.c index ba0e177..46e2e77 100644 --- a/samples/bpf/sockex2_kern.c +++ b/samples/bpf/sockex2_kern.c @@ -6,6 +6,7 @@ #include #include #include +#include #define IP_MF 0x2000 #define IP_OFFSET 0x1FFF @@ -219,3 +220,4 @@ int bpf_prog2(struct __sk_buff *skb) } char _license[] SEC("license") = "GPL"; +int _version SEC("version") = LINUX_VERSION_CODE; diff --git a/samples/bpf/sockex2_user.c b/samples/bpf/sockex2_user.c index 29a276d..3df6442 100644 --- a/samples/bpf/sockex2_user.c +++ b/samples/bpf/sockex2_user.c @@ -1,10 +1,9 @@ #include #include -#include -#include "libbpf.h" -#include "bpf_load.h" #include #include +#include +#include "utils.h" struct pair { __u64 packets; @@ -15,19 +14,26 @@ int main(int ac, char **argv) { char filename[256]; FILE *f; - int i, sock; + int i, sock, map_fd, prog_fd; + struct bpf_object *obj; snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); - if (load_bpf_file(filename)) { - printf("%s", bpf_log_buf); + obj = load_bpf_file(filename); + if (!obj) + return 1; + + map_fd = get_map_fd(obj, 0); + prog_fd = get_prog_fd(obj, 0); + if (map_fd < 0 || prog_fd < 0) { + fprintf(stderr, "failed to get file descriptor\n"); return 1; } sock = open_raw_sock("lo"); - assert(setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, prog_fd, - sizeof(prog_fd[0])) == 0); + assert(setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, &prog_fd, + sizeof(prog_fd)) == 0); f = popen("ping -c5 localhost", "r"); (void) f; @@ -36,8 +42,8 @@ int main(int ac, char **argv) int key = 0, next_key; struct pair value; - while (bpf_get_next_key(map_fd[0], &key, &next_key) == 0) { - bpf_lookup_elem(map_fd[0], &next_key, &value); + while (bpf_map_get_next_key(map_fd, &key, &next_key) == 0) { + bpf_map_lookup_elem(map_fd, &next_key, &value); printf("ip %s bytes %lld packets %lld\n", inet_ntoa((struct in_addr){htonl(next_key)}), value.bytes, value.packets); diff --git a/samples/bpf/sockex3_kern.c b/samples/bpf/sockex3_kern.c index 41ae2fd..6ac0d17 100644 --- a/samples/bpf/sockex3_kern.c +++ b/samples/bpf/sockex3_kern.c @@ -13,6 +13,7 @@ #include #include #include +#include #define IP_MF 0x2000 #define IP_OFFSET 0x1FFF @@ -288,3 +289,4 @@ int main_prog(struct __sk_buff *skb) } char _license[] SEC("license") = "GPL"; +int _version SEC("version") = LINUX_VERSION_CODE; diff --git a/samples/bpf/sockex3_user.c b/samples/bpf/sockex3_user.c index 2617772..99a7126 100644 --- a/samples/bpf/sockex3_user.c +++ b/samples/bpf/sockex3_user.c @@ -1,10 +1,10 @@ #include #include #include -#include "libbpf.h" -#include "bpf_load.h" #include #include +#include +#include "utils.h" struct flow_keys { __be32 src; @@ -25,18 +25,25 @@ int main(int argc, char **argv) { char filename[256]; FILE *f; - int i, sock; + int i, sock, map_fd, prog_fd; + struct bpf_object *obj; snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); - if (load_bpf_file(filename)) { - printf("%s", bpf_log_buf); + obj = load_bpf_file(filename); + if (!obj) + return 1; + + map_fd = get_map_fd(obj, 2); + prog_fd = get_prog_fd(obj, 4); + if (map_fd < 0 || prog_fd < 0) { + fprintf(stderr, "failed to get file descriptor\n"); return 1; } sock = open_raw_sock("lo"); - assert(setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, &prog_fd[4], + assert(setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, &prog_fd, sizeof(__u32)) == 0); if (argc > 1) @@ -51,8 +58,8 @@ int main(int argc, char **argv) sleep(1); printf("IP src.port -> dst.port bytes packets\n"); - while (bpf_get_next_key(map_fd[2], &key, &next_key) == 0) { - bpf_lookup_elem(map_fd[2], &next_key, &value); + while (bpf_map_get_next_key(map_fd, &key, &next_key) == 0) { + bpf_map_lookup_elem(map_fd, &next_key, &value); printf("%s.%05d -> %s.%05d %12lld %12lld\n", inet_ntoa((struct in_addr){htonl(next_key.src)}), next_key.port16[0], diff --git a/samples/bpf/test_maps.c b/samples/bpf/test_maps.c index 6299ee9..435d55e 100644 --- a/samples/bpf/test_maps.c +++ b/samples/bpf/test_maps.c @@ -15,7 +15,7 @@ #include #include #include -#include "libbpf.h" +#include "utils.h" /* sanity tests for map API */ static void test_hashmap_sanity(int i, void *data) @@ -32,59 +32,59 @@ static void test_hashmap_sanity(int i, void *data) key = 1; value = 1234; /* insert key=1 element */ - assert(bpf_update_elem(map_fd, &key, &value, BPF_ANY) == 0); + assert(bpf_map_update_elem(map_fd, &key, &value, BPF_ANY) == 0); value = 0; /* BPF_NOEXIST means: add new element if it doesn't exist */ - assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 && + assert(bpf_map_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 && /* key=1 already exists */ errno == EEXIST); - assert(bpf_update_elem(map_fd, &key, &value, -1) == -1 && errno == EINVAL); + assert(bpf_map_update_elem(map_fd, &key, &value, -1) == -1 && errno == EINVAL); /* check that key=1 can be found */ - assert(bpf_lookup_elem(map_fd, &key, &value) == 0 && value == 1234); + assert(bpf_map_lookup_elem(map_fd, &key, &value) == 0 && value == 1234); key = 2; /* check that key=2 is not found */ - assert(bpf_lookup_elem(map_fd, &key, &value) == -1 && errno == ENOENT); + assert(bpf_map_lookup_elem(map_fd, &key, &value) == -1 && errno == ENOENT); /* BPF_EXIST means: update existing element */ - assert(bpf_update_elem(map_fd, &key, &value, BPF_EXIST) == -1 && + assert(bpf_map_update_elem(map_fd, &key, &value, BPF_EXIST) == -1 && /* key=2 is not there */ errno == ENOENT); /* insert key=2 element */ - assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == 0); + assert(bpf_map_update_elem(map_fd, &key, &value, BPF_NOEXIST) == 0); /* key=1 and key=2 were inserted, check that key=0 cannot be inserted * due to max_entries limit */ key = 0; - assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 && + assert(bpf_map_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 && errno == E2BIG); /* check that key = 0 doesn't exist */ - assert(bpf_delete_elem(map_fd, &key) == -1 && errno == ENOENT); + assert(bpf_map_delete_elem(map_fd, &key) == -1 && errno == ENOENT); /* iterate over two elements */ - assert(bpf_get_next_key(map_fd, &key, &next_key) == 0 && + assert(bpf_map_get_next_key(map_fd, &key, &next_key) == 0 && (next_key == 1 || next_key == 2)); - assert(bpf_get_next_key(map_fd, &next_key, &next_key) == 0 && + assert(bpf_map_get_next_key(map_fd, &next_key, &next_key) == 0 && (next_key == 1 || next_key == 2)); - assert(bpf_get_next_key(map_fd, &next_key, &next_key) == -1 && + assert(bpf_map_get_next_key(map_fd, &next_key, &next_key) == -1 && errno == ENOENT); /* delete both elements */ key = 1; - assert(bpf_delete_elem(map_fd, &key) == 0); + assert(bpf_map_delete_elem(map_fd, &key) == 0); key = 2; - assert(bpf_delete_elem(map_fd, &key) == 0); - assert(bpf_delete_elem(map_fd, &key) == -1 && errno == ENOENT); + assert(bpf_map_delete_elem(map_fd, &key) == 0); + assert(bpf_map_delete_elem(map_fd, &key) == -1 && errno == ENOENT); key = 0; /* check that map is empty */ - assert(bpf_get_next_key(map_fd, &key, &next_key) == -1 && + assert(bpf_map_get_next_key(map_fd, &key, &next_key) == -1 && errno == ENOENT); close(map_fd); } @@ -103,41 +103,41 @@ static void test_arraymap_sanity(int i, void *data) key = 1; value = 1234; /* insert key=1 element */ - assert(bpf_update_elem(map_fd, &key, &value, BPF_ANY) == 0); + assert(bpf_map_update_elem(map_fd, &key, &value, BPF_ANY) == 0); value = 0; - assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 && + assert(bpf_map_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 && errno == EEXIST); /* check that key=1 can be found */ - assert(bpf_lookup_elem(map_fd, &key, &value) == 0 && value == 1234); + assert(bpf_map_lookup_elem(map_fd, &key, &value) == 0 && value == 1234); key = 0; /* check that key=0 is also found and zero initialized */ - assert(bpf_lookup_elem(map_fd, &key, &value) == 0 && value == 0); + assert(bpf_map_lookup_elem(map_fd, &key, &value) == 0 && value == 0); /* key=0 and key=1 were inserted, check that key=2 cannot be inserted * due to max_entries limit */ key = 2; - assert(bpf_update_elem(map_fd, &key, &value, BPF_EXIST) == -1 && + assert(bpf_map_update_elem(map_fd, &key, &value, BPF_EXIST) == -1 && errno == E2BIG); /* check that key = 2 doesn't exist */ - assert(bpf_lookup_elem(map_fd, &key, &value) == -1 && errno == ENOENT); + assert(bpf_map_lookup_elem(map_fd, &key, &value) == -1 && errno == ENOENT); /* iterate over two elements */ - assert(bpf_get_next_key(map_fd, &key, &next_key) == 0 && + assert(bpf_map_get_next_key(map_fd, &key, &next_key) == 0 && next_key == 0); - assert(bpf_get_next_key(map_fd, &next_key, &next_key) == 0 && + assert(bpf_map_get_next_key(map_fd, &next_key, &next_key) == 0 && next_key == 1); - assert(bpf_get_next_key(map_fd, &next_key, &next_key) == -1 && + assert(bpf_map_get_next_key(map_fd, &next_key, &next_key) == -1 && errno == ENOENT); /* delete shouldn't succeed */ key = 1; - assert(bpf_delete_elem(map_fd, &key) == -1 && errno == EINVAL); + assert(bpf_map_delete_elem(map_fd, &key) == -1 && errno == EINVAL); close(map_fd); } @@ -163,21 +163,21 @@ static void test_map_large(void) for (i = 0; i < MAP_SIZE; i++) { key = (struct bigkey) {.c = i}; value = i; - assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == 0); + assert(bpf_map_update_elem(map_fd, &key, &value, BPF_NOEXIST) == 0); } key.c = -1; - assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 && + assert(bpf_map_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 && errno == E2BIG); /* iterate through all elements */ for (i = 0; i < MAP_SIZE; i++) - assert(bpf_get_next_key(map_fd, &key, &key) == 0); - assert(bpf_get_next_key(map_fd, &key, &key) == -1 && errno == ENOENT); + assert(bpf_map_get_next_key(map_fd, &key, &key) == 0); + assert(bpf_map_get_next_key(map_fd, &key, &key) == -1 && errno == ENOENT); key.c = 0; - assert(bpf_lookup_elem(map_fd, &key, &value) == 0 && value == 0); + assert(bpf_map_lookup_elem(map_fd, &key, &value) == 0 && value == 0); key.a = 1; - assert(bpf_lookup_elem(map_fd, &key, &value) == -1 && errno == ENOENT); + assert(bpf_map_lookup_elem(map_fd, &key, &value) == -1 && errno == ENOENT); close(map_fd); } @@ -225,9 +225,9 @@ static void do_work(int fn, void *data) for (i = fn; i < MAP_SIZE; i += TASKS) { key = value = i; if (do_update) - assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == 0); + assert(bpf_map_update_elem(map_fd, &key, &value, BPF_NOEXIST) == 0); else - assert(bpf_delete_elem(map_fd, &key) == 0); + assert(bpf_map_delete_elem(map_fd, &key) == 0); } } @@ -254,19 +254,19 @@ static void test_map_parallel(void) run_parallel(TASKS, do_work, data); /* check that key=0 is already there */ - assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 && + assert(bpf_map_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 && errno == EEXIST); /* check that all elements were inserted */ key = -1; for (i = 0; i < MAP_SIZE; i++) - assert(bpf_get_next_key(map_fd, &key, &key) == 0); - assert(bpf_get_next_key(map_fd, &key, &key) == -1 && errno == ENOENT); + assert(bpf_map_get_next_key(map_fd, &key, &key) == 0); + assert(bpf_map_get_next_key(map_fd, &key, &key) == -1 && errno == ENOENT); /* another check for all elements */ for (i = 0; i < MAP_SIZE; i++) { key = MAP_SIZE - i - 1; - assert(bpf_lookup_elem(map_fd, &key, &value) == 0 && + assert(bpf_map_lookup_elem(map_fd, &key, &value) == 0 && value == key); } @@ -276,7 +276,7 @@ static void test_map_parallel(void) /* nothing should be left */ key = -1; - assert(bpf_get_next_key(map_fd, &key, &key) == -1 && errno == ENOENT); + assert(bpf_map_get_next_key(map_fd, &key, &key) == -1 && errno == ENOENT); } int main(void) diff --git a/samples/bpf/test_verifier.c b/samples/bpf/test_verifier.c index 563c507..0566fc0 100644 --- a/samples/bpf/test_verifier.c +++ b/samples/bpf/test_verifier.c @@ -17,13 +17,17 @@ #include #include #include -#include "libbpf.h" +#include "utils.h" +#include #define MAX_INSNS 512 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) #define MAX_FIXUPS 8 +#define LOG_BUF_SIZE 65536 +static char bpf_log_buf[LOG_BUF_SIZE]; + struct bpf_test { const char *descr; struct bpf_insn insns[MAX_INSNS]; @@ -1250,9 +1254,10 @@ static int test(void) } printf("#%d %s ", i, tests[i].descr); - prog_fd = bpf_prog_load(prog_type ?: BPF_PROG_TYPE_SOCKET_FILTER, - prog, prog_len * sizeof(struct bpf_insn), - "GPL", 0); + bpf_log_buf[0] = '\0'; + prog_fd = bpf_load_program(prog_type ?: BPF_PROG_TYPE_SOCKET_FILTER, + prog, prog_len, "GPL", 0, + bpf_log_buf, sizeof(bpf_log_buf)); if (unpriv && tests[i].result_unpriv != UNDEF) expected_result = tests[i].result_unpriv; diff --git a/samples/bpf/trace_output_user.c b/samples/bpf/trace_output_user.c index 661a7d0..4ef02cb 100644 --- a/samples/bpf/trace_output_user.c +++ b/samples/bpf/trace_output_user.c @@ -19,8 +19,7 @@ #include #include #include -#include "libbpf.h" -#include "bpf_load.h" +#include "utils.h" static int pmu_fd; @@ -61,7 +60,7 @@ struct perf_event_sample { char data[]; }; -void perf_event_read(print_fn fn) +static void perf_event_read(print_fn fn) { __u64 data_tail = header->data_tail; __u64 data_head = header->data_head; @@ -150,7 +149,7 @@ static void print_bpf_output(void *data, int size) } } -static void test_bpf_perf_event(void) +static void test_bpf_perf_event(int map_fd) { struct perf_event_attr attr = { .sample_type = PERF_SAMPLE_RAW, @@ -162,7 +161,7 @@ static void test_bpf_perf_event(void) pmu_fd = perf_event_open(&attr, -1/*pid*/, 0/*cpu*/, -1/*group_fd*/, 0); assert(pmu_fd >= 0); - assert(bpf_update_elem(map_fd[0], &key, &pmu_fd, BPF_ANY) == 0); + assert(bpf_map_update_elem(map_fd, &key, &pmu_fd, BPF_ANY) == 0); ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0); } @@ -170,15 +169,15 @@ int main(int argc, char **argv) { char filename[256]; FILE *f; + struct bpf_object *obj; snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); - if (load_bpf_file(filename)) { - printf("%s", bpf_log_buf); + obj = load_bpf_file(filename); + if (!obj) return 1; - } - test_bpf_perf_event(); + test_bpf_perf_event(get_map_fd(obj, 0)); if (perf_event_mmap(pmu_fd) < 0) return 1; diff --git a/samples/bpf/tracex1_user.c b/samples/bpf/tracex1_user.c index 31a4818..0652339 100644 --- a/samples/bpf/tracex1_user.c +++ b/samples/bpf/tracex1_user.c @@ -1,20 +1,19 @@ #include #include #include -#include "libbpf.h" -#include "bpf_load.h" +#include "utils.h" int main(int ac, char **argv) { FILE *f; char filename[256]; + struct bpf_object *obj; snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); - if (load_bpf_file(filename)) { - printf("%s", bpf_log_buf); + obj = load_bpf_file(filename); + if (!obj) return 1; - } f = popen("taskset 1 ping -c5 localhost", "r"); (void) f; diff --git a/samples/bpf/tracex2_user.c b/samples/bpf/tracex2_user.c index cd0241c..86700bb 100644 --- a/samples/bpf/tracex2_user.c +++ b/samples/bpf/tracex2_user.c @@ -4,8 +4,9 @@ #include #include #include -#include "libbpf.h" -#include "bpf_load.h" +#include +#include +#include "utils.h" #define MAX_INDEX 64 #define MAX_STARS 38 @@ -44,12 +45,12 @@ static void print_hist_for_pid(int fd, void *task) long max_value = 0; int i, ind; - while (bpf_get_next_key(fd, &key, &next_key) == 0) { + while (bpf_map_get_next_key(fd, &key, &next_key) == 0) { if (memcmp(&next_key, task, SIZE)) { key = next_key; continue; } - bpf_lookup_elem(fd, &next_key, &value); + bpf_map_lookup_elem(fd, &next_key, &value); ind = next_key.index; data[ind] = value; if (value && ind > max_ind) @@ -76,7 +77,7 @@ static void print_hist(int fd) int task_cnt = 0; int i; - while (bpf_get_next_key(fd, &key, &next_key) == 0) { + while (bpf_map_get_next_key(fd, &key, &next_key) == 0) { int found = 0; for (i = 0; i < task_cnt; i++) @@ -97,9 +98,11 @@ static void print_hist(int fd) } +static int hist_map_fd; + static void int_exit(int sig) { - print_hist(map_fd[1]); + print_hist(hist_map_fd); exit(0); } @@ -108,7 +111,8 @@ int main(int ac, char **argv) char filename[256]; long key, next_key, value; FILE *f; - int i; + int i, map_fd; + struct bpf_object *obj; snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); @@ -122,15 +126,16 @@ int main(int ac, char **argv) f = popen("dd if=/dev/zero of=/dev/null count=5000000", "r"); (void) f; - if (load_bpf_file(filename)) { - printf("%s", bpf_log_buf); + obj = load_bpf_file(filename); + if (!obj) return 1; - } + map_fd = get_map_fd(obj, 0); + hist_map_fd = get_map_fd(obj, 1); for (i = 0; i < 5; i++) { key = 0; - while (bpf_get_next_key(map_fd[0], &key, &next_key) == 0) { - bpf_lookup_elem(map_fd[0], &next_key, &value); + while (bpf_map_get_next_key(map_fd, &key, &next_key) == 0) { + bpf_map_lookup_elem(map_fd, &next_key, &value); printf("location 0x%lx count %ld\n", next_key, value); key = next_key; } @@ -138,7 +143,7 @@ int main(int ac, char **argv) printf("\n"); sleep(1); } - print_hist(map_fd[1]); + print_hist(hist_map_fd); return 0; } diff --git a/samples/bpf/tracex3_user.c b/samples/bpf/tracex3_user.c index 0aaa933..4c26a6f 100644 --- a/samples/bpf/tracex3_user.c +++ b/samples/bpf/tracex3_user.c @@ -11,8 +11,7 @@ #include #include #include -#include "libbpf.h" -#include "bpf_load.h" +#include "utils.h" #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) @@ -24,7 +23,7 @@ static void clear_stats(int fd) __u64 value = 0; for (key = 0; key < SLOTS; key++) - bpf_update_elem(fd, &key, &value, BPF_ANY); + bpf_map_update_elem(fd, &key, &value, BPF_ANY); } const char *color[] = { @@ -83,7 +82,7 @@ static void print_hist(int fd) for (key = 0; key < SLOTS; key++) { value = 0; - bpf_lookup_elem(fd, &key, &value); + bpf_map_lookup_elem(fd, &key, &value); cnt[key] = value; total_events += value; if (value > max_cnt) @@ -105,13 +104,13 @@ int main(int ac, char **argv) { char filename[256]; int i; + struct bpf_object *obj; snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); - if (load_bpf_file(filename)) { - printf("%s", bpf_log_buf); + obj = load_bpf_file(filename); + if (!obj) return 1; - } for (i = 1; i < ac; i++) { if (strcmp(argv[i], "-a") == 0) { @@ -142,7 +141,7 @@ int main(int ac, char **argv) for (i = 0; ; i++) { if (i % 20 == 0) print_banner(); - print_hist(map_fd[1]); + print_hist(get_map_fd(obj, 1)); sleep(2); } diff --git a/samples/bpf/tracex4_user.c b/samples/bpf/tracex4_user.c index bc4a3bd..273bd33 100644 --- a/samples/bpf/tracex4_user.c +++ b/samples/bpf/tracex4_user.c @@ -12,8 +12,7 @@ #include #include #include -#include "libbpf.h" -#include "bpf_load.h" +#include "utils.h" struct pair { long long val; @@ -37,8 +36,8 @@ static void print_old_objects(int fd) key = write(1, "\e[1;1H\e[2J", 12); /* clear screen */ key = -1; - while (bpf_get_next_key(map_fd[0], &key, &next_key) == 0) { - bpf_lookup_elem(map_fd[0], &next_key, &v); + while (bpf_map_get_next_key(fd, &key, &next_key) == 0) { + bpf_map_lookup_elem(fd, &next_key, &v); key = next_key; if (val - v.val < 1000000000ll) /* object was allocated more then 1 sec ago */ @@ -51,17 +50,17 @@ static void print_old_objects(int fd) int main(int ac, char **argv) { char filename[256]; + struct bpf_object *obj; int i; snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); - if (load_bpf_file(filename)) { - printf("%s", bpf_log_buf); + obj = load_bpf_file(filename); + if (!obj) return 1; - } for (i = 0; ; i++) { - print_old_objects(map_fd[1]); + print_old_objects(get_map_fd(obj, 0)); sleep(1); } diff --git a/samples/bpf/tracex5_user.c b/samples/bpf/tracex5_user.c index a04dd3c..bcbd7fc 100644 --- a/samples/bpf/tracex5_user.c +++ b/samples/bpf/tracex5_user.c @@ -4,8 +4,7 @@ #include #include #include -#include "libbpf.h" -#include "bpf_load.h" +#include "utils.h" /* install fake seccomp program to enable seccomp code path inside the kernel, * so that our kprobe attached to seccomp_phase1() can be triggered @@ -27,13 +26,13 @@ int main(int ac, char **argv) { FILE *f; char filename[256]; + struct bpf_object *obj; snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); - if (load_bpf_file(filename)) { - printf("%s", bpf_log_buf); + obj = load_bpf_file(filename); + if (!obj) return 1; - } install_accept_all_seccomp(); diff --git a/samples/bpf/tracex6_user.c b/samples/bpf/tracex6_user.c index 8ea4976..a400e31 100644 --- a/samples/bpf/tracex6_user.c +++ b/samples/bpf/tracex6_user.c @@ -8,12 +8,11 @@ #include #include #include -#include "libbpf.h" -#include "bpf_load.h" +#include "utils.h" #define SAMPLE_PERIOD 0x7fffffffffffffffULL -static void test_bpf_perf_event(void) +static void test_bpf_perf_event(int map_fd) { int nr_cpus = sysconf(_SC_NPROCESSORS_CONF); int *pmu_fd = malloc(nr_cpus * sizeof(int)); @@ -36,7 +35,7 @@ static void test_bpf_perf_event(void) goto exit; } - bpf_update_elem(map_fd[0], &i, &pmu_fd[i], BPF_ANY); + bpf_map_update_elem(map_fd, &i, &pmu_fd[i], BPF_ANY); ioctl(pmu_fd[i], PERF_EVENT_IOC_ENABLE, 0); } @@ -50,22 +49,21 @@ static void test_bpf_perf_event(void) exit: for (i = 0; i < nr_cpus; i++) close(pmu_fd[i]); - close(map_fd[0]); free(pmu_fd); } int main(int argc, char **argv) { char filename[256]; + struct bpf_object *obj; snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); - if (load_bpf_file(filename)) { - printf("%s", bpf_log_buf); + obj = load_bpf_file(filename); + if (!obj) return 1; - } - test_bpf_perf_event(); + test_bpf_perf_event(get_map_fd(obj, 0)); read_trace_pipe(); return 0;