From e41074d39d71aa62a6ec557af09cd42ca0928e05 Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Thu, 14 Nov 2019 10:57:07 -0800 Subject: selftest/bpf: Simple test for fentry/fexit Add simple test for fentry and fexit programs around eth_type_trans. Signed-off-by: Alexei Starovoitov Signed-off-by: Daniel Borkmann Acked-by: Andrii Nakryiko Acked-by: Song Liu Link: https://lore.kernel.org/bpf/20191114185720.1641606-8-ast@kernel.org --- tools/testing/selftests/bpf/prog_tests/kfree_skb.c | 39 ++++++++++++++-- tools/testing/selftests/bpf/progs/kfree_skb.c | 52 ++++++++++++++++++++++ 2 files changed, 88 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/testing/selftests/bpf/prog_tests/kfree_skb.c b/tools/testing/selftests/bpf/prog_tests/kfree_skb.c index 55d36856e621..7507c8f689bc 100644 --- a/tools/testing/selftests/bpf/prog_tests/kfree_skb.c +++ b/tools/testing/selftests/bpf/prog_tests/kfree_skb.c @@ -60,15 +60,17 @@ void test_kfree_skb(void) .file = "./kfree_skb.o", }; + struct bpf_link *link = NULL, *link_fentry = NULL, *link_fexit = NULL; + struct bpf_map *perf_buf_map, *global_data; + struct bpf_program *prog, *fentry, *fexit; struct bpf_object *obj, *obj2 = NULL; struct perf_buffer_opts pb_opts = {}; struct perf_buffer *pb = NULL; - struct bpf_link *link = NULL; - struct bpf_map *perf_buf_map; - struct bpf_program *prog; int err, kfree_skb_fd; bool passed = false; __u32 duration = 0; + const int zero = 0; + bool test_ok[2]; err = bpf_prog_load("./test_pkt_access.o", BPF_PROG_TYPE_SCHED_CLS, &obj, &tattr.prog_fd); @@ -82,9 +84,28 @@ void test_kfree_skb(void) prog = bpf_object__find_program_by_title(obj2, "tp_btf/kfree_skb"); if (CHECK(!prog, "find_prog", "prog kfree_skb not found\n")) goto close_prog; + fentry = bpf_object__find_program_by_title(obj2, "fentry/eth_type_trans"); + if (CHECK(!fentry, "find_prog", "prog eth_type_trans not found\n")) + goto close_prog; + fexit = bpf_object__find_program_by_title(obj2, "fexit/eth_type_trans"); + if (CHECK(!fexit, "find_prog", "prog eth_type_trans not found\n")) + goto close_prog; + + global_data = bpf_object__find_map_by_name(obj2, "kfree_sk.bss"); + if (CHECK(!global_data, "find global data", "not found\n")) + goto close_prog; + link = bpf_program__attach_raw_tracepoint(prog, NULL); if (CHECK(IS_ERR(link), "attach_raw_tp", "err %ld\n", PTR_ERR(link))) goto close_prog; + link_fentry = bpf_program__attach_trace(fentry); + if (CHECK(IS_ERR(link_fentry), "attach fentry", "err %ld\n", + PTR_ERR(link_fentry))) + goto close_prog; + link_fexit = bpf_program__attach_trace(fexit); + if (CHECK(IS_ERR(link_fexit), "attach fexit", "err %ld\n", + PTR_ERR(link_fexit))) + goto close_prog; perf_buf_map = bpf_object__find_map_by_name(obj2, "perf_buf_map"); if (CHECK(!perf_buf_map, "find_perf_buf_map", "not found\n")) @@ -108,14 +129,26 @@ void test_kfree_skb(void) err = perf_buffer__poll(pb, 100); if (CHECK(err < 0, "perf_buffer__poll", "err %d\n", err)) goto close_prog; + /* make sure kfree_skb program was triggered * and it sent expected skb into ring buffer */ CHECK_FAIL(!passed); + + err = bpf_map_lookup_elem(bpf_map__fd(global_data), &zero, test_ok); + if (CHECK(err, "get_result", + "failed to get output data: %d\n", err)) + goto close_prog; + + CHECK_FAIL(!test_ok[0] || !test_ok[1]); close_prog: perf_buffer__free(pb); if (!IS_ERR_OR_NULL(link)) bpf_link__destroy(link); + if (!IS_ERR_OR_NULL(link_fentry)) + bpf_link__destroy(link_fentry); + if (!IS_ERR_OR_NULL(link_fexit)) + bpf_link__destroy(link_fexit); bpf_object__close(obj); bpf_object__close(obj2); } diff --git a/tools/testing/selftests/bpf/progs/kfree_skb.c b/tools/testing/selftests/bpf/progs/kfree_skb.c index f769fdbf6725..dcc9feac8338 100644 --- a/tools/testing/selftests/bpf/progs/kfree_skb.c +++ b/tools/testing/selftests/bpf/progs/kfree_skb.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2019 Facebook #include +#include #include "bpf_helpers.h" #include "bpf_endian.h" @@ -116,3 +117,54 @@ int trace_kfree_skb(struct trace_kfree_skb *ctx) &meta, sizeof(meta)); return 0; } + +static volatile struct { + bool fentry_test_ok; + bool fexit_test_ok; +} result; + +struct eth_type_trans_args { + struct sk_buff *skb; + struct net_device *dev; + unsigned short protocol; /* return value available to fexit progs */ +}; + +SEC("fentry/eth_type_trans") +int fentry_eth_type_trans(struct eth_type_trans_args *ctx) +{ + struct sk_buff *skb = ctx->skb; + struct net_device *dev = ctx->dev; + int len, ifindex; + + __builtin_preserve_access_index(({ + len = skb->len; + ifindex = dev->ifindex; + })); + + /* fentry sees full packet including L2 header */ + if (len != 74 || ifindex != 1) + return 0; + result.fentry_test_ok = true; + return 0; +} + +SEC("fexit/eth_type_trans") +int fexit_eth_type_trans(struct eth_type_trans_args *ctx) +{ + struct sk_buff *skb = ctx->skb; + struct net_device *dev = ctx->dev; + int len, ifindex; + + __builtin_preserve_access_index(({ + len = skb->len; + ifindex = dev->ifindex; + })); + + /* fexit sees packet without L2 header that eth_type_trans should have + * consumed. + */ + if (len != 60 || ctx->protocol != bpf_htons(0x86dd) || ifindex != 1) + return 0; + result.fexit_test_ok = true; + return 0; +} -- cgit v1.2.3-59-g8ed1b