[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAEf4BzZBPS_QmHfCV-AQYNHQPEvo6kcAC4PC1SZ=ucG15jv1rg@mail.gmail.com>
Date: Fri, 1 Mar 2019 11:13:35 -0800
From: Andrii Nakryiko <andrii.nakryiko@...il.com>
To: Daniel Borkmann <daniel@...earbox.net>
Cc: Alexei Starovoitov <ast@...com>, bpf@...r.kernel.org,
Networking <netdev@...r.kernel.org>, joe@...d.net.nz,
john.fastabend@...il.com, tgraf@...g.ch,
Yonghong Song <yhs@...com>, Andrii Nakryiko <andriin@...com>,
Jakub Kicinski <jakub.kicinski@...ronome.com>,
lmb@...udflare.com
Subject: Re: [PATCH bpf-next v2 6/7] bpf, selftest: test global
data/bss/rodata sections
On Thu, Feb 28, 2019 at 3:32 PM Daniel Borkmann <daniel@...earbox.net> wrote:
>
> From: Joe Stringer <joe@...d.net.nz>
>
> Add tests for libbpf relocation of static variable references
> into the .data, .rodata and .bss sections of the ELF. Tests with
> different offsets are all passing:
>
> # ./test_progs
> [...]
> test_static_data_access:PASS:load program 0 nsec
> test_static_data_access:PASS:pass packet 278 nsec
> test_static_data_access:PASS:relocate .bss reference 1 278 nsec
> test_static_data_access:PASS:relocate .data reference 1 278 nsec
> test_static_data_access:PASS:relocate .rodata reference 1 278 nsec
> test_static_data_access:PASS:relocate .bss reference 2 278 nsec
> test_static_data_access:PASS:relocate .data reference 2 278 nsec
> test_static_data_access:PASS:relocate .rodata reference 2 278 nsec
> test_static_data_access:PASS:relocate .bss reference 3 278 nsec
> test_static_data_access:PASS:relocate .bss reference 4 278 nsec
> Summary: 223 PASSED, 0 FAILED
>
> Joint work with Daniel Borkmann.
>
> Signed-off-by: Joe Stringer <joe@...d.net.nz>
> Signed-off-by: Daniel Borkmann <daniel@...earbox.net>
> ---
> tools/testing/selftests/bpf/bpf_helpers.h | 2 +-
> .../selftests/bpf/progs/test_global_data.c | 61 +++++++++++++++++++
> tools/testing/selftests/bpf/test_progs.c | 50 +++++++++++++++
> 3 files changed, 112 insertions(+), 1 deletion(-)
> create mode 100644 tools/testing/selftests/bpf/progs/test_global_data.c
>
> diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h
> index d9999f1ed1d2..0463662935f9 100644
> --- a/tools/testing/selftests/bpf/bpf_helpers.h
> +++ b/tools/testing/selftests/bpf/bpf_helpers.h
> @@ -11,7 +11,7 @@
> /* helper functions called from eBPF programs written in C */
> static void *(*bpf_map_lookup_elem)(void *map, void *key) =
> (void *) BPF_FUNC_map_lookup_elem;
> -static int (*bpf_map_update_elem)(void *map, void *key, void *value,
> +static int (*bpf_map_update_elem)(void *map, const void *key, const void *value,
> unsigned long long flags) =
> (void *) BPF_FUNC_map_update_elem;
> static int (*bpf_map_delete_elem)(void *map, void *key) =
> diff --git a/tools/testing/selftests/bpf/progs/test_global_data.c b/tools/testing/selftests/bpf/progs/test_global_data.c
> new file mode 100644
> index 000000000000..2a7cf40b8efb
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/progs/test_global_data.c
> @@ -0,0 +1,61 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (c) 2019 Isovalent, Inc.
> +
> +#include <linux/bpf.h>
> +#include <linux/pkt_cls.h>
> +#include <string.h>
> +
> +#include "bpf_helpers.h"
> +
> +struct bpf_map_def SEC("maps") result = {
> + .type = BPF_MAP_TYPE_ARRAY,
> + .key_size = sizeof(__u32),
> + .value_size = sizeof(__u64),
> + .max_entries = 9,
> +};
> +
> +static __u64 static_bss = 0; /* Reloc reference to .bss section */
> +static __u64 static_data = 42; /* Reloc reference to .data section */
> +static const __u64 static_rodata = 24; /* Reloc reference to .rodata section */
> +static __u64 static_bss2 = 0; /* Reloc reference to .bss section */
> +static __u64 static_data2 = 0xffeeff; /* Reloc reference to .data section */
> +static const __u64 static_rodata2 = 0xabab; /* Reloc reference to .rodata section */
> +static const __u64 static_rodata3 = 0xab; /* Reloc reference to .rodata section */
In the light of Yonghong's explanation about static vs non-static
globals, it would be nice to add test for non-static initialized
globals here as well?
> +
> +SEC("static_data_load")
> +int load_static_data(struct __sk_buff *skb)
> +{
> + __u32 key;
> +
> + key = 0;
> + bpf_map_update_elem(&result, &key, &static_bss, 0);
> +
> + key = 1;
> + bpf_map_update_elem(&result, &key, &static_data, 0);
> +
> + key = 2;
> + bpf_map_update_elem(&result, &key, &static_rodata, 0);
> +
> + key = 3;
> + bpf_map_update_elem(&result, &key, &static_bss2, 0);
> +
> + key = 4;
> + bpf_map_update_elem(&result, &key, &static_data2, 0);
> +
> + key = 5;
> + bpf_map_update_elem(&result, &key, &static_rodata2, 0);
> +
> + key = 6;
> + static_bss2 = 1234;
> + bpf_map_update_elem(&result, &key, &static_bss2, 0);
> +
> + key = 7;
> + bpf_map_update_elem(&result, &key, &static_bss, 0);
> +
> + key = 8;
> + bpf_map_update_elem(&result, &key, &static_rodata3, 0);
> +
> + return TC_ACT_OK;
> +}
> +
> +char _license[] SEC("license") = "GPL";
> diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c
> index c59d2e015d16..a3e64c054572 100644
> --- a/tools/testing/selftests/bpf/test_progs.c
> +++ b/tools/testing/selftests/bpf/test_progs.c
> @@ -738,6 +738,55 @@ static void test_pkt_md_access(void)
> bpf_object__close(obj);
> }
>
> +static void test_static_data_access(void)
> +{
> + const char *file = "./test_global_data.o";
> + struct bpf_object *obj;
> + __u32 duration = 0, retval;
> + int i, err, prog_fd, map_fd;
> + uint64_t value;
> +
> + err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
> + if (CHECK(err, "load program", "error %d loading %s\n", err, file))
> + return;
> +
> + map_fd = bpf_find_map(__func__, obj, "result");
> + if (map_fd < 0) {
> + error_cnt++;
> + goto close_prog;
> + }
> +
> + err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4),
> + NULL, NULL, &retval, &duration);
> + CHECK(err || retval, "pass packet",
> + "err %d errno %d retval %d duration %d\n",
> + err, errno, retval, duration);
> +
> + struct {
> + char *name;
> + uint32_t key;
> + uint64_t value;
> + } tests[] = {
> + { "relocate .bss reference 1", 0, 0 },
> + { "relocate .data reference 1", 1, 42 },
> + { "relocate .rodata reference 1", 2, 24 },
> + { "relocate .bss reference 2", 3, 0 },
> + { "relocate .data reference 2", 4, 0xffeeff },
> + { "relocate .rodata reference 2", 5, 0xabab },
> + { "relocate .bss reference 3", 6, 1234 },
> + { "relocate .bss reference 4", 7, 0 },
> + };
> + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
> + err = bpf_map_lookup_elem(map_fd, &tests[i].key, &value);
> + CHECK (err || value != tests[i].value, tests[i].name,
> + "err %d result %lu expected %lu\n",
> + err, value, tests[i].value);
> + }
> +
> +close_prog:
> + bpf_object__close(obj);
> +}
> +
> static void test_obj_name(void)
> {
> struct {
> @@ -2182,6 +2231,7 @@ int main(void)
> test_map_lock();
> test_signal_pending(BPF_PROG_TYPE_SOCKET_FILTER);
> test_signal_pending(BPF_PROG_TYPE_FLOW_DISSECTOR);
> + test_static_data_access();
>
> printf("Summary: %d PASSED, %d FAILED\n", pass_cnt, error_cnt);
> return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS;
> --
> 2.17.1
>
Powered by blists - more mailing lists