Merge branch 'double-fix bpf_test_run + XDP_PASS recycling'
Alexander Lobakin says: ==================== Enabling skb PP recycling revealed a couple issues in the bpf_test_run code. Recycling broke the assumption that the headroom won't ever be touched during the test_run execution: xdp_scrub_frame() invalidates the XDP frame at the headroom start, while neigh xmit code overwrites 2 bytes to the left of the Ethernet header. The first makes the kernel panic in certain cases, while the second breaks xdp_do_redirect selftest on BE. test_run is a limited-scope entity, so let's hope no more corner cases will happen here or at least they will be as easy and pleasant to fix as those two. ==================== Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
commit
94bbbdfbde
@ -208,6 +208,16 @@ static void xdp_test_run_teardown(struct xdp_test_data *xdp)
|
||||
kfree(xdp->skbs);
|
||||
}
|
||||
|
||||
static bool frame_was_changed(const struct xdp_page_head *head)
|
||||
{
|
||||
/* xdp_scrub_frame() zeroes the data pointer, flags is the last field,
|
||||
* i.e. has the highest chances to be overwritten. If those two are
|
||||
* untouched, it's most likely safe to skip the context reset.
|
||||
*/
|
||||
return head->frm.data != head->orig_ctx.data ||
|
||||
head->frm.flags != head->orig_ctx.flags;
|
||||
}
|
||||
|
||||
static bool ctx_was_changed(struct xdp_page_head *head)
|
||||
{
|
||||
return head->orig_ctx.data != head->ctx.data ||
|
||||
@ -217,7 +227,7 @@ static bool ctx_was_changed(struct xdp_page_head *head)
|
||||
|
||||
static void reset_ctx(struct xdp_page_head *head)
|
||||
{
|
||||
if (likely(!ctx_was_changed(head)))
|
||||
if (likely(!frame_was_changed(head) && !ctx_was_changed(head)))
|
||||
return;
|
||||
|
||||
head->ctx.data = head->orig_ctx.data;
|
||||
|
@ -86,12 +86,12 @@ static void test_max_pkt_size(int fd)
|
||||
void test_xdp_do_redirect(void)
|
||||
{
|
||||
int err, xdp_prog_fd, tc_prog_fd, ifindex_src, ifindex_dst;
|
||||
char data[sizeof(pkt_udp) + sizeof(__u32)];
|
||||
char data[sizeof(pkt_udp) + sizeof(__u64)];
|
||||
struct test_xdp_do_redirect *skel = NULL;
|
||||
struct nstoken *nstoken = NULL;
|
||||
struct bpf_link *link;
|
||||
LIBBPF_OPTS(bpf_xdp_query_opts, query_opts);
|
||||
struct xdp_md ctx_in = { .data = sizeof(__u32),
|
||||
struct xdp_md ctx_in = { .data = sizeof(__u64),
|
||||
.data_end = sizeof(data) };
|
||||
DECLARE_LIBBPF_OPTS(bpf_test_run_opts, opts,
|
||||
.data_in = &data,
|
||||
@ -105,8 +105,9 @@ void test_xdp_do_redirect(void)
|
||||
DECLARE_LIBBPF_OPTS(bpf_tc_hook, tc_hook,
|
||||
.attach_point = BPF_TC_INGRESS);
|
||||
|
||||
memcpy(&data[sizeof(__u32)], &pkt_udp, sizeof(pkt_udp));
|
||||
memcpy(&data[sizeof(__u64)], &pkt_udp, sizeof(pkt_udp));
|
||||
*((__u32 *)data) = 0x42; /* metadata test value */
|
||||
*((__u32 *)data + 4) = 0;
|
||||
|
||||
skel = test_xdp_do_redirect__open();
|
||||
if (!ASSERT_OK_PTR(skel, "skel"))
|
||||
|
@ -52,7 +52,7 @@ int xdp_redirect(struct xdp_md *xdp)
|
||||
|
||||
*payload = MARK_IN;
|
||||
|
||||
if (bpf_xdp_adjust_meta(xdp, 4))
|
||||
if (bpf_xdp_adjust_meta(xdp, sizeof(__u64)))
|
||||
return XDP_ABORTED;
|
||||
|
||||
if (retcode > XDP_PASS)
|
||||
|
Loading…
x
Reference in New Issue
Block a user