Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
Alexei Starovoitov says: ==================== pull-request: bpf-next 2020-07-13 The following pull-request contains BPF updates for your *net-next* tree. We've added 36 non-merge commits during the last 7 day(s) which contain a total of 62 files changed, 2242 insertions(+), 468 deletions(-). The main changes are: 1) Avoid trace_printk warning banner by switching bpf_trace_printk to use its own tracing event, from Alan. 2) Better libbpf support on older kernels, from Andrii. 3) Additional AF_XDP stats, from Ciara. 4) build time resolution of BTF IDs, from Jiri. 5) BPF_CGROUP_INET_SOCK_RELEASE hook, from Stanislav. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -111,6 +111,7 @@ SCRATCH_DIR := $(OUTPUT)/tools
|
||||
BUILD_DIR := $(SCRATCH_DIR)/build
|
||||
INCLUDE_DIR := $(SCRATCH_DIR)/include
|
||||
BPFOBJ := $(BUILD_DIR)/libbpf/libbpf.a
|
||||
RESOLVE_BTFIDS := $(BUILD_DIR)/resolve_btfids/resolve_btfids
|
||||
|
||||
# Define simple and short `make test_progs`, `make test_sysctl`, etc targets
|
||||
# to build individual tests.
|
||||
@@ -177,7 +178,7 @@ $(BPFOBJ): $(wildcard $(BPFDIR)/*.[ch] $(BPFDIR)/Makefile) \
|
||||
$(Q)$(MAKE) $(submake_extras) -C $(BPFDIR) OUTPUT=$(BUILD_DIR)/libbpf/ \
|
||||
DESTDIR=$(SCRATCH_DIR) prefix= all install_headers
|
||||
|
||||
$(BUILD_DIR)/libbpf $(BUILD_DIR)/bpftool $(INCLUDE_DIR):
|
||||
$(BUILD_DIR)/libbpf $(BUILD_DIR)/bpftool $(BUILD_DIR)/resolve_btfids $(INCLUDE_DIR):
|
||||
$(call msg,MKDIR,,$@)
|
||||
mkdir -p $@
|
||||
|
||||
@@ -190,6 +191,16 @@ else
|
||||
cp "$(VMLINUX_H)" $@
|
||||
endif
|
||||
|
||||
$(RESOLVE_BTFIDS): $(BPFOBJ) | $(BUILD_DIR)/resolve_btfids \
|
||||
$(TOOLSDIR)/bpf/resolve_btfids/main.c \
|
||||
$(TOOLSDIR)/lib/rbtree.c \
|
||||
$(TOOLSDIR)/lib/zalloc.c \
|
||||
$(TOOLSDIR)/lib/string.c \
|
||||
$(TOOLSDIR)/lib/ctype.c \
|
||||
$(TOOLSDIR)/lib/str_error_r.c
|
||||
$(Q)$(MAKE) $(submake_extras) -C $(TOOLSDIR)/bpf/resolve_btfids \
|
||||
OUTPUT=$(BUILD_DIR)/resolve_btfids/ BPFOBJ=$(BPFOBJ)
|
||||
|
||||
# Get Clang's default includes on this system, as opposed to those seen by
|
||||
# '-target bpf'. This fixes "missing" files on some architectures/distros,
|
||||
# such as asm/byteorder.h, asm/socket.h, asm/sockios.h, sys/cdefs.h etc.
|
||||
@@ -352,9 +363,11 @@ endif
|
||||
|
||||
$(OUTPUT)/$(TRUNNER_BINARY): $(TRUNNER_TEST_OBJS) \
|
||||
$(TRUNNER_EXTRA_OBJS) $$(BPFOBJ) \
|
||||
$(RESOLVE_BTFIDS) \
|
||||
| $(TRUNNER_BINARY)-extras
|
||||
$$(call msg,BINARY,,$$@)
|
||||
$$(CC) $$(CFLAGS) $$(filter %.a %.o,$$^) $$(LDLIBS) -o $$@
|
||||
$(RESOLVE_BTFIDS) --no-fail --btf btf_data.o $$@
|
||||
|
||||
endef
|
||||
|
||||
|
@@ -2,20 +2,6 @@
|
||||
#ifndef __BPF_LEGACY__
|
||||
#define __BPF_LEGACY__
|
||||
|
||||
/*
|
||||
* legacy bpf_map_def with extra fields supported only by bpf_load(), do not
|
||||
* use outside of samples/bpf
|
||||
*/
|
||||
struct bpf_map_def_legacy {
|
||||
unsigned int type;
|
||||
unsigned int key_size;
|
||||
unsigned int value_size;
|
||||
unsigned int max_entries;
|
||||
unsigned int map_flags;
|
||||
unsigned int inner_map_idx;
|
||||
unsigned int numa_node;
|
||||
};
|
||||
|
||||
#define BPF_ANNOTATE_KV_PAIR(name, type_key, type_val) \
|
||||
struct ____btf_map_##name { \
|
||||
type_key key; \
|
||||
|
33
tools/testing/selftests/bpf/prog_tests/core_retro.c
Normal file
33
tools/testing/selftests/bpf/prog_tests/core_retro.c
Normal file
@@ -0,0 +1,33 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (c) 2020 Facebook
|
||||
#define _GNU_SOURCE
|
||||
#include <test_progs.h>
|
||||
#include "test_core_retro.skel.h"
|
||||
|
||||
void test_core_retro(void)
|
||||
{
|
||||
int err, zero = 0, res, duration = 0;
|
||||
struct test_core_retro *skel;
|
||||
|
||||
/* load program */
|
||||
skel = test_core_retro__open_and_load();
|
||||
if (CHECK(!skel, "skel_load", "skeleton open/load failed\n"))
|
||||
goto out_close;
|
||||
|
||||
/* attach probe */
|
||||
err = test_core_retro__attach(skel);
|
||||
if (CHECK(err, "attach_kprobe", "err %d\n", err))
|
||||
goto out_close;
|
||||
|
||||
/* trigger */
|
||||
usleep(1);
|
||||
|
||||
err = bpf_map_lookup_elem(bpf_map__fd(skel->maps.results), &zero, &res);
|
||||
if (CHECK(err, "map_lookup", "failed to lookup result: %d\n", errno))
|
||||
goto out_close;
|
||||
|
||||
CHECK(res != getpid(), "pid_check", "got %d != exp %d\n", res, getpid());
|
||||
|
||||
out_close:
|
||||
test_core_retro__destroy(skel);
|
||||
}
|
@@ -4,6 +4,7 @@
|
||||
#include <sched.h>
|
||||
#include <sys/socket.h>
|
||||
#include <test_progs.h>
|
||||
#include "test_perf_buffer.skel.h"
|
||||
#include "bpf/libbpf_internal.h"
|
||||
|
||||
/* AddressSanitizer sometimes crashes due to data dereference below, due to
|
||||
@@ -25,16 +26,11 @@ static void on_sample(void *ctx, int cpu, void *data, __u32 size)
|
||||
|
||||
void test_perf_buffer(void)
|
||||
{
|
||||
int err, prog_fd, on_len, nr_on_cpus = 0, nr_cpus, i, duration = 0;
|
||||
const char *prog_name = "kprobe/sys_nanosleep";
|
||||
const char *file = "./test_perf_buffer.o";
|
||||
int err, on_len, nr_on_cpus = 0, nr_cpus, i, duration = 0;
|
||||
struct perf_buffer_opts pb_opts = {};
|
||||
struct bpf_map *perf_buf_map;
|
||||
struct test_perf_buffer *skel;
|
||||
cpu_set_t cpu_set, cpu_seen;
|
||||
struct bpf_program *prog;
|
||||
struct bpf_object *obj;
|
||||
struct perf_buffer *pb;
|
||||
struct bpf_link *link;
|
||||
bool *online;
|
||||
|
||||
nr_cpus = libbpf_num_possible_cpus();
|
||||
@@ -51,33 +47,21 @@ void test_perf_buffer(void)
|
||||
nr_on_cpus++;
|
||||
|
||||
/* load program */
|
||||
err = bpf_prog_load(file, BPF_PROG_TYPE_KPROBE, &obj, &prog_fd);
|
||||
if (CHECK(err, "obj_load", "err %d errno %d\n", err, errno)) {
|
||||
obj = NULL;
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
prog = bpf_object__find_program_by_title(obj, prog_name);
|
||||
if (CHECK(!prog, "find_probe", "prog '%s' not found\n", prog_name))
|
||||
skel = test_perf_buffer__open_and_load();
|
||||
if (CHECK(!skel, "skel_load", "skeleton open/load failed\n"))
|
||||
goto out_close;
|
||||
|
||||
/* load map */
|
||||
perf_buf_map = bpf_object__find_map_by_name(obj, "perf_buf_map");
|
||||
if (CHECK(!perf_buf_map, "find_perf_buf_map", "not found\n"))
|
||||
goto out_close;
|
||||
|
||||
/* attach kprobe */
|
||||
link = bpf_program__attach_kprobe(prog, false /* retprobe */,
|
||||
SYS_NANOSLEEP_KPROBE_NAME);
|
||||
if (CHECK(IS_ERR(link), "attach_kprobe", "err %ld\n", PTR_ERR(link)))
|
||||
/* attach probe */
|
||||
err = test_perf_buffer__attach(skel);
|
||||
if (CHECK(err, "attach_kprobe", "err %d\n", err))
|
||||
goto out_close;
|
||||
|
||||
/* set up perf buffer */
|
||||
pb_opts.sample_cb = on_sample;
|
||||
pb_opts.ctx = &cpu_seen;
|
||||
pb = perf_buffer__new(bpf_map__fd(perf_buf_map), 1, &pb_opts);
|
||||
pb = perf_buffer__new(bpf_map__fd(skel->maps.perf_buf_map), 1, &pb_opts);
|
||||
if (CHECK(IS_ERR(pb), "perf_buf__new", "err %ld\n", PTR_ERR(pb)))
|
||||
goto out_detach;
|
||||
goto out_close;
|
||||
|
||||
/* trigger kprobe on every CPU */
|
||||
CPU_ZERO(&cpu_seen);
|
||||
@@ -94,7 +78,7 @@ void test_perf_buffer(void)
|
||||
&cpu_set);
|
||||
if (err && CHECK(err, "set_affinity", "cpu #%d, err %d\n",
|
||||
i, err))
|
||||
goto out_detach;
|
||||
goto out_close;
|
||||
|
||||
usleep(1);
|
||||
}
|
||||
@@ -110,9 +94,7 @@ void test_perf_buffer(void)
|
||||
|
||||
out_free_pb:
|
||||
perf_buffer__free(pb);
|
||||
out_detach:
|
||||
bpf_link__destroy(link);
|
||||
out_close:
|
||||
bpf_object__close(obj);
|
||||
test_perf_buffer__destroy(skel);
|
||||
free(online);
|
||||
}
|
||||
|
111
tools/testing/selftests/bpf/prog_tests/resolve_btfids.c
Normal file
111
tools/testing/selftests/bpf/prog_tests/resolve_btfids.c
Normal file
@@ -0,0 +1,111 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <string.h>
|
||||
#include <bpf/btf.h>
|
||||
#include <bpf/libbpf.h>
|
||||
#include <linux/btf.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/btf_ids.h>
|
||||
#include "test_progs.h"
|
||||
|
||||
static int duration;
|
||||
|
||||
struct symbol {
|
||||
const char *name;
|
||||
int type;
|
||||
int id;
|
||||
};
|
||||
|
||||
struct symbol test_symbols[] = {
|
||||
{ "unused", BTF_KIND_UNKN, 0 },
|
||||
{ "S", BTF_KIND_TYPEDEF, -1 },
|
||||
{ "T", BTF_KIND_TYPEDEF, -1 },
|
||||
{ "U", BTF_KIND_TYPEDEF, -1 },
|
||||
{ "S", BTF_KIND_STRUCT, -1 },
|
||||
{ "U", BTF_KIND_UNION, -1 },
|
||||
{ "func", BTF_KIND_FUNC, -1 },
|
||||
};
|
||||
|
||||
BTF_ID_LIST(test_list)
|
||||
BTF_ID_UNUSED
|
||||
BTF_ID(typedef, S)
|
||||
BTF_ID(typedef, T)
|
||||
BTF_ID(typedef, U)
|
||||
BTF_ID(struct, S)
|
||||
BTF_ID(union, U)
|
||||
BTF_ID(func, func)
|
||||
|
||||
static int
|
||||
__resolve_symbol(struct btf *btf, int type_id)
|
||||
{
|
||||
const struct btf_type *type;
|
||||
const char *str;
|
||||
unsigned int i;
|
||||
|
||||
type = btf__type_by_id(btf, type_id);
|
||||
if (!type) {
|
||||
PRINT_FAIL("Failed to get type for ID %d\n", type_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(test_symbols); i++) {
|
||||
if (test_symbols[i].id != -1)
|
||||
continue;
|
||||
|
||||
if (BTF_INFO_KIND(type->info) != test_symbols[i].type)
|
||||
continue;
|
||||
|
||||
str = btf__name_by_offset(btf, type->name_off);
|
||||
if (!str) {
|
||||
PRINT_FAIL("Failed to get name for BTF ID %d\n", type_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!strcmp(str, test_symbols[i].name))
|
||||
test_symbols[i].id = type_id;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int resolve_symbols(void)
|
||||
{
|
||||
struct btf *btf;
|
||||
int type_id;
|
||||
__u32 nr;
|
||||
|
||||
btf = btf__parse_elf("btf_data.o", NULL);
|
||||
if (CHECK(libbpf_get_error(btf), "resolve",
|
||||
"Failed to load BTF from btf_data.o\n"))
|
||||
return -1;
|
||||
|
||||
nr = btf__get_nr_types(btf);
|
||||
|
||||
for (type_id = 1; type_id <= nr; type_id++) {
|
||||
if (__resolve_symbol(btf, type_id))
|
||||
break;
|
||||
}
|
||||
|
||||
btf__free(btf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_resolve_btfids(void)
|
||||
{
|
||||
unsigned int i;
|
||||
int ret = 0;
|
||||
|
||||
if (resolve_symbols())
|
||||
return -1;
|
||||
|
||||
/* Check BTF_ID_LIST(test_list) IDs */
|
||||
for (i = 0; i < ARRAY_SIZE(test_symbols) && !ret; i++) {
|
||||
ret = CHECK(test_list[i] != test_symbols[i].id,
|
||||
"id_check",
|
||||
"wrong ID for %s (%d != %d)\n", test_symbols[i].name,
|
||||
test_list[i], test_symbols[i].id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
@@ -41,7 +41,7 @@ void test_skeleton(void)
|
||||
CHECK(bss->in4 != 0, "in4", "got %lld != exp %lld\n", bss->in4, 0LL);
|
||||
CHECK(bss->out4 != 0, "out4", "got %lld != exp %lld\n", bss->out4, 0LL);
|
||||
|
||||
CHECK(rodata->in6 != 0, "in6", "got %d != exp %d\n", rodata->in6, 0);
|
||||
CHECK(rodata->in.in6 != 0, "in6", "got %d != exp %d\n", rodata->in.in6, 0);
|
||||
CHECK(bss->out6 != 0, "out6", "got %d != exp %d\n", bss->out6, 0);
|
||||
|
||||
/* validate we can pre-setup global variables, even in .bss */
|
||||
@@ -49,7 +49,7 @@ void test_skeleton(void)
|
||||
data->in2 = 11;
|
||||
bss->in3 = 12;
|
||||
bss->in4 = 13;
|
||||
rodata->in6 = 14;
|
||||
rodata->in.in6 = 14;
|
||||
|
||||
err = test_skeleton__load(skel);
|
||||
if (CHECK(err, "skel_load", "failed to load skeleton: %d\n", err))
|
||||
@@ -60,7 +60,7 @@ void test_skeleton(void)
|
||||
CHECK(data->in2 != 11, "in2", "got %lld != exp %lld\n", data->in2, 11LL);
|
||||
CHECK(bss->in3 != 12, "in3", "got %d != exp %d\n", bss->in3, 12);
|
||||
CHECK(bss->in4 != 13, "in4", "got %lld != exp %lld\n", bss->in4, 13LL);
|
||||
CHECK(rodata->in6 != 14, "in6", "got %d != exp %d\n", rodata->in6, 14);
|
||||
CHECK(rodata->in.in6 != 14, "in6", "got %d != exp %d\n", rodata->in.in6, 14);
|
||||
|
||||
/* now set new values and attach to get them into outX variables */
|
||||
data->in1 = 1;
|
||||
|
75
tools/testing/selftests/bpf/prog_tests/trace_printk.c
Normal file
75
tools/testing/selftests/bpf/prog_tests/trace_printk.c
Normal file
@@ -0,0 +1,75 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2020, Oracle and/or its affiliates. */
|
||||
|
||||
#include <test_progs.h>
|
||||
|
||||
#include "trace_printk.skel.h"
|
||||
|
||||
#define TRACEBUF "/sys/kernel/debug/tracing/trace_pipe"
|
||||
#define SEARCHMSG "testing,testing"
|
||||
|
||||
void test_trace_printk(void)
|
||||
{
|
||||
int err, iter = 0, duration = 0, found = 0;
|
||||
struct trace_printk__bss *bss;
|
||||
struct trace_printk *skel;
|
||||
char *buf = NULL;
|
||||
FILE *fp = NULL;
|
||||
size_t buflen;
|
||||
|
||||
skel = trace_printk__open();
|
||||
if (CHECK(!skel, "skel_open", "failed to open skeleton\n"))
|
||||
return;
|
||||
|
||||
err = trace_printk__load(skel);
|
||||
if (CHECK(err, "skel_load", "failed to load skeleton: %d\n", err))
|
||||
goto cleanup;
|
||||
|
||||
bss = skel->bss;
|
||||
|
||||
err = trace_printk__attach(skel);
|
||||
if (CHECK(err, "skel_attach", "skeleton attach failed: %d\n", err))
|
||||
goto cleanup;
|
||||
|
||||
fp = fopen(TRACEBUF, "r");
|
||||
if (CHECK(fp == NULL, "could not open trace buffer",
|
||||
"error %d opening %s", errno, TRACEBUF))
|
||||
goto cleanup;
|
||||
|
||||
/* We do not want to wait forever if this test fails... */
|
||||
fcntl(fileno(fp), F_SETFL, O_NONBLOCK);
|
||||
|
||||
/* wait for tracepoint to trigger */
|
||||
usleep(1);
|
||||
trace_printk__detach(skel);
|
||||
|
||||
if (CHECK(bss->trace_printk_ran == 0,
|
||||
"bpf_trace_printk never ran",
|
||||
"ran == %d", bss->trace_printk_ran))
|
||||
goto cleanup;
|
||||
|
||||
if (CHECK(bss->trace_printk_ret <= 0,
|
||||
"bpf_trace_printk returned <= 0 value",
|
||||
"got %d", bss->trace_printk_ret))
|
||||
goto cleanup;
|
||||
|
||||
/* verify our search string is in the trace buffer */
|
||||
while (getline(&buf, &buflen, fp) >= 0 || errno == EAGAIN) {
|
||||
if (strstr(buf, SEARCHMSG) != NULL)
|
||||
found++;
|
||||
if (found == bss->trace_printk_ran)
|
||||
break;
|
||||
if (++iter > 1000)
|
||||
break;
|
||||
}
|
||||
|
||||
if (CHECK(!found, "message from bpf_trace_printk not found",
|
||||
"no instance of %s in %s", SEARCHMSG, TRACEBUF))
|
||||
goto cleanup;
|
||||
|
||||
cleanup:
|
||||
trace_printk__destroy(skel);
|
||||
free(buf);
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
}
|
75
tools/testing/selftests/bpf/prog_tests/udp_limit.c
Normal file
75
tools/testing/selftests/bpf/prog_tests/udp_limit.c
Normal file
@@ -0,0 +1,75 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <test_progs.h>
|
||||
#include "udp_limit.skel.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
static int duration;
|
||||
|
||||
void test_udp_limit(void)
|
||||
{
|
||||
struct udp_limit *skel;
|
||||
int fd1 = -1, fd2 = -1;
|
||||
int cgroup_fd;
|
||||
|
||||
cgroup_fd = test__join_cgroup("/udp_limit");
|
||||
if (CHECK(cgroup_fd < 0, "cg-join", "errno %d", errno))
|
||||
return;
|
||||
|
||||
skel = udp_limit__open_and_load();
|
||||
if (CHECK(!skel, "skel-load", "errno %d", errno))
|
||||
goto close_cgroup_fd;
|
||||
|
||||
skel->links.sock = bpf_program__attach_cgroup(skel->progs.sock, cgroup_fd);
|
||||
skel->links.sock_release = bpf_program__attach_cgroup(skel->progs.sock_release, cgroup_fd);
|
||||
if (CHECK(IS_ERR(skel->links.sock) || IS_ERR(skel->links.sock_release),
|
||||
"cg-attach", "sock %ld sock_release %ld",
|
||||
PTR_ERR(skel->links.sock),
|
||||
PTR_ERR(skel->links.sock_release)))
|
||||
goto close_skeleton;
|
||||
|
||||
/* BPF program enforces a single UDP socket per cgroup,
|
||||
* verify that.
|
||||
*/
|
||||
fd1 = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (CHECK(fd1 < 0, "fd1", "errno %d", errno))
|
||||
goto close_skeleton;
|
||||
|
||||
fd2 = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (CHECK(fd2 >= 0, "fd2", "errno %d", errno))
|
||||
goto close_skeleton;
|
||||
|
||||
/* We can reopen again after close. */
|
||||
close(fd1);
|
||||
fd1 = -1;
|
||||
|
||||
fd1 = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (CHECK(fd1 < 0, "fd1-again", "errno %d", errno))
|
||||
goto close_skeleton;
|
||||
|
||||
/* Make sure the program was invoked the expected
|
||||
* number of times:
|
||||
* - open fd1 - BPF_CGROUP_INET_SOCK_CREATE
|
||||
* - attempt to openfd2 - BPF_CGROUP_INET_SOCK_CREATE
|
||||
* - close fd1 - BPF_CGROUP_INET_SOCK_RELEASE
|
||||
* - open fd1 again - BPF_CGROUP_INET_SOCK_CREATE
|
||||
*/
|
||||
if (CHECK(skel->bss->invocations != 4, "bss-invocations",
|
||||
"invocations=%d", skel->bss->invocations))
|
||||
goto close_skeleton;
|
||||
|
||||
/* We should still have a single socket in use */
|
||||
if (CHECK(skel->bss->in_use != 1, "bss-in_use",
|
||||
"in_use=%d", skel->bss->in_use))
|
||||
goto close_skeleton;
|
||||
|
||||
close_skeleton:
|
||||
if (fd1 >= 0)
|
||||
close(fd1);
|
||||
if (fd2 >= 0)
|
||||
close(fd2);
|
||||
udp_limit__destroy(skel);
|
||||
close_cgroup_fd:
|
||||
close(cgroup_fd);
|
||||
}
|
50
tools/testing/selftests/bpf/progs/btf_data.c
Normal file
50
tools/testing/selftests/bpf/progs/btf_data.c
Normal file
@@ -0,0 +1,50 @@
|
||||
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
||||
|
||||
struct S {
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
};
|
||||
|
||||
union U {
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
};
|
||||
|
||||
struct S1 {
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
};
|
||||
|
||||
union U1 {
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
};
|
||||
|
||||
typedef int T;
|
||||
typedef int S;
|
||||
typedef int U;
|
||||
typedef int T1;
|
||||
typedef int S1;
|
||||
typedef int U1;
|
||||
|
||||
struct root_struct {
|
||||
S m_1;
|
||||
T m_2;
|
||||
U m_3;
|
||||
S1 m_4;
|
||||
T1 m_5;
|
||||
U1 m_6;
|
||||
struct S m_7;
|
||||
struct S1 m_8;
|
||||
union U m_9;
|
||||
union U1 m_10;
|
||||
};
|
||||
|
||||
int func(struct root_struct *root)
|
||||
{
|
||||
return 0;
|
||||
}
|
30
tools/testing/selftests/bpf/progs/test_core_retro.c
Normal file
30
tools/testing/selftests/bpf/progs/test_core_retro.c
Normal file
@@ -0,0 +1,30 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (c) 2020 Facebook
|
||||
#include <linux/bpf.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_core_read.h>
|
||||
|
||||
struct task_struct {
|
||||
int tgid;
|
||||
} __attribute__((preserve_access_index));
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY);
|
||||
__uint(max_entries, 1);
|
||||
__type(key, int);
|
||||
__type(value, int);
|
||||
} results SEC(".maps");
|
||||
|
||||
SEC("tp/raw_syscalls/sys_enter")
|
||||
int handle_sys_enter(void *ctx)
|
||||
{
|
||||
struct task_struct *task = (void *)bpf_get_current_task();
|
||||
int tgid = BPF_CORE_READ(task, tgid);
|
||||
int zero = 0;
|
||||
|
||||
bpf_map_update_elem(&results, &zero, &tgid, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
@@ -12,8 +12,8 @@ struct {
|
||||
__uint(value_size, sizeof(int));
|
||||
} perf_buf_map SEC(".maps");
|
||||
|
||||
SEC("kprobe/sys_nanosleep")
|
||||
int BPF_KPROBE(handle_sys_nanosleep_entry)
|
||||
SEC("tp/raw_syscalls/sys_enter")
|
||||
int handle_sys_enter(void *ctx)
|
||||
{
|
||||
int cpu = bpf_get_smp_processor_id();
|
||||
|
||||
|
@@ -20,7 +20,9 @@ long long in4 __attribute__((aligned(64))) = 0;
|
||||
struct s in5 = {};
|
||||
|
||||
/* .rodata section */
|
||||
const volatile int in6 = 0;
|
||||
const volatile struct {
|
||||
const int in6;
|
||||
} in = {};
|
||||
|
||||
/* .data section */
|
||||
int out1 = -1;
|
||||
@@ -46,7 +48,7 @@ int handler(const void *ctx)
|
||||
out3 = in3;
|
||||
out4 = in4;
|
||||
out5 = in5;
|
||||
out6 = in6;
|
||||
out6 = in.in6;
|
||||
|
||||
bpf_syscall = CONFIG_BPF_SYSCALL;
|
||||
kern_ver = LINUX_KERNEL_VERSION;
|
||||
|
21
tools/testing/selftests/bpf/progs/trace_printk.c
Normal file
21
tools/testing/selftests/bpf/progs/trace_printk.c
Normal file
@@ -0,0 +1,21 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (c) 2020, Oracle and/or its affiliates.
|
||||
|
||||
#include "vmlinux.h"
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_tracing.h>
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
|
||||
int trace_printk_ret = 0;
|
||||
int trace_printk_ran = 0;
|
||||
|
||||
SEC("tp/raw_syscalls/sys_enter")
|
||||
int sys_enter(void *ctx)
|
||||
{
|
||||
static const char fmt[] = "testing,testing %d\n";
|
||||
|
||||
trace_printk_ret = bpf_trace_printk(fmt, sizeof(fmt),
|
||||
++trace_printk_ran);
|
||||
return 0;
|
||||
}
|
42
tools/testing/selftests/bpf/progs/udp_limit.c
Normal file
42
tools/testing/selftests/bpf/progs/udp_limit.c
Normal file
@@ -0,0 +1,42 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
|
||||
int invocations = 0, in_use = 0;
|
||||
|
||||
SEC("cgroup/sock_create")
|
||||
int sock(struct bpf_sock *ctx)
|
||||
{
|
||||
__u32 key;
|
||||
|
||||
if (ctx->type != SOCK_DGRAM)
|
||||
return 1;
|
||||
|
||||
__sync_fetch_and_add(&invocations, 1);
|
||||
|
||||
if (in_use > 0) {
|
||||
/* BPF_CGROUP_INET_SOCK_RELEASE is _not_ called
|
||||
* when we return an error from the BPF
|
||||
* program!
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
__sync_fetch_and_add(&in_use, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
SEC("cgroup/sock_release")
|
||||
int sock_release(struct bpf_sock *ctx)
|
||||
{
|
||||
__u32 key;
|
||||
|
||||
if (ctx->type != SOCK_DGRAM)
|
||||
return 1;
|
||||
|
||||
__sync_fetch_and_add(&invocations, 1);
|
||||
__sync_fetch_and_add(&in_use, -1);
|
||||
return 1;
|
||||
}
|
@@ -12,6 +12,9 @@
|
||||
#include <string.h>
|
||||
#include <execinfo.h> /* backtrace */
|
||||
|
||||
#define EXIT_NO_TEST 2
|
||||
#define EXIT_ERR_SETUP_INFRA 3
|
||||
|
||||
/* defined in test_progs.h */
|
||||
struct test_env env = {};
|
||||
|
||||
@@ -111,13 +114,13 @@ static void reset_affinity() {
|
||||
if (err < 0) {
|
||||
stdio_restore();
|
||||
fprintf(stderr, "Failed to reset process affinity: %d!\n", err);
|
||||
exit(-1);
|
||||
exit(EXIT_ERR_SETUP_INFRA);
|
||||
}
|
||||
err = pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset);
|
||||
if (err < 0) {
|
||||
stdio_restore();
|
||||
fprintf(stderr, "Failed to reset thread affinity: %d!\n", err);
|
||||
exit(-1);
|
||||
exit(EXIT_ERR_SETUP_INFRA);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +129,7 @@ static void save_netns(void)
|
||||
env.saved_netns_fd = open("/proc/self/ns/net", O_RDONLY);
|
||||
if (env.saved_netns_fd == -1) {
|
||||
perror("open(/proc/self/ns/net)");
|
||||
exit(-1);
|
||||
exit(EXIT_ERR_SETUP_INFRA);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +138,7 @@ static void restore_netns(void)
|
||||
if (setns(env.saved_netns_fd, CLONE_NEWNET) == -1) {
|
||||
stdio_restore();
|
||||
perror("setns(CLONE_NEWNS)");
|
||||
exit(-1);
|
||||
exit(EXIT_ERR_SETUP_INFRA);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -740,7 +743,7 @@ out:
|
||||
close(env.saved_netns_fd);
|
||||
|
||||
if (env.succ_cnt + env.fail_cnt + env.skip_cnt == 0)
|
||||
return EXIT_FAILURE;
|
||||
return EXIT_NO_TEST;
|
||||
|
||||
return env.fail_cnt ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
||||
|
Reference in New Issue
Block a user