mirror of
https://gitee.com/bianbu-linux/linux-6.6
synced 2025-04-24 14:07:52 -04:00
Test skb and xdp dynptr functionality in the following ways: 1) progs/test_cls_redirect_dynptr.c * Rewrite "progs/test_cls_redirect.c" test to use dynptrs to parse skb data * This is a great example of how dynptrs can be used to simplify a lot of the parsing logic for non-statically known values. When measuring the user + system time between the original version vs. using dynptrs, and averaging the time for 10 runs (using "time ./test_progs -t cls_redirect"): original version: 0.092 sec with dynptrs: 0.078 sec 2) progs/test_xdp_dynptr.c * Rewrite "progs/test_xdp.c" test to use dynptrs to parse xdp data When measuring the user + system time between the original version vs. using dynptrs, and averaging the time for 10 runs (using "time ./test_progs -t xdp_attach"): original version: 0.118 sec with dynptrs: 0.094 sec 3) progs/test_l4lb_noinline_dynptr.c * Rewrite "progs/test_l4lb_noinline.c" test to use dynptrs to parse skb data When measuring the user + system time between the original version vs. using dynptrs, and averaging the time for 10 runs (using "time ./test_progs -t l4lb_all"): original version: 0.062 sec with dynptrs: 0.081 sec For number of processed verifier instructions: original version: 6268 insns with dynptrs: 2588 insns 4) progs/test_parse_tcp_hdr_opt_dynptr.c * Add sample code for parsing tcp hdr opt lookup using dynptrs. This logic is lifted from a real-world use case of packet parsing in katran [0], a layer 4 load balancer. The original version "progs/test_parse_tcp_hdr_opt.c" (not using dynptrs) is included here as well, for comparison. When measuring the user + system time between the original version vs. using dynptrs, and averaging the time for 10 runs (using "time ./test_progs -t parse_tcp_hdr_opt"): original version: 0.031 sec with dynptrs: 0.045 sec 5) progs/dynptr_success.c * Add test case "test_skb_readonly" for testing attempts at writes on a prog type with read-only skb ctx. * Add "test_dynptr_skb_data" for testing that bpf_dynptr_data isn't supported for skb progs. 6) progs/dynptr_fail.c * Add test cases "skb_invalid_data_slice{1,2,3,4}" and "xdp_invalid_data_slice{1,2}" for testing that helpers that modify the underlying packet buffer automatically invalidate the associated data slice. * Add test cases "skb_invalid_ctx" and "xdp_invalid_ctx" for testing that prog types that do not support bpf_dynptr_from_skb/xdp don't have access to the API. * Add test case "dynptr_slice_var_len{1,2}" for testing that variable-sized len can't be passed in to bpf_dynptr_slice * Add test case "skb_invalid_slice_write" for testing that writes to a read-only data slice are rejected by the verifier. * Add test case "data_slice_out_of_bounds_skb" for testing that writes to an area outside the slice are rejected. * Add test case "invalid_slice_rdwr_rdonly" for testing that prog types that don't allow writes to packet data don't accept any calls to bpf_dynptr_slice_rdwr. [0] https://github.com/facebookincubator/katran/blob/main/katran/lib/bpf/pckt_parsing.h Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Acked-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/r/20230301154953.641654-11-joannelkoong@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
102 lines
2.1 KiB
C
102 lines
2.1 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/* Copyright (c) 2022 Facebook */
|
|
|
|
#include <test_progs.h>
|
|
#include <network_helpers.h>
|
|
#include "dynptr_fail.skel.h"
|
|
#include "dynptr_success.skel.h"
|
|
|
|
enum test_setup_type {
|
|
SETUP_SYSCALL_SLEEP,
|
|
SETUP_SKB_PROG,
|
|
};
|
|
|
|
static struct {
|
|
const char *prog_name;
|
|
enum test_setup_type type;
|
|
} success_tests[] = {
|
|
{"test_read_write", SETUP_SYSCALL_SLEEP},
|
|
{"test_dynptr_data", SETUP_SYSCALL_SLEEP},
|
|
{"test_ringbuf", SETUP_SYSCALL_SLEEP},
|
|
{"test_skb_readonly", SETUP_SKB_PROG},
|
|
{"test_dynptr_skb_data", SETUP_SKB_PROG},
|
|
};
|
|
|
|
static void verify_success(const char *prog_name, enum test_setup_type setup_type)
|
|
{
|
|
struct dynptr_success *skel;
|
|
struct bpf_program *prog;
|
|
struct bpf_link *link;
|
|
int err;
|
|
|
|
skel = dynptr_success__open();
|
|
if (!ASSERT_OK_PTR(skel, "dynptr_success__open"))
|
|
return;
|
|
|
|
skel->bss->pid = getpid();
|
|
|
|
prog = bpf_object__find_program_by_name(skel->obj, prog_name);
|
|
if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name"))
|
|
goto cleanup;
|
|
|
|
bpf_program__set_autoload(prog, true);
|
|
|
|
err = dynptr_success__load(skel);
|
|
if (!ASSERT_OK(err, "dynptr_success__load"))
|
|
goto cleanup;
|
|
|
|
switch (setup_type) {
|
|
case SETUP_SYSCALL_SLEEP:
|
|
link = bpf_program__attach(prog);
|
|
if (!ASSERT_OK_PTR(link, "bpf_program__attach"))
|
|
goto cleanup;
|
|
|
|
usleep(1);
|
|
|
|
bpf_link__destroy(link);
|
|
break;
|
|
case SETUP_SKB_PROG:
|
|
{
|
|
int prog_fd;
|
|
char buf[64];
|
|
|
|
LIBBPF_OPTS(bpf_test_run_opts, topts,
|
|
.data_in = &pkt_v4,
|
|
.data_size_in = sizeof(pkt_v4),
|
|
.data_out = buf,
|
|
.data_size_out = sizeof(buf),
|
|
.repeat = 1,
|
|
);
|
|
|
|
prog_fd = bpf_program__fd(prog);
|
|
if (!ASSERT_GE(prog_fd, 0, "prog_fd"))
|
|
goto cleanup;
|
|
|
|
err = bpf_prog_test_run_opts(prog_fd, &topts);
|
|
|
|
if (!ASSERT_OK(err, "test_run"))
|
|
goto cleanup;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
ASSERT_EQ(skel->bss->err, 0, "err");
|
|
|
|
cleanup:
|
|
dynptr_success__destroy(skel);
|
|
}
|
|
|
|
void test_dynptr(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(success_tests); i++) {
|
|
if (!test__start_subtest(success_tests[i].prog_name))
|
|
continue;
|
|
|
|
verify_success(success_tests[i].prog_name, success_tests[i].type);
|
|
}
|
|
|
|
RUN_TESTS(dynptr_fail);
|
|
}
|