-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
selftests/bpf: tests for using dynptrs to parse skb and xdp buffers
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>
- Loading branch information
Joanne Koong
authored and
Alexei Starovoitov
committed
Mar 1, 2023
1 parent
66e3a13
commit cfa7b01
Showing
15 changed files
with
2,522 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
#ifndef __BPF_KFUNCS__ | ||
#define __BPF_KFUNCS__ | ||
|
||
/* Description | ||
* Initializes an skb-type dynptr | ||
* Returns | ||
* Error code | ||
*/ | ||
extern int bpf_dynptr_from_skb(struct __sk_buff *skb, __u64 flags, | ||
struct bpf_dynptr *ptr__uninit) __ksym; | ||
|
||
/* Description | ||
* Initializes an xdp-type dynptr | ||
* Returns | ||
* Error code | ||
*/ | ||
extern int bpf_dynptr_from_xdp(struct xdp_md *xdp, __u64 flags, | ||
struct bpf_dynptr *ptr__uninit) __ksym; | ||
|
||
/* Description | ||
* Obtain a read-only pointer to the dynptr's data | ||
* Returns | ||
* Either a direct pointer to the dynptr data or a pointer to the user-provided | ||
* buffer if unable to obtain a direct pointer | ||
*/ | ||
extern void *bpf_dynptr_slice(const struct bpf_dynptr *ptr, __u32 offset, | ||
void *buffer, __u32 buffer__szk) __ksym; | ||
|
||
/* Description | ||
* Obtain a read-write pointer to the dynptr's data | ||
* Returns | ||
* Either a direct pointer to the dynptr data or a pointer to the user-provided | ||
* buffer if unable to obtain a direct pointer | ||
*/ | ||
extern void *bpf_dynptr_slice_rdwr(const struct bpf_dynptr *ptr, __u32 offset, | ||
void *buffer, __u32 buffer__szk) __ksym; | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
93 changes: 93 additions & 0 deletions
93
tools/testing/selftests/bpf/prog_tests/parse_tcp_hdr_opt.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
|
||
#include <test_progs.h> | ||
#include <network_helpers.h> | ||
#include "test_parse_tcp_hdr_opt.skel.h" | ||
#include "test_parse_tcp_hdr_opt_dynptr.skel.h" | ||
#include "test_tcp_hdr_options.h" | ||
|
||
struct test_pkt { | ||
struct ipv6_packet pk6_v6; | ||
u8 options[16]; | ||
} __packed; | ||
|
||
struct test_pkt pkt = { | ||
.pk6_v6.eth.h_proto = __bpf_constant_htons(ETH_P_IPV6), | ||
.pk6_v6.iph.nexthdr = IPPROTO_TCP, | ||
.pk6_v6.iph.payload_len = __bpf_constant_htons(MAGIC_BYTES), | ||
.pk6_v6.tcp.urg_ptr = 123, | ||
.pk6_v6.tcp.doff = 9, /* 16 bytes of options */ | ||
|
||
.options = { | ||
TCPOPT_MSS, 4, 0x05, 0xB4, TCPOPT_NOP, TCPOPT_NOP, | ||
0, 6, 0xBB, 0xBB, 0xBB, 0xBB, TCPOPT_EOL | ||
}, | ||
}; | ||
|
||
static void test_parse_opt(void) | ||
{ | ||
struct test_parse_tcp_hdr_opt *skel; | ||
struct bpf_program *prog; | ||
char buf[128]; | ||
int err; | ||
|
||
LIBBPF_OPTS(bpf_test_run_opts, topts, | ||
.data_in = &pkt, | ||
.data_size_in = sizeof(pkt), | ||
.data_out = buf, | ||
.data_size_out = sizeof(buf), | ||
.repeat = 3, | ||
); | ||
|
||
skel = test_parse_tcp_hdr_opt__open_and_load(); | ||
if (!ASSERT_OK_PTR(skel, "skel_open_and_load")) | ||
return; | ||
|
||
pkt.options[6] = skel->rodata->tcp_hdr_opt_kind_tpr; | ||
prog = skel->progs.xdp_ingress_v6; | ||
|
||
err = bpf_prog_test_run_opts(bpf_program__fd(prog), &topts); | ||
ASSERT_OK(err, "ipv6 test_run"); | ||
ASSERT_EQ(topts.retval, XDP_PASS, "ipv6 test_run retval"); | ||
ASSERT_EQ(skel->bss->server_id, 0xBBBBBBBB, "server id"); | ||
|
||
test_parse_tcp_hdr_opt__destroy(skel); | ||
} | ||
|
||
static void test_parse_opt_dynptr(void) | ||
{ | ||
struct test_parse_tcp_hdr_opt_dynptr *skel; | ||
struct bpf_program *prog; | ||
char buf[128]; | ||
int err; | ||
|
||
LIBBPF_OPTS(bpf_test_run_opts, topts, | ||
.data_in = &pkt, | ||
.data_size_in = sizeof(pkt), | ||
.data_out = buf, | ||
.data_size_out = sizeof(buf), | ||
.repeat = 3, | ||
); | ||
|
||
skel = test_parse_tcp_hdr_opt_dynptr__open_and_load(); | ||
if (!ASSERT_OK_PTR(skel, "skel_open_and_load")) | ||
return; | ||
|
||
pkt.options[6] = skel->rodata->tcp_hdr_opt_kind_tpr; | ||
prog = skel->progs.xdp_ingress_v6; | ||
|
||
err = bpf_prog_test_run_opts(bpf_program__fd(prog), &topts); | ||
ASSERT_OK(err, "ipv6 test_run"); | ||
ASSERT_EQ(topts.retval, XDP_PASS, "ipv6 test_run retval"); | ||
ASSERT_EQ(skel->bss->server_id, 0xBBBBBBBB, "server id"); | ||
|
||
test_parse_tcp_hdr_opt_dynptr__destroy(skel); | ||
} | ||
|
||
void test_parse_tcp_hdr_opt(void) | ||
{ | ||
if (test__start_subtest("parse_tcp_hdr_opt")) | ||
test_parse_opt(); | ||
if (test__start_subtest("parse_tcp_hdr_opt_dynptr")) | ||
test_parse_opt_dynptr(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.